从 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
的服务,以便 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,可以运行 kubectl proxy
作为 Pod 中新的边车容器的 命令。这样,kubectl proxy
将向 API 进行身份验证并将其公开在 Pod 的 localhost
接口上,以便 Pod 中的其他容器可以直接使用它。
不使用代理
可以通过将身份验证令牌直接传递给 API 服务器来避免使用 kubectl proxy。内部证书可确保连接安全。
# 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"
}
]
}