如何正确设置--kubelet-certificate-authority apiserver参数?
How Do I Properly Set --kubelet-certificate-authority apiserver parameter?
我正在使用 KubeSpray 在 AWS 上配置一个双节点集群。默认情况下,不使用 --kubelet-certificate-authority
参数。但是,我想设置它。
我不知道 --kubelet-certificate-authority
的正确设置。当我将其设置为 /etc/kubernetes/pki/ca.crt
时,我在日志中看到如下消息:
TLS handshake error from 10.245.207.223:59278: remote error: tls: unknown certificate authority
为了创建一个隔离的测试环境,我通过 SSH 连接到我的控制器节点 运行 这个命令 运行s api 服务器在非标准端口4667
。我直接从 /etc/kubernetes/manifests/kube-apiserver.yaml
复制了这些值。您需要调整该值以匹配您自己的集群。我特意 运行 以交互模式连接容器,以便我可以看到日志消息。
sudo docker run \
--name api-server-playground \
-it \
--rm \
--network host \
--volume /etc/kubernetes:/etc/kubernetes:ro \
--volume /etc/pki:/etc/pki:ro \
--volume /etc/ssl:/etc/ssl/:ro \
k8s.gcr.io/kube-apiserver:v1.18.9 \
kube-apiserver \
--advertise-address=10.245.207.223 \
--allow-privileged=true \
--anonymous-auth=True \
--apiserver-count=1 \
--authorization-mode=Node,RBAC \
--bind-address=0.0.0.0 \
--client-ca-file=/etc/kubernetes/ssl/ca.crt \
--cloud-config=/etc/kubernetes/cloud_config \
--cloud-provider=aws \
--enable-admission-plugins=NodeRestriction \
--enable-aggregator-routing=False \
--enable-bootstrap-token-auth=true \
--endpoint-reconciler-type=lease \
--etcd-cafile=/etc/ssl/etcd/ssl/ca.pem \
--etcd-certfile=/etc/ssl/etcd/ssl/node-ip-10-245-207-223.ec2.internal.pem \
--etcd-keyfile=/etc/ssl/etcd/ssl/node-ip-10-245-207-223.ec2.internal-key.pem \
--etcd-servers=https://10.245.207.119:2379 \
--event-ttl=1h0m0s \
--insecure-port=0 \
--kubelet-client-certificate=/etc/kubernetes/ssl/apiserver-kubelet-client.crt \
--kubelet-client-key=/etc/kubernetes/ssl/apiserver-kubelet-client.key \
--kubelet-preferred-address-types=InternalDNS,InternalIP,Hostname,ExternalDNS,ExternalIP \
--profiling=False \
--proxy-client-cert-file=/etc/kubernetes/ssl/front-proxy-client.crt \
--proxy-client-key-file=/etc/kubernetes/ssl/front-proxy-client.key \
--request-timeout=1m0s \
--requestheader-allowed-names=front-proxy-client \
--requestheader-client-ca-file=/etc/kubernetes/ssl/front-proxy-ca.crt \
--requestheader-extra-headers-prefix=X-Remote-Extra- \
--requestheader-group-headers=X-Remote-Group \
--requestheader-username-headers=X-Remote-User \
--secure-port=6447 \
--service-account-key-file=/etc/kubernetes/ssl/sa.pub \
--service-cluster-ip-range=10.233.0.0/18 \
--service-node-port-range=30000-32767 \
--storage-backend=etcd3 \
--tls-cert-file=/etc/kubernetes/ssl/apiserver.crt \
--tls-private-key-file=/etc/kubernetes/ssl/apiserver.key
现在可以再次通过 SSH 连接到控制器并使用 curl
与自定义 api 服务器容器进行交互。
- 将 APISERVER 变量设置为指向控制器节点。我使用上面
advertise-address
参数的值。
APISERVER=https://10.245.207.223:6447
- 获得令牌。
TOKEN=$(kubectl get secrets -o jsonpath="{.items[?(@.metadata.annotations['kubernetes\.io/service-account\.name']=='default')].data.token}"|base64 --decode); echo "TOKEN=$TOKEN"
- 发出 api 请求。此请求将失败,因为“无法识别对等证书颁发者”。
curl --header "Authorization: Bearer $TOKEN" -X GET $APISERVER/api
一条错误消息将出现在 docker 日志中。它看起来像这样:
I0921 14:39:07.662368 1 log.go:172] http: TLS handshake error
from 10.245.207.223:59278: remote error: tls: unknown certificate authority
- 现在使用
-k
curl参数绕过识别问题。
curl -k --header "Authorization: Bearer $TOKEN" -X GET $APISERVER/api
{
"kind": "APIVersions",
"versions": [
"v1"
],
"serverAddressByClientCIDRs": [
{
"clientCIDR": "0.0.0.0/0",
"serverAddress": "10.245.207.223:6447"
}
]
}
您会看到请求正常工作。但是,我不想使用 -k
参数。所以我尝试使用来自 api 服务器的证书颁发机构。
- 从 api 服务器获取证书颁发机构。
echo | \
openssl s_client -connect $APISERVER 2>/dev/null | \
openssl x509 -text | \
sed -n "/BEGIN CERTIFICATE/,/END CERTIFICATE/p" \
> apiserver.ca.crt
- 为 api 请求使用证书颁发机构文件。
curl --cacert apiserver.ca.crt --header "Authorization: Bearer $TOKEN" -X GET $APISERVER/api
更新
根据 Wiktor 的回复提示的想法,我添加了 /etc/kubernetes/ssl/ca.crt 作为证书颁发机构。并在我的 curl
命令中使用了该文件。
curl --cacert /etc/kubernetes/ssl/ca.crt --header "Authorization: Bearer $TOKEN" -X GET $APISERVER/api
这有效。
为了使 --kubelet-certificate-authority
标志起作用,您首先需要确保您获得了 Kubelet authentication and Kubelet authorization enabled. After that you can follow the Kubernetes documentation and setup the TLS connection between the apiserver and kubelet。最后,您可以在主节点上编辑 API 服务器 pod 规范文件 /etc/kubernetes/manifests/kube-apiserver.yaml
并将 --kubelet-certificate-authority
参数设置为证书颁发机构的证书文件的路径。
因此,总结要执行的步骤是:
使用 --anonymous-auth=false
标志启动 kubelet
使用 --client-ca-file
标志启动 kubelet,提供 CA 包以使用
验证客户端证书
使用 --kubelet-client-certificate
和 --kubelet-client-key
标志启动 apiserver
确保 authentication.k8s.io/v1beta1
API 组在 API 服务器中启用
使用 --authentication-token-webhook
和 --kubeconfig flags
启动 kubelet
kubelet 在配置的 API 服务器上调用 TokenReview
API 来确定来自承载令牌的用户信息
确保 authorization.k8s.io/v1beta1
API 组在 API 服务器中启用
使用 --authorization-mode=Webhook
和 --kubeconfig
标志启动 kubelet
kubelet在配置的API服务器上调用SubjectAccessReview
API判断每个请求是否被授权
- 使用
--kubelet-certificate-authority
标志为 apiserver 提供根证书包以用于验证 kubelet 的服务证书。
可以在链接的文档中找到更多详细信息。
我正在使用 KubeSpray 在 AWS 上配置一个双节点集群。默认情况下,不使用 --kubelet-certificate-authority
参数。但是,我想设置它。
我不知道 --kubelet-certificate-authority
的正确设置。当我将其设置为 /etc/kubernetes/pki/ca.crt
时,我在日志中看到如下消息:
TLS handshake error from 10.245.207.223:59278: remote error: tls: unknown certificate authority
为了创建一个隔离的测试环境,我通过 SSH 连接到我的控制器节点 运行 这个命令 运行s api 服务器在非标准端口4667
。我直接从 /etc/kubernetes/manifests/kube-apiserver.yaml
复制了这些值。您需要调整该值以匹配您自己的集群。我特意 运行 以交互模式连接容器,以便我可以看到日志消息。
sudo docker run \
--name api-server-playground \
-it \
--rm \
--network host \
--volume /etc/kubernetes:/etc/kubernetes:ro \
--volume /etc/pki:/etc/pki:ro \
--volume /etc/ssl:/etc/ssl/:ro \
k8s.gcr.io/kube-apiserver:v1.18.9 \
kube-apiserver \
--advertise-address=10.245.207.223 \
--allow-privileged=true \
--anonymous-auth=True \
--apiserver-count=1 \
--authorization-mode=Node,RBAC \
--bind-address=0.0.0.0 \
--client-ca-file=/etc/kubernetes/ssl/ca.crt \
--cloud-config=/etc/kubernetes/cloud_config \
--cloud-provider=aws \
--enable-admission-plugins=NodeRestriction \
--enable-aggregator-routing=False \
--enable-bootstrap-token-auth=true \
--endpoint-reconciler-type=lease \
--etcd-cafile=/etc/ssl/etcd/ssl/ca.pem \
--etcd-certfile=/etc/ssl/etcd/ssl/node-ip-10-245-207-223.ec2.internal.pem \
--etcd-keyfile=/etc/ssl/etcd/ssl/node-ip-10-245-207-223.ec2.internal-key.pem \
--etcd-servers=https://10.245.207.119:2379 \
--event-ttl=1h0m0s \
--insecure-port=0 \
--kubelet-client-certificate=/etc/kubernetes/ssl/apiserver-kubelet-client.crt \
--kubelet-client-key=/etc/kubernetes/ssl/apiserver-kubelet-client.key \
--kubelet-preferred-address-types=InternalDNS,InternalIP,Hostname,ExternalDNS,ExternalIP \
--profiling=False \
--proxy-client-cert-file=/etc/kubernetes/ssl/front-proxy-client.crt \
--proxy-client-key-file=/etc/kubernetes/ssl/front-proxy-client.key \
--request-timeout=1m0s \
--requestheader-allowed-names=front-proxy-client \
--requestheader-client-ca-file=/etc/kubernetes/ssl/front-proxy-ca.crt \
--requestheader-extra-headers-prefix=X-Remote-Extra- \
--requestheader-group-headers=X-Remote-Group \
--requestheader-username-headers=X-Remote-User \
--secure-port=6447 \
--service-account-key-file=/etc/kubernetes/ssl/sa.pub \
--service-cluster-ip-range=10.233.0.0/18 \
--service-node-port-range=30000-32767 \
--storage-backend=etcd3 \
--tls-cert-file=/etc/kubernetes/ssl/apiserver.crt \
--tls-private-key-file=/etc/kubernetes/ssl/apiserver.key
现在可以再次通过 SSH 连接到控制器并使用 curl
与自定义 api 服务器容器进行交互。
- 将 APISERVER 变量设置为指向控制器节点。我使用上面
advertise-address
参数的值。
APISERVER=https://10.245.207.223:6447
- 获得令牌。
TOKEN=$(kubectl get secrets -o jsonpath="{.items[?(@.metadata.annotations['kubernetes\.io/service-account\.name']=='default')].data.token}"|base64 --decode); echo "TOKEN=$TOKEN"
- 发出 api 请求。此请求将失败,因为“无法识别对等证书颁发者”。
curl --header "Authorization: Bearer $TOKEN" -X GET $APISERVER/api
一条错误消息将出现在 docker 日志中。它看起来像这样:
I0921 14:39:07.662368 1 log.go:172] http: TLS handshake error
from 10.245.207.223:59278: remote error: tls: unknown certificate authority
- 现在使用
-k
curl参数绕过识别问题。
curl -k --header "Authorization: Bearer $TOKEN" -X GET $APISERVER/api
{
"kind": "APIVersions",
"versions": [
"v1"
],
"serverAddressByClientCIDRs": [
{
"clientCIDR": "0.0.0.0/0",
"serverAddress": "10.245.207.223:6447"
}
]
}
您会看到请求正常工作。但是,我不想使用 -k
参数。所以我尝试使用来自 api 服务器的证书颁发机构。
- 从 api 服务器获取证书颁发机构。
echo | \
openssl s_client -connect $APISERVER 2>/dev/null | \
openssl x509 -text | \
sed -n "/BEGIN CERTIFICATE/,/END CERTIFICATE/p" \
> apiserver.ca.crt
- 为 api 请求使用证书颁发机构文件。
curl --cacert apiserver.ca.crt --header "Authorization: Bearer $TOKEN" -X GET $APISERVER/api
更新
根据 Wiktor 的回复提示的想法,我添加了 /etc/kubernetes/ssl/ca.crt 作为证书颁发机构。并在我的 curl
命令中使用了该文件。
curl --cacert /etc/kubernetes/ssl/ca.crt --header "Authorization: Bearer $TOKEN" -X GET $APISERVER/api
这有效。
为了使 --kubelet-certificate-authority
标志起作用,您首先需要确保您获得了 Kubelet authentication and Kubelet authorization enabled. After that you can follow the Kubernetes documentation and setup the TLS connection between the apiserver and kubelet。最后,您可以在主节点上编辑 API 服务器 pod 规范文件 /etc/kubernetes/manifests/kube-apiserver.yaml
并将 --kubelet-certificate-authority
参数设置为证书颁发机构的证书文件的路径。
因此,总结要执行的步骤是:
使用
--anonymous-auth=false
标志启动 kubelet使用
验证客户端证书--client-ca-file
标志启动 kubelet,提供 CA 包以使用使用
--kubelet-client-certificate
和--kubelet-client-key
标志启动 apiserver确保
authentication.k8s.io/v1beta1
API 组在 API 服务器中启用使用
启动 kubelet--authentication-token-webhook
和--kubeconfig flags
kubelet 在配置的 API 服务器上调用
TokenReview
API 来确定来自承载令牌的用户信息
确保
authorization.k8s.io/v1beta1
API 组在 API 服务器中启用使用
--authorization-mode=Webhook
和--kubeconfig
标志启动 kubeletkubelet在配置的API服务器上调用
SubjectAccessReview
API判断每个请求是否被授权
- 使用
--kubelet-certificate-authority
标志为 apiserver 提供根证书包以用于验证 kubelet 的服务证书。
可以在链接的文档中找到更多详细信息。