1 背景
我们搭建好K8S集群后,默认都是从master节点上连接到集群,执行命令。但是有时候我们需要在其他机器连接k8s集群,这就需要我们的kubectl命令能够和集群的apiserver通讯,由于是通过https通讯,因此需要生成对应的证书文件。
2 最简方式
由于我们的集群是通过kubeadm部署,因此部署后会自动生成一个用于admin用户连接集群的配置文件——/etc/kubernetes/admin.conf,
[root@master ~]# cat /etc/kubernetes/admin.conf
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: ****
server: https://192.168.0.110:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: ****
client-key-data: ****
所以最简单的方式就是将该文件拷贝到对应的机器上,这样就能直接连接到k8s集群,比如我们把这个登录凭证拷贝node1上,
[root@node1 ~]# kubectl get node --kubeconfig=./admin.conf
NAME STATUS ROLES AGE VERSION
master Ready control-plane,master 256d v1.21.2
node1 Ready <none> 256d v1.21.2
node2 Ready <none> 256d v1.21.2
可见连接成功,命令正常返回。
3 证书方式
如果我们没有admin.conf文件,或者文件丢失,那我们就可以自己生成证书,然后将生成的证书拷贝到目标机器,一样可以实现远程连接。
3.1 安装cfssl工具
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
chmod +x cfssl_linux-amd64 cfssljson_linux-amd64 cfssl-certinfo_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
mv cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo
3.2 生成ca配置
证书有效时间为10年
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"expiry": "87600h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
EOF
3.3 生成admin证书请求配置
cat > admin-csr.json <<EOF
{
"CN": "admin",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing",
"O": "system:masters",
"OU": "System"
}
]
}
EOF
3.4 生成admin证书
进入集群证书目录,/etc/kubernetes/pki
[root@master pki]# cfssl gencert -ca=ca.crt -ca-key=ca.key -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin
2022/03/27 07:12:43 [INFO] generate received request
2022/03/27 07:12:43 [INFO] received CSR
2022/03/27 07:12:43 [INFO] generating key: rsa-2048
2022/03/27 07:12:44 [INFO] encoded CSR
2022/03/27 07:12:44 [INFO] signed certificate with serial number 479626741822853067875971057191146068697711629773
2022/03/27 07:12:44 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 ("Information Requirements").
[root@master pki]# ls admin*
admin.csr admin-csr.json admin-key.pem admin.pem
因为我的集群是kubeadm部署的,因此已经有ca证书对,就不需要重新生成,直接使用就好。
4 配置远端目标机器
将生成的admin证书对,以及集群的ca证书拷贝到目标远端机器,
scp admin-key.pem admin.pem ca.crt node2:/root
然后登录远端机器,开始配置kubeconfig。
4.1 添加集群
将我们的集群添加到目标机器中,并设置使用证书文件授权,这里要注意证书文件的名字和路径,
kubectl config set-cluster kubernetes \
--server=https://master:6443 \
--embed-certs=true \
--certificate-authority=/root/ca.crt
4.2 设置客户端连接集群的认证参数
其中k8sadmin就是我们指定的用户名
kubectl config set-credentials k8sadmin \
--embed-certs=true \
--certificate-authority=/root/ca.crt\
--client-key=/root/admin-key.pem \
--client-certificate=/root/admin.pem
4.3 设置上下文
将用户和集群关联
kubectl config set-context default \
--cluster=kubernetes \
--user=k8sadmin
4.4 切换上下文
将集群切到我们需要连接的集群
kubectl config use-context default
此时,/root/.kube/config就会生成和admin.conf类似的认证文件,我们就能连接到目标集群。
4.5 测试连接
[root@node2 ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
master Ready control-plane,master 256d v1.21.2
node1 Ready <none> 256d v1.21.2
node2 Ready <none> 256d v1.21.2
5 最安全的方式
不管是拷贝admin.conf文件还是生成admin证书对都有个问题,权限过大,因为kubeadm和我们创建admin证书时,我们用的是以下配置,
"O": "system:masters",
system:masters是一个例外的,超级用户组,可以绕过鉴权层,比如RBAC,这是比较危险的。
所以,如果我们需要给某个用户集群权限,就需要能够限制他的权限范围。
将签名请求文件中的用户组设置为其他组,比如dev
cat > dev-csr.json <<EOF
{
"CN": "test",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing",
"O": "dev",
"OU": "System"
}
]
}
EOF
然后同样生成dev的证书对,并拷贝至目标机器,
[root@master pki]# cfssl gencert -ca=ca.crt -ca-key=ca.key -config=ca-config.json -profile=kubernetes dev-csr.json | cfssljson -bare dev
[root@master pki]# scp dev-key.pem dev.pem node2:/root
cluster我们上面已经设置过,就不需要重复设置,我们只要设置新的连接凭证和上下文就可以了,
[root@node2 ~]# kubectl config set-credentials test \
> --certificate-authority=/root/ca.crt\
> --client-key=/root/dev-key.pem \
> --client-certificate=/root/dev.pem
[root@node2 ~]# kubectl config set-context test \
> --cluster=kubernetes \
> --user=test
[root@node2 ~]# kubectl config use-context test
这时候我们尝试连接集群,
[root@node2 ~]# kubectl get node
Error from server (Forbidden): nodes is forbidden: User "test" cannot list resource "nodes" in API group "" at the cluster scope
不出意外,出现意外了,因为我们还没给这个用户授予权限。
这时RBAC就需要登场了。假设我们只允许这个用户访问nginx这个namespace,我们在master节点上授予test用户nginx这个namespace的admin权限。
[root@master ~]# kubectl create rolebinding test-admin-binding --clusterrole=admin --user=test --namespace=nginx
这时我们再测试下,可见,这时test用户在nginx namespace里可以为所欲为,
[root@node2 ~]# kubectl get pod -n nginx
NAME READY STATUS RESTARTS AGE
centos7 1/1 Running 1 30s
[root@node2 ~]# kubectl delete pod centos7 -n nginx
pod "centos7" deleted
但是在其他namespace就没办法了。
[root@node2 ~]# kubectl get pod -n kube-system
Error from server (Forbidden): pods is forbidden: User "test" cannot list resource "pods" in API group "" in the namespace "kube-system"
参考文档:
- https://kubernetes.io/docs/reference/access-authn-authz/rbac/