十七、K8s+gitlab+Jenkins建立CI/CD解决方案

一、什么是CI/CD:

CI:可持续集成
CD:可持续交付\可持续部署
具体含义请参考:https://blog.csdn.net/tushanpeipei/article/details/118082462?spm=1001.2014.3001.5501

CI/CD环境流程图:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第1张图片

二、实验环境总览:

十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第2张图片

本次实验仅存在测试部署环境。

实验流程:

步骤1: 程序员将代码编辑完成后推到代码仓库GitLab里;

步骤2: CI Tool Jenkins将Gitlab里的代码代码打包成镜像;

步骤3: Jenkins将镜像推送到镜像仓库Docker Registry;

步骤4: Jenkins在测试环境K8s集群中部署应用;

步骤5: K8s集群在部署应用的镜像从创建的私有镜像仓库Docker Registry中下载。

物理环境图:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第3张图片

为了节约设备性能,我们将Jenkins、GitLab、Registry三个部分搭建到一个虚拟机(Centos8)上,且已经安装好了docker-ce。

在K8s集群中,有三台虚拟机,一台Master、两台Worker Nodes。

总体来说,实验环境一共用到了四台虚拟机和一台测试使用的物理机(本机)。

准备步骤:
步骤1:在centos8上设置docker的私有仓库源

[root@localhost ~]# cat /usr/lib/systemd/system/docker.service

ExecStart=/usr/bin/dockerd --insecure-registry 192.168.0.166:5000 -H fd:// --containerd=/run/containerd/containerd.sock

在ExecStart=这个位置写上私有仓库的地址和端口号(192.168.0.166:5000)

步骤2:由于Jenkins需要借助其宿主的docker来构建编译和推送,所以还需要在ExecStart=这个位置加上如下的信息

[root@localhost ~]# cat /usr/lib/systemd/system/docker.service

ExecStart=/usr/bin/dockerd --insecure-registry 192.168.0.166:5000 -H tcp://0.0.0.0:2376 -H fd:// --containerd=/run/containerd/containerd.sock

后续Jenkins可以通过其宿主机的2376端口使用docker的相关功能。

步骤3: 重启docker

systemctl daemon-reload ; systemctl restart docker

步骤4: 在centos上下载后续使用所需使用的镜像nginx

docker pull nginx

三、Docker Registey搭建:

步骤1: centos8上下载registry镜像

docker pull registry

步骤2: 运行容器

docker run -d --name registry -p 5000:5000 --restart=always -v /myreg:/var/lib/registry registry

registry使用宿主机的5000端口,并将宿主机的目录/myreg映射到了容器的/var/lib/registry中。

步骤3: 查看容器是否正常运行

[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE              COMMAND                  CREATED       STATUS                    PORTS                                                           NAMES
8131b6a2970e   registry:latest    "/entrypoint.sh /etc…"   2 weeks ago   Up 15 minutes             0.0.0.0:5000->5000/tcp   

四、K8s环境搭建:

十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第4张图片

篇幅较长,请参考:
https://blog.csdn.net/tushanpeipei/article/details/118395393?spm=1001.2014.3001.5501

注意:为了能够让K8s的worker也能够访问私有仓库,拉取镜像,也需要在2个Worker上设置docker的私有仓库源:

cat /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd --insecure-registry 192.168.0.166:5000 -H fd:// --containerd=/run/containerd/containerd.sock

五、Gitlab搭建:

实验环境:Centos8,已经提前安装好Docker。

步骤1:拉取gitlab镜像

docker pull gitlab/gitlab-ce

ce是社区版本,免费。

步骤2:运行gitlab-ce容器
通常会将 GitLab 的配置 (etc) 、 日志 (log) 、数据 (data)放到容器之外, 便于日后升级, 因此请先准备这三个目录。并确保目录存在并且已授予适当的权限。

在系统的根目录执行(存放的路径根据自己随意设置即可)。

mkdir -p /data/gitlab/etc /data/gitlab/log /data/gitlab/data
chmod 777 /data/gitlab/etc /data/gitlab/log /data/gitlab/data

然后创建容器:

docker run -dit --name=gitlab --restart=always -p 8443:443 -p 80:80 -p 222:22 -v /data/gitlab/etc/:/etc/gitlab -v /data/gitlab/log:/var/log/gitlab -v /data/gitlab/data:/var/opt/gitlab --privileged=true gitlab/gitlab-ce

解释:

  1. -d:后台运行
  2. -p:将容器内部端口向外映射
  3. –name:命名容器名称
  4. -v:将容器内数据文件夹或者日志、配置等文件夹挂载到宿主机指定目录
  5. 8443:443:将http:8443映射到外部端口443
  6. 80:80:将web:80映射到外部端口80
  7. 222:22:将ssh:22映射到外部端口222

注意: 如果端口映射冲突可以自行更改端口。

查看容器是否启动:

[root@localhost /]# docker ps
CONTAINER ID   IMAGE              COMMAND                  CREATED         STATUS                            PORTS                                                            NAMES
881d0b875d3a   gitlab/gitlab-ce   "/assets/wrapper"        2 minutes ago   Up 2 minutes (health: starting)   0.0.0.0:80->80/tcp, 0.0.0.0:222->22/tcp, 0.0.0.0:8443->443/tcp   gitlab

步骤3:修改gitlab.rb文件
按上面的方式,gitlab容器运行没问题,但在gitlab上创建项目的时候,生成项目的URL访问地址是按容器的hostname来生成的,也就是容器的id。作为gitlab服务器,我们需要一个固定的URL访问地址,于是需要配置gitlab.rb ,配置http协议所使用的访问地址。

首先需要将gitlab的容器stop一下:

docker stop gitlab

通过vim来编辑相应的配置,:

vim /data/gitlab/etc/gitlab.rb

此文件中的所有信息都是被注释掉的,需要找到如下三行取消注释,并修改其中的内容。

配置http协议所使用的访问地址(宿主机地址),不加端口号默认为80:

external_url 'http://192.168.0.166'  

配置ssh协议所使用的访问地址和端口:

gitlab_rails['gitlab_ssh_host'] = '192.168.0.166'
gitlab_rails['gitlab_shell_ssh_port'] = 222 # 此端口是run时22端口映射的222端口

保存配置文件并退出。

步骤4:修改gitlab.yml文件

vim /data/gitlab/data/gitlab-rails/etc/gitlab.yml

设置host为自己的地址:

 ## GitLab settings
  gitlab:
    ## Web server settings (note: host is the FQDN, do not include http://)
    host: 192.168.0.166
    port: 80
    https: false

步骤5:启动容器,登录检查

docker start gitlab

输入命令后等待一段时间,使用命令docker ps查看容器的状态:

[root@localhost /]# docker ps
CONTAINER ID   IMAGE              COMMAND                  CREATED          STATUS                   PORTS                                                                              NAMES
881d0b875d3a   gitlab/gitlab-ce   "/assets/wrapper"        24 minutes ago   Up 2 minutes (healthy)   0.0.0.                  0:80->80/tcp, 0.0.0.0:222->22/tcp, 0.0.0.0:8443->443/tcp   gitlab

注意STATUS这里一定要是healthy。然后再游览器中输入192.168.0.166这个宿主机地址,进入到gitlab的页面。初次登陆会让你设置root账号的密码,并且需要满足一定的安全性要求,然后就可以通过root和你设置的密码进行登录。
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第5张图片
步骤6: 创建gitlab项目
选择创建空白的项目:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第6张图片
设置项目名称并创建:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第7张图片
完成后,我们可以看到这里的提示:点击添加SSH Key
在这里插入图片描述
返回centos8,创建公钥和私钥:

[root@localhost ~]# ssh-keygen -N ""
[root@localhost ~]# ls .ssh
id_rsa  id_rsa.pub  known_hosts

查看公钥信息,然后复制到gitlab的Key中。

cat .ssh/id_rsa.pub

十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第8张图片
完成了这一步后,我们就可以用ssh连接到gitlab上。

步骤7:初始化项目
重新回到我们的项目页面:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第9张图片
复制内容到我们的centos8上,设置一些变量:(没有安装git的话,需要提前安装yum install git -y)

然后根据第二步,克隆test_project:

git clone ssh://[email protected]:222/root/test_project.git

根据第三步提示,进入克隆的目录,创建README.md介绍文件,并push到gitlab上:

cd test_project
touch README.md
git add README.md
git commit -m "add README"
git push -u origin master

在这个步骤中,如果第一次创git,提示报错的话,需要按照其提示的信息操作。完成上述步骤后,我们就将创建的README.md push到了gitlab的项目中,可以查看:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第10张图片
注意:

到目前为止,gitlab的操作已经完成一大半,最后需要等Jenkins搭建完成后,触发Jenkins做操作。

六、Jenkins搭建:

步骤1:Centos8上下载Jenkins镜像

docker pull jenkins/jenkins

步骤2:创建目录,在本地创建一个数据卷挂载docker容器中的数据卷

mkdir /jenkins ; chown 1000.1000 /jenkins

需要修改下目录权限,因为当映射本地数据卷时,/jenkins目录的拥有者为root用户,而容器中jenkins用户的 uid 为 1000。

步骤3:创建Jenkins容器

docker run -dit -p 8080:8080 -p 50000:50000 --name jenkins --privileged=true --restart=always -v /jenkins:/var/jenkins_home jenkins/jenkins

步骤4:修改Jenkins信息
当通过游览器访问如下页面后(8080端口),等待一段时间,就可以停止掉Jenkins了:十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第11张图片

docker stop Jenkins

修改如下文件的设置,将更新Jenkins,安装Jenkins插件的地址修改为国内的源:

[root@localhost ~]# cat /jenkins/hudson.model.UpdateCenter.xml
<?xml version='1.1' encoding='UTF-8'?>
<sites>
  <site>
    <id>default</id>
    <url>http://mirrors.tuna.tsinghua.edu.cn/jenkins</url>
  </site>
</sites>

修改的第二个地址:vim /jenkins/updates/default.json;将第一行的www.google.com修改为www.baidu.com。

步骤5: 重新启动jenkins

docker start jenkins

步骤6:访问jenkins,并拷贝密码登陆
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第12张图片
容器内的目录为/var/jenkins_home/secrets/initiaAdminPassword,对应的宿主机目录如下:

cat /jenkins/secrets/initialAdminPassword

拷贝密码后登陆jenkins,然后选择安装推荐的插件。这个时候就会自动去安装,当插件都安装成功后,会看到如下的页面:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第13张图片
填写信息并创建管理员用户。创建完成后,我们就进入了jenkins的主页:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第14张图片
步骤7:连接jenkins和宿主机的docker,让jenkins能够构建镜像,发布到镜像仓库中

按照如下的步骤进行:安装docker插件
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第15张图片
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第16张图片
如果不能直接安装,则选择install without restart,然后点击已安装,就可以找到对应的插件了:
在这里插入图片描述
然后按照以下的图示去连接到宿主机的docker上:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第17张图片
在这里插入图片描述
选择docker:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第18张图片
然后选择设置详细信息:按照如下的信息进行连接。
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第19张图片
继续操作:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第20张图片
找到docker builder一栏,然后测试连通性,并保存。
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第21张图片
完成这部以后,jenkins就能连接到宿主机,做镜像打包等操作了。

步骤8: 在jenkins中设置gitlab连接的安全参数
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第22张图片
设置授权策略并保存:

十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第23张图片
返回到Centos8中去关闭CSRF,进入容器中:

docker exec -u root -it jenkins bash

如果容器里面协议vi或者vim,则需要下载:

apt-get update
apt-get install vim

修改文件,大概在第37行,添加如下内容:

vim /usr/local/bin/jenkins.sh

修改的内容如下:

 exec java -Duser.home="$JENKINS_HOME" -Dhudson.security.csrf.GlobalCrumbIssuerConfiguration.DISABLE_CSRF_PROTECTION=true  "${java_opts_array[@]}" -jar ${JENKINS_WAR} "${jenkins_opts_array[@]}" "$@"

保存后退出,重启jenkins。完成后重新登陆jenkins,然后再安全设置里面可以看到CSRF已经被关闭掉了。
在这里插入图片描述

步骤9: 在jenkins中下载k8s客户端(能够在K8s环境下部署)

在Centos8上:注意版本号和k8s集群的要相同

curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.21.0/bin/linux/amd64/kubectl

获取K8s的登陆文件kc1,如何获取可以查看https://blog.csdn.net/tushanpeipei/article/details/118662027?spm=1001.2014.3001.5501,记得还需要对对应用户进行授权(给了cluster-admin权限)。

然后拷贝kc1和kubectl到容器中:

[root@localhost ~]# docker cp kc1 jenkins:/
[root@localhost ~]# docker cp kubectl jenkins:/

进入jenkins容器,给kubectl加上权限:

[root@localhost ~]# docker exec -u root -it jenkins bash
root@1703fb001ac9:/# chmod +x ./kubectl
root@1703fb001ac9:/# chmod 644 kc1

查看是否能够登陆k8s,并进行管理:

root@1703fb001ac9:/# ./kubectl --kubeconfig=kc1 get nodes -n security
NAME             STATUS   ROLES                  AGE   VERSION
vms201.rhce.cc   Ready    control-plane,master   11d   v1.21.0
vms202.rhce.cc   Ready    <none>                 11d   v1.21.0
vms203.rhce.cc   Ready    <none>                 11d   v1.21.0

步骤10:创建jenkins任务,构建触发器

构建触发器的目的是让gitlab中代码修改后能够触发jenkins完成镜像构建。点击主页的新建任务:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第24张图片
输入任务名称,选择构建一个自由风格的软件项目。点击确定后,选择构建触发器:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第25张图片
然后记录触发器的URL:
JENKINS_URL/job/test_task/build?token=TOKEN_NAME,替换为自己的URL:http://192.168.0.166:8080/job/test_task/build?token=prin123;后续需要在gitlab中应用。

步骤11:定义jenkins执行的任务
选择增加构建步骤,这里记为步骤1
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第26张图片
执行shell命令,从gitlab上获取克隆的代码:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第27张图片
其中,shell脚本时进入jenkins的home目录,然后删除掉原来clone的文件,然后重新克隆。克隆的地址可以在gitlab的项目中获取:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第28张图片
设置完成后,点击添加构建步骤,这记为步骤2,目的是构建镜像并推送到镜像仓库,点击build/Publish docker image,然后按照下面的图示填写:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第29张图片
完成后,继续添加构建步骤,这里记为步骤3,选择shell,这个步骤的目的是部署应用到k8s环境:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第30张图片
shell脚本的含义是,使用登陆文件kc1,然后替换掉deployment/web1的镜像为自己构建的新镜像,命令空间为net。完成后选择保存。

为了配合实验,我们需要到k8s的master上创建对应的ns、deployment和服务:

[root@vms201 cicd]# kubectl create namespace net
namespace/net created
[root@vms201 cicd]# kubens net
Context "kubernetes-admin@kubernetes" modified.
Active namespace is "net".

创建对应命名空间并切换后,部署deployment,yaml文件为:

[root@vms201 cicd]# cat web1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: web1
  name: web1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web1
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: web1
    spec:
      containers:
      - image: nginx
        name: nginx
        imagePullPolicy: IfNotPresent
        resources: {}
status: {}

通过yaml文件部署3个nginx的pod:

[root@vms201 cicd]# kubectl apply -f web1.yaml
deployment.apps/web1 created
[root@vms201 cicd]# kubectl get pods
NAME                    READY   STATUS    RESTARTS   AGE
web1-5bfb6d8dcc-5g9mt   1/1     Running   0          22s
web1-5bfb6d8dcc-fgqvn   1/1     Running   0          22s
web1-5bfb6d8dcc-glv5k   1/1     Running   0          22s

创建对应的服务:

[root@vms201 cicd]# kubectl expose --name=svc1 deployment web1 --port=80 --type=NodePort
service/svc1 exposed
[root@vms201 cicd]# kubectl get svc
NAME   TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
svc1   NodePort   10.105.213.119   <none>        80:32221/TCP   5s

现在可以在物理机上访问k8s集群内任意IP地址的32221端口,查看nginx应用:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第31张图片
步骤12:设置Gitlab触发jenkins
点击admin area:
在这里插入图片描述
修改outbround request配置:允许jenkins连接
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第32张图片
返回自己的项目中,点击webhook,添加之前得到的jenkins的url。完成后点击添加webhook。
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第33张图片
测试webhook是否成功:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第34张图片
可以看到如下的提示:说明webhook部署成功。
在这里插入图片描述
完成了这一步后,整个环境就部署完成。

七、最终测试

步骤1:在centos8上,创建一个nginx的dockerfile

[root@localhost test_project]# cat Dockerfile
FROM docker.io/nginx
MAINTAINER Prin
ADD index.html /usr/share/nginx/html/
EXPOSE 80
CMD ["nginx","-g","daemon off;"]

其中,此镜像由nginx基础镜像来构建,并且替换了index.html主页到容器内。

index.html文件如下:

[root@localhost test_project]# cat index.html
Hello World!!!! K8s CICD Test!

步骤2:将2个文件推送到到Gitlab中

[root@localhost test_project]# git add .
[root@localhost test_project]# git commit -m "test"
[master 9ed8b7f] test
 2 files changed, 6 insertions(+)
 create mode 100644 Dockerfile
 create mode 100644 index.html
[root@localhost test_project]# git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 2 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 449 bytes | 449.00 KiB/s, done.
Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
To ssh://192.168.0.166:222/root/test_project.git
   12fae63..9ed8b7f  master -> master

步骤3:查看整体效果

在gitlab上查看时是否推送成功:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第35张图片
然后再jenkins上查看构建记录:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第36张图片
查看控制台输出:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第37张图片
以下是控制台输出的内容:分别记录了再gitlab中克隆代码、构建镜像、推送镜像和部署应用的工程。
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第38张图片
我们可以在游览器上重新访问k8s集群里的nginx,查看主页是否被替换:
十七、K8s+gitlab+Jenkins建立CI/CD解决方案_第39张图片
可以看到,主页被替换,整体部署成功!!!

创作不易,如果觉得写的不错,请点个赞吧!!!

参考资料:
《老段CKA课程》
k8s+Jenkins+GitLab-自动化部署asp.net core项目:

你可能感兴趣的:(云计算,DevOps,K8s,gitlab,jenkins,CI/CD)