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

相关推荐
菜地里的小菜鸟1 天前
kubectl debug
k8s·kubectldebug
腾飞开源3 天前
01_K8s干货笔记之认识K8s
运维·笔记·云原生·容器·kubernetes·k8s·容器化部署
小匠石钧知6 天前
02_在多个RockyLinux10虚拟机上安装k8s集群
云原生·容器·kubernetes·k8s
ShirleyWang01212 天前
让headlamp控制台能访问
linux·服务器·python·k8s·k3s
spider_xcxc12 天前
K8s 部署学习笔记
docker·容器·kubernetes·云计算·k8s
ShirleyWang01212 天前
Day02 K3s NGF(Nginx Gateway Fabric)单 Worker 环境网关更新与故障处置 SOP
linux·服务器·python·k8s·k3s
ShirleyWang01212 天前
DAY01 K3s 私有化部署排障复盘与 SOP
linux·服务器·k8s·k3s·企业部署
XUHUOJUN16 天前
AKS 不是安装在 Windows Server 上,而是运行在 Windows Server 之上的 Azure 平台能力
windows·架构·k8s·azure local·azure stack
Geek-Chow16 天前
Connecting kubectl to a Private EKS Cluster Over an Internal Domain
kubernetes·k8s·aws
spider_xcxc18 天前
Docker Compose 容器通信详解:同一个 Compose 文件才能互通吗?
docker·容器·k8s·容器化·容器网络