從零進階--構建docker-swarm結合Gitlab-runner持續集成實現hyperf 部署

        構建docker-swarm結合Gitlab-runner持續集成實現hyperf部署

最近發現有用到hyperf,應需求,便按照官網的,弄一下Gitlab-runner持續集成部署,詳細可見官方文檔:Hyperfphp

簡介

Docker-swarmSwarm Docker 官方提供的一款集羣管理工具,其主要做用是把若干臺 Docker主機抽象爲一個總體,而且經過一個入口統一管理這些 Docker 主機上的各類 Docker 資源。node

Gitlab-runnergitlab-runner gitlab 提供的持續集成工具,經過.gitlab-ci.yml實現有效項目部署。python

HyperfHyperf 是基於 Swoole 4.3+ 實現的高性能、高靈活性的 PHP 協程框架,是基於微服務開源的框架。詳細可見官官方文檔:Hyperfmysql

Kong: 網關服務,主要用於數據轉發,主要做用於保護,管理和擴展微服務和API 。git

對於整個架構實現,我簡單整理了一下,如圖1,大概實現的效果是這樣的:github


1.png

1web

環境:

         Node2172.25.0.30 centos7 主節點 Leandersql

         Node3172.25.0.33 centos7  workerdocker

 

1、安裝 Dockergitlab

1Node2node3安裝docker

安裝dockersshell

#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的新項目


 2.png

 

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


下面URLtoken爲註冊runner準備

 

3.png

 

而後配置發佈用的 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

4.png

 

修改 gitlab-runner 併發執行個數

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


五、gitlab-runner服務相關命令

gitlab-runner啓動:

# service gitlab-runner start

……….

或者

啓動:

#gitlab-runner start

重啓:

#gitlab-runner restart

中止:

# gitlab-runner stop

2、搭建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

二、建立自定義 Overlay 網絡

構建自定義網絡,不能再用10.0.0.0/24,否則構建完的DRIVER狀態爲空

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


三、檢查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


四、添加集羣

工做節點:增長容量。當將服務部署到集羣時,引擎調度任務到可用節點上,不論是工做節點仍是管理節點。當工做節點加入到集羣時,可擴展集羣處理任務規模不會影響管理者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

查看集羣狀態

6.png

注:

若是須要添加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


五、安裝 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

7.png

進去建立local的就好了

8.png

 

能夠看到本地的docker

9.png

查看集羣

10.png

也是正常的了

3、Hyperf持續集成部署

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

一、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添加部署密鑰

11.png

添加部署密鑰,注意是可寫入,要勾選

12.png

獲取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

13.png

 

 

3)、拉取demo的項目

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


二、配置阿里鏡像倉庫

建立鏡像倉庫,存儲鏡像

首先建立一個命名空間,而後建立一個鏡像倉庫 demo,並使用本地倉庫。

14.png

15.png

 

 

而後到咱們直接打包用的服務器中,登陸阿里雲 Docker Registry

Node2:

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

三、增長鏡像地址,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"]


四、Portainer 建立對應的 Configs

 

這個是demo項目,能夠隨便一點就行,添加config名字爲demo_v1.0config主要是配置一些服務參數

配置以下:

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


 

過程以下:


 16.png 

17.png

五、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,咱們能夠發現找到個人項目正在部署

18.png

一段時間後,能夠發現兩個都構建任務都構建成功了

19.png

點進去可看構建的過程,也是排錯的地方

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."}


 

4、安裝 KONG 網關,代理http轉發

默認的Docker Swarm 集羣是不會直接對外暴露提供訪問的,因此咱們能夠在上層構建一個網關服務, Kong在保護,管理和擴展微服務和API的同時,也能夠充當一個網關的角色經過提供日誌,認證或者其餘功能的插件來給給HTTP提供任何資源。

 

一、安裝數據庫

#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


二、安裝網關、初始化數據庫

 

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


三、啓動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 端口,能夠把端口映射-p 80:8000-p 443:8443 映射到本地80443端口。

 

四、安裝 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

五、配置 Service

接下來只須要把部署 KONG 網關的機器 IP 對外暴露訪問,而後配置對應的 Service 便可。

配置service

20.png

 

六、配置route

添加路由

21.png

配置好的以下

22.png

訪問是否代理成功

#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."}

5、相關錯誤與分析處理

分析一:

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的特色。

6、問題總結

 

一、發現每次構建的時候,就會構建一個新的鏡像,爲了可控資源,docker須要控制鏡像的數量。

二、在服務方面,日誌是不可少的,因此後期方面,日誌該如何處理。

三、須要熟練Dockerfiles方面語法/編寫。

………………………….

相關文章
相關標籤/搜索