6.4 k8s的informer机制

本节重点总结

  • 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 用来存储资源对象并自带索引功能的本地存储
相关推荐
探索云原生5 分钟前
开源 vGPU 方案 HAMi 原理分析 Part1:hami-device-plugin-nvidia 实现
云原生·kubernetes·gpu·vgpu
生活爱好者!3 小时前
NAS 部署白板工具,实现思维导图/画板/流程图自由
运维·docker·容器
亿牛云爬虫专家8 小时前
Kubernetes下的分布式采集系统设计与实战:趋势监测失效引发的架构进化
分布式·python·架构·kubernetes·爬虫代理·监测·采集
乌鸦不像写字台9 小时前
【docker部署】在服务器上使用docker
服务器·docker·容器
艾伦_耶格宇12 小时前
【docker】-1 docker简介
运维·docker·容器
IvanCodes13 小时前
二、Docker安装部署教程
docker·容器
Andy杨16 小时前
20250707-4-Kubernetes 集群部署、配置和验证-K8s基本资源概念初_笔记
笔记·容器·kubernetes
容器魔方19 小时前
中选名单出炉|18位学生入选开源之夏KubeEdge课题,欢迎加入!
云原生·容器·云计算
love530love20 小时前
Docker 稳定运行与存储优化全攻略(含可视化指南)
运维·人工智能·windows·docker·容器
人生匆匆21 小时前
docker进入启动失败的容器
运维·docker·容器