前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Kubernetes 必须掌握技能之 RBAC

Kubernetes 必须掌握技能之 RBAC

作者头像
YP小站
发布2020-06-04 15:52:41
9820
发布2020-06-04 15:52:41
举报
文章被收录于专栏:YP小站YP小站

什么是 Kubernetes RBAC

基于角色的访问控制(Role-Based Access Control, 即 "RBAC"):使用 “rbac.authorization.k8s.io” API Group 实现授权决策,允许管理员通过 Kubernetes API 动态配置策略。

RBAC 从 Kubernetes v1.6 处于beta版本,从 v1.8 开始,RBAC已作为 稳定的功能。启用 RBAC,请使用 --authorization-mode=RBAC 启动 API Server。[1]

API 概述

本节将介绍RBAC API所定义的四种顶级类型。用户可以像使用其他Kubernetes API资源一样 (例如通过kubectl、API调用等)与这些资源进行交互。例如,命令 kubectl create -f (resource).yml 可以被用于以下所有的例子,当然,读者在尝试前可能需要先阅读以下相关章节的内容。[1]

RBAC 简易概览图

ClusterRole 与 Role

Role(角色):是一系列权限的集合,例如一个角色可以包含读取 Pod 的权限和列出 Pod 的权限。Role 只能用来给某个特定 namespace 中的资源作鉴权。对 namespace 、集群级资源 和 非资源类的 API(如 /healthz)使用 ClusterRole

ClusterRole:对象可以授予与 Role 对象相同的权限,但由于它们属于集群范围对象,也可以使用它们授予对以下几种资源的访问权限:

  • 集群范围资源(例如节点,即 node)
  • 非资源类型 endpoint(例如 /healthz)
  • 授权多个 Namespace

下面例子描述了 default namespace 中的一个 Role 对象的定义,用于授予对 pod 的读访问权限

代码语言:javascript
复制
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: default
  name: demo-role
rules:
- apiGroups: [""] # 空字符串""表明使用 core API group
  resources: ["pods"]
  verbs: ["get", "watch", "list", "create", "delete"]

下面例子中 ClusterRole 定义可用于授予用户对某一个 namespace,或者 所有 namespace的 secret(取决于其绑定方式)的读访问权限

代码语言:javascript
复制
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  # ClusterRole 是集群范围对象,没有 "namespace" 区分
  name: demo-clusterrole
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "watch", "list", "create", "delete"]

ClusterRoleBinding 与 RoleBinding

RoleBinding:把 Role 或 ClusterRole 中定义的各种权限映射到 User,Service Account 或者 Group,从而让这些用户继承角色在 namespace 中的权限。

ClusterRoleBinding:让用户继承 ClusterRole 在整个集群中的权限。

RoleBinding 可以引用在同一命名空间内定义的Role对象。

代码语言:javascript
复制
# 以下角色绑定定义将允许用户 "jane" 从 "default" 命名空间中读取pod
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User
  name: jane
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

RoleBinding 对象也可以引用一个 ClusterRole 对象用于在 RoleBinding 所在的命名空间内授予用户对所引用的ClusterRole 中定义的命名空间资源的访问权限。这一点允许管理员在整个集群范围内首先定义一组通用的角色,然后再在不同的命名空间中复用这些角色。

例如,尽管下面示例中的 RoleBinding 引用的是一个 ClusterRole 对象,但是用户”dave”(即角色绑定主体)还是只能读取”development” 命名空间中的 secret(即RoleBinding所在的命名空间)

代码语言:javascript
复制
# 以下角色绑定允许用户"dave"读取"development"命名空间中的secret。
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
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

最后,可以使用 ClusterRoleBinding 在集群级别和所有命名空间中授予权限。下面示例中所定义的 ClusterRoleBinding 允许在用户组 ”manager” 中的任何用户都可以读取集群中任何命名空间中的 secret 。

代码语言:javascript
复制
# 以下`ClusterRoleBinding`对象允许在用户组"manager"中的任何用户都可以读取集群中任何命名空间中的secret。
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
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

对资源的引用

大多数资源由代表其名字的字符串表示,例如 ”pods”,就像它们出现在相关API endpoint 的URL中一样。然而,有一些Kubernetes API还 包含了”子资源”,比如 podlogs。在Kubernetes中,pod logs endpoint的URL格式为:

GET /api/v1/namespaces/{namespace}/pods/{name}/log

在这种情况下,”pods”是命名空间资源,而”log”是pods的子资源。为了在RBAC角色中表示出这一点,我们需要使用斜线来划分资源 与子资源。如果需要角色绑定主体读取pods以及pod log,您需要定义以下角色:

代码语言:javascript
复制
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: default
  name: pod-and-pod-logs-reader
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list"]

通过 resourceNames 列表,角色可以针对不同种类的请求根据资源名引用资源实例。当指定了 resourceNames 列表时,不同动作 种类的请求的权限,如使用 ”get”、”delete”、”update”以及”patch”等动词的请求,将被限定到资源列表中所包含的资源实例上。例如,如果需要限定一个角色绑定主体只能 ”get” 或者 ”update” 一个 configmap 时,您可以定义以下角色:

代码语言:javascript
复制
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: default
  name: configmap-updater
rules:
- apiGroups: [""]
  resources: ["configmap"]
  resourceNames: ["my-configmap"]
  verbs: ["update", "get"]

值得注意的是,如果设置了 resourceNames,则请求所使用的动词不能是 list、watch、create或者deletecollection。由于资源名不会出现在 create、list、watch和deletecollection 等API请求的URL中,所以这些请求动词不会被设置了resourceNames 的规则所允许,因为规则中的 resourceNames 部分不会匹配这些请求。[1]

例子

  • 绑定用户能查看所有 namespace
代码语言:javascript
复制
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  # 鉴于ClusterRole是集群范围对象,所以这里不需要定 义"namespace"字段
  name: view-namespace-clusterrole
rules:
- apiGroups:
  - ""
  resources:
  - namespaces
  - namespaces/status
  verbs:
  - get
  - list
  - watch
  • 定义 develop-role 用户对 default 命名空间详细权限
代码语言:javascript
复制
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: develop-role
  namespace: default
rules:
- apiGroups:
  - ""
  resources:
  - endpoints
  - serviceaccounts
  - configmaps
  - persistentvolumeclaims
  - persistentvolumes
  - services
  - replicationcontrollers
  - replicationcontrollers/scale
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - pods
  - pods/log
  - pods/status
  - pods/exec
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - bindings
  - events
  - limitranges
  - namespaces/status
  - replicationcontrollers/status
  - resourcequotas
  - resourcequotas/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - namespaces
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - apps
  resources:
  - daemonsets
  - statefulsets
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - apps
  resources:
  - deployments
  - deployments/scale
  - replicasets
  - replicasets/scale
  verbs:
  - get
  - list
  - watch
  - update
- apiGroups:
  - autoscaling
  resources:
  - horizontalpodautoscalers
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - batch
  resources:
  - cronjobs
  - jobs
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - extensions
  resources:
  - daemonsets
  - statefulsets
  - ingresses
  - networkpolicies
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - extensions
  resources:
  - deployments
  - deployments/scale
  - replicasets
  - replicasets/scale
  - replicationcontrollers/scale
  verbs:
  - get
  - list
  - watch
  - update
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - networking.k8s.io
  resources:
  - networkpolicies
  verbs:
  - get
  - list
  - watch

默认角色 与 默认角色绑定

API Server 会创建一组默认的 ClusterRoleClusterRoleBinding 对象。这些默认对象中有许多包含 system: 前缀,表明这些资源由 Kubernetes基础组件”拥有”。对这些资源的修改可能导致非功能性集群(non-functional cluster)。一个例子是 system:node ClusterRole 对象。这个角色定义了 kubelet 的权限。如果这个角色被修改,可能会导致kubelet 无法正常工作。

所有默认的 ClusterRoleClusterRoleBinding 对象都会被标记为 kubernetes.io/bootstrapping=rbac-defaults。[1]

面向用户的角色

通过命令 kubectl get clusterrole 查看到并不是所有都是以 system:前缀,它们是面向用户的角色。这些角色包含超级用户角色(cluster-admin),即旨在利用 ClusterRoleBinding(cluster-status)在集群范围内授权的角色, 以及那些使用 RoleBinding(admin、edit和view)在特定命名空间中授权的角色。

  • cluster-admin超级用户权限,允许对任何资源执行任何操作。在 ClusterRoleBinding 中使用时,可以完全控制集群和所有命名空间中的所有资源。在 RoleBinding 中使用时,可以完全控制 RoleBinding 所在命名空间中的所有资源,包括命名空间自己。
  • admin管理员权限,利用 RoleBinding 在某一命名空间内部授予。在 RoleBinding 中使用时,允许针对命名空间内大部分资源的读写访问, 包括在命名空间内创建角色与角色绑定的能力。但不允许对资源配额(resource quota)或者命名空间本身写访问
  • edit:允许对某一个命名空间内大部分对象的读写访问,但不允许查看或者修改角色或者角色绑定。
  • view:允许对某一个命名空间内大部分对象的只读访问。不允许查看角色或者角色绑定。由于可扩散性等原因,不允许查看 secret 资源

