在Kubernetes中,所有资源对象都是通过API进行操作,他们保存在etcd里。而对etcd的操作我们需要通过访问 kube-apiserver 来实现,上面的Service Account其实就是APIServer的认证过程,而授权的机制是通过RBAC:基于角色的访问控制实现。
RBAC有四个资源对象,分别是:
一组权限的集合,在一个命名空间中,可以用其来定义一个角色,只能对命名空间内的资源进行授权。如果是集群级别的资源,则需要使用ClusterRole。例如:定义一个角色用来读取Pod的权限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: rbac
name: pod-read
rules:
- apiGroups: [""]
resources: ["pods"]
resourceNames: []
verbs: ["get","watch","list"]
rules中的参数说明:
1、apiGroups:支持的API组列表,例如:"apiVersion: apps/v1"等
2、resources:支持的资源对象列表,例如pods、deployments、jobs等
3、resourceNames: 指定resource的名称
4、verbs:对资源对象的操作方法列表。
具有和角色一致的命名空间资源的管理能力,还可用于以下特殊元素的授权
举例:定义一个集群角色可让用户访问任意secrets
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: secrets-clusterrole
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get","watch","list"]
角色绑定和集群角色绑定用于把一个角色绑定在一个目标上,可以是User,Group,Service Account,使用RoleBinding为某个命名空间授权,使用ClusterRoleBinding为集群范围内授权。
例如:将在rbac命名空间中把pod-read角色授予用户es
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-read-bind
namespace: rbac
subjects:
- kind: User
name: es
apiGroup: rbac.authorization.k8s.io
roleRef:
- kind: Role
name: pod-read
apiGroup: rbac.authorizatioin.k8s.io
RoleBinding也可以引用ClusterRole,对属于同一命名空间内的ClusterRole定义的资源主体进行授权, 例如:es能获取到集群中所有的资源信息
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: es-allresource
namespace: rbac
subjects:
- kind: User
name: es
apiGroup: rbac.authorization.k8s.io
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
多数资源可以用其名称的字符串表示,也就是Endpoint中的URL相对路径,例如pod中的日志是GET
/api/v1/namaspaces/{namespace}/pods/{podname}/log
例如:若想授权让某个主体同时能够读取Pod和Pod log,则可以配置 resources为一个数组
kubectl create ns test
vim role-test.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: logs-reader
namespace: test
rules:
- apiGroups: [""]
resources: ["pods","pods/log"]
verbs: ["get","list","watch"]
kubectl apply -f role-test.yaml
kubectl create sa sa-test -n test
kubectl create rolebinding sa-test-1 -n test --role=logs-reader --serviceaccount=test:sa-test
vim pod-test.yaml
apiVersion: v1
kind: Pod
metadata:
name: sa-test-pod
namespace: test
labels:
app: sa
spec:
serviceAccountName: sa-test
containers:
- name: sa-tomcat
ports:
- containerPort: 80
image: nginx
imagePullPolicy: IfNotPresent
kubectl apply -f pod-test.yaml
kubectl exec -it sa-test-pod -n test -- /bin/bash
root@sa-test-pod:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt -H "Authorization: Bearer $(cat ./token)" https://kubernetes.default/api/v1/namespaces/test/pods/sa-test-pod/logs
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "pods \"sa-test-pod\" is forbidden: User \"system:serviceaccount:test:sa-test\" cannot get resource \"pods/logs\" in API group \"\" in the namespace \"test\"",
"reason": "Forbidden",
"details": {
"name": "sa-test-pod",
"kind": "pods"
},
"code": 403
}
kubectl create rolebinding sa-test-2 -n test --role=logs-reader --user=system:serviceaccount:test:sa-test
root@sa-test-pod:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt -H "Authorization: Bearer $(cat ./token)" https://kubernetes.default/api/v1/namespaces/test/pods/sa-test-pod/log
例如,下面的声明让一个主体只能对名为my-configmap的Configmap进行get和update操作:
apiVersion: rabc.authorization.k8s.io/v1
kind: Role
metadata:
namaspace: default
name: configmap-update
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["my-configmap"]
verbs: ["get","update"]
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get","list","watch","create","update","patch","delete"]
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
- apiGroups: [""]
resources: ["jobs"]
verbs: ["get","list","watch","create","update","patch","delete"]
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["my-configmap"]
verbs: ["get"]
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get","list","watch"]
rules:
- nonResourceURLs: ["/healthz","/healthz/*"]
verbs: ["get","post"]
subjects:
- kind: User
name: alice
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: Group
name: alice
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: default
namespace: kube-system
Service Account也是一种账号,是给运行在Pod里的进程提供了必要的身份证明。需要在Pod定义中指明引用的Service Account,这样就可以对Pod的进行赋权操作。
例如:pod内可获取rbac命名空间的所有Pod资源,pod-reader-sc的Service Account是绑定了名为pod-read的Role
kubectl create ns rbac
kubectl create sa pod-reader-sc -n rbac
cat pod-rbac.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: rbac
spec:
serviceAccountName: pod-reader-sc
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
kubectl apply -f pod-rbac.yaml
kubectl create rolebinding my-sa-view --clusterrole=view --serviceaccount=my-namespace:my-sa --namespace=my-namespace
kubectl create rolebinding default-view --clusterrole=view --serviceaccount=my-namespace:default --namespace=my-namespace
如果希望在一个命名空间中,任何Service Account应用都具有一个角色,则可以为这一命名空间的Service Account群组进行授权
kubectl create rolebinding serviceaccounts-view --clusterrole=view --group=system:serviceaccounts:my-namespace --namespace=my-namespace
如果不想为每个命名空间管理授权,则可以把一个集群级别的角色赋给所有Service Account。
kubectl create clusterrolebinding serviceaccounts-view --clusterrole=view --group=system:serviceaccounts
kubectl create clusterrolebinding serviceaccounts-view --clusterrole=cluster-admin --group=system:serviceaccounts
kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=es --namespace=rbac
kubctl create rolebinding myapp-role-binding --clusterrole=view --serviceaccount=rbac:myapp --namespace=rbac
kubectl create clusterrolebinding cluster-binding --clusterrole=cluster-admin --user=root
kubectl create clusterrolebinding service-account-binding --clusterrole=view --serviceaccount=myapp
生成一个证书
生成一个私钥
cd /etc/kubernetes/pki/
(umask 077; openssl genrsa -out lucky.key 2048)
生成一个证书请求
openssl req -new -key lucky.key -out lucky.csr -subj "/CN=lucky"
生成一个证书
openssl x509 -req -in lucky.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out lucky.crt -days 3650
在kubeconfig下新增加一个lucky这个用户
把lucky这个用户添加到kubernetes集群中,可以用来认证apiserver的连接
kubectl config set-credentials lucky --client-certificate=./lucky.crt --client-key=./lucky.key --embed-certs=true
在kubeconfig下新增加一个lucky这个账号
kubectl config set-context lucky@kubernetes --cluster=kubernetes --user=lucky
切换账号到lucky,默认没有任何权限
kubectl config use-context lucky@kubernetes
kubectl config use-context kubernetes-admin@kubernetes #这个是集群用户,有任何权限
把user这个用户通过rolebinding绑定到clusterrole上,授予权限,权限只是在lucky这个名称空间有效
kubectl create ns lucky-test
kubectl create rolebinding lucky -n lucky-test --clusterrole=cluster-admin --user=lucky
切换到lucky这个用户
kubectl config use-context lucky@kubernetes
测试是否有权限
kubectl get pods -n lucky-test
添加一个test的普通用户
useradd test
cp -ar /root/.kube /tmp/
#修改/tmp/.kube/config文件,把kubernetes-admin相关的删除,只留lucky用户
cp -ar /tmp/.kube/ /home/test/
chown -R test.test /home/test/
su - test
kubectl get pods -n lucky
退出test用户,需要在把集群环境切换成管理员权限
kubectl config use-context kubernetes-admin@kubernetes
生成一个私钥
cd /etc/kubernetes/pki/
(umask 077; openssl genrsa -out lucky1.key 2048)
生成一个证书请求
openssl req -new -key lucky1.key -out lucky1.csr -subj "/CN=lucky66"
生成一个证书
openssl x509 -req -in lucky1.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out lucky1.crt -days 3650
把lucky66这个用户添加到kubernetes集群中,可以用来认证apiserver的连接
kubectl config set-credentials lucky66 --client-certificate=./lucky1.crt --client-key=./lucky1.key --embed-certs=true
在kubeconfig下新增加一个lucky66这个账号
kubectl config set-context lucky66@kubernetes --cluster=kubernetes --user=lucky66
创建一个clusterrole
vim lucky66-clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: lucky66-get-pod
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
kubectl apply -f lucky66-clusterrole.yaml
创建一个clusterrolebinding
kubectl create clusterrolebinding lucky66-get-pods --clusterrole=lucky66-get-pod --user=lucky66
添加一个test66的普通用户
useradd test66
rm -rf /tmp/.kube
cp -ar /root/.kube /tmp/
#修改/tmp/.kube/config文件,把kubernetes-admin和lucky相关的删除,只留lucky66用户
cp -ar /tmp/.kube/ /home/test66/
chown -R test66.test66 /home/test66/
vim /home/test66/.kube/config
#把current-context变成如下:
current-context: lucky66@kubernetes
su - test66
kubectl get pods
kubectl get pods -n kube-system