Top 40+ câu hỏi phỏng vấn Kubernetes phổ biến

Khi hạ tầng chuyển dịch lên cloud-native, nhu cầu tuyển dụng kỹ sư hiểu Kubernetes ngày càng tăng. Phỏng vấn Kubernetes không chỉ xoay quanh lý thuyết, mà còn bao gồm các câu hỏi kiểm tra về tư duy kỹ thuật và khả năng vận hành hệ thống thực tế. Nếu bạn đang ứng tuyển cho các vị trí liên quan đến DevOps, Cloud và microservices hiện đại, thì bộ câu hỏi phỏng vấn Kubernetes dưới đây sẽ giúp bạn ôn tập đầy đủ, bài bản, đúng trọng tâm theo từng cấp độ.

Đọc bài viết sau để được hướng dẫn trả lời:

  • Câu hỏi phỏng vấn Kubernetes sơ cấp (Junior level)
  • Câu hỏi phỏng vấn Kubernetes trung cấp (Intermediate Level)
  • Câu hỏi phỏng vấn Kubernetes cao cấp (Advanced Level)

Tổng quan về Kubernetes

Kubernetes (viết tắt là K8s) là một hệ thống mã nguồn mở để “orchestrate” (tự động quản lý) các ứng dụng chạy trong container. Kubernetes được xây dựng dựa trên kinh nghiệm hơn 15 năm vận hành vận hành container ở quy mô siêu lớn của Google. Từ năm 2014 nó trở thành một dự án mã nguồn mở được quản lý bởi Cloud Native Computing Foundation (CNCF).

Kubernetes thường dùng để:

  • Tự động deploy, scale và quản lý các ứng dụng được container hóa, tùy theo nhu cầu dựa trên cơ chế cấu hình theo kiểu khai báo (declarative configuration).
  • Hỗ trợ service discovery và load balancing: Giúp các phần của ứng dụng (chạy ở container khác nhau) có thể liên lạc với nhau một cách ổn định thông qua DNS nội bộ hoặc Service IP, đồng thời phân phối tải hợp lý.
  • Quản lý & phân bổ tài nguyên linh hoạt (CPU, memory, storage…), bao gồm cả resource requests/limits, giúp tận dụng hạ tầng hiệu quả mà vẫn giữ độ ổn định cao.
  • Chạy linh hoạt trên nhiều môi trường: Có thể chạy trên máy chủ vật lý, máy ảo, public cloud (AWS EKS, GKE, AKS), private cloud hoặc môi trường hybrid, giúp ứng dụng “di động” giữa các cơ sở hạ tầng khác nhau.
  • Tăng tính ổn định và độ tin cậy với cơ chế self-healing: Nếu một container hoặc node bị lỗi, Kubernetes có khả năng self-healing – tự khởi động lại, tái lập container, reschedule Pod sang node khỏe mạnh, đảm bảo service vẫn chạy thông suốt.

Đọc chi tiết: Kubernetes là gì: Toàn diện kiến thức Kubernetes nền tảng cần biết

Câu hỏi phỏng vấn Kubernetes sơ cấp (Junior level)

Pod, Container là gì? Sự khác nhau giữa Pod và Container?

  • Container là đơn vị thực thi nhẹ, độc lập, gồm toàn bộ môi trường cần thiết để chạy một ứng dụng: mã nguồn, runtime, thư viện, dependencies. Container giúp đóng gói ứng dụng theo cách cô lập, đảm bảo rằng ứng dụng chạy nhất quán trên nhiều môi trường khác nhau, bất kể môi trường host có khác nhau ra sao.

Khi chạy độc lập (không qua orchestrator như Kubernetes), mỗi container có network namespace riêng, IP riêng, và cần cấu hình riêng để giao tiếp với container khác.

  • Pod: Kubernetes không chạy container trực tiếp, nó chạy Pod – đơn vị triển khai nhỏ nhất và đơn vị scheduling cơ bản. Pod đại diện cho một hoặc nhiều container chạy cùng nhau, chia sẻ chung mạng (network namespace) và lưu trữ (volumes). Các container bên trong cùng một Pod có thể giao tiếp qua localhost, dùng chung một IP address duy nhất và port space. 

Về bản chất, Pod là nơi các container có quan hệ chặt chẽ được gom lại để chạy cùng vòng đời. (ví dụ container ứng dụng chính + container sidecar hỗ trợ logging, monitoring, proxy, hoặc init containers cho các tác vụ initialization).

Đọc chi tiết: Kubernetes architecture: Tìm hiểu tổng quan kiến trúc Kubernetes A-Z cho người mới

Bảng so sánh sự khác biệt Pod và Container

Tiêu chíPodContainer
Đơn vị quản lý trong KubernetesPod là đơn vị nhỏ nhất mà Kubernetes tạo, lên lịch và quản lý.Container nằm bên trong Pod; Kubernetes không quản lý container riêng lẻ mà thông qua Pod.
Số lượngMột Pod có thể chứa một hoặc nhiều container (thường là 1 main container + optional sidecar/init containers).Một container là một thực thể đơn, chứa một ứng dụng (hoặc process).
Mạng & giao tiếpCác container trong cùng Pod chia sẻ mạng, dùng chung IP, port; giao tiếp qua localhost.Container riêng biệt có mạng riêng; không tự động chia sẻ mạng với container khác trừ khi được cấu hình đặc biệt.
Lưu trữ / volumePod có thể khai báo shared volumes, tất cả container trong Pod truy cập chung storage thông qua volumeMounts.Container có filesystem riêng (container image + overlay filesystem), không share volume tự động.
Mục đích sử dụngDùng để nhóm, phối hợp & quản lý các container có liên quan chặt chẽ như app + sidecar, hoặc app + helper.Dùng để chạy một ứng dụng/process độc lập, cùng môi trường chuẩn từ image.
Quản lý vòng đờiKubernetes quản lý Pod (scheduling, restart, scaling, volume, networking…). Pod có trạng thái: Pending, Running, Succeeded, Failed, Unknown.Container runtime quản lý container đơn lẻ; nếu muốn orchestration cần Kubernetes/Pod/Workload resource.

Deployment trong Kubernetes là gì? Hoạt động như thế nào?

Trong Kubernetes, Deployment là một Workload API object dùng để declarative (khai báo) định nghĩa cách bạn muốn triển khai và quản lý các bản sao của ứng dụng (thông qua ReplicaSets và Pods). 

Khi tạo một Deployment, chúng ta sẽ khai báo desired state (trạng thái mong muốn) của ứng dụng: 

  • Bao nhiêu bản sao (replicas) của Pod
  • Container image nào và version/tag
  • Cấu hình như thế nào (environment variables, volumes, ports…)
  • Update strategy (RollingUpdate hoặc Recreate)
  • Health checks (liveness/readiness probes)

→ Kubernetes sẽ đảm bảo trạng thái thực tế khớp với trạng thái mong muốn đó.

→ Sau đó, Deployment Controller sẽ đảm bảo trạng thái thực tế (actual state)khớp với trạng thái mong muốn đó thông qua reconciliation loop.

Vì sao Deployment được xem là lớp trừu tượng cao hơn ReplicaSet?

Vì Deployment cho phép quản lý toàn bộ vòng đời ứng dụng mà không cần thao tác thủ công với từng Pod. Thay vì tự tạo, xoá hay thay thế Pod, người dùng chỉ cần khai báo trạng thái mong muốn, còn Kubernetes sẽ tự động xử lý phần còn lại.

Service trong Kubernetes là gì? Giúp giải quyết vấn đề gì?

Trong Kubernetes, Service là một abstraction về mạng, cung cấp một điểm truy cập ổn định (stable network endpoint) để truy cập vào các Pod. 

  • Service tạo ra IP address và DNS name cố định

Khi bạn tạo một Service → Bạn định nghĩa selector (ví dụ một label mà Pod cần có) 

→ Kubernetes sẽ tự động theo dõi các Pod phù hợp và đảm bảo rằng mọi traffic hướng đến Service sẽ được chuyển tiếp đến một (hoặc nhiều) Pod backend tương ứng. 

Nhờ cơ chế này, dù Pod có thể bị tạo mới, xoá, scale hoặc di chuyển sang node khác, thì địa chỉ truy cập của ứng dụng vẫn giữ nguyên, cho phép ứng dụng được truy cập mà không phụ thuộc vào Pod cụ thể nào. Điều này giúp hệ thống ổn định và resilient hơn, đồng thời tránh việc phải “gắn cứng” IP hay Pod cụ thể trong code hoặc config.

  • Service cũng hỗ trợ load balancing nội bộ: nếu có nhiều Pod tham gia backend, Service sẽ phân phối traffic giữa các Pod đó (mặc định sử dụng thuật toán round-robin), giúp cân bằng tải và tăng độ sẵn sàng.
  • Service có thể định nghĩa chế độ mạng khác nhau tùy nhu cầu:
    • Service nội bộ giữa các Pod/ứng dụng trong cluster (Cluster-internal service).
    • Service giúp expose ứng dụng ra bên ngoài (external access), cho phép người dùng bên ngoài hoặc các hệ thống khác truy cập.

Service có gì khác với Deployment?  

  • Deployment chịu trách nhiệm quản lý vòng đời của Pod. Nó định nghĩa trạng thái mong muốn (desired state), tập trung vào việc triển khai, cập nhật và duy trì Pod ổn định trong cluster.
  • Ngược lại, Service không quản lý Pod mà cung cấp một điểm truy cập mạng ổn định đến các Pod do Deployment tạo ra. Điều này giúp ứng dụng luôn sẵn sàng và có khả năng giao tiếp ổn định trong môi trường động của Kubernetes.

Tóm tắt:

  • Deployment = Quản lý Pod: tạo mới, cập nhật, scale, rollback.
  • Service = Quản lý truy cập: cung cấp endpoint cố định và cân bằng tải đến các Pod.

Bảng so sánh Service và Deployment:

Tiêu chíServiceDeployment
Chức năng chínhTriển khai và quản lý vòng đời Pod (tạo, cập nhật, scale, rollback).Cung cấp endpoint mạng ổn định để truy cập Pod và phân phối lưu lượng (load balancing).
Quản lý PodCó – Deployment điều khiển ReplicaSet để duy trì số lượng Pod mong muốn.Không – Service chỉ định tuyến traffic đến Pod, không kiểm soát vòng đời.
Ổn định địa chỉ truy cậpKhông cung cấp địa chỉ cố định, Pod có thể thay đổi IP khi restart.Có – Service tạo ra DNS và địa chỉ ảo cố định, không bị ảnh hưởng khi Pod thay đổi.
Load BalancingKhông hỗ trợ.Có – Service phân phối lưu lượng đến nhiều Pod backend.
Cập nhật ứng dụngHỗ trợ rolling update, rollback, versioning.Không hỗ trợ cập nhật ứng dụng; chỉ xử lý routing và networking.
Loại tài nguyênWorkload Controller.Networking Abstraction.
Sử dụng khi nào?Khi bạn cần triển khai ứng dụng và đảm bảo Pod hoạt động ổn định.Khi bạn cần expose ứng dụng hoặc tạo kết nối ổn định giữa các Pod/ dịch vụ.

Làm sao để xem log của Pod?  

Cách chính thức là sử dụng lệnh kubectl logs:

  • Pod chỉ có một container
kubectl logs <pod-name>

Ví dụ:

kubectl logs my-pod
  • Pod có nhiều container

Bạn cần chỉ định container cụ thể bằng flag -c hoặc --container:

kubectl logs <pod-name> -c <container-name>

Cách này thường dùng khi:

  • Cần debug lỗi ứng dụng, kiểm tra exception hoặc warning từ container.
  • Muốn theo dõi hành vi ứng dụng theo thời gian thực, đặc biệt trong quá trình deploy hoặc test.
  • Pod hoặc container bị restart, dùng –previous để tìm nguyên nhân gốc rễ.

Các tùy chọn thường dùng khi xem log

Tuỳ chọnÝ nghĩa
-f / --followTheo dõi log theo thời gian thực, tương tự lệnh tail -f
--tail=<số_dòng>Chỉ hiển thị một số dòng log cuối cùng, hữu ích khi cần xem nhanh log mới nhất
--since=<duration> hoặc --since-time=<timestamp>Lấy log trong một khoảng thời gian nhất định trước đó, giúp khoanh vùng sự kiện lỗi
-p / --previousXem log của container trước khi bị restart, rất hữu ích khi debug các lỗi khiến Pod crash

ConfigMap và Secret khác nhau ra sao?  

Trong Kubernetes, ConfigMap và Secret đều dùng để cung cấp cấu hình cho ứng dụng, nhưng khác nhau về mục tiêu và cách xử lý dữ liệu.

ConfigMap

  • Lưu trữ dữ liệu cấu hình dạng không nhạy cảm
  • Lưu dữ liệu dưới dạng text thuần (plain text), không có mã hóa. 
  • Thích hợp cho các giá trị cấu hình như URL dịch vụ, tên môi trường, tham số ứng dụng, config files (như nginx.conf, application.properties). 
  • Thường được sử dụng rộng rãi trong mọi loại workload.

Secret 

  • Chứa thông tin nhạy cảm như mật khẩu, token hoặc khóa API.
  • Được mã hóa bằng Base64 (Base64 chỉ là encoding, không phải encryption thực sự)và Kubernetes áp dụng các cơ chế bảo mật bổ sung để hạn chế quyền truy cập vào loại dữ liệu này. 
  • Đảm bảo rằng thông tin nhạy cảm được tách biệt khỏi mã nguồn và không bị lộ khi triển khai ứng dụng.

Tóm lại:

  • ConfigMap → chứa cấu hình không nhạy cảm, không mã hóa.
  • Secret → chứa dữ liệu nhạy cảm, được mã hóa và bảo vệ nghiêm ngặt hơn.

Bảng tóm tắt so sánh ConfigMap và Secret

Tiêu chíConfigMapSecret
Mục đích sử dụngLưu trữ cấu hình không nhạy cảm cho ứng dụng.Lưu trữ dữ liệu nhạy cảm như mật khẩu, token, khóa API.
Mức độ bảo mậtKhông có mã hóa, lưu dạng plain text.Dữ liệu được mã hóa ở dạng Base64, có thể được mã hóa khi lưu trữ (encryption at rest) và được quản lý bằng cơ chế RBAC nghiêm ngặt hơn.
Loại dữ liệu lưu trữCác tham số cấu hình, giá trị môi trường, đường dẫn, tên dịch vụ…Thông tin nhạy cảm: passwords, OAuth tokens, SSH keys, TLS certs
Cách Kubernetes xử lýKubernetes không áp dụng bảo vệ đặc biệt vì dữ liệu không nhạy cảm.Được mount dưới dạng tmpfs, được ẩn trong log và event, đồng thời hỗ trợ mã hóa khi lưu trữ (encryption at rest)
Sử dụng trong PodĐược mount vào Pod dưới dạng biến môi trường (environment variables) hoặc dưới dạng volume (file)Tương tự như ConfigMap nhưng được mount trực tiếp vào bộ nhớ (tmpfs), không ghi dữ liệu xuống ổ đĩa.
Thích hợp choCấu hình chung của ứng dụng, không cần bảo vệ.Các giá trị bí mật bắt buộc phải được tách khỏi mã nguồn.

Cách scale Deployment lên nhiều replicas?  

Để scale Deployment lên nhiều replicas trong Kubernetes, bạn chỉ cần thay đổi số lượng Pod mà Deployment phải duy trì. Quá trình scale được thực hiện thông qua ReplicaSet – thành phần chịu trách nhiệm đảm bảo số Pod luôn khớp với trạng thái mong muốn. Khi bạn điều chỉnh số lượng replicas, Kubernetes sẽ tự động tạo mới hoặc xóa bớt Pod tương ứng để duy trì đúng số lượng.

Bạn có thể scale Deployment theo hai cách:

Cách 1 – Nhanh nhất và phổ biến nhất

Scale trực tiếp bằng lệnh:

kubectl scale deployment <tên-deployment> --replicas=<số-lượng>

Ví dụ:

kubectl scale deployment nginx-deploy --replicas=5

Ngay sau khi chạy lệnh, Kubernetes sẽ cập nhật ReplicaSet và tạo thêm Pod để đạt đủ 5 replicas.

Cách 2: Scale bằng cách chỉnh sửa file YAML

spec:

  replicas: 5

Sau đó apply lại:

kubectl apply -f deployment.yaml

Việc scale qua YAML phù hợp khi bạn quản lý cấu hình bằng GitOps hoặc muốn kiểm soát cấu hình lâu dài.

Dù dùng cách nào, Kubernetes sẽ luôn đảm bảo số lượng Pod bằng đúng giá trị replicas mà bạn khai báo nhờ cơ chế tự đồng bộ trạng thái giữa Deployment và ReplicaSet.

Khi nào nên dùng nhiều Namespace?  

Sử dụng nhiều Namespace trong Kubernetes giúp tổ chức, phân tách môi trường và quản lý tài nguyên một cách rõ ràng, đặc biệt phù hợp khi có nhiều ứng dụng, nhiều team, hoặc nhiều môi trường khác nhau. 

Dưới đây là các trường hợp cụ thể nên dùng nhiều Namespace:

  • Khi có nhiều ứng dụng / micro-services chạy cùng cluster → đặt mỗi ứng dụng vào một Namespace riêng giúp ngăn cách các resource (Pod, Service, ConfigMap, Secret…) tránh xung đột về tên, cấu hình hay truy cập mạng nội bộ.
  • Khi cần phân chia môi trường (dev / staging / prod): Mỗi môi trường đặt trong một Namespace riêng giúp dễ kiểm soát quyền, cấu hình và tránh ảnh hưởng chéo giữa môi trường.
  • Khi muốn phân quyền truy cập & quản lý riêng biệt theo Team / Module: Namespace giúp bạn áp dụng quyền Role-Based Access Control (RBAC) một cách rõ ràng theo team hoặc module. Mỗi team chỉ nhìn thấy resource trong Namespace của họ, giúp giới hạn phạm vi thao tác, dễ audit và kiểm soát ai deploy gì, sử dụng bao nhiêu resource,…
  • Khi cần giới hạn tài nguyên hoặc quota cho từng nhóm dịch vụ: Bạn có thể áp đặt ResourceQuota, LimitRange trên mỗi Namespace, giúp ngăn một ứng dụng chiếm hết CPU, memory của toàn cluster, đảm bảo tính công bằng giữa nhiều dịch vụ. Hữu ích khi cluster dùng chung nhiều dịch vụ.
  • Khi muốn tách biệt mạng, service discovery và cô lập lỗi / ảnh hưởng: Namespace giúp tránh xung đột service discovery nhờ phạm vi tên riêng (<service>.<namespace>.svc.cluster.local) và tạo nền tảng để cô lập lỗi tốt hơn. Khi một dịch vụ trong Namespace gặp sự cố, các Namespace khác thường không bị ảnh hưởng trực tiếp.

Hãy nêu một vài kinh nghiệm dùng Namespace mà bạn có.

  • Để đạt được mức độ bảo mật đầy đủ, Namespace phải được sử dụng cùng NetworkPolicy, RBAC và Pod Security Standards
  • Một số resources là cluster-scoped (không thuộc namespace): Nodes, PersistentVolumes, StorageClasses, ClusterRoles
  • Các namespace mặc định: kube-system (system components), kube-public (public info), kube-node-lease (node heartbeats), default

Cách debug Pod bị CrashLoopBackOff?  

Khi một Pod rơi vào trạng thái CrashLoopBackOff, điều đó có nghĩa là container khởi động lên nhưng liên tục bị crash sau một thời gian ngắn và Kubernetes sử dụng exponential backoff delay nhằm kiểm soát tần suất restart và hạn chế vòng lặp lỗi liên tục. 

Theo hướng dẫn chính thức từ Kubernetes, bạn có thể thực hiện debug bằng các bước sau:

Nội dung kiểm traLệnh sử dụngMục đích / Cần chú ý
Kiểm tra log cũ của container xem container gặp lỗi gìkubectl logs <pod-name> --previousFlag –previous đặc biệt quan trọng vì container thường crash quá nhanh, log mới có thể không ghi lại lỗi gốc. Nếu có nhiều container: thêm -c <container-name> để chỉ định container cụ thể.
Kiểm tra mô tả chi tiết Podkubectl describe pod <pod-name>Xem Events, , lý do container exit, Exit Code, lỗi pull image, volume, probe; Xem phần Last State để xác định lỗi ngay trước khi Pod restart
Kiểm tra cấu hình liveness/readiness probe(Xem YAML Pod/Deployment)Nhiều Pod rơi vào CrashLoopBackOff vì liveness probe cấu hình sai, khiến Kubernetes liên tục kill container. Hãy kiểm tra:probe timeout quá ngắnendpoint probe không đúngứng dụng khởi động lâu nhưng probe không đợi đủ thời gian
Debug container bằng cách override commandTạo một Pod tạm thời để kiểm tra container image:
kubectl run debug
--image=<image>
--command -- sleep 3600

Hoặc debug pod đang tồn tại (K8s 1.18+)
kubectl debug <pod-name> -it
--image=<debug-image>
--share-processes
--copy-to=debug-pod
Cách này giúp vào môi trường container để kiểm tra file, cấu hình hoặc dependency mà ứng dụng cần.
Kiểm tra resource limits & requests(Xem resources.limits và resources.requests trong Pod/Deployment)Container có thể bị crash do thiếu CPU/RAM nếu limit quá thấp hoặc request không hợp lý

File YAML của Deployment bao gồm những phần chính nào?  

Một manifest YAML để tạo Deployment trong Kubernetes thường bao gồm các phần cơ bản sau:

apiVersion

Định nghĩa phiên bản API mà manifest sử dụng, giúp Kubernetes hiểu cách xử lý resource.

Ví dụ: apiVersion: apps/v1

kind

Xác định loại resource mà bạn tạo (ở đây là “Deployment”).

Ví dụ: kind: Deployment

metadata

Chứa thông tin về resource:

  • name: tên của Deployment, sẽ dùng để tham chiếu.
  • namespace: (nếu cần) xác định namespace, nếu không khai báo thì mặc định dùng “default”.
  • (Có thể thêm) labels và annotations để tag, phân loại resource dễ dàng.

spec

Phần chính để khai báo mong muốn (desired state) của Deployment. Bên trong spec thường gồm:

  • replicas: số lượng bản sao Pod mà bạn muốn; ví dụ replicas: 3.
  • selector: điều kiện để chọn Pod mà Deployment quản lý, thường sử dụng matchLabels với label phù hợp.
  • template: định nghĩa cấu hình cho Pod sẽ được tạo ra. template lại bao gồm hai phần:
    • metadata (thường chứa labels, giúp khớp với selector).
    • spec: định nghĩa cấu hình cho container bên trong Pod, gồm các trường như: containers (danh sách các container, mỗi container cần khai báo: name, image, có thể có ports, env, resources, volumeMounts… ). Ngoài ra còn có volumes, initContainers, các thiết lập về tài nguyên (resource requests/limits), môi trường, storage,…

(Tuỳ chọn) Các cấu hình phụ trợ khác

Bạn có thể khai báo thêm trong spec.template.spec, chẳng hạn: volumes, initContainers, affinity, tolerations, nodeSelector, env/envFrom, resources (request/limit), livenessProbe / readinessProbe, v.v. — giúp kiểm soát chi tiết hơn hành vi và môi trường của Pod.

Bạn cũng có thể thêm strategy trong spec, để định nghĩa cách Deployment update (rolling update, recreate, v.v.).

Ví dụ minh họa một file YAML của Deployment (giản lược)

apiVersion: apps/v1

kind: Deployment

metadata:

  name: my-app-deployment

spec:

  replicas: 3

  selector:

    matchLabels:

      app: my-app

  template:

    metadata:

      labels:

        app: my-app

    spec:

      containers:

        - name: my-app-container

          image: my-app-image:latest

          ports:

            - containerPort: 80

Câu hỏi phỏng vấn Kubernetes trung cấp (Intermediate Level)

Kiến trúc Kubernetes cluster gồm những thành phần nào? 

Một Kubernetes cluster tiêu chuẩn được xây dựng dựa trên hai nhóm thành phần chính: Control Plane (Master) và Worker Nodes. 

Control Plane – Bộ não điều khiển toàn bộ cluster

Control Plane chịu trách nhiệm quản lý trạng thái mong muốn (desired state) của hệ thống. Nó quyết định ứng dụng được chạy ở đâu, khi nào cần scale, và sẽ tự động khôi phục khi có lỗi xảy ra. 

