3) Tạo Deployment và tham chiếu đến Secret và Configmap:
Tham chiếu đến Secret chỉ định và biết chúng environment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app-container
image: gitpod/openvscode-server:1.101.1
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-password
key: password
Kiểm tra env trong pod:
kubectl exec -it <pod name> -- bash
Biến tất cả các key/value trong secret thành Environment của Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app-container
image: gitpod/openvscode-server:1.101.1
envFrom:
- secretRef:
name: db-password
Biến tất cả các key/value trong Configmap thành Environment của Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app-container
image: gitpod/openvscode-server:1.101.1
envFrom:
- configMapRef:
name: app-config
Mount ConfigMap thành file trong Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app-container
image: gitpod/openvscode-server:1.101.1
volumeMounts:
- name: config-volume
# Đường dẫn đích trong container.
# QUAN TRỌNG: Vì có `subPath` ở dưới, `/etc/config` sẽ trở thành một FILE, không phải một thư mục.
# Nội dung của file /etc/config sẽ là nội dung của key `schedule.txt` trong ConfigMap.
mountPath: /etc/config
# Chỉ định chỉ mount một file/mục cụ thể từ Volume.
# Tên `schedule.txt` này PHẢI KHỚP VỚI MỘT KEY trong phần `data` của ConfigMap `app-config`.
subPath: schedule.txt
volumes:
- name: config-volume
configMap:
# Tham chiếu đến tên của ConfigMap sẽ được sử dụng làm nguồn dữ liệu cho Volume `config-volume`.
name: app-config
Nếu trong configmap có nhiều Key/Value
kubectl create configmap multi-config --from-literal=database.conf=postgres://user:pass@localhost/db --from-literal=apt.conf=your_api_key_here
######
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app-container
image: gitpod/openvscode-server:1.101.1
volumeMounts:
- name: config-volume
mountPath: /etc/config # Đường dẫn nơi các file sẽ được mount vào container
volumes:
- name: config-volume
configMap:
name: multi-config # Tên của ConfigMap
Biến secret thành 1 file trong workload:
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
data:
username: YWRtaW4= # echo -n 'admin' | base64
password: UzNjclN0UEBzc3cwcmQ= # echo -n 'S3cr3tP@ssw0rd' | base64
####
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment-with-secret
spec:
replicas: 2 # Bạn có thể tạo bao nhiêu Pod tùy ý
selector:
matchLabels:
app: my-secret-app
template: # Đây là phần định nghĩa cho Pod sẽ được tạo ra
metadata:
labels:
app: my-secret-app # Label này phải khớp với selector ở trên
spec: # Toàn bộ spec của Pod sẽ nằm ở đây
containers:
- name: my-app-container
image: busybox
# Lệnh này giữ cho container chạy để chúng ta có thể kiểm tra
command: [ "sleep", "3600" ]
volumeMounts:
# Mount key 'username' từ Secret thành một file
- name: secret-volume
mountPath: /etc/db/username # Đường dẫn đầy đủ đến file username
subPath: username # Tên của key trong Secret
# Mount key 'password' từ Secret thành một file khác
- name: secret-volume
mountPath: /etc/db/password # Đường dẫn đầy đủ đến file password
subPath: password # Tên của key trong Secret
volumes:
# Khai báo Volume sẽ sử dụng Secret
- name: secret-volume
secret:
secretName: db-credentials # Tên của Secret cần sử dụng
####
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment-with-secret
spec:
replicas: 2 # Bạn có thể tạo bao nhiêu Pod tùy ý
selector:
matchLabels:
app: my-secret-app
template: # Đây là phần định nghĩa cho Pod sẽ được tạo ra
metadata:
labels:
app: my-secret-app # Label này phải khớp với selector ở trên
spec: # Toàn bộ spec của Pod sẽ nằm ở đây
containers:
- name: my-app-container
image: busybox
# Lệnh này giữ cho container chạy để chúng ta có thể kiểm tra
command: [ "sleep", "3600" ]
volumeMounts:
- name: secret-volume
mountPath: /etc/db/
volumes:
# Khai báo Volume sẽ sử dụng Secret
- name: secret-volume
secret:
secretName: db-credentials # Tên của Secret cần sử dụng
4) Kiến thức thực tiễn
Câu hỏi đặt ra là: Khi chúng ta chỉnh sửa (edit) một ConfigMap hoặc Secret, có cần phải khởi động lại (terminate/restart) các Pod đang sử dụng nó không?
4.1) Khi ConfigMap/Secret được mount dưới dạng Volume
Đây là trường hợp phức tạp hơn và cần được chia thành hai tình huống:
4.1.a) Khi Mount toàn bộ Volume (Không dùng subPath)
Đây là trường hợp bạn mount toàn bộ ConfigMap/Secret vào một thư mục.
# Ví dụ: không có subPath
volumeMounts:
- name: config-volume
mountPath: /etc/config
-
Hành vi: Kubernetes sẽ tự động cập nhật các file bên trong thư mục
/etc/configkhi ConfigMap/Secret thay đổi. -
Cơ chế: Kubelet tạo ra một cấu trúc thư mục với các symlink (liên kết tượng trưng). Khi ConfigMap thay đổi, Kubelet sẽ cập nhật các symlink này để trỏ đến dữ liệu mới.
-
Cần khởi động lại Pod không? Không.
-
Lưu ý quan trọng:
-
Sẽ có một độ trễ ngắn (thường dưới một phút) để kubelet đồng bộ thay đổi.
-
Ứng dụng của bạn phải có khả năng phát hiện thay đổi và tải lại file cấu hình một cách linh động. Nếu ứng dụng chỉ đọc file cấu hình một lần khi khởi động, bạn vẫn phải khởi động lại Pod để nó nhận thay đổi.
-
4.1.b) Khi Mount bằng subPath (Mount một file cụ thể)
Đây là trường hợp bạn chỉ mount một key duy nhất từ ConfigMap/Secret thành một file.
# Ví dụ: có dùng subPath
volumeMounts:
- name: config-volume
mountPath: /etc/config/schedule.txt
subPath: schedule.txt
-
Hành vi: Dữ liệu được mount sẽ KHÔNG tự động cập nhật.
-
Cơ chế: Việc sử dụng
subPathsẽ ngăn cản Kubelet sử dụng cơ chế symlink. Thay vào đó, nó tạo ra một file vật lý (inode) trực tiếp trên filesystem của container. File này sẽ không thay đổi ngay cả khi ConfigMap/Secret gốc đã được cập nhật. -
Cần khởi động lại Pod không? Có. Bạn bắt buộc phải khởi động lại Pod để nó đọc lại dữ liệu mới từ ConfigMap/Secret.
4.2) Khi ConfigMap/Secret được dùng làm Biến môi trường (Environment Variables)
# Ví dụ: Dùng làm biến môi trường
env:
- name: MY_SETTING
valueFrom:
configMapKeyRef:
name: my-config
key: my-key
-
Hành vi: Giá trị của biến môi trường sẽ KHÔNG tự động cập nhật.
-
Cơ chế: Biến môi trường chỉ được thiết lập một lần duy nhất khi container được khởi tạo.
-
Cần khởi động lại Pod không? Có.
Bảng tóm tắt (Summary Table) đã cập nhật
| Kiểu Mount (Mount Type) | Tự động cập nhật? (Auto Update?) | Cần khởi động lại Pod? (Pod Restart Needed?) | Ứng dụng cần tải lại động? (App Reload Needed?) |
|---|---|---|---|
| Volume (Toàn bộ thư mục) | Có (sau một lúc) | Không | Có (Rất quan trọng!) |
Volume (Dùng subPath) |
Không | Có | Không áp dụng (Vì Pod phải khởi động lại) |
| Biến môi trường (Env Variables) | Không | Có | Không áp dụng |