在阿里云上体验Docker 1.12的路由能力和容器应用分发部署

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: Docker 1.12除了提供内置的编排能力,也提供了服务路由支持 routing mesh,和新的多容器应用分发和部署机制, Docker Stack和Distributed Application Bundle

14680725458431

阿里云容器服务团队将为大家奉献一系列深入学习的文章来帮助大家了解Docker 1.12的最新动态。

简述

Docker 1.12除了提供内置的编排能力,也提供了服务路由支持 routing mesh,和新的多容器应用分发和部署机制。

这里我们先介绍两个概念

  • 分布式应用打包 (Distributed Application Bundle,简称DAB):DAB 是一个用于应用分发的文件格式,其中可以包含多个容器服务定义。
  • Stack(应用栈):可以从一个DAB文件创建一个应用栈实例,一个应用栈中包含多个服务实例。

如果你熟悉Docker Compose,这些概念听起来是不是很熟悉?一个Docker Compose模板中可以包含多个服务的描述,而利用Compose模板可以创建一个完整的应用。但是Docker Compose本身被设计成为面向单机的开发工具,并不能对分布式应用进行部署、管理。而DAB提供了一个标准化的分发格式解决了这个问题。另外Docker提供了工具,可以将一个已有Docker Compose模板转换成DAB格式,并部署为Docker Stack实例。

14680556259171

本文中,我们会部署一个WordPress DAB应用到阿里云上的Swarm模式Docker集群中,其中包含两个服务wordpress和mysql。我们还会利用阿里云 SLB实现wordpress任务容器的路由和负载均衡。

集群创建

首先我们先构建一个Docker Swarm模式集群,有两种方法一种是利用ROS资源编排模板一键创建一个Swarm集群,另一种方法则是我们前文介绍的利用Docker Machine手工创建完整的环境。为了加深理解,我们这次采用分解动作,使用第二种方法进行集群创建。

在这个环境中我们将创建一个三个ECS实例构成的Swarm集群,其中一个是manager。另外我们会创建一个SLB实例来实现服务的路由和负载均衡,集群中三个ECS实例都会作为SLB的后端服务器。我们会在集群上部署应用,并配置服务路由。大概的拓扑示意图如下:

14694976178970

首先我们创建一个SLB实例

14679813399994

SLB创建成功之后,我们利用docker-machine来创建三个ECS节点来组成Docker集群执行环境。

我们首先在命令行上配置一些共用的环境变量

export DEBUG=true 
export ECS_ACCESS_KEY_ID=<您的Access Key ID>
export ECS_ACCESS_KEY_SECRET=<您的Access Key Secret>
export ECS_REGION=cn-beijing
export ECS_ZONE=cn-beijing-b
export ECS_SSH_PASSWORD=<ECS实例SSH密码>
export ECS_UPGRADE_KERNEL=true
export MACHINE_DOCKER_INSTALL_URL= http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/experimental/intranet
export ENGINE_REGISTRY_MIRROR=https://6udu7vtl.mirror.aliyuncs.com
export ECS_SLB_ID=<您的SLB实例ID>

然后我们可以通过如下命令在阿里云上创建3个ECS实例,它还会自动升级操作系统内核,安装配置最新的测试版Docker引擎,并将新创建的SLB实例添加为指定SLB的后端服务器。

docker-machine create -d aliyunecs node-1
docker-machine create -d aliyunecs node-2
docker-machine create -d aliyunecs node-3

等待三个ECS实例会创建完成,我们可以通过如下命令登录到 node-1,初始化Docker Swarm集群,显示master节点的ECS内网"eth0"地址

docker-machine ssh node-1 ip addr show eth0
docker-machine ssh node-1 docker swarm init --advertise-addr <NODE1_IP>

上面的命令会返回如下内容

Swarm initialized: current node (xxxxxxx) is now a manager.

To add a worker to this swarm, run the following command:
    docker swarm join \
    --token SWMTKN-1-1xxxxxxx-xxxxxxx \
    10.xx.xx.xx:2377

