1. 程式人生 > 其它 >小白學k8s(11)-k8s中Secret理解

小白學k8s(11)-k8s中Secret理解

理解Secret

什麼是Secret

Secret物件型別用來儲存敏感資訊,例如密碼、OAuth

令牌和 SSH 金鑰。 將這些資訊放在secret中比放在Pod的定義或者 容器映象中來說更加安全和靈活。

Secret是一種包含少量敏感資訊例如密碼、令牌或金鑰的物件。 這樣的資訊可能會被放在Pod 規約中或者映象中。 使用者可以建立Secret,同時系統也建立了一些Secret

要使用Secret,Pod 需要引用SecretPod可以用三種方式之一來使用 Secret:

  • 作為掛載到一個或多個容器上的卷中的檔案。

  • 作為容器的環境變數

  • 由kubelet在為Pod拉取映象時使用

Secret的型別

Kubernetes提供若干種內建的型別,用於一些常見的使用場景。 針對這些型別,Kubernetes

所執行的合法性檢查操作以及對其所實施的限制各不相同。

內建型別 用法
Opaque 使用者定義的任意資料
kubernetes.io/service-account-token 服務賬號令牌
kubernetes.io/dockercfg ~/.dockercfg 檔案的序列化形式
kubernetes.io/dockerconfigjson ~/.docker/config.json 檔案的序列化形式
kubernetes.io/basic-auth 用於基本身份認證的憑據
kubernetes.io/ssh-auth 用於 SSH 身份認證的憑據
kubernetes.io/tls 用於 TLS 客戶端或者伺服器端的資料
bootstrap.kubernetes.io/token 啟動引導令牌資料

Opaque Secret

Opaque型別的資料是一個map型別,要求valuebase64編碼格式:

建立我們需要的兩個base64賬號資訊

$ echo -n "root" | base64
  cm9vdA==
$ echo -n "123456" | base64
  MTIzNDU2

secrets.yml

apiVersion: v1
kind: Secret
metadata:
  name: secret-test
type: Opaque
data:
  password: MTIzNDU2
  username: cm9vdA==

建立 secret:kubectl create -f secrets.yml

$ kubectl get secret
  NAME                         TYPE                                  DATA   AGE
  secret-test                  Opaque                                2      8s

可以看到我們剛剛建立的secret

Opaque Secret的使用

建立好secret之後,有兩種方式來使用它:

  • 以 Volume 方式

  • 以環境變數方式

將Secret掛載到Volume中

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: secret-test
      items:
      - key: username
        path: my-group/my-username

成功執行之後,進入到pod中

root@mypod:/etc/foo/my-group# ls
my-username

root@mypod:/etc/foo/my-group# cat my-username 
root

可以看到我們之前定義的secret的username已經被當前的pod引用,併成功掛載

掛載的Secret會被自動更新

當已經儲存於卷中被使用的Secret被更新時,被對映的鍵也將終將被更新。 元件kubelet在週期性同步時檢查被掛載的Secret是不是最新的。 但是,它會使用其本地快取的數值作為Secret的當前值。

不過,使用Secret作為子路徑卷掛載的容器 不會收到Secret更新。

將Secret匯出到環境變數中

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

啟動pod,之後進入pod

root@secret-env-pod:/data# echo $SECRET_USERNAME
root
root@secret-env-pod:/data# echo $SECRET_PASSWORD
123456

可以看到secret的值已經成功寫入到環境變數中了

Secret更新之後對應的環境變數不會被更新

如果某個容器已經在通過環境變數使用某Secret,對該Secret的更新不會被 容器馬上看見,除非容器被重啟。有一些第三方的解決方案能夠在Secret發生變化時觸發容器重啟。

kubernetes.io/dockerconfigjson

型別kubernetes.io/dockerconfigjson被設計用來儲存JSON資料的序列化形式, 該 JSON 也遵從~/.docker/config.json檔案的格式規則,而後者是~/.dockercfg的新版本格式。 使用此Secret型別時,Secret物件的 data 欄位必須包含.dockerconfigjson鍵,其鍵值為base64編碼的字串包含~/.docker/config.json檔案的內容。

下面是一個kubernetes.io/dockercfg型別Secret的示例:

apiVersion: v1
kind: Secret
metadata:
  name: secret-dockercfg
type: kubernetes.io/dockercfg
data:
  .dockercfg: |
        "<base64 encoded ~/.dockercfg file>"

kubernetes.io/service-account-token

kubernetes.io/service-account-token: 用於被serviceaccount引用。serviceaccout建立時Kubernetes會預設建立對應的secret。Pod如果使用了serviceaccount,對應的 secret 會自動掛載到Pod的/run/secrets/kubernetes.io/serviceaccount目錄中。

$ kubectl run nginx --image nginx
  pod/nginx created
$ kubectl get pods
  NAME             READY   STATUS              RESTARTS   AGE
  nginx            0/1     ContainerCreating   0          26s
$ kubectl exec nginx ls /run/secrets/kubernetes.io/serviceaccount
  ca.crt
  namespace
  token

Kubernetes在建立Pod時會自動建立一個服務賬號Secret並自動修改你的Pod以使用該Secret。該服務賬號令牌Secret中包含了訪問Kubernetes API所需要的憑據。

不可更改的Secret

Kubernetes對於SecretConfigMap提供了一種不可變更的配置選擇,對於大量使用Secret的叢集(至少有成千上萬各不相同的SecretPod掛載), 禁止變更它們的資料有下列好處:

  • 防止意外(或非預期的)更新導致應用程式中斷

  • 通過將 Secret 標記為不可變來關閉 kube-apiserver 對其的監視,從而顯著降低 kube-apiserver 的負載,提升叢集效能。

Secretimmutable欄位設定為true建立不可更改的Secret

apiVersion: v1
kind: Secret
metadata:
  ...
data:
  ...
immutable: true

1、當一個secret設定成不可更改,如果想要更改secret中的內容,就需要刪除並且重新建立這個secret

2、對於引用老的secret的pod,需要刪除並且重新建立

Secret與Pod生命週期的關係

通過API建立Pod時,不會檢查引用的Secret是否存在。一旦Pod被排程,kubelet就會嘗試獲取該Secret的值。如果獲取不到該Secret,或者暫時無法與API伺服器建立連線,kubelet將會定期重試。kubelet將會報告關於 Pod 的事件,並解釋它無法啟動的原因。 一旦獲取到Secret,kubelet將建立並掛載一個包含它的卷。在Pod的所有卷被掛載之前,Pod中的容器不會啟動。

Secret與ConfigMap對比

相同點:

  • key/value 的形式

  • 屬於某個特定的 namespace

  • 可以匯出到環境變數

  • 可以通過目錄 / 檔案形式掛載 (支援掛載所有 key 和部分 key)

不同點:

  • Secret 可以被 ServerAccount 關聯 (使用)

  • Secret 可以儲存 register 的鑑權資訊,用在 ImagePullSecret 引數中,用於拉取私有倉庫的映象

  • Secret 支援 Base64 加密

  • Secret 檔案儲存在 tmpfs 檔案系統中,Pod 刪除後 Secret 檔案也會對應的刪除。

參考

【Secret】https://feisky.gitbooks.io/kubernetes/content/concepts/secret.html
【k8s官方對Secret的描述】https://kubernetes.io/zh/docs/concepts/configuration/secret/