K8S 集群中的认证、授权与 kubeconfig
一、kubeconfig 介绍
-[appuser@k8s-master-1 ~]$ cat /etc/kubernetes/kubeconfig
apiVersion: v1
kind: Config
clusters:
- name: shjq-dev01-chenqiang-cluster
cluster:
server: https://10.130.14.155:443
certificate-authority: /etc/kubernetes/ssl/ca.crt
users:
- name: shjq-dev01-chenqiang-user
user:
client-certificate: /etc/kubernetes/ssl/cs_client.crt
client-key: /etc/kubernetes/ssl/cs_client.key
contexts:
- context:
cluster: shjq-dev01-chenqiang-cluster
user: shjq-dev01-chenqiang-user
name: shjq-dev01-chenqiang
------
# 上面为 指定目录格式
# 我们要配置成单个 kubeconfig 配置文件,我们需要做如下操作:
- 修改 certificate-authority 成 certificate-authority-data
- 修改 client-certificate 成 client-certificate-data
- 修改 client-key 成 client-key-data
- 对 /etc/kubernetes/ssl/ca.crt, cs_client.crt, cs_client.key 进行 base64 编码,分别执行 /etc/kubernetes/ssl/ca.crt|base64 等。
-------
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZuVENDQTRXZ0F3SUJBZ0lKQVBuVlJIdW9zZXpqTUEwR0NTcUdTSWIzRFFFQkN3VUFNR1V4Q3pBSkJnTlYKQkFZVEFrTk9NUkV3RHdZRFZRUUlEQWhUYUdGdVoyaGhhVEVQTUEwR0ExVUVCd3dHVUhWa2IyNW5NUll3RkFZRApWUVFLREExellXbGpiVzkwYjNJdVkyOXRNUXd3Q2dZRFZRUUxEQU5yT0hNeEREQUtCZ05WQkFNTUEyczRjekFlCkZ3MHhPREF6TURnd05qSTJORE5hRncweE9UQXpNRGd3TmpJMk5ETmFNR1V4Q3pBSkJnTlZCQVlUQWtOT01SRXcKRHdZRFZRUUlEQWhUYUdGdVoyaGhhVEVQTUEwR0ExVUVCd3dHVUhWa2IyNW5NUll3RkFZRFZRUUtEQTF6WVdsagpiVzkwYbnpCSDQvOG9Od0NDaHkrcUdYVE9hNTY2UzhjNW5vQ2c2TlovTGxZVjFLUHlJdjFMblRmd3VselUKenpSTGUwVkRjZXpwUmY0RnJ4TVJLSzg # 太长了 有删减
server: https://10.130.14.155:443
name: shjq-dev01-chenqiang-cluster
contexts:
- context:
cluster: shjq-dev01-chenqiang-cluster
user: shjq-dev01-chenqiang-user
name: shjq-dev01-chenqiang
current-context: shjq-dev01-chenqiang
kind: Config
preferences: {}
users:
- name: shjq-dev01-chenqiang-user
user:
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVBakNDQWVvQ0NRQ0NhYWdFUnFmNExEQU5CZ2txaGtpRzl3MEJBUXNGQURCbE1Rc3dDUVlEVlFRR0V3SkQ # 太长了 有删减
client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBeUI4djN5YjlqRmxRU0x3L1FYaVUycFdGck5jNjB0bmp1ZVh5N3gvNTZOcXNpOUhwCjdlSzZaSG5LL1JabDcxZUltS0tPNjhrVm9aSUZsRmx2UTJMWmtJMkVrYXpndHNrdnpvQ3l4aEhQSndIV01sRloKQ1dndDFXVHdkTm93emI1ZEtpSnhGbHFvWlJtZ3BBMGJ # 太长了 有删减
以实际环境的 kubeconfig 为例进行分析,主要包含以下几部分信息
三大部分
clusters 用于集群认证 Server 字段: 存储集群的地址
证书路径(certificate-authority: /etc/kubernetes/ssl/ca.crt)或
证书内容(certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZuVENDQTRXZ)
可以有多个 cluster 集群
users 用于用户认证 存储用户的证书、密钥(两种形式,路径或内容)
证书形式
client-certificate: /etc/kubernetes/ssl/cs_client.crt
client-key: /etc/kubernetes/ssl/cs_client.key
密钥token形式:
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0
client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktL
可以有多个 user 用户
context 上下文,用户和集群的组合 采用某个 context :表示采用某个用户去管控某个集群
默认情况是,采用 admin 用户管控集群,具有所有资源的创建权限
二、明确一个问题
由于 RBAC 机制,ServiceAccount 可以(通过Rolebinding或 ClusterRolebinding)具有(Role 或 ClusterRole 定义的)某些权限
那么在默认 context 下(就是 admin user)下,创建一个具有 pod create 权限的 ServiceAccount,接下来使用该 ServiceAccount 去创建 Pod 等,并不能说是该 ServiceAccount 在管控集群,实际上仍是 admin user 在管控集群,所以此时不能成为 k8s 多用户管控集群
因为在该 k8s 环境中,仍可以创建 deployment 、Service、daemonset 等资源
若是该 ServiceAccount 管控集群,在k8s环境中,应该只能创建 pod
所以可以这么理解
cluster 多集群
user 多用户,user 的权限(可绑定 ServiceAccount,进行权限限制,下文将讲如何用 ServiceAccount 创建 User)
context 表示使用用户管控集群(该集群的最大权限就是用户的权限)
SA 通过 RoleBinding 绑定 Role ,具有 Role 权限,只能操作 Role 所在 namespace
可以实现 SA 具有操作别的 namespace 中资源的权限(例如 SA 在 ns1, Role 在 ns2,SA 可操作 ns2 资源)
SA 通过 RoleBinding 绑定 ClusterRole, 具有 ClusterRole 权限,只能操作 SA 所在的 namespace
可以实现 SA 在所在 namespace 具有高权限,但不能跨出当前 namespace
SA 通过 ClusterRoleBinding 绑定 ClusterRole,具有 ClusterRole 权限,可操作所有 namespace 和集群资源
没有 ClusterRoleBinding 与 Role de 组合
三、使用 ServiceAccount 创建 kubeconfig 中的 User
3.1 创建 ServiceAccount 获取 Token
首先创建 role 或 clusterrole 进行权限定义
之后创建 ServiceAccount 用于与 role 或 clusterrole 绑定
最后取出 ServiceAccount 对应的 Token (创建 serviceaccount 时会自动创建个同名的 secret 并挂载上,其用于访问集群)
# 简单举例
# 创建命名空间
kubectl create ns ns-sa
# 创建 serviceaccount
kubectl create sa sa-test -n ns-sa
# 创建 role 赋予某些权限 也可以通过 yaml 编写
kubectl -n ns-sa create role role-1 --verb=get,list --resources=Pod,Deployment -n test-sa
# 绑定 赋予 sa 权限
kubectl -n ns-sa create rolebinding sa-rolebinding-1 --role=ns-sa:role-1 --serviceaccount=sa-test
# 获取 sa 的 token
# 首先查看对应的 secret
kubectl -n ns-sa get secret | grep sa-test # 获知 secret 的名称 如 sa-test-token-gz2jr
# 然后获取 token
kubectl -n ns-sa describe secret sa-test-token-gz2jr
# 或
kubectl -n kube-system get secret admin-token-nwphb -o jsonpath={.data.token}|base64 -d # 这种方法 后面可能多个 % 删除就好
3.2 创建 k8s user 管控
实际上就是创建个 user,使用的是上面 ServiceAccount 的 Token
第一步:设置一个账号鉴权信息(创建一个k8s user)
上面的<TokenOfSecret>的内容就是我们上面通过kubectl describe secret获取到的 Token 值,注意指定的值两边没有 符号
$ kubectl config set-credentials test-user(自定义) --token <TokenOfSecret>
第二步:设置集群的访问信息
若配置访问已有的集群信息,忽略此步
若添加新集群,则需要添加下面信息
$ kubectl config set-cluster new-cluster-name(自定义) --server https://10.192.0.2:6443 --certificate-authority /home/shiyanlou/ca.crt --embed-certs=true
Cluster "new-cluster-name" set.
第三步:创建一个 Context,把集群信息和鉴权信息绑定在一起
# 采用了自己的集群 minikube
$ kubectl config set-context your-context-name(自定义) --cluster minikube --user test-user
Context "your-context-name" created.
第四步:使用这个创建的 Context
$ kubectl config use-context your-context-name
Switched to context "your-context-name".
通过以上步骤的设置,我们就可以在本地通过 kubectl 使用我们创建的 ServiceAccount 来调用 API 接口,访问集群中资源的信息了。
好了,让我们来简单查看下默认命名空间 default 中的 Pod 列表
$ kubectl get pods
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:shiyanlou-admin" cannot list pods in the namespace "default"
为什么会出现此信息?
因为我们 role 赋予的权限是在 ns-sa 命名空间下查看 pod,因此无法获取 default 空间下的 pod
3.3 利用 mac 用户进行管控
因为 mac 用户不是 k8s user,所以不太清楚怎么利用mac user 创建 contxt
此处测试 mac user 与 clusterrole admin 绑定,验证是否有创建pod权限
新建mac 用户 yeah
【小技巧】macOS 下用 dscl 命令行管理用户 创建用户
赋予权限
# 绑定 admin clusterrole
k create clusterrolebinding test-sa-admin2 --user=yeah --clusterrole=admin
验证权限
# 验证是否授权成功
kubectl auth can-i create pods --namespace default --as yeah
四、命令总结
kubeconfig配置文件可通过kubectl config命令进行设定
kubectl config view #打印文件内容
kubectl config set-cluster # 设置clusters段
kubectl config set-credentials # 设置users段
kubectl config set-context # 设置contexts段
kubectl config set-use-context # 设置current-context段
获取secret的token
# 创建 serviceaccount 时会自动创建个同名的 secret 并挂载上,其用于访问集群
kubectl -n kube-system get secret|grep admin-token
# 用 jsonpath 方式获取 token 的值
kubectl -n kube-system get secret admin-token-nwphb -o jsonpath={.data.token}|base64 -d
使用指定用户创建资源
# mac 用户
$ k apply -f 1sysctl.yaml --as=yeah
# 使用 ServiceAccount
$ k apply -f 1sysctl.yaml --as system:serviceaccount:default:sa-test1
验证用户是否有某些权限
# 测试权限 因为 k8s User 绑定的 serveraccount, 所以 k8s User 本身并没有权限
$ kubectl auth can-i create pods --namespace default --as user-test1
no
# ServiceAccount 才有权限
$ kubectl auth can-i create pods --namespace default --as system:serviceaccount:default:sa-test1
yes