Gần đây, mình được yêu cầu tham gia vào quá trình tuyển dụng và onboarding bạn mới. Khi team và dự án phát triển cả về quy mô và độ phức tạp, tài liệu để chuyển giao giữa các dự án cũng càng thêm phức tạp và chỉ hoạt động trong một số hệ điều hành nhất định. Vì vậy, để đảm bảo quá trình tích hợp diễn ra nhanh chóng và có thể sử dụng lại, mình phải đưa ra một hướng mới để tạo ra một môi trường cô lập và đơn giản nhất có thể.
My goal
An isolate enviroment where every member get their own resource and custom preinstall package
Dự án hiện tại ở cty Jobhopin mình đang làm kết hợp nhiều ngôn ngữ như (Rust, Python, …) và quá trình dựng virtualenv khá dài dòng với phải thử nhiều cách mới chạy được ở máy của bạn mới. Thông thường thì người mới phải mất đến 2-3 tuần để tìm hiểu về các dự án hiện tại của và làm việc một cách hiệu quả
Why not use containers image?
Bước đầu, mình khuyến khích team sử dụng Docker và docker-compose để code và debug project nhưng AI team thường có cả thành viên là engineer và data scientist. Team data scientist cảm thấy khó debug trong docker và mất rất nhiều thời gian để các thành viên mới tìm hiểu và sử dụng docker’s image. Hơn nữa, tôi muốn tạo một máy ảo (VM) thực sự mà thành viên có quyền truy cập root - mọi người có thể thiết lập sysctls, cài đặt gói mới, tạo quy tắc iptables, cấu hình mạng bằng ip, chạy perf, về cơ bản là bất cứ thứ gì có họ có thể làm như trên personal device của họ.
Why not use virtual machine?
Mình đã thử một số nhà cung cấp VM (Qemu và Vmware) để tạo cho mỗi VM cho mỗi thành viên nhưng quá nhiều vấn đề gặp phải trong quá trình này:
- Thời gian khởi động VM chậm cộng với kích thước VM quá lớn.
- Thiếu API và VM backup phải được tạo thủ công mà không có cách nào document và sử dụng lại các step đã khởi tạo được.
Mình muốn các thành viên của team chỉ cần cung cấp thông tin đăng nhập của họ và kích thước VM => submit thông tin là sẽ có ngay một con VM hoàn chỉnh.
Firecracker can start a VM in less than a second with base OCI container
Ban đầu khi tôi đọc về việc Firecracker khi nó mới launch, tôi nghĩ nó chỉ là một tool cho các cloud vendor sử dụng để cung cấp bảo mật hơn là chạy trên thuần docker, nhưng tôi không nghĩ rằng mình lại có thể sử dụng luôn được để tạo một microVM.
Sau khi đọc một vài thông tin, tôi ấn tượng với khả năng tạo VM nhanh chóng và tiện lợi của Firecracker
Một vài so sánh giữa Firecracker và QEMU
Firecracker tích hợp với nhiều tool để quản lý container, làm cho việc áp dụng khá dễ dàng và dễ sử dụng. Tôi chọn sử dụng service Ignite mà lệnh CLI rất giống với docker
ignite run
instead of docker run
How to use Firecracker with ignite
Cài đặt Ignite và khởi động máy ảo mới rất đơn giản, về cơ bản có 3 bước:
Step 1
: Kiểm tra xem hệ thống của bạn đã bật ảo hóa KVM chưa và cài đặt Ignite tại đây Installing-guide
$ ignite version
Ignite version: version.Info{Major:"0", Minor:"8", GitVersion:"v0.10.0", GitCommit:"...", GitTreeState:"clean", BuildDate:"...", GoVersion:"...", Compiler:"gc", Platform:"linux/amd64"}
Firecracker version: v0.22.4
Runtime: containerd
Step 2
: Tạo một con VM mẫu config.yaml
apiVersion: ignite.weave.works/v1alpha4
kind: VM
metadata:
name: haiche-vm
spec:
cpus: 2
memory: 1GB
diskSize: 6GB
image:
oci: weaveworks/ignite-ubuntu
ssh: true
Step 3
: Khởi động máy chủ VM của bạn dưới 125 mili giây
It takes <= 125 ms to go from receiving the Firecracker InstanceStart API call to the start of the Linux guest user-space /sbin/init process
$ sudo ignite run --config config.yaml
INFO[0001] Created VM with ID "3c5fa9a18682741f" and name "haiche-vm"
Wolla 🎉 🎉 🎉 bạn đã tạo thành công một máy ảo mới. Để liệt kê các máy ảo đang chạy, hãy nhập:
$ ignite ps
VM ID IMAGE KERNEL CREATED SIZE CPUS MEMORY STATE IPS PORTS NAME
3c5fa9a18682741f weaveworks/ignite-ubuntu:latest weaveworks/ignite-kernel:5.10.51 63m ago 4.0 GB 2 1.0 GB Running 172.17.0.3 haiche-vm
Sau khi máy ảo được khởi động, nó sẽ được cấu hình mạng và có thể truy cập được từ máy chủ thông qua SSH không cần mật khẩu và với quyền sudo
SSH into the VM
Via ignite cli
$ ignite ssh haiche-vm
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 5.10.51 x86_64)
...
root@3c5fa9a18682741f:~#
Để thoát khỏi SSH, chỉ cần logout khỏi shell như Ctrl+C hoặc gõ exit.
Via ssh cli and rsa key
Thêm public key của bạn vào ~/.ssh/allow_keys
trong máy ảo mới được tạo hoặc cập nhập config máy ảo và tạo máy ảo mới với đường dẫn mặc định đến public key
spec:
...
ssh: path/your/id_rsa.pub
Và cuối cùng sử dụng ssh để truy cập vào máy ảo
$ ssh -i path/your/id_rsa root@172.17.0.3
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 5.10.51 x86_64)
...
root@3c5fa9a18682741f:~#
Secure bastion host
Sử dụng bastion host để bảo mật hoàn toàn ssh cho máy chủ VM
~/.ssh/config
Host workstation
HostName 192.168.1.15
User haiche
IdentityFile ~/.ssh/id_rsa
Host haiche-vm
HostName 172.17.0.3
ProxyJump workstation
User root
IdentityFile ~/.ssh/id_rsa
Thêm cấu hình ở trên vào thư mục ssh của bạn và chạy ssh haiche-vm
để truy cập máy chủ VM từ máy client
How I extend container to reduce repeatable setup process
Sau khi tạo VM thành công, chủ yếu là tôi sẽ cài đặt conda và một số tool mà tôi hay xài lên đó. Nhưng tôi không muốn cài đặt nhiều lần conda và tạo môi trường mới mỗi lần tạo lại VM. Đây là các bước để mở rộng image base Ubuntu và sử dụng nó để tạo trải nghiệm VM tốt hơn
Dockerfile
FROM weaveworks/ignite-ubuntu
ENV PATH="/root/miniconda3/bin:${PATH}"
ARG PATH="/root/miniconda3/bin:${PATH}"
RUN apt-get update -qq && \
apt-get update -y && \
apt-get install git vim rsync \
build-essential curl -y
RUN wget \
https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh && \
mkdir /root/.conda && \
bash Miniconda3-latest-Linux-x86_64.sh -b && \
rm -f Miniconda3-latest-Linux-x86_64.sh
RUN conda create -n haiche python=3.7
SHELL ["conda", "run", "-n", "haiche", "/bin/bash", "-c"]
RUN conda install fastapi
RUN which python && python -c "import fastapi"
RUN conda init bash && echo "source activate haiche" >> ~/.bashrc
miniconda-vm.yaml
apiVersion: ignite.weave.works/v1alpha4
kind: VM
metadata:
name: haiche-minconda-vm
spec:
cpus: 2
memory: 1GB
diskSize: 6GB
image:
oci: haiche/ubuntu-minconda
ssh: path/your/id_rsa.pub
Đây là một số phần phức tạp, version Ignite hiện tại không hỗ trợ xây dựng image docker từ local. Tôi phải đẩy image vào Docker Hub để import thành công image mới vào Ignite.
Để tạo một máy ảo với Docker image mới
$ sudo ignite run --config miniconda-vm.yaml
...
INFO[0002] Created image with ID "cae0ac317cca74ba" and name "haiche/ubuntu-minconda"
INFO[0004] Created VM with ID "c1ab652804e664ed" and name "haiche-minconda-vm"
Nếu bạn sử dụng private registry như ECR, hãy chạy lệnh trên với --runtime docker
để pull image từ private registry
Kiểm tra máy ảo với môi trường conda mới
$ ssh -i path/your/id_rsa root@172.17.0.4
...
(haiche) root@c1ab652804e664ed:~# python
Python 3.7.13 (default, Mar 29 2022, 02:18:16)
[GCC 7.5.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import fastapi
>>> fastapi.__version__
'0.74.1'
>>>
Tôi thích cách tiếp cận sử dụng config file để tạo VM và có thể xem tất cả mọi config ở một nơi. Bây giờ thành viên của team chỉ cần cung cấp config file và public key, tôi chỉ cần gõ 1 câu lệnh là một máy ảo mới với có sẵn tất cả các môi trường cần thiết. Họ có thể vọc vạc và run code ngay lập tức không cần phải học về cách setup môi trường
Cloud supports nested virtualization
Một câu hỏi khác mà tôi đã nghĩ đến: “được rồi, tôi sẽ chạy những máy ảo Firecracker này ở đâu trong môi trường Production?”. Điều thú vị khi chạy một máy ảo trên cloud là các cloud instances đã là máy ảo. Việc chạy một máy ảo bên trong một máy ảo được gọi là “nested virtualization” và không phải tất cả các nhà cung cấp dịch vụ cloud đều hỗ trợ - ví dụ: AWS chỉ hỗ trợ nested virtualization trong các phiên bản Bare-metal có giá cao ngất ngưởng.
GCP hỗ trợ nested virtualization nhưng không hỗ trợ mặc định, bạn phải bật tính năng này trong phần tạo instance. DigitalOcean hỗ trợ nested virtualization mặc định ngay cả trên instance rẻ nhất.
Some afterthought
Một số điều vẫn tôi còn thấy lấn cấn với cách tiếp cận tạo VM này:
-
Hiện tại Firecracker không hỗ trợ khôi phục và backup snapshot nhưng sẽ hỗ trợ trong tương lai gần https://github.com/firecracker-microvm/firecracker/issues/1184
-
Không thể dễ dàng nâng cấp base image như
docker pull
. Tôi đã giải quyết vấn đề này bằng cách tạo bản copy mới, nhưng điều đó khá chậm và thực sự không hiệu quả. Có một số giải pháp mà tôi tìm được và sẽ thử sau lại sau Device mapper to manage firecracker images -
Tôi không biết liệu có thể chạy các ứng dụng đồ họa trong Firecracker hay không
-
Firecracker với Kubernetes là một trend mới nhưng tôi không thấy hấp dẫn vì việc sử dụng Pod để nhóm các vùng chứa đã nhanh chóng và an toàn. Một số người đã cho tôi một thread hữu ích này thảo luận về lý do tại sao chúng chưa tương thích với nhau
I often hear people ask why Kubernetes and Firecracker (FC) can’t just be used together. It seems like an intuitive combination, Kubernetes is popular for orchestration, and Firecracker provides strong isolation boundaries. So why aren’t they compatible yet? Read on 🧵
— Micah Hausler (@micahhausler) March 13, 2020
Dưới đây là một số links tôi thấy hữu ích khi nghiên cứu về Firecracker:
-
How AWS Firecracker works: a deep dive trình bày một số khái niệm về Firecracker
-
AWS Fargate và Lambda được tạo bởi Firecracker serverless computing
-
So sánh kỹ thuật isolation khác Sandboxing and Workload Isolation
Комментарии