构建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协程框架,是基于微服务开源的框架。详细可见官官方文档:HyperfKong: 网关服务,主要用于数据转发,主要作用于保护,管理和扩展微服务和API 。
对于整个架构实现,我简单整理了一下,如图1,大概实现的效果是这样的:
图1环境:Node2:172.25.0.30 centos7主节点LeanderNode3:172.25.0.33 centos7 worker
一、安装Docker、gitlab
1、Node2、node3安装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了
j4mxeizwtckinetworkoverlayswarm
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 ip:2377
manager离开集群导致集群出错处理
这里有个小问题,我发现一个节点以manager角色加入集群,然后在manager角色节点使用docker swarm leave --force,命令离开集群,发现主节点会崩溃。
模拟过程:
主节点:
获取managerTOKEN:# docker swarm join-token manager
Manager节点:
manager角色加入集群# docker swarm join --token ip:2377
强制离开集群# docker swarm leave --force
重新加入
# docker swarm join --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目录下面
创建访问账户密码:
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添加部署密钥
添加部署密钥,注意是可写入,要勾选
获取demo的git ssh地址
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,源images的PHP基本扩展很全,就不用安装了,我们主要改一下源。
# 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 " 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,配置了only和tags,推送代码到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
这里有一个就是,如果机器直接对外暴露访问,80和443端口,可以把端口映射-p80:8000、-p 443:8443映射到本地80和443端口。
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方面语法/编写。
………………………….