Kubernetes 鉴权证书详解

一、K8S 证书介绍
在 Kube-apiserver 中提供了很多认证方式,其中最常用的就是 TLS 认证,当然也有 BootstrapToken,BasicAuth 认证等,只要有一个认证通过,那么 Kube-apiserver 即认为认证通过。下面就主要讲解 TLS 认证。

如果你是使用 kubeadm安装的 Kubernetes, 则会自动生成集群所需的证书。但是如果是通过二进制搭建,所有的证书是需要自己生成的,这里我们说说集群必需的证书。

在了解 Kubernetes 证书之前,需要先了解什么是 “单向 TLS 认证” 和 “双向 TLS 认证”

• 服务器单向认证:只需要服务器端提供证书,客户端通过服务器端证书验证服务的身份,但服务器并不验证客户端的身份。这种情况一般适用于对 Internet 开放的服务,例如搜索引擎网站,任何客户端都可以连接到服务器上进行访问,但客户端需要验证服务器的身份,以避免连接到伪造的恶意服务器。

• 双向 TLS 认证:除了客户端需要验证服务器的证书,服务器也要通过客户端证书验证客户端的身份。这种情况下服务器提供的是敏感信息,只允许特定身份的客户端访问。开启服务端验证客户端默认是关闭的,需要在服务端开启认证配置。

二、鉴权证书
Kube-apiserver,Kubelet 来说,它们都能提供 HTTPS 服务,Kube-apiserver、Kubelet 对于一个请求,既要认证也要鉴权。在 Kube-apiserver 中,鉴权也有多种方式:

• Node
• ABAC
• RBAC
• Webhook

在 TLS + RBAC 模式下,访问 Kube-apiserver 有三种方式:

• 证书 + RBAC(就是上一篇说到的那些证书)
• Node + RBAC( Kubelet 访问 Kube-apiserver 时)
• ServiceAccount + RBAC( Kubernetes 集群内 Pod 访问 Kube-apiserver )

三、K8S 证书的 CN、O
RBAC 鉴权需要对 User 或者 Group 来绑定相应权限达到效果。Kubernetes 证书中的 CN 表示 User,O 表示 Group,看一个例子:

用 openssl 命令解析 kubelet 的客户端证书,kubelet 访问 Kube-apiserver 的时候就会用这个证书来认证,鉴权。

openssl x509 -noout -text -in kubelet-client-current.pem 

Kubernetes RBAC 鉴权机制就是利用将权限绑定到 User 或者 Group,使得 User、Group 拥有对应权限,下面就看看 Kubernetes 如何 根据证书、ServiceAccount 鉴权的。

四、Kubectl
Kubectl 使用 KubeConfig 与 Kube-apiserver 进行认证、鉴权。认证上一篇说过了,就是通过 TLS 认证。这里说鉴权,先看看 KubeConfig 的客户端证书 O、CN
使用 openssl 命令解析 KubeConfig 中 client-certificate-data 字段,查看 KubeConfig 客户端证书的 O、CN

[root@master1 ~]#  cat /root/.kube/config | grep client-certificate-data: | sed 's/    client-certificate-data: //g' | base64 -d | openssl x509 -noout  -subject
subject= /O=system:masters/CN=kubernetes-admin

可以看到 KubeConfig 客户端证书为 kubernetes-admin User 且属于 system:masters Group。
system:masters 是 Kubernetes 内置的用户组,且 Kubernetes 集群中也包含许多默认 ClusterRole、ClusterRolebinding,其中 cluster-admin 的 ClusterRolebinding 就将 cluster-admin 的 ClusterRole 绑定到 system:masters Group,这样 KubeConfig 就拥有权限来操作 Kube-apiserver 了。

# cluster-admin ClusterRole 拥有所有资源的所有权限
[root@master1 ~]# kubectl get clusterrole cluster-admin -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  creationTimestamp: "2023-11-28T12:49:34Z"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: cluster-admin
  resourceVersion: "106"
  uid: 37c414b1-dc69-447c-90b4-101a48ecbfe3
rules:
- apiGroups:
  - '*'
  resources:
  - '*'
  verbs:
  - '*'
- nonResourceURLs:
  - '*'
  verbs:
  - '*'
# cluster-admin ClusterRoleBinding 将 cluster-admin ClusterRole 绑定到 system:masters Group
[root@master1 ~]# kubectl get clusterrolebinding cluster-admin -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  creationTimestamp: "2023-11-28T12:49:35Z"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: cluster-admin
  resourceVersion: "171"
  uid: 2362baeb-2a09-4485-883f-7c0e3a4a0bd3
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:masters

五、Kube-scheduler、Kube-controller-manager
Kube-scheduler、Kube-controller-manager 也是使用各自的 KubeConfig 来认证、鉴权。但是他们和 Kubectl 的 KubeConfig 不属于同一个用户、组。
使用 openssl 命令解析 Kube-scheduler 的 KubeConfig 中 client-certificate-data 字段,查看 KubeConfig 客户端证书的 O、CN

