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

🧰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-confignamespace: my-namespacelabels:prometheus: system-monitoring-prometheus
spec:staticConfigs:- labels:job: prometheustargets:- 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: 2vmstorage:replicaCount: 2storageDataPath: "/vm-data"storage:volumeClaimTemplate:spec:resources:requests:storage: "10Gi"resources:limits:cpu: "1"memory: "1Gi"vmselect:replicaCount: 2cacheMountPath: "/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-ordernamespace: test  
spec:  env:  - name: OTEL_SERVICE_NAME  value: orderselector:  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.mzph.cn/web/43144.shtml

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

相关文章

去水印小程序源码修复版-前端后端内置接口+第三方接口

去水印小程序源码,前端后端,内置接口第三方接口, 修复数据库账号密码错误问题,内置接口支持替换第三方接口, 文件挺全的,可以添加流量主代码,搭建需要准备一台服务器,备案域名和http…

农牧行业CRM洞察:打造营、销、服一体化数字营销平台

01、行业应用背景 保持企业活力,支撑业务单元协调发展,稳定核心产品竞争力,将成为农牧行业企业数字化、数智化建设的指导方向。 积极发挥数据在生产、流通、消费各个环节的决策支撑,为农牧企业特别是多业态集团型企业&#xff0…

JVM:类的生命周期

