1. 首页 > KubeSphere教程 > 正文

KubeSphere教程FG041-KubeSphere CI-CD流水线参数化构建实战

本教程详细介绍KubeSphere中CI-CD流水线参数化构建的实战操作,包括基础概念、生产环境规划、具体实施方案和实战案例。风哥教程参考KubeSphere官方文档KubeSphere容器平台使用指南、KubeSphere DevOps指南、Jenkins Pipeline指南等相关内容。

目录大纲

Part01-基础概念与理论知识

1.1 CI-CD核心概念

CI-CD是指持续集成和持续部署,它包括:

  • 持续集成(CI):频繁地将代码集成到主干分支
  • 持续部署(CD):自动将代码部署到生产环境
  • 持续交付:确保代码随时可以部署
  • 自动化测试:自动执行测试
  • 自动化部署:自动执行部署

1.2 参数化构建核心概念

参数化构建是指使用参数来控制构建过程,它包括:

  • 字符串参数:字符串类型的参数
  • 布尔参数:布尔类型的参数
  • 选择参数:选择类型的参数
  • 文件参数:文件类型的参数
  • 密码参数:密码类型的参数

1.3 流水线核心概念

流水线是指将构建过程分解为多个阶段,它包括:

  • 阶段:流水线的一个阶段
  • 步骤:阶段中的一个步骤
  • 并行:并行执行多个步骤
  • 串行:串行执行多个步骤
  • 条件:根据条件执行步骤

Part02-生产环境规划与建议

2.1 CI-CD架构规划

在实施CI-CD流水线参数化构建时,CI-CD架构规划是非常重要的:

  • 代码仓库选择:选择合适的代码仓库
  • 构建工具选择:选择合适的构建工具
  • 测试工具选择:选择合适的测试工具
  • 部署工具选择:选择合适的部署工具
  • 监控工具选择:选择合适的监控工具

2.2 参数化构建规划

参数化构建规划对于CI-CD流水线参数化构建也非常重要:

  • 参数设计:设计合理的参数
  • 参数验证:验证参数的有效性
  • 参数默认值:设置参数的默认值
  • 参数权限:设置参数的访问权限
  • 参数文档:编写参数文档

2.3 流水线规划

流水线规划是CI-CD流水线参数化构建的重要组成部分:

  • 阶段设计:设计流水线的阶段
  • 步骤设计:设计流水线的步骤
  • 并行设计:设计并行执行的步骤
  • 条件设计:设计条件执行的步骤
  • 错误处理:设计错误处理机制

Part03-生产环境项目实施方案

3.1 CI-CD配置

CI-CD的配置步骤:

  • 启用DevOps功能:启用KubeSphere DevOps功能
  • 配置代码仓库:配置Git仓库
  • 配置镜像仓库:配置Docker镜像仓库
  • 配置构建工具:配置Maven、Gradle等构建工具
  • 配置部署工具:配置Kubernetes部署工具

3.2 参数化构建配置

参数化构建的配置步骤:

  • 创建参数:创建构建参数
  • 配置参数类型:配置参数的类型
  • 配置参数默认值:配置参数的默认值
  • 配置参数验证:配置参数的验证规则
  • 测试参数化构建:测试参数化构建

3.3 流水线配置

流水线的配置步骤:

  • 创建流水线:创建Jenkins流水线
  • 配置流水线阶段:配置流水线的阶段
  • 配置流水线步骤:配置流水线的步骤
  • 配置流水线触发器:配置流水线的触发器
  • 测试流水线:测试流水线是否正常工作

Part04-生产案例与实战讲解

4.1 CI-CD流水线实战

下面我们来实战演示CI-CD流水线: 风哥提示:

# 创建DevOps项目
kubectl create namespace devops
namespace/devops created
# 创建Jenkins实例
cat <<EOF | kubectl apply -f –
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins
namespace: devops

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: jenkins
namespace: devops
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: admin
subjects:
– kind: ServiceAccount
name: jenkins
namespace: devops

apiVersion: apps/v1
kind: Deployment
metadata:

name: jenkins
namespace: devops
spec:
replicas: 1
selector:
matchLabels:
app: jenkins
template:
metadata:
labels:
app: jenkins
spec:
serviceAccountName: jenkins
containers:
– name: jenkins
image: jenkins/jenkins:lts
ports:
– containerPort: 8080
– containerPort: 50000
volumeMounts:
– name: jenkins-home
mountPath: /var/jenkins_home
volumes:
– name: jenkins-home
emptyDir: {}

