密鑰

「密鑰 (Secret)」是一個包含少量敏感資料的物件,例如密碼、權杖或金鑰。這些資訊如果直接放入 Pod 規格或 容器映像檔 中可能會帶來風險。使用密鑰意味著您不需要將機密資料包含在應用程式代碼中。

由於密鑰可以獨立於使用它們的 Pod 而建立,因此在建立、檢視和編輯 Pod 的工作流程中,密鑰(及其資料)外洩的風險較小。Kubernetes 以及在叢集中執行的應用程式也可以對密鑰採取額外的預防措施,例如避免將敏感資料寫入非揮發性儲存裝置。

密鑰與 ConfigMap 類似,但其目的專門用於保存機密資料。

注意

Kubernetes 密鑰在預設情況下,是以未加密形式儲存在 API 伺服器的底層資料儲存區 (etcd) 中的。任何擁有 API 存取權的人都可以擷取或修改密鑰,任何能存取 etcd 的人也是如此。此外,任何被授權在命名空間中建立 Pod 的人,都可以利用該存取權讀取該命名空間中的任何密鑰;這包括間接存取,例如建立 Deployment 的能力。

為了安全地使用密鑰,請至少採取以下步驟:

  1. 啟用靜態加密 (Encryption at Rest) 以保護密鑰。
  2. 啟用或設定 RBAC 規則,以實現對密鑰的最小權限存取。
  3. 將密鑰存取權限制在特定容器中。
  4. 考慮使用外部密鑰儲存提供者。.

如需更多管理和提升密鑰安全性的指南,請參閱 Kubernetes 密鑰的最佳實踐

請參閱密鑰的資訊安全以了解更多詳細資訊。

密鑰的用途

您可以將密鑰用於以下目的:

Kubernetes 控制平面也會使用密鑰;例如,啟動引導權杖密鑰 (Bootstrap token Secrets) 是一種協助自動化節點註冊的機制。

使用案例:密鑰卷中的 dotfiles(設定檔)

您可以透過定義以點(dot)開頭的鍵,使資料成為「隱藏」狀態。此鍵代表 dotfile 或「隱藏」檔案。例如,當以下密鑰掛載到 volume(名稱為 secret-volume)中時,該 volume 將包含一個名為 .secret-file 的檔案,且 dotfile-test-container 將會在路徑 /etc/secret-volume/.secret-file 處找到此檔案。

注意

以點字元開頭的檔案會從 ls -l 的輸出中隱藏;列出目錄內容時,您必須使用 ls -la 才能看到它們。
apiVersion: v1
kind: Secret
metadata:
  name: dotfile-secret
data:
  .secret-file: dmFsdWUtMg0KDQo=
---
apiVersion: v1
kind: Pod
metadata:
  name: secret-dotfiles-pod
spec:
  volumes:
    - name: secret-volume
      secret:
        secretName: dotfile-secret
  containers:
    - name: dotfile-test-container
      image: registry.k8s.io/busybox
      command:
        - ls
        - "-l"
        - "/etc/secret-volume"
      volumeMounts:
        - name: secret-volume
          readOnly: true
          mountPath: "/etc/secret-volume"

使用案例:Pod 中僅單一容器可見的密鑰

考慮一個需要處理 HTTP 請求、執行複雜業務邏輯,然後使用 HMAC 對某些訊息進行簽章的程式。由於它具有複雜的應用程式邏輯,伺服器中可能會存在未被察覺的遠端檔案讀取漏洞,這可能會將私鑰暴露給攻擊者。

這可以劃分為兩個容器中的兩個程序:一個前端容器,負責處理使用者互動和業務邏輯,但無法看到私鑰;以及一個簽章容器,可以存取私鑰,並回應來自前端(例如透過 localhost 網路)的簡單簽章請求。

透過這種分割方法,攻擊者現在必須誘導應用程式伺服器執行某些任意操作,這可能比讓它讀取一個檔案要困難得多。

密鑰的替代方案

您可以選擇替代方案,而不是僅使用密鑰來保護機密資料。

