基于docker swarm的搭建高可用web集群

项目描述

实现一个高可用的负载均衡的web服务器集群,底层采用swarm管理的docker集群来提供web服务,大量使用容器来完成web服务的扩展性、高可用性。

拓扑结构

项目环境

环境配置 参数
Docker Docker version 1.13.1, build 64e9980/1.13.1
OS CentOS Linux release 7.8.2003 (Core) (7台)
nginx(负载均衡器) nginx/1.16.1
Keepalived Keepalived v1.3.5 (03/19,2017)
nginx nginx/1.19.0
load-balancer-1 ens33: 192.168.0.121
load-balancer-2 ens33: 192.168.0.122
swarm-manager 192.168.0.101
swarm-2 192.168.0.102
swarm-3 192.168.0.103
swarm-4 192.168.0.104
nfs server 192.168.0.105

项目步骤

  1. 规划设计整个集群的架构,前端使用nginx做负载均衡,采用keepalived实现高可用,后端使用swarm来实现负载均衡和高可用;
  2. 后端采用swarm来管理整个docker集群,每个docker宿主机需要启动10个容器,总共启动40个容器来提供web服务;
  3. 制作自己的nginx容器的镜像,定制nginx.conf的内容,编译安装nginx,指定参数(安装路径、https、状态统计等配置);
  4. 使用nfs服务为所有的docker节点提供相同的web数据,实现数据一致性。在所有的docker宿主机上创建使用nfs服务器的数据卷,然后所有的docker nginx容器使用此数据卷,实现所有的容器使用相同的数据卷;
  5. 排错和故障解决,整理项目文档。

具体操作

准备工作

  1. 修改主机名,便于区分。

    # 临时修改
    hostname xxx
    
    # 永久修改
    hostnamectl set-hostname xxx
    
  2. 配置静态ip

    systemctl stop NetworkManager
    systemctl disable NetworkManager
    
    vim /etc/sysconfig/network-script/ifcfg-ens33
    
    service network restart
    
  3. 关闭防火墙和selinux

     service firewalld stop
     systemctl disable firewalld.service
     setenforce 0
     sed -i "s/SELINUX=enforcing/SELINUX=disabled/" /etc/selinux/config
    

配置负载均衡

  1. 下载安装nginx

    yum install epel-release -y
    yum install nginx -y
    
    # 启动服务
    nginx
    # 设置nginx开机自启
    echo 'nginx' >> /etc/rc.d/rc.local
    chmod +x /etc/rc.d/rc.local
    
  2. 修改nginx配置定义负载均衡器

    # 定义负载均衡器
        upstream mylb1{
            server 192.168.0.131;
            server 192.168.0.132;
            server 192.168.0.133;
            server 192.168.0.134;
        }
    
        server {
            listen       80 default_server;
            listen       [::]:80 default_server;
            server_name  _;
            root         /usr/share/nginx/html;
    		
    		...
    
    		# 添加负载均衡的使用
            location / {
                    proxy_pass http://mylb1;
            }
            
            ...
        }
    

keepalived实现高可用

  1. 在两台做负载均衡的机器上安装keepalived

    yum install keepalived -y
    
    # 启动服务
    service keepalived start
    # 设置开机自启
    systemctl enable keepalived
    
  2. 修改配置文件/etc/keepalived/keepalived.conf启用VRRP协议

    virtual_server及后面全部删掉

    global_defs {
    	...
    	# 将下面这行注释掉。
    	vrrp_strict
    	...
    }
    
    vrrp_instance VI_1 {
    	state MASTER
    	interface ens33
    	virtual_router_id 51
    	priority 99
    	advert_int 1
    	authentication {
    		auth_type PASS
    		auth_pass 1111
    	}
    	virtual_ipaddress {
    		192.168.0.136
    	}
    }
    

    另一台也如上修改配置,稍有不同的是state MASTER修改为BACKUPpriority修改为101(比MASTER小就行)

  3. 刷新服务

    service keepalived restart
    

搭建swarm集群

  1. 在四台docker节点上安装docker

    yum install docker -y
    
    # 启动服务
    service docker start
    # 设置开机自启
    systemctl enable docker
    
  2. 在四台docker节点上配置/etc/hosts文件,修改ip和域名的记录,内容如下。

    127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
    ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
    192.168.0.101 swarm-manager
    192.168.0.102 swarm-2
    192.168.0.103 swarm-3
    192.168.0.104 swarm-4
    
  3. 在swarm-manager上创建swarm集群,然后添加节点

    [root@swarm-manager ~]# docker swarm init --advertise-addr 192.168.0.101
    Swarm initialized: current node (czi8ny7odir7hiu84r25f0h92) is now a manager.
    
    To add a worker to this swarm, run the following command:
    
        docker swarm join 
        --token SWMTKN-1-1a7esyutfqeeuub4ztfmzf74uv55zsvhe47xi3tgnz7w2esl1y-d3vtqw592lypiexfgk0527s9h 
        192.168.0.101:2377
    
    To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
    
    [root@swarm-manager ~]# 
    

    输入命令后的输出显示当前节点已经加入swarm集群,成为swarm集群的一个manager,并提供了添加worker节点的方式。

    在其余几台待用作worker节点的机器上执行添加节点命令。

    [root@swarm-2 ~]# docker swarm join 
    >     --token SWMTKN-1-1a7esyutfqeeuub4ztfmzf74uv55zsvhe47xi3tgnz7w2esl1y-d3vtqw592lypiexfgk0527s9h 
    >     192.168.0.101:2377
    This node joined a swarm as a worker.
    [root@swarm-2 ~]# 
    
    [root@swarm-3 ~]# docker swarm join 
    >     --token SWMTKN-1-1a7esyutfqeeuub4ztfmzf74uv55zsvhe47xi3tgnz7w2esl1y-d3vtqw592lypiexfgk0527s9h 
    >     192.168.0.101:2377
    This node joined a swarm as a worker.
    [root@swarm-3 ~]# 
    
    [root@swarm-4 ~]# docker swarm join 
    >     --token SWMTKN-1-1a7esyutfqeeuub4ztfmzf74uv55zsvhe47xi3tgnz7w2esl1y-d3vtqw592lypiexfgk0527s9h 
    >     192.168.0.101:2377
    Error response from daemon: This node is already part of a swarm. Use "docker swarm leave" to leave this swarm and join another one.
    [root@swarm-4 ~]# 
    

    几条命令

    • docker info 显示 docker 系统信息,可以查看集群信息

    • docker swarm leave -f 退出集群,-f 强制

    • docker node ls 在manager节点上查看集群中的机器及状态(我只是临时修改主机名,所以这里显示的还是默认主机名)

      [root@swarm-manager ~]# docker node ls
      ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
      6knoty95gqux8lzd6qb3bd423    swarm-4   Ready   Active        
      czi8ny7odir7hiu84r25f0h92 *  swarm-manager   Ready   Active        Leader
      gzuczyy7vf91kq9an9tfn34r0    swarm-3   Ready   Active        
      ogsujfhe8erbfpka3rl3qdmlb    swarm-2   Ready   Active        
      [root@swarm-manager ~]# 
      

    这时候一个swarm集群已经搭建起来了,自动的创建了一个Overlay网络,多个容器之间通过Overlay网络进行通信。

    [root@swarm-manager ~]# docker network ls
    NETWORK ID          NAME                DRIVER              SCOPE
    719f75aee18c        bridge              bridge              local
    ef1f2df1c727        docker_gwbridge     bridge              local
    ff329dbafde9        host                host                local
    jrbmwuddnbzi        ingress             overlay             swarm
    fa67605df455        none                null                local
    [root@swarm-manager ~]# 
    

    可以自定义一个Overlay网络。

    [root@swarm-manager ~]# docker network create -d overlay nginx_net
    wg2edv8o98jg848br9er063vo
    [root@swarm-manager ~]# 
    
  4. 验证swarm集群——部署服务

    # 创建了一个具有20个副本(--replicas 20 )的nginx服务,使用镜像nginx。
    # 这个命令执行后会自动下载容器镜像。
    [root@swarm-manager ~]# docker service create --replicas 20 --network nginx_net --name mynginx -p 80:80 nginx
    

搭建nfs服务

