前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【重识云原生】第六章容器6.3.2节——API Server组件

【重识云原生】第六章容器6.3.2节——API Server组件

作者头像
江中散人_Jun
发布2022-10-04 19:54:27
8140
发布2022-10-04 19:54:27
举报

1 API Server概述

        kube-apiserver 是 Kubernetes 最重要的核心组件之一,是所有服务访问的统一入口(所有请求的统一的入口),并提供认证、授权、访问控制、API 注册和发现等能力,同时也是是 Kubernetes Cluster 的前端接口,各种客户端工具(CLI 或 UI)以及 Kubernetes 其他组件可以通过它管理 Cluster 的各种资源。

1.1 API Server的作用

API Server 提供了以下的功能:

  1. 整个集群管理的 API 接口:所有对集群进行的查询和管理都要通过 API 来进行。集群内部的组件(如kubelet)也是通过Apiserver更新和同步数据到etcd中。
  2. 集群内部各个模块之间通信的枢纽:所有模块之前并不会之间互相调用,而是通过和 API Server 打交道来完成自己那部分的工作。
  3. 集群安全控制:API Server 提供的验证和授权保证了整个集群的安全。
  4. 数据中心枢纽: API Server 负责和 Etcd 交互存放集群用到的运行数据。

1.2 REST API

        kube-apiserver 支持同时提供 https(默认监听在 6443 端口)和 http API(默认监听在 127.0.0.1 的 8080 端口),其中 http API 是非安全接口,不做任何认证授权机制,不建议生产环境启用。两个接口提供的 REST API 格式相同,参考 Kubernetes API Reference 查看所有 API 的调用格式。