Các thành phần cốt lõi bao gồm:

  • kube-apiserver
    • Là cổng giao tiếp trung tâm của Kubernetes (RESTful API).
    • Tất cả thao tác từ kubectl, CI/CD, hoặc các service khác đều đi qua API Server.
    • Xác thực (authentication) và phân quyền (authorization) mọi request
    • Là component duy nhất tương tác trực tiếp với etcd
  • etcd
    • Cơ sở dữ liệu distributed key-value lưu trữ toàn bộ trạng thái của cluster
    • Chỉ API Server mới được phép truy cập trực tiếp
    • Đảm bảo tính nhất quán và độ tin cậy cao.
  • kube-scheduler: Quyết định Pod sẽ chạy trên node nào dựa trên tài nguyên trống, giới hạn, affinity/anti-affinity hoặc tolerations.
  • kube-controller-manager
    • Gồm nhiều loại controller đảm nhiệm các tác vụ tự động như:
      • đảm bảo số replica đúng,
      • quản lý Node,
      • theo dõi trạng thái resource.
  • Khi phát hiện chênh lệch giữa desired state và current state, controller sẽ hành động để đồng bộ lại.

Worker Nodes – Nơi ứng dụng thực sự chạy

Worker nodes là nơi triển khai container. Mỗi node chứa các thành phần sau:

  • Kubelet
    • Agent chạy trên mỗi node.
    • Mọi request đến API Server đều được thực hiện qua HTTPS.
    • Nhận lệnh từ API Server và đảm bảo Pod được tạo, theo dõi, khởi động lại nếu thất bại.
    • Mount volumes, pull images, report Pod/Node status
    • Không quản lý containers không được tạo bởi Kubernetes
  • Kube-Proxy
    • Quản lý networking cho Pod và Service.
    • Đảm bảo traffic được định tuyến đúng giữa các Pods hoặc từ bên ngoài vào cluster.
  • Container Runtime
    • Hệ thống chạy container, ví dụ: containerd, CRI-O.
    • Thực thi các image và quản lý vòng đời container.

Add-ons và các thành phần mở rộng

Tuỳ nhu cầu sử dụng, cluster còn có thêm các add-on quan trọng phục vụ nhu cầu production:

  • DNS (CoreDNS/kube-dns) – cung cấp phân giải tên cho dịch vụ trong cluster
  • CNI plugin – quản lý mạng (Calico, Flannel, Cilium…)
  • Ingress Controller – điều phối traffic HTTP/HTTPS từ bên ngoài
  • Dashboard hoặc monitoring stack (Prometheus, Grafana…)
  • Metrics Server: cung cấp các chỉ số tài nguyên (CPU, memory) cho HPA
  • Storage plugins (CSI drivers): Tích hợp với storage systems

Sự khác nhau giữa ReplicaSet, Deployment và StatefulSet? 

Trong Kubernetes, ReplicaSet, Deployment và StatefulSet đều là những workload resources giúp quản lý vòng đời các Pod. 

ReplicaSet – Đảm bảo số lượng Pod luôn ổn định thông qua vòng lặp reconciliation

ReplicaSet thường chỉ được dùng khi cần kiểm soát trực tiếp cơ chế nhân bản Pod mà không cần tính năng rollout phức tạp.

  • Nếu Pod bị lỗi hoặc biến mất, ReplicaSet sẽ tự động tạo Pod mới nhằm đảm bảo đúng số replica đã cấu hình.
  • Hoạt động dựa trên label selector để xác định các Pod thuộc phạm vi quản lý.
  • Không hỗ trợ rolling update hoặc rollback.
  • Thường không được sử dụng trực tiếp, vì Deployment đã bao gồm ReplicaSet.

Deployment – Quản lý rollout và rollback ứng dụng

Deployment là lớp điều khiển cao hơn của ReplicaSet. Nếu ứng dụng không cần lưu trạng thái theo Pod và cần cập nhật linh hoạt, Deployment là lựa chọn mặc định. 

  • Quản lý nhiều ReplicaSets (mỗi version một ReplicaSet)
  • Có khả năng rollout phiên bản mới, rollback khi gặp lỗi, và cập nhật Pod từng phần (rolling update) mà không gây downtime.
  • Cho phép pause/resume deployment

StatefulSet — Quản lý ứng dụng có trạng thái (stateful)

StatefulSet được thiết kế cho các ứng dụng cần danh tính cố định (persistent identity) giữa các Pod – điều mà ReplicaSet và Deployment không cung cấp.

  • Pod có tên định danh cố định theo thứ tự (ví dụ: web-0, web-1…).
  • Mỗi Pod được gắn với PersistentVolume riêng, không thay đổi kể cả khi Pod bị xóa.
  • Quá trình scale, update và delete diễn ra theo thứ tự, đảm bảo sự nhất quán.

StatefulSet thường dùng cho database và các hệ thống phân tán như MySQL, PostgreSQL, MongoDB, Kafka, Zookeeper hoặc Elasticsearch, hoặc một số trường hợp cần khởi động hoặc tắt Pod theo thứ tự (ordered startup/shutdown).

Bảng so sánh ReplicaSet, Deployment và StatefulSet

Tiêu chíReplicaSetDeploymentStatefulSet
Quản lý số lượng Pod✔ (qua ReplicaSet)
Hỗ trợ rollout/rollback✔ (nhưng theo thứ tự)
Pod có danh tính cố định
Dùng cho ứng dụng stateful
Dùng cho ứng dụng statelessKhông tối ưu
Thứ tự tạo/xóa PodKhông đảm bảoKhông đảm bảoCó đảm bảo
Gắn PersistentVolume riêng cho từng Pod

HPA (Horizontal Pod Autoscaler) hoạt động như thế nào? 

Horizontal Pod Autoscaler (HPA) là cơ chế tự động điều chỉnh số lượng Pod trong Kubernetes dựa trên mức tải thực tế. HPA giúp ứng dụng mở rộng khi nhu cầu tăng và thu nhỏ lại khi tải giảm, từ đó tối ưu tài nguyên và đảm bảo hiệu năng ổn định.

HPA theo dõi metric để quyết định scale

HPA liên tục kiểm tra các chỉ số hoạt động của Pod, phổ biến nhất là:

  • CPU utilization
  • Memory utilization
  • Custom metrics thông qua Custom Metrics API (ví dụ: số request mỗi giây, độ dài hàng đợi)
  • External metrics qua External Metrics API (metrics từ hệ thống bên ngoài như AWS CloudWatch)

HPA nhận dữ liệu metric thông qua Metrics Server (bắt buộc phải cài đặt) hoặc các nguồn metric mở rộng như Prometheus Adapter.

Xác định số Pod cần thiết dựa trên công thức mục tiêu

Trong mỗi cấu hình HPA, bạn sẽ đặt giá trị mục tiêu (target) cho metric, ví dụ:

“Giữ CPU ở mức 70%”.

“Giữ memory ở 80%”

“Giữ requests per second ở 1000”

Công thức tính toán:

desiredReplicas = ceil[currentReplicas * (currentMetricValue / targetMetricValue)]

Dựa trên metric thực tế, HPA sử dụng công thức tính toán để quyết định số replica phù hợp. Nếu mức sử dụng vượt ngưỡng, HPA sẽ scale Pod lên; nếu thấp hơn nhiều, HPA sẽ giảm Pod xuống trong giới hạn minReplicas và maxReplicas.

HPA gửi yêu cầu cập nhật số replica cho Deployment/ReplicaSet

Khi xác định cần thay đổi, HPA sẽ:

  • Gửi lệnh tới Deployment hoặc ReplicaSet hoặc StatefulSet.
  • Điều chỉnh spec.replicas về số Pod mới.
  • Kubernetes tự động tạo hoặc xoá Pod theo yêu cầu.

Quy trình này diễn ra từng bước để tránh làm hệ thống thay đổi đột ngột.

  • Scale-up delay: Chờ 3 phút giữa các lần scale up (mặc định)
  • Scale-down delay: Chờ 5 phút giữa các lần scale down (mặc định)
  • Tolerance: Không scale nếu thay đổi < 10% (configurable)

Thông thường, HPA cập nhật nhịp đo liên tục theo chu kỳ (khoảng 15 giây trở lên tùy cấu hình). Điều này giúp ứng dụng phản ứng nhanh khi tải tăng đột biến, đồng thời không gây dao động quá mạnh trong số lượng Pod.

ClusterIP, NodePort và LoadBalancer khác nhau như thế nào?

Trong Kubernetes, ClusterIP, NodePort và LoadBalancer là ba loại Service phổ biến nhất giúp ứng dụng có thể giao tiếp bên trong hoặc bên ngoài cluster. Mỗi loại Service cung cấp một mức độ truy cập khác nhau, phù hợp cho từng mục đích triển khai.

Bảng so sánh ClusterIP, NodePort và LoadBalancer

Tiêu chíClusterIPNodePortLoadBalancer
Mục đích sử dụngChỉ dùng trong nội bộ cluster, là kiểu Service mặc địnhMở cổng trên tất cả Node để truy cập từ bên ngoàiExpose ứng dụng ra Internet 
Cơ chếCung cấp một địa chỉ IP nội bộ (virtual IP từ service CIDR range) để các Pod hoặc Service khác trong cùng cluster có thể giao tiếp với nhau.DNS name tự động: <service-name>.<namespace>.svc.cluster.localMở một port cố định (thường trong dải 30000–32767) trên mỗi Node. Traffic gửi đến Node trên port này sẽ được chuyển tiếp vào Service và Pod tương ứng.Tạo một Load Balancer bên ngoài (từ cloud provider như AWS, GCP, Azure) và trỏ traffic về NodePort/ClusterIP phía dưới.
Trường hợp sử dụngMicroservices nội bộ hoặc giao tiếp backend–backend.– Khi cần môi trường đơn giản để test hoặc build demo.- Khi cần expose ứng dụng ra ngoài mà không cần load balancer chuyên dụng.Triển khai ứng dụng lên môi trường production cần một điểm truy cập ổn định, hiệu năng cao
Phạm vi truy cậpChỉ trong nội bộ clusterBên ngoài cluster qua địa chỉ IP của NodeInternet trực tiếp
Port truy cậpCluster IP nội bộGiống nhau trên tất cả các Node (30000–32767)IP public của load balancer
Cân bằng tảiNội bộ clusterHạn chế, phải thông qua NodeTốt (dùng LB của cloud provider)
Cần cloud providerKhôngKhông
Luồn trafficInternal → ClusterIP → PodExternal → NodePort → ClusterIP → PodExternal → LoadBalancer → NodePort → ClusterIP → Pod
Khả năng truy cập InternetKhông thểCó thể (gián tiếp)Có thể
Độ phức tạp cấu hìnhRất dễDễDễ nhưng phụ thuộc provider

Persistent Volume (PV) và Persistent Volume Claim (PVC) khác nhau thế nào? 

Trong Kubernetes, việc lưu trữ dữ liệu lâu dài là điều cần thiết cho các ứng dụng stateful. Để tách biệt lớp lưu trữ khỏi Pod, Kubernetes sử dụng hai khái niệm quan trọng: Persistent Volume (PV) và Persistent Volume Claim (PVC). Đây là cơ chế giúp việc lưu trữ trở nên linh hoạt, ổn định và độc lập với vòng đời Pod.

Điểm khác biệt giữa 2 khái niệm này là:

Tiêu chíPersistent Volume (PV)Persistent Volume Claim (PVC)
Khái niệmKhông gian lưu trữ có sẵn do cluster cung cấp và quản lý, giống như “ổ đĩa dùng chung”Cơ chế để Pod yêu cầu và sử dụng storage từ phía ứng dụng/người dùng
Vai tròQuản lý tài nguyên lưu trữ vật lýGiúp tách biệt ứng dụng và hệ thống lưu trữ
Ai tạo?Admin tạo thủ công (static provisioning) hoặc tự động thông qua StorageClass (dynamic provisioning)Người dùng hoặc ứng dụng
Nguồn storageLocal disk, NFS, cloud storage (EBS, GCE, Azure Disk…)Yêu cầu storage mà không quan tâm đến backend là gì.
Thời điểm tồn tạiTrước hoặc độc lập với Pod
Khi ứng dụng yêu cầu
Tồn tại khi Pod bị xóaCó thể vẫn tồn tạiChỉ tồn tại khi còn nhu cầu
Cách Pod sử dụngPod không truy cập trực tiếpPod sử dụng storage thông qua PVC
Cơ chế gắn kết (Binding)Chờ PVC phù hợp để bind (static binding)Khi PVC được tạo, Kubernetes sẽ tìm và bind PV phù hợp để gắn kết hai thành phần này lại.
Dung lượng (Capacity)Được định nghĩa sẵn khi tạo PVYêu cầu dung lượng (ví dụ: storage: 10Gi)
Access ModesKhai báo khi tạo PV: ReadWriteOnce/RWO,  ReadOnlyMany/ROX,  ReadWriteMany/RWXYêu cầu accessModes phù hợp
StorageClassCó thể gắn với StorageClassChỉ định storageClassName để dynamic provisioning
ProvisioningStatic (tạo thủ công) hoặc DynamicKích hoạt dynamic provisioning nếu dùng StorageClass

