k8s中的访问控制

k8s官方文档关于访问控制的说明


1. 概述

用户可以通过 kubectl命令行、客户端库或者通过发送 REST 请求访问 API Server 。用户被分为用户账户和 Kubernetes 服务账户,二者都可以被授权进行 API Server 访问。 请求到达 API Server后会经过几个阶段,具体说明如图:
访问流程
如果客户端想要访问Api server 需要经过如下三个步骤:

  1. 认证(Authenticating
  2. 授权(Authorization
  3. 准入控制(Admission Controllers

认证可以理解为Api Server需要知道你是谁。

授权可以理解为在知道你是谁的情况下,你可以对哪些资源进行哪些操作。

准入控制可以理解为对于一些存在关联关系的资源,需要进行进一步的权限判断。


2. 认证

客户端想要访问Api Server首先需要的就是进行认证,只有认证通过了,k8s知道你是谁,才有后面的授权和准入控制。如果请求认证失败,则请求被拒绝,返回 401 状态码。

在k8s中有两种用户:用户账户和服务账户。

用户账户可以理解为人类使用的账号,服务账户可以理解为k8s的组件或者是集群中的Pod中的进程访问Api Server的账号

Kubernetes 区分用户账户和服务账户的概念主要基于以下原因:

  • 用户账户是针对人而言的。 服务账户是针对运行在 pod 中的进程而言的。
  • 用户账户是全局性的。 其名称在集群各 namespace 中都是全局唯一的,未来的用户资源不会做 namespace 隔离, 服务账户是 namespace 隔离的。
  • 通常情况下,集群的用户账户可能会从企业数据库进行同步,其创建需要特殊权限,并且涉及到复杂的业务流程。 服务账户创建的目的是为了更轻量,允许集群用户为了具体的任务创建服务账户 ( 即权限最小化原则 )。
  • 对人员和服务账户审计所考虑的因素可能不同。
  • 针对复杂系统的配置可能包含系统组件相关的各种服务账户的定义。 因为服务账户可以定制化地创建,并且有 namespace 级别的名称,这种配置是很轻量的。

下面的图片描述了认证的流程。
在这里插入图片描述


2.1 服务账户-ServiceAccount

ServiceAccount是 Kubernetes API 所管理的用户。它们被绑定到特定的名称空间, 或者由 API 服务器自动创建,或者通过 API 调用创建。

ServiceAccount与一组以 Secret 保存的凭据相关,这些凭据会被通过volume的方式自动挂载到 Pod 中的/var/run/secrets/kubernetes.io/serviceaccount路径下,且文件名是secret的名称,从而允许集群内的进程访问 Kubernetes API。可以认为ServiceAccount就是集群中的Pod中的进程访问Api server的凭证。

查看一下k8s集群中默认存在的ServiceAccount。sa是ServiceAccount的简写。

# sa 是 serviceaccount的简写
[root@k8s-master01 access-control]$ kubectl get sa --all-namespaces 
NAMESPACE         NAME                                 SECRETS   AGE
default           default                              1         23h
kube-node-lease   default                              1         23h
kube-public       default                              1         23h
kube-system       attachdetach-controller              1         23h
kube-system       bootstrap-signer                     1         23h
kube-system       certificate-controller               1         23h
kube-system       clusterrole-aggregation-controller   1         23h
kube-system       coredns                              1         23h
kube-system       cronjob-controller                   1         23h

正是这些ServiceAccount的存在,才可以让集群中的Pod(例如coredns)能够访问Api Server

[root@k8s-master01 ~]# kubectl describe pod -n kube-system coredns-9d85f5447-b8pdz 
Name:                 coredns-9d85f5447-b8pdz
Namespace:            kube-system
......
Containers:
  coredns:
    Container ID:  docker://b260fe1bcaea002a40679d86ae3b992d0ccbe05ef73592bea1cf608388eb0f9f
......
    Mounts:
      /etc/coredns from config-volume (ro)
      /var/run/secrets/kubernetes.io/serviceaccount from coredns-token-hpr7b (ro)

2.1.1 ServiceAccount的基本操作

ServiceAccount是标准的k8s资源对象,可以使用命令行或者是资源清单进行创建。

命令行的方式创建

# sa 是 serviceaccount的简写
[root@k8s-master01 access-control]# kubectl create sa my-sa
serviceaccount/my-sa created

使用资源清单的方式创建

[root@k8s-master01 access-control]# cat > create-sa.yaml << EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-sa2
EOF

创建my-sa2

[root@k8s-master01 access-control]# kubectl create -f create-sa.yaml

使用kubectl delete sa <service-account-name> -n <namespace-name> 或者是 kubectl delete -f xxx.yaml 命令删除创建的ServiceAccount

查看一下创建的ServiceAccount

[root@k8s-master01 access-control]# kubectl get sa my-sa 
NAME    SECRETS   AGE
my-sa   1         7s
[root@k8s-master01 access-control]# kubectl describe sa my-sa 
Name:                my-sa
Namespace:           default
Labels:              <none>
Annotations:         <none>
Image pull secrets:  <none>
# 有一个类型为serviceaccount-token的secret与之关联
Mountable secrets:   my-sa-token-cd85c
Tokens:              my-sa-token-cd85c
Events:              <none>

我们每创建一个ServiceAccount就会有类型为service-account-tokenSecret与之关联。

查看与my-sa关联的Secret

[root@k8s-master01 access-control] # kubectl get secret my-sa-token-fdwdl
NAME                TYPE                                  DATA   AGE
my-sa-token-fdwdl   kubernetes.io/service-account-token   3      19s
#查看secret中的数据
[root@k8s-master01 access-control] # kubectl describe secret my-sa-token-fdwdl
Name:         my-sa-token-fdwdl
Namespace:    default
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: my-sa
              kubernetes.io/service-account.uid: a183161e-1816-4a44-9d15-a085df6e741d

Type:  kubernetes.io/service-account-token

Data
====
token:      ......
ca.crt:     1025 bytes
namespace:  7 bytes

ServiceAccount可以包含imagePullSecretssecrets。我们可以将拉取docker镜像的凭证,隐藏在ServiceAccount中,而不是直接暴露在pod.spec的定义中。

如果创建的Pod没有指定ServiceAccount,那么就会使用集群中,Pod所在名称空间的名为defaultServiceAccountdefaultServiceAccount的权限非常小,只能访问当前Pod自己的资源。

查看一下各个名称空间下默认的ServiceAccount

[root@k8s-master01 access-control]# kubectl get sa --all-namespaces 
NAMESPACE         NAME                                 SECRETS   AGE
default           default                              1         23h
kube-node-lease   default                              1         23h
kube-public       default                              1         23h
kube-system       default                              1         23h
......

2.1.2 Pod使用自定义的ServiceAccount

除了名称空间下默认的ServiceAccount,我们还可以让Pod使用自定义的ServiceAccount,当我们给这个自定义的ServiceAccount赋予了相应的权限,那么这Pod就可以访问集群中的资源,一个典型的例子就是dashboard。

案例演示

[root@k8s-master01 access-control]# cat > pod-sa.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
  name: pod-sa
spec:
  serviceAccountName: my-sa
  containers:
  - name: pod-sa
    image: wangyanglinux/myapp:v1
    imagePullPolicy: IfNotPresent
EOF

创建这个Pod,并且查看Pod使用的ServiceAccount

[root@k8s-master01 access-control]# kubectl create -f pod-sa.yaml 
pod/pod-sa created
[root@k8s-master01 access-control]# kubectl describe pod pod-sa

......
pullable://wangyanglinux/myapp@sha256:9c3dc30b5219788b2b8a4b065f548b922a34479577befb54b03330999d30d513
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Mon, 12 Oct 2020 22:36:44 +0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from my-sa-token-cd85c (ro)
......
Volumes:
  my-sa-token-cd85c:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  my-sa-token-cd85c
    Optional:    false

另外ServiceAccount关联的类型为service-account-tokenSecret会被自动挂载到容器的/var/run/secrets/kubernetes.io/serviceaccount路径下。文件名token的名称,文件内容为经过base64解密后的字符串。

[root@k8s-master01 access-control]# kubectl exec pod-sa -- ls -al /var/run/secrets/kubernetes.io/serviceaccount
total 4
drwxrwxrwt    3 root     root           140 Oct 14 02:35 .
drwxr-xr-x    3 root     root          4096 Feb 25  2018 ..
drwxr-xr-x    2 root     root           100 Oct 14 02:35 ..2020_10_14_02_35_57.281690733
lrwxrwxrwx    1 root     root            31 Oct 14 02:35 ..data -> ..2020_10_14_02_35_57.281690733
lrwxrwxrwx    1 root     root            13 Oct 14 02:35 ca.crt -> ..data/ca.crt
lrwxrwxrwx    1 root     root            16 Oct 14 02:35 namespace -> ..data/namespace
lrwxrwxrwx    1 root     root            12 Oct 14 02:35 token -> ..data/token
[root@k8s-master01 access-control]# kubectl exec pod-sa -- cat /var/run/secrets/kubernetes.io/serviceaccount/token
eyJhbGciOiJSUzI1NiIsImtpZCI6IlFfX3o4OVVzYUgyMUVGWDJ1RU9nNEl5YlFhX01RYWhlTEVtd3EwU0dpblUif
......

2.2 用户账户

我们可以使用kubectl命令行去访问k8s集群,那么这是怎么经过Api Server的认证呢?

在k8s中使用 kubeconfig 文件来组织有关集群、用户、命名空间和身份认证机制的信息。kubectl 命令行工具使用 kubeconfig 文件来查找选择集群所需的信息,并与集群的 API 服务器进行通信。

默认情况下,kubectl$HOME/.kube 目录下查找名为 config 的文件。 可以通过设置 KUBECONFIG 环境变量或者设置 --kubeconfig参数来指定其他 kubeconfig 文件。

使用 kubeconfig 文件,可以组织集群、用户和命名空间。还可以定义上下文,以便在集群和命名空间之间快速轻松地切换。

使用 kubectl config --help 查看一下命令的使用

[root@k8s-master01 access-control] $ kubectl config --help
Modify kubeconfig files using subcommands like "kubectl config set current-context my-context"

 The loading order follows these rules:

  1.  If the --kubeconfig flag is set, then only that file is loaded. The flag may only be set once and no merging takes place.
  2.  If $KUBECONFIG environment variable is set, then it is used as a list of paths (normal path delimiting rules for your system). These paths are merged. When a value is modified, it is modified in the file that defines the stanza. When a value is created, it is created in the first file that exists. If no files in the chain exist, then it creates the last file in the list.
  3.  Otherwise, ${HOME}/.kube/config is used and no merging takes place.

Available Commands:
  current-context Displays the current-context
  delete-cluster  Delete the specified cluster from the kubeconfig
  delete-context  Delete the specified context from the kubeconfig
  get-clusters    Display clusters defined in the kubeconfig
  get-contexts    Describe one or many contexts
  rename-context  Renames a context from the kubeconfig file.
  set             Sets an individual value in a kubeconfig file
  set-cluster     Sets a cluster entry in kubeconfig
  set-context     Sets a context entry in kubeconfig
  set-credentials Sets a user entry in kubeconfig
  unset           Unsets an individual value in a kubeconfig file
  use-context     Sets the current-context in a kubeconfig file
  view            Display merged kubeconfig settings or a specified kubeconfig file

Usage:
  kubectl config SUBCOMMAND [options]

Use "kubectl <command> --help" for more information about a given command.
Use "kubectl options" for a list of global command-line options (applies to all commands).

上面的英文主要是在强调如果存在多个 kubeconfig 配置文件,配置优先级的问题。

--kubeconfig命令行、KUBECONFIG环境变量、${HOME}/.kube/config,这三个配置文件的优先级

  1. 只要在命令行中设置 --kubeconfig命令行,那么所有的配置都以命令行中指定的配置文件中的配置信息为准。
  2. 如果没有设置--kubeconfig命令行,并且设置了KUBECONFIG环境变量,那么将它用作应合并的文件列表。合并的原则是就近原则。例如如果两个文件都指定了 red-user,则仅使用第一个文件的 red-user 中的值。即使第二个文件在 red-user 下有非冲突条目,也要丢弃它们。
    一个环境变量可以设置多个值,在linux中通过":"分割。例如export KUBECONFIG=$KUBECONFIG:$HOME/.kube/config
  3. 如果既没有设置 --kubeconfig命令行,也没有设置KUBECONFIG环境变量,使用${HOME}/.kube/config配置文件。

主要的命令有:

  1. 对于context上下文的增删改查,以及切换上下文context。current-contextdelete-contextget-contextsrename-contextset-contextuse-context
  2. 对于cluster集群的增删改查。get-clustersdelete-clusterset-cluster
  3. 对于user的新增。set-credentials
  4. setunset可以设置或者是删除cluster、context、user

先使用kubectl config view 命令,查看一下当前的cluster、context、user、namespace

[root@k8s-master01 access-control] $ kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://192.168.1.180: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

可以看到配置文件中存在着集群名为kubernetes,用户名为kubernetes-admin,context为kubernetes-admin@kubernetes。context一般定义的格式为用户名@集群名称

这是使用kubeadm工具初始化集群之后,默认生成的配置文件。


2.2.1 cluster

cluster可以理解为是对集群的抽象,主要的配置有 Api Server 服务器地址和端口号、certificate-authority ca证书地址等。
使用kubectl config set-cluster --help 命令查看一下如何设置一个集群

[root@k8s-master01 access-control] # kubectl config set-cluster --help
Sets a cluster entry in kubeconfig.
......
Usage:
  kubectl config set-cluster NAME [--server=server] [--certificate-authority=path/to/certificate/authority]
[--insecure-skip-tls-verify=true] [--tls-server-name=example.com] [options]

Use "kubectl options" for a list of global command-line options (applies to all commands).

这里我们使用--kubeconfig命令,将配置信息保存到指定路径下的文件中。我们先创建一个集群

[root@k8s-master01 access-control]# kubectl config set-cluster k8s1 --server=https://192.168.1.180:6443 --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --kubeconfig=/temp/k8s/config
Cluster "k8s1" set.

解释一下上面的命令
--server=https://192.168.1.180:6443 指定Api Server的ip和端口
--certificate-authority 指定kubernetes集群中ca.crt证书的地址。
--embed-certs=true 是否嵌入证书信息,默认不嵌入,true表示嵌入。
--kubeconfig=/temp/k8s/config 将配置信息保存到指定文件中,如果没有就创建或者是读取配置文件

查看一下新定义的配置信息,这里需要带上--kubeconfig=/temp/k8s/config

[root@k8s-master01 access-control]# kubectl config view --kubeconfig=/temp/k8s/config 
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://192.168.1.180:6443
  name: k8s1
contexts: null
current-context: ""
kind: Config
preferences: {}
users: null
#查看一下生成的配置文件
[root@k8s-master01 access-control]# cat /temp/k8s/config 
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: ......
    server: https://192.168.1.180:6443
  name: k8s1
contexts: null
current-context: ""
kind: Config
preferences: {}
users: null

如果要删除cluser,可以使用kubectl config delete-cluster NAME [options]或者是kubectl config unset clusters.<NAME> [options]命令,当然了如果使用了自定义的配置文件,需要使用--kubeconfig=path,指定配置文件的路径。


2.2.1 user、gruop

k8s官方文档证书管理

这里使用OpenSSL的方式,其他方式类似,可以参照官方文档。

这里如果要定义用户或者是组,就需要由集群的ca.crtca.key签署客户端的私钥和证书

这里需要先自己定义生成私钥,然后生成证书签署请求,定义签署的用户和组,最后根据集群中的ca.crtca.key签署证书签署请求,生成对应的客户端的.crt文件。

集群中的ca.crtkey.crt默认放置在/etc/kubernetes/pki/路径下。

[root@k8s-master01 /]# cd /etc/kubernetes/pki/
[root@k8s-master01 pki]# ls
apiserver.crt              apiserver.key                 ca.crt  etcd                front-proxy-client.crt     sa.pub
apiserver-etcd-client.crt  apiserver-kubelet-client.crt  ca.key  front-proxy-ca.crt  front-proxy-client.key  
apiserver-etcd-client.key  apiserver-kubelet-client.key  ca.srl  front-proxy-ca.key            sa.key

2.2.1.1 生成私钥
#生成私钥
[root@k8s-master01 pki]# openssl genrsa -out magedu.key 2048
Generating RSA private key, 2048 bit long modulus
.............+++
......+++
e is 65537 (0x10001)
#查看生成的私钥
[root@k8s-master01 pki]# cat magedu.key 
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAtvVU8oAmvG+cFu6O+ewz/1qJbV13tghP2DlAUgYjo5jqjJNM
......
pIimlmxTFWnSKiOF56lkBSDaHUtQEQs8Kqh7mfzAg7r7cx7nLrRp5w==
-----END RSA PRIVATE KEY-----

2.2.1.2 基于配置文件生成证书签名请求
#这里的magedu就是用户
[root@k8s-master01 pki]# openssl req -new -key magedu.key -out magedu.csr -subj "/CN=magedu/O=app1/O=app2"
[root@k8s-master01 pki]# cat magedu.csr 
-----BEGIN CERTIFICATE REQUEST-----
......
gv9vfI83POMCeNYvaIuAZy87pLjj5uA65rU=
-----END CERTIFICATE REQUEST----

这里CN字段表示为用户名,O字段表示用户组。


2.2.1.3 由ca.crt和ca.key签署生成证书
[root@k8s-master01 pki]# openssl x509 -req -in magedu.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out magedu.crt -days 365
Signature ok
subject=/CN=magedu
Getting CA Private Key
[root@k8s-master01 pki]# cat magedu.crt 
-----BEGIN CERTIFICATE-----
MIICojCCAYoCCQDVh+opYUNFDDANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwpr
......
#查看一下证书中的内容
[root@k8s-master01 pki]# openssl x509 -in magedu.crt -text -noout
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            d5:87:ea:29:61:43:45:0c
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=kubernetes
        Validity
            Not Before: Oct 18 01:55:53 2020 GMT
            Not After : Oct 18 01:55:53 2021 GMT
        Subject: CN=magedu
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:b6:f5:54:f2:80:26:bc:6f:9c:16:ee:8e:f9:ec:
					......
                Exponent: 65537 (0x10001)
    Signature Algorithm: sha256WithRSAEncryption
         74:5b:f2:a7:10:4f:c1:e1:85:37:b3:08:44:64:18:12:57:10:
		 ......

2.2.1.4 生成user
#查看一下生成用户的帮助信息
[root@k8s-master01 pki]# kubectl config set-credentials -h
Sets a user entry in kubeconfig
......
Usage:
  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]

Use "kubectl options" for a list of global command-line options (applies to all commands).

可以看出需要指定ca.crt证书的地址、私钥的地址等。当然了也可以指定名称空间,将用户限制在指定的名称空间下。

接下来创建magedu这个用户,指定客户端的.crt证书的地址、私钥的地址,指定使用的配置文件/temp/k8s/config

[root@k8s-master01 pki]# kubectl config set-credentials magedu --client-certificate=./magedu.crt --client-key=./mageedu.key --kubeconfig=/temp/k8s/config
User "magedu" set.

查看一下定义的配置文件/temp/k8s/config

[root@k8s-master01 pki]# kubectl config view --kubeconfig=/temp/k8s/config 
apiVersion: v1
clusters:
- cluster:
    certificate-authority: /etc/kubernetes/pki/ca.crt
    server: https://192.168.1.180:6443
  name: k8s1
contexts: null
current-context: ""
kind: Config
preferences: {}
users:
- name: magedu
  user:
    client-certificate: /etc/kubernetes/pki/magedu.crt
    client-key: /etc/kubernetes/pki/mageedu.key

可以看到已经定义了一个cluser和一个user。

如果要删除用户,可以使用kubectl config unset users.<username>命令

[root@k8s-master01 pki]# kubectl config unset users.magedu --kubeconfig=/temp/k8s/config
Property "users.magedu" unset.

2.2.1 context

通过 kubeconfig 文件中的 context 元素,使用简便的名称来对访问参数进行分组。每个上下文都有三个参数:cluster、namespace 和 user。可以认为context是对cluster、namespace、user的一个封装。默认情况下,kubectl 命令行工具使用当前上下文中的参数与集群进行通信。

#查看一下当前使用的context
[root@k8s-master01 access-control]# kubectl config current-context 
kubernetes-admin@kubernetes
#列举出所有的context
[root@k8s-master01 access-control]# kubectl config get-contexts 
CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin
#创建一个context
[root@k8s-master01 access-control]# kubectl config set-context magedu@k8s1 --cluster=k8s1 --user=magedu --kubeconfig=/temp/k8s/config

解析一下上面的命令

  • --cluser 指定集群的名称。context的名称一般的格式为:username[-namespace]@clsurer_name,如果设置了namespace,可以将namespace也设置到对应的context的名称中。
  • --user指定用户。
  • --kubeconfig指定使用的配置文件。

查看一下创建的context

[root@k8s-master01 pki]# kubectl config get-contexts --kubeconfig=/temp/k8s/config 
CURRENT   NAME          CLUSTER   AUTHINFO   NAMESPACE
          magedu@k8s1   k8s1      magedu

删除context,可以使用kubectl config delete-context NAME [options]或者是kubectl config unset contexts.<NAME> [options]命令

使用刚才创建的名为magedu@k8s1的context

[root@k8s-master01 access-control]# kubectl config use-context magedu@k8s1 --kubeconfig=/temp/k8s/config 
Switched to context "magedu@k8s1".
[root@k8s-master01 pki]# kubectl config current-context --kubeconfig=/temp/k8s/config 
magedu@k8s1

我们使用一下刚才创建的context去访问k8s集群

[root@k8s-master01 pki]# kubectl get pod -n kube-system --kubeconfig=/temp/k8s/config 
Error from server (Forbidden): pods is forbidden: User "magedu" cannot list resource "pods" in API group "" at the cluster scope

我们发现返回Forbidden,状态码为403。在restful风格的api中,403表示为未授权。这说明我们没有为magedu这个账号授予访问kube-system名称空间下pod的访问权限。接下来我们继续讲解如何为用户账号和服务账号进行授权。


3. 授权

k8s官方文档RBAC进行授权

我们使用用户账号或者是服务账号去访问k8s中的资源,通过认证之后,就要校验其是否有关于相关资源操作的权限了。

在k8s中授权有4中方式:

  • Node - 一个专用授权程序,根据计划运行的 pod 为 kubelet 授予权限。了解有关使用节点授权模式的更多信息,请参阅节点授权。
  • ABAC - 基于属性的访问控制(ABAC)定义了一种访问控制范例,通过使用将属性组合在一起的策略,将访问权限授予用户。策略可以使用任何类型的属性(用户属性,资源属性,对象,环境属性等)。要了解有关使用 ABAC 模式的更多信息,请参阅 ABAC 模式。
  • RBAC - 基于角色的访问控制(RBAC)是一种基于企业内个人用户的角色来管理对计算机或网络资源的访问的方法。在此上下文中,权限是单个用户执行特定任务的能力,例如查看,创建或修改文件。要了解有关使用 RBAC 模式的更多信息,请参阅 RBAC 模式。
    当指定的 RBAC(基于角色的访问控制)使用 rbac.authorization.k8s.io API 组来驱动授权决策时,允许管理员通过 Kubernetes API 动态配置权限策略。
    要启用 RBAC,请使用 --authorization-mode = RBAC 启动 apiserver 。
  • Webhook - WebHook 是一个 HTTP 回调:发生某些事情时调用的 HTTP POST;通过 HTTP POST 进行简单的事件通知。实现 WebHook 的 Web 应用程序会在发生某些事情时将消息发布到 URL。要了解有关使用 Webhook 模式的更多信息,请参阅 Webhook 模式。

基于角色(Role)的访问控制(RBAC)是一种基于企业中用户的角色来调节控制对计算机或网络资源的访问方法。

RBAC 使用 rbac.authorization.k8s.io API 组 来驱动鉴权操作,允许管理员通过 Kubernetes API 动态配置策略。

在 1.8 版本中,RBAC 模式是稳定的并通过 rbac.authorization.k8s.io/v1 API 提供支持。要启用 RBAC,在启动 API 服务器时添加 --authorization-mode=RBAC 参数。

配置多个授权模块时,将按顺序检查每个模块。 如果任何授权模块批准或拒绝请求,则立即返回该决定,并且不会与其他授权模块协商。 如果所有模块对请求没有意见,则拒绝该请求。一个拒绝响应返回 HTTP 状态代码 403 。

下面这个图描述了用户账户和服务账户去访问Api Server的交互过程
在这里插入图片描述


3.1 k8s中的resources

在k8s中对于资源的操作的定义与Restful风格类似,请求方式代表一种对资源的操作类型。
下面的表格列举了这些操作和定义

HTTP 动词request 动词
POSTcreate
GET,HEADget (单个资源),list (资源集合)
PUTupdate
PATCHpatch
DELETEdelete (单个资源),deletecollection (资源集合)

我们可以使用kube-proxy开启一个代理,去访问api server

[root@k8s-master01 ~]# kubectl proxy -p 8080
Starting to serve on 127.0.0.1:8080

-p 就是指定端口

我们使用curl命令去访问一下proxy,进而访问Api Server。

[root@k8s-master01 access-control]# curl http://127.0.0.1:8080/api/v1/namespaces/kube-system
{
  "kind": "Namespace",
  "apiVersion": "v1",
  "metadata": {
    "name": "kube-system",
    "selfLink": "/api/v1/namespaces/kube-system",
    "uid": "101cd2e4-56b0-49c5-98df-288b2fe7e8c5",
    "resourceVersion": "15",
    "creationTimestamp": "2020-10-11T15:08:35Z"
  },
  "spec": {
    "finalizers": [
      "kubernetes"
    ]
  },
  "status": {
    "phase": "Active"
  }
}

在k8s中一些资源一般以其名称字符串来表示,这些字符串一般会在API的URL地址中出现;同时某些资源也会包含子资源,例如logs资源就属于pods的子资源,API中的URL样例如下

GET /apis/apps/v1/namespaces/{namespace}/pods/{name}/log

我们查看一下kube-system名称空间中的名为coredns的deployment

[root@k8s-master01 access-control]# curl http://127.0.0.1:8080/apis/apps/v1/namespaces/kube-system/deployments/coredns
{
  "kind": "Deployment",
  "apiVersion": "apps/v1",
  ......
}

3.2 Role、ClusterRole

在 RBAC API 中,一个角色包含一组相关权限的规则。权限是纯粹累加的(不存在拒绝某操作的规则)。 角色可以用 Role 来定义到某个命名空间上, 或者用 ClusterRole 来定义到整个集群作用域。


3.2.1 Role

一个 Role 只可以用来对某一命名空间中的资源赋予访问权限。 下面的 Role 示例定义到名称为 "default" 的命名空间,可以用来授予对该命名空间中的 Pods 的读取权限:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader
rules:
  # "" 指定核心 API 组
- apiGroups:
  - ""
  resources:
  - "pods"
  verbs:
  - "get"
  - "watch"
  - "list"

3.2.2 ClusterRole

ClusterRole 可以授予的权限和 Role 相同, 但是因为 ClusterRole 属于集群范围,所以它也可以授予以下访问权限:

  • 集群范围资源 (比如 nodes)
  • 非资源端点(比如 “/healthz”)
  • 跨命名空间访问的有名字空间作用域的资源(如 Pods),比如运行命令kubectl get pods --all-namespaces 时需要此能力

需要特别注意的是ClusterRole是属于集群范围,不属于任何名称空间。
下面的 ClusterRole 示例可用来对某特定命名空间下的 Secrets 的读取操作授权, 或者跨所有命名空间执行授权(取决于它是如何绑定的):

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  # 此处的 "namespace" 被省略掉是因为 ClusterRoles 是没有命名空间的。
  name: secret-reader
rules:
- apiGroups:
  - ""
  resources:
  - "secrets"
  verbs:
  - "get"
  - "watch"
  - "list"

查看一下集群中默认存在的ClusterRole

[root@k8s-master01 access-control]# kubectl get clusterrole
NAME                                                                   AGE
admin                                                                  8d
cluster-admin                                                          8d
edit                                                                   8d
flannel                                                                8d
nginx-ingress-clusterrole                                              5d1h
system:aggregate-to-admin                                              8d
......
view                                                                   8d

3.2.3 对资源的引用

我们想要对pod的log这个资源进行定义,在这种情况下,“pods” 是有命名空间的资源,而 “log” 是 pods 的子资源。在 RBAC 角色中, 使用"/"分隔资源和子资源。允许一个主体要同时读取 pods 和 pod logs,你可以这么写:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-and-pod-logs-reader
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list"]

对于某些请求,也可以通过 resourceNames 列表按名称引用资源。 在指定时,可以将请求类型限制资源的单个实例。限制只可以 “get” 和 “update” 的单一configmap,你可以这么写:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: configmap-updater
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  resourceNames: ["my-configmap"]
  verbs: ["update", "get"]

3.3 RoleBinding 和 ClusterRoleBinding

角色绑定(RoleBinding)是将角色中定义的权限赋予一个或者一组用户。 它包含若干主体(用户,组和服务账户)的列表和对这些主体所获得的角色的引用。 可以使用 RoleBinding 在指定的命名空间中执行授权, 或者在集群范围的命名空间使用 ClusterRoleBinding 来执行授权。

RoleBinding 或者 ClusterRoleBinding 需要绑定角色到主体。主体可以是组,人类用户或者服务账户。

人类用户是由字符串表示,它们可以是普通的用户名,像 “alice”,或者是 邮件格式 “bob@example.com”,或者是数字ID。由 Kubernetes 管理员配置身份认证模块需要的格式。RBAC 鉴权系统不对格式作任何要求,但是前缀 system: 是 Kubernetes 系统保留的, 所以管理员要确保配置的用户名不能出现上述前缀格式。

用户组信息是 Kubernetes 现在提供的一种身份验证模块,与用户一样,对组的字符串没有格式要求, 只是不能使用保留的前缀 system:

服务账号的用户名前缀为system:serviceaccount:, 属于前缀为 system:serviceaccounts: 的用户组。

用户和角色都是多对多的关系,可以理解RoleBindingClusterRoleBinding就是多对多的中间表,将用户和角色进行绑定


3.3.1 Role绑定RoleBinding

一个 RoleBinding 可以引用同一的命名空间中的 Role 。 下面的例子 RoleBinding 将 “pod-reader” 角色授予在 “default” 命名空间中的用户 “jane”; 这样,用户 “jane” 就具有了读取 “default” 命名空间中 pods 的权限。
roleRef 里的内容决定了实际创建绑定的方法。kind 可以是 RoleClusterRolename 将引用你要指定的 RoleClusterRole 的名称。在下面的例子中,角色绑定使用 roleRef 将用户 “jane” 绑定到前文创建的角色 Role,其名称是 pod-reader

apiVersion: rbac.authorization.k8s.io/v1
# 此角色绑定使得用户 "jane" 能够读取 "default" 命名空间中的 Pods
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User
  name: jane # Name is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role #this must be Role or ClusterRole
  name: pod-reader # 这里的名称必须与你想要绑定的 Role 或 ClusterRole 名称一致
  apiGroup: rbac.authorization.k8s.io

3.3.2 RoleBinding绑定ClusterRole

RoleBinding 也可以引用 ClusterRole,对 ClusterRole 所定义的、位于 RoleBinding 命名空间内的资源授权。 这可以允许管理者在整个集群中定义一组通用的角色,然后在多个命名空间中重用它们。可以理解为将ClusterRole进行降级,降级到RoleBinding所在名称空间,然后其所绑定的usersagroup只有RoleBinding所在名称空间的权限。

例如下面的例子,RoleBinding 绑定的是 ClusterRole, “dave” (主体,区分大小写)将只可以读取在"development" 命名空间( RoleBinding 的命名空间)中的"secrets"。

apiVersion: rbac.authorization.k8s.io/v1
# 这个角色绑定允许 "dave" 用户在 "development" 命名空间中有读取 secrets 的权限。
kind: RoleBinding
metadata:
  name: read-secrets
  namespace: development # 这里只授予 "development" 命名空间的权限。
subjects:
- kind: User
  name: dave # 名称区分大小写
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

3.3.3 ClusterRoleBingding绑定ClusterRole

最后,ClusterRoleBinding 可用来在集群级别或对所有命名空间执行授权。 下面的例子允许 “manager” 组中的任何用户读取任意命名空间中 “secrets”。

apiVersion: rbac.authorization.k8s.io/v1
# 这个集群角色绑定允许 "manager" 组中的任何用户读取任意命名空间中 "secrets"。
kind: ClusterRoleBinding
metadata:
  name: read-secrets-global
subjects:
- kind: Group
  name: manager # 名称区分大小写
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

你不能修改绑定对象所引用的 RoleClusterRole 。 试图改变绑定对象的 roleRef 将导致验证错误。想要 改变现有绑定对象中 roleRef 字段的内容,必须删除并重新创建绑定对象。
这种限制有两个主要原因:

  1. 关于不同角色的绑定是完全不一样的。更改 roleRef 需要删除/重建绑定,确保要赋予绑定的完整主体列表是新的角色(而不是只是启用修改 roleRef 在不验证所有现有 主体的情况下的,应该授予新角色对应的权限)。
  2. 使得 roleRef 不可以改变现有绑定主体用户的 update 权限, 这样可以让它们能够管理主体列表,而不能更改授予这些主体相关的角色。

4 案例演示

前面我们在k8s集群中创建了一个名为magedu的用户,接下来使用magedu这个用户进行权限演示。

4.1 前置准备工作

下面是前期的准备工作:

  1. 创建一个名为magedu的linux用户,并且设置密码。
  2. 将root用户的.kube文件夹下的内容复制到/home/magedu/路径下
  3. /temp/k8s/config复制到/home/magedu/.kube/路径下,如果存在config文件,直接覆盖
  4. 修改/home/magedu/.kube文件夹的权限为magedu:magedu

下面使用root账号进行操作

#添加magedu用户
[root@k8s-master01 access-control]# useradd magedu
#设置magedu用户的密码
[root@k8s-master01 ~]# passwd magedu
更改用户 magedu 的密码 。
新的 密码:
无效的密码: 密码少于 8 个字符
重新输入新的 密码:
passwd:所有的身份验证令牌已经成功更新。
#将.kube文件夹中的内容复制到/home/magedu目录下
[root@k8s-master01 access-control]# cp -rp /root/.kube/ /home/magedu/
#用/temp/k8s/config覆盖/home/magedu/.kube/config文件
[root@k8s-master01 access-control]# cp /temp/k8s/config /home/magedu/.kube/
#提示是否修改,修改
cp:是否覆盖"/home/magedu/.kube/config"yes
#修改/home/mageud路径下的文件的所在用户和用户组
[root@k8s-master01 access-control]# chown -R magedu:magedu /home/magedu/

重新打开一个shell窗口,使用magedu登录k8s-master01服务器。

#查看当前的配置信息
[magedu@k8s-master01 ~]$ kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority: /etc/kubernetes/pki/ca.crt
    server: https://192.168.1.180:6443
  name: k8s1
contexts:
- context:
    cluster: k8s1
    user: magedu
  name: magedu@k8s1
current-context: magedu@k8s1
kind: Config
preferences: {}
users:
- name: magedu
  user:
    client-certificate: /etc/kubernetes/pki/magedu.crt
    client-key: /etc/kubernetes/pki/mageedu.key
#查看当前正在使用的context
[magedu@k8s-master01 ~]$ kubectl config current-context
magedu@k8s1
#查看Pod
[magedu@k8s-master01 ~]$ kubectl get pod --all-namespaces
Error from server (Forbidden): pods is forbidden: User "magedu" cannot list resource "pods" in API group "" at the cluster scope

我们发现并没有权限,接下来我们为magedu这个账号赋予相应的权限,进行访问。


4.2 只能对kube-system名称空间下pod的查看的权限

这里我们先使用root账号进行操作
定义Role

[root@k8s-master01 access-control]# kubectl create role pod-reader --verb=list --resource=pod --namespace=kube-system 
role.rbac.authorization.k8s.io/pod-reader created

这里我们创建一个Role,只有kube-system名称空间下pod的list权限。

定义RoleBinding,将上面定义的Role绑定到magedu上,同时指定名称空间为kube-system

[root@k8s-master01 access-control]# kubectl create rolebinding magedu-pod-reader --role=pod-reader --user=magedu -n kube-system 
rolebinding.rbac.authorization.k8s.io/magedu-pod-reader created

现在使用magedu这个账号进行操作,打开magedu的shell界面

我们查看kube-system名称空间下的pod,发现是可以查看的。

[magedu@k8s-master01 ~]$ kubectl get pod -n kube-system
NAME                                   READY   STATUS    RESTARTS   AGE
coredns-9d85f5447-b8pdz                1/1     Running   4          8d
coredns-9d85f5447-hrmzh                1/1     Running   4          8d
etcd-k8s-master01                      1/1     Running   4          8d
kube-apiserver-k8s-master01            1/1     Running   4          8d
kube-controller-manager-k8s-master01   1/1     Running   4          8d
kube-flannel-ds-amd64-9zbxf            1/1     Running   4          8d
kube-flannel-ds-amd64-kqfjs            1/1     Running   4          8d
kube-flannel-ds-amd64-txqpc            1/1     Running   4          8d
kube-proxy-hltxq                       1/1     Running   4          8d
kube-proxy-nmg8b                       1/1     Running   4          8d
kube-proxy-rzghv                       1/1     Running   4          8d
kube-scheduler-k8s-master01            1/1     Running   4          8d

我们查看其它名称空间例如ingress-nginx中的Pod

[magedu@k8s-master01 ~]$ kubectl get pod -n ingress-nginx
Error from server (Forbidden): pods is forbidden: User "magedu" cannot list resource "pods" in API group "" in the namespace "ingress-nginx"

我们发现并没有查看ingress-nginx名称空间的Pod的权限,这是因为我们并没有赋予相应的权限。


4.3 使用RoleBinding去绑定ClusterRole

在k8s集群中存在着许多默认的ClusterRole。其中一个是admin,意思是管理员,该角色几乎拥有对资源的所有操作的权限。

现在我们有这样一个需求,为每个名称空间设置一个管理员,那么该如何实现呢?

在每个名称空间中创建一个RoleBinding,然后使用RoleBinding去绑定admin这个ClusterRole,那么就完成了需求为每个名称空间设置一个管理员。不需要在每个名称空间定义一个Role,即可完成批量绑定的操作。

查看一下k8s集群中默认存在的ClusterRole

[root@k8s-master01 access-control]# kubectl get clusterrole
NAME                                                                   AGE
admin                                                                  8d
cluster-admin                                                          8d
edit                                                                   8d
......

假如我们现在需要为ingress-nginx设置管理员,使用root账号进行操作。
在ingress-nginx名称空间中创建RoleBinding去绑定ClusterRole到magedu这个账户中。

[root@k8s-master01 access-control]# kubectl create rolebinding magedu-admin-ingress-nginx --clusterrole=admin --user=magedu -n ingress-nginx
rolebinding.rbac.authorization.k8s.io/magedu-admin-ingress-nginx created

接下来使用magedu这个账户进行验证。对ingress-nginx名称空间中的pod进行增删改查,发现都能够进行操作。

#查看Pod
[magedu@k8s-master01 ~]$ kubectl get pod -n ingress-nginx
NAME                                      READY   STATUS    RESTARTS   AGE
nginx-ingress-controller-c699bd4f-lfgtv   1/1     Running   2          5d1h
#删除Pod
[magedu@k8s-master01 ~]$ kubectl delete pod --all -n ingress-nginx
pod "nginx-ingress-controller-c699bd4f-lfgtv" deleted
[magedu@k8s-master01 ~]$ kubectl get pod -n ingress-nginx
NAME                                      READY   STATUS    RESTARTS   AGE
nginx-ingress-controller-c699bd4f-xt5w4   0/1     Running   0          19s

5. 准入控制

准入控制是Api Server插件的集合,通过添加不同的插件,实现额外的准入控制规则。甚至基于Api Server的一些主要功能都需要通过Admission Controller实现,比如ServiceAccount。
官方文档上有一份针对不同版本的准入控制器推荐列表:

NamespaceLifecycle, LimitRanger, ServiceAccount, TaintNodesByCondition, Priority, DefaultTolerationSeconds, DefaultStorageClass, StorageObjectInUseProtection, PersistentVolumeClaimResize, MutatingAdmissionWebhook, ValidatingAdmissionWebhook, RuntimeClass, ResourceQuota

列举几个插件的功能:

  • NamespaceLifecycle:防止在不存在的namespace上创建对象,防止删除系统预置namespace,删除namespace时,连带删除它的所有资源。
  • LimitRanger:确保请求的资源不会超过资源所在Namespace的LimitRange的限制。
  • SerivceAccount:实现了自动化添加ServiceAccount。
  • ResourceQuota:确保请求的资源不会超过资源的ResourceQuota限制。

由于准入控制用得不是很多,这里就不多介绍了。


6. 使用dashboard练习访问控制

前面一直在使用命令行进行操作,现在k8s官方提供了一个可视化界面dashboard,用于简化k8s的操作。
当然了还有更多强大的k8s的发行版,例如Rancher、Kubesphere等。

Dashboard可以取访问k8s集群,是使用ServiceAccount作为访问的凭证,同时创建了一系列的RoleClusterRole。这些RoleClusterRole具有一定的权限去获取集群中的资源,同时将RoleClusterRole绑定到对应的ServiceAccount上,那么Dashboard就可以取访问k8s集群。进而我们通过UI可视化界面进行操作集群了。

dashboard的github地址k8s官方文档dashboard


6.1 安装dashboard

安装dashboard的方式有两种:helm安装、资源清单的方式安装。

这里使用资源清单的方式进行演示

首先下载资源清单

[root@k8s-master01 access-control]# wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.4/aio/deploy/recommended.yaml
--2020-10-24 11:08:19--  https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.4/aio/deploy/recommended.yaml
正在解析主机 raw.githubusercontent.com (raw.githubusercontent.com)... 199.232.68.133
正在连接 raw.githubusercontent.com (raw.githubusercontent.com)|199.232.68.133|:443... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:7552 (7.4K) [text/plain]
正在保存至: “recommended.yaml”

100%[===================================================================================================================>] 7,552       16.6KB/s 用时 0.4s   

2020-10-24 11:08:22 (16.6 KB/s) - 已保存 “recommended.yaml” [7552/7552])

[root@k8s-master01 access-control]# ll
总用量 16
-rw-r--r-- 1 root root 7552 10月 24 11:08 recommended.yaml

执行配置文件recommended.yaml

[root@k8s-master01 access-control]# kubectl apply -f recommended.yaml 
namespace/kubernetes-dashboard created
serviceaccount/kubernetes-dashboard created
service/kubernetes-dashboard created
secret/kubernetes-dashboard-certs created
secret/kubernetes-dashboard-csrf created
secret/kubernetes-dashboard-key-holder created
configmap/kubernetes-dashboard-settings created
role.rbac.authorization.k8s.io/kubernetes-dashboard created
clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard created
rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created
clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created
deployment.apps/kubernetes-dashboard created
service/dashboard-metrics-scraper created
deployment.apps/dashboard-metrics-scraper created

等待大概2分钟后,查看运行情况

[root@k8s-master01 access-control]# kubectl get sa,secret,cm,role,clusterrole,rolebinding,clusterrolebinding,svc,deploy -n kubernetes-dashboard -l k8s-app
NAME                                  SECRETS   AGE
serviceaccount/kubernetes-dashboard   1         5m52s

NAME                                TYPE     DATA   AGE
secret/kubernetes-dashboard-certs   Opaque   0      5m52s
secret/kubernetes-dashboard-csrf    Opaque   1      5m52s

NAME                                      DATA   AGE
configmap/kubernetes-dashboard-settings   0      5m52s

NAME                                                  AGE
role.rbac.authorization.k8s.io/kubernetes-dashboard   5m52s

NAME                                                         AGE
clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard   5m52s

NAME                                                         AGE
rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard   5m52s

NAME                                TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/dashboard-metrics-scraper   ClusterIP   10.96.46.142     <none>        8000/TCP   5m52s
service/kubernetes-dashboard        ClusterIP   10.101.195.224   <none>        443/TCP    5m52s

NAME                                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/dashboard-metrics-scraper   1/1     1            1           5m51s
deployment.apps/kubernetes-dashboard        1/1     1            1           5m52s

6.2 进入dashboard

首先将Dashboard的Service类型修改为NodePort,当然了也可以使用Ingress的方式。

这里使用path打补丁的方式修改Service为NodePort的方式,然后查看暴露出的端口

[root@k8s-master01 access-control]# kubectl patch svc kubernetes-dashboard -p '{"spec":{"type":"NodePort"}}' -n kubernetes-dashboard 
service/kubernetes-dashboard patched
[root@k8s-master01 access-control]# kubectl get svc kubernetes-dashboard -n kubernetes-dashboard 
NAME                   TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)         AGE
kubernetes-dashboard   NodePort   10.99.194.5   <none>        443:32240/TCP   11m

