项目描述
实现一个高可用的负载均衡的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 |
项目步骤
- 规划设计整个集群的架构,前端使用nginx做负载均衡,采用keepalived实现高可用,后端使用swarm来实现负载均衡和高可用;
- 后端采用swarm来管理整个docker集群,每个docker宿主机需要启动10个容器,总共启动40个容器来提供web服务;
- 制作自己的nginx容器的镜像,定制nginx.conf的内容,编译安装nginx,指定参数(安装路径、https、状态统计等配置);
- 使用nfs服务为所有的docker节点提供相同的web数据,实现数据一致性。在所有的docker宿主机上创建使用nfs服务器的数据卷,然后所有的docker nginx容器使用此数据卷,实现所有的容器使用相同的数据卷;
- 排错和故障解决,整理项目文档。
具体操作
准备工作
修改主机名,便于区分。
# 临时修改 hostname xxx # 永久修改 hostnamectl set-hostname xxx
配置静态ip
systemctl stop NetworkManager systemctl disable NetworkManager vim /etc/sysconfig/network-script/ifcfg-ens33 service network restart
关闭防火墙和selinux
service firewalld stop systemctl disable firewalld.service setenforce 0 sed -i "s/SELINUX=enforcing/SELINUX=disabled/" /etc/selinux/config
配置负载均衡
-
下载安装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
-
修改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实现高可用
-
在两台做负载均衡的机器上安装keepalived
yum install keepalived -y # 启动服务 service keepalived start # 设置开机自启 systemctl enable keepalived
-
修改配置文件/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修改为BACKUP
、priority修改为101(比MASTER小就行)
-
刷新服务
service keepalived restart
搭建swarm集群
-
在四台docker节点上安装docker
yum install docker -y # 启动服务 service docker start # 设置开机自启 systemctl enable docker
-
在四台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
-
在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 ~]#
-
-
验证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用于实现不同机器之间的文件共享。
-
配置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,输出详情 -
配置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
-
定制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
-
在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
-
网络问题,在生成镜像时,依赖下载不下来。