Tóm tắt: Tạo bằng kubectl create configmap|secret ... --dry-run=client -o yaml | kubectl apply -f - (idempotent). Đưa vào Pod qua env (env/envFrom, chỉ đọc lúc container start) hoặc volume (file, kubelet tự cập nhật sau một khoảng trễ, trừ subPath). Đổi giá trị env thì phải kubectl rollout restart. Secret chỉ là base64, cần RBAC và encryption at rest.
Luồng hoạt động
flowchart LR F["file / literal / .env"] --> C["ConfigMap / Secret"] C -->|"env, envFrom"| E["Biến môi trường (đọc 1 lần khi start)"] C -->|"volume"| V["File trong Pod (tự cập nhật, trễ)"] C -->|"volume + subPath"| S["File (KHÔNG cập nhật)"] E --> R["rollout restart để nhận giá trị mới"]
Cấu hình
Tạo bằng kubectl
# ConfigMap
kubectl create configmap api-config -n app \
--from-literal=LOG_LEVEL=info --from-literal=APP_ENV=prod \
--dry-run=client -o yaml | kubectl apply -f -
kubectl create configmap api-env -n app --from-env-file=api.env \
--dry-run=client -o yaml | kubectl apply -f -
kubectl create configmap nginx-conf -n app --from-file=default.conf=./nginx/default.conf \
--dry-run=client -o yaml | kubectl apply -f -
# Secret generic: đọc giá trị từ biến môi trường/file, không gõ thẳng trên dòng lệnh
kubectl create secret generic api-db -n app \
--from-literal=username=api \
--from-literal=password="$DB_PASSWORD" \
--dry-run=client -o yaml | kubectl apply -f -
# Secret TLS (key tls.crt, tls.key) và pull secret cho registry
kubectl create secret tls app-tls -n app --cert=fullchain.pem --key=privkey.pem
kubectl create secret docker-registry regcred -n app \
--docker-server=registry.example.com --docker-username=ci --docker-password="$REG_TOKEN"--from-env-file không dùng chung được với --from-literal/--from-file trong cùng một lệnh (error: from-env-file cannot be combined...): tách thành hai ConfigMap hoặc gộp hết vào file .env.
Manifest
apiVersion: v1
kind: ConfigMap
metadata:
name: api-config
namespace: app
data:
LOG_LEVEL: info
app.toml: |
[server]
port = 8000
---
apiVersion: v1
kind: Secret
metadata:
name: api-db
namespace: app
type: Opaque
stringData: # viết plain text, API server tự encode base64 vào data
username: api
password: "***" # đừng commit giá trị thật, dùng SOPS / Sealed Secrets / External SecretsĐưa vào Pod: env và volume
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
namespace: app
spec:
selector:
matchLabels: { app: api }
template:
metadata:
labels: { app: api }
spec:
containers:
- name: api
image: registry.example.com/api:1.4.2
envFrom:
- configMapRef: { name: api-config } # mọi key hợp lệ thành biến env
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef: { name: api-db, key: password }
volumeMounts:
- name: config
mountPath: /etc/api # /etc/api/app.toml, tự cập nhật
readOnly: true
- name: tls
mountPath: /etc/tls
readOnly: true
volumes:
- name: config
configMap:
name: api-config
items:
- key: app.toml
path: app.toml
- name: tls
secret:
secretName: app-tls
defaultMode: 0400| env / envFrom | volume | |
|---|---|---|
| Đổi giá trị | Không cập nhật, cần restart Pod | Kubelet cập nhật file sau vài chục giây đến khoảng 1-2 phút |
| Lộ secret | Dễ lộ qua env, crash dump, log debug |
Ít lộ hơn, phân quyền file được |
| App phải làm gì | Không gì | Tự theo dõi file và reload (inotify, SIGHUP), hoặc restart |
Làm app nhận cấu hình mới
# Cách đơn giản: restart rolling sau khi apply ConfigMap/Secret
kubectl apply -f api-config.yaml && kubectl rollout restart deploy/api -n app
kubectl rollout status deploy/api -n app
# Kiểm tra giá trị Pod đang thấy
kubectl exec -n app deploy/api -- env | grep LOG_LEVEL
kubectl exec -n app deploy/api -- cat /etc/api/app.tomlTự động hoá:
- Kustomize
configMapGenerator/secretGenerator: tên có hậu tố hash nội dung, đổi nội dung là đổi tên, Deployment tự rollout. - Helm: annotation
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}trong Pod template. - Controller như Stakater Reloader theo dõi ConfigMap/Secret và tự restart workload có annotation.
Cấu hình không bao giờ đổi lúc chạy: đặt immutable: true để giảm tải watch cho API server (muốn đổi phải xoá rồi tạo lại).
Lỗi thường gặp
| Triệu chứng | Nguyên nhân | Cách xử lý |
|---|---|---|
Pod CreateContainerConfigError |
ConfigMap/Secret hoặc key được tham chiếu không tồn tại (sai namespace) | kubectl describe pod xem tên thiếu; hoặc optional: true nếu thật sự tuỳ chọn |
Pod kẹt ContainerCreating, event FailedMount ... not found |
Volume tham chiếu ConfigMap/Secret chưa có | Tạo trước, kiểm tra namespace |
| Đã apply ConfigMap mới mà app vẫn giá trị cũ | Dùng env, hoặc app không reload file | kubectl rollout restart |
File mount bằng subPath không bao giờ cập nhật |
Hạn chế của subPath |
Mount cả thư mục, hoặc restart khi đổi |
Key bị bỏ qua khi envFrom |
Tên key không phải tên biến env hợp lệ (vd app.toml) |
Dùng env.valueFrom đặt tên riêng, hoặc mount file |
kubectl apply báo field is immutable |
ConfigMap/Secret có immutable: true |
Xoá và tạo lại, rồi restart Pod |
| Lỗi tạo object quá lớn | ConfigMap/Secret tối đa 1 MiB | Đưa file lớn vào image hoặc volume khác |
| Secret có giá trị sai ký tự xuống dòng | echo thêm \n khi tự base64 |
Dùng stringData hoặc echo -n / printf |