Operator 开发入门系列(一):Hello World

背景

我们公司最近计划将产品迁移到 Kubernetes 环境。 为了更好地管理和自动化我们的应用程序,我们决定使用 Kubernetes Operator。 本系列博客将记录我们学习和开发 Operator 的过程,希望能帮助更多的人入门 Operator 开发。

目标读者

  • 对 Kubernetes 有一定了解的开发人员和运维人员
  • 希望使用 Operator 自动化管理应用程序的人员
  • 对 Go 语言有基本了解的人员

准备工作

在开始之前,你需要准备以下环境:

  • Go 语言环境 (>= 1.23): Operator 通常使用 Go 语言开发,你需要安装 Go 语言环境。 建议使用 Go 1.21 或更高版本。 可以从 https://go.dev/dl/ 下载安装包。 安装完成后,请配置好 GOPATHPATH 环境变量。

  • Kubernetes 集群: 你需要一个可用的 Kubernetes 集群来部署和测试 Operator。 可以使用 Minikube、Kind 或其他的 Kubernetes 发行版。

  • kubectl 命令行工具: kubectl 是 Kubernetes 的命令行工具,用于与 Kubernetes 集群交互。 请确保你已经安装并配置了 kubectl, 并且能够连接到你的 Kubernetes 集群。

  • Kubebuilder (>= 3.0): Kubebuilder 是一个用于快速构建 Kubernetes Operator 的框架。 使用 Kubebuilder 可以简化 Operator 的开发流程,并生成一些必要的代码框架。 可以使用以下命令安装 Kubebuilder:

cd $HOME/go/bin
curl -L -o kubebuilder "https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH)"
chmod +x kubebuilder

请确保 $HOME/go/bin 目录在你的 PATH 环境变量中。 可以运行 kubebuilder version 命令来验证 Kubebuilder 是否安装成功。

  • Docker (可选): 如果你需要构建 Operator 的 Docker 镜像,你需要安装 Docker。

我的环境是 MacOS(arm64) + Orbstack

什么是 Operator?

简单来说,Operator 是 Kubernetes 的扩展,它利用自定义资源(Custom Resources, CRs)来自动化管理应用程序。Operator 允许我们像管理 Kubernetes 内置资源一样管理复杂的应用程序,例如数据库、消息队列等。

为什么选择 Operator?

Operator 提供了一种声明式的方式来管理应用程序的生命周期,包括部署、升级、备份、恢复等。它可以简化运维流程,提高自动化程度,并确保应用程序的状态符合预期。

我们的第一个 Operator:Hello World

这个 Operator 将监听一个名为 HelloWorld 的自定义资源,并在 Kubernetes 中创建一个 Pod,该 Pod 运行一个简单的 “Hello World” 应用程序。

1. 初始化 Kubebuilder 项目

首先,我们需要使用 Kubebuilder 创建一个新的项目。 在你的 GOPATH 目录下创建一个新的目录,例如 hello-world-operator,然后进入该目录,运行以下命令

kubebuilder init --domain infini.cloud --repo github.com/infinilabs/hello-world-operator

这个命令会创建一个新的 Kubebuilder 项目,并生成一些必要的文件和目录。

2. 创建自定义资源(Custom Resource Definition, CRD)

接下来,我们需要定义 HelloWorld 资源的结构。 运行以下命令

kubebuilder create api --group example --version v1alpha1 --kind HelloWorld

这个命令会创建一个新的 API 定义,包括 api/v1alpha1/helloworld_types.gocontrollers/helloworld_controller.go 两个文件。

编辑 api/v1alpha1/helloworld_types.go 文件,修改 HelloWorldSpec 的定义,添加 namemessage 字段:

// HelloWorldSpec defines the desired state of HelloWorld
type HelloWorldSpec struct {// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster// Important: Run "make" to regenerate code after modifying this file// Name is the name of the HelloWorld resourceName string `json:"name,omitempty"`// Message is the message to be printed by the podMessage string `json:"message,omitempty"`
}

3. 实现 Reconcile 逻辑

