六、Kubernetes CICD之旅
1、概述
在前面的章节中我们已经演示了不少案例与各种组件的介绍与使用,我们也实战搭建了项目。通过K8S的帮助,我们可以很方便的部署项目,但还不是很完美。如果我们部署的是自己的项目,而我们的项目又是要经常改动的,这就意味着我们需要经常进行 打包、上传、重启、测试
等,这些都是重复性的工作,一次两次还好,次数多了也烦人。所以下面要讲的 CI/CD
就是来帮我们解放双手,摆脱这些重复性的工作!
1.1、CI/CD是什么?
-
CI/CD 是一种通过在应用开发阶段引入 自动化 来频繁向客户交付应用的方法。
-
CI/CD 的核心概念是持续集成、持续交付和持续部署。
-
CI/CD 主要针对在集成新代码时所引发的问题。
-
CI/CD 可让持续自动化和持续监控贯穿于应用的整个生命周期(从集成和测试阶段,到交付和部署)。
-
这些关联的事务通常被统称为 “CI/CD 管道”,由开发和运维团队以敏捷方式协同支持。
1.2、 CI 和 CD 有什么区别?
- CI/CD 中的 “CI” 始终指持续集成,它属于开发人员的自动化流程。
- 成功的 CI 意味着应用代码的新更改会定期构建、测试并合并到共享存储库中。
- 该解决方案可以解决在一次开发中有太多应用分支,从而导致相互冲突的问题。
- CI/CD 中的“CD”指的是持续交付和/或持续部署,这些相关概念有时会交叉使用。
- 两者都事关管道后续阶段的自动化,但它们有时也会单独使用,用于说明自动化程度。
更多概念可以到
红帽
看官方介绍: https://www.redhat.com/zh/topics/devops/what-is-ci-cd
下面这张图就相对完整的介绍了本章节要进行的工作:
- 开发手动提交代码到git仓库
- 自动拉取代码
- 自动进行Maven构建、代码检查、单元测试
- 这个步骤在生产环境一般不会做自动构建,因为公司可能进行代码检查,确认无误后由QA手动进行部署
- 本章节只进行Maven构建,代码检查和单元测试需要集成其他组件,读者可以自行了解
- 自动build镜像、上传镜像至镜像仓库
- 自动拉取镜像进行部署
2、环境准备
- 准备一个项目
- 准备一个 Git 仓库
- 可以是自己搭建的也可以是GitHub或者码云都可以
- 准备一个镜像仓库
- 这里使用阿里云的镜像仓库
- 准备一个安装了 Kubernetes 的机器
- 直接使用之前搭建好的 K8S 集群
- 安装 Java
- 安装 Maven
- 安装 Git
- 安装 Jenkins
- Jenkins必须在k8s集群中,因为后面需要在jenkins的目录下创建文件执行K8S的命令
- 其他环境在这台机器安装的原因在于Jenkins需要依赖这些环境
2.1、环境搭建
-
安装 Java
-
下载 Java 安装包上传并解压到服务器
-
配置环境变量
- 采用 profile.d 目录设置环境变量,好处在于想删掉该环境可以直接删除文件,无需修改配置文件
# 1、配置环境变量 [root@worker01-kubeadm-k8s profile.d]# pwd /etc/profile.d [root@worker01-kubeadm-k8s profile.d]# vi java.sh export JAVA_HOME=/root/develop/java/jdk1.8.0_181 export JRE_HOM=$JAVA_HOME/jre export CLASSPATH=$JAVA_HOME/lib/ export PATH=$PATH:$JAVA_HOME/bin # 2、赋予权限 [root@worker01-kubeadm-k8s profile.d]# chmod 755 ./java.sh # 3、编译文件 [root@worker01-kubeadm-k8s profile.d]# source ./java.sh # 4、测试 [root@worker01-kubeadm-k8s profile.d]# java -version java version "1.8.0_181" Java(TM) SE Runtime Environment (build 1.8.0_181-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
-
-
安装 Maven
-
下载 Maven 安装包上传并解压到服务器
-
配置环境变量
# 1、配置环境变量 [root@worker01-kubeadm-k8s profile.d]# vi mvn.sh export MAVEN_HOME=/root/develop/maven/apache-maven-3.6.3 export PATH=$PATH:$MAVEN_HOME/bin # 2、赋予权限 [root@worker01-kubeadm-k8s profile.d]# chmod 755 ./mvn.sh # 3、编译文件 [root@worker01-kubeadm-k8s profile.d]# source ./mvn.sh # 4、测试 [root@worker01-kubeadm-k8s profile.d]# mvn -v Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f) Maven home: /root/develop/maven/apache-maven-3.6.3 Java version: 1.8.0_181, vendor: Oracle Corporation, runtime: /root/develop/java/jdk1.8.0_181/jre Default locale: en_US, platform encoding: UTF-8 OS name: "linux", version: "3.10.0-1062.18.1.el7.x86_64", arch: "amd64", family: "unix"
-
配置本地仓库路径、阿里云镜像
# 1、本地仓库路径,改成自己的 <localRepository>/root/develop/maven/repo</localRepository> # 2、配置阿里云镜像 <mirror> <id>aliyunmaven</id> <mirrorOf>*</mirrorOf> <name>阿里云公共仓库</name> <url>https://maven.aliyun.com/repository/public</url> </mirror>
-
-
安装 Git
-
下载安装
# 1、安装 Git [root@worker01-kubeadm-k8s ~]# yum install git # 2、测试 [root@worker01-kubeadm-k8s ~]# git --version git version 1.8.3.1
+ 配置账号 ```ruby [root@worker01-kubeadm-k8s ~]# git config --global user.name "Sunny" [root@worker01-kubeadm-k8s ~]# git config --global user.email "yzy_zhaoyang@163.com" [root@worker01-kubeadm-k8s ~]# ssh-keygen -t rsa -C "yzy_zhaoyang@163.com" # 出现需要输入密码的地方可以设置自己的ssh密码, 也可以直接回车表示不设置密码 Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa. # 这里的路径文件指的是公钥,我们要打开这个文件将公钥填到 Git 仓库 Your public key has been saved in /root/.ssh/id_rsa.pub. The key fingerprint is: ae:ca:9b:84:t5:3e:b7:as:98:51:d1:77:31:34:0e:tt yzy_zhaoyang@163.com The key's randomart image is: +--[ RSA 2048]----+ | ...o | | . E. o | |o .. o . | |.o . o | |. . S | | .. . | | .... . | |.o=+.. . | |.=+o*o. | +-----------------+
-
2.2、准备项目
image.png-
上传到 Git 仓库
image.png
2.3、搭建 Jenkins
-
前情提要
Jenkins 官网:https://jenkins.io/
入门指南:https://jenkins.io/zh/doc/pipeline/tour/getting-started/
-
下载并上传 Jenkins 到服务器
-
启动 Jenkins
#以后台启动方式启动 Jenkins,设置端口为 8088 [root@worker01-kubeadm-k8s jenkins]# [root@sunny jenkins]# nohup java -jar jenkins.war --httpPort=8088 & # 查看启动日志 [root@worker01-kubeadm-k8s jenkins]# tail -f nohup.out Running from: /root/jenkins/jenkins.war webroot: $user.home/.jenkins 2020-04-16 15:20:49.849+0000 [id=1] INFO org.eclipse.jetty.util.log.Log#initialized: Logging initialized @753ms to org.eclipse.jetty.util.log.JavaUtilLog # ... 省略 ... ************************************************************* ************************************************************* ************************************************************* Jenkins initial setup is required. An admin user has been created and a password generated. Please use the following password to proceed to installation: # 这是进入 Jenkins 管理页面所需要的密码 f9025b52a4824997b09cb62d5c89f7cc # 这是存放密码的文件 This may also be found at: /root/.jenkins/secrets/initialAdminPassword ************************************************************* ************************************************************* *************************************************************
-
2.3.1、配置 Jenkins
-
安装推荐的插件
image.png
等待安装即可,需要的时间比较久
也可以先点推荐安装,然后刷新页面选择跳过安装,之后手动下载插件安装,这样会更快
如果跳过,先截图保存一下推荐插件的列表,后面手动安装要去搜索的
-
创建用户
image.pngusername: sunny password: sunny
-
安装插件
这里说的是推荐插件安装完后还需要安装的一些插件,如果你选择了跳过安装,那要先记好它推荐了哪些插件,有些插件是必要的
- 中文插件
- Locale
- Localization: Chinese (Simplified)
- Localization Support
- git插件
- GitHub / Gitee
- Gitlab Hook
- Gitlab Plugin
- 中文插件
-
配置Java、Maven、Git路径
-
Manage Jenkins — Global Tool Configuration
-
配置机器中的路径
image.png
-
2.3.2、镜像仓库与Kubernetes集群
-
镜像仓库采用国内的阿里云镜像仓库
-
Kubernetes 集群直接采用我们之前章节中已经搭建好的 Kubernetes 集群即可。
3、Pipeline任务
我们一个步骤一个步骤的演示,从最开始的拉取代码,慢慢延伸到最终的CICD!
3.1 拉取项目代码
Jenkins要实现自动拉取代码,需要安装Git相关插件,以及要到Git仓库去进行一些配置,插件之前都已经安装了,接下来就演示一下Jenkins的配置。
-
创建任务
image.png
-
创建流水线任务
image.png
-
编写pipeline
注意这里要勾选上,保存webhook的链接,后面配置自动拉取时要用到
node {
// Pull
stage('Pull') { //stage表示一个任务
//这里是任务的内容
//因为我们的机器已经生成了秘钥且与Gieee进行了绑定,所以无需输入账号密码就可以进行拉取代码
git 'https://gitee.com/suny95/springboot-demo-k8s.git'
}
}
配置完成后点击保存
-
构建任务
image.png
image.png构建完成后会显示绿色,构建失败是红色,可以去查看错误信息
这里是Jenkins工作目录:/root/.jenkins/workspace目录
代码是拉取到这个目录下的
# Jenkins工作目录
[root@worker01-kubeadm-k8s workspace]# pwd
/root/.jenkins/workspace
[root@worker01-kubeadm-k8s workspace]# ll
total 0
drwxr-xr-x. 4 root root 62 Apr 18 14:37 springboot-k8s-task
# 新建的任务目录
[root@worker01-kubeadm-k8s workspace]# cd springboot-k8s-task/
[root@worker01-kubeadm-k8s springboot-k8s-task]# ll
total 4
-rw-r--r--. 1 root root 1277 Apr 18 14:37 pom.xml
drwxr-xr-x. 3 root root 18 Apr 18 14:37 src
3.2 Maven自动编译
修改之前编写好的流水线任务,增加一个Stage用来做Maven自动编译
-
修改Pipeline脚本内容
node { // Pull stage('Pull') { //stage表示一个任务 //这里是任务的内容 //因为我们的机器已经生成了秘钥且与Gieee进行了绑定,所以无需输入账号密码就可以进行拉取代码 git 'https://gitee.com/suny95/springboot-demo-k8s.git' } //Maven stage('AutoCompile') { sh "mvn clean package" } }
-
构建任务
开始构建任务后,可以通过Console Output监控当前任务执行情况
# 再次查看目录,发现已经成功编译出 target 目录了
[root@worker01-kubeadm-k8s springboot-k8s-task]# ll
total 4
-rw-r--r--. 1 root root 1277 Apr 18 14:37 pom.xml
drwxr-xr-x. 3 root root 18 Apr 18 14:37 src
drwxr-xr-x. 6 root root 181 Apr 18 14:56 target
到这里为止,手动构建的方式已经完成, 下面将要开始配置自动构建
3.3 Git Push 触发 Jenkins 自动构建
当用户进行git push提交代码到 GitHub / Git EE 时,能够通知 jenkins 自动构建
注意: Jenkins 的 ip 一定要是 Git EE 能够访问到的地址
我这里由于是本地搭建的虚拟机,就不做演示了,百度搜一下有很多的教程可以参考
3.4 build 与 push 镜像
经过前面的演示,现在已经可以获取到代码,并且用maven进行构建了,最终拿到一个target/xxx.jar
现在我们要演示Docker的镜像构建与Push镜像到镜像仓库!
-
准备执行文件
-
到 Jenkins 的工作目录
- cd /root/.jenkins/workspace
-
创建 .sh 执行文件
# 创建专门存放脚本的目录 [root@worker01-kubeadm-k8s workspace]# mkdir scripts [root@worker01-kubeadm-k8s workspace]# cd scripts/ # 编写执行文件 [root@worker01-kubeadm-k8s scripts]# vi springboot-demo-k8s-build-image.sh # ================== 执行文件内容 ====================== # 进入到springboot-k8s-task目录 cd ../springboot-k8s-task # 编写Dockerfile文件, 这里也可以先在项目里写好 cat <<EOF > Dockerfile FROM openjdk:8-jre-alpine COPY target/springboot-demo-0.0.1-SNAPSHOT.jar /springboot-demo.jar ENTRYPOINT ["java","-jar","/springboot-demo.jar"] EOF echo "Dockerfile created successfully!" # 基于指定目录下的Dockerfile构建镜像 # 注意 zhao_yang 这个命名空间是公开的,如果是私有的,还需要配置K8S的认证 docker build -t registry.cn-hangzhou.aliyuncs.com/zhao_yang/springboot-demo-k8s:v1.0 . # 登录docker账号 # 注意: 如果密码不能开放的话,可以先手动在机器上登录一次,那这里就无需再次登录了 docker login --username=用户名 --password=密码 registry.cn-shanghai.aliyuncs.com # push镜像 docker push registry.cn-hangzhou.aliyuncs.com/zhao_yang/springboot-demo-k8s:v1.0 # ================== 执行文件内容 ====================== # 增加执行权限 [root@worker01-kubeadm-k8s scripts]# chmod +x ./springboot-demo-k8s-build-image.sh
-
-
修改任务的Pipeline脚本
node { // Pull stage('Pull') { //stage表示一个任务 //这里是任务的内容 //因为我们的机器已经生成了秘钥且与Gieee进行了绑定,所以无需输入账号密码就可以进行拉取代码 git 'https://gitee.com/suny95/springboot-demo-k8s.git' } //Maven stage('AutoCompile') { sh "mvn clean package" } //增加任务,执行脚本文件 stage('Build And Push Image') { sh "/root/.jenkins/workspace/scripts/springboot-demo-k8s-build-image.sh" } }
-
构建任务,监控输出
image.png image.png
build 镜像与 push 镜像至镜像仓库 都已成功!!!
3.1.5 Kubernetes 拉取镜像运行
这个过程需要提前准备的也就是image镜像和ingress,image刚才我们都已经上传到阿里云镜像仓库了,ingress我们在之前也准备过了,如果没有ingress环境的,可以去看前面的 kubernetes 网络模型
,里面有安装ingress的流程!
-
编写 YAML 文件
YAML文件可以写到项目中,也可以直接在机器上创建
- vi /root/.jenkins/workspace/scripts/springboot-demo-k8s.yaml
# 以Deployment部署Pod apiVersion: apps/v1 kind: Deployment metadata: name: springboot-demo-k8s spec: selector: matchLabels: app: springboot-demo-k8s replicas: 1 template: metadata: labels: app: springboot-demo-k8s spec: containers: - name: springboot-demo-k8s image: registry.cn-hangzhou.aliyuncs.com/zhao_yang/springboot-demo-k8s:v1.0 ports: - containerPort: 8080 --- # 创建Pod的Service apiVersion: v1 kind: Service metadata: name: springboot-demo-k8s spec: ports: - port: 80 protocol: TCP targetPort: 8080 selector: app: springboot-demo-k8s --- # 创建Ingress,定义访问规则 apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: springboot-demo-k8s spec: rules: - host: springboot.sunny.com http: paths: - path: / backend: serviceName: springboot-demo-k8s servicePort: 80
-
编写 .sh 执行文件
[root@worker01-kubeadm-k8s scripts]# vi /root/.jenkins/workspace/scripts/k8s-deploy-springboot-demo.sh # ================== YAML文件内容 ============ kubectl delete -f /root/.jenkins/workspace/scripts/springboot-demo-k8s.yaml kubectl apply -f /root/.jenkins/workspace/scripts/springboot-demo-k8s.yaml echo "k8s deploy success!" # ================== YAML文件内容 ============ [root@worker01-kubeadm-k8s scripts]# chmod +x k8s-deploy-springboot-demo.sh
-
修改Pipeline
node { // Pull stage('Pull') { //stage表示一个任务 //这里是任务的内容 //因为我们的机器已经生成了秘钥且与Gieee进行了绑定,所以无需输入账号密码就可以进行拉取代码 git 'https://gitee.com/suny95/springboot-demo-k8s.git' } //Maven stage('AutoCompile') { sh "mvn clean package" } //build push stage('Build And Push Image') { sh "/root/.jenkins/workspace/scripts/springboot-demo-k8s-build-image.sh" } //k8s stage('K8S Deploy') { sh "/root/.jenkins/workspace/scripts/k8s-deploy-springboot-demo.sh" } }
-
构建任务并监控输出
image.png
发现出现异常了,这个问题其实是因为我们选择的机器在 K8S 集群中不是 Master 节点,它没有执行kubectl 命令的权限,我们需要配置一下!
-
复制 .kube 文件目录到 Worker01 节点
image.png[root@master-kubeadm-k8s .kube]# pwd /root/.kube # 这里的 config 是权限认证的文件 [root@master-kubeadm-k8s .kube]# ll total 12 drwxr-xr-x. 3 root root 23 Mar 24 14:32 cache -rw-------. 1 root root 5454 Mar 24 14:30 config drwxr-xr-x. 3 root root 4096 Apr 4 08:59 http-cache
```ruby
[root@worker01-kubeadm-k8s ~]# mkdir .kube
[root@worker01-kubeadm-k8s ~]# cd .kube/
# 将 Master 节点中config文件内容复制进去即可
[root@worker01-kubeadm-k8s .kube]# vi config
[root@worker01-kubeadm-k8s .kube]# ll
total 8
-rw-r--r--. 1 root root 5454 Apr 19 09:45 config
```
-
重新构建并监控
image.png
-
测试
# pod 运行成功 [root@worker01-kubeadm-k8s scripts]# kubectl get pods NAME READY STATUS RESTARTS AGE springboot-demo-k8s-79c867fd58-ts2f7 1/1 Running 0 5m53s # service 也创建成功 [root@worker01-kubeadm-k8s scripts]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 25d springboot-demo-k8s ClusterIP 10.99.138.171 <none> 80/TCP 6m46s # ingress 也在 [root@worker01-kubeadm-k8s scripts]# kubectl get ingress NAME HOSTS ADDRESS PORTS AGE springboot-demo-k8s springboot.sunny.com 80 10m # 访问 Service IP + 路径, 成功访问到结果 [root@worker01-kubeadm-k8s scripts]# curl 10.99.138.171/k8s hello K8S
- 通过Ingress访问也成功
由于机器问题,我没办法演示 Git Push 就触发自动构建的任务,大家如果有公网的机器的话,可以去尝试弄一下!