Phần 12 — Multi-tenancy và Multi-cluster: chia sẻ K8s an toàn ở quy mô
Ý kiến
0
Chưa có ý kiến nào. Hãy là người đầu tiên chia sẻ!
Chưa có ý kiến nào. Hãy là người đầu tiên chia sẻ!
Phần cuối series K8s: Cluster API (CAPI) quản lý cluster bằng K8s API, FinOps với OpenCost + Karpenter + right-sizing, AI/ML workloads (GPU, Kubeflow, KServe, vLLM, Argo Workflows, gang scheduling), Edge K8s và WebAssembly.
Service Mesh chuyên sâu cho K8s: Istio (sidecar + ambient), Linkerd (proxy Rust nhẹ), Cilium Service Mesh (eBPF sidecarless) — mTLS, VirtualService, AuthorizationPolicy, canary, mirror, multi-cluster, đo overhead, khi không nên dùng mesh.
Production checklist K8s: observability stack (Prometheus/Loki/Tempo), backup etcd + Velero + app-level, cluster upgrade kubeadm, disaster recovery RTO/RPO, capacity planning, cost optimization, tools nên có.
Series Kubernetes Toàn Tập — 13 phần:
Phần 12 — Multi-tenancy & Multi-cluster ← bạn đang đọc
Khi tổ chức lớn lên, câu hỏi không còn là cluster hoạt động không? mà là nhiều team cùng dùng K8s, nhiều môi trường, nhiều region, làm sao để không dẫm chân và không tốn vô độ?
Phần này gom các pattern multi-tenancy (nhiều tenant chia sẻ một cluster) và multi-cluster (quản lý nhiều cluster).
| Soft | Hard |
|---|---|
| Cùng cluster, tách bằng namespace | Cluster riêng / virtual cluster |
| Trust giữa tenant (cùng công ty/team) | Tenant không tin nhau (SaaS, regulated) |
| Rủi ro: kernel exploit, noisy neighbor | Cô lập gần như VM |
| Cost thấp | Cost cao, vận hành nặng |
Hầu hết tổ chức bắt đầu với soft. Khi tenant không tin nhau (vd. cluster cho khách hàng), hard là bắt buộc.
Mặc định, mọi team có namespace riêng. Trong namespace:
RoleBinding admin ClusterRole cho team lead.
RoleBinding edit cho dev.
RoleBinding view cho stakeholder.
kubectl create namespace team-a
kubectl create rolebinding team-a-admin \
--clusterrole=admin --user=alice --user=bob -n team-a
Đã nói ở Phần 8. Mỗi namespace có quota CPU/RAM/PVC/object để 1 team không độc chiếm cluster.
Ép Pod có resource request/limit. Tránh BestEffort pod ngầm chiếm node.
Mỗi namespace có policy default-deny, allow rõ ràng các đường tới namespace khác qua namespaceSelector.
Tránh team B preempt pod team A. Mỗi tenant có priority class riêng bị giới hạn qua quota:
spec:
scopeSelector:
matchExpressions:
- operator: In
scopeName: PriorityClass
values: ["team-a-default"]
hard:
pods: "100"
Mọi namespace tenant phải restricted. Không cho privileged, hostPath, hostNetwork.
kubectl label namespace team-a \
pod-security.kubernetes.io/enforce=restricted
Ép thêm chính sách custom: image phải từ registry nội bộ, image phải có signature, mọi Service LoadBalancer phải có tag cost-center, mọi Pod phải có topologySpreadConstraints…
Soft tenancy không bảo vệ khỏi:
Kernel exploit (escape container). Bật seccomp, AppArmor, dùng Kata Containers cho workload không tin được.
Noisy neighbor: pod ăn IOPS/network băng thông. Mitigate bằng node pool tách biệt + taints + tolerations.
CoreDNS/etcd quá tải khi tenant tạo nhiều object. Resource quota object count + monitoring.
Namespace flat không thể hiện cấu trúc team → squad → service. HNC (extension chính thức) cho phép namespace cha–con. Policy/RoleBinding ở cha tự xuống con.
apiVersion: hnc.x-k8s.io/v1alpha2
kind: SubnamespaceAnchor
metadata:
name: team-a-dev
namespace: team-a
HNC tạo namespace con team-a-dev, tự inherit RBAC, ResourceQuota, NetworkPolicy từ team-a.
Operator open-source quản lý tenant như object. Tenant gồm nhiều namespace, owner, quota, policy.
apiVersion: capsule.clastix.io/v1beta2
kind: Tenant
metadata:
name: team-a
spec:
owners:
- name: alice
kind: User
resourceQuotas:
items:
- hard:
requests.cpu: "20"
requests.memory: 40Gi
pods: "200"
namespaceOptions:
quota: 5 # tenant tạo tối đa 5 namespace
networkPolicies:
items:
- ingress:
- from:
- namespaceSelector: { matchLabels: { capsule.clastix.io/tenant: team-a } }
vCluster chạy cả control plane (k3s/k0s/k8s) bên trong pod của host cluster. Tenant nhìn vào thấy như cluster K8s riêng — có quyền tạo CRD, ClusterRole, Namespace bất kỳ — nhưng workload thật vẫn ánh xạ về node host.
vcluster create team-a -n vcluster-team-a
vcluster connect team-a -n vcluster-team-a
vCluster cô lập tốt hơn namespace, ít overhead hơn cluster thật. Phù hợp giai đoạn middle-ground hard/soft.
Sản phẩm thương mại bên trên vCluster + Capsule, có UI quản lý nhiều tenant + nhiều cluster.
Khi tenant là khách hàng external hoặc regulated industry (banking, healthcare), cluster riêng là cách an toàn nhất.
Trade-off:
Mỗi cluster control plane riêng (3 master + etcd).
Tối thiểu 3 node worker cho HA.
Quản lý nhiều cluster phức tạp → cần multi-cluster tooling.
Bạn có nhiều cluster vì:
Phân tách env (dev/staging/prod).
Đa region (latency, regulatory data residency, DR).
Hard multi-tenancy (1 cluster / tenant lớn).
Workload đa dạng (gen-purpose, GPU, edge).
┌───────────────┐
│ Mgmt Cluster │ ← Argo CD, Crossplane, Cluster API
└───────┬───────┘
│ provision + sync
┌───────────┼───────────┐
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│ prod- │ │ prod- │ │ stag- │
│ us-east│ │ eu-west│ │ ing │
└────────┘ └────────┘ └────────┘
Management cluster chứa GitOps tools, dashboard, observability — chỉ admin truy cập. Workload chạy ở workload cluster.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: api-everywhere
spec:
generators:
- clusters: {} # tự generate cho mọi cluster đã đăng ký
template:
metadata:
name: 'api-{{name}}'
spec:
project: default
source:
repoURL: https://git.example.com/api
targetRevision: HEAD
path: 'overlays/{{metadata.labels.env}}'
destination:
server: '{{server}}'
namespace: api
Deploy app api sang mọi cluster registered, mỗi cluster dùng overlay theo label env.
Flux có Kustomization object pointing đến Git path. Mỗi cluster reconcile từ branch/path khác.
CAPI là sub-project SIG-Cluster-Lifecycle: K8s API để tạo và quản lý K8s cluster. Bạn khai báo:
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
name: prod-us-east
spec:
controlPlaneRef:
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: KubeadmControlPlane
name: prod-us-east-cp
infrastructureRef:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: AWSCluster
name: prod-us-east
CAPI controller gọi cloud API (AWS/Azure/GCP/vSphere/OpenStack/bare metal) provision máy, init kubeadm, đăng ký node. Upgrade, scale, replace node chỉ là edit CR.
| Tool | Cách làm |
|---|---|
| Submariner | Tunnel L3 giữa cluster + ServiceImport/ServiceExport |
| Skupper | App-level layer 7 mesh, mTLS, không cần network peering |
| Istio multi-cluster | Mesh trải nhiều cluster |
| Cilium Cluster Mesh | eBPF cross-cluster, identity-based policy |
| Linkerd multi-cluster | Gateway pattern, traffic split |
Karmada cho phép apply 1 PropagationPolicy → deploy resource lên N cluster theo placement rule:
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: api
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
name: api
placement:
clusterAffinity:
clusterNames:
- us-east
- eu-west
replicaScheduling:
replicaSchedulingType: Divided
replicaDivisionPreference: Weighted
weightPreference:
staticWeightList:
- targetCluster:
clusterNames: [us-east]
weight: 70
- targetCluster:
clusterNames: [eu-west]
weight: 30
Crossplane mở rộng K8s API để quản lý cloud resource (RDS, S3, VPC, K8s cluster) bằng CR. Tổ chức 1 management cluster control plane mọi cloud asset.
apiVersion: rds.aws.upbound.io/v1beta1
kind: Instance
metadata:
name: app-db
spec:
forProvider:
region: us-east-1
instanceClass: db.t3.medium
engine: postgres
allocatedStorage: 20
writeConnectionSecretToRef:
name: app-db-conn
Mimir / Thanos — receive Prometheus remote write từ mỗi cluster, query liên cluster.
Loki — multi-tenant; mỗi cluster push log với label cluster=.
Grafana ở management cluster, datasource từng cluster hoặc qua federate.
Đặt external_labels: { cluster: prod-us-east } mọi Prometheus tránh đụng metric name.
| Mô hình | Cost tương đối | Vận hành |
|---|---|---|
| 1 cluster, soft tenancy | 1× | Dễ |
| vCluster | 1.2× | Trung bình |
| Cluster / tenant | 3–5× | Khó (cần Cluster API) |
| Multi-region cluster | 2–3× | Khó (cross-region storage, traffic cost) |
Đừng nhảy sang multi-cluster vì nghe nói nó tốt. Mỗi cluster mới = 1 backlog vận hành.
| Use case | Khuyến nghị |
|---|---|
| Startup < 50 service, 1 team | 1 cluster, namespace per service |
| Công ty 5–20 team, trust nội bộ | 1 cluster + Capsule/HNC + Pod Security |
| SaaS host workload khách hàng | vCluster hoặc cluster / tenant |
| Đa region, low latency requirement | Cluster / region + CAPI + ArgoCD |
| Regulated industry (banking, health) | Cluster / tenant, hard isolation |
| Workload đặc thù (GPU, ARM) | NodePool taint + tenant share hoặc cluster riêng |
1 cluster all-prod không có staging/canary cluster — không có nơi test upgrade.
Cluster nhỏ mỗi service — vận hành kinh khủng, cost gấp 10×.
Không có management cluster, vẫn quản lý workload cluster bằng kubectl tay — không repeatable.
Tenant share kube-apiserver nhưng quên ResourceQuota — 1 tenant tạo 100k object phá etcd.
NetworkPolicy chỉ trong namespace, quên policy cross-namespace.
Không có inter-cluster TLS, dùng plain trong public network — vi phạm bảo mật cơ bản.
Bắt đầu soft, nâng dần khi cần.
1 cluster prod / region + 1 staging cluster làm tối thiểu.
Management cluster riêng cho Argo CD, Crossplane, observability.
Mỗi tenant: namespace + RBAC + Quota + LimitRange + NetworkPolicy + Pod Security label, đóng gói bằng Capsule hoặc HNC.
Khi cần hard tenancy: vCluster trước, cluster riêng sau.
Cluster API quản lý lifecycle cluster.
GitOps đa cluster qua Argo CD ApplicationSet hoặc Flux.
Quan trắc liên cluster qua Mimir/Loki/Thanos với label cluster rõ ràng.
Đo cost theo namespace + cluster (opencost), gắn label cost-center.
Soft multi-tenancy: namespace + RBAC + Quota + Network Policy + Pod Security.
Toolbox nâng cao: HNC, Capsule, vCluster, Kyverno.
Hard multi-tenancy: cluster riêng, dùng Cluster API.
Multi-cluster: management cluster + GitOps + service discovery cross-cluster.
Đừng over-engineer — chỉ thêm cluster khi có lý do rõ ràng.
Phần 13: Cluster API sâu, FinOps cho K8s, và workload AI/ML.