从Helm到 Operator:Kubernetes应用管理的进化

news2024/12/29 11:09:20

🧰Helm 的作用

在开始前需要先对 kubernetes  Operator 有个简单的认识。

以为我们在编写部署一些简单 Deployment 的时候只需要自己编写一个 yaml 文件然后 kubectl apply 即可。

apiVersion: apps/v1  
kind: Deployment  
metadata:  
  labels:  
    app: k8s-combat  
  name: k8s-combat  
spec:  
  replicas: 1  
  selector:  
    matchLabels:  
      app: k8s-combat  
  template:  
    metadata:  
      labels:  
        app: k8s-combat  
    spec:  
      containers:  
        - name: k8s-combat  
          image: crossoverjie/k8s-combat:v1  
          imagePullPolicy: Always  
          resources:  
            limits:  
              cpu: "1"  
              memory: 300Mi  
            requests:  
              cpu: "0.1"  
              memory: 30Mi
kubectl apply -f deployment.yaml

这对于一些并不复杂的项目来说完全够用了,但组件一多就比较麻烦了。

1cdd7d815f216c0223308038cebbd62d.png这里以 Apache Pulsar 为例:它的核心组件有:

  • Broker

  • Proxy

  • Zookeeper

  • Bookkeeper

  • Prometheus(可选)

  • Grafana(可选) 等组件,每个组件的启动还有这依赖关系。

必须需要等 Zookeeper 和 Bookkeeper 启动之后才能将流量放进来。

此时如何还继续使用 yaml 文件一个个部署就会非常繁琐,好在社区有提供 Helm 一键安装程序,使用它我们只需要在一个同意的 yaml 里简单的配置一些组件,配置就可以由 helm 来部署整个复杂的 Pulsar 系统。

components:  
  # zookeeper  
  zookeeper: true  
  # bookkeeper  
  bookkeeper: true  
  # bookkeeper - autorecovery  
  autorecovery: true  
  # broker  
  broker: true  
  # functions  
  functions: false  
  # proxy  
  proxy: true  
  # toolset  
  toolset: true  
  # pulsar manager  
  pulsar_manager: false  
monitoring:  
  # monitoring - prometheus  
  prometheus: true  
  # monitoring - grafana  
  grafana: true  
  # monitoring - node_exporter  
  node_exporter: true  
  # alerting - alert-manager  
  alert_manager: false

比如在 helm 的 yaml 中我们可以选择使用哪些 components,以及是否启用监控组件。

最后直接使用这个文件进行安装:

helm install pulsar apache/pulsar \
 --values charts/pulsar/values.yaml \
 --set namespace=pulsar \
    --set initialize=true

它就会自动生成各个组件的 yaml 文件,然后统一执行。

所以 helm 的本质上和 kubectl apply yaml 一样的,只是我们在定义 value.yaml 时帮我们处理了许多不需要用户低频修改的参数。

我们可以使用 helm 将要执行的 yaml 输出后人工审核

helm install pulsar apache/pulsar --dry-run --debug > debug.yaml

🤔Operator 是什么

💔Helm 的痛点

Helm 虽然可以帮我们部署或者升级一个大型应用,但他却没法帮我们运维这个应用。

举个例子:比如我希望当 Pulsar Broker 的流量或者内存达到某个阈值后就指定扩容 Broker,闲时再自动回收。

或者某个 Bookkeeper 的磁盘使用率达到阈值后可以自动扩容磁盘,这些仅仅使用 Helm 时都是无法实现的。

以上这些需求我们目前也是通过监控系统发出报警,然后再由人工处理。

其中最大的痛点就是进行升级:

  • 升级ZK

  • 关闭auto recovery

  • 升级Bookkeeper

  • 升级Broker

  • 升级Proxy

  • 开启auto recovery

因为每次升级是有先后顺序的,需要依次观察每个组件运行是否正常才能往后操作。

如果有 Operator 理性情况下下我们只需要更新一下镜像版本,它就可以自动执行以上的所有步骤最后将集群升级完毕。

所以相对于 Helm 来说 Operator 是可以站在一个更高的视角俯视整个应用系统,它能发现系统哪个地方需要它从而直接修复。

💎CRD(Custom Resource Definitions)

