使用虚拟机搭建代码托管、持续集成系统

目录

摘要

本教程将简要介绍如何在VMware虚拟机中安装CentOS7服务器系统,以及Tailscale1PanelAdGuard HomeGitlabGitlab CI/CDJenkins的应用。

下载镜像

以下是镜像下载地址:

https://repo.huaweicloud.com/centos/7.9.2009/isos/x86_64/

因为要做服务器使用,所以推荐下CentOS-7-x86_64-Minimal-2009.iso版本。

安装系统

创建虚拟机

打开VMware客户端,点击左上角文件 - 新建虚拟机,选择典型,然后点击下一步,

选择下载的CentOS系统镜像,点击下一步,

选择虚拟机文件保存的位置,继续下一步,

指定磁盘容量,建议设置在50GB以上,并选择将虚拟磁盘拆分为多个文件,点击下一步,

进入自定义硬件界面

设置内存(建议8GB以上),处理器(建议双核四线程以上),移除打印机和声卡驱动,点击应用并确定,回到上一个页面后点击完成,开始安装虚拟机系统。

安装系统

选中第一个安装选项并回车Install CentOS7,稍待片刻,进入语言选择界面,选择简体中文,点击右下角继续

点击系统-安装位置,选择默认磁盘,点击完成。点击网络与主机名,打开以太网连接,然后点击完成。两者配置完毕,点击开始安装


安装过程中可配置root密码,点击完成即可,右边的创建新用户无须设置。等待系统自行安装完毕。

检查网络

安装完毕后点击重启,进入命令行界面。输入用户名root登录,(密码为上一步设置的root密码)。

登录完成后,输入ping baidu.com检查网络是否通畅,如有返回,则说明可以访问外网,无须其他配置。

开启 SSH 远程登录功能

输入sudo systemctl start sshd命令,启动ssh远程连接功能。

输入ip addr | head -n 20查询虚拟机 ip(ens33网卡),我的是192.168.36.129,(下文以192.168.115.237为例)。

使用 windows powershell 连接终端

打开宿主机系统的Windows Powershell,输入ssh root@刚刚查询的IP地址(如ssh root@192.168.115.237),将警告此密钥没有任何名称,忽略直接填写 yes。回车输入密码即可在本机终端连接你的虚拟机服务器终端,

Windows Terminal 添加快速访问终端

此时可以使CentOS虚拟机后台运行,自主地在Windows Powershell中进行接下来的操作了。如果你电脑上安装了新版的Windows Terminal添加快速访问终端,可以直接把它添加到配置文件中。

点击设置->添加配置文件->复制,然后在命令行一栏中添加如下命令,ssh root@刚刚查询的IP地址,点击 保存即可。




端口映射

有时候我们可能需要把虚拟机中运行的服务提供给宿主机所在的局域网其他主机访问,这时就需要将所需端口到宿主机。

打开VMware客户端,点击菜单栏编辑 - 虚拟网络编辑器,并点击右下角的更改设置按钮。

选择VMnet8,点击NAT设置按钮,

在以下窗口中点击添加按钮,填写主机端口虚拟机IP虚拟机服务端口等内容,即可将指定的端口映射到宿主机上,设置完毕后点击确定并应用。


防火墙设置

打开Windows安全中心Windows denfender),选择防火墙和网络保护模块,点击高级设置

点击入站规则,选择右侧的新建规则

选择创建端口规则,点击下一页,

根据服务需要选择TCPUDP协议类型,一般为TCP,然后选择所有本地端口(如果不想暴露所有端口到局域网,可以根据需要指定端口)。点击下一页

选择允许连接,点击下一页

全部勾选,点击下一页

填写名称和描述,点击完成

以上各步骤皆设置完毕后,在浏览器通过宿主机的 IP 加映射的主机端口就可以访问虚拟机中的服务了,同时在设置过防火墙之后,局域网的其他主机也可以访问了。

外网访问

以上配置只允许在宿主机所在的局域网中访问,有时候我们可能需要远程办公或者在外网操作,这时候就无法访问虚拟机中的网络了。

所以我们需要使用 VPN 组网工具,市面上类似的 VPN 工具有很多,比如蒲公英这样的,虽然我曾经在该公司工作过,但是我并不推荐个人用户使用它,因为它既不便捷也不便宜,虽然个人在有所限制的情况下可以免费使用。但它提供的免费带宽和设备数远远不够我们的使用需求。

在这里我推荐使用tailscaleZeroTier来进行组网,它们的安装以及配置都十分简单。

Tailscale

安装与使用

访问 https://tailscale.com/download , 下载客户端(支持AndroidLinuxMacosIOSWindows)。

安装完毕之后,点击托盘图标login登录,

可以直接使用微软Github谷歌等账号注册登录,

授权登录,

登录完毕之后,显示自己有一台设备在线。

同样的,在另一台设备重复此操作,登录同一个账号,然后这两台设备就可以相互访问了。

在托盘中可以看到自己的设备IP和在线的其他设备IP

设备管理页面,


自建中继服务器

在一般情况下,我们无须对Tailscale做任何配置,但如果你对网络有更高的稳定性要求,默认配置可能就不能够满足了。Tailscale旨在处于网络上的任何位置的机器进行点对点连接,但在

共享主机文件夹

安装 VMware Tools

必须安装VMware Tools才能开启共享主机文件夹功能,如果你已安装,请跳过此步骤。

首先,打开顶部虚拟机菜单,点击安装 VMware Tools按钮,把软件提供的ISO文件挂载到虚拟磁盘上(点击安装后,可查看虚拟机设置是否已挂载成功,并勾选已连接启动时连接),重启系统。

重启后进入虚拟机系统中,执行ls /dev查看是否存在cdrom目录,不存在的话请检查设置vm-tooliso是否已成功挂载并连接。

如果存在,则继续执行以下命令,安装编译所需的依赖:

shell 复制代码
yum -y install perl gcc gcc-c++ make cmake kernel kernel-headers kernel-devel net-tools

安装完毕后,依次执行以下命令:

shell 复制代码
# 在 /mnt目录下创建cdrom文件夹
mkdir -p /mnt/cdrom

# 以只读方式挂载cdrom
mount -t auto /dev/cdrom /mnt/cdrom

# 挂载后,查看/mnt/cdrom下的VMwareTools-xxx.tar.gz文件名
ls /mnt/cdrom

# 拷贝VMwareTools文件到用户根目录 (注意替换文件名)
cp /mnt/cdrom/VMwareTools-10.3.25-20206839.tar.gz ~

# 卸载cdrom
umount /dev/cdrom

# 切换到用户目录
cd ~

# 解压文件 (注意替换文件名)
tar -zxvf VMwareTools-10.3.25-20206839.tar.gz

# 运行可执行文件
./vmware-tools-distrib/vmware-install.pl

提示open-vm-tools packages are available from the OS vendor and VMware recommends using open-vm-tools packages. See http://kb.vmware.com/kb/2073803 for more information. Do you still want to proceed with this installation? [no]

输入yes后一路回车,然后VMwareTools的安装就完成了,此时便可移除CD驱动器或者VMware Tools ISO镜像的连接了。最后需要执行reboot,或手动重启虚拟机。

设置共享目录

打开虚拟机-设置,切换到选项-共享文件夹选项卡,勾选总是启用,然后点击添加按钮。

选择一个你需要共享的目录,注意,目录名不能包含空格和中文、特殊符号。然后点击下一步

勾选启用此共享,取消勾选只读,然后点击完成并确定。

进入虚拟机系统,执行vmware-hgfsclient命令,可查看是否已经开启共享,如果已成功开启,会打印主机目录名。

挂载共享目录

依次执行以下命令:

shell 复制代码
# 在mnt目录下创建hgfs文件夹
mkdir -p /mnt/hgfs

# 挂载主机文件夹到指定目录,注意替换 VMShare 为你自己的目录名。
vmhgfs-fuse .host:/VMShare /mnt/hgfs

# 查看目录是否挂载成功
ls /mnt/hgfs/VMShare

挂载成功后,即可在虚拟机系统中读写主机文件夹中的内容了。

实用工具

1Panel

在服务器系统中安装 Web 管理面板可以极大提升服务器操作的便捷性,推荐使用基于 Docker 的服务器开源管理面板1Panel,本文后续的应用安装,也将基于1Panel进行操作。

安装

只需执行以下命令,即可完成安装

bash 复制代码
curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_start.sh && sh quick_start.sh

配置

配置默认服务器地址

点击面板左侧的面板设置,配置默认的服务器地址为你的虚拟机系统 IP,比如我的是192.168.36.129,配置完毕后点击确定。

取消安全访问入口

面板设置中的安全选项卡下,置空默认的安全入口设置。

SSH 密钥管理

有时候我们可能需要通过 SSH 远程登录服务器,所以需要开启 SSH 密钥登录功能,展开面板左侧的主机菜单,打开SSH管理页面,root用户设置为允许SSH登录,并开启密钥认证功能。

点击密钥信息按钮,打开配置弹窗,加密方式选择RSA密码输入框置空,然后点击生成密钥即可。

镜像加速

容器中的配置选项卡下,设置镜像加速源,内容如下:

https://hub-mirror.c.163.com
https://docker.m.daocloud.io
https://ghcr.io
https://mirror.baidubce.com
https://docker.nju.edu.cn

AdGuard Home

我们在虚拟机中安装了服务器系统后,要想访问,总是要通过 IP + 端口的形式,或者通过修改Hosts文件的方式进行域名访问,每一个域名都需要单独配置,这样极为不便,推荐安装AdGuard Home创建一个私人 DNS 解析服务器,这样我们就能够在本地使用自动解析域名的方式访问自己的服务了。

安装

应用商店

点击1Panel面板的应用商店,直接搜索AdGuard,找到后点击安装

弹出自定义参数窗口,一般默认配置无须修改,勾选底部的端口外部访问,然后点击确定,开始安装。

进入已安装应用界面查看,安装完毕后,点击服务端口按钮,将自动跳转到 Web 管理页(如果跳转的 IP 地址不对,请按照上面的步骤在面板设置中配置默认的服务器地址)。

Docker Compose

除了使用应用商店一键安装外,你也可以自行编写Docker compose模板进行安装,以下是1Panel提供的模板,你可以直接粘贴到容器 - 创建编排中进行安装(其中的变量请按需修改)。

yaml 复制代码
networks:
  1panel-network:
    external: true
services:
  adguardhome:
    container_name: ${CONTAINER_NAME}
    deploy:
      resources:
        limits:
          cpus: ${CPUS}
          memory: ${MEMORY_LIMIT}
    image: adguard/adguardhome:v0.107.36
    labels:
      createdBy: Apps
    networks:
      - 1panel-network
    ports:
      - ${HOST_IP}:${PANEL_APP_PORT_DNS}:53/tcp
      - ${HOST_IP}:${PANEL_APP_PORT_DNS}:53/udp
      - ${HOST_IP}:${PANEL_APP_PORT_DHCP_1}:67/udp
      - ${HOST_IP}:${PANEL_APP_PORT_DHCP_2}:68/udp
      - ${HOST_IP}:${PANEL_APP_PORT_HTTP_1}:80/tcp
      - ${HOST_IP}:${PANEL_APP_PORT_DOH}:443/tcp
      - ${HOST_IP}:${PANEL_APP_PORT_DOH}:443/udp
      - ${HOST_IP}:${PANEL_APP_PORT_HTTP}:3000/tcp
      - ${HOST_IP}:${PANEL_APP_PORT_DOT}:853/tcp
      - ${HOST_IP}:${PANEL_APP_PORT_QUIC_1}:784/udp
      - ${HOST_IP}:${PANEL_APP_PORT_DOT}:853/udp
      - ${HOST_IP}:${PANEL_APP_PORT_QUIC_2}:8853/udp
      - ${HOST_IP}:${PANEL_APP_PORT_DNS_CRYPT}:5443/tcp
      - ${HOST_IP}:${PANEL_APP_PORT_DNS_CRYPT}:5443/udp
    restart: always
    volumes:
      - ./data/work:/opt/adguardhome/work
      - ./data/conf:/opt/adguardhome/conf
version: "3"

初始化配置

在初始配置页面,网页管理界面的监听端口选择所有接口,端口填3000,DNS 服务器监听接口也选择所有接口,端口保持默认的53,然后点击下一步。

设置用户名和密码,点击下一步。

点击后会自动跳转到IP:3000地址,发现打不开,不要慌张,你应该访问的依然是你面板中自动跳转的端口,就是刚刚设置初始配置的端口(23001)。

更换为正确地址后,输入用户名和密码,就可以进入控制台页面了。

规则配置

以下仅列出需要修改的配置,未提及的配置均保持默认。

  1. 常规设置

    常规设置 - 日志配置中,配置查询日志保留时间24小时

  2. DNS 配置

    上游 DNS 服务器

    114.114.114.114
    114.114.115.115
    223.5.5.5
    223.6.6.6
    119.29.29.29
    101.226.4.6
    123.125.81.6
    101.226.4.6
    101.226.4.6
    https://dns.google/dns-query
    https://dns.quad9.net/dns-query
    https://doh.opendns.com/dns-query
    https://1.1.1.1/dns-query
    tls://dns.rubyfish.cn
    tls://8.8.8.8
    tls://8.8.4.4
    tls://dns.google:853
    

    Bootstrap DNS 服务器

    180.76.76.76
    119.29.29.29
    223.5.5.5
    8.8.8.8
    8.8.4.4
    208.67.222.222
    
  3. 自定义过滤规则

    根据自己的需要,可以在这里配置自定义解析规则,比如你想设置的域名是dev.com以及其所有子域名,解析到虚拟机(已映射到宿主机)的服务上,就可以这样设置(详细配置说明见官方文档):

    ||dev.com^$dnsrewrite=192.168.2.171,client=192.168.2.0/24
    
    • ||dev.com^表示匹配所有根域名为dev.com的地址
    • $dnsrewrite=192.168.2.171表示将其重写并解析到 IP 为192.168.2.171(我的宿主机在局域网中的 IP)的服务器上
    • client=192.168.2.0/24表示仅当入站 IP 为局域网网段为192.168.2.0 ~ 192.168.2.255中的主机访问时生效。

使用方法

配置完成后,我们就可以在自己电脑或局域网中的主机上使用自己的私人 DNS 了,

打开VMware虚拟网络编辑器,将虚拟机中的20053端口映射到宿主机的53端口上,并分别映射TCPUDP类型,配置完毕后点击确定并应用该配置。


这时,宿主机的 DNS 解析功能已经配置完毕。打开 Windows 控制面板,配置网络适配器IPV4

设置 DNS 解析为自己的宿主机 IP(局域网内的其他主机也可以填写你的宿主机 IP 作为 DNS 解析服务器),

验证效果

  1. 静态网站

    1Panel中新建一个静态网站,主域名为www.dev.com,点击确定。然后在浏览器访问,看看是不是已经被浏览器正确解析啦?

  2. 反向代理

    我们也可以使用反向代理来使用私人 DNS 解析,在1Panel中新建一个反向代理服务,主域名填写panel.dev.com,代理地址填写127.0.0.1:42629(端口为你的1Panel面板访问端口),点击确定。然后在浏览器访问panel.dev.com时,发现已经解析到1Panel管理面板了,我们以后访问面板管理服务器,再也不用使用IP + 端口访问了(需在面板设置中把安全入口置空)。

外网解析

配置 Tailscale

如果你已经按照上面安装了Tailscale,我们还可以把私人 DNS 解析服务器应用到所有加入组网的设备中,而无须在单独为每台设备在网络适配器中设置IPV4 DNS服务器

打开Tailscale控制台,切换到DNS选项卡,在Nameservers模块点击Add nameserver按钮,选择Custom

Nameserver IP输入框填写你虚拟机所在宿主机的Tailscale分配的IP(100开头的),开启Restrict to domainDomain输入框填写你需要使用私人DNS解析的域名,如dev.com,配置完毕后,点击Save保存。

配置 AdGuard Home

打开AdGuard Home - 过滤器 - 自定义过滤规则,在规则中添加||dev.com^$dnsrewrite=100.xxx.xxx.xxx,client=~192.168.0.0/16条目,IP为宿主机的Tailscale所分配的IP

验证结果

以上步骤设置完毕,现在你不必为每台主机都进行DNS配置了,只要登录了Tailcale授权账号的组网设备,都可以自动使用该私人DNS服务器了。

Tailscale可以进行更多自定义配置,不同账号之间可以共享组网网络,也可以按照不同的组或者标签来进行权限控制,具体操作文档,请访问 https://tailscale.com/kb/ ,这里不再展开说明。

Gitlab

上面的教程中在安装系统时,特意分配了双核四线程8G内存的硬件配置,这同样符合Gitlab仓库Citlab CI/CD的配置需求,我们在日常工作中经常会用到代码托管系统,所以可以在服务器中部署这样一套集代码托管、持续集成、自动部署为一体的流程,供局域网中的任何主机使用。

安装

在我写这篇笔记的时候,1Panel的应用商店中,还没有收录Gitlab,所以我们使用自定义的Docker Compose进行安装。(其实应用商店中的应用也是使用Dcoker Compose进行安装的,在安装时也可以选择高级设置可以自定义Compose模板)

选择1Panel左侧的容器菜单,切换到编排模板,点击创建编排模板,填写名称gitlab-all(任意),代码框中贴入如下代码 (两个服务可分别部署,如果不需要持续集成功能,可将gitlab-runner部分删除,以后用到时在单独安装),点击确定保存:

yaml 复制代码
version: "3"

services:
  gitlab:
    image: gitlab/gitlab-ce:latest
    restart: always
    hostname: git.dev.com #这里填写映射的域名或者服务器地址
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'http://git.dev.com'
    ports:
      - "8888:80"
      - "4343:443"
      - "2222:22"
    volumes:
      - "./gitlab/config:/etc/gitlab"
      - "./gitlab/logs:/var/log/gitlab"
      - "./gitlab/data:/var/opt/gitlab"

  gitlab-runner:
    image: gitlab/gitlab-runner:latest
    restart: always
    depends_on:
      - gitlab
    volumes:
      - "./gitlab-runner/config:/etc/gitlab-runner"
      - "/var/run/docker.sock:/var/run/docker.sock" #不可修改

切换到编排选项卡,点击创建编排,选中编排模板,填写文件夹名(会把数据和配置文件保存在这里),下拉选择刚才编写的模板,然后点击确定保存后,docker compose开始拉取镜像,自动部署成功。

切换到容器选项卡,发现多了两个正在运行的gitlab-all为前缀的容器,这就是刚才我们所创建的,当状态为已启动之后,说明容器运行成功,点击gitlab容器的 Web 端口,即可自动跳转到所部署的gitlab首页,

获取初始密码

打开网站之后,需要进行登录。默认管理员账号为root,初始密码须至容器目录中获取。点击容器选项卡,点击Gitlab所在容器右侧的终端,连接后输入grep 'Password:' /etc/gitlab/initial_root_password,即可查看密码,此密码查看方式将在首次登录后自动删除,请务必修改密码。

个性化配置

登录成功后,发现Gitlab页面为英文页面,我们可以在设置中进行一些个性化配置。

点击左上角的头像,打开Preferences菜单。

在打开的页面中,往下拉到Localization模块,可以配置显示语言为Chinese Simolified - 简体中文。在这个页面中你也可以根据个人喜好进行一些其他配置,包括主题、代码风格、界面布局等。

以上的偏好设置,是针对当前用户的,如果你想对所有用户都预设一个默认配置(比如语言),需要使用root账号进入管理中心,进行全局配置。

管理中心选项中,展开底部的设置菜单,打开偏好设置

偏好设置中下拉,展开本地化模块,设置默认语言Chinese Simolified - 简体中文

除了偏好设置,在设置菜单中你也可以根据个人需求配置一些其他的项目/用户通用设置,比如仅支持http方式拉取代码,关闭ssh方式,比如自动到如其他仓库代码(如GithubGitea)等。

创建群组和项目

我们在开发中,经常有需要控制用户权限或者为项目分组,比如把前端项目放到一个分组里,把后端项目放到另一个组里,方便管理,Gitlab就提供了这样的功能。

我们可以点击左上角+号,新建群组

然后点击创建群组,填写相关信息,可见性级别选择私有,然后点击创建

群组创建完毕后,自动跳转到群组详情页面,我们可以在其中直接继续创建项目,然后选创建空白项目,填写相关信息,并勾选使用自述文件初始化仓库,然后点击创建

这样,一个新的项目就创建成功了,仓库中已自动创建了一个Readme.md文件,这表示该项目已经被初始化,可以进行推送操作了。

点击右边的克隆,使用GITHTTP方式把项目代码克隆到本地电脑,然后就可以进行开发了。

新版的Gitlab还提供了WEB IDE在线开发的功能,我们也可以进行在线编码,而无须拉取代码到本地。

Gitlab CI/CD

安装 Runner 服务

如果在上面安装Gitlab没有同时安装Gitlab Runner服务,需要先进行安装,创建Docker compose模板,贴入如下代码,运行即可:

yaml 复制代码
gitlab-runner:
  image: gitlab/gitlab-runner:latest
  restart: always
  depends_on:
    - gitlab
  volumes:
    - "./gitlab-runner/config:/etc/gitlab-runner"
    - "/var/run/docker.sock:/var/run/docker.sock" #不可修改

创建 Runner 实例

已安装Runner服务后,打开Gitlab,点击左上角管理中心设置菜单(不同版本可能入口位置有所区别),展开CI|CD菜单,点击Runner新建实例Runner(这里只做展示用,所以创建了全局Runner实例,后续可根据需要可单独在群组、项目中创建实例)。


来到配置页面,设置以下内容:

  • 操作系统默认选择Linux,一般无需修改。
  • 容器为Docker(在上一步创建docker comppose模板时,卷映射地址为/var/run/docker.sock:/var/run/docker.sock,切勿修改,这将把外部Docker通讯服务映射到容器内部,当Gitlab Runner执行构建时,会通知调用外部的Docker执行操作)。
  • 标签可填可不填。
    • 当填写标签时,取消勾选运行未打标签的作业(当不允许运行未打标签的作业时,标签不能为空),在项目中如果想触发构建流水线,就必须在项目的.gitlab-ci.yml文件中配置tags选项指定标签名以在对应Runner上运行。
    • 当不填写标签时,勾选运行未打标签的作业,这样所有的项目都可以在此Runner上运行,触发时机可在对应项目的.gitlab-ci.yml文件中配置。
  • 详情可填写该Runner的作用描述,以便识别。
  • 配置可按需求选择,一般保持默认就好,取消勾选受保护选项。

配置完毕后,点击创建Runner,跳转到了注册页面,显示了如下操作步骤,

注册 Runner 实例

切换到1Panel - 容器菜单,选择我们刚刚使用Docker compose创建的gitlab-runner容器,连接终端

依次执行如下操作:

  • 开始注册Runner,在终端执行gitlab-runner register命令,

  • Enter the GitLab instance URL (for example, https://gitlab.com/):

    输入Gitlab的访问地址,填写你的虚拟机 内部 IP 加 Gitlab 服务的端口号(比如http://192.168.36.129:8888),填写完毕后回车。

  • Enter the registration token:

    把刚才创建Gitlab Runner时注册页面生成的token粘贴进来,然后回车。

  • Verifying runner...

    这一步会验证上面输入的instance URLtoken是否能够访问或连接,如果URLtoken有误,会结束对话。如果输入了正确的内容,则会提示is valid runner=iPQAvdywz,并生成一个Runner ID,自动进入下一步。

  • Enter a name for the runner. This is stored only in the local config.toml file:

    填写一个可供自己辨别的Runner名称,这个名称用于在生成的config.toml文件中标明配置块,日后可自行在config.toml文件中增删Runner。继续下一步。

  • Enter an executor: docker-windows, instance, ssh, virtualbox, docker-autoscaler, docker+machine, custom, docker, parallels, shell, kubernetes:

    选择Runner在哪里运行,请填写docker,然后回车。

  • Enter the default Docker image (for example, ruby:2.7):

    这里可根据个人需要填写该Runner运行时默认使用的基础镜像,当有项目在此Runner中运行时,如果.gitlab-ci.yml中的步骤没有指定镜像,则会自动使用此镜像,.gitlab-ci配置文件优先。我这里填写node:lts-alpine

  • Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded! Configuration (with the authentication token) was saved in "/etc/gitlab-runner/config.toml"

    出现该提示,则说明配置完成,GitlabGitlab Runner已成功建立连接,并已将配置文件保存在了/etc/gitlab-runner/config.toml文件中。

配置完成后,回到Gitlab中,打开Runner菜单,发现列表中刚刚创建的Runner已经连接成功,状态应为在线。大功告成,一个全局的Runner已经配置完毕。

准备工作

接下来我们就要在项目中配置.gitlab-ci.yml文件了,这个文件记录了如何触发CI|CD流水线和具体的构建步骤。

我这里已经创建了一个Vue-test项目,接下来我将使用这个项目作为示例。

在编写.gitlab-ci之前,我们应该先明白自己需要这个使用项目做些什么。比如这个Vue-test项目,我需要它能够在我提交代码到main分支后,自动开始进行npm run build操作,并将产出的dist目录下的文件,部署到我的服务器搭建的静态网站上。这就需要厘清以下几点:

  • 该流水线需要哪些步骤?

    • buildVue项目需要先npm install然后进行npm run build操作,所以需要一个build步骤。
    • deploy : 我需要把它部署到静态网站目录中,所以还需要一个deploy步骤。
  • 构建时需要依赖哪些镜像?

    • node:lts-alpine : 在build步骤中需要使用npm指令进行操作,所以需要在带有node环境的镜像中运行,这里我选择的是node:lts-alpine镜像。
    • lgatica/openssh-client : 在deploy步骤中,把文件推送到远程服务器目录,需要远程登录到服务器终端,要用到ssh功能,所以需要一个带有ssh功能的镜像中运行,这里我选择lgatica/openssh-client镜像。
  • 需要定义哪些变量?

    • 远程服务器 IP
    • 远程服务器账号
    • 远程服务器 SSH 登录密钥(或者密码)
    • 要推送到的服务器目录根路径
    • 要推送到的服务器目录网站路径

启用 Runner 共享

知道需要哪些东西后,我们开始进行配置CI/CD,首先在该项目所在的群组左侧,展开设置,打开CI/CD菜单,展开Runner模块,开启为该组启用共享Runner,这样这个群组下面的所有项目,就都可以使用在全局或群组中创建的Runner实例了。

定义通用变量

然后展开变量模块,我们需要添加刚才总结出来的几个变量,以供.gitlab-ci.yml读取(变量可以单独在群组、项目中设置中定义,也可以在gitlab-ci.yml文件中定义),这里我们把远程服务器IP远程服务器SSH登录密钥等这些通用变量定义到群组中,该群组下面的所有项目都可以继承这些变量。点击添加变量,填写,勾选隐藏变量,,点击确定。

这里我的定义如下:

  • SSH_PRIVATE_KEY:在服务器中 SSH 管理模块生成的SSH RSA密钥对(也可以使用密码,参考下一段笔记使用密码而非密钥
  • SSH_SERVER192.168.36.129
  • SSH_USERroot
  • STATIC_SITE_PATH/opt/1panel/apps/openresty/openresty/www/sites

变量配置完毕,我们切换到Vue-test项目中,同样展开左下角的设置,打开CI/CD菜单,展开Runner模块,

可以看到,我们现在有一个可以使用的共享Runer,这就是我们刚才所创建的全局Runner,并通过群组设置了允许共享

然后展开变量模块,可以看到该项目已经继承了在群组中的通用变量。

编写配置文件

变量配置完成,我们现在正式开始编写.gitlab-ci.yaml文件,可以在本地进行编写,然后把文件推送到仓库。也可以直接点击项目名称下方的配置CI/CD按钮进行编写,或者点击左侧菜单栏的流水线编辑器,然后开始配置流水线

填写以下内容(仅供参考):

stages:
  - build
  - deploy
cache:
  paths:
    - node_modules/
variables:
  # 可在这里定义临时变量
  # WEB_DIR为要推送到的服务器目录网站路径
  WEB_DIR: www.dev.com/index

build:
  stage: build
  image: node:lts-alpine # 如果与Runner指定的镜像相同,则无须在步骤中指定镜像。
  script:
    - npm install --registry https://registry.npm.taobao.org
    - npm run build
  artifacts:
    paths:
      # 这里定义产物的目录,可供下一个步骤使用
      # 产物可以在菜单 构建 - 产物 中找到
      - dist
    expire_in: 24 hours # 这里定义产物的自定清除时间
  only:
    - main

deploy:
  stage: deploy
  image: lgatica/openssh-client
  script:
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - ssh-keyscan $SSH_SERVER >> ~/.ssh/known_hosts
    - chmod 644 ~/.ssh/known_hosts
    - scp -r dist/* $SSH_USER@$SSH_SERVER:$STATIC_SITE_PATH/$WEB_DIR/
    - ssh $SSH_USER@$SSH_SERVER "service nginx restart"
  only:
    - main

配置完毕,点击提交更改。可以看到,流水线已开始运行。

点击前面的小月牙图标,可以查看构建详情。

看到这两个勾,说明你已经构建并部署成功。

浏览器打开你的网站,发现内容已经改变,我们已经成功搭建了一套持续集成/部署的代码托管系统。

题外

构建时的容器

流水线运行后,回到1Panel面板,容器菜单下,会发现多了两个以Runner为前缀名的容器,这是流水线在构建时启动的临时容器,它会自动拉取registry.gitlab.com/gitlab-org/gitlab-runner/gitlab-runner-helperregistry.gitlab.com/gitlab-org/cluster-integration/auto-build-image两个镜像。

流水线中用到的自定义镜像,比如node:lts-alpinelgatica/openssh-client等,都会被自动拉取,并存储在镜像库中。

使用非 root 用户

我们前面在定义通用变量SSH_USER时使用了root用户,这是服务器的超级管理员账号,我们在实际的团队工作中,一般不会使用root用户来构建项目,因为它拥有对所有文件的管理权限,我们必须创建一个具有更小的、局部操作权限的账号,以供流水线构建使用。

比如以上的构建示例中,其实只需要对服务器的这个静态站点目录STATIC_SITE_PATH/opt/1panel/apps/openresty/openresty/www/sites)进行读写操作,而其他的权限一概不需要,我们可以创建一个只对此目录有操作权限的用户,来管理静态站点。

1Panel面板左侧菜单栏,展开主机,连接终端,依次执行以下命令:

  • sudo useradd sites_ctrl

    创建名为sites_ctrl的新用户

  • sudo passwd sites_ctrl

    sites_ctrl用户设置密码

  • sudo chown -R sites_ctrl:sites_ctrl /opt/1panel/apps/openresty/openresty/www/sites

    赋予sites_ctrl用户静态站点目录及其子目录的所有权

  • sudo chmod -R 700 /opt/1panel/apps/openresty/openresty/www/sites

    修改静态站点目录及子目录的操作权限,700表示目录所有者拥有读、写、执行(rwx)的所有权限

  • sudo su - sites_ctrl

    登录sites_ctrl用户

  • ssh-keygen -t rsa

    生成SSH密钥,保存位置默认就好

  • cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

    将公钥复制到sites_ctrl用户的~/.ssh/authorized_keys文件中,以允许该用户使用SSH密钥进行登录

  • cat ~/.ssh/id_rsa

    打印rsa私钥内容,复制下来备用

  • sudo systemctl restart sshd

    重启 SSH 服务以应用更改

以上步骤操作完毕后,需要将前面Gitlab中配置的SSH_USER变量值改为sites_ctrlSSH_PRIVATE_KEY值改为上面打印的rsa私钥。

后续我们触发流水线时,就会自动使用仅有静态站点目录操作权限的sites_ctrl用户进行推送、部署操作了。

使用密码而非密钥

有的时候小项目可能是不那么注重安全,在这样的场景下,我们只追求简便快捷,生成密钥对的过程对于有些人来说是比较繁琐的,我们可以直接使用sshpass实现自动化交互式密码登录。

首先我们同样把服务器的用户密码配置为变量,变量名可以自定义,我这里命名为SSH_PWD,然后重新修改.gitlab-ci.ymldeploy步骤如下:

yaml 复制代码
deploy:
  stage: deploy
  image: ringcentral/sshpass #sshpass镜像
  script:
    # 关闭主机密钥严格检查,清空目标文件夹内容
    - sshpass -p $SSH_PWD ssh -o "StrictHostKeyChecking=no" $SSH_USER@$SSH_SERVER "rm -rf $STATIC_SITE_PATH/$WEB_DIR/*"
    # 把产物拷贝到目标文件夹
    - sshpass -p $SSH_PWD scp -r dist/* $SSH_USER@$SSH_SERVER:$STATIC_SITE_PATH/$WEB_DIR/
  only:
    - main

Jenkins

除了使用Gitlab紧密绑定的Runner服务完成CI/CD之外,我们其实还有其他选择,Jenkins就是一个可以实现任意平台(比如GithubGiteaGiteeGitlab等)持续集成/部署功能的自动构建系统,并将服务独立于其之外。

安装

应用商店

1Panel中已经内置了JenkinsDocker compose安装脚本,我们可以在应用商店找到它,进行一键安装。

安装时可填写任意空闲端口,并勾选端口外部访问

Docker Compose

除了使用应用商店一键安装外,你也可以自行编写Docker compose模板进行安装,以下是1Panel提供的模板,你可以直接粘贴到容器 - 创建编排中进行安装(其中的变量请按需修改)。

yaml 复制代码
networks:
  1panel-network:
    external: true
services:
  jenkins:
    container_name: ${CONTAINER_NAME}
    deploy:
      resources:
        limits:
          cpus: ${CPUS}
          memory: ${MEMORY_LIMIT}
    image: jenkins/jenkins:2.421
    labels:
      createdBy: Apps
    networks:
      - 1panel-network
    ports:
      - ${HOST_IP}:${PANEL_APP_PORT_HTTP}:8080
    privileged: true
    restart: always
    user: root
    volumes:
      - ./jenkins:/var/jenkins_home
      - /var/run/docker.sock:/var/run/docker.sock
      - ${DOCKER_BINARY}:${DOCKER_BINARY}
version: "3"

初始化

安装完毕之后,直接在已安装应用中点击服务端口,即可自动跳转到Jenkins的 Web 管理页面

首次登录时,需要先至容器中获取初始密码,以解锁Jenkins,在Jenkins所在的容器中连接终端,输入cat /var/jenkins_home/secrets/initialAdminPassword

解锁之后,开始进行初始化配置,第一步请选择安装推荐的插件

安装完毕之后,创建管理员账号,创建好之后,初始化配置已经完成,可以进入基础配置了。

准备工作

正如上面的Gitlab CI/CD笔记一样,在计划配置一个自动构建的流水线之前,我们需要知道自己要做什么。

需求和上面的Gitlab CI/CD基本一致,我在Gitlab已经创建了一个vue-jenkins项目,需要它能够在我提交代码到main分支后,自动开始进行npm run build操作,并将产出的dist目录下的文件,部署到服务器搭建的静态网站上。

基于该需求,我们可知:

  • 该流水线需要哪些步骤?

    • buildVue项目需要先npm install然后进行npm run build操作,所以需要一个build步骤。
    • deploy : 我需要把它部署到静态网站目录中,所以还需要一个deploy步骤。
  • 构建时需要依赖哪些插件?

    • node.js : 在build步骤中需要使用npm指令进行操作,所以需要在带有node环境的镜像中运行。
    • Publish Over SSH : 在deploy步骤中,把文件推送到远程服务器目录,需要远程登录到服务器终端,所以需要用到ssh功能。
    • Gitlab : 由于我们的项目源代码托管在Gitlab仓库中,所以需要把Jenkins和其连接起来,以使其可以拉取代码并正确反应构建进度到Gitlab的流水线状态中。
  • 需要知道哪些信息?

    • 远程服务器 IP
    • 远程服务器账号
    • 远程服务器 SSH 登录密码(或密钥)
    • 要推送到的服务器目录根路径
    • 要推送到的服务器目录网站路径

知道需要哪些东西后,我们接下来就为该项目做一些配置。

安装插件

Node.js

  1. 选择左侧菜单栏的系统设置,然后打开插件管理,切换到Avilable plugins搜索nodejs,勾选搜索结果前面的复选框,点击安装。


  2. 安装完毕后,回到系统管理,打开全局工具配置,滚动到页面底部,点击新增NodeJS

  3. 填写别名以及版本等信息,可以在此时安装一些全局的依赖模块,比如yarn。填完之后点击保存。

Publish Over SSH

  1. 同样在插件管理中,搜索Publish Over SSH并安装。

  2. 安装完毕之后,打开系统设置,滚动到页面底部,在Publish Over SSH模块中,点击新增SSH server,填写任意名称以及远程服务器IP、远程服务器账号、要推送到的服务器目录根路径。

  3. 基础信息配置完毕后,点击下面的高级,并勾选Use password authentication, or use a different key,在Passphrase / Password项输入登录密码(也可以置空密码输入框,把SSH密钥贴入下面的Key输入框中)。

  4. 所有内容填写完毕后,滚动到底部,点击右下角的Test Configuration按钮,会自动检测所填的内容是否正确,以及是否能够正常连接,左侧出现Success,说明可以可以保存了。如果报错,请根据错误提示进行修改。

Gitlab

  1. 同样在插件管理中,搜索Gitlab并安装。

  2. 安装完毕之后,打开系统设置,找到Gitlab模块(在页面中间位置),填写任意Connection name,以及Gitlab地址GitLab host URL,然后点击Credentials下面的添加按钮,新增Jenkins凭据

  3. 凭据类型选择Gitlab TokenDomain范围保持默认,ID描述任意填便于自己识别的内容,下面的API token需要在Gitlab中获取,见下一段落。

  4. 进入Gitlab,点击对应项目或群组进行设置,打开访问令牌页面,并添加访问令牌,填写任意便于自己识别的令牌名称到期时间可不填,默认为一年,最长不超过两年。角色请使用Maintainer范围选择api,否则在构建或反射状态时将发生401权限错误。填写完毕后,点击创建访问令牌,回到列表页,复制访问令牌,粘贴访问令牌到上一段所述Jenkins 凭据创建中的API token输入框中,凭据内容填写完毕后,点击添加,该操作会在Gitlab中生成一个bot用户(默认访问级别为普通,可使用管理员在用户管理中进行修改)。

  5. 添加好之后,Credentials下拉框选中刚才添加的凭据,然后点击右下角Test Connection,出现Success之后,表示连接成功,可以进行保存了。如果报错,请根据错误提示进行修改。

创建自动部署任务

回到JenkinsDashboard首页,点击Create a job,填写任务名称,点击创建一个自由风格的软件项目,然后进入任务配置页。

常规配置

可以根据自己的需求配置,比如勾选丢弃旧的构建

源码管理

勾选Git,填写项目地址Repository URL,填写之后会报凭据错误无法连接仓库,别慌,点击下面的Credentials添加按钮,类型选择Usmame with password,输入Gitlab的密码和用户名,其他不用管,点击保存。然后选择钢才添加的账号密码凭据,错误警告就会消失了(如果仍然报错,请检查账号密码是否正确)。然后再Branches to build指定一个你要在Jenkins进行源码管理的分支或标签等名称,比如*/mainrefs/heads/mainrefs/tags/v1.0.0,点击应用。

构建触发器

  1. 勾选 Build when a change is pushed to GitLab(请复制后面的Gitlab webhook URL地址,这个在后面需要使用),并勾选可触发该构建任务的事件,比如Push或者Merge Request,然后展开高级

  2. 展开高级按钮后,往下拉找到Secret token,点击右下角Genarate按钮生成一个令牌,点击应用。

  3. 打开Gitlab页面,使用root账户进入管理中心,打开设置 - 网络,展开出站请求,勾选允许来自 webhooks 和集成对本地网络的请求Gitlab 10.6以上版本,默认不允许向本地网络发送webhook请求,故须手动勾选此选项)。并取消勾选强制执行 DNS 重新绑定攻击保护。设置完毕后,点击保存。

  4. Gitlab进入对应项目(如vue-jenkins)打开Webhook设置,点击添加新的 webhook按钮,进入配置页面。

  5. Webhook配置页面,URL填写刚才我们在Jenkins 构建触发器第一步中复制的Gitlab webhook URL地址。Secret 令牌贴入刚才我们在Jenkins 构建触发器第二步中生成的Secret token令牌。然后勾选需要触发构建的事件,一般和Jenkins 构建触发器第一步中所勾选的触发器一致即可。最后取消勾选底部的SSL验证,点击添加webhook按钮保存。

  6. 添加webhook后,可点击列表右侧测试按钮,指定一个事件,测试是否能够正常触发Jenkins流水线构建。

  7. 测试成功,顶部会有Hook executed successfully: HTTP 200提示,此时打开Jenkins,发现构建任务已经在运行了。如果测试时有报错,请根据提示内容检查URLToken是否有误, 点击编辑按钮滚动到页面底部,可查看测试结果的详细内容。

  8. 完成上一步之后,GitlabJenkins已经成功建立双向连接。此时,需要继续对Jenkins剩余的内容进行配置,打开刚才的Job配置,继续配置构建环境

构建环境

勾选在构建中添加时间戳前缀,并勾选Provide Node & npm bin/ folder to PATH为该项目选择前面已配置的Node版本,点击应用。

Build Steps

点击增加构建步骤,选择执行Shell(也可选择Execute NodeJS script),在命令中填写以下代码,然后点击应用:

shell 复制代码
npm install
npm run build

构建后操作

点击增加构建后操作步骤,选择Send build artifacts over SSH

  • SSH Publishers Name

    选择刚才我们设置好的ssh server

  • Transfer Set Source files

    设置为编译后的产物路径dist/**

  • Remove prefix

    同上,设置为dist,以删除其前缀。

  • Remote directory

    要推送到的服务器目录网站路径,此路径相对于前面在Publish Over SSH设置的要推送到的服务器目录根路径。比如这里我这里填写www.dev.com/index

  • Exec command

    发布后需要执行的命令,这里我们暂时不填。

  • Clean remote

    展开高级,勾选此按钮,用于在推送时先清空此目录内容。

触发构建并验证

根据以上的步骤操作之后,我们已经完整创建了一个构建任务。现在可以在Gitlab中推送或合并代码,看看是否能够触发流水线了。

我们修改一下项目代码,然后提交推送到指定触发构建的分支,我这里直接在前面定义的是main分支,所以就直接推送到main

推送成功,进入CI/CD菜单,可以看到,一个名为jenkins的流水线,已经开始构建。

点进去,会自动跳转到jenkins的构建任务详情页面,点击左侧菜单栏的控制台输出,我们可以看到更详细的构建日志。最后一句会打印Finished: SUCCESSGitlab流水线页面也会显示已通过。如果构建失败,请在日志中检查错误信息并排查错误。

接下来,我们打开我们部署的目标站点www.dev.com,可以看到,修改后的代码已成功部署到网站上了。

相关推荐
ZHOU西口1 小时前
微服务实战系列之玩转Docker(十八)
分布式·docker·云原生·架构·数据安全·etcd·rbac
川石课堂软件测试7 小时前
性能测试|docker容器下搭建JMeter+Grafana+Influxdb监控可视化平台
运维·javascript·深度学习·jmeter·docker·容器·grafana
追风林14 小时前
mac 本地docker-mysql主从复制部署
mysql·macos·docker
城南vision16 小时前
Docker学习—Docker核心概念总结
java·学习·docker
wclass-zhengge16 小时前
Docker篇(Docker Compose)
运维·docker·容器
梦魇梦狸º20 小时前
腾讯轻量云服务器docker拉取不到镜像的问题:拉取超时
docker·容器·github
鬼才血脉20 小时前
docker+mysql配置
mysql·adb·docker
詹姆斯爱研究Java20 小时前
Docker 的基本概念和优势
docker
南猿北者1 天前
docker镜像仓库常用命令
运维·docker·容器
杨浦老苏1 天前
Docker可视化管理面板DPanel的安装
运维·docker·群晖