PV và PVC làm việc với nhau như thế nào?

  • Admin tạo PV hoặc hệ thống tự động cung cấp thông qua StorageClass.
  • Ứng dụng gửi yêu cầu PVC.
  • Control loop trong kube-controller-manager tìm PV phù hợp với yêu cầu PVC
  • Kubernetes tìm PV phù hợp với yêu cầu PVC.
  • Khi PV được bind, Pod có thể mount PVC như một volume và bắt đầu sử dụng.

Cách debug Pod ở trạng thái Pending? 

Khi một Pod bị “Pending”, nghĩa là Kubernetes chưa thể schedule Pod lên bất kỳ Node nào. Đây là tình huống thường gặp khi cluster thiếu tài nguyên, cấu hình Pod chưa đúng hoặc có sự ràng buộc khiến scheduler không tìm được Node phù hợp. Việc debug đúng cách giúp bạn nhanh chóng xác định nguyên nhân và khắc phục lỗi.

Nội dung kiểm traLệnh cần chạyCần chú ý điều gì
Kiểm tra mô tả chi tiết của Podkubectl describe pod <pod-name>Xem phần Events để xác định nguyên nhân Pod không được schedule, ví dụ: thiếu CPU/RAM, node có taint, yêu cầu volume không tồn tại, scheduler không tìm được node phù hợp
Xác minh tài nguyên của clusterkubectl get nodeskubectl top nodeskubectl describe node <node-name>Pod thường ở trạng thái Pending do không đủ tài nguyên→ Kiểm tra CPU/memory khả dụng, node có bị cordon/drain, node có đang ở trạng thái NotReady hay không
Kiểm tra requests & limits của Pod(Xem YAML Pod/Deployment)Nếu Pod yêu cầu quá nhiều tài nguyên so với Node, scheduler sẽ không thể đặt Pod lên Node nào cả.→ Đảm bảo resources.requests không vượt quá khả năng của bất kỳ node nào và limits không đặt quá cao gây cản trở scheduling
Rà soát các ràng buộc scheduling(Xem YAML Pod/Deployment)Pod có thể bị Pending do:NodeSelector không khớpNodeAffinity yêu cầu quá chặtPodAffinity/AntiAffinity khiến không còn Node phù hợpTaint/Toleration không tương thíchHãy kiểm tra lại cấu hình YAML để đảm bảo các ràng buộc hợp lý.
Kiểm tra PVC và storage (nếu dùng volume)kubectl get pvckubectl describe pvc <pvc-name>Xác định PVC đã được bind với PV hay chưa, storage class có hợp lệ không; PVC chưa bind thì Pod sẽ bị Pending
Kiểm tra tình trạng pull imagekubectl describe pod <pod-name>Pod Pending vì container image chưa sẵn sàng để pull (registry private, thiếu secret, sai đường dẫn image).
→ Kiểm tra các event như ImagePullBackOff, ErrImagePull

Ingress là gì? Khi nào cần dùng Ingress thay vì Service? 

Ingress là một API object tài nguyên trong Kubernetes cho phép quản lý truy cập HTTP/HTTPS từ bên ngoài vào các ứng dụng chạy trong cluster thông qua HTTP và HTTPS. 

  • Thay vì mở nhiều cổng khác nhau hoặc tạo nhiều LoadBalancer, Ingress cung cấp một điểm vào duy nhất và định tuyến traffic thông minh đến các Service bên trong.
  • Ingress không tự hoạt động độc lập, mà cần một Ingress Controller để thực thi các rule định tuyến. Controller này chịu trách nhiệm xử lý routing theo hostname hoặc đường dẫn, cũng như các logic HTTP/HTTPS ở tầng ứng dụng (Layer 7).

Nên dùng Ingress thay vì chỉ dùng Service trong các trường hợp sau:

Trường hợpVì sao nên dùng Ingress thay vì Service
Cần expose nhiều Service qua chung một IP / Load BalancerIngress cho phép nhiều ứng dụng chia sẻ một entry point duy nhất, thay vì mỗi Service cần một LoadBalancer riêng → giảm chi phí khi chạy trên cloud (AWS, GCP, Azure).
Muốn định tuyến theo hostname hoặc đường dẫnService không thể làm được routing theo host hoặc pathl, trong khi Ingress hỗ trợ:domain riêng: api.example.com, web.example.comrouting theo URL: /api, /webVirtual hosting: một IP có thể phục vụ nhiều domainPath-based routing với regex matching (tùy Ingress Controller)
Ứng dụng web phức tạp hoặc microservicesIngress phù hợp khi có nhiều service phía sau một cổng web, cần điều phối traffic linh hoạt theo HTTP/HTTPS.
Cần bật HTTPS/TLS cho nhiều dịch vụThay vì cài đặt chứng chỉ riêng lẻ cho từng Service, bạn chỉ cần quản lý tại Ingress.Ingress cho phép cấu hình SSL/TLS tập trung. Hỗ trợ SSL termination – giải mã HTTPS tại Ingress và forward HTTP đến backendTích hợp cert-manager để tự động gia hạn chứng chỉ SSLHỗ trợ SNI (Server Name Indication) cho nhiều domain trên cùng IP
Cần các tính năng Layer 7 nâng caoIngress cung cấp các tính năng:Rewrite URLCanary deployment (tuỳ vào controller)Rate limitingAuthentication tùy chỉnhHỗ trợ các thuật toán cân bằng tải như round-robin, least-connections và IP hashCho phép thao tác và chỉnh sửa header của request/responseHỗ trợ WebSocket và gRPCCác tính năng này không sẵn có trong ClusterIP, NodePort hay LoadBalancer.

So sánh nhanh Ingress và Service

Tiêu chíIngressService (NodePort / LoadBalancer)
Lớp mạngLayer 7 (HTTP/HTTPS)Layer 4 (TCP/UDP)
Khả năng định tuyếnCó (path, host, header-based)Không theo path/host
Số IP public cầnMột IP duy nhấtThường mỗi Service 1 IP
SSL/TLSTập trung tại IngressCấu hình riêng lẻ từng Service
Chi phíTiết kiệmCao khi có nhiều Service
Dùng choWeb traffic phức tạpCác service đơn giản, non-HTTP protocols

Storage Class dùng để làm gì? 

Trong Kubernetes, StorageClass được sử dụng để mô tả “kiểu storage” mà cluster có thể cung cấp và quyết định cách mà Kubernetes tạo PV khi có Persistent Volume Claim (PVC) yêu cầu.  

Về bản chất, StorageClass giúp:

  • Tự động tạo PV khi có PVC
  • Giúp tự động hóa cách cấp phát và quản lý storage, đảm bảo ứng dụng có storage phù hợp theo nhu cầu: nhanh, chậm, rẻ hoặc hiệu năng cao
  • Cho phép dùng nhiều loại storage khác nhau trong cùng một cluster
  • Ứng dụng sử dụng dữ liệu bền vững (persistent storage)

Bạn nên dùng StorageClass trong các trường hợp:

  • Muốn tự động tạo PV mỗi khi có PVC
  • Cần nhiều loại storage khác nhau cho các workload (database, cache, file storage…)
  • Muốn tối ưu chi phí bằng cách sử dụng từng loại storage phù hợp từng ứng dụng
  • Muốn đơn giản hóa quản lý storage trong môi trường multi-cluster hoặc cloud
  • Cần snapshot và backup policies tự động
  • Khi cần mã hóa dữ liệu nhạy cảm ở trạng thái lưu trữ (encryption at rest)

Lệnh nào dùng để kiểm tra status của node? 

Lệnh phổ biến nhất để xem trạng thái tổng quan của tất cả node là:

kubectl get nodes

Lệnh này hiển thị danh sách node cùng các thông tin quan trọng như:

  • STATUS: Ready / NotReady / Unknown
  • ROLES: control-plane, worker
  • VERSION: phiên bản kubelet
  • AGE: thời gian node tồn tại
  • INTERNAL-IP và EXTERNAL-IP (với -o wide)

Lệnh nào dùng để xem chi tiết hơn từng node?

Nếu muốn xem chi tiết hơn từng node, bạn có thể dùng: 

kubectl describe node <node-name>

Lệnh này cho phép bạn kiểm tra:

  • Điều kiện node (Node Conditions: Ready, DiskPressure, MemoryPressure…)
  • Thông tin allocatable & capacity
  • Danh sách Pod đang chạy trên node
  • Sự kiện (Events) giúp debug khi node gặp vấn đề
  • Taints và tolerations
  • Thông tin hệ thống: hệ điều hành (OS), kiến trúc phần cứng (architecture) và container runtime

Các loại Volume phổ biến: hostPath, nfs, emptyDir khác nhau ra sao? 

Trong Kubernetes, Volume đóng vai trò quan trọng trong việc lưu trữ dữ liệu và đảm bảo ứng dụng hoạt động ổn định. Ba loại volume phổ biến nhất là hostPath, NFS, và emptyDir:

hostPath – Gắn thư mục trên Node vào Pod

hostPath cho phép Pod truy cập trực tiếp vào một thư mục hoặc file trên node vật lý nơi Pod đang chạy.

Đặc điểm:

  • Dữ liệu nằm trên máy chủ vật lý, không phụ thuộc vào việc Pod bị xoá hay tạo lại.
  • Phụ thuộc vào node: Pod chỉ chạy đúng nếu được scheduler gán vào node chứa path đó.
  • Thường dùng cho các daemon hoặc agent cần truy cập file hệ thống của host.
  • Security risk: có thể truy cập vào host filesystem
  • Có nhiều type: Directory, DirectoryOrCreate, File, FileOrCreate, Socket, CharDevice, BlockDevice

Dùng hostPath khi:

  • Thu thập log của node
  • Chạy monitoring agent (như Prometheus Node Exporter)
  • Trường hợp cần truy cập file hệ thống host
  • DaemonSet cần truy cập vào Docker socket (/var/run/docker.sock)
  • Cần quyền truy cập vào kubelet certificates hoặc các file cấu hình liên quan

NFS – Volume chia sẻ giữa nhiều Pod

NFS (Network File System) là loại volume hỗ trợ truy cập qua mạng, cho phép nhiều Pod ở nhiều node khác nhau đọc và ghi cùng một dữ liệu.

Đặc điểm:

  • Hỗ trợ chia sẻ dữ liệu giữa nhiều Pod.
  • Không phụ thuộc vào node – Pod chạy ở đâu cũng truy cập được.
  • Cần có server NFS chạy độc lập.
  • Hỗ trợ access mode ReadWriteMany (RWX)
  • Hiệu năng phụ thuộc nhiều vào độ trễ mạng (network latency)
  • Yêu cầu cấu hình NFS client trên các worker node

Dùng NFS khi:

  • Lưu trữ dữ liệu chung giữa các Pod trong cùng ứng dụng
  • Lưu file upload của người dùng
  • Chạy các ứng dụng yêu cầu shared storage (CMS, web app nhiều replica…)

emptyDir – Thư mục tạm thời gắn với Pod

emptyDir được tạo khi Pod bắt đầu chạy và bị xoá khi Pod bị xoá.

Đặc điểm:

  • Dữ liệu chỉ sống trong lifecycle của Pod.
  • Thường được dùng để lưu trữ file tạm, cache, buffer.
  • Không dùng cho dữ liệu cần lưu bền vững.
  • Hỗ trợ ReadWriteMany (RWX) access mode
  • Performance phụ thuộc vào network latency
  • Cần cấu hình NFS client trên các worker nodes

Dùng emptyDir khi:

  • Lưu temporary files
  • Lưu cache cho ứng dụng web
  • Chia sẻ dữ liệu tạm trong cùng một Pod giữa nhiều container
  • Dùng làm không gian tạm (scratch space) cho các tác vụ xử lý dữ liệu
  • Init container sử dụng để chuẩn bị dữ liệu cho container chính
  • Áp dụng sidecar pattern để xử lý hoặc thu thập log

So sánh nhanh hostPath vs NFS vs emptyDir

Đặc điểmhostPathNFSemptyDir
PersistenceTồn tại theo nodeTồn tại trên server NFSMất khi Pod xoá
Chia sẻ giữa PodsKhôngChỉ trong cùng Pod
Phụ thuộc nodeKhôngKhông
Use case chínhTruy cập file hệ thống hostLưu trữ chia sẻCache, file tạm
Độ linh hoạtThấpCaoTrung bình
Yêu cầu hạ tầngKhôngCần NFS serverKhông

