Appearance
Kubernetes 維運技巧速查
日常維運高頻使用的 Kubernetes 指令、設定技巧與 YAML 片段:跨 Namespace 存取、環境變數注入、kubeconfig 管理、儲存與安全設定。
概述
本文收錄 Kubernetes 日常維運中常用但散落各處的技巧,作為快速查找的速查手冊。涵蓋跨 Namespace 服務存取的 DNS 命名規則、ConfigMap/Secret 批次注入、kubeconfig 多叢集管理、Azure 特有的 Internal LoadBalancer 設定、PVC 寫入權限排除,以及 emptyDir 暫存 Volume 的使用方式。
這些技巧的共同特點是:各自獨立、使用頻率高,但每次需要時都得重新查文件——適合整理成速查手冊。
核心內容
跨 Namespace 存取服務
Pod 預設只能透過短名稱存取同一 Namespace 內的 Service。若要存取其他 Namespace 的 Service,需使用完整的叢集 DNS FQDN(Fully Qualified Domain Name):
<servicename>.<namespacename>.svc.cluster.local例如,app Namespace 的 Pod 存取 ingress-basic Namespace 的 Squid Proxy:
squid-service.ingress-basic.svc.cluster.local:3128K8s 的 CoreDNS 會解析此 FQDN 為對應 Service 的 ClusterIP,不需要任何額外設定。
環境變數注入(envFrom)
將個別 key 注入環境變數需逐一設定 env.valueFrom.configMapKeyRef;使用 envFrom 可一次將整份 ConfigMap 或 Secret 的所有 key-value 注入為環境變數,更為簡潔:
ConfigMap 整組注入:
yaml
envFrom:
- configMapRef:
name: special-configSecret 整組注入:
yaml
envFrom:
- secretRef:
name: mysecretConfigMap 或 Secret 中的每個 key 會直接成為環境變數名稱。注意若有多份來源存在同名 key,後者會覆蓋前者。
Kubeconfig 管理
合併多份 config 為一份:
bash
export KUBECONFIG=~/.kube/config:~/someotherconfig
kubectl config view --flatten > new-config--flatten 會將憑證資料內嵌(base64 embed)到輸出檔案中,而非保留外部路徑引用,確保輸出的單一檔案可攜。
從合併的 config 輸出特定 context:
bash
# 切換至目標 context
kubectl config use-context CONTEXT_NAME
# 只輸出目前 context 的獨立設定檔(--minify 過濾掉其他 context)
kubectl config view --minify --flatten > exported_context.yaml
# base64 單行編碼,常用於 CI/CD Pipeline 中注入為 Secret
cat master1-config | base64 -w0 > master1-config-base64NFS Provisioner 安裝
NFS Subdir External Provisioner 建立一個 StorageClass,讓 Pod 能透過 PVC 動態掛載 NFS 共享目錄:
bash
helm repo add nfs-subdir-external-provisioner \
https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/ \
--insecure-skip-tls-verify
helm repo update
helm install nfs-subdir-external-provisioner \
nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
--insecure-skip-tls-verify \
--set nfs.server=10.248.36.109 \
--set nfs.path=/mnt/nfs_share \
--namespace nfs安裝後會建立名為 nfs-subdir-external-provisioner 的 StorageClass,Pod 申請 PVC 時指定此 StorageClass 即可自動在 NFS 上建立子目錄。
建立 KeyVault Secret(Azure AKS)
從 .env 檔案批次建立 K8s Secret,常用於存放 Azure Key Vault 或 Service Principal 連線認證:
bash
kubectl create secret generic keyvault-secret \
--from-env-file=.keyvault.env \
-n ingress-basic \
-o yaml --dry-run=client | kubectl apply -f -.keyvault.env 範例:
bash
AZURE_CLIENT_ID=2fe43815-a524-405d-8b57-460f42dbfe99
AZURE_TENANT_ID=da6e0628-fc83-4caf-9dd2-73061cbab167
AZURE_CLIENT_SECRET=64k.AgXqp_tOVxiY9u0ISD-FZ6u3~qLk3j--dry-run=client | kubectl apply -f - 的好處是冪等(idempotent):Secret 已存在時會更新而非因「already exists」報錯,適合在自動化腳本中重複執行。
Azure Internal LoadBalancer
將 Service 暴露為 VNet 內部專用 LoadBalancer(不對公網開放),是 Azure AKS 上暴露叢集內服務給 VNet 內其他資源(如 VM、其他 AKS 叢集)存取的標準做法:
yaml
apiVersion: v1
kind: Service
metadata:
name: squid-service
namespace: ingress-basic
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "true"
service.beta.kubernetes.io/azure-load-balancer-ipv4: 10.30.196.60
labels:
app: squid
spec:
type: LoadBalancer
ports:
- port: 3128
selector:
app: squid兩個 annotation 的作用:
azure-load-balancer-internal: "true"— 建立 Azure Internal LB(VNet 內部)而非 Public LBazure-load-balancer-ipv4— 指定靜態內部 IP(必須在 AKS Subnet 的可用範圍內)
靜態 IP 讓下游服務的連線目標固定,避免 LB IP 因重建而改變。
PVC 寫入權限問題(Permission Denied)
Container 執行時若 UID/GID 與 PVC 掛載目錄的擁有者不符,會出現 Permission Denied 錯誤。在 spec.template.spec 加入 securityContext.fsGroup 可讓 K8s 在掛載時自動將 Volume 的群組擁有權設為指定 GID,並確保容器中的程序可寫入:
yaml
spec:
template:
spec:
securityContext:
fsGroup: 999fsGroup 的值對應 Container 內應用程式使用的 GID(例如:postgres 為 999、mysql 為 999、www-data 為 33)。
檔案傳輸(kubectl cp)
從 Pod 複製檔案到本機:
bash
kubectl cp ingress-basic/carbon-form-server-7fbf99c95-f28z6:/root/server/sqlite/58.db /tmp/58.db格式為 <namespace>/<pod-name>:<容器路徑> <本機路徑>。
替代作法(適用於 kubectl cp 因 tar 版本問題失敗時):
bash
kubectl exec -n ingress-basic carbon-form-server-7fbf99c95-f28z6 -- cat /root/server/sqlite/58.db > /tmp/58.dbkubectl cp 底層使用 tar 封裝,若容器內的 tar 版本與本機不相容會失敗。kubectl exec -- cat > 直接透過 stdout redirect,繞開 tar 相容問題,但缺點是不支援目錄複製。
emptyDir — 臨時共享與記憶體暫存 Volume
emptyDir 是 Pod 生命週期內的臨時 Volume,Pod 刪除後資料即消失。主要兩種使用場景:
- 同一 Pod 內多個 Container 共用儲存(例如 init container 寫入、main container 讀取)
- 高頻 I/O 暫存(使用記憶體模式)
記憶體模式(使用 tmpfs,速度等同 RAM):
yaml
volumes:
- name: cache-volume
emptyDir:
sizeLimit: 500Mi
medium: Memory不指定 medium 時預設使用節點本機硬碟;指定 medium: Memory 時使用 tmpfs,速度更快但會佔用節點的實體記憶體,需注意資源用量。
關鍵要點
- 跨 Namespace 存取必須使用完整 DNS 名稱:
<svc>.<ns>.svc.cluster.local envFrom可整組注入 ConfigMap 或 Secret,比逐一設定env更簡潔kubectl config view --flatten內嵌憑證,--minify只輸出目前 context- Azure Internal LB 需兩個 annotation:
internal: "true"+ 靜態 IP - PVC 寫入權限問題通常可透過
securityContext.fsGroup解決 kubectl exec -- cat >是kubectl cp因 tar 版本問題失敗時的可靠替代方案emptyDir medium: Memory使用 tmpfs,速度快但佔節點記憶體,需設定sizeLimit防止 OOM
實際應用
這些技巧在日常維運中反覆用到:跨 Namespace DNS 是微服務架構中服務互通的基礎;envFrom 讓環境設定從 Pod spec 中解耦;kubeconfig 合併與匯出在管理多叢集時不可缺少;NFS Provisioner 提供多 Pod 可讀寫的共享儲存;Azure Internal LB 確保內部服務不暴露於公網;fsGroup 排除了最常見的 PVC 掛載問題之一。
部署設定參考
以下為實際部署時使用的參數與指令,供日後查詢與複製使用。
環境參數
| 項目 | 值 |
|---|---|
| NFS Server IP | 10.248.36.109 |
| NFS Share Path | /mnt/nfs_share |
| Internal LB 靜態 IP | 10.30.196.60 |
| Internal LB Port(Squid) | 3128 |
| KeyVault Secret Namespace | ingress-basic |
| Azure Client ID | 2fe43815-a524-405d-8b57-460f42dbfe99 |
| Azure Tenant ID | da6e0628-fc83-4caf-9dd2-73061cbab167 |
| Azure Client Secret | 64k.AgXqp_tOVxiY9u0ISD-FZ6u3~qLk3j |
操作指令
bash
# NFS Provisioner 安裝
helm repo add nfs-subdir-external-provisioner \
https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/ \
--insecure-skip-tls-verify
helm repo update
helm install nfs-subdir-external-provisioner \
nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
--insecure-skip-tls-verify \
--set nfs.server=10.248.36.109 \
--set nfs.path=/mnt/nfs_share \
--namespace nfs
# KeyVault Secret 冪等建立
kubectl create secret generic keyvault-secret \
--from-env-file=.keyvault.env \
-n ingress-basic \
-o yaml --dry-run=client | kubectl apply -f -
# Kubeconfig 合併與匯出
export KUBECONFIG=~/.kube/config:~/someotherconfig
kubectl config view --flatten > new-config
kubectl config use-context CONTEXT_NAME
kubectl config view --minify --flatten > exported_context.yaml
cat master1-config | base64 -w0 > master1-config-base64
# 檔案傳輸
kubectl cp ingress-basic/carbon-form-server-7fbf99c95-f28z6:/root/server/sqlite/58.db /tmp/58.db
# 替代(繞過 tar 版本問題)
kubectl exec -n ingress-basic carbon-form-server-7fbf99c95-f28z6 -- cat /root/server/sqlite/58.db > /tmp/58.db相關概念
- Kubernetes RBAC 帳號管理 — kubeconfig 對應的 ServiceAccount 與憑證管理
- Kubernetes HPA 水平自動擴縮 — Pod 自動擴縮設定
- Kubernetes VolumeSnapshot 磁碟快照 — PVC 快照建立與還原 SOP
- Squid Proxy(Kubernetes 部署) — Internal LB 暴露的實際應用案例
- KEDA(Kubernetes Event-Driven Autoscaling) — 基於外部事件的進階擴縮方案
- Kubernetes Pod Anti-Affinity 與 Deployment Strategy — 將副本分散至不同節點的反親和性設定,以及 ReadWriteOnce PVC 的 Recreate 策略