在浏览器输入htts://192.168.180:32240
需要注意的是这里使用的是https而不是http
在这里插入图片描述
初始化之后需要配置token或者是kubeconfig
这里两种方式都进行演示


6.3 配置token

使用token的方式
我们先查看Dashboard组件使用的ServiceAccount所关联的Secret 的token的值

[root@k8s-master01 access-control]# kubectl get secret kubernetes-dashboard-token-tnmbz -n kubernetes-dashboard -o jsonpath='{.data.token}' | base64 -d && echo
eyJhbGciOiJSUzI1NiIsImtpZCI6Il9tRWROYTg2Y2VZSkQ15NTWczRHR2Zjl6X2tqSTFNODlYMWsifQ.eyJpc3MiOiJrdW......

这里token的值是经过base64加密的,需要使用base64进行解密,然后将其复制粘贴到输入框中。点击确认,进入Dashboard
在这里插入图片描述
进入之后发现疯狂报错
在这里插入图片描述
这是为什么呢?这是由于Dashboard默认创建以及绑定的RoleClusterRole的权限非常小,没有对RoleServiceAccount等资源进行定义。
我们可以查看一下默认创建以及绑定的RoleClusterRole

查看创建的Role

[root@k8s-master01 access-control]# kubectl get role kubernetes-dashboard -n kubernetes-dashboard -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {......}
  creationTimestamp: "2020-10-24T03:16:47Z"
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
  resourceVersion: "134085"
  selfLink: /apis/rbac.authorization.k8s.io/v1/namespaces/kubernetes-dashboard/roles/kubernetes-dashboard
  uid: f2c7ae8f-b5b7-4f67-b591-6f24c625f0b7
rules:
- apiGroups:
  - ""
  resourceNames:
  - kubernetes-dashboard-key-holder
  - kubernetes-dashboard-certs
  - kubernetes-dashboard-csrf
  resources:
  - secrets
  verbs:
  - get
  - update
  - delete
- apiGroups:
  - ""
  resourceNames:
  - kubernetes-dashboard-settings
  resources:
  - configmaps
  verbs:
  - get
  - update
- apiGroups:
  - ""
  resourceNames:
  - heapster
  - dashboard-metrics-scraper
  resources:
  - services
  verbs:
  - proxy
- apiGroups:
  - ""
  resourceNames:
  - heapster
  - 'http:heapster:'
  - 'https:heapster:'
  - dashboard-metrics-scraper
  - http:dashboard-metrics-scraper
  resources:
  - services/proxy
  verbs:
  - get

查看创建的ClusterRole

[root@k8s-master01 access-control]# kubectl get clusterrole kubernetes-dashboard -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRole","metadata":{"annotations":{},"labels":{"k8s-app":"kubernetes-dashboard"},"name":"kubernetes-dashboard"},"rules":[{"apiGroups":["metrics.k8s.io"],"resources":["pods","nodes"],"verbs":["get","list","watch"]}]}
  creationTimestamp: "2020-10-24T03:16:47Z"
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  resourceVersion: "134086"
  selfLink: /apis/rbac.authorization.k8s.io/v1/clusterroles/kubernetes-dashboard
  uid: b864995a-87cc-4757-8ae3-3b68517025c3
