CI:可持续集成
CD:可持续交付\可持续部署
具体含义请参考:https://blog.csdn.net/tushanpeipei/article/details/118082462?spm=1001.2014.3001.5501
本次实验仅存在测试部署环境。
实验流程:
步骤1: 程序员将代码编辑完成后推到代码仓库GitLab里;
步骤2: CI Tool Jenkins将Gitlab里的代码代码打包成镜像;
步骤3: Jenkins将镜像推送到镜像仓库Docker Registry;
步骤4: Jenkins在测试环境K8s集群中部署应用;
步骤5: K8s集群在部署应用的镜像从创建的私有镜像仓库Docker Registry中下载。
为了节约设备性能,我们将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
步骤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
篇幅较长,请参考:
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
实验环境: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
解释:
注意: 如果端口映射冲突可以自行更改端口。
查看容器是否启动:
[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和你设置的密码进行登录。
步骤6: 创建gitlab项目
选择创建空白的项目:
设置项目名称并创建:
完成后,我们可以看到这里的提示:点击添加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
步骤7:初始化项目
重新回到我们的项目页面:
复制内容到我们的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的项目中,可以查看:
注意:
到目前为止,gitlab的操作已经完成一大半,最后需要等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了:
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,并拷贝密码登陆
容器内的目录为/var/jenkins_home/secrets/initiaAdminPassword,对应的宿主机目录如下:
cat /jenkins/secrets/initialAdminPassword
拷贝密码后登陆jenkins,然后选择安装推荐的插件。这个时候就会自动去安装,当插件都安装成功后,会看到如下的页面:
填写信息并创建管理员用户。创建完成后,我们就进入了jenkins的主页:
步骤7:连接jenkins和宿主机的docker,让jenkins能够构建镜像,发布到镜像仓库中
按照如下的步骤进行:安装docker插件
如果不能直接安装,则选择install without restart,然后点击已安装,就可以找到对应的插件了:
然后按照以下的图示去连接到宿主机的docker上:
选择docker:
然后选择设置详细信息:按照如下的信息进行连接。
继续操作:
找到docker builder一栏,然后测试连通性,并保存。
完成这部以后,jenkins就能连接到宿主机,做镜像打包等操作了。
步骤8: 在jenkins中设置gitlab连接的安全参数
设置授权策略并保存:
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完成镜像构建。点击主页的新建任务:
输入任务名称,选择构建一个自由风格的软件项目。点击确定后,选择构建触发器:
然后记录触发器的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
执行shell命令,从gitlab上获取克隆的代码:
其中,shell脚本时进入jenkins的home目录,然后删除掉原来clone的文件,然后重新克隆。克隆的地址可以在gitlab的项目中获取:
设置完成后,点击添加构建步骤,这记为步骤2,目的是构建镜像并推送到镜像仓库,点击build/Publish docker image,然后按照下面的图示填写:
完成后,继续添加构建步骤,这里记为步骤3,选择shell,这个步骤的目的是部署应用到k8s环境:
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应用:
步骤12:设置Gitlab触发jenkins
点击admin area:
修改outbround request配置:允许jenkins连接
返回自己的项目中,点击webhook,添加之前得到的jenkins的url。完成后点击添加webhook。
测试webhook是否成功:
可以看到如下的提示:说明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上查看时是否推送成功:
然后再jenkins上查看构建记录:
查看控制台输出:
以下是控制台输出的内容:分别记录了再gitlab中克隆代码、构建镜像、推送镜像和部署应用的工程。
我们可以在游览器上重新访问k8s集群里的nginx,查看主页是否被替换:
可以看到,主页被替换,整体部署成功!!!
创作不易,如果觉得写的不错,请点个赞吧!!!
参考资料:
《老段CKA课程》
k8s+Jenkins+GitLab-自动化部署asp.net core项目: