筆記Day09 下 :加密配置管理中心 Secret 講解與應用實例)
一、Secret 概述1.1 什么是 Secret簡單來說Secret 就是 ConfigMap 的“加密版”——專門用來存敏感數據的Secret 是 Kubernetes 中用于保存敏感數據的資源對象如密碼、Token、密鑰等。它的設計目的與 ConfigMap 類似——將配置與鏡像解耦但專門針對機密性數據。ConfigMap vs SecretConfigMap 存放明文配置如配置文件Secret 存放敏感數據如密碼、私鑰。兩者功能相似但 Secret 在存儲和傳輸中做了編碼處理。Secret 可以以Volume 掛載或環(huán)境變量的方式被 Pod 使用。需注意Secret本質就是“加密版”的ConfigMap二者在源碼層面是同一種數據結構data 字段的不同包裝所以在語法上有驚人的相似度使用方法也幾乎完全一致1.2 Secret 的可選類型類型用途generic通用最常用用于存儲密碼、密鑰等普通敏感數據tls專門用于存儲 TLS 私鑰和證書docker-registry用于存儲私有 Docker 倉庫的認證信息kubernetes.io/service-account-token由 Kubernetes 自動創(chuàng)建用于 ServiceAccount 身份認證關于 ServiceAccount 的自動掛載每個 ServiceAccount 創(chuàng)建時Kubernetes 會為其自動創(chuàng)建一個對應的 Secret并掛載到 Pod 的/run/secrets/kubernetes.io/serviceaccount目錄下用于 Pod 與 API Server 之間的認證通信。1.3 Secret 的數據編碼Secret 的數據并非加密而是Base64 編碼。Base64 只是將原始數據轉換成可打印字符不屬于真正的加密可以輕松解碼回原文。因此Secret 只是比 ConfigMap 多了一層編碼并非安全加密。對于極高安全要求的場景建議配合外部加密工具如 HashiCorp Vault使用。Base64 編碼示例# 編碼[roothd1 ~]# echo -n admin | base64YWRtaW4[roothd1 ~]# echo -n 123456 | base64MTIzNDU2# 解碼[roothd1 ~]# echo MTIzNDU2 | base64 -d123456二、使用 Secret2.1 通過環(huán)境變量引入 SecretsecretKeyRef場景將 Secret 中的某個 key 的值注入為 Pod 容器的環(huán)境變量。語法kubectl create secret secret類型 secret名 --from-literalkeyvalue步驟1創(chuàng)建 Secret# 創(chuàng)建一個名為 mysql-password 類型為 generic 的 Secret包含 passwordheihei66[roothd1 ~]# kubectl create secret generic mysql-password --from-literalpasswordheihei66# 查看 Secret 列表[roothd1 ~]# kubectl get secretNAME TYPE DATA AGE mysql-password Opaque130s# 查看 Secret 詳情注意實際值顯示為字節(jié)數不展示原文[roothd1 ~]# kubectl get secret mysql-password -o yamlapiVersion: v1 data: password:aGVpaGVpNjYkind: Secret metadata: creationTimestamp:2026-08-05T12:30:32Zname: mysql-password namespace: default resourceVersion:253749uid: 47ee1b04-9fa9-4741-ba76-454d4271f1a2 type: Opaque[roothd1 ~]# kubectl describe secret mysql-passwordName: mysql-password Namespace: default Labels:noneAnnotations:noneType: Opaque Datapassword:8bytes#這里并不會顯示出我們的數據信息#驗證存入的是base64編碼[roothd1 ~]# kubectl get secret mysql-password -o yamlapiVersion: v1 data: password:aGVpaGVpNjY#這里就是剛剛存入的數據并非明文步驟2創(chuàng)建 Pod 引用該 Secret[roothd1 ~]# cat pod-secret.yamlapiVersion:v1kind:Podmetadata:name:pod-secretlabels:app:myappspec:containers:-name:myappimage:mysql:8.0imagePullPolicy:IfNotPresentports:-name:mysqlcontainerPort:3306env:-name:MYSQL_ROOT_PASSWORD# Pod 中的環(huán)境變量名這個環(huán)境變量對于使用官方 MySQL 容器鏡像來說是必須的valueFrom:#與 secretKeyRef 作用一致secretKeyRef:name:mysql-password# Secret 名稱key:password# 指定Secret 中的 key可以看得出來secret和ConfigMap的使用方法幾乎完全一致[roothd1 ~]# kubectl apply -f pod-secret.yaml# 驗證進入 Pod 查看環(huán)境變量[roothd1 ~]# kubectl exec -it pod-secret -- /bin/bash/# printenvMYSQL_ROOT_PASSWORDheihei662.2 通過 Volume 掛載 Secret使用yaml文件創(chuàng)建 Secret方法一手動創(chuàng)建加密數據步驟1手動創(chuàng)建包含 Base64 編碼數據的 Secret[roothd1 ~]# echo -n admin | base64YWRtaW4[roothd1 ~]# echo -n 123456 | base64MTIzNDU2步驟2編寫 Secret YAML 文件[roothd1 ~]# vim secret.yamlapiVersion:v1kind:Secretmetadata:name:mysecrettype:Opaquedata:username:YWRtaW4# base64 編碼后的 adminpassword:MTIzNDU2# base64 編碼后的 123456方法二使用stringData:可以讓它自動生成注意我們使用stringData:可以讓它自動生成[roothd1 ~]# vim secret.yamlapiVersion:v1kind:Secretmetadata:name:mysecrettype:OpaquestringData:#使用stringData: 直接配置明文即可username:adminpassword:123456[roothd1 ~]# kubectl apply -f secret.yaml[roothd1 ~]# kubectl get secret mysecret -o yamlapiVersion: v1 data: password: MTIzNDU2 username:YWRtaW4步驟3將 Secret 以 Volume 形式掛載到 Pod[roothd1 ~]# vim pod_secret_volume.yamlapiVersion:v1kind:Podmetadata:name:pod-secret-volumespec:containers:-name:myappimage:docker.io/library/nginx:latestimagePullPolicy:IfNotPresentvolumeMounts:-name:secret-volumemountPath:/etc/secretreadOnly:truevolumes:-name:secret-volumesecret:#指定類型為secretsecretName:mysecret#secret名稱[roothd1 ~]# kubectl apply -f pod_secret_volume.yaml# 驗證Secret 數據在 Pod 中被解密為明文[roothd1 ~]# kubectl exec -it pod-secret-volume -- /bin/bashrootpod-secret-volume:/# ls /etc/secretpassword username#已經翻譯成明文rootpod-secret-volume:/# cat /etc/secret/usernameadmin rootpod-secret-volume:/# cat /etc/secret/password123456關鍵理解Secret 存儲在 etcd 中是 Base64 編碼的但掛載到 Pod 后kubelet 會自動解碼所以容器內讀取到的是明文。2.3 Docker 私有倉庫認證docker-registry類型場景Pod 需要從私有 Docker 倉庫拉取鏡像時需要提供倉庫認證信息。步驟1創(chuàng)建 docker-registry 類型的 Secret創(chuàng)建一個docker鏡像倉庫類型的Secret命名為regcred格式為kubectl create secret docker-registry regcred \ --docker-server你的鏡像倉庫服務器 \ --docker-username你的用戶名 \ --docker-password你的密碼 \ --docker-email你的郵箱地址導入我們阿里云容器鏡像服務ACRAlibaba Cloud Container Registry 的憑證#會在當前 Namespace 下創(chuàng)建一個docker-registry類型名為 regcred 的 Secret[rooth1 ~]# kubectl create secret docker-registry regcred \--docker-serverregistry.cn-hangzhou.aliyuncs.com\--docker-usernamewmbenet126.com\--docker-password123.com.憑證獲取步驟鏡像服務管理后臺進入鏡像倉庫步驟2在 Pod 中引用該 Secret 拉取私有鏡像[rooth3 ~]# cat pod_secret_docker.yamlapiVersion:v1kind:Podmetadata:name:private-regspec:containers:-name:private-reg-containerimage:your-private-image# 替換為你的私有鏡像地址imagePullSecrets:# 【核心字段】拉取鏡像時使用的憑證列表-name:regcred# 引用上一步創(chuàng)建的 Secret注意imagePullSecrets字段設置在 Pod 級別而非容器級別表示拉取該 Pod 的所有鏡像時使用的認證信息。2.4 TLS 證書與私鑰tls類型場景為 Ingress 或服務間通信配置 TLS 證書。語法kubectl create secret tls tls-secret \ --certpath/to/tls.cert \ #證書路徑 --keypath/to/tls.key #私鑰路徑#生成證書和私鑰[roothd1 ~]# openssl req -x509 -nodes -days 36500 -newkey rsa:2048 -keyout abc.key -out abc.crt#將證書和私鑰變成secret[roothd1 ~]# kubectl create secret tls tls-secret --certabc.crt --keyabc.keysecret/tls-secret created這個 Secret 的應用場景示例我們創(chuàng)建的這個 tls-secret最典型的用法是掛載到 Ingress網關 上讓集群對外提供 HTTPS 服務apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:example-ingressspec:tls:-hosts:-www.myapp.comsecretName:tls-secret# 引用你剛才創(chuàng)建的 TLS Secretrules:-host:www.myapp.comhttp:paths:-path:/backend:service:name:my-serviceport:number:80三、綜合案例部署 MySQL 并集成 ConfigMap Secret3.1 案例要求用 Deployment 部署一個 MySQL 數據庫將my.cnf做成 ConfigMap修改端口為33060傳入 Pod 配置文件路徑將 MySQL root 密碼做成 Secret以環(huán)境變量方式傳入 Pod3.2 實現步驟步驟1創(chuàng)建 ConfigMapMySQL 配置文件# mysql-configmap.yamlapiVersion:v1kind:ConfigMapmetadata:name:mysql-configdata:my.cnf:|[mysqld] port33060 socket/var/run/mysqld/mysqld.sock這段配置是把mysql的端口改成了33060并指定了sock文件的路徑[roothd1 ~]# kubectl apply -f mysql-configmap.yaml步驟2創(chuàng)建 SecretMySQL root 密碼這個就是我們在上文創(chuàng)建的[roothd1 ~]# kubectl create secret generic mysql-password --from-literalpassword123456步驟3創(chuàng)建 PVC持久化存儲這里使用的是存儲類還是我們之前創(chuàng)建的那個。忘記的可以回去看KubernetesK8s筆記Day06 持久化存儲7.4的步驟5和步驟6把供應商和sc拉起來就行了# mysql-pvc.yamlapiVersion:v1kind:PersistentVolumeClaimmetadata:name:mysql-pv-claimspec:storageClassName:nfsaccessModes:-ReadWriteOnceresources:requests:storage:2Gi[roothd1 ~]# kubectl apply -f mysql-pvc.yaml步驟4創(chuàng)建 Deployment整合所有配置# mysql-deployment.yamlapiVersion:apps/v1kind:Deploymentmetadata:name:mysqlspec:selector:matchLabels:app:mysqlstrategy:type:Recreate# 重建策略先刪舊 Pod再建新 Pod不是滾動更新template:metadata:labels:app:mysqlspec:containers:-image:mysql:8.0name:mysqlenv:-name:MYSQL_ROOT_PASSWORD#這個是注入mysql密碼的標準的變量名稱valueFrom:# 從外部資源取值secretKeyRef:#使用secret導入環(huán)境變量依舊是mysql的密碼name:mysql-password#指定導入的secret名稱key:password# Secret 中的鍵名ports:-containerPort:33060name:mysqlvolumeMounts:# 【存儲掛載】容器內的掛載點-name:mysql-persistent-storagemountPath:/var/lib/mysql# MySQL 數據目錄存放庫表文件-name:mysql-config-volumemountPath:/etc/my.cnfsubPath:my.cnf#關鍵點加上這個在掛載的時候就不會完全覆蓋目標路徑而是把特定文件導入只替換這一個文件volumes:-name:mysql-persistent-storagepersistentVolumeClaim:claimName:mysql-pv-claim-name:mysql-config-volumeconfigMap:# 使用 ConfigMap 作為配置源name:mysql-config# ConfigMap 名稱這個配置文件利用了configmap的特性 secret 也一樣configmap的字段掛載進pod會變成文件以此掛載用來替換特定的配置文件[roothd1 ~]# kubectl apply -f mysql-deployment.yaml3.3 案例總結這個案例利用ConfigMap 實現配置文件外置端口修改利用Secret 實現密碼安全注入環(huán)境變量利用PVC 實現數據持久化存儲保留利用Deployment 的 Recreate 策略保障單實例存儲安全最終完成了一個“配置可調、密碼安全、數據不丟”的標準 MySQL 容器化部署四、擴展命令kubectl port-forwardkubectl port-forward能夠在本地主機和Kubernetes 集群中的 Pod之間建立端口轉發(fā)用于開發(fā)和調試場景。作用在不修改 Service 暴露配置如 LoadBalancer 或 NodePort的情況下直接從本地訪問集群內部的服務或應用。kubectl delete pod --all常用命令# 監(jiān)聽宿主機的回環(huán)接口127.0.0.1kubectl port-forwardpod-name8000:8080# 監(jiān)聽宿主機的所有接口可被外部訪問kubectl port-forward--address0.0.0.0pod-name8000:8080示例如果你在集群中運行了一個 Web 應用Pod 內監(jiān)聽 8080 端口想在本機瀏覽器查看執(zhí)行kubectl port-forward pod-name 8000:8080后即可通過http://127.0.0.1:8000訪問該應用。五、核心知識點速查ConfigMap vs Secret 對比特性ConfigMapSecret用途存儲非機密配置數據存儲敏感數據密碼、密鑰、證書數據格式明文Base64 編碼非加密僅編碼大小限制≤ 1 MiB≤ 1 MiB使用方式環(huán)境變量 / Volume環(huán)境變量 / Volume / imagePullSecrets熱更新Volume 方式支持Volume 方式支持Secret 使用方式總結使用方式適用場景示例環(huán)境變量secretKeyRef將單個 key 注入為環(huán)境變量MySQL 密碼注入為MYSQL_ROOT_PASSWORDVolume 掛載將 Secret 作為文件掛載到目錄TLS 證書、配置文件掛載imagePullSecrets私有倉庫鏡像拉取認證從阿里云 ACR 拉取鏡像Secret 類型速查類型用途Opaque通用存儲任意敏感數據密碼、API Keykubernetes.io/dockerconfigjsonDocker 私有倉庫認證kubernetes.io/tlsTLS 證書和私鑰kubernetes.io/service-account-tokenServiceAccount 認證系統(tǒng)自動創(chuàng)建關鍵注意事項注意點說明Base64 不是加密Secret 僅做編碼不提供真正的加密保護密鑰大小限制Secret 數據大小 ≤ 1 MiB命名空間隔離Secret 只能被同一命名空間的 Pod 引用熱更新支持Volume 方式支持熱更新環(huán)境變量方式不支持