当前位置: 首页 > article >正文

Kubernetes Operator开发实战

Kubernetes Operator开发实战一、Operator概述Kubernetes Operator是一种软件扩展模式用于管理复杂的有状态应用。1.1 Operator模式┌─────────────────────────────────────────────────────────────┐ │ Operator │ │ ┌───────────────────────────────────────────────────────┐ │ │ │ Controller ── Watch ── Reconcile ── Update │ │ │ └───────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Custom Resource │ │ (定义应用期望状态) │ └─────────────────────────────────────────────────────────────┘1.2 Operator组成组件说明Custom Resource定义应用的自定义资源Controller监听资源变化维持期望状态Reconcile Loop核心控制循环持续调谐状态二、环境准备2.1 安装Operator SDK# 安装Operator SDK curl -sL https://github.com/operator-framework/operator-sdk/releases/download/v1.32.0/operator-sdk_linux_amd64 -o operator-sdk chmod x operator-sdk sudo mv operator-sdk /usr/local/bin/ # 验证安装 operator-sdk version2.2 初始化项目# 创建项目 operator-sdk init --domain example.com --repo github.com/example/myapp-operator # 添加API operator-sdk create api --group apps --version v1 --kind MyApp --resource --controller三、定义Custom Resource3.1 API定义// MyAppSpec defines the desired state of MyApp type MyAppSpec struct { Replicas *int32 json:replicas,omitempty Image string json:image,omitempty Port int32 json:port,omitempty // 自定义配置 Resources Resources json:resources,omitempty Env []EnvVar json:env,omitempty } // MyAppStatus defines the observed state of MyApp type MyAppStatus struct { ReadyReplicas int32 json:readyReplicas,omitempty Phase string json:phase,omitempty Conditions []metav1.Condition json:conditions,omitempty } // kubebuilder:object:roottrue // kubebuilder:subresource:status // MyApp is the Schema for the myapps API type MyApp struct { metav1.TypeMeta json:,inline metav1.ObjectMeta json:metadata,omitempty Spec MyAppSpec json:spec,omitempty Status MyAppStatus json:status,omitempty } // kubebuilder:object:roottrue // MyAppList contains a list of MyApp type MyAppList struct { metav1.TypeMeta json:,inline metav1.ListMeta json:metadata,omitempty Items []MyApp json:items }3.2 生成CRD# 生成CRD make manifests # 查看生成的CRD cat config/crd/bases/apps.example.com_myapps.yaml四、Controller实现4.1 Reconcile逻辑func (r *MyAppReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log : log.FromContext(ctx) // 1. 获取MyApp资源 var myapp appsv1.MyApp if err : r.Get(ctx, req.NamespacedName, myapp); err ! nil { if apierrors.IsNotFound(err) { return ctrl.Result{}, nil } log.Error(err, Unable to fetch MyApp) return ctrl.Result{}, err } // 2. 检查Deployment是否存在 var deployment appsv1.Deployment deploymentName : myapp.Name if err : r.Get(ctx, types.NamespacedName{Name: deploymentName, Namespace: myapp.Namespace}, deployment); err ! nil { if apierrors.IsNotFound(err) { // 创建Deployment deployment r.createDeployment(myapp) if err : r.Create(ctx, deployment); err ! nil { log.Error(err, Failed to create Deployment) return ctrl.Result{}, err } return ctrl.Result{Requeue: true}, nil } log.Error(err, Unable to fetch Deployment) return ctrl.Result{}, err } // 3. 检查副本数是否匹配 if *deployment.Spec.Replicas ! *myapp.Spec.Replicas { deployment.Spec.Replicas myapp.Spec.Replicas if err : r.Update(ctx, deployment); err ! nil { log.Error(err, Failed to update Deployment) return ctrl.Result{}, err } return ctrl.Result{Requeue: true}, nil } // 4. 更新状态 r.updateStatus(ctx, myapp, deployment) return ctrl.Result{}, nil }4.2 创建Deploymentfunc (r *MyAppReconciler) createDeployment(myapp *appsv1.MyApp) appsv1.Deployment { labels : map[string]string{ app: myapp.Name, } return appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: myapp.Name, Namespace: myapp.Namespace, OwnerReferences: []metav1.OwnerReference{ *metav1.NewControllerRef(myapp, appsv1.GroupVersion.WithKind(MyApp)), }, }, Spec: appsv1.DeploymentSpec{ Replicas: myapp.Spec.Replicas, Selector: metav1.LabelSelector{ MatchLabels: labels, }, Template: corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: labels, }, Spec: corev1.PodSpec{ Containers: []corev1.Container{{ Name: myapp.Name, Image: myapp.Spec.Image, Ports: []corev1.ContainerPort{{ ContainerPort: myapp.Spec.Port, }}, Resources: myapp.Spec.Resources, Env: myapp.Spec.Env, }}, }, }, }, } }4.3 更新状态func (r *MyAppReconciler) updateStatus(ctx context.Context, myapp *appsv1.MyApp, deployment *appsv1.Deployment) { readyReplicas : deployment.Status.ReadyReplicas phase : Pending if readyReplicas *deployment.Spec.Replicas { phase Ready } else if readyReplicas 0 { phase Partial } myapp.Status.ReadyReplicas readyReplicas myapp.Status.Phase phase if err : r.Status().Update(ctx, myapp); err ! nil { log.FromContext(ctx).Error(err, Failed to update MyApp status) } }4.4 Setup With Managerfunc (r *MyAppReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(appsv1.MyApp{}). Owns(appsv1.Deployment{}). Owns(corev1.Service{}). Complete(r) }五、测试Operator5.1 创建测试CRapiVersion: apps.example.com/v1 kind: MyApp metadata: name: myapp-sample spec: replicas: 3 image: nginx:latest port: 80 resources: requests: memory: 128Mi cpu: 100m limits: memory: 256Mi cpu: 200m env: - name: ENV value: production5.2 部署Operator# 部署CRD kubectl apply -f config/crd/bases/apps.example.com_myapps.yaml # 部署Operator make install make deploy IMGmyapp-operator:latest # 创建示例资源 kubectl apply -f config/samples/apps_v1_myapp.yaml5.3 验证部署# 查看Operator日志 kubectl logs -n myapp-operator-system -l control-planecontroller-manager # 查看MyApp状态 kubectl get myapps kubectl describe myapp myapp-sample # 查看创建的资源 kubectl get deployments kubectl get pods六、高级功能6.1 事件处理func (r *MyAppReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log : log.FromContext(ctx) var myapp appsv1.MyApp if err : r.Get(ctx, req.NamespacedName, myapp); err ! nil { return ctrl.Result{}, client.IgnoreNotFound(err) } // 记录事件 r.Recorder.Event(myapp, corev1.EventTypeNormal, Reconciling, Starting reconciliation) // ... 业务逻辑 ... r.Recorder.Event(myapp, corev1.EventTypeNormal, Reconciled, Reconciliation completed) return ctrl.Result{}, nil }6.2 Finalizer处理func (r *MyAppReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { var myapp appsv1.MyApp if err : r.Get(ctx, req.NamespacedName, myapp); err ! nil { return ctrl.Result{}, client.IgnoreNotFound(err) } // 检查是否正在删除 if myapp.GetDeletionTimestamp() ! nil { // 清理资源 if err : r.cleanupResources(ctx, myapp); err ! nil { return ctrl.Result{}, err } // 移除finalizer myapp.Finalizers removeString(myapp.Finalizers, myapp.finalizer) if err : r.Update(ctx, myapp); err ! nil { return ctrl.Result{}, err } return ctrl.Result{}, nil } // 添加finalizer if !containsString(myapp.Finalizers, myapp.finalizer) { myapp.Finalizers append(myapp.Finalizers, myapp.finalizer) if err : r.Update(ctx, myapp); err ! nil { return ctrl.Result{}, err } } // ... 业务逻辑 ... }6.3 状态条件func (r *MyAppReconciler) updateStatusConditions(ctx context.Context, myapp *appsv1.MyApp, ready bool) { conditionType : appsv1.MyAppReady status : metav1.ConditionFalse if ready { status metav1.ConditionTrue } r.Status().Patch(ctx, myapp, client.MergeFrom(myapp.DeepCopy())) myapp.Status.Conditions append(myapp.Status.Conditions, metav1.Condition{ Type: string(conditionType), Status: status, LastTransitionTime: metav1.Now(), Reason: Reconciled, Message: MyApp is ready, }) }七、部署与分发7.1 构建镜像# 构建镜像 make docker-build IMGmyapp-operator:latest # 推送镜像 make docker-push IMGmyapp-operator:latest7.2 Helm ChartapiVersion: v2 name: myapp-operator description: A Helm chart for MyApp Operator type: application version: 0.1.0 appVersion: 1.0 dependencies: - name: cert-manager version: v1.13.0 repository: https://charts.jetstack.io condition: cert-manager.enabled templates: - deployment.yaml - service.yaml - rbac.yaml7.3 OLM部署# 创建Catalog operator-sdk olm install # 打包Operator operator-sdk bundle create --image-builder docker --directory deploy/olm-catalog/myapp-operator # 推送Bundle docker push myapp-operator-bundle:latest # 订阅Operator kubectl apply -f deploy/olm-catalog/myapp-operator/subscription.yaml八、最佳实践8.1 设计原则幂等性Reconcile应该是幂等的重试机制使用Result.Requeue进行重试错误处理区分可重试和不可重试错误状态管理合理使用Status字段8.2 性能优化// 使用FieldSelector减少监听范围 func (r *MyAppReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(appsv1.MyApp{}). WithEventFilter(predicate.GenerationChangedPredicate{}). Complete(r) }8.3 测试策略func TestMyAppReconciler(t *testing.T) { tests : []struct { name string setup func(*envtest.Environment) wantErr bool }{ { name: create myapp, setup: func(env *envtest.Environment) { // 测试设置 }, wantErr: false, }, } for _, tt : range tests { t.Run(tt.name, func(t *testing.T) { // 测试逻辑 }) } }九、总结开发Kubernetes Operator需要以下步骤定义CRD使用kubebuilder定义自定义资源实现Controller编写Reconcile逻辑处理状态更新资源状态测试验证单元测试和集成测试部署分发构建镜像和ChartOperator模式是管理复杂应用的最佳实践通过声明式API提供一致的管理体验。

相关文章:

Kubernetes Operator开发实战

Kubernetes Operator开发实战 一、Operator概述 Kubernetes Operator是一种软件扩展模式,用于管理复杂的有状态应用。 1.1 Operator模式 ┌──────────────────────────────────────────────────────────…...

Elasticsearch聚合查询优化实战

Elasticsearch聚合查询优化实战 一、聚合查询概述 Elasticsearch的聚合功能是数据分析的核心,支持多种聚合类型来满足不同的分析需求。 1.1 聚合类型 类型说明使用场景Metric指标聚合求和、平均值、最大值、最小值Bucket桶聚合分组统计、区间统计Pipeline管道聚合基…...

从‘盲猜’到‘先知’:深度解读神经RRT*如何让采样规划拥有‘大局观’

神经RRT*:当路径规划算法学会"思考"的范式革命 在自动驾驶汽车寻找最短路径、无人机规划避障航线的场景中,传统RRT算法就像一位盲人摸象的探险者——它通过随机撒点的方式探索环境,虽然最终能找到出路,却需要耗费大量时…...

保姆级教程:在Windows上跑通Deeplabv3+,用Cityscapes数据集训练语义分割模型(附避坑指南)

保姆级教程:在Windows上跑通Deeplabv3,用Cityscapes数据集训练语义分割模型(附避坑指南) 语义分割作为计算机视觉领域的核心技术之一,正在自动驾驶、医疗影像分析等领域发挥越来越重要的作用。而Deeplabv3作为语义分割…...

告别传统知识蒸馏:用CVPR2022的‘逆向蒸馏’在PyTorch里玩转工业异常检测

工业级异常检测实战:基于CVPR2022逆向蒸馏的PyTorch实现指南 当传统知识蒸馏在工业缺陷检测中遭遇瓶颈——学生网络对异常样本产生"幻觉响应"、模型对微小缺陷敏感度不足、复杂纹理场景下误报率飙升——CVPR2022提出的逆向蒸馏架构犹如一剂精准的手术刀。…...

山海再赴,探索向新|2026 第二届搜狐极限探索者大会盛大启航!

2025年6月5日,由搜狐主办的首届搜狐极限探索者大会在北京盛大举行。大会以“致敬极限探索者”(Salute to the Ultimate Explorers)为主题,汇聚中国上百位各极限运动领域顶尖的探索者、企业及明星嘉宾,通过巅峰演讲、深…...

Bifrost三星固件下载器:免费跨平台获取官方系统的一站式解决方案

Bifrost三星固件下载器:免费跨平台获取官方系统的一站式解决方案 【免费下载链接】Bifrost Cross-platform tool for downloading Samsung mobile device firmware. 项目地址: https://gitcode.com/gh_mirrors/sa/Bifrost 你是否曾为寻找三星设备官方固件而烦…...

