1、k8s中的访问控制

        API server作为kubernetes集群系统的网关,是访问及管理资源对象的唯一入口,而其他所有的组件及kubectl命令都要经由此网关进行集群的访问和管理。而各组件及客户端每一次的访问请求都要有api server进行合法性校验,包括身份鉴别、操作权限验证等。所有的检查通过之后才能访问或存入数据于后端的etcd中。客户端的认证操作是由api server配置的一到多个认证插件完成,授权操作由一到多个授权插件进行,而通过授权检测的用户所请求的相关操作还要经由一到多个准入控制插件的遍历检测。

(1)用户账号和用户组

        客户端访问API服务的途径通常有三种分别是kubectl、客户端库、REST接口,而执行此类请求的主体通常有两类分别是常规用户(User Account)和服务账号(Service Account)。

          ①User Account:一般是独立于kubernetes之外的其他服务管理的用户账号,如管理员分发的秘钥、keystone一类的用户  存储等。Kubernetes中不存在标识此类用户账户的对象,因此,不能被直接添加进kubernetes系统中。该账号通常用于复杂的业务逻辑管控,它作用于系统全局,故其名称必须全局唯一。

          ②Service Account:是由kubernetes API管理的账号,用于为Pod中的服务进程在访问Kubernetes API时提供身份标识。该账户需要绑定于特定的名称空间,他们由API server创建或,附带着一组存储为secret的用于访问api的凭证。Service Account隶属于名称空间,仅用于实现某些特定的操作任务。

        用户组是用户账号的逻辑集合,本身并无操作权限,但附加于组上的权限可由其内部的所有用户继承,以实现高效的授权管理机制。Kubernetes中附带着一些内建的用于特殊目的的组。

(2)认证、授权与准入控制

        Kubernetes使用身份认证插件对API请求进行身份认证时支持的认证方式包括客户端认证、承载令牌认证(bearer tokens)、身份验证代理(authingenticating proxy)及http base认证等。API Server同时支持多种认证机制,但至少分别为Service Accoun和User Account各自启用一个认证插件。API server支持的具体认证方式有:

          ①X509客户端证书认证

          ②静态令牌文件(Static Token File):由kube-apiserver的命令行工具—token-auth-file加载

          ③引导令牌(Bootstrap Tokens):动态管理承载令牌进行身份认证的方式,常用于简化新建kubernetes集群的节点认证过程

          ④静态密码文件

          ⑤服务账户令牌

          ⑥OpenID连接令牌

          ⑦Webhook令牌

          ⑧认证代理

          ⑨Keystone密码

          ⑩匿名请求

       身份认证后具体的操作请求还需要转交给授权插件进行许可权限检查。API server主要支持使用四类内建的授权插件来定义用户的操作权限:

          ①Node:基于pod资源的目标调度节点来实现对kubelet的访问控制

          ②ABAC(attribute-based access control):基于属性的访问控制

          ③RBAC(role-based access control):基于角色的访问控制

          ④Webhook:基于HTTP回调机制通过外部REST服务检查确认用户授权的访问控制

        准入控制器用于在客户端请求经过身份验证和授权检查之后但在对象持久化存储etcd之前拦截请求,用于实现在资源的创建、更新和删除操作期间强制执行对象的语义验证等功能,API Server内置的常用准入控制器有:

          ①AlwaysAdmit:允许所有的请求

          ②AlwaysDeny:拒绝所有的请求,仅用于测试

          ③AlwaysPullImages:总是下载镜像,常用于多租户环境中

          ④NamespaceLifecycle:拒绝与不存在的名称空间中创建资源

          ⑤LimitRange:可用资源的范围界定

          ⑥ServiceAccount:用于实现Service Account管控机制的自动化

2、服务账号的管理与应用

        服务账户就是用于让Pod对象内的容器进程访问其他服务时提供身份认证信息的账户。一个Service Account资源一般由用户名及相关的Secret对象组成。

(1)Service Account自动化

        Kubernetes系统通过三个独立的组件间的相互协作来实现服务账户的自动化,三个组件分别为Service Account准入控制器、令牌控制器(token controller)和Service Account账户控制器。

          ①Service Account准入控制器是API Service的一部分,负责在创建更新Pod时对其按需进行Service Account对象相关信息的修改。

          ②令牌控制器是controller-manager的子组件,工作与异步模式;主要监控Service Account的创建删除操作、Secret对象的添加删除操作。

