十. k8s--访问控制 serviceaccount和RBAC 学习笔记

[TOC]html

用户帐户与服务帐户

Kubernetes 区分用户帐户和服务帐户的概念主要基于如下缘由:node

  • 用户帐户是针对人而言的。 服务帐户是针对运行在pod中的进程而言的。
  • 用户帐户是全局性的。 其名称在集群各namespace中都是全局惟一的,将来的用户资源不会作namespace隔离, 服务帐户是namespace隔离的。
  • 一般状况下,集群的用户帐户可能会从企业数据库进行同步,其建立须要特殊权限,而且涉及到复杂的业务流程。 服务帐户建立的目的是为了更轻量,容许集群用户为了具体的任务建立服务帐户 (即权限最小化原则)。
  • 对人员和服务帐户审计所考虑的因素可能不一样。
  • 针对复杂系统的配置可能包含系统组件相关的各类服务帐户的定义。 由于服务帐户能够定制化地建立,而且有namespace级别的名称,这种配置是很轻量的。
UserAccount经常使用于复杂业务逻辑管控,做用于系统全局,独立于K8s以外
ServiceAccount仅用于实现某些特定操做任务,隶属于名称空间,由API Server管理

访问控制过程

客户端 → API Server → 认证插件 → 受权插件 → 准入控制插件 → 写入成功nginx

须要注意:认证受权过程只存在HTTPS形式的API中。也就是说,若是客户端使用HTTP链接到kube-apiserver,是不会进行认证受权的。因此说,能够这么设置,在集群内部组件间通讯使用HTTP集群, 外部就使用HTTPS,这样既增长了安全性,也不至于太复杂。
### K8s内建用户组:
  • system:unauthenticated,未经过认证测试的用户所属的组
  • system:authenticated,认证成功的用户自动加入的组,用于快捷引用全部正常经过认证的用户账号
  • system:serviceaccounts,当前系统上全部Service Account对象
  • system:serviceaccounts:<namespace>,特定名称空间内全部Service Account对象

认证. 受权与准入控制

  • API Server支持同时启用多种认证机制, 但至少包括UserAccount和ServiceAccount中的一种
  • 启用多种认证插件时, 认证过程会以串行方式进行, 直到一种成功便可, 认证失败会返回401

认证方式

  1. X509客户端证书认证:客户端请求报文中携带X509格式证书,经过后,CN字段是用户名,O字段是所属的组,O能够有多个,即属于多个组
  2. 静态令牌文件:由kube-apiserver 选项--token-auth-file加载,启动后不可更改;HTTP客户端也能使用承载令牌进行身份验证,将令牌编码后,请求报文中Authorization承载传递
  3. 引导令牌:kubeadm join将节点加入集群时,就是这种方式
  4. 静态密码文件:用户名密码等以明文存储的CSV格式文件,由kube-apiserver经过--basic-auth-file加载
  5. 服务账户令牌:由kube-apiserver自动启用。ServiceAccount一般由API Server自动建立,并经过ServiceAccount准入控制器将其注入Pod对象,容器中应用请求API Server的服务时将以此完成身份证
  6. OpenID链接令牌:OAuth2认证
  7. Webhook令牌:客户端使用kubeconfig格式的配置文件
  8. 认证代理:X-Remote-User
  9. Keystone密码:借助Keystone服务器进行身份认证
  10. 匿名请求:未被任何验证机制明确拒绝的用户即匿名用户,system:anonymous 属于 system:unauthenticated组;匿名用户可经过 --anonymous-auth=false禁用

内建的受权插件:

  1. Node,基于Pod资源的目标调度节点来实现对kubelet的访问控制shell

  2. ABAC,基于属性的访问控制,attribute-based access control数据库

  3. RBAC,基于角色的访问控制,role-based access controlapi

  4. Webhook,基于HTTP回调机制经过外部REST服务检查确认用户受权的访问控制安全

  5. AlwaysDeny,老是拒绝,仅用于测试服务器

  6. AlwaysAllow,老是容许app

    启用API Server时 --authorization-mode定义要启用的受权机制,多个选项以逗号分隔frontend

准入控制器

在对象持久化存储etcd前,强制执行对象的语义验证等功能 读取资源信息的请求不会通过准入控制器检查

  1. AlwaysAdmit,容许全部请求
  2. AlwaysDeny,拒绝全部请求,仅用于测试
  3. AlwaysPullImages,老是下载镜像
  4. NamespaceLifecycle,拒绝在不存在的名称空间建立资源,删除名称空间会级联删除其下全部资源
  5. LimitRanger,可用资源范围界定,确保资源请求不会超限
  6. ServiceAccount,实现ServiceAccount管理机制自动化,建立Pod对象时自动为其附加相关ServiceAccount对象
  7. PersistnetVolumeLabel,为由云计算服务商提供的PV自动附加region或zone标签
  8. DefaultStorageClass,监控全部建立PVC对象的请求,保证没有附加专用StorageClass的请求会自动设定一个默认值
  9. ResourceQuota,对名称空间设置可用资源上限,确保在其中建立的设置了资源限额的对象不会超出名称空间的资源配额
  10. DefaultTolerationSeconds,若是Pod对象上不存在污点宽容期限,则为它们设置默认宽容期,以宽容 notready:NoExecute 和 unreachable:NoExctute 类污点5min
  11. ValidatingAdmissionWebhook,并行调用匹配当前请求的全部验证类Webhook,任何一个校验失败,请求即失败
  12. MutatingAdmissionWebhook,串行调用匹配当前请求的全部变异类Webhook,每一个调用均可能会更改对象

ServiceAccount管理与应用

Service Account 资源通常由用户名和相关的Secret对象组成
用于让Pod对象内的容器进程访问其余服务时提供身份认证信息,这些其余服务包括:API 调度器 Pod控制器 节点控制器 私有Registry服务等

Service Account 自动化

每一个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 describe serviceaccounts default Name: default Namespace: default Labels: Annotations: Image pull secrets: Mountable secrets: default-token-l5bzk Tokens: default-token-l5bzk Events: ```

K8s中的SSL/TLS认证

  • etcd集群内对等节点通讯:默认2380端口,基于SSL/TLS通讯
  • etcd服务器与客户端通讯:Restful API 默认2379端口,基于SSL/TLS通讯

建立一个ServiceAccount

#测试
[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

客户端配置文件kubeconfig

包括kubectl、kubelet、kube-controller-manager等在内的API Server的各种客户端均可以使用kubeconfig配置文件提供接入多个集群的相关配置信息

包括API Server的URL及认证信息,且可设置不一样的上下文,并在各环境之间快速切换

/etc/kubernetes/admin.conf即为kubeconfig格式的配置文件

查看当前正在使用的配置文件, 上下文是集群和用户的配对
``` kubectl config view #显示群集列表、用户列表、上下文列表、当前使用的上下文 ```
[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段

添加ServiceAccount

  1. 为账号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 # 验证证书(可选)
  2. 以默认管理员 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 (Role-Based Access Control)

相关概念

Role与ClusterRole

在RBAC API中,一个角色包含了一套表示一组权限的规则。 权限以纯粹的累加形式累积(没有”否认”的规则)。 角色能够由命名空间(namespace)内的Role对象定义,而整个Kubernetes集群范围内有效的角色则经过ClusterRole对象实现。

一个Role对象只能用于授予对某一单一命名空间中资源的访问权限。
如下示例描述了”default”命名空间中的一个Role对象的定义,用于授予对pod的读访问权限:
**建立一个`role`**
[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对象相同的权限,但因为它们属于集群范围对象, 也可使用它们授予对如下几种资源的访问权限:
- 集群范围资源(例如节点,即node) - 非资源类型endpoint(例如”/healthz”) - 跨全部命名空间的命名空间范围资源(例如pod,须要运行命令`kubectl get pods --all-namespaces`来查询集群中全部的pod)

建立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

ClusterRoleUser绑定, 并验证权限是否生效

[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

RoleBinding与ClusterRoleBinding

角色绑定将一个角色中定义的各类权限授予一个或者一组用户。 角色绑定包含了一组相关主体(即subject, 包括用户——User、用户组——Group、或者服务帐户——Service Account)以及对被授予角色的引用。 在命名空间中能够经过RoleBinding对象授予权限,而集群范围的权限授予则经过ClusterRoleBinding对象完成。

RoleBinding能够引用在同一命名空间内定义的Role对象。 下面示例中定义的RoleBinding对象在”default”命名空间中将”pod-reader”角色授予用户”kube-user1”。 这一受权将容许用户”kube-user1”从”default”命名空间中读取pod。
```yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: user1-read-pods namespace: default roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: pod-reader subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: kube-user1 ```
RoleBinding对象也能够引用一个ClusterRole对象用于在RoleBinding所在的命名空间内授予用户对所引用的ClusterRole中 定义的命名空间资源的访问权限。这一点容许管理员在整个集群范围内首先定义一组通用的角色,而后再在不一样的命名空间中复用这些角色。
**将clusterrole经过rolebinding和user绑定到一块儿, 会降级到rolebinding所在的namespace**
[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"

最后将ClusterRoleUser经过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

参考连接

https://pdf.us/2019/03/21/3061.html

https://jimmysong.io/kubernetes-handbook/concepts/rbac.html

相关文章
相关标签/搜索