從 Pod 訪問 Kubernetes API
本指南演示瞭如何從 Pod 內部訪問 Kubernetes API。
準備工作
你需要有一個 Kubernetes 叢集,並且 kubectl 命令列工具已配置為與你的叢集通訊。 建議在至少有兩個不作為控制平面主機的節點叢集上執行本教程。 如果你還沒有叢集,可以使用 minikube 建立一個叢集,或者使用這些 Kubernetes 演練場之一
從 Pod 內部訪問 API
從 Pod 內部訪問 API 時,API 伺服器的定位和身份認證與外部客戶端略有不同。
從 Pod 內部使用 Kubernetes API 最簡單的方法是使用官方的客戶端庫之一。這些庫可以自動發現 API 伺服器並進行身份認證。
使用官方客戶端庫
在 Pod 內部,連線 Kubernetes API 的推薦方式是:
對於 Go 客戶端,使用官方的 Go 客戶端庫。
rest.InClusterConfig()
函式會自動處理 API 主機發現和身份認證。請參閱此處示例。對於 Python 客戶端,使用官方的 Python 客戶端庫。
config.load_incluster_config()
函式會自動處理 API 主機發現和身份認證。請參閱此處示例。還有許多其他可用的庫,請參閱客戶端庫頁面。
在每種情況下,Pod 的服務帳戶憑據都用於與 API 伺服器進行安全通訊。
直接訪問 REST API
在 Pod 中執行時,容器可以透過獲取 `KUBERNETES_SERVICE_HOST` 和 `KUBERNETES_SERVICE_PORT_HTTPS` 環境變數來為 Kubernetes API 伺服器建立 HTTPS URL。API 伺服器的叢集內地址也釋出到 `default` 名稱空間中名為 `kubernetes` 的 Service,以便 Pod 可以將 `kubernetes.default.svc` 作為本地 API 伺服器的 DNS 名稱引用。
注意
Kubernetes 不保證 API 伺服器對於主機名 `kubernetes.default.svc` 擁有有效證書;然而,控制平面**預期**為 `$KUBERNETES_SERVICE_HOST` 所代表的主機名或 IP 地址提供有效證書。與 API 伺服器通訊時,推薦使用服務賬號憑據。 預設情況下,Pod 會關聯一個服務賬號,該服務賬號的憑據(令牌)會被放置到 Pod 中每個容器的檔案系統樹中,路徑為 /var/run/secrets/kubernetes.io/serviceaccount/token
。
如果可用,證書包將放置在每個容器的檔案系統樹中,路徑為 `/var/run/secrets/kubernetes.io/serviceaccount/ca.crt`,應用於驗證 API 伺服器的伺服器證書。
最後,用於名稱空間 API 操作的預設名稱空間位於每個容器中檔案 /var/run/secrets/kubernetes.io/serviceaccount/namespace
。
使用 kubectl proxy
如果你想在沒有官方客戶端庫的情況下查詢 API,可以在 Pod 中執行 `kubectl proxy` 作為新sidecar 容器的命令。 這樣,`kubectl proxy` 將向 API 進行身份認證,並將其暴露在 Pod 的 `localhost` 介面上,以便 Pod 中的其他容器可以直接使用它。
不使用代理
可以透過將身份驗證令牌直接傳遞給 API 伺服器來避免使用 kubectl 代理。 內部證書可確保連線安全。
# Point to the internal API server hostname
APISERVER=https://kubernetes.default.svc
# Path to ServiceAccount token
SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount
# Read this Pod's namespace
NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace)
# Read the ServiceAccount bearer token
TOKEN=$(cat ${SERVICEACCOUNT}/token)
# Reference the internal certificate authority (CA)
CACERT=${SERVICEACCOUNT}/ca.crt
# Explore the API with TOKEN
curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET ${APISERVER}/api
輸出將類似於此
{
"kind": "APIVersions",
"versions": ["v1"],
"serverAddressByClientCIDRs": [
{
"clientCIDR": "0.0.0.0/0",
"serverAddress": "10.0.1.149:443"
}
]
}