文章目录 一、介绍二、加载阶段三、连接阶段1、验证阶段2、准备阶段3、解析阶段 四、初始化阶段 一、介绍 类的生命周期描述了一个类加载、连接(验证、准备和解析)、初始化、使用、卸载的整个过程。 二、加载阶段 加载(Loading&#xff09…

全栈业务开发入门——登录业务接口

业务已上传则资源 实现登录业务的前后端联调,前端点击登录按钮向后端发送一个请求,后端调用接口向前端响应结果 效果如下: 设计环境:springbootmybatisvue3axios 一.前端设计 1.基于vue3脚手架创建项目,搭建项目结构…

LAZYNVIM学习使用笔记

文章目录 1. 前言VIM的模式快捷键参考 1. 前言 习惯使用vscode进行代码编辑,无意中刷到lazynvim,感觉功能强大,于是下载、安装,学习使用一下,本篇主要记录学习使用lazynvim的一些要点,防止遗忘。 持续更新…

帝特(DTECH)USB转RS485/422串口线在Ubuntu系统中的安装

因为测试需要,买了一根帝特(DTECH)USB转RS485/422串口线,今天测试了一下在Ubuntu 22.04系统上的使用。帝特的网站上提供了驱动程序,下载以后发现接口芯片是CP2102,厂商只提供了Linux内核2.6和3.x版本的驱动…

游戏AI的创造思路-技术基础-情感计算(2)

上一篇我们介绍了情感计算的基本支持,本篇将呈现情感计算在游戏AI中的使用实例~~~ 目录 7. 情感计算在游戏AI中的运用实例 7.1. RPG游戏中的运用实例 7.1.1. 实例背景 7.1.2. AI情感计算系统 7.1.3. 引导用户执行任务 7.1.4. 推动游戏剧情发展 7.1.5. 实例效…

用Python玩转Excel的五大功能!

在日常的数据处理工作中,Excel无疑是一个强大的工具。然而,当数据量较大或需要自动化处理时,Python凭借其强大的库支持,如pandas和openpyxl,能够更高效地处理Excel文件。 本文将介绍Python中常用的五种Excel操作**&am…

Python办公自动化:增值税发票批量识别和核验

腾讯云免费体验地址: https://console.cloud.tencent.com/api/explorer?Product=ocr&Version=2018-11-19&Action=VatInvoiceVerifyNew 首先进行识别,这里以python为例子 # -*- coding: utf-8 -*- import jsonfrom tencentcloud.common.common_client import Commo…

【C++航海王:追寻罗杰的编程之路】关联式容器的底层结构——红黑树

目录 1 -> 红黑树 1.1 -> 红黑树的概念 1.2 -> 红黑树的性质 1.3 -> 红黑树节点的定义 1.4 -> 红黑树的结构 1.5 -> 红黑树的插入操作 1.6 -> 红黑树的验证 1.8 -> 红黑树与AVL树的比较 2 -> 红黑树模拟实现STL中的map与set 2.1 -> 红…

【堆 优先队列】1354. 多次求和构造目标数组

本文涉及知识点 堆 优先队列 LeetCode1354. 多次求和构造目标数组 给你一个整数数组 target 。一开始&#xff0c;你有一个数组 A &#xff0c;它的所有元素均为 1 &#xff0c;你可以执行以下操作&#xff1a; 令 x 为你数组里所有元素的和 选择满足 0 < i < target.…

linux信息收集与提权

目录 版本信息收集 kali得一些exp网站 kali自带的searchsploit工具 脏牛提权漏洞&#xff08;改写没有写权限的文件&#xff09; 测试靶场下载链接 sudo提权 上传恶意C脚本进行编译生成dirty的elf文件&#xff0c;也可以在攻击机编译好上传 启动&#xff0c;123456是设…

体验完这款售价29999元起苹果新品,我大受震撼

讲道理&#xff0c;数码圈已经很久没有出现过让人耳目一新的产品了。 整个圈子近些年各家新品逻辑给我的一种感觉是普遍主打循规循距&#xff0c;用高情商话来说那叫稳扎稳打不易出错&#xff0c;而低情商嘛&#xff0c;说白了叫创新精神严重缺失。 「科技最后以换皮为准」这…

【CUDA】 Trust基本特性介绍及性能分析

Trust简介 Thrust 是一个实现了众多基本并行算法的 C 模板库,类似于 C 的标准模板库(standard template library, STL)。该库自动包含在 CUDA 工具箱中。这是一个模板库,仅仅由一些头文件组成。在使用该库的某个功能时,包含需要的头文件即可。该库中的所有类型与函数都在命名空…

【linux】 sudo apt update报错——‘由于没有公钥,无法验证下列签名: NO_PUBKEY 3B4FE6ACC0B21F32’

【linux】 sudo apt update报错——‘由于没有公钥&#xff0c;无法验证下列签名&#xff1a; NO_PUBKEY 3B4FE6ACC0B21F32’ 在运行sudo apt update时遇到报错&#xff0c;由于没有公钥&#xff0c;无法验证下列签名&#xff1a; NO_PUBKEY 3B4FE6ACC0B21F32 解决方法&#x…

Qt:11.输入类控件(QLineEdit-单行文本输入控件、QTextEdit-多行文本输入控件、QComboBox-下拉列表的控件)

一、QLineEdit-单行文本输入控件&#xff1a; 1.1QLineEdit介绍&#xff1a; QLineEdit 是 Qt 库中的一个单行文本输入控件&#xff0c;不能换行。允许用户输入和编辑单行文本。 1.2属性介绍&#xff1a; inputMask 设置输入掩码&#xff0c;以限定输入格式。setInputMask(con…

react学习——25redux实现求和案例(完整版)

1、目录结构 2、count/index.js import React, {Component} from "react"; //引入store,用于获取数据 import store from ../../redux/store //引入actionCreator 专门创建action对象 import {createDecrementAction,createIncrementAction} from ../../redux/coun…

CSS【详解】边框 border,边框-圆角 border-radius,边框-填充 border-image,轮廓 outline

边框 border border 是以下三种边框样式的简写&#xff1a; border-width 边框宽度 —— 数值 px&#xff08;像素&#xff09;,thin&#xff08;细&#xff09;,medium&#xff08;中等&#xff09;,thick&#xff08;粗&#xff09;border-style 边框线型 —— none【默认值…

78. UE5 RPG 创建技能数据并初始化技能ui

在上一篇文章里&#xff0c;我们创建了技能的UI&#xff0c;接下来&#xff0c;我们要考虑如何实现对技能UI的填充&#xff0c;肯定不能直接写死&#xff0c;需要有一些方法去实现技能的更新。我们期望能够创建一个技能数据&#xff0c;然后根据数据通过回调的方式实现数据的更…

一键掌握天气动态 - 基于Vue和高德API的实时天气查询

前言 本文将学习如何使用Vue.js快速搭建天气预报界面,了解如何调用高德地图API获取所需的天气数据,并掌握如何将两者有机结合,实现一个功能丰富、体验出色的天气预报应用 无论您是前端新手还是有一定经验,相信这篇教程都能为您带来收获。让我们一起开始这段精彩的Vue.js 高德…