CNI plugin là gì và tại sao Kubernetes cần nó? 

CNI plugin là một thành phần tuân theo chuẩn Container Network Interface (CNI), cho phép Kubernetes cấu hình và quản lý mạng cho các container. Trong Kubernetes, việc kết nối mạng giữa các Pod, node và dịch vụ là yếu tố cốt lõi để ứng dụng hoạt động ổn định. Một số CNI phổ biến gồm: Calico, Flannel, Cilium, Weave Net.

Kubernetes cần CNI plugin để:

Cấp phát IP cho Pod

Mỗi Pod trong Kubernetes cần một IP riêng biệt. CNI plugin chịu trách nhiệm:

  • Cấp phát IP từ dải CIDR đã cấu hình (IPAM)
  • Gắn interface mạng cho Pod (thường là veth pair)
  • Thiết lập route để Pod có thể gửi/nhận dữ liệu
  • Đảm bảo IP không bị trùng lặp trong cluster

Đảm bảo kết nối Pod-to-Pod trong toàn cluster

CNI plugin tạo nên mạng phẳng (flat network), nghĩa là Pod ở bất kỳ node nào cũng có thể giao tiếp với Pod ở node khác mà không cần NAT, đảm bảo các Pod có thể giao tiếp theo mô hình “Pod-to-Pod”, “Pod-to-Service”.

Điều này là nền tảng cho:

  • Microservices
  • Hệ thống phân tán
  • Service discovery
  • Quản lý luồng traffic East-West bên trong cluster
  • Hỗ trợ tích hợp với service mesh

Áp dụng chính sách mạng (Network Policies)

Một lý do quan trọng khác là về bảo mật. Các CNI plugin như Calico hoặc Cilium cho phép áp dụng Network Policy để kiểm soát lưu lượng:

  • Pod nào được giao tiếp với Pod nào
  • Giao thức và port nào được phép
  • Chặn truy cập giữa các namespace
  • Hỗ trợ các rule Ingress và Egress
  • Áp dụng chính sách ở Layer 3/4 và Layer 7 (ví dụ với Cilium)
  • Hỗ trợ mã hóa dữ liệu khi truyền (encryption in transit), như WireGuard với Calico
  • Cung cấp khả năng cô lập và phân đoạn mạng (network isolation và segmentation)

Định tuyến lưu lượng giữa các Pod và node

Trong hệ thống nhiều node, việc định tuyến thủ công là không khả thi.

CNI plugin đảm bảo:

  • Lưu lượng giữa node được định tuyến tự động
  • Tránh xung đột IP
  • Đảm bảo hiệu năng với các kỹ thuật như VXLAN, IP-in-IP, hoặc BGP routing
  • Hỗ trợ networking giữa nhiều cluster (multi-cluster)

Cách theo dõi tài nguyên cluster bằng kubectl? 

Theo dõi tài nguyên trong Kubernetes là bước quan trọng để đảm bảo cluster hoạt động ổn định, tránh tình trạng quá tải và hỗ trợ xử lý lỗi hiệu quả. Với kubectl, bạn có thể nhanh chóng kiểm tra mức sử dụng CPU, RAM của node và Pod để đánh giá hiệu năng hệ thống.

Có các cách sau:

  1. Kiểm tra tài nguyên của Node

Lệnh cơ bản để xem mức sử dụng tài nguyên của tất cả node:

kubectl top nodes

Lệnh này cho bạn thấy:

  • CPU đang sử dụng
  • Bộ nhớ (RAM) đang dùng
  • Tỷ lệ % so với tổng tài nguyên node
  • CPU(cores) và CPU%
  • MEMORY(bytes) và MEMORY%

Đây là cách nhanh nhất để biết node nào đang bị quá tải.

  1. Kiểm tra tài nguyên của Pod

Để xem mức sử dụng CPU và RAM của từng Pod trong một namespace:

kubectl top pods -n <namespace>

Bạn có thể bỏ -n <namespace> để xem tất cả Pod trong namespace mặc định.

Lệnh này hữu ích khi:

  • Pod chạy chậm
  • Ứng dụng tiêu thụ bộ nhớ bất thường
  • Muốn đánh giá việc scale hoặc tối ưu tài nguyên
  • Xác định những Pod cần thực hiện vertical scaling
  • Debug các sự cố OOMKilled
  1. Xem chi tiết resource limit và request của Pod

Bạn có thể xem thông tin cấu hình tài nguyên Pod bằng:

kubectl describe pod <pod-name> -n <namespace>

Trong phần mô tả, Kubernetes hiển thị:

  • Requests (CPU/RAM tối thiểu Pod cần)
  • Limits (ngưỡng tối đa Pod được dùng)

Điều này giúp đối chiếu việc tiêu thụ thực tế (kubectl top) với cấu hình.

  1. Theo dõi sự kiện liên quan đến tài nguyên

Khi Pod bị thiếu CPU hoặc RAM, Kubernetes thường ghi sự kiện (Events):

kubectl get events --sort-by=.metadata.creationTimestamp

Các sự kiện như:

  • OOMKilled
  • FailedScheduling
  • Insufficient CPU/Memory

cho thấy Pod đang gặp vấn đề tài nguyên.

Câu hỏi phỏng vấn Kubernetes cao cấp (Advanced Level)

Cách thiết kế cluster Kubernetes có độ khả dụng cao (high availability)? 

Để một cluster Kubernetes có độ khả dụng cao, tức là vẫn hoạt động ổn định, chịu lỗi (fault-tolerant), có khả năng phục hồi và đảm bảo service không gián đoạn, tôi thường thiết kế theo một số nguyên tắc sau:

Đa Control-Plane (đa node điều khiển / đa master)

  • Thiết lập nhiều node cho Control Plane (API Server, etcd, Scheduler, Controller-Manager). Nếu một master bị lỗi, các master khác vẫn đảm bảo cluster hoạt động.
  • Đảm bảo bộ nhớ etcd được replica và đồng bộ giữa các master để tránh mất state khi một master chết.

Phân tán Worker node & tránh single point of failure (điểm lỗi duy nhất)

  • Sử dụng nhiều worker node (ít nhất 2-3 node), phân bổ workload đều.
  • Không đặt tất cả Pod / service quan trọng vào cùng một node, dùng labels/taints/affinity để đảm bảo phân phối load.
  • Theo dõi tình trạng node: nếu một node bị lỗi, Pod tự động được scheduler lại trên node khác.

Lưu trữ & Persistent Volume có khả năng chịu lỗi

Với ứng dụng cần lưu trữ bền vững, không sử dụng lưu trữ cục bộ chỉ gắn với một node. Nên dùng:

  • Storage backend hỗ trợ high avaibility, ví dụ lưu trữ mạng hoặc lưu trữ đám mây (block storage, network storage).
  • Dùng lớp abstraction như StorageClass + PersistentVolume để storage không phụ thuộc vào node cụ thể.

Network & CNI plugin ổn định và có dự phòng

  • Dùng CNI plugin ổn định, hỗ trợ nhiều node và cho phép Pod trên các node khác nhau giao tiếp mượt mà.
  • Đảm bảo mạng giữa node và pod, và giữa các pod không bị single point failure.
  • Nếu cần, thiết lập mạng phủ (overlay network) hoặc chính sách mạng (network policy)
    để tăng tính an toàn và khả năng chịu lỗi.

Cân bằng tải & expose dịch vụ có HA

  • Khi expose ứng dụng ra bên ngoài, sử dụng LoadBalancer hoặc Ingress Controller với hỗ trợ high avaibility (có nhiều instance, dùng external LB/cloud LB nếu có).
  • Tránh dùng NodePort đơn giản cho production nếu cần khả năng chịu lỗi và cân bằng tải tốt.

Monitoring, Logging & Auto-Recovery

  • Triển khai hệ thống giám sát (monitoring) để theo dõi node, Pod, tài nguyên hệ thống; phát hiện sớm khi node, container, hoặc service gặp sự cố.
  • Thiết lập alert, tự động recovery: nếu Pod chết, Deployment/ReplicaSet/StatefulSet tự tái khởi động; nếu node lỗi, scheduler tự chuyển Pod sang node khác.
  • Đảm bảo log và data được lưu trữ bên ngoài cluster nếu cần lưu trữ lâu dài, tránh mất log khi Pod/node bị xoá.

Backup etcd & dữ liệu quan trọng

  • Do etcd chứa toàn bộ state cluster, nên backup định kỳ để đảm bảo có thể phục hồi cluster khi có sự cố nghiêm trọng.
  • Với các ứng dụng stateful thì cần backup database, files, storage định kỳ

Khi nào nên áp dụng thiết kế cluster HA?

Bạn nên thiết kế cluster HA khi:

  • Chạy môi trường production, nhiều user, đòi hỏi uptime cao.
  • Ứng dụng cần khả năng chịu lỗi, không chấp nhận downtime khi node hoặc master gặp sự cố.
  • Có nhiều microservices / workloads, cần cân bằng tải và phân tán.
  • Cần mở rộng (scaling), deployment thường xuyên, update phiên bản mà vẫn đảm bảo ổn định.

RBAC (Role-Based Access Control) hoạt động thế nào? 

Trong Kubernetes, RBAC (Role-Based Access Control) là cơ chế kiểm soát truy cập dựa trên quyền, giúp giới hạn những hành động mà user, group hoặc tài khoản dịch vụ (service account) được phép thực hiện. RBAC được đặt làm mặc định từ Kubernetes 1.6.

RBAC trong Kubernetes hoạt động dựa trên bốn thành phần chính:

  • Role
    • Quy định danh sách các hành động (verb) được phép thực hiện trên tài nguyên (resources) trong một namespace.
    • Các verb bao gồm: get, list, watch, create, update, patch, delete.
  • ClusterRole
    • Giống Role nhưng áp dụng toàn cluster, không giới hạn namespace.
    • Dùng cho các resource ở cấp cluster như node, PersistentVolume, namespace…
    • Có thể được tổng hợp thông qua aggregationRule
  • RoleBinding
    • Gán Role cho user, group hoặc service account trong một namespace cụ thể.
  • ClusterRoleBinding
    • Gán ClusterRole cho user hoặc service account trên toàn bộ cluster.

Kubernetes sẽ kiểm tra quyền theo quy trình:

  • User gửi yêu cầu (ví dụ: “create Pod”).
  • Authentication: Xác thực danh tính (thông qua certificates, tokens, OIDC – hệ thống định danh bên ngoài)
  • Authorization: API Server kiểm tra chính sách phân quyền RBAC, xem người dùng đó có được phép thực hiện hành động trên tài nguyên tương ứng hay không
  • Admission Control kiểm soát đầu vào và webhook:
    • Có thể chỉnh sửa yêu cầu (mutate)
    • Hoặc kiểm tra và từ chối yêu cầu (validate)

Ví dụ: ép buộc namespace, thêm label, kiểm tra quota, policy bảo mật…

  • Ra quyết định:
    • Nếu RoleBinding / ClusterRoleBinding cho phép hành động → Yêu cầu được chấp nhận
    • Nếu không có quyền → Trả về lỗi 403 – Bị từ chối truy cập (Forbidden)

Làm thế nào để tạo Role mới trong Kubernetes?

Bước 1: Tạo Role

Ví dụ: Tạo một Role chỉ cho phép đọc và liệt kê Pod trong namespace dev

apiVersion: rbac.authorization.k8s.io/v1

kind: Role

metadata:

  namespace: dev

  name: pod-reader

rules:

- apiGroups: [""]

  resources: ["pods"]

  verbs: ["get", "list", "watch"]

Áp dụng Role vào cluster:

kubectl apply -f role.yaml

Bước 2: Tạo RoleBinding

Ví dụ: Gán Role pod-reader cho service account app-sa trong namespace dev.

apiVersion: rbac.authorization.k8s.io/v1

kind: RoleBinding

metadata:

  name: read-pods-binding

  namespace: dev

subjects:

- kind: ServiceAccount

  name: app-sa

  namespace: dev

roleRef:

  kind: Role

  name: pod-reader

  apiGroup: rbac.authorization.k8s.io

Áp dụng RoleBinding: 

kubectl apply -f rolebinding.yaml

Canary Deployment khác gì Blue/Green Deployment? 

Trong phát triển và vận hành phần mềm hiện đại, khi cập nhật ứng dụng chạy trên Kubernetes, có hai chiến lược triển khai phổ biến là Blue/Green Deployment và Canary Deployment. Cả hai đều là Progressive Delivery strategies.

