基于docker swarm构建一套可以快速伸缩的应用系统。我们的系统并非是微服务架构,考虑到微服务需要的面对的挑战(分布式事务等)太多了,我们仅仅是多个单体服务,服务间的调用很少,服务间均衡负载使用docker的service实现。
可视化管理集群,网关统一输出API,日志统一处理,存储统一处理,网关流量监控,故障转移。
准备工作的内容需要为每台机器都执行一遍。
关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
安全起见,生产环境建议保留防火墙,只开放需要的端口。
修改DNS
vi /etc/resolv.conf
nameserver修改为114.114.114.114
修改Hostname
给每台机器重新设置一下hostname,node-1、node-2、…..node8
hostnamectl set-hostname node-1 --static
关闭selinux
vim /etc/selinux/config
#重启服务器
reboot
安装docker-ce
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
dnf install -y yum-utils device-mapper-persistent-data lvm2
dnf makecache
dnf install https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.6-3.3.el7.x86_64.rpm
# centos8默认自带podman,因此会冲突,需要加上参数自动替换
dnf install docker-ce docker-ce-cli --allowerasing
# 验证一下是否安装成功
docker version
# 开机自启
systemctl enable docker
修改docker配置文件
vim /etc/docker/daemon.json
配置内容:
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn"
"dns":["114.114.114.114"]
主要是加速docker镜像拉取。
管理节点必须是奇数个
172.16.113.4
172.16.113.5
172.16.113.6
172.16.113.7
172.16.113.8
172.16.113.9
172.16.113.10
172.16.113.11
172.16.113.12
初始化swarm集群
我们在172.16.113.4
上执行初始化命令
docker swarm init --listen-addr 0.0.0.0:2377 --cert-expiry 87600h0m0s --task-history-limit 1
然后我们在每个工作节点、运维节点、网关节点上运行
# 该命令在初始化完成后会打印在控制台中,后续也可以在管理节点上执行docker swarm join-token worker来获取
docker swarm join
然后我们在剩下的每个管理节点上运行
# 在管理节点上运行docker swarm join-token manager来获取
docker swarm join
# 在管理节点上,应该列出6个节点
docker node ls
部署Portainer-ce
Portainer我们不需要安装成集群,我们安装到运维节点上。
在运维节点上
docker network create \
--driver overlay \
--attachable \
--subnet 10.12.0.0/24 \
portainer_agent_network
安装portainer-ce
docker run -d \
-p 8000:8000 \
-p 9000:9000 \
--name=portainer \
--network=portainer_agent_network \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /data/portainer:/data \
portainer/portainer-ce
安装portainer-agent
docker service create \
--name portainer_agent \
--network portainer_agent_network \
--mode global \
--constraint 'node.platform.os == linux' \
--mount type=bind,src=//var/run/docker.sock,dst=/var/run/docker.sock \
--mount type=bind,src=//var/lib/docker/volumes,dst=/var/lib/docker/volumes \
portainer/agent
配置portainer-ce
用浏览器打开运维节点IP:9000
,登录完成后,如下配置即可。
部署traefik网关
创建应用网络
在管理节点上运行
docker network create \
--driver overlay \
--attachable \
--subnet 10.100.0.0/24 \
application_net
创建配置文件
[global]
checkNewVersion = true
sendAnonymousUsage = true
[entryPoints]
[entryPoints.web]
address = ":80"
[entryPoints.websecure]
address = ":443"
[log]
filePath = "log/traefik.log"
[accessLog]
filePath = "/log/log.txt"
[api]
insecure = true
dashboard = true
[ping]
[providers.docker]
swarmMode = true
endpoint = "ssh://root@172.16.113.4"
network = "application_net"
注意:配置文件中的endpoint应该任意2个管理节点的ip,这里利用ssh保障docker access api的安全。
SSH免密登录配置
每个管理节点都需要支持ssh免密登录,然后把公钥存放到网关节点上,这样网关节点就不需要密码就能ssh到管理节点上。免密登录的配置请自己查资料了。
创建traefik容器
在2台网关节点上都要运行,创建2个网关入口,以保障高可用(可以使用keepalived来实现vIP漂移)。
docker run -d -p 81:8080 -p 80:80 \
-v /data/traefik/conf/traefik.toml:/etc/traefik/traefik.toml \
--name=traefik \
--network=application_net \
-v /root/.ssh:/root/.ssh \
traefik:v2.4.8
到这一步,portainer上应该可以看到运行traefik的容器了。
这步很关键!(安装ssh)
目前traefik其实还没正确连接到swarm集群。ok!
我们在portainer上进入traefik的容器,然后运行
apk update
apk add openssh
等待安装完成后,traefik就能自动连接上swarm集群,至此集群和网关就搭建完成了。
这里使用nginx来充当应用。
在任何一台管理节点上运行
docker service create \
--replicas 10 \
--publish 8080:80 \
--network=application_net \
--label="traefik.http.routers.nginx-service.rule=Host(\`nb.io\`)" \
--label="traefik.http.services.nginx-service.loadbalancer.server.port=80" \
--name nginx nginx
Host
中的nb.io
实际应该换成自己的域名,没有域名自己想办法吧,可以使用docker镜像sameersbn/bind
搭建一个私有dns服务器。
等待完成后,我们可以在traefik的webUI上看到:
现在你可以访问nb.io
来访问nginx服务集群了。
约束应用部署的节点
现在在swarm集群中部署服务,服务的容器会跑到运维节点和网关节点,其实这不是我们想要的。
给节点打标签
在portainer的swarm菜单下为每个节点进行打标签,或者使用命令,该命令需要在管理节点执行
docker node update —label-add role=application node-1
docker node update —label-add role=application node-2
docker node update —label-add role=application node-3
docker node update —label-add role=application node-4
docker node update —label-add role=application node-5
docker node update —label-add role=application node-6
docker node update —label-add role=gateway node-7
docker node update —label-add role=gateway node-8
docker node update —label-add role=sys node-9
调整服务创建命令
docker service create \
现在应用服务只会部署在node-1到node-6
节点了。