apiVersion: v1
kind: Service
metadata:
name: jenkins
namespace: devops
spec:
selector:
app: jenkins
ports:
– port: 8080
targetPort: 8080
name: http
– port: 50000
targetPort: 50000
name: agent
type: LoadBalancer
EOF
serviceaccount/jenkins created
rolebinding.rbac.authorization.k8s.io/jenkins created
deployment.apps/jenkins created
service/jenkins created
# 查看Jenkins状态
kubectl get pods -n devops
NAME READY STATUS RESTARTS AGE
jenkins-6b8d9b8c7f-abcde 1/1 Running 0 10s
# 获取Jenkins初始密码
kubectl exec -n devops jenkins-6b8d9b8c7f-abcde — cat /var/jenkins_home/secrets/initialAdminPassword
abc123def456789012345678901234567890
# 创建流水线
cat <<EOF > Jenkinsfile
pipeline {
agent any

parameters {
string(name: ‘BRANCH_NAME’, defaultValue: ‘main’, description: ‘Git branch name’)
choice(name: ‘ENVIRONMENT’, choices: [‘dev’, ‘staging’, ‘production’], description: ‘Deployment environment’)
booleanParam(name: ‘RUN_TESTS’, defaultValue: true, description: ‘Run tests’)
booleanParam(name: ‘DEPLOY’, defaultValue: true, description: ‘Deploy application’)
}

stages {
stage(‘Checkout’) {
steps {
git branch: params.BRANCH_NAME, url: ‘https://github.com/example/app.git’
}
}

stage(‘Build’) {
steps {
sh ‘mvn clean package’
}
}

stage(‘Test’) {
when {
expression { params.RUN_TESTS }
}
steps {
sh ‘mvn test’
}
}

stage(‘Docker Build’) {
steps {
sh “docker build -t myapp:${BUILD_NUMBER} .”
}
}

stage(‘Docker Push’) {
steps {
sh “docker tag myapp:${BUILD_NUMBER} registry.example.com/myapp:${BUILD_NUMBER}”
sh “docker push registry.example.com/myapp:${BUILD_NUMBER}”
}
}

stage(‘Deploy’) {

when {
expression { params.DEPLOY }
}
steps {
sh “kubectl set image deployment/myapp myapp=registry.example.com/myapp:${BUILD_NUMBER} -n ${params.ENVIRONMENT}”
}
}
}

post {
success {
echo ‘Pipeline succeeded!’
}
failure {
echo ‘Pipeline failed!’
}
}
}
EOF

# 提交Jenkinsfile到代码仓库
git add Jenkinsfile
git commit -m “Add Jenkinsfile”
git push origin main
[main abc123def] Add Jenkinsfile
1 file changed, 50 insertions(+)
create mode 100644 Jenkinsfile
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 1.2 KiB | 1.2 MiB/s, done.
Total 4 (delta 1), reused 0 (delta 0)
To https://github.com/example/app.git
abc123def..fghij456 main -> main
# 在Jenkins中创建流水线任务
# 访问Jenkins UI: http://jenkins.devops.svc.cluster.local:8080
# 使用初始密码登录
# 创建新的Pipeline任务
# 配置Pipeline definition为Pipeline script from SCM
# 配置SCM为Git
# 配置Repository URL为https://github.com/example/app.git
# 配置Script Path为Jenkinsfile

4.2 参数化构建实战

下面我们来实战演示参数化构建: 学习交流加群风哥微信: itpux-com 学习交流加群风哥QQ113257174

