如何使用大使模式在CoreOS上动态配置服务

来自菜鸟教程
跳转至:导航、​搜索

介绍

Docker 链接功能启用了一种动态配置容器之间网络连接的方法,称为 大使模式 。 大使模式促进了 providerconsumer 容器之间的服务可移植性。 在 CoreOS 中,可以利用 etcd 来实现分布在集群中多台机器上的大使模式。

在本教程中,我们将演示如何部署一个注册到 etcd 的 Apache HTTP 容器。 Apache 容器将代表我们的提供者容器,我们将使用 HAProxy 作为我们的消费者容器。 我们将使用来自 这个 CoreOS 大使演示 的 Docker 镜像作为我们的大使容器,我们将从头开始创建我们自己的 Apache 和 HAProxy Docker 镜像。

先决条件

您必须在 DigitalOcean 上有一个至少由三台机器组成的 CoreOS 集群。 以下是如何设置的教程:如何在 CoreOS 集群上创建和运行服务

您必须具备使用 CoreOS、etcdctl、fleetctl、设置服务和运行 Docker 容器的基本知识。 这些主题在 CoreOS 入门教程系列 中有介绍。

您必须拥有 Docker Hub 帐户或私有 Docker 注册表。 这在 How To Create and Run a Service on a CoreOS Cluster 教程的 Creating the Docker Container 部分中有介绍。

有关大使模式如何工作的完整详细信息,请查看来自 Docker 的通过大使容器 链接的 链接。 另外,请查看 CoreOS 博客上发布的这篇文章:Dynamic Docker links with an Ambassador by etcd

我们的目标

在本教程结束时,我们将在两台机器上运行六个容器。 本节将简要介绍每一项,以及如何将它们组合在一起。 这种确切的设置对大多数人来说没有用,但可以对其进行调整以允许对您自己的服务进行动态服务发现。

机器A

机器 A 将运行提供者容器,即 Apache Web 服务器,以及其他几个支持它的容器。

  • Apache Web 服务器:我们将从头开始创建的基本 Apache 容器,类似于 如何在 CoreOS 集群上创建和运行服务 教程中描述的容器。 这是我们的制作人
  • polvi/docker-register:一个注册容器,它将通过Docker API读取Apache的IP地址和端口并将其写入etcd
  • polvi/simple-amb:一个简单的大使容器,将流量转发到指定位置。 在这种情况下,我们会将流量转发到 etcd 并将其链接到 docker-register 容器,以提供该容器对 etcd 的访问。 在CoreOS中,由于etcd的位置是静态的,如果将docker-register修改为直接访问etcd可以去掉

机器 B

机器 B 是将运行消费者容器的 CoreOS 机器,即 HAProxy,以及主要的大使容器。

  • HAProxy Reverse Proxy:一个基本的 HAProxy 容器,我们将从头开始创建,它将代表我们的 consumer。 这将用于证明大使设置有效
  • polvi/dynamic-etcd-amb:主大使容器。 一个动态代理,它监视提供者容器的 IP 地址和端口的指定 etcd 键,并将所有流量路由到提供者容器。 可以更新key的值,代理会自己更新
  • polvi/simple-amb:在另一台机器上使用的相同容器,但用于将dynamic-etcd-amb链接到etcd

创建 Apache Docker 映像

SSH 到您的一台 CoreOS 机器,并传递您的 SSH 代理(替换为公共 IP 地址):

ssh -A core@coreos-1_public_IP

然后登录 Docker:

docker login

出现提示时输入您的 用户名 、密码和电子邮件地址。

接下来,创建一个新目录来将您的 Apache Dockerfile 写入:

mkdir -p ambassador/apache

现在切换到目录并打开Dockerfile进行编辑:

cd ambassador/apache
vi Dockerfile

基于 How To Create and Run a Service on a CoreOS Cluster 中的 Apache 容器设置,我们可以创建以下 Dockerfile(用您自己的 Docker 用户名替换 user_name):

FROM ubuntu:14.04
MAINTAINER user_name

