认证介绍

发布时间: 更新时间: 总字数:2512 阅读时间:6m 作者: 分享 复制网址

Kubernetes 提供多种认证机制,本文详细介绍。

概念

Kubernetes 认证机制如下:

  • 身份认证(Authentication)通过认证插件实现,检查用户是否为合法用户,认证包括:
    • 令牌认证 token(Bootstrap Tokens),通过预共享密钥
    • JWT tokens
    • TLS 认证,通过 X509 client certs 证书 Subject 添加:
      • CN: user/serviceaccount
      • O: group
    • user/password
    • Static Token File
    • Static Password File
    • Service Account Tokens
    • OpenId Connect Tokens
  • 授权(Authorization):通过授权插件实现,判断该用户是否具有该操作的权限
    • RBAC(Role-based Access Controller),许可授权,RBAC 为主流方式
    • ABAC
    • Node 认证
    • Webhook 认证
  • 准入机制(Admission Control):请求的最后一个步骤,一般用于拓展功能,如检查 pod 的 resource 是否配置,yaml 配置的安全是否合规等。一般使用 admission webhooks 来实现

Kubernetes 的资源的权限分配,通过用户扮演角色来实现:

  • 命名空间(namespace)资源,通过 RoleBinding 实现权限分配
    • Role(角色),也可以表示为 permission(许可) = Operations + Objects
      • Operations
      • Objects
    • RoleBinding
      • UserAccount
      • Group
      • ServiceAccount(若采用 key 认证,通过 Subject 字段指定)
        • 创建Pod时,指定 spec.serviceAccountName
      • Role
  • 集群资源,通过 ClusterRole, ClusterRoleBinding 实现权限分配
  • Kubernetes 资源包括:
    • resource group
    • resource
    • non-resource url

其中,可以通过 RoleBinding 绑定 ClusterRole 实现用户对指定命名空间权限限制。

关于接口调用,参考:Kubernetes API 介绍

Service Account

  • 帮助
kubectl create serviceaccount -h

kubectl get sa

kubectl create serviceaccount NAME [--dry-run=server|client|none] [options]
  • dry-run
kubectl create serviceaccount mysa -o yaml --dry-run=client
  • serviceaccount-demo.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: null
  name: mysa

  • 执行
$ kubectl apply -f serviceaccount-demo.yaml
serviceaccount/mysa created
$ kubectl get sa
NAME      SECRETS   AGE
default   1         24d
mysa      1         3s
$ kubectl get sa mysa -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"creationTimestamp":null,"name":"mysa","namespace":"default"}}
  creationTimestamp: "2022-03-19T02:11:53Z"
  name: mysa
  namespace: default
  resourceVersion: "1198052"
  uid: 5eb600e0-57d4-428f-9ee8-e0d4d9b9ec6c
secrets:
- name: mysa-token-hnklw
$ kubectl get secrets mysa-token-hnklw
NAME               TYPE                                  DATA   AGE
mysa-token-hnklw   kubernetes.io/service-account-token   3      71s
$ kubectl describe sa mysa
Name:                mysa
Namespace:           default
Labels:              <none>
Annotations:         <none>
Image pull secrets:  <none>
Mountable secrets:   mysa-token-hnklw
Tokens:              mysa-token-hnklw
Events:              <none>

说明:

  1. 会自动创建对应的 ServiceAccountSecrets
  2. 默认情况下存在名字为 default 的 ServiceAccount,默认注入所有容器内,默认挂载在 Pod 的 /var/run/secrets/kubernetes.io/serviceaccount/ 目录
  3. 创建容器时,可以通过 kubectl explain pods.spec.serviceAccountName 指定 Service Account,然后通过 ServiceAccount 和 role 的 banding 赋予不同的权限
  4. 可以为 ServiceAccount bingding 对应的 Image pull secrets 赋予拉去镜像的认证信息,该方法比创建容器是指定 kubectl explain pods.spec.imagePullSecrets 更为方便

创建用户PKI

kubelet 认证机制

默认通过加载 ~/.kube/config 中的认证信息进行认证,我们可以使用 kubectl config 进行配置,示例:

$ kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://172.20.0.81: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: REDACTED
    client-key-data: REDACTED

我们可以在控制节点的 /etc/kubernetes/pki/ 目录下发现对应的 CA key。

创建用户

下面为用户 xianbin 创建认证的 key

  • 创建 key
cd /etc/kubernetes/pki/
umask 077; openssl genrsa -out xianbin.key 2048
  • 生成证书签署请求
openssl req -new -key xianbin.key -out xianbin.csr -subj "/CN=xianbin"

其中,Subject 中:

  • O: 表示组

  • CN: 表示用户名

  • 使用 Kubernetes 的 CA 为 xianbin 用户签署证书

openssl x509 -req -in xianbin.csr -CA ./ca.crt -CAkey ./ca.key -CAcreateserial -out xianbin.crt -days 700
  • 查看证书
$ openssl x509 -in xianbin.crt -text -noout
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            6c:ae:6f:1d:78:0f:0c:90:57:dd:4f:78:14:0b:d1:61:bc:92:7c:1c
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN = kubernetes  # 签署者
        Validity
            Not Before: Mar 19 02:38:46 2022 GMT
            Not After : Feb 17 02:38:46 2024 GMT
        Subject: CN = xianbin  # 被签署的用户
...
  • 给 kubectl 创建 credentials
$ kubectl config set-credentials -h

kubectl config set-credentials NAME [--client-certificate=path/to/certfile]
[--client-key=path/to/keyfile] [--token=bearer_token] [--username=basic_user]
[--password=basic_password] [--auth-provider=provider_name] [--auth-provider-arg=key=value]
[--exec-command=exec_command] [--exec-api-version=exec_api_version] [--exec-arg=arg]
[--exec-env=key=value] [options]
$ kubectl config set-credentials xianbin --client-certificate=./xianbin.crt --client-key=./xianbin.key --embed-certs=true
User "xianbin" set.
$ kubectl config view
...
users:
...
- name: xianbin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
  • 设置 context
$ kubectl config set-context xianbin@kubernetes --cluster=kubernetes --user=xianbin
Context "xianbin@kubernetes" created.
$ kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://172.20.0.81:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
- context:
    cluster: kubernetes
    user: xianbin
  name: xianbin@kubernetes  # 新设置的 context
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
- name: xianbin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
  • 切换 context
$ kubectl config use-context xianbin@kubernetes
Switched to context "xianbin@kubernetes".
  • 创建 cluster(可选)
kubectl config set-cluster -h

kubectl config set-cluster NAME [--server=server]
[--certificate-authority=path/to/certificate/authority] [--insecure-skip-tls-verify=true]
[--tls-server-name=example.com] [options]
  • 命令执行,默认情况下,当前用户 xianbin 没有任何权限
xiexianbin@k8s-master:~$ kubectl get pod
Error from server (Forbidden): pods is forbidden: User "xianbin" cannot list resource "pods" in API group "" in the namespace "default"
xiexianbin@k8s-master:~$ kubectl get pod -n kube-system
Error from server (Forbidden): pods is forbidden: User "xianbin" cannot list resource "pods" in API group "" in the namespace "kube-system"

Role

  • 帮助
kubectl create role -h

kubectl create role NAME --verb=verb --resource=resource.group/subresource [--resource-name=resourcename] [--dry-run=server|client|none] [options]
  • dry-run
kubectl create role pod-reader --verb=get,list,watch --resource=pods -o yaml --dry-run=client
  • role-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: default
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch

  • 执行
$ kubectl apply -f role-demo.yaml
role.rbac.authorization.k8s.io/pod-reader created
$ kubectl get role
NAME         CREATED AT
pod-reader   2022-03-19T21:35:04Z
$ kubectl describe role pod-reader
Name:         pod-reader
Labels:       <none>
Annotations:  <none>
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  pods       []                 []              [get list watch]

RoleBinding

  • 帮助
kubectl create rolebinding -h

kubectl create rolebinding NAME --clusterrole=NAME|--role=NAME [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run=server|client|none] [options]
  • dry-run
