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流水线: 风哥提示:
kubectl create namespace devops
namespace/devops created
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
kubectl get pods -n devops
NAME READY STATUS RESTARTS AGE
jenkins-6b8d9b8c7f-abcde 1/1 Running 0 10s
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
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 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
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
# 在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
java -version
openjdk version “1.8.0_292”
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”配置
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
kubectl get deployment myapp -n staging
NAME READY UP-TO-DATE AVAILABLE AGE
myapp 0/2 0 0 10m
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
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
