K8s是如何Watch的?

1. 概述

进入 K8s 的世界,会发现几乎所有对象都被抽象为了资源(Resource),包括 K8s Core Resources(Pod, Service, Namespace 等)、CRD、APIService 扩展的资源类型。同时 K8s 底层将这些资源统一抽象为了 RESTful 的存储(Storage),一方面服务端按目录形式(/registry/xxx) 存放在 ETCD 中,另一方面也为客户端提供了 RESTful API 接口,便于对资源的操作(get/post/put/patch/delete 等)。

K8s Watch API 就是为资源提供的一种持续监听其变化的机制,当资源有任何变化的时候,都可以实时、顺序、可靠的传递给客户端,使得用户可以针对目标资源进行灵活应用与操作。

那 K8s Watch 机制是怎么实现的呢?底层具体依赖了哪些技术?

本文将从 HTTP 协议、APIServer 启动、ETCD Watch 封装、服务端 Watch 实现、客户端 Watch 实现等方面,对 K8s Watch 实现机制进行了解析。

大致流程如下

本文及后续相关文章都基于 K8s v1.23

2. 从 HTTP 说起

2.1 Content-Length

如下图所示,HTTP 发送请求 Request 或服务端 Response,会在 HTTP header 中携带 Content-Length,以表明此次传输的总数据长度。如果 Content-Length 长度与实际传输长度不一致,则会发生异常(大于实际值会超时, 小于实际值会截断并可能导致后续的数据解析混乱)。

curl baidu.com -v

> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: baidu.com
> Accept: */*

< HTTP/1.1 200 OK
< Date: Thu, 17 Mar 2022 04:15:25 GMT
< Server: Apache
< Last-Modified: Tue, 12 Jan 2010 13:48:00 GMT
< ETag: "51-47cf7e6ee8400"
< Accept-Ranges: bytes
< Content-Length: 81
< Cache-Control: max-age=86400
< Expires: Fri, 18 Mar 2022 04:15:25 GMT
< Connection: Keep-Alive
< Content-Type: text/html

<html>
<meta http-equiv="refresh" content="0;url=http://www.baidu.com/">
</html>

如果服务端提前不知道要传输数据的总长度,怎么办?

2.2 Chunked Transfer Encoding

HTTP 从 1.1 开始增加了分块传输编码(Chunked Transfer Encoding),将数据分解成一系列数据块,并以一个或多个块发送,这样服务器可以发送数据而不需要预先知道发送内容的总大小。数据块长度以十六进制的形式表示,后面紧跟着 \r\n,之后是分块数据本身,后面也是 \r\n,终止块则是一个长度为 0 的分块。

> GET /test HTTP/1.1
> Host: baidu.com
> Accept-Encoding: gzip

< HTTP/1.1 200 OK
< Server: Apache
< Date: Sun, 03 May 2015 17:25:23 GMT
< Content-Type: text/html
< Transfer-Encoding: chunked
< Connection: keep-alive
< Content-Encoding: gzip

4\r\n        (bytes to send)
Wiki\r\n     (data)
6\r\n        (bytes to send)
pedia \r\n   (data)
E\r\n        (bytes to send)
in \r\n
\r\n
chunks.\r\n  (data)
0\r\n        (final byte - 0)
\r\n         (end message)

为了实现以流(Streaming)的方式 Watch 服务端资源变更,HTTP1.1 Server 端会在 Header 里告诉 Client 要变更 Transfer-Encoding 为 chunked,之后进行分块传输,直到 Server 端发送了大小为 0 的数据。

2.3 HTTP/2

HTTP/2 并没有使用 Chunked Transfer Enc

### Kubernetes API 接口对接与 Service 配置 Kubernetes 提供了一种灵活的方式用于外部系统与其内部资源进行交互。以下是关于 Kubernetes API 接口对接以及 Service 配置的相关说明。 #### 1. Kubernetes API Server 的访问机制 API Server 是 Kubernetes 控制平面的核心组件之一,负责处理 REST 请求并与集群中的其他组件通信。为了安全地访问 API Server,通常需要使用客户端证书认证方式。具体流程如下: - **准备客户端证书** 在 `/etc/kubernetes/pki` 目录下准备好 `apiserver-kubelet-client.crt` 和 `apiserver-kubelet-client.key` 文件作为客户端证书和私钥[^1]。 - **验证服务端身份** Kubelet 节点上会生成自己的服务器证书 `/var/lib/kubelet/pki/kubelet.crt` 和密钥文件 `/var/lib/kubelet/pki/kubelet.key`,这些文件用于证明节点的身份并建立 TLS 连接[^1]。 通过上述配置,可以实现从 API Server 到 Kubelet 的安全 HTTPS 请求。 --- #### 2. 使用 Python SDK 对接 Kubernetes Cluster API 除了命令行工具(如 kubectl),还可以借助编程语言库直接操作 Kubernetes API。Python 官方提供了 `kubernetes` 库支持这一功能[^3]。 下面是一个简单的例子展示如何通过 Python 访问 Kubernetes API 并获取 Pod 列表: ```python from kubernetes import client, config # 加载本地 kubeconfig 或者 InClusterConfig (适用于部署到 Kubernetes 内部的应用) try: config.load_incluster_config() except Exception as e: config.load_kube_config() v1 = client.CoreV1Api() print("Listing pods with their IPs:") ret = v1.list_pod_for_all_namespaces(watch=False) for i in ret.items: print(f"{i.status.pod_ip}\t{i.metadata.namespace}\t{i.metadata.name}") ``` 此脚本展示了加载配置、初始化 Core V1 API Client,并调用方法列举所有命名空间下的 Pods。 --- #### 3. Service 的工作原理及其接口通信配置 Service 是 Kubernetes 中用来定义一组逻辑上的 Pod 及其对外暴露的网络策略的一种抽象对象。它主要依靠标签选择器匹配目标 Pod 实现流量转发[^2]。 当创建一个 Service 后,Kubernetes 自动为其分配虚拟 IP 地址(ClusterIP)。如果希望外部能够访问该 Service,则可以通过 NodePort、LoadBalancer 类型或设置 ingress 来完成公开化过程[^2]。 以下是一份 YAML 示例描述了一个典型的服务声明: ```yaml apiVersion: v1 kind: Service metadata: name: my-service spec: selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 9376 type: LoadBalancer --- apiVersion: apps/v1 kind: Deployment metadata: name: my-deployment spec: replicas: 3 selector: matchLabels: app: MyApp template: metadata: labels: app: MyApp spec: containers: - name: nginx-container image: nginx:latest ports: - containerPort: 9376 ``` 在此配置中,Service 将请求分发给带有 Label `app=MyApp` 的三个副本实例;同时指定 Type 为 `LoadBalancer` 表明允许云提供商提供负载均衡能力以便于公网接入。 --- #### 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值