K3s kubeconfig 使用令牌而不是客户端证书进行身份验证

K3s kubeconfig authenticate with token instead of client cert

我在服务器上设置了 K3s:

curl -sfL https://get.k3s.io | K3S_TOKEN={token} INSTALL_K3S_EXEC="server --cluster-init --disable=traefik --write-kubeconfig-mode 644" sh -s -

然后我从 /etc/rancher/k3s/k3s.yaml 抓取了 kube 配置并将其复制到我的本地机器,这样我就可以从我的机器而不是我安装 K3s 的服务器节点与集群交互。我不得不换掉对 127.0.0.1 的引用,并将其更改为我安装 K3s 的服务器的实际主机名,但除此之外它还有效。

然后我将另外 2 个服务器节点连接到集群以使用以下方法进行高可用性设置:

curl -sfL https://get.k3s.io | K3S_TOKEN={token} INSTALL_K3S_EXEC="server --server {https://{hostname or IP of server 1}:6443 --disable=traefik --write-kubeconfig-mode 644" sh -s -

现在我再次在我的本地机器上我 运行 kubectl get pods (例如)并且它有效但我想要一个高可用性设置所以我在前面放置了一个 TCP 负载平衡器(实际上是 NGINX)我的集群。现在我正在尝试通过该代理/负载均衡器连接到 Kubernetes API,不幸的是,由于我的 ~/.kube/config 有一个用于身份验证的客户端证书,这不再有效,因为我的负载均衡器/代理位于该服务器的前端无法将我的客户端证书传递到 K3s 服务器。

我的~/.kube/config:

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: {omitted}
    server: https://my-cluster-hostname:6443
  name: default
contexts:
- context:
    cluster: default
    user: default
  name: default
current-context: default
kind: Config
preferences: {}
users:
- name: default
  user:
    client-certificate-data: {omitted}
    client-key-data: {omitted}

我还在我的 kube 配置中获取了客户端证书和密钥,将其导出到一个文件中,然后使用 curl 访问 API 服务器,当我直接访问服务器节点时它可以工作,但当我去的时候没有通过我的代理/负载平衡器。

我想做的不是使用客户端证书方法,而是使用 token 身份验证,因为我的代理不会干扰它。但是,我不确定如何获得这样的令牌。我阅读了 Kubernetes Authenticating guide and specifically I tried creating a new service account and getting the token associated with it as described in the Service Account Tokens section but that also did not work. I also dug through K3s server config options 以查看是否提及静态令牌文件等,但没有找到任何可能的内容。

这是 K3s 的一些限制还是我只是做错了什么(可能)?

我的kubectl version输出:

Client Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.7", GitCommit:"132a687512d7fb058d0f5890f07d4121b3f0a2e2", GitTreeState:"clean", BuildDate:"2021-05-12T12:40:09Z", GoVersion:"go1.15.12", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.7+k3s1", GitCommit:"ac70570999c566ac3507d2cc17369bb0629c1cc0", GitTreeState:"clean", BuildDate:"2021-11-29T16:40:13Z", GoVersion:"go1.16.10", Compiler:"gc", Platform:"linux/amd64"}

通过阅读 Kubernetes Authenticating Guide in more detail. I settled on the Service Account Tokens 方法,我找到了一种适合我的方法,因为它说:

Normally these secrets are mounted into pods for in-cluster access to the API server, but can be used from outside the cluster as well.

我用的是集群外。

首先,我创建了一个名为 cluster-admin 的新 ServiceAccount

kubectl create serviceaccount cluster-admin

然后我创建了一个 ClusterRoleBinding 来为我的 ServiceAccount 分配集群范围的权限(我将其命名为 cluster-admin-manual 因为 K3s 已经创建了一个我不想要的名为 cluster-admin 的权限搞砸):

kubectl create clusterrolebinding cluster-admin-manual --clusterrole=cluster-admin --serviceaccount=default:cluster-admin

现在您必须获取在您创建 ServiceAccount 时为您创建的 Secret:

kubectl get serviceaccount cluster-admin -o yaml

你会看到类似这样的返回:

apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: "2021-12-20T15:55:55Z"
  name: cluster-admin
  namespace: default
  resourceVersion: "3973955"
  uid: 66bab124-8d71-4e5f-9886-0bad0ebd30b2
secrets:
- name: cluster-admin-token-67jtw

获取 Secret 内容:

kubectl get secret cluster-admin-token-67jtw -o yaml

在该输出中,您将看到 data/token 属性。这是一个 base64 编码的 JWT 不记名令牌。解码:

echo {base64-encoded-token} | base64 --decode

现在您拥有了不记名令牌,您可以使用以下命令将用户添加到您的 ~/.kube/config。您还可以将该 JWT 粘贴到 jwt.io 中以查看属性并确保您的 base64 解码正确。

kubectl config set-credentials my-cluster-admin --token={token}

然后确保 ~/.kube/config 中现有的 context 已正确设置用户(我通过编辑我的 kube 配置文件手动完成此操作,但可能有一个 kubectl config 命令).例如:

- context:
    cluster: my-cluster
    user: my-cluster-admin
  name: my-cluster

我在 kube 配置中的用户如下所示:

- name: my-cluster-admin
  user:
    token: {token}

现在我可以使用令牌向集群进行身份验证,而不是依赖我的代理/负载平衡器不会干扰的传输层特定机制(TLS 与相互身份验证)。

我发现有帮助的其他资源: