Mình lại chào các bạn 👋👋. Mong là chào hoài các bạn không chán 😂
Tiếp tục với series học Kubernetes, ở bài trước ta đã học các Deploy app lên K8S Cluster, scale, update,… Cũng gọi là tự deploy trên K8S được rồi đấy, cơ mà một trong những thứ mà hầu như ta luôn cần khi deploy đó là cấu hình, secret, biến môi trường,… những thứ mà ta cần cấu hình tuỳ biến theo từng môi trường khác nhau (dev, staging, production),…Ở bài này chúng ta sẽ cùng nhau tìm hiểu cách dùng ConfigMap và Secret để làm điều đó nhé (và còn hơn thế nữa ).
Nếu các bạn đã quen với Docker, Docker Compose, cách dùng
environmenthayenv_fromđể truyền biến môi trường vào container thì bài này sẽ rất dễ xơi đấy
Lên thuyền cùng mình nào anh em ⛵️⛵️
Lấy K8S Session
Vẫn như thường lệ, trước khi bắt đầu các bạn đảm giúp mình là đã lấy được K8S Session để truy cập vào cluster của mình đẻ lát nữa ta thực hành nhé. Xem lại bài cũ giúp mình nhé
ConfigMap
Giới thiệu qua chút thì ConfigMap là 1 object lưu data dạng key-value, dùng cho các dạng data không bảo mật, không “nhạy cảm”.
Ta có thể lưu string, number, boolean vào đó hoặc có thể lưu nội dung của cả 1 file text vào cũng được. 1 trong những trường hợp phổ biến nhất là ta dùng nó để lưu biến môi trường. Nghe đơn giản nhỉ ? , ta cùng nhau đi vào ví dụ cho dễ hiểu hơn nhé.
Ở bài này mình đã chuẩn bị cho các bạn ví dụ là 1 webapp rất đơn giản như sau:
- có 2 màn: login và main
- Sau khi login xong thì user được đưa vào màn main
Ví dụ về Configmap ta sẽ tập trung vào màn login nơi ta cấu hình 1 số thông tin không “nhạy cảm”:

Ở trên ta có app title và Introduction là những thứ public, và có thể config được, và ta sẽ dùng ConfigMap nhé.
Đầu tiên các bạn tạo cho mình file configmap.yml với nội dung như sau:
apiVersion: v1
kind: ConfigMap
metadata:name: myapp-config
data:app_name:"Hello World"introduction.txt:|
My Introduction
Xem xem ở đây ta có gì nào:
- để tạo configmap thì
kindta phải để làConfigMap - bên trong
datalà nơi ta để config của chúng ta - ta có thể để key-value đơn giản như
app_name, value là string đơn giản làHello world - hoặc ta cũng có thể để cả 1 file rất dài vào đây, để ý dấu
|nhé
Rất đơn giản phải không những người anh em thiện lành
Sau đây ta apply để tạo Configmap nhé:
kubectl apply -f configmap.yml --kubeconfig=kubernetes-config
Ta thấy in ra:
configmap/myapp-config created
Để get configmap thì ta cũng làm như ta thường làm với Pod, service,…
kubectl get configmap --kubeconfig=kubernetes-config
--->>
myapp-config 2 4m39s
Để xem cụ thể bên trong Configmap có đúng như ở trong file manifest ta viết hay không các bạn làm như sau:
kubectl get configmap myapp-config -o yaml --kubeconfig=kubernetes-config
Ta sẽ thấy in ra kiểu kiẻu như sau:

Nom ổn áp rồi đó 😎
Tiếp sau đây ta tạo deployment nhé, các bạn tạo cho mình file myapp.yml như sau:
apiVersion: apps/v1
kind: Deployment
metadata:name: myapp-deployment
labels:app: myapp
spec:selector:matchLabels:app: myapp-pod
template:metadata:labels:app: myapp-pod
spec:securityContext:runAsUser:1001runAsGroup:1001fsGroup:1001containers:-name: myapp-container
image: maitrungduc1410/configmap-and-secret
ports:-containerPort:3000name: http
resources:requests:memory:"128Mi"cpu:"64m"limits:memory:"750Mi"cpu:"500m"env:-name: APP_NAME
valueFrom:configMapKeyRef:name: myapp-config
key: app_name
volumeMounts:-name: config
mountPath:"/app/storage"readOnly:truevolumes:-name: config
configMap:name: myapp-config
items:-key:"introduction.txt"path:"introduction.txt"---apiVersion: v1
kind: Service
metadata:name: myapp-svc
spec:type: LoadBalancer
ports:-name: http
protocol: TCP
port:8080targetPort: http
selector:app: myapp-pod
Ở bên trên nom khá giống với bài trước về Deployment ấy nhỉ 🤔
Cùng điểm qua 1 số điểm chính mới nhé:
- Đầu tiên ta có
envlà danh sách các biến môi trường ta muốn truyền vào container khi start, giống vớienvironmentmà ta vẫn dùng vớidocker compose. Ở đó ta định nghĩa 1 biến tên làAPP_NAME, lấy giá trị từ ConfigMap (valueFrom->configMapKeyRef), tiếp đó ta có tên của configmapmyapp-configvà cái key trong configmap mà ta muốn lấy raapp_name - Tiếp theo ta định nghĩa 1
volumestên làconfig(tên là gì tuỳ ý các bạn nhé), lấy từ configmap tương ứng,itemslà danh sách các key ta muốn lấy ra, ở đây ta chỉ muốn lấy ra 1 key trong configmap tên làintroduction.txtvà map nó vào file cùng tênintroduction.txt - Sau khi đã định nghĩa
volumesthì việc của ta là sử dụng nó - Bên trong phần cấu hình
containersta cóvolumeMounts, đây là nơi ta sẽ tham chiếu tớivolumeskia.namelà tên của volumes ta vừa định nghĩa,mountPathlà ta muốn mount cái volume kia vào đường dẫn nào, cuối cùng là ta córeadOnly: trueý là ta không cho phép container ghi đè vào file
úi xồi nhiều khái niệm quá, nom volumes rồi volumeMounts cứ loạn hết cả lên 😪😪 lằng nhà lằng nhằng (cái này ta sẽ làm rõ hơn ở bài về volume nhé)
Bên cạnh đó mình cũng có thêm
securityContext, để chỉ định ta muốn chạy container bằng user nào, group nào, nó sẽ override luôn cáiUSERmà ta định nghĩa ở Dockerfile nếu có, phần này ta sẽ nói thêm ở các bài sau nhé
Nếu các bạn để ý thì sẽ thấy là volumes và containers được định nghĩa ngang hàng (level) với nhau:

Tức là volumes không bị phụ thuộc vào 1 container nào mà nó có thể được dùng chung giữa nhiều container
Âu cây rồi đó, ta cùng deploy nhé:
kubectl apply -f myapp.yml --kubeconfig=kubernetes-config
Sau đó trong thời gian chờ LoadBalancer được khởi tạo (mất vài phút để bên cloud provider tạo LB) thì tranh thủ ta vọc vạch chút nhé.
Cùng chui zô container xem có gì nào 👁️👁️
À từ từ phải get xem có pod nào mới chui zô được chứ 😂😂:
kubectl get po --kubeconfig=kubernetes-config
---->>>
NAME READY STATUS RESTARTS AGE
myapp-deployment-995b4d567-8p4fr 1/1 Running 0 18m
Gòi gòi, giờ mới chui zô container được lè 🤪
kubectl exec -it myapp-deployment-995b4d567-8p4fr --kubeconfig=kubernetes-config -- sh
đổi tên pod sao cho khớp với của các bạn nhé
Thử check user id và group id tí xem securityContext đã được set đúng chưa nhé:
whoami
id -u
id -g
id
Ta thấy in ra như sau:

Nom có vẻ đúng rồi đấy nhỉ
App chúng ta chạy ở bài này là app NextJS. Anh em React đâu giơ tay xem cái nào 🖐️🖐️
Tiếp theo ta sẽ kiểm tra xem biến môi trường và volume của ta đã có chưa nhé:
ls -la
echo $APP_NAME
ls -la storage
cat storage/introduction.txt
Ta sẽ thấy in ra như sau:

Nom xinh tươi rồi đó nhỉ, có hết rồi 😎😎
Nếu các bạn để ý thì folder
storagenơi ta mount volume vào nó đang nằm dưới userroot, mặc dù group thì vẫn đúngnodejs. Cái này ta sẽ nói ở các bài sau nhé
Ổn rồi đó, giờ chui lại ra ngoài và get service để lấy EXTERNAL-IP nào (bấm CTRL + D để chui ra nhé):
kubectl get svc --kubeconfig=kubernetes-config
--->>>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
myapp-svc LoadBalancer 10.245.64.155 167.99.30.23 8080:32101/TCP 3m20s
Như ở trên thì Service của mình có EXTERNAL-IP là 167.99.30.23. Giờ ta quay lại trình duyệt và kiểm tra nhé, các bạn mở trình duyệt ở địa chỉ 167.99.30.23:8080 xem nhé:

yeah, app name đã được set thành Hello World, bấm thử nút Download Introduction ta sẽ thấy kết quả như mong đợi 🥰🥰:

tuyệt vời ông mặt trời, cảm giác như vừa giải cứu thế giới vậy 🤩🤩🤩🤩
Giờ ta thử update lại Configmap xem nhé:
apiVersion: v1
kind: ConfigMap
metadata:name: myapp-config
data:app_name:"My Kubernetes App"introduction.txt:|
This is to demo how to update Configmap
Sau đó ta apply lại Configmap nhé:
kubectl apply -f configmap.yml --kubeconfig=kubernetes-config
---->>>
configmap/myapp-config configured
Đoạn này mới vi diệu này. Ta quay trở lại trình duyệt, bấm F5, và bấm Download Introduction, mở file download ta sẽ thấy giá trị đã được update:

Uầy, nom xịn phết nhờ, update ngay cả khi container đang chạy luôn, không cần restart lại deployment….
Chuyện, hàng xịn mà lại 😎😎
Thế nhưng các bạn để thì APP_NAME vẫn không thay đổi, ta vẫn thấy Hello world
Volume được update ngay lập tức là vì bản chất nó chằng khác gì cái volume mà ta vẫn dùng bên Docker suốt rồi, mọi thay đổi ở volume đều sẽ được mount trực tiếp vào container lúc runtime (đang chạy). Còn với biến môi trường thì ta sẽ phải restart lại deployment đấy. Ta chạy command rollout restart nhé:
kubectl rollout restart deploy myapp-deployment --kubeconfig=kubernetes-config
Chờ một tẹo cho Pod mới được deploy xong xuôi (các bạn tự get pod kiểm tra bao giờ thấy RUNNING là được nhé), và giờ ta quay lại trình duyệt F5:

Tuyệt vời, APP_NAME đã được update 🥳🥳🥳. Sử dụng ConfigMap khá đơn giản ý nhỉ Ta triển tiếp phần sau nhé
Secret
Với các dạng config chung chung, không riêng tư thì ta có thể dùng Configmap như trên, nhưng còn với các dạng thông tin cần bảo mật: thông tin kết nối data, password, API key/secret, JWT secret, docker secret để pull image từ private registry,… Với những thứ riêng tư như vậy thì ta cần 1 thứ tốt hơn, K8S mang tới cho chúng ta Secret.
Secret thì có nhiều loại Secret, nhưng phổ biến và ta hay làm việc nhất là type=Opaque, cách dùng thì nom cũng không khác gì ConfigMap, rất dễ. Ta cùng xem nhé
Tạo và sử dụng secret
Ở cái app NextJS của mình thì ta còn có thể login với email và password của admin (được config từ phía backend), login thành công vào trong thì ta sẽ có thể download được file secret. Và bởi vì những thông tin như username/password, và file secret cần bảo mật hơn nên ta sẽ đưa nó vào secret nhé.
Các bạn tạo cho mình file secret.yml với nội dung như sau:
apiVersion: v1
kind: Secret
metadata:name: myapp-secret
type: Opaque
stringData:EMAIL:"admin@test.com"PASSWORD:"123456"secret.txt:|
My supersecret
Nhìn vào secret ta vừa định nghĩa bên trên nom khá là giống với ConfigMap luôn ý nhỉ? đơn giản ghê.
Thì như mình đã nói ở trên đây là loại secret phổ biến nhất type=Opaque cách dùng rất đơn giản. Ta có thể truyền vào trực tiếp stringData là dạng data thuần, raw data. Hoặc ta cũng có thể truyền vào base64. Ví dụ với file secret bên trên mà ta muốn dùng base64 thì sẽ như sau:
...type: Opaque
data:EMAIL: YWRtaW5AdGVzdC5jb20K
PASSWORD: MTIzNDU2Cg==
secret.txt: TXkgc3VwZXJzZWNyZXQK
chú ý rằng với data dạng base64 thì ta phải dùng
datathay vìstringDatanhé
còn nữa là nếu ta dùng
stringData, thì lát nữa sau khiapplyxong vàgetthì K8S sẽ show data dạng base64 thôi.
Giờ ta lưu file secret.yml lại (bản raw, dùng stringData ý nhé). Và apply để tạo secret nhé:
kubectl apply -f secret.yml --kubeconfig=kubernetes-config
--->>>
secret/myapp-secret created
ta thử get danh sách các secret hiện có ở namespace nhé:
kubectl get secret --kubeconfig=kubernetes-config
--->>>
NAME TYPE DATA AGE
default-token-4lggr kubernetes.io/service-account-token 3 10m
myapp-secret Opaque 3 41s
âu cây secret của ta được tạo ngon rồi đó. Giờ ta thử get detail xem bên trong secret của ta sau khi tạo nó nom như thế nào nhé:
kubectl get secret myapp-secret -o yaml --kubeconfig=kubernetes-config
Ta sẽ thấy dạng dạng như sau:

Như các bạn thấy thì dù file manifest của ta để là stringData nhưng sau khi apply thì K8S đã đổi thành data và dùng dạng base64. Phần này K8S làm tự động ta không cần quan tâm, lát nữa dùng ta cũng không cần convert ngược lại mà cứ thế dùng thôi nhé.
Giờ ta quay lại file deployment myapp.yml và update lại 1 chút như sau để inject (truyền) biến môi trường vào cho phần login và cả file secret sau khi login để user có thể download nhé. Ta mở file myapp.yml:
apiVersion: apps/v1
kind: Deployment
metadata:name: myapp-deployment
labels:app: myapp
spec:selector:matchLabels:app: myapp-pod
template:metadata:labels:app: myapp-pod
spec:securityContext:runAsUser:1001runAsGroup:1001fsGroup:1001containers:-name: myapp-container
image: maitrungduc1410/configmap-and-secret
ports:-containerPort:3000name: http
resources:requests:memory:"128Mi"cpu:"64m"limits:memory:"750Mi"cpu:"500m"env:-name: APP_NAME
valueFrom:configMapKeyRef:name: myapp-config
key: app_name
-name: EMAIL
valueFrom:secretKeyRef:name: myapp-secret
key: EMAIL
-name: PASSWORD
valueFrom:secretKeyRef:name: myapp-secret
key: PASSWORD
volumeMounts:-name: config
mountPath:"/app/storage/introduction.txt"subPath: introduction.txt
readOnly:true-name: secret
mountPath:"/app/storage/secret.txt"subPath: secret.txt
readOnly:truevolumes:-name: config
configMap:name: myapp-config
items:-key:"introduction.txt"path:"introduction.txt"-name: secret
secret:secretName: myapp-secret
items:-key: secret.txt
path: secret.txt
---apiVersion: v1
kind: Service
metadata:name: myapp-svc
spec:type: LoadBalancer
ports:-name: http
protocol: TCP
port:8080targetPort: http
selector:app: myapp-pod
Có một số thay đổi ở Deployment, (Service thì giữ nguyên). Ta cùng xem nhé:
- đầu tiên là ở
volumestương tự như configMap ta định nghĩa thêm 1 volume dành cho secret để mount filesecret.txtvào, các bạn để ý những keyword, cú pháp của nó nhé, gần như tương tự config map, khác mỗi cái bên configmap để lànamethì bên secret ta để làsecretName - Ở
envta định nghĩa thêm 2 biến nữa làEMAILvàPASSWORDlấy từ secret, vẫn tương tự như configmap - cuối cùng là đoạn có vẻ “thay đổi nhiều nhất” là phần
volumeMounts - ở đó giống như configmap, ta mount thêm volume của secret vào, nhưng có 1 điều là cái
mountPathcủa cả 2 ta vừa update lại để dùng đường dẫn có chứa cả tên file, và ta cũng thêm cảsubPathlà tên file nữa subPathchính là cáipathmà ta định nghĩa ở phầnvolumesbên dưới- còn lí do cái
mountPathta phải thêm cả tên file là bởi vì hiện tại ta muốn mount 2 volumes vào chung 1 đường dẫn/app/storagemà K8S không cho phépmountPathtrùng nhau giữa cácvolumeMounts, nếu ta để 2 cáimountPathđều là/app/storagenhư cũ thì lúcapplysẽ có lỗi, nên ta phải thêm tên file vào cho nó khác nhau đi, và bởi vì ta dùng trực tiếp đường dẫn có cả tên file nên ta phải dùng chung vớisubPathđể lấy ra đúng file ta mong muốn từvolumes
ối dồi ôi nghe loạn cả óc, khóc ròng🤣🤣, nếu các bạn thấy khó nuốt quá thì dành ra đôi phút thiền để có thể thẩm thấu dễ hơn nhé
Oke rồi đó giờ ta apply lại deployment nào:
kubectl apply -f myapp.yml --kubeconfig=kubernetes-config
Sau đó ta chờ 1 lúc để Pod mới được deploy (các bạn từ get pod để check status nhé), sau đó ta quay lại trình duyệt, bấm F5 và login với EMAIL và PASSWORD như ta định nghĩa trong file secret. Login thành công vào trong ta bấm nút Get Secret:

Mở file download lên và ta thấy được nội dung file secret của chúng ta:

Oke vậy là ta đã hoàn thành setup Secret và Configmap rồi đó .
Vọc vạch
Thử vọc thêm tí nữa nhé. Bây giờ ta thử update lại secret.yml:
apiVersion: v1
kind: Secret
metadata:name: myapp-secret
type: Opaque
stringData:EMAIL:"newadmin@gmail.com"PASSWORD:"abcdefg"secret.txt:|
This is new secret
Sau đó ta apply lại:
kubectl apply -f secret.yml --kubeconfig=kubernetes-config
Ngay bây giờ, đừng restart deployment vội nhé, ta chui luôn vô container để xem cái file secret.txt đã được cập nhật chưa:
kubectl exec -it myapp-deployment-6dcc8b9b68-gpnvk --kubeconfig=kubernetes-config -- sh
đổi tên pod khi
execcho giống với của các bạn nhé
Sau khi vào trong ta xem file secret.txt có gì nhé:
/app $ cat storage/secret.txt
--->>>
My supersecret
Ô, cái gì nó nổ ý nhề? 🧨🧨, ủa sao file secret lại không update nữa rồi. Khi nãy ở bên Configmap update volume cái thì bên trong nó tự động đổi luôn không cần restart mà??? 🤔🤔🤔
Lí do volume của ta không được update “realtime” vào trong container nữa là bởi vì hiện tại ta dùng subPath để mount, và như vậy ta sẽ không nhận được update mới nữa mà phải restart lại deployment. Đây là K8S quy định chứ không phải mình tự vẽ ra nhé các bạn 🤣🤣🤣.
Bây giờ cái configmap và secret ta đều đang dùng subPath nên khi thay đổi chúng thì ta phải restart lại deployment, các bạn thử check với Configmap xem nhé
Giờ ta restart lại deployment là được nhé:
kubectl rollout restart deploy myapp-deployment --kubeconfig=kubernetes-config
Sau đó ta quay lại trình duyệt F5, thử login với EMAIL và PASSWORD mới, vô trong ta download file secret mới được rồi đó. Các bạn tự làm phần này nhé
À tí quên, nếu các bạn để ý khi ta chui vào container và list file:


Ta để ý thấy rằng, khi ta dùng subPath, thì ta chỉ mount file vào bên trong folder storage sẵn có từ trước (từ build image, trong Dockerfile), do vậy permission của folder storage vẫn được bảo toàn nextjs:nodejs, chỉ là 2 file được mount vào bên trong thì của root:nodejs.
Nó hơi khác 1 chút so với ở đầu bài đoạn làm với Configmap, ta mount cả volume vào thẳng đường dẫn /app/storage, tức là mount đè lên folder storage sẵn có của image, và làm cho cả folder storage bị đặt dưới quyền root:nodejs
Về permission thì ta sẽ thảo luận dần dần ở các bài sau để làm rõ hơn nhé
Câu hỏi liên quan
Có nên push cả ConfigMap và Secret lên Git?
Câu trả lời là không, à tuỳ . nhưng best pratice là ta không bao giờ đưa thông tin “nhạy cảm” lên git, và secret cũng vậy.
Ví dụ ConfigMap của bạn chưa thông tin có thể public, không riêng tư thì có thể đưa lên được, còn Secret thì hầu như không.
Thông thường mình vẫn muốn push file secret.yml lên Git để mọi người có thể track được file đó là gì, cấu trúc như nào. Thì trước khi git push mình sẽ sửa lại như sau:
apiVersion: v1
kind: Secret
metadata:name: myapp-secret
type: Opaque
stringData:EMAIL: <PLACEHOLDER>PASSWORD: <PLACEHOLDER>secret.txt: <PLACEHOLDER>
Secret có những Type nào?
Ở trong bài này ta mới chỉ nói về Type=Opaque là type phổ biến và hay dùng nhất cho Secret, nhưng Secret còn có 1 số type khác, như hình dưới:

ví dụ type dockercfg/dockerconfigjson dùng để kết nối tới private registry để pull image, hiện tại ta pull trực tiếp từ Dockerhub Public nên không cần cái đó. Hay type service-account-token dành cho ServiceAccount, và một số type khác.
Các type này hầu như ta khá ít phải tự tay trực tiếp tạo chúng, chúng thường được tạo luôn bằng các tool như Helm hay như lúc ta dùng package dạng cert-manager nó cũng tự tạo cho chúng ta. Còn mấy type về docker config để pull image từ private registry thì ví dụ như mình dùng Digital Ocean thì họ có option để tự động inject (truyền) config vào luôn K8S cluster của mình nếu như mình dùng Registry của họ
Tạo Secret bằng command?
Nếu các bạn muốn đi “tàu nhanh” dùng Terminal để tạo secret thì cũng được. Ta dùng các command dạng như sau:
kubectl create secret generic prod-db-secret --from-literal=EMAIL=admin@test.com --from-literal=PASSWORD=123456
Nhưng như mình vẫn nói, thì ta luôn ưu tiên dùng file manifest tạo tất cả mọi resource trên K8S nhé, để sau này có thể puhs lên Git, dễ dàng cho việc xem lại và track thay đổi
Nom Secret có khác gì ConfigMap đâu???
Để ý thấy rằng từ lúc ta định nghĩa secret (type=Opaque) đến lúc ta dùng nó ở env hay mount nó vào bằng volumes thì có khác gì ConfigMap đâu??? Chả nhẽ nó được bảo mật hơn vì được hash thành base64 à, mà base64 thì làm gì có bảo mật vì nó có thể được revert 1 cách rất dễ dàng?? 🤔🤔🤔
Các bạn nói đúng suy nghĩ của mình lúc mới học K8S rồi đó, mình đã rất băn khoăn là ủa chúng có cái gì khác nhau nhỉ, mấy cái mình hay dùng bên secret thì configmap cũng có đủ cả, chả thiếu gì. Sao người ta lại phải bày vẽ ra thêm 1 loại làm gì cơ chứ?, sao không dùng 1 cái thôi????
Thì tìm được câu trả lời ở trên StackOverflow từ trực tiếp author (người tham gia vào phát triển) của 2 tính này năng này.
Đơn giản ô ý cũng chỉ nói là:
- dùng secret cho data “nhạy cảm”
- còn configmap dùng cho những thứ không nhạy cảm
- tương lai thì họ sẽ thêm nhiều feature vào cho secret hơn nữa
Nhưng thật sự với mình thì giải thích như vậy chưa làm mình “thoả mãn” vì sự khác nhau giữa chúng vẫn chưa được nói rõ lên:
- vậy sao ta không dùng luôn secret cho rồi??
- secret gọi là là”bảo mật hơn” vì nó được mã hoá base64 à? base64 thì làm gì có bảo mật vì nó có thể được revert (đảo ngược dễ dàng)??
Ở thời điểm hiện tại (2022), từ góc độ của của mình thì nó vẫn hơi giống kiểu “best pratice”, đó là “ừ, cứ cái nào nhạy cảm thì nên dùng secret, thế thôi” 😅😅
Lấy toàn bộ secret vào truyền thẳng vào biến môi trường
Ở bên Docker Compose ta có thể khai báo env_file để truyền toàn bộ biến ở trong 1 file env nào đó vào biến môi trường, kiểu như sau:
APP_NAME="Hello World"
EMAIL=admin@test.com
PASSWORD=123456
Tương tự ở bên K8S thì ta cũng có thể truyền toàn bộ ConfigMap hay Secret vào làm biến môi trường, ở file myapp.yml phần khai báo containers ta thêm vào nhưu sau là được:
containers:-name: myapp-container
image: maitrungduc1410/configmap-and-secret
envFrom:-secretRef:name: myapp-secret
-configMapRef:name: myapp-config
Kiểu này mình khá là hay dùng, vì đơn giản và tiện lợi, mình thường tổ chức các file secret/configmap kiểu:
- file chỉ chứa biến môi trường ra 1 kiểu:
apiVersion: v1
kind: Secret
metadata:name: myapp-secret
type: Opaque
stringData:EMAIL:"newadmin@gmail.com"PASSWORD:"abcdefg"
- còn lại nếu file có chứa nội dung dài, dạng text bất kì thì đưa ra thành các configmap/secret riêng:
apiVersion: v1
kind: Secret
metadata:name: myapp-secret
type: Opaque
stringData:file1.txt:|
This is new secretfile2.txt:|
This is new secret
Và như vậy thì khi mình muốn truyền toàn bộ configmap hay secret vào env sẽ tiện hơn, đỡ bị mix giữa biến môi trường và những dạng text kiểu file. Đây là hướng đi cá nhân thôi nhé, còn hoàn toàn tuỳ các bạn
Với secret nên dùng stringData hay data
Câu trả lời là tuỳ các bạn nhé, vì stringData thì sau khi apply nó cũng được K8S convert thành data, và giữa 2 cái chẳng cái nào bảo mật hơn vì base64 của data thì cũng dễ dàng được revert
Thôi bỏ qua ConfigMap, cứ dùng Secret cho lành
Như ở phần trên mình nói về sự khác biệt giữa ConfigMap và Secret. Thì với những dữ liệu dạng không “nhạy cảm” thì ta có thể dùng ConfigMap thay vì Secret.
Nhưng thật sự nếu các bạn nói là thôi cứ dùng Secret cho lành thì cũng không sao cả
Mà kể ra nếu các bạn biết chia đâu là configmap đâu là secret, nó cũng cho thấy cách bạn tổ chức project, config,… tốt thế nào và bạn hiểu project của bạn ra sao: cái nào nhạy cảm, cái nào không,….
, vậy nên cố gắng đừng máy móc nhé
Chấm hết
Phùu…… bài tưởng ngắn mà dãi quá đáng 😂😂
Mong là qua bài này các bạn đã biết về ConfigMap và Secret trên K8S, các tạo, sử dụng, update,…Thật ra nói thì nhiều vậy chứ thực tế thì mình thấy cách dùng nó khá đơn giản. Phổ biến nhất là dùng nó để truyền biến môi trường vào container, đơn giản như đan rổ 😎😎
Chúc các bạn thực hành vui vẻ. Hẹn gặp lại các bạn ở những bài sau ^^
Nguồn: viblo.asia
