kubernetes對象之secrets

系列目錄html

Secrets是Kubernetes中一種對象類型,用來保存密碼、私鑰、口令等敏感信息。與直接將敏感信息嵌入image、pod相比,Secrets更安全、更靈活,用戶對敏感信息的控制力更強。同Docker對敏感信息的管理相似,首先用戶建立Secrets將敏感信息加密後保存在集羣中,建立pod時經過volume、環境變量引用Secrets。redis

建立Secrets數據庫

假設pod須要訪問數據庫。首先將用戶名保存在文件./username.txt,將密碼保存在./password.txt文件:json

# Create files needed for rest of example.
$ echo -n 'admin' > ./username.txt
$ echo -n '1f2d1e2e67df' > ./password.txt

將兩個文件做爲參數運行以下命令建立Secret,此時敏感數據被保存在系統中:api

$ kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt
secret "db-user-pass" created

用Secret名稱查看建立Secret:安全

$ kubectl get secrets
NAME                  TYPE                                  DATA      AGE
db-user-pass          Opaque                                2         51s

$ kubectl describe secrets/db-user-pass
Name:            db-user-pass
Namespace:       default
Labels:          <none>
Annotations:     <none>

Type:            Opaque

Data
====
password.txt:    12 bytes
username.txt:    5 bytes

以上經過命令行建立Secret,須要首先將敏感內容保存在文件中,文件名做爲Secret中單條條目的key。另一種建立Secret的方法是聲明對象。敏感信息可能包含任何控制字符、不可顯示字符等,首先進行base64編碼:bash

$ echo -n 'admin' | base64
YWRtaW4=
$ echo -n '1f2d1e2e67df' | base64
MWYyZDFlMmU2N2Rm

而後像下邊這樣聲明Secret對象:ide

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm

Kubernetes用map存儲Secret中的data數據部分,合法的key由字母、數字、’-‘、’_’、’.’組成,value能夠是任何值,但要base64編碼。運行以下命令建立Secret:性能

經過以下方法查看Secret中key所對應的值,首先運行以下命令:ui

$ kubectl get secret mysecret -o yaml
apiVersion: v1
data:
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm
kind: Secret
metadata:
  creationTimestamp: 2016-01-22T18:41:56Z
  name: mysecret
  namespace: default
  resourceVersion: "164619"
  selfLink: /api/v1/namespaces/default/secrets/mysecret
  uid: cfee02d6-c137-11e5-8d73-42010af00002
type: Opaque

運行以下命令base64解碼:

$ echo 'MWYyZDFlMmU2N2Rm' | base64 --decode
1f2d1e2e67df

使用Secrets

Pod使用Secret的兩種方法:volume與環境變量。

經過volume使用Secret基於流程:

建立或者使用已存Secret,同一Secret可被多個pod引用。
修改pod定義,在.spec.volumes[]下增長新volume,名稱隨意。在相應的.spec.volumes[].secret.secretName指定Secret名稱。
爲使用Secret的容器添加.spec.containers[].volumeMounts[],同時指定.spec.containers[].volumeMounts[].readOnly = true。指定.spec.containers[].volumeMounts[].mountPath爲未使用的目錄名稱。
在容器的image中,經過指定的目錄與Secret中的key訪問敏感內容。

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: foo
    secret:
      secretName: mysecret

若是須要引用多個Secret,須要爲每一個Secret在.spec.volumes[]添加相應的條目。若是單個容器須要引用多個Secret,則在.spec.containers[].volumeMounts[]中爲每一個Secret添加Mount。能夠將多個文件添加到一個Secret中,或者爲每一個文件建立Secret。

默認狀況下Secret中的全部key被映射到相同目錄下,能夠經過 .spec.volumes[].secret.items爲key設定映射目錄:

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: foo
    secret:
      secretName: mysecret
      items:
      - key: username
        path: my-group/my-username

以上配置致使的結果爲username被映射到/etc/foo/my-group/my-username,而非默認的/etc/foo/username,而且password未被映射。 若是不使用.spec.volumes[].secret.items,Secret中全部key被映射到默認目錄,若是在.spec.volumes[].secret.items指定了key與特定的映射目錄,則只映射列出的key。若是打算使用.spec.volumes[].secret.items而且映射全部Secret的key,那麼須要列出Secret中全部key。

能夠在.spec.volumes[].secret.defaultMode中爲Secret指定Permission,若是須要進一步在.spec.volumes[].secret.items[].mode爲每一個key單獨指定permission。若是沒有指定permission,默認爲0644。示例以下:

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
  volumes:
  - name: foo
    secret:
      secretName: mysecret
      defaultMode: 256

上例中的256等於8進制的0400,在json\yaml配置文件中不可使用八進制表示數字。單位爲key指定permission:

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
  volumes:
  - name: foo
    secret:
      secretName: mysecret
      items:
      - key: username
        path: my-group/my-username
        mode: 511

當經過Secret經過volume形式被使用時,其中的key若是發生變動的話,由kubelet自動週期性監控變動併爲pod更新,可是注意此特性並不是實時,存在延遲。

經過環境使用Secret流程:

建立或者使用已存在Secrets,一個Secret能夠被多個pod使用。
修改pod聲明中使用Secret的容器配置,爲其添加環境變量env[].valueFrom.secretKeyRef,每條key對應一個環境變量。
在容器的image中經過引用環境變量使用敏感數據。

示例:

apiVersion: v1
kind: Pod
metadata:
  name: secret-env-pod
spec:
  containers:
  - name: mycontainer
    image: redis
    env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: username
      - name: SECRET_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: password
  restartPolicy: Never

Secrets限制條件

  • 建立Pod時須要對其使用的Secret進行有效性檢查,所以Secrets要先於pod建立。

  • Secrets寄居於namespace之下,只有處於同一namespace下的pod能夠引用

  • 單個Secret的size不能超過1M,防止Secrets佔用太多內存引發apiServer性能惡化。但過多的Secrets仍然會佔用大量的內在,關於限制全部Secrets佔用內存的特性正在計劃中。

  • kubelet在不通過apiServer、控制器建立pod,如–manifest-url、–config時不能使用Secrets。

  • 若是在建立pod時Secret不存在或者key不存在,pod不能啓動。經過環境變量引用Secret時,若是envFrom中指定的key的名稱不合法,pod仍然能啓動但會觸發相應錯誤事件,如:

$ kubectl get events
LASTSEEN   FIRSTSEEN   COUNT     NAME            KIND      SUBOBJECT                         TYPE      REASON
0s         0s          1         dapi-test-pod   Pod                                         Warning   InvalidEnvironmentVariableNames   kubelet, 127.0.0.1      Keys [1badkey, 2alsobad] from the EnvFrom secret default/mysecret were skipped since they are considered invalid environment variable names.
相關文章
相關標籤/搜索