开发 k8s 管理平台 - k8sailor 13. 使用 k8s informer 订阅集群事件

简介: 开发 k8s 管理平台 - k8sailor 13. 使用 k8s informer 订阅集群事件

开发 k8s 管理平台 - k8sailor 13. 使用 k8s informer 订阅集群事件

原文地址: https://tangx.in/posts/books/k8sailor/chapter02/13-k8s-informer/
tag: https://github.com/tangx/k8sailor/tree/feat/13-k8s-informer

informer-design.jpeg

从应用层面来说, 创建 informer 并启动之后就与 k8s cluster 创建了一个长链接并订阅了 某个资源 Resource 的变化。

至于订阅后得到的数据要怎么用完全取决于订阅者的业务设计。

Shared Informer Factory 共享机制

Informer 又称为 Shared Informer,表明是可以共享使用的,在使用 client-go 写代码时,若同一资源的 Informer 被实例化太多次,每个 Informer 使用一个 Reflector,会运行过多的相同 ListAndWatch(即图中的第一步),太多重复的序列化和反序列化会导致 k8s API Server 负载过重。

而 Shared Informer 通过对同一类资源 Informer 共享一个 Reflector 可以节约很多资源,这通过 map 数据结构即可实现这样一个共享 Informer 机制。

// Start initializes all requested informers.
func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {
    f.lock.Lock()
    defer f.lock.Unlock()

    for informerType, informer := range f.informers {
        if !f.startedInformers[informerType] {
            go informer.Run(stopCh)
            f.startedInformers[informerType] = true
        }
    }
}
  1. informer.Run(stopCh) : informer 在启动的时候需要传入一个 通知停止的 channel stopCh <-chan struct{}。 因此用户是可以 主动 关闭 informer 通道的。
  2. 所有 informer 都是通过 go 协程跑在后台的。

Shared Informer Factory 注册 infomers

上面提到, Shared Informer Factory 一个很重要的作用就是

  1. 管理注册 Informer
  2. 防止相同类型的 Infomer 重复注册

/pkg/confk8s/informer.go , 在注册 Informer 的时候其实很还是很方便的。

// WithEventHandlers 注册 handler
func (inf *Informer) WithEventHandlers(handlers ...InformerEventHandler) *Informer {
    for _, handler := range handlers {
        kind := handler.InformerKind()
        switch kind {
        case "deployment":
            inf.factory.Apps().V1().Deployments().Informer().AddEventHandler(handler)
        case "pod":
            inf.factory.Core().V1().Pods().Informer().AddEventHandler(handler)
        }
    }

    return inf
}

informer event handler

所有的 informer handler 满足接口

type ResourceEventHandler interface {
    OnAdd(obj interface{})
    OnUpdate(oldObj, newObj interface{})
    OnDelete(obj interface{})
}

即处理 OnAdd, OnUpdate, OnDelete 三种事件。

项目案例

例如在本项目中

k8sailor-with-informer.png

在本地创建了一个名为 k8scache 的存储空间, 使用 k8s informer 订阅了 Deployment 的数据并保存到了 本地 /internal/k8scache/deployment.go 中的 DeploymentCache 对象中。 并对外提供 deployment 的查询功能。

由于项目本地都存的是数据副本,只提供了 查询 namespace 下的所有数据根据 name 查询某个 deployment 这样简单的功能。 原本 k8s 通过 label 查询 这样 好用 功能, 目前也就无法再提供了。

自此, biz 代码逻辑中与 Deployment 相关的查询使用的数据源都修改为 k8scache

// GetDeploymentByName 通过名称获取 deployment
func GetDeploymentByName(ctx context.Context, input GetDeploymentByNameInput) (*Deployment, error) {

    /* k8s api 返回的数据 */
    // v1dep, err := k8sdao.GetDeploymentByName(ctx, input.Namespace, input.Name)

    /* 使用本地的 k8scache */
    v1dep, err := k8scache.DepTank.GetDeploymentByName(ctx, input.Namespace, input.Name)
    if err != nil {
        return nil, err
    }

    dep := extractDeployment(*v1dep)
    return dep, nil
}

informer 启动

上面已经说了, 使用 informer 创建的是一个独立 应用/模块, 可以作为一个 模块存在于应用内部, 也可以作为一个 独立的应用

无论是怎么定义的, informer 的启动和关闭都 必须要 独立控制。

本项目中是作为一个模块, 在启动 http server 之前进行启动。 /cmd/k8sailor/cmd/httpserver.go

var cmdHttpserver = &cobra.Command{
    Use:  "httpserver",
    Long: "启动 web 服务器",
    Run: func(cmd *cobra.Command, args []string) {
        // 启动 informer
        runInformer()

        // 启动服务
        runHttpserver()
    },
}

func runInformer() {

    clientset := global.KubeClient.Client()
    informer := global.KubeInformer.WithClientset(clientset)

    k8scache.RegisterHandlers(informer)

    informer.Start()
}

分层后代码实现的问题

其实上述 切换数据源 的实现是有问题的。

数据源的切换不应该是在 biz 中完成, 而是应该在 k8sdao 中进行。

  1. 从逻辑上来说 k8scachek8s 是一层的, 都是数据的提供者。
  2. DAO 的含义是 数据访问对象 data access object, 其职责就是对 来自不同数据源的相同数据 执行 适合自身业务逻辑的抽象和封装

扩展阅读

