使用 docker swarm 搭建一套,高可用的 docker 服务集群

这是一篇关于,如何搭建高可用的Docker集群的教程,文章中的方案只是个人的经验和想法,考虑的不一定非常全面主要是给大家起到抛砖引玉的作用,也欢迎大家指出问题我好加以完善,当然如果你有更好方案也欢迎分享讨论。话不多说,直接进入正题。

一、网络篇

1.1 申请公网

从互联网服务提供商(ISP)处申请一个或多个公网 IP 地址。便于外网访问使用(如果只需要内网访问,可以直接跳过),申请多个公网ip的目的是为了当其中一条网络中断时(如:网络线缆被挖断...),保证其它网络可以畅通的访问到我们的集群服务。

1.2. 域名注册

注册域名(如果有则跳过),在 DNS 服务提供商处(当然也可以自己搭建DNS服务)配置域名解析记录,将申请的多个公网 IP 地址,添加到解析记录中。

1.3. 网络接入

在机房内部,使用多个网络线路接入到不同的网络服务提供商(ISP)。确保每个网络线路都能够独立连接到互联网,即具有不同的公网 IP 地址。这样,即使其中一个线路断开,其他线路仍然可用。并将每条线路都转发到(VIP地址)后边会说到。

二、软件篇

2.1. Docker Swarm

创建3个高可用的 Swarm Manger 管理节点

# 安装 Docker
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install -y docker-ce docker-ce-cli containerd.io

# 启动 Docker 服务
systemctl start docker
systemctl enable docker

# 配置 Docker Swarm
docker swarm init --advertise-addr <MANAGER-IP>

# 获取加入管理节点的 Swarm Token
docker swarm join-token -q manager

# 在其他两个节点上加入 Swarm Manager 节点
docker swarm join --token <SWARM-TOKEN> <MANAGER-IP>:2377

手动加入 Swarm Worker 节点,后边我会讲解如何使用 Docker Machine 在集群上批量安装 Docker,并加入到 Worker 节点

# 在 Swarm Manager 节点执行
# 获取加入工作节点的 Swarm Token
docker swarm join-token -q worker

# 加入 Swarm Worker 节点
docker swarm join --token <SWARM-TOKEN> <MANAGER-IP>:2377

2.2. Keepalived

Keepalived(Keep Alive Daemon)是一个用于实现高可用性的开源工具,通常用于在 Linux 系统上提供服务的冗余。它通过将一个虚拟 IP 地址(Virtual IP,VIP)绑定到一个或多个服务器节点上,并使用 Virtual Router Redundancy Protocol(VRRP)或 Health Checking 策略来监测节点的健康状态,实现主备切换。

我们在3台 Docker Swarm 管理节点上都安装上 keppalived

# CentOS 需要安装 EPEL 存储库
yum install epel-release keepalived

Keepalived 的配置文件通常位于 /etc/keepalived/keepalived.conf。你需要编辑这个文件来配置虚拟 IP 地址、健康检查等参数。

# Keepalived 脚本定义,用于检查 Docker Swarm 状态
vrrp_script chk_swarm {
    script "/path/to/check_swarm.sh"  # 检查 Docker Swarm 状态的脚本路径
    interval 2  # 检查间隔,单位是秒
}

# Keepalived 实例配置
vrrp_instance VI_1 {
    state MASTER  # 初始状态为 MASTER,表示当前节点是主节点
    interface eth0  # 需要监控的网络接口
    virtual_router_id 51  # VRRP 虚拟路由器 ID,确保唯一
    priority 101  # 优先级,较高的节点将成为主节点
    advert_int 1  # VRRP 广播间隔,单位是秒
    authentication {
        auth_type PASS
        auth_pass your_password  # VRRP 认证密码
    }
    virtual_ipaddress {
        192.168.1.100  # 虚拟 IP 地址,Keepalived 将在主备切换时绑定到该地址
    }
    track_script {
        chk_swarm  # 使用 chk_swarm 脚本来检查 Docker Swarm 状态
    }
    # 在发生主备切换的时候,发送邮件通知
    notify_master "/path/to/notify.sh MASTER"
    notify_backup "/path/to/notify.sh BACKUP"

    # 以下是从节点需要注意的配置
    ## state BACKUP  # 初始状态为 BACKUP,表示当前节点是备份节点
    ## priority 100  # 优先级,较低的节点将成为备份节点,值越小优先级越低
    ## 注意:在从节点中,通常不需要设置虚拟 IP 地址,因为它会在主备切换时从主节点移动到备份节点
    ## 所以不需要虚拟 IP 地址,可以删除或注释掉 virtual_ipaddress 部分
}

/path/to/check_swarm.sh 脚本内容

#!/bin/bash

# Docker Swarm 状态检查脚本

SWARM_STATUS=$(docker info --format '{{.Swarm.LocalNodeState}}')

# 检查 Docker Swarm 是否处于活跃状态
if [ "$SWARM_STATUS" == "active" ]; then
    echo "Docker Swarm is healthy. Exiting with success code (0)."
    exit 0  # 代表脚本执行成功,Swarm处于活跃状态
else
    # 在切换时可能需要执行的一些操作,例如通知、记录日志等
    echo "Docker Swarm is not active. Taking necessary actions..."
    echo "Exiting with failure code (1)."
    exit 1  # 代表脚本执行失败,Swarm不处于活跃状态
fi

/path/to/notify.sh 脚本内容,仅作为示例展示,需根据自身情况做调整

#!/bin/bash

TO="email1@example.com,email2@example.com"
SUBJECT="Keepalived State Change"
BODY="<html><body><p>The Keepalived state has changed. New state: $1</p></body></html>"

echo "$BODY" | mail -a "Content-type: text/html;" -s "$SUBJECT" "$TO"

启动 Keepalived 服务

# 启动 Keepalived 服务
systemctl start keepalived
# 设置 Keepalived 为开机自启动
systemctl enable keepalived

2.3. NFS(网络文件系统)

所有需要使用到 nfs 文件系统的节点,都需要安装 nfs 服务

为了使集群中配置文件保持相同,可以使用 nfs 文件系统,安装方法参考我之前的文章:在服务器 CentOS 上部署 NFS(网络文件系统)

三、实战篇

3.1 创建 Nginx 服务

大多数时候我们都会使用 nginx 做反代,所以这里以创建2个副本的 nginx 为例。同时使用到 nfs 卷将多个实例的配置文件进行统一维护。

# 在NFS服务器上创建共享目录,这里假设共享根目录为 /nfs
# 在NFS服务器上,创建Nginx服务所需要映射的目录
mkdir -p /nfs/nginx/conf.d /nfs/nginx/html

# 在Docker节点上创建NFS卷
# 这个卷将在Swarm集群中的多个节点上共享
docker volume create --driver local \
  --opt type=nfs \
  --opt o=addr=nfs-server-ip,rw \   # nfs-server-ip 替换成nfs的ip
  --opt device=:/nfs \
  nfs-volume    # 自定义卷名称

# 在Swarm中创建Nginx服务
# 在 Docker Swarm 中默认使用的 ingress 网络,这是Swarm集群的内部网络,可以通过服务名称相互通信。
# 这个服务包括两个副本,并将NFS卷挂载到两个不同的目录中
docker service create --name nginx-service \
  --replicas 2 \
  --mount type=volume,source=nfs-volume,target=/mnt/nfs \
  --mount type=bind,source=/mnt/nfs/nginx/conf.d,target=/etc/nginx/conf.d \
  --mount type=bind,source=/mnt/nfs/nginx/html,target=/usr/share/nginx/html \
  --publish published=80,target=80 \
  --publish published=443,target=443 \
  nginx:latest

假设我现在要部署一个基于 my-image 镜像的新服务,并通过 nginx 进行反代 8080 端口。

# 创建一个新服务
docker service create --name my-image-service \
  --replicas 1 \
  --publish published=8080,target=8080 \
  my-image

# 创建 nginx 反代配置文件
# 文件路径:/nfs/nginx/conf.d/myimage.conf
server {
    listen 80;

    # 配置用于代理的域名或 IP 地址
    server_name example.com;

    # 配置反向代理规则,将请求代理到 myimage 服务的端口(8080)
    location / {
        proxy_pass http://my-image-service:8080; # 在 Docker Swarm 中默认使用的 ingress 网络,可以通过服务名称相互通信。

        # 配置一些反向代理相关的设置
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

# docker service update 命令可以更新服务的配置,而不会中断服务。
# 在重新创建服务期间,Swarm会逐步替换旧的容器。
docker service update --force nginx-service
分享到:
本文链接:https://blog.renzicu.com/2023/12/474.html
版权声明:本博客所有文章除特别声明外,均采用 CC BY 4.0 许可协议。转载请注明出处!
THE END
二维码
打赏
文章目录
关闭
目 录