直接 docker run mysql 行,K8s 上要怎麼傳密碼?
docker run 跑 MySQL 你會這樣寫:
docker run -e MYSQL_ROOT_PASSWORD=root1234 -d mysql:8.0
-e 注入環境變數。但 K8s 沒有 -e 參數 — 它是聲明式的,要寫在 YAML 裡。
這篇學 env 區塊的三種寫法:直接寫值、從 ConfigMap、從 Secret。
不給密碼會怎樣?親身體驗一下
先寫個沒密碼的 MySQL Pod:
# mysql-no-env.yaml
apiVersion: v1
kind: Pod
metadata:
name: mysql-broken
spec:
containers:
- name: mysql
image: mysql:8.0
ports:
- containerPort: 3306
kubectl apply -f mysql-no-env.yaml
kubectl get pods
# STATUS: CrashLoopBackOff ← 跟你預期的一樣
kubectl logs mysql-broken
# [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified
# You need to specify one of the following: -e MYSQL_ROOT_PASSWORD ... etc.
MySQL 啟動時要建一個 root 帳號,必須先給密碼。沒給就拒絕啟動。
清掉重來:
kubectl delete pod mysql-broken
寫法 1:直接寫值(env + value)
# mysql.yaml
apiVersion: v1
kind: Pod
metadata:
name: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: "root1234"
- name: MYSQL_DATABASE
value: "mydb"
- name: MYSQL_USER
value: "appuser"
- name: MYSQL_PASSWORD
value: "app1234"
kubectl apply -f mysql.yaml
kubectl get pods
# STATUS: Running
# 進去確認
kubectl exec -it mysql -- mysql -uroot -proot1234
mysql> SHOW DATABASES;
# information_schema, mydb, mysql, performance_schema, sys
mysql> exit
對應 docker run:
| Docker | K8s YAML |
|---|---|
-e MYSQL_ROOT_PASSWORD=root1234 | env: - name: MYSQL_ROOT_PASSWORD; value: "root1234" |
-e MYSQL_DATABASE=mydb | env: - name: MYSQL_DATABASE; value: "mydb" |
⚠️value一定要是字串,寫數字記得加引號:value: "3306"不是value: 3306。
寫法 2:從 ConfigMap 取(不敏感的設定)
把非敏感的設定(資料庫名、port、log level)放 ConfigMap,密碼類放 Secret。分開管理才好維護。
ConfigMap:
# mysql-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-config
data:
MYSQL_DATABASE: "mydb"
MYSQL_USER: "appuser"
Pod 引用:
spec:
containers:
- name: mysql
image: mysql:8.0
env:
- name: MYSQL_DATABASE
valueFrom:
configMapKeyRef:
name: mysql-config
key: MYSQL_DATABASE
- name: MYSQL_USER
valueFrom:
configMapKeyRef:
name: mysql-config
key: MYSQL_USER
寫法 3:從 Secret 取(密碼類)
Secret:
# 用指令建(base64 自動處理)
kubectl create secret generic mysql-secret \
--from-literal=MYSQL_ROOT_PASSWORD=root1234 \
--from-literal=MYSQL_PASSWORD=app1234
Pod 引用:
spec:
containers:
- name: mysql
image: mysql:8.0
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: MYSQL_ROOT_PASSWORD
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: MYSQL_PASSWORD
📖 ConfigMap 跟 Secret 在 Day 6 會深入教,這裡先看寫法。
寫法 4:envFrom 一次塞整包(懶人寫法)
如果 ConfigMap / Secret 裡所有 key 都要當環境變數,逐個寫太煩:
spec:
containers:
- name: mysql
image: mysql:8.0
envFrom:
- configMapRef:
name: mysql-config
- secretRef:
name: mysql-secret
ConfigMap / Secret 裡的每個 key 都會自動變成環境變數。省事,但少了「明確指定哪些變數」的清晰度,看你取捨。
確認環境變數有進去
kubectl exec mysql -- env | grep MYSQL
# MYSQL_ROOT_PASSWORD=root1234
# MYSQL_DATABASE=mydb
# MYSQL_USER=appuser
# MYSQL_PASSWORD=app1234
三種寫法對照表
| 寫法 | 用途 | 特點 |
|---|---|---|
value: "xxx" | 不敏感、固定值 | 直接寫死在 YAML |
valueFrom.configMapKeyRef | 不敏感、要分離 | 改 ConfigMap 不用改 Pod |
valueFrom.secretKeyRef | 密碼、Token | 跟程式碼分離、能用 RBAC 管權限 |
envFrom | 整包塞 | 偷懶,但欄位不夠明確 |
真實工作的最佳實踐
資料庫名、user、port、log level → ConfigMap
密碼、API Token、TLS 憑證 → Secret
程式內部固定值 → 直接 value
永遠不要把密碼 value: "xxx" 寫在 YAML 然後 commit 到 Git。即使是私有 repo 也一樣。
重點整理
- K8s 沒有
docker run -e,環境變數寫在env區塊 - 直接寫值用
value: "xxx"(記得字串加引號) - 從 ConfigMap 取用
valueFrom.configMapKeyRef - 從 Secret 取用
valueFrom.secretKeyRef envFrom一次塞整包(省事但欄位不明確)- 密碼類永遠用 Secret,不要 commit 到 Git
下一步
到目前為止你的 Pod 都是「一個人做事」 — Pod 一掛就什麼都沒了。下一篇正式進入 Deployment 入門:從一個人做事變成一個團隊做事,刪 Pod 自動補回。