之前用rancher创建了几个rke集群,rancher提供的kubeconfig包含两个context,一个是通过rancher转发到apiserver的,一个是直连apiserver的,但是这两个context都用的是同一个user,这个user又藏在rancher的命名空间里面
现在需要把这个rke集群切换到另一个rancher上面管理,从旧rancher上面踢出集群后,集群上rancher的命名空间会被删掉,kubectl用的user也会跟着被删掉,导致kubectl无法连接到集群,只能回滚虚拟机
为了切换到新rancher,需要单独为kubectl创建一个新的user,在rke脱离rancher后仍然能控制集群
创建账号并授权
创建一个新的ServiceAccount
可以写yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: kubectl-admin
namespace: default
当然也可以直接一句话
kubectl create serviceaccount kubectl-admin
然后给这个SA授权,这里可以用Role和RoleBinding授权,限制这个账户仅可对特定的命名空间执行特定的操作,也可以用ClusterRole和ClusterRoleBinding来授予跨命名空间的权限,具体参考k8s的RBAC文档
因为这里创建的kubectl-admin账户是给kubectl用来控制集群的,所以使用ClusterRoleBinding来授予权限
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kubectl-admin-binding
subjects:
- kind: ServiceAccount
name: kubectl-admin
namespace: default
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
roleRef引用的ClusterRole是cluster-admin
,这是k8s内置的一个集群角色,拥有集群的所有权限,用这个就不需要自己配ClusterRole了
接下来获取ServiceAccount的Token
[root@master-01 ~]# kubectl describe serviceaccounts kubectl-admin
Name: kubectl-admin
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: kubectl-admin-token-t56kr
Tokens: kubectl-admin-token-t56kr
Events: <none>
可以看到Token的名称是kubectl-admin-token-t56kr
[root@master-01 ~]# kubectl describe secrets kubectl-admin-token-t56kr
Name: kubectl-admin-token-t56kr
Namespace: default
Labels: <none>
Annotations: kubernetes.io/service-account.name: kubectl-admin
kubernetes.io/service-account.uid: 1c477ddc-281f-41f3-b6a7-539056c34a0a
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1058 bytes
namespace: 7 bytes
token: eyJhbGciO.....X6gPw
把eyJhbGciO.....X6gPw
这一长串复制下来,这就是ServiceAccount的Token
创建kubeconfig文件
先看看rancher提供的kubeconfig是啥样子的
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUd......tLQ==
server: https://rce.test.cn/k8s/clusters/c-8pffj
name: test
- cluster:
certificate-authority-data: LS0tLS1CRU......LQo=
server: https://192.168.0.11:6443
name: test-master-01
users:
- name: test
user:
token: kubeconfig-user-5782d.c-8pffj:lls.....m42bt
contexts:
- context:
cluster: test
user: test
name: test
- context:
cluster: test-master-01
user: test
name: test-master-01
current-context: test-master-01
可以看到配置文件主要分成三块:
clusters
:指定kubectl要连接的集群的信息,rancher为文件生成了两个信息,一个是通过rancher的代理,一个是直连集群的ip地址,除了地址以外还带了个证书users
:指定kubectl与集群通信所使用的用户身份,rancher只提供了一个用户,这里就要用到上面创建的新的ServiceAccount了contexts
:指定kubectl连接上下文,某个上下文的名称是什么,连接的集群是哪个,使用的用户身份是哪一个,切换上下文可以用kubectl config use-context
命令
users和context已经有了,就差一个cluster的证书了,这个证书在rke集群下可以在master节点的/etc/kubernetes/ssl/
目录下找到,名字是kube-ca.pem
可以用下面的命令取出来,以base64编码的方式粘贴到kubeconfig里面
cat /etc/kubernetes/ssl/kube-ca.pem | base64
最终的kubeconfig文件内容如下
apiVersion: v1
kind: Config
clusters:
- cluster:
name: local
certificate-authority-data: LS0tLS1CRU.......LS0tLQo= # 这里粘kube-ca.pem经过base64编码后的内容
server: https://192.168.70.11:6443
contexts:
- context:
cluster: local
user: kubectl-admin
name: local
users:
- name: kubectl-admin # 这个名字无所谓,不对应SA,下面的Token对就行
user:
token: eyJhbGc....9omOX6gPw # 这里粘ServiceAccount的Token
切换一下kubectl的上下文
kubectl config use-context local
尝试获取node信息
[root@master-01 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
test-master-01 Ready controlplane,etcd 206d v1.20.15
test-worker-01 Ready worker 247d v1.20.15
test-worker-02 Ready worker 246d v1.20.15
可以看到kubectl已经可以正常和apiserver通信