前置条件

五台云服务器/五台虚拟机(当然也可以只用一台,所有环境都部署在一台服务器上,或者所有环境都使用docker搭建)

环境:jdk-8

我这里使用的是五台虚拟机,分别为:192.168.31.3、192.168.31.4、192.168.31.5、192.168.31.6、192.168.31.7

配置均为4H8G

ip地址功能
192.168.31.3docker容器
192.168.31.4gitlab
192.168.31.5jenkins
192.168.31.6harbor
192.168.31.7k8s

Centos7安装Docker

在192.168.31.3、192.168.31.4、192.168.31.5运行以下命令

#安装一些必要的系统工具
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
#添加Docker软件源
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#更新yum软件包索引
sudo yum makecache fast
#安装Docker-ce
sudo yum -y install docker-ce
#启动Docker服务
sudo service docker start
#查看docker版本
docker version
# docker 服务开机自启
systemctl enable docker.service

配置阿里加速镜像:https://cr.console.aliyun.com/cn-shanghai/instances/mirrors

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://xxx.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

安装并初始化gitlab

在192.168.31.4这台服务器上安装gitlab

创建保存gitlab配置的文件夹

mkdir -p /etc/gitlab
mkdir -p /var/log/gitlab
mkdir -p /var/opt/gitlab
chmod -R 755 /etc/gitlab
chmod -R 755 /var/log/gitlab
chmod -R 755 /var/opt/gitlab

拉取gitlab镜像,并创建容器

docker run --name gitlab \
--hostname gitlab.oolo.cc \
--restart=always \
-p 80:80 \
-v /etc/gitlab:/etc/gitlab \
-v /var/log/gitlab:/var/log/gitlab \
-v /var/opt/gitlab:/var/opt/gitlab \
-d gitlab/gitlab-ce

等待下载完成过后,就可以通过http://192.168.31.4/访问gitlab了

然后运行以下命令拿到密码,用户名为root

[root@localhost ~]# sudo docker exec -it gitlab grep 'Password:' /etc/gitlab/initial_root_password
Password: PoiF4n5OCdH1azEEAfNKrSmOu9sVYXHiUy821eq0Tro=
[root@localhost ~]#

英文看着别扭可以设置中文

安装并初始化jenkins

在192.168.31.5上安装jenkins

jdk8:https://cdn.oolo.cc/source/jdk-8u341-linux-x64.tar.gz

maven:https://cdn.oolo.cc/source/apache-maven-3.8.6-bin.tar.gz

maven配置文件:https://cdn.oolo.cc/source/setting.xml

cd /usr/local
wget --no-check-certificate https://cdn.oolo.cc/source/jdk-8u341-linux-x64.tar.gz
wget --no-check-certificate https://cdn.oolo.cc/source/apache-maven-3.8.6-bin.tar.gz
tar zxvf jdk-8u341-linux-x64.tar.gz
tar zxvf apache-maven-3.8.6-bin.tar.gz
mv jdk1.8.0_341 jdk
mv apache-maven-3.8.6 maven
rm -f jdk-8u341-linux-x64.tar.gz
rm -f apache-maven-3.8.6-bin.tar.gz
cd /usr/local/maven/conf
rm -f settings.xml
wget --no-check-certificate https://cdn.oolo.cc/source/setting.xml

创建jenkins配置文件夹,创建jenkins镜像并启动容器,版本最好从官网查看最新版本,使用latest并不是最新版本,很多插件不支持低版本,插件下载会出现红叉等情况。

https://www.jenkins.io/download/

rm -rf /var/jenkins/
mkdir -p /var/jenkins/
chmod -R 777 /var/jenkins/
docker rm -f jenkins
docker run --name jenkins \
--restart=always \
-p 80:8080 \
-p 50000:50000 \
-v /var/jenkins/:/var/jenkins_home/ \
-v /usr/local/jdk:/usr/local/jdk \
-v /usr/local/maven:/usr/local/maven \
-e JENKINS_UC=https://mirrors.tuna.tsinghua.edu.cn/jenkins/ \
-e JENKINS_UC_DOWNLOAD=https://mirrors.tuna.tsinghua.edu.cn/jenkins/ \
-d jenkins/jenkins:2.396
docker logs -f jenkins

执行完上面的命令后,在最后会有一个初始密钥,在第一次进入jenkins的时候需要使用初始密钥进入,然后就是选择插件。

此时有两个选项 1.安装推荐的插件 2.选择插件来安装。

点击第二个,不需要任何修改,直接点继续

进入jenkins后,需要安装两个插件

1.Git Parameter:用于拉取git上的源代码

2.Publish Over SSH:将编译好的jar包通过ssh发送到目标服务器

安装过程:

配置jdk和maven:

容器中的jdk和maven是来自于宿主机挂载的目录,分别位于容器中/usr/local/jdk,/usr/local/maven

至此,gitlab和jenkins的创建和初始化就已经完成了。

Jenkins自动拉取构建(非Docker部署)

新建gitlab仓库

首先需要在gitlab中创建一个新项目,权限设置为公共(测试使用公共)

使用:git remote add origin http://gitlab.oolo.cc/root/webchat.git 添加远端仓库

然后add、commit后push将代码推送到gitlab,推送的时候报错

这是由于我们在创建gitlab容器的时候指定了gitlab的hostname为gitlab.oolo.cc,所以克隆地址都是gitlab.oolo.cc

解决方法:

1.可以在指定远程版本库的时候将gitlab.oolo.cc修改为gitlab的ip

比如:git remote add origin http://192.168.31.4/root/webchat.git

2.在本地hosts配置新增:192.168.31.4 gitlab.oolo.cc

Jenkins新建任务拉取代码

简单测试一下jenkins拉代码,打包是否正常

新建任务->选择构建一个自由风格的软件项目

需要修改的配置

1.源码管理->勾选git->填入git仓库地址(如果是私有仓库,需要添加用户名密码)

测试jenkins拉取代码是否成功

可以看到,在对应的目录下,代码已经拉取到本地了

Jenkins使用maven打包项目

接下来就需要使用maven进行打包

Build Steps -> 增加构建步骤 -> 执行shell

sh /usr/local/maven/bin/mvn package

查看对应目录下,已经构建出了jar包

添加目标服务器SSH

但是这个jar包只是保存在jenkins上,我们需要把他发送给其他服务器进行部署,这里就需要配置ssh了

首先进入首页点击 系统管理 -> 系统配置 -> 拉到最下方找到Publish over SSH -> 新增SSH Servers,填入接收jar包的服务器用户名、密码、jar包存放的路径,

发布jar包到目标服务器并运行

然后就是配置在构建完成后的操作了,其具体的流程为:将target和target文件夹下所有jar包发送到目标服务器上(之前配置了SSH的服务器)-> kill掉旧进程 -> 运行新进程

# kill进程名称为webChat-0.1的进程
ps -ef | grep webChat-0.1 | grep -v grep | awk '{print $2}' | xargs kill
# 后台运行webChat-0.1.jar(必须在末尾添加sleep 1)
nohup java -jar /usr/local/target/webChat-0.1.jar & sleep 1

可以看到192.168.31.3多了一个target文件夹,webChat-0.1.jar也已经从jenkins发送过来了,此时也正在运行

Jenkins自动拉取构建(Docker部署)

以上部署是直接将jar包部署到目标服务器,如果要在目标服务器上使用Docker进行部署,那么只需要修改构建后的配置即可。

新建Dockerfile

创建一个docker文件夹,创建一个Dockerfile文件

修改jenkins中构建后配置

1.如果我们使用Docker,就必须保证COPY的文件和Dockerfile是在同一级目录下,否则就会报错。

2.Docker存储库名称也必须小写,否则也会报错:

例如:docker build -t oolo/webChat:1.0 /usr/local/webchat
需要修改为 docker build -t oolo/webchat:1.0 /usr/local/webchat

系统管理 -> 系统配置 -> SSH Servers 将/usr/local修改为/usr/local/webchat

进入工程设置,图中的修改对应以下几个操作

1.Remove prefix为忽略target前缀,直接将target下的jar包发送到SSH设置指定目录,也就是/usr/local/webchat

2.删除之前直接部署在服务器上的命令,否则会导致端口冲突

3.点击Add Transfer Set,Remove prefix为忽略docker前缀,将docker目录下的所有文件发送到/usr/local/webchat

4.执行docker命令

docker build -t oolo/webchat:1.0 /usr/local/webchat
docker rm -f webchat
docker run -d -p 3333:3333 --name=webchat oolo/webchat:1.0

在部署完成后就可以看见目标服务器上新建的镜像和运行的容器了

安装部署Harbor镜像仓库

在之前的项目部署中,使用jenkins将构建好的代码通过 publish over ssh 插件推送到远程服务器进行部署,然后在远程服务器上进行镜像的构建以及容器的启动。那么如果是多台服务器就会比较耗时,这时采用在jenkins服务器上直接构建好镜像推送到镜像仓库,然后jenkins通知远程服务器直接去镜像仓库拉取镜像即可。