(2)创建服务账户

        Service Account是kubernetes API上的一种资源类型,隶属于名称空间,用于让Pod对象内部的应用程序在API Service通信时完成身份认证。每个名称空间都有一个名为default的默认资源对象。

]# kubectl get serviceaccounts --all-namespaces
NAMESPACE       NAME                                 SECRETS   AGE
default         default                              1         112d
ingress-nginx   default                              1         110d
kube-public     default                              1         112d

        每个pod均可附加其所属名称空间中的一个Service Account资源,且只能附加一个,但一个Service Account资源可由其所属的名称空间中的多个pod共享使用,在创建pod时,可通过”spec.serviceAccountName”字段直接指定要是用的Service Account对象。

        Service Account资源的创建可通过yaml配置文件创建,也可通过命令创建。通过命令创建Service Account资源的命令格式如下:

  kubectl create serviceaccount NAME [--dry-run] [options]

       通过资源配置清单定义一个Service Account资源如下:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: sa-demo
  namespace: default

(3)调用imagePullSecret资源对象

        ServiceAccount资源还可以基于spec.imagePullSecret字段附带一个由下载镜像专用的Secret资源组成的列表,用于在容器创建时,从某私有镜像仓库下载镜像之前进行服务认证。

# 创建一个用于在阿里云认证的secrete资源
]# kubectl create secret docker-registry aliyun-registry --docker-username=dayi123 --docker-password=dayi123 --docker-email=dayi123@126.com --docker-server=registry.cn-hangzhou.aliyuncs.com
secret/aliyun-auth created
# 定义serviceaccount资源
]# cat aliyun-sa.yaml 
apiVersion: v1
kind: ServiceAccount
metadata:
  name: sa-demo
  namespace: default
imagePullSecrets:
- name: aliyun-registry
# 创建该secrete
]# kubectl create -f aliyun-sa.yaml 
serviceaccount/sa-demo created
# 定义pod资源,并去阿里云私有仓库中拉取镜像并运行
]# cat pod-sa.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: sa-demo
spec:
  serviceAccountName: sa-demo
  containers:
  - name: aliyun-busybox
    image: registry.cn-hangzhou.aliyuncs.com/dayi123/busybox:v1.1

3、X.509数字证书认证

       Kubernetes支持的各种认证方式中基于TLS/SSL协议的客户端认证以其安全性高且易于实现等特性成为主要使用的认证方式。在服务端与客户端相互认证的场景中,双方各自都需要配备一套证书,并拥有信任的签证机构的列表。

(1)kubernetes中的ssl/tls认证

       处于安全的目的,kubernetes集群中masteer的各组件(API server,controller-manager和scheduler)需要基于SSL/TLS向外提供服务,master的组件与集群中的组件(如节点组件kubelet,kube-proxy)通信时需要双向的身份认证。

         ①etcd集群内各节点的通信以及各节点与客户端之间的通信都应该以加密的方式进行并需要身份验证

         ②API Server与客户端之间采用HTTPS通信可实现通信与认证功能

         ③集群中的应用与客户端的通信经由不可行的网络传输时也需要用到TLS/SSL协议。

(2)客户端配置文件

       1)kubectlconfig

        客户端的配置文件kubeconfig为初始化集群后生成的配置文件,默认路劲为”$HOME/.kube/config”.。kubeconfig配置文件可以为kubectl、kubelet、kube-controller-manager等在内的API Server的各类客户端提供接入多个集群的相关配置信息。使用”kubectl config view”命令能够显示当前正在使用的配置文件。

]# kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://192.168.16.196: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配置文件中的主要配置信息如下:

          ①clusters:集群列表,包含访问API Server的rul和所属集群的名称

          ②users:contexts:用户列表

          ③kubelet的可用上下文列表

          ④current-context:kubelet当前使用的上下文名称

       在使用默认的配置文件时用户也可以按需自定义相关的配置信息于kubeconfig配置文件中,以实现使用不同的用户账号接入集群等功能。Kubectl config命令的常用操作有:

         ①kubectl config view:打印当前正在使用的配置文件

         ②kubectl config set-cluster:设置kubeconfig的clusteer配置段

         ③kubectl config set-credentials:设置kubeconfig 的user配置段

         ④kubectl config set-context:设置kubeconfig的contexts的配置段

         ⑤kubectl config use-context:设置kubeconfig的current-context配置段

       2)创建基于SSL/TLS的认证的自定义用户账号

       使用kubeadm部署的kubernetes集群默认提供了拥有集群管理权限的kubeconfig配置文件/etc/Kubernetes/admin.conf,它可被复制到任何有着kubectl的主机上以用于管理整个集群。管理员可以创建基于SSL/TLS认证的自定义用户账号,以授权非管理员的集群资源使用权限,配置过程如下:

       首先为用户创建私钥及证书文件,保存于/etc/Kubernetes/pki目录中:

#创建私钥文件
]# cd /etc/kubernetes/pki/
]# (umask 077;openssl genrsa -out kube-user01.key 2048)
# 创建证书签署请求
]# openssl req -new -key kube-user01.key -out kube-user01.csr -subj "/CN=kube-user01/O=kubernetes"
# 签署证书
]# openssl x509 -req -in kube-user01.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out kube-user01.crt -days 3650
# 验证证书信息
]# openssl x509 -in kube-user01.crt -text -noout

       证书文件创建完成后需要以默认的管理员kubernetes-admin@kubernetes为新建的kube-user01设定kubeconfig配置文件,默认会保存于当前系统用户的.kube/config文件中,也可以通过kubectl使用—lubeconfig选项指定自定义的专用文件路劲。

# 配置集群信息
]# kubectl config set-cluster kubernetes --embed-certs=true --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.16.196:6443
# 配置客户端证书及秘钥
]# kubectl config set-credentials kube-user01 --embed-certs=true --client-certificate=/etc/kubernetes/pki/kube-user01.crt --client-key=/etc/kubernetes/pki/kube-user01.key
# 配置context,用来组合cluster和credentials
]# kubectl config set-context kube-user01@kubernetes --cluster=kubernetes --user=kube-user01
# 切换到新建的用户
]# kubectl config use-context kube-user01@kubernetes
# 由于没有授权所以不能请求pod
]# kubectl get pods
Error from server (Forbidden): pods is forbidden: User "kube-user01" cannot list resource "pods" in API group "" in the namespace "default"
# 继续切回到admin用户
]# kubectl config use-context kubernetes-admin@kubernetes

(3)TLS boottstrapping机制

       Kubelet TLS Bootstrapping机制是由kubelet自行生成私钥和证书签署请求,然后发送给集群上的证书签署进程(CA),由管理员验证请求后予以签署直接控制进程自动统一部署。

4、基于角色的访问控制

       RBAC是一种新型、灵活且使用广泛的访问控制机制。在RBAC中用于(user)就是一个可以独立访问数据资源的主体(Subject),角色是指一个组织或任务中的工作或者位置,它代表了一种权利、资格和责任。许可(Permission)就是允许对一个或多个客体(Object)执行的操作。RBAC试讲权限授予角色之上。

(1)RBAC授权插件

       RBAC用于界定那些主体(Subject)能够或不能够操作(verb)哪个或哪类对象(Object)。Verb包括create、apply、delete、update、patch、edit和get等。

       RBAC授权插件支持Role和ClusterRole两类角色,Role作用于名称空间级别,用于定义名称空间内的资源权限集合,ClusterRole用于组织集群级别的资源权限集合。而对这两类角色进行授权时需要用到RoleBinding和ClusterRoleBinding两种资源类型。

       RoleBingding用于将Role上的许可权限绑定到一个或一组用户上,它隶属于且仅能作用于一个名称空间;绑定时,可以应用同一名称中的Role,也可以应用集群级别的ClusterRole.

       ClusterRoleBingding则把ClusterRole中定义的许可权限绑定在一个或一组用户之上,仅可以引用集群级别的ClusterRole。

(2)Role和RoleBinding

       1)Role

       Role仅是一组许可(permission)权限的集合,它描述了那些资源可执行何种操作,资源配置清单中使用rules字段嵌套授权规则,role的创建可通过命令创建或资源配置清单创建,创建role的命令如下:

kubectl create role NAME --verb=verb --resource=resource.group/subresource [--resource-name=resourcename] [--dry-run]

       定义一个role的资源配置清单文件如下:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  creationTimestamp: null
  name: pods-reader