编辑 controllers/helloworld_controller.go 文件,实现 Reconcile 函数, 创建一个 Pod,该 Pod 运行一个 busybox 镜像,并输出 HelloWorld 资源中定义的 message

package controllersimport ("context""fmt"corev1 "k8s.io/api/core/v1"apierrors "k8s.io/apimachinery/pkg/api/errors"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/apimachinery/pkg/runtime"ctrl "sigs.k8s.io/controller-runtime""sigs.k8s.io/controller-runtime/pkg/client""sigs.k8s.io/controller-runtime/pkg/log"examplev1alpha1 "github.com/infinilabs/hello-world-operator/api/v1alpha1"
)// HelloWorldReconciler reconciles a HelloWorld object
type HelloWorldReconciler struct {client.ClientScheme *runtime.Scheme
}//+kubebuilder:rbac:groups=example.com,resources=helloworlds,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=example.com,resources=helloworlds/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=example.com,resources=helloworlds/finalizers,verbs=update
//+kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch;create;update;patch;delete// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.13.0/pkg/reconcile
func (r *HelloWorldReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {log := log.FromContext(ctx)// 1. Fetch the HelloWorld instancehelloWorld := &examplev1alpha1.HelloWorld{}err := r.Get(ctx, req.NamespacedName, helloWorld)if err != nil {if apierrors.IsNotFound(err) {// Object not found, return.  Created objects are automatically garbage collected.// For additional cleanup logic use finalizers.log.Info("HelloWorld resource not found. Ignoring since object must be deleted")return ctrl.Result{}, nil}// Error reading the object - requeue the request.log.Error(err, "Failed to get HelloWorld")return ctrl.Result{}, err}// 2. Define the desired Podpod := &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name:      helloWorld.Name + "-pod",Namespace: helloWorld.Namespace,Labels: map[string]string{"app": helloWorld.Name,},},Spec: corev1.PodSpec{Containers: []corev1.Container{{Name:  "hello-world",Image: "busybox",Command: []string{"sh", "-c", fmt.Sprintf("echo '%s' && sleep 3600", helloWorld.Spec.Message)},},},},}// 3. Set HelloWorld instance as the owner and controllerif err := ctrl.SetControllerReference(helloWorld, pod, r.Scheme); err != nil {log.Error(err, "Failed to set controller reference")return ctrl.Result{}, err}// 4. Check if the Pod already existsfound := &corev1.Pod{}err = r.Get(ctx, client.ObjectKey{Name: pod.Name, Namespace: pod.Namespace}, found)if err != nil && apierrors.IsNotFound(err) {log.Info("Creating a new Pod", "Pod.Namespace", pod.Namespace, "Pod.Name", pod.Name)err = r.Create(ctx, pod)if err != nil {log.Error(err, "Failed to create new Pod", "Pod.Namespace", pod.Namespace, "Pod.Name", pod.Name)return ctrl.Result{}, err}// Pod created successfully - return and requeuereturn ctrl.Result{Requeue: true}, nil} else if err != nil {log.Error(err, "Failed to get Pod")return ctrl.Result{}, err}// 5. Pod already exists - don't requeuelog.Info("Skip reconcile: Pod already exists", "Pod.Namespace", found.Namespace, "Pod.Name", found.Name)return ctrl.Result{}, nil
}// SetupWithManager sets up the controller with the Manager.
func (r *HelloWorldReconciler) SetupWithManager(mgr ctrl.Manager) error {return ctrl.NewControllerManagedBy(mgr).For(&examplev1alpha1.HelloWorld{}).Owns(&corev1.Pod{}).Complete(r)
}

4. 安装 CRD 到 Kubernetes 集群

运行以下命令安装 CRD 到 Kubernetes 集群:

make install

5. 运行 Operator

运行以下命令在本地运行 Operator:

make run

6. 创建 HelloWorld 资源

创建一个名为 my-hello-world.yaml 的文件,内容如下:

apiVersion: example.com/v1alpha1
kind: HelloWorld
metadata:name: my-hello-world
spec:name: my-hello-worldmessage: "Hello World from Operator!"

使用 kubectl apply -f my-hello-world.yaml 创建资源。

7. 验证

使用 kubectl get pods 命令查看是否创建了名为 my-hello-world-pod 的 Pod。 使用 kubectl logs my-hello-world-pod 查看 Pod 的日志,确认是否输出了 “Hello World from Operator!”。

总结

恭喜你完成了第一个 Operator! 虽然这个 Operator 非常简单,但它展示了 Operator 的基本原理:监听自定义资源,并根据资源的状态来管理 Kubernetes 资源。 在接下来的系列中,我们将深入探讨 Operator 的更多高级特性。

敬请期待下一篇博客!

作者:罗厚付,极限科技(INFINI Labs)云上产品设计与研发负责人,拥有多年安全风控及大数据系统架构经验,主导过多个核心产品的设计与落地,日常负责运维超大规模 ES 集群(800+节点/1PB+数据)。
原文:https://infinilabs.cn/blog/2025/kubernetes-operator-develop-part-1/

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

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

相关文章

Java基础知识面试题(已整理Java面试宝典pdf版)

什么是Java Java是一门面向对象编程语言,不仅吸收了C语言的各种优点,还摒弃了C里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论…

科学视角下的打坐:身心获益的实证探究

在快节奏的现代生活中,人们在追求物质丰富的同时,也愈发关注身心的健康与平衡。古老的打坐修行方式,正逐渐走进科学研究的视野,并以大量实证数据展现出对人体多方面的积极影响。​ 什么是打坐: 打坐是一种养生健身法…

javaSE————网络编程套接字

网络编程套接字~~~~~ 好久没更新啦,蓝桥杯爆掉了,从今天开始爆更嗷; 1,网络编程基础 为啥要有网络编程呢,我们进行网络通信就是为了获取丰富的网络资源,说实话真的很神奇,想想我们躺在床上&a…

MySQL性能调优(三):MySQL中的系统库(mysql系统库)

文章目录 MySQL性能调优数据库设计优化查询优化配置参数调整硬件优化 MySQL中的系统库1.5.Mysql中mysql系统库1.5.1.权限系统表1.5.2.统计信息表1.5.2.1.innodb_table_stats1.5.2.2.innodb_index_stats 1.5.3.日志记录表1.5.3.1. general_log1.5.3.2. slow_log 1.5.4.InnoDB中的…

多个路由器互通(静态路由)无单臂路由(简单版)

多个路由器互通(静态路由)无单臂路由(简单版) 开启端口并配ip地址 维护1 Router>en Router#conf t Router(config)#int g0/0 Router(config-if)#no shutdown Router(config-if)#ip address 192.168.10.254 255.255.255.0 Ro…

关于 AI驱动的智慧家居、智慧城市、智慧交通、智慧医疗和智慧生活 的详细解析,涵盖其定义、核心技术、应用场景、典型案例及未来趋势

以下是关于 AI驱动的智慧家居、智慧城市、智慧交通、智慧医疗和智慧生活 的详细解析,涵盖其定义、核心技术、应用场景、典型案例及未来趋势: 一、AI智慧家居 1. 定义与核心功能 定义:通过AI与物联网(IoT)技术&#…

【ESP32|音频】一文读懂WAV音频文件格式【详解】

简介 最近在学习I2S音频相关内容,无可避免会涉及到关于音频格式的内容,所以刚开始接触的时候有点一头雾水,后面了解了下WAV相关内容,大致能够看懂wav音频格式是怎么样的了。本文主要为后面ESP32 I2S音频系列文章做铺垫&#xff0…

端侧大模型综述On-Device Language Models: A Comprehensive Review

此为机器翻译,仅做个人学习使用 设备端语言模型:全面回顾 DOI:10.48550/arXiv.2409.00088 1 摘要 大型语言模型 (LLM) 的出现彻底改变了自然语言处理应用程序,由于减少延迟、数据本地化和个性化用户体验…

推流265视频,网页如何支持显示265的webrtc

科技发展真快,以前在网页上(一般指谷歌浏览器),要显示265的视频流,都是很鸡肋的办法,要么转码,要么用很慢的hls,体验非常不好,而今谷歌官方最新的浏览器已经支持265的web…

redis的sorted set的应用场景

Redis 的 Sorted Set(有序集合,简称 ZSet) 结合了 Set 的去重特性 和 按分数(score)排序 的特性,非常适合需要 高效排序 或 范围查询 的场景。以下是它的典型应用场景及示例: 实时排行榜 场景&…

18-21源码剖析——Mybatis整体架构设计、核心组件调用关系、源码环境搭建

学习视频资料来源:https://www.bilibili.com/video/BV1R14y1W7yS 文章目录 1. 架构设计2. 核心组件及调用关系3. 源码环境搭建3.1 测试类3.2 实体类3.3 核心配置文件3.4 映射配置文件3.5 遇到的问题 1. 架构设计 Mybatis整体架构分为4层: 接口层&#…

未启用CUDA支持的PyTorch环境** 中使用GPU加速解决方案

1. 错误原因分析 根本问题:当前安装的PyTorch是CPU版本,无法调用GPU硬件加速。当运行以下代码时会报错:model YOLO("yolov8n.pt").to("cuda") # 或 .cuda()2. 解决方案步骤 步骤1:验证CUDA可用性 在Pyth…

JVM-基于Hotspot

前言 Java虚拟机(Java Virtual Machine简称JVM)是运行所有Java程序的抽象计算机,是Java语言的运行环境,其主要任务为将字节码装载到内部,解释/编译为对应平台上的机器指令执行。 Java虚拟机规范定义了一个抽象的——…

智能合约安全审计平台——可视化智能合约漏洞扫描

目录 可视化智能合约漏洞扫描 —— 理论、实践与安全保障1. 引言2. 理论背景与漏洞原理2.1 智能合约简介2.2 常见漏洞类型2.3 漏洞扫描与安全评估原理3. 系统架构与工作流程3.1 系统总体架构3.2 模块说明4. 漏洞扫描流程详解4.1 代码上传与静态解析4.2 漏洞模式检测4.3 风险评估…

【MySQL数据库】数据类型详解

目录 数据类型tinyint类型(整形)bit类型小数浮点数 float、doubledecimal 字符串类型charvarcharchar与varchar的比较 日期时间类型enum和set总结 数据类型 tinyint类型(整形) 例: mysql> create table tt1(num tinyint);mysql> insert into tt1 values(1)…

咪咕MG101_晨星MSO9380芯片_安卓5.1.1_免拆卡刷固件包

咪咕MG101_晨星MSO9380芯片_安卓5.1.1_免拆卡刷固件包(内有教程) 刷机教程简单说明: 1、把下载好的刷机包,U盘里建立一个upgrade文件夹,固件放入此文件夹里,放入U盘中,注意升级包为压缩包不要对…

CS61A:STRING REPRESENTATION

Python 规定所有对象都应该产生两种不同的字符串表示形式:一种是人类可解释的文本,另一种是 Python 可解释的表达式。字符串的构造函数 str 返回一个人类可读的字符串。在可能的情况下,repr 函数会返回一个计算结果相等的 Python 表达式。rep…

LangChain缓存嵌入技术完全指南:CacheBackedEmbedding原理与实践(附代码示例)

一、嵌入缓存技术背景与应用场景 1.1 为什么需要嵌入缓存? 算力消耗问题:现代嵌入模型(如text-embedding-3-small)单次推理需要约0.5-1秒/文本 资源浪费现状:实际业务中约30%-60%的文本存在重复计算 成本压力&#…

精益数据分析(3/126):用数据驱动企业发展的深度解析

精益数据分析(3/126):用数据驱动企业发展的深度解析 大家好!一直以来,我都坚信在当今竞争激烈的商业环境中,数据是企业获得竞争优势的关键。最近深入研究《精益数据分析》这本书,收获颇丰&…

wpf ScaleTransform

在WPF中,ScaleTransform是用于实现元素缩放的核心类,属于System.Windows.Media命名空间下的变换类型。以下是其主要特性与使用方式的总结: ‌核心属性‌ ‌缩放比例‌ ScaleX:水平方向缩放比例(默认1.0,即…