Kubernetes访问控制之RBAC_docker

kubernete中账户分为两种:

  • User Account (用户账户):kubernetes集群外部用户使用
  • Service Account (服务账号):用于集群内部使用

Kubernetes设计了一种Secret资源,分为两类,一种是用于 ServiceAccount,每创建一个SA,就会随之创建一个Secret;另一种就是用户自定义的保密信息Opaque

一、ServiceAccount中添加Image pull secrets

创建用于拉取镜像的secret
# kubectl create secret docker-registry harbor-registrykey \
--docker-server=devops.harbor.com \
--docker-username=admin \
--docker-password=admin@123
创建sa并绑定secret
# cat imagepull-sa.yml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: imagepull-sa
  namespace: devops
imagePullSecrets: #添加此字段
- name: harbor-registrykey

这个时候,只要是使用此 SA 的Pod,都可以在docker-registry拉取镜像了。

二、RBAC

RBAC介绍

在Kubernetes中,所有资源对象都是通过API对象进行操作,他们保存在etcd里。而对etcd的操作我们需要通过访问 kube-apiserver 来实现,上面的Service Account其实就是APIServer的认证过程,而授权的机制是通过RBAC:基于角色的访问控制实现。RBAC使用rbac.authorization.k8s.io API Group 来实现授权决策,允许管理员通过 Kubernetes API 动态配置策略,要启用RBAC,需要在 apiserver 中添加参数--authorization-mode=RBAC

Role and ClusterRole

在RBAC API中,Role表示一组规则权限,Role 是定义在一个 namespace 中,而 ClusterRole 是集群级别 下面定义一个Role

# cat test-role.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: test-role
  namespace: devops
rules:
- apiGroups: [""]  # 为空表示为默认的core api group
  resources: ["pods"] # 数据源类型
  verbs: ["get","watch","list"] #赋予的权限

以上策略表示对devops名称空间下的Pods有get,watch,list的权限

ClusterRole 具有与 Role 相同权限角色控制能力,不同的就是 Cluster Role是集群级别,主要用于:

  • 集群级别的资源控制(例如 node 访问权限)
  • 非资源型 endpoints(例如对某个目录或文件的访问:/healthz)
  • 所有命名空间资源控制(Pod、Deployment等)
# cat test-clusterrole.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: test-clusterrole
rules:
- apiGroups: [""]
  resources: ["services"]
  verbs: ["get","create","list"]

以上策略表示,有get,create,list整个集群service的权限

创建以上规则

kubectl apply -f test-role.yml
kubectl apply -f test-clusterrole.yml
RoleBinding 和 ClusterRoleBinding

RoleBinding可以将角色中定义的权限授予用户或用户组,RoleBinding包含一组权限列表(Subjects),权限列表中包含有不同形式的待授予权限资源类型(users,groups, or Service Account)

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: test-rolebinding1
  namespace: devops
subjects:
- kind: User  # 权限资源类型
  name: liheng  # 名称
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role  #要绑定的Role的类型(可以是Role或ClusterRole)
  name: test-role # Role的名称
  apiGroup: rbac.authorization.k8s.io

将名称为test-role的Role的权限资源赋予名为devops的用户,作用域为devops名称空间

RoleBinding也可以引用ClusterRole来对当前 namespace 内用户、用户组或SA来进行授权,这种操作允许管理员在整个集群中定义一些通用的ClusterRole,然后在不同的namespace中使用RoleBinding绑定。

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: test-rolebinding2
  namespace: devops
subjects:
- kind: User
  name: devops
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: test-clusterrole
  apiGroup: rbac.authorization.k8s.io

将名称为test-clusterrole的ClusterRole的资源权限赋予给了名称为devops的用户,但由于Role仅作用于单个namespace,所以此资源策略仅仅对devops名称空间下的资源有效

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: test-clusterrolebinding
subjects:
- kind: Group
  name: devops
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: test-clusterrole
  apiGroup: rbac.authorization.k8s.io

将名称为test-clusterrole的ClusterRole的资源权限赋予给groupname为devops的用户组,对此用户组下所有用户生效。

创建一个用户只能查看devops名称空间下的pod资源

1、生成用户(liheng)私钥

# openssl genrsa -out liheng.key 2048

2、通过生成的私钥生成证书签名请求文件:liheng.csr,注意-subj中的CN表示用户名,O表示用户组。

# openssl req -new -key liheng.key -out liheng.csr -subj "/CN=liheng/O=yunweizhongxi"

3、通过kubernetes集群的CA证书为用户颁发签名证书

# openssl x509 -req -in liheng.csr -CA /opt/kubernetes/ssl/ca.pem \
-CAkey /opt/kubernetes/ssl/ca-key.pem \
-CAcreateserial -out liheng.crt -days 500

4、使用创建的证书文件和私钥创建用户(客户端)认证凭据

# kubectl config set-credentials liheng \
--client-certificate=liheng.crt \
--embed-certs=true \
--client-key=liheng.key \
--kubeconfig=liheng.kubeconfig

5、创建用户上下文(Context)

# kubectl config set-context liheng-context \
--cluster=kubernetes \
--namespace=kube-system \
--user=liheng \
--kubeconfig=liheng.kubeconfig

6、设置要访问的集群信息

# kubectl config set-cluster kubernetes \
--certificate-authority=/opt/kubernetes/ssl/ca.pem \
--embed-certs=true \ #表示将--certificate-authority证书写入到kubeconfig中
--server=${KUBE_APISERVER} \
--kubeconfig=liheng.kubeconfig

7、为用户(liheng)设置RBAC权限

# cat test-role.yml
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: test-role
  namespace: devops
