用户控制

所有 Kubernetes 集群都有两类用户:由 Kubernetes 管理的服务账号和普通用户。

普通用户: 对于普通用户k8s内部并没有进行管理,也没有对应的资源对象来表示。

普通用户可以通过以下方式进行管理

  • 负责分发私钥的管理员
  • 类似 Keystone 或者 Google Accounts 这类用户数据库
  • 包含用户名和密码列表的文件

可以使用k8s集群签发给用户证书,通过证书信息来判断用户是否是合法的用户。简单的说是通过签发证书的方式给一个普通的用户。

证书的 subject 来表示用户名。

服务账号是 Kubernetes API 所管理的用户。是被绑定到特定的namespace上的。

访问api-server 的时候通过携带 证书,token 或用户名密码来确认用户信息。

RBAC 权限

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

开启RBAC可以通过权限对资源的操作进行权限的控制。

k8s内有一个非常重要的概念也就是namespace,通过namespace 可以隔离不同的环境,有时候需要对不同的namespace的操作权限隔离开。
而通过rbac定义的权限可以分割开不同的用户的不同namespace权限。同时也可以对不同的集群权限进行隔离控制。

rbac权限具有如下特点

  • 对集群中的资源和非资源权限均有完整的覆盖。
  • 整个RBAC完全由几个API对象完成,同其他API对象一样,可 以用kubectl或API进行操作。
  • 可以在运行时进行调整,无须重新启动API Server。

开启

如果未开启,需要在kube-apiserver 的启动参数中增加使用rbac权限

1
vim /etc/kubernetes/manifests/kube-apiserver.yaml

RBAC 统一使用资源对象来对权限控制

四种Kubernetes 对象:Role、ClusterRole、RoleBinding 和 ClusterRoleBinding。

Role

Role 是一个资源对象,一般是用来设置namespace的访问权限。

下面举例 通过Role 定义角色只能对指定的namespace 中的资源进行授权

1
2
3
4
5
6
7
8
9
10
11

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # "" 标明 core API 组
resources: ["pods"]
verbs: ["get", "watch", "list"]

1
2
3
4
5
//应用角色
kubectl apply -f role.yaml
//查询角色
kubectl get role

  • 定义了一个名字为pod-reader 的Role 资源对象
  • 作用的namespace 是 default
  • resources 表示作用的资源对象是 pods
  • verbs 表示允许操作的命令

注意: 角色中没有拒绝的配置,只有允许的配置

cluster Role

集群角色的权限控制范围除了namespace的控制,还可以控制

  • 集群资源如node
  • 非资源型的 ,比如路径请求信息 “/test”
  • 包含全部命名空间的资源,例如pods(用于kubectl get pods – all-namespaces这样的操作授权)。

示例:

1
2
3
4
5
6
7
8
9
10
11
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# "namespace" 被忽略,因为 ClusterRoles 不受名字空间限制
name: secret-reader
rules:
- apiGroups: [""]
# 在 HTTP 层面,用来访问 Secret 对象的资源的名称为 "secrets"
resources: ["secrets"]
verbs: ["get", "watch", "list"]

1
2
3

kubectl get clusterrole

也可以看到,目前系统本身也存在许多clusterrole.其中以 system: 开头的表示是系统生成的clusterRole

角色绑定 RoleBinding ClusterRoleBinding

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

示例格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: rbac.authorization.k8s.io/v1
# 此角色绑定允许 "jane" 读取 "default" 名字空间中的 Pods
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
# 你可以指定不止一个“subject(主体)”
- kind: User
name: jane # "name" 是区分大小写的
apiGroup: rbac.authorization.k8s.io
roleRef:
# "roleRef" 指定与某 Role 或 ClusterRole 的绑定关系
kind: Role # 此字段必须是 Role 或 ClusterRole
name: pod-reader # 此字段必须与你要绑定的 Role 或 ClusterRole 的名称匹配
apiGroup: rbac.authorization.k8s.io

实现鉴权

  1. 创建一个新的namespace

    1
    kubectl create namespace rbac-np
    1
    2
    3
    4
    5
    6
    7
    8
    9
    [root@master ~]# kubectl get ns
    NAME STATUS AGE
    default Active 8d
    kube-node-lease Active 8d
    kube-public Active 8d
    kube-system Active 8d
    rbac-np Active 14s
    test-namespace Active 5d

  2. 在namespace 中创建pod

    1
    kubectl run nginx --image=nginx -n rbac-np
    1
    2
    3
    4
    [root@master ~]# kubectl get pod -n rbac-np
    NAME READY STATUS RESTARTS AGE
    nginx 0/1 ContainerCreating 0 14s

  3. 创建一个只有针对该命名空间的pod的创建的角色

    1
    2
    3
    4
    5
    6
    7
    8
    9
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
    namespace: rbac-np
    name: pod-get
    rules:
    - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "watch", "list"]
    1
    kubectl apply -f pod-get.yaml 
  4. 创建角色绑定

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
    name: read-pods
    namespace: rbac-np
    subjects:
    - kind: User
    name: wang
    apiGroup: rbac.authorization.k8s.io
    roleRef:
    kind: Role
    name: pod-get
    apiGroup: rbac.authorization.k8s.io
    • 定义namespace
    • 定义subjects 即用户的信息
    • 定义管理的role信息
    1
    kubectl apply -f role-binding.yaml

  1. 创建一个其他的资源对象 用于测试
1
kubectl create deploy tomcat-test  --image=tomcat:8 -n rbac-np
  1. 使用脚本用户信息的整数
  #rbac-user.sh

  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
cat > wang-csr.json <<EOF
{
"CN": "wang",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing"
}
]
}
EOF

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes wang-csr.json | cfssljson -bare wang

kubectl config set-cluster kubernetes \
--certificate-authority=ca.pem \
--embed-certs=true \
--server=https://192.168.199.116:6443 \
--kubeconfig=wang-kubeconfig

kubectl config set-credentials wang \
--client-key=wang-key.pem \
--client-certificate=wang.pem \
--embed-certs=true \
--kubeconfig=wang-kubeconfig

kubectl config set-context default \
--cluster=kubernetes \
--user=wang \
--kubeconfig=wang-kubeconfig

kubectl config use-context default --kubeconfig=wang-kubeconfig

注意修改点: - json 文件名 - json 中CN的值 - kubeconfig 的名称 cfssl 如果未安装,需要先安装cfssl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

cfssl version
  1. 命令测试

    1
    2
    3
    4

    kubectl get pods -n rbac-np

    kubectl get deploy -n rbac-np