从零进阶--构建docker-swarm结合Gitlab-runner持续集成实现hyperf 部署

构建 docker-swarm 结合 Gitlab-runner 持续集成实现 hyperf 部署

最近发现有用到 hyperf ,应需求,便按照官网的,弄一下 Gitlab-runner 持续集成部署, 详细可见 官方文档: Hyperf

简介

Docker-swarm Swarm Docker 官方提供的一款集群管理工具,其主要作用是把若干台 Docker 主机抽象为一个整体,并且通过一个入口统一管理这些 Docker 主机上的各种 Docker 资源

Gitlab-runner gitlab-runner gitlab 提供的持续集成工具 , 通过 .gitlab-ci.yml 实现有效项目部署。

Hyperf Hyperf 是基于   Swoole 4.3+   实现的高性能、高灵活性的 PHP 协程框架,是基于微服务开源的框架。详细可见 官官方文档: Hyperf

Kong: 网关服务 , 主要用于数据转发,主要作用于保护,管理和扩展微服务和 API 

对于整个 架构实现,我简单整理了一下,如图 1 ,大概实现的效果是这样的:

1

环境:

Node2 172.25.0.30 centos7 主节点 Leander

         Node3:172.25.0.33 centos7  worker

一、安装 Dockergitlab

1Node2node3 安装 docker

安装 dockers

#curl -sSL https://get.daocloud.io/docker | sh

配置允许使用 TCP 连接 Docker

#vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H unix:// -H tcp://0.0.0.0:2375

配置阿里加速仓库镜像地址

#vim /etc/docker/daemon.json 
{"registry-mirrors": ["https://xxxx.mirror.aliyuncs.com"]}

xxxx 为你自己阿里云的账号的加速地

2 、搭建 Gitlab 服务

我们来通过 Docker 启动一个 Gitlab 服务,如下:

安装 gitlab

域名我们随便就行了。

docker run -d --hostname gitlab.xxx.cn \
--publish 443:443 --publish 80:80 --publish 2222:22 \
--name gitlab --restart always --volume /srv/gitlab/config:/etc/gitlab \
--volume /srv/gitlab/logs:/var/log/gitlab \
--volume /srv/gitlab/data:/var/opt/gitlab \
gitlab/gitlab-ce:latest

首次登录 Gitlab 需要重置密码,默认用户名为 root

3 、创建一个 demo 的新项目

4 、安装 gitlab-runner

这里建议与 Gitlab 服务器分开部署,专门提供单独的 runner 服务器。

这里就直接在 node2 上安装了

Node2

curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh | sudo bash
yum install gitlab-runner

找到 setting à CI/CD à runner Expand

下面 URL token 为注册 runner 准备

然后配置发布用的 gitlab-runner

注册 gitlab-runner

#gitlab-runner register --clone-url http://172.25.0.30
 
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
http://gitlab.xxx.cn/   #你的gitlab地址 ,注意该地址可以被gitlab-runner主机访问
Please enter the gitlab-ci token for this runner:
an2eDx6LUfdsfh  #上面获取项目的token
Please enter the gitlab-ci description for this runner:
test  #描述,如: test
Please enter the gitlab-ci tags for this runner (comma separated):
builder # 项目标签,如:builder; 线上环境可以设置为 tags,测试环境设置为 test
Please enter the executor: docker-ssh, shell, docker+machine, docker-ssh+machine, docker, parallels, ssh, virtualbox, kubernetes:
shell  #执行者:shell就行了

gitlab 可以查看已创建的 runner

修改 gitlab-runner 并发执行个数

$ vim /etc/gitlab-runner/config.toml
concurrent = 5

5、gitlab-runner服务相关命令

gitlab-runner 启动:

# service gitlab-runner start

……….

或者

启动:

#gitlab-runner start

重启:

#gitlab-runner restart

停止:

# gitlab-runner stop

二、搭建 Swarm 集群

1 、初始化 Swarm 集群

Node2

#docker swarm init

如果有多个网络的,指定 ip

#docker swarm init  --advertise-addr=172.25.0.30
To add a worker to this swarm, run the following command:
 
    docker swarm join --token SWMTKN-1-5u33b53uo759k9e5ktq9sx4szzl07p56m7b5b02gp5icpgi2sr-bej3o747ln4sjx2ffvmvh29zs 172.25.0.30:2377
 
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
 
docker swarm leave --force

初始化会创建 ingress 的网络,该网络网段为 10.0.0.0/24

2、创建自定义 Overlay 网络

构建自定义网络,不能再用 10.0.0.0/24 ,不然构建完的 DRIVER 状态为空

#docker network create \
--driver overlay \
--subnet 10.0.1.0/24 \
--opt encrypted \
--attachable \
network

3、检查network状态

# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
eef2832b5f79        bridge              bridge              local
79941a5ab0b2        docker_gwbridge     bridge              local
379db27e8b2f        host                host                local
poq791eacuk8        ingress             overlay             swarm
676019f0e1f3        none                null                local
j4mxeizwtcki        network             overlay             swarm

可以看到network了

j4mxeizwtcki        network               overlay            swarm

4、添加集群

工作节点 :增加容量。当将服务部署到集群时,引擎调度任务到可用节点上,不管是工作节点还是管理节点。当工作节点加入到集群时,可扩展集群处理任务规模不会影响管理者 raft 使用。

管理节点 :增加容错能力。管理节点执行集群编排和管理功能。在所有管理节点中,会选择出一个领导者,来执行编排任务。当该领导者故障了,其余的管理节点选择出一个新的领导者,并恢复对集群状态的编排和管理。默认情况下,管理节点也运行任务

Node2 主节点:

查看 node 加入 worker 集群命令:

#docker swarm join-token worker
docker swarm join --token SWMTKN-1-5u33b53uo759k9e5ktq9sx4szzl07p56m7b5b02gp5icpgi2sr-bej3o747ln4sjx2ffvmvh29zs 172.25.0.30:2377

node3 加入集群

#docker swarm join --token SWMTKN-1-5u33b53uo759k9e5ktq9sx4szzl07p56m7b5b02gp5icpgi2sr-bej3o747ln4sjx2ffvmvh29zs 172.25.0.30:2377

查看集群状态

注:

如果需要添加 manager ,可以查看直接添加

显示 manager 节点的 TOKEN

# docker swarm join-token manager

加入 manager 节点到集群

# docker swarm join --token <token> ip:2377

manager 离开集群导致集群出错处理

这里有个小问题,我发现一个节点以 manager 角色加入集群,然后在 manager 角色节点使用 docker swarm leave --force ,命令离开集群,发现主节点会崩溃。

模拟过程:

主节点:

获取 managerTOKEN

# docker swarm join-token manager

Manager 节点:

manager 角色加入集群

# docker swarm join --token <token> ip:2377

强制离开集群

# docker swarm leave --force

重新加入

# docker swarm join --token <token> ip:2377
Error response from daemon: rpc error: code = Unknown desc = The swarm does not have a leader. It's possible that too few managers are online. Make sure more than half of the managers are online.

主节点:

获取 managerTOKEN

# docker swarm join-token manager
Error response from daemon: rpc error: code = Unknown desc = The swarm does not have a leader. It's possible that too few managers are online. Make sure more than half of the managers are online.

处理方法:

主节点:

# docker swarm leave --force

重新初始化

#docker swarm init

安装 mysql, 检测自定义的 network 可用性

以下以 Mysql 为例,直接使用上述 network ,支持容器内使用 name 互调。可以为我们项目提供 mysql 服务

#docker run --name mysql -v /srv/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 --network network -d mysql:5.7

5、安装 Portainer

Portainer 为容器的 web 可视化管理界面

docker service create \
    --name portainer \
    --publish 9000:9000 \
    --replicas=1 \
    --constraint 'node.role == manager' \
    --mount type=volume,src=portainer_data,dst=/data \
    --mount type=bind,src=//var/run/docker.sock,dst=/var/run/docker.sock \
    portainer/portainer

注,如果是默认装的 docker.sock ,在 /var/run 下的

访问 http://172.25.0.30:9000/

创建访问账户密码:

admin

password

进去创建 local 的就行了

可以看到本地的 docker

查看集群

也是正常的了

三、Hyperf持续集成部署

Hyperf 代码地址https://github.com/hyperf/hyperf-skeleton.git

1、hyperf-skeleton代码导入 Demo 项目

Node2:

1)、拉取hyperf项目代码

#cd /usr/local;git clone https://github.com/hyperf/hyperf-skeleton.git

2)、配置demo免密部署keys

获取本地主机的 id_keys

# cat /root/.ssh/id_rsa.pub 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+2y1ApIlNj0M2nHMdP8lhgjJgNcrcv+LzoOBhs0Ji5tuRUmj7a891KLigymal/2jZWPj5TTX/LEEHXVlfy2+eAPWfq05p9pI3/nJmHfB/JgUXSCrgk/mojf/goALfzRHvaOe/LlwFNr87U5SrpmztD4qRODBp root@node3

如果没有这个文件生成一下

#ssh-keygen

Gitlab 添加部署密钥

添加部署密钥,注意是可写入,要勾选

获取 demogit ssh 地址

git@gitlab.xxx.cn:root/demo.git 这个地址是不正确的,因为我们在构建时,使用的端口并不是 22 端口,直接使用这个地址, clone 会提示输入密码,无法拉取代码,正确地址是 :

ssh://git@gitlab.xxx.cn:2222/root/demo.git

4)、hyperf代码导入demo项目

进入 hyperf 代码目录删除 git 记录

#cd /usr/local/hyperf-skeleton/;rm -rf .git/

更改 .git 目录记录

# cd /usr/local/hyperf-skeleton/;cp -rf /usr/local/demo/.git .

推送代码到 demo

# cd /usr/local/hyperf-skeleton/
# git add -A
# git commit -m 'add new files'
# git push origin master

3)、拉取demo的项目

# cd /usr/local;git clone ssh://git@gitlab.xxx.cn:2222/root/demo.git

2、配置阿里镜像仓库

创建镜像仓库,存储镜像

首先创建一个命名空间,然后创建一个镜像仓库 demo ,并使用本地仓库。

然后到我们直接打包用的服务器中,登录阿里云 Docker Registry

Node2:

usermod -aG docker gitlab-runner
su gitlab-runner
docker login --username=(你的账户—name) registry.cn-shanghai.aliyuncs.com

3、增加镜像地址,network配置,Dockerfile

1)、修改 hyperf 的 .gitlab-ci.yml文件配置

发现官网没有很细节的说,直接按官网的有点问题的 , 该配置   CI   用你的项目中做哪些操作,这个文件位于仓库的根目录

# usermod -aG docker gitlab-runner
 
stages:
  - build
  - deploy
 
variables:
  PROJECT_NAME: demo #gitlab项目名
  REGISTRY_URL: registry.cn-shanghai.aliyuncs.com/test-space1 #阿里源仓库名
 
build_test_docker:
  stage: build
  before_script:
#    - git submodule sync --recursive
#    - git submodule update --init --recursive
  script:
    - docker build . -t $PROJECT_NAME
    - docker tag $PROJECT_NAME $REGISTRY_URL/$PROJECT_NAME:test
    - docker push $REGISTRY_URL/$PROJECT_NAME:test
  only:
    - test   #定义job所引用的git分支
  tags:
    - builder   #gitlab-runner创建时的tags,tags为runner标签
 
deploy_test_docker:
  stage: deploy
  script:
    - docker stack deploy -c deploy.test.yml --with-registry-auth $PROJECT_NAME
  only:
    - test
  tags:
    - builder
 
build_docker:
  stage: build
  before_script:
#    - git submodule sync --recursive
#    - git submodule update --init --recursive
  script:
    - docker build . -t $PROJECT_NAME
    - docker tag $PROJECT_NAME $REGISTRY_URL/$PROJECT_NAME:$CI_COMMIT_REF_NAME
    - docker tag $PROJECT_NAME $REGISTRY_URL/$PROJECT_NAME:latest
    - docker push $REGISTRY_URL/$PROJECT_NAME:$CI_COMMIT_REF_NAME
    - docker push $REGISTRY_URL/$PROJECT_NAME:latest
  only:
    - tags
  tags:
    - builder
 
deploy_docker:
  stage: deploy
  script:
    - echo SUCCESS
  only:
    - tags
  tags:
    - builder

2)、修改deploy.test.yml配置

version: '3.7'
services:
  demo:
    image: $REGISTRY_URL/$PROJECT_NAME:test
    environment:
      - "APP_PROJECT=demo" #项目名字
      - "APP_ENV=test"  
    ports:
      - 9501:9501
    deploy:
      replicas: 1
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 5
      update_config:
        parallelism: 2
        delay: 5s
        order: start-first
    networks:
      - network  #我们自定义的swarm网络
    configs:
      - source: demo_v1.0  #项目的配置名字,之后需要在portainer创建
        target: /opt/www/.env
configs:
  demo_v1.0:
    external: true
networks:
  network: #我们自定义的swarm网络
    external: true

3)、dockerfile配置

发现我在搭建的时候有点问题,就修改一下 dockerfile,imagesPHP 基本扩展很全,就不用安装了,我们主要改一下源。

# Default Dockerfile
#
# @link     https://www.hyperf.io
# @document https://doc.hyperf.io
# @contact  group@hyperf.io
# @license  https://github.com/hyperf-cloud/hyperf/blob/master/LICENSE
 
FROM hyperf/hyperf:7.2-alpine-v3.9-cli
LABEL maintainer="Hyperf Developers <group@hyperf.io>" version="1.0" license="MIT"
 
##
# ---------- env settings ----------
##
# --build-arg timezone=Asia/Shanghai
ARG timezone
 
ENV TIMEZONE=${timezone:-"Asia/Shanghai"} \
    COMPOSER_VERSION=1.9.1 \
    APP_ENV=prod
 
# update
RUN set -ex \
    && apk update \
    # install composer
    && cd /tmp \
    && wget https://github.com/composer/composer/releases/download/${COMPOSER_VERSION}/composer.phar \
    && chmod u+x composer.phar \
    && mv composer.phar /usr/local/bin/composer \
    # show php version and extensions
    && php -v \
    && php -m \
    #  ---------- some config ----------
    && cd /etc/php7 \
    # - config PHP
    && { \
        echo "upload_max_filesize=100M"; \
        echo "post_max_size=108M"; \
        echo "memory_limit=1024M"; \ 
        echo "date.timezone=${TIMEZONE}"; \
    } | tee conf.d/99-overrides.ini \
    # - config timezone
    && ln -sf /usr/share/zoneinfo/${TIMEZONE} /etc/localtime \
    && echo "${TIMEZONE}" > /etc/timezone \
    # ---------- clear works ----------
    && rm -rf /var/cache/apk/* /tmp/* /usr/share/man \
    && echo -e "\033[42;37m Build Completed :).\033[0m\n"
 
WORKDIR /opt/www
 
# Composer Cache
# COPY ./composer.* /opt/www/
# RUN composer install --no-dev --no-scripts
 
COPY . /opt/www
#添加阿里源composer地址,主要加速
RUN composer config  repo.packagist composer https://mirrors.aliyun.com/composer/
RUN composer install --no-dev -o
 
EXPOSE 9501
 
ENTRYPOINT ["php", "/opt/www/bin/hyperf.php", "start"]

4、Portainer 创建对应的 Configs

这个是 demo 项目,可以随便一点就行 , 添加 config 名字为 demo_v1.0 config 主要是配置一些服务参数

配置如下:

APP_NAME=demo
 
DB_DRIVER=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=hyperf
DB_USERNAME=root
DB_PASSWORD=123456
DB_CHARSET=utf8mb4
DB_COLLATION=utf8mb4_unicode_ci
DB_PREFIX=
 
REDIS_HOST=localhost
REDIS_AUTH=
REDIS_PORT=6379
REDIS_DB=0

过程如下:

5、gitlab-CD/CI持续集成部署

因为 demo 配置了 gitlab-ci.yml ,配置了 onlytags, 推送代码到 test 分支自动会检测 test 分支和 tags ,所以直接把 test 分支推送到 gitlab 就行。

到这一步,我们可能会有个疑问,怎么推送到 test 分支服务就起来了呢

其实过程并不复杂,由于我们配置 .gitlab-ci.yml 文件,当我们把代码推送到指定的分支后,便会触发 gitlab-runner, 通过读取 .gitlab-ci.yml 进行整个项目的构建。

1)、代码推送到特定分支

推送代码到 test 分支

#git branch test
#git push origin test

2)、查看构建jobs

找到 gitlab-demo 项目 à CI/CD à Pipelines à Running, 我们可以发现找到我的项目正在部署

一段时间后,可以发现两个都构建任务都构建成功了

点进去可看构建的过程,也是排错的地方

3)、集群验证

接下来我们就可以访问集群任意一台机器的 9501 端口。进行测试了

查看集群的 9501 的端口是否起来了

node2

# netstat -ntpl | grep 9501
tcp6       0      0 :::9501                 :::*                    LISTEN      129611/dockerd

node3:

# netstat -ntpl | grep 9501
tcp6       0      0 :::9501                 :::*                    LISTEN      2247/dockerd

集群 hyperf 的服务端口都起来了,访问hyperf

#curl http://172.25.0.30:9501/
{"method":"GET","message":"Hello Hyperf."}
# curl http://172.25.0.33:9501/
{"method":"GET","message":"Hello Hyperf."}

四、安装 KONG 网关,代理http转发

默认的 Docker Swarm 集群是不会直接对外暴露提供访问的,所以我们可以在上层构建一个网关服务, Kong 在保护,管理和扩展微服务和 API 的同时,也可以充当一个网关的角色通过提供日志,认证或者其他功能的插件来给给 HTTP 提供任何资源。

1、安装数据库

#docker run -d --name kong-database \
  --network=network \
  -p 5432:5432 \
  -e "POSTGRES_USER=kong" \
  -e "POSTGRES_DB=kong" \
  -e "POSTGRES_PASSWORD=123456" \
  postgres:9.6

2、安装网关、初始化数据库

docker run --rm \
  --network=network \
  -e "KONG_DATABASE=postgres" \
  -e "KONG_PG_HOST=kong-database" \
  -e "KONG_PG_PASSWORD=123456" \
  -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
  kong:0.14.1  kong migrations up

3、启动kong

docker run -d --name kong \
  --network=network \
  -e "KONG_DATABASE=postgres" \
  -e "KONG_PG_HOST=kong-database" \
  -e "KONG_PG_PASSWORD=123456" \
  -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
  -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \
  -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \
  -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \
  -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \
  -e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \
  -p 8000:8000 \
  -p 8443:8443 \
  -p 8001:8001 \
  -p 8444:8444 \
  kong:0.14.1

这里有一个就是,如果机器直接对外暴露访问, 80443 端口,可以把端口映射 -p 80:8000 -p 443:8443 映射到本地 80443 端口。

4、安装 KONG Dashboard

docker run  --network=network -p 8080:8080 -d --name kong-dashboard pgbi/kong-dashboard start \
  --kong-url http://kong:8001 \
  --basic-auth kong=kong

5、配置 Service

接下来只需要把部署 KONG 网关的机器 IP 对外暴露访问,然后配置对应的 Service 即可。

配置 service

6、配置route

添加路由

配置好的如下

访问是否代理成功

#curl -i -X GET --url http://172.25.0.30:8000/
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 42
Connection: keep-alive
Server: Hyperf
Date: Mon, 27 Apr 2020 06:41:52 GMT
X-Kong-Upstream-Latency: 1
X-Kong-Proxy-Latency: 2
Via: kong/0.14.1
{"method":"GET","message":"Hello Hyperf."}

五、相关错误与分析处理

分析一:

Gitlab 搭建 docker 浮动性大。经常出现,无限重启的状态,

分析:在资源消耗,后期维护的问题上,不建议 docker 上安装。

分析二:

构建项目时突然出现

fatal: git fetch-pack: expected shallow list

fatal: The remote end hung up unexpectedly

分析:这个 Git 的版本问题,重新安装就好

#yum install http://opensource.wandisco.com/centos/7/git/x86_64/wandisco-git-release-7-2.noarch.rpm
#yum install git -y

重新运行 jobs 就行了

分析三:

新加入的节点,是否直接加入到工作状态。

分析:

模拟了一下,当我们新加一个新的节点后,发现 9501 端口也会起来的,这就是集群的作用;另外,模拟了好几次后发现 hyperf 它都只会在集群的 其中一个节点 运行,但是其他节点是正常访问的,其它节点是起到工作分担的作用,这也是 dokcer swarm 的特点。

六、问题总结

1、 发现每次构建的时候,就会构建一个新的镜像,为了可控资源, docker 需要控制镜像的数量。

2、 在服务方面,日志是不可少的,所以后期方面,日志该如何处理。

3、需要熟练Dockerfiles方面语法/编写。

………………………….

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章