Skip to main content

2.1. Core Concepts: Cluster Architecture and Components

Mục lục​


1. Giới thiệu phần Core Concepts​

Một Kubernetes cluster trông như thế nào ở bên trong, và những khái niệm nào (Pod, ReplicaSet, Deployment, Service) làm nên một ứng dụng chạy được trên đó? Đây là điểm khởi đầu của các khái niệm cốt lõi (core concepts) trong Kubernetes: kiến trúc cluster ở mức tổng quan trước, rồi tới các API primitive nền tảng gồm Pods, ReplicaSets, Deployments, tiếp theo là Services. Nếu bạn đã học qua khóa dành cho người mới bắt đầu (beginners course) hoặc khóa chứng chỉ dành cho application developer, có thể bỏ qua một số chủ đề này, hoặc chỉ làm riêng phần practice test.

Bắt đầu với kiến trúc cluster.


2. Kiến trúc Cluster Kubernetes ở mức tổng quan​

Một Kubernetes cluster gồm hàng loạt process chạy song song trên nhiều máy khác nhau, nhưng chỉ cần một câu hỏi để bắt đầu hiểu toàn bộ: ai đang làm gì, và chúng nói chuyện với nhau ra sao? Phần này trả lời ở mức tổng quan trước, rồi mới đi sâu vào vai trò, trách nhiệm và cách cấu hình của từng thành phần. Cuối cùng là một practice test: bạn xem xét một cluster có sẵn và xác định các chi tiết liên quan tới từng thành phần trong đó.

Phần này dùng một analogy về tàu thuyền (ships) để hiểu kiến trúc của Kubernetes.

Mục đích của Kubernetes là host ứng dụng dưới dạng container theo cách tự động hóa, để có thể dễ dàng deploy bao nhiêu instance của ứng dụng tùy ý, và dễ dàng cho phép giao tiếp giữa các service khác nhau trong ứng dụng. Có rất nhiều thành phần cùng phối hợp để làm được điều này.

💡 Hình dung: có 2 loại tàu trong analogy này. Tàu chở hàng (cargo ships) làm công việc chính là chở container qua biển, còn tàu điều khiển (control ships) chịu trách nhiệm giám sát và quản lý các tàu chở hàng.

Kubernetes cluster gồm một tập hợp các node (có thể là vật lý hoặc ảo, on-premise hoặc trên cloud) host ứng dụng dưới dạng container. Các node này tương ứng với tàu chở hàng trong analogy. Worker node trong cluster là những con tàu chạy container.

Nhưng ai đó cần load container lên tàu. Không chỉ load, mà còn phải lên kế hoạch load thế nào, xác định đúng tàu, lưu thông tin về các tàu, giám sát vị trí của container trên tàu, quản lý toàn bộ quy trình load, v.v. Việc này thuộc về các tàu điều khiển, nơi đặt các văn phòng và phòng ban khác nhau, thiết bị giám sát, thiết bị liên lạc, cần cẩu để di chuyển container giữa các tàu, v.v.

Tàu điều khiển tương ứng với master node trong Kubernetes cluster. Master node chịu trách nhiệm quản lý Kubernetes cluster: lưu thông tin về các node khác nhau, lên kế hoạch container nào đi đâu, giám sát các node và container trên chúng, v.v. Master node thực hiện tất cả việc này thông qua một tập hợp component gọi chung là control plane components.

etcd — kho lưu trữ key-value​

Hằng ngày có rất nhiều container được load và unload khỏi tàu. Vì vậy cần duy trì thông tin về các tàu khác nhau: container nào ở trên tàu nào, được load lúc nào, v.v. Tất cả thông tin này nằm trong một key-value store có tính sẵn sàng cao (highly available), gọi là etcd. etcd là một database lưu thông tin dưới dạng key-value.

kube-scheduler​

Khi tàu cập bến, container được load lên bằng cần cẩu. Cần cẩu xác định container nào cần được đặt lên tàu nào, dựa trên kích thước tàu, khả năng chứa, số lượng container đã có trên tàu, và các điều kiện khác như điểm đến của tàu, loại container tàu được phép chở, v.v. Cần cẩu đó giữ vai trò của scheduler trong Kubernetes cluster.

Một scheduler xác định đúng node để đặt một container lên, dựa trên resource requirement của container, khả năng của worker node, hoặc các policy/constraint khác như taints và tolerations (cơ chế đánh dấu node để hạn chế pod nào được phép đặt lên nó) hay node affinity rules (quy tắc ưu tiên đặt pod lên node có thuộc tính nhất định).

Controllers​

Có nhiều văn phòng khác nhau trong bến tàu được giao các nhiệm vụ hoặc phòng ban đặc biệt. Ví dụ, đội vận hành (operations team) lo việc điều hướng tàu, kiểm soát giao thông, xử lý các vấn đề liên quan tới hư hỏng, tuyến đường mà các tàu khác nhau đi, v.v. Đội cargo lo việc container: khi container bị hư hỏng hoặc phá hủy, đội đảm bảo có container mới thay thế. Còn có văn phòng Service Accounts lo việc xác thực và giao tiếp giữa các tàu.

Tương tự, trong Kubernetes có các controller phụ trách các mảng khác nhau. Node controller lo việc quản lý node: onboarding node mới vào cluster, xử lý tình huống node không còn khả dụng hoặc bị hủy. Replication controller đảm bảo số lượng container mong muốn luôn đang chạy tại mọi thời điểm trong một replication group.

kube-apiserver​

Tới đây đã có đủ các thành phần: các văn phòng, các tàu, kho dữ liệu, cần cẩu. Nhưng chúng giao tiếp với nhau ra sao, và ai quản lý tất cả ở mức tổng quan?

kube-apiserver là management component chính của Kubernetes. kube-apiserver chịu trách nhiệm điều phối (orchestrate) mọi hoạt động bên trong cluster. Nó expose Kubernetes API, được dùng bởi người dùng bên ngoài để thực hiện các thao tác quản lý trên cluster, cũng như bởi các controller khác nhau để giám sát trạng thái của cluster và thực hiện thay đổi cần thiết, và bởi các worker node để giao tiếp với kube-apiserver.

Container runtime engine​

Container xuất hiện ở khắp nơi trong cluster. Ứng dụng ở dạng container. Các component tạo nên toàn bộ hệ thống quản lý trên master node có thể được host dưới dạng container. DNS service và giải pháp networking cũng vậy. Vì vậy cần phần mềm có khả năng chạy container, gọi là container runtime engine, mà phổ biến nhất là Docker.

Vì vậy cần cài Docker hoặc phần tương đương được hỗ trợ trên tất cả các node trong cluster, kể cả master node, nếu muốn host control plane component dưới dạng container. Không nhất thiết phải là Docker, vì Kubernetes hỗ trợ các runtime engine khác như containerd, rkt.

kubelet​

Mỗi tàu đều có một thuyền trưởng (captain) quản lý toàn bộ hoạt động trên tàu. Thuyền trưởng cũng là người liên lạc với tàu chủ (master ship): báo cho tàu chủ biết mình muốn gia nhập nhóm, nhận thông tin về các container cần load lên tàu và load đúng container theo yêu cầu, gửi báo cáo về trạng thái của tàu và container trên tàu, v.v.

Thuyền trưởng của tàu chính là kubelet trong Kubernetes. kubelet là một agent chạy trên mỗi node trong cluster. Nó lắng nghe hướng dẫn từ kube-apiserver và deploy hoặc destroy container trên các node khi cần. kube-apiserver định kỳ lấy status report từ kubelet để giám sát trạng thái của node và container trên chúng.

kube-proxy​