以下是您的一些選擇:

  • 如果您的雲端原生元件需要向您已知在同一個 Kubernetes 叢集中執行的另一個應用程式進行驗證,您可以使用 ServiceAccount 及其權杖來識別您的用戶端。
  • 有一些協力廠商工具,您可以選擇在叢集內或叢集外執行,用以管理敏感資料。例如,一個 Pod 透過 HTTPS 存取的服務,如果用戶端正確驗證(例如使用 ServiceAccount 權杖),該服務就會揭露密鑰。
  • 對於驗證,您可以實作自訂的 X.509 憑證簽署者,並使用 CertificateSigningRequests 讓該自訂簽署者為需要憑證的 Pod 發行憑證。
  • 您可以使用 裝置外掛 (device plugin) 將節點本機的加密硬體公開給特定的 Pod。例如,您可以將受信任的 Pod 排程到提供「信任平台模組 (Trusted Platform Module, TPM)」且已進行頻外 (out-of-band) 設定的節點上。

您也可以結合上述兩種或多種選項,包括使用密鑰物件本身的選項。

例如:實作(或部署)一個 Operator,從外部服務取得短效期工作階段權杖 (short-lived session tokens),然後基於這些短效期權杖建立密鑰。在您的叢集中執行的 Pod 可以利用這些工作階段權杖,而 Operator 確保它們是有效的。這種分離意味著您可以執行不需要確切了解如何發行和重新整理這些權杖機制的 Pod。

密鑰類型

建立密鑰時,您可以使用 Secret 資源的 type 欄位或某些對等的 kubectl 命令列旗標(如果可用)來指定其類型。密鑰類型用於促進密鑰資料的程式化處理。

Kubernetes 為常見的使用場景提供了幾種內建類型。這些類型在執行的驗證和 Kubernetes 對其施加的限制方面有所不同。

內建類型用法
Opaque任意使用者定義的資料
kubernetes.io/service-account-tokenServiceAccount 權杖
kubernetes.io/dockercfg序列化的 ~/.dockercfg 檔案
kubernetes.io/dockerconfigjson序列化的 ~/.docker/config.json 檔案
kubernetes.io/basic-auth基本驗證所需的憑證
kubernetes.io/ssh-authSSH 驗證所需的憑證
kubernetes.io/tlsTLS 用戶端或伺服器所需的資料
bootstrap.kubernetes.io/token啟動引導權杖資料

您可以透過為密鑰物件指定一個非空字串作為 type 值來定義並使用您自己的密鑰類型(空字串會被視為 Opaque 類型)。

Kubernetes 對類型名稱沒有施加任何限制。然而,如果您正在使用其中一種內建類型,則必須滿足該類型定義的所有要求。

如果您正在定義一種用於公開用途的密鑰類型,請遵循慣例,將密鑰類型結構化為在名稱前加上您的網域名稱,並以 / 分隔。例如:cloud-hosting.example.net/cloud-api-credentials

不透明密鑰 (Opaque Secrets)

如果您沒有在密鑰清單中明確指定類型,Opaque 是預設的密鑰類型。當您使用 kubectl 建立密鑰時,必須使用 generic 子命令來指明這是一個 Opaque 密鑰類型。例如,以下命令建立了一個 Opaque 類型的空白密鑰:

kubectl create secret generic empty-secret
kubectl get secret empty-secret

輸出如下:

NAME           TYPE     DATA   AGE
empty-secret   Opaque   0      2m6s

DATA 欄顯示儲存在密鑰中的資料項目數量。在此案例中,0 表示您建立了一個空白密鑰。

服務帳戶權杖密鑰 (ServiceAccount token Secrets)

kubernetes.io/service-account-token 類型的密鑰用於儲存識別 ServiceAccount 的權杖憑證。這是一種提供長期 ServiceAccount 憑證給 Pod 的舊有機制。

在 Kubernetes v1.22 及更高版本中,建議的方法是透過使用 TokenRequest API 來取得短效期、自動輪替的 ServiceAccount 權杖。您可以使用以下方法取得這些短效期權杖:

注意

僅當您無法使用 TokenRequest API 取得權杖,且您能接受在可讀的 API 物件中保存永不過期的權杖憑證所帶來的安全風險時,才應該建立 ServiceAccount 權杖密鑰。相關說明請參閱手動為 ServiceAccount 建立長期 API 權杖

使用此密鑰類型時,您需要確保 kubernetes.io/service-account.name 註解已設定為現有的 ServiceAccount 名稱。如果您同時建立 ServiceAccount 和密鑰物件,則應先建立 ServiceAccount 物件。

在建立密鑰後,Kubernetes 控制器會填入一些其他欄位,例如 kubernetes.io/service-account.uid 註解,以及 data 欄位中的 token 鍵,其中會填入驗證權杖。

以下配置範例宣告了一個 ServiceAccount 權杖密鑰:

apiVersion: v1
kind: Secret
metadata:
  name: secret-sa-sample
  annotations:
    kubernetes.io/service-account.name: "sa-name"
type: kubernetes.io/service-account-token
data:
  extra: YmFyCg==

建立密鑰後,等待 Kubernetes 填入 data 欄位中的 token 鍵。

如需了解 ServiceAccount 如何運作的更多資訊,請參閱 ServiceAccount 文件。您也可以檢查 PodautomountServiceAccountToken 欄位和 serviceAccountName 欄位,了解如何在 Pod 內部參照 ServiceAccount 憑證。

Docker 設定密鑰 (Docker config Secrets)

如果您要建立密鑰以儲存存取容器映像檔登錄庫 (container image registry) 的憑證,必須針對該密鑰使用以下 type 值之一:

  • kubernetes.io/dockercfg:儲存序列化的 ~/.dockercfg,這是設定 Docker 命令列的傳統格式。密鑰的 data 欄位包含一個 .dockercfg 鍵,其值為 base64 編碼的 ~/.dockercfg 檔案內容。
  • kubernetes.io/dockerconfigjson:儲存遵循與 ~/.docker/config.json 檔案相同格式規則的序列化 JSON,這是 ~/.dockercfg 的新格式。密鑰的 data 欄位必須包含一個 .dockerconfigjson 鍵,其值為 base64 編碼的 ~/.docker/config.json 檔案內容。

以下是 kubernetes.io/dockercfg 類型密鑰的範例:

apiVersion: v1
kind: Secret
metadata:
  name: secret-dockercfg
type: kubernetes.io/dockercfg
data:
  .dockercfg: |
    eyJhdXRocyI6eyJodHRwczovL2V4YW1wbGUvdjEvIjp7ImF1dGgiOiJvcGVuc2VzYW1lIn19fQo=    

注意

如果您不想執行 base64 編碼,則可以選擇使用 stringData 欄位。

當您使用清單建立 Docker 設定密鑰時,API 伺服器會檢查 data 欄位中是否存在預期的鍵,並驗證所提供的值是否能被解析為有效的 JSON。API 伺服器不會驗證該 JSON 是否真的是 Docker 設定檔。

您也可以使用 kubectl 建立用於存取容器登錄庫的密鑰,例如在您沒有 Docker 設定檔的情況下:

kubectl create secret docker-registry secret-tiger-docker \
  --docker-email=tiger@acme.example \
  --docker-username=tiger \
  --docker-password=pass1234 \
  --docker-server=my-registry.example:5000

此命令會建立一個類型為 kubernetes.io/dockerconfigjson 的密鑰。

從該新密鑰中擷取 .data.dockerconfigjson 欄位並解碼資料:

kubectl get secret secret-tiger-docker -o jsonpath='{.data.*}' | base64 -d

其輸出等同於下列 JSON 文件(這也是一個有效的 Docker 設定檔):

{
  "auths": {
    "my-registry.example:5000": {
      "username": "tiger",
      "password": "pass1234",
      "email": "tiger@acme.example",
      "auth": "dGlnZXI6cGFzczEyMzQ="
    }
  }
}

注意

其中的 auth 值是 base64 編碼的;它是模糊化的,但並非機密。任何能夠讀取該密鑰的人都可以得知登錄庫存取的 bearer token。

建議使用 憑證提供者 (credential providers),以動態且安全地按需提供拉取密鑰。

基本驗證密鑰 (Basic authentication Secret)

