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 用来存储资源对象并自带索引功能的本地存储
相关推荐
Libby博仙24 分钟前
docker 改了镜像源为阿里云,还是下载失败
阿里云·docker·容器
钗头风1 小时前
3.Docker常用命令
运维·docker·容器
ITPUB-微风3 小时前
网易严选DevOps实践:从传统到云原生的演进
运维·云原生·devops
桂月二二3 小时前
基于eBPF的全栈可观测性系统:重新定义云原生环境诊断范式
云原生
ITPUB-微风4 小时前
云原生数据抽象与弹性加速:Fluid开源系统的技术解析
云原生·开源
爬山算法4 小时前
Zookeeper(58)如何在Zookeeper中实现分布式锁?
分布式·zookeeper·云原生
圣心4 小时前
Ollama Docker 镜像部署
运维·docker·容器
Karoku0665 小时前
【CI/CD】Jenkinsfile管理+参数化构建+邮件通知以及Jenkins + SonarQube 代码审查
运维·ci/cd·容器·kubernetes·jenkins·rancher
转身後 默落5 小时前
06.Docker 镜像制作和管理
java·docker·容器
明明跟你说过6 小时前
【Kubernetes】常用命令全解析:从入门到实战(下)
运维·云原生·容器·kubernetes·k8s