kubelet giống thuyền trưởng quản lý container trên tàu. Nhưng các ứng dụng chạy trên worker node cần có khả năng giao tiếp với nhau. Ví dụ có thể có một web server chạy trong 1 container trên 1 node, và một database server chạy trong 1 container khác trên node khác. Làm sao web server reach tới database server trên node kia?

Giao tiếp giữa các worker node được kích hoạt bởi một component khác chạy trên worker node, gọi là kube-proxy service. kube-proxy service đảm bảo các rule cần thiết được thiết lập trên worker node, cho phép các container chạy trên chúng reach được tới nhau.

Tóm tắt kiến trúc​

Vậy có master node và worker node.

Trên master, có etcd cluster lưu thông tin về cluster. Có kube-scheduler chịu trách nhiệm lên lịch ứng dụng hoặc container trên các node. Có các controller khác nhau lo các chức năng khác nhau như node controller, replication controller, v.v. Có kube-apiserver chịu trách nhiệm điều phối mọi hoạt động bên trong cluster.

Trên worker node, có kubelet lắng nghe hướng dẫn từ kube-apiserver và quản lý container, và kube-proxy giúp kích hoạt giao tiếp giữa các service trong cluster.

Kubernetes Cluster Architecture — Master & Worker NodeMaster Node — Control Planeetcdkey-value storekube-apiservercentral hubcontroller-managernode, replication...kube-schedulerchọn node cho PodWorker Nodekubelettạo/giám sát containerContainer RuntimeDocker, containerd...kube-proxyroute traffic tới PodMọi giao tiếp giữa control plane và worker node đều đi qua kube-apiserver

Đó là overview tổng quan về các component khác nhau. Các phần tiếp theo sẽ đi sâu vào từng component.


3. Container Runtime: Docker, containerd và CRI​

Docker và containerd sẽ xuất hiện rất nhiều lần trong tài liệu này. Khi đọc blog hay trang tài liệu cũ, sẽ thấy Docker được nhắc tới cùng Kubernetes. Khi đọc blog mới hơn, sẽ thấy containerd, và có thể sẽ tự hỏi sự khác biệt giữa 2 cái này là gì. Ngoài ra còn có vài CLI tool như ctr, crictl hay nerdctl, và có thể sẽ tự hỏi các tool này là gì và nên dùng cái nào.

Lịch sử: từ Docker tới CRI​

Quay lại thời điểm bắt đầu kỷ nguyên container: ban đầu chỉ có Docker, và có các tool khác như rkt, nhưng trải nghiệm người dùng của Docker khiến việc làm việc với container trở nên siêu đơn giản, nên Docker thành container tool thống trị. Kubernetes ra đời sau đó, và được xây dựng để orchestrate cụ thể Docker. Hai bên gắn chặt với nhau: lúc ấy Kubernetes chỉ hoạt động với Docker, không hỗ trợ giải pháp container nào khác.

Sau đó Kubernetes tăng độ phổ biến với vai trò container orchestrator, và các container runtime khác như rkt muốn tham gia. Người dùng Kubernetes cần nó hoạt động với các container runtime khác ngoài Docker. Vì vậy Kubernetes giới thiệu một interface gọi là Container Runtime Interface, hay CRI. CRI cho phép bất kỳ vendor nào hoạt động như một container runtime cho Kubernetes, miễn tuân thủ chuẩn OCI.

OCI là viết tắt của Open Container Initiative, gồm một image spec và một runtime spec. Image spec định nghĩa các tiêu chuẩn về cách một image cần được build. Runtime spec định nghĩa tiêu chuẩn về cách bất kỳ container runtime nào cần được phát triển. Theo các chuẩn này, bất kỳ ai cũng có thể build một container runtime để bất kỳ ai khác dùng cùng Kubernetes.

CRI: kubelet nói chuyện qua 1 chuẩn chung, không quan tâm runtime nào phía saukubeletCRI — Container Runtime Interface (chuẩn)containerdCRI-Oruntime khácTuân thủ CRI → cắm thẳng vào kubelet, không cần adapter⚠ Docker Engine không tuân thủ CRI trực tiếp — muốn dùng lạivới Kubernetes mới, cần cri-dockerd (adapter cộng đồng duy trì riêng).

rkt và các container runtime khác tuân thủ chuẩn OCI được hỗ trợ làm container runtime cho Kubernetes thông qua CRI. Docker thì không, vì Docker ra đời từ trước khi CRI xuất hiện, mà lúc đó Docker vẫn là container tool đa số người dùng đang chạy. Kubernetes vì vậy phải tiếp tục hỗ trợ Docker, bằng Dockershim: một cách hacky và tạm thời để giữ Docker chạy được bên ngoài Container Runtime Interface. Hầu hết runtime khác đi qua CRI, riêng Docker đi vòng.

Docker thực chất gồm nhiều tool​

Docker không chỉ đơn thuần là một container runtime. Docker gồm nhiều tool ghép lại: Docker CLI, Docker API, các build tool giúp build image, hỗ trợ volume, auth, security, và cuối cùng là container runtime tên runc, cùng daemon quản lý runc gọi là containerd. containerd tương thích CRI và có thể hoạt động trực tiếp với Kubernetes, như mọi runtime khác. containerd có thể được dùng làm runtime độc lập, tách biệt khỏi Docker.

Kubernetes duy trì hỗ trợ Docker Engine trực tiếp thêm một thời gian. Nhưng việc gánh thêm Dockershim là công sức không cần thiết và làm hệ thống phức tạp hơn. Ở phiên bản Kubernetes 1.24, Dockershim bị loại bỏ, kéo theo hỗ trợ Docker. Mọi image build trước đó vẫn chạy bình thường, vì Docker tuân theo image spec của chuẩn OCI, nên image do Docker build vẫn hoạt động với containerd. Thứ bị gỡ khỏi danh sách runtime được Kubernetes hỗ trợ chính thức chỉ là bản thân Docker.

containerd: một dự án CNCF độc lập​

containerd, dù là một phần của Docker, giờ là một dự án độc lập, và là thành viên của CNCF với trạng thái graduated. Có thể cài containerd độc lập mà không cần cài Docker. Nếu không cần tới các tính năng khác của Docker, chỉ cài containerd là đủ.

ctr — CLI debug đi kèm containerd​

Trước đây, container được chạy bằng lệnh docker run khi có Docker. Nếu không cài Docker, làm sao chạy container chỉ với containerd? containerd đi kèm một CLI tool tên ctr, nhưng công cụ này chỉ dành riêng để debug containerd, không thân thiện với người dùng vì chỉ hỗ trợ một tập tính năng giới hạn.

Để pull image Redis:

ctr images pull docker.io/library/redis:latest
# Output minh họa
docker.io/library/redis:latest: resolved |++++++++++++++++++++++++++++++++++++++|
manifest-sha256:1a2b3c...: done |++++++++++++++++++++++++++++++++++++++|
config-sha256:4d5e6f...: done |++++++++++++++++++++++++++++++++++++++|
layer-sha256:7g8h9i...: done |++++++++++++++++++++++++++++++++++++++|
elapsed: 3.2 s total: 16.2 Mi (5.1 MiB/s)

(Output minh họa — cấu trúc và định dạng progress bar đúng theo lệnh thật, số liệu cụ thể chỉ mang tính ví dụ.)

Để chạy container:

ctr run docker.io/library/redis:latest redis-test
# Output minh họa (chạy foreground, không có output nếu container thoát bình thường)

(Lệnh ctr run mặc định chạy container ở foreground và gắn liền với terminal hiện tại — không có flag tương đương -d như docker run trừ khi thêm --detach.)

