hyperf/docs/zh-hk/tutorial/docker-swarm.md
李铭昕 e259a59184
v2.0.12 (#2555)
* Update CHANGELOG-2.0.md

* Update

* Update doc and translate

Co-authored-by: huangzhhui <huangzhwork@gmail.com>
2020-09-21 10:25:38 +08:00

11 KiB
Raw Blame History

Docker Swarm 集羣搭建

現階段,容器技術已經相當成熟了,就算是中小型公司,也可以基於 Gitlab、Aliyun 鏡像倉庫服務 和 Docker Swarm 輕鬆搭建自己的 Docker 集羣服務。

安裝 Docker

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

修改文件 /lib/systemd/system/docker.service,允許使用 TCP 連接 Docker

ExecStart=/usr/bin/dockerd -H unix:// -H tcp://0.0.0.0:2375

配置倉庫鏡像地址

基於跨國線路訪問速度過慢等問題,我們可以為 Docker 配置倉庫鏡像地址,來改善這些網絡問題,如 阿里雲(Aliyun) Docker 鏡像加速器,我們可以申請一個 Docker 加速器,然後配置到服務器上的 /etc/docker/daemon.json 文件,添加以下內容,然後重啟 Docker,下面的地址請填寫您自己獲得的加速器地址。

{"registry-mirrors": ["https://xxxxx.mirror.aliyuncs.com"]}

搭建 Gitlab 服務

安裝 Gitlab

修改 sshd 默認端口號

首先我們需要修改一下服務器的 sshd 服務的端口號,把默認的 22 端口改為 2222 端口(或其它未被佔用的端口),這樣可以讓 gitlab 通過使用 22 端口來進行 ssh 連接。

$ vim /etc/ssh/sshd_config

# 默認 Port 改為 2222
Port 2222

# 重啟服務
$ systemctl restart sshd.service

重新登錄機器

ssh -p 2222 root@host 

安裝 Gitlab

我們來通過 Docker 啟動一個 Gitlab 服務,如下:

sudo docker run -d --hostname gitlab.xxx.cn \
--publish 443:443 --publish 80:80 --publish 22: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

安裝 gitlab-runner

這裏建議與 Gitlab 服務器分開部署,專門提供單獨的 runner 服務器。

我們以 CentOS 的的安裝方式為例,其餘可參考 Gitlab 官網文檔

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

當然,也可以用 curl https://setup.ius.io | sh 命令,更新為最新的 git 源,然後直接使用 yum 安裝 git 和 gitlab-runner。

$ curl https://setup.ius.io | sh
$ yum -y install git2u
$ git version
$ yum install gitlab-runner

註冊 gitlab-runner

通過 gitlab-runner register --clone-url http://your-ip/ 命令來將 gitlab-runner 註冊到 Gitlab 上,注意要替換 your-ip 為您的 Gitlab 的內網 IP如下

$ gitlab-runner register --clone-url http://your-ip/

Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
http://gitlab.xxx.cc/
Please enter the gitlab-ci token for this runner:
xxxxx
Please enter the gitlab-ci description for this runner:
xxx
Please enter the gitlab-ci tags for this runner (comma separated):
builder
Please enter the executor: docker-ssh, shell, docker+machine, docker-ssh+machine, docker, parallels, ssh, virtualbox, kubernetes:
shell

修改 gitlab-runner 併發執行個數

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

初始化 Swarm 集羣

登錄另外一台機器,初始化集羣

$ docker swarm init

創建自定義 Overlay 網絡

docker network create \
--driver overlay \
--subnet 10.0.0.0/24 \
--opt encrypted \
--attachable \
default-network

加入集羣

# 顯示manager節點的TOKEN
$ docker swarm join-token manager
# 加入manager節點到集羣
$ docker swarm join --token <token> ip:2377

# 顯示worker節點的TOKEN
$ docker swarm join-token worker
# 加入worker節點到集羣
$ docker swarm join --token <token> ip:2377

然後配置發佈用的 gitlab-runner

其他與 builder 一致,但是 tag 卻不能一樣。線上環境可以設置為 tags測試環境設置為 test

安裝其他應用

以下以 Mysql 為例,直接使用上述 network,支持容器內使用 name 互調。

docker run --name mysql -v /srv/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=xxxx -p 3306:3306 --rm --network default-network -d mysql:5.7

安裝 Portainer

Portainer

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

創建一個 Demo 項目

登錄 Gitlab 創建一個 Demo 項目。並導入我們的項目 hyperf-skeleton

配置鏡像倉庫

我們直接使用阿里雲的即可

首先創建一個命名空間 test_namespace然後創建一個鏡像倉庫 demo並使用本地倉庫。

然後到我們直接打包用的服務器中,登錄阿里雲 Docker Registry

usermod -aG docker gitlab-runner
su gitlab-runner
docker login --username=your_name registry.cn-shanghai.aliyuncs.com

修改我們項目裏的 .gitlab-ci.yml

variables:
  PROJECT_NAME: demo
  REGISTRY_URL: registry.cn-shanghai.aliyuncs.com/test_namespace

還有 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:
      - default-network
    configs:
      - source: demo_v1.0
        target: /opt/www/.env
configs:
  demo_v1.0:
    external: true
networks:
  default-network:
    external: true

然後在我們的 Portainer 中,創建對應的 Config demo_v1.0。當然,以下參數需要根據實際情況調整,因為我們的 Demo 中,沒有任何 I/O 操作,所以填默認的即可。

APP_NAME=demo

DB_DRIVER=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=hyperf
DB_USERNAME=root
DB_PASSWORD=
DB_CHARSET=utf8mb4
DB_COLLATION=utf8mb4_unicode_ci
DB_PREFIX=

REDIS_HOST=localhost
REDIS_AUTH=
REDIS_PORT=6379
REDIS_DB=0

因為我們配置的 gitlab-ci.yml 會檢測 test 分支和 tags所以我們把修改的內容合併到 test 分支,然後推到 gitlab 上。

接下來我們就可以訪問集羣任意一台機器的 9501 端口。進行測試了

curl http://127.0.0.1:9501/

安裝 KONG 網關

通常情況下Docker Swarm 集羣是不會直接對外暴露提供訪問的,所以我們可以在上層構建一個網關服務,這裏推薦使用 KONG 作為網關。 還有另外一個原因是 Docker Swarm 的 Ingress 網絡 存在設計的缺陷,在連接不復用的情況下,會有併發瓶頸,具體細節請查看對應的 Issue #35082KONG 作為網關服務,默認情況下會複用後端的連接,所以會極大減緩上述問題。

安裝數據庫

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

安裝網關

初始化數據庫

docker run --rm \
  --network=default-network \
  -e "KONG_DATABASE=postgres" \
  -e "KONG_PG_HOST=kong-database" \
  -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
  kong:latest kong migrations bootstrap

啟動

docker run -d --name kong \
  --network=default-network \
  -e "KONG_DATABASE=postgres" \
  -e "KONG_PG_HOST=kong-database" \
  -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:latest

安裝 KONG Dashboard

暫時 Docker 中沒有更新 v3.6.0 所以最新版的 KONG 可能無法使用

docker run --rm --network=default-network -p 8080:8080 -d --name kong-dashboard pgbi/kong-dashboard start \
  --kong-url http://kong:8001 \
  --basic-auth user1=password1 user2=password2

配置 Service

接下來只需要把部署 KONG 網關的機器 IP 對外暴露訪問,然後配置對應的 Service 即可。 如果機器直接對外暴露訪問,那麼最好只開放 80443 端口,然後把 Kong 容器的 80008443 端口映射到 80443 端口上。 當然,如果使用了 SLB 等負載均衡服務,也直接通過負載均衡,把 80443 端口映射到 KONG 所在機器的 8000 8443 端口上。

如何使用 Linux Crontab

Hyperf 雖然提供了 crontab 組件,但可能並不一定可以滿足所有人的需求,這裏提供一個 Linux 下使用的腳本,來執行 Docker 內的 Command

#!/usr/bin/env bash
basepath=$(cd `dirname $0`; pwd)
docker pull registry-vpc.cn-shanghai.aliyuncs.com/namespace/project:latest
docker run --rm -i -v $basepath/.env:/opt/www/.env \
--entrypoint php registry-vpc.cn-shanghai.aliyuncs.com/namespace/project:latest \
/opt/www/bin/hyperf.php your_command

內核優化

本小節內容,有待驗證,謹慎使用

安裝 KONG 網關時,有介紹 Ingress 網絡 存在設計的缺陷,這塊可以通過 優化內核 處理。

  • 指定 TLinux 源
tee /etc/yum.repos.d/CentOS-TLinux.repo <<-'EOF' 
[Tlinux]
name=Tlinux for redhat/centos $releasever - $basearch
failovermethod=priority
gpgcheck=0
gpgkey=http://mirrors.tencentyun.com/epel/RPM-GPG-KEY-EPEL-7
enabled=1
baseurl=https://mirrors.tencent.com/tlinux/2.4/tlinux/x86_64/
EOF
  • 安裝指定內核
yum -y install kernel-devel-4.14.105-19.0012.tl2.x86_64 kernel-4.14.105-19.0013.tl2.x86_64 kernel-headers-4.14.105-19.0013.tl2.x86_64
  • 使內核生效
sudo awk -F\' '$1=="menuentry " {print i++ " : " $2}' /etc/grub2.cfg
grub2-set-default 0
grub2-mkconfig -o /boot/grub2/grub.cfg
  • 重啟機器
reboot

容器參數優化

需要 Docker 19.09.0 以上支持,與 image 配置同級

sysctls:
  # 網絡連接複用模式的選擇
  - net.ipv4.vs.conn_reuse_mode=0
  # 當LVS轉發數據包發現目的RS無效刪除會丟棄該數據包但不刪除相應連接。值為1時則馬上釋放相應連接
  - net.ipv4.vs.expire_nodest_conn=1

常見問題

fatal: git fetch-pack: expected shallow list

這種情況是 gitlab-runner 使用的 git 版本過低,更新 git 版本即可,如下:

$ curl https://setup.ius.io | sh
$ yum remove -y git
$ yum -y install git2u
$ git version

# 重新安裝 gitlab-runner 並重新註冊 gitlab-runner
$ yum install gitlab-runner