(图片来自 OpenShift Blog

        在实际使用中,通常通过 kubectl 来访问 apiserver,也可以通过 Kubernetes 各个语言的 client 库来访问 apiserver。在使用 kubectl 时,打开调试日志也可以看到每个 API 调用的格式,比如:

代码语言:javascript
复制
$ kubectl --v=8 get pods

        可通过 kubectl api-versions 和 kubectl api-resources 查询 Kubernetes API 支持的 API 版本以及资源对象。

代码语言:javascript
复制
$ kubectl api-versions 
admissionregistration.k8s.io/v1beta1 
apiextensions.k8s.io/v1beta1 apiregistration.k8s.io/v1 
apiregistration.k8s.io/v1beta1 
apps/v1 
apps/v1beta1 
apps/v1beta2 
authentication.k8s.io/v1 
authentication.k8s.io/v1beta1 
authorization.k8s.io/v1 
authorization.k8s.io/v1beta1 
autoscaling/v1 
autoscaling/v2beta1 
batch/v1 
batch/v1beta1 
certificates.k8s.io/v1beta1 
events.k8s.io/v1beta1 
extensions/v1beta1 
metrics.k8s.io/v1beta1 
networking.k8s.io/v1 
policy/v1beta1 
rbac.authorization.k8s.io/v1 
rbac.authorization.k8s.io/v1beta1 
scheduling.k8s.io/v1beta1 storage.k8s.io/v1 
storage.k8s.io/v1beta1 
v1 

$ kubectl api-resources --api-group=storage.k8s.io 
NAME             SHORTNAMES     APIGROUP         NAMESPACED         KIND 
storageclasses     sc         storage.k8s.io     false         StorageClass 
volumeattachments             storage.k8s.io     false         VolumeAttachment

1.3 OpenAPI 和 Swagger

        通过 /swaggerapi 可以查看 Swagger API,/openapi/v2 查看 OpenAPI。

        开启 --enable-swagger-ui=true 后还可以通过 /swagger-ui 访问 Swagger UI。

        根据 OpenAPI 也可以生成各种语言的客户端,比如可以用下面的命令生成 Go 语言的客户端:

代码语言:javascript
复制
git clone https://github.com/kubernetes-client/gen /tmp/gen 
cat >go.settings <<EOF 
# Kubernetes branch name 
export KUBERNETES_BRANCH="release-1.11" 

# client version for packaging and releasing. 
export CLIENT_VERSION="1.0" 
# Name of the release package 
export PACKAGE_NAME="client-go" 
EOF 

/tmp/gen/openapi/go.sh ./client-go ./go.settings

1.4 访问控制

        Kubernetes API 的每个请求都会经过多阶段的访问控制之后才会被接受,这包括认证、授权以及准入控制(Admission Control)等。

1.4.1 认证

        开启 TLS 时,所有的请求都需要首先认证。Kubernetes 支持多种认证机制,并支持同时开启多个认证插件(只要有一个认证通过即可)。如果认证成功,则用户的 username 会传入授权模块做进一步授权验证;而对于认证失败的请求则返回 HTTP 401。

        Kubernetes 不直接管理用户虽然 Kubernetes 认证和授权用到了 username,但 Kubernetes 并不直接管理用户,不能创建 user 对象,也不存储 username。

        更多认证模块的使用方法可以参考 Kubernetes 认证插件

1.4.2 授权

        认证之后的请求就到了授权模块。跟认证类似,Kubernetes 也支持多种授权机制,并支持同时开启多个授权插件(只要有一个验证通过即可)。如果授权成功,则用户的请求会发送到准入控制模块做进一步的请求验证;而对于授权失败的请求则返回 HTTP 403.

        更多授权模块的使用方法可以参考 Kubernetes 授权插件

1.4.3 准入控制

        准入控制(Admission Control)用来对请求做进一步的验证或添加默认参数。不同于授权和认证只关心请求的用户和操作,准入控制还处理请求的内容,并且仅对创建、更新、删除或连接(如代理)等有效,而对读操作无效。准入控制也支持同时开启多个插件,它们依次调用,只有全部插件都通过的请求才可以放过进入系统。

        更多准入控制模块的使用方法可以参考 Kubernetes 准入控制

1.5 启动 apiserver 示例

代码语言:javascript
复制
kube-apiserver --feature-gates=AllAlpha=true --runtime-config=api/all=true \
 --requestheader-allowed-names=front-proxy-client \
 --client-ca-file=/etc/kubernetes/pki/ca.crt \
 --allow-privileged=true \
 --experimental-bootstrap-token-auth=true \
 --storage-backend=etcd3 \
 --requestheader-username-headers=X-Remote-User \
 --requestheader-extra-headers-prefix=X-Remote-Extra- \
 --service-account-key-file=/etc/kubernetes/pki/sa.pub \
 --tls-cert-file=/etc/kubernetes/pki/apiserver.crt \
 --tls-private-key-file=/etc/kubernetes/pki/apiserver.key \
 --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt \
 --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt \
 --insecure-port=8080 \
 --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds \
 --requestheader-group-headers=X-Remote-Group \
 --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key \
 --secure-port=6443 \
 --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname \
 --service-cluster-ip-range=10.96.0.0/12 \
 --authorization-mode=RBAC \
 --advertise-address=192.168.0.20 --etcd-servers=http://127.0.0.1:2379

2 工作原理

        kube-apiserver 提供了 Kubernetes 的 REST API,实现了认证、授权、准入控制等安全校验功能,同时也负责集群状态的存储操作(通过 etcd)。

2.1 整体控制逻辑

        API Server 的架构从上向下可以分为一下几层:

1、API层

        主要以REST方式提供各种API接口,除了有Kubernetes资源对象的CRUD和Watch等主要API,还有健康检查、UI、日志、性能指标等运维监控相关的API。注意:Kubernetes从1.11版本开始废弃Heapster监控组件,转而使用Metrics Server提供Metrics API接口,进一步完善了自身的监控能力。

2、访问控制层

        当客户端访问API接口时,访问控制层负责对用户身份鉴权,验明用户身份,核准用户对 Kubernetes 资源对象的访问权限,然后根据配置的各种资源访问许可逻辑(Admission Control),判断是否允许访问。

3、注册表层

        Kubernetes把所有资源对象都保存在注册表(Registry)中,针对注册表中的各种资源对象都定义了:资源对象的类型、如何创建资源对象、如何转换资源的不同版本,以及如何将资源编码和解码为 JSON或 ProtoBuf格式进行存储。

4、Etcd数据库

        用于持久化存储 Kubernetes 资源对象的KV数据库。etcd的watch API接口对于API Server来说至关重要,因为通过这个接口,API Server 创新性地设计了 List-Watch 这种高性能的资源对象实时同步机制,使 Kubernetes 可以管理超大规模的集群,及时响应和快速处理集群中的各种事件。

2.2 如何访问apiserver

        k8s通过kube-apiserver这个进程提供服务,该进程运行在单个k8s-master节点上。默认有两个端口。

1)本地端口

  1. 该端口用于接收HTTP请求;
  2. 该端口默认值为8080,可以通过API Server的启动参数“–insecure-port”的值来修改默认值;
  3. 默认的IP地址为“localhost”,可以通过启动参数“–insecure-bind-address”的值来修改该IP地址;
  4. 非认证或授权的HTTP请求通过该端口访问API Server。