To add a manager to this swarm, run the following command:
    docker swarm join \
    --token SWMTKN-1-1xxxxxxx-xxxxxxx \
    10.xx.xx.xx:2377

之后,我们把node-2和node-3作为worker加入Docker Swarm集群,执行docker-machine ssh <NODE> 之后拷贝上文返回的第一个命令来添加一个worker节点

docker-machine ssh node-2 docker swarm join --token <WORKER_TOKEN> <NODE1_IP>:2377
docker-machine ssh node-3 docker swarm join --token <WORKER_TOKEN> <NODE1_IP>:2377

这样整个Docker集群就已经创建成功了,现在我们来部署一个WordPress应用。

生成Distributed Application Bundle

注:这一节是为了介绍DAB的创建过程,心急的同学可以忽略。

本文使用Wordpress作为实例,其Docker Compose模板如下

version: '2'
services:
  wordpress:
    image: wordpress:4.5.3
    environment:
      - WORDPRESS_DB_PASSWORD=password
      - WORDPRESS_AUTH_KEY=changeme
      - WORDPRESS_SECURE_AUTH_KEY=changeme
      - WORDPRESS_LOGGED_IN_KEY=changeme
      - WORDPRESS_NONCE_KEY=changeme
      - WORDPRESS_AUTH_SALT=changeme
      - WORDPRESS_SECURE_AUTH_SALT=changeme
      - WORDPRESS_LOGGED_IN_SALT=changeme
      - WORDPRESS_NONCE_SALT=changeme
      - WORDPRESS_NONCE_AA=changeme
    ports:
      - 80:80
    restart: always
  mysql:
    image: mysql:5.7.13
    environment:
      - MYSQL_ROOT_PASSWORD=password
    restart: always

这里我们可以看到它包含两个服务"wordpress"和"mysql", 我们可以利用 docker-compose bundle 命令生成DAB格式文件。

yili@yili-mbp:~/work/docker-experimental/wordpress$ docker-compose bundle
WARNING: Unsupported key 'restart' in services.wordpress - ignoring
WARNING: Unsupported key 'restart' in services.mysql - ignoring
Wrote bundle to wordpress.dab

注:目前DAB/Docker Service/Stack的能力还不完备,有很多Docker Compose声明还不能被正确处理,比如volume支持等等。

产生的"wordpress.dab"文件内容如下

{
  "Services": {
    "mysql": {
      "Env": [
        "MYSQL_ROOT_PASSWORD=password"
      ], 
      "Image": "mysql@sha256:a9a5b559f8821fe73d58c3606c812d1c044868d42c63817fa5125fd9d8b7b539", 
      "Networks": [
        "default"
      ]
    }, 
    "wordpress": {
      "Env": [
        "WORDPRESS_AUTH_SALT=changeme", 
        "WORDPRESS_LOGGED_IN_KEY=changeme", 
        "WORDPRESS_AUTH_KEY=changeme", 
        "WORDPRESS_NONCE_AA=changeme", 
        "WORDPRESS_SECURE_AUTH_SALT=changeme", 
        "WORDPRESS_NONCE_KEY=changeme", 
        "WORDPRESS_DB_PASSWORD=password", 
        "WORDPRESS_LOGGED_IN_SALT=changeme", 
        "WORDPRESS_NONCE_SALT=changeme", 
        "WORDPRESS_SECURE_AUTH_KEY=changeme"
      ], 
      "Image": "wordpress@sha256:7bb9549fb6d80c230bec2da6bd181be8f30e5199687e53e5ad5744a3144eae1b", 
      "Networks": [
        "default"
      ], 
      "Ports": [
        {
          "Port": 80, 
          "Protocol": "tcp"
        }
      ]
    }
  }, 
  "Version": "0.1"
}

关于DAB格式的详细定义请参见官方文档注意:目前DAB依然是一个实验性质的特性,其格式可能会在未来进行调整。

创建Wordpress Stack

我们要登录到集群的master节点来部署应用,首先我们从Github上获取相应的示例文件

git clone https://github.com/denverdino/docker-experimental
cd docker-experimental/wordpress/

