Kubernetes容器集羣 - Secret(特殊存儲卷)

 

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 憑證自動建立和附加secretKubernetes 自動建立包含訪問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
相關文章
相關標籤/搜索