kubernetes api自定义服务帐户如何工作

In my last article, I showed how to develop the KubeLogExporter, a tool that collects log data from a set of pods. So far the exporter relies on full access to the Cluster by using the local .kubeconfig file. If we want the exporter to run as a cron job inside the cluster, it needs to have suitable access rights. Originally I wanted to just write about the cron job implementation, but found that investigating how Kubernetes access rights work to be very educational. That’s why it became the article that you are reading now.

在上一篇文章中,我展示了如何开发KubeLogExporter,该工具可以从一组容器中收集日志数据。 到目前为止,导出器依赖于使用本地.kubeconfig文件对群集的完全访问权限。 如果我们希望导出器在集群中作为cron作业运行,则它需要具有适当的访问权限。 最初,我只想写有关cron作业的实现,但是发现调查Kubernetes访问权限的工作方式非常有教育意义。 这就是为什么它成为您现在正在阅读的文章。

This article originally appeared at my blog.

本文最初出现在 我的博客中

Kubernetes基本概念 (Essential Kubernetes Concepts)

When you run a Pod inside a Kubernetes cluster, several default configurations and security aspects are already made by default. To determine the access right to the rich Kubernetes API, the essential resources are ServiceAccount, Role and RoleBindings.

在Kubernetes集群中运行Pod时,默认情况下已经进行了一些默认配置和安全方面的操作。 为了确定对丰富Kubernetes API的访问权,必不可少的资源是ServiceAccountRoleRoleBindings

Let’s understand these concepts by considering how the cron job to read pod logs works. When the job runs, it needs read access to namespaces and pods. This access is defined in a Role or ClusterRole. The Role is limited to one namespace only, so we will use the ClusterRole. When a pod is created, it is given the default system account and the default system account token to access the K8S API. However, this account does not have the required access rights, so we need to define a custom ServiceAccount. The final piece is the RoleBinding or ClusterRoleBinding: It connects the ClusterRole with the ServiceAccount.

让我们通过考虑cron作业读取pod日志的方式来理解这些概念。 作业运行时,它需要对名称空间和Pod的读取权限。 此访问权限在RoleClusterRole定义。 该Role仅限于一个名称空间,因此我们将使用ClusterRole 。 创建Pod时,会为它提供默认的系统帐户和默认的系统帐户令牌,以访问K8S API。 但是,此帐户没有必需的访问权限,因此我们需要定义一个自定义ServiceAccount 。 最后一块是RoleBindingClusterRoleBinding :它将ClusterRoleServiceAccount连接起来。

K8S API:直接访问 (K8S API: Direct Access)

To see how those concepts are applied when working with Kubernetes, I followed this excellent article in which the API is accessed directly with curl.

为了了解在使用Kubernetes时如何应用这些概念,我关注了这篇出色的文章 ,其中使用curl直接访问API。

Let’s start simple by creating the api-explorer pod that by writing the api-explorer-pod.yaml file with the following content.

让我们从创建api-explorer容器开始,从创建具有以下内容的api-explorer-pod.yaml文件开始。

apiVersion: v1
kind: Pod
metadata:
name: api-explorer
spec:
containers:
- name: alpine
image: alpine
args: ['sleep', '3600']

Then we create the container and wait until it is started.

然后,我们创建容器并等待其启动。

> kubectl create -f api-explorer-pod.yamlpod/api-explorer created

Then we jump into the container, and install the curl package.

然后,我们跳入容器,并安装curl包装。

> kubectl api-explorer -it sh
> apk add curl

To access the Kubernetes API, we always need to send a valid security token. This token is stored inside the pod at the location /run/secrets/kubernetes.io/serviceaccount/token. With this token, we can make the API request.

要访问Kubernetes API,我们始终需要发送一个有效的安全令牌。 该令牌存储在pod内部的/run/secrets/kubernetes.io/serviceaccount/token位置。 使用此令牌,我们可以发出API请求。

> TOKEN=$(cat /run/secrets/kubernetes.io/serviceaccount/token)
> curl -H "Authorization: Bearer $TOKEN" https://kubernetes/api/v1/namespaces/default/pods/ --insecure
{
"kind": "Status",
"apiVersion": "v1",
"metadata": { },
"status": "Failure",
"message": "pods is forbidden: User \"system:serviceaccount:default:default\" cannot list resource \"pods\" in API group \"\" in the namespace \"default\"",
"reason": "Forbidden",
"details": {
"kind": "pods"
},
"code": 403
}

But as we see, we cannot access the pod at all because the default service account does not have the correct access rights.

但是,正如我们看到的那样,因为默认服务帐户没有正确的访问权限,所以我们根本无法访问Pod。

定义自定义服务帐户 (Defining a Custom Service Account)

So we need to have a properly configured ServiceAccount that grants us a token with which the Kubernetes API can be accessed.

因此,我们需要具有正确配置的ServiceAccount ,该ServiceAccount会授予我们可以访问Kubernetes API的令牌。

Create the file pod-read-access-service-account.yaml and put the ServiceAccount definition on top. This resource is basically only metadata.

创建文件pod-read-access-service-account.yaml ,并将ServiceAccount定义放在顶部。 该资源基本上只是元数据。

---
apiVersion: v1
kind: ServiceAccount
metadata:
name: log-exporter-sa
namespace: default
labels:
app: log-exporter
---

The next thing is the ClusterRole definition. Inside its spec block, we define which apiGroups and resources we want to access. The core API group is denoted by "", and under resources we list pods. Finally, the verbs determine which action we want to apply to the resources: In our case, its reading and listing.

接下来是ClusterRole定义。 在其spec块内,我们定义要访问的apiGroupsresources 。 核心API组用""表示,在resources下方列出了pods 。 最后, verbs确定我们要对资源执行的操作:在我们的案例中,是其阅读和列出。

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: log-exporter-cr
labels:
app: log-exporter
rules:
- apiGroups:
- ''
resources:
- pods
- pods/log
- namespaces
verbs:
- get
- list
---

Finally we create the RoleBinding resource to combine the SeviceAccount and the ClusterRole.

最后,我们创建RoleBinding资源以结合SeviceAccountClusterRole

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: log-exporter-rb
roleRef:
kind: ClusterRole
name: log-exporter-cr
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: log-exporter-sa
namespace: default
---

Now we create all resources.

现在我们创建所有资源。

> kubectl create -f pod-read-access-service-account.yamlserviceaccount/log-exporter-sa created
clusterrole.rbac.authorization.k8s.io/log-exporter-cr created
rolebinding.rbac.authorization.k8s.io/log-exporter-rb created

Some more details: As you see, the ServiceAccount is explicitly created in the default namespace. Be careful about the ClusterRoleBinding as it needs to reference this ServiceAccount in its defined namespace as well, or it will not work correctly.

更多详细信息:如您所见, ServiceAccount是在default名称空间中显式创建的。 注意ClusterRoleBinding因为它也需要在其定义的名称空间中引用此ServiceAccount ,否则它将无法正常工作。

K8S API:使用自定义服务帐户访问 (K8S API: Access with Custom Service Account)

To use the newly created ServiceAccount, we define that the pod uses the new role. Going back to the api-explorer-pod.yaml file, we add the new configuration item spec.serviceAccountName.

要使用新创建的ServiceAccount ,我们定义吊舱使用新角色。 回到api-explorer-pod.yaml文件,我们添加了新的配置项目spec.serviceAccountName

apiVersion: v1
kind: Pod
metadata:
name: api-explorer
spec:
serviceAccountName: log-exporter-sa
containers:
- name: alpine
image: alpine
args: ['sleep', '3600']

Back in the container, we grab the token to make the request — and it works!

回到容器中,我们抓取令牌以发出请求-它起作用了!

curl -H "Authorization: Bearer $TOKEN" https://kubernetes/api/v1/namespaces/default/pods/ --insecure
{
"kind": "PodList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/namespaces/default/pods/",
"resourceVersion": "320995"
},
"items": [
{
"metadata": {
"name": "api-explorer2",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/pods/api-explorer2",
"uid": "343aaf7e-1be5-45da-aadb-e83ee329a7fd",
"resourceVersion": "320976",
"creationTimestamp": "2020-05-24T10:16:58Z"
},
...

Now as the final proof of concepts, let’s try to read logs from a different pod in a different namespace. We grab the coredns pod from the kube-system namespace.

现在,作为概念的最终证明,让我们尝试从不同名称空间中的其他容器读取日志。 我们从kube-system名称空间中获取coredns pod。

kb get pods -n kube-systemNAME                                      READY   STATUS    RESTARTS   AGE
metrics-server-6d684c7b5-6ww29 1/1 Running 7 8d
coredns-d798c9dd-pdswq 1/1 Running 7 8d

The url to access this pod is composed as this: /api/v1/namespaces/{namespace}/pods/{name}/log. So, we need the exact namespace and the exact pod name for this request to work. Get back into the api-explorer pod and access the log files.

用于访问此pod的url是这样组成的: /api/v1/namespaces/{namespace}/pods/{name}/log 。 因此,我们需要确切的名称空间和确切的pod名称,此请求才能正常工作。 返回api-explorer窗格并访问日志文件。

> curl -H "Authorization: Bearer $TOKEN" https://kubernetes/api/v1/namespaces/kube-system/pods/coredns-d798c9dd-pdswq/log --insecure[INFO] plugin/reload: Running configuration MD5 = 4665410bf21c8b272fcfd562c482cb82
______ ____ _ _______
/ ____/___ ________ / __ \/ | / / ___/ ~ CoreDNS-1.6.3
/ / / __ \/ ___/ _ \/ / / / |/ /\__ \ ~ linux/arm, go1.12.9
/ /___/ /_/ / / / __/ /_/ / /| /___/ /
\____/\____/_/ \___/_____/_/ |_//____/

We are happy to see that it works as intended.

我们很高兴看到它按预期工作。

结论 (Conclusion)

In this article, we learned about the essential Kubernetes resources for enabling to access pods and their log files in any namespace. A ClusterRole defines which resources and which actions on those resources should be given. These access rights are bound with a ClusterRoleBinding to a ServiceAccount. Then we use this ServiceAccount to provide the access rights to a Pod. We showed how the Kubernetes API can be access from within a pod by using the curl command. In the next article we will see how to implement a cron job that uses this service account to export the log files.

在本文中,我们了解了必要的Kubernetes资源,这些资源可用于访问任何命名空间中的Pod及其日志文件。 ClusterRole定义应指定哪些资源以及ClusterRole资源应执行的操作。 这些访问权限通过ClusterRoleBinding绑定到ServiceAccount 。 然后,我们使用此ServiceAccount提供对Pod的访问权限。 我们展示了如何使用curl命令从pod内访问Kubernetes API。 在下一篇文章中,我们将看到如何实现使用该服务帐户导出日志文件的cron作业。

翻译自: https://medium.com/@admantium/kubernetes-api-how-custom-service-accounts-work-936709f18740

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值