基于这种场景下,就可以使用harbor来统一管理镜像,主要流程为

jenkins推送jar包和Dockerfile到harbor服务器 -> harbor服务器构建过后push到harbor仓库 -> 目标服务器从harbor仓库拉取镜像

安装脚本:

# 卸载旧版本
sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
# 安装新版本
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install -y docker-ce-20.10.9 docker-ce-cli-20.10.9 containerd.io
# 启动Docker
sudo systemctl start docker
# 下载Docker Cmpose二进制文件
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 授予 Docker Compose 二进制文件执行权限
sudo chmod +x /usr/local/bin/docker-compose
# 验证 Docker Compose 安装是否成功:
docker-compose --version
cd /usr/local
# 下载harbor
wget --no-check-certificate https://github.com/goharbor/harbor/releases/download/v1.10.14/harbor-offline-installer-v1.10.14.tgz
tar xzvf harbor-offline-installer-v1.10.14.tgz

修改Harbor核心配置文件harbor.yml

  • hostname:192.168.31.6
  • 注释掉 https.*

用户名:admin,默认密码:Harbor12345

安装Harbor

./install.sh

进入后创建一个新项目

在Harbor服务器(192.168.31.6)和目标服务器(192.168.31.3)新增镜像源

cat > /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://fskvstob.mirror.aliyuncs.com"],
"insecure-registries": ["192.168.31.232:80"]
}
EOF
systemctl daemon-reload
systemctl restart docker

Jenkins实现CI持续集成

第一步,jenkins将jar包和Dockerfile推送到Harbor服务器,所以需要在jenkins配置Harbor服务器的SSH

进入 系统管理->系统配置 -> 新增SSH服务器

构建后操作 -> Add Server

添加harbor服务器构建后配置

流程:将target文件夹中的jar包和docker文件夹中的所有文件都发送到harbor服务器下的/usr/local/webchat文件夹下,然后执行以下脚本

# 构建镜像
docker build -t 192.168.31.6:80/public/webchat:1.0 /usr/local/webchat
# 登录到harbor
docker login -u admin -p Harbor12345 192.168.31.6:80
# 将镜像推送到harbor
docker push 192.168.31.6:80/public/webchat:1.0

Harbor服务器配置

修改工程配置中构建后顺序,因为jenkins需要先把Dockerfile和jar包发送给Harbor,harbor构建镜像过后再由目标服务器拉取镜像,所以需要Harbor执行顺序在目标服务器之前

拖拽该按钮至目标服务器配置之前

修改目标服务器构建后配置

流程:目标服务器只需要从harbor服务器拉取镜像,启动容器,不需要传输文件,只需要执行以下命令即可

docker rm -f webchat
docker run -d -p 3333:3333 --name=webchat 192.168.31.6:80/public/webchat:1.0

目标服务器构建后配置

配置完成后点击立即构建,发现harbor和目标服务器上都出现了对应的镜像

Jenkins参数化构建实现多版本发布

可以看到,以上构建镜像的时候,版本号都是写死的,如果需要修改版本号,还得去jenkins对应的配置中修改版本号。我们希望的是版本号可以从git的tag标签动态的获取

在jenkins配置中配置tag环境变量,后续版本号通过$tag来获取

修改打包步骤,首先git checkout $tag切换到指定的标签,然后对该标签版本进行打包

注:切换标签操作必须在打包之前,否则将直接对当前master分支进行打包

将原先所有写死的版本号修改为$tag

修改pom.xml和Dockerfile

使用${version}代表版本号

使用sed命令,将Dockerfile中的${version}替换为tag版本号

sed -i 's/${version}/$tag/' /usr/local/webchat/Dockerfile

至此Jenkins参数化构建实现多版本发布就已经完成了。

在gitlab中新建一个标签,假如当前最新的版本为1.0.0,此时我新增了一些功能,那么版本就在原来的基础上+1,为1.0.1,首先修改pom.xml中的版本为1.0.1,然后推送到gitlab上,(注:我这里是直接推送到master分支,如果在公司里面需要等待自己的分支合并到master分支选择master分支创建tag或者将master分支合并到自己的分支以后再选择自己的分支创建tag),然后在gitlab中创建一个新的标签,版本也为1.0.1,然后保存,然后在jenkins中点击Build with Parameters(原立即构建),选择对应的版本号,就可以构建所对应的tag版本的jar包。通过选择不同的tag进行构建,在代码出现问题的时候,我们可以很方便的进行回滚。

同时,harbor中也出现了对应版本的镜像

Jenkins Pipeline流水线作业

以上我们创建任务都是通过自由风格创建的,所有的配置都是通过界面来进行配置,这种方式有两个缺点:1.配置麻烦。2.不易于管理

而Jenkins Pipeline流水线作业可以直接通过脚本来部署

新建一个任务名称->选择pipeline流水线创建

然后配置tag环境变量,后续版本号通过$tag来获取,这个步骤跟之前的步骤是相同的

然后就是编写流水线脚本了,流水线脚本可以根据图形界面动态生成

脚本生成器:http://192.168.31.5/job/webchat-pipeline/pipeline-syntax/

比如我需要配置git,那么我就选择:checkout:Check out from version control

生成git配置脚本

生成Maven打包脚本

生成发送Dockerfil和jar包,构建镜像并推送到Harbor仓库脚本

生成运行容器脚本

下图为生成的脚本,stage为自己定义的当前步骤的名称,steps中的内容由脚本生成器生成

本质上跟我们之前的操作是一样的,只不过pipeline流水线是使用的脚本命令

pipeline {
    agent any

    stages {
        stage('Pull SourceCode'){
            steps{
                checkout scmGit(branches: [[name: '$tag']], extensions: [], userRemoteConfigs: [[url: 'http://192.168.31.4/root/webchat']])
            }
        }
        stage('Maven Build'){
            steps{
                sh '/usr/local/maven/bin/mvn package'
            }
        }
        stage('Publish Harbor Image'){
            steps{
                sshPublisher(publishers: [sshPublisherDesc(configName: 'harbor', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: 'echo 0', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: 'target', sourceFiles: 'target/*.jar'), sshTransfer(cleanRemote: false, excludes: '', execCommand: '''sed -i \'s/${version}/$tag/\' /usr/local/webchat/Dockerfile
                docker build -t 192.168.31.6:80/public/webchat:$tag /usr/local/webchat
                docker login -u admin -p Harbor12345 192.168.31.6:80
                docker push 192.168.31.6:80/public/webchat:$tag''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: 'docker', sourceFiles: 'docker/*')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
            }
        }
        stage('Run Container'){
            steps{
                sshPublisher(publishers: [sshPublisherDesc(configName: 'target', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''docker rm -f webchat
docker run -d -p 3333:3333 --name=webchat 192.168.31.6:80/public/webchat:$tag''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
            }
        }
    }
}

然后我们通过Build with Parameters,就可以进行发布了

发布的步骤与我们编写的脚本顺序是一致的

Gitlab托管Jenkinsfile

有时候我们希望能将脚本写在项目里面,而不是保存在Jenkins中,这时候就可以在项目中根目录创建一个Jenkinsfile文件,将我们之前的流水线脚本复制进去。

修改流水线配置,将Pipeline script修改为Pipeline script from SCM,然后配置git,最后指定流水线脚本文件,也就是Jenkinsfile,在配置完成后,Jenkins就会从git中获取Jenkinsfile配置

配置

引入容器编排Kubernetes

利⽤Kubeode快速部署单节点K8S

Kudeode官网:https://gitee.com/q7104475/kubeode

Kudeode下载地址:

k8s-2022-04-15.tar
链接:https://cloud.189.cn/t/JRZrmiBFbeUj
(访问码:6cae)

下载完成后将压缩包上传至/usr/local目录,解压缩,并执⾏安装

tar xf k8s-2022-04-24.tar
cd k8s-2022-04-24
bash install.sh

选择第一个单机部署

然后等待安装完成即可

http://192.168.31.7:30080
⽤户名:admin
密码:Kuboard123

进入首页后点击添加集群,输入名称和描述后,其他操作无需修改,直接点击确定即可

然后复制该指令执行,安装Agent,等待导入,时间可能会比较长,待到纳管状态变为已就绪就代表导入完成

http://192.168.31.7:30000 为监控平台

为docker-daemon.json增加insecure-registries私有仓库

vim /etc/docker/daemon.json

添加insecure-registries私有仓库

{
    "registry-mirrors": ["https://dockerhub.azk8s.cn","https://hub-mirror.c.163.com"],
    "insecure-registries": ["192.168.31.6:80"],
    "exec-opts": ["native.cgroupdriver=cgroupfs"],
    "log-driver": "json-file",
    "log-opts": {"max-size": "10m","max-file": "10"}
}

重载配置

sudo systemctl daemon-reload
sudo systemctl restart docker

若可以从harbor仓库拉取镜像则说明配置成功

创建K8S部署(Deployment)脚本

Deployment 介绍

为了更好地解决服务编排的问题,k8s在V1.2版本开始,引入了deployment控制器,值得一提的是,这种控制器并不直接管理pod,而是通过replicaset来间接管理pod,即:deployment管理replicaset,replicaset管理pod。所以deployment比replicaset的功能更强大

使用Harbor创建Deployment脚本

在Kuboard中default命名空间利用YAML创建部署

apiVersion: apps/v1 # 这是API版本
kind: Deployment # 这是资源类型
metadata:
  name: webchat-deployment # 这是资源名称
spec:
  # 这是副本数量
  replicas: 2
  selector:
    matchLabels:
      app: webchat-pod # 这是标签选择器
  template:
    metadata:
      labels:
        app: webchat-pod # 这是标签
    spec:
      containers:
        - name: webchat # 这是容器名称
          image: 192.168.31.6:80/public/webchat:1.1.0 # 这是容器镜像地址
          ports:
            - containerPort: 80 # 这是容器端口号

Kuboard还支持容器的动态伸缩,也就是可以控制容器的数量,也可以直接修改yaml中的replicas

通过命令的方式新增和运行Deployment脚本

在k8s主服务器上创建webchat-deployment.yml文件

mkdir /etc/k8s
cd /etc/k8s/
# 创建webchat-deployment.yml并写入脚本
cat > webchat-deployment.yml <<- 'EOF'
apiVersion: apps/v1 # 这是API版本
kind: Deployment # 这是资源类型
metadata:
  name: webchat-deployment # 这是资源名称
spec:
  # 这是副本数量
  replicas: 2
  selector:
    matchLabels:
      app: webchat-pod # 这是标签选择器
  template:
    metadata:
      labels:
        app: webchat-pod # 这是标签
    spec:
      containers:
        - name: webchat # 这是容器名称
          image: 192.168.31.6:80/public/webchat:1.1.0 # 这是容器镜像地址
          ports:
            - containerPort: 80 # 这是容器端口号
EOF

创建yml完成后通过kubectl apply -f /etc/k8s/webchat-deployment.yml启动脚本

# 选择webchat-deployment.yml配置启动脚本
kubectl apply -f /etc/k8s/webchat-deployment.yml

查看当前部署的pod

kubectl get pod

删除部署,执行后,所有pod都会进入Terminating状态,一段时间后被删除

kubectl delete deployment webchat-deployment

使用Harbor创建k8s服务(Service)脚本

很多Pod ⽹络插件的实现⽅式是将PodIP 作为私有IP地址,Pod 与Pod之间的通信是在⼀个私有⽹络中,因此要将Pod 中运⾏的服务发布出去,必然需要⼀个服务发布机制。

apiVersion: v1 # API版本
kind: Service # 资源类型
metadata: # 元数据
  name: webchat-service # 名称
spec: # 规范
  type: NodePort # Service类型
  ports: # 暴露的端口和名称
  - port: 3333 # 容器暴露的端口号
    name: service-port # 端口名称
    nodePort: 31005 # 外界访问的端口号,只能选取30000-32767范围的端口号
  selector: # 所选择的Pod标签
    app: webchat-pod # 标签名称

通过192.168.31.7:31005就可以访问容器中的3333端口了(多个容器由k8s自动进行负载均衡)

通过命令的方式新增和运行Service脚本

创建webchat-service.yml

cd /etc/k8s/
cat > webchat-service.yml <<- 'EOF'
apiVersion: v1 # API版本
kind: Service # 资源类型
metadata: # 元数据
  name: webchat-service # 名称
spec: # 规范
  type: NodePort # Service类型
  ports: # 暴露的端口和名称
  - port: 3333 # 容器暴露的端口号
    name: service-port # 端口名称
    nodePort: 31005 # 外界访问的端口号,只能选取30000-32767范围的端口号
  selector: # 所选择的Pod标签
    app: webchat-pod # 标签名称
EOF

通过命令创建Service

kubectl apply -f webchat-service.yml

运行提示当前这个service已经被创建了,这是因为我们刚才在Kuboard已经创建并运行了,所以我们可以删除当前service,重新创建即可

kubectl delete service webchat-service

Jenkins流水线驱动k8s持续部署、

使用k8s部署和使用docker的区别就是修改最后一个步骤,将docker启动容器的命令修改为k8s启动容器即可

在工程根路径下创建deployment.yml

apiVersion: apps/v1 # 这是API版本
kind: Deployment # 这是资源类型
metadata:
  name: webchat-deployment # 这是资源名称
spec:
  # 这是副本数量
  replicas: 2
  selector:
    matchLabels:
      app: webchat-pod # 这是标签选择器
  template:
    metadata:
      labels:
        app: webchat-pod # 这是标签
    spec:
      containers:
        - name: webchat # 这是容器名称
          image: 192.168.31.6:80/public/webchat:<TAG> # 这是容器镜像地址,TAG后续用于版本号切换
          ports:
            - containerPort: 80 # 这是容器端口号
---
apiVersion: v1 # API版本
kind: Service # 资源类型
metadata: # 元数据
  name: webchat-service # 名称
spec: # 规范
  type: NodePort # Service类型
  ports: # 暴露的端口和名称
    - port: 3333 # 容器暴露的端口号
      name: service-port # 端口名称
      nodePort: 31005 # 外界访问的端口号,只能选取30000-32767范围的端口号
  selector: # 所选择的Pod标签
    app: webchat-pod # 标签名称

Jenkins新增k8s Master服务器SSH

使用脚本生成器生成脚本语法

k8s脚本生成

修改Jenkinsfile脚本中的最后一步

至此,Jenkins每次构建都会将deployment.yml发送给k8s服务器,然后再通过kubectl运行k8s容器

Gitlab Webhook自动版本发布

以上操作都需要我们手动在gitlab中创建tag后再通过Build with Parameters进行构建,

有没有办法当我们创建tag版本后Jenkins就自动进行构建?

可以通过gitlab的webhook机制实现,具体过程为,Jenkins提供一个地址,当访问这个地址的时候,Jenkins就会进行构建。当gitlab检测到有新的tag产生后,就自动调用Jenkins的接口

Jenkins新增Generic Webhook Trigger插件

安装完成后重启Jenkins,进入流水线配置,找到构建触发器,勾选Generic Webhook Trigger 保存

访问http://192.168.31.5/generic-webhook-trigger/invoke,就可以触发Jenkins构建任务,但是此时构建肯定是会失败的,因为我们通过访问url构建,并没有选择tag,也就是说,deployment.yml中的、\<TAG>并不会被替换。后面的内容再解决这个问题

设置gitlab允许Webhook和服务对本地网络的请求

进入我们自己的代码仓库,点击设置->Webhooks,写入Jenkins构建url,Secret令牌为验证,同时需要在Jenkins中配置一致的Token令牌

新建一个标签,测试是否可以触发构建,查看gitlab发送的参数,可以看到,gitlab发送的参数中包含我们需要的版本号,可以在Jenkins中解析获取版本号

该设置为解析json中的ref字段,并且去除refs/tags/,如果过滤后的结果为空,默认为1.0.0

我新创建一个版本号为1.1.9,对应Jenkins也可以通过解析获得1.1.9版本号

Helm:Kubernetes包管理工具

随着容器技术和微服务架构逐渐被企业接受,在Kubernetes上已经能便捷地部署简单的应⽤了。但对于复杂的应⽤或者中间件系统,在Kubernetes上进⾏容器化部署并⾮易事,通常需要研究Docker镜像的运⾏需求、环境变量等内容,为容器配置依赖的存储、⽹络等资源,并设计和编写Deployment、ConfigMap、Service、Volume、Ingress等YAML⽂件,再将其依次提交给Kubernetes部署。总之,微服务架构和容器化给复杂应⽤的部署和管理都带来了很⼤的挑战。Helm由Deis公司(已被微软收购)发起,⽤于对需要在Kubernetes上部署的复杂应⽤进⾏定义、安装和更新,是CNCF基⾦会的毕业项⽬,由Helm社区维护。Helm将Kubernetes的资源如Deployment、Service、ConfigMap、Ingress等,打包到⼀个Chart(图表)中,⽽Chart被保存到Chart仓库,由Chart仓库存储、分发和共享。Helm⽀持应⽤Chart的版本管理,简化了Kubernetes应⽤部署的应⽤定义、打包、部署、更新、删除和回滚等操作。简单来说,Helm通过将各种Kubernetes资源打包,类似于Linux的apt-get或yum⼯具,来完成复杂软件的安装和部署,并且⽀持部署实例的版本管理等,大大简化了在Kubernetes上部署和管理应用的复杂度。

安装helm

安装脚本

yum install -y wget
mkdir -p /usr/local/helm
cd /usr/local/helm
wget --no-check-certificate https://cdn.oolo.cc//source/helm-v3.10.0-linux-amd64.tar.gz
tar zxvf helm-v3.10.0-linux-amd64.tar.gz
mv -f linux-amd64/helm /usr/bin

helm镜像仓库站:https://artifacthub.io/

比如我现在需要安装nginx,那么就在helm镜像仓库站搜索nginx,点击install

# 添加一个名为bitnami的Helm仓库
helm repo add bitnami https://charts.bitnami.com/bitnami
# 更新仓库中的 Charts 列表和元数据信息
helm repo update
# 移除my-nginx
helm uninstall my-nginx
#从远程 Helm 仓库中下载 Bitnami 的 Nginx chart,并将其安装到 Kubernetes 集群中
helm install my-nginx bitnami/nginx --version 13.2.32
helm list
# 查看my-nginx状态
helm status my-nginx
# 查看部署情况
kubectl get deploy
# 在部署后,可以使用set修改变量,比如这里是将my-nginx副本修改为3
helm upgrade my-nginx bitnami/nginx --version 13.2.10 --set replicaCount=3 

k8s自动将41526端口转发到nginx容器的80端口

构建Helm私有仓库发布自定义Charts

私有仓库使用chartmuseum,一般来说需要单独的服务器,但是这里电脑内存有点不够了,我直接在192.168.31.3使用docker进行部署

进入服务器(192.168.31.3)

docker run --name chatmuseum \
 -p 8080:8080 \
 --restart=always \
 -d bitnami/chartmuseum:0.15.0

在k8s服务器(192.168.31.7)创建/usr/local/charts目录

mkdir -p /usr/local/charts
cd /usr/local/charts
helm create webchat-charts
  • charts/: 包含了 Chart 依赖的其他 Charts。这些 Charts 可以在安装 Chart 时自动下载和安装。
  • Chart.yaml: 包含 Chart 的元数据信息(例如名称、版本、作者、依赖关系等)。
  • templates/: 包含了 Kubernetes 对象的模板文件。这些模板文件使用 Go 的文本模板语言(Template)编写,并允许在部署期间动态地生成 Kubernetes 对象的 YAML 描述文件。
  • values.yaml: 包含了默认的 Helm 值,用于覆盖 Kubernetes 对象的默认值。这些值可以在安装 Chart 时通过 --set 参数或通过外部值文件进行覆盖。

进入templates,删除所有文件,创建deployment.yaml和service.yaml

cat > deployment.yaml <<-'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webchat-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: webchat-pod
  template:
    metadata:
      labels:
        app: webchat-pod
    spec:
      containers:
        - name: webchat
          image: 192.168.31.6:80/public/webchat:<TAG>
          ports:
            - containerPort: 80
EOF

cat > service.yaml <<-'EOF'
apiVersion: v1
kind: Service
metadata:
  name: webchat-service
spec:
  type: NodePort
  ports:
    - port: 3333
      name: service-port
      nodePort: 31005
  selector:
    app: webchat-pod
EOF

回到根目录,对当前目录构建压缩包

cd /usr/local/charts/webchat-charts
helm package .

向chatmuseums服务器上传Helm Chart

curl --data-binary "@webchat-charts-0.1.0.tgz" http://192.168.31.3:8080/api/charts

如果需要删除,可以执行以下命令

curl -X DELETE http://192.168.31.3:8080/api/charts/webchat-charts/0.1.0

安装我们自己的helm脚本

首先删除我们之前部署的webchat-deployment和webchat-service,保证后续操作不会出现冲突

helm uninstall webchat
kubectl delete deployment webchat-deployment
kubectl delete service webchat-service

增加一个仓库

# 删除原有的my-repo
helm repo remove my-repo
# 新增 my-repo
helm repo add my-repo http://192.168.31.3:8080/
# 查看当前仓库
helm repo list
# 对仓库缓存进行更新,保证每次获取到的仓库信息都是最新的,每次对仓库进行修改都应该先执行更新
helm repo update
# 查看我们上传的helm
helm search repo my-repo

使用helm脚本部署

helm install webchat my-repo/webchat-charts

基于Charts模板实现版本动态发布

重写Chart.yaml,修改生成的tgz的名称和版本号

cat -> /usr/local/charts/webchat-charts/Chart.yaml <<-'EOF'
apiVersion: v2
name: webchat-charts
description: A Helm chart for Kubernetes
type: application
version: 1.0.0
appVersion: stable

重写values.yaml,设置默认3个pod节点,版本号为1.0.0,对外暴露的节点为31005,这个为默认值,如果我们没有使用--set修改,那么默认deployment中的这些字段就使用的values.yaml中的值

cat > /usr/local/charts/webchat-charts/values.yaml <<-'EOF'
replicas: 3
tag: 1.0.0
nodePort: 31005
EOF

重写deployment.yaml

cat > /usr/local/charts/webchat-charts/templates/deployment.yaml <<-'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webchat-deployment
spec:
  replicas: {{.Values.replicas}}
  selector:
    matchLabels:
      app: webchat-pod
  template:
    metadata:
      labels:
        app: webchat-pod
    spec:
      containers:
      - name: webchat
        image: 192.168.31.6:80/public/webchat:{{.Values.tag}}
        ports:
        - containerPort: 80
EOF

重写service.yaml

cat > /usr/local/charts/webchat-charts/templates/service.yaml <<-'EOF'
apiVersion: v1
kind: Service
metadata:
  name: webchat-service
spec:
  type: NodePort
  ports:
  - port: 80
    name: service-port
    nodePort: {{.Values.nodePort}}
  selector:
    app: webchat-pod
EOF

发布charts

curl -X DELETE http://192.168.31.3:8080/api/charts/webchat-charts/1.0.0
helm package .
curl --data-binary "@webchat-charts-0.1.0.tgz" http://192.168.31.3:8080/api/charts

运行

helm install webchat my-repo/webchat-charts --set replicas=2 --set tag=1.2.1

更新

helm upgrade webchat my-repo/webchat-charts --set replicas=1 --set tag=1.2.1

基于Helm实施Jenkins动态发布

前面我们的charts打包,发布都是在k8s服务器中进行的,规范的做法应该是在jenkins里面进行打包发布,然后在k8s服务器中进行install

将charts文件放到我们的项目根目录中

复制我们之前创建的流水线任务,命名为webchat-pipeline-k8s

然后进行配置,新增replicas和tag环境变量、tag之前已经创建了的话可以忽略

添加参数,选择字符参数,replicas,该配置可以让我们在手动部署的时候选择replicas

添加webhook参数配置,该配置可以在我们新增标签过后,生成一个replicas环境变量,默认值为2

流水线中新增Helm Build&Upload步骤

stage('Helm Build&Upload'){
            steps {
                sh 'curl -X DELETE http://192.168.31.3:8080/api/charts/webchat-charts/1.0.0'
                sh 'helm package ./charts/webchat-charts'
                sh 'curl --data-binary "@webchat-charts-1.0.0.tgz" http://192.168.31.3:8080/api/charts'
            }
        }

修改流水线配置

生成helm部署脚本

helm uninstall webchat
helm repo add my-repo http://192.168.31.3:8080/
helm repo update
helm install webchat my-repo/webchat-charts --set replicas=$replicas --set tag=$tag

将生成的流水线脚本覆盖Jenkinsfile中最后一步

到这里,基于Helm实施Jenkins动态发布就已经完成了

但是部署的时候出现了一个问题

这是因为Jenkins容器中没有安装Helm

yum install -y wget
mkdir -p /usr/local/helm
cd /usr/local/helm
wget --no-check-certificate https://cdn.oolo.cc//source/helm-v3.10.0-linux-amd64.tar.gz
tar zxvf helm-v3.10.0-linux-amd64.tar.gz
mv -f linux-amd64/helm /usr/bin
docker cp /usr/bin/helm jenkins:/usr/bin/helm

总结

总体思路如下

执行流程:

  1. IDEA推送代码的IDEA仓库,内含代码、Dockerfile、HelmCharts
  2. Gitlab接受到代码后,研发⼈员定义Tag,如配置WebHook,则⾃动触发Jenkins流⽔线
  3. 配置管理员、运维⼈员在Jenkins选择Tag,开始Jekins流⽔线。
    a. Jenkins 从Gitlab checkout指定Tag的代码
    b. Jenkins本地执⾏mvn package⽣成Jar包
    c. Jenkins本地执⾏helm package⽣成helm-charts.tgz⽂件
    d. Jenkins将Jar与Dockerfile发送到Harbor镜像服务器,先执⾏docker build构建镜像,再执⾏
    docker push将镜像推送是Habor仓库
    e. Jenkins将本地⽣成的helm-chart.tgz通过curl --data-binary 上传⾄Helm Museum私服
    f. Jenkins远程连接到K8S Master执⾏helm install,K8S Master先拉取Helm Charts,再执⾏脚
    本⾃动从Habor拉取Tag镜像,完整⾃动化发布流程
最后修改:2023 年 04 月 01 日
如果觉得我的文章对你有用,请随意赞赏