目录
1.安全机制说明
Kubernetes作为一个分布式集群的管理工具,保证集群的安全性是其一个重要的任务。API Server是集群内部各个组件通信的中介,也是外部控制的入口。所以Kubernetes的安全机制基本就是围绕保护API Server来设计的。
比如kubectl如果想向API Server请求资源,需要过三关,第一关是认证(Authentication),第二关是鉴权(Authorization),第三关是准入控制(Admission Control),只有通过这三关才可能会被K8S创建资源。
2.认证——Authentication
2.1认证的方式
-
HTTP Token认证
通过一个Token来识别合法用户
HTTP Token的认证是用一个很长的特殊编码方式的并且难以被模仿的Token字符串来表达客户的一种方式。Token是一个很长的很复杂的字符串,每一个Token对应一个用户名存储在API Server能访问的文件中。当客户端发起API调用请求时,需要在HTTP Header里放入Token。 -
HTTP Base认证
通过用户名+密码的方式认证
用户名+密码用BASE64算法进行编码后的字符串放在HTTP Request中的HeatherAuthorization域里发送给服务端,服务端收到后进行解码,获取用户名及密码。 -
HTTPS证书认证
最严格,基于CA根证书签名的客户端身份认证方式
注:Token认证和Base认证方式只能进行服务端对客户端的单向认证,而客户端不知道服务端是否合法;而HTTPS证书认证方式则可以实现双向认证。
2.2认证组件
2.2.1需要被认证的访问类型
Kubernetes组件对API Server的访问:kubectl、kubelet、kube-proxy
Kubernetes管理的Pod对API Server的访问:Pod(coredns,dashborad 也是以Pod形式运行)
2.2.2安全性说明
Controller Manager、Scheduler与API Server在同一台机器,所以直接使用API Server的非安全端口访问,--insecure-bind-address=127.0.0.1
kubectl、kubelet、kube-proxy访问API Server就都需要证书进行HTTPS双向认证
2.2.3证书颁发
手动签发:使用二进制部署时,需要先手动跟CA进行签发HTTPS证书
自动签发:kubelet首次访问API Server时,使用token做认证,通过后,Controller Manager会为kubelet生成一个证书,以后的访问都是用证书做认证了。
2.3kubeconfig
kubeconfig文件包含集群参数(CA证书、API Server地址),客户端参数(上面生成的证书和私钥),集群context上下文参数(集群名称、用户名)。Kubernetes组件(如 kubelet、kube-proxy)通过启动时指定不同的kubeconfig文件可以切换到不同的集群,连接到apiserver。
也就是说kubeconfig文件既是一个集群的描述,也是集群认证信息的填充。包含了集群的访问方式和认证信息。kubectl文件默认位于~/.kube/config
2.4ServiceAccount
ServiceAccount是为了方便Pod中的容器访问API Server。因为Pod的创建、销毁是动态的,所以要为每一个Pod手动生成证书就不可行了。Kubernetes使用了ServiceAccount来循环认证,从而解决了Pod访问API Server的认证问题。
2.5Secret与SA的关系
Kubernetes设计了一种资源对象叫做Secret,分为两类:
- 1.用于保存ServiceAccount的service-account-token
- 2.用于保存用户自定义保密信息的Opaque
ServiceAccount中包含三个部分:
- Token:是使用API Server私钥签名的Token字符串序列号,用于访问API Server时,Server端认证
- ca.crt:ca根证书,用于Client端验证API Server发送来的证书
- namespace:标识这个service-account-token的作用域名空间
[root@k8s-master01 ~]# kubectl get secret --all-namespaces
[root@k8s-master01 ~]# kubectl describe secret default-token-5gm9r --namespace=kube-system
默认情况下,每个namespace都会有一个ServiceAccount,如果Pod在创建时没有指定ServiceAccount,就会使用Pod所属的namespace的ServiceAccount。每个Pod在创建后都会自动设置spec.serviceAccount为default(除非指定了其他ServiceAccout)。
2.6总结
3.鉴权——Authorization
之前的认证过程,只是确定通信的双方都确认了对方是可信的,可以相互通信。而鉴权是确定请求方有哪些资源的权限。API Server目前支持以下几种授权策略:(通过API Server的启动参数"--authorization-mode"设置)
- AlwaysDeny:表示拒绝所有的请求,一般用于测试。
- AlwaysAllow:允许接收所有请求,如果集群不需要授权流程,则可以采用该策略,一般用于测试。
- ABAC(Attribute-Based Access Control):基于属性的访问控制,表示使用用户配置的授权规则对用户请求进行匹配和控制。也就是说定义一个访问类型的属性,用户可以使用这个属性访问对应的资源。此方式设置较为繁琐,每次设置需要定义一长串的属性才可以。
- Webhook:通过调用外部REST服务对用户进行授权,即可在集群外部对K8S进行鉴权。
- RBAC(Role-Based Access Control):基于角色的访问控制,K8S自1.6版本起默认使用规则。
详细可参考:https://www.cnblogs.com/even160941/p/15504722.html
4.准入控制——Admission Control
准入控制是API Server的一个准入控制器插件列表,通过添加不同的插件,实现额外的准入控制规则。发送到API Server的请求都需要经过这个列表中的每个准入控制器插件的检查,检查不通过,则拒绝请求。
一般建议直接采用官方默认的准入控制器。
官方准入控制器推荐列表(不同版本各有不同):
NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,NodeRestriction
列举几个插件的功能:
- NamespaceLifecycle:用于命名空间回收,防止在不存在的namespace上创建对象,防止删除系统预置namespace,删除namespace时,连带删除它的所有资源对象。
- LimitRanger:用于配额管理,确保请求的资源量不会超过资源所在Namespace的LimitRange的限制。
- ServiceAccount:用于在每个Pod中自动化添加ServiceAccount,方便访问API Server。
- ResourceQuota:基于命名空间的高级配额管理,确保请求的资源数量不会超过资源的ResourceQuota限制。
- NodeRestriction:用于Node加入到K8S集群中以最小权限运行。
官方文档参考:https://kubernetes.io/zh/docs/reference/access-authn-authz/admission-controllers/
资源限制——Pod
Kubernetes对资源的限制实际上是通过cgroup来控制的,cgroup是容器的一组用来控制内核如何运行进程的相关属性集合。针对内存、CPU和各种设备都有对应的cgroup。
默认情况下,Pod运行没有CPU和内存的限额。这意味着系统中的任何Pod将能够像执行该Pod所在的节点一样,消耗足够多的CPU和内存。一般会针对某些应用的pod资源进行资源限制,这个资源限制是通过resources的requests和limits来实现。requests为创建Pod时初始要分配的资源,limits为Pod最高请求的资源值。
5.总结
客户端若想要发送请求给apiserver操作管理K8S资源对象,需要先通过三关安全验证:认证(Authentication)、鉴权(Authorization)、准入控制(Admission Control)
5.1认证(Authentication):确认请求方是否有连接apiserver的权限
K8S支持的认证方式:
- token认证(通过token令牌字符串来认证)
- base认证(根据账户:密码的方式认证)
- https认证(使用证书认证,支持双向认证)
认证过程:
K8S集群中以守护进程运行的组件(kubectl、kubelet、kube-proxy、controller-manager、scheduler)可使用cfssl工具手动签发证书或tls bootstrap机制自动签发客户端证书,再基于证书生成kubeconfig集群引导配置文件,这些组件可根据kubeconfig配置中的集群参数(ca证书、apiserver地址)和客户端参数(客户端证书和私钥信息)连接指定的K8S集群的apiserver并做双向认证。
K8S集群中以Pod形式运行的组件(dashboard、coreDNS、ingress控制器、外置存储卷插件等)使用serviceaccount账户作为Pod的服务账户(如有没有指定默认使用当前命名空间的default),K8S会自动创建相关的service-account-token类型的secret资源,创建Pod时会自动挂载这个secret卷到Pod容器的/var/run/secrets/kubernetes.io/serviceaccount
目录中,Pod与apiserver通信时会使用其中的ca证书和token与apiserver做认证。
5.2鉴权(Authorization):确认请求方具有对哪些资源对象的操作权限
推荐使用RBAC(基于角色的访问控制)kube-apiserver --authorization-mode=Node,RBAC
RBAC有关的4个资源对象:
- Role
- ClusterRole
- RoleBinding
- ClusterRoleBinding
角色(Role、ClusterRole)定义角色能够对哪些资源对象拥有哪些操作权限
- Role:受命名空间的影响,只能在指定的命名空间中操作资源
- ClusterRole:默认可在K8S集群中所有的命名空间中操作资源,不需要配置namespace
角色绑定(RoleBinding、ClusterRoleBinding)将主体账户(User、Group、ServiceAccount)与角色进行绑定,使得主体账户具有角色相关的资源操作权限
- ClusterRoleBinding:只能与ClusterRole绑定,使主体账户在所有的命名空间中具有ClusterRole相关的资源操作权限
- RoleBinding:可以与相同命名空间下的Role绑定,使主体账户在指定的命名空间中具有Role相关的资源操作权限;也可以与ClusterRole绑定,使主体账户只能在RoleBinding指定的命名空间中具有ClusterRole相关的资源操作权限
5.3准入控制(Admission Control):使用准入控制插件对资源请求做进一步的规范检查,如果检查不通过则会拒绝请求
K8S在初始化时会默认启动官方推荐的准入控制插件,一般不做修改,但也可以通过修改apiserver的启动参数来设置:
kube-apiserver --enable-admission-plugins=NamespaceLifecycle,LimitRanger ... #添加指定的准入控制插件
kube-apiserver --disable-admission-plugins=PodNodeSelector,AlwaysDeny ... #禁用指定的准入控制插件
LimitRanger:用来给在指定的命名空间中创建的Pod或容器设置默认的requests和limits资源量限制
ResourceQuota:用来在指定的命名空间中进行资源配额,即设置在指定的命名空间中能够创建的资源对象的数量总额或Pod容器能够使用的requests、limits资源量限制的总额。
如何授权一个普通用户使用kubectl连接K8S操作管理资源?
详细过程可参考:https://www.cnblogs.com/even160941/p/17728030.html
先做认证授权
- 1.签发kubectl使用的客户端证书和私钥文件
- 2.基于客户端证书和私钥文件创建kubectl使用的kubeconfig集群引导配置文件,并放置在用户家目录中
~/.kube/config
再做鉴权授权 - 3.创建角色Role|ClusterRole
rules:
- apiGroups: #指定资源对象的api组,可参考kubectl api-resources的APIVERSION字段
- "" #例如,v1则设为"",apps/v1则设为"apps",networking.k8s.io/v1则设为"networking.k8s.io"
resources: #指定授权的资源名,可参考kubectl api-resources的NAME字段
- pods #资源名
- pods/log #子资源名
verbs: #指定对资源对象的操作权限
- get
- list
- watch
- 4.给主体账户绑定角色
kubectl create clusterrolebinding <资源名称> --clusterrole=<ClusterRole资源名称> --user=<用户名> [--group=<组名>] [--serviceaccount=<命名空间>:<sa账户名称>]
kubectl create rolebinding <资源名称> -n <命名空间> --clusterrole=<ClusterRole资源名称>|--role=<Role资源名称> --user=<用户名> [--group=<组名>] [--serviceaccount=<命名空间>:<sa账户名称>]
标签:kubernetes,证书,认证,安全,API,机制,Server,Pod,资源
From: https://www.cnblogs.com/even160941/p/18423268