kubernetes.io/basic-auth 類型專門用於儲存基本驗證 (basic authentication) 所需的憑證。使用此密鑰類型時,密鑰的 data 欄位必須包含以下兩個鍵之一:

  • username:驗證的使用者名稱
  • password:驗證的密碼或權杖

上述兩個鍵的值皆為 base64 編碼的字串。您也可以在密鑰清單中使用 stringData 欄位來提供明文內容。

以下清單是一個基本驗證密鑰的範例:

apiVersion: v1
kind: Secret
metadata:
  name: secret-basic-auth
type: kubernetes.io/basic-auth
stringData:
  username: admin # required field for kubernetes.io/basic-auth
  password: t0p-Secret # required field for kubernetes.io/basic-auth

注意

密鑰的 stringData 欄位在使用「伺服器端套用 (server-side apply)」時無法良好運作。

基本驗證密鑰類型僅是為了方便而提供。您可以為基本驗證所使用的憑證建立 Opaque 類型密鑰。然而,使用已定義的公開密鑰類型 (kubernetes.io/basic-auth) 有助於他人理解您的密鑰用途,並為預期的鍵名稱設定慣例。

SSH 驗證密鑰 (SSH authentication Secrets)

內建類型 kubernetes.io/ssh-auth 專門用於儲存 SSH 驗證中使用的資料。使用此密鑰類型時,您必須在 data(或 stringData)欄位中指定 ssh-privatekey 鍵值對,作為要使用的 SSH 憑證。

以下清單是一個用於 SSH 公鑰/私鑰驗證的密鑰範例:

apiVersion: v1
kind: Secret
metadata:
  name: secret-ssh-auth
type: kubernetes.io/ssh-auth
data:
  # the data is abbreviated in this example
  ssh-privatekey: |
    UG91cmluZzYlRW1vdGljb24lU2N1YmE=    

SSH 驗證密鑰類型僅是為了方便而提供。您可以為 SSH 驗證所使用的憑證建立 Opaque 類型密鑰。然而,使用已定義的公開密鑰類型 (kubernetes.io/ssh-auth) 有助於他人理解您的密鑰用途,並為預期的鍵名稱設定慣例。Kubernetes API 會驗證此類密鑰是否已設定了必要的鍵。

注意

SSH 私鑰本身無法建立 SSH 用戶端與主機伺服器之間的信任通訊。需要一種輔助手段來建立信任以減輕「中間人 (man in the middle)」攻擊,例如將 known_hosts 檔案新增到 ConfigMap 中。

TLS 密鑰 (TLS Secrets)

kubernetes.io/tls 密鑰類型用於儲存通常用於 TLS 的憑證及其相關私鑰。

TLS 密鑰的一個常見用途是為 Ingress 設定傳輸中加密 (encryption in transit),但您也可以將其用於其他資源或直接用於您的工作負載。使用此類密鑰時,data(或 stringData)欄位中必須提供 tls.keytls.crt 鍵,儘管 API 伺服器實際上並不會驗證每個鍵的值。

作為使用 stringData 的替代方案,您可以使用 data 欄位來提供 base64 編碼的憑證和私鑰。有關詳細資訊,請參閱密鑰名稱和資料的限制

以下 YAML 包含一個 TLS 密鑰的配置範例:

apiVersion: v1
kind: Secret
metadata:
  name: secret-tls
type: kubernetes.io/tls
data:
  # values are base64 encoded, which obscures them but does NOT provide
  # any useful level of confidentiality
  # Replace the following values with your own base64-encoded certificate and key.
  tls.crt: "REPLACE_WITH_BASE64_CERT" 
  tls.key: "REPLACE_WITH_BASE64_KEY"

TLS 密鑰類型僅是為了方便而提供。您可以為 TLS 驗證所使用的憑證建立 Opaque 類型密鑰。然而,使用已定義的公開密鑰類型 (kubernetes.io/tls) 有助於確保您專案中密鑰格式的一致性。API 伺服器會驗證此類密鑰是否已設定了必要的鍵。

若要使用 kubectl 建立 TLS 密鑰,請使用 tls 子命令:

kubectl create secret tls my-tls-secret \
  --cert=path/to/cert/file \
  --key=path/to/key/file