Vì vậy không nên dùng ctr để chạy hay quản lý container trên môi trường production.

nerdctl — Docker-like CLI cho containerd​

Lựa chọn thay thế được khuyến nghị là nerdctl, một Docker-like CLI cho containerd. Nó hỗ trợ hầu hết hoặc toàn bộ option mà Docker hỗ trợ, đồng thời mở đường tới các tính năng mới nhất của containerd, ví dụ làm việc với encrypted container image (một tính năng khá mới, sẽ được đưa vào các lệnh Docker thông thường trong tương lai). Nó cũng hỗ trợ lazy pulling of images, P2P image distribution, image signing và verifying, cùng namespaces trong Kubernetes, những thứ không có sẵn trong Docker.

Thay vì dùng docker run để tạo container, dùng nerdctl run. Muốn map hay expose port bằng option -p như với docker run, cách làm y hệt: thay docker bằng nerdctl.

crictl — CLI debug từ phía Kubernetes​

Còn một command-line utility nữa là crictl, hay CRI control. crictl tương tác với container runtime tương thích CRI như containerd, Rocket và các runtime khác, từ góc nhìn Kubernetes. Cộng đồng Kubernetes phát triển và duy trì tool này. Khác với ctr và nerdctl vốn do cộng đồng containerd xây dựng và chỉ dành cho containerd, crictl chạy được trên mọi container runtime.

crictl phải cài riêng, và dùng để inspect và debug container runtime, không phải để tạo container như Docker hay nerdctl. Về mặt kỹ thuật vẫn tạo được container bằng crictl, nhưng không dễ, và chỉ nên dùng cho mục đích debug đặc biệt.

⚠️ Lưu ý: crictl hoạt động cùng kubelet. kubelet chịu trách nhiệm đảm bảo đúng số lượng container hoặc pod luôn khả dụng trên một node tại một thời điểm. Nếu dùng crictl để tạo container, kubelet sẽ xóa chúng đi, vì kubelet không biết về những container/pod được tạo ngoài phạm vi quản lý của nó.

Một số ví dụ command line:

crictl ps
# Output minh họa
CONTAINER IMAGE CREATED STATE NAME POD ID
a1b2c3d4e5f6 nginx 2 minutes ago Running nginx f6e5d4c3b2a1

(Output minh họa — cấu trúc và tên cột đúng theo lệnh thật, ID/thời gian cụ thể chỉ mang tính ví dụ.)

Tương tự lệnh docker ps, dùng để list container. Để chạy một command bên trong container (tương tự docker exec):

crictl exec -i -t a1b2c3d4e5f6 sh
# Output minh họa — mở shell tương tác bên trong container
/ #

Để xem log:

crictl logs a1b2c3d4e5f6
# Output minh họa
2026-08-19T10:00:01Z [notice] nginx started
2026-08-19T10:00:01Z [notice] using the "epoll" event method

Điểm khác biệt lớn là crictl biết về pod, nên có thể list pod bằng:

crictl pods
# Output minh họa
POD ID CREATED STATE NAME NAMESPACE ATTEMPT
f6e5d4c3b2a1 3 minutes ago Ready nginx-pod default 0

(Output minh họa — cấu trúc và tên cột đúng theo lệnh thật, ID/thời gian cụ thể chỉ mang tính ví dụ.)

Docker không biết về khái niệm pod. Trước đây khi làm việc với Kubernetes, lệnh Docker được dùng nhiều để troubleshoot container và xem log, đặc biệt trên worker node. Giờ việc đó chuyển sang crictl, với cú pháp khá tương tự.

Bảng so sánh giữa Docker và crictl:

Nhóm lệnhDanh sáchMức độ tương thích
Hoạt động y hệt nhauattach, exec, images, info, inspect, logs, ps, stats, versionCú pháp và cách dùng giống hệt Docker
Hoạt động tương tựCác lệnh tạo, xóa, start và stop imageTương tự nhưng không hoàn toàn giống Docker

Thay đổi default endpoint của crictl từ Kubernetes 1.24​

Ở các phiên bản Kubernetes trước 1.24, tool crictl kết nối tới runtime endpoint theo thứ tự mặc định nhất định. Tuy nhiên, với việc phát hành Kubernetes 1.24, một thay đổi đáng kể đã được thực hiện: dockershim.sock được thay bằng cri-dockerd.sock. Kết quả là default endpoint cập nhật cho tool crictl đã thay đổi. Thay đổi này được thực hiện do việc deprecate các default setting trước đó. Giờ đây người dùng được khuyến khích tự set endpoint thủ công. Những thay đổi này được ghi lại trong repo GitHub cri-tools của Kubernetes, cụ thể tại pull request 869 và issue 868.

Tóm tắt​

  • ctr: CLI đi kèm containerd, dùng cho mục đích debug, có tập tính năng rất hạn chế. Về cơ bản không nên dùng tool này.
  • nerdctl: CLI từ cộng đồng containerd, là Docker-like CLI cho containerd, dùng cho mục đích thông thường để tạo container, hỗ trợ tính năng ngang bằng hoặc nhiều hơn Docker CLI.
  • crictl: utility từ cộng đồng Kubernetes, dùng để tương tác với runtime tương thích CRI, không riêng containerd mà mọi runtime hỗ trợ CRI, chủ yếu cho mục đích debug.

ctr và crictl chủ yếu dùng cho mục đích debug, còn nerdctl dùng cho mục đích thông thường. ctr và nerdctl đến từ cộng đồng containerd và làm việc với containerd, còn crictl đến từ cộng đồng Kubernetes và làm việc trên mọi runtime tương thích CRI.

Vì sao vẫn nói về Docker dù đã bị deprecate?​

Một câu hỏi thường gặp: vì sao tài liệu vẫn nhắc tới Docker nếu nó đã bị deprecate khỏi Kubernetes? Docker vốn là container runtime gốc và duy nhất được Kubernetes hỗ trợ. Để mở Kubernetes cho các runtime khác, Container Runtime Interface đã được giới thiệu. Và như mục trên đã tách ra, phần tương thích CRI nằm bên trong chính Docker chính là containerd, thứ chạy trực tiếp với Kubernetes như mọi runtime khác, và dùng được độc lập, tách biệt khỏi Docker.

Một khi thay đổi này được thực hiện, Kubernetes không còn cần các tool khác mà Docker hỗ trợ, như Docker CLI, API, hay build/volume, vì chính Kubernetes đã tự đảm nhiệm. Nhờ vậy Kubernetes có thể deprecate hỗ trợ cho Docker.

⚠️ Không có nghĩa là Docker biến mất. Docker vẫn là giải pháp container phổ biến nhất, vẫn được nhiều người dùng trong quy trình phát triển và build hằng ngày. Chỉ là Kubernetes không còn yêu cầu Docker làm runtime nữa.

Vì vậy, xuyên suốt tài liệu này, các ví dụ về container vẫn dùng Docker, và điều đó không sao: cần hiểu container hoạt động ra sao trước, rồi mới tới cách nó vận hành trong thế giới container orchestration của Kubernetes. Nếu máy bạn không có Docker, hoặc chỉ có containerd, vẫn chạy được cùng các ví dụ bằng cách thay lệnh docker bằng nerdctl trong hầu hết trường hợp.

Container runtime là bên "chạy" container trên mỗi node. Nhưng cluster còn cần một nơi khác để nhớ trạng thái: node nào đang có, pod nào đang chạy ở đâu, cấu hình nào đã áp dụng. Đó là việc của etcd.


4. ETCD​

ETCD là gì?​

