Namespace Isolation & Hierarchical Namespace Controller
Tại sao tổ chức namespace quan trọng ở scale
Khi bạn có 5 namespace, quản lý chúng thủ công không vấn đề gì. Khi bạn có 500 namespace cho 500 tenant, hoặc một tenant cần 10 namespace (frontend, backend, batch, staging...), mô hình namespace phẳng (flat) của Kubernetes trở thành nút thắt vận hành. Mỗi namespace cần RBAC RoleBinding, NetworkPolicy default-deny, ResourceQuota, LimitRange, Pod Security labels — và bạn phải áp dụng nhất quán cho hàng trăm namespace, đồng bộ khi policy thay đổi.
Đây là vấn đề propagation: làm sao đảm bảo mọi namespace của tenant X đều thừa kế cùng một bộ chính sách bảo mật, và khi platform team cập nhật chính sách, nó tự động lan tỏa? Namespace phẳng không có khái niệm "cha-con", nên không có propagation tự nhiên. Hierarchical Namespace Controller (HNC) giải quyết chính xác vấn đề này.
Internal model: namespace bao bọc cái gì và không bao bọc cái gì
Để dùng namespace đúng, phải biết chính xác ranh giới của nó. Tài nguyên Kubernetes chia thành hai loại:
Namespaced resources (bị namespace bao bọc): Pod, Deployment, Service, ConfigMap, Secret, ServiceAccount, Role, RoleBinding, NetworkPolicy, ResourceQuota, LimitRange, PVC, Ingress. Hai namespace có thể có Pod cùng tên api mà không xung đột. RBAC scoped theo namespace áp dụng cho các tài nguyên này.
Cluster-scoped resources (KHÔNG bị namespace bao bọc): Node, PersistentVolume, Namespace (bản thân nó), ClusterRole, ClusterRoleBinding, CustomResourceDefinition, StorageClass, PriorityClass, IngressClass. Các tài nguyên này dùng chung toàn cluster — đây là điểm rò rỉ tiềm năng trong multi-tenancy.
Hệ quả thực tế quan trọng cho multi-tenancy:
CRD là cluster-scoped. Nếu một tenant được cấp quyền tạo CRD, họ ảnh hưởng toàn cluster. Đừng cấp quyền CRD cho tenant. Một CRD do tenant A tạo có thể conflict tên hoặc thay đổi hành vi cho tenant B.
PriorityClass là cluster-scoped. Một tenant tạo PriorityClass giá trị cao có thể khiến Pod của họ preempt Pod của tenant khác. Phải kiểm soát ai được tạo/dùng PriorityClass nào (qua admission policy).
StorageClass là cluster-scoped. Tenant chia sẻ StorageClass; phải đảm bảo
reclaimPolicyvà quyền truy cập không rò rỉ volume giữa tenant.PersistentVolume là cluster-scoped (PVC là namespaced). Cần cẩn thận với volume tái sử dụng — dữ liệu của tenant cũ có thể còn trên PV nếu reclaim policy sai.
Shared vs isolated resources: quyết định gì dùng chung
Trong một cluster multi-tenant, một số tài nguyên cố ý dùng chung (để hiệu quả), một số phải cách ly (để bảo mật). Đây là phân loại điển hình:
| Tài nguyên | Chiến lược | Lý do |
|---|---|---|
| Ingress controller | Chia sẻ (platform namespace) | Một LB chung tiết kiệm chi phí; phân tách bằng host/path |
| Monitoring/logging agents | Chia sẻ (DaemonSet cluster-wide) | Cần chạy trên mọi node |
| CoreDNS | Chia sẻ (bắt buộc) | Cluster-level service |
| Secrets | Cách ly (per-namespace) | Không tenant nào được đọc secret của tenant khác |
| ServiceAccount | Cách ly (per-namespace) | Identity phải scoped theo tenant |
| ResourceQuota | Cách ly (per-namespace) | Fair allocation cần ranh giới rõ |
| NetworkPolicy | Cách ly (per-namespace) | Default-deny phải áp dụng riêng từng namespace |
Nguyên tắc: chia sẻ infrastructure (ingress, observability), cách ly identity và data (secrets, SA, quota).
Hierarchical Namespace Controller (HNC)
Vấn đề HNC giải quyết
Namespace của Kubernetes là phẳng — không có quan hệ cha-con. Nhưng tổ chức thực tế có cấu trúc cây: tenant acme có các team con, mỗi team có các môi trường con. Bạn muốn:
- Một policy (RBAC RoleBinding, NetworkPolicy) gắn ở
acmetự động áp dụng cho mọi namespace con củaacme. - Tenant admin của
acmeđược tự tạo namespace con mà không cần quyền tạo namespace ở cấp cluster (vốn là cluster-scoped và nguy hiểm). - Khi platform team cập nhật policy gốc, nó tự lan xuống toàn bộ cây.
HNC là một mở rộng của Kubernetes (open-source, từ nhóm sig-multitenancy, được tích hợp vào GKE qua Config Sync/Hierarchy Controller) tạo ra quan hệ phân cấp giữa các namespace và propagate các đối tượng được chọn từ namespace cha xuống con.
Mental model: cây namespace và propagation
acme (parent namespace)
│ ├── RoleBinding: acme-admins ──┐
│ ├── NetworkPolicy: default-deny ──┤ propagate xuống
│ └── ResourceQuota (qua HRQ) ──┘ tất cả con
│
├── acme-frontend (subnamespace)
│ └── [tự động nhận] acme-admins, default-deny
├── acme-backend (subnamespace)
│ └── [tự động nhận] acme-admins, default-deny
└── acme-batch (subnamespace)
└── [tự động nhận] acme-admins, default-denyCác khái niệm chính:
Subnamespace: namespace con được tạo qua một
SubnamespaceAnchorđặt trong namespace cha. Người có quyền trong namespace cha có thể tạo subnamespace mà không cần quyền cluster-levelcreate namespace. Đây là điểm cốt lõi cho self-service tenant.Propagated objects: HNC propagate các loại đối tượng được cấu hình — mặc định thường là RBAC
Role/RoleBinding, và có thể cấu hình thêmNetworkPolicy,ResourceQuota(qua HierarchicalResourceQuota),LimitRange, Secret, ConfigMap. Đối tượng propagate là bản sao read-only trong namespace con (không sửa được tại con, chỉ sửa ở gốc).Tree labels: HNC tự gắn label
<ns>.tree.hnc.x-k8s.io/depthlên các namespace con, cho phép NetworkPolicy dùng namespaceSelector để khớp toàn bộ cây con của một tenant.HierarchicalResourceQuota (HRQ): cho phép đặt quota ở cấp cha bao trùm tổng tiêu thụ của tất cả con — giải quyết hạn chế rằng ResourceQuota thường chỉ áp dụng một namespace.
Use case multi-tenancy với HNC
Self-service namespace cho tenant: Platform team tạo namespace gốc tenant-acme, gắn RBAC cho tenant admin của acme và một SubnamespaceAnchor quyền. Tenant admin acme tự tạo tenant-acme-prod, tenant-acme-dev mà không cần đụng đến platform team hay quyền cluster-level. Mọi namespace con tự thừa kế default-deny NetworkPolicy và RBAC từ gốc — không thể "quên" áp dụng policy.
Policy propagation nhất quán: Khi compliance yêu cầu mọi namespace của một tenant phải có một NetworkPolicy egress mới, platform team chỉ cần cập nhật ở namespace gốc của tenant; HNC propagate xuống toàn bộ cây. Không có drift giữa các namespace.
Cấu hình HNC trên GKE
Trên GKE, Hierarchy Controller được cung cấp như một phần của Config Sync (Anthos Config Management). Tương tác chính qua plugin kubectl-hns:
# Tạo subnamespace dưới namespace cha
kubectl hns create acme-frontend -n acme
# Xem cây phân cấp
kubectl hns tree acme
# Cấu hình loại object được propagate
kubectl hns config set-resource networkpolicies --mode Propagate
kubectl hns config set-resource resourcequotas --mode PropagateVí dụ SubnamespaceAnchor (cách HNC biểu diễn quan hệ cha-con):
apiVersion: hnc.x-k8s.io/v1alpha2
kind: SubnamespaceAnchor
metadata:
name: acme-frontend # tên namespace con sẽ được tạo
namespace: acme # namespace chaLưu ý: theo tài liệu Config Sync, Hierarchy Controller đang được khuyến nghị thay thế bằng các pattern dựa trên Config Sync namespace inheritance trong các phiên bản mới hơn; hãy kiểm tra phiên bản và lộ trình trước khi áp dụng cho production.
Production architecture patterns
Pattern 1: Tenant root + subnamespace tree
Mỗi tenant có một namespace gốc do platform team quản lý, chứa toàn bộ policy nền tảng. Tenant tự tạo subnamespace cho các môi trường/dịch vụ của họ. Đây là pattern self-service chuẩn cho internal platform quy mô lớn (hàng trăm namespace).
Pattern 2: Flat namespace + GitOps propagation (thay thế HNC)
Nhiều tổ chức không dùng HNC mà thay bằng GitOps: mọi namespace và policy được định nghĩa trong Git, một controller (Config Sync, ArgoCD, Flux) reconcile. Propagation đạt được bằng templating (Kustomize/Helm) trong pipeline thay vì runtime controller. Ưu điểm: ít moving part runtime, audit trail qua Git. Nhược điểm: không có self-service runtime, mọi namespace mới qua PR.
Đây thực tế là hướng đi được ưa chuộng hiện nay vì HNC thêm một controller runtime cần vận hành, trong khi GitOps đã là tiêu chuẩn cho phần lớn platform team.
Common mistakes / anti-patterns
Anti-pattern 1: Một namespace khổng lồ cho nhiều tenant
Vì sao xảy ra: Đội bắt đầu nhỏ, nhồi nhiều ứng dụng/đội vào namespace default hoặc một namespace apps chung.
Hệ quả ở scale: Không thể áp RBAC, Quota, NetworkPolicy ở mức tenant vì tất cả nằm chung một namespace. Không có ranh giới nào. Mọi Pod thấy mọi Service qua DNS, mọi ServiceAccount nằm chung. Tách ra về sau cực kỳ tốn kém.
Cách phòng tránh: Một tenant tối thiểu một namespace ngay từ đầu. Không bao giờ dùng default cho workload production.
Anti-pattern 2: Quên rằng CRD/PriorityClass là cluster-scoped
Vì sao xảy ra: Đội cấp cho tenant một ClusterRole rộng (ví dụ edit ở cấp cluster) nghĩ rằng namespace sẽ giới hạn.
Hệ quả ở scale: Tenant tạo CRD conflict, hoặc PriorityClass giá trị cao để Pod của họ preempt tenant khác. Một tenant chiếm tài nguyên bằng cách tự nâng priority.
Cách phòng tránh: Không bao giờ cấp ClusterRole có quyền ghi tài nguyên cluster-scoped cho tenant. Kiểm soát PriorityClass qua admission policy (xem Chương 10).
Anti-pattern 3: Tin rằng HNC giải quyết bảo mật
Vì sao xảy ra: Nhầm HNC (công cụ tổ chức/propagation) với một cơ chế isolation bảo mật.
Hệ quả ở scale: HNC chỉ giúp áp dụng nhất quán các policy — nó không tự tạo isolation. Nếu các policy được propagate yếu (ví dụ không có default-deny NetworkPolicy), HNC chỉ propagate sự yếu kém đó một cách nhất quán. Bản thân quan hệ cha-con không cách ly gì.
Cách phòng tránh: Dùng HNC để propagate các policy đã được thiết kế đúng. Sức mạnh isolation đến từ NetworkPolicy/RBAC/PSA, HNC chỉ là cơ chế phân phối.