使用 Docker、CoreOS、Mesos 部署可扩展的 Web 应用
【编者的话】本文作者重点介绍了如何使用 Docker、CoreOS、Mesos、Vulcand、对象存储来部署一个可扩展的 Web 应用,他首先介绍了 为什么要选择这些工具以及与其它工具相比这些工具的优势。紧接着,他通过实际案例演示了整个部署过程,图文并茂,推荐阅读。
介绍
让我们先来讨论一下为什么我决定使用这些软件来展示如何创建一个可扩展的 Web 基础架构。
为什么选择 Docker?
那问题来了,为啥要选择 Linux 容器?因为相比于虚拟机,Linux 容器拥有更低的计算和存储开销。
Docker 简化了人们使用 Linux 容器的方式,并且提供一些非常实用的特性,比如 Dockerfiles、Docker Hub、分层文件系统。在本文中,我将使用使用 Amazon S3 API 的 VIPR 搭建私有的 Docker Registry 以存储镜像(如我 以前的帖子 中描述)。
为什么选择 CoreOS?
所有的组件都会在 Docker 容器中运行,所以你可能会说,操作系统并没有那么重要。但是, CoreOS 有很多的优势,具体如下:
- 以一个单元的形式自动更新整个系统,而不是一个包接着一个包的更新(如果你的基础设施没有 SPOF,甚至要重启系统)
- 包含用于发现服务的 etcd,也使用 Vulcand(甚至设置中需要 mesos)
- 包含了 systemd 和 fleet,一个可以以一个 init 系统呈现你整个集群的工具。在这个设置中我不使用 fleet,但是在其它方面我有使用它,比如几秒内启动 elastic search 集群。
为什么选择 Vulcand?
我看到有关如何部署容器或虚拟机的很多教程,但我总是惊讶地看到,他们很少涉及基础设施的负载均衡部分。
在我看来,负载均衡是一个可扩展的 Web 应用架构的重要组成部分。如果用户不能正常访问你的应用,那还搞什么自动化?
Vulcand 是一个为 HTTP API 管理和微服务而设计的反向代理工具。Vulcand 会监控 etcd,并自动检测到它需要实现新的规则,所以你不需要重新加载任何服务。只需在 etcd 添加正确的密钥,然后你的服务/应用程序就可以被使用了。
为什么选择 Mesos?
有三种不同的方式来自动化部署 Docker 容器,具体如下:
- Fleet:Fleet 是一个通过 Systemd 对 CoreOS 集群进行控制和管理的工具。如果你想启动容器或者手动指定映射到主机的端口,那 Fleet 是一个不错的选择(译者注:Fleet 的更多资料可以阅读 本文 )。
- Kubernetes:这可能是最佳的选择之一,但现在 Kuernetes 还太年轻。
- Mesos:Mesos 目前已经支持 Docker,它已经是一个相对稳定的平台,并且可以用来部署其它软件,例如 Hadoop。
为什么选择对象存储?
我们可以通过上面介绍的软件来部署可扩展和高可用的应用。但是,数据怎么处理?
结构化的内容可能会被存储到分布式数据库中,例如 MongoDB。非结构化的内容一般会存储在一个本地文件系统、NAS 或者对象存储。
本地文件系统并不适合现在的场景,因为容器可能会被部署到集群的任何一个节点上。
理论上 NAS 共享 方案可行,但是特别复杂的。例如,NAS 共享需要挂载到所有的主机上,所以你需要为每个容器指定 Volume,并在特权模式下运行容器...当容器启动而 NAS 共享不可用时,容器内的应用程序需要能够处理相关问题。
然而,对象存储却可以在任何容器的任何应用中使用,并且是高可用的,因为我们使用了负载均衡器,它不需要任何配置,这也可以加快应用程序的开发周期。为什么了?因为开发者不需要考虑数据的存储方式、目录结构管理等。
我已经开发了一个 Web 应用程序,它展示了一个应用程序如何不通过数据路径处理上传和下载,我会在下面运行这个应用程序。
上图展示了几个不同的组件,以及我如何设置 3 个节点的 CoreOS 集群。
我使用 Keepalived 来确保公共 IP 10.64.231.84 是可用的,不管对应在 coreos1 还是 coreos3 节点上。
Vulcand 会运行再每个节点上,以均衡用户和 Web 应用程序之间的负载,同事也可以平衡应用程序和不同的 VIPR 节点。
私有的 Docker Registry 在 coreos1 节点上运行,并使用 Amazon S3 API 在 VIPR 上存储镜像。
Mesos 主节点(Master)和 Marathon 运行在 coreos2 节点上。
Demo
视频 可以点此链接浏览。
为我的 Web 应用程序创建 Docker 镜像
这里是我用来构建 Docker 镜像的 Dockerfile:
FROM golang WORKDIR / RUN git clone https://djannot:xxxx@github.com/djannot/s3pics.git WORKDIR /s3pics RUN go build EXPOSE 8080
构建镜像时我使用了--no-cache 参数,以确保最新的源代码是从 GitHub 上克隆的。
core@coreos1 /media/share1/Dockerfiles/s3pics $ docker build --no-cache . Sending build context to Docker daemon 2.048 kB Sending build context to Docker daemon Step 0 : FROM golang ---> 1ea210e0e1f6 Step 1 : WORKDIR / ---> Running in f6987b175723 ---> 022aa96f56d0 Removing intermediate container f6987b175723 Step 2 : RUN git clone https://djannot:xxxx@github.com/djannot/s3pics.git ---> Running in 54d6a32e90ba Cloning into 's3pics'... ---> 3369bca87577 Removing intermediate container 54d6a32e90ba Step 3 : WORKDIR /s3pics ---> Running in d875bc08eac9 ---> 73946142ea54 Removing intermediate container d875bc08eac9 Step 4 : RUN go build ---> Running in e0bd59c1f28b ---> baebdd1b633e Removing intermediate container e0bd59c1f28b Step 5 : EXPOSE 8080 ---> Running in 16d3fa9be1c5 ---> 815b7aed2c83 Removing intermediate container 16d3fa9be1c5 Successfully built 815b7aed2c83
最后,我推送镜像到 Docker registry。
core@coreos1 /media/share1/Dockerfiles/s3pics $ docker push 10.64.231.45:5000/s3pics:2.0 The push refers to a repository [10.64.231.45:5000/s3pics] (len: 1) Sending image list Pushing repository 10.64.231.45:5000/s3pics (1 tags) Image 511136ea3c5a already pushed, skipping Image 16386e29a1f4 already pushed, skipping Image 835c4d274060 already pushed, skipping Image 22c23ce0a90c already pushed, skipping Image 3f1e6432f26e already pushed, skipping Image 7982826b1e59 already pushed, skipping Image 1dafbd563f5a already pushed, skipping Image 7a94d87545e8 already pushed, skipping Image e2d60f7b3d07 already pushed, skipping Image 4f23222e2f74 already pushed, skipping Image 258b590ccdee already pushed, skipping Image 986643313a7b already pushed, skipping Image 1ea210e0e1f6 already pushed, skipping 022aa96f56d0: Image successfully pushed 3369bca87577: Image successfully pushed 73946142ea54: Image successfully pushed baebdd1b633e: Image successfully pushed 815b7aed2c83: Image successfully pushed Pushing tag for rev [815b7aed2c83] on {http://10.64.231.45:5000/v1/repositories/s3pics/tags/2.0}
我已经指定了一个 tag(2.0),以确保集群中的每个节点都会从 Docker Registry 获取最新版本。
部署 Mesos 应用程序
现在,让我们使用 Docker 镜像部署一个 Mesos 应用:
POST http://<Mesos Marathon IP>:8080/v2/apps { "id": "s3pics", "cmd": "cd /s3pics; ./s3pics -AccessKey=denis@ad.forest -SecretKey=xxxx -EndPoint=http://denisnamespace.ns.viprds.ad.forest -Namespace=denisnamespace", "cpus": 0.1, "mem": 64.0, "instances": 1, "container": { "type": "DOCKER", "docker": { "image": "10.64.231.45:5000/s3pics:2.0", "network": "BRIDGE", "portMappings": [ { "containerPort": 8080, "hostPort": 0, "protocol": "tcp" } ] } }, "healthChecks": [ { "protocol": "HTTP", "portIndex": 0, "path": "/", "gracePeriodSeconds": 10, "intervalSeconds": 20, "maxConsecutiveFailures": 3 } ] }
当 Mesos 应用程序启动后,Mesos Marathon UI 就会显示应用程序的状态。
几秒钟之后,应用部署成功,Docker 主机和端口显示在 UI 中。
访问 web 应用
使用在 Marathon UI 显示的信息,我可以访问 URL 为 http://coreos1.ad.forest:31000 的 Web 应用程序。
当应用程序运行时页面左上角会显示容器名称,用于上载和下载的图片的 Amazon S3 终端(endpoint)会显示在左下角,并表明 ViPR 用于存储数据。
我们现在可以上传图片了。
下面是由 Web 应用程序发送到浏览器的代码,以让浏览器直接上传图片到对象存储平台。
var files = $("#file")[0].files; var reader = new FileReader(); reader.onload = function(event){ var content = event.target.result; try { $.ajax({ url: 'http://bucket1.denisnamespace.ns.viprds.ad.forest:80/pictures/B6C3OuVCIAEfwjm.jpg', data: content, cache: false, processData: false, type: 'PUT', beforeSend: function (request) { request.setRequestHeader('Content-Length','35964'); request.setRequestHeader('Content-Type','binary/octet-stream'); request.setRequestHeader('x-amz-date','Sun, 11 Jan 2015 12:53:12 UTC'); request.setRequestHeader('host','bucket1.denisnamespace.ns.viprds.ad.forest'); request.setRequestHeader('Authorization','AWS denis@ad.forest:iCnahEUOy8/lanI96tQYA3WKQVE='); }, success: function(data, textStatus, request){ $('#alert-success').html("Picture uploaded").show().delay(5000).fadeOut(); }, error: function(data, textStatus, request){ $('#alert-danger').html("Upload failed").show().delay(5000).fadeOut(); } }); } catch (e) { alert(e); } } reader.readAsArrayBuffer(files[0]);
图片直接上传到对象存储平台的事实意味着该 Web 应用程序中并没有数据路径。也就是说无需部署数百个实例应用程序就可以扩展。
这个 Web 应用程序,也可用于显示所有存储在相应的 Amazon S3 的图片。
图片下方显示的 URL 表明图片可以直接从对象存储平台下载,而这又意味着 Web 应用程序不是从数据路径直接下载。
对象存储是事实上的标准网络规模应用。
更新 vulcand 代理
现在,让我们看看如何能够从外界访问该 Web 应用程序。
我使用 Golang 开发了一个小工具,同时使用 Marathon API 和 etcd API:
- 找到那些运行的 Mesos 应用程序但却没有相对应的在 etcd 中的 vulcand 规则,然后新建缺失的规则。
- 找到那些存在与 etdc 的 vulcand 规则中的不再运行的 Mesos 应用,然后删除。
Web 应用程序现在可以从外界访问。( http://s3pics.ad.fores t).
扩展 Mesos 应用程序
其中 Mesos 之美在于它能够轻松地扩展当前正在运行的应用程序的实例数目。
几秒钟后,20 个实例正在运行。
我需要再次运行我的工具来更新 vulcand 规则。
现在,如果我刷新我的网页浏览器,可以看到,在左上角显示的容器名称是基于服务的应用程序实例发生变化。
使用 Marathon UI 或 API 时,它也可以按比例缩小的实例数并再次运行工具来更新 vulcand 规则。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: 12 个最佳的免费网络监控工具
下一篇: 彻底找到 Tomcat 启动速度慢的元凶
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论