nfs用于实现不同机器之间的文件共享。

  1. 配置NFS-SERVER

    [root@nfs-server ~]# yum install nfs-utils -y
    
    # 启动nfs服务
    [root@nfs-server ~]# service nfs-server start
    Redirecting to /bin/systemctl start nfs-server.service
    # 设置开机自启
    [root@nfs-server ~]# systemctl enable nfs-server
    
    # /etc/exports是nfs默认的配置文件
    # rw:可读写
    # ro: 只读
    [root@nfs-server ~]# vim /etc/exports
    /web 192.168.0.0(rw,all_squash,sync)
    
    # 创建/web目录并设置权限
    [root@nfs-server ~]# mkdir /web
    [root@nfs-server ~]# chmod 777 /web
    
    # 导出目录
    [root@nfs-server ~]# exportfs -rv
    exporting 192.168.0.0:/web
    [root@nfs-server ~]# 
    

    rw:可读写
    ro: 只读
    no_root_squash:对root用户不压制,如果客户端以root用户写入,在服务端都映射为服务端的root用户
    root_squash: nfs服务:默认情况使用的是相反参数root_squash,
    如果客户端是用户root操作,会被压制成nobody用户
    all_squash: 不管客户端的使用nfs的用户是谁,都会压制成nobody用户
    insecure: 允许从客户端过来的非授权访问
    sync: 数据同步写入到内存和硬盘
    async: 数据先写入内存,不直接写入到硬盘
    anonuid: 指定uid的值,此uid必须存在于/etc/passwd中 --》 anonymous
    anongid:指定gid的值

    -r: Reexport all directories: 重新导出所有目录
    -v: verbose,输出详情

  2. 配置docker node。创建数据卷,在所有的docker worker节点上创建一样名字的数据卷执行nfs服务器的相同共享目录

    # 下载安装nfs并设置开机自启
    yum install nfs-utils -y
    systemctl enable nfs-server
    
    mkdir /con_web
    chmod 777 /con_web
    # 将docker node上的/con_web目录挂载到nfs服务器的/web上
    mount 192.168.0.105:/web  /con_web/
    
    # 创建数据卷
    docker volume create --driver local --opt type=nfs --opt o=addr=192.168.0.105,rw --opt device=:/web  mynginx
    
    # 验证
    docker volume inspect mynginx
    
  3. 定制nginx镜像,修改网页根目录,指定到/app目录

    mkdir mynginx
    cd mynginx
    
    vim Dockerfile
    

    Dockerfile文件内容如下:

    FROM docker.io/sglim2/centos7
    
    MAINTAINER Charramma
    
    WORKDIR /
    COPY nginx-1.19.0.tar.gz  /
    
    RUN yum install zlib zlib-devel openssl openssl-devel pcre pcre-devel gcc gcc-c++ autoconf automake make  -y 
        && tar xf nginx-1.19.0.tar.gz 
        && cd nginx-1.19.0 
        &&  ./configure  --prefix=/usr/local/nginx   --with-threads  --with-file-aio  --with-http_ssl_module  --with-http_stub_status_module  --with-stream  
        &&make -j 2 ; make install  
        && sed -i '44 c root /app ;' /usr/local/nginx/conf/nginx.conf
    
    ENV PATH /usr/local/nginx/sbin:$PATH
    EXPOSE 80
    STOPSIGNAL  SIGTERM
    ENTRYPOINT ["nginx"]
    
    CMD ["-g","daemon off;"]
    

    下载nginx包

    curl -O http://nginx.org/download/nginx-1.19.0.tar.gz
    

    生成镜像

    docker build -t my_nginx_app .
    

    导出镜像

    docker save -o my_nginx_app.tar my_nginx_app
    

    导入到其他节点上

    docker load -i my_nginx_app.tar
    
  4. 在manager节点上启动服务

    [root@swarm-manager ~]# docker service create --name ngs-my-nginx  --publish 80:80   --mount type=volume,source=mynginx,destination=/app  --replicas 40 my_nginx_app
    

遇到的问题

  • 生成镜像时,运行到编译安装一步时,报错。

    [Warning] IPv4 forwarding is disabled. Networking will not work.
    

    解决方法:

    echo 'net.ipv4.ip_forward=1' >> /usr/lib/sysctl.d/00-system.conf
    
  • 网络问题,在生成镜像时,依赖下载不下来。

原文地址:https://www.cnblogs.com/CharrammaBlog/p/13629159.html