续——基于Jenkins构建微服务发布平台-1
4 流水线自动发布微服务项目
4.4 Docker阿里云镜像加速失效解决方案
在所有节点上执行。
# tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://do.nark.eu.org",
"https://dc.j8.work",
"https://docker.m.daocloud.io",
"https://dockerproxy.com",
"https://docker.mirrors.ustc.edu.cn",
"https://docker.nju.edu.cn"
],
"exec-opts": ["native.cgroupdriver=systemd"],
"insecure-registries": ["172.16.1.61"]
}
EOF
# systemctl daemon-reload
# systemctl restart docker
4.5 将 k8s-master1 上的 maven cache 复制到 k8s-node1、k8s-node2 节点上
[root@k8s-master1 ~]# scp -rp /root/.m2/ root@172.16.1.83:/root/
[root@k8s-master1 ~]# scp -rp /root/.m2/ root@172.16.1.84:/root/
4.6 微服务配置修改
1 由于镜像无法从互联网拉取,将镜像推送到本地公共镜像仓库
[root@k8s-master1 ~]# docker tag java:8-jdk-alpine 172.16.1.61/library/java:8-jdk-alpine
[root@k8s-master1 ~]# docker push 172.16.1.61/library/java:8-jdk-alpine
2 修改所有微服务文件夹中 Dockerfile 的基础镜像源
[root@k8s-master1 ~]# cd ms/simple-microservice/
# 以 product-service 服务为例
[root@k8s-master1 simple-microservice]# vim product-service/product-service-biz/Dockerfile
FROM 172.16.1.61/library/java:8-jdk-alpine
......
3 推送代码
[root@k8s-master1 simple-microservice]# git add .
[root@k8s-master1 simple-microservice]# git commit -m "modify Dockerfile"
[root@k8s-master1 simple-microservice]# git push
4.7 本地 harbor 镜像仓库
1 公共镜像仓库
2 微服务项目仓库
4.8 jenkinsfile脚本文件
#!/usr/bin/env groovy
// 所需插件: Git Parameter/Git/Pipeline/Config File Provider/kubernetes/Extended Choice Parameter
// harbor仓库地址
def registry = "172.16.1.61"
// harbor仓库项目名称
def project = "microservice"
// jenkins agent 镜像
jenkins_agent = "172.16.1.61/library/jenkins-slave-jdk:1.8"
// gitlab仓库地址
def git_url = "http://172.16.1.62:9999/dev/microservice.git"
// jenkins存储的认证信息
def harbor_auth = "cefb7cc5-d454-4e88-9095-e6d7f6f796c5"
def git_auth = "e80eb4fe-4564-48f5-9ef4-a75b49c1c079"
def k8s_auth = "5c5ae334-12dd-4a6a-8a47-1e2a1dbed983"
pipeline {
agent {
kubernetes {
label "jenkins-agent"
yaml """
apiVersion: v1
kind: Pod
metadata:
name: jenkins-agent
spec:
containers:
- name: jnlp
image: "${jenkins_agent}"
imagePullPolicy: Always
volumeMounts:
- name: docker-cmd
mountPath: /usr/bin/docker
- name: docker-sock
mountPath: /var/run/docker.sock
- name: maven-cache
mountPath: /root/.m2
volumes:
- name: docker-cmd
hostPath:
path: /usr/bin/docker
- name: docker-sock
hostPath:
path: /var/run/docker.sock
- name: maven-cache
hostPath:
path: /root/.m2
"""
}
}
parameters {
gitParameter branch: '', branchFilter: '.*', defaultValue: 'origin/master', description: '选择发布的分支', name: 'Branch', \
quickFilterEnabled: false, selectedValue: 'NONE', sortMode: 'NONE', tagFilter: '*', type: 'GitParameterDefinition'
extendedChoice description: '选择发布的微服务', multiSelectDelimiter: ',', name: 'Service', \
quoteValue: false, saveJSONParameterToFile: false, type: 'PT_CHECKBOX', \
value: 'eureka-service,gateway-service,portal-service,product-service,order-service,stock-service', visibleItemCount: 5
}
stages {
stage('拉取代码') {
steps {
checkout scmGit(branches: [[name: "${params.Branch}"]], extensions: [], \
userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]])
}
}
stage('代码编译') {
// 编译指定服务
steps {
sh """
pwd
echo ${WORKSPACE}
ls -l ${WORKSPACE}
export JAVA_HOME=/usr/local/jdk1.8.0_45
export PATH=\${JAVA_HOME}/bin:\${PATH}
mvn clean package -Dmaven.test.skip=true
"""
}
}
stage('构建镜像') {
steps {
withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
sh """
docker login -u ${username} -p ${password} ${registry}
for service in \$(echo ${Service} |sed 's/,/ /g'); do
cd \${service}
if ls |grep biz &>/dev/null; then
cd \${service}-biz
fi
service_name=\${service%-*}
image_name=${registry}/${project}/\${service_name}:${BUILD_NUMBER}
docker build -t \${image_name} .
docker push \${image_name}
cd ${WORKSPACE}
sed -i -r "s#(image: )(.*)#\\1\${image_name}#" k8s/\${service_name}.yaml
done
"""
}
}
}
stage('部署到K8S') {
steps {
configFileProvider([configFile(fileId: "${k8s_auth}", targetLocation: 'admin.kubeconfig')]) {
sh """
cd ${WORKSPACE}/k8s/
for service in \$(echo ${Service} |sed 's/,/ /g'); do
service_name=\${service%-*}
kubectl apply -f \${service_name}.yaml --kubeconfig ${WORKSPACE}/admin.kubeconfig
done
"""
}
}
}
}
}
4.9 创建pipeline流水线
1 创建名为 jenkins-ms 的 pipeline 流水线任务
2 将"4.8 jenkinsfile脚本文件"贴入如下 "Pipeline script" 文本框中并保存流水线任务
4.10 执行pipeline流水线任务
1 第一次构建流水线任务(第一次构建时会报错,为参数化构建做准备)
2 参数化构建
3 构建时会自动创建 jenkins agent pod,流水线结束后该 pod 会自动被销毁
4 构建完成
(1) Console Output
......
(2) 流水线步骤
5 查看镜像仓库
所有镜像的版本号都和pipeline流水线构建版本号相同,以 gateway 服务镜像为例。
6 查看pod状态
pod自动销毁后并自动重建
4.11 流水线脚本与源代码一起版本管理
Jenkinsfile 文件建议与源代码放在一起进行版本管理,实现流水线即代码(Pipeline as Code),这样做的好处有:
(1) Jenkins从Git仓库中读取Jenkinsfile
(2) 自动为所有分支创建流水线脚本。
(3) 方便流水线代码复查、追踪、迭代。
(4) 可被项目成员查看和编辑。
4.12 小结
1 使用Jenkins的插件
(1) Chinese
(2) Git & gitParameter
(3) Kubernetes
(4) Pipeline
(5) Config File Provider
(6) Extended Choice Parameter
2 CI/CD环境特点
(1) Slave 弹性伸缩
(2) 基于镜像隔离构建环境
(3) 流水线发布,易维护
(4) Jenkins 参数化构建可帮助你完成更复杂环境 CI/CD