Đây là phần giới thiệu nhanh về etcd cho người mới bắt đầu; nếu đã biết etcd, bạn có thể bỏ qua. Phần này bàn về etcd là gì, key-value store là gì, nó khác database truyền thống ra sao, cách bắt đầu với etcd và cách dùng client tool để thao tác với nó. Phần sau của tài liệu sẽ bàn về high availability: thế nào là một distributed system, etcd hoạt động ra sao ở chế độ cluster, Raft protocol là gì, và best practice xoay quanh số lượng node trong một etcd cluster.

etcd là một distributed, reliable key-value store: đơn giản, bảo mật, và nhanh.

Key-value store so với database truyền thống​

Truyền thống, database ở dạng bảng (tabular), tức SQL hay relational database, lưu dữ liệu dưới dạng hàng và cột. Mỗi hàng đại diện cho một cá nhân, mỗi cột đại diện cho loại thông tin được lưu. Muốn thêm thông tin mới (ví dụ salary), phải thêm một cột mới, và việc này ảnh hưởng toàn bộ bảng: nhiều ô sẽ trống nếu không phải mọi hàng đều có thông tin đó (ví dụ chỉ sinh viên mới có "grade").

Relational database có schema chặt chẽ, chạy được complex query bằng SQL, hiệu năng tốt, nhưng khá cứng nhắc, và phù hợp nhất với dữ liệu có cấu trúc (structured data).

Document store lưu thông tin dưới dạng document: mỗi cá nhân có một document riêng, mọi thông tin về cá nhân đó nằm trong file đó. Các file này có thể ở bất kỳ định dạng hay cấu trúc nào, và thay đổi trên một file không ảnh hưởng các file khác. Document store thường lưu dữ liệu ở định dạng JSON. So với relational database, nó thường không cần định nghĩa schema, bị hạn chế khi chạy complex query join nhiều bảng, hiệu năng tốt, dễ thay đổi cấu trúc, và phù hợp nhất với dữ liệu bán cấu trúc (semi-structured data).

Key-value store là loại lưu trữ thứ ba, siêu đơn giản: lưu một value ứng với một key. Ví dụ key là name, value là John; key khác là location, value là New York; key age, value 45; key salary, value 5000. Cũng lưu được dữ liệu phức tạp hơn, với key là user:John Doe và value là một tập property hoặc cả một JSON document.

So với các mô hình lưu trữ khác, key-value store không nhất thiết có schema, không hỗ trợ complex query, nhưng tra cứu cực nhanh: lưu được gần như bất kỳ thứ gì mà không phá vỡ cấu trúc khác hay phải lo về data structure. Vì vậy nó phù hợp nhất cho các lookup đơn giản, nhanh.

3 mô hình lưu trữ: Relational vs Document vs Key-Value (etcd)Relational (SQL)name | age | salaryJohn | 45 | 5000Mary | 30 | (trống)Thêm cột mới → ảnh hưởngmọi hàng, ô trống nếu thiếu.Document (JSON){ name: John,age: 45 }{ name: Mary,grade: A }Mỗi document độc lập —field tự do, không cần giống nhau.Key-Value (etcd)name → Johnage → 45location → NYSiêu đơn giản, tra cứu cựcnhanh — đúng mô hình etcd dùng.Kubernetes chỉ cần tra cứu nhanh theo path, không cần query phức tạp — nên chọn key-value.

etcd là một key-value store thuộc loại này, distributed và reliable.

Cài đặt và dùng thử etcd​

Cách cài đặt và bắt đầu với etcd: tải binary, giải nén, và chạy. Tải binary phù hợp với hệ điều hành từ trang GitHub Releases, giải nén, và chạy executable etcd. Khi chạy etcd, nó khởi động một service lắng nghe trên port 2379 theo mặc định, và đó là etcd server. Đây là cách chạy etcd server đơn giản nhất; thực tế nên chạy nó như một system service hoặc như một pod trên Kubernetes cluster.

Client mặc định đi kèm etcd là etcd control client, hay etcdctl, một command-line client cho etcd. Dùng nó để lưu và truy xuất key-value pair.

Lưu một cặp key-value:

etcdctl put key1 value1
# Output minh họa
OK

Truy xuất dữ liệu đã lưu:

etcdctl get key1
# Output minh họa
key1
value1

(Output minh họa — etcdctl trả về key rồi tới value trên 2 dòng riêng, đúng hành vi thật của lệnh get.)

Xem thêm các option:

etcdctl
# Output minh họa (rút gọn)
NAME:
etcdctl - A simple command line client for etcd3.

USAGE:
etcdctl [flags]

COMMANDS:
get Gets the key or a range of keys
put Puts the given key into the store
del Removes the specified key or range of keys
...

(Output minh họa, rút gọn — danh sách lệnh đầy đủ dài hơn nhiều.)

Lịch sử phiên bản etcd​

Có thể sẽ gặp các phiên bản command khác nhau khi tìm hiểu etcd và các bài viết liên quan trực tuyến, nên cần hiểu lịch sử các bản release của etcd để biết điều gì thay đổi khi nào.

  • Phiên bản đầu tiên của etcd, v0.1, được release vào tháng 8/2013.
  • Bản stable chính thức, v2.0, được release vào tháng 2/2015, cũng là lúc thuật toán đồng thuận Raft (Raft consensus algorithm) được thiết kế lại và hỗ trợ hơn 1.000 writes/giây.
  • Vào tháng 1/2017, etcd release version 3 với nhiều tối ưu hóa và cải thiện hiệu năng hơn.

Thay đổi lớn giữa version 2 và 3 nằm ở API: API version thay đổi, nên lệnh etcdctl cũng thay đổi theo. API cũ (v2) dùng lệnh etcdctl set và etcdctl get thay vì etcdctl put và get; ở v2 dùng rm để xóa value, ở v3 dùng del. Và v2 không hỗ trợ transaction, còn v3 có hỗ trợ transaction.

  • Vào tháng 11/2018, etcd trở thành CNCF incubating project, nghĩa là Cloud Native Computing Foundation tiếp quản việc quản trị và hỗ trợ dự án.
  • Nhiều bản release tiếp theo cho tới tháng 11/2020, khi etcd trở thành CNCF graduated project.
  • Vào tháng 6/2021, version 3.5 được release.

Bạn sẽ gặp blog, tài liệu online nói về API cũ dùng lệnh etcdctl set và get thay vì etcdctl put và get; chúng đang ở phiên bản cũ hơn. Xem version bằng lệnh:

etcdctl version
# Output minh họa
etcdctl version: 3.5.9
API version: 3.5

(Output minh họa — số version cụ thể chỉ mang tính ví dụ, điểm cần chú ý là dòng "API version" cho biết đang ở version 2 hay 3.)

Nhìn vào API version, sẽ thấy đang ở version 2 hay 3. Phiên bản mới hơn dùng lệnh put, get, và delete thay vì set, get, và rm.

Vai trò của etcd trong Kubernetes​

Datastore etcd lưu thông tin về cluster, như node, pod, config, secret, account, role, role binding, và nhiều thứ khác. Mọi thông tin thấy được khi chạy lệnh kubectl get đều đến từ etcd server. Mọi thay đổi thực hiện trên cluster (thêm node mới, deploy pod hoặc ReplicaSet) đều được cập nhật vào etcd server. Chỉ khi ghi xong vào etcd thì thay đổi đó mới được xem là hoàn tất.

Tùy vào cách cluster được thiết lập, etcd được deploy khác nhau. Có 2 kiểu deploy Kubernetes: một là deploy from scratch, hai là dùng tool kubeadm. Môi trường practice test dùng kubeadm, còn phần sau của tài liệu, khi tự setup cluster, sẽ setup from scratch, nên cần nắm khác biệt giữa 2 cách.