利用 docker deploy命令来部署"wordpress" stack,Docker命令缺省会在本目录寻找同名的.dab文件作为Stack部署描述。

root@node-1:~/docker-experimental/wordpress# docker deploy wordpress
Loading bundle from wordpress.dab
Creating network wordpress_default
Creating service wordpress_mysql
Creating service wordpress_wordpress

之后,我们可以利用docker service lsdocker stack tasks命令来查看相应service/task状态

root@node-1:~/docker-experimental/wordpress# docker service ls
ID            NAME                 REPLICAS  IMAGE                                                                              COMMAND
3p616th5ypgc  wordpress_wordpress  1/1       wordpress@sha256:7bb9549fb6d80c230bec2da6bd181be8f30e5199687e53e5ad5744a3144eae1b  
dzyof5wz1s5y  wordpress_mysql      1/1       mysql@sha256:a9a5b559f8821fe73d58c3606c812d1c044868d42c63817fa5125fd9d8b7b539      
root@node-1:~/docker-experimental/wordpress# docker stack tasks wordpress
ID                         NAME                   SERVICE              IMAGE                                                                              LAST STATE       DESIRED STATE  NODE
2d9bjq6htn7xbcweocy192ubx  wordpress_wordpress.1  wordpress_wordpress  wordpress@sha256:7bb9549fb6d80c230bec2da6bd181be8f30e5199687e53e5ad5744a3144eae1b  Running 1 hours  Running        node-2
b31ol0r0eow2b4a5ut684dofy  wordpress_mysql.1      wordpress_mysql      mysql@sha256:a9a5b559f8821fe73d58c3606c812d1c044868d42c63817fa5125fd9d8b7b539      Running 1 hours  Running        node-3

现在我们通过docker service inspect命令检查"wordpress_wordpress"服务状态

root@node-1:~# docker service inspect wordpress_wordpress
[
    {
        "ID": "3p616th5ypgcrfxfb4a9v44ew",
        "Version": {
            "Index": 498
        },
        "CreatedAt": "2016-07-09T07:43:25.368994849Z",
        "UpdatedAt": "2016-07-09T07:43:25.378275593Z",
        "Spec": {
            "Name": "wordpress_wordpress",
            "Labels": {
                "com.docker.stack.namespace": "wordpress"
            },
            "TaskTemplate": {
                "ContainerSpec": {
                    "Image": "wordpress@sha256:7bb9549fb6d80c230bec2da6bd181be8f30e5199687e53e5ad5744a3144eae1b",
                    "Env": [
                        "WORDPRESS_AUTH_SALT=changeme",
                        "WORDPRESS_LOGGED_IN_KEY=changeme",
                        "WORDPRESS_AUTH_KEY=changeme",
                        "WORDPRESS_NONCE_AA=changeme",
                        "WORDPRESS_SECURE_AUTH_SALT=changeme",
                        "WORDPRESS_NONCE_KEY=changeme",
                        "WORDPRESS_DB_PASSWORD=password",
                        "WORDPRESS_LOGGED_IN_SALT=changeme",
                        "WORDPRESS_NONCE_SALT=changeme",
                        "WORDPRESS_SECURE_AUTH_KEY=changeme"
                    ]
                }
            },
            "Mode": {
                "Replicated": {
                    "Replicas": 1
                }
            },
            "Networks": [
                {
                    "Target": "5cb3ojhzk5snap2s3nsjtexsf",
                    "Aliases": [
                        "wordpress"
                    ]
                }
            ],
            "EndpointSpec": {
                "Mode": "vip",
                "Ports": [
                    {
                        "Protocol": "tcp",
                        "TargetPort": 80
                    }
                ]
            }
        },
        "Endpoint": {
            "Spec": {
                "Mode": "vip",
                "Ports": [
                    {
                        "Protocol": "tcp",
                        "TargetPort": 80
                    }
                ]
            },
            "Ports": [
                {
                    "Protocol": "tcp",
                    "TargetPort": 80,
                    "PublishedPort": 30000
                }
            ],
            "VirtualIPs": [
                {
                    "NetworkID": "6qj71vtgeipenr838hbjt1ash",
                    "Addr": "10.255.0.6/16"
                },
                {
                    "NetworkID": "5cb3ojhzk5snap2s3nsjtexsf",
                    "Addr": "10.0.0.5/24"
                }
            ]
        }
    }
]