而提到 Operator 那就不得不提到 CRD(Custom Resource Definitions)翻译过来就是自定义资源。

这是 kubernetes 提供的一个 API 扩展机制,类似于内置的 Deployment/StatefulSet/Services 资源,CRD 是一种自定义的资源。

这里以我们常用的 prometheus-operatorVictoriaMetrics-operator 为例:

Prometheus:

  • **Prometheus**:用于定义 Prometheus 的 Deployment

  • **Alertmanager**:用于定义 Alertmanager

  • **ScrapeConfig**:用于定会抓取规则

apiVersion: monitoring.coreos.com/v1alpha1
kind: ScrapeConfig
metadata:
  name: static-config
  namespace: my-namespace
  labels:
    prometheus: system-monitoring-prometheus
spec:
  staticConfigs:
    - labels:
        job: prometheus
      targets:
        - prometheus.demo.do.prometheus.io:9090

使用时的一个很大区别就是资源的 kind: ScrapeConfig 为自定义的类型。

VictoriaMetrics 的 CRD:

  • VMPodScrape:Pod 的抓取规则

  • VMCluster:配置 VM 集群

  • VMAlert:配置 VM 的告警规则

  • 等等

# vmcluster.yaml
apiVersion: operator.victoriametrics.com/v1beta1
kind: VMCluster
metadata:
  name: demo
spec:
  retentionPeriod: "1"
  replicationFactor: 2
  vmstorage:
    replicaCount: 2
    storageDataPath: "/vm-data"
    storage:
      volumeClaimTemplate:
        spec:
          resources:
            requests:
              storage: "10Gi"
    resources:
      limits:
        cpu: "1"
        memory: "1Gi"
  vmselect:
    replicaCount: 2
    cacheMountPath: "/select-cache"
    storage:
      volumeClaimTemplate:
        spec:
          resources:
            requests:
              storage: "1Gi"
    resources:
      limits:
        cpu: "1"
        memory: "1Gi"
      requests:
        cpu: "0.5"
        memory: "500Mi"
  vminsert:
    replicaCount: 2

以上是用于创建一个 VM 集群的 CRD 资源,应用之后就会自动创建一个集群。

Operator 原理

78ddb8ade8e195145eb54915aef8ddc0.pngOperator 通常是运行在 kubernetes API server 的 webhook 之上,简单来说就是在一些内置资源的关键节点 API-server 会调用我们注册的一个 webhook,在这个 webhook 中我们根据我们的 CRD 做一些自定义的操作。

理论上我们可以使用任何语言都可以写 Operator,只需要能处理 api-server 的回调即可。

只是 Go 语言有很多成熟的工具,比如常用的 kubebuilder 和 operator-sdk.

他们内置了许多命令行工具,可以帮我们节省需要工作量。

这里以 operator-sdk 为例:

$ operator-sdk create webhook --group cache --version v1alpha1 --kind Memcached --defaulting --programmatic-validation

会直接帮我们创建好一个标准的 operator 项目:

├── Dockerfile
├── Makefile
├── PROJECT
├── api
│   └── v1alpha1
│       ├── memcached_webhook.go
│       ├── webhook_suite_test.go
├── config
│   ├── certmanager
│   │   ├── certificate.yaml
│   │   ├── kustomization.yaml
│   │   └── kustomizeconfig.yaml
│   ├── default
│   │   ├── manager_webhook_patch.yaml
│   │   └── webhookcainjection_patch.yaml
│   └── webhook
│       ├── kustomization.yaml
│       ├── kustomizeconfig.yaml
│       └── service.yaml
├── go.mod
├── go.sum
└── main.go

其中 Makefile 中包含了开发过程中常用的工具链(包括根据声明的结构体自动生成 CRD 资源、部署k8s 环境测试等等)、Dockerfile 等等。

这样我们就只需要专注于开发业务逻辑即可。

因为我前段时间给 https://github.com/open-telemetry/opentelemetry-operator 贡献过两个 feature,所以就以这个 Operator 为例:

它有一个 CRD: kind: Instrumentation,在这个 CRD 中可以将 OpenTelemetry 的 agent 注入到应用中。

apiVersion: opentelemetry.io/v1alpha1  
kind: Instrumentation  
metadata:  
  name: instrumentation-test-order
  namespace: test  
spec:  
  env:  
    - name: OTEL_SERVICE_NAME  
      value: order
  selector:  
    matchLabels:  
      app: order  
  java:  
    image: autoinstrumentation-java:2.4.0-release  
    extensions:  
      - image: autoinstrumentation-java:2.4.0-release  
        dir: /extensions  
  
    env:  
      - name: OTEL_RESOURCE_ATTRIBUTES  
        value: service.name=order  
      - name: OTEL_INSTRUMENTATION_MESSAGING_EXPERIMENTAL_RECEIVE_TELEMETRY_ENABLED  
        value: "true"  
      - name: OTEL_TRACES_EXPORTER  
        value: otlp  
      - name: OTEL_METRICS_EXPORTER  
        value: otlp  
      - name: OTEL_LOGS_EXPORTER  
        value: none  
      - name: OTEL_EXPORTER_OTLP_ENDPOINT  
        value: http://open-telemetry-opentelemetry-collector.otel.svc.cluster.local:4317  
      - name: OTEL_EXPORTER_OTLP_COMPRESSION  
        value: gzip  
      - name: OTEL_EXPERIMENTAL_EXPORTER_OTLP_RETRY_ENABLED  
        value: "true"

它的运行规则是当我们的 Pod 在启动过程中会判断 Pod 的注解中是否开启了注入 OpenTelemetry 的配置。

如果开启则会将我们在 CRD 中自定义的镜像里的 javaagent 复制到业务容器中,同时会将下面的那些环境变量也一起加入的业务容器中。

要达到这样的效果就需要我们注册一个回调 endpoint。

mgr.GetWebhookServer().Register("/mutate-v1-pod", &webhook.Admission{  
    Handler: podmutation.NewWebhookHandler(cfg, ctrl.Log.WithName("pod-webhook"), decoder, mgr.GetClient(),  
       []podmutation.PodMutator{  
          sidecar.NewMutator(logger, cfg, mgr.GetClient()),  
          instrumentation.NewMutator(logger, mgr.GetClient(), mgr.GetEventRecorderFor("opentelemetry-operator"), cfg),  
       }),})

当 Pod 创建或有新的变更请求时就会回调我们的接口。

func (pm *instPodMutator) Mutate(ctx context.Context, ns corev1.Namespace, pod corev1.Pod) (corev1.Pod, error) {  
    logger := pm.Logger.WithValues("namespace", pod.Namespace, "name", pod.Name)
    }

在这个接口中我们就可以拿到 Pod 的信息,然后再获取 CRD Instrumentation 做我们的业务逻辑。

var otelInsts v1alpha1.InstrumentationList  
if err := pm.Client.List(ctx, &otelInsts, client.InNamespace(ns.Name)); err != nil {  
    return nil, err  
}


// 从 CRD 中将数据复制到业务容器中。
pod.Spec.InitContainers = append(pod.Spec.InitContainers, corev1.Container{
 Name:      javaInitContainerName,
 Image:     javaSpec.Image,
 Command:   []string{"cp", "/javaagent.jar", javaInstrMountPath + "/javaagent.jar"},
 Resources: javaSpec.Resources,
 VolumeMounts: []corev1.VolumeMount{{
  Name:      javaVolumeName,
  MountPath: javaInstrMountPath,
 }},
})

for i, extension := range javaSpec.Extensions {
 pod.Spec.InitContainers = append(pod.Spec.InitContainers, corev1.Container{
  Name:      initContainerName + fmt.Sprintf("-extension-%d", i),
  Image:     extension.Image,
  Command:   []string{"cp", "-r", extension.Dir + "/.", javaInstrMountPath + "/extensions"},
  Resources: javaSpec.Resources,
  VolumeMounts: []corev1.VolumeMount{{
   Name:      javaVolumeName,
   MountPath: javaInstrMountPath,
  }},
 })
}

不过需要注意的是想要在测试环境中测试 operator 是需要安装一个 cert-manage,这样 webhook 才能正常的回调。

009ba0d3f35f11e361efc7a9bd0b8551.png要使得 CRD 生效,我们还得先将 CRD 安装进 kubernetes 集群中,不过这些 operator-sdk 这类根据已经考虑周到了。

我们只需要定义好 CRD 的结构体:b39292b1a0405ed1763b1ffbc8d34f4b.png

然后使用 Makefile 中的工具 make bundle 就会自动将结构体转换为 CRD。

参考链接:

  • https://github.com/VictoriaMetrics/operator

  • https://github.com/prometheus-operator/prometheus-operator

    往期推荐

    如何找到并快速上手一个开源项目

    OpenTelemetry 深度定制:跨服务追踪的实战技巧

    从 Prometheus 到 OpenTelemetry: 指标监控的演进与实践

    从 Dapper 到 OpenTelemetry:分布式追踪的演进之旅

    实操 OpenTelemetry:通过 Demo 掌握微服务监控的艺术

    ab8c94efd5579def0dba183d4ba2f9c4.gif

    点分享

    9b785d96af38ff71a2611c38331dd390.gif

    点收藏

    fb8ca8057dc45a8bdd311d75971abaae.gif

    点点赞

    5147ebc5cc405c49bb6638c7c0d7a4c8.gif

    点在看

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1912690.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Camera Raw:常规工具

在 Camera Raw 窗口右下角提供了四个常用的工具,它们分别是:缩放工具、抓手工具、切换取样器叠加以及切换网格叠加工具。 ◆ ◆ ◆ 缩放工具 Zoom Tool 用于放大或缩小预览图像,便于查看和编辑细节。 快捷键:Z 1、双击“缩放工具…

jvm 06 对象内存结构,指针压缩,调优

01 内存布局 mark word 32bit 4B 64bit 8B 类型指针 klass pointer 开启指针压缩 4B 关闭指针压缩 8B 数组长度 4B 没有这个区域 实例数据 bool 1B 1 true,0 false #define TRUE 1 byte 1B char 2B 1B int 4B float 4B long 8B double 8B 引用类型 开启指针压缩 4B …

部署前端项目

