编排
声明式 API
比如:控制器中的 Deployment,服务中的 NodePort,等等,都是 Kubernetes 提供的 API 对象,我们常用的使用方式就是通过 YAML 文件来声明要使用的这些 API 对象。
基于YAML文件的操作方式,就是“声明式 API”吗?
不是。
比如:在本地编写一个 Deployment 的 YAML 文件:
然后,使用 kubectl create 命令在 Kubernetes 里创建 nginx 这个 Deployment 对象:
这样,两个 Nginx 的 Pod 就会运行起来了。
接下来修改这个 YAML 文件里的 Pod 模板部分,把 Nginx 容器的镜像改成 1.7.9,如下所示:
再接下来,就可以执行一句 kubectl replace 操作,来完成这个 Deployment 的更新:
但是,对于上面这种先 kubectl create,再 replace 的操作,我们称为命令式配置文件操作。
什么才是“声明式 API”呢?
使用 kubectl apply 命令来创建这个 Deployment:
这样,Nginx 的 Deployment 就被创建了出来,这看起来跟 kubectl create 的效果一样。
然后,我再修改一下 nginx.yaml 里定义的镜像:
这时候,关键来了。
在修改完这个 YAML 文件之后,我不再使用 kubectl replace 命令进行更新,而是继续执行一条 kubectl apply 命令,即:
这时,Kubernetes 就会立即触发这个 Deployment 的“滚动更新”。
Q:它跟 kubectl replace 命令有什么本质区别吗?
A:kubectl replace 的执行过程,是使用新的 YAML 文件中的 API 对象,替换原有的 API 对象;而 kubectl apply,则是执行了一个对原有 API 对象做局部更新的 PATCH 操作。 类似地,kubectl set image 和 kubectl edit 也是对已有 API 对象的修改。对于声明式请求(比如,kubectl apply),一次能处理多个写操作,并且具备 Merge 能力。
总结
首先,所谓“声明式”,指的就是我只需要提交一个定义好的 API 对象来“声明”,我所期望的状态是什么样子。
其次,“声明式 API”允许有多个 API 写端,以 PATCH 的方式对 API 对象进行修改,而无需关心本地原始 YAML 文件的内容。
最后,也是最重要的,有了上述两个能力,Kubernetes 项目才可以基于对 API 对象的增、删、改、查,在完全无需外界干预的情况下,完成对“实际状态”和“期望状态”的调谐(Reconcile)过程。
Reconcile:Kubernetes 的控制器,实际上就是一个“死循环”,它不断地获取“实际状态”,然后与“期望状态”作对比,并以此为依据决定下一步的操作。
** 声明式 API,是 Kubernetes 项目编排能力“赖以生存”的核心所在。**
权限控制之RBAC
Kubernetes 中所有的 API 对象,都保存在 Etcd 里。而对这些 API 对象的操作,都是通过访问 kube-apiserver 实现的。其中一个非常重要的原因,就是需要 APIServer 来做授权工作。而在 Kubernetes 项目中,负责完成授权(Authorization)工作的机制,就是 RBAC:基于角色的访问控制(Role-Based Access Control)。Kubernetes 的 RBAC 与基于数据库来实现 RBAC 的方式不同,但核心思想是相同的。
Role:角色,它其实是一组规则,定义了一组对 Kubernetes API 对象的操作权限。
Subject:被作用者,既可以是“人”,也可以是“机器”,也可以是你在 Kubernetes 里定义的“用户”。
RoleBinding:定义了“被作用者”和“角色”的绑定关系。
Role
以上的含义是:允许“被作用者”,对 mynamespace 下面的 Pod 对象,进行 GET、WATCH 和 LIST 操作。
RoleBinding
以上的 Role 还没有指定"被作用者",需要通过 RoleBinding 来指定,它的作用相当于通过数据库来实现 RBAC 方式中的关联表。
还缺一个 ServiceAccount 的定义:
Subject
操作验证
创建如上3个对象:
可以看到,Kubernetes 会为一个 ServiceAccount 自动创建并分配一个 Secret 对象,即:上述 ServiceAcount 定义里最下面的 secrets 字段。
这个 Secret,就是这个 ServiceAccount 对应的、用来跟 APIServer 进行交互的授权文件,一般称它为:Token。Token 文件的内容一般是证书或者密码,它以一个 Secret 对象的方式保存在 Etcd 当中。
等这个 Pod 运行起来之后,我们就可以看到,该 ServiceAccount 的 token,也就是一个 Secret 对象,被 Kubernetes 自动挂载到了容器的 /var/run/secrets/kubernetes.io/serviceaccount 目录下,如下所示:
这样,容器里的应用,就可以使用这个 ca.crt 来访问 APIServer 了。更重要的是,此时它只能够做 GET、WATCH 和 LIST 操作。因为 example-sa 这个 ServiceAccount 的权限,已经被绑定了 Role 做了权限限制。
用户组
一个 ServiceAccount,在 Kubernetes 里对应的“用户”的名字是:
而它对应的内置“用户组”的名字,就是:
比如,可以在 RoleBinding 里定义如下的 subjects:
这就意味着这个 Role 的权限规则,作用于 mynamespace 里的所有 ServiceAccount。这就用到了“用户组”的概念。也就相当于指定 Role 与指定的 mynamespace 下所有的 ServiceAccount 都在关联表中建立了关联记录。
而下面这个例子:
就意味着这个 Role 的权限规则,作用于整个系统里的所有 ServiceAccount。
ClusterRole 与 ClusterRoleBinding
Role 和 RoleBinding 对象都是 Namespaced 对象(Namespaced Object),它们对权限的限制规则仅在它们自己的 Namespace 内有效,roleRef 也只能引用当前 Namespace 里的 Role 对象。那么,对于非 Namespaced(Non-namespaced)对象(比如:Node),或者,某一个 Role 想要作用于所有的 Namespace 的时候,该如何去做授权呢?
这时候,就必须要使用 ClusterRole 和 ClusterRoleBinding 这两个组合了。这两个 API 对象的用法跟 Role 和 RoleBinding 完全一样。只不过,它们的定义里,没有了 Namespace 字段:
上面的例子里的 ClusterRole 和 ClusterRoleBinding 的组合,意味着名叫 example-user 的用户,拥有对所有 Namespace 里的 Pod 进行所有操作的权限。
Kubernetes 提供了四个预先定义好的 ClusterRole 来供用户直接使用:
cluster-admin:最高权限
admin:
edit:
view:规定了被作用者只有 Kubernetes API 的只读权限。
Last updated
Was this helpful?