$ kubectl create rolebinding xianbin-read-pod --role=pod-reader --user=xianbin --dry-run=client -o yaml
  • rolebinding-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  creationTimestamp: null
  name: xianbin-read-pod
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: pod-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: xianbin

其中,用户 xianbin 不存在,是标识,ssl key 中的 CN

  • 执行
$ kubectl apply -f rolebinding-demo.yaml
rolebinding.rbac.authorization.k8s.io/xianbin-read-pod created
$ kubectl describe rolebindings xianbin-read-pod
Name:         xianbin-read-pod
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  Role
  Name:  pod-reader
Subjects:
  Kind  Name     Namespace
  ----  ----     ---------
  User  xianbin

Role & RoleBinding 测试

kubectl config use-context xianbin@kubernetes

# 有权限
xiexianbin@k8s-master:~$ kubectl get pod
NAME             READY   STATUS    RESTARTS       AGE
hello-app-sf-0   1/1     Running   0              14h
hello-app-sf-1   1/1     Running   0              14h
t1               1/1     Running   1 (2d6h ago)   14h

# 无权限
xiexianbin@k8s-master:~$ kubectl get pod -n kube-system
Error from server (Forbidden): pods is forbidden: User "xianbin" cannot list resource "pods" in API group "" in the namespace "kube-system"

ClusterRole

  • 帮助
kubectl create clusterrole -h

kubectl create clusterrole NAME --verb=verb --resource=resource.group [--resource-name=resourcename] [--dry-run=server|client|none] [options]
  • dry-run
kubectl create clusterrole cluster-reader --verb=get,list,watch --resource=pods -o yaml --dry-run=client
  • clusterrole-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  creationTimestamp: null
  name: cluster-reader
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch

  • 执行
$ kubectl apply -f clusterrole-demo.yaml
clusterrole.rbac.authorization.k8s.io/cluster-reader created
kubectl get clusterrole cluster-reader
NAME             CREATED AT
cluster-reader   2022-03-19T21:56:47Z
$ kubectl describe clusterrole cluster-reader
Name:         cluster-reader
Labels:       <none>
Annotations:  <none>
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  pods       []                 []              [get list watch]

默认的 clusterrole

获取所有 clusterrole:

kubectl get clusterrole

说明:

  • admin: 在指定命名空间 rolebinding 可以给指定命名空间的管理员权限

  • cluster-admin: kubernetes 集群管理员

  • 获取对应的 yaml 文件

kubectl get clusterrole admin -o yaml

ClusterRoleBinding

  • 帮助
kubectl create clusterrolebinding -h

kubectl create clusterrolebinding NAME --clusterrole=NAME [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run=server|client|none] [options]
  • dry-run
kubectl create clusterrolebinding xianbin-read-all-pods --clusterrole=cluster-reader --user=xianbin --dry-run=client -o yaml
  • clusterrolebinding-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  creationTimestamp: null
  name: xianbin-read-all-pods
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: xianbin

  • 执行
$ kubectl apply -f clusterrolebinding-demo.yaml
clusterrolebinding.rbac.authorization.k8s.io/xianbin-read-all-pods created
$ kubectl get clusterrolebindings xianbin-read-all-pods
NAME                    ROLE                         AGE
xianbin-read-all-pods   ClusterRole/cluster-reader   17s
$ kubectl describe clusterrolebindings xianbin-read-all-pods
Name:         xianbin-read-all-pods
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  ClusterRole
  Name:  cluster-reader
Subjects:
  Kind  Name     Namespace
  ----  ----     ---------
  User  xianbin
  • 测试如下命令,均有对应的权限
kubectl get pod
kubectl get pod -n kube-system
kubectl get pod -n ingress-nginx

若删除资源没有权限:

$ kubectl -n ingress-nginx delete pod ingress-nginx-admission-create-bkrxs
Error from server (Forbidden): pods "ingress-nginx-admission-create-bkrxs" is forbidden: User "xianbin" cannot delete resource "pods" in API group "" in the namespace "ingress-nginx"

