1、Secret介紹
在Kubernetes集羣資源中,Secret對象與ConfigMap對象相似,但它主要是用於存儲小片敏感的須要加密的數據,例如密碼,token和SSH key密鑰等等。這類數據固然也能夠存放在Pod的定義中或者鏡像中,可是放在Secret中是爲了更方便的控制如何使用數據,更加安全和靈活,並減小信息暴露的風險。在secret中存儲的數據都須要經過base64進行轉換加密後存放。Secret解決了密碼、token、密鑰等敏感數據的配置問題,使用Secret能夠避免把這些敏感數據以明文的形式暴露到鏡像或者Pod Spec中。用戶能夠建立本身的secret,系統也會有本身的secret。nginx
Secret一旦被建立,則能夠經過如下三種方式來使用:
-> 在建立Pod時,經過爲pod指定Service Account來自動使用該Secret,主要用於API Server鑑權的過程;
-> 經過掛載Secret到Pod來使用它。即做爲volume的一個域被一個或多個容器掛載;
-> Docker鏡像下載時使用,經過指定Pod的spc.ImagePullSecret來引用。通常用於私有倉庫登陸拉取鏡像。即在拉取鏡像的時候被kubelet引用。redis
Kubernetes集羣中有內建的Secrets:即由ServiceAccount建立的API證書附加的祕鑰,Kubernetes會自動生成的用來訪問apiserver的Secret,全部Pod會默認使用這個Secret與apiserver通訊。這是Kubernetes 默認的行爲,也能夠經過自定義的方式禁用或者建立咱們所須要的Secret。docker
2、Secret 類型和使用
-> Opaque:使用base64編碼存儲信息,能夠經過base64 --decode解碼得到原始數據,所以安全性弱。
-> kubernetes.io/dockerconfigjson:用於存儲docker registry的認證信息。
-> kubernetes.io/service-account-token (即Service Account):用於被 serviceaccount 引用。serviceaccout 建立時,Kubernetes 會默認建立對應的 secret。Pod 若是使用了 serviceaccount,對應的 secret 會自動掛載到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目錄中。Service Account 是內置secret,使用 API 憑證自動建立和附加secret。Kubernetes 自動建立包含訪問API憑據的secret,並自動修改pod以使用此類型的secret。若是須要,能夠禁用或覆蓋自動建立和使用API憑據。可是,若是須要的只是安全地訪問apiserver,則推薦這樣的工做流程。json
第一種類型: Opaque Secret
Opaque類型的Secret,其value爲base64編碼後的值。api
1)從文件中建立Secret:分別建立兩個名爲username.txt和password.txt的文件安全
[root@k8s-master01 ~]# echo -n "shibo" > ./username.txt [root@k8s-master01 ~]# echo -n "shibo@123" > ./password.txt
使用kubectl create secret命令建立secret,該命令將這些文件打包到一個Secret中並在API server中建立了一個對象。bash
[root@k8s-master01 ~]# kubectl create secret generic shibo-secret --from-file=./username.txt --from-file=./password.txt secret/shibo-secret created
2)使用描述文件建立Secret: 首先使用base64對數據進行編碼app
[root@k8s-master01 ~]# echo -n 'kevin_bo' | base64 a2V2aW5fYm8= [root@k8s-master01 ~]# echo -n 'kevin@123' | base64 a2V2aW5AMTIz
建立一個類型爲Secret的描述文件ui
[root@k8s-master01 ~]# cat secret.yaml apiVersion: v1 kind: Secret metadata: name: mysecret type: Opaque data: username: a2V2aW5fYm8= password: a2V2aW5AMTIz
執行建立編碼
[root@k8s-master01 ~]# kubectl create -f secret.yaml secret/mysecret created
查看此Secret
[root@k8s-master01 ~]# kubectl get secret|grep "shibo" shibo-secret Opaque 2 2m27s [root@k8s-master01 ~]# kubectl get secret shibo-secret -o yaml apiVersion: v1 data: password.txt: c2hpYm9AMTIz username.txt: c2hpYm8= kind: Secret metadata: creationTimestamp: "2019-06-26T11:20:17Z" name: shibo-secret namespace: default resourceVersion: "1152263" selfLink: /api/v1/namespaces/default/secrets/shibo-secret uid: 607ea323-9804-11e9-90d4-005056ac7c81 type: Opaque [root@k8s-master01 ~]# kubectl describe secret/shibo-secret Name: shibo-secret Namespace: default Labels: <none> Annotations: <none> Type: Opaque Data ==== username.txt: 5 bytes password.txt: 9 bytes
須要注意:默認狀況下,get 和 describe 命令都不會顯示文件的內容。這是爲了防止將secret中的內容被意外暴露給從終端日誌記錄中刻意尋找它們的人。
3)Secret的使用
建立好Secret以後,能夠經過兩種方式使用:
-> 以Volume方式
-> 以環境變量方式
Secret 能夠做爲數據卷被掛載,或做爲環境變量暴露出來以供 pod 中的容器使用。它們也能夠被系統的其餘部分使用,而不直接暴露在 pod 內。例如,它們能夠保存憑據,系統的其餘部分應該用它來表明您與外部系統進行交互。
在 Pod 中的 volume 裏使用 Secret:
-> 建立一個 secret 或者使用已有的 secret。多個 pod 能夠引用同一個 secret。
-> 修改您的 pod 的定義在 spec.volumes[] 下增長一個 volume。能夠給這個 volume 隨意命名,它的 spec.volumes[].secret.secretName 必須等於 secret 對象的名字。
-> 將下面的配置
spec.containers[].volumeMounts[]
加到須要用到該 secret 的容器中。指定下面的配置
spec.containers[].volumeMounts[].readOnly = true
並設置下面內容爲想要該 secret 出現的還沒有使用的目錄。
spec.containers[].volumeMounts[].mountPath
-> 修改鏡像而且/或者命令行讓程序從該目錄下尋找文件。Secret的data映射中的每個鍵都成爲了mountPath下的一個文件名。
3.1 將Secret掛載到Volume中 (下面是一個在pod中使用volume掛載secret的例子)
apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: mypod image: redis volumeMounts: - name: data mountPath: "/etc/data" readOnly: true volumes: - name: data secret: secretName: shibo-secret
進入Pod查看掛載的Secret:
# ls /etc/data password.txt username.txt # cat /etc/data/username.txt kevin # cat /etc/data/password.txt kevin@123
想要用的每一個secret都須要在spec.volumes 中指明。若是pod中有多個容器,每一個容器都須要本身的volumeMounts配置塊,可是每一個secret只須要一個spec.volumes。還能夠打包多個文件到一個secret中,或者使用的多個secret,怎樣方便就怎樣來。也能夠向特性路徑映射secret密鑰。
還能夠控制Secret key映射在 volume 中的路徑,可使用 spec.volumes[].secret.items字段修改每一個key的目標路徑。也就是說能夠只掛載Secret中特定的key:
apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: mypod image: redis volumeMounts: - name: data mountPath: "/etc/data" readOnly: true volumes: - name: data secret: secretName: shibo-secret items: - key: username path: my-group/my-username
須要注意,在這種狀況下:
username 存儲在 /etc/data/my-group/my-username中
password 未被掛載
若是使用了 spec.volumes[].secret.items,只有在 items 中指定的 key 被影射。要使用 secret 中全部的 key,全部這些都必須列在 items 字段中。全部列出的密鑰必須存在於相應的 secret 中。不然,不會建立卷。
3.2 將Secret設置爲環境變量
apiVersion: v1 kind: Pod metadata: name: secret-env-pod spec: containers: - name: mycontainer image: redis env: - name: SECRET_USERNAME valueFrom: secretKeyRef: name: shibo-secret key: username - name: SECRET_PASSWORD valueFrom: secretKeyRef: name: shibo-secret key: password restartPolicy: Never
第二種類型:kubernetes.io/dockerconfigjson
kubernetes.io/dockerconfigjson用於存儲docker registry的認證信息,能夠直接使用kubectl create secret命令建立:
[root@k8s-master01 ~]# kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL secret/myregistrykey created
查看secret的內容:
[root@k8s-master01 ~]# kubectl get secret|grep myregistrykey myregistrykey kubernetes.io/dockerconfigjson 1 54s [root@k8s-master01 ~]# kubectl get secret myregistrykey -o yaml apiVersion: v1 data: .dockerconfigjson: eyJhdXRocyI6eyJET0NLRVJfUkVHSVNUUllfU0VSVkVSIjp7InVzZXJuYW1lIjoiRE9DS0VSX1VTRVIiLCJwYXNzd29yZCI6IkRPQ0tFUl9QQVNTV09SRCIsImVtYWlsIjoiRE9DS0VSX0VNQUlMIiwiYXV0aCI6IlJFOURTMFZTWDFWVFJWSTZSRTlEUzBWU1gxQkJVMU5YVDFKRSJ9fX0= kind: Secret metadata: creationTimestamp: "2019-06-26T11:35:22Z" name: myregistrykey namespace: default resourceVersion: "1153734" selfLink: /api/v1/namespaces/default/secrets/myregistrykey uid: 7b769a8a-9806-11e9-90d4-005056ac7c81 type: kubernetes.io/dockerconfigjson
經過 base64 對 secret 中的內容解碼:
[root@k8s-master01 ~]# echo "eyJhdXRocyI6eyJET0NLRVJfUkVHSVNUUllfU0VSVkVSIjp7InVzZXJuYW1lIjoiRE9DS0VSX1VTRVIiLCJwYXNzd29yZCI6IkRPQ0tFUl9QQVNTV09SRCIsImVtYWlsIjoiRE9DS0VSX0VNQUlMIiwiYXV0aCI6IlJFOURTMFZTWDFWVFJWSTZSRTlEUzBWU1gxQkJVMU5YVDFKRSJ9fX0=" | base64 --decode {"auths":{"DOCKER_REGISTRY_SERVER":{"username":"DOCKER_USER","password":"DOCKER_PASSWORD","email":"DOCKER_EMAIL","auth":"RE9DS0VSX1VTRVI6RE9DS0VSX1BBU1NXT1JE"}}}
在建立 Pod 的時候,經過 imagePullSecrets 來引用剛建立的 myregistrykey:
apiVersion: v1 kind: Pod metadata: name: data spec: containers: - name: data image: janedoe/awesomeapp:v1 imagePullSecrets: - name: myregistrykey
第三種類型:kubernetes.io/service-account-token
用於被 serviceaccount 引用。serviceaccout 建立時 Kubernetes 會默認建立對應的 secret。Pod 若是使用了 serviceaccount,對應的 secret 會自動掛載到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目錄中。
[root@k8s-master01 ~]# kubectl run kevin_nginx --image nginx deployment "nginx" created [root@k8s-master01 ~]# kubectl get pods NAME READY STATUS RESTARTS AGE kevin_nginx-3137573019-md1u2 1/1 Running 0 13s [root@k8s-master01 ~]# kubectl exec kevin_nginx-3137573019-md1u2 ls /run/secrets/kubernetes.io/serviceaccount ca.crt namespace token