核心组件角色、其它组件角色 和 控制器(Controller)角色 这里不在一一列出。具体见参考链接中[1]。

Permissive RBAC

所谓 Permissive RBAC 是指授权给所有的 Service Accounts 管理员权限。不推荐的配置

代码语言:javascript
复制
$ kubectl create clusterrolebinding permissive-binding \
  --clusterrole=cluster-admin \
  --user=admin \
  --user=kubelet \
  --group=system:serviceaccounts

创建用户 shell 脚本

代码语言:javascript
复制
#!/usr/bin/env bash
# 注意修改KUBE_APISERVER为你的API Server的地址

KUBE_APISERVER=$1
USER=$2
USER_SA=system:serviceaccount:default:${USER}
Authorization=$3
USAGE="USAGE: create-user.sh <api_server> <username> <clusterrole authorization>\n
Example: https://192.168.1.2:6443 brand"
CSR=`pwd`/user-csr.json
SSL_PATH="/opt/kubernetes/ssl"
USER_SSL_PATH="/opt/kubernetes/create-user"
SSL_FILES=(ca-key.pem ca.pem ca-config.json)
CERT_FILES=(${USER}.csr $USER-key.pem ${USER}.pem)

if [[ $KUBE_APISERVER == "" ]]; then
   echo -e $USAGE
   exit 1
fi
if [[ $USER == "" ]];then
    echo -e $USAGE
    exit 1
fi

if [[ $Authorization == "" ]];then
    echo -e $USAGE
    exit 1
fi

# 创建用户的csr文件
function createCSR(){
cat>$CSR<<EOF
{
  "CN": "USER",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ]
}
EOF

# 替换csr文件中的用户名
sed -i "s/USER/$USER_SA/g" $CSR
}

function ifExist(){
if [ ! -f "$SSL_PATH/$1" ]; then
    echo "$SSL_PATH/$1 not found."
    exit 1
fi
}

function ifClusterrole(){
kubectl get clusterrole ${Authorization} &> /dev/null
if (( $? !=0 ));then
   echo "${Authorization} clusterrole there is no"
   exit 1
fi
}

# 判断clusterrole授权是否存在
ifClusterrole

# 判断证书文件是否存在
for f in ${SSL_FILES[@]};
do
    echo "Check if ssl file $f exist..."
    ifExist $f
    echo "OK"
done

echo "Create CSR file..."
createCSR
echo "$CSR created"
echo "Create user's certificates and keys..."
cd $USER_SSL_PATH
cfssl gencert -ca=${SSL_PATH}/ca.pem -ca-key=${SSL_PATH}/ca-key.pem -config=${SSL_PATH}/ca-config.json -profile=kubernetes $CSR| cfssljson -bare $USER_SA

# 创建 sa
kubectl create sa ${USER} -n default

# 设置集群参数
kubectl config set-cluster kubernetes \
--certificate-authority=${SSL_PATH}/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=${USER}.kubeconfig

# 设置客户端认证参数
kubectl config set-credentials ${USER_SA} \
--client-certificate=${USER_SSL_PATH}/${USER_SA}.pem \
--client-key=${USER_SSL_PATH}/${USER_SA}-key.pem \
--embed-certs=true \
--kubeconfig=${USER}.kubeconfig

# 设置上下文参数
kubectl config set-context kubernetes \
--cluster=kubernetes \
--user=${USER_SA} \
--namespace=development \
--kubeconfig=${USER}.kubeconfig

# 设置默认上下文
kubectl config use-context kubernetes --kubeconfig=${USER}.kubeconfig

# 创建 namespace
# kubectl create ns $USER

# 绑定角色
# kubectl create rolebinding ${USER}-admin-binding --clusterrole=admin --user=$USER --namespace=$USER --serviceaccount=$USER:default
kubectl create clusterrolebinding ${USER}-binding --clusterrole=${Authorization} --user=${USER_SA}

# kubectl config get-contexts

echo "Congratulations!"
echo "Your kubeconfig file is ${USER}.kubeconfig"

参考链接

  • [1] https://jimmysong.io/kubernetes-handbook/concepts/rbac.html
  • https://www.shipengqi.top/kubernetes-learn/auth/rbac.html
  • https://juejin.im/entry/5b23280ce51d4558cd2acdea

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-02-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 YP小站 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是 Kubernetes RBAC
  • API 概述
  • RBAC 简易概览图
  • ClusterRole 与 Role
  • ClusterRoleBinding 与 RoleBinding
  • 对资源的引用
  • 例子
  • 默认角色 与 默认角色绑定
  • 面向用户的角色
  • Permissive RBAC
  • 创建用户 shell 脚本
  • 参考链接
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档