APIServer 本质上就是一个特殊的 RESTful HTTPS 服务器。从协议底层看,它接收的仍然是标准的 HTTP/1.1 或 HTTP/2 请求,但语义、认证方式、状态管理哲学与普通业务 HTTP API 差异极大。

一、APIServer 接收的请求长什么样?

1.1 一个真实的完整请求(kubectl create pod 的底层)

当你在终端执行:

kubectl run nginx --image=nginx

kubectl 实际上向 APIServer 发送了如下 HTTP 请求(简化版):

POST /api/v1/namespaces/default/pods HTTP/2
Host: 10.96.0.1:443
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
Content-Type: application/json
Accept: application/json

{
  "apiVersion": "v1",
  "kind": "Pod",
  "metadata": {
    "name": "nginx",
    "namespace": "default",
    "labels": {
      "run": "nginx"
    }
  },
  "spec": {
    "containers": [{
      "name": "nginx",
      "image": "nginx",
      "resources": {}
    }]
  }
}

APIServer 返回:

HTTP/2 201 Created
Content-Type: application/json

{
  "kind": "Pod",
  "apiVersion": "v1",
  "metadata": {
    "name": "nginx",
    "uid": "a3f5c8d2-...",
    "resourceVersion": "1234567",
    "creationTimestamp": "2026-05-12T11:51:00Z"
  },
  "spec": { ... },
  "status": { "phase": "Pending" }
}

1.2 URI 的固定结构(RESTful 资源路径)

K8s API 的 URL 不是随意设计的,而是严格的资源层级

/api/v1/namespaces/{namespace}/pods/{name}
/api/v1/namespaces/{namespace}/services/{name}
/apis/apps/v1/namespaces/{namespace}/deployments/{name}
/apis/networking.k8s.io/v1/namespaces/{namespace}/ingresses/{name}

URL 段

含义

/api/v1

核心 API 组(Pod/Service/Node/Namespace 等)

/apis/apps/v1

命名 API 组(Deployment/StatefulSet/DaemonSet)

/namespaces/{ns}

命名空间作用域

/{resource}

资源类型(复数小写)

/{name}

具体资源实例

/{name}/status

子资源:仅更新状态(权限可独立控制)

/{name}/scale

子资源:扩缩容专用端点

/{name}/log

子资源:Pod 日志(连接至 kubelet)

/{name}/exec

子资源:远程执行(WebSocket 升级)

二、与普通 HTTP API 的六大核心差异

差异 1:声明式(Declarative)vs 命令式(Imperative)

维度

普通业务 HTTP API

K8s APIServer

哲学

"去做这件事"(命令)

"我要这个状态"(声明)

请求语义

POST /orders → 创建订单

POST /pods → 声明"我想要一个 Pod"

幂等性

通常不保证

绝对幂等:相同 YAML 重复 apply,结果不变

状态收敛

业务系统自己维护

APIServer 只负责持久化期望状态,实际状态由 Controller 异步收敛

例子

  • 普通 API:POST /send-sms 执行一次就发一条短信,重复调用发多条。
  • K8s API:POST /pods 如果 Pod 已存在且 spec 未变,直接返回 200/409,不会创建第二个。

差异 2:内置全局版本控制(ResourceVersion)

每个 K8s 资源都有 resourceVersion,本质是 etcd 的 MVCC 版本号:

"metadata": {
  "resourceVersion": "1234567"
}

作用

  • 乐观并发控制PUT 请求带 If-Match: "1234567",若服务端版本已变,返回 409 Conflict,防止覆盖。
  • Watch 断点续传:客户端断开重连时携带 resourceVersion,APIServer 从该版本之后推送事件。

普通 HTTP API 通常没有:需要自己设计 version 字段或 ETag 机制。

差异 3:Watch 机制(长轮询/流式事件)

这是 K8s API 最独特的能力,普通 HTTP API 极少需要:

GET /api/v1/namespaces/default/pods?watch=1&resourceVersion=1234567 HTTP/1.1
Accept: application/json

返回不是一次性 JSON,而是持续的 Chunked Transfer 流

{"type":"ADDED", "object":{...}}
{"type":"MODIFIED", "object":{...}}
{"type":"DELETED", "object":{...}}

谁在用 Watch?

  • kubelet:Watch 本节点 Pod 变化,决定创建/销毁容器
  • Controller:Watch Deployment,发现副本数变化后创建 ReplicaSet
  • Scheduler:Watch 未绑定节点的 Pod,执行调度

普通 HTTP API:如果需要实时推送,通常用 WebSocket 或 SSE,但语义与 Watch 完全不同。

差异 4:FieldSelector / LabelSelector(服务端过滤)

GET /api/v1/pods?fieldSelector=status.phase=Running,spec.nodeName=node-01
GET /api/v1/pods?labelSelector=app=payment,env=prod

APIServer 在收到请求后,会将过滤条件下推至 etcd,只返回匹配的资源。

普通 HTTP API:通常是 GET /api/items?status=active,由业务服务自己查数据库过滤。K8s 的 Selector 是基础设施级能力,且支持集合运算(InNotInExists)。

差异 5:子资源(Subresource)与权限精细化

普通 API 通常是 /resource/{id} 平铺,K8s 有子资源概念:

子资源

URL

独立权限

Status

/pods/{name}/status

可单独授权(如 kubelet 只允许更新 status,不允许改 spec)

Log

