[TOC]html
Kubernetes 区分用户帐户和服务帐户的概念主要基于如下缘由:node
- 用户帐户是针对人而言的。 服务帐户是针对运行在pod中的进程而言的。
- 用户帐户是全局性的。 其名称在集群各namespace中都是全局惟一的,将来的用户资源不会作namespace隔离, 服务帐户是namespace隔离的。
- 一般状况下,集群的用户帐户可能会从企业数据库进行同步,其建立须要特殊权限,而且涉及到复杂的业务流程。 服务帐户建立的目的是为了更轻量,容许集群用户为了具体的任务建立服务帐户 (即权限最小化原则)。
- 对人员和服务帐户审计所考虑的因素可能不一样。
- 针对复杂系统的配置可能包含系统组件相关的各类服务帐户的定义。 由于服务帐户能够定制化地建立,而且有namespace级别的名称,这种配置是很轻量的。
UserAccount经常使用于复杂业务逻辑管控,做用于系统全局,独立于K8s以外 ServiceAccount仅用于实现某些特定操做任务,隶属于名称空间,由API Server管理
客户端 → API Server → 认证插件 → 受权插件 → 准入控制插件 → 写入成功nginx
须要注意:认证受权过程只存在HTTPS形式的API中。也就是说,若是客户端使用HTTP链接到kube-apiserver,是不会进行认证受权的。因此说,能够这么设置,在集群内部组件间通讯使用HTTP集群, 外部就使用HTTPS,这样既增长了安全性,也不至于太复杂。 |
Node,基于Pod资源的目标调度节点来实现对kubelet的访问控制shell
ABAC,基于属性的访问控制,attribute-based access control数据库
RBAC,基于角色的访问控制,role-based access controlapi
Webhook,基于HTTP回调机制经过外部REST服务检查确认用户受权的访问控制安全
AlwaysDeny,老是拒绝,仅用于测试服务器
AlwaysAllow,老是容许app
启用API Server时 --authorization-mode定义要启用的受权机制,多个选项以逗号分隔frontend
在对象持久化存储etcd前,强制执行对象的语义验证等功能 读取资源信息的请求不会通过准入控制器检查
Service Account 资源通常由用户名和相关的Secret对象组成 用于让Pod对象内的容器进程访问其余服务时提供身份认证信息,这些其余服务包括:API 调度器 Pod控制器 节点控制器 私有Registry服务等 |
每一个Pod都会自动关联一个存储卷,挂载至 /var/run/secrets/kubernetes.io/serviceaccount
[root@master ~]# kubectl exec nginx-554b9c67f9-r5852 ls /var/run/secrets/kubernetes.io/serviceaccount ca.crt # 这是API Server的CA公钥证书,用于Pod中的Process对API Server的服务端数字证书进行校验时使用的 namespace token # token保存了Service Account的认证token 容器中进程使用它向API Server发起链接请求
每一个Pod对象都只有一个服务账户,若建立时未明确指定,会自动附加当前名称空间中默认服务账户default |
#测试 [root@master ~]# kubectl create serviceaccount admin -o yaml --dry-run #干跑 apiVersion: v1 kind: ServiceAccount metadata: creationTimestamp: null name: admin kubectl create serviceaccount admin #查看以建立的service账号 [root@master ~]# kubectl get sa NAME SECRETS AGE admin 1 6s default 1 24d #查看详细信息 kubectl describe sa admin ##简洁输出 kubectl get pods myapp-0 -o yaml --export
pod使用上述建立的ServiceAccount
apiVersion: v1 kind: Pod metadata: name: pod-sa-demo namespace: default labels: app: myapp tier: frontend annotations: leiyan.com/reatedby: "cluster admin" spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: http containerPort: 80 serviceAccountName: admin
包括kubectl、kubelet、kube-controller-manager等在内的API Server的各种客户端均可以使用kubeconfig配置文件提供接入多个集群的相关配置信息
包括API Server的URL及认证信息,且可设置不一样的上下文,并在各环境之间快速切换
/etc/kubernetes/admin.conf
即为kubeconfig
格式的配置文件
查看当前正在使用的配置文件, 上下文是集群和用户的配对 |
[root@master ~]# kubectl config view apiVersion: v1 clusters: - cluster: certificate-authority-data: DATA+OMITTED server: https://10.0.0.50:6443 name: kubernetes contexts: - context: cluster: kubernetes user: kubernetes-admin name: kubernetes-admin@kubernetes current-context: kubernetes-admin@kubernetes kind: Config preferences: {} users: - name: kubernetes-admin user: client-certificate-data: REDACTED client-key-data: REDACTED
kubeconfig配置文件可经过kubectl config命令进行设定
kubectl config view,打印文件内容 kubectl config set-cluster,设置clusters段 kubectl config set-credentials,设置users段 kubectl config set-context,设置contexts段 kubectl config set-use-context,设置current-context段
为账号kube-user1建立私钥及证书文件,保存于/etc/kubernetes/pki目录中 #须要在master节点以root用户执行
cd /etc/kubernetes/pki (umask 077; openssl genrsa -out kube-user1.key 2048) openssl req -new -key kube-user1.key -out kube-user1.csr -subj "/CN=kube-user1/O=kubeusers" # 其中 CN是用户名,O是用户组 openssl x509 -req -in kube-user1.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out kube-user1.crt -days 3650 openssl x509 -in kube-user1.crt -text -noout # 验证证书(可选)
以默认管理员 kubernetes-admin@kubernetes为新用户kube-user1设定配置文件,默认保存于 .kube/config 也可以使用 --kubeconfig指定自定义路径
2.1 配置集群信息,存在可省略此步骤
kubectl config set-cluster kubernetes-new --embed-certs=true --certificate-authority=/etc/kubernetes/pki/ca.crt --server="https://10.0.0.50:6443"
2.2 配置客户端证书及密钥,用户名组名会自动提取
kubectl config set-credentials kube-user1 --embed-certs=true --client-certificate=/etc/kubernetes/pki/kube-user1.crt --client-key=/etc/kubernetes/pki/kube-user1.key
2.3 配置context,组合cluster和credentials
kubectl config set-context kube-user1@kubernetes-new --cluster=kubernetes-new --user=kube-user1
2.4 指定当前上下文
kubectl config use-context kube-user1@kubernetes-new
2.5 测试
[root@master pki]# kubectl get pods Error from server (Forbidden): pods is forbidden: User "kube-user1" cannot list resource "pods" in API group "" in the namespace "default" #切换回来 kubectl config use-context kubernetes-admin@kubernetes [root@master pki]# kubectl get pods NAME READY STATUS RESTARTS AGE nginx-554b9c67f9-r5852 1/1 Running 0 89m pod-cm-1 1/1 Running 0 6d pod-cm-2 1/1 Running 0 6d pod-hostpath-demo 1/1 Terminating 0 7d21h
在RBAC API中,一个角色包含了一套表示一组权限的规则。 权限以纯粹的累加形式累积(没有”否认”的规则)。 角色能够由命名空间(namespace)内的Role
对象定义,而整个Kubernetes集群范围内有效的角色则经过ClusterRole
对象实现。
一个Role对象只能用于授予对某一单一命名空间中资源的访问权限。 如下示例描述了”default”命名空间中的一个Role对象的定义,用于授予对pod的读访问权限: |
[root@master manifests]# cat role-demo.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: pods-reader namespace: default rules: - apiGroups: - "" resources: - pods verbs: - get - list - watch
[root@master manifests]# kubectl apply -f role-demo.yaml role.rbac.authorization.k8s.io/pods-reader created
将role和user绑定, 并验证已经生效, 能够get到pod资源
# 将kube-user1和pods-reader绑定 [root@master manifests]# kubectl create rolebinding kube-user1-read-pods --role=pods-reader --user=kube-user1 rolebinding.rbac.authorization.k8s.io/kube-user1-read-pods created # 切换用户到kube-user1 [root@master manifests]# kubectl config use-context kube-user1@kubernetes Switched to context "kube-user1@kubernetes". # 测试能够get到pod信息 [root@master manifests]# kubectl get pod NAME READY STATUS RESTARTS AGE myapp-0 1/1 Running 0 5d4h myapp-1 1/1 Running 0 5d4h myapp-2 1/1 Running 0 5d4h myapp-3 1/1 Running 0 5d4h
ClusterRole对象能够授予与Role对象相同的权限,但因为它们属于集群范围对象, 也可使用它们授予对如下几种资源的访问权限: |
建立ClusterRole
[root@master manifests]# cat cluster-role-demo.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: cluster-role rules: - apiGroups: - "" resources: - pods verbs: - get - list - watch
[root@master manifests]# kubectl apply -f cluster-role-demo.yaml clusterrole.rbac.authorization.k8s.io/cluster-role created
将ClusterRole
和User
绑定, 并验证权限是否生效
[root@master manifests]# cat clusterrolebinding-demo.yaml apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: user1-read-all-pods roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-reader subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: kube-user1
[root@master manifests]# kubectl apply -f clusterrolebinding-demo.yaml clusterrolebinding.rbac.authorization.k8s.io/user1-read-all-pods created
验证权限
# 切换用户到kube-user1 [root@master manifests]# kubectl config use-context kube-user1@kubernetes Switched to context "kube-user1@kubernetes". # 成功获取到默认namespace的pod信息 [root@master manifests]# kubectl get pod NAME READY STATUS RESTARTS AGE myapp-0 1/1 Running 0 5d4h myapp-1 1/1 Running 0 5d4h myapp-2 1/1 Running 0 5d4h myapp-3 1/1 Running 0 5d4h # 成功获取到其余namespace的pod信息 [root@master manifests]# kubectl get pod -n ingress-nginx NAME READY STATUS RESTARTS AGE nginx-ingress-controller-7995bd9c47-crpwt 1/1 Running 0 12d
角色绑定将一个角色中定义的各类权限授予一个或者一组用户。 角色绑定包含了一组相关主体(即subject, 包括用户——User、用户组——Group、或者服务帐户——Service Account)以及对被授予角色的引用。 在命名空间中能够经过RoleBinding
对象授予权限,而集群范围的权限授予则经过ClusterRoleBinding
对象完成。
RoleBinding能够引用在同一命名空间内定义的Role对象。 下面示例中定义的RoleBinding对象在”default”命名空间中将”pod-reader”角色授予用户”kube-user1”。 这一受权将容许用户”kube-user1”从”default”命名空间中读取pod。 |
RoleBinding对象也能够引用一个ClusterRole对象用于在RoleBinding所在的命名空间内授予用户对所引用的ClusterRole中 定义的命名空间资源的访问权限。这一点容许管理员在整个集群范围内首先定义一组通用的角色,而后再在不一样的命名空间中复用这些角色。 |
[root@master manifests]# cat rolebinding-clusterrole.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: user1-read-pods namespace: default roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-reader subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: kube-user1 [root@master manifests]# kubectl apply -f rolebinding-clusterrole.yaml rolebinding.rbac.authorization.k8s.io/user1-read-pods created
这时候发现只能获取到RoleBinding
设置的namespace
中的pod
了
[root@master ~]# kubectl config use-context kube-user1@kubernetes Switched to context "kube-user1@kubernetes". [root@master ~]# kubectl get pod NAME READY STATUS RESTARTS AGE myapp-0 1/1 Running 0 5d4h myapp-1 1/1 Running 0 5d4h myapp-2 1/1 Running 0 5d4h myapp-3 1/1 Running 0 5d4h [root@master ~]# kubectl get pod -n ingress-nginx Error from server (Forbidden): pods is forbidden: User "kube-user1" cannot list resource "pods" in API group "" in the namespace "ingress-nginx"
最后将ClusterRole
和User
经过ClusterRoleBinding
绑定到一块儿
容许用户kube-user1读取全部namespace的pod信息
apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: user1-read-all-pods roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-reader subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: kube-user1
[root@master manifests]# kubectl apply -f clusterrolebinding-demo.yaml clusterrolebinding.rbac.authorization.k8s.io/user1-read-all-pods created
[root@master manifests]# kubectl config use-context kube-user1@kubernetes Switched to context "kube-user1@kubernetes". [root@master manifests]# kubectl get pod NAME READY STATUS RESTARTS AGE myapp-0 1/1 Running 0 5d7h myapp-1 1/1 Running 0 5d7h myapp-2 1/1 Running 0 5d7h myapp-3 1/1 Running 0 5d7h [root@master manifests]# kubectl get pod -n ingress-nginx NAME READY STATUS RESTARTS AGE nginx-ingress-controller-7995bd9c47-crpwt 1/1 Running 0 13d