Chuyển đến nội dung chính

BÀI 43: MULTI-TENANCY & NAMESPACE ISOLATION

Multi-tenant architecture trên shared K8s cluster, namespace isolation strategies, Network Policies, Hierarchical Namespaces, resource fairness, và tenant onboarding automation.

🔒 DevSecOps — Bài 43 BÀI 43: MULTI-TENANCY & NAMESPACE ISOLATION

Deploy Microservices On-Premises với Kubernetes HA

Phần 10: Deployment Patterns & Auto-Scaling

xdev.asia

🎯 MỤC TIÊU BÀI HỌC

  • ✅ Multi-tenancy models (soft vs hard isolation)
  • ✅ Namespace-per-team/environment strategy
  • ✅ Network Policies cho namespace isolation
  • ✅ RBAC per tenant
  • ✅ Tenant onboarding automation (Kyverno generate)

PHẦN 1: MULTI-TENANCY MODELS


Multi-Tenancy Models:

Model 1: Namespace per Environment
┌────────────────────────────────┐
│     Shared K8s Cluster         │
│  ┌──────┐ ┌──────┐ ┌────────┐ │
│  │ dev  │ │staging│ │  prod  │ │
│  │      │ │      │ │        │ │
│  └──────┘ └──────┘ └────────┘ │
└────────────────────────────────┘

Model 2: Namespace per Team
┌────────────────────────────────┐
│     Shared K8s Cluster         │
│  ┌────────┐ ┌────────┐        │
│  │team-a  │ │team-b  │        │
│  │-staging│ │-staging│ ...    │
│  │-prod   │ │-prod   │        │
│  └────────┘ └────────┘        │
└────────────────────────────────┘

Model 3: Cluster per Team/Env (hard isolation)
┌────────┐ ┌────────┐ ┌──────────┐
│Dev     │ │Staging │ │Production│
│Cluster │ │Cluster │ │Cluster   │
└────────┘ └────────┘ └──────────┘
AspectNamespace IsolationCluster Isolation
CostLow (shared infra)High (separate clusters)
SecurityMedium (soft boundary)High (hard boundary)
ComplexityLowHigh
Resource SharingEfficientWasteful
Best ForSame-org teamsDifferent customers/compliance

PHẦN 2: NAMESPACE STRATEGY

# Namespace template with all isolation:
apiVersion: v1
kind: Namespace
metadata:
  name: team-payments-prod
  labels:
    team: payments
    environment: production
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/enforce-version: latest
  annotations:
    scheduler.alpha.kubernetes.io/node-selector: "env=production"
# Auto-provision with Kyverno (on namespace create):
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: tenant-onboarding
spec:
  rules:
    # 1. Create ResourceQuota:
    - name: generate-quota
      match:
        any:
          - resources:
              kinds: ["Namespace"]
              selector:
                matchExpressions:
                  - key: team
                    operator: Exists
      generate:
        synchronize: true
        apiVersion: v1
        kind: ResourceQuota
        name: tenant-quota
        namespace: "{{request.object.metadata.name}}"
        data:
          spec:
            hard:
              requests.cpu: "8"
              requests.memory: 16Gi
              limits.cpu: "16"
              limits.memory: 32Gi
              pods: "50"
              services.loadbalancers: "2"

    # 2. Create LimitRange:
    - name: generate-limitrange
      match:
        any:
          - resources:
              kinds: ["Namespace"]
              selector:
                matchExpressions:
                  - key: team
                    operator: Exists
      generate:
        synchronize: true
        apiVersion: v1
        kind: LimitRange
        name: tenant-limits
        namespace: "{{request.object.metadata.name}}"
        data:
          spec:
            limits:
              - type: Container
                default:
                  cpu: 200m
                  memory: 256Mi
                defaultRequest:
                  cpu: 100m
                  memory: 128Mi

    # 3. Create default NetworkPolicy:
    - name: generate-netpol
      match:
        any:
          - resources:
              kinds: ["Namespace"]
              selector:
                matchExpressions:
                  - key: team
                    operator: Exists
      generate:
        synchronize: true
        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        name: deny-all-default
        namespace: "{{request.object.metadata.name}}"
        data:
          spec:
            podSelector: {}
            policyTypes:
              - Ingress
              - Egress
            egress:
              - to: []
                ports:
                  - port: 53
                    protocol: UDP
                  - port: 53
                    protocol: TCP

PHẦN 3: NETWORK ISOLATION

# Allow intra-namespace traffic:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-same-namespace
  namespace: team-payments-prod
spec:
  podSelector: {}
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector: {}

---
# Allow ingress from gateway only:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-gateway
  namespace: team-payments-prod
spec:
  podSelector:
    matchLabels:
      app: payment-service
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              app: istio-gateway
      ports:
        - port: 8080

---
# Allow egress to database namespace:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-to-database
  namespace: team-payments-prod
spec:
  podSelector: {}
  policyTypes:
    - Egress
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              purpose: database
      ports:
        - port: 5432
    - to: []
      ports:
        - port: 53
          protocol: UDP

PHẦN 4: RBAC PER TENANT

# Team RBAC:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: team-developer
  namespace: team-payments-prod
rules:
  - apiGroups: ["", "apps", "batch"]
    resources: ["pods", "deployments", "services", "configmaps", "jobs"]
    verbs: ["get", "list", "watch", "create", "update", "delete"]
  - apiGroups: [""]
    resources: ["pods/log", "pods/exec"]
    verbs: ["get", "create"]
  # No access to secrets, RBAC, or namespace-level resources

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: payments-team-binding
  namespace: team-payments-prod
subjects:
  - kind: Group
    name: team-payments
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: team-developer
  apiGroup: rbac.authorization.k8s.io

💡 KEY TAKEAWAYS

  1. Namespace-per-team: Balance isolation vs resource efficiency
  2. Automated onboarding: Kyverno generates Quota + LimitRange + NetworkPolicy
  3. Network isolation: Default deny-all, allow specific cross-namespace
  4. RBAC per tenant: Role per team, no cluster-admin
  5. PSS labels: Enforce restricted on all tenant namespaces

🎯 BÀI TẬP

Bài tập 1: Tenant Onboarding

  • Create namespace with team label → verify auto-provisioned resources
  • Verify NetworkPolicy blocks cross-namespace traffic
  • Test RBAC: team member can deploy, but not access secrets

Bài tập 2: Cross-Namespace Communication

  • Allow team-A service to call team-B API via NetworkPolicy
  • Configure Istio AuthorizationPolicy for service-to-service auth

📚 BÀI TIẾP THEO

Trong Bài 44: Disaster Recovery & Backup Strategies, chúng ta sẽ bắt đầu Section 11 — DR & Chaos Engineering.