Nếu setup cluster from scratch, etcd được deploy bằng cách tự tải etcd binary, cài đặt binary, và tự cấu hình etcd như một service trên master node. Có nhiều option truyền vào service, một số liên quan tới certificate (phần sau của tài liệu có hẳn một mục về TLS certificate). Các option khác dùng để cấu hình etcd như một cluster. Option cần chú ý ngay bây giờ là advertised client URL: địa chỉ etcd lắng nghe, thường là IP của server và port 2379. Đây là URL cần cấu hình trên kube-apiserver khi nó reach tới etcd server.

Nếu setup cluster bằng kubeadm, kubeadm deploy etcd server dưới dạng một pod trong namespace kube-system (namespace là cách Kubernetes nhóm và cô lập tài nguyên bên trong cùng một cluster; kube-system là namespace riêng Kubernetes dùng cho các component nội bộ của chính nó, và phần Namespaces của tài liệu sẽ bàn chi tiết hơn). Có thể khám phá etcd database bằng utility etcdctl bên trong pod đó. Để list toàn bộ key được lưu bởi Kubernetes:

etcdctl get / --prefix --keys-only
# Output minh họa (rút gọn)
/registry/minions/node01
/registry/pods/default/nginx-pod
/registry/replicasets/default/myapp-rs
/registry/deployments/default/frontend-deployment
...

(Output minh họa, rút gọn — cấu trúc đường dẫn /registry/<loại resource>/... đúng theo thật, danh sách key đầy đủ dài hơn nhiều.)

Kubernetes lưu dữ liệu theo một cấu trúc thư mục cụ thể. Thư mục gốc là registry, và bên dưới đó là các construct khác nhau của Kubernetes như Minions hay nodes, pods, ReplicaSets, Deployments, v.v.

Trong môi trường high availability, cluster có nhiều master node, và tương ứng có nhiều instance etcd trải trên các master node đó. Khi ấy phải đảm bảo các instance etcd biết về nhau bằng cách set đúng tham số trong cấu hình etcd service: option initial cluster là nơi chỉ định các instance khác nhau của etcd service.

ETCDCTL — Commands (tùy chọn)​

ETCDCTL là CLI tool dùng để tương tác với ETCD, qua 2 phiên bản API: Version 2 và Version 3. Mặc định nó dùng Version 2. Mỗi version có tập lệnh khác nhau.

Ví dụ, ETCDCTL version 2 hỗ trợ các lệnh sau:

etcdctl backup
etcdctl cluster-health
etcdctl mk
etcdctl mkdir
etcdctl set

Trong khi các lệnh khác nhau ở version 3:

etcdctl snapshot save
etcdctl endpoint health
etcdctl get
etcdctl put

Để set đúng version API, set biến môi trường ETCDCTL_API:

export ETCDCTL_API=3

Khi API version không được set, nó được coi là version 2, và các lệnh version 3 liệt kê ở trên sẽ không hoạt động. Khi API version được set là version 3, các lệnh version 2 liệt kê ở trên sẽ không hoạt động.

Ngoài ra, phải chỉ định đường dẫn tới các file certificate để ETCDCTL có thể authenticate tới ETCD API Server. Các file certificate có sẵn trên etcd-master tại đường dẫn sau (phần security của tài liệu sẽ bàn thêm về certificate):

--cacert /etc/kubernetes/pki/etcd/ca.crt
--cert /etc/kubernetes/pki/etcd/server.crt
--key /etc/kubernetes/pki/etcd/server.key

Vậy để các lệnh nói trên hoạt động, phải chỉ định version API của ETCDCTL và đường dẫn tới các file certificate. Dưới đây là dạng đầy đủ:

kubectl exec etcd-controlplane -n kube-system -- sh -c "ETCDCTL_API=3 etcdctl get / \
--prefix --keys-only --limit=10 / \
--cacert /etc/kubernetes/pki/etcd/ca.crt \
--cert /etc/kubernetes/pki/etcd/server.crt \
--key /etc/kubernetes/pki/etcd/server.key"
# Output minh họa
/registry/apiregistration.k8s.io/apiservices/v1.
/registry/apiregistration.k8s.io/apiservices/v1.admissionregistration.k8s.io
/registry/apiregistration.k8s.io/apiservices/v1.apps
/registry/clusterrolebindings/cluster-admin
/registry/clusterroles/admin
/registry/controllerrevisions/kube-system/kube-proxy-...
/registry/daemonsets/kube-system/kube-proxy
/registry/deployments/kube-system/coredns
/registry/minions/controlplane
/registry/namespaces/default
/registry/pods/kube-system/etcd-controlplane

(Output minh họa, rút gọn theo --limit=10 — mỗi dòng là 1 key theo đường dẫn /registry/<loại resource>/..., giá trị thật của các key này không hiển thị vì dùng --keys-only.)


5. Kube-apiserver​

Trước đó đã bàn rằng kube-apiserver là management component chính trong Kubernetes. Khi chạy một lệnh kubectl, thực chất kubectl đang reach tới kube-apiserver. kube-apiserver trước tiên authenticate request và validate nó, sau đó truy xuất dữ liệu từ etcd cluster và trả về thông tin được yêu cầu.

Không nhất thiết phải dùng command line kubectl; cũng có thể gọi API trực tiếp bằng cách gửi một POST request. Ví dụ tạo một Pod: request được authenticate trước, rồi validate. Sau đó API server tạo một pod object chưa gán vào node nào, cập nhật thông tin trong etcd server, và báo cho user biết pod đã được tạo.

Scheduler liên tục giám sát kube-apiserver và nhận ra có một pod mới chưa được gán node. Scheduler xác định đúng node để đặt pod mới, và giao tiếp lại với kube-apiserver. API server sau đó cập nhật thông tin trong etcd cluster. API server sau đó chuyển thông tin đó tới kubelet trên worker node phù hợp. kubelet tạo Pod trên node và chỉ thị container runtime engine deploy application image. Xong việc, kubelet cập nhật status ngược lại cho API server, và API server cập nhật dữ liệu vào etcd cluster.

Pattern tương tự được lặp lại mỗi khi có yêu cầu thay đổi. kube-apiserver là trung tâm của mọi tác vụ cần thực hiện để tạo thay đổi trong cluster.

kube-apiserver — trung tâm điều phối clusterkube-apiservertrung tâm điều phốikubectl / Usergửi request, nhận kết quảkube-schedulerchọn node phù hợp cho podkube-controller-managergiám sát & điều chỉnhetcdlưu trạng thái clusterkubeletnhận lệnh & triển khai podKhông component nào giao tiếp trực tiếp với nhau — tất cả đều đi qua kube-apiserverkube-apiserver là component duy nhất tương tác trực tiếp với etcd

Như vậy kube-apiserver chịu trách nhiệm authenticate và validate request, cũng như truy xuất và cập nhật dữ liệu trong etcd data store. Nó cũng là component duy nhất tương tác trực tiếp với etcd. Các component khác như scheduler, kube-controller-manager, và kubelet đều phải đi qua kube-apiserver để thực hiện cập nhật trong cluster ở mảng tương ứng của chúng.

Cài đặt và xem cấu hình kube-apiserver​

Nếu bootstrap cluster bằng tool kubeadm, không cần biết chi tiết này. Nhưng nếu setup theo cách thủ công (hard way), kube-apiserver có sẵn dưới dạng binary trên trang release của Kubernetes. Tải về và cấu hình để chạy như một service trên Kubernetes master node:

wget https://storage.googleapis.com/kubernetes-release/release/v1.xx.0/bin/linux/amd64/kube-apiserver

(URL minh họa — thay v1.xx.0 bằng version thật cần cài.)

kube-apiserver được chạy với rất nhiều tham số. Kiến trúc Kubernetes gồm nhiều component phối hợp và giao tiếp với nhau theo nhiều cách, nên chúng cần biết vị trí của nhau. Thêm vào đó là nhiều mode xác thực (authentication), phân quyền (authorization), mã hóa (encryption) và bảo mật khác nhau, nên danh sách option mới dài như vậy. Phần lớn option trong số đó là certificate dùng để bảo mật kết nối giữa các component (mục SSL/TLS Certificates sau này của tài liệu có hẳn một phần riêng cho chủ đề này).

Một option cần biết là --etcd-servers: nơi chỉ định vị trí của etcd server, và cũng là cách kube-apiserver kết nối tới nó. Định nghĩa service (rút gọn), kube-apiserver.service:

ExecStart=/usr/local/bin/kube-apiserver \
--advertise-address=${INTERNAL_IP} \
--allow-privileged=true \
--apiserver-count=3 \
--authorization-mode=Node,RBAC \
--bind-address=0.0.0.0 \
--client-ca-file=/var/lib/kubernetes/ca.pem \
--enable-admission-plugins=Initializers,NamespaceLifecycle,NodeRestriction,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota \
--enable-swagger-ui=true \
--etcd-cafile=/var/lib/kubernetes/ca.pem \
--etcd-certfile=/var/lib/kubernetes/kubernetes.pem \
--etcd-keyfile=/var/lib/kubernetes/kubernetes-key.pem \
--etcd-servers=https://127.0.0.1:2379 \
--event-ttl=1h \
--kubelet-certificate-authority=/var/lib/kubernetes/ca.pem \
--kubelet-client-certificate=/var/lib/kubernetes/kubernetes.pem \
--kubelet-client-key=/var/lib/kubernetes/kubernetes-key.pem \
--kubelet-https=true \
--runtime-config=api/all \
--service-account-key-file=/var/lib/kubernetes/service-account.pem \
--service-cluster-ip-range=10.32.0.0/24 \
...

(Nội dung minh họa, rút gọn — hai nhóm option đáng chú ý: --etcd-cafile/--etcd-certfile/--etcd-keyfile để kube-apiserver xác thực với etcd, và --kubelet-certificate-authority/--kubelet-client-certificate/--kubelet-client-key để kube-apiserver xác thực với kubelet trên worker node.)

Cách xem option của kube-apiserver trên một cluster có sẵn phụ thuộc vào cách cluster được setup:

Nếu setup bằng kubeadm, kubeadm deploy kube-apiserver dưới dạng pod trong namespace kube-system trên master node. Xem option trong pod definition file tại thư mục /etc/kubernetes/manifests:

cat /etc/kubernetes/manifests/kube-apiserver.yaml
# Output minh họa (rút gọn)
apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
namespace: kube-system
spec:
containers:
- name: kube-apiserver
image: k8s.gcr.io/kube-apiserver:v1.xx.0
command:
- kube-apiserver
- --advertise-address=192.168.1.10
- --allow-privileged=true
- --authorization-mode=Node,RBAC
- --client-ca-file=/etc/kubernetes/pki/ca.crt
- --etcd-servers=https://127.0.0.1:2379
...

(Output minh họa, rút gọn — danh sách option đầy đủ dài hơn nhiều, IP và version chỉ mang tính ví dụ.)

Trong setup không dùng kubeadm, inspect option bằng cách xem kube-apiserver service tại /etc/systemd/system, file kube-apiserver.service (nội dung như trong khối ExecStart ở trên). Cũng có thể xem process đang chạy và các option hiệu lực bằng cách list process trên master node và tìm kube-apiserver:

ps -aux | grep kube-apiserver
# Output minh họa (rút gọn)
root 3466 10.0 1.5 /usr/local/bin/kube-apiserver --advertise-address=192.168.1.10 --allow-privileged=true --authorization-mode=Node,RBAC --etcd-servers=https://127.0.0.1:2379 ...

(Output minh họa, rút gọn — cả 2 cách trên đều cho thấy cùng tập option đang chạy thật trên master node.)

kube-apiserver biết cách lưu và truy xuất trạng thái, nhưng bản thân nó không tự "hành động" khi có gì đó lệch khỏi trạng thái mong muốn. Vậy ai phát hiện khi node chết, khi pod thiếu, rồi tự sửa? Đó là việc của một nhóm process khác: controller.


6. Kube-controller-manager​

kube-controller-manager quản lý các controller khác nhau trong Kubernetes.

💡 Hình dung: một controller giống một văn phòng bên trong con tàu chủ (master ship), có tập trách nhiệm riêng. Một văn phòng lo việc giám sát các tàu và xử lý mỗi khi có tàu mới tới, tàu rời đi hay bị hủy. Văn phòng khác quản lý container trên các tàu, lo việc container bị hư hỏng hoặc rơi khỏi tàu. Các văn phòng này vừa liên tục theo dõi trạng thái của đội tàu, vừa ra tay khắc phục khi có sự cố.

Trong thuật ngữ Kubernetes, một controller là một process liên tục giám sát trạng thái của các component khác nhau trong hệ thống, và hoạt động để đưa toàn bộ hệ thống về trạng thái hoạt động mong muốn.

kube-controller-manager — một process, nhiều controller bên trongkube-controller-managermột process bao gồm nhiều controller bên trongNode Controllergiám sát & khôi phục nodeReplication Controllergiữ đúng số lượng podDeployment Controllerquản lý rollout & rollbackNamespace Controllerdọn dẹp resource khi xóa nsService Account Controllertạo service account & tokenPersistent Volume Controllergắn & giải phóng volume…và còn nhiều controller khác (Job, Endpoint, ReplicaSet, …)mỗi construct trong Kubernetes đều có một controller đứng sauCài kube-controller-manager là cài luôn toàn bộ các controller bên trong nó

Node controller​

Ví dụ, node controller chịu trách nhiệm giám sát trạng thái của các node và thực hiện hành động cần thiết để giữ ứng dụng tiếp tục chạy. Nó thực hiện việc này thông qua Kube API Server.

Node controller kiểm tra trạng thái của node mỗi 5 giây, nhờ vậy giám sát được sức khỏe của node. Nếu ngừng nhận heartbeat từ một node, nó chờ 40 giây rồi mới đánh dấu node đó là unreachable. Sau khi bị đánh dấu unreachable, node còn 5 phút để quay lại hoạt động. Hết 5 phút, các pod được gán cho node đó bị gỡ và cấp phát lại trên các node khỏe mạnh, nếu chúng thuộc một ReplicaSet.

Replication controller​

Controller tiếp theo là Replication Controller. Nó chịu trách nhiệm giám sát trạng thái của ReplicaSet và đảm bảo số lượng pod mong muốn luôn khả dụng tại mọi thời điểm trong tập đó. Nếu một pod chết, nó tạo pod khác.

Đó chỉ là 2 ví dụ; Kubernetes còn nhiều controller khác. Bất kỳ khái niệm nào bạn đã gặp trong Kubernetes, như deployments, services, namespaces, hay persistent volumes, cùng toàn bộ phần logic (intelligence) gắn vào các construct đó, đều được triển khai thông qua controller. Gần như mọi hành vi tự động của Kubernetes đều bắt nguồn từ một controller nào đó.

kube-controller-manager: cài đặt và cấu hình​