rules:
- apiGroups: [""]
  resources: ["pods","pods/log"]
  verbs: ["get","list","watch"]

       在上述的资源配置清单中,rules主要用于定义策略规则,但不包含策略应用的目标,可内嵌的字段如下:

           apiGroups:包含了资源API组的名称,支持列表格式指定的多个组,空串(“”)标识 核心组。

           resourceNames:规则应用的目标资源名称列表,默认为资源类型下的所有资源

           resources:规则应用的目标资源类型组成的列表,ResourceAll标识所有的资源

           verb:可应用至此规则匹配到的所有资源类型的操作列表,可用的选项有:get、list、create、update、patch、watch、proxy、redirect、dekete和deletecollection。

           nonResourceURLs:定义用户应该有权限访问的网址列表,并非名称空间级别的资源。只能永于ClusterRole和ClusterRoleBinding

       2)RoleBinding

       角色本身不能作为动作执行的主体,他们需要绑定到主体(user,group,service account)之上才能发生作用。RoleBinding用于将Role中定义的权限赋予一个或一组用户;同时RoleBinding仅能够引用同一名称空间中的Role对象完成授权。RoleBinding由一组主体以及一个要应用来赋予这组主体的Role或ClusterRole组成。RoleBinding的创建也可通过命令创建或者定义资源清单创建。

       通过命令创建的命令格式如下:

  kubectl create rolebinding NAME --clusterrole=NAME|--role=NAME [--user=username] [--group=groupname]

       定义一个RoleBinding的资源配置清单如下:

]# cat role-pods-reader-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  creationTimestamp: null
  name: admin-services
  namespace: testing
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: pods-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: kube-user01

       如果将该RrolBinding资源应用到集群中,kube-user01用于便有了读取testing名称空间中pod资源的权限。

# 创建该RoleBinding
]# kubectl create -f role-pods-reader
# 切换用户到kube-user01
]# kubectl config use-context kube-user01@kubernetes
# 读取testing名称空间中的pod资源
]# kubectl get pods -n testing
No resources found.

       RoleBinding不能扩名称空间使用,但主体中的用户账号、用户组和服务账号不受名称空间的限制,因此管理员可以为一个主体通过不同的RoleBinding资源绑定多个名称空间中的角色。

       RoleBinding的配置主要包含两个嵌套的字段subjects和roleRef,roleRef的值是单个对象,用于指定要绑定的Role或ClusterRole;subject用于指定要绑定的主体,

subject主要的嵌套字段如下:

           apiGroup:要应用的主体所属的API群组,ServiceAccount类的主体默认值为””,user和group类主体的默认值为”rbac.authorization.k8s.io”

           kind:要引用的资源对象所属的类别,可用值为User、Group、ServiceAccount

           name:引用的主体名称

           namespace:引用主体所属的名称空间

       roleRef的主要嵌套字段如下:

           apiGroup:应用的资源所属的API群组

           kind:引用的资源所属的类别

           name:引用的资源的名称

(3)ClusterRole和ClusterRoleBinding

       ClusteerRole资源除了能够管理与Role资源一样的许可权限之外,还可用于集群级组件的授权,ClusterRole资源的定义方式与Role资源类似。

# 定义一个具有访问集群节点信息的clusterrole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: nodes-reader
rules:
- apiGroups: [""]
  resources: ["nodes"]
  verbs:
  - get
  - watch
  - list

       ClusterRoleBinding是集群级别的资源,它不属于名称空间,所以不需要指定名称空间;RoleBinding也能够将主题绑定至ClusterRole资源之上,但仅能够赋予用户访问RoleBinding资源本身所在的名称空间之内可由ClusterRole赋予的权限。

       集群级别的资源(如nodes、pv)以及非资源型的URL不属于名称空间级别所以无法通过RoleBinding授权,但可通过ClusterRoleBinding授权,但这类资源的读取权限已经由系统默认名称为system:discovery的ClusterRole和ClusterRoleBinding两个资源自动设定。

]# kubectl get clusterrolebinding system:discovery -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
. . . . . .
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:discovery
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:authenticated
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:unauthenticated

       由上面的结果可知,ClusterRoleBinding绑定了system:authenticated和system:unauthencated两个组,这包括了所有的用户账号,因此所有的用户均由权限请求读取这些资源,任何发往API Server的此类端点的请求都会得到响应。

(4)聚合型的ClusterRole

       K8s自1.9版本开始支持ClusterRole在Role字段中嵌套aggregationRule字段来整合其他的Cluster对象的规则,这种类型的ClusterRole的权限受限于控制器,他们由所有被标签选择器匹配到的用于聚合的ClusterRole的授权规则合并生成。聚合型ClusterRole的规则会随着标签选择器的匹配结果动态变化。

