在Kubernetes1.6版本中新增角色访问控制机制(Role-Based Access,RBAC)让集群管理员可以针对特定使用者或服务账号的角色,进行更精确的资源访问控制。在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。在一个组织中,角色是为了完成各种工作而创造,用户则依据它的责任和资格来被指派相应的角色,用户可以很容易地从一个角色被指派到另一个角色。
需要理解 RBAC 一些基础的概念和思路,RBAC 是让用户能够访问 Kubernetes API 资源的授权方式。
在 RBAC 中定义了两个对象,用于描述在用户和资源之间的连接权限。
角色
角色是一系列的权限的集合,例如一个角色可以包含读取 Pod 的权限和列出 Pod 的权限, ClusterRole 跟 Role 类似,但是可以在集群中到处使用( Role 是 namespace 一级的)。
角色绑定
RoleBinding 把角色映射到用户,从而让这些用户继承角色在 namespace 中的权限。ClusterRoleBinding 让用户继承 ClusterRole 在整个集群中的权限。
service account原理
k8s里面有两种用户,一种是User,一种就是service account,User给人用的,service account给进程用的,让进程有相关的权限。
如dasboard就是一个进程,我们就可以创建一个service account给它,让它去访问k8s。
示例1: dashborad yaml
# ------------------- Dashboard Secret ------------------- # apiVersion: v1 kind: Secret metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard-certs namespace: kube-system type: Opaque --- # ------------------- Dashboard Service Account ------------------- # apiVersion: v1 kind: ServiceAccount metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard namespace: kube-system --- # ------------------- Dashboard Role & Role Binding ------------------- # kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: name: kubernetes-dashboard-minimal namespace: kube-system rules: # Allow Dashboard to create 'kubernetes-dashboard-key-holder' secret. - apiGroups: [""] resources: ["secrets"] verbs: ["create"] # Allow Dashboard to create 'kubernetes-dashboard-settings' config map. - apiGroups: [""] resources: ["configmaps"] verbs: ["create"] # Allow Dashboard to get, update and delete Dashboard exclusive secrets. - apiGroups: [""] resources: ["secrets"] resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs"] verbs: ["get", "update", "delete"] # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map. - apiGroups: [""] resources: ["configmaps"] resourceNames: ["kubernetes-dashboard-settings"] verbs: ["get", "update"] # Allow Dashboard to get metrics from heapster. - apiGroups: [""] resources: ["services"] resourceNames: ["heapster"] verbs: ["proxy"] - apiGroups: [""] resources: ["services/proxy"] resourceNames: ["heapster", "http:heapster:", "https:heapster:"] verbs: ["get"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: kubernetes-dashboard-minimal namespace: kube-system roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: kubernetes-dashboard-minimal subjects: - kind: ServiceAccount name: kubernetes-dashboard namespace: kube-system --- # ------------------- Dashboard Deployment ------------------- # kind: Deployment apiVersion: apps/v1 metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard namespace: kube-system spec: replicas: 1 revisionHistoryLimit: 10 selector: matchLabels: k8s-app: kubernetes-dashboard template: metadata: labels: k8s-app: kubernetes-dashboard spec: nodeSelector: node-role.kubernetes.io/master: "" containers: - name: kubernetes-dashboard image: registry.cn-hangzhou.aliyuncs.com/k8sth/kubernetes-dashboard-amd64:v1.8.3 ports: - containerPort: 8443 protocol: TCP args: - --auto-generate-certificates # Uncomment the following line to manually specify Kubernetes API server Host # If not specified, Dashboard will attempt to auto discover the API server and connect # to it. Uncomment only if the default does not work. # - --apiserver-host=http://my-address:port volumeMounts: - name: kubernetes-dashboard-certs mountPath: /certs # Create on-disk volume to store exec logs - mountPath: /tmp name: tmp-volume livenessProbe: httpGet: scheme: HTTPS path: / port: 8443 initialDelaySeconds: 30 timeoutSeconds: 30 volumes: - name: kubernetes-dashboard-certs secret: secretName: kubernetes-dashboard-certs - name: tmp-volume emptyDir: {} serviceAccountName: kubernetes-dashboard # Comment the following tolerations if Dashboard must not be deployed on master tolerations: - key: node-role.kubernetes.io/master effect: NoSchedule --- # ------------------- Dashboard Service ------------------- # kind: Service apiVersion: v1 metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard namespace: kube-system spec: type: NodePort ports: - port: 443 targetPort: 8443 nodePort: 30000 selector: k8s-app: kubernetes-dashboard --- apiVersion: v1 kind: ServiceAccount metadata: name: admin-user namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: admin-user roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: admin-user namespace: kube-system # 获取TOken # kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')
示例2: 创建devuser的用户,并赋予特定namespace下的pod只读权限
第一步,安装cfssl
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 chmod +x cfssl_linux-amd64 mv cfssl_linux-amd64 /bin/cfssl wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 chmod +x cfssljson_linux-amd64 mv cfssljson_linux-amd64 /bin/cfssljson wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 chmod +x cfssl-certinfo_linux-amd64 mv cfssl-certinfo_linux-amd64 /bin/cfssl-certinfo
第二步,签发客户端证书
创建ca-config.json文件
cat > ca-config.json <<EOF { "signing": { "default": { "expiry": "87600h" }, "profiles": { "kubernetes": { "usages": [ "signing", "key encipherment", "server auth", "client auth" ], "expiry": "87600h" } } } } EOF
创建devuser-csr.json文件
cat > devuser-csr.json <<EOF { "CN": "devuser", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "System" } ] } EOF
第三步,生成devuser的证书
$ cfssl gencert -ca=ca.crt -ca-key=ca.key -config=ca-config.json -profile=kubernetes devuser-csr.json | cfssljson -bare devuser
就会生成3个文件:devuser.csr devuser-key.pem devuser.pem
第四步,生成config文件
ubeadm已经生成了admin.conf,我们可以直接利用这个文件,省的自己再去配置集群参数
$ cp /etc/kubernetes/admin.conf devuser.kubeconfig
设置客户端认证参数:
kubectl config set-credentials devuser --client-certificate=/etc/kubernetes/pki/devuser.pem --client-key=/etc/kubernetes/pki/devuser-key.pem --embed-certs=true --kubeconfig=devuser.kubeconfig
设置上下文参数:
kubectl config set-context kubernetes --cluster=kubernetes --user=devuser --namespace=kube-system --kubeconfig=devuser.kubeconfig
设置莫认上下文:
kubectl config use-context kubernetes --kubeconfig=devuser.kubeconfig
以上执行一个步骤就可以看一下 devuser.kubeconfig的变化。里面最主要的三个东西
- cluster: 集群信息,包含集群地址与公钥
- user: 用户信息,客户端证书与私钥,正真的信息是从证书里读取出来的,人能看到的只是给人看的。
- context: 维护一个三元组,namespace cluster 与 user
第五步,创建角色
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: kube-system name: pod-reader rules: - apiGroups: [""] # 表示核心API Group resources: ["pods"] # 能够访问的资源对象 verbs: ["get", "watch", "list"] # 能够执行的操作 --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: read-pods namespace: kube-system subjects: - kind: User name: devuser namespace: kube-system apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io
第六步,使用新的config文件
$ rm .kube/config && cp devuser.kubeconfig .kube/config
第七步,测试效果
[root@node01 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE coredns-777d78ff6f-rrpx8 1/1 Running 3 8d coredns-777d78ff6f-tql47 1/1 Running 3 8d etcd-node01 1/1 Running 3 8d kube-apiserver-node01 1/1 Running 3 8d kube-controller-manager-node01 1/1 Running 3 8d kube-flannel-ds-rxrp5 1/1 Running 3 8d kube-proxy-r6bd2 1/1 Running 3 8d kube-scheduler-node01 1/1 Running 2 8d kubernetes-dashboard-d4866d978-kpz4m 1/1 Running 0 10h [root@node01 ~]# kubectl get service No resources found. Error from server (Forbidden): services is forbidden: User "devuser" cannot list services in the namespace "kube-system"
参考文档:https://www.jianshu.com/p/61e8297f9838