Vậy làm sao thấy các controller này, và chúng nằm ở đâu trong cluster? Tất cả được đóng gói vào một process duy nhất gọi là kube-controller-manager. Khi cài Kubernetes controller manager, các controller khác nhau cũng được cài theo.

Cách cài và xem Kubernetes controller manager: tải kube-controller-manager từ trang release của Kubernetes, giải nén và chạy như một service. Khi chạy, nó nhận một danh sách option, và đây là nơi tùy chỉnh controller. Một số setting mặc định của node-controller đã bàn ở trên, như node-monitor-period, grace period, và eviction timeout, đều đi vào đây dưới dạng option. Có thêm một option tên controllers để chỉ định controller nào được bật: mặc định tất cả đều bật, nhưng có thể chọn chỉ bật một số. Nếu một controller không hoạt động hoặc không tồn tại, đây là chỗ đầu tiên nên kiểm tra.

Cách xem option của service kube-controller-manager: nếu setup bằng tool kubeadm, kubeadm deploy kube-controller-manager dưới dạng pod trong namespace kube-system trên master node. Có thể list các pod hệ thống để xác nhận nó đang chạy:

kubectl get pods -n kube-system
# Output minh họa
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-78fcdf6894-hwrq9 1/1 Running 0 16m
kube-system coredns-78fcdf6894-rzhjr 1/1 Running 0 16m
kube-system etcd-master 1/1 Running 0 15m
kube-system kube-apiserver-master 1/1 Running 0 15m
kube-system kube-controller-manager-master 1/1 Running 0 15m
kube-system kube-proxy-lzt6f 1/1 Running 0 16m
kube-system kube-proxy-zm5qd 1/1 Running 0 16m
kube-system kube-scheduler-master 1/1 Running 0 15m
kube-system weave-net-29z42 2/2 Running 1 16m
kube-system weave-net-snmdl 2/2 Running 1 16m

(Output minh họa — tên pod có hậu tố ngẫu nhiên/tên node, số lượng và trạng thái chỉ mang tính ví dụ.)

Xem option trong pod definition file tại thư mục /etc/kubernetes/manifests:

cat /etc/kubernetes/manifests/kube-controller-manager.yaml
# Output minh họa (rút gọn)
spec:
containers:
- command:
- kube-controller-manager
- --address=127.0.0.1
- --cluster-signing-cert-file=/etc/kubernetes/pki/ca.crt
- --cluster-signing-key-file=/etc/kubernetes/pki/ca.key
- --controllers=*,bootstrapsigner,tokencleaner
- --kubeconfig=/etc/kubernetes/controller-manager.conf
- --leader-elect=true
- --root-ca-file=/etc/kubernetes/pki/ca.crt
- --service-account-private-key-file=/etc/kubernetes/pki/sa.key
- --use-service-account-credentials=true

(Output minh họa, rút gọn.)

Trong setup không dùng kubeadm, có thể inspect option bằng cách xem kube-controller-manager service tại /etc/systemd/system, file kube-controller-manager.service:

cat /etc/systemd/system/kube-controller-manager.service
# Output minh họa (rút gọn)
[Service]
ExecStart=/usr/local/bin/kube-controller-manager \
--address=0.0.0.0 \
--cluster-cidr=10.200.0.0/16 \
--cluster-name=kubernetes \
--cluster-signing-cert-file=/var/lib/kubernetes/ca.pem \
--cluster-signing-key-file=/var/lib/kubernetes/ca-key.pem \
--kubeconfig=/var/lib/kubernetes/kube-controller-manager.kubeconfig \
--leader-elect=true \
--root-ca-file=/var/lib/kubernetes/ca.pem \
--service-account-private-key-file=/var/lib/kubernetes/service-account-key.pem \
--service-cluster-ip-range=10.32.0.0/24 \
--use-service-account-credentials=true \
--v=2
Restart=on-failure
RestartSec=5

(Output minh họa, rút gọn.)

Cũng có thể xem process đang chạy và option hiệu lực bằng cách list process trên master node và tìm kube-controller-manager:

ps -aux | grep kube-controller-manager
# Output minh họa (rút gọn)
root 3520 8.0 1.2 /usr/local/bin/kube-controller-manager --address=0.0.0.0 --cluster-cidr=10.200.0.0/16 --leader-elect=true --use-service-account-credentials=true ...

(Output minh họa, rút gọn — cả 3 cách trên đều cho thấy cùng tập option đang chạy thật trên master node.)


7. Kube-scheduler​

Phần trên đã nói Kubernetes scheduler chịu trách nhiệm lên lịch (schedule) Pod trên các node. Nhưng scheduler chỉ quyết định Pod nào đi lên node nào, chứ không tự đặt Pod lên node. Việc đặt thuộc về kubelet, tức thuyền trưởng trên tàu.

Vì sao cần scheduler?​

Khi có nhiều tàu và nhiều container, cần đảm bảo đúng container lên đúng tàu. Tàu và container có nhiều kích thước khác nhau, nên phải chọn tàu đủ dung lượng chứa. Các tàu lại đi tới những điểm đến khác nhau, nên container phải lên đúng con tàu đi đúng nơi cần tới.

Trong Kubernetes, scheduler quyết định Pod được đặt lên node nào dựa trên một số tiêu chí nhất định. Có thể có pod với resource requirement khác nhau, và có thể có node trong cluster dành riêng cho một số ứng dụng nhất định.

Scheduler hoạt động qua 2 giai đoạn​

Scheduler nhìn vào từng pod và tìm node tốt nhất cho nó. Lấy ví dụ một pod có yêu cầu CPU và memory nhất định. Scheduler đi qua 2 giai đoạn để xác định node phù hợp.

Giai đoạn 1 (Filter): scheduler lọc bỏ các node không phù hợp với profile của Pod, ví dụ node không đủ tài nguyên CPU và memory mà pod yêu cầu. Trong hình dưới, 2 node nhỏ đầu tiên bị loại, còn lại 2 node có thể đặt pod lên.

Giai đoạn 2 (Rank): còn lại 2 node, scheduler chọn node nào? Nó xếp hạng các node bằng một priority function, gán điểm theo thang từ 0 đến 10. Ví dụ, scheduler tính lượng tài nguyên còn trống trên node sau khi đặt pod lên. Node bên phải còn 6 CPU trống nếu nhận pod, nhiều hơn node bên trái 4 CPU, nên được xếp hạng cao hơn và thắng.

kube-scheduler — chọn node cho Pod qua 2 giai đoạnPod — cần CPU: 10Giai đoạn 1 — Filter: loại node không đủ CPUNode A4 CPU✕không đủ CPUNode B4 CPU✕không đủ CPUNode C12 CPU✓ đủ điều kiệnNode D16 CPU✓ đủ điều kiệnGiai đoạn 2 — Rank theo CPU trốngNode Ctổng CPU: 12CPU trống: 2bị loại ở vòng rankNode Dtổng CPU: 16CPU trống: 6🏆 Thắngnhiều CPU trống hơnNode D thắng vì có nhiều CPU trống hơn sau khi đặt Pod (6 so với 2)

Đó là cách scheduler hoạt động ở mức tổng quan. Các bước này đều tùy chỉnh được, và bạn cũng có thể tự viết scheduler riêng. Còn nhiều chủ đề khác cần tìm hiểu, như resource requirement, limit, taints và tolerations, node selector, affinity rule, v.v. Tài liệu có hẳn một mục riêng dành cho scheduling để bàn chi tiết từng thứ.

Cài đặt và cấu hình kube-scheduler​

Cách cài kube-scheduler: tải binary kube-scheduler từ trang release của Kubernetes, giải nén và chạy như một service. Khi chạy như một service, chỉ định file cấu hình scheduler.

Cách xem option của service kube-scheduler: nếu setup bằng tool kubeadm, kubeadm deploy kube-scheduler dưới dạng pod trong namespace kube-system trên control plane node. Xem option trong pod definition file tại thư mục /etc/kubernetes/manifests:

cat /etc/kubernetes/manifests/kube-scheduler.yaml
# Output minh họa (rút gọn)
spec:
containers:
- command:
- kube-scheduler
- --authentication-kubeconfig=/etc/kubernetes/scheduler.conf
- --authorization-kubeconfig=/etc/kubernetes/scheduler.conf
- --bind-address=127.0.0.1
- --kubeconfig=/etc/kubernetes/scheduler.conf
- --leader-elect=true

(Output minh họa, rút gọn.)

Cũng có thể xem process đang chạy và option hiệu lực bằng cách list process trên control plane node và tìm kube-scheduler:

ps -aux | grep kube-scheduler
# Output minh họa (rút gọn)
root 3610 3.0 0.9 /usr/local/bin/kube-scheduler --bind-address=127.0.0.1 --kubeconfig=/etc/kubernetes/scheduler.conf --leader-elect=true ...

(Output minh họa, rút gọn — cả 2 cách trên đều cho thấy cùng tập option đang chạy thật trên control plane node.)


8. Kubelet​

Quay lại hình ảnh thuyền trưởng trên tàu: dẫn dắt mọi hoạt động trên tàu, và lo mọi thủ tục giấy tờ cần thiết để tàu trở thành một phần của cluster. Thuyền trưởng là đầu mối liên lạc duy nhất với tàu chủ, load hoặc unload container theo chỉ thị của scheduler trên master, và gửi báo cáo định kỳ về trạng thái của tàu cùng container trên đó.

kubelet trên Kubernetes worker node đăng ký node đó với Kubernetes cluster. Khi nhận chỉ thị load một container hay pod lên node, nó yêu cầu container runtime engine (có thể là Docker) pull image cần thiết và chạy một instance. kubelet sau đó tiếp tục giám sát trạng thái của pod và các container trong nó, và báo cáo về kube-apiserver theo định kỳ.

Cài đặt kubelet​

Nếu dùng tool kubeadm để deploy cluster, nó không tự động deploy kubelet, khác với các component khác. Bạn luôn phải tự cài kubelet thủ công trên các worker node: tải installer, giải nén, và chạy như một service.

Có thể xem process kubelet đang chạy và các option hiệu lực bằng cách list process trên worker node và tìm kubelet.

Phần sau của tài liệu sẽ đi sâu hơn về kubelet: cách cấu hình kubelet, generate certificate, và cách TLS bootstrap kubelet.


9. Kube-proxy​

Bên trong một Kubernetes cluster, mọi pod đều có thể reach tới mọi pod khác. Điều này đạt được bằng cách deploy một giải pháp pod networking cho cluster. Pod network là một mạng ảo nội bộ trải trên toàn bộ node trong cluster, mà mọi pod kết nối vào. Thông qua mạng này, chúng có thể giao tiếp với nhau. Có nhiều giải pháp để deploy một mạng như vậy.

Ví dụ, có một web application deploy trên node đầu tiên và database application deploy trên node thứ hai. Web app reach tới database được bằng IP của pod, nhưng không có gì đảm bảo IP của database pod luôn giữ nguyên. Cách tốt hơn là dùng một service để expose database application trên toàn cluster. Web application khi đó truy cập database bằng tên service, ví dụ db. Service cũng được gán một địa chỉ IP. Bất cứ khi nào một pod reach tới service bằng IP hay tên của nó, service forward traffic tới pod backend, ở đây là database.

Nhưng service này là gì, và nó lấy IP ở đâu? Service không gia nhập pod network, vì service không phải một "vật" có thân xác: nó không phải container như pod, nên không có interface hay process nào đang lắng nghe. Nó là một component ảo chỉ tồn tại trong bộ nhớ của Kubernetes. Trong khi đó service lại phải truy cập được từ mọi node trên toàn cluster. Chỗ này là lúc kube-proxy vào cuộc.

Kube-proxy hoạt động ra sao​

Kube-proxy là một process chạy trên mỗi node trong Kubernetes cluster. Công việc của nó là tìm các service mới, và mỗi khi một service mới được tạo, nó tạo các rule phù hợp trên mỗi node để forward traffic tới các service đó, tới pod backend.

Một cách nó thực hiện việc này là dùng rule IP tables (iptables: cơ chế lọc gói tin và NAT tích hợp sẵn trong nhân Linux, cho phép định nghĩa rule chuyển hướng traffic dựa trên địa chỉ IP/port). Nó tạo một IP tables rule trên mỗi node trong cluster, để forward traffic hướng tới IP của service, ví dụ 10.96.0.12, sang IP của pod đứng sau, ví dụ 10.32.0.15. Đó là cách kube-proxy cấu hình một service.

kube-proxy — dùng iptables đưa traffic từ service IP tới pod IPPod NetworkNode 1 — Web App10.32.0.14pod web appNode 2 — Database10.32.0.15pod databasekube-proxykube-proxyservice: db10.96.0.1210.96.0.1210.32.0.14iptables rule trỏ vào pod ở Node 110.96.0.1210.32.0.15iptables rule trỏ vào pod ở Node 2 (ví dụ trên)

Phần sau của tài liệu có hẳn một mục lớn dành riêng cho networking, bàn thêm nhiều về service, kube-proxy và pod networking. Đây mới chỉ là overview ở mức tổng quan.

Cài đặt kube-proxy​

Cách cài kube-proxy: tải binary kube-proxy từ trang release của Kubernetes, giải nén, và chạy như một service. Tool kubeadm deploy kube-proxy dưới dạng pod trên mỗi node, cụ thể là một DaemonSet, nên luôn có đúng một pod trên mỗi node trong cluster.

Vậy là đã có overview mức tổng quan về các component chính của Kubernetes, gồm cả control plane lẫn component ở cấp node như kube-proxy vừa nêu. Các mục sau của tài liệu sẽ xem xét từng component chi tiết hơn.


Nguồn tham khảo​

Nguồn gốc: Khóa "Certified Kubernetes Administrator (CKA)" — phần "Core Concepts" (giới thiệu phần Core Concepts, kiến trúc cluster, container runtime Docker/containerd/CRI, ETCD, kube-apiserver, kube-controller-manager, kube-scheduler, kubelet, kube-proxy), nền tảng KodeKloud. Giảng viên: Mumshad Mannambeth.

Repo ghi chú, link tài liệu, và đáp án các practice question của toàn bộ khóa học: kodekloudhub/certified-kubernetes-administrator-course.

Fact-check:

  • node-monitor-period mặc định 5s, node-monitor-grace-period mặc định 40s trên kube-controller-manager — 2026-08-19, Kubernetes — kube-controller-manager reference
  • Từ Kubernetes 1.18, cơ chế gỡ Pod khỏi node unreachable chuyển sang taint-based eviction — mặc định tolerationSeconds=300 (5 phút) cho taint node.kubernetes.io/not-ready/unreachable, điều khiển qua --default-not-ready-toleration-seconds/--default-unreachable-toleration-seconds trên kube-apiserver — 2026-08-19, kubernetes/kubernetes#74651
  • Kubernetes 1.24 gỡ Dockershim, đổi default socket từ dockershim.sock sang cri-dockerd.sock — 2026-08-19, cri-tools PR #869, issue #868
  • NodePort range mặc định 30000–32767 (--service-node-port-range) — 2026-08-19, Kubernetes — Service