本节重点总结
-
informer机制的作用:
- Informer 机制在不依赖中间件的情况下保证消息的实时性,可靠性和顺序性
- 降低了k8s各个组件跟 Etcd 与 k8s API Server 的通信压力
- k8s 中的 informer 框架可以很方便的让每个子模块以及扩展程序拿到 k8s 中的资源信息。
-
informer机制的主要对象
- reflector 用来直接和 k8s api server 通信,内部实现了 listwatch 机制
- DeltaFIFO:更新队列
- informer 是我们要监听的资源的一个代码抽象
- Indexer:Client-go 用来存储资源对象并自带索引功能的本地存储
informer机制的作用
- k8s 中的 informer 框架可以很方便的让每个子模块以及扩展程序拿到 k8s 中的资源信息。
informer机制的作用
- Informer 机制在不依赖中间件的情况下保证消息的实时性,可靠性和顺序性
- 降低了k8s各个组件跟 Etcd 与 k8s API Server 的通信压力
informer机制的框架

架构图分为两部分
- 黄色图标是开发者需要自行开发的部分
- 而其它的部分是 client-go 已经提供的,直接使用即可
informer机制的主要对象
-
Reflector: reflector 用来直接和 k8s api server 通信,内部实现了 listwatch 机制
- listwatch 就是用来监听资源变化的
- 一个listwatch 只对应一个资源
- 这个资源可以是 k8s 中内部的资源也可以是自定义的资源
- 当收到资源变化时(创建、删除、修改)时会将资源放到 Delta Fifo 队列中
- Reflector 包会和 apiServer 建立长连接
-
DeltaFIFO:更新队列
- FIFO 就是一个队列,拥有队列基本方法(ADD,UPDATE,DELETE,LIST,POP,CLOSE 等)
- Delta 是一个资源对象存储,保存存储对象的消费类型,比如 Added,Updated,Deleted,Sync 等
-
informer:informer 是我们要监听的资源的一个代码抽象
- 能够将 delta filo 队列中的数据弹出
- 然后保存到本地缓存indexer中,也就是图中的步骤5
- 同时将数据分发到自定义controller 中进行事件处理也就是图中的步骤6
-
Indexer:Client-go 用来存储资源对象并自带索引功能的本地存储
- Reflector 从 DeltaFIFO 中将消费出来的资源对象存储到 Indexer
- Indexer 与 Etcd 集群中的数据完全保持一致
- 从而 client-go 可以本地读取,减少 Kubernetes API 和 Etcd 集群的压力
使用informer代码
新建项目k8s-informer
shell
go mod init k8s-informer
informer.go
go
package main
import (
"context"
"flag"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/homedir"
"k8s.io/klog/v2"
"log"
"os"
"os/signal"
"path/filepath"
"syscall"
"time"
)
func main() {
var kubeconfig *string
//如果是windows,那么会读取C:\Users\xxx\.kube\config 下面的配置文件
//如果是linux,那么会读取~/.kube/config下面的配置文件
if home := homedir.HomeDir(); home != "" {
kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
} else {
kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
}
flag.Parse()
config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
if err != nil {
panic(err)
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err)
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// 监听信号
ch := make(chan os.Signal, 1)
signal.Notify(ch, os.Interrupt, syscall.SIGTERM)
go func() {
<-ch
klog.Info("Received termination, signaling shutdown")
cancel()
}()
//表示每分钟进行一次resync,resync会周期性地执行List操作
sharedInformers := informers.NewSharedInformerFactory(clientset, time.Minute)
informer := sharedInformers.Core().V1().Pods().Informer()
informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
mObj := obj.(v1.Object)
log.Printf("New Pod Added to Store: %s", mObj.GetName())
},
UpdateFunc: func(oldObj, newObj interface{}) {
oObj := oldObj.(v1.Object)
nObj := newObj.(v1.Object)
log.Printf("%s Pod Updated to %s", oObj.GetName(), nObj.GetName())
},
DeleteFunc: func(obj interface{}) {
mObj := obj.(v1.Object)
log.Printf("Pod Deleted from Store: %s", mObj.GetName())
},
})
informer.Run(ctx.Done())
}
解读一下
- 先通过kubeconfig创建 restclient.Config
go
config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
- 然后创建和apiserver交互的 clientset
go
clientset, err := kubernetes.NewForConfig(config)
- 监听退出信号,并创建退出的context
go
// 监听信号
ch := make(chan os.Signal, 1)
signal.Notify(ch, os.Interrupt, syscall.SIGTERM)
go func() {
<-ch
klog.Info("Received termination, signaling shutdown")
cancel()
}()
- 使用SharedInformerFactory创建sharedInformer,传入的Resync时间是1分钟,代表1分钟执行list操作
- 然后创建pod资源的informer
go
//表示每分钟进行一次resync,resync会周期性地执行List操作
sharedInformers := informers.NewSharedInformerFactory(clientset, time.Minute)
informer := sharedInformers.Core().V1().Pods().Informer()
- 添加EventHandler,并执行
- AddFunc代表新的资源创建时的回调
- UpdateFunc代表资源更新时的回调
- DeleteFunc代表资源删除时的回调
- 代码如下
go
informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
mObj := obj.(v1.Object)
log.Printf("New Pod Added to Store: %s", mObj.GetName())
},
UpdateFunc: func(oldObj, newObj interface{}) {
oObj := oldObj.(v1.Object)
nObj := newObj.(v1.Object)
log.Printf("%s Pod Updated to %s", oObj.GetName(), nObj.GetName())
},
DeleteFunc: func(obj interface{}) {
mObj := obj.(v1.Object)
log.Printf("Pod Deleted from Store: %s", mObj.GetName())
},
})
informer.Run(ctx.Done())
编译执行
go
go build
./informer
效果查看
执行后拉取全量的结果
shell
[root@k8s-master01 k8s-informer]# ./informer
2021/09/16 11:32:05 New Pod Added to Store: kube-proxy-kc258
2021/09/16 11:32:05 New Pod Added to Store: k8s-mon-daemonset-z6sfw
2021/09/16 11:32:05 New Pod Added to Store: blackbox-exporter-55c457d5fb-rzn7l
2021/09/16 11:32:05 New Pod Added to Store: grafana-d5d85bcd6-f74ch
2021/09/16 11:32:05 New Pod Added to Store: calico-kube-controllers-854b9dcf89-gct84
2021/09/16 11:32:05 New Pod Added to Store: prometheus-0
2021/09/16 11:32:05 New Pod Added to Store: etcd-k8s-master01
2021/09/16 11:32:05 New Pod Added to Store: test-alpine-inject-01
2021/09/16 11:32:05 New Pod Added to Store: calico-node-8pwz5
2021/09/16 11:32:05 New Pod Added to Store: ink8s-pod-metrics-deployment-85d9795d6-95lsp
2021/09/16 11:32:05 New Pod Added to Store: prometheus-k8s-0
2021/09/16 11:32:05 New Pod Added to Store: tigera-operator-cf6b69777-mlgk9
2021/09/16 11:32:05 New Pod Added to Store: k8s-mon-deployment-6d7d58bdc8-rxj42
2021/09/16 11:32:05 New Pod Added to Store: sleep-557747455f-w79wf
2021/09/16 11:32:05 New Pod Added to Store: nginx-pod-failed-to-scheduler
2021/09/16 11:32:05 New Pod Added to Store: grafana-d5d85bcd6-l44mx
2021/09/16 11:32:05 New Pod Added to Store: prometheus-operator-54c4665c6b-7j9jr
2021/09/16 11:32:05 New Pod Added to Store: kube-state-metrics-564668c858-dnmnh
2021/09/16 11:32:05 New Pod Added to Store: prometheus-operator-7775c66ccf-hkmpr
2021/09/16 11:32:05 New Pod Added to Store: alertmanager-main-2
2021/09/16 11:32:05 New Pod Added to Store: grafana-9df57cdc4-tf6qj
2021/09/16 11:32:05 New Pod Added to Store: node-exporter-7rqfg
2021/09/16 11:32:05 New Pod Added to Store: prometheus-adapter-59df95d9f5-glwk7
2021/09/16 11:32:05 New Pod Added to Store: calico-node-58m74
2021/09/16 11:32:05 New Pod Added to Store: ingress-nginx-controller-6cb6fdd64b-p4s65
2021/09/16 11:32:05 New Pod Added to Store: alpine01
2021/09/16 11:32:05 New Pod Added to Store: alpine33
2021/09/16 11:32:05 New Pod Added to Store: kube-proxy-zx87g
2021/09/16 11:32:05 New Pod Added to Store: alertmanager-main-0
2021/09/16 11:32:05 New Pod Added to Store: coredns-68b9d7b887-ckwgh
2021/09/16 11:32:05 New Pod Added to Store: coredns-68b9d7b887-vfmft
2021/09/16 11:32:05 New Pod Added to Store: kube-scheduler-k8s-master01
2021/09/16 11:32:05 New Pod Added to Store: metrics-server-7dbf6c4558-zwp5m
2021/09/16 11:32:05 New Pod Added to Store: alertmanager-main-1
2021/09/16 11:32:05 New Pod Added to Store: kube-state-metrics-76f6cb7996-27dc2
2021/09/16 11:32:05 New Pod Added to Store: nginx-pod
2021/09/16 11:32:05 New Pod Added to Store: calico-typha-56958ddd97-9zpd2
2021/09/16 11:32:05 New Pod Added to Store: node-exporter-b5pnx
2021/09/16 11:32:05 New Pod Added to Store: kube-controller-manager-k8s-master01
2021/09/16 11:32:05 New Pod Added to Store: prometheus-k8s-1
2021/09/16 11:32:05 New Pod Added to Store: prometheus-adapter-59df95d9f5-28n4c
2021/09/16 11:32:05 New Pod Added to Store: sidecar-injector-webhook-deployment-5cd7466c9f-ns7f6
2021/09/16 11:32:05 New Pod Added to Store: test-alpine-inject-02
2021/09/16 11:32:05 New Pod Added to Store: nginx-pod-test
2021/09/16 11:32:05 New Pod Added to Store: calico-typha-56958ddd97-gnt8k
2021/09/16 11:32:05 New Pod Added to Store: kube-apiserver-k8s-master01
新增一个pod
shell
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod-for-informer01
spec:
containers:
- name: nginx
image: nginx:1.8
EOF
- informer那边
shell
2021/09/16 11:34:47 New Pod Added to Store: nginx-pod-for-informer01
2021/09/16 11:34:47 nginx-pod-for-informer01 Pod Updated to nginx-pod-for-informer01
2021/09/16 11:34:47 nginx-pod-for-informer01 Pod Updated to nginx-pod-for-informer01
2021/09/16 11:34:47 nginx-pod-for-informer01 Pod Updated to nginx-pod-for-informer01
2021/09/16 11:34:48 nginx-pod-for-informer01 Pod Updated to nginx-pod-for-informer01
修改刚才创建的pod,添加标签信息
- pod的yaml
shell
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod-for-informer01
labels:
region: bj
spec:
containers:
- name: nginx
image: nginx:1.8
EOF
- informer的update 日志
shell
2021/09/16 11:37:00 nginx-pod-for-informer01 Pod Updated to nginx-pod-for-informer01
每次的resync也会触发 update
本节重点总结 :
-
informer机制的作用 :
- k8s 中的 informer 框架可以很方便的让每个子模块以及扩展程序拿到 k8s 中的资源信息。
-
informer机制的作用:
- Informer 机制在不依赖中间件的情况下保证消息的实时性,可靠性和顺序性
- 降低了k8s各个组件跟 Etcd 与 k8s API Server 的通信压力
-
informer机制的主要对象
- reflector 用来直接和 k8s api server 通信,内部实现了 listwatch 机制
- DeltaFIFO:更新队列
- informer 是我们要监听的资源的一个代码抽象
- Indexer:Client-go 用来存储资源对象并自带索引功能的本地存储