/pods/{name}/log

实际代理到 kubelet,权限可独立控制

Exec

/pods/{name}/exec

WebSocket 升级,独立 RBAC 规则

Scale

/deployments/{name}/scale

HPA 只需要 scale 权限,不需要 full update 权限

Bind

/pods/{name}/binding

Scheduler 专用,将 Pod 绑定到节点

金融级意义:等保要求最小权限,子资源让 RBAC 可以精确到"只能看日志,不能删 Pod"。

差异 6:内置认证授权链(不是"加个 JWT 中间件"那么简单)

APIServer 的请求在到达业务逻辑前,必须经过三道安检

客户端请求
    │
    ├──► 1. TLS 握手(mTLS 客户端证书验证,或 Token 校验)
    │
    ├──► 2. 认证(Authentication):你是谁?
    │      • X509 客户端证书(kubelet/controller-manager)
    │      • Bearer Token(ServiceAccount JWT / OIDC / Webhook)
    │      • Bootstrap Token(节点加入集群)
    │
    ├──► 3. 授权(Authorization):你能做什么?
    │      • RBAC(Role/ClusterRole + RoleBinding)
    │      • Node 授权(kubelet 只能操作本节点 Pod)
    │      • Webhook(对接银行 AD/LDAP/Keycloak)
    │
    └──► 4. 准入控制(Admission Control):请求是否合规?
           • Mutating(修改请求,如自动注入 Sidecar)
           • Validating(校验请求,如 OPA/Kyverno 策略拦截)

普通 HTTP API:通常只有一层 Authorization: Bearer xxx + 业务层鉴权,没有 K8s 这种协议级、标准化的多阶段安检

三、APIServer 的协议细节(与普通 HTTP 的微妙差异)

3.1 内容协商:JSON vs Protobuf

APIServer 同时支持两种序列化:

# 默认:JSON(人类可读,kubectl 默认)
Accept: application/json

# 高性能:Protobuf(内部组件优先使用,带宽和 CPU 节省 3-5 倍)
Accept: application/vnd.kubernetes.protobuf

银行级优化:集群内部组件(kubelet、controller-manager)应强制使用 Protobuf,减少 APIServer 序列化压力。

3.2 动词(Verb)与 HTTP 方法的映射

K8s 在 RBAC 中使用逻辑动词,不完全等于 HTTP 方法:

HTTP 方法

K8s RBAC Verb

说明

GET

get / list / watch

list 是集合查询,get 是单个资源,watch 是长连接

POST

create

PUT

update

全量替换

PATCH

patch

部分更新(JSON Patch / Strategic Merge Patch)

DELETE

delete / deletecollection

特殊kubectl apply 底层是 PATCH(Strategic Merge Patch),不是简单的 PUT

3.3 Strategic Merge Patch(K8s 独创)

普通 HTTP API 的 PATCH 通常是 JSON Merge Patch 或 JSON Patch(RFC 6902)。K8s 发明了Strategic Merge Patch,解决容器列表的合并语义:

# 原 Deployment
containers:
- name: nginx
  image: nginx:1.19
- name: sidecar
  image: busybox

# 用户 PATCH(只改 nginx 版本)
containers:
- name: nginx
  image: nginx:1.20

# K8s Strategic Merge 结果:保留 sidecar,只更新 nginx
# 普通 JSON Merge Patch 结果:可能直接替换整个 containers 数组,sidecar 丢失

关键patchStrategy:"merge" patchMergeKey:"name" 注解定义了合并策略,这是普通 HTTP API 没有的。

四、金融级视角:APIServer 调用的安全与审计

4.1 审计日志(等保 3.0 要求)

APIServer 的每个请求都会生成结构化审计事件

{
  "kind": "Event",
  "apiVersion": "audit.k8s.io/v1",
  "level": "RequestResponse",
  "timestamp": "2026-05-12T11:51:00Z",
  "verb": "create",
  "user": {
    "username": "zhangsan@bank.com",
    "groups": ["digital-banking", "system:authenticated"]
  },
  "sourceIPs": ["10.0.1.15"],
  "objectRef": {
    "resource": "pods",
    "namespace": "prod-core",
    "name": "payment-api-xxx"
  },
  "requestObject": { ... },      // 请求体(敏感资源可能省略)
  "responseObject": { ... },     // 响应体
  "responseStatus": { "code": 201 }
}

银行要求:审计日志必须留存 6 个月,WORM 存储,对接 SIEM。

4.2 API Priority and Fairness(APF):防止请求洪峰

银行大集群中,某个失控的 CI Job 批量 List Pod 可能挤爆 APIServer。APF 将请求分级:

# FlowSchema:区分系统组件、人类用户、服务账号
priorityLevelConfiguration:
  - name: system-high        # kubelet、controller 高优
  - name: operator-medium    # 运维人员中优
  - name: ci-low             # CI 流水线低优,限流排队

普通 HTTP API:通常用 Nginx/Envoy 限流,但缺乏 K8s 这种基于身份和动词的内置优先级队列

五、一句话讲清差异

APIServer 的 API 在协议层面就是 HTTP/JSON(或 Protobuf),但在语义层面是"面向终态的、版本化的、事件驱动的、带内置安检链的分布式资源控制系统"。

它与普通 HTTP API 的关系,类似于**"SQL 与 Excel 都是表格"**——表面都是行列数据,但底层哲学和适用域完全不同。

更多推荐