Blue/Green Deployment

Blue/Green Deployment hoạt động bằng cách duy trì hai môi trường hoàn chỉnh cùng lúc:

  • Môi trường “Blue”: phiên bản ứng dụng hiện đang chạy (production).
  • Môi trường “Green”: phiên bản mới của ứng dụng, được triển khai song song.
  • Hoán đổi traffic tức thì 100% từ Blue sang Green
  • Thường dùng với Service selector hoặc Ingress rules

Khi phiên bản Green ổn định, bạn chuyển toàn bộ traffic từ Blue sang Green, nghĩa là cả hệ thống dùng phiên bản mới cùng lúc. Sau đó, phiên bản Blue có thể bị gỡ bỏ hoặc giữ làm rollback.

Ưu điểm:

  • Downtime gần như bằng 0.
  • Nếu phiên bản mới có lỗi, rollback nhanh chóng bằng cách chuyển lại traffic sang Blue.
  • Đảm bảo môi trường Green được test hoàn chỉnh trước khi chuyển đổi.
  • Đơn giản và dễ dự đoán.

Nhược điểm:

  • Cần gấp đôi hạ tầng khi duy trì song song hai môi trường.
  • Quản lý phức tạp hơn nếu ứng dụng có dữ liệu/stateful cần migration.

Canary Deployment

Canary Deployment là phương pháp triển khai dần (gradual release):

  • Đầu tiên, bạn deploy phiên bản mới cho một tỷ lệ nhỏ người dùng/requests.
  • Quan sát hiệu năng, lỗi, hành vi thực tế.
  • Nếu ổn, tiếp tục mở rộng dần cho toàn bộ người dùng.

Ưu điểm:

  • Giảm rủi ro do rollout từ từ, phiên bản mới chỉ ảnh hưởng một phần nhỏ trong hệ thống trước khi rollout hoàn toàn.
  • Có thể phát hiện lỗi sớm, dễ rollback nhanh nếu có sự cố.
  • Tiết kiệm tài nguyên, không cần gấp đôi hạ tầng như Blue/Green.

Nhược điểm:

  • Việc quản lý phiên bản và routing traffic phức tạp hơn.
  • Một phần người dùng có thể trải nghiệm phiên bản mới, nếu có lỗi, ảnh hưởng tới họ.

Bảng so sánh Blue/Green và Canary Deployment

Tiêu chíBlue/Green DeploymentCanary Deployment
Cách thức triển khaiDeploy toàn bộ ứng dụng mới sang môi trường Green, sau đó chuyển toàn bộ trafficDeploy dần, một phần nhỏ traffic dùng phiên bản mới, sau đó mở rộng
DowntimeGần như không cóGần như không có (nếu cấu hình đúng)
Nguồn lực hạ tầng cầnCao, cần hai môi trường song songThấp hơn, không cần gấp đôi toàn bộ
Rủi ro khi rolloutCó, nếu phiên bản mới lỗi thì ảnh hưởng toàn bộThấp hơn, chỉ ảnh hưởng một phần nhỏ
RollbackĐơn giản, chuyển lại traffic sang BlueCần dừng phiên bản Canary, routing trở lại phiên bản ổn định
Phù hợp choỨng dụng nhỏ/medium, ít microservice, cần release đồng bộỨng dụng lớn, microservices, cần kiểm thử thực tế, giảm rủi ro

Giải thích các cơ chế taints/tolerations & affinity/anti-affinity là gì? 

  • Taint: là cách gắn “nhãn cấm” vào một node, nghĩa là node đó “không muốn nhận Pod trừ khi Pod đó chấp nhận (tolerate) taint”.
  • Toleration: là khai báo trong Pod để “chịu đựng” taint, nhờ đó Pod có thể được schedule lên node đã bị taint.
  • Node Affinity / Anti-Affinity: là cách để Pod yêu cầu hoặc tránh node dựa trên label của node. Ví dụ bạn có thể yêu cầu Pod chạy trên node có label ssd: “true” (affinity), hoặc tránh node có label gpu: “true” (anti-affinity).
  • Pod Affinity / Anti-Affinity: tương tự nhưng dựa trên label của Pod khác, nghĩa là bạn có thể yêu cầu Pod chạy gần Pod khác, hoặc tránh chạy cùng Pod có label đặc biệt.

Nhờ các cơ chế này, bạn có thể kiểm soát nơi nào Pod được phân bổ, rất hữu ích khi cluster có nhiều node, hoặc bạn muốn tách biệt workload, hay ưu tiên node có resource đặc biệt.

Sử dụng taints/tolerations và affinity/anti-affinity khi nào và như thế nào?

Bạn nên sử dụng các tính năng này trong các trường hợp sau:

  • Muốn đảm bảo workload nhạy cảm (database, stateful service, latency-critical) chạy trên node chuyên biệt có resource tốt.
  • Cần cô lập các dịch vụ, tránh chúng chạy chung trên node để giảm rủi ro ảnh hưởng lẫn nhau.
  • Cần tách môi trường: dev / staging / production, mỗi môi trường trên các node khác nhau.
  • Cluster có nhiều node với cấu hình khác nhau (SSD vs HDD, GPU vs CPU thường, …), muốn tối ưu resource.
  • Bảo vệ master node: gán taint cho các master node để ngăn workload được schedule lên đó
  • Cần tăng độ tin cậy, phân tán Pod tránh điểm lỗi đơn (single-point-of-failure).

Cụ thể hơn:

  • Taints/Tolerations: Dùng khi bạn muốn đặt “hàng rào” cố định tại node, để node chỉ sẵn sàng đón Pod có toleration. Rất hữu ích để cô lập node cho workload đặc biệt.
  • Affinity / Anti-Affinity: Linh hoạt hơn, dựa trên label, dùng để hướng Pod đến hoặc tránh node/Pod theo điều kiện linh hoạt (như resource, topology, workload type).

Trong nhiều kịch bản, bạn có thể kết hợp cả hai để đạt được kiểm soát tốt nhất. Ví dụ: dùng taint để bảo vệ node nhạy cảm + dùng affinity để đảm bảo Pod phù hợp được schedule đúng nơi.

Cách sử dụng (ví dụ YAML + giải thích)

  • Ví dụ dùng Taints / Tolerations:

Gắn taint lên Node

kubectl taint nodes node-1 key=value:NoSchedule

Ví dụ:

kubectl taint nodes gpu-node-1 gpu=true:NoSchedule

kubectl taint nodes master-node node-role.kubernetes.io/master:NoSchedule

Node node-1 giờ có taint. Pod bình thường sẽ không được schedule vào node này.

Trong Pod/Deployment, thêm toleration

spec:

  tolerations:

  - key: "key"

    operator: "Equal"

    value: "value"

    effect: "NoSchedule"

Khi Pod có đoạn trên, nó có thể được schedule lên node-1.

Ý nghĩa: taint/toleration giúp bạn giữ “node cô lập”, chỉ những Pod được phép mới vào node đó.

  • Ví dụ dùng Node Affinity / Anti-Affinity:

Yêu cầu Pod chạy trên node có label nhất định (affinity)

spec:

  affinity:

    nodeAffinity:

      requiredDuringSchedulingIgnoredDuringExecution:

        nodeSelectorTerms:

        - matchExpressions:

          - key: "disk"

            operator: In

            values:

            - "ssd"

Pod sẽ chỉ được schedule trên node gắn label disk=ssd.

Tránh Pod chạy cùng node có label cụ thể (anti-affinity)

spec:

  affinity:

    podAntiAffinity:

      requiredDuringSchedulingIgnoredDuringExecution:

      - labelSelector:

          matchLabels:

            app: "backend"

        topologyKey: "kubernetes.io/hostname"

Pod sẽ tránh chạy trên cùng node với bất kỳ Pod nào có label app: backend.

Network Policy trong Kubernetes dùng để chặn hoặc cho phép traffic ra sao? 

Network Policy trong Kubernetes là tập hợp quy tắc giúp bạn kiểm soát Pod được phép gửi hoặc nhận traffic từ đâu. Thay vì để toàn bộ Pod trong cluster tự do giao tiếp với nhau (mặc định là “allow all”), Network Policy cho phép bạn giới hạn traffic theo IP, namespace hoặc label của Pod, giúp tăng cường bảo mật và giảm nguy cơ lây lan khi có sự cố.

Network Policy không tự chặn traffic; nó hoạt động dựa trên hai yếu tố:

  • Pod selector: xác định tập Pod mà chính sách này áp dụng.
  • Ingress / Egress rules: mô tả nguồn traffic được phép đi vào (ingress) hoặc đi ra (egress) từ Pod.

Khi một Network Policy được áp dụng lên Pod, mọi traffic không khớp với các rule được khai báo sẽ bị chặn mặc định. Điều này biến Pod từ chế độ “mở hoàn toàn” sang “chỉ cho phép những gì được khai báo”.

Chặn hoặc cho phép traffic Ingress (traffic đi vào Pod)

Bạn có thể cho phép Pod nhận traffic từ:

  • Pod khác có label cụ thể
  • Namespace có label cụ thể
  • IP range (CIDR) bên ngoài cluster

Ví dụ: Chỉ cho phép Pod nhận traffic từ Pod có label app=frontend:

ingress:

- from:

  - podSelector:

      matchLabels:

        app: frontend

Mọi nguồn khác không thuộc app=frontend sẽ bị chặn.

Chặn hoặc cho phép traffic Egress (traffic đi ra khỏi Pod)

Egress rules giúp bạn kiểm soát Pod có thể gửi traffic đến đâu, ví dụ:

  • Chỉ cho phép Pod truy cập database
  • Cấm Pod truy cập external internet
  • Cấm Pod truy cập internet
  • Chỉ cho phép gọi API nội bộ

Ví dụ: Chỉ cho phép Pod gửi traffic đến dải IP nội bộ 10.0.0.0/24:

egress:

- to:

  - ipBlock:

      cidr: 10.0.0.0/24

Pod không thể gửi traffic ra ngoài dải IP này.

Khi nào Network Policy có hiệu lực?

Network Policy chỉ hoạt động nếu cluster hỗ trợ CNI phù hợp. Nếu CNI không hỗ trợ Network Policy thì policy sẽ không có hiệu lực, dù bạn áp dụng đúng. 

Và không phải mọi CNI plugin đều hỗ trợ Network Policy. Các plugin nổi bật hỗ trợ gồm:

  • Calico
  • Cilium
  • Weave Net
  • Kube-router

Khi nào nên dùng Network Policy?

Tôi thường dùng Network Policy khi:

  • Cần cô lập các service quan trọng như database hoặc API nhạy cảm
  • Muốn đảm bảo mỗi microservice chỉ giao tiếp đúng phạm vi
  • Cần đáp ứng tiêu chuẩn bảo mật (ISO, PCI-DSS…)
  • Cluster đa tenant với cơ chế cô lập bằng Namespace
  • Muốn giảm rủi ro khi một Pod bị xâm nhập, hạn chế lateral movement
  • Yêu cầu tuân thủ (compliance) đối với các ngành chịu sự quản lý nghiêm ngặt

Cách tối ưu chi phí cho cluster Kubernetes? 

Dưới đây là các cách mà tôi áp dụng để tối ưu chi phí khi vận hành cluster.

Chọn loại tài nguyên phù hợp & điều chỉnh đúng requests/limits

  • Đặt requests và limits hợp lý cho Pod, tránh khai báo quá cao so với nhu cầu thực tế, khiến node phải cấp phát tài nguyên dư thừa.
  • Sử dụng tài nguyên shared hoặc nhẹ cho các service nhỏ, tránh sử dụng node cứng cấu hình cao cho workload nhẹ.
  • LimitRange được sử dụng để áp đặt giới hạn tài nguyên tối thiểu và tối đa cho mỗi Pod

Dùng auto-scaling: scale theo nhu cầu thực tế

  • Sử dụng Horizontal Pod Autoscaler (HPA) để tự động scale Pod khi tải tăng, và scale xuống khi tải thấp, tiết kiệm tài nguyên khi cluster ít sử dụng.
  • Nếu có thể, dùng Cluster Autoscaler để tự động scale node, tức là thêm node khi cần, thu gọn khi không cần, giảm chi phí idle node.
  • Tự động scale dựa trên dự đoán bằng mô hình Machine Learning để nhận diện và học các mô hình traffic

