K8S API概述

可参考:https://kubernetes.io/zh-cn/docs/concepts/overview/kubernetes...

Kubernetes API是Kubernetes管制立体的外围。它是一组REST API,用于与Kubernetes中的各种对象进行交互,如Pods、Namespaces、ConfigMaps和Events等。通过这些API,能够查问和操作Kubernetes中API对象的状态。

API server是Kubernetes集群中的一个组件,它公开了这些REST API。Kubernetes中的各种组件,包含kubectl命令行工具、kubeadm等工具,都通过调用这些API来执行操作。

除了应用kubectl等工具之外,也能够间接应用REST调用来拜访API。如果正在编写应用Kubernetes API的应用程序,请思考应用其中一个客户端库。

残缺的API详细信息都应用OpenAPI进行文档化,这使得运维开发人员能够很容易地理解API的性能和应用形式。

OpenAPI 标准

Kubernetes OpenAPI 标准实际上只有一种,它是基于 OpenAPI 3.0 标准的。之前版本的 Kubernetes API 应用的是 Swagger 2.0 标准,但当初曾经降级到了 OpenAPI 3.0 标准。

须要留神的是,尽管 OpenAPI 3.0 标准是 Swagger 2.0 标准的继承者,但它们之间有一些重要的区别,如参数、响应、申请体和平安等方面的定义形式都有所不同。因而,在应用 OpenAPI 标准时须要留神版本兼容性。接下来,别离理解一下V2和V3。

OpenAPI V2

Kubernetes API服务器提供了一个聚合的 OpenAPI v2 标准,通过拜访 /openapi/v2 端点获取。这个标准包含了所有的API组的定义,以及每个API组的所有API的定义,使得运维开发人员能够分明地理解Kubernetes API的构造和性能。

通过在HTTP申请头中指定不同的响应格局,运维开发人员能够取得不同格局的OpenAPI标准文档。下表列出了可用的申请头和响应格局:

头部可选值阐明
Accept-Encodinggzip不指定此头部也是能够的
Acceptapplication/com.github.proto-openapi.spec.v2@v1.0+protobuf次要用于集群外部
application/json默认值
*提供application/json

通过应用这些申请头,开发人员能够获取他们所需的格式化的OpenAPI标准文档,以便在应用程序中进行解决和解析。

Kubernetes的API应用Protobuf作为序列化格局进行外部通信。这种序列化格局有助于缩小网络传输的数据量和进步通信的效率。在Kubernetes中,每个API对象都有一个对应的Protobuf定义文件。这些文件形容了对象的构造和字段。Kubernetes还提供了应用这些Protobuf定义文件生成客户端和服务器代码的工具,以便开发人员能够轻松地应用Kubernetes API。除了Protobuf之外,Kubernetes还反对应用其余序列化格局进行通信,例如JSON和YAML。这些格局更易于浏览和编写,并且通常用于与内部零碎的集成。不过,在集群外部通信时,Protobuf依然是最罕用的序列化格局。

想进一步理解 Kubernetes Protobuf 序列化可参考:https://github.com/kubernetes/design-proposals-archive/blob/main/api-machinery/protobuf.md

OpenAPI V3

OpenAPI V3是Kubernetes反对的一种API形容格局。从Kubernetes v1.27版本开始,这个性能曾经被稳固反对。

Kubernetes提供了一个名为 /discovery/v3 的端点来展现所有可用的API组和版本列表。这个端点只返回JSON格局的数据。这些API组和版本会以特定的格局出现:

{    "paths": {        ...,        "api/v1": {            "serverRelativeURL": "/openapi/v3/api/v1?hash=CC0E9BFD992D8C59AEC98A1E2336F899E8318D3CF4C68944C3DEC640AF5AB52D864AC50DAA8D145B3494F75FA3CFF939FCBDDA431DAD3CA79738B297795818CF"        },        "apis/admissionregistration.k8s.io/v1": {            "serverRelativeURL": "/openapi/v3/apis/admissionregistration.k8s.io/v1?hash=E19CC93A116982CE5422FC42B590A8AFAD92CDE9AE4D59B5CAAD568F083AD07946E6CB5817531680BCE6E215C16973CD39003B0425F3477CFD854E89A9DB6597"        },        ....    }}

为了进步客户端缓存效率,这些绝对URL指向不可变的OpenAPI形容信息。为此,API服务器还设置了适当的HTTP缓存标头(将Expires设置到将来的1年,将Cache-Control设置为不可变)。当应用过期的URL时,API服务器会将其重定向到最新的URL。

Kubernetes API服务器在 /openapi/v3/apis/<group>/<version>?hash=<hash> 端点为每个Kubernetes组版本公布一个OpenAPI v3标准。

承受的申请标头请参考下表:

头部可选值阐明
Accept-Encodinggzip不提供此头部也是可承受的
Acceptapplication/com.github.proto-openapi.spec.v3@v1.0+protobuf次要用于集群外部应用
application/json默认
*以 application/json 模式返回

API参考

API 端点、资源类型以及示例可参考: https://kubernetes.io/zh-cn/docs/reference/kubernetes-api/

申请API经验的阶段

可参考:https://kubernetes.io/zh-cn/docs/concepts/security/controllin...

用户能够应用kubectl、客户端库或通过进行REST申请来拜访Kubernetes API。无论是人类用户还是Kubernetes服务账户,都能够被受权拜访API。当申请达到API时,它会通过几个阶段,如下图所示:

![图片]()

连贯和证书:

  • API Server默认在6443端口上进行监听,也能够批改。
  • 拜访API,应用TLS建设连贯。
  • API Server证书,能够是公有CA、也能够是公认CA。

上图步骤的认证过程:

  1. 申请API时,会和APIServer建设TLS连贯。
  2. 进入身份认证模块(Authentication),验证拜访API的用户是否非法,认证不通过则返回401。
  3. 进入鉴权模块(Authorization),确认该用户是否具备拜访某个资源或执行某个操作的权限, 如果现有策略申明该用户有权实现申请的操作,则鉴权通过。
  4. 进入准入控制器(Admission Control),执行验证和/或变更操作。
  5. 通过所有准入控制器后,再查看对应的API对象,而后将其写入对象存储。

鉴权模块阐明:鉴权模块的实现有RBAC、ABAC、Node、Webhook。可参考:https://kubernetes.io/zh-cn/docs/reference/access-authn-authz...

准入控制器阐明:准入控制器会在申请通过认证和鉴权之后、对象被长久化之前拦挡达到 APIServer的申请,准入管制过程会运行两个阶段,别离是第1阶段是运行变更准入控制器,第2阶段是运行验证准入控制器。留神了,某些控制器既是变更准入控制器又是验证准入控制器。如果两个阶段之一的任何一个控制器回绝了某申请,则整个申请将立刻被回绝,并向最终用户返回谬误。如要进一步理解准入控制器可参考:https://kubernetes.io/zh-cn/docs/reference/access-authn-authz...

申请API之前筹备一个普通用户

所有 Kubernetes 集群都有两类用户:

  • 由 Kubernetes 治理的服务账号
  • 普通用户

在理论工作中要调用K8S API,为了减少安全性,倡议创立一个专用的一般程序账号。

1. 创立普通用户的私钥

为了让普通用户可能通过认证并调用API,须要执行几个步骤。首先,该用户必须领有Kubernetes集群签发的证书,而后将该证书提供给Kubernetes API。

可参考:https://kubernetes.io/zh-cn/docs/reference/access-authn-authz...

# 创立一个普通用户的私钥和证书签名申请 (Certificate Signing Request, CSR)。能够应用 OpenSSL 工具生成私钥和 CSR:openssl genrsa -out tantianran.key 2048openssl req -new -key tantianran.key -out tantianran.csr -subj "/CN=tantianran/O=noblameops"

这里 tantianran 是用户的名称,noblameops 是用户所属的组织。

2. 创立证书签名申请(CertificateSigningRequest),并提交到Kubernetes集群