rules:
- apiGroups:
  - metrics.k8s.io
  resources:
  - pods
  - nodes
  verbs:
  - get
  - list
  - watch

我们想要为kubernetes-dashboard这个ServiceAccount赋予更大的权限如何做呢?

这里我们创建一个ClusterRolebinding,去绑定集群中的名为adminCluserRole,该ClusterRole几乎拥有所有的权限。然后将创建的ClusterRolebinding,绑定到kubernetes-dashboard这个ServiceAccount中。这样在UI界面就几乎能够进行访问所有名称空间下的所有的资源了。

[root@k8s-master01 access-control]# kubectl create clusterrolebinding kubernetes-dashboard-admin \ 
	--clusterrole=admin --serviceaccount=kubernetes-dashboard:kubernetes-dashboard
clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard-admin created

重新登录即可。


6.4 配置kubeconfig

具体步骤为:

  • 创建名为kubernetes的cluster
  • 保存kubernetes-dashboard这个ServiceAccount对应的Secret的值
  • 创建user
  • 创建context
  • 定义使用的上下文dashboard-kubeconfig@kubernetes
  • 复制kubeconfig文件到window环境下,进行访问测试

创建名为kubernetes的cluster,然后指定配置文件为/temp/k8s2/config

[root@k8s-master01 access-control]# kubectl config set-cluster kubernetes --server="https://192.168.1.180:6443" --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --kubeconfig=/temp/k8s2/config
Cluster "kubernetes" set.