Sử dụng máy ảo giá rẻ Spot / Preemptible / Low-cost instances (cho môi trường không quá quan trọng)

  • Với workload không yêu cầu uptime 24/7 hoặc chấp nhận mất node tạm thời, bạn có thể dùng spot instance / preemptible VM – giá mềm hơn rất nhiều so với instance thường.
  • Phù hợp với batch job, workload không quan trọng uptime, hoặc workload có khả năng tự recover.

Tối ưu việc chia sẻ tài nguyên và khai thác mô hình đa người dùng

  • Gộp nhiều microservice nhẹ vào cùng node nếu không xung đột resource, tận dụng tối đa CPU/RAM, tránh dư thừa.
  • Dùng Namespace kết hợp quota và giới hạn tài nguyên để phân bổ resource công bằng, tránh lãng phí tài nguyên.

Xoá resource không cần thiết

  • Xoá Pod, Job, ReplicaSet cũ, storage không dùng nữa, tránh giữ resource idle.
  • Áp dụng lifecycle policy cho Persistent Volume, logs, artifacts…

Giám sát, đo lường chi phí và sử dụng tài nguyên thường xuyên

  • Sử dụng monitoring để theo dõi mức sử dụng CPU, memory, storage, network, từ đó phát hiện resource dư thừa.
  • Phân tích chi phí theo namespace, workload, thời gian để tìm nơi đang gây lãng phí tài nguyên.
  • Dựa vào dữ liệu thực tế để tối ưu requests/limits, scaling, scheduling.

Chọn đúng loại storage & giải pháp lưu trữ phù hợp

  • Với dữ liệu không cần bền lâu: dùng storage nhẹ, shared storage, không cần disk hiệu năng cao.
  • Với production: cân nhắc giữa performance và chi phí để chọn storage phù hợp workload, tránh dùng storage đắt tiền cho service nhỏ.
  • Thường xuyên dọn dẹp các PersistentVolumeClaims (PVC) và snapshots không còn sử dụng để tránh lãng phí tài nguyên lưu trữ

Tôi thường áp dụng tối ưu chi phí cluster khi:

  • Cluster có nhiều service, microservice, workload đa dạng.
  • Chi phí vận hành cao, muốn tối ưu ngân sách.
  • Tài nguyên cloud hạn chế, cần cân nhắc hiệu quả sử dụng.
  • Muốn đảm bảo hiệu năng mà vẫn tiết kiệm chi phí cho dài hạn.

Giải thích quy trình scheduling của Kubernetes? 

Trong Kubernetes, scheduling là quá trình mà hệ thống lựa chọn node phù hợp nhất để đặt một Pod mới lên, quyết định Pod sẽ chạy ở node nào. Việc scheduling đảm bảo rằng Pod có đủ tài nguyên, đáp ứng ràng buộc và tối ưu phân bổ tài nguyên toàn cluster.

Khi bạn tạo Pod (qua Deployment, ReplicaSet hoặc trực tiếp), scheduler của Kubernetes sẽ thực hiện các bước sau:

  • Pod được gửi tới API Server

Pod specification (manifest) được gửi lên qua API (ví dụ kubectl apply). Kubernetes lưu Pod vào etcd với trạng thái “Pending” và nodeName field rỗng.

  • Scheduler lọc các node phù hợp

Scheduler (thường là kube-scheduler) sẽ tìm tất cả node phù hợp để đặt Pod bằng cách kiểm tra nhiều điều kiện như:

  • Node có đủ tài nguyên (CPU, memory) trống để đáp ứng requests/limits của Pod.
  • Node phù hợp với affinity/anti-affinity, taints/tolerations hoặc các ràng buộc khác.
  • Node đáp ứng ràng buộc về labels, taints, zone/region, topology constraints…

Nếu không đáp ứng, node đó bị loại (filter) khỏi danh sách.

  • Scheduler đánh giá & ưu tiên

Trong số các node còn lại, scheduler sẽ chấm điểm (score) từng node theo các tiêu chí, ví dụ:

  • Node có ít workload hơn (tải thấp)
  • Node phù hợp nhất về resource, locality, dữ liệu storage, network
  • Ưu tiên cân bằng tải giữa các node

Node có điểm cao nhất được chọn để chạy Pod.

  • Binding Pod với Node

Sau khi chọn node, scheduler gửi thông báo đến API Server để bind Pod với node đó, tức là khẳng định Pod sẽ chạy ở node đó.

  • Kubelet trên node nhận lệnh và khởi chạy Pod

Trên node được chọn: Agent kubelet nhận lệnh, tải container image, gắn volume, thiết lập networking, và khởi động container theo spec.

  • Thiết lập networking, storage, volumes và theo dõi trạng thái

Sau khi container khởi chạy, hệ thống gắn IP, mount volume, thiết lập network (qua CNI plugin nếu có), áp dụng policy, và quản lý lifecycle của Pod.

Vì sao quy trình scheduling quan trọng?

  • Giúp tối ưu resource, tránh phân bổ vượt mức tài nguyên (overcommit), tận dụng CPU/memory hiệu quả.
  • Đảm bảo tính ổn định: Pod không bị schedule lên node không phù hợp (quá tải, thiếu tài nguyên, không đáp ứng affinity/taint).
  • Hỗ trợ scale & high availability: Khi có nhiều node, scheduler phân bổ đều, tránh single point of failure (điểm lỗi duy nhất).
  • Cho phép áp dụng ràng buộc phức tạp (affinity, taints/tolerations, storage locality…), giúp deployment linh hoạt và phù hợp nhiều scenario.

Vì sao Secret encryption at rest quan trọng? Khi nào nên bật Secret encryption at rest?

Encryption at rest nghĩa là quá trình mã hóa dữ liệu ngay khi nó được lưu trữ, tức là khi dữ liệu không nằm trong quá trình truyền (in-transit), mà đang “nghỉ” (at rest) trên đĩa. Mặc định, Kubernetes lưu Secrets trong etcd dưới dạng base64 encoded (KHÔNG PHẢI encrypted).

Với Kubernetes, khi bạn sử dụng Secret để lưu thông tin nhạy cảm (mật khẩu, token, key), nếu bật Secret encryption at rest, nghĩa là Kubernetes sẽ mã hóa nội dung Secret bằng encryption providers trước khi lưu vào store nội bộ (ví dụ etcd), đảm bảo rằng ngay cả khi ai đó truy cập vào dữ liệu lưu trữ vật lý cũng không đọc được dữ liệu gốc mà không có khóa giải mã. 

Nó giúp:

  • Bảo vệ dữ liệu nhạy cảm: Secrets chứa mật khẩu, token, certificate… nếu không mã hóa, ai có quyền đọc store lưu trữ có thể lấy toàn bộ. Encryption at rest giúp ngăn việc lộ dữ liệu.
  • Giảm thiểu rủi ro khi sao lưu hoặc snapshot: Khi cluster bị backup, snapshot ổ đĩa hoặc etcd được lưu lại, dữ liệu vẫn ở dạng mã hóa, tránh rò rỉ nếu backup bị lộ.
  • Tuân thủ yêu cầu bảo mật & compliance: Nhiều tiêu chuẩn bảo mật yêu cầu dữ liệu nhạy cảm phải được mã hóa khi lưu trữ, encryption at rest giúp đáp ứng điều này.
  • An toàn ngay cả khi server vật lý bị xâm phạm: Nếu ai đó có truy cập vật lý hoặc truy cập vào ổ lưu trữ, họ cũng không thể đọc dữ liệu Secret nếu không có khóa giải mã.

Nên bật khi:

  • Cluster chứa dữ liệu nhạy cảm (credential, key, token…).
  • Có chính sách bảo mật nghiêm ngặt hoặc tuân thủ compliance.
  • Có backup, snapshot, hoặc lưu trữ dài hạn dữ liệu.
  • Muốn bảo vệ dữ liệu trước cả các rủi ro vật lý (ổ đĩa, server).

Làm sao phát hiện resource bottleneck của một workload? 

Để phát hiện workload đang gặp resource bottleneck, nên theo dõi ba nhóm chỉ số chính: CPU, memory và I/O (disk hoặc network). Nếu một trong các tài nguyên này liên tục bị dùng gần mức tối đa hoặc vượt quá requests/limits, đó là dấu hiệu rõ ràng của bottleneck.

Ví dụ:

  • CPU bottleneck: Pod luôn ở mức 90–100% CPU, container phản hồi chậm, HPA scale lên liên tục.
  • Memory bottleneck: Pod thường xuyên bị OOMKilled hoặc memory spike cao bất thường.
  • I/O bottleneck: Ứng dụng đọc/ghi chậm, latency network tăng mạnh khi traffic cao.

Tôi sử dụng kubectl top pods, metrics server, Prometheus/Grafana để xem xu hướng tài nguyên. Khi thấy workload bị giới hạn ở một tài nguyên nhất định trong khi các tài nguyên khác còn dư, đó chính là bottleneck. Từ đó tôi điều chỉnh requests/limits, scale pods hoặc tối ưu ứng dụng tùy theo nguyên nhân.

Container Runtime Interface (CRI) hoạt động ra sao? Vì sao nó quan trọng?

CRI (Container Runtime Interface) là một giao diện chuẩn mà Kubernetes sử dụng để tương tác với phần mềm runtime chịu trách nhiệm khởi chạy, quản lý, và vận hành container trên node. Nhờ CRI, Kubernetes không phụ thuộc vào một container runtime cố định, nó có thể làm việc với nhiều runtime khác nhau như containerd, CRI-O,…

Cách CRI hoạt động trong Kubernetes

  • Khi Kubernetes muốn chạy một Pod / container, nó gửi yêu cầu đến kubelet trên node.
  • Kubelet sử dụng CRI để chuyển yêu cầu đó tới runtime (containerd, CRI-O, …).
  • Container runtime thực hiện các bước khởi tạo container: tải image, tạo filesystem, cấp phát resource, thiết lập mạng/volume, và khởi container.
  • Sau đó runtime giám sát container, báo lại cho kubelet về trạng thái (running, exited, logs, resource usage, restart, …).
  • Nhờ CRI, Kubernetes có thể thay đổi runtime mà không cần thay đổi logic orchestration, từ đó giúp cluster linh hoạt và dễ nâng cấp.

Vì sao CRI quan trọng?

  • Tính đa dạng & linh hoạt: Cho phép dùng nhiều container runtime khác nhau tùy nhu cầu.
  • Tách biệt orchestration & runtime: Kubernetes lo scheduling, quản lý Pod, còn runtime lo khởi container. Đây là kiến trúc rõ ràng, dễ bảo trì.
  • Tương thích tiêu chuẩn: Nhờ CRI, runtime tuân theo chuẩn chung, giảm rủi ro tương thích khi đổi runtime.

Pod Security Standards (PSS) gồm những mức nào? Vì sao không tồn tại một mức trung gian giữa Privileged và Baseline?

Pod Security Standards (PSS) gồm những mức nào?

Pod Security Standards (PSS) replaced Pod Security Policies (PSP) in Kubernetes 1.25. PSS là bộ quy tắc bảo mật áp dụng cho Pod nhằm kiểm soát mức độ rủi ro khi chạy workload.

  1. Privileged – Mức ít hạn chế nhất
  • Cho phép Pod thực hiện hầu hết hành động mà container có thể làm trên node.
  • Dùng cho các trường hợp đặc biệt như công cụ quản trị hệ thống, plugin mạng hoặc workload thao tác trực tiếp với kernel.
  • Không được khuyến khích sử dụng trong môi trường sản xuất nếu không thật sự cần thiết.
  • Mức độ rủi ro bảo mật: CAO NHẤT
  1. Baseline – Cân bằng giữa chức năng và rủi ro
  • Mức hạn chế vừa phải, chặn các cấu hình container có nguy cơ cao nhưng vẫn đủ linh hoạt cho phần lớn ứng dụng.
  • Không cho phép: đặc quyền root tùy ý, hostPID/hostNetwork, mount hostPath không kiểm soát, hoặc thay đổi các capability nhạy cảm.
  1. Restricted – Mức bảo mật cao nhất
  • Thiết kế để tuân theo best practice của container security.
  • Yêu cầu Pod chạy với quyền tối thiểu, bật seccomp, hạn chế capability, không được chạy với user root, và không can thiệp vào tài nguyên của host.

Vì sao không tồn tại một mức trung gian giữa Privileged và Baseline?

Không tồn tại một mức trung gian giữa Privileged và Baseline vì Kubernetes muốn giữ PSS đơn giản, rõ ràng và dễ áp dụng. Khoảng cách giữa hai mức này thể hiện ranh giới quan trọng:

  • Privileged: cho phép hành vi ảnh hưởng trực tiếp đến host → rủi ro cao.
  • Baseline: chặn toàn bộ hành vi có thể gây nguy hiểm cho node → an toàn hơn đáng kể.

