共计 4109 个字符,预计需要花费 11 分钟才能阅读完成。
一、什么是 CI/CD
持续集成(CI)与持续交付(CD)是软件开发和交付中的实践。
什么是持续集成?
软件开发中,集成是一个很可能发生未知错误的过程。持续集成是一种软件开发实践,希望团队中的成员频繁提交代码到代码仓库,且每次提交都能通过自动化测试进行验证,从而使问题尽早暴露和解决。
持续集成的好处是什么?
持续集成可以使问题尽早暴露,从而也降低了解决问题的难度,持续集成无法消除 bug,但却能大大降低修复的难度和时间。
什么是持续交付?
持续交付是持续集成的扩展,指的是将通过自动化测试的软件部署到产品环境。持续交付的本质是把每个构建成功的应用更新交付给用户使用。
持续交付的好处是什么?
持续交付的好处在于快速获取用户反馈;适应市场变化和商业策略的变化。开发团队保证每次提交的修改都是可上线的修改,那么决定何时上线,上线哪部分功能则完全由产品业务团队决定。
二、环境准备
节点名称 | IP 地址 | 资源配置 |
---|---|---|
zutuanxue-master | 192.168.1.160 | 4U4G |
zutuanxue-node-1 | 192.168.1.161 | 2U4G |
zutuanxue-node-2 | 192.168.1.162 | 2U4G |
zutuanxue-gitlab | 192.168.1.168 | 4U4G |
zutuanxue-nfs | 192.168.1.169 | 2U2G |
zutuanxue-harbor | 192.168.1.240 | 2U2G |
Master 节点配置:安装 Java:yum -y install java-1.8.0-* | |
java -version | |
openjdk version "1.8.0_252" | |
OpenJDK Runtime Environment (build 1.8.0_252-b09) | |
OpenJDK 64-Bit Server VM (build 25.252-b09, mixed mode) | |
安装 maven:官方下载地址:http://maven.apache.org/download.cgi | |
wget https://mirror.bit.edu.cn/apache/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz | |
tar -xf apache-maven-3.6.3-bin.tar.gz | |
mv -f apache-maven-3.6.3 /usr/local/ | |
编辑 /etc/profile,在文件末尾添加如下代码:export MAVEN_HOME=/usr/local/apache-maven-3.6.3 | |
export PATH=${PATH}:${MAVEN_HOME}/bin | |
保存文件,并运行如下命令使环境变量生效:source /etc/profile | |
mvn -v | |
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f) | |
Maven home: /usr/local/apache-maven-3.6.3 | |
Java version: 1.8.0_252, vendor: Oracle Corporation, runtime: /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.252.b09-3.el8_2.x86_64/jre | |
Default locale: en_US, platform encoding: ANSI_X3.4-1968 | |
OS name: "linux", version: "4.18.0-147.8.1.el8_1.x86_64", arch: "amd64", family: "unix" | |
安装 jenkins:官方网站:https://www.jenkins.io/zh/ | |
wget http://mirrors.jenkins.io/war-stable/latest/jenkins.war | |
nohup java -jar jenkins.war --httpPort=8080 > myout.file 2>&1 & | |
打开浏览器进入链接 http://IP:8080 | |
根据浏览器提示完成后续安装 | |
cat /root/.jenkins/secrets/initialAdminPassword | |
e8ec34c745064620a3f88ced0b522692 | |
三、流水线示例
jenkins 流水线代码:node {env.BUILD_DIR = "/opt/build-work/" | |
env.HOST = "aaa.zutuanxue.com" | |
stage('Preparation') {// for display purposes | |
// Get some code from a GitHub repository | |
git 'http://192.168.1.168/root/spring-web.git' | |
} | |
stage('Maven Build') { | |
// Run the maven build | |
sh "mvn package" | |
} | |
stage('Build Image') {sh "/opt/jenkins/script/build-image-web.sh" | |
} | |
stage('Deploy') {sh "/opt/jenkins/script/deploy.sh" | |
} | |
} | |
------------------------------------------------------------------- | |
说明:node {env.BUILD_DIR = "/opt/build-work/" 定义 build 的工作目录 | |
env.HOST = "aaa.zutuanxue.com" 定义 ingress 的域名 | |
下载我们需要的代码:stage('Preparation') {// for display purposes | |
// Get some code from a GitHub repository | |
git 'http://192.168.1.168/root/spring-web.git' | |
} | |
通过 maven 工具进行构建:stage('Maven Build') { | |
// Run the maven build | |
sh "mvn package" | |
} | |
通过脚本构建我们需要的镜像:stage('Build Image') {sh "/opt/jenkins/script/build-image-web.sh" | |
} | |
通过脚本在 k8s 集群内部署我们的业务:stage('Deploy') {sh "/opt/jenkins/script/deploy.sh" | |
} | |
} |
build 脚本:#!/bin/bash | |
# 先判断一下我们 build 的工作目录是否存在,如果不存的话,那么就去创建对应的目录 | |
if ["${BUILD_DIR}" == "" ];then | |
echo "env'BUILD_DIR'There is no such directory" | |
exit 1 | |
fi | |
DOCKER_DIR=${BUILD_DIR}/${JOB_NAME} | |
if [! -d ${DOCKER_DIR} ];then | |
mkdir -p ${DOCKER_DIR} | |
fi | |
# jenkins 的工作空间下的哪一个项目目录 | |
JENKINS_DIR=${WORKSPACE}/ | |
# 进入我们 build 的工作目录,清除不需要的文件,将我们要用到的文件移动过来 | |
cd ${DOCKER_DIR} | |
rm -rf * | |
mv ${JENKINS_DIR}/target ${DOCKER_DIR} | |
mv ${JENKINS_DIR}/dockerfile ${DOCKER_DIR} | |
# 以当前的时间当做我们镜像的版本号 | |
VERSION=$(date +%Y%m%d%H%M%S) | |
# 定义我们镜像的名称:harbor 地址 / 仓库项目名称 / 镜像项目名称:版本号 | |
IMAGE_NAME=www.zutuanxue.com.cn/library/${JOB_NAME}:${VERSION} | |
# 将构建的镜像名称输入到文件,方便部署的时候进行调用 | |
echo "${IMAGE_NAME}" > ${WORKSPACE}/IMAGE | |
# 构建镜像 | |
docker build -t ${IMAGE_NAME} . | |
# 上传镜像到 harbor | |
docker push ${IMAGE_NAME} | |
k8s 部署脚本:#!/bin/bash | |
name=${JOB_NAME} | |
image=$(cat ${WORKSPACE}/IMAGE) | |
host=${HOST} | |
cd /opt/jenkins/script/template/ | |
echo "deploying ... name: ${name}, image: ${image}, host: ${host}" | |
sed -i "s,{{name}},${name},g" web.yaml | |
sed -i "s,{{image}},${image},g" web.yaml | |
sed -i "s,{{host}},${host},g" web.yaml | |
echo "ready to apply" | |
kubectl apply -f web.yaml | |
# yaml 模板文件: | |
apiVersion: v1 | |
kind: Service | |
metadata: | |
name: {{name}} | |
spec: | |
ports: | |
- port: 80 | |
protocol: TCP | |
targetPort: 8080 | |
selector: | |
app: {{name}} | |
type: ClusterIP | |
apiVersion: extensions/v1beta1 | |
kind: Ingress | |
metadata: | |
name: {{name}} | |
spec: | |
rules: | |
- host: {{host}} | |
http: | |
paths: | |
- path: / | |
backend: | |
serviceName: {{name}} | |
servicePort: 80 | |
apiVersion: apps/v1 | |
kind: Deployment | |
metadata: | |
name: {{name}} | |
spec: | |
selector: | |
matchLabels: | |
app: {{name}} | |
replicas: 1 | |
template: | |
metadata: | |
labels: | |
app: {{name}} | |
spec: | |
containers: | |
- name: {{name}} | |
image: {{image}} | |
ports: | |
- containerPort: 8080 |
正文完
星哥玩云-微信公众号
