為 Pod 配置服務帳戶
Kubernetes 提供兩種不同的方式,讓叢集內執行的用戶端,或與叢集控制平面有關係的其他用戶端,可以向 API 伺服器驗證身分。
服務帳戶為在 Pod 中執行的程序提供身分,並對應到 ServiceAccount 物件。當您向 API 伺服器驗證身分時,您會將自己識別為特定的使用者。Kubernetes 認知使用者的概念,但是,Kubernetes 本身沒有 User API。
本任務指南是有關 ServiceAccount,其存在於 Kubernetes API 中。本指南向您展示一些為 Pod 配置 ServiceAccount 的方法。
準備開始
您需要有一個 Kubernetes 叢集,而且必須將 kubectl 命令列工具設定為與您的叢集通訊。建議在至少有兩個節點的叢集上執行本教學課程,這些節點不作為控制平面主機。如果您還沒有叢集,可以使用 minikube 建立一個,或者您可以使用這些 Kubernetes Playground 之一
使用預設服務帳戶存取 API 伺服器
當 Pod 聯絡 API 伺服器時,Pod 會以特定的 ServiceAccount(例如,default
)進行身分驗證。每個命名空間中始終至少有一個 ServiceAccount。
每個 Kubernetes 命名空間都包含至少一個 ServiceAccount:該命名空間的預設 ServiceAccount,名為 default
。如果您在建立 Pod 時未指定 ServiceAccount,Kubernetes 會自動指派該命名空間中名為 default
的 ServiceAccount。
您可以擷取您已建立之 Pod 的詳細資訊。例如
kubectl get pods/<podname> -o yaml
在輸出中,您會看到欄位 spec.serviceAccountName
。如果您在建立 Pod 時未指定,Kubernetes 會自動設定該值。
在 Pod 內部執行的應用程式可以使用自動掛載的服務帳戶憑證來存取 Kubernetes API。請參閱存取叢集以瞭解更多資訊。
當 Pod 以 ServiceAccount 身分驗證時,其存取層級取決於使用中的授權外掛程式與原則。
當 Pod 被刪除時,即使最終程式碼已就位,API 憑證也會自動撤銷。特別是,API 憑證會在 Pod 上設定的 .metadata.deletionTimestamp
之後 60 秒撤銷(刪除時間戳記通常是刪除請求被接受的時間加上 Pod 的終止寬限期)。
選擇不使用 API 憑證自動掛載
如果您不希望 kubelet 自動掛載 ServiceAccount 的 API 憑證,您可以選擇不使用預設行為。您可以透過在 ServiceAccount 上設定 automountServiceAccountToken: false
,來選擇不自動掛載 /var/run/secrets/kubernetes.io/serviceaccount/token
上服務帳戶的 API 憑證
例如
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-robot
automountServiceAccountToken: false
...
您也可以選擇不自動掛載特定 Pod 的 API 憑證
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
serviceAccountName: build-robot
automountServiceAccountToken: false
...
如果 ServiceAccount 和 Pod 的 .spec
都為 automountServiceAccountToken
指定了值,則 Pod 規格優先。
使用多個 ServiceAccount
每個命名空間至少都有一個 ServiceAccount:名為 default
的預設 ServiceAccount 資源。您可以使用以下指令,列出目前命名空間中的所有 ServiceAccount 資源:
kubectl get serviceaccounts
輸出結果會類似於這樣:
NAME SECRETS AGE
default 1 1d
您可以像這樣建立額外的 ServiceAccount 物件:
kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-robot
EOF
ServiceAccount 物件的名稱必須是有效的 DNS 子網域名稱。
如果您取得 Service Account 物件的完整傾印,會像這樣:
kubectl get serviceaccounts/build-robot -o yaml
輸出結果會類似於這樣:
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2019-06-16T00:12:34Z
name: build-robot
namespace: default
resourceVersion: "272500"
uid: 721ab723-13bc-11e5-aec2-42010af0021e
您可以使用授權外掛程式來設定 Service Account 的權限。
若要使用非預設的 Service Account,請將 Pod 的 spec.serviceAccountName
欄位設定為您想要使用的 ServiceAccount 名稱。
您只能在建立 Pod 時,或是在新 Pod 的範本中設定 serviceAccountName
欄位。您無法更新已存在 Pod 的 .spec.serviceAccountName
欄位。
注意
.spec.serviceAccount
欄位是 .spec.serviceAccountName
的已棄用別名。如果您想要從 workload 資源中移除這些欄位,請在 Pod 範本上將這兩個欄位都明確設定為空值。清除
如果您嘗試從上面的範例中建立 build-robot
ServiceAccount,您可以使用以下指令來清除它:
kubectl delete serviceaccount/build-robot
為 ServiceAccount 手動建立 API 權杖
假設您有一個名為 "build-robot" 的現有 Service Account,如先前所述。
您可以使用 kubectl
為該 ServiceAccount 取得有時間限制的 API 權杖
kubectl create token build-robot
該指令的輸出是一個權杖,您可以使用該權杖以該 ServiceAccount 的身分進行驗證。您可以使用 kubectl create token
的 --duration
命令列引數請求特定的權杖持續時間(發出的權杖的實際持續時間可能會更短,甚至可能更長)。
Kubernetes v1.31 [beta]
(預設啟用:true)使用 kubectl
v1.31 或更高版本,可以建立直接繫結到節點 (Node) 的 Service Account 權杖
kubectl create token build-robot --bound-object-kind Node --bound-object-name node-001 --bound-object-uid 123...456
權杖將在到期或關聯的節點或 Service Account 被刪除之前有效。
注意
Kubernetes v1.22 之前的版本會自動為存取 Kubernetes API 建立長期憑證。這種較舊的機制是基於建立權杖 Secret,然後可以掛載到正在執行的 Pod 中。在更新的版本中,包括 Kubernetes v1.32,API 憑證是直接使用 TokenRequest API 取得的,並使用 投影卷掛載到 Pod 中。使用此方法取得的權杖具有限定的生命週期,並且在掛載它們的 Pod 被刪除時會自動失效。
您仍然可以手動建立 Service Account 權杖 Secret;例如,如果您需要一個永不過期的權杖。但是,建議改為使用 TokenRequest 子資源來取得存取 API 的權杖。
為 ServiceAccount 手動建立長期有效的 API 權杖
如果您想要取得 ServiceAccount 的 API 權杖,您可以建立一個新的 Secret,並帶有一個特殊的註解 kubernetes.io/service-account.name
。
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: build-robot-secret
annotations:
kubernetes.io/service-account.name: build-robot
type: kubernetes.io/service-account-token
EOF
如果您使用以下指令檢視 Secret:
kubectl get secret/build-robot-secret -o yaml
您可以看到 Secret 現在包含 "build-robot" ServiceAccount 的 API 權杖。
由於您設定的註解,控制平面會自動為該 ServiceAccount 產生權杖,並將它們儲存到關聯的 Secret 中。控制平面也會清除已刪除 ServiceAccount 的權杖。
kubectl describe secrets/build-robot-secret
輸出結果會類似於這樣:
Name: build-robot-secret
Namespace: default
Labels: <none>
Annotations: kubernetes.io/service-account.name: build-robot
kubernetes.io/service-account.uid: da68f9c6-9d26-11e7-b84e-002dc52800da
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1338 bytes
namespace: 7 bytes
token: ...
注意
此處省略了 token
的內容。
請注意不要在您的終端機/電腦螢幕可能被旁觀者看到的地方顯示 kubernetes.io/service-account-token
Secret 的內容。
當您刪除具有關聯 Secret 的 ServiceAccount 時,Kubernetes 控制平面會自動從該 Secret 中清除長期有效的權杖。
注意
如果您使用以下指令檢視 ServiceAccount:
kubectl get serviceaccount build-robot -o yaml
您無法在 ServiceAccount API 物件的 .secrets
欄位中看到 build-robot-secret
Secret,因為該欄位僅在使用自動產生的 Secret 時才會填入。
將 ImagePullSecrets 新增至 Service Account
首先,建立 imagePullSecret。接下來,驗證它是否已建立。例如:
建立 imagePullSecret,如 在 Pod 上指定 ImagePullSecrets 中所述。
kubectl create secret docker-registry myregistrykey --docker-server=<registry name> \ --docker-username=DUMMY_USERNAME --docker-password=DUMMY_DOCKER_PASSWORD \ --docker-email=DUMMY_DOCKER_EMAIL
驗證它是否已建立。
kubectl get secrets myregistrykey
輸出結果會類似於這樣:
NAME TYPE DATA AGE myregistrykey kubernetes.io/.dockerconfigjson 1 1d
將 image pull secret 新增至 Service Account
接下來,修改命名空間的預設 Service Account,以使用此 Secret 作為 imagePullSecret。
kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "myregistrykey"}]}'
您可以透過手動編輯物件來達到相同的結果:
kubectl edit serviceaccount/default
sa.yaml
檔案的輸出結果會類似於這樣:
您選取的文字編輯器將會開啟一個類似於以下的組態:
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2021-07-07T22:02:39Z
name: default
namespace: default
resourceVersion: "243024"
uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
使用您的編輯器,刪除包含金鑰 resourceVersion
的行,新增 imagePullSecrets:
的行並儲存它。保持 uid
值與您找到的值相同。
在您進行這些變更後,編輯後的 ServiceAccount 看起來會像這樣:
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2021-07-07T22:02:39Z
name: default
namespace: default
uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
imagePullSecrets:
- name: myregistrykey
驗證是否為新的 Pod 設定了 imagePullSecrets
現在,當在目前的命名空間中建立新的 Pod 並使用預設 ServiceAccount 時,新的 Pod 會自動設定其 spec.imagePullSecrets
欄位
kubectl run nginx --image=<registry name>/nginx --restart=Never
kubectl get pod nginx -o=jsonpath='{.spec.imagePullSecrets[0].name}{"\n"}'
輸出結果為:
myregistrykey
ServiceAccount 權杖卷投影
Kubernetes v1.20 [stable]
注意
若要啟用和使用權杖請求投影,您必須為 kube-apiserver
指定以下每個命令列引數:
--service-account-issuer
- 定義 Service Account 權杖簽發者的識別符。您可以多次指定
--service-account-issuer
引數,這對於啟用簽發者的非破壞性變更可能很有用。當多次指定此標誌時,第一個用於產生權杖,所有標誌都用於確定哪些簽發者被接受。您必須執行 Kubernetes v1.22 或更高版本才能夠多次指定--service-account-issuer
。 --service-account-key-file
- 指定包含 PEM 編碼的 X.509 私鑰或公鑰(RSA 或 ECDSA)的檔案路徑,用於驗證 ServiceAccount 權杖。指定的檔案可以包含多個金鑰,並且可以多次指定該標誌,使用不同的檔案。如果多次指定,則 Kubernetes API 伺服器會將任何指定金鑰簽署的權杖視為有效。
--service-account-signing-key-file
- 指定包含 Service Account 權杖簽發者目前私鑰的檔案路徑。簽發者使用此私鑰簽署發出的 ID 權杖。
--api-audiences
(可以省略)- 定義 ServiceAccount 權杖的對象 (audiences)。Service Account 權杖驗證器驗證針對 API 使用的權杖是否繫結到至少其中一個對象。如果多次指定
api-audiences
,則 Kubernetes API 伺服器會將任何指定對象的權杖視為有效。如果您指定--service-account-issuer
命令列引數,但未設定--api-audiences
,則控制平面預設為包含僅簽發者 URL 的單一元素對象清單。
kubelet 也可以將 ServiceAccount 權杖投影到 Pod 中。您可以指定權杖的所需屬性,例如對象和有效期限。這些屬性在預設 ServiceAccount 權杖上是不可設定的。當 Pod 或 ServiceAccount 被刪除時,權杖也會對 API 失效。
您可以使用名為 ServiceAccountToken
的 投影卷類型,為 Pod 的 spec
設定此行為。
來自此投影卷的權杖是 JSON Web 權杖 (JWT)。此權杖的 JSON 酬載遵循明確定義的結構描述 - Pod 繫結權杖的範例酬載:
{
"aud": [ # matches the requested audiences, or the API server's default audiences when none are explicitly requested
"https://kubernetes.default.svc"
],
"exp": 1731613413,
"iat": 1700077413,
"iss": "https://kubernetes.default.svc", # matches the first value passed to the --service-account-issuer flag
"jti": "ea28ed49-2e11-4280-9ec5-bc3d1d84661a",
"kubernetes.io": {
"namespace": "kube-system",
"node": {
"name": "127.0.0.1",
"uid": "58456cb0-dd00-45ed-b797-5578fdceaced"
},
"pod": {
"name": "coredns-69cbfb9798-jv9gn",
"uid": "778a530c-b3f4-47c0-9cd5-ab018fb64f33"
},
"serviceaccount": {
"name": "coredns",
"uid": "a087d5a0-e1dd-43ec-93ac-f13d89cd13af"
},
"warnafter": 1700081020
},
"nbf": 1700077413,
"sub": "system:serviceaccount:kube-system:coredns"
}
啟動使用 Service Account 權杖投影的 Pod
若要為 Pod 提供對象為 vault
且有效期限為兩小時的權杖,您可以定義類似於以下的 Pod 清單:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- mountPath: /var/run/secrets/tokens
name: vault-token
serviceAccountName: build-robot
volumes:
- name: vault-token
projected:
sources:
- serviceAccountToken:
path: vault-token
expirationSeconds: 7200
audience: vault
建立 Pod
kubectl create -f https://k8s.io/examples/pods/pod-projected-svc-token.yaml
kubelet 將:代表 Pod 請求和儲存權杖;在可設定的檔案路徑上使權杖可供 Pod 使用;並在權杖接近到期時重新整理權杖。如果權杖的存活時間 (TTL) 已超過總時間的 80%,或者權杖已超過 24 小時,則 kubelet 會主動請求輪換權杖。
應用程式負責在權杖輪換時重新載入權杖。應用程式通常只需按排程載入權杖(例如:每 5 分鐘一次),而無需追蹤實際的到期時間,就已足夠。
Service Account 簽發者探索
Kubernetes v1.21 [stable]
如果您已為叢集中的 ServiceAccount 啟用權杖投影,那麼您也可以使用探索功能。Kubernetes 提供了一種讓用戶端可以作為身分提供者聯合的方式,以便一個或多個外部系統可以充當依賴方。
注意
簽發者 URL 必須符合 OIDC 探索規範。實際上,這表示它必須使用 https
協定,並且應該在 {service-account-issuer}/.well-known/openid-configuration
提供 OpenID 提供者組態。
如果 URL 不符合規範,則不會註冊或存取 ServiceAccount 簽發者探索端點。
啟用後,Kubernetes API 伺服器會透過 HTTP 發布 OpenID 提供者組態文件。組態文件發布在 /.well-known/openid-configuration
。OpenID 提供者組態有時被稱為探索文件。Kubernetes API 伺服器也會透過 HTTP 在 /openid/v1/jwks
發布相關的 JSON Web 金鑰集 (JWKS)。
注意
在/.well-known/openid-configuration
和 /openid/v1/jwks
提供的回應旨在與 OIDC 相容,但並非嚴格符合 OIDC 標準。這些文件僅包含執行 Kubernetes Service Account 權杖驗證所需的參數。使用 RBAC 的叢集包含名為 system:service-account-issuer-discovery
的預設 ClusterRole。預設的 ClusterRoleBinding 會將此角色指派給 system:serviceaccounts
群組,所有 ServiceAccount 都隱含地屬於該群組。這允許在叢集上執行的 Pod 透過它們掛載的 Service Account 權杖存取 Service Account 探索文件。管理員還可以選擇將角色繫結到 system:authenticated
或 system:unauthenticated
,具體取決於其安全性需求以及他們打算與哪些外部系統聯合。
JWKS 回應包含依賴方可以用於驗證 Kubernetes Service Account 權杖的公鑰。依賴方首先查詢 OpenID 提供者組態,並使用回應中的 jwks_uri
欄位來尋找 JWKS。
在許多情況下,Kubernetes API 伺服器在公共網際網路上不可用,但使用者或服務提供者可以提供從 API 伺服器提供快取回應的公共端點。在這些情況下,可以覆寫 OpenID 提供者組態中的 jwks_uri
,使其指向公共端點,而不是 API 伺服器的位址,方法是將 --service-account-jwks-uri
標誌傳遞給 API 伺服器。與簽發者 URL 一樣,JWKS URI 也必須使用 https
協定。
下一步
另請參閱
- 閱讀 Service Account 的叢集管理員指南
- 閱讀關於 Kubernetes 中的授權
- 閱讀關於 Secret
- 或學習如何安全地使用 Secret 分發憑證
- 但也要記住,使用 Secret 進行 ServiceAccount 驗證已被棄用。建議的替代方案是 ServiceAccount 權杖卷投影。
- 閱讀關於 投影卷。
- 如需 OIDC 探索的背景資訊,請閱讀 ServiceAccount 簽署金鑰檢索 Kubernetes 增強提案
- 閱讀 OIDC 探索規範