将 CSR 提交给 Kubernetes 集群中的证书签名机构 (Certificate Authority, CA) 进行签名。能够应用 kubectl 工具提交 CSR 并获取签名后的证书:

cat <<EOF | kubectl apply -f -apiVersion: certificates.k8s.io/v1kind: CertificateSigningRequestmetadata:  name: tantianranspec:  request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ2J6Q0NBVmNDQVFBd0tqRVRNQkVHQTFVRUF3d0tkR0Z1ZEdsaGJuSmhiakVUTUJFR0ExVUVDZ3dLYm05aQpiR0Z0Wlc5d2N6Q0NBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQU1Jc0M0R2JSQ0NJCmE1L2RLenpYc3VtUXVxay9qclZRemJuSmpiVkY5ZVV6bU1OR3drTi9aanRrVU5ZTUNRMkRpY1JIRUJzTFVMTTIKSFhTdkZtV1lUUGN6OEJWOHgvR214YXlWcVNmQTU4aDNtdjJERjhZdFB2aFlVc3hmUVZpUUxFRGFwRXpoV29TcApVN3BwRjJ4YXZjeG9GbDd3emRQWE9YMnhDQXNSQ3pINjB6cG9zSEJiNHBaSGJjYjNyQ1hjdHBnVlFDeklubWRGCjFrNHJncHg5SGsrek4rNzQ1R04vS1dMMWdLcFNhN2YxemdHdXVaT2FrZEhKaldGdCtWYzNFSG90SFQ3V3g1VTEKazV4ZnpuZkk2VlkvN0NTbzR1K2hhSTg2RHBRaXZmdk1OM3ZGeURwOVR2UWVsOFJpZlFiMkxaMnlUYzdEL3hHQQpCWUZhQ25OUjl3a0NBd0VBQWFBQU1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ0hyNmYxd3A0NFd1L1dtczAvCmRFdWswVjJrMElzQzZoOHppbkptN3BHMjlpSFVrVDZNWDNBR3E0WlVZNkVBN3BYa1VDazhsYXFGVjVQTmJoSXkKUTBEUndRdW82WHNqZ1JMQmdZZFNRaU5vVUYrR1ZCSEEyNmZEV3c2VU8zdjErZXVJODlOWXVJbXl4UGtpaE0xYgpyZkNoa1RCeXRBbUxHbVlwOU5OMnBHdDJyTW94cGtDME5PSElWOWdPUnp1Q1h3cytWTE5zS3VSS2diT1hsUVhMCmVOeVd4TGlCR0ZSZ1BsaWpyTnQrdnA1WktHRjV1SEVXYStjZ3NXN1cwZCtoRm9XMlYxczVDZ2ZzdU1IdUNlR3AKMUxSVnZheVJSaDVtekdnTlNrdUpkUTBHdU1lbk5tRGpoSDI1NU5CNVBzdHpTOVBSU1lCVUIvdUdIYi9yVXByWgprOHRECi0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=  signerName: kubernetes.io/kube-apiserver-client  expirationSeconds: 86400  # one day  usages:  - client authEOF

须要留神的几点:

  • usage 字段必须是 'client auth'
  • expirationSeconds 能够设置为更长(例如 864000 是十天)或者更短(例如 3600 是一个小时)
  • request 字段是 CSR 文件内容的 base64 编码值。 要失去该值,能够执行命令

    cat tantianran.csr | base64 | tr -d "\n"

创立实现后查看一下CSR列表:

[root@k8s-a-master api-user]# kubectl get csrNAME         AGE   SIGNERNAME                            REQUESTOR          REQUESTEDDURATION   CONDITIONtantianran   58s   kubernetes.io/kube-apiserver-client   kubernetes-admin   24h                 Pending
3. 批准证书签名申请(CertificateSigningRequest,简称CSR)
[root@k8s-a-master api-user]# kubectl certificate approve tantianrancertificatesigningrequest.certificates.k8s.io/tantianran approved

反之,如果要驳回:

kubectl certificate deny tantianran
4. 获取证书

从CSR获取证书:

kubectl get csr/tantianran -o yaml

证书的内容应用 base64 编码,寄存在字段 status.certificate。

从 CertificateSigningRequest 导出颁发的证书:

kubectl get csr tantianran -o jsonpath='{.status.certificate}'| base64 -d > tantianran.crt
5. 基于RBAC的鉴权模式,创立Role(角色)

在 Kubernetes 中,Role 和 ClusterRole 都是用于受权拜访 Kubernetes API 资源的对象,但它们之间有着不同的作用域。Role 是一个名字空间作用域的资源,它定义了一个角色,即一组操作权限,能够被授予给一个或多个用户、服务账户或其余角色,以管制它们在某个特定命名空间内的操作权限。因而,当您创立 Role 时,必须指定该 Role 所属的命名空间。与之绝对,ClusterRole 是一个集群作用域的资源,它定义了一组操作权限,能够授予给任何命名空间内的用户、服务账户或其余角色。因而,ClusterRole 能够用于受权对整个 Kubernetes 集群的操作权限。须要留神的是,因为 Kubernetes 对象要么是名字空间作用域的,要么是集群作用域的,因而 Role 和 ClusterRole 的名称不同,以便将它们辨别开来。如果您要在特定的命名空间内设置拜访权限,则应该应用 Role。如果您要在整个集群中设置拜访权限,则应该应用 ClusterRole。

创立了证书之后,为了让这个用户能拜访 Kubernetes 集群资源,当初就要创立 Role 和 RoleBinding(在下一大节创立) 了。

上面命令将在 rook-ceph 命名空间中创立一个名为 developer 的角色,并为该角色调配一些操作权限。具体来说,该角色将被授予在该命名空间内创立、获取、列出、更新和删除 pods 资源的权限。

kubectl create role developer --verb=create --verb=get --verb=list --verb=update --verb=delete --namespace=rook-ceph --resource=pods
  • kubectl create role developer:创立一个名为 developer 的角色。
  • --verb=create --verb=get --verb=list --verb=update --verb=delete:指定该角色容许的操作权限,即创立、获取、列出、更新和删除。
  • --namespace=rook-ceph:指定该角色所属的命名空间为 rook-ceph。
  • --resource=pods:指定该角色所受权的资源类型为 pods。

对应的yaml如下:

apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata:  name: developer  namespace: rook-cephrules:- apiGroups:  - ""  resources:  - pods  verbs:  - create  - get  - list  - update  - delete

列出rook-ceph命名空间下的role:

[root@k8s-a-master api-user]# kubectl get roles -n rook-cephNAME                              CREATED ATcephfs-external-provisioner-cfg   2023-04-03T08:28:33Zdeveloper                         2023-04-19T08:10:25Z # 这个就是方才创立的rbd-csi-nodeplugin                2023-04-03T08:28:33Zrbd-external-provisioner-cfg      2023-04-03T08:28:33Zrook-ceph-cmd-reporter            2023-04-03T08:28:33Zrook-ceph-mgr                     2023-04-03T08:28:33Zrook-ceph-osd                     2023-04-03T08:28:33Zrook-ceph-purge-osd               2023-04-03T08:28:33Zrook-ceph-rgw                     2023-04-03T08:28:33Zrook-ceph-system                  2023-04-03T08:28:33Z
6. 基于RBAC的鉴权模式,创立 RoleBinding (角色绑定)

角色绑定(Role Binding)是将角色中定义的权限赋予一个或者一组用户。 它蕴含若干 主体(用户、组或服务账户)的列表和对这些主体所取得的角色的援用。 RoleBinding 在指定的名字空间中执行受权,而 ClusterRoleBinding 在集群范畴执行受权。一个 RoleBinding 能够援用同一的名字空间中的任何 Role。 或者,一个 RoleBinding 能够援用某 ClusterRole 并将该 ClusterRole 绑定到 RoleBinding 所在的名字空间。 如果你心愿将某 ClusterRole 绑定到集群中所有名字空间,你要应用 ClusterRoleBinding。

上面的命令是在Kubernetes集群中创立一个名为developer-binding-tantianran的角色绑定对象,其作用是将一个用户(tantianran)与一个名为developer的角色关联起来。

kubectl create rolebinding developer-binding-tantianran --role=developer --user=tantianran --namespace=rook-ceph
  • --role选项指定了要绑定的角色,这里是developer。
  • --user选项指定了要绑定到该角色的用户,这里是tantianran。

这意味着,一旦角色绑定对象被创立,用户tantianran就将取得developer角色的权限。

对应的yaml如下:

apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata:  name: developer-binding-tantianran  namespace: rook-cephroleRef:  apiGroup: rbac.authorization.k8s.io  kind: Role  name: developersubjects:- apiGroup: rbac.authorization.k8s.io  kind: User  name: tantianran

列出rook-ceph命名空间下的RoleBinding:

[root@k8s-a-master api-user]# kubectl get rolebinding -n rook-cephNAME                              ROLE                                   AGEcephfs-csi-provisioner-role-cfg   Role/cephfs-external-provisioner-cfg   15ddeveloper-binding-tantianran      Role/developer                         14s # 这个是方才创立的rbd-csi-nodeplugin-role-cfg       Role/rbd-csi-nodeplugin                15drbd-csi-provisioner-role-cfg      Role/rbd-external-provisioner-cfg      15drook-ceph-cluster-mgmt            ClusterRole/rook-ceph-cluster-mgmt     15drook-ceph-cmd-reporter            Role/rook-ceph-cmd-reporter            15drook-ceph-mgr                     Role/rook-ceph-mgr                     15drook-ceph-mgr-system              ClusterRole/rook-ceph-mgr-system       15drook-ceph-osd                     Role/rook-ceph-osd                     15drook-ceph-purge-osd               Role/rook-ceph-purge-osd               15drook-ceph-rgw                     Role/rook-ceph-rgw                     15drook-ceph-system                  Role/rook-ceph-system                  15d
7. 增加到kubeconfig

kubeconfig 是 Kubernetes 集群客户端的配置文件,它蕴含连贯到 Kubernetes API Server 所需的信息,包含 API Server 地址、证书、认证形式等。

最初一步是将这个用户增加到 kubeconfig文件。首先,须要增加新的凭据:

kubectl config set-credentials tantianran --client-key=tantianran.key --client-certificate=tantianran.crt --embed-certs=true --namespace=rook-ceph
  • tantianran 是用户凭据条目标名称,能够自定义。
  • --client-key=tantianran.key 示意应用名为 tantianran.key 的客户端密钥文件作为用户凭据的一部分。客户端密钥用于对 API 服务器进行身份验证。
  • --client-certificate=tantianran.crt 示意应用名为 tantianran.crt 的客户端证书文件作为用户凭据的一部分。客户端证书用于对 API 服务器进行身份验证。
  • --embed-certs=true 示意将客户端证书嵌入到 kubeconfig 文件中,而不是将其作为文件援用。这能够帮忙简化 kubeconfig 文件的治理。
  • --namespace=rook-ceph 示意在 rook-ceph 命名空间中应用该用户凭据。命名空间用于将 Kubernetes 资源划分为不同的逻辑组。

应用 kubectl config set-credentials 命令创立了名为 tantianran 的用户凭据,那么能够在输入后果中搜寻 tantianran 来查看该用户凭据的详细信息。上面是应用 kubectl config view 命令查看 kubeconfig 文件中用户凭据的示例输入:

[root@k8s-a-master api-user]# kubectl config viewapiVersion: v1clusters:- cluster:    certificate-authority-data: DATA+OMITTED    server: https://192.168.11.10:6443  name: kubernetescontexts:- context:    cluster: kubernetes    user: kubernetes-admin  name: kubernetes-admin@kubernetes- context:    cluster: kubernetes    user: tantianran  name: tantianrancurrent-context: kubernetes-admin@kuberneteskind: Configpreferences: {}users:- name: kubernetes-admin  user:    client-certificate-data: REDACTED    client-key-data: REDACTED- name: tantianran  user:    client-certificate-data: REDACTED    client-key-data: REDACTED

