Kubernetes controllers, schedulers, and kubelets stay in-sync by streaming resource changes from the API server. The underlying transport is nothing exotic—just plain HTTP/1.1 kept alive with Transfer-Encoding: chunked. This article strips the problem down to the wire format and shows how the chunking mechanism is used to deliver watch events.
Chunked encoding refrseher
When a handler does not know the final body size it can send the response as a sequence of chunks. Each chunk is prefixed by its length in hexadecimal, terminated by \r\n, and followed by the payload and another \r\n. The stream ends with a zero-length chunk.
The following toy server demonstrates the idea:
func streamHandler(w http.ResponseWriter, r *http.Request) {
flusher, ok := w.(http.Flusher)
if !ok {
http.Error(w, "streaming unsupported", http.StatusInternalServerError)
return
}
w.Header().Set("Transfer-Encoding", "chunked")
w.Header().Set("Content-Type", "text/plain")
for i := 0; i < 3; i++ {
fmt.Fprintf(w, "tick %d\n", i)
flusher.Flush()
time.Sleep(time.Second)
}
}
A curl trace shows the raw bytes:
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: text/plain
7\r\ntick 0\n\r\n
7\r\ntick 1\n\r\n
7\r\ntick 2\n\r\n
0\r\n
The client simply reads until io.EOF; the HTTP library re-assembles the chunks transparently.
Watch endopint in action
Expose the API server locally:
$ kubectl proxy
Starting to serve on 127.0.0.1:8001
Open a watch on any object:
$ curl -N http://localhost:8001/api/v1/watch/namespaces/default/configmaps/sample
The first event arrives immediately:
{"type":"ADDED","object":{...}}
Now edit the ConfigMap; a second event appears:
{"type":"MODIFIED","object":{...}}
Both JSON documents are delivered as separate chunks. A packet capture confirms the framing:
Hypertext Transfer Protocol
HTTP/1.1 200 OK\r\n
Transfer-Encoding: chunked\r\n
Content-Type: application/json\r\n
\r\n
000003a8\r\n{"type":"ADDED",...}\r\n
000003ab\r\n{"type":"MODIFIED",...}\r\n
The hexadecimal numbers 3a8 and 3ab are the byte lengths of the two JSON payloads. The connection remains open; further changes will be emitted as additional chunks until the client closes the stream or the server times it out.
Thus, Kubernetes watch streams are ordinary HTTP chunked responses where each chunk is a complete watch event. No custom framing protocol is required—just the standard mechanism already built into every HTTP/1.1 stack.