(5)面向用户内建的ClusterRolle

       API Server内建了一组默认的ClusterRole和ClusterRoleBinding以预留系统使用,其中大多数以“system:”为前缀。而内建的ClusterRole资源cluster-admin拥有管理集群所有资源的权限,他基于同名的ClusterRoleBinding资源绑定到了”system:master”组上,这以为这所有隶属于此组的用户都将具有集群的超级管理权限。

5、准入控制器

       认证插件和授权插件完成身份认证和权限检查之后,准入控制器将拦截那些创建、更新和删除的相关操作请求以强制实现控制器中实现的功能。

(1)LimitRange资源与准入控制器

       LimitRange资源在每个名称空中为每个容器指定最小及最大的计算资源用量,甚至是设置默认的计算资源需求和计算资源限制。

       LimitRaneg资源支持限制容器、Pod和PersistentVolumeClaim三种资源对象的系统资源用量。定义一个容器cpu资源限制如下:

]# cat limitrange-cpu.yaml 
apiVersion: v1
kind: LimitRange
metadata:
  name: cpu-limit-range
spec:
  limits:
  - default:
      cpu: 1000m
    defaultRequest:
      cpu: 1000m
    min:
      cpu: 500m
    max:
      cpu: 2000m
    maxLimitRequestRatio:
      cpu: 4
    type: Container

(2)ResourceQuota资源与准入控制器

       ResourceQuota资源用于定义名称空间的对象数量或系统资源配额,它支持限制每种资源类型的对象总数以及所有对象所能消耗的计算资源及存储资源总量。

       ResourceQuota对象可限制指定名称空间中非终止状态的所有pod对象的计算资源需求及计算资源的限制总量:

         ①cpu或requests.cpu:cpu资源需求的总量限制

         ②memory或requests.memory:内存资源需求的总量限制

         ③limits.cpu:cpu资源限制的总量限制

         ④limits.memory:内存资源限制的总量限制

ResourceQuota资源还支持限制特定名称空间中可以使用的PVC数量和这些PVC资源的空间总大小,以及特定名称空间中可在指定的StorageClass上使用的PVC数量和这些PVC资源总数:

         ①requests.storage:所有PVC存储需求的总量限制

         ②persistentvolumeclaims:可以创建的pvc总数

         ③<storage-class-name>.storageclass.storage.k8s.io/requests.storage:指定存储类上可使用的所有PVC存储需求的总量限额

        ④<storage-class-name>.storageclass.storage.k8s.io/persistentvolumeclaims:指定存储类上可使用的PVC总数

        ⑤requests.ephemeral-storage:所有pod可用的本地临时存储需求的总量

        ⑥limits.ephemeral-storage:所有pod可用的本地临时存储限制的总量

# 创建一个resourcesquota对象并查看
]# cat resourcequota-test.yaml 
apiVersion: v1
kind: ResourceQuota
metadata:
  name: quota-example
spec:
  hard:
    pods: "5"
    requests.cpu: 5
    requests.memory: 1Gi
    limits.cpu: "2"
    limits.memory: 2Gi
    count/deployments.apps: "1"
    count/deployments.extensions: "1"
    persistentvolumeclaims: "2"
]# kubectl describe resourcequota quota-example
Name:                         quota-example
Namespace:                    default
Resource                      Used  Hard
--------                      ----  ----
count/deployments.apps        0     1
count/deployments.extensions  0     1
limits.cpu                    0     2
limits.memory                 0     2Gi
persistentvolumeclaims        4     2
pods                          4     5
requests.cpu                  0     5
requests.memory               0     1Gi

        在名称空间上启用了CPU和内存等系统资源的配额后,用户创建Pod对象时必须指定资源需求或资源限制,否则会触发ResouceQuota准入控制器拒绝相应的操作。同事资源配额仅对那些在ResourceQuota对象创建之后生成的对象有效,对已经存在的对象不会产生任何的影响。

(3)PodSecurityPolicy

       PSP是集群级别的资源类型,用于控制用户在配置pod资源的期望状态时可以设定的特殊类的权限。但PSP对象定义的策略本身并不会直接发生作用,需要经由PodSecurityPolicy准入控制器检查并强制生效。不过PSP准入控制器默认是处于未启用状态。

       设定重要的Pod安全策略,而后启用PSP准入控制器使其生效的方法

       1)设置特殊及受限的PSP对象

       2)创建ClusterRole并完成账户绑定

       3)启用PSP准入控制器

 

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