2)安全端口

  1. 该端口默认值为6443,可通过启动参数“–secure-port”的值来修改默认值;
  2. 默认IP地址为非本地(Non-Localhost)网络端口,通过启动参数“–bind-address”设置该值;
  3. 该端口用于接收HTTPS请求;
  4. 用于基于Tocken文件或客户端证书及HTTP Base的认证;
  5. 用于基于策略的授权;
  6. 默认不启动HTTPS安全访问控制。

2.3 请求处理过程

        以 /apis/batch/v2alpha1/jobs 为例,GET 请求的处理过程如下图所示:

        POST 请求的处理过程为:

(图片来自 OpenShift Blog

2.4 API 访问方式

        有多种方式可以访问 Kubernetes 提供的 REST API:

  • kubectl 命令行工具
  • SDK,支持多种语言
    • Go
    • Python
    • Javascript
    • Java
    • CSharp
    • 其他 OpenAPI 支持的语言,可以通过 gen 工具生成相应的 client

2.4.1 kubectl访问方式

        命令行工具kubectl客户端,通过命令行参数转换为对API Server的REST API调用,并将调用结果输出。

代码语言:javascript
复制
kubectl get --raw /api/v1/namespaces 
kubectl get --raw /apis/metrics.k8s.io/v1beta1/nodes 
kubectl get --raw /apis/metrics.k8s.io/v1beta1/pods

2.4.2 kubectl proxy方式

        Kubectl Proxy代理程序既能作为API Server的反向代理,也能作为普通客户端访问API Server的代理。通过master节点的8080端口来启动该代理程序。

代码语言:javascript
复制
$ kubectl proxy --port=8080 & 
$ curl http://localhost:8080/api/ { "versions": [ "v1" ] }

2.4.3 curl方式

代码语言:javascript
复制
# In Pods with service account. 
$ TOKEN=$(cat /run/secrets/kubernetes.io/serviceaccount/token) 
$ CACERT=/run/secrets/kubernetes.io/serviceaccount/ca.crt 
$ curl --cacert $CACERT --header "Authorization: Bearer 
$TOKEN" https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT/api 
{ 
  "kind": "APIVersions", 
  "versions": [
     "v1" 
  ], 
  "serverAddressByClientCIDRs": [ 
    {
       "clientCIDR": "0.0.0.0/0",
       "serverAddress": "10.0.1.149:443" 
    }
 ] 
}
代码语言:javascript
复制
# Outside of Pods. 
$ APISERVER=$(kubectl config view | grep server | cut -f 2- -d ":" | tr -d " ") 
$ TOKEN=$(kubectl describe secret 
$(kubectl get secrets | grep default | cut -f1 -d ' ') | grep -E '^token'| cut -f2 -d':'| tr -d '\t') 
$ curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure 
{
  "kind": "APIVersions",
  "versions": 
    [
      "v1"
    ],
  "serverAddressByClientCIDRs":
  [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "10.0.1.149:443" 
    }
  ]
}

2.4.4 SDK方式调用