我们可以看到这个"wordpress_wordpress"服务发布了一个tcp端口“30000”来对外提供服务。那么我们怎么访问这个服务呢?

利用SLB创建服务路由

阿里云的SLB提供了对多台ECS服务器进行流量分发的负载均衡服务。下面我们将利用SLB服务来配置对Swarm集群中的服务的路由和负载均衡。

首先添加侦听端口,我们选择"http"和"8080"(可以任选)作为前端协议[端口], "http"和"30000"作为后端的协议[端口]。注意 :后端端口必须与服务状态中的"PublishedPort"端口值保持一致。

14680524171808

配置健康检查配置时,可以把“/license.txt”作为检查路径,这样只要wordpress服务的Apache可以被访问就认为服务是健康的

14680521587487

完成配置

14680519323177

随后,我们就会在SLB负载均衡实例上看到相应的侦听端口和健康检查状态

14680666664389

访问SLB实例的公网IP地址,我们就可以看到熟悉的Wordpress设置界面了,

14680523321519

我们还可以利用docker service scale命令对服务进行伸缩,也可以试验一下负载均衡的效果

root@node-1:~# docker service scale wordpress_wordpress=6
wordpress_wordpress scaled to 6
root@node-1:~# docker service ps wordpress_wordpress
ID                         NAME                   SERVICE              IMAGE                                                                              LAST STATE         DESIRED STATE  NODE
2d9bjq6htn7xbcweocy192ubx  wordpress_wordpress.1  wordpress_wordpress  wordpress@sha256:7bb9549fb6d80c230bec2da6bd181be8f30e5199687e53e5ad5744a3144eae1b  Running 1 hours    Running        node-2
8w2dsfyyjb9cjiiw3d4j0111h  wordpress_wordpress.2  wordpress_wordpress  wordpress@sha256:7bb9549fb6d80c230bec2da6bd181be8f30e5199687e53e5ad5744a3144eae1b  Running 2 minutes  Running        node-1
42ym2i9lic0bvg1763acdudwc  wordpress_wordpress.3  wordpress_wordpress  wordpress@sha256:7bb9549fb6d80c230bec2da6bd181be8f30e5199687e53e5ad5744a3144eae1b  Running 2 minutes  Running        node-1
6f33yfwbrpj9g601z2c2gs3qu  wordpress_wordpress.4  wordpress_wordpress  wordpress@sha256:7bb9549fb6d80c230bec2da6bd181be8f30e5199687e53e5ad5744a3144eae1b  Running 2 minutes  Running        node-3
6xxkek3t8dgg48zs5mjwrakg8  wordpress_wordpress.5  wordpress_wordpress  wordpress@sha256:7bb9549fb6d80c230bec2da6bd181be8f30e5199687e53e5ad5744a3144eae1b  Running 2 minutes  Running        node-2
5idxgssy8t439jgoj65d6g4ln  wordpress_wordpress.6  wordpress_wordpress  wordpress@sha256:7bb9549fb6d80c230bec2da6bd181be8f30e5199687e53e5ad5744a3144eae1b  Running 2 minutes  Running        node-2

Docker的Routing Mesh简析

看完上面的示例,大家一定非常关心相应服务和路由的网络配置。我们就来简单分析一下。在"node-1"节点上,我们执行下面的命令

root@node-1:~# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
29de61a371e7        bridge              bridge              local               
bdeb358293a3        docker_gwbridge     bridge              local               
78ee3e892931        host                host                local               
6qj71vtgeipe        ingress             overlay             swarm               
70d0aaba61cc        none                null                local               
5cb3ojhzk5sn        wordpress_default   overlay             swarm               

