# Kubernetes Permission Controler概览

伴随着Kubernetes的迅猛发展，depolying、scaling和managing containeried applications等概念在开发、运维管理等相关工作人员间广泛流传。无论技术概念多么的新颖，一项工程技术在大规模应用实践生产环境前，首先需要考量安全问题。因此生产环境安全部署的相关问题也是kubernetes最重要的内容之一。Kubernetes对用户和应用请求认证和授权管理的底层逻辑也是相关工作人员最应该掌握的硬核知识。

*这一系列文档都是关于Kubernetes集群内部pods等资源对外部请求的认证与授权的管以及如何使用roles和role binding控制Kubernetes内部资源的访问权限。*

* Kubernetes Permission Controler概览
* Permission Controler-通过Instance理解Kubernetes的Auth
* Permission Controler-通过Instance理解Kubernetes的授权
* Permission Controler-探索Kubernetes的Service Accounts

*下面的示例都是运行在最新版的Kubernetes集群中，当然你也可以使用运行在本地的Minikube作为实验环境*

### API Server - Kubernetes的网关

Kubernetes一切资源(Nodes,Labels,Pods,Deployments,Services,Secrets,Configmaps,Ingress等)都是对象，Kubernetes通过API Service控制着这些资源的访问权限。通过使用暴露给外部用户REST API接口执行对Kubernetes资源的CRUD操作。

API Server是Kubernetes内部的核心模块之一，扮演者集群网关的角色。Kubernetes内部模块(诸如：Kubelet, Scheduler, Controller) 都是通过API Service进行调度和调谐。分布式键值对数据库（etcd）也只能通过API Server访问。

![](/files/-LqzNfxbLfctm3IT7RZm)

Kubectl素有集群管理的瑞士军刀之称，它操作Kubernetes的所有请求最终都会发送到Api Server。其它类似的工具或者模块也是通过API Server操作Kubernetes的资源对象。

在Kubernetes对象被操作前，Kubernetes集群使用API Server验证请求的合法性。发送请求的客户端使用X.509认证对发出的请求进行加密，加密使用X.509认证的CA certificate和client certificate都是Kubectl从本地获取的。

```
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://35.203.146.149:6443
  name: kubernetes-the-hard-way
contexts:
- context:
    cluster: kubernetes-the-hard-way
    user: admin
  name: kubernetes-the-hard-way
current-context: kubernetes-the-hard-way
kind: Config
preferences: {}
users:
- name: admin
  user:
    client-certificate: /Volumes/BOOTCAMP/dev/gcp/gcloud-k8s-config/script/admin.pem
    client-key: /Volumes/BOOTCAMP/dev/gcp/gcloud-k8s-config/script/admin-key.pem

```

ca.pem(介于安全考量，我并未配置在Kubectl Config中)本地认证中心需要一个CA证书。 显而易见，Kubectl正是通过上下文配置中的certificates和keys加密请求。

我们能否通过curl命令向API Server发送请求吗？当然可以了！

除了需要相关的CA加密文件，我们也要将token按照base64编码后嵌入到请求体的header中。

```
kubectl config view -o jsonpath='{"Cluster name\tServer\n"}{range .clusters[*]}{.name}{"\t"}{.cluster.server}{"\n"}{end}'

```

![](/files/-LqzNpuRMW-gVxfddvL6)

```
export CLUSTER_NAME="kubernetes-the-hard-way"

```

```
APISERVER=$(kubectl config view -o jsonpath="{.clusters[?(@.name==\"$CLUSTER_NAME\")].cluster.server}")

```

下面的命令将获取default service account中的token：

```
TOKEN=$(kubectl get secrets -o jsonpath="{.items[?(@.metadata.annotations['kubernetes\.io/service-account\.name']=='default')].data.token}"|base64 -D)

```

现在我们可以使用curl命令请求api server：

```
curl -X GET \
	--cacert /Volumes/BOOTCAMP/dev/gcp/gcloud-k8s-config/script/ca.pem \
	--header "Authorization: Bearer $TOKEN" \
	$APISERVER/version
	
```

![](/files/-LqzNwEqhclLEUlb_Q_J)

### Kubernetes权限控制的三层模型

像上面所说的那样，所有的外部用户或者pods在操作Kubernetes内部对象前都需要对API Server进行认证。

当一个合法的请求到达API Server后，系统将会通过三层认证验证对请求的资源是否有操作权限。

![](/files/-LqzO1qqjWD15QWihODJ)

#### 1. Authentication

在请求被TLS认证后，API Server将使用Kubernetes中已经开启的一个或多个认证模块对它进行相关的认证操作。相关的认证模块在集群创建时就已经指定，多个认证模块会被放在队列中，只有上一个认证模块成功认证后，才会被下一个模块进行认证。

Kubernetes中的认证模块主要有client certificates、password、plain tokens、bootstrap tookens和JWT tokens。Clinet certifiactes是集群中默认也是最常见的认证模块。关于认证模块的更多内容，你可以参照相关[模块文档](https://link.juejin.im?target=https%3A%2F%2Fkubernetes.io%2Fdocs%2Freference%2Faccess-authn-authz%2Fauthentication%2F)。

Kubernetes并未维护专门的用户表或者认证用户的画像，而是通过认证X.509认证文件或者传递给认证模块的token。理解这一点后就可以很容易明白Kubernetes通过将OpenID,Github甚至LDAP协议集成到Kubernetes认证体系的原理。

#### 2.Authorization

一旦API请求被认证后，下一步将会验证请求是否被授权操作Kubernetes内部资源，这一行为发生在请求验证流程中的第二步。

在授权验证时，Kubernetes将主要考查请求的用户名、请求的行为和请求将会影响的对象。用户名是从请求的header中提取的，请求行为是对应CRUD操作中的Http行为（GET，PUT，DELETE等），请求将会影响的对象是Kubernetes内部的Pods，Service等。

Kubernetes对资源对象的授权策略遵循由关到开的哲学，这就意味着如果想要访问资源必须配置相关的授权策略。

像认证一样，授权的行为也可以通过一个或多个授权模块配置权限，诸如ABAC，RBAC和Webhook中。在管理员创建集群时就已经将相应的授权模块集成到Kubernetes API Server中了。如果Kubernetes集群启用了多个授权模块，API Server会逐一使用授权模块对请求进行验证。只有所有的模块验证通过后，请求才能通过授权的验证，否则请求将会被拒绝（Http的status code是403）。关于授权模块的更多内容，你可以参照相关[模块文档](https://link.juejin.im?target=https%3A%2F%2Fkubernetes.io%2Fdocs%2Freference%2Faccess-authn-authz%2Fauthorization%2F%23authorization-modules)。

#### 3.Admission Control

请求通过认证和授权后最后来到准入控制，像认证和授权一样，准入控制器也是插件式模块。

与认证和授权不同的是准入控制可能会修改请求资源对象。除了读取资源对象，准入控制可以对创建、删除、更新和代理资源对象的请求发生了作用。例如准入控制拦截创建存储数据卷（PVC）请求，指定PVC资源的存储类型。还可以在创建Pod时强制重新拉取镜像。关于更多准入控制模块，参照[Kubernetes文档](https://link.juejin.im?target=https%3A%2F%2Fkubernetes.io%2Fdocs%2Freference%2Faccess-authn-authz%2Fadmission-controllers%2F)。

在准入控制器处理的过程中，请求一旦被任何一个控制器拒绝，请求立刻就会被Kubernetes拒绝。只有请求顺利通过所有的准入控制器后，请求才具备操作相应资源对象的权限。

在下一篇文章中，我将会进一步讲解[如何创建用户和认证用户](https://juejin.im/post/5d6a2538e51d4561fa2ec0bb)，加油吧小伙伴！

*文章翻译自*[*A Primer on Kubernetes Access Control*](https://link.juejin.im?target=https%3A%2F%2Fthenewstack.io%2Fa-primer-on-kubernetes-access-control%2F)*，行文时略有删减*\
作者：spursyy\
链接：<https://juejin.im/post/5d60fe39f265da03f564ee68\\>
来源：掘金\
著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.k8stech.net/kubernetes-permission-controler-gai-lan.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