深入理解 k8s informer: https://cloudnative.to/blog/client-go-informer-source-code/
相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务&nbsp;ACK 容器服务&nbsp;Kubernetes&nbsp;版(简称&nbsp;ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
相关文章
|
11天前
|
运维 Kubernetes 监控
Kubernetes 集群的持续性能优化实践
【4月更文挑战第26天】 在动态且不断增长的云计算环境中,维护高性能的 Kubernetes 集群是一个挑战。本文将探讨一系列实用的策略和工具,旨在帮助运维专家监控、分析和优化 Kubernetes 集群的性能。我们将讨论资源分配的最佳实践,包括 CPU 和内存管理,以及集群规模调整的策略。此外,文中还将介绍延迟和吞吐量的重要性,并提供日志和监控工具的使用技巧,以实现持续改进的目标。
|
2天前
|
Kubernetes Cloud Native Go
Golang深入浅出之-Go语言中的云原生开发:Kubernetes与Docker
【5月更文挑战第5天】本文探讨了Go语言在云原生开发中的应用,特别是在Kubernetes和Docker中的使用。Docker利用Go语言的性能和跨平台能力编写Dockerfile和构建镜像。Kubernetes,主要由Go语言编写,提供了方便的客户端库与集群交互。文章列举了Dockerfile编写、Kubernetes资源定义和服务发现的常见问题及解决方案,并给出了Go语言构建Docker镜像和与Kubernetes交互的代码示例。通过掌握这些技巧,开发者能更高效地进行云原生应用开发。
36 1
|
3天前
|
运维 监控 Kubernetes
Kubernetes 集群的监控与维护策略
【5月更文挑战第4天】 在当今微服务架构盛行的时代,容器化技术已成为软件开发和部署的标准实践。Kubernetes 作为一个开源的容器编排平台,因其强大的功能和灵活性而广受欢迎。然而,随着 Kubernetes 集群规模的扩大,集群的监控和维护变得日益复杂。本文将探讨 Kubernetes 集群监控的重要性,分析常见的监控工具,并提出一套有效的集群维护策略,以帮助运维人员确保集群的健康运行和高可用性。
32 10
|
4天前
|
存储 运维 监控
Kubernetes 集群的持续监控与优化策略
【5月更文挑战第3天】在微服务架构和容器化部署日益普及的背景下,Kubernetes 已成为众多企业的首选容器编排平台。然而,随着集群规模的增长和业务复杂度的提升,有效的集群监控和性能优化成为确保系统稳定性和提升资源利用率的关键。本文将深入探讨针对 Kubernetes 集群的监控工具选择、监控指标的重要性解读以及基于数据驱动的性能优化实践,为运维人员提供一套系统的持续监控与优化策略。
|
7天前
|
运维 Kubernetes 监控
Kubernetes 集群的监控与维护策略
【4月更文挑战第30天】 在现代云计算环境中,容器化技术已成为应用程序部署和管理的重要手段。其中,Kubernetes 作为一个开源的容器编排平台,以其强大的功能和灵活性受到广泛欢迎。然而,随之而来的是对 Kubernetes 集群监控和维护的复杂性增加。本文将探讨针对 Kubernetes 集群的监控策略和维护技巧,旨在帮助运维人员确保集群的稳定性和高效性。通过分析常见的性能瓶颈、故障诊断方法以及自动化维护工具的应用,我们将提供一套实用的解决方案,以优化 Kubernetes 环境的性能和可靠性。
|
7天前
|
运维 Kubernetes 监控
Kubernetes集群的持续性能优化策略
【4月更文挑战第30天】 在动态且不断扩展的云计算环境中,保持应用性能的稳定性是一个持续的挑战。本文将探讨针对Kubernetes集群的持续性能优化策略,旨在为运维工程师提供一套系统化的性能调优框架。通过分析集群监控数据,我们将讨论如何诊断常见问题、实施有效的资源管理和调度策略,以及采用自动化工具来简化这一过程。
|
7天前
|
Prometheus 监控 Kubernetes
Kubernetes 集群的监控与日志管理策略
【4月更文挑战第30天】 在微服务架构日益普及的当下,容器化技术与编排工具如Kubernetes成为了运维领域的重要话题。有效的监控和日志管理对于保障系统的高可用性和故障快速定位至关重要。本文将探讨在Kubernetes环境中实施监控和日志管理的最佳实践,包括选用合适的工具、部署策略以及如何整合这些工具来提供端到端的可见性。我们将重点讨论Prometheus监控解决方案和EFK(Elasticsearch, Fluentd, Kibana)日志管理堆栈,分析其在Kubernetes集群中的应用,并给出优化建议。
|
8天前
|
SQL Kubernetes 调度
【一文看懂】部署Kubernetes模式的Havenask集群
本次分享内容为havenask的kubernetes模式部署,由下面2个部分组成(部署Kubernetes模式Havenask集群、 Kubernetes模式相关问题排查),希望可以帮助大家更好了解和使用Havenask。
16 1
|
8天前
|
Kubernetes 网络协议 Python
一文教会你,如何通过kubeadm,在生产环境部署K8S高可用集群(二)
一文教会你,如何通过kubeadm,在生产环境部署K8S高可用集群(二)
|
9天前
|
Kubernetes 应用服务中间件 开发工具
一文教会你,如何通过kubeadm,在生产环境部署K8S高可用集群(一)
一文教会你,如何通过kubeadm,在生产环境部署K8S高可用集群(一)

推荐镜像

更多