从‘盲人摸象’到‘全局视野’:手把手教你用MATLAB/Simulink仿真PSO-MPPT对抗光伏遮荫(避坑指南)

从‘盲人摸象’到‘全局视野’:手把手教你用MATLAB/Simulink仿真PSO-MPPT对抗光伏遮荫(避坑指南) 光伏发电系统在局部遮荫条件下,功率-电压特性曲线会呈现多峰值现象,传统MPPT算法容易陷入局部最优。粒子群优化&#x…...

SPICE仿真实战:从时序分析基础到建立保持时间验证

1. 项目概述:从“香料”到“时序”的工程思维“时序分析基本概念介绍”这个标题,乍一看可能有点割裂。前半部分“时序分析基本概念介绍”指向一个非常经典且基础的电子工程领域——信号在时间维度上的行为分析,这是电路设计、通信系统乃至嵌入…...

5元级MCU Air601实战评测:硬件兼容、LuatOS开发与ESP12F迁移指南

1. 项目概述:一颗5元级MCU的“越级”挑战最近在捣鼓一个智能家居的小玩意儿,原本计划用ESP12F(也就是我们常说的ESP8266模组)来做,毕竟它生态成熟,资料遍地都是。但在采购物料时,偶然瞥见了合宙…...

【计算机毕业设计】基于Springboot的工作流程管理系统设计与实现+万字文档

博主介绍:✌全网粉丝3W,csdn特邀作者、CSDN新星计划导师、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、…...

保姆级教程:手把手教你搞定OpenPnP主次基准点矫正(附PCB制作与避坑心得)

OpenPnP主次基准点矫正实战指南:从硬件准备到精准调试 1. 准备工作:构建稳定的校准环境 在开始OpenPnP主次基准点矫正之前,充分的准备工作能避免80%的常见问题。首先需要理解基准点在贴片机坐标系中的核心作用——它们如同地图上的经纬度&…...

别再死循环了!手把手教你用Python实现D*算法(附完整代码与避坑指南)

从理论到实践:Python实现D*算法的工程化指南与避坑策略 路径规划中的动态适应挑战 在机器人导航和游戏AI开发中,路径规划算法扮演着至关重要的角色。传统算法如A*和Dijkstra虽然能有效解决静态环境下的路径规划问题,但在动态变化的环境中却显…...

从2023蓝桥杯JavaB组省赛真题看算法思维与实战技巧

1. 从真题看算法思维培养 去年参加蓝桥杯省赛时,我对着那道阶乘求和题足足愣了十分钟。题目要求计算1!到202320232023!的和的最后9位数字,我第一反应就是暴力计算每个阶乘值再累加。结果刚算到20!就发现long类型溢出了,当时整个人都懵了。后来…...

使用Taotoken后如何通过用量看板清晰掌握各模型API消耗情况

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 使用Taotoken后如何通过用量看板清晰掌握各模型API消耗情况 当你将多个大模型API的调用统一接入到Taotoken平台后,一个…...

从账单明细看 Taotoken 按 Token 计费模式带来的成本控制优势

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 从账单明细看 Taotoken 按 Token 计费模式带来的成本控制优势 1. 成本感知的起点:账单明细结构 对于使用大模型 API 的…...

如何将 Infinix 手机中的联系人传输到 iPhone

如果您刚从Infinix Android手机换到新款 iPhone ,首先可能会担心如何安全快捷地将联系人从 Infinix 转移到 iPhone。由于这两个系统使用不同的数据生态系统,许多用户不确定哪种方法最有效。幸运的是,有几种可靠的方法可以转移您的通讯录&…...

UE5动画进阶:用Control Rig的Aim节点,5分钟搞定角色头部平滑跟随任意Actor

UE5动画进阶:Control Rig的Aim节点实现角色头部动态跟随 在游戏开发中,角色与环境的动态交互是提升沉浸感的关键要素之一。想象一个场景:NPC能够自然地跟随玩家的移动而转动头部,或是怪物精准锁定目标时的头部动作——这些细节往往…...

HLS行为差异测试:挑战与LLM驱动的解决方案

1. 高层次综合(HLS)行为差异测试的挑战与机遇在AI计算和边缘计算快速发展的今天,FPGA因其可重构性和并行计算能力,成为硬件加速的重要选择。高层次综合(High-Level Synthesis, HLS)技术允许开发者使用C/C等高级语言编写算法,然后自动转换为硬…...

7天掌握FontForge:免费开源字体编辑器的完整使用指南

7天掌握FontForge:免费开源字体编辑器的完整使用指南 【免费下载链接】fontforge Free (libre) font editor for Windows, Mac OS X and GNULinux 项目地址: https://gitcode.com/gh_mirrors/fo/fontforge 你是否曾梦想设计属于自己的字体?无论是…...

Claude Code 上下文管理机制深度拆解:超长 Agent 任务如何不崩盘

在一个真正复杂的企业级软件设计与编码任务里,Coding Agent 面对的从来不是一句简单的“帮我写个小游戏”。 它要理解用户的原始需求,要读取项目里的既有代码,要遵守架构约束、编码规范、接口协议,还要调用各种工具、加载不同的技能和规则,甚至记住用户十分钟前随口补充的…...

3分钟快速上手:Tsukimi打造你的个人Jellyfin媒体中心

3分钟快速上手:Tsukimi打造你的个人Jellyfin媒体中心 【免费下载链接】tsukimi A simple third-party Jellyfin client for Linux 项目地址: https://gitcode.com/gh_mirrors/ts/tsukimi 还在为复杂的媒体播放器设置而烦恼吗?Tsukimi这款简单易用…...

用Python+OpenCV+SORT搞定高空抛物监测:从摄像头选型到代码调试的保姆级避坑指南

PythonOpenCVSORT高空抛物监测系统实战:从硬件选型到算法调优全解析 1. 项目背景与技术选型 高空抛物监测系统作为智慧社区建设的关键环节,面临着复杂的环境挑战。传统监控摄像头仅能记录画面,无法实现主动预警。而基于计算机视觉的智能分析…...

别再死记硬背了!用打王者荣耀掉帧的例子,5分钟搞懂视频编码里的I/P/B帧

游戏卡顿背后的秘密:用王者荣耀掉帧理解视频编码中的I/P/B帧 当你正沉浸在王者荣耀的激烈团战中,手指在屏幕上飞速滑动,准备释放关键技能时,画面突然卡顿——右上角的FPS数值从60骤降到20。这种令人抓狂的体验背后,隐藏…...

4种颠覆性组合:重构Pixelle-Video的模块化潜能

4种颠覆性组合:重构Pixelle-Video的模块化潜能 【免费下载链接】Pixelle-Video 🚀 AI 全自动短视频引擎 | AI Fully Automated Short Video Engine 项目地址: https://gitcode.com/GitHub_Trending/pi/Pixelle-Video 想象一下:输入&qu…...

Unity3D RPG游戏开发实战:从零搭建角色与场景交互系统(含源码)

1. Unity3D RPG游戏开发基础准备 第一次打开Unity3D时,很多人会被复杂的界面吓到。别担心,我们先从最基础的设置开始。我建议使用2021 LTS版本,这个版本稳定性好,社区支持也完善。安装完成后,记得在Hub里勾选"Wi…...

喜马拉雅音频下载终极指南:免费解锁付费内容的桌面神器

喜马拉雅音频下载终极指南:免费解锁付费内容的桌面神器 【免费下载链接】xmly-downloader-qt5 喜马拉雅FM专辑下载器. 支持VIP与付费专辑. 使用GoQt5编写(Not Qt Binding). 项目地址: https://gitcode.com/gh_mirrors/xm/xmly-downloader-qt5 你是否曾因网络…...

ARM P-Channel接口设计与低功耗SoC电源管理实践

1. ARM P-Channel接口深度解析在低功耗SoC设计中,电源管理接口的可靠性和时序一致性直接决定了系统的能效表现。ARM P-Channel作为专为电源管理设计的标准化接口协议,通过独特的四阶段握手机制,为设备与电源控制器之间建立了高效的状态协商通…...

基于Orange Pi 5 Plus与DEEPX栈的边缘AI部署实战指南

1. 项目概述:当一块开发板遇见AI大潮最近在深圳参加了一场关于人工智能硬件与边缘计算的行业峰会,感触颇深。会上,一款基于Orange Pi 5 Plus开发板打造的DEEPX人工智能产品,实实在在地吸引了我的目光。这不仅仅是又一款“开发板AI…...

L298N驱动模块进阶玩法:用Arduino实现直流电机的软启动、缓停与速度曲线控制

L298N驱动模块进阶玩法:用Arduino实现直流电机的软启动、缓停与速度曲线控制 在创客和嵌入式开发领域,直流电机的控制是基础但至关重要的技能。大多数初学者会从简单的正反转和调速开始,但当项目需要更精细的运动控制时,粗暴的启…...