我们可以看到有两个集群范围的overlay网络"ingress"和"wordpress_default"。其中"ingress"是在集群创建之后就自动创建的接入路由网络,而后者是部署"wordpress.dab"的时候自动创建的。

如果没有手工指定,Swarm manager会自动给需要对外访问的服务分配一个在30000-32767之内的PublishedPort。在上文中"wordpress_wordpress"所分配的端口为30000。

在Swarm集群内的每个节点上,都侦听着相同的PublishedPort来为服务提供接入路由。所以我们可以在SLB上配置一个侦听端口对集群中节点进行转发和负载均衡,而不管后端节点是否运行着服务的任务容器。Swarm集群中的所有节点都可以通过ingress网络连接到运行的任务容器,并保证入口流量被引导到正确的容器实例上。

关于Routing mesh的Ingress网络的负载均衡,其设计如下图。我们可以看到每个服务实际上都被分配了一个虚拟IP,而虚拟IP到服务任务容器端口之间的负载均衡是通过IPVS来实现的。

注意:Routing mesh的端口映射机制和bridge网络下容器publish端口的实现完全不同,不要混淆。

14680691310281

我们可以通过下面的命令来看看iptables中ECS节点主机端口到服务虚拟IP的转发配置

root@node-1:~# iptables -L DOCKER-INGRESS -t nat
Chain DOCKER-INGRESS (2 references)
target     prot opt source               destination         
DNAT       tcp  --  anywhere             anywhere             tcp dpt:30000 to:172.18.0.2:30000
RETURN     all  --  anywhere             anywhere            

总结

Docker 1.12带来了新的分布式应用打包格式,可以给在集群上部署多容器应用带来很多便利。但是目前DAB的能力和成熟度都有待提高,和Docker Compose的兼容性也存在一些问题,希望会在未来版本中逐渐解决。

如果你了解阿里云容器服务,会发现很多新Swarm模式下的服务概念和我们实现有很多相似性。我们目前是通过对现有开源编排方案上做增强来提供类似的能力。比如我们扩展了Docker Compose中Service的概念,加强生命周期管理,提供服务伸缩和自动恢复支持等。不远的未来我们也会提供平滑的升级,支持Docker最新的编排技术。

在网络方面,Docker Swarm模式的routing mesh可以和外部的负载均衡技术结合。在阿里云上我们利用SLB实现了Docker服务路由和负载均衡。目前这个工作还需要一些手动工作来完成的,在稍后我们会推出全自动化的方式自动配置SLB监听端口,让整个流程完全自动化。

此外,我们可以看到Docker Swarm模式和阿里云容器服务的路由设计原理上是类似的,只是容器服务中每个节点利用HAProxy为服务提供7层或4层的路由实现,而Docker Engine是每个节点利用IPVS做为4层的路由实现。7层的优势在于可以支持virtual host、session affinity等较复杂的路由策略,而基于kernel空间的4层路由可以有更好的性能表现。我们计划会融合这些技术在阿里云容器服务中给大家带来更好的体验。

想了解更多容器服务内容,请访问 https://www.aliyun.com/product/containerservice

