Giao diện
ConfigMaps & Secrets: The 12-Factor Way
Trong Kubernetes, việc quản lý cấu hình (Configuration) và dữ liệu nhạy cảm (Secrets) tách biệt khỏi mã nguồn (Code) là một nguyên tắc cốt lõi, tuân thủ chặt chẽ triết lý 12-Factor App. Bài này sẽ đi sâu vào cách xử lý cấu hình chuẩn "Production-Ready".
1. The Problem: Hardcoded Configs
Hãy tưởng tượng bạn có một ứng dụng kết nối Database, và bạn hardcode URL kết nối ngay trong code hoặc Dockerfile:
python
# BAD PRACTICE: Hardcoded Configuration
db_url = "jdbc:postgresql://dev-db:5432/myapp"Vấn đề: Khi bạn muốn deploy lên môi trường Production (prod-db), bạn buộc phải sửa code và rebuild lại toàn bộ Docker Image.
- ❌ Tốn kém: Tốn thời gian build lại, tốn băng thông đẩy image.
- ❌ Rủi ro: Image ở Dev và Prod không giống hệt nhau (vi phạm nguyên tắc "Build once, deploy anywhere").
👉 Giải pháp: Tách cấu hình ra khỏi Image. Inject chúng vào lúc Runtime.
2. ConfigMap (The Plain Text Store)
ConfigMap là object dùng để lưu trữ dữ liệu cấu hình không nhạy cảm (non-confidential data) dưới dạng key-value.
Cơ chế hoạt động
Bạn có thể inject ConfigMap vào Pod theo 2 cách chính:
- Environment Variables: Biến môi trường cho process.
- Mounted Volumes: File cấu hình (ví dụ
nginx.conf) nằm trong container.
💡 Pro Tip: The subPath Trick
Một vấn đề "kinh điển" của Newbie: Khi mount một ConfigMap làm file config (ví dụ /etc/nginx/nginx.conf), mặc định K8s sẽ ghi đè (overwrite) toàn bộ thư mục target /etc/nginx/. Các file có sẵn khác trong thư mục đó sẽ bị mất.
Để chỉ mount đúng 1 file mà không làm ảnh hưởng các file khác, hãy dùng subPath:
yaml
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/nginx.conf # Đường dẫn đích
subPath: nginx.conf # Key trong ConfigMap3. Secrets (The Sensitive Store)
Secret tương tự ConfigMap nhưng dùng cho dữ liệu nhạy cảm (Passwords, OAuth Tokens, SSH Keys).
CAUTION
Base64 is NOT Encryption! Kubernetes lưu Secret dưới dạng Base64 encoded string. Bất kỳ ai có quyền truy cập vào cụm K8s (hoặc file YAML) đều có thể decode nó dễ dàng (echo "..." | base64 -d).
- Secret KHÔNG được mã hóa mặc định khi lưu trong etcd (trừ khi bật Encryption at Rest).
- Tính năng bảo mật chính của Secret là nó được lưu trên RAM (tmpfs) của Worker Node thay vì ghi xuống ổ cứng, giảm nguy cơ bị lộ data khi ổ cứng bị trộm/scan.
HPN Standard: Security First
Tại HPN, chúng ta tuân thủ nghiêm ngặt:
- ❌ NEVER commit Secrets to Git: Dù là repo private, việc lưu plaintext secret trong Git là lỗ hổng bảo mật nghiêm trọng.
- ✅ Use Enterprise Solutions:
- Sealed Secrets (Bitnami): Mã hóa Secret thành
SealedSecret(an toàn để commit Git), chỉ Controller trong Cluster mới decrypt được. - External Secrets Operator (ESO): Sync secret từ các Vault chuyên dụng (AWS Secrets Manager, HashiCorp Vault) vào K8s.
- Sealed Secrets (Bitnami): Mã hóa Secret thành
4. Injection Methods: Env Vars vs Volumes
Làm sao ứng dụng đọc được Config/Secret?
Method A: Environment Variables (Simple)
Thích hợp cho các giá trị đơn lẻ (DB_HOST, API_KEY). Ứng dụng đọc bằng os.environ['DB_HOST'].
yaml
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: db_hostLưu ý: Nếu update ConfigMap, Pod cần restart để nhận ENV mới.
Method B: Volumes (Dynamic Updates - Deep Tech)
Thích hợp cho file config (nginx.conf, settings.json). K8s mount ConfigMap thành file trong Container.
Tính năng mạnh mẽ: Khi bạn update ConfigMap, K8s sẽ tự động update nội dung file trong Container (sau delay khoảng 1-2 phút) mà không cần restart Pod. Ứng dụng cần có cơ chế "watch file change" để reload config (như Nginx reload, hoặc code tự watch).
5. Visual Summary
Next Step: Module 5: Storage & Persistence