CI&CD:
如果springboot-demo需要修改某些代码,按照上述流程,是不是又要重新打包?然后写Dockerfile,push镜像,然后写k8s配置文件等等之类的操作,在生产环境我们也会遇到发包更新频繁的问题,那么有什么办法提高我们的发布效率与协作效率呢?这里我们通常会引入CI&CD的概念
-
持续集成(Continuous integration,简称CI:频繁地(一天多次或者N次)将代码集成到主干。将软件个人研发的部分向软件整体部分交付,频繁进行集成以便更快地发现其中的错误。
-
持续交付(Continuous delivery):指的是,频繁地将软件的新版本,交付给质量团队或者用户,以供评审。如果评审通过,代码就进入生产阶段。持续交付在持续集成的基础上,将集成后的代码部署到更贴近真实运行环境的「类生产环境」(production-like environments)中。持续交付优先于整个产品生命周期的软件部署,建立在高水平自动化持续集成之上。
-
持续部署(continuous deployment,简称CD):是持续交付的下一步,指的是代码通过评审以后,自动部署到生产环境。持续部署的目标是,代码在任何时刻都是可部署的,可以进入生产阶段。持续部署的前提是能自动化完成测试、构建、部署等步骤。
持续集成、持续交付、持续部署提供了一个优秀的 DevOps 环境。对于整个开发团队来说,能很大地提升开发效率,好处与挑战并行。无论如何,频繁部署、快速交付以及开发测试流程自动化都将成为未来软件工程的重要组成部分。
我们就来感受一下CICD带来的效率,首先我们基于先前的SpringBoot-demo工程进行发布,当有Push操作的时候会通过Web Hook钩子让Jenkins进行构建,推送,让后简历docker镜像,k8s构建pod。发布服务:
基础环境准备:
- JDK 1.8.0_161 :https://www.cnblogs.com/wuzhenzhao/p/9481083.html
- apache-maven-3.6.3.
- git 2.24.1.
- Docker 环境。
- 必须要在 k8s 集群中,我这边选用的是两台阿里云的服务器。注意需要有外网IP。接受 Web Hook
- 准备一个springboot-demo,上传至Github,用IDEA进行关联。等等需要Push代码触发 Web Hook
- 需要安装Jenkins:https://www.cnblogs.com/wuzhenzhao/p/11425237.html ,并且把 Git ,Maven ,JDK 三个全局工具配置好。nohup java -jar jenkins.war --httpPort=8080 & 启动。
测试pipeline任务:
(1)创建jenkins的task
(2)拉取github代码,在最下面编写pipeline,然后“保存和立即构建“,同时可以查看“Console Output”
脚本如下
node { def mvnHome stage('Preparation') { // for display purposes git 'https://github.com/itcrazy2016/springboot-demo.git' } }
创建完返回首页点击构建:
(3)来到Jenkins安装节点: /root/.jenkins/workspace/springboot-demo
(4)配置springboot-demo的task,修改pipeline内容 ,增加maven构建,然后“保存和立即构建“,同时可以查看“Console Output”
node { def mvnHome stage('Preparation') { // for display purposes git 'https://github.com/wuzhenzhao/springboot-demo.git' } dir('/root/.jenkins/workspace/springboot-demo/springboot-demo') { // 切换到/home/jenkins目录中做一些事情 // some block stage('Maven Build') { sh "mvn clean package" } } }
(5)来到节点:ll /root/.jenkins/workspace/springboot-demo/springboot-demo
先看Jenkins控制台的输出
看看服务器的目录,果然生成了 target目录。
至此,我们已经可以通过在jenkins上手动构建的方式,拿到github上的代码,并且用maven进行构建。
git push触发jenkins自动构建:
(1)在github上配置jenkins的webhook地址,配置GitHub Server [系统管理]->[系统配置]->[找到github服务器]->找到Github,这里有 Web Hook的地址:
选择构建触发器,并且选择Github Hook触发
然后配置Github:
(2)生成Personal access tokens
Jenkins访问github需要授权,所以在github上生成token交给jenkins使用,即 Personal access tokens.
github的Settings[个人信息右上角]-->Developer settings-->Personal access tokens
Generate new token 最后保存好该token,比如: 0b9d624404e95d6fe36f86d84374f2dcce402b43
(3) 配置GitHub Server [系统管理]->[系统配置]->[找到github服务器]->[添加github服务器] 然后按照下面图片步骤进行操作:
jenkins安装插件:
01 安装github plugin插件:[系统管理]->[插件管理]->[可选插件] 02 安装gitlab插件和gitlab hook插件:[系统管理]->[插件管理]->[可选插件]
系统设置找到Github,这里有 Web Hook的地址:
配置完是这样的:
然后用 IDEA 提交以下代码测试一下,确保无误进行下面的操作。
核心实战走起:
build&push镜像:经过前面的折腾,肯定可以获取到代码,并且用maven进行构建了,最终拿到一个target/xxx.jar
来到 jenkins安装主机节点上的workspace目录:cd /root/.jenkins/workspace
(1) 创建文件夹准备一个文件,名称为springboot-demo-build-image.sh
mkdir /root/.jenkins/workspace/scripts/
vi /root/.jenkins/workspace/scripts/springboot-demo-build-image.sh
(2)编写springboot-demo-build-image.sh文件
# 进入到springboot-demo目录
cd ../springboot-demo
# 编写Dockerfile文件
cat < Dockerfile
FROM openjdk:8-jre-alpine
COPY target/springboot-demo-1.0-SNAPSHOT.jar /springboot-demo.jar
ENTRYPOINT ["java","-jar","/springboot-demo.jar"]
EOF
echo "Dockerfile created successfully!"
# 基于指定目录下的Dockerfile构建镜像
docker build -t registry.cn-hangzhou.aliyuncs.com/wuzz-docker/springboot-demo:v1.0 .
# push镜像,这边需要阿里云镜像仓库登录,在当前安装了jenkins主机上登录
docker push registry.cn-hangzhou.aliyuncs.com/wuzz-docker/springboot-demo:v1.0
sudo docker login --username=随风去wuzz registry.cn-hangzhou.aliyuncs.com 先登录。
chmod +x /root/.jenkins/workspace/scripts/springboot-demo-build-image.sh 给文件授权
(3)增加pipeline
node { def mvnHome stage('Preparation') { // for display purposes git 'https://github.com/wuzhenzhao/springboot-demo.git' } dir('/root/.jenkins/workspace/springboot-demo/springboot-demo') { // 切换到/home/jenkins目录中做一些事情 // some block stage('Maven Build') { sh "mvn clean package" } stage('Build Image') { sh "/root/.jenkins/workspace/scripts/springboot-demo-build-image.sh" } } }
(4):重新构建,成功如下
查看镜像:docker images
看看阿里云仓库是否有镜像了:
Kubernetes拉取镜像运行:
经过前面的折腾,现在已经能够把镜像push到镜像仓库了,接下来就是k8s拉取镜像并且运行在集群中咯。根据前面的经验,肯定再创建一个stage,然后运行sh脚本,脚本中执行内容,包括yaml文件
(1) 编写springboot-demo.yaml文件 。在/root/.jenkins/workspace/scripts/目录下创建springboot-demo.yaml
# 以Deployment部署Pod apiVersion: apps/v1 kind: Deployment metadata: name: springboot-demo spec: selector: matchLabels: app: springboot-demo replicas: 1 template: metadata: labels: app: springboot-demo spec: containers: - name: springboot-demo image: registry.cn-hangzhou.aliyuncs.com/wuzz-docker/springboot-demo:v1.0 ports: - containerPort: 8888 --- # 创建Pod的Service apiVersion: v1 kind: Service metadata: name: springboot-demo spec: ports: - port: 80 protocol: TCP targetPort: 8080 selector: app: springboot-demo --- # 创建Ingress,定义访问规则 apiVersion: extensions/v1beta1 kind: Ingress metadata: name: springboot-demo spec: rules: - host: springboot.wuzz.com http: paths: - path: / backend: serviceName: springboot-demo servicePort: 80
(2)编写k8s-deploy-springboot-demo.sh文件
vi /root/.jenkins/workspace/scripts/k8s-deploy-springboot-demo.sh
kubectl delete -f /root/.jenkins/workspace/scripts/springboot-demo.yaml kubectl apply -f /root/.jenkins/workspace/scripts/springboot-demo.yaml echo "k8s deploy success!"
(3)编写pipeline:
node {
def mvnHome
stage('Preparation') { // for display purposes
git 'https://github.com/wuzhenzhao/springboot-demo.git'
}
dir('/root/.jenkins/workspace/springboot-demo/springboot-demo') { // 切换到/home/jenkins目录中做一些事情
// some block
stage('Maven Build') {
sh "mvn clean package"
}
stage('Build Image') {
sh "/root/.jenkins/workspace/scripts/springboot-demo-build-image.sh"
}
stage('K8S Deploy') {
sh "/root/.jenkins/workspace/scripts/k8s-deploy-springboot-demo.sh"
}
}
}
chmod +x /root/.jenkins/workspace/scripts/k8s-deploy-springboot-demo.sh 授权。
先查看一下 Nodes 是都是 ready :kubectl get nodes:
确保网络没问题:查看系统 pods:kubectl get pods --all-namespaces -w
这个时候IDEA 修改后提交代码,会触发构建:
查看 pod,service,ingress信息
再查看一下 pod 的启动日志 :kubectl logs -f pod-name:
到这里就部署完成了,由于我这里是阿里云没有域名,无法再本地操作,到了这一步,只要 k8s集群没问题,部署就没问题了。如果 Jenkins 是部署在 worker 节点, worker执行不了kubectl
- 切换到master上,cd ~ ---> cat .kube/config --->复制内容
- 切换到worker上 cd ~ ---> vi .kube/config --->粘贴内容