2.5 k8s Proxy API

        k8s API Server最主要的REST接口是资源对象的增删改查。另外还有一类特殊的REST接口—k8s Proxy API接口,这类接口的作用是代理REST请求,即kubernetes API Server把收到的REST请求转发到某个Node上的kubelet守护进程的REST端口上,由该kubelet进程负责响应。

2.5.1 Node 的相关接口

        首先来说说 Kubernetes Proxy API 里关于Node的相关接口。

        该接口的REST路径为 /api/v1/proxy/nodes/{name} ,其中{name}为节点的名称或IP地址,包括以下几个具体接口:

  • /api/v1/proxy/nodes/{name}/pods # 列出指定节点内所有Pod的息
  • /api/v1/proxy/nodes/{name}/stats # 列出指定节点内物理资源的统计信息
  • /api/v1/proxy/nodes/{name}/spec # 列出指定节点的概要信息

        例如,当前 Node 的名称为 k8s-node-1,用下面的命令即可获取该节点上所有运行中的 Pod:

代码语言:javascript
复制
curl localhost:8080/api/v1/proxy/nodes/k8s-node-1/pods

        需要说明的是:这里获取的Pod的信息数据来自Node而非etcd数据库,所以两者可能在某些时间点有所偏差。

2.5.1.1 接口扩展

        此外,如果 kubelet 进程在启动时包含 --enable-debugginghandlers=true参数,那么Kubernetes Proxy API 还会增加下面的接口:

  • /api/v1/proxy/nodes/{name}/run # 在节点上运行某个容器
  • /api/v1/proxy/nodes/{name}/exec # 在节点上的某个容器上运行某条命令
  • /api/v1/proxy/nodes/{name}/attach # 在节点上attach某个容器
  • /api/v1/proxy/nodes/{name}/portForward # 实现节点上的Pod端口转发
  • /api/v1/proxy/nodes/{name}/logs # 列出节点的各类日志信息, 例如tallylog、lastlog、wtmp、ppp/、rhsm/、audit/、tuned/和anaconda/等
  • /api/v1/proxy/nodes/{name}/metrics # 列出和该节点相关的Metrics信息
  • /api/v1/proxy/nodes/{name}/runningpods # 列出节点内运行中的Pod信息
  • /api/v1/proxy/nodes/{name}/debug/pprof # 列出节点内当前Web服务的状态,包括CPU占用情况和内存使用情况等

2.5.2 Pod 的相关接口

        Kubernetes Proxy API里关于Pod的相关接口,通过这些接口,我们可以访问Pod里某个容器提供的服务(如Tomcat在8080端口的服务):

  • /api/v1/proxy/namespaces/{namespace}/pods/{name}/{path:*} # 访问Pod的某个服务接口
  • /api/v1/proxy/namespaces/{namespace}/pods/{name} # 访问Pod
  • /api/v1/namespaces/{namespace}/pods/{name}/proxy/{path:*} # 访问Pod的某个服务接口
  • /api/v1/namespaces/{namespace}/pods/{name}/proxy # 访问Pod

        在上面的4个接口里,后面两个接口的功能与前面两个完全一样,只是写法不同。

2.5.2.1 举例说明Proxy用法

        下面用Tomcat Pod来说明上述Proxy接口的用法。首先, 得到Pod的名称:

代码语言:javascript
复制
# kubectl get pods 
NAME         READY  STATUS   RESTARTS     AGE 
mysql-c95jc   1/1   Running     0         8d 
myweb-g9pmm   1/1   Running     0         8d

        然后, 运行下面命令, 输出Tomcat的首页, 相当于访问 http://localhost:8080/ :

代码语言:javascript
复制
​# curl http://localhost:8080/api/v1/proxy/namespaces/default/pods/myweb-g9pmm/

        我们也可以在浏览器中访问上面的地址,比如Master的IP地址是192.168.18.131,我们在浏览器中输入 http://192.168.18.131:8080/api/v1/proxy/namespaces/default/pods/myweb-g9pmm/ ,就能够访问Tomcat首页了;而如果输入 /api/v1/proxy/namespaces/default/pods/myweb-g9pmm/demo,就能访问Tomcat中Demo应用的页面了。

        看到这里,你可能明白Pod 的Proxy接口的作用和意义了:

        在Kubernetes集群之外访问某个 Pod 容器的服务(HTTP服务)时,可以用Proxy API实现,这种场景多用于管理目的,比如逐一排查Service的Pod副本,检查哪些Pod的服务存在异常。