相关实践学习
巧用云服务器ECS制作节日贺卡
本场景带您体验如何在一台CentOS 7操作系统的ECS实例上,通过搭建web服务器,上传源码到web容器,制作节日贺卡网页。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
1月前
|
应用服务中间件 PHP nginx
今日小结通过aliyun的本地容器镜像部署我的nginx和php环境
简介: 本教程介绍如何基于 Dragonwell 的 Ubuntu 镜像创建一个运行 Nginx 的 Docker 容器。首先从阿里云容器镜像服务拉取基础镜像,然后编写 Dockerfile 确保 Nginx 作为主进程运行,并暴露 80 端口。最后,在包含 Dockerfile 的目录下构建自定义镜像并启动容器,确保 Nginx 在前台运行,避免容器启动后立即退出。通过 `docker build` 和 `docker run` 命令完成整个流程。
113 24
今日小结通过aliyun的本地容器镜像部署我的nginx和php环境
|
12天前
|
人工智能 Kubernetes jenkins
容器化AI模型的持续集成与持续交付(CI/CD):自动化模型更新与部署
在前几篇文章中,我们探讨了容器化AI模型的部署、监控、弹性伸缩及安全防护。为加速模型迭代以适应新数据和业务需求,需实现容器化AI模型的持续集成与持续交付(CI/CD)。CI/CD通过自动化构建、测试和部署流程,提高模型更新速度和质量,降低部署风险,增强团队协作。使用Jenkins和Kubernetes可构建高效CI/CD流水线,自动化模型开发和部署,确保环境一致性并提升整体效率。
|
2月前
|
数据库 Docker 容器
docker容器为啥会开机自启动
通过配置适当的重启策略,Docker容器可以在主机系统重启后自动启动。这对于保持关键服务的高可用性和自动恢复能力非常有用。选择适合的重启策略(如 `always`或 `unless-stopped`),可以确保应用程序在各种情况下保持运行。理解并配置这些策略是确保Docker容器化应用可靠性的关键。
282 93
|
2月前
|
Java Linux C语言
《docker基础篇:2.Docker安装》包括前提说明、Docker的基本组成、Docker平台架构图解(架构版)、安装步骤、阿里云镜像加速、永远的HelloWorld、底层原理
《docker基础篇:2.Docker安装》包括前提说明、Docker的基本组成、Docker平台架构图解(架构版)、安装步骤、阿里云镜像加速、永远的HelloWorld、底层原理
497 90
|
3天前
|
存储 测试技术 对象存储
使用容器服务ACK快速部署QwQ-32B模型并实现推理智能路由
阿里云最新发布的QwQ-32B模型,通过强化学习大幅度提升了模型推理能力。QwQ-32B模型拥有320亿参数,其性能可以与DeepSeek-R1 671B媲美。
|
7天前
|
安全 持续交付 云计算
课时5:阿里云容器服务:最原生的集成Docker和云服务
阿里云容器服务以服务化形式构建容器基础设施,大幅提升开发效率,简化应用部署流程。通过Docker容器和DevOps工具(如Jenkins),实现自动化部署与迭代,优化企业内部复杂部署问题。该服务支持GPU调度、混合云架构无缝迁移,并与阿里云产品体系无缝集成,提供安全防护、网络负载均衡等多重功能支持。凭借微服务架构,帮助企业突破业务瓶颈,提高资源利用率,轻松应对海量流量。
课时5:阿里云容器服务:最原生的集成Docker和云服务
|
12天前
|
机器学习/深度学习 人工智能 Kubernetes
容器化AI模型部署实战:从训练到推理
在上一篇中,我们探讨了AI技术如何赋能容器化生态。本篇聚焦于AI模型的容器化部署,通过图像分类任务实例,详细介绍了从模型训练到推理服务的完整流程。使用PyTorch训练CNN模型,Docker打包镜像,并借助Kubernetes进行编排和部署,最终通过FastAPI提供推理服务。容器化技术极大提升了AI模型部署的便利性和管理效率,未来将成为主流趋势。
|
27天前
|
网络协议 API Docker
Docker+consul容器服务的更新与发现
通过本文的介绍,我们详细探讨了如何结合Docker和Consul来实现容器服务的更新与发现。通过Consul的服务注册和发现功能,可以高效地管理和监控容器化服务,确保系统的高可用性和可扩展性。希望本文能帮助您在实际项目中更好地应用Docker和Consul,提高系统的可靠性和管理效率。
64 23
|
27天前
|
Ubuntu API 网络虚拟化
ubuntu22 编译安装docker,和docker容器方式安装 deepseek
本脚本适用于Ubuntu 22.04,主要功能包括编译安装Docker和安装DeepSeek模型。首先通过Apt源配置安装Docker,确保网络稳定(建议使用VPN)。接着下载并配置Docker二进制文件,创建Docker用户组并设置守护进程。随后拉取Debian 12镜像,安装系统必备工具,配置Ollama模型管理器,并最终部署和运行DeepSeek模型,提供API接口进行交互测试。
333 15
|
3月前
|
监控 NoSQL 时序数据库
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
340 78