在上述输入中,能够看到名为 tantianran 的用户凭据信息,包含客户端证书、客户端密钥和命名空间等。

而后,增加上下文:

kubectl config set-context tantianran --cluster=kubernetes --user=tantianran --namespace=rook-ceph

kubectl config set-context 命令用于创立或批改 kubeconfig 文件中的上下文。上下文蕴含了与一个 Kubernetes 集群的连贯所需的所有信息,包含集群、用户和命名空间等。下面的参数阐明如下:

  • tantianran 是上下文的名称
  • --cluster 参数指定了集群名称为 kubernetes
  • --user 参数指定了用户名称为 tantianran
  • --namespace 参数指定了默认命名空间为 rook-ceph。 简而言之,这个命令创立了一个名为 tantianran 的上下文,该上下文与 kubernetes 集群建设连贯,并应用 tantianran 用户进行身份验证。同时,该上下文默认的命名空间为 rook-ceph,通过实战,其实是没必要指定命名空间。因为,就算指定了命名空间,当不论是查看还是删除上下文的时候,不论有没有指定命名空间都是能够的。比方查看的时候,不指定命名空间也能查到,比方删除的时候,不指定命名空间照样也能删除。

如果要删除上下文能够用上面的命令:

kubectl config delete-context tantianran# 或kubectl config delete-context tantianran -n rook-ceph

增加后,查看以后可用的 Kubernetes 配置文件上下文:

[root@k8s-a-master api-user]# kubectl config get-contextsCURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin             tantianran                    kubernetes   tantianran         rook-ceph# 或[root@k8s-a-master api-user]# kubectl config get-contexts -n rook-cephCURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin             tantianran                    kubernetes   tantianran         rook-ceph[root@k8s-a-master api-user]#       

上下文切换:

# 切换到普通用户的上下文[root@k8s-a-master api-user]# kubectl config use-context tantianran# 列出以后上下文[root@k8s-a-master api-user]# kubectl config get-contextsCURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE          kubernetes-admin@kubernetes   kubernetes   kubernetes-admin   *         tantianran                    kubernetes   tantianran # 此处的*号代表以后上下文是处于这个账户下# 把上下文切换回admin:kubectl config use-context kubernetes-admin@kubernetes

查看以后用户是否能够执行给定操作(无论应用何种鉴权模式该命令都能够工作,我这里是RBAC(基于角色的访问控制)的鉴权模式):

# 在admin上下文中执行查看操作:[root@k8s-a-master api-user]# kubectl auth can-i list pods --namespace rook-ceph --as tantianranyes[root@k8s-a-master api-user]# kubectl auth can-i list pods --namespace default --as tantianran # 能够看到,处于default命名空间下的pod的,tantianran是没有权限的no# 如果曾经切换到了一般账户的上下文中,那么能够用上面的命令查看:[root@k8s-a-master api-user]# kubectl config use-context tantianran[root@k8s-a-master api-user]# kubectl auth can-i create pods --namespace rook-cephyes[root@k8s-a-master api-user]# kubectl auth can-i create pods --namespace default no

客户端库

当要应用 Kubernetes REST API 来操作K8S各种资源时,能够依据本人喜爱的编程语言来抉择适合的客户端库。客户端库有官网反对的,也有社区保护的。官网反对的 Kubernetes 客户端库有Go、Python、C、Java等等,作为运维开发工程师,能够应用Go或者Python。而我,以前是写Python的,老早就曾经彻底转Go了,而且还是Go的深度发烧友。对于客户端库更多的信息可参考:https://kubernetes.io/zh-cn/docs/reference/using-api/client-l...

我打算别离应用Golang和Python的K8S客户端库来进行编码,明天的工夫无限,放到下篇分享。

本文转载于WX公众号:不背锅运维(喜爱的盆友关注咱们):https://mp.weixin.qq.com/s/G8jK0IBcfM3kxQfZD_ebEw