目标
定制kubectl可以操作k8s资源的权限,比如,对所有资源只能读取,不能增删改。
基本知识
kubernetes 本身支持 RBAC 权限校验,现在的主流版本已经默认支持,并默认开启了。你也可以通过查看 apiserver 配置来看自己的k8s是否支持
我们要实现对 kubectl 权限管理,就得依赖 k8s 的 RBAC,我们知道,kubectl 默认情况下,是读取 ~/.kube/config 文件作为配置,和 k8s 的 apiserver 通信的,所以,问题的关键之一就是,我们如何生成这个配置文件。
k8s的RBAC定义了4个资源对象:Role、ClusterRole;Rolebinding、ClusterRoleBinding,其中:
Role:定义权限的集合,需要注意,Role 是定义在 Namespace 下的。
ClusterRole:和 Role 类似,只不过,它是整个集群范围使用的,没有命名空间的束缚。
RoleBinding:它是为了把 Role 绑定到 Subject 上,让 Subject 可以集成 Role 定义的所有权限。
ClusterRoleBinding:和 RoleBinding 差不多,只不过,它是将 ClusterRole 绑定到 Subject 上。
那么,Subject 是什么?Subject 其实可以理解为“用户”,它有几类,分别是:User、Group、ServiceAccount,我们直接通过源码看 Subject 的定义(着重看注释!!!)
// Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference,
// or a value for non-objects such as user and group names.
type Subject struct {
// Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount".
// If the Authorizer does not recognized the kind value, the Authorizer should report an error.
Kind string `json:"kind" protobuf:"bytes,1,opt,name=kind"`
// APIGroup holds the API group of the referenced subject.
// Defaults to "" for ServiceAccount subjects.
// Defaults to "rbac.authorization.k8s.io" for User and Group subjects.
// +optional
APIGroup string `json:"apiGroup,omitempty" protobuf:"bytes,2,opt.name=apiGroup"`
// Name of the object being referenced.
Name string `json:"name" protobuf:"bytes,3,opt,name=name"`
// Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty
// the Authorizer should report an error.
// +optional
Namespace string `json:"namespace,omitempty" protobuf:"bytes,4,opt,name=namespace"`
}
那么,Subject 在哪里?我们要绑定 Role 或者 ClusterRole,就得配置 RoleBinding 或者 ClusterRoleBinding,所以,Subject 就在 RoleBinding 或者 ClusterRoleBinding 里。下面进行实操步骤。
实施
1、创建一个ClusterRole
定义只读资源的操作。首先,创建文件 clusterrole-mytest-view.yaml,内容如下:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
name: mytest-view
rules:
- apiGroups:
- ""
resources:
- configmaps
- endpoints
- persistentvolumeclaims
- pods
- replicationcontrollers
- replicationcontrollers/scale
- serviceaccounts
- services
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- bindings
- events
- limitranges
- namespaces/status
- pods/log
- pods/exec
- pods/status
- replicationcontrollers/status
- resourcequotas
- resourcequotas/status
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- namespaces
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- pods/exec
verbs:
- create
- apiGroups:
- apps
resources:
- daemonsets
- deployments
- deployments/scale
- replicasets
- replicasets/scale
- statefulsets
- statefulsets/scale
verbs:
- get
- list
- watch
- apiGroups:
- autoscaling
resources:
- horizontalpodautoscalers
verbs:
- get
- list
- watch
- apiGroups:
- batch
resources:
- cronjobs
- jobs
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- daemonsets
- deployments
- deployments/scale
- ingresses
- networkpolicies
- replicasets
- replicasets/scale
- replicationcontrollers/scale
verbs:
- get
- list
- watch
- apiGroups:
- policy
resources:
- poddisruptionbudgets
verbs:
- get
- list
- watch
- apiGroups:
- networking.k8s.io
resources:
- networkpolicies
verbs:
- get
- list
- watch
2、创建 ServiceAccount
经过这一步之后,其实就有了 Secret 资源,这是因为,创建 ServiceAccount 后,k8s 会自动创建 Secret 资源,而 Secret 资源,有我们需要的证书等信息
kubectl create ns mytest
kubectl create sa -n mytest user-guest
3、创建 ClusterRoleBinding,将 ClusterRole 的权限,绑定到 ServiceAccount
创建文件 clusterrolebinding-view.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: mytest:user-guest
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: mytest-view
subjects:
- kind: ServiceAccount
name: user-guest
namespace: mytest
执行命令,创建资源
kubectl apply -f clusterrolebinding-view.yml
4、生成配置:guest.config
TOKEN=$(kubectl get sa -n mytest user-guest -o go-template='{{range .secrets}}{{.name}}{{end}}')
echo $TOKEN
CA_CERT=$(kubectl get secret -n mytest ${TOKEN} -o yaml | awk '/ca.crt:/{print $2}')
echo $CA_CERT
# 注意这里,需要改为你的apiserver的地址
API_SERVER="https://172.1.3.17:6443"
echo $API_SERVER
cat <<EOF > guest.config
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority-data: $CA_CERT
server: $API_SERVER
name: cluster
EOF
5、更新 guest.config 配置
SECRET=$(kubectl -n mytest get secret ${TOKEN} -o go-template='{{.data.token}}')
kubectl config set-credentials mytest-guest --token=`echo ${SECRET} | base64 -d` --kubeconfig=guest.config
kubectl config set-context default --cluster=cluster --user=mytest-guest --kubeconfig=guest.config
kubectl config use-context default --kubeconfig=guest.config
6、将 guest.config,重命名之后,放到 ~/.kube 目录下即可。