更優(yōu)雅的 Kubernetes 集群事件度量方案
大家好,我是張晉濤。
群里有個(gè)小伙伴問(wèn)了我上圖中這個(gè)問(wèn)題,如何度量滾動(dòng)升級(jí)這個(gè)過(guò)程的時(shí)間。
這個(gè)問(wèn)題可以抽象為一種通用需求,適用于多種場(chǎng)景。
- 比如你是 Kubernetes 集群的管理員,你想度量這個(gè)過(guò)程中的耗時(shí),以便發(fā)現(xiàn)優(yōu)化點(diǎn);
- 比如你是在做 CI/CD ,你想通過(guò)度量這個(gè)過(guò)程的耗時(shí),來(lái)給出 CI/CD 過(guò)程的耗時(shí);
現(xiàn)有方案
Kubernetes 已經(jīng)提供了很方便的辦法來(lái)解決此問(wèn)題,也就是我回復(fù)中談到的,通過(guò) event 來(lái)度量即可。
比如,我們?cè)?K8S 中,創(chuàng)建一個(gè) deployment,看看這個(gè)過(guò)程中的 event 信息:
- ➜ ~ kubectl create ns moelove
- namespace/moelove created
- ➜ ~ kubectl -n moelove create deployment redis --image=ghcr.io/moelove/redis:alpine
- deployment.apps/redis created
- ➜ ~ kubectl -n moelove get deploy
- NAME READY UP-TO-DATE AVAILABLE AGE
- redis 1/1 1 1 16s
- ➜ ~ kubectl -n moelove get events
- LAST SEEN TYPE REASON OBJECT MESSAGE
- 27s Normal Scheduled pod/redis-687967dbc5-gsz5n Successfully assigned moelove/redis-687967dbc5-gsz5n to kind-control-plane
- 27s Normal Pulled pod/redis-687967dbc5-gsz5n Container image "ghcr.io/moelove/redis:alpine" already present on machine
- 27s Normal Created pod/redis-687967dbc5-gsz5n Created container redis
- 27s Normal Started pod/redis-687967dbc5-gsz5n Started container redis
- 27s Normal SuccessfulCreate replicaset/redis-687967dbc5 Created pod: redis-687967dbc5-gsz5n
- 27s Normal ScalingReplicaSet deployment/redis Scaled up replica set redis-687967dbc5 to 1
可以看到我們主要關(guān)注的一些事件均已經(jīng)有記錄了。但是總不能每次都通過(guò) kubectl 這么來(lái)看吧,有點(diǎn)浪費(fèi)時(shí)間。
我之前的一種做法是在 K8S 中寫了一個(gè)程序,持續(xù)的監(jiān)聽&收集 K8S 集群中的 event ,并將它寫入到我另外開發(fā)的一套系統(tǒng)中進(jìn)行存儲(chǔ)和可視化。但這種方法需要做額外的開發(fā)也并不普適。這里我來(lái)介紹另一個(gè)更優(yōu)的解決方案。
更優(yōu)雅的方案
K8S 中的這些事件,都對(duì)應(yīng)著我們的一個(gè)操作,比如上文中是創(chuàng)建了一個(gè) deployment ,它產(chǎn)生了幾個(gè) event , 包括 Scheduled
, Pulled
, Created
等。我們將其進(jìn)行抽象,是不是和我們做的鏈路追蹤(tracing)很像呢?
這里我們會(huì)用到一個(gè) CNCF 的畢業(yè)項(xiàng)目 Jaeger[1] ,在之前的K8S生態(tài)周報(bào) 中我有多次介紹它,Jaeger 是一款開源的,端對(duì)端的分布式 tracing 系統(tǒng)。不過(guò)本文重點(diǎn)不是介紹它,所以我們查看其文檔,快速的部署一個(gè) Jaeger 即可。另一個(gè) CNCF 的 sandbox 級(jí)別的項(xiàng)目是 OpenTelemetry[2] 是一個(gè)云原生軟件的可觀測(cè)框架,我們可以把它跟 Jaeger 結(jié)合起來(lái)使用。不過(guò)本文的重點(diǎn)不是介紹這倆項(xiàng)目,這里暫且略過(guò)。
接下來(lái)介紹我們這篇文章的用到的主要項(xiàng)目,是來(lái)自 Weaveworks 開源的一個(gè)項(xiàng)目,名叫 kspan ,它的主要做法就是將 K8S 中的 event 作為 trace 系統(tǒng)中的 span 進(jìn)行組織。
部署 kspan
- ---
- apiVersion: v1
- kind: ServiceAccount
- metadata:
- name: kspan
- ---
- apiVersion: rbac.authorization.k8s.io/v1
- kind: ClusterRoleBinding
- metadata:
- creationTimestamp: null
- name: kspan-admin
- roleRef:
- apiGroup: rbac.authorization.k8s.io
- kind: ClusterRole
- name: cluster-admin
- subjects:
- - kind: ServiceAccount
- name: kspan
- namespace: default
- ---
- apiVersion: v1
- kind: Pod
- metadata:
- labels:
- run: kspan
- name: kspan
- spec:
- containers:
- - image: docker.io/weaveworks/kspan:v0.0
- name: kspan
- resources: {}
- dnsPolicy: ClusterFirst
- restartPolicy: Always
- serviceAccountName: kspan
可以直接使用我這里提供的 YAML 進(jìn)行部署測(cè)試, 但注意上述配置文件別用在生產(chǎn)環(huán)境下, RBAC 權(quán)限需要修改 。
它默認(rèn)會(huì)使用 otlp-collector.default:55680
傳遞 span ,所有你需要確保有這個(gè) svc 存在。以上所有內(nèi)容部署完成后你大概會(huì)是這樣:、
- ➜ ~ kubectl get all
- NAME READY STATUS RESTARTS AGE
- pod/jaeger-76c84457fb-89s5v 1/1 Running 0 64m
- pod/kspan 1/1 Running 0 35m
- pod/otel-agent-sqlk6 1/1 Running 0 59m
- pod/otel-collector-69985cc444-bjb92 1/1 Running 0 56m
- NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
- service/jaeger-collector ClusterIP 10.96.47.12 <none> 14250/TCP 60m
- service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 39h
- service/otel-collector ClusterIP 10.96.231.43 <none> 4317/TCP,14250/TCP,14268/TCP,9411/TCP,8888/TCP 59m
- service/otlp-collector ClusterIP 10.96.79.181 <none> 55680/TCP 52m
- NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
- daemonset.apps/otel-agent 1 1 1 1 1 <none> 59m
- NAME READY UP-TO-DATE AVAILABLE AGE
- deployment.apps/jaeger 1/1 1 1 73m
- deployment.apps/otel-collector 1/1 1 1 59m
- NAME DESIRED CURRENT READY AGE
- replicaset.apps/jaeger-6f77c67c44 0 0 0 73m
- replicaset.apps/jaeger-76c84457fb 1 1 1 64m
- replicaset.apps/otel-collector-69985cc444 1 1 1 59m
上手實(shí)踐
這里我們先創(chuàng)建一個(gè) namespace 用于測(cè)試:
- ➜ ~ kubectl create ns moelove
- namespace/moelove created
創(chuàng)建一個(gè) Deployment
- ➜ ~ kubectl -n moelove create deployment redis --image=ghcr.io/moelove/redis:alpine
- deployment.apps/redis created
- ➜ ~ kubectl -n moelove get pods
- NAME READY STATUS RESTARTS AGE
- redis-687967dbc5-xj2zs 1/1 Running 0 10s
在 Jaeger 上進(jìn)行查看:
點(diǎn)開看詳細(xì)內(nèi)容
可以看到,和此創(chuàng)建 deploy 有關(guān)的 event 均被歸到了一起,在時(shí)間線上可以看到其耗時(shí)等詳細(xì)信息。
總結(jié)
本文介紹了如何結(jié)合 Jaeger 利用 tracing 的方式來(lái)采集 K8S 中的 events ,以便更好的掌握 K8S 集群中所有事件的耗時(shí)點(diǎn),更易于找到優(yōu)化的方向及度量結(jié)果。