0、场景:
使用kubernetes的过程中,往往会有多套环境,每套环境也会有多个
namespace
,对应的也会有多种角色来操作集群,比如运维工程师、开发工程师、测试工程师。我司就是这样,开发人员和测试人员会登录服务器( 别问我为什么不用个kubesphere、rancher啥的 0.0 )了解自己应用的运行情况,查看对应的服务日志等等操作。他们不太熟悉k8s操作,相比让他们不断找我,我更倾向于让他们自己解决问题。所以我写了个简单的shell把常用的k8s命令都包含进去了。
操作k8s集群肯定是需要使用
kubectl
与apiServer
进行交互的,那必然会涉及到权限问题,管理员权限自然不能给,毕竟我司开发曾经干掉过线上一整个namespace的业务pod。。。基于以上描述和应用场景,就可以通过创建指定特定权限的kubeconfig文件,将该config文件分发给不同角色的用户完成权限限制。
1、原理
学艺不精,就简单介绍一下通过kubeconfig认证的原理。
Kubernetes中所有的访问,无论外部内部,都会通过API Server处理,访问Kubernetes资源前需要经过认证(Authentication)与授权(Authorization)。
Authentication:用于识别用户身份的认证,Kubernetes分外部服务帐号和内部服务帐号,采取不同的认证机制
Authorization:用于控制用户对资源访问的授权,对访问的授权目前主要使用RBAC机制
认证与ServiceAccount
Kubernetes的用户分为服务帐户(ServiceAccount)和普通帐户两种类型。
服务帐户与Namespace绑定,关联一套凭证,存储在Secret中,Pod创建时挂载Secret,从而允许与API Server之间调用。
Kubernetes中没有代表普通帐户的对象,这类帐户默认由外部服务独立管理(一般都是外部IAM),比如在华为云上CCE的用户是由IAM管理的。
如果仅使用k8s原生的rbac模块,那么就需要将Role/ClusterRole定义的资源权限通过RoleBinding/ClusterRoleBinding绑定到某个名称空间下的SA账户;
如果希望借助外部IAM模块,则可以将上述的SA账户替换成外部的IAM用户
2、操作流程
前提条件:
需要能够访问k8s集群apiserver并且对集群有admin操作权限
2.1 限制用户仅具有某个特定名称空间权限
如果你要授予linux用户名称空间级别的权限,那么流程可以是:
在相应名称空间下创建一个SA->创建一个ClusterRole或者Role(相应名称空间级别资源权限)->创建一个Rolebinding绑定到该SA,这样以该sa生成的kubeconfig文件就会具有相应名称空间级别资源的权限
①
创建一个sa
(推荐在该特定名称空间中)创建SA后,会自动创建一个绑定的secret,在后面的kubeconfig文件中,会用到该secret中的token
apiVersion: v1
kind: ServiceAccount
metadata:
name: develop-sa
namespace: develop
②
创建一个role
或clusterRole
,创建role
或clusterRole
时,将希望授予使用者的资源和权限都放进去
下面示例创建一个
Role
,即授予角色develop-role
在develop namespce
下对pods、configmaps、secrets、services
等core API
资源的读写更新删除权限,以及授予对extensions API
等资源的相应权限。
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: develop-role
namespace: develop
rules:
- apiGroups: [""] # ""为空代表core API组
resources:
- pods
# 在这里,pods对应名称空间作用域的Pod资源,而log是pods的子资源。在RBAC
# 在 RBAC 角色表达子资源时,使用斜线(/)来分隔资源和子资源
- pods/log
- configmaps
- secrets
- services
verbs:
- get
- list
- watch
- create
- update
- delete
- patch
- apiGroups:
- extensions
- apps
resources:
- deployments
- daemonsets
- replicationcontrollers
- replicasets
- statefulsets
- horizontalpodautoscalers
- jobs
- applications
verbs:
- get
- list
- watch
- create
- update
- delete
- patch
③
创建一个RoleBinding
或者ClusterRolebinding
,将sa
和Role/ClusterRole
绑定起来。绑定之后,该sa
就拥有了Role/ClusterRole
所对应的那些资源权限了。ClusterRole的ClusterRolebinding所具有的权限级别是集群级别的,而Role的RoleBinding则是名称空间级别的。当然,ClusterRole的Rolebinding也是名称空间级别的,只不过你可以在多个名称空间下使用该ClusterRole,不需要重复定义新的Role了
kind: RoleBinding
# 此 RoleBinding 允许 develop-sa 读取、删除、更新 "develop"
名称空间下特定资源( develop-role所指定的名称空间和资源 )
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: develop-rolebinding
namespace: develop
subjects:
- kind: ServiceAccount
name: develop-sa
roleRef:
kind: Role
name: develop-role
apiGroup: rbac.authorization.k8s.io
④
创建kubeconfig
文件,模板如下:
# <> 标注的地方需要被替换
apiVersion: v1
kind: Config
users:
- name: develop
user:
token: <token>
clusters:
- cluster:
certificate-authority-data: <certificate-authority-data>
server: <api-server>
name: develop-cluster
contexts:
- context:
cluster: develop-cluster
namespace: develop
user: develop
name: develop-cluster
current-context: develop-cluster
kubeconfig中几个参数获取的方法:
# 通过config view拿到 <certificate-authority-data> 和 <api-server> 信息
kubectl config view --flatten --minify
# 通过describe sa拿到sa 绑定的 secret 名称(输出结果的“Tokens”)
kubectl describe sa develop-sa -n develop
# 通过describe secret拿到token信息(输出结果的“token”字段)
kubectl describe secret <key> -n develop
⑤
将编辑好的kubeconfig文件加载到linux用户的.bashrc中即可下面的某些步骤可以根据自己的实际情况选择性使用
su XXXX
mkdir -p /home/XXX/.kube/conf
sudo cp -i /etc/kubernetes/XXXXX.conf /home/XXX/.kube/conf
sudo chown -R XXX:XXX $HOME/.kube/conf/
echo "export KUBECONFIG=/home/XXX/.kube/conf/admin.conf" >> ~/.bashrc
# 配置自动补全
echo "source <(kubectl completion bash)" >> ~/.bashrc
source .bashrc
2.2 限制用户具有多名称空间资源的权限
如果你要授予linux用户集群级别多个名称空间的权限,那么流程可以是:
在任意的名称空间创建一个sa -> 创建一个ClusterRole(具有相应的集群级别资源权限 -> 创建一个 ClusterRoleBinding 绑定 ClusterRole 权限给 SA,这样以该sa生成的kubeconfig文件就会具有相应集群级别资源的权限)
参考:
1、华为云CCE
2、kubernetes.io/configure-service-account
3、oracle.com/serviceaccount
4、kubernetes.io/rbac
5、ishells.cn/k8s-rbac-study
评论