Chuyển tới nội dung chính

Docker - containerd - runc - CRI/OCI

Khi nói "chạy container", thật ra có nhiều lớp phối hợp với nhau. Bài này tách từng lớp ra: mỗi lớp là gì, làm gì, và Kubernetes dùng lớp nào.

1. Overview​

LớpThành phầnMức độMột câu
Giao diện người dùngDocker (CLI + dockerd)CaoBộ công cụ đầy đủ cho người dùng: build, run, network, volume
Quản lý containercontainerdTrungQuản lý image và vòng đời container
Giữ container chạycontainerd-shimTrungTiến trình trung gian, giữ container sống độc lập với containerd
Tạo containerruncThấpGọi nhân Linux để thật sự tạo container
Chuẩn giao tiếpCRIChuẩnAPI để kubelet nói chuyện với runtime
Chuẩn containerOCIChuẩnQuy định định dạng image và cách chạy container

2. Docker​

Docker là bộ công cụ hoàn chỉnh để làm việc với container, gồm nhiều phần:

Thành phầnViệc làm
docker CLILệnh người dùng gõ: docker build, docker run, docker ps
dockerd (Docker Engine)Daemon nhận lệnh từ CLI, quản lý network, volume, build image
BuildKitBuild image từ Dockerfile
containerdDocker Engine giao việc chạy container xuống containerd
docker CLI → dockerd → containerd → containerd-shim → runc → container
  • Docker rất tiện cho máy dev: build image, chạy thử, có docker compose.
  • Nhưng với Kubernetes, phần lớn tính năng của Docker là thừa: Kubernetes đã tự lo network (CNI), volume (CSI), lập lịch (scheduler). Kubernetes chỉ cần phần chạy container, tức là containerd.
💡 Kubernetes không dùng Docker Engine, nhưng image Docker vẫn chạy được
  • Image build bằng docker build vẫn chạy bình thường trên Kubernetes, vì nó theo chuẩn OCI image.
  • Docker vẫn là công cụ tốt để build và test image trên máy dev. Chỉ là Kubernetes không dùng Docker Engine làm runtime nữa.

3. containerd​

containerd là runtime chuyên quản lý vòng đời container. Ban đầu là một phần của Docker, sau được tách ra thành dự án độc lập.

containerd làmcontainerd không làm
Tải image từ registry, lưu và giải nén imageBuild image từ Dockerfile
Tạo, chạy, dừng, xóa containerQuản lý network nâng cao (giao cho CNI)
Quản lý snapshot (lớp file system)Lập lịch container lên máy (việc của scheduler)
Cung cấp CRI plugin cho kubelet

4. runc​

runc là công cụ cấp thấp nhất: chương trình thật sự tạo container bằng các tính năng của nhân Linux (namespaces để cô lập, cgroups để giới hạn CPU/RAM). runc không tự chạy, nó được containerd gọi qua shim.

Flow tạo container​

BướcAi làmViệc
1containerdTải image nginx từ registry
2containerdTạo OCI bundle từ image: thư mục rootfs (file của container) + file config.json (cách chạy)
3containerdKhởi động containerd-shim cho Pod
4shimGọi runc create với bundle
5runcTạo container, chạy tiến trình nginx, rồi thoát
6shimỞ lại làm "cha" của container: giữ log, báo khi container dừng
💡 Ghi nhớ
  • OCI bundle do containerd tạo từ image, theo chuẩn OCI nên runc đọc được.
  • Shim ("miếng chêm") đứng giữa containerd và container, để restart containerd không làm chết container.

5. CRI – Container Runtime Interface​

CRI là bộ API do Kubernetes định nghĩa (dùng gRPC), để kubelet ra lệnh cho container runtime mà không cần biết runtime đó là gì.

CRI gồm hai nhóm API:

NhómVí dụ thao tácDùng khi
RuntimeServiceRunPodSandbox, CreateContainer, StartContainer, StopContainer, ListContainersTạo Pod và container
ImageServicePullImage, ListImages, RemoveImageTải và quản lý image

Các runtime theo CRI thường gặp:

RuntimeGhi chú
containerdPhổ biến nhất: kubeadm, EKS, GKE, AKS đều dùng
CRI-OViết riêng cho Kubernetes, dùng nhiều trên OpenShift

6. OCI – Open Container Initiative​

OCI là một bộ luật chung cho container, để các công cụ của nhiều hãng khác nhau hiểu được nhau.

Nếu không có OCI: image build bằng Docker chỉ chạy được trên Docker. Kubernetes muốn dùng containerd thì bạn phải build lại image theo kiểu khác.

Nhờ có OCI: bạn build image bằng docker build trên laptop, đẩy lên Docker Hub hoặc ECR, rồi containerd trên cluster vẫn tải về và chạy bình thường.

Ba chuẩn, theo hành trình của một image​

ChuẩnTrả lời câu hỏiVí dụ dễ hiểu
ImageMột image gồm những gì, xếp ra sao?Image Docker build ra thì containerd cũng mở được
DistributionĐẩy image lên kho và tải về bằng cách nào?Docker Hub hay ECR đều push/pull giống nhau
RuntimeCó image rồi thì chạy container thế nào?containerd đưa cho runc đúng "công thức" để tạo container
💡 Phân biệt CRI và OCI
  • CRI: luật để kubelet nói chuyện với containerd (do Kubernetes đặt ra).
  • OCI: luật về image và cách chạy container (do tổ chức OCI đặt ra).

7. Công cụ dòng lệnh: ctr, nerdctl, crictl​

Công cụNói chuyện vớiDùng đểDùng khi thi?
ctrcontainerd trực tiếpDebug containerd mức thấp, ít tính năngHiếm
nerdctlcontainerd trực tiếpCú pháp giống Docker (nerdctl run -p 8080:80 nginx)Không
crictlBất kỳ runtime theo CRIKiểm tra, debug container và Pod sandbox trên node✅ Có
kubectlkube-apiserverQuản lý tài nguyên cluster✅ Có

crictl​

sudo crictl pods                     # liệt kê Pod sandbox trên node
sudo crictl ps -a # liệt kê container, kể cả container đã chết
sudo crictl images # liệt kê image
sudo crictl logs <container-id> # xem log
sudo crictl exec -it <container-id> sh
sudo crictl inspect <container-id>
  • Cấu hình endpoint nằm ở /etc/crictl.yaml; nếu chưa có, chỉ định bằng --runtime-endpoint unix:///run/containerd/containerd.sock.

ctr​

sudo ctr namespaces ls               # default, k8s.io, moby...
sudo ctr -n k8s.io containers ls # container do kubelet tạo
sudo ctr -n k8s.io images ls
  • Phải thêm -n k8s.io, nếu không ctr chỉ xem namespace default và sẽ thấy trống.

8. Tóm tắt​

Thành phầnLà gìAi dùng nó
DockerBộ công cụ đầy đủ cho người dùngDeveloper trên máy dev
containerdRuntime quản lý image và containerkubelet (qua CRI), Docker Engine
containerd-shimTiến trình giữ container sốngcontainerd
runcCông cụ cấp thấp tạo containercontainerd (qua shim)
CRIAPI giữa kubelet và runtimekubelet
OCIChuẩn image, runtime, registryMọi công cụ build, registry, runtime
crictlCLI debug runtime trên nodeAdmin khi debug, kỳ thi CKA