使用容器技术快速搭建一个高可用服务集群。
应用栈具体结构

经典的 Web 高可用架构。由一个负载均衡代理容器,两个 Web 应用容器,和一个主从架构的数据库容器集群组成。使用容器技术,使你能够在资源有限的计算机上快速搭建实践一个高可用架构,提高学习效率 :>
准备工作
获取镜像
$ docker pull django
$ docker pull haproxy
$ docker pull redis
启动并互联容器栈节点
使用 --link
参数进行互联(现在这个参数已经成为 LEGACY
,官方推荐使用用户自定义 bridge
来替代它)。
# Boot the redis cluster.
$ docker run -it --name redis-master redis /bin/bash
$ docker run -it --name redis-slave1 --link redis-master:master redis /bin/bash
$ docker run -it --name redis-slave2 --link redis-master:master redis /bin/bash
# Boot the application cluster.
$ docker run -it --name APP1 --link redis-master:db -v /your/path/to/APP1:/usr/src/app django /bin/bash
$ docker run -it --name APP2 --link redis-master:db -v /your/path/to/APP2:/usr/src/app django /bin/bash
# Boot the HAProxy container.
$ docker run -it --name HAProxy --link APP1:APP1 --link APP2:APP2 -p 6301:6301 -v /your/path/to/HAProxy:/tmp haproxy /bin/bash
检查容器运行状态
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
54b9018f61e6 haproxy "/docker-entrypoint.…" 21 hours ago Up 21 hours 0.0.0.0:6301->6301/tcp HAProxy
b5bd8728af08 django "/bin/bash" 43 hours ago Up 43 hours APP2
7b9fdd342f3c django "/bin/bash" 43 hours ago Up 43 hours APP1
fb1c509d0245 redis "docker-entrypoint.s…" 43 hours ago Up 43 hours 6379/tcp redis-slave2
4b3284f6a268 redis "docker-entrypoint.s…" 43 hours ago Up 43 hours 6379/tcp redis-slave1
19419d882a8d redis "docker-entrypoint.s…" 43 hours ago Up 43 hours 6379/tcp redis-master
可见,一个 haproxy
容器,两个 django
容器和三个 redis
容器都在正常运行中。
配置工作
配置 Redis 集群
拷贝默认的 redis.conf
模板至容器的 /data
目录下,对于 redis-master
,我们需要修改模板中的这些参数:
# bind 127.0.0.1
protected-mode no
daemonize yes
pidfile /var/run/redis.pid
修改后在其目录下运行 redis
:
$ /usr/local/bin/redis-server redis.conf
对于从数据库 redis-slave1
和 redis-slave2
,我们需要修改模板中的这些参数:
daemonize yes
pidfile /var/run/redis.pid
slaveof master 6379
修改后在其目录下执行该命令运行 redis
:
# /usr/local/bin/redis-server redis.conf
Redis 节点测试
在 redis-master
, redis-slave1
和 redis-slave2
上分别启动 Redis
客户端程序:
# redis-cli
在 redis-master
上写入 <“master”, “19419d882a8d”> 的数据:
127.0.0.1:6379> set master 19419d882a8d
OK
尝试在 redis-master
上获取刚写入的 “master” 数据:
127.0.0.1:6379> get master
"19419d882a8d"
在 redis-slave1
和 redis-slave2
中获取 “master” 数据:
127.0.0.1:6379> get master
"19419d882a8d"
若能获取到则说明 Master 中的数据已经成功同步至 Slave 的数据库中,主从架构的 Redis 集群已经搭建好了。
配置应用集群
APP1
和APP2
这两个容器都需要进行配置。
首先安装 redis
的 Python SDK:
# pip install redis
在容器的 /usr/src/app
目录下创建 Django 应用:
# cd /usr/src/app/
# django-admin startproject redisweb
# cd redisweb/
# python manage.py startapp helloworld
新建好应用之后,可以在主机中挂载的目录 /your/path/to/APP1
进行编辑。
或是
/your/path/to/APP2
。
修改视图文件 redisweb/helloworld/views.py
:
from django.shortcuts import render
from django.http import HttpResponse
import redis
def hello(request):
str = redis.__file__
str += "<br>"
r = redis.Redis(host='db', port=6379, db=0)
info = r.info()
r.set('Hi', 'HelloWorld-APP1')
str += ("Get Hi: %s <br>" % r.get("Hi"))
str += ("Redis info: <br>")
str += ("Key: Info Value")
for key in info:
str += ("%s: %s <br>" % (key, info[key]))
return HttpResponse(str)
修改路由表 redisweb/redisweb/urls.py
:
from django.conf.urls import url
from django.contrib import admin
from helloworld.views import hello
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^helloworld$', hello),
]
修改 Django 应用设置,将 helloworld
应用加入 INSTALLED_APPS
中 :
# Line 33
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'helloworld',
]
修改完之上的文件之后,重新回到容器中,在目录 /usr/src/app/redisweb
下完成数据库的迁移:
# python manage.py makemigrations
# python manage.py migrate
为了使用 HAProxy
进行负载均衡的代理,我们将 APP1
的服务端口设为 8001
,APP2
的服务端口设为 8002
,根据这个配置来启动应用服务器:
# APP1
# python manage.py runserver 0.0.0.0:8001
# APP2
# python manage.py runserver 0.0.0.0:8002
可以通过应用服务容器的 IP 地址来尝试访问下服务,如果都能够访问,则应用服务器配置成功。
配置 HAProxy
最后我们需要配置 HAProxy
节点,它将作为我们的网关,直接对外进行服务并完成应用的负载均衡。
在 HAProxy
容器的挂载目录下新建 haproxy.cfg
配置文件:
global
log 127.0.0.1 local0
maxconn 4096
chroot /usr/local/sbin
daemon
nbproc 4
pidfile /usr/local/sbin/haproxy.pid
defaults
log 127.0.0.1 local3
mode http
option dontlognull
option redispatch
retries 2
maxconn 2000
balance roundrobin
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
listen redis_proxy
bind 0.0.0.0:6301
stats enable
stats uri /haproxy-stats
server APP1 APP1:8001 check inter 2000 rise 2 fall 5
server APP2 APP2:8002 check inter 2000 rise 2 fall 5
配置完后,在同目录下启动 HAProxy 服务:
# /usr/local/sbin/haproxy -f haproxy.cfg
大功告成
现在,通过 docker inspect
查看 HAProxy
容器的 IP,就可以在你喜欢的浏览器上看到我们刚才搭建的 Web 服务了!
查看 HAProxy
容器 IP:
$ HAPROXY_IP=$(docker inspect --format "{{ .NetworkSettings.IPAddress }}" HAProxy)
$ echo $HAPROXY_IP
访问 http://HAPROXY_IP/haproxy-stats
即为 HAProxy
的数据面板;http://HAPROXY_IP/helloworld
即为刚才我们所编写的应用!



Congratulations to yourself 🎉
本文大部分内容来自《Docker 容器与容器云(第2版)》的 2.3 章节,可能时间久远镜像更新,该书中部分操作无法重现,故写此博文将我的方法分享给各位,希望能够有所帮助。

本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。