2.5.3 service 相关接口

        Kubernetes Proxy API也有 Service 的 Proxy 接口,其接口定义与 Pod 的接口定义基本一样:

  • /api/v1/proxy/namespaces/{namespace}/services/{name}

        比如,若我们想访问 MyWeb 这个 Service,则可以在浏览器里输入 http://192.168.18.131:8080/api/v1/proxy/namespaces/default/services/myweb/demo/ 。

2.6 集群功能模块之间的通信

        kubernetes API Server作为集群的核心,负责集群各功能模块之间的通信,集群内各个功能模块通过API Server将信息存入etcd,当需要获取和操作这些数据时,通过API Server提供的REST接口(GET\LIST\WATCH方法)来实现,从而实现各模块之间的信息交互。

2.6.1 kubelet与apiserver交互

        每个Node节点上的kubelet定期就会调用API Server的REST接口报告自身状态,API Server接收这些信息后,将节点状态信息更新到etcd中。kubelet也通过API Server的Watch接口监听Pod信息,从而对Node机器上的POD进行管理。

2.6.2 kube-controller-manager与apiserver交互

        kube-controller-manager中的Node Controller模块通过API Server提供的Watch接口,实时监控Node的信息,并做相应处理。

2.6.3 kube-scheduler与apiserver交互

        Scheduler通过API Server的Watch接口监听到新建Pod副本的信息后,它会检索所有符合该Pod要求的Node列表,开始执行Pod调度逻辑。调度成功后将Pod绑定到目标节点上。

2.7 apiserver参数介绍

        API Server 主要是和 etcd 打交道,并且对外提供 HTTP 服务,以及进行安全控制,因此它的命令行提供的参数也主要和这几个方面有关。下面是一些比较重要的参数以及说明(不同版本参数可能会有不同):

参考链接

kube-apiserver · Kubernetes指南

【云原生训练营】模块六 Kubernetes 控制平面组件:API Server_果子哥丶的博客-CSDN博客_api server

Kubernetes核心原理(一)之API Server_宝贝啊!的博客-CSDN博客

API Server简介_含笑饮毒酒_的博客-CSDN博客_apiserver

独特的 Kubernetes Proxy API接口 | IT工程师的生活足迹

API Server 组件之访问方式和架构解析 | IT工程师的生活足迹

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-09-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 API Server概述
    • 1.1 API Server的作用
      • 1.2 REST API
        • 1.3 OpenAPI 和 Swagger
          • 1.4 访问控制
            • 1.4.1 认证
            • 1.4.2 授权
            • 1.4.3 准入控制
          • 1.5 启动 apiserver 示例
          • 2 工作原理
            • 2.1 整体控制逻辑
              • 2.2 如何访问apiserver
                • 2.3 请求处理过程
                  • 2.4 API 访问方式
                    • 2.4.1 kubectl访问方式
                    • 2.4.2 kubectl proxy方式
                    • 2.4.3 curl方式
                    • 2.4.4 SDK方式调用
                  • 2.5 k8s Proxy API
                    • 2.5.1 Node 的相关接口
                    • 2.5.1.1 接口扩展
                    • 2.5.2 Pod 的相关接口
                    • 2.5.2.1 举例说明Proxy用法
                    • 2.5.3 service 相关接口
                  • 2.6 集群功能模块之间的通信
                    • 2.6.1 kubelet与apiserver交互
                    • 2.6.2 kube-controller-manager与apiserver交互
                    • 2.6.3 kube-scheduler与apiserver交互
                  • 2.7 apiserver参数介绍
                  • 参考链接
                  相关产品与服务
                  容器服务
                  腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档