Cấu hình RBAC và giới hạn quyền truy cập Namespace
Bước đầu tiên là thiết lập cơ chế phân quyền chặt chẽ để mỗi nhóm phát triển chỉ có quyền thao tác trong namespace riêng của họ, ngăn chặn truy cập trái phép vào các tài nguyên hệ thống.
Chúng ta sẽ tạo Role và RoleBinding cho namespace cụ thể, sau đó gán ServiceAccount của Backstage hoặc user Kubernetes vào Role đó.
1. Tạo file Role cho namespace dev-sprint-01 để giới hạn quyền chỉ đọc và ghi đối với Deployment và Pod.
cat > /etc/kubernetes/rbac/dev-sprint-01-role.yaml
Kết quả mong đợi: File YAML được tạo thành công, định nghĩa quyền hạn cụ thể cho namespace này.
2. Áp dụng Role vừa tạo vào cluster.
kubectl apply -f /etc/kubernetes/rbac/dev-sprint-01-role.yaml
Kết quả mong đợi: Thông báo "role.rbac.authorization.k8s.io/dev-sprint-01-developer created".
3. Tạo RoleBinding để liên kết Role với ServiceAccount của Backstage (giả sử tên là backstage-runner).
cat > /etc/kubernetes/rbac/dev-sprint-01-binding.yaml
Kết quả mong đợi: File YAML được tạo, chuẩn bị cho việc cấp quyền.
4. Áp dụng RoleBinding.
kubectl apply -f /etc/kubernetes/rbac/dev-sprint-01-binding.yaml
Kết quả mong đợi: Thông báo "rolebinding.rbac.authorization.k8s.io/dev-sprint-01-binding created".
Verify kết quả RBAC
Chạy lệnh kiểm tra xem ServiceAccount có thể liệt kê Pod trong namespace hay không.
kubectl auth can-i list pods --namespace=dev-sprint-01 --subsystem=backstage-runner
Kết quả mong đợi: Trả về "yes". Nếu trả về "no", cần kiểm tra lại ServiceAccount name hoặc RoleRef.
Tích hợp Backstage với Kubernetes để hiển thị trạng thái
Bước tiếp theo là cấu hình plugin kubernetes trong Backstage để nó có thể kết nối với cluster và hiển thị trạng thái tài nguyên theo đúng quyền hạn RBAC đã định nghĩa ở trên.
1. Cài đặt plugin Kubernetes trong Backstage.
cd /opt/backstage
npm install @backstage/plugin-kubernetes
Kết quả mong đợi: Package được cài đặt và dependencies được giải quyết.
2. Tạo file cấu hình app-config.yaml để Backstage biết cách kết nối tới cluster và sử dụng RoleBinding đã tạo.
cat > /opt/backstage/app-config.yaml
Kết quả mong đợi: File cấu hình được tạo, Backstage sẽ sử dụng token của ServiceAccount để authenticate và lọc namespace dựa trên RoleBinding.
3. Cập nhật file catalog-info.yaml của hệ thống để kích hoạt plugin.
cat > /opt/backstage/entities/catalog-info.yaml
Kết quả mong đợi: File metadata được cập nhật, Backstage sẽ quét và hiển thị cluster trong tab Kubernetes.
Verify kết quả tích hợp Backstage
Truy cập trang web Backstage, vào tab "Kubernetes", chọn cluster "dev-cluster".
Kết quả mong đợi: Chỉ hiển thị namespace dev-sprint-01 và các Pod/Deployment bên trong. Các namespace khác (như kube-system) sẽ bị ẩn hoặc không hiển thị do RBAC chặn.
Xây dựng quy trình tự động xóa môi trường Dev sau Sprint
Để tránh lãng phí tài nguyên, chúng ta cần một cơ chế tự động xóa toàn bộ namespace khi Sprint kết thúc. Chúng ta sẽ sử dụng Kubernetes CronJob kết hợp với TimeToLive annotation.
1. Tạo một CronJob chạy mỗi đêm lúc 23:00 để quét các namespace có annotation ttl: delete-after-sprint và đã hết hạn.
cat > /etc/kubernetes/jobs/sprint-cleanup-cronjob.yaml
Kết quả mong đợi: CronJob được tạo, sẵn sàng chạy định kỳ.
2. Áp dụng CronJob.
kubectl apply -f /etc/kubernetes/jobs/sprint-cleanup-cronjob.yaml
Kết quả mong đợi: Thông báo "cronjob.batch/dev-sprint-cleanup created".
3. Cấu hình Crossplane để tự động gắn annotation khi tạo môi trường mới từ Template Backstage.
Chúng ta cần sửa lại CompositeResourceDefinition hoặc Composition của Crossplane để thêm metadata ttl vào Namespace.
cat > /etc/crossplane/compositions/namespace-sprint.yaml
Kết quả mong đợi: Composition được cập nhật, khi Backstage tạo request, Crossplane sẽ tự động gắn ngày hết hạn vào metadata của Namespace.
Verify kết quả tự động xóa
Tạo một Namespace test có annotation ngày hết hạn trong quá khứ để kiểm tra logic CronJob.
kubectl create namespace test-cleanup
kubectl annotate namespace test-cleanup tTL/deletion-date="2020-01-01"
Kiểm tra cronjob logs sau khi kích hoạt thủ công hoặc chờ đến giờ chạy.
kubectl logs -f \$(kubectl get pod -l job-name=sprint-cleanup-cleanup -o jsonpath='{.items[0].metadata.name}')
Kết quả mong đợi: Namespace test-cleanup bị xóa và log hiển thị thông báo xóa thành công.
Cấu hình cảnh báo (Alerting) chi phí và lỗi Sync
Chúng ta cần Prometheus và Alertmanager để giám sát. Mục tiêu là cảnh báo khi chi phí dự kiến vượt ngưỡng hoặc khi ArgoCD/Crossplane gặp lỗi sync.
1. Cài đặt Prometheus Operator (giả định đã có), tạo file PrometheusRule cho cảnh báo.
cat > /etc/prometheus/rules/platform-alerts.yaml 0
for: 5m
labels:
severity: critical
team: platform-team
annotations:
summary: "Crossplane gặp lỗi khi đồng bộ tài nguyên"
description: "Có lỗi xảy ra trong quá trình reconcile của Crossplane."
- alert: ArgoCDAppOutOfSync
expr: argocd_app_health_status{status="Degraded"} == 1
for: 10m
labels:
severity: critical
team: dev-team
annotations:
summary: "Ứng dụng ArgoCD bị lỗi hoặc không đồng bộ"
description: "Ứng dụng \$\$argocd_app_name\$\$ đang ở trạng thái Degraded."
EOF
Kết quả mong đợi: File rule được tạo với các biểu thức PromQL chính xác.
2. Áp dụng Rule vào cluster.
kubectl apply -f /etc/prometheus/rules/platform-alerts.yaml
Kết quả mong đợi: Thông báo "prometheusrule.monitoring.coreos.com/platform-engineering-alerts created".
3. Cấu hình Alertmanager để gửi cảnh báo vào kênh Slack hoặc Email của team.
cat > /etc/alertmanager/alertmanager-config.yaml
Kết quả mong đợi: File cấu hình Alertmanager được tạo.
Verify kết quả Alerting
Trigger một cảnh báo thử nghiệm bằng cách tạo một Pod giả tạo tiêu tốn tài nguyên hoặc gây lỗi sync.
kubectl create deployment test-spam --image=busybox --replicas=10 --command sleep infinity
Kiểm tra dashboard Prometheus tại http://prometheus:9090/alerts.
Kết quả mong đợi: Alert "HighInfrastructureCost" chuyển sang trạng thái "Firing" và thông báo được gửi vào kênh Slack #platform-alerts.
Quản lý Secrets và Credentials an toàn
Chúng ta sẽ sử dụng ExternalSecrets (qua Crossplane hoặc External Secrets Operator) để đồng bộ secrets từ Vault hoặc AWS Secrets Manager vào Kubernetes mà không lưu nội dung plaintext trong Git.
1. Cài đặt External Secrets Operator (giả định đã có) và tạo SecretStore để kết nối với Vault.
cat > /etc/external-secrets/vault-secretstore.yaml
Kết quả mong đợi: SecretStore được tạo, cho phép External Secrets truy cập Vault.
2. Tạo ExternalSecret để tự động kéo secret từ Vault vào Kubernetes.
cat > /etc/external-secrets/external-secret-db.yaml
Kết quả mong đợi: ExternalSecret được tạo, nó sẽ tự động tạo một Kubernetes Secret tên db-creds-secret với giá trị DB_PASSWORD lấy từ Vault.
3. Áp dụng cả hai tài nguyên.
kubectl apply -f /etc/external-secrets/vault-secretstore.yaml
kubectl apply -f /etc/external-secrets/external-secret-db.yaml
Kết quả mong đợi: Thông báo "secretstore.external-secrets.io/vault-backend created" và "externalsecret.external-secrets.io/db-credentials created".
Verify kết quả quản lý Secrets
Kiểm tra xem Kubernetes Secret có được tạo và có giá trị hay không (không hiển thị giá trị thật).
kubectl get secret db-creds-secret -n dev-sprint-01 -o jsonpath='{.data}'
Kết quả mong đợi: Trả về JSON chứa các key đã được base64 encode. Nếu chạy lệnh kubectl describe secret db-creds-secret, bạn sẽ thấy giá trị DB_PASSWORD tồn tại.
Để kiểm tra tính an toàn, thử truy cập file config trong Git, đảm bảo không có giá trị plaintext nào.
git log --oneline -- /path/to/secrets
Kết quả mong đợi: Không có commit nào chứa file secrets hoặc giá trị nhạy cảm trong lịch sử commit.
Điều hướng series:
Mục lục: Series: Series: Xây dựng hệ thống Platform Engineering nội bộ với Crossplane, Backstage và GitOps trên hạ tầng Kubernetes để tự động hóa môi trường Dev
« Phần 5: Tích hợp Backstage với Crossplane để tạo Template tự động
Phần 7: Troubleshooting, tối ưu hóa và bài học kinh nghiệm »