[K8S小白问题集] - APIServer接受到的API调用都是什么样的?与http请求的API差别很大吗?

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 是基础设施级能力 ,且支持集合运算(In、NotIn、Exists)。

差异 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 都是表格"**------表面都是行列数据,但底层哲学和适用域完全不同。

相关推荐
冷小鱼2 小时前
从 Docker 到容器编排:框架选型与指令详解实战指南
运维·docker·容器·k8s·docker compose·docker swarm
wxh_无香花自开3 小时前
k8s证书到期处理
k8s
云游牧者2 天前
K8S故障排查三板斧-CSDN博客
运维·docker·云原生·kubernetes·k8s·容器化·故障排查
@王先生12 天前
【K8S-ETCD初始化三节点集群】
前端·chrome·k8s·etcd·集群
牛奶咖啡132 天前
CI/CD——在jenkins中构建流程实现springboot项目的自动化构建与部署
java·ci/cd·k8s·jenkins·springboot·springboot制作镜像·使用源码项目制作镜像
脑子加油站5 天前
K8S-Ingress资源对象
算法·贪心算法·k8s
~黄夫人~7 天前
Kubernetes 入门到实战:概念详解 + kubeadm 安装 + 节点克隆全流程
linux·运维·学习·k8s·集群
yunson_Liu13 天前
aws EKS集群pvc存储扩容
k8s·aws
张32316 天前
k8s etcd备份恢复
数据库·k8s·etcd