结论:clusterrolebinding 对应的 clusterrole 后,用户或组有所有命名空间的相应的权限

默认的 cluster-admin 介绍

获取 cluster-admin 配置,默认由组 system:masters 绑定到 ClusterRole cluster-admin 上,详情如下:

$ kubectl get clusterrolebinding cluster-admin -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  creationTimestamp: "2022-02-26T16:19:44Z"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: cluster-admin
  resourceVersion: "149"
  uid: 495f9241-9fa1-4f8d-863c-7c48a3f9acf9
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group  # 组
  name: system:masters
  • system:masters 默认配置在 apiserver-kubelet-client.crt 中,如下:
$ cd /etc/kubernetes/pki/
$ openssl x509 -in apiserver-kubelet-client.crt -text noout
$ root@k8s-master:/etc/kubernetes/pki# openssl x509 -in ./apiserver-kubelet-client.crt -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 4641301856873790702 (0x40693772ba52bcee)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN = kubernetes
        Validity
            Not Before: Feb 26 16:19:27 2022 GMT
            Not After : Feb 26 16:19:27 2023 GMT
        Subject: O = system:masters, CN = kube-apiserver-kubelet-client
  • 解析 ~/.kube/config 中 kubenetes-admin 的 client-certificate-data,通过
$ echo $client-certificate-data | base64 -d >> kubeneters-admin.crt
$ openssl x509 -in kubeneters-admin.crt -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1774077173576686618 (0x189ec9ca372adc1a)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN = kubernetes
        Validity
            Not Before: Feb 26 16:19:27 2022 GMT
            Not After : Feb 26 16:19:29 2023 GMT
        Subject: O = system:masters, CN = kubernetes-admin

可以看到 kubeneters-adminkube-apiserver-kubelet-client 均属于 system:masters 组。

Subject 中:

  • O: 表示组
  • CN: 表示用户名

RoleBinding 绑定 ClusterRole

该场景下,ClusterRole 的权限,只针对 RoleBinding 所在的名称空间生效。因此,我们可以定义通用的 ClusterRole。

下面示例,为 xianbin 用户配置 cluster-reader,结构如下:

xianbin -> rolebinding - clusterrole: cluster-reader
  • 清理已有绑定
kubectl get clusterrolebinding xianbin-read-all-pods
kubectl delete clusterrolebinding xianbin-read-all-pods
kubectl delete rolebindings xianbin-read-pods
  • 新建 rolebinding
kubectl create rolebinding xianbin-read-pods --clusterrole=cluster-reader --user=xianbin --dry-run=client -o yaml
  • rolebinding-clusterrole-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  creationTimestamp: null
  name: xianbin-read-pods
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: xianbin

  • 执行
root@k8s-master:~/manifests# kubectl apply -f rolebinding-clusterrole-demo.yaml
rolebinding.rbac.authorization.k8s.io/xianbin-read-pods created
root@k8s-master:~/manifests# kubectl describe rolebindings xianbin-read-pods
Name:         xianbin-read-pods
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  ClusterRole
  Name:  cluster-reader
Subjects:
  Kind  Name     Namespace
  ----  ----     ---------
  User  xianbin
  • 测试
xiexianbin@k8s-master:~$ kubectl get pod
NAME             READY   STATUS    RESTARTS       AGE
hello-app-sf-0   1/1     Running   0              14h
hello-app-sf-1   1/1     Running   0              14h
t1               1/1     Running   1 (2d6h ago)   14h
xiexianbin@k8s-master:~$ kubectl get pod -n kube-system
Error from server (Forbidden): pods is forbidden: User "xianbin" cannot list resource "pods" in API group "" in the namespace "kube-system"

结论:访问 default 命名空间下的 pod 正常,其他的不正常

default 命名空间创建管理员

  • 清理权限
kubectl delete -f rolebinding-clusterrole-demo.yaml
  • 创建命令
kubectl create rolebinding default-ns-admin --clusterrole=admin --user=xianbin

xianbin 用户只有 default 命名空间的管理员权限

最新评论
加载中...
Home Archives Categories Tags Statistics