公鑰/私鑰對必須事先存在。用於 --cert 的公鑰憑證必須是 .PEM 編碼的,且必須與用於 --key 的給定私鑰相符。

啟動引導權杖密鑰 (Bootstrap token Secrets)

bootstrap.kubernetes.io/token 密鑰類型用於節點啟動引導 (node bootstrap) 過程中使用的權杖。它儲存用於簽署已知 ConfigMap 的權杖。

啟動引導權杖密鑰通常建立在 kube-system 命名空間中,命名格式為 bootstrap-token-<token-id>,其中 <token-id> 是權杖 ID 的 6 個字元字串。

作為 Kubernetes 清單,啟動引導權杖密鑰可能如下所示:

apiVersion: v1
kind: Secret
metadata:
  name: bootstrap-token-5emitj
  namespace: kube-system
type: bootstrap.kubernetes.io/token
data:
  auth-extra-groups: c3lzdGVtOmJvb3RzdHJhcHBlcnM6a3ViZWFkbTpkZWZhdWx0LW5vZGUtdG9rZW4=
  expiration: MjAyMC0wOS0xM1QwNDozOToxMFo=
  token-id: NWVtaXRq
  token-secret: a3E0Z2lodnN6emduMXAwcg==
  usage-bootstrap-authentication: dHJ1ZQ==
  usage-bootstrap-signing: dHJ1ZQ==

啟動引導權杖密鑰在 data 下指定了以下鍵:

  • token-id:一個 6 個字元的隨機字串,作為權杖識別碼。必填。
  • token-secret:一個 16 個字元的隨機字串,作為實際的權杖密鑰。必填。
  • description:一個人類可讀的字串,用於描述權杖的用途。選填。
  • expiration:一個使用 RFC3339 的絕對 UTC 時間,指定權杖何時過期。選填。
  • usage-bootstrap-<usage>:一個布林旗標,指示啟動引導權杖的其他用途。
  • auth-extra-groups:一個以逗號分隔的群組名稱列表,除了 system:bootstrappers 群組之外,還將作為這些群組進行驗證。

您也可以在密鑰的 stringData 欄位中提供這些值,而無需對其進行 base64 編碼:

apiVersion: v1
kind: Secret
metadata:
  # Note how the Secret is named
  name: bootstrap-token-5emitj
  # A bootstrap token Secret usually resides in the kube-system namespace
  namespace: kube-system
type: bootstrap.kubernetes.io/token
stringData:
  auth-extra-groups: "system:bootstrappers:kubeadm:default-node-token"
  expiration: "2020-09-13T04:39:10Z"
  # This token ID is used in the name
  token-id: "5emitj"
  token-secret: "kq4gihvszzgn1p0r"
  # This token can be used for authentication
  usage-bootstrap-authentication: "true"
  # and it can be used for signing
  usage-bootstrap-signing: "true"

注意

密鑰的 stringData 欄位在使用「伺服器端套用 (server-side apply)」時無法良好運作。

使用密鑰

建立密鑰

建立密鑰有幾種選擇:

密鑰名稱和資料的限制

密鑰物件的名稱必須是有效的 DNS 子網域名稱

建立密鑰的設定檔時,您可以指定 data 和/或 stringData 欄位。這兩個欄位均為選填。data 欄位中所有鍵的值都必須是 base64 編碼的字串。如果不希望轉換為 base64 字串,您可以選擇指定 stringData 欄位,它接受任意字串作為值。

datastringData 的鍵必須由字母數字字元、-_. 組成。stringData 欄位中的所有鍵值對會在內部合併到 data 欄位中。如果一個鍵同時出現在 datastringData 欄位中,則 stringData 欄位中指定的值優先。

大小限制

個別密鑰的大小限制為 1MiB。這是為了防止建立可能耗盡 API 伺服器和 kubelet 記憶體的超大密鑰。不過,建立大量較小的密鑰也可能耗盡記憶體。您可以使用 資源配額 (resource quota) 來限制命名空間中密鑰(或其他資源)的數量。

編輯密鑰

除非密鑰是不可變的,否則您可以編輯現有密鑰。若要編輯密鑰,請使用以下方法之一:

您也可以使用 Kustomize 工具編輯密鑰中的資料。但是,此方法會使用編輯後的資料建立一個新的 Secret 物件。

根據您建立密鑰的方式以及 Pod 中使用密鑰的方式,現有 Secret 物件的更新會自動傳播到使用該資料的 Pod。有關更多資訊,請參閱在 Pod 中將密鑰作為檔案使用一節。

使用密鑰

密鑰可以作為資料卷掛載,或公開為 環境變數,供 Pod 中的容器使用。密鑰也可以被系統的其他部分使用,而無需直接暴露給 Pod。例如,密鑰可以保存系統其他部分為了代表您與外部系統互動而需要使用的憑證。

密鑰卷來源會經過驗證,以確保指定的物件參照確實指向一個 Secret 類型的物件。因此,在任何依賴它的 Pod 建立之前,必須先建立密鑰。

如果無法擷取密鑰(可能是因為它不存在,或是因為與 API 伺服器的連線暫時中斷),kubelet 會定期重試執行該 Pod。kubelet 也會為該 Pod 報告一個 Event,其中包含擷取密鑰時發生問題的詳細資訊。

選填密鑰

當您在 Pod 中參照密鑰時,可以將該密鑰標記為 *選填 (optional)*,如下例所示。如果選填的密鑰不存在,Kubernetes 將會忽略它。

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
      optional: true

預設情況下,密鑰是必須的。除非所有非選填的密鑰都可用,否則 Pod 的任何容器都不會啟動。

如果 Pod 參照了非選填密鑰中的特定鍵,且該密鑰確實存在,但缺少指定的鍵,則 Pod 會在啟動期間失敗。

在 Pod 中將密鑰作為檔案使用

如果您想在 Pod 中存取密鑰資料,一種方法是讓 Kubernetes 使該密鑰的值以檔案形式存在於一個或多個 Pod 容器的檔案系統中。

相關說明請參閱建立一個透過 Volume 存取密鑰資料的 Pod

當 Volume 包含來自密鑰的資料,且該密鑰更新時,Kubernetes 會追蹤此變更並以「最終一致性 (eventually-consistent)」的方式更新 Volume 中的資料。

注意

使用密鑰作為 subPath Volume 掛載的容器,不會自動接收密鑰更新。

kubelet 會快取該節點上 Pod 所使用的密鑰之目前鍵值。您可以設定 kubelet 偵測這些快取值變更的方式。kubelet 設定中的 configMapAndSecretChangeDetectionStrategy 欄位控制 kubelet 使用的策略。預設策略為 Watch

密鑰的更新可以透過 API watch 機制(預設)、基於設定 TTL 的快取,或在每次 kubelet 同步迴圈中從叢集 API 伺服器進行輪詢 (polling) 來傳播。

因此,從密鑰更新那一刻起,到新鍵被投影 (projected) 到 Pod 為止的總延遲時間,最長可達 kubelet 同步週期 + 快取傳播延遲,其中快取傳播延遲取決於所選的快取類型(順序與前段文字相同:watch 傳播延遲、已設定的快取 TTL,或是直接輪詢時為零)。

將密鑰用作環境變數

若要在 Pod 中的 環境變數中使用密鑰:

  1. 對於 Pod 規格中的每個容器,為您想要使用的每個密鑰鍵新增一個環境變數至 env[].valueFrom.secretKeyRef 欄位。
  2. 修改您的映像檔和/或命令列,以便程式能在指定的環境變數中尋找值。

相關說明請參閱使用密鑰資料定義容器環境變數

請注意,Pod 中環境變數名稱允許的字元範圍是受限制的。如果任何鍵不符合規則,這些鍵將不會提供給您的容器,儘管 Pod 仍會被允許啟動。

容器映像檔拉取密鑰 (Container image pull Secrets)

如果您想從私有儲存庫拉取容器映像檔,您需要一種方式讓每個節點上的 kubelet 向該儲存庫進行驗證。您可以設定 *映像檔拉取密鑰 (image pull Secrets)* 來實現這一點。這些密鑰是在 Pod 層級設定的。

使用 imagePullSecrets

imagePullSecrets 欄位是同一個命名空間中密鑰的參照列表。您可以使用 imagePullSecrets 將包含 Docker(或其他)映像檔登錄庫密碼的密鑰傳遞給 kubelet。kubelet 使用此資訊代表您的 Pod 拉取私有映像檔。有關 imagePullSecrets 欄位的更多資訊,請參閱 PodSpec API

手動指定 imagePullSecret

您可以從 容器映像檔 文件中了解如何指定 imagePullSecrets

安排自動附加 imagePullSecrets

您可以手動建立 imagePullSecrets,並從 ServiceAccount 中參照它們。任何使用該 ServiceAccount 建立的 Pod,或是預設使用該 ServiceAccount 建立的 Pod,其 imagePullSecrets 欄位都會設定為該服務帳戶的設定。詳細解釋請參閱將 ImagePullSecrets 新增至服務帳戶

在靜態 Pod 中使用密鑰

您不能將 ConfigMap 或密鑰用於 靜態 Pod

不可變密鑰 (Immutable Secrets)

功能狀態: Kubernetes v1.21 [穩定]

Kubernetes 允許您將特定的密鑰(和 ConfigMap)標記為 *不可變 (immutable)*。防止對現有密鑰的資料進行變更具有以下好處:

  • 保護您免受可能導致應用程式中斷的意外(或不想要的)更新。
  • 對於大量使用密鑰的叢集(至少數萬個唯一的密鑰對 Pod 掛載),切換到不可變密鑰可顯著減輕 kube-apiserver 的負載,進而提高叢集的效能。kubelet 不需要為標記為不可變的任何密鑰維持 [watch] 機制。

標記密鑰為不可變

您可以透過將 immutable 欄位設定為 true 來建立不可變密鑰。例如:

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

您也可以更新任何現有的可變密鑰,使其變為不可變。

注意

一旦密鑰或 ConfigMap 被標記為不可變,就*無法*撤銷此變更,也無法變更 data 欄位的內容。您只能刪除並重建該密鑰。現有的 Pod 會保持對已刪除密鑰的掛載點——建議重建這些 Pod。

密鑰的資訊安全

儘管 ConfigMap 和密鑰的工作方式相似,但 Kubernetes 對密鑰物件實施了一些額外的保護。

密鑰通常保存著重要性各異的值,其中許多可能會導致 Kubernetes 內部(例如服務帳戶權杖)以及對外部系統的權限升級。即使個別應用程式可以理解其預期互動的密鑰權限,同一個命名空間內的其他應用程式也可能使這些假設失效。

授權設定會影響如何在命名空間內存取密鑰資料。例如,授予密鑰的 listwatch 權限,允許主體讀取該命名空間中的所有密鑰資料,而不僅僅是其 Pod 明確參照的密鑰。將存取權限制在工作負載運作所需的最小權限集,並避免授予廣泛的角色(如 cluster-admin),除非管理目的需要。

也請參閱 授權文件

密鑰只有在該節點上的 Pod 需要時,才會被傳送到該節點。為了將密鑰掛載到 Pod 中,kubelet 會將資料複本儲存在 tmpfs 中,以便機密資料不會被寫入持久儲存裝置。一旦依賴該密鑰的 Pod 被刪除,kubelet 就會從該密鑰中刪除其機密資料的本機複本。

一個 Pod 中可能有幾個容器。預設情況下,您定義的容器只能存取預設的 ServiceAccount 及其相關密鑰。您必須明確定義環境變數或將 Volume 對映到容器中,才能提供對任何其他密鑰的存取權。

同一個節點上可能有幾個 Pod 的密鑰。然而,只有 Pod 請求的密鑰才可能在容器內可見。因此,一個 Pod 無法存取另一個 Pod 的密鑰。

設定密鑰的最小權限存取

為了加強圍繞密鑰的安全措施,請使用單獨的命名空間來隔離對掛載密鑰的存取權。

警告

任何在節點上以 privileged: true 執行的容器都可以存取該節點上使用的所有密鑰。

接下來


最後修改於 2026 年 3 月 17 日上午 1:33 (PST):改進 Kubernetes 密鑰的安全性說明 (#54644) (8af7916eb8)