[root@master1 ~]# cat /etc/kubernetes/scheduler.conf | grep client-certificate-data: | sed 's/    client-certificate-data: //g' | base64 -d | openssl x509 -noout  -subject
subject= /CN=system:kube-scheduler

system:kube-scheduler 也是 Kubernetes 集群内部的设置的用户,Kubernetes 集群中也存在对应默认的 ClusterRole system:kube-scheduler 和 ClusterRoleBinding system:kube-scheduler 。

# system:kube-scheduler ClusterRole 拥有细分的权限
[root@master1 ~]# kubectl get clusterrole system:kube-scheduler -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  creationTimestamp: "2023-11-28T12:49:35Z"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:kube-scheduler
  resourceVersion: "139"
  uid: 3013d5c5-4682-4080-abd7-368d9a45aa16
rules:
- apiGroups:
  - ""
  - events.k8s.io
  resources:
  - events
  verbs:
  - create
  - patch
  - update
- apiGroups:
  - coordination.k8s.io
  resources:
  - leases
  verbs:
  - create
- apiGroups:
  - coordination.k8s.io
  resourceNames:
  - kube-scheduler
  resources:
  - leases
  verbs:
  - get
  - update
- apiGroups:
  - ""
  resources:
  - nodes
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - delete
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - bindings
  - pods/binding
  verbs:
  - create
- apiGroups:
  - ""
  resources:
  - pods/status
  verbs:
  - patch
  - update
- apiGroups:
  - ""
  resources:
  - replicationcontrollers
  - services
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - apps
  - extensions
  resources:
  - replicasets
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - apps
  resources:
  - statefulsets
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - persistentvolumeclaims
  - persistentvolumes
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - authentication.k8s.io
  resources:
  - tokenreviews
  verbs:
  - create
- apiGroups:
  - authorization.k8s.io
  resources:
  - subjectaccessreviews
  verbs:
  - create
- apiGroups:
  - storage.k8s.io
  resources:
  - csinodes
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - namespaces
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - storage.k8s.io
  resources:
  - csidrivers
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - storage.k8s.io
  resources:
  - csistoragecapacities
  verbs:
  - get
  - list
  - watch
# system:kube-scheduler ClusterRoleBinding 将 system:kube-scheduler ClusterRole 绑定到 system:kube-scheduler User
[root@master1 ~]# kubectl get clusterrolebinding system:kube-scheduler -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  creationTimestamp: "2023-11-28T12:49:35Z"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:kube-scheduler
  resourceVersion: "179"
  uid: 35788c57-a2ed-4619-8ad7-363d0af21ba1
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:kube-scheduler
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: system:kube-scheduler

可以发现 Kube-scheduler 权限并不是向 Kubectl 那样拥有所有资源的所有操作权限,即使是内部组件,基于最小权限原则,Kubernetes 依然会为这两个用户只绑定必要的权限。
Kube-controller-manager 和 Kube-scheduler 一样,只不过 Kube-controller-manager 的 User 是 system:kube-controller-manager

六、Kubelet
Kubelet 同样也会访问 Kube-apiserver,Kubelet 使用其客户端证书与 Kube-apiserver 认证、鉴权。
使用 openssl 命令解析 Kubelet 客户端证书,查看证书的 O、CN

[root@master1 ~]# openssl x509 -noout  -subject -in /var/lib/kubelet/pki/kubelet-client-current.pem
subject= /O=system:nodes/CN=system:node:master1

可以发现 Kubelet 客户端证书为 system:node:master-172-31-97-104 User 且属于 system:nodes Group。

#system:nodes 也是 Kubernetes 内置用户组,通过查看其默认的 ClusterRole、ClusterRoleBinding
[root@master1 ~]# kubectl get clusterrolebinding system:node -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  creationTimestamp: "2023-11-28T12:49:35Z"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:node
  resourceVersion: "181"
  uid: cdcd9989-e268-40d0-80f7-acf9d8ce7d09
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:node

七、Kube-apiserver
其他组件访问 Kube-apiserver,然后 Kube-apiserver 对访问者进行授权,然而 Kube-apiserver 也会作为客户端去访问 Kubelet,例如:kubectl logs/exec,Kube-apiserver 都会去访问 Kubelet。Kubelet 作为服务端内部也是通过 TLS + RBAC 这种模式去认证、鉴权。
使用 openssl 命令解析 Kube-apiserver 客户端证书,查看证书的 O、CN

[root@master1 ~]# openssl x509 -noout  -subject -in /etc/kubernetes/pki/apiserver-kubelet-client.crt
subject= /O=system:masters/CN=kube-apiserver-kubelet-client

可以发现 Kube-apiserver 访问 Kubelet 客户端证书为 kube-apiserver-kubelet-client User 且属于 system:masters Group。

在 Kubectl 章节介绍了 system:masters 属于内置用户组,且默认拥有超级权限,所以 Kube-apiserver 可以去访问 Kubelet 操作资源。

八、ServiceAccount
在 Kubernetes 集群内部,比如 Pod 需要访问 Kube-apiserver,就会使用其配置的 Service Account(没有配置,则使用默认) 与 Kube-apiserver 认证、鉴权。

你可能感兴趣的:(kubernetes,容器,云原生)