尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Building a Docker Swarm Cluster and Deploying Hyperf Services with GitLab CI/CD

Building a Docker Swarm Cluster and Deploying Hyperf Services with GitLab CI/CD 后端Web框架微服务RPC框架异步编程【免费下载链接】hyperf A coroutine framework that focuses on hyperspeed and flexibility. Building microservice or middleware with ease.项目地址https://gitcode.com/hyperf/hyperf点击查看免费下载本教程以 Hyperf 官方文档《Docker Swarm cluster building tutorial》为主体系统讲解如何基于 Docker、GitLab含 gitlab-runner、阿里云镜像仓库与 Docker Swarm 搭建一套可自建的容器集群并将 Hyperf 项目以官方骨架 hyperf-skeleton 为例通过 GitLab CI 持续构建、推送到镜像仓库、再以 Docker Stack 部署到 Swarm 集群的全过程。读完本文你将掌握从 Docker 安装、GitLab 与 runner 注册、Swarm 集群初始化与 Overlay 网络规划到 Portainer 可视化管理、KONG 网关接入、Linux crontab 调度容器内 Hyperf 命令以及常见故障排查的完整实战链路。环境概览与前置准备现阶段容器技术已经相当成熟即使是中小型公司也可以基于 GitLab、阿里云镜像仓库服务和 Docker Swarm 轻松搭建属于自己的 Docker 集群服务。本文的整体架构如下GitLab 服务器承载代码仓库与 GitLab CI 流水线并通过 gitlab-runner 执行构建任务gitlab-runner 服务器建议与 GitLab 分开部署专门承担打包、推送镜像的职责Swarm 集群由多台 Docker 节点组成通过overlay网络互通对外以 9501 端口暴露 Hyperf HTTP 服务镜像仓库以阿里云容器镜像服务上海节点registry.cn-shanghai.aliyuncs.com为例保存构建产物Portainer以 Docker Service 形式运行在 manager 节点上提供集群与 Config 的可视化管理。Hyperf 是常驻内存的 CLI 框架详见 快速开始服务默认监听 9501 端口——该默认值定义在 Port.php 的protected int $port 9501;因此本文中所有服务发布端口均以 9501 为例。安装 Docker在所有参与构建与运行的机器上安装 Dockercurl -sSL https://get.daocloud.io/docker | sh为了后续让 gitlab-runner、开发账户免sudo执行 Docker 命令可将当前用户加入 docker 用户组usermod -aG docker $USER配置仓库镜像加速地址如果服务器位于境外线路访问较慢可以为 Docker 配置镜像加速器。申请到阿里云 Docker 加速器地址后写入/etc/docker/daemon.json然后重启 Docker请将地址替换为您自己获得的加速器地址{registry-mirrors: [https://xxxxx.mirror.aliyuncs.com]}搭建 GitLab 服务安装 GitLab由于 GitLab 默认通过 SSH 的22端口提供 git 拉取/推送首先需要把系统sshd服务的默认端口从22改为2222或其它未被占用的端口把22让给 GitLab$ vim /etc/ssh/sshd_config # 默认 Port 改为 2222 Port 2222 # 重启服务 $ systemctl restart sshd.service重新登录机器ssh -p 2222 roothost接下来用 Docker 启动 GitLab 容器。--hostname一定要配置如果没有域名可以直接填外网地址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。如果需要获取初始密码可以执行docker exec gitlab cat /etc/gitlab/initial_root_password如果希望 GitLab 发送邮件例如用户创建通知可以修改/srv/gitlab/config/gitlab.rb配置 SMTPgitlab_rails[smtp_enable] true gitlab_rails[smtp_address] smtp.exmail.qq.com gitlab_rails[smtp_port] 465 gitlab_rails[smtp_user_name] gitxxxx.com gitlab_rails[smtp_password] xxxx gitlab_rails[smtp_authentication] login gitlab_rails[smtp_enable_starttls_auto] true gitlab_rails[smtp_tls] true gitlab_rails[gitlab_email_from] gitxxxx.com gitlab_rails[smtp_domain] exmail.qq.com安装 gitlab-runner建议将 gitlab-runner 与 GitLab 服务器分开部署单独提供一台 runner 服务器。以 CentOS 为例安装方式如下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将 runner 注册到 GitLab注意将your-ip替换为 GitLab 的内网 IP$ sudo 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, dockermachine, docker-sshmachine, docker, parallels, ssh, virtualbox, kubernetes: shell交互式注册中需要填写的关键信息包括配置项说明coordinator URLGitLab 的访问地址即注册页面展示的 CI 地址tokenGitLab 项目或实例的 runner 注册令牌descriptionrunner 的描述便于在 GitLab 后台区分tagsrunner 标签流水线通过标签选择执行器executor执行器类型本文选择shell直接在宿主机执行命令修改 gitlab-runner 并发执行个数编辑 runner 的配置文件调整并发任务数$ vim /etc/gitlab-runner/config.toml concurrent 5为 gitlab-runner 增加权限免 sudo 执行 docker 的权限sudo usermod -aG docker gitlab-runner镜像仓库的登录权限后续推送镜像必需su gitlab-runner docker login -u username your-docker-repository初始化 Swarm 集群登录另外一台机器初始化集群$ docker swarm init创建自定义 Overlay 网络创建自定义 overlay 网络供集群内所有服务互通。以下提供三种方式按需选择其一直接创建自定义 overlay 网络docker network create \ --driver overlay \ --subnet 12.0.0.0/8 \ --opt encrypted \ --attachable \ default-network有时可能因为网段冲突导致 stack 启动失败可以尝试缩小--subnet网段该网段下最多支持 65535 个 IPdocker network create \ --driver overlay \ --subnet 10.1.0.1/16 \ --opt encrypted \ --attachable \ default-network大多数情况下是 ingress 网络默认网段与新建网段冲突可以先删除 ingress 网络再重建docker network rm ingress docker network create --ingress --subnet 192.168.0.1/16 --driver overlay ingress然后再创建--subnet为10.0.0.1/8的default-network。加入集群将其他节点加入 Swarm 集群。先查看 manager 节点令牌并加入# 显示 manager 节点的 TOKEN $ docker swarm join-token manager # 将 manager 节点加入集群 $ docker swarm join --token token ip:2377再查看 worker 节点令牌并加入# 显示 worker 节点的 TOKEN $ docker swarm join-token worker # 将 worker 节点加入集群 $ docker swarm join --token token ip:2377配置发布用的 gitlab-runner集群初始化完成后再配置一台专门用于“发布”的 gitlab-runner。它与构建用的 runner 其余配置一致但 tag 不能相同——例如线上环境可设置为tags测试环境设置为test这样流水线就能按环境选择不同的 runner 执行发布任务。安装其他应用以 MySQL 为例集群内部署中间件时直接使用上述default-network网络容器间即可通过服务名name互相调用docker run --name mysql -v /srv/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORDxxxx -p 3306:3306 --rm --network default-network -d mysql:5.7注意在容器内部署的服务之间互相访问时应使用服务名而非127.0.0.1。安装 PortainerPortainer 提供了可视化的集群管理界面以 Docker Service 形式部署在 manager 节点上docker service create \ --name portainer \ --publish 9000:9000 \ --replicas1 \ --constraint node.role manager \ --mount typevolume,srcportainer_data,dst/data \ --mount typebind,src//var/run/docker.sock,dst/var/run/docker.sock \ portainer/portainer其中--constraint node.role manager保证 Portainer 只调度到 manager 节点--mount挂载 docker.sock 以管理集群。备份与恢复 Portainer 数据备份portainer_container为实际容器名docker run -it --volumes-from portainer_container -v $(pwd):/backup --name backup --rm nginx tar -cf /backup/data.tar /data/恢复先重新创建 portainer 服务再执行docker run -it --volumes-from portainer_container -v $(pwd):/backup --name importer --rm nginx bash cd /backup tar xf data.tar -C /最后重启容器即可。创建一个 Demo 项目登录 GitLab 创建一个 Demo 项目并导入官方骨架项目hyperf-skeletonHyperf 官方准备的骨架工程内置了常用组件与相关配置是一个可直接上手开发的基础 Web 项目详见 安装文档。导入后项目的目录结构包含config/、app/、bin/hyperf.php等标准内容本地可通过php bin/hyperf.php start启动服务。配置镜像仓库我们直接使用阿里云容器镜像服务。首先在阿里云创建一个命名空间test_namespace然后创建一个镜像仓库demo并使用本地仓库。随后到负责打包的服务器上登录阿里云 Docker Registryusermod -aG docker gitlab-runner su gitlab-runner docker login --usernameyour_name registry.cn-shanghai.aliyuncs.com修改项目中的 .gitlab-ci.yml修改项目根目录的.gitlab-ci.yml声明项目名与镜像仓库地址变量variables: PROJECT_NAME: demo REGISTRY_URL: registry.cn-shanghai.aliyuncs.com/test_namespace流水线会按分支/标签触发构建将代码打包成镜像并推送到$REGISTRY_URL/$PROJECT_NAME对应的 tag。编写 deploy.test.ymlStack 编排文件项目中的deploy.test.yml是 Docker Stack 的编排文件需要仔细对比以下内容version: 3.7 services: demo: image: $REGISTRY_URL/$PROJECT_NAME:test environment: - APP_PROJECTdemo - APP_ENVtest 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关键点解读image引用.gitlab-ci.yml中定义的变量test为测试环境镜像 tagports9501:9501将容器内 Hyperf HTTP 端口映射到宿主机对应 Port.php 中定义的默认端口deploy.replicas副本数测试环境为 1restart_policy失败重启策略condition: on-failure表示失败时重启delay: 5s表示间隔 5 秒max_attempts: 5表示最多尝试 5 次update_config滚动更新策略parallelism: 2表示每次并行更新 2 个副本delay: 5s为更新间隔order: start-first表示先启动新实例再停止旧实例零停机发布configs将 Swarm Configdemo_v1.0挂载到容器内/opt/www/.env即 Hyperf 项目的环境配置文件configs.demo_v1.0.external: true与networks.default-network.external: true表示 Config 与网络均已在集群中预先创建不随 stack 自动创建。在 Portainer 中创建 Config然后在 Portainer 中创建对应的 Configdemo_v1.0。Demo 项目中没有任何 I/O 操作因此先填默认参数即可实际项目中需要根据环境调整APP_NAMEdemo DB_DRIVERmysql DB_HOSTlocalhost DB_PORT3306 DB_DATABASEhyperf DB_USERNAMEroot DB_PASSWORD DB_CHARSETutf8mb4 DB_COLLATIONutf8mb4_unicode_ci DB_PREFIX REDIS_HOSTlocalhost REDIS_AUTH REDIS_PORT6379 REDIS_DB0这些变量正是 Hyperf 骨架项目读取的环境配置数据库、Redis 连接信息容器启动后会被挂载为/opt/www/.env供框架读取。触发部署并验证因为我们配置的 gitlab-ci.yml 会检测test分支和 tags所以把修改的内容合并到test分支然后推送到 GitLab流水线会自动完成打包、推镜像、更新服务。接下来就可以访问集群任意一台机器的 9501 端口进行测试curl http://127.0.0.1:9501/若部署成功接口会返回 Hyperf 的欢迎信息如{code:0,data:{user:Hyperf,method:GET,message:Hello Hyperf.}}。使用 Linux Crontab 调度容器内的 Hyperf 命令Hyperf 虽然提供了 crontab 组件可支持秒级任务调度详见 任务调度文档但可能无法满足所有人的需求。这里提供一个 Linux 下的脚本用于定时执行 Docker 容器内的 Hyperf 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该脚本每次执行前先docker pull拉取最新镜像然后以只读方式挂载宿主机上的.env到容器内/opt/www/.env最后通过--entrypoint php直接调用容器内的bin/hyperf.php执行指定命令实现“定时任务跑在最新代码”的效果。接入 KONG 网关通常情况下Docker Swarm 集群不会直接对外暴露访问因此可以在上层构建网关服务这里推荐使用 KONG。另一个原因是 Docker Swarm 的 Ingress 网络在设计上存在缺陷在连接不复用的情况下会有并发瓶颈。KONG 作为网关服务默认会复用后端连接可以极大缓解该问题。安装数据库docker run -d --name kong-database \ --networkdefault-network \ -p 5432:5432 \ -e POSTGRES_USERkong \ -e POSTGRES_DBkong \ -e POSTGRES_PASSWORDkong \ postgres:9.6安装网关先初始化数据库docker run --rm \ --networkdefault-network \ -e KONG_DATABASEpostgres \ -e KONG_PG_HOSTkong-database \ -e KONG_PG_PASSWORDkong \ -e KONG_CASSANDRA_CONTACT_POINTSkong-database \ kong:latest kong migrations bootstrap再启动网关docker run -d --name kong \ --networkdefault-network \ -e KONG_DATABASEpostgres \ -e KONG_PG_HOSTkong-database \ -e KONG_PG_PASSWORDkong \ -e KONG_CASSANDRA_CONTACT_POINTSkong-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_LISTEN0.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 Dashboarddocker run --rm --networkdefault-network -p 8080:8080 -d --name kong-dashboard pgbi/kong-dashboard start \ --kong-url http://kong:8001 \ --basic-auth user1password1 user2password2配置 Service把部署 KONG 网关的机器 IP 对外暴露访问然后配置对应的 Service 即可。如果机器直接对外暴露访问最好只开放80和443端口把 KONG 容器的8000和8443端口映射到80和443端口上如果使用了 SLB 等负载均衡服务也可以通过负载均衡把80、443端口映射到 KONG 所在机器的8000、8443端口。内核优化谨慎使用本小节内容有待验证谨慎使用。针对上文提到的 Ingress 网络设计缺陷可以通过优化内核来处理。指定 TLinux 源tee /etc/yum.repos.d/CentOS-TLinux.repo -EOF [Tlinux] nameTlinux for redhat/centos $releasever - $basearch failovermethodpriority gpgcheck0 gpgkeyhttp://mirrors.tencentyun.com/epel/RPM-GPG-KEY-EPEL-7 enabled1 baseurlhttps://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\ $1menuentry {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_mode0 # 当 LVS 转发数据包发现目的 RS 无效删除时会丢弃该数据包但不删除相应连接值为 1 时则马上释放相应连接 - net.ipv4.vs.expire_nodest_conn1常见问题排查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-runnerService 重启后内网偶发“容器无法触达”问题现象多次从其他容器访问此服务接口出现Connection refused。原因通常是可用 IP 不够用可以通过修改网段增加可用 IP创建新的 Networkdocker network create \ --driver overlay \ --subnet 10.0.0.0/8 \ --opt encrypted \ --attachable \ default-network为服务增加新的 Networkdocker service update --network-add default-network service_name删除原来的 Networkdocker service update --network-rm old-network service_name为 Service 增加节点时一直卡在 create 阶段原因和解决办法同上网段 IP 耗尽需要扩充可用网段。在 Portainer 中修改了仓库密码后更新 Service 失败这是因为 Portainer 修改密码后不能作用于已经创建的服务手动更新即可docker service update --with-registry-auth service_name附录只安装 Docker Swarm 的最小流程如果你只需要安装并使用 Docker Swarm可以按以下流程操作。假设有三台机器 A、B、C默认将 A 作为 Leader。安装 Docker三台机器都执行curl -sSL https://get.docker.com/ | sh如需允许 TCP 连接 Docker可修改/lib/systemd/system/docker.service追加-H tcp://0.0.0.0:2375ExecStart/usr/bin/dockerd -H fd:// --containerd/run/containerd/containerd.sock -H tcp://0.0.0.0:2375初始化 Docker Swarm进入 A 机器执行初始化$ docker swarm init重建 ingress 网络解决网段冲突docker network rm ingress docker network create --ingress --subnet 192.168.0.1/16 --driver overlay ingress再创建业务网络docker network create \ --driver overlay \ --subnet 10.0.0.1/8 \ --opt encrypted \ --attachable \ default-network执行展示加入集群的命令三台机器规模下建议都声明为 manager$ docker swarm join-token manager若后期需要加入新的 worker 节点则执行$ docker swarm join-token worker将另外两台节点加入集群到 B、C 机器执行生成的命令docker swarm join --token xxxx ip:2377回到 A 机器查看节点是否加入成功docker node ls如果能看到 B 和 C 的节点则代表加入成功。登录镜像仓库三台机器全部执行登录操作docker login --usernamexxxx registry.cn-shanghai.aliyuncs.com打包并推送镜像可以在任意一台机器打包也可以在开发环境打包非上述三台机器环境需要先docker logindocker build . -t registry.cn-shanghai.aliyuncs.com/your_namespace/your_project:latest docker push registry.cn-shanghai.aliyuncs.com/your_namespace/your_project:latest制作 stack yml 文件回到 A 机器到/opt/www/your_project目录下编辑deploy.ymlversion: 3.7 services: your_project: image: registry.cn-shanghai.aliyuncs.com/your_namespace/your_project:latest ports: - 9501:9501 deploy: replicas: 3 restart_policy: condition: on-failure delay: 5s max_attempts: 5 update_config: parallelism: 2 delay: 5s order: start-first networks: - default-network configs: - source: your_project_v1.1 target: /opt/www/.env configs: your_project_v1.1: file: /opt/www/your_project/.env networks: default-network: external: true注意此处与前面 Portainer 方式不同Config 直接使用file:引用宿主机上的.env文件由 Docker 自动创建。编辑.env文件完成配置时不要使用 127.0.0.1 连接 MySQL 等服务应填写集群内服务名或可路由的地址。启动服务docker pull registry.cn-shanghai.aliyuncs.com/your_namespace/your_project:latest docker stack deploy -c /opt/www/your_project/deploy.yml --with-registry-auth your_project查看是否正常启动以下三个命令都应存在对应数据docker stack ls docker service ls docker ps测试服务是否可用到三台机器上分别执行 curl 测试如果都能返回对应数据代表服务启动成功curl http://127.0.0.1:9501/更新服务开发机打包并推送到镜像仓库docker build . -t registry.cn-shanghai.aliyuncs.com/your_namespace/your_project:latest docker push registry.cn-shanghai.aliyuncs.com/your_namespace/your_project:latest回到 A 机器执行拉取与重新部署docker pull registry.cn-shanghai.aliyuncs.com/your_namespace/your_project:latest docker stack deploy -c /opt/www/your_project/deploy.yml --with-registry-auth your_projectdocker stack deploy是幂等操作配置未变化时不会触发重启镜像 tag 更新后会自动按update_config策略完成滚动更新。与 Hyperf 框架的衔接要点最后总结本教程与 Hyperf 框架本身相关的事实依据便于读者对照源码深入理解默认端口 9501定义于 Port.php因此所有 Swarm 服务的ports映射都以 9501 为基准启动方式Hyperf 是常驻 CLI 应用通过php bin/hyperf.php start启动见 快速开始容器镜像的--entrypoint php加/opt/www/bin/hyperf.php即对应此启动入口环境配置Hyperf 骨架项目通过.env读取数据库、Redis 等配置这正是 Swarm Config 挂载/opt/www/.env的意义所在定时任务框架内置 crontab 组件支持秒级调度见 任务调度文档若需在容器内执行自定义命令可参考上文 Linux crontab 脚本方案。按此方案搭建完成后团队即可获得一条“代码推送 → GitLab CI 构建 → 镜像推送 → Swarm 滚动发布”的完整链路并且可通过 Portainer 可视化查看集群状态、管理 Config实现中小团队低成本的自建 DevOps 体系。赞分享后端Web框架微服务RPC框架异步编程【免费下载链接】hyperf A coroutine framework that focuses on hyperspeed and flexibility. Building microservice or middleware with ease.项目地址https://gitcode.com/hyperf/hyperf点击查看免费下载相关推荐Building gRPC Services with Hyperf: From .proto Definitions to Coroutine-Safe ClientsBuilding gRPC Services with Hyperf: From .proto Definitions to Coroutine Safe Cl后端Web框架微服务RPC框架异步编程Deploying UIE Information Extraction Services with PaddleNLP SimpleServingDeploying UIE Information Extraction Services with PaddleNLP SimpleServing 本文是 P人工智能大模型预训练微调LoRARLHF强化学习分布式训练模型推理服务推理引擎模型量化模型压缩本地部署NLPVue-Fabric-Editor: Building a Plugin-Architecture Image Editor with fabric.js and VueVue Fabric Editor: Building a Plugin Architecture Image Editor with fabric.js an前端图像处理上一篇智能抢购助手京东商品自动下单工具让购物效率提升300%下一篇京东商品自动化工具三步实现效率提升300%的智能监控方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表