RUN apt-get update && \
    DEBIAN_FRONTEND=noninteractive apt-get -y install apache2 && \
    echo "<h1>Running from Docker on CoreOS</h1>" > /var/www/html/index.html

EXPOSE 80

ENTRYPOINT ["/usr/sbin/apache2ctl"]
CMD ["-D", "FOREGROUND"]

保存并退出。

现在我们有了一个安装 Apache 并用基本消息替换 index.html 的 Dockerfile,构建您的 Docker 映像并使用以下命令将其命名为“apache”(替换您自己的用户名):

docker build --tag="user_name/apache" .

现在,为了让您的其他 CoreOS 机器可以使用该映像,使用以下命令将其 push 到您的 Docker 注册表:

docker push user_name/apache

现在您的 Apache 映像已经可以使用了。 让我们继续创建 HAProxy 映像。

创建 HAProxy Docker 映像

我们将基于 HAproxy Dockerfile 创建一个 HAProxy Docker 映像,用于可信的自动化 Docker 构建 。 我们将稍微修改提供的 haproxy.cfgstart.bash 文件。

ambassador 目录中,使用 git 克隆 HAProxy 存储库:

cd ~/ambassador
git clone https://github.com/dockerfile/haproxy.git

这将创建一个 haproxy 目录,其中包含 Dockerfilehaproxy.cfgstart.bash 文件。

Dockerfile 基本上安装了 HAProxy 并暴露了 80 和 443 端口,所以我们可以保持原样。

我们将修改 haproxy.cfg 文件以添加 frontendbackend。 打开haproxy.cfg进行编辑:

cd haproxy
vi haproxy.cfg

现在找到并删除以下行:

listen stats :80
  stats enable
  stats uri /

然后在文件末尾添加以下行:

frontend www-http
        bind :80
        default_backend www-backend

backend www-backend
        server apache private_ipv4:80 check

这将 HAProxy 配置为侦听端口 80 并将传入流量转发到由单个服务器组成的 www-backend。 当 HAProxy 容器启动时,我们将使用 start.bash 脚本将 private_ipv4 替换为该容器将在其上运行的 CoreOS 机器的私有 IP 地址。 我们的动态大使容器(HAProxy 会将流量转发到 Apache 容器)将在同一台机器上运行。

打开start.bash文件进行编辑:

vi start.bash

在文件的底部,您将找到将在此容器中启动 HAProxy 进程的行。 它看起来像这样:

haproxy -f /etc/haproxy/haproxy.cfg -p "$PIDFILE"

在此行的正上方,插入以下行:

# Set backend IP address to machine's private IP address
PRIVATE_IPV4=$(curl -sw "\n" http://169.254.169.254/metadata/v1/interfaces/private/0/ipv4/address)
sed -i -e "s/server apache private_ipv4:80 check/server apache ${PRIVATE_IPV4}:80 check/g" $HAPROXY/$CONFIG

保存并退出。 curl 命令将通过 DigitalOcean 元数据服务检索容器将在其上运行的机器的私有 IP 地址。 sed 命令将 haproxy.cfg 中的 private_ipv4 字符串替换为从元数据中检索到的实际 IP 地址。 该脚本从 HAProxy 容器内部运行,因此私有 IP 地址将在运行时配置。

现在我们已经准备好构建 HAProxy docker 镜像了。 使用以下命令构建您的 Docker 映像并将其命名为“haproxy”(替换您自己的用户名):

docker build --tag="user_name/haproxy" .

现在,为了让您的其他 CoreOS 机器可以使用该映像,使用以下命令将其 push 到您的 Docker 注册表:

docker push user_name/haproxy

您的 HAProxy 映像已准备好使用。 我们准备好编写我们的车队服务单元文件了!

车队服务单位文件

现在所有必需的 Docker 映像都可用于我们的 CoreOS 集群,让我们开始处理部署容器所需的文件。 因为我们使用的是 CoreOS 集群,所以我们可以从单个 CoreOS 机器创建和调度我们所有的队列服务单元文件。

我们将在之前创建的 ~/ambassador 目录中创建所有服务文件,因此现在切换到该目录:

cd ~/ambassador

阿帕奇服务

apache.service 单元将在 Host A 上运行。

我们将创建的第一个服务文件用于 Apache Web 服务器容器 user_name/apache。 现在打开一个名为 apache.service 的文件进行编辑:

vi apache.service

添加以下行(在两个地方替换您的 Docker 用户名):

[Unit]
Description=Apache web server service

[Service]
EnvironmentFile=/etc/environment
ExecStartPre=-/usr/bin/docker kill %n
ExecStartPre=-/usr/bin/docker rm %n
ExecStartPre=/usr/bin/docker pull user_name/apache
ExecStart=/usr/bin/docker run --rm --name %n -p ${COREOS_PRIVATE_IPV4}::80 user_name/apache
ExecStop=/usr/bin/docker stop -t 3 %n

保存并退出。 这是一个相当简单的服务文件,它以前台模式启动 Apache。 特别值得注意的是,我们将容器内的端口 80 绑定到专用网络接口 (-p ${COREOS_PRIVATE_IPV4}::80) 上的动态端口。

etcd-amb-apache.service

etcd-amb-apache.service 单元将在 Host A 上运行。

接下来,我们将要为我们的简单大使容器 (simple-amb) 创建一个服务文件,该文件将允许 Apache 注册容器访问 etcd。 现在打开一个名为 etcd-amb-apache.service 的文件:

vi etcd-amb-apache.service

添加以下行:

[Unit]
Description=Simple Apache ambassador
After=apache.service
BindsTo=apache.service

[Service]
ExecStartPre=-/usr/bin/docker kill %n
ExecStartPre=-/usr/bin/docker rm %n
ExecStart=/usr/bin/docker run --rm --name %n polvi/simple-amb 172.17.42.1:4001
ExecStop=/usr/bin/docker stop -t 3 %n

[X-Fleet]
X-ConditionMachineOf=apache.service

保存并退出。

simple-amb 容器将它在端口 10000 上接收到的所有流量转发到它启动时提供的参数,即 172.17.42.1:4001,即etcd在CoreOS中的标准位置。

X-ConditionMachineOf=apache.service 告诉 Fleet 将其安排在与 Apache 容器相同的机器上,这很关键,因为 docker-register 容器使用它来注册 Apache 使用的 IP 地址和端口到 [X206X ]。

apache-docker-reg.service

apache-docker-reg.service 单元将在 Host A 上运行。

让我们为我们的容器创建服务文件,该文件将在 etcddocker-register 中注册 Apache 的 IP 地址和端口。 现在打开一个名为 apache-docker-reg.service 的文件:

vi apache-docker-reg.service

插入以下行:

[Unit]
Description=Register Apache
After=etcd-amb-apache.service
BindsTo=etcd-amb-apache.service

[Service]
ExecStartPre=-/usr/bin/docker kill %n
ExecStartPre=-/usr/bin/docker rm %n
ExecStart=/usr/bin/docker run --link etcd-amb-apache.service:etcd -v /var/run/docker.sock:/var/run/docker.sock --rm polvi/docker-register apache.service 80 apache-A

[X-Fleet]
X-ConditionMachineOf=etcd-amb-apache.service

保存并退出。 以下是 docker run 命令值得注意的部分的细分:

  • --link etcd-amb-apache.service:etcd 将此容器链接到简单大使,它将用于将 Apache 的连接信息传递给 etcd
  • -v /var/run/docker.sock:/var/run/docker.sock 允许此容器通过它将运行的机器的 Docker API 确定 Apache 绑定到的动态端口。
  • apache.service 80 apache-A 将这些参数传递给容器。 前两个参数指定要查找的 docker 容器的名称和端口,第三个参数指定要写入的 etcd 键的名称。 该容器启动后,会将apache.service的动态端口和IP地址写入/services/apache-A/apache.service键。

X-ConditionMachineOf=etcd-amb-apache.service 告诉 Fleet 将其安排在与简单大使容器相同的机器上,这很关键,因为它们与 Docker 链接链接,以便为注册容器提供查找 etcd 的方法。

etcd-amb-apache2.service

etcd-amb-apache2.service 单元将在 Host B 上运行。

为我们的第二个简单大使容器 (simple-amb) 创建一个服务文件,该文件将允许动态大使容器访问 etcd。 现在打开一个名为 etcd-amb-apache2.service 的文件:

vi etcd-amb-apache2.service

添加以下行:

[Unit]
Description=Simple Apache ambassador 2

[Service]
ExecStartPre=-/usr/bin/docker kill %n
ExecStartPre=-/usr/bin/docker rm %n
ExecStart=/usr/bin/docker run --rm --name %n polvi/simple-amb 172.17.42.1:4001
ExecStop=/usr/bin/docker stop -t 3 %n

[X-Fleet]
X-Conflicts=apache.service

保存并退出。

这与 etcd-amb-apache.service 几乎相同的服务文件,除了 X-Conflicts=apache.service 告诉 Fleet 将其安排在与 Apache 容器不同的机器上,它将用于将动态大使链接到 etcd

apache-dyn-amb.service

apache-dyn-amb.service 单元将在 Host B 上运行。

为我们的动态大使容器 (dynamic-etd-amb) 创建一个服务文件,该文件将允许动态大使容器访问 etcd。 现在打开一个名为 apache-dyn-amb.service 的文件:

vi apache-dyn-amb.service

添加以下行:

[Unit]
Description=Dynamic ambassador for Apache
After=etcd-amb-apache2.service
BindsTo=etcd-amb-apache2.service

[Service]
EnvironmentFile=/etc/environment
ExecStartPre=-/usr/bin/docker kill %n
ExecStartPre=-/usr/bin/docker rm %n
ExecStartPre=/usr/bin/docker pull polvi/dynamic-etcd-amb
ExecStart=/usr/bin/docker run --link etcd-amb-apache2.service:etcd --rm --name %n -p ${COREOS_PRIVATE_IPV4}:80:80 polvi/dynamic-etcd-amb apache-A 80
ExecStop=/usr/bin/docker stop -t 3 %n

[X-Fleet]
X-ConditionMachineOf=etcd-amb-apache2.service

保存并退出。 以下是 docker run 命令值得注意的部分的细分:

  • --link etcd-amb-apache2.service:etcd 将此容器链接到第二个简单大使,它将用于从 etcd 检索 Apache 的连接信息
  • -p ${COREOS_PRIVATE_IPV4}:80:80 暴露容器上的 80 端口和机器的私有网络接口
  • apache-A 80 是指定端口 80 流量的两个参数(即 专用网络接口上的端口 80)应代理到在 etcd 中注册为 apache-A 的服务

X-ConditionMachineOf=etcd-amb-apache2.service 告诉 Fleet 将其安排在与第二个简单大使容器相同的机器上,这很关键,因为它们与 Docker 链接链接,以便为动态大使容器提供查找 etcd 的方法。

haproxy.service

haproxy.service 单元将在 Host B 上运行。

为我们的 HAProxy 容器 (haproxy) 创建一个服务文件,该文件将用于通过动态大使容器连接到 Apache 容器。 现在打开一个名为 haproxy.service 的文件:

vi haproxy.service

添加以下行(在两个地方替换您的 Docker 用户名):

[Unit]
Description=HAProxy consumer

[Service]
EnvironmentFile=/etc/environment
ExecStartPre=-/usr/bin/docker kill %n
ExecStartPre=-/usr/bin/docker rm %n
ExecStartPre=/usr/bin/docker pull user_name/haproxy
ExecStart=/usr/bin/docker run --name %n -p ${COREOS_PUBLIC_IPV4}:80:80 user_name/haproxy
ExecStop=/usr/bin/docker stop -t 3 %n

[X-Fleet]
X-ConditionMachineOf=apache-dyn-amb.service

保存并退出。 这是一个简单的服务文件,它启动 HAProxy 并在其主机的公共 IP 地址上公开端口 80。 请记住,后端服务器将在端口 80 上配置为主机的私有 IP 地址,这恰好是动态大使正在侦听代理到 Apache 服务的流量的地方。

X-ConditionMachineOf=apache-dyn-amb.service 告诉 Fleet 将其安排在与动态大使容器相同的机器上,这很重要,因为动态大使为 HAProxy 容器提供了到达 Apache 容器的路由。

随舰队部署

现在我们拥有了所有必要的车队服务文件,我们终于可以部署我们的大使设置了。 在包含所有服务文件的目录中,运行以下命令:

fleetctl start apache.service
fleetctl start etcd-amb-apache.service
fleetctl start apache-docker-reg.service
fleetctl start etcd-amb-apache2.service
fleetctl start apache-dyn-amb.service
fleetctl start haproxy.service

您应该会看到消息说每个服务都已加载。 要检查您的舰队单位的状态,请运行以下命令:

fleetctl list-units

您应该会看到类似于以下内容的输出:

UNIT                       MACHINE                      ACTIVE   SUB
apache-docker-reg.service  ceb3ead2.../10.132.233.107   active   running
apache-dyn-amb.service     3ce87ca7.../10.132.233.106   active   running
apache.service             ceb3ead2.../10.132.233.107   active   running
etcd-amb-apache.service    ceb3ead2.../10.132.233.107   active   running
etcd-amb-apache2.service   3ce87ca7.../10.132.233.106   active   running
haproxy.service            3ce87ca7.../10.132.233.106   active   running

所有状态应为 activerunning。 另一件需要注意的是,“机器 A”单元应该在同一台机器上,而“机器 B”单元应该在不同的机器上——只需查看每个单元的 IP 地址即可确认这一点。

测试您的设置

确保 HAProxy 可以访问 Apache

因为我们没有指定 HAProxy 容器应该在特定的机器上运行,所以我们需要找到它在哪里运行。 一个简单的方法是使用 fleetctl ssh 命令:

fleetctl ssh haproxy.service

这会将您连接到运行 haproxy.service 容器的机器。 现在您可以使用 /etc/environment 文件获取运行 HAProxy 的 CoreOS 机器的公共 IP 地址:

. /etc/environment
echo $COREOS_PUBLIC_IPV4

获取生成的 IP 地址并使用 Web 浏览器访问它。 您将看到以下图像:

请注意,您正在访问 HAProxy,而 HAProxy 正在通过动态大使代理访问 Apache。

现在您可以退出当前的 SSH 会话以返回原始 SSH 会话:

exit

测试故障转移

现在您已确认大使设置工作正常,让我们看看当提供程序服务 (apache.service) 更改其 IP 地址和端口时会发生什么。

使用 fleetctl 连接到正在运行 apache.service 的机器:

fleetctl ssh apache.service

现在重新启动运行 Apache 的机器:

sudo reboot

注意: 如果 apache.service 正在您最初通过 SSH 连接的机器上运行,您将被断开连接。 如果是这种情况,只需通过 SSH 连接到同一 CoreOS 集群中的另一台机器。

现在等一下,检查哪些单元正在运行:

fleetctl list-units

根据您等待的时间,您可能会看到与“主机 A”相关的三个单元(apache.serviceetcd-amb-apache.serviceapache-docker-reg.service)正在重新启动或处于活动状态。 最终,它们都应该回到 active 状态。 一旦他们这样做了,请注意他们现在在与以前不同的机器上运行。

现在返回连接到 HAProxy 的 Web 浏览器,然后点击刷新。 您应该会看到与之前相同的测试页面,表明 HAProxy 仍然能够通过动态大使连接到 Apache!

结论

现在您已经设置了自己的大使模式,您应该能够将本教程中介绍的概念应用到您自己的服务中。 这是一种在运行时配置消费者服务的独特方式,它允许您轻松地在机器之间移动后端提供者服务。 在更现实的设置中,您可能会用一个或多个应用程序容器替换 Apache 服务,并且您可能会为 HAProxy 配置多个后端服务器(或使用完全不同的消费者服务)。