极客油画

Secret和ConfigMap是apiserver的核心概念

Projected Volume(投射数据卷) 和 RBAC

  • Secret;
  • ConfigMap;
  • Downward API: 让Pod里的容器能够直接获取到这个Pod API对象本身的信息。
  • ServiceAccountToken

我现在有了一个Pod,我能不能在这个Pod里安装一个Kubernetes的Client,这样就可以从容器里直接访问并且操作这个Kubernetes的API了呢?

Service Account对象的作用,就是Kubernetes系统内置的一种"服务账号",它是Kubernetes进行权限分配的对象。比如,Service Account A,可以只被允许对Kubernetes API进行GET操作,而Service Account B,则可以有Kubernetes API的所有操作权限。

像这样的Service Account的授权信息和文件,实际上保存在它所绑定的一个特殊的Secret对象里的。这个特殊的Secret对象,就叫作ServiceAccountToken。任何运行在Kubernetes集群上的应用,都必须使用这个ServiceAccountToken里保存的授权信息,也就是Token,才可以合法地访问API Server。

所以说,Kubernetes项目的Projected Volume其实只有三种,因为第四种ServiceAccountToken,只是一种特殊的Secret而已。

另外,为了方便使用,Kubernetes已经为你提供了一个默认"服务账户"(default Service Account)。并且,任何一个运行在Kubernetes里的Pod,都可以直接使用这个默认的Service Account,而无需显示地声明挂载它。

这是如何做到的呢?

当然还是靠Projected Volume机制。

如果你查看一下任意一个运行在Kubernetes集群里的Pod,就会发现,每一个Pod,都已经自动声明一个类型是Secret、名为default-token-xxxx的Volume,然后自动挂载在每个容器的一个固定目录上。比如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ kubectl describe pod nginx-deployment-5c678cfb6d-lg9lw
Containers:
...
  Mounts:
    /var/run/secrets/kubernetes.io/serviceaccount from default-token-s8rbq (ro)
Volumes:
  default-token-s8rbq:
  Type:    Secret (a volume populated by a Secret)
  SecretName: default-token-s8rbq
  Optional:   false

这样,一旦Pod创建完成,容器里的应用就可以直接从这个默认ServiceAccountToken的挂载目录(/var/run/secrets/kubernetes.io/serviceaccount)里访问到授权信息和文件。而这个Secret类型的Volume里面的内容如下所示:

1
2
$ ls /var/run/secrets/kubernetes.io/serviceaccount
ca.crt namespace token

所以,你的应用程序只要直接加载这些授权文件,就可以访问并操作Kubernetes API了。而且,如果你使用的是Kubernetes官方的Client包(k8s.io/client-go)的话,它还可以自动挂载这个目录下的文件,你不需要做任何配置或者编码操作。

这种把Kubernetes客户端以容器的方式运行在集群里,然后使用default Service Account自动授权的方式,被称为"InClusterConfig",也是我最推荐的进行Kubernetes API编程的授权方式。

RBAC(Role-Based Access Control)

  • Role(权限组):角色,它其实是一组规则,定义了一组对 Kubernetes API 对象的操作权限。
1
2
3
4
5
6
7
8
9
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: mynamespace
  name: example-role
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]
  • RoleBinding:定义了“被作用者”和“角色”的绑定关系。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: example-rolebinding
  namespace: mynamespace
subjects:
- kind: ServiceAccount
  name: example-user
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: example-role
  apiGroup: rbac.authorization.k8s.io

需要再次提醒的是,Role 和 RoleBinding 对象都是 Namespaced 对象(Namespaced Object),它们对权限的限制规则仅在它们自己的 Namespace 内有效,roleRef 也只能引用当前 Namespace 里的 Role 对象。

那么,对于非 Namespaced(Non-namespaced)对象(比如:Node),或者,某一个 Role 想要作用于所有的 Namespace 的时候,我们又该如何去做授权呢?

  • ClusterRole
1
2
3
4
5
6
7
8
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: example-clusterrole
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]
  • ClusterRoleBinding
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: example-clusterrolebinding
subjects:
- kind: ServiceAccount
  name: example-user
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: example-clusterrole
  apiGroup: rbac.authorization.k8s.io
  • Subject:被作用者,既可以是“人”,也可以是“机器”,也可以是你在 Kubernetes 里定义的“用户”。
1
2
3
4
5
apiVersion: v1
kind: ServiceAccount
metadata:
  namespace: mynamespace
  name: example-sa

部署完ServiceAccount后,再来查看下它的yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$ kubectl get sa -n mynamespace -o yaml
- apiVersion: v1
  kind: ServiceAccount
  metadata:
    creationTimestamp: 2018-09-08T12:59:17Z
    name: example-sa
    namespace: mynamespace
    resourceVersion: "409327"
    ...
  secrets:
  - name: example-sa-token-vmfg6

可以发现,Kubernetes 会为一个 ServiceAccount 自动创建并分配一个 Secret 对象,即:上述 ServiceAcount 定义里最下面的 secrets 字段。

这个 Secret,就是这个 ServiceAccount 对应的、用来跟 APIServer 进行交互的授权文件,我们一般称它为:Token。Token 文件的内容一般是证书或者密码,它以一个 Secret 对象的方式保存在 Etcd 当中。

  • 使用ServiceAccount 在pod的yaml中添加serviceAccountName字段。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
apiVersion: v1
kind: Pod
metadata:
  namespace: mynamespace
  name: sa-token-test
spec:
  containers:
  - name: nginx
    image: nginx:1.7.9
  serviceAccountName: example-sa

默认会挂载到/var/run/secrets/kubernetes.io/serviceaccount 目录下。

  • 用户组

实际上,一个 ServiceAccount,在 Kubernetes 里对应的“用户”的名字是system:serviceaccount:<Namespace名字>:<ServiceAccount名字>

而它对应的内置“用户组”的名字,就是:system:serviceaccounts:<Namespace名字>

比如,现在我们可以在 RoleBinding 里定义如下的 subjects:

1
2
3
4
5
...
subjects:
- kind: Group
  name: system:serviceaccounts:mynamespace
  apiGroup: rbac.authorization.k8s.io

这就意味着这个 Role 的权限规则,作用于 mynamespace 里的所有 ServiceAccount。这就用到了“用户组”的概念。

1
2
3
4
5
...
subjects:
- kind: Group
  name: system:serviceaccounts
  apiGroup: rbac.authorization.k8s.io

就意味着这个 Role 的权限规则,作用于整个系统里的所有 ServiceAccount。

最后,值得一提的是,在 Kubernetes 中已经内置了很多个为系统保留的 ClusterRole,它们的名字都以 system: 开头。你可以通过 kubectl get clusterroles 查看到它们。


本文发表于 0001-01-01,最后修改于 0001-01-01。

本站永久域名「 jiavvc.top 」,也可搜索「 极客油画 」找到我。


上一篇 « 下一篇 »

赞赏支持

请我吃鸡腿 =^_^=

i ysf

云闪付

i wechat

微信

推荐阅读

Big Image