本文主要基于Kubernetes1.21.9和Linux操作系统CentOS7.4。
服务器版本 | docker软件版本 | Kubernetes(k8s)集群版本 | CPU架构 |
---|---|---|---|
CentOS Linux release 7.4.1708 (Core) | Docker version 20.10.12 | v1.21.9 | x86_64 |
CI/CD解决方案架构图:
CI/CD解决方案架构图描述:
程序员写好代码之后,向gitlab代码仓库提交代码,gitlab检测到变化之后,触发CI/CD服务器Jenkins,CI/CD服务器
Jenkins构建镜像,镜像构建好之后推送到registry镜像仓库,最后使用新的镜像在Kubernetes(k8s)环境部署。
CI/CD解决方案架构:k8scloude1作为Kubernetes(k8s)的master节点,k8scloude2,k8scloude3作为Kubernetes(k8s)的worker节点,由于机器有限,etcd1作为CI/CD服务器,镜像仓库,代码仓库。
服务器 | 操作系统版本 | CPU架构 | 进程 | 功能描述 |
---|---|---|---|---|
etcd1/192.168.110.133 | CentOS Linux release 7.4.1708 (Core) | x86_64 | docker,jenkins | CI/CD服务器 |
etcd1/192.168.110.133 | CentOS Linux release 7.4.1708 (Core) | x86_64 | registry | 镜像仓库 |
etcd1/192.168.110.133 | CentOS Linux release 7.4.1708 (Core) | x86_64 | gitlab,Git | 代码仓库 |
k8scloude1/192.168.110.130 | CentOS Linux release 7.4.1708 (Core) | x86_64 | docker,kube-apiserver,etcd,kube-scheduler,kube-controller-manager,kubelet,kube-proxy,coredns,calico | k8s master节点 |
k8scloude2/192.168.110.129 | CentOS Linux release 7.4.1708 (Core) | x86_64 | docker,kubelet,kube-proxy,calico | k8s worker节点 |
k8scloude3/192.168.110.128 | CentOS Linux release 7.4.1708 (Core) | x86_64 | docker,kubelet,kube-proxy,calico | k8s worker节点 |
DevOps是一种将开发(Development)和运维(Operations)相结合的软件开发方法论。它通过自动化和持续交付的方式,将软件开发、测试和部署等环节紧密集成,以提高效率和产品质量。在本篇博客中,我们将介绍如何使用GitLab、Jenkins和Kubernetes(k8s)来构建一个完整的CI/CD解决方案。
使用GitLab、Jenkins和Kubernetes(k8s)来构建CI/CD解决方案的前提是已经有一套可以正常运行的Kubernetes集群,关于Kubernetes(k8s)集群的安装部署,可以查看博客《Centos7 安装部署Kubernetes(k8s)集群》https://www.cnblogs.com/renshengdezheli/p/16686769.html。
DevOps通过打破开发和运维之间的壁垒,促进了更紧密的合作和快速响应变化的能力。它强调团队间的协作、自动化和持续改进。通过引入DevOps实践,组织可以更快地交付软件,并确保高质量的发布。
CI/CD代表持续集成(Continuous Integration)和持续交付(Continuous Delivery)。持续集成是指团队成员将其工作频繁地集成到共享存储库中,并进行自动化构建和测试,以减少集成问题。持续交付是指将应用程序更频繁地交付给用户,以便快速获得反馈并提供新功能。本次使用的CI/CD工具为Jenkins。
etcd1机器作为集成服务器,需要下载大量镜像,所以首先需要安装docker,docker版本标识:社区版 docker-ce 和企业版 docker-ee。
[root@etcd1 ~]# yum -y install docker-ce
为了让镜像下载速度变快,需要配置镜像加速器,关于docker更多详细内容,请查看博客《一文搞懂docker容器基础:docker镜像管理,docker容器管理》。
[root@etcd1 ~]# vim /etc/docker/daemon.json
[root@etcd1 ~]# cat /etc/docker/daemon.json
{
"registry-mirrors": ["https://frz7i079.mirror.aliyuncs.com"]
}
重启docker使配置生效。
[root@etcd1 ~]# systemctl restart docker
[root@etcd1 ~]# systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled)
Active: active (running) since 六 2022-03-26 17:53:49 CST; 40s ago
Docs: https://docs.docker.com
Main PID: 1495 (dockerd)
Memory: 32.9M
CGroup: /system.slice/docker.service
└─1495 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
设置docker开机自启动
[root@etcd1 ~]# systemctl enable docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
修改docker启动脚本,–insecure-registry=192.168.110.133:5000是镜像仓库的地址, 我们使用registry搭建镜像仓库,添加了–insecure-registry=192.168.110.133:5000参数之后,就可以使用http的方式拉取镜像,不然默认使用https的方式拉取镜像。
jenkins需要做的工作:构建,编译,推送,这些操作都需要借助docker去完成,但是jenkins自身是没有docker命令的,要让jenkins连接到物理机的docker上,需要添加参数:-H tcp://0.0.0.0:2376。
[root@etcd1 ~]# vim /usr/lib/systemd/system/docker.service
[root@etcd1 ~]# cat /usr/lib/systemd/system/docker.service
.....
ExecStart=/usr/bin/dockerd --insecure-registry=192.168.110.133:5000 -H tcp://0.0.0.0:2376 -H fd:// --containerd=/run/containerd/containerd.sock
.....
重新加载配置文件,重启docker。
[root@etcd1 ~]# systemctl daemon-reload ;systemctl restart docker
查看状态可以发现:8083 /usr/bin/dockerd --insecure-registry=192.168.110.133:5000 -H tcp://0.0.0.0:2376 -H fd:// --containerd=/run/containerd/containerd.sock,修改参数成功。
[root@etcd1 ~]# systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: active (running) since 二 2022-03-29 11:37:51 CST; 20s ago
Docs: https://docs.docker.com
Main PID: 8083 (dockerd)
Memory: 36.8M
CGroup: /system.slice/docker.service
└─8083 /usr/bin/dockerd --insecure-registry=192.168.110.133:5000 -H tcp://0.0.0.0:2376 -H fd:// --containerd=/run/containerd/containerd.sock
我们把镜像推送到registry镜像仓库之后,k8s集群的worker节点会向registry镜像仓库拉取镜像,默认使用https的方式从镜像仓库拉取镜像,需要在k8s的worker节点修改docker启动参数,添加–insecure-registry=192.168.110.133:5000,让其使用http的方式从registry镜像仓库拉取镜像。
[root@k8scloude2 ~]# vim /usr/lib/systemd/system/docker.service
[root@k8scloude2 ~]# cat /usr/lib/systemd/system/docker.service
......
ExecStart=/usr/bin/dockerd --insecure-registry=192.168.110.133:5000 -H fd:// --containerd=/run/containerd/containerd.sock
......
[root@k8scloude2 ~]# grep ExecStart /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd --insecure-registry=192.168.110.133:5000 -H fd:// --containerd=/run/containerd/containerd.sock
重新加载配置文件,重启docker。
[root@k8scloude2 ~]# systemctl daemon-reload ;systemctl restart docker
[root@k8scloude2 ~]# systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: active (running) since 二 2022-03-29 11:51:36 CST; 4s ago
Docs: https://docs.docker.com
Main PID: 57510 (dockerd)
Memory: 63.6M
CGroup: /system.slice/docker.service
├─57510 /usr/bin/dockerd --insecure-registry=192.168.110.133:5000 -H fd:// --containerd=/run/containerd/containerd.sock
├─57759 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 80 -container-ip 172.17.0.2 -container-port 80
└─57767 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 80 -container-ip 172.17.0.2 -container-port 80
k8scloude3节点也需要修改docker启动参数,添加–insecure-registry=192.168.110.133:5000,让其使用http的方式从registry镜像仓库拉取镜像。
[root@k8scloude3 ~]# vim /usr/lib/systemd/system/docker.service
[root@k8scloude3 ~]# grep ExecStart /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd --insecure-registry=192.168.110.133:5000 -H fd:// --containerd=/run/containerd/containerd.sock
重新加载配置文件,重启docker。
[root@k8scloude3 ~]# systemctl daemon-reload ;systemctl restart docker
[root@k8scloude3 ~]# systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: active (running) since 二 2022-03-29 15:55:13 CST; 5s ago
Docs: https://docs.docker.com
Main PID: 9099 (dockerd)
Memory: 43.1M
CGroup: /system.slice/docker.service
└─9099 /usr/bin/dockerd --insecure-registry=192.168.110.133:5000 -H fd:// --containerd=/run/containerd/containerd.sock
现在k8s集群的所有worker节点都加上了–insecure-registry=192.168.110.133:5000参数。
在etcd1机器拉取nginx镜像,之后做web容器的时候会用到。
[root@etcd1 ~]# docker pull nginx
Using default tag: latest
......
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
[root@etcd1 ~]# docker images | grep nginx
nginx latest 605c77e624dd 3 months ago 141MB
本次使用registry搭建镜像仓库,也可以使用harbor搭建镜像仓库,功能更丰富,关于harbor的详细内容,请查看博客《搭建docker镜像仓库(二):使用harbor搭建本地镜像仓库》。
拉取registry镜像
[root@etcd1 ~]# docker pull hub.c.163.com/library/registry:latest
[root@etcd1 ~]# docker images | grep registry
hub.c.163.com/library/registry latest 751f286bc25e 4 years ago 33.2MB
注意:registry的数据卷为:VOLUME [/var/lib/registry],不能是其他的。
创建registry容器,registry镜像生成容器作为私有仓库,-p 5000:5000做端口映射,物理机端口5000:容器端口5000,
-v /myregistry:/var/lib/registry数据卷挂载,物理机目录/myregistry:容器目录/var/lib/registry。
[root@etcd1 ~]# docker run -d --name registry -p 5000:5000 --restart=always -v /myregistry:/var/lib/registry hub.c.163.com/library/registry
3aa799d1974611fc403ce38aa19a156cb165a82573b84b16fde665d9e3b62eb0
现在registry镜像仓库就搭建好了。
[root@etcd1 ~]# docker ps | grep registry
3aa799d19746 hub.c.163.com/library/registry "/entrypoint.sh /etc…" 8 seconds ago Up 7 seconds 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp registry
此时镜像仓库下还没有任何文件
[root@etcd1 ~]# ls /myregistry/
在etcd1机器下载gitlab中文版镜像
[root@etcd1 ~]# docker pull beginor/gitlab-ce
[root@etcd1 ~]# docker images | grep gitlab
beginor/gitlab-ce latest 5595d4ff803e 3 years ago 1.5GB
创建gitlab配置文件目录,日志目录,代码目录
[root@etcd1 ~]# mkdir -p /data/gitlab/etc /data/gitlab/log /data/gitlab/data
给gitlab配置文件目录,日志目录,代码目录授予777权限
[root@etcd1 ~]# chmod 777 /data/gitlab/etc /data/gitlab/log /data/gitlab/data
创建gitlab容器,使用–privileged=true参数,使container内的root拥有真正的root权限。否则,container内的root只是外部的一个普通用户权限。–privileged=true启动的容器,可以看到很多host上的设备,并且可以执行mount。甚至允许你在docker容器中启动docker容器。
-v指定数据卷,gitlab容器的配置文件,日志文件,数据文件也都存储到了物理机上,我们修改对应数据卷的内容,gitlab容器的相关内容也随之改变。-p指定端口映射。
[root@etcd1 ~]# 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 beginor/gitlab-ce
查看gitlab容器
[root@etcd1 ~]# docker ps | grep gitlab
d23f2df47e42 beginor/gitlab-ce "/assets/wrapper" 22 hours ago Up 6 hours (healthy) 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:222->22/tcp, :::222->22/tcp, 0.0.0.0:8443->443/tcp, :::8443->443/tcp gitlab
现在gitlab配置文件目录,日志目录,代码目录都有相关文件了。
[root@etcd1 ~]# ls /data/gitlab/etc/
gitlab.rb gitlab-secrets.json ssh_host_ecdsa_key ssh_host_ecdsa_key.pub ssh_host_ed25519_key ssh_host_ed25519_key.pub ssh_host_rsa_key ssh_host_rsa_key.pub trusted-certs
[root@etcd1 ~]# ls /data/gitlab/log/
gitaly gitlab-monitor gitlab-rails gitlab-shell gitlab-workhorse logrotate nginx node-exporter postgres-exporter postgresql prometheus reconfigure redis redis-exporter sidekiq sshd unicorn
[root@etcd1 ~]# ls /data/gitlab/data/
backups gitaly gitlab-ci gitlab-rails gitlab-workhorse nginx postgres-exporter prometheus redis
bootstrapped git-data gitlab-monitor gitlab-shell logrotate node-exporter postgresql public_attributes.json trusted-certs-directory-hash
注意先让gitlab容器运行一段时间,让其数据进行初始化,然后再停止gitlab容器,修改配置文件。
[root@etcd1 ~]# docker stop gitlab
下面开始修改gitlab的配置文件。
修改/data/gitlab/etc/gitlab.rb