使用Jenkins和单个模板部署多个Kubernetes组件
前言
在持续集成和部署中,我们通常需要部署多个实例或组件到Kubernetes集群中。通过Jenkins的管道脚本,我们可以自动化这个过程。在本文中,我将演示如何使用Jenkins Pipeline及单个YAML模板文件(.tpl
)来部署多个类似的Kubernetes组件,而不需要为每个组件提供单独的模板文件。
问题背景
参照:Jenkins Pipeline 脚本优化实践:从繁琐到简洁 批量生成 Kubernetes 部署模板:从 1 到20顺序模板
pipeline {agent none // Use none at the top level, each stage will define its own agent.environment {REGISTRY = "xxxx/master-metaspace"KUBE_CONFIG = "--namespace=master-metaspace --context=master"KUBE_YAML_PATH = "/home/jenkins/workspace/yaml/master-metaspace"// Assume that 'data' is defined elsewhere or injected as a parameter.BASE_WORKSPACE = "xxxxxxx" // 定义一个基础工作空间路径}stages {stage("GetCode") {agent { label "build01" }steps {script {checkout scm: [$class: 'GitSCM',branches: [[name: env.branchName]],extensions: [[$class: 'CloneOption', depth: 1, noTags: false, shallow: true]],userRemoteConfigs: [[credentialsId: 'xxxx', url: env.gitHttpURL]]]}}}stage("Docker Builds") {parallel {stage('Build dataloader-game-ucenter') {agent { label "build01" }when { environment name: 'dataloader', value: 'true' }steps {buildAndPushDockerImage("dataloader-game-ucenter", env.data, env.BASE_WORKSPACE)}}stage('Build datawriter-game-ucenter') {agent { label "build01" }when { environment name: 'datawriter', value: 'true' }steps {buildAndPushDockerImage("datawriter-game-ucenter", env.data, env.BASE_WORKSPACE)}}stage('Build game-ucenter') {agent { label "build01" }when { environment name: 'game-ucenter', value: 'true' }steps {buildAndPushDockerImage("game-ucenter", env.data, env.BASE_WORKSPACE)}}}}stage('Development Deployment') {parallel {stage("Deploy datawriter-game-ucenter") {when { environment name: 'datawriter-game-ucenter', value: 'true' }agent { label "huaweiyun-xx" }steps {deployToKubernetes("datawriter-game-ucenter")}}stage("Deploy dataloader-game-ucenter") {when { environment name: 'dataloader', value: 'true' }agent { label "huaweiyun-xx" }steps {deployToKubernetes("dataloader-game-ucenter")}}stage("Deploy game-ucenter") {when { environment name: 'game-ucenter', value: 'true' }agent { label "huaweiyun-xx" }steps {deployToKubernetes("game-ucenter-1")deployToKubernetes("game-ucenter-2")deployToKubernetes("game-ucenter-3")deployToKubernetes("game-ucenter-4")............................}}}}}
}// Define methods outside pipeline to avoid repetitiondef buildAndPushDockerImage(String imageName, String tag, String workspacePath) {sh "cd ${workspacePath} && echo 'Current directory: \$(pwd)'" // 使用基础工作空间变量sh "cd ${workspacePath}/${imageName}&& docker build --build-arg NODE_ENV=$imageName -t $REGISTRY/$imageName:$tag ."withCredentials([usernamePassword(credentialsId: 'xxxxx', passwordVariable: 'dockerPassword', usernameVariable: 'dockerUser')]) {sh "docker login -u $dockerUser -p $dockerPassword $REGISTRY"sh "docker push $REGISTRY/$imageName:$tag"}
}def deployToKubernetes(String kubernetesComponent) {String templateFile = "${KUBE_YAML_PATH}/${kubernetesComponent}.tpl"String outputFile = "${KUBE_YAML_PATH}/${kubernetesComponent}.yaml"sh "sed -e 's/{data}/$data/g' $templateFile > $outputFile"sh "sudo kubectl apply -f $outputFile $KUBE_CONFIG"
}
默认jenkins pipeline如上,我们有多个相似的游戏用户中心服务game-ucenter-*
运行在Kubernetes集群中,它们都使用非常相似的Kubernetes YAML配置文件,配置文件之间的差异主要是一些标识符的不同(例如,服务的序号)。在传统的做法中,维护一系列几乎一样的模板文件(如game-ucenter-1.tpl
, game-ucenter-2.tpl
等)将非常低效且易出错。
为了精简流程和提高效率,我们需要一个方法来通过单一模板生成多个配置文件,并由此部署多个不同的服务实例。
解决方案
使用Jenkins Pipeline中的sed
命令和循环结构,我们可以从单一模板生成多个Kubernetes配置文件,并相应地部署每个服务实例。参照generate_templates.sh脚本
#!/bin/bash# Define the name of the template file.
TEMPLATE_FILE="game-ucenter.tpl"# Check if the template file exists.
if [ ! -f "$TEMPLATE_FILE" ]; thenecho "Template file $TEMPLATE_FILE does not exist."exit 1
fi# Loop to create files from game-ucenter-2 to pvp-game-20 based on the template.
for i in $(seq 1 20); do# Define the name of the new file.NEW_FILE="game-ucenter-${i}.yaml"# Copy the template to the new file.cp $TEMPLATE_FILE $NEW_FILE# Use 'sed' to replace 'game-ucenter-1' with 'game-ucenter-N' and save inline (-i option).sed -i "s/game-ucenter/game-ucenter-${i}/g" $NEW_FILEecho "Created file: $NEW_FILE"
doneecho "All files created successfully."
步骤 1: 定义Jenkins Pipeline
在我们的Jenkins脚本中,我们首先定义了基础环境变量和两个函数:buildAndPushDockerImage
和 deployToKubernetes
。这些函数将用于构建Docker镜像并部署到Kubernetes
def buildAndPushDockerImage(String imageName, String tag, String workspacePath) {sh "cd ${workspacePath} && echo 'Current directory: \$(pwd)'" // 使用基础工作空间变量sh "cd ${workspacePath}/${imageName}&& docker build --build-arg NODE_ENV=$imageName -t $REGISTRY/$imageName:$tag ."withCredentials([usernamePassword(credentialsId: 'xxx', passwordVariable: 'dockerPassword', usernameVariable: 'dockerUser')]) {sh "docker login -u $dockerUser -p $dockerPassword $REGISTRY"sh "docker push $REGISTRY/$imageName:$tag"}
}def deployToKubernetes(String kubernetesComponent) {String templateFile = "${KUBE_YAML_PATH}/${kubernetesComponent}.tpl"String outputFile = "${KUBE_YAML_PATH}/${kubernetesComponent}.yaml"sh "sed -e 's/{data}/$data/g' $templateFile > $outputFile"sh "sudo kubectl apply -f $outputFile $KUBE_CONFIG"
}
步骤 2: 修改deployToKubernetes函数
接下来,我们需要修改deployToKubernetes
函数,以便它能够接受组件名称,并使用单一模板文件创建具体的配置文件。
def deployToKubernetes(String kubernetesComponent, int instance=1, int totalInstances=1) {// 检查实例值if (instance < 1) {error("实例数必须大于0")}// 根据 instance 的值来定义资源的名称和文件名String nameSuffix = totalInstances > 1 ? "-${instance}" : "" // 总是添加后缀,除非只有一个实例String outputFileName = "${kubernetesComponent}${nameSuffix}.yaml"String templateFile = "${KUBE_YAML_PATH}/${kubernetesComponent}.tpl"String outputFile = "${KUBE_YAML_PATH}/${outputFileName}"String nameReplacement = "${kubernetesComponent}${nameSuffix}"sh """cat "${templateFile}" \| sed 's/{data}/${data}/g' \| sed 's/name: ${kubernetesComponent}/name: ${nameReplacement}/g' \| sed 's/app: ${kubernetesComponent}/app: ${nameReplacement}/g' \> "${outputFile}""""// 使用 KUBE_CONFIG 应用 Kubernetes 配置sh "kubectl apply -f ${outputFile} ${KUBE_CONFIG}"
}
对于单实例的业务,例如Deploy dataloader-game-ucenter
,我们不需要传递实例编号。
stage("Deploy dataloader-game-ucenter") {when { environment name: 'dataloader', value: 'true' }agent { label "huaweiyun-xx" }steps {deployToKubernetes("dataloader-game-ucenter")}
}
对于多实例。我这里生成 规则优点强迫症了。如果多实例我生成的规则要求符合game-ucenter-1,game-ucenter-2,game-ucenter-3…顺序,当单个实例的时候则保持原来的不加标签:
stage("Deploy game-ucenter") {when { environment name: 'game-ucenter', value: 'true' }agent { label "k8s-node-06" }steps {script {int instances = 2 // 假设我们有2个实例for (int i = 1; i <= instances; i++) {def componentName = "game-ucenter"deployToKubernetes("game-ucenter", i, instances)}}}}
步骤 3: 准备模板文件
我们的模板文件game-ucenter.tpl
将包含通用的Kubernetes服务或部署定义,使用占位符game-ucenter-1
game-ucenter-2来标识应该被替换的地方。
# game-ucenter-1.tpl (示例部分)
apiVersion: apps/v1
kind: Deployment
metadata:name: game-ucenter
spec:replicas: 1strategy:rollingUpdate:maxSurge: 1maxUnavailable: 0selector:matchLabels:app: game-ucentertemplate:metadata:labels:app: game-ucenterspec:containers:- name: game-ucenterimage: xxxx/xxx/game-ucenter:{data}envFrom:- configMapRef:name: deployports:- containerPort: 80resources:requests:memory: "4096M"cpu: "2000m"limits:memory: "4096M"cpu: "2000m" livenessProbe:httpGet:scheme: HTTPpath: /test.htmlport: 80initialDelaySeconds: 20periodSeconds: 120successThreshold: 1failureThreshold: 3readinessProbe:httpGet:scheme: HTTPpath: /test.htmlport: 80initialDelaySeconds: 20periodSeconds: 120imagePullSecrets: - name: xxx
---apiVersion: v1
kind: Service
metadata:name: game-ucenterlabels:app: game-ucenter
spec:ports:- port: 80protocol: TCPtargetPort: 80selector:app: game-ucenter# ...
步骤 4: 执行Jenkins Pipeline
当Jenkins Pipeline运行到"Development Deployment"阶段时,它将循环创建和应用game-ucenter-1.yaml
到game-ucenter-2.yaml
的配置文件,从而部署2个game-ucenter
deployment服务实例。
并保证单个实例的原有命名规则:
通过这一方法,我们不再需要为每个服务实例维护一个单独的模板文件,而是可以通过一个模板文件和Jenkins Pipeline的自动化来简化服务部署工作。这样做不仅提升了效率,也降低了出错的风险。
注意:
以上代码和命令为示例性质,可能需要根据您具体的Jenkins环境和Kubernetes集群进行相应的调整。在生产环境中部署之前,请确保进行充分的测试。
相关文章:
使用Jenkins和单个模板部署多个Kubernetes组件
前言 在持续集成和部署中,我们通常需要部署多个实例或组件到Kubernetes集群中。通过Jenkins的管道脚本,我们可以自动化这个过程。在本文中,我将演示如何使用Jenkins Pipeline及单个YAML模板文件(.tpl)来部署多个类似的…...
Unity Meta Quest 一体机开发(十二):【手势追踪】Poke 交互 - 用手指点击由 3D 物体制作的 UI 按钮
文章目录 📕教程说明📕给玩家配置 HandPokeInteractor📕用 3D 物体制作可以被点击的 UI 按钮⭐搭建物体层级⭐给物体添加脚本⭐为脚本变量赋值 📕模仿官方样例按钮的样式📕在按钮上添加文字📕修改按钮图片 …...
Vue 3 中安装并使用 Axios 详细步骤+样例代码详解
axios详细步骤 在集成终端打开,使用 npm 或 yarn 安装 Axios: npm install axios或 yarn add axios这将在您的项目中安装 Axios。 在您的 Vue 3 项目中创建一个用于发送 HTTP 请求的模块或文件,比如 http.js。 在 http.js 文件中导入 Axios…...
IDEA 控制台中文出现乱码问题解决
一、问题概述 请看下图 二、问题分析 IDEA控制台输出乱码一般会有三种来源: ① IDEA本身编码错误 ② Tomcat日志输出编码错误 ③ 项目本身原因。 终极原因:IDEA编码和Tomcat编码不一致,统一设置为UTF-8即可。 三、解决思路 修改…...
计算机网络(1)
计算机网络(1) 小程一言专栏链接: [link](http://t.csdnimg.cn/ZUTXU) 计算机网络和因特网(1)因特网概念解读服务常见的服务 协议网络边缘特点强调 网络核心特点强调 小程一言 我的计算机网络专栏,是自己在计算机网络…...
如果我想用python自动操作手机、电脑软件,应该学python哪方面的知识呢?
Python 作为一门万能语言,在各方面的表现都非常好 如果我们想使用 Python 来操作手机和电脑,那么需要学习掌握如下几个方面的知识 1. 基本的Python编程 显而易见,你需要学习Python的基本语法、数据类型、控制流和函数等基本概念。这是后面…...
关于java命令行传参
关于java命令行传参 本篇文章拓展以下java中的命令行传参😎 有时候你希望运行一个程序的时候再传递给它消息,这要靠传递命令行参数给main()方法来实现。首先我们先来创建一个数组遍历。 public class Demo {public static void main(String[] args){/…...
[LeetCode][Python]389. 找不同
简单 给定两个字符串 s 和 t ,它们只包含小写字母。 字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。 请找出在 t 中被添加的字母。 示例 1: 输入:s "abcd", t "abcde" 输出:"…...
鸿蒙崛起:互联网大厂加速鸿蒙原生应用开发,人才争夺战打响
随着华为鸿蒙系统的发布和不断推进,一场以鸿蒙为中心的生态竞争已经拉开帷幕。近日,网易、美团等多家互联网公司发布了与鸿蒙系统有关的岗位招聘,加速推进鸿蒙原生应用开发转型。这种趋势表明,鸿蒙系统已经引起了行业的广泛关注&a…...
OR-NeRF论文笔记
OR-NeRF论文笔记 文章目录 OR-NeRF论文笔记论文概述Abstract1 Introduction2 Related Work3 Background4 Method4.1 Multiview Segmentation4.2 Scene Object Removal 5 ExperimentsDatasetsMetricsMultiview SegmentationScene Object Removal 6 Conclusion 论文概述 目的&am…...
【web】vue 播放后端(flask)发送的 mp3 文件
文章目录 演示后端(flask)前端(vue3)重要说明 演示 后端(flask) 后端返回的是 mp3 文件的 url,是可以直接在浏览器上打开后播放的处理跨域请求pip install flask-cors后端代码from flask impor…...
vmware安装openEuler 22.03 LTS操作系统
vmware安装openEuler 22.03 LTS操作系统 1、下载openEuler操作系统镜像文件2、安装openEuler操作系统3、配置openEuler操作系统3.1、配置静态IP地址 和 dns3.2、查看磁盘分区3.3、查看系统版本 1、下载openEuler操作系统镜像文件 官网下载链接 链接: https://www.openeuler.or…...
Android registerForActivityResult
startActivityForResult 已经被标记为不推荐的方法,推荐的替代方案是使用 registerForActivityResult: // Activity 的 onCreate 方法中调用 registerForActivityResult val activityResultLauncher registerForActivityResult(ActivityResultContract…...
【CSS】布局方式梳理和总结
1. 前言 网页布局是CSS的重点功能,布局的传统方案是基于盒子模型,依靠display属性、position属性和float属性,它对一些特殊布局很麻烦。 CSS3推出的Flex布局和网格布局,让开发者更容易定制自己想要的布局。本篇梳理和总结一些布局…...
PHP计算某时间段内有几个周及某时间为今年第几周函数
date_default_timezone_set(PRC); function count_weeks($startDate, $endDate ){//开始时间$startDate date(Y-m-d, $startDate);//结束时间if(empty($endDate)) {$endDate date(Y-m-d);}else{$endDate date(Y-m-d, $endDate);}//跨越天数$n (strtotime($endDate)-strtot…...
华为无线AC内三层漫游配置详解
重要说明 1、在一台ac中实现三层漫游 2、ac和核心的互联vlan和ap的管理vlan是同一个广播域,可以不用配option 43 3、直接转发模式,ac上可以不起业务vlan,ac和核心交换机上可以只放行一个互联vlan 10 4、ac上要启两个vap魔板,两个…...
GPT-5、开源、更强的ChatGPT!OpenAI公布2024年计划
年终岁尾,正值圣诞节热闹气氛的OpenAI写下了2024年的发展清单。 OpenAI联合创始人兼首席执行官Sam Altman在社交平台公布,AGI(稍晚一些)、GPT-5、更好的语音模型、更高的费率限制; 更好的GPTs;更好的推理…...
java idea中做一个简易的图书管理系统(控制台输入输出,无数据库)
1:先创建增删改查四个接口 (1)QueryBook查询接口 package com.by.dao;import com.by.entity.Book;public interface QueryBook {/*** 查询所有图书信息* param bs*/void selectBook(Book[] bs);/*** 根据名字查询一个图书信息* param bookN…...
C# PrinterSettings修改打印机纸张类型,paperType
需求:直接上图,PrinterSettings只能改变纸张大小,打印质量,无法更改打印纸类型 爱普生打印机打印照片已经设置了最高质量,打印图片仍不清晰,需要修改打印纸类型,使用PrintDialog调出对话框&…...
TV端Web页面性能优化实践
01 背景 随着互联网技术的持续创新和电视行业的高速发展,通过电视观看在线视频已经逐渐成为大众的重要娱乐方式。奇异果App作为在TV设备上用户活跃度最高的应用之一,为广大用户提供了丰富的内容播放服务,除此之外,同样有会员运营、…...
2023年终总结
前言: 嘻嘻,12月底广州降温了又到了写年终总结的时间,这也是我第二年写年终总结。今年的年终总结主要记录了我大三下学期和大四上学期这两个时间段的学习和收获,也是我尝试走出校园,接触社会的第一年(感触…...
深入探索MongoDB集群模式:从高可用复制集
MongoDB复制集概述 MongoDB复制集主要用于实现服务的高可用性,与Redis中的哨兵模式相似。它的核心作用是数据的备份和故障转移。 复制集的主要功能 数据复制:数据写入主节点(Primary)时,自动复制到一个或多个副本节…...
gem5学习(8):创建一个简单的缓存对象--Creating a simple cache object
目录 一、SimpleCache SimObject 二、Implementing the SimpleCache 1、getSlavePort() 2、handleRequest() 3、AccessEvent() 4、accessTiming() (1)缓存命中:sendResponse() (2)缓存未命中: 三、…...
【PTA-C语言】实验七-函数与指针I
如果代码存在问题,麻烦大家指正 ~ ~有帮助麻烦点个赞 ~ ~ 目录——实验七-函数与指针I 6-1 弹球距离(分数 10)6-2 使用函数输出一个整数的逆序数(分数 10)6-3 使用函数求最大公约数(分数 10)6-4…...
C# 让数据保留小数后两位,不足的补充0
在C#中,可以使用Math.Floor、Math.Ceiling或者Math.Round方法结合字符串格式化来实现小数点后两位的保留,并在不足的情况下补充0。 以下是一个例子: double value 1.2345; string formattedValue value.ToString("0.00"); // 输…...
RK3568驱动指南|第九篇 设备模型-第92章 引用计数器实验
瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工…...
苹果电脑Dock栏优化软件 mac功能亮点
hyperdock mac是一款Dock优化软件,hyperdock支持使用窗口自动排列功能,您可以直接通过将窗口拖拉至屏幕上方来快速最大化至全屏,又或者拖动到左右来进行左分屏和右分屏。而且Dock优化软件还有一个特色便是对Dock的强大管理哪里能力࿰…...
【UE5蓝图】读取本地json文件修改窗口大小
效果 插件 蓝图 1.判断文件存在 2.1文件不存在,生成文件 {"ResolutionX":540, "ResolutionY":960} 2.2文件存在,直接读取 3.设置窗口大小 遇到的坑 1.分辨率太大,导致效果不理想,建议先往小填写。 2.选对…...
ACM32F403/F433 12 位多通道国产芯片,支持 MPU 存储保护功能,应用于工业控制,智能家居等产品中
ACM32F403/F433 芯片的内核基于 ARMv8-M 架构,支持 Cortex-M33 和 Cortex-M4F 指令集。芯片内核 支持一整套DSP指令用于数字信号处理,支持单精度FPU处理浮点数据,同时还支持Memory Protection Unit (MPU)用于提升应用的…...
2024最新前端React面试题:JSX是什么,它和JS有什么区别
JSX是什么,它和JS有什么区别 回答思路:1.编写方式--->2.分别是什么?--->3.分别是怎么编译的?1.编写方式2.分别是什么?3.分别是怎么编译的? 回答思路:1.编写方式—>2.分别是什么&#x…...
不懂网站怎么做平台/厦门站长优化工具
web前端群,189394454,有视频、源码、学习方法等大量干货分享效果知识点: 企业布局思维的巧妙运用, DIV加CSS,css样式拆解与归类,css3过度与阴影,定位与动,常用如何搭配,开发标准。👇…...
万网买好域名后如何开通网站/百度网络营销中心
页面的打开速度对网站的优化有极大的意义,如果打开一个页面一直处于白屏状态,若超过5s,可能大部份人都会把它关了。或者是页面加载出来了,但是比较慢,页面显示不完整,标签栏一直在转圈,页面长期…...
北京 房地产 网站建设/sem推广竞价
jdk7及以前: 通过-XX:PermSize 来设置永久代初始分配空间,默认值是20.75m -XX:MaxPermSize来设定永久代最大可分配空间,32位是64m,64位是82m jdk8及之后: 通过-XX:MetaspaceSize 来设置永久代初始分配空间ÿ…...
长沙网络营销推广公司/广州网站制作实力乐云seo
首先, clone 一个远端仓库,到其目录下: $ Git clone git://example.com/myproject $ cd myproject 然后,看看你本地有什么分支: $ git branch * master 但是有些其他分支你在的仓库里面是隐藏的,你可以加上-…...
西安建网站价格低/网络营销服务的内容
这里的移位寄存器不是简单的向左移位将串行输入转换为并行输出,而且要保留最后一个周期的输入数作为下一次输出的最高位,代码如下所示: module shift_reg(clk,rst,din,dout//,ordy);input clk;input rst;input [7:0] din;output [31:0] dout…...
伊春网站推广/一键优化
根据参考一些网络资料收集整理:因为使用代码添加的 每一次添加一个控件容器控件内部都做了自动计算 主要在这两句代码headerRow.Cells.Add(headerCell);detailRow.Cells.Add(detailCell);向XRTableRow 添加 XRTableCell 第一次新添加的会XRTableCell会以XRTableRow 的宽度值第二…...