常见部署方式有:静态托管服务、服务器部署 1. 静态托管服务 使用平台部署代码,比如 GitHub。 | 创建一个仓库,仓库名一般是 yourGithubName.github.io。 | 将打包后的静态文件文件上传到仓库。 | 在“Settings”(选项&#xff0…

一文入门云上StarRocks | EMR Serverless StarRocks

一文入门云上StarRocks | EMR Serverless StarRocks 什么是EMR Serverless StarRocksEMR Serverless StarRocks 操作免费开通创建实例连接StarRocks实例临时查询新建连接元数据管理诊断与分析 写在最后 什么是EMR Serverless StarRocks 在使用一个云产品之前,我们首…

C语言 结构体和共用体——结构体类型与结构体变量

目录 问题的提出 数组的解决方法 我们希望的内存分配图 如何声明一个结构体类型? 如何定义一个结构体变量? 用typedef给数据类型定义一个别名 如何定义一个结构体变量? 结构体变量的初始化 问题的提出 数组的解决方法 我们希望的内存…

解决树形表格 第一列中文字没有对齐

二级分类与一级分类的文字没有对齐 <el-table:data"templateStore.hangyeList"style"width: 100%"row-key"id":tree-props"{ children: subData, hasChildren: hasChildren }" ><el-table-column prop"industryCode&quo…

【Unity2D 2022:Audio】添加游戏音乐和音效

一、添加背景音乐 1. 创建空的游戏物体&#xff0c;名为BackgroundMusic 2. 为音频播放器添加音频源&#xff08;Audio Source&#xff09;组件 3. 将背景音乐音频赋值到AudioClip&#xff08;红色&#xff09; 4. 设置循环播放&#xff08;蓝色&#xff09; 二、添加草莓拾取…

AI赋能,全面筑牢防线:重点非煤矿山重大灾害风险防控系统探析

一、背景需求 随着工业化和现代化的快速发展&#xff0c;非煤矿山作为重要的资源开采基地&#xff0c;其安全生产问题日益受到社会各界的广泛关注。非煤矿山在开采过程中&#xff0c;面临着诸多重大灾害风险&#xff0c;如滑坡、坍塌、水害、火灾等&#xff0c;这些灾害一旦发…

Start LoongArch64 Alpine Linux VM on x86_64

一、Build from source(build on x86_64) Obtain the latest libvirt, virt manager, and QEMU source code, compile and install them 1.1 Build libvirt from source sudo apt-get update sudo apt-get install augeas-tools bash-completion debhelper-compat dh-apparmo…

【音视频 | RTSP】SDP(会话描述协议)详解 及 抓包例子分析

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

机器视觉理论入门

文章目录 前言一、马尔视觉理论二、图形与图像三、图像基础名词总结 前言 Marr的视觉计算理论立足于计算机科学&#xff0c;系统地概括了心理物理学、神经生理学、临床神经病理学等方面已取得的所有重要成果&#xff0c;是迄今为止最为系统的视觉理论。Marr 的视觉计算理论虽然…

Linux学习——Linux中无法使用ifconfg命令

Linux学习——Linux中无法使用ifconfg命令&#xff1f; &#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅…

内网对抗-基石框架篇单域架构域内应用控制成员组成用户策略信息收集环境搭建

知识点&#xff1a; 1、基石框架篇-单域架构-权限控制-用户和网络 2、基石框架篇-单域架构-环境搭建-准备和加入 3、基石框架篇-单域架构-信息收集-手工和工具1、工作组(局域网) 将不同的计算机按照功能分别列入不同的工作组。想要访问某个部门的资源&#xff0c;只要在“网络…

金蝶部署常见问题解决

金蝶部署常见问题解决 金蝶版本&#xff1a; Apusic Application Server Enterprise Edition 9.0 SP8 kbc build 202312041121 报错信息&#xff1a; 与金蝶官方人员沟通&#xff0c;发现lib包版本太低&#xff0c;升级后可正常使用。替换lib包后重启服务。 下载lib: 链接: …

Data-Juicer:阿里巴巴荣誉出品的大模型数据清洗框架

Diffusion Models专栏文章汇总:入门与实战 前言:如何优雅地进行大规模数据清洗是一门艺术,特别对于大模型,数据的质量是决定模型成功最关键的因素之一。阿里巴巴最近开源了一项专门针对大语言模型和视频生成大模型的数据清洗框架,值得关注! 目录 主要特点 数据处理 分…

代理详解之静态代理、动态代理、SpringAOP实现

1、代理介绍 代理是指一个对象A通过持有另一个对象B&#xff0c;可以具有B同样的行为的模式。为了对外开放协议&#xff0c;B往往实现了一个接口&#xff0c;A也会去实现接口。但是B是“真正”实现类&#xff0c;A则比较“虚”&#xff0c;他借用了B的方法去实现接口的方法。A…

大小端详解

引例 我们知道整形(int)是4个字节&#xff0c;例如随便举个例子&#xff1a;0x01020304&#xff0c;它一共占了四个地址位&#xff0c;01,02,03,04分别占了一个字节&#xff08;一个字节就对应了一个地址&#xff09;。 那么就会有个问题&#xff1a;我们的01到底是存储在高地…

Apache Flink核心特性应用场景

Flink的定义 Apache Flink是一个分布式处理引擎&#xff0c;用于处理 无边界数据流&#xff0c; 有边界数据流上金秀贤有状态的计算。Flink能在所有常见的集群环境中运行&#xff0c;并能以内存速度和任意规模进行计算如下Flink官网的一张图 Flink 与Spark的区别 Flink 中处…

Global Mapper:地理信息的温柔探索

引言 在这纷繁复杂的世界里&#xff0c;地理信息系统&#xff08;GIS&#xff09;如同一把利器&#xff0c;帮助我们剖析、理解和改造这个世界。而在众多GIS软件中&#xff0c;Global Mapper无疑是其中的佼佼者。作为一款功能全面且易于使用的GIS应用程序&#xff0c;Global M…

【Python基础】代码如何打包成exe可执行文件

本文收录于 《一起学Python趣味编程》专栏&#xff0c;从零基础开始&#xff0c;分享一些Python编程知识&#xff0c;欢迎关注&#xff0c;谢谢&#xff01; 文章目录 一、前言二、安装PyInstaller三、使用PyInstaller打包四、验证打包是否成功五、总结 一、前言 本文介绍如何…