# 触发参数化构建
# 在Jenkins UI中点击”Build with Parameters”
# 配置参数:
# BRANCH_NAME: develop
# ENVIRONMENT: staging
# RUN_TESTS: true
# DEPLOY: true
# 点击”Build”
# 查看构建日志
# 在Jenkins UI中点击构建编号
# 点击”Console Output”
Started by user admin
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /var/jenkins_home/workspace/myapp
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Checkout)}
[Pipeline] git
Cloning repository https://github.com/example/app.git
> git init /var/jenkins_home/workspace/myapp # timeout=10
Fetching upstream changes from https://github.com/example/app.git
> git –version # timeout=10
> git –version # timeout=10
> git fetch –tags –force –progress — https://github.com/example/app.git +refs/heads/*:refs/remotes/origin/* # timeout=10
> git config remote.origin.url https://github.com/example/app.git # timeout=10
> git config –add remote.origin.fetch +refs/heads/*:refs/remotes/origin/* # timeout=10
> git config remote.origin.url https://github.com/example/app.git # timeout=10
> git rev-parse –verify HEAD # timeout=10
No valid HEAD. Skipping resetting FETCH_HEAD.
> git fetch –tags –force –progress — https://github.com/example/app.git +refs/heads/develop:refs/remotes/origin/develop # timeout=10
> git config core.sparsecheckout # timeout=10
> git checkout -f abc123def456789012345678901234567890
HEAD is now at abc123def Add Jenkinsfile
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Build)}
[Pipeline] sh
+ mvn clean package
[INFO] Scanning for projects…
[INFO]
[INFO] ———————< com.example:app:1.0.0 ---------------------
[INFO] Building myapp 1.0.0
[INFO] ——————————–[ jar ]———————————
[INFO]
[INFO] — maven-clean-plugin:3.1.0:clean (default-clean) @ app —
[INFO] Deleting /var/jenkins_home/workspace/myapp/target
[INFO]
[INFO] — maven-resources-plugin:3.0.2:resources (default-resources) @ app —
[INFO] Using ‘UTF-8’ encoding to copy filtered resources.

[INFO] Copying 1 resource
[INFO]
[INFO] — maven-compiler-plugin:3.8.0:compile (default-compile) @ app —
[INFO] Changes detected – recompiling the module!
[INFO] Compiling 1 source file to /var/jenkins_home/workspace/myapp/target/classes
[INFO]
[INFO] — maven-resources-plugin:3.0.2:testResources (default-testResources) @ app —
[INFO] Using ‘UTF-8’ encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /var/jenkins_home/workspace/myapp/src/test/resources
[INFO]
[INFO] — maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ app —
[INFO] No sources to compile
[INFO]
[INFO] — maven-surefire-plugin:2.22.1:test (default-test) @ app —
[INFO] No tests to run.
[INFO]
[INFO] — maven-jar-plugin:3.0.2:jar (default-jar) @ app —
[INFO] Building jar: /var/jenkins_home/workspace/myapp/target/app-1.0.0.jar
[INFO] ————————————————————————
[INFO] BUILD SUCCESS
[INFO] ————————————————————————
[INFO] Total time: 5.123 s
[INFO] Finished at: 2024-01-01T00:00:00Z
[INFO] ————————————————————————
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Test)}
[Pipeline] sh
+ mvn test
[INFO] Scanning for projects…
[INFO]
[INFO] ———————< com.example:app:1.0.0 ---------------------
[INFO] Building myapp 1.0.0
[INFO] ——————————–[ jar ]———————————
[INFO]
[INFO] — maven-surefire-plugin:2.22.1:test (default-test) @ app —
[INFO] No tests to run.
[INFO]
[INFO] ————————————————————————
[INFO] BUILD SUCCESS
[INFO] ————————————————————————
[INFO] Total time: 2.345 s
[INFO] Finished at: 2024-01-01T00:00:05Z
[INFO] ————————————————————————
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Docker Build)}
[Pipeline] sh
+ docker build -t myapp:1 .
Sending build context to Docker daemon 123.4kB
Step 1/5 : FROM openjdk:11-jre-slim
—> abc123def456
Step 2/5 : WORKDIR /app
—> Running in 1234567890ab
Removing intermediate container 1234567890ab
—> fghij456789
Step 3/5 : COPY target/app-1.0.0.jar app.jar
—> abc123def456
Step 4/5 : EXPOSE 8080
—> Running in 2345678901bc
Removing intermediate container 2345678901bc
—> 3456789012cd
Step 5/5 : ENTRYPOINT [“java”,”-jar”,”app.jar”]
—> Running in 4567890123de
Removing intermediate container 4567890123de
—> 5678901234ef
Successfully built 5678901234ef
Successfully tagged myapp:1
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Docker Push)}
[Pipeline] sh
+ docker tag myapp:1 registry.example.com/myapp:1
+ docker push registry.example.com/myapp:1
The push refers to repository [registry.example.com/myapp]
abc123def456: Pushed
fghij456789: Pushed
1: digest: sha256:abc123def456789012345678901234567890123456789012345678901234567890 size: 1234
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Deploy)}
[Pipeline] sh
+ kubectl set image deployment/myapp myapp=registry.example.com/myapp:1 -n staging
deployment.apps/myapp image updated
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Pipeline succeeded!
Finished: SUCCESS
# 验证部署
kubectl get pods -n staging -l app=myapp
NAME READY STATUS RESTARTS AGE
myapp-6b8d9b8c7f-abcde 1/1 Running 0 10s
myapp-6b8d9b8c7f-fghij 1/1 Running 0 10s

4.3 流水线优化实战

下面我们来实战演示流水线优化: 更多视频教程www.fgedu.net.cn

# 创建优化后的Jenkinsfile
cat <<EOF > Jenkinsfile.optimized

pipeline {
agent any

options {
buildDiscarder(logRotator(numToKeepStr: ’10’))
disableConcurrentBuilds()
timeout(time: 30, unit: ‘MINUTES’)
}

parameters {
string(name: ‘BRANCH_NAME’, defaultValue: ‘main’, description: ‘Git branch name’)
choice(name: ‘ENVIRONMENT’, choices: [‘dev’, ‘staging’, ‘production’], description: ‘Deployment environment’)
booleanParam(name: ‘RUN_TESTS’, defaultValue: true, description: ‘Run tests’)
booleanParam(name: ‘DEPLOY’, defaultValue: true, description: ‘Deploy application’)
string(name: ‘IMAGE_TAG’, defaultValue: ”, description: ‘Docker image tag (empty for BUILD_NUMBER)’)
}

environment {
DOCKER_REGISTRY = ‘registry.example.com’
APP_NAME = ‘myapp’
IMAGE_TAG = params.IMAGE_TAG ?: “${BUILD_NUMBER}”
}

stages {
stage(‘Checkout’) {
steps {
checkout scm
}
}

stage(‘Build’) {
steps {
sh ‘mvn clean package -DskipTests’
}
}

stage(‘Test’) {
parallel {
stage(‘Unit Tests’) {
when {
expression { params.RUN_TESTS }
}
steps {
sh ‘mvn test’
}
}
stage(‘Integration Tests’) {
when {
expression { params.RUN_TESTS }
}
steps {
sh ‘mvn verify -DskipUnitTests’
}
}
}
}

stage(‘Docker Build’) {
steps {
script {
docker.build(“${APP_NAME}:${IMAGE_TAG}”)
}
}
}

stage(‘Docker Push’) {
steps {
script {
docker.withRegistry(“https://${DOCKER_REGISTRY}”, ‘docker-registry-credentials’) {
docker.image(“${APP_NAME}:${IMAGE_TAG}”).push()
docker.image(“${APP_NAME}:${IMAGE_TAG}”).push(‘latest’)
}
}
}
}

stage(‘Security Scan’) {
steps {
script {
docker.image(‘aquasec/trivy:latest’).inside {
sh “trivy image –severity HIGH,CRITICAL ${DOCKER_REGISTRY}/${APP_NAME}:${IMAGE_TAG}”
}
}
}
}

stage(‘Deploy’) {
when {
expression { params.DEPLOY }
}
steps {
script {
kubernetesDeploy(
configs: ‘k8s/deployment.yaml’,
kubeconfigId: ‘kubernetes-config’,
enableConfigSubstitution: true
)
}
}
}

stage(‘Smoke Test’) {
when {
expression { params.DEPLOY }
}
steps {
script {
sleep(30)
sh “kubectl get pods -n ${params.ENVIRONMENT} -l app=${APP_NAME}”
}
}
}

}

post {
always {
cleanWs()
}
success {
echo ‘Pipeline succeeded!’
emailext (
subject: “Build Success: ${env.JOB_NAME} – ${env.BUILD_NUMBER}”,
body: “Build succeeded. Check ${env.BUILD_URL}”,
to: ‘team@example.com’
)
}
failure {
echo ‘Pipeline failed!’
emailext (
subject: “Build Failed: ${env.JOB_NAME} – ${env.BUILD_NUMBER}”,
body: “Build failed. Check ${env.BUILD_URL}”,
to: ‘team@example.com’
)
}
}
}
EOF

# 配置Webhook触发器
# 在GitHub仓库中配置Webhook
# Payload URL: http://jenkins.devops.svc.cluster.local:8080/github-webhook/
# Content type: application/json
# Secret: your-secret-token
# Events: Push, Pull Request
# 配置定时构建
# 在Jenkinsfile中添加triggers配置
triggers {
cron(‘H H(0-2) * * *’) // 每天凌晨0点到2点之间执行
}

Part05-风哥经验总结与分享

5.1 常见问题与解决方案

问题1:流水线构建失败

现象:流水线执行过程中出现错误 更多学习教程公众号风哥教程itpux_com

原因:代码错误、依赖问题或配置错误

解决方案:

# 查看构建日志
# 在Jenkins UI中点击构建编号
# 点击”Console Output”
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project app: Fatal error compiling: invalid target release: 11 -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project app: Fatal error compiling: invalid target release: 11
# 检查JDK版本
java -version
openjdk version “1.8.0_292”
# 安装JDK 11
apt-get update && apt-get install -y openjdk-11-jdk
Reading package lists… Done
Building dependency tree… Done
Reading state information… Done
The following additional packages will be installed:

Setting up openjdk-11-jdk (11.0.11+9-0ubuntu2~20.04) …

问题2:参数化构建不生效

现象:参数化构建的参数没有生效

原因:参数配置错误或参数传递失败

解决方案:

# 检查参数配置
# 在Jenkins UI中点击”Configure”
# 检查”Build with Parameters”配置
# 检查Jenkinsfile中的参数引用
cat Jenkinsfile | grep “params.”
string(name: ‘BRANCH_NAME’, defaultValue: ‘main’, description: ‘Git branch name’)
choice(name: ‘ENVIRONMENT’, choices: [‘dev’, ‘staging’, ‘production’], description: ‘Deployment environment’)
booleanParam(name: ‘RUN_TESTS’, defaultValue: true, description: ‘Run tests’)
booleanParam(name: ‘DEPLOY’, defaultValue: true, description: ‘Deploy application’)
git branch: params.BRANCH_NAME, url: ‘https://github.com/example/app.git’
expression { params.RUN_TESTS }
expression { params.DEPLOY }
sh “kubectl set image deployment/myapp myapp=registry.example.com/myapp:${BUILD_NUMBER} -n ${params.ENVIRONMENT}”

问题3:部署失败

现象:应用部署到Kubernetes失败

原因:Kubernetes配置错误或权限不足

解决方案: from K8S+DB视频:www.itpux.com

# 检查Kubernetes配置
kubectl get deployment myapp -n staging
NAME READY UP-TO-DATE AVAILABLE AGE
myapp 0/2 0 0 10m
# 查看Pod状态
kubectl get pods -n staging -l app=myapp
NAME READY STATUS RESTARTS AGE
myapp-6b8d9b8c7f-abcde 0/1 ImagePullBackOff 0 10s
myapp-6b8d9b8c7f-fghij 0/1 ImagePullBackOff 0 10s
# 查看Pod事件
kubectl describe pod myapp-6b8d9b8c7f-abcde -n staging | grep -A 10 Events
Events:
Type Reason Age From Message
—- —— —- —- ——-
Normal Scheduled 10s default-scheduler Successfully assigned staging/myapp-6b8d9b8c7f-abcde to node1
Normal Pulling 9s kubelet Pulling image “registry.example.com/myapp:1”
Warning Failed 8s kubelet Failed to pull image “registry.example.com/myapp:1”: rpc error: code = Unknown desc = Error response from daemon: pull access denied for myapp, repository does not exist or may require ‘docker login’

5.2 最佳实践建议

建议1:合理设计流水线

在设计流水线时,应该:

  • 将流水线分解为多个阶段
  • 使用并行执行提高效率
  • 使用条件执行控制流程
  • 设置合理的超时时间
  • 配置错误处理机制

建议2:合理使用参数化构建

在使用参数化构建时,应该:

  • 设计合理的参数类型
  • 设置参数的默认值
  • 验证参数的有效性
  • 编写参数文档
  • 定期审查和优化参数

建议3:建立完善的测试体系

在建立测试体系时,应该:

  • 编写单元测试
  • 编写集成测试
  • 编写端到端测试
  • 使用自动化测试工具
  • 定期审查和优化测试

5.3 性能优化技巧

技巧1:优化构建速度

构建速度的优化可以通过以下方式实现:

  • 使用缓存
  • 并行执行任务
  • 优化依赖管理
  • 使用增量构建
  • 优化Docker镜像

技巧2:优化部署速度

部署速度的优化可以通过以下方式实现:

  • 使用滚动更新
  • 使用蓝绿部署
  • 优化镜像大小
  • 使用本地镜像缓存
  • 优化Kubernetes配置

技巧3:优化流水线性能

流水线性能的优化可以通过以下方式实现:

  • 使用分布式构建
  • 优化资源分配
  • 使用构建缓存
  • 优化日志输出
  • 定期清理构建历史

CI-CD流水线参数化构建是KubeSphere DevOps的重要组成部分,需要根据实际业务需求进行合理规划和配置。在生产环境中,建议建立完善的测试体系和监控体系,以确保代码质量和部署稳定性。同时,要定期优化流水线性能,提高构建和部署效率。

本教程由风哥提供,更多KubeSphere实战教程请关注风哥课堂

本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html

联系我们

在线咨询:点击这里给我发消息

微信号:itpux-com

工作日:9:30-18:30,节假日休息