赞
踩
我们通过 kubectl、或者自己写程序,是可以调用apiserver的api接口的,但是我这里有两个问题:
1)访问apiserver的时候,我们需要做哪些事情?apiserver对访问的用户有没有什么需求?
首先,需要说明的是,在k8s中可以使用两种用户来访问apiserver,分别是普通用户和k8s的service account. 对于普通用户来说,他只是对于外部来说的,并不是k8s的对象,也不会在k8s中部署。而对于普通用户来说,会给这个用户绑定指定证书的权限,之后普通用户既可以访问apiserver的api.
但是对于service account,会通过给这个serviceaccount,绑定指定的权限让他有权限来访问service api. 一般来说,部署在k8的pod会使用service account这种用户来访问apiserver指定的资源。
2)当apiserver收到client的请求时,apiserver自己又做了哪些事情呢?
When a request reaches the API, it goes through several stages, illustrated in the following diagram:
当访问apiserver, apiserver会经过如下几个阶段,也可以看下面这个图。
access kubernetes api step
Human User/kubernetes serviceAccount—–>Transport Security -->Authentication—>Authorization---->Admission Control---->存入存储。
一旦开启了tls,所有的请求都需要先通过认证,可以为apiserver配置很多 Authenticator Modulers,这些模块会被依次执行。只要有一个通过了,就表示认证成功了。之后会进入授权模块
授权和认证相同,在k8中,也有很多种授权方式,例如ABAC模式,RBAC模式和Webhook模式。 管理员创建集群时,他们配置了应该在API服务器中使用的授权模块。 如果配置了多个授权模块,则Kubernetes会检查每个模块,如果有任何模块授权该请求,则该请求可以继续进行。 如果所有模块均拒绝该请求,则该请求将被拒绝(HTTP状态码403)。
目前一般基于RBAC的比较多一点,感兴趣可以看这个https://kubernetes.io/docs/reference/access-authn-authz/authorization
After the request is authenticated as coming from a specific user, the request must be authorized.
将请求验证为来自特定用户后,这个特定用户会有权限。
例如,如果Bob具有以下策略,那么他只能在名称空间projectCaribou中读取pod:
{
"apiVersion": "abac.authorization.kubernetes.io/v1beta1",
"kind": "Policy",
"spec": {
"user": "bob",
"namespace": "projectCaribou",
"resource": "pods",
"readonly": true
}
}
If Bob makes the following request, the request is authorized because he is allowed to read objects in the projectCaribou namespace:
如果Bob发出如下的请求,则该请求将会被授权,因为它允许在projectCaribou ns中读取对象。但是如果Bob想发生写的请求,则将会被拒绝。
{
"apiVersion": "authorization.k8s.io/v1beta1",
"kind": "SubjectAccessReview",
"spec": {
"resourceAttributes": {
"namespace": "projectCaribou",
"verb": "get",
"group": "unicorn.example.org",
"resource": "pods"
}
}
}
Admission Control Modules are software modules that can modify or reject requests.
In addition to the attributes available to Authorization Modules, Admission Control Modules can access the contents of the object that is being created or updated. They act on objects being created, deleted, updated or connected (proxy), but not reads.
准入控制模块是可以修改或拒绝请求的软件模块。 除授权模块可用的属性外,准入控制模块还可以访问正在创建或更新的对象的内容。 它们作用于正在创建,删除,更新的对象,但不读取。
控制器遵循如下几个原则:
准入控制器是一段代码,用于在对象持久化之前但在请求得到验证和授权之后,截取对Kubernetes API服务器的请求。
controllers 有很多controller组成,且都内置于 kube-apiserver的 binary,且只能由集群管理员配置。
在这些控制器中,有两个特殊的控制器:MutatingAdmissionWebhook和ValidatingAdmissionWebhook。 它们分别执行在API中配置的Mutating(变异)和验证准入控制Webhook。
准入控制过程分为两个阶段。 在第一阶段,运行变异许可控制器。 在第二阶段,运行验证准入控制器。
Kubernetes中的许多高级功能都需要启用接纳控制器才能正确支持该功能。 因此,未正确配置正确的访问控制器集的Kubernetes API服务器是不完整的服务器,将不支持您期望的所有功能。
可以通过命令行的方式让apiserver启动admission controller,默认会启动如下的几个:
kube-apiserver --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota
禁用admission controller
kube-apiserver --disable-admission-plugins=PodNodeSelector,
What does each admission controller do? 我们可以看其中的一个例子
1)AlwaysPullImages
This admission controller modifies every new Pod to force the image pull policy to Always. 这个功能很有用,比如对于多租户的场景,可以确保用户拥有权限之后才能拉取镜像,而且每次都是从新拉,但是如果没有这个控制器,那么一旦镜像到了这个节点,就可以跑起来了,安全性就会做的很差。
其他详细的controller可以看这个地址 https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/
我们来看官网对于Dynamic Admission Control的描述:
In addition to compiled-in admission plugins, admission plugins can be developed as extensions and run as webhooks configured at runtime.
通俗地讲:即是,除了K8s内置的Admission plugin, 我们也可以自定义Admission plugin 作为扩展,自定义的Admission plugin可以配置给k8s集群,之后自定义插件可以作为 admission webhook来执行。
1) 我们来思考一个如下的场景,在就绪的kubernetes集群上,我们有如下需求,我们需要在创建pod前,给pod打上一些label或执行一些操作,那么我们需要修改apiserver代码,之后,重新编译,部署新的apiserver二进制,这样,线上的apiserver的服务,需要重启,显然是不合适的,所以k8s的apiserver提供了热插拔的机制,即是dynamic admission control。
2) webhook 可动态扩展 Admission 能力,满足自定义客户的需求
成功使用此功能的开源项目:
比如:istio的 sidecar 注入 就使用了apiserver的 Dynamic Admission Control,也叫Initializer. 会在pod创建前,给pod的spec中填充sidecar容器的相关属性。
在说如何使用之前,我们先了解一下admission webhook.且k8s集群必须满足如下条件:
一般情况下会启动如下几个controler:可以看到这两个controller是在里面启动的。
--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota
其实他就是一个http的callback,当收到admission request时,会执行一些操作。
k8s有两种类型的admission webhook,validate和mutating两种, mutating会优先执行,这种webhook会修改k8s的资源对象,之后可以通过validate来对修改后的对象进行校验。
k8s 会创建AdmissionReview 对象发送给webhook server,webhook server处理之后会返回AdmissionReview对象。
准入webhook示例服务器将ClientAuth字段保留为空,默认为NoClientCert。 这意味着webhook服务器不会对客户端(假定为apiserver)的身份进行身份验证。 如果您需要双向TLS或其他方式来认证客户端,下面有认证方式。
可以参考官网 https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#authenticate-apiservers
可以将这个webhook service 部署在k8s集群内或k8s集群外.但是这个服务地址需要在admission controller的配置文件中配置。
You can dynamically configure what resources are subject to what admission webhooks via ValidatingWebhookConfiguration or MutatingWebhookConfiguration.
你可以动态的配置什么样的资源从属于,受什么样的adminssion webhooks 所管理。
注册此admission webhook, 告诉apiserver应该使用自己。方式是通过创建MutatingWebhookConfiguration 或 ValidatingWebhookConfiguration API 对象。
下面是一个ValidatingWebhookConfiguration的配置,具体详细的配置使用参照k8s官方API
# Deprecated in v1.16 in favor of admissionregistration.k8s.io/v1 apiVersion: admissionregistration.k8s.io/v1beta1 kind: ValidatingWebhookConfiguration metadata: name: "pod-policy.example.com" webhooks: - name: "pod-policy.example.com" rules: - apiGroups: [""] apiVersions: ["v1"] operations: ["CREATE"] resources: ["pods"] scope: "Namespaced" clientConfig: service: namespace: "example-namespace" name: "example-service" caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle containing the CA that signed the webhook's serving certificate>...tLS0K" admissionReviewVersions: ["v1beta1"] timeoutSeconds: 5
注意下面的问题:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。