Xem bản video
Tự gõ ba lệnh này
$ kubectl get secret db-cred -o yaml
data:
password: c2lldUJhbWF0IUAyMDI2
$ echo 'c2lldUJhbWF0IUAyMDI2' | base64 -d
sieuBamat!@2026
Hai giây, từ lúc gõ tới lúc thấy mật khẩu nguyên văn.
base64 không phải mã hoá
| Mã hoá | base64 |
|---|---|
| cần khoá mới đọc ngược lại được | không có khoá nào cả |
| không có khoá → chịu | sinh ra để nhét dữ liệu nhị phân vào một trường chữ |
Mặc định, Secret nằm trong etcd đúng ở dạng đó. Ai đọc được etcd là đọc được hết.
Mã hoá lúc nghỉ — có, nhưng phải tự bật
Khai bằng một EncryptionConfiguration cho API server. Ở đây có một cái bẫy: nếu chọn kiểu đơn
giản nhất thì khoá nằm ngay trên máy chạy control plane — ai lấy được ổ đĩa máy đó thì có cả
hai thứ. Muốn chặt thì dùng nhà cung cấp KMS để khoá nằm ở chỗ khác.
Chỗ làm tôi giật mình nhất
Bạn nghĩ chỉ người có quyền đọc Secret mới đọc được. Không hẳn.
Ai tạo được Pod trong một namespace thì đọc được mọi Secret trong namespace đó. Viết một Pod gắn Secret ấy vào làm volume, rồi in ra. Hết.
create pods ≈ get secrets (cả namespace)
Hệ quả cho cách chia quyền: ranh giới tin cậy thật sự là namespace, không phải loại tài nguyên. Chia RBAC tinh vi trong cùng một namespace mà vẫn cho tạo Pod thì chỉ là cảm giác an toàn.
ConfigMap so với Secret
Giống nhau nhiều hơn bạn tưởng: cùng cách gắn vào Pod, cùng giới hạn 1 MiB (giới hạn của etcd). Khác ở ba chỗ — Secret mã hoá base64, Secret không bị in ra ở một số chỗ, và chúng là hai loại tài nguyên riêng nên RBAC tách được. Chỗ thứ ba mới là giá trị thật.
Biến môi trường so với volume
Khác biệt này làm rất nhiều người mất buổi chiều:
- biến môi trường — đọc đúng một lần lúc container khởi động, sau đó không bao giờ đổi
- volume — kubelet đồng bộ lại, file trong container đổi theo, chỉ trễ một chút
Ngoại lệ phải nhớ: gắn bằng subPath thì mất luôn khả năng cập nhật đó.
Một trường nhỏ đáng bật
kind: ConfigMap
metadata:
name: app-config-v7
immutable: true
Được hai thứ: không ai sửa nhầm một thứ đang có mười dịch vụ dùng, và kubelet thôi phải theo dõi nó (đỡ tải cho API server ở cụm lớn). Muốn đổi thì tạo cái mới rồi trỏ Pod sang.
Làm gì cho đúng
- Bật mã hoá lúc nghỉ — và nếu được thì dùng KMS, đừng để khoá cạnh etcd
- Tách namespace theo ranh giới tin cậy
- Cân nhắc để bí mật thật ở ngoài cụm, trong một kho bí mật riêng, rồi đồng bộ vào — cách này còn được thêm hai thứ Kubernetes không có: xoay khoá tự động, và nhật ký ai đã đọc cái gì
Mang gì đi
- Secret mặc định chỉ là base64 — đừng coi cái tên là một lời hứa
- Ranh giới thật là namespace
- Biến môi trường đọc một lần rồi thôi; muốn cập nhật thì gắn qua volume (và đừng dùng subPath)