查看刚才创建的cluster

[root@k8s-master01 access-control]# kubectl config get-clusters --kubeconfig=/temp/k8s2/config 
NAME
kubernetes

保存Secret的值

[root@k8s-master01 access-control]# token=$(kubectl get secret kubernetes-dashboard-token-89q9w -n kubernetes-dashboard -o jsonpath='{.data.token}' | base64 -d)
[root@k8s-master01 access-control]# echo $token
......

创建dashboard-kubeconfig用户,创建用户的方式有很多,这里使用token的方式,这里的token指的就是ServiceAccount与之关联的Secret的值

#这里使用上一步保存的token
[root@k8s-master01 access-control]# kubectl config set-credentials dashboard-kubeconfig --token=$token --kubeconfig=/temp/k8s2/config
User "dashboard-kubeconfig" set.

查看创建的用户

[root@k8s-master01 access-control]# kubectl config view --kubeconfig=/temp/k8s2/config 
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://192.168.1.180:6443
  name: kubernetes
contexts: null 
kind: Config
preferences: {}
users:
- name: dashboard-kubeconfig
  user:
    token: ......

创建名为dashboard-kubeconfig@kubernetes的上下文context,上下文context命名方式一般为username@clustername

[root@k8s-master01 access-control]# kubectl config set-context dashboard-kubeconfig@kubernetes --cluster=kubernetes --user=dashboard-kubeconfig --kubeconfig=
/temp/k8s2/config
Context "dashboard-kubeconfig@kubernetes" created.

查看创建的上下文context

[root@k8s-master01 access-control]# kubectl config get-contexts --kubeconfig=/temp/k8s2/config 
CURRENT   NAME                              CLUSTER      AUTHINFO               NAMESPACE
*         dashboard-kubeconfig@kubernetes   kubernetes   dashboard-kubeconfig

使用刚才创建的上下文,并且查看上下文是否切换

[root@k8s-master01 access-control]# kubectl config use-context dashboard-kubeconfig@kubernetes --kubeconfig=/temp/k8s2/config 
Switched to context "dashboard-kubeconfig@kubernetes".
[root@k8s-master01 access-control]# kubectl config current-context 
kubernetes-admin@kubernetes

查看kubeconfig中的内容

[root@k8s-master01 access-control]# cat /temp/k8s2/config 
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: ......
    server: https://192.168.1.180:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: dashboard-kubeconfig
  name: dashboard-kubeconfig@kubernetes
current-context: dashboard-kubeconfig@kubernetes
kind: Config
preferences: {}
users:
- name: dashboard-kubeconfig
  user:
    token: ......

将config文件复制到window系统中,进行访问测试。
在这里插入图片描述

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