Một mức “ở giữa” sẽ khiến tiêu chuẩn trở nên phức tạp, khó hiểu và khó áp dụng, đồng thời không mang lại giá trị thực tế, vì chỉ cần bật một số quyền đặc biệt là workload đã tiến gần đến mức Privileged. Do đó, Kubernetes giữ cấu trúc 3 mức (Privileged, Baseline, và Restricted) để đơn giản hóa cả triển khai lẫn đánh giá rủi ro bảo mật.

Nguyên nhân và cách xử lý khi Node bị NotReady nhưng workload không tự recover

Khi một node trong Kubernetes bị đánh dấu NotReady, nghĩa là Kubernetes không cho rằng node đó đủ điều kiện để chạy workload. Tuy nhiên, trong một số trường hợp, workload (Pod) không được tự động di dời hoặc recover. Dưới đây sẽ chỉ ra các nguyên nhân phổ biến và cách khắc phục:

Nguyên nhânCách khắc phục
Taint của node chưa được áp dụng: Nếu node không bị taint khi NotReady, scheduler có thể không coi node là “không dùng được”. Mặc định, khi node NotReady, Kubernetes sẽ tự động thêm taint node.kubernetes.io/not-ready:NoSchedule và node.kubernetes.io/not-ready:NoExecute sau một khoảng thời gian nhất định (mặc định 5 phút).Taint node ngay khi phát hiện NotReady
kubectl taint node <node-name> key=value:NoSchedule
Việc này đảm bảo scheduler không đặt thêm Pod vào node gặp sự cố.
Pod có nodeAffinity hoặc nodeSelector ràng buộc cố định node đó → Scheduler sẽ không tìm nơi khác.Rà soát và nới lỏng affinity hoặc selector để Pod có thể được schedule sang node khác khi node hiện tại gặp sự cố.
Pod không ở trạng thái cho phép di dời: Pod được cấu hình với podDisruptionBudget, hoặc là StatefulSet/DaemonSet mà không cho phép tự động di dời.Kích hoạt hay điều chỉnh lại podDisruptionBudget / affinity để Pod có thể di chuyển, đảm bảo rằng Pod không bị khóa buộc node cũ.
Không có node thừa (spare node) trong cluster → Scheduler không tìm được node khác đáp ứng resource & ràng buộc.Đảm bảo có node dự phòng (spare node) hoặc mở rộng node bằng auto-scaler để scheduler có nơi di dời.
Persistent Volume / storage bound với node cụ thể → Pod yêu cầu storage cục bộ, nên không thể migrate dễ dàng.Sử dụng storage network hoặc PV không gắn cố định node (Avoid hostPath / local storage nếu cần HA) để Pod có thể mount storage trên node khác nếu migrate.
CNI / network / volume plugin gặp lỗi sau khi node trở lại trạng thái Ready, khiến Pod không thể chạy ở node khác.Kiểm tra event và trạng thái node để xác định lỗi nền (network, disk, memory, volume mount), sau đó khắc phục plugin hoặc môi trường liên quan:kubectl describe node <node-name>kubectl get events –sort-by=.metadata.creationTimestamp

Nếu cần khôi phục nhanh trong tình huống khẩn cấp, hãy chủ động xoá Pod để scheduler tạo lại Pod trên node healthy khác thay vì chờ cơ chế tự động:

kubectl delete pod <pod-name>

Ngoài ra, một số mẹo chuẩn bị trước để tránh sự cố:

  • Nếu có Persistent Volume / dịch vụ stateful, nên thiết kế storage & affinity phù hợp để dễ migrate.
  • Cluster có nhiều node để tránh single point of failure.
  • Thiết lập giám sát/alert để phát hiện node NotReady sớm và tự taint & migrate workload.
  • Cấu hình tolerationSeconds phù hợp cho workload nhằm kiểm soát thời gian chờ trước khi Pod bị evict.

Cần kiểm tra những gì khi HPA scale không đúng với load thực tế? 

Nếu bạn thấy Horizontal Pod Autoscaler (HPA) không scale lên khi load tăng, hoặc scale không đúng so với tải, dưới đây là các khía cạnh cần rà soát:

Kiểm tra metric source / metrics API

  • Nếu metrics-server không hoạt động, HPA không nhận được số liệu thì sẽ không scale được → Đảm bảo cluster có metrics-server (hoặc một metrics-provider hợp lệ) đang chạy và cung cấp metric CPU/Memory. 
  • Kiểm tra logs của metrics-server hoặc component tương đương để xem có lỗi trong việc thu thập dữ liệu không.
  • Kiểm tra HPA status: xem có message lỗi kiểu “unable to get memory metrics for resource” hay “no metrics returned from resource metrics API” → Đây là những dấu hiệu rõ ràng của việc thiếu metric.

Kiểm tra cấu hình HPA (target, metric, requests/limits)

  • Nếu workload không tiêu tốn metric bạn dùng để scale, HPA sẽ không trigger scale → Đảm bảo bạn đã chỉ định đúng target metric (ví dụ CPU utilization, memory, hoặc custom metrics) phù hợp với workload. 
  • QUAN TRỌNG: HPA bắt buộc phải có requests để tính toán mức độ sử dụng tài nguyên; nếu thiếu, HPA sẽ không hoạt động hoặc không đạt ngưỡng trigger để scale → Đảm bảo container đã cấu hình resources.requests (và limits nếu cần). 

Kiểm tra thời gian lấy mẫu & ổn định load

  • Nếu load tăng đột biến ngắn, HPA có thể bỏ lỡ: metrics sampling và polling có độ trễ, nên scale không kịp.
  • Nếu load giảm ngay sau đó, HPA có thể scale xuống nhanh, dẫn đến “ping-pong” (scale lên xuống liên tục) → Cần cấu hình hợp lý hoặc dùng ổn định load/trễ.

Kiểm tra resource constraints & hạn chế cluster

  • Kiểm tra xem cluster có đủ node/CPU/memory để scale không? → Nếu cluster không còn node trống (CPU/memory), HPA scale lên nhưng Pod không được schedule, nhìn từ ngoài sẽ giống như “không scale”.
  • Kiểm tra Pod log/scheduling error → có thể Pod mới bị Crash, pending, hoặc không thể khởi động.

Kiểm tra quyền truy xuất metric & RBAC (nếu dùng external/custom metrics)

  • Nếu dùng custom/external metrics, cần đảm bảo HPA có quyền truy cập metrics API, service account có đúng permission.
  • Kiểm tra rằng metric endpoint vẫn hoạt động, không bị chặn bởi network policy, authentication,…

Kiểm tra cấu hình cluster autoscaler / node autoscaling (nếu có)

  • Nếu bạn dùng autoscaler để scale node, mà node không được thêm khi cần, HPA scale Pod nhưng không có node phù hợp thì Pod sẽ Pending → lầm tưởng là HPA không hoạt động.
  • Kiểm tra xem cluster autoscaler được cấu hình đúng chưa (min/max nodes, taints, limits,…).

Xử lý như thế nào nếu Ingress hoạt động không ổn định khi có traffic lớn? 

Khi bạn dùng Ingress (ví dụ thông qua NGINX Ingress Controller) để expose ứng dụng, dưới tải lớn có thể gặp các vấn đề như response chậm, lỗi 502/503, upstream timeout, hoặc CPU cao. Để khắc phục, có các cách sau:

Tăng tài nguyên và cấu hình cho Ingress Controller

  • Đảm bảo Ingress Controller Pod có đủ CPU và memory để xử lý số lượng kết nối lớn nếu resource quá thấp, controller có thể bị nghẽn.
  • Nếu sử dụng Deployment/DaemonSet, cân nhắc scale số POD của Ingress Controller để cân tải.
  • Cấu hình đúng worker_processes, worker_connections, keepalive_timeout, client_max_body_size, proxy_buffers … để Ingress có thể xử lý nhiều kết nối đồng thời.

Sử dụng Load Balancer hoặc đa Ingress Controller để tránh single point of failure

  • Nếu traffic lớn, không nên để một Ingress Controller đơn lẻ, hãy deploy nhiều replica hoặc dùng dịch vụ cân tải phía trước (cloud load-balancer hoặc external LB) để phân phối đều.
  • Đảm bảo mỗi Ingress Controller nhận traffic vừa sức, tránh overload.
  • Cân nhắc sử dụng Service type LoadBalancer hoặc NodePort kết hợp với external load balancer để phân phối traffic hiệu quả.

Bật caching, gzip, compression, rate-limit nếu phù hợp

  • Nếu nội dung tĩnh hoặc phản hồi có thể cache, cấu hình caching hoặc HTTP cache để giảm tải backend.
  • Sử dụng gzip / compression để giảm lượng dữ liệu truyền, giúp mạng và Ingress đỡ tải hơn.
  • Đặt giới hạn (rate-limit) với annotations nginx.ingress.kubernetes.io/limit-rps hoặc nginx.ingress.kubernetes.io/limit-connections nếu có nhiều request từ cùng client để tránh DDoS hoặc spike traffic đột biến.

Kiểm tra health-check, readiness/liveness probe cho backend & Ingress Controller

  • Đảm bảo backend service (Pod) đủ ổn định, không bị crash. Nếu backend kém ổn định, Ingress dễ lỗi khi chuyển upstream.
  • Cấu hình readiness/liveness probe giúp Kubernetes chỉ gửi traffic tới Pod sẵn sàng, tránh lỗi do Pod chưa sẵn sàng.
  • Cấu hình health check cho Ingress Controller để Load Balancer nhận biết chính xác controller nào đang ở trạng thái healthy:

readinessProbe:

    httpGet:

      path: /healthz

      port: 10254

Giám sát & logging để phân tích nguyên nhân bottleneck

  • Theo dõi metric của Ingress Controller: CPU, memory, số kết nối, latency, số lỗi 5xx/4xx.
  • Kiểm tra log của NGINX Ingress để tìm lỗi timeout, upstream lỗi, connection reset, …
  • Từ dữ liệu thực tế, xác định xem bottleneck nằm ở đâu: network, backend, Ingress config, hay resource, từ đó điều chỉnh tương ứng.
  • Sử dụng Prometheus + Grafana để giám sát các chỉ số NGINX Ingress thông qua built-in exporter.

Tối ưu backend & ứng dụng để giảm áp lực lên Ingress

  • Đảm bảo backend được scale phù hợp với tải, cân nhắc sử dụng HPA cho dịch vụ backend. Nếu backend yếu, Ingress dù ổn vẫn không trả được request.
  • Tối ưu thời gian xử lý request, database query, caching, connection pooling, CDN, giúp backend phản hồi nhanh, giảm thời gian giữ kết nối.
  • Nếu có static assets hoặc CDN, nên offload các nội dung tĩnh sang CDN thay vì serve qua Ingress để tiết kiệm tài nguyên cho cluster.
  • Cân nhắc triển khai circuit breaker pattern kết hợp retry logic hợp lý để ngăn chặn hiện tượng lỗi dây chuyền (cascade failure) trong hệ thống.

Tổng kết câu hỏi phỏng vấn Kubernetes

Từ những câu hỏi nền tảng như Pod, Service, Deployment… đến các chủ đề nâng cao như RBAC, Network Policy, scheduling, storage, high availability, bài tổng hợp câu hỏi phỏng vấn Kubernetes trên giúp bạn ôn luyện kiến thức vững chắc để tự tin ứng tuyển vào các vị trí DevOps hoặc Cloud.

Khi hiểu rõ cả lý thuyết lẫn các tình huống thực tế, bạn sẽ dễ dàng thể hiện năng lực trước nhà tuyển dụng. Hãy tiếp tục luyện tập và cập nhật kiến thức để sẵn sàng cho mọi buổi phỏng vấn nhé.

TÁC GIẢ
Tuong Uyen
Tuong Uyen

Senior Content Writer

Có hơn 3 năm kinh nghiệm chuyên thực hiện các phỏng vấn chuyên sâu về kiến thức công nghệ thông tin với nhiều chuyên gia IT thuộc nhiều lĩnh vực IT hấp dẫn như Software Development, Game, Blockchain, Data, RPA,… Với niềm yêu thích và nghiên cứu về những kiến thức nền tảng mà mọi người kỹ sư công nghệ thông tin nào cũng cần phải nắm vững, như C++, Framework Front-End, Web, Mobile, Database,…, Uyên mang đến đa dạng những bài viết kiến thức IT cho mọi người đọc từ cơ bản đến nâng cao.