【问题标题】:How Do I Properly Set --kubelet-certificate-authority apiserver parameter?如何正确设置 --kubelet-certificate-authority apiserver 参数?
【发布时间】:2021-01-07 16:36:23
【问题描述】:

我正在使用 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 连接到我的控制器节点以运行此命令,该命令在4667 的非标准端口上运行 apiserver。我直接从/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 与自定义 apiserver 容器进行交互。

  • 将 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 参数。所以我尝试使用来自 apiserver 的证书颁发机构。

  • 从 apiserver 获取证书颁发机构。
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

这行得通。

【问题讨论】:

    标签: kubernetes kubernetes-apiserver kube-apiserver


    【解决方案1】:

    为了使--kubelet-certificate-authority 标志起作用,您首先需要确保启用了Kubelet authenticationKubelet authorization。之后,您可以按照 Kubernetes 文档设置TLS connection between the apiserver and kubelet。最后,您可以在主节点上编辑 API server pod 规范文件/etc/kubernetes/manifests/kube-apiserver.yaml,并将--kubelet-certificate-authority 参数设置为证书颁发机构的证书文件路径。

    所以,总结一下要做的步骤是:

    1. Kubelet authentication:
    • 使用 --anonymous-auth=false 标志启动 kubelet

    • 使用 --client-ca-file 标志启动 kubelet,提供 CA 包来验证客户端证书

    • 使用 --kubelet-client-certificate--kubelet-client-key 标志启动 apiserver

    • 确保在 API 服务器中启用了 authentication.k8s.io/v1beta1 API 组

    • 使用 --authentication-token-webhook--kubeconfig flags 启动 kubelet

    • kubelet 调用配置的 API 服务器上的TokenReview API 来从承载令牌中确定用户信息

    1. Kubelet authorization:
    • 确保在 API 服务器中启用了 authorization.k8s.io/v1beta1 API 组

    • 使用 --authorization-mode=Webhook--kubeconfig 标志启动 kubelet

    • kubelet 在配置的 API 服务器上调用SubjectAccessReview API 来判断每个请求是否被授权

    1. 使用 --kubelet-certificate-authority 标志为 apiserver 提供根证书包,用于验证 kubelet 的服务证书。

    可以在链接的文档中找到更多详细信息。

    【讨论】:

      猜你喜欢
      • 2018-05-24
      • 2018-12-04
      • 1970-01-01
      • 2019-06-01
      • 2022-01-25
      • 2020-06-16
      • 2019-10-02
      • 1970-01-01
      • 2021-01-09
      相关资源
      最近更新 更多