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

js8*_*s80 5 kubernetes k3s

我在服务器上设置了 K3s:

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

然后,我从中获取 kube 配置/etc/rancher/k3s/k3s.yaml并将其复制到本地计算机,这样我就可以从我的计算机而不是安装 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 -
Run Code Online (Sandbox Code Playgroud)

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

我的~/.kube/config

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

我还在我的 kube 配置中获取了客户端证书和密钥,将其导出到一个文件,并使用curl访问API服务器,当我直接访问服务器节点时它会起作用,但当我通过代理/负载均衡器时则不起​​作用。

我想要做的不是使用客户端证书方法而是使用token身份验证,因为我的代理不会干扰这一点。但是,我不确定如何获得这样的令牌。我阅读了Kubernetes 身份验证指南,特别尝试创建一个新的服务帐户并获取与其关联的令牌,如服务帐户令牌部分中所述,但这也不起作用。我还深入研究了K3s 服务器配置选项,看看是否有提及静态令牌文件等,但没有找到任何可能的内容。

这是 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"}
Run Code Online (Sandbox Code Playgroud)

js8*_*s80 7

通过更详细地阅读Kubernetes 身份验证指南,我找到了一种适合我的方法。我选择了服务帐户令牌方法,如下所示:

\n
\n

通常,这些机密会挂载到 Pod 中,以便在集群内访问 API 服务器,但也可以从集群外部使用。

\n
\n

我的用途是在集群外部。

\n

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

\n
kubectl create serviceaccount cluster-admin\n
Run Code Online (Sandbox Code Playgroud)\n

然后,我创建了一个ClusterRoleBinding将集群范围的权限分配给我的 ServiceAccount(我命名它是cluster-admin-manual因为 K3s 已经创建了一个cluster-admin我不想搞乱的名称):

\n
kubectl create clusterrolebinding cluster-admin-manual --clusterrole=cluster-admin --serviceaccount=default:cluster-admin\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
kubectl get serviceaccount cluster-admin -o yaml\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
kubectl create serviceaccount cluster-admin\n
Run Code Online (Sandbox Code Playgroud)\n

通过以下方式获取秘密内容:

\n
kubectl get secret cluster-admin-token-67jtw -o yaml\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
echo {base64-encoded-token} | base64 --decode\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
kubectl config set-credentials my-cluster-admin --token={token}\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
kubectl create clusterrolebinding cluster-admin-manual --clusterrole=cluster-admin --serviceaccount=default:cluster-admin\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
kubectl get serviceaccount cluster-admin -o yaml\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

我发现有用的其他资源:

\n\n