rules:
- apiGroups: [""]  # 为空表示为默认的core api group
  resources: ["pods"] # 数据源类型
  verbs: ["get","watch","list"] #赋予的权限
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: test-rolebinding
  namespace: devops
subjects:
- kind: User
  name: liheng
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: test-role      # 绑定上文中创建的名称为 test-rbac 的Role,具体权限,往上翻下哈
  apiGroup: rbac.authorization.k8s.io
# kubectl apply -f test-role.yml

8、设置默认上下文

# kubectl config use-context liheng-context

9、测试

# [root@sl-k8s-master-01 devops]# kubectl get pod
NAME                       READY   STATUS    RESTARTS   AGE
jenkins-745596c48d-fjt59   1/1     Running   0          2d20h
# [root@sl-k8s-master-01 devops]# kubectl exec  jenkins-745596c48d-fjt59 -n devops -- sh
Error from server (Forbidden): pods "jenkins-745596c48d-fjt59" is forbidden: User "liheng" cannot create resource "pods/exec" in API group "" in the namespace "devops"
# [root@sl-k8s-master-01 devops]# kubectl get svc
Error from server (Forbidden): services is forbidden: User "liheng" cannot list resource "services" in API group "" in the namespace "devops"

可以看到liheng用户只有查看devops名称空间下pod的权限。

cfssl颁发签名证书方法

1、创建CA证书签名请求文件

# cat liheng-csr.json
{
    "CN": "liheng",    # 用户名,必填
    "hosts": [],       # 主机地址,不填表示所有主机都可使用
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "BeiJing",
            "ST": "Beijing",
            "O": "yunweizhongxin",
            "OU": "System"
        }
    ]
}

2、创建访问证书

# cfssl gencert -ca=/opt/kubernetes/ssl/ca.pem \
-ca-key=/opt/kubernetes/ssl/ca-key.pem \
-profile=kubernetes liheng-csr.json|cfssljson -bare liheng

3、为liheng用户生成集群配置文件

# kubectl config set-cluster kubernetes \
--certificate-authority=/opt/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} --kubeconfig=liheng.kubeconfig
# kubectl config set-credentials liheng \
--client-certificate=liheng.pem \
--client-key=liheng-key.pem \
--embed-certs=true --kubeconfig=liheng.kubeconfig
# kubectl config set-context liheng-context \
--cluster=kubernetes \
--user=liheng \
--namespace=devops \
--kubeconfig=liheng.kubeconfig

4、切换上下文

# kubectl config use-context liheng-context --kubeconfig=liheng.kubeconfig

5、测试

# [root@sl-k8s-master-01 src]# kubectl get pod -n kube-system --kubeconfig=liheng.kubeconfig 
Error from server (Forbidden): pods is forbidden: User "liheng" cannot list resource "pods" in API group "" in the namespace "kube-system"
配置具有操作整个集群的管理员用户(admin)

1、生成用户(admin)私钥

# openssl genrsa -out admin.key 2048

2、通过生成的私钥生成证书签名请求文件:admin.csr.

# openssl req -new -key admin.key -out admin.csr \
-subj "/CN=admin/O=system:masters"

使用config还需要注意用户已经经过授权(如RBAC授权),上述例子中用户的证书中O字段为system:masters,kube-apiserver预定义的ClusterRoleBinding cluster-admin默认将Group system:masters与ClusterRole cluster-admin进行了绑定,该ClusterRole授予了调用kube-apiserver相关API的权限;-subj中的CN表示用户名,O表示用户组

3、通过kubernetes集群的CA证书为用户颁发签名证书

# openssl x509 -req -in admin.csr -CA /opt/kubernetes/ssl/ca.pem \
-CAkey /opt/kubernetes/ssl/ca-key.pem \
-CAcreateserial -out admin.crt -days 500

4、使用创建的证书文件和私钥创建用户(客户端)认证凭据

# kubectl config set-credentials admin \
--client-certificate=admin.crt \
--embed-certs=true \
--client-key=admin.key
--kubeconfig=admin.kubeconfig

5、创建用户上下文(Context)

# kubectl config set-context admin-context \
--cluster=kubernetes \
--user=admin
--kubeconfig=admin.kubeconfig
# kubectl config set-cluster kubernetes \
--certificate-authority=/opt/kubernetes/ssl/ca.pem \
--embed-certs=true \ #表示将--certificate-authority证书写入到kubeconfig中
--server=${KUBE_APISERVER} \
--kubeconfig=admin.kubeconfig

6、设置默认上下文

# kubectl config use-context admin-context
创建一个只能访问某个 namespace 的ServiceAccount

接下来配置创建一个ServiceAccount来访问特定名称空间下资源的示例 1、创建名为liheng-sa的ServiceAccount

# kubectl create sa liheng-sa -n devops

2、新建一个 Role和RoleBinding 对象

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: liheng-sa-role
  namespace: devops
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
# 将上面的 liheng-sa 和角色 liheng-sa-role 进行绑定
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: liheng-sa-rolebinding
  namespace: devops
subjects:
- kind: ServiceAccount
  name: liheng-sa
  namespace: devops
roleRef:
  kind: Role
  name: liheng-sa-role
  apiGroup: rbac.authorization.k8s.io

3、验证 每个ServiceAccount会生成一个Secret对象和它进行映射,这个Secret里面包含一个 token,我们可以利用这个token去登录Dashboard进行验证

# kubectl get secret -n devops |grep liheng-sa
# kubectl get secret liheng-sa-token-klju -o jsonpath={.data.token} -n devops |base64 -d

如果文章对您有帮助,还想了解更过关于k8s相关的实战经验,请微信扫描下方二维码关注“IT运维图谱”公众号或着通过微信搜一搜关注公众号。

Kubernetes访问控制之RBAC_RBAC_02