CICD 概念

首先我们先了解一下 CICD 的概念:

既持续集成称为 CI、持续交付和持续部署可以统称为 CD

持续集成/持续交付软件

这次使用的持续交付系统是通过Jenkins实现的,通过Jenkins可以快速的搭建符合自己业务场景的流水线流程,结合大量的开源插件,可以轻松的满足不同语言、不同平台、包括不同框架的持续基层场景。

环境搭建

本次使用的环境:

1、Centos 7服务器(可以为虚拟机)

2、容器镜像云服务 (可以为私有,本文中使用的为阿里云容器服务)

3、Kubernetes (我使用的是自己搭建的,也适用阿里云容器)

4、Gitee

首先搭建 Jenkins 系统,这次选择使用容器搭建 Jenkins 系统。我们会在一个 CentOS 7 的机器上去安装 Docker 服务,然后使用 Docker 去启动 Jenkins master,master 启动起来以后我们就可以登录到他的 web 界面上边去,从界面上去给他安装插件,然后配置构建节点,并且运行第一个构建项目。

1、安装Docker运行环境

# 1.移除以前docker相关包
sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

# 2. 配置yum源
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 3. 安装docker
sudo yum install -y docker-ce docker-ce-cli containerd.io

# 4. 启动docker
systemctl enable docker --now

# 5. 配置阿里云加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://26t56xmf.mirror.aliyuncs.com"],
  "live-restore": true,
  "storage-driver": "overlay2"
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

上面的命令没有报错的话doker就已经启动成功了,也可以使用systemctl status docker 查看docker是否在运行,running表示已经在运行了

2、安装Jenkins

接下来我们启动Jenkins容器(命令为一整行,因为过长换行了,不要分开复制)

docker run -u root -itd -p 8080:8080 -p 50000:50000 -v /var/jenkins_home:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock --name jenkins-master jenkins/jenkins:jdk11

参数解释:

-u root 表示用root运行这个容器

-itd 以交互模式后台运行这个容器

-p 8080:8080 将容器内的8080端口映射到主机8080端口,前面为主机端口,后面为容器内端口,主机端口可以自行更改

-p 50000:50000 同上

-v /var/jenkins_home:/var/jenkins_home 将容器的/var/jenkins_home目录挂在到主机的/var/jenkins_home目录上,方便我们修改Jenkins相关配置,前面为主机目录,后面为容器内目录

-v /var/run/docker.sock:/var/run/docker.sock 因为容器内可能会用到docker命令,所以把主机目录挂载到容器中

–name jenkins-master 为容器命名

jenkinsci/blueocean 表示我们使用的是Jenkins master 镜像的 blueocean 的版

docker会先去拉取镜像,镜像拉取完成以后容器就会开始启动,拉取速度视网络而定,所以要稍等一会,容器运行以后可以使用docker ps命令查看运行状态,运行成功以后就可以通过本机IP:8080的方式访问jenkins了,出现下面的页面表示启动成功(没有可以等一会,程序启动需要时间)

因为我们已经把容器里的/var/jenkins_home挂载到本机,所以直接cat /var/jenkins_home/secrets/initialAdminPassword就可以了,输入密码后选择继续

登陆成功后,可以看到 Jenkins 给我们提供了两个选项:一个就是安装推荐的插件,一个是选择插件的安装。我们新手刚搭建起来的话,可以直接点击安装推荐的插件。后续的话,我们可以在 Jenkins 的插件管理界面上边自定义的添加自己想要的插件。选择选择安装推荐的插件即可

推荐插件安装完成之后,会进入到如下图所示界面,可以创建一个管理员用户

接下来的设置我们采用默认的就好

到此Jenkins安装完成
Jenkins CI 这个系统里不希望 master 作为构建节点,所以我们需要在系统设置里边关于系统的主目录以及执行者数量作出修改,原先是2,我们把它设置成零进行保存,这样设置的话,Jenkins master 就不允许作业运行在它上边,我们需要另外给它配置 slave 节点去执行相应的 job。(系统管理->节点管理,然后点mastre后面的小齿轮)

3、配置构建节点

为了方便,构建节点也使用容器部署

# 拉取镜像
docker pull registry.cn-beijing.aliyuncs.com/codepipeline/jenkins-slave-java:latest

# 启动镜像(将容器里的22端口,也就是SSH的端口映射到宿主机的30001上)
docker run -itd -p 30001:22 -v /var/run/docker.sock:/var/run/docker.sock registry.cn-beijing.aliyuncs.com/codepipeline/jenkins-slave-java:latest

因为后面我们要通过ssh连接到容器里,所以我们等容器运行以后进入容器,修改root密码

[root@test ~]# docker ps -a
CONTAINER ID   IMAGE                                                                     COMMAND                  CREATED      STATUS      PORTS                                              NAMES
bff4112a43e6   registry.cn-beijing.aliyuncs.com/codepipeline/jenkins-slave-java:latest   "/usr/sbin/sshd -D"      3 days ago   Up 3 days   0.0.0.0:30001->22/tcp                              objective_feynman
2ebfca3486d7   jenkinsci/blueocean                                                       "/sbin/tini -- /usr/…"   3 days ago   Up 3 days   0.0.0.0:8080->8080/tcp, 0.0.0.0:50000->50000/tcp   jenkins-master
[root@test ~]# docker exec -it bff4112a43e6 /bin/bash
root@bff4112a43e6:/# sudo passwd root
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully

接着依次点击 系统配置 –> 节点管理,这里我们可以看到只有 master 这一个节点,由于刚才它已经被我们设置了可执行数量为0,因此它现在是没法去构建 job。因此我们需要新建一个节点,起名字叫做 slave-java,勾选固定节点,然后点击ok

然后进入到详细设置页面,首先来设置并发构建数,我们可以改成5;然后设置 Job 在该构建节点上的工作空间,这里为 /home/jenkins;然后设置标签,标签用于在 Job 的配置中选择,可以映射到具体的构建节点,用法一般选择只允许运行绑定到这台机器上的 Job

启动方式的话,我们可以选择 SSH 远程连接方式,其中的主机就是宿主机的公网ip地址,登陆凭证的话我们需要创建一个 SSH 登陆的用户名和密码,也就是我们前面设置的容器用户名密码,用户名为root,密码为你自己前面设置的
Credentials 选择刚刚创建的凭证;host key 选择不采用验证策略
点开这里的高级,修改端口号设置为30001,因为我们容器启动的时候将容器内的22映射到了宿主机的30001

以上设置都设置完成后,点击保存即可看到新创建的节点,此时该节点显示❌,代表与 Jekins master 连接是有问题的,这里是因为它在初始化,我们等待一会即可看到 slave-java 节点已经正常的连接,而且它是有五个 executor 的执行者,也就是说有五个 job 可以在这个节点上面并行构建。

4、构建第一个项目

回到 Jenkins 的主页面,现在新建一个任务,名字叫做 java-demo 构建,选择一个自由风格的软件项目。

需要配置这个 job 可以运行在 slave-java 构建节点上面

然后我们需要配置一个源码管理。这里有一个我自己的项目代码,地址为:https://gitee.com/sheepanger/java-demo-manage.git,它是一个公共仓库,可以直接克隆下来,而不需要配置用户名密码。如果是私有仓库的话,这边需要添加一个包含用户名和密码的证书。源码的分支的话,我这是master (根据实际情况填写)

构建这部分的话,我们添加一个执行 shell,将 maven 打包命令写进去

mvn package -B -DskipTests

操作设置完成后,保存任务,然后点击立即构建。我们来看控制台输出,首先是 admin 用户,然后运行在 slave-java 节点上边进行源码的拉取源码构建

据构建命令进行构建。在构建过程中,会先拉取一些依赖的 jar 包


最后构建成功

5、把项目打包成docker镜像推送到镜像仓库

成功运行构建了一个项目,在该任务配置里边的话,我们在 slave-java 节点上将源码的拉取下来进行构建,构建产物也就是这个 jar 包其实是放置在该构建节点上面的,我们应该要将它打包成一个docker 镜像,然后推送到镜像仓库。

需要使用到一个插件,这个插件目前是没有安装的,我们需要在 Manage Jenkins 中的 Manage Plugins 中的可选插件中搜索CloudBees Docker Build and Publish 这个插件点击 Download now and install after restar,也就是下载然后重启安装,因为所有插件的安装都得在 Jenkins master 重启后才生效

我们在 docker 镜像打包完成以后,需要把它推送到镜像仓库里边。这边我们就会使用到另外一个阿里云的服务叫做容器镜像服务,这个服务目前也是免费的,第一次使用我们需要创建一个命名空间

还需要在访问凭证界面中设置一下 Register 的登录密码,这个和你登录阿里云控制台的这个用户密码是不一样的,是拉取/推送镜像时候的验证密码

安装完插件以后,这边就会出现一个docker build and publish 的插件,这个插件就是能帮助我们打包 docker 镜像并且进行推送。接下来我们就是需要填入这个插件所需要的各个参数项

Repository Name 的话,格式为name space/仓库名称。仓库的名称的话,我们可以起个名字,比如说 java -demo。Tag 的话就是说这个镜像它的标签我们可以给出 v1。Docker host URI 以及 server credentials 我们可以不用管。

需要添加一个镜像仓库的用户名密码作为证书,账号是阿里云账号,密码就是前面设置的 Registry 的密码

在 Jenkins 页面上重新执行 java-demo任务,观察控制台变化,等待一会,就可以看到已经 success,镜像已经推送到我们的阿里云镜像仓库

如果构建失败的话查看日志,是不是需要在主机中先登陆阿里云的容器服务,在终端中输入访问凭证,登录Registry实例

sudo docker login --username=你的用户名 registry.cn-hangzhou.aliyuncs.com

然后输入密码就可以推送到仓库了

镜像版本的话,也是 v1 跟 latest 两个版本,因为该插件默认会把 latest 标签也推送上来。这个就完成了docker 镜像的构建和推送这个步骤。

6、部署容器到部署到k8s集群

部署到 k8s 集群中,我们首先需要安装一个插件

插件安装完成以后,在 Jenkins 这端我们要去给 java-demo 这个任务新增一个构建步骤,选则 Deploy to Kubenetes

我们要先配置kuberconfig凭证,如果是自己搭建的kubernetes,在master的/root/.kube/config文件中

阿里云容器服务的话在设置里复制config信息即可,先复制一下他的 KubeConfig 的信息添加到 Content 区域,然后点击保存

选择我们刚刚创建的证书,然后 configure files 的话是我们要部署的样本文件,这里为 deployment.yaml,该文件是放在这个gitee源码文件里边的

deployment.yaml 文件内容(注意:yaml文件中冒号后面必须有一个空格,写入文档以后要检查空格。apiVersion后面的参数根据kubernetes实际情况而定)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: java-demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: java-demo
  template:
    metadata:
      labels:
        app: java-demo
    spec:
      imagePullSecrets:
        - name: aliyun #如果配置了镜像仓库密文的话要加入这段,不然无法拉取镜像
      containers:
      - name: java-demo
        image: registry.cn-hangzhou.aliyuncs.com/anger/java-demo:v1 
        imagePullPolicy: Always
        ports:
        - containerPort: 8080

---
apiVersion: v1
kind: Service
metadata:
  name: java-demo
spec:
  ports:
  - port: 80
    targetPort: 8080
    #集群外可访问的端口
    nodePort: 30000
    name: java-demo
  selector:
    app: java-demo
  type: NodePort

添加完成以后,我们保存,然后进行构建,可以看一下这个控制台的输出

项目镜像已经成功推送到 k8s 的集群中,然后我们在kubernetes的master节点通过命令就可以看到推送上来的 java-demo-001 服务以及它的外部访问信息,这样我们通过该外部端点就可以直接访问该项目了

至此,就已经完成了一个项目从源码的拉取、编译构建、打包成docker镜像、推送镜像到影响仓库、部署到k8s容器集群这一系列流程的自动化,最终实现可以从浏览器上边访问到这个服务。

写在最后

搭建过程中遇到比较多的坑,还好都解决了,第一次写这么长的文档,如果没有说明白的地方可以留言给我,或者在我的gitee回复我,以及可以给我发邮件,这套环境我都是在本地测试环境中搭建、运行、测试,不保证完全适用你的环境,可以先在测试环境中搭建测试后使用

最后感谢CSDN大神Baret-H提供思路和文档,原文地址 https://bareth.blog.csdn.net/article/details/121272581