Cấu hình Namespace và Resource Quota để phân tách tài nguyên
Việc đầu tiên là tạo ra các Namespace riêng biệt cho từng tenant để cô lập không gian logic, sau đó áp dụng ResourceQuota để giới hạn tổng tài nguyên và LimitRange để kiểm soát mức tối thiểu/tối đa cho từng Pod.
Tạo file cấu hình Kubernetes cho tenant "tenant-a" và "tenant-b" với các giới hạn tài nguyên cụ thể. File này sẽ được lưu tại /etc/k8s/tenant-configs/tenants.yaml.
apiVersion: v1
kind: Namespace
metadata:
name: tenant-a
labels:
team: team-a
environment: production
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: tenant-a-quota
namespace: tenant-a
spec:
hard:
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "8"
limits.memory: 16Gi
pods: "20"
---
apiVersion: v1
kind: LimitRange
metadata:
name: tenant-a-limits
namespace: tenant-a
spec:
limits:
- default:
cpu: 500m
memory: 512Mi
defaultRequest:
cpu: 100m
memory: 128Mi
max:
cpu: "2"
memory: 4Gi
min:
cpu: 50m
memory: 64Mi
type: Container
---
apiVersion: v1
kind: Namespace
metadata:
name: tenant-b
labels:
team: team-b
environment: staging
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: tenant-b-quota
namespace: tenant-b
spec:
hard:
requests.cpu: "2"
requests.memory: 4Gi
limits.cpu: "4"
limits.memory: 8Gi
pods: "10"
---
apiVersion: v1
kind: LimitRange
metadata:
name: tenant-b-limits
namespace: tenant-b
spec:
limits:
- default:
cpu: 200m
memory: 256Mi
defaultRequest:
cpu: 50m
memory: 64Mi
max:
cpu: "1"
memory: 2Gi
min:
cpu: 25m
memory: 32Mi
type: Container
Áp dụng cấu hình vào cluster để tạo Namespace và áp đặt giới hạn ngay lập tức.
kubectl apply -f /etc/k8s/tenant-configs/tenants.yaml
Kiểm tra xem Namespace đã được tạo và ResourceQuota đã được gắn (bound) chưa. Bạn sẽ thấy trạng thái "Bound" trong output của lệnh describe.
kubectl get namespaces | grep tenant
kubectl describe quota tenant-a-quota -n tenant-a
kubectl describe limitrange tenant-a-limits -n tenant-a
Cô lập mạng giữa các Tenant với NetworkPolicy
Sau khi có Namespace, cần ngăn chặn lưu lượng mạng mặc định (allow-all) giữa các tenant. Chúng ta sẽ sử dụng NetworkPolicy để chỉ cho phép traffic từ bên trong cùng tenant hoặc từ các dịch vụ hệ thống cụ thể (như DNS).
Chuẩn bị file cấu hình NetworkPolicy tại /etc/k8s/tenant-configs/network-policies.yaml. Cấu hình này áp dụng chính sách "Default Deny" cho tất cả các Pod trong namespace, sau đó mở cổng cho traffic nội bộ.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-tenant-a
namespace: tenant-a
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-internal-tenant-a
namespace: tenant-a
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector: {}
- namespaceSelector:
matchLabels:
team: team-a
egress:
- to:
- podSelector: {}
- namespaceSelector:
matchLabels:
team: team-a
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-tenant-b
namespace: tenant-b
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-internal-tenant-b
namespace: tenant-b
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector: {}
- namespaceSelector:
matchLabels:
team: team-b
egress:
- to:
- podSelector: {}
- namespaceSelector:
matchLabels:
team: team-b
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
Áp dụng NetworkPolicy vào cluster. Lưu ý: Cluster của bạn phải đang chạy CNI hỗ trợ NetworkPolicy (như Calico, Cilium, hoặc Weave Net).
kubectl apply -f /etc/k8s/tenant-configs/network-policies.yaml
Verify bằng cách tạo 2 Pod test (mỗi tenant 1 cái) và cố gắng ping từ tenant-a sang tenant-b. Kết quả mong đợi là timeout hoặc connection refused, chứng tỏ NetworkPolicy đang hoạt động.
kubectl run test-a --image=busybox:1.28 --namespace=tenant-a --command -- sleep 3600
kubectl run test-b --image=busybox:1.28 --namespace=tenant-b --command -- sleep 3600
kubectl exec -it test-a -n tenant-a -- ping -c 3 test-b.tenant-b.svc.cluster.local
Thiết lập RBAC cơ bản cho User và Service Account
Để đảm bảo người dùng của tenant A không thể thao tác trên tài nguyên của tenant B, cần thiết lập Role và RoleBinding giới hạn phạm vi tác động (scope) trong namespace tương ứng. Service Account cũng cần được cấu hình tương tự.
Tạo file RBAC tại /etc/k8s/tenant-configs/rbac.yaml. File này định nghĩa Role cho phép read/write Pod, Service trong namespace và gắn nó vào ServiceAccount hoặc User cụ thể.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: tenant-a-developer
namespace: tenant-a
rules:
- apiGroups: ["", "extensions", "apps"]
resources: ["pods", "services", "deployments", "configmaps", "secrets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: tenant-a-dev-binding
namespace: tenant-a
subjects:
- kind: ServiceAccount
name: tenant-a-sa
namespace: tenant-a
- kind: Group
name: "team-a-users"
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: tenant-a-developer
apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: tenant-a-sa
namespace: tenant-a
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: tenant-b-developer
namespace: tenant-b
rules:
- apiGroups: ["", "extensions", "apps"]
resources: ["pods", "services", "deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: tenant-b-dev-binding
namespace: tenant-b
subjects:
- kind: ServiceAccount
name: tenant-b-sa
namespace: tenant-b
roleRef:
kind: Role
name: tenant-b-developer
apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: tenant-b-sa
namespace: tenant-b
Áp dụng cấu hình RBAC vào cluster. Các ServiceAccount sẽ được tự động tạo ra cùng lúc với Role và RoleBinding.
kubectl apply -f /etc/k8s/tenant-configs/rbac.yaml
Kiểm tra xem RoleBinding đã được tạo đúng namespace và gắn với Subject chưa. Sau đó, thử dùng ServiceAccount của tenant-a để liệt kê Pod trong tenant-b (sẽ bị từ chối lỗi 403 Forbidden).
kubectl get rolebindings -n tenant-a
kubectl get rolebindings -n tenant-b
kubectl auth can-i list pods --namespace=tenant-b --as=system:serviceaccount:tenant-a:tenant-a-sa
Triển khai Service Mesh (Istio) để quản lý Traffic nội bộ
Để nâng cao khả năng kiểm soát traffic, giám sát và bảo mật (mTLS) giữa các microservices của tenant, chúng ta sẽ triển khai Istio. Cấu hình này sẽ tập trung vào việc inject sidecar và thiết lập PeerAuthentication để yêu cầu mTLS bắt buộc.
Triển khai Istio bằng cách sử dụng profile "demo" hoặc "default" tùy vào nhu cầu, sau đó đánh dấu namespace tenant để tự động inject Envoy sidecar. File cấu hình nằm tại /etc/k8s/istio/istio-setup.yaml.
apiVersion: v1
kind: Namespace
metadata:
name: istio-system
---
# Lưu ý: Trong thực tế, bạn cần chạy lệnh 'istioctl install' trước.
# Đây là cấu hình để đánh dấu namespace tenant để tự động inject sidecar.
apiVersion: v1
kind: Namespace
metadata:
name: tenant-a
labels:
istio-injection: enabled
---
apiVersion: v1
kind: Namespace
metadata:
name: tenant-b
labels:
istio-injection: enabled
---
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: tenant-a-mtls
namespace: tenant-a
spec:
mtls:
mode: STRICT
---
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: tenant-b-mtls
namespace: tenant-b
spec:
mtls:
mode: STRICT
Áp dụng nhãn injection vào các namespace tenant và thiết lập chính sách mTLS STRICT. Đảm bảo rằng Istio control plane đã được cài đặt trong cluster trước khi chạy lệnh này.
kubectl label namespace tenant-a istio-injection=enabled
kubectl label namespace tenant-b istio-injection=enabled
kubectl apply -f /etc/k8s/istio/istio-setup.yaml
Deploy một ứng dụng mẫu vào tenant-a và tenant-b. Sau khi Pod lên, kiểm tra xem có thêm container "istio-proxy" hay không và verify kết nối mTLS bằng cách vào bên trong Pod.
kubectl run sleep-a --image=busybox:1.28 --namespace=tenant-a --command -- sleep 3600
kubectl run sleep-b --image=busybox:1.28 --namespace=tenant-b --command -- sleep 3600
kubectl get pods -n tenant-a -o wide
kubectl exec -it sleep-a -n tenant-a -- ls -la /etc/istio/config
Điều hướng series:
Mục lục: Series: Series: Xây dựng nền tảng Secure Multi-Tenant Data Platform với Kubernetes, Falco, OPA và Apache Iceberg để bảo vệ dữ liệu doanh nghiệp trong môi trường chia sẻ tài nguyên
« Phần 1: Chuẩn bị môi trường và kiến trúc tổng quan cho nền tảng Multi-Tenant
Phần 3: Xây dựng nền tảng dữ liệu Apache Iceberg với cơ chế chia sẻ an toàn »