如何使用Confd和ETCD动态重新配置服务在CoreOS

ETCD是一个全球分布式key-value存储是在CoreOS的安装使用。通过在这家商店注册服务,相关的应用程序可以根据提供的值来调整它们的配置。在本指南中,我们将演示如何配置`confd`监测`etcd`,以便动态生成Nginx的配置。 `的连续etcd`投票允许我们配置Nginx作为调整其后端服务器的列表,因为它们启动或停止负载平衡器。

介绍

CoreOS允许您在一组机器上轻松运行Docker容器中的服务。 这样做一般程序包括启动服务的一个或多个实例,然后注册每个实例etcd ,CoreOS的分布式key-value存储。 通过利用这种模式,相关服务可以获得关于基础设施的状态的有价值的信息,并且使用这些知识来通知他们自己的行为。这使得有可能对服务动态地配置自身每当显著etcd值的变化。 在本指南中,我们将讨论一个叫做工具confd ,这是专门制作的观赏分布式键值存储更改。它从Docker容器中运行,用于触发配置修改和服务重新加载。

先决条件和目标

为了完成本指南,您应该对CoreOS及其组件有基本的了解。在以前的指南中,我们设置了一个CoreOS集群,并熟悉了用于管理集群的一些工具。 以下是在开始阅读本文之前应该阅读的指南。我们将修改这些指南中描述的一些服务的行为,因此虽然了解材料很重要,但在使用本指南时应该重新开始: 此外,为了更熟悉我们将使用的一些管理工具,您需要阅读以下指南: “如何创建灵活的服务”指南对于本指南尤其重要,因为模板化的主要+ sidekick服务将作为我们将在本指南中设置的前端服务的基础。如前所述,虽然上面的指南讨论了Apache和sidekick服务的创建,但是本指南还有一些配置更改,使得从头开始更容易。我们将在本指南中创建这些服务的修改版本。 在本教程中,我们将重点介绍使用Nginx创建一个新的应用程序容器。这将作为对我们可以从我们的模板文件生成的各种Apache实例的反向代理。 nginx的容器将被配置confd观看服务注册,我们的搭档服务负责。 我们将从我们通过这个系列使用的相同的三个机器集群开始。
  • coreos-1
  • coreos-2
  • coreos-3
当您阅读完上述指南并让您的三个机器群集可用后,继续。

配置后端Apache服务

我们将开始设置我们的后端Apache服务。这将主要反映上一个指南的最后一部分,但我们将通过整个过程在这里,由于一些细微的差异。 登录到您的一台CoreOS机器以开始:
ssh -A core@ip_address

Apache容器设置

我们将从创建基本的Apache容器开始。这实际上与上一个指南相同,因此如果您的Docker Hub帐户中已有该映像,则不必再次执行此操作。我们将这个容器放在Ubuntu 14.04容器镜像之外。 我们可以通过键入下拉基本映像并启动容器实例:
docker run -i -t ubuntu:14.04 /bin/bash
你将会进入一个bash一旦容器启动会话。 从这里,我们就会更新本地apt包指数和安装apache2
apt-get update
apt-get install apache2 -y
我们还将设置默认页面:
echo "<h1>Running from Docker on CoreOS</h1>" > /var/www/html/index.html
我们现在可以退出容器,因为它处于我们需要的状态:
exit
通过键入以下内容登录或创建您的帐户:
docker login
您必须为您的Docker Hub帐户提供您的用户名,密码和电子邮件地址。 接下来,获取刚刚离开的实例的容器ID:
docker ps -l
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
1db0c9a40c0d        ubuntu:14.04        "/bin/bash"         2 minutes ago       Exited (0) 4 seconds ago                       jolly_pare
上面突出显示的字段是容器ID。复制您在自己的计算机上看到的输出。 现在,使用该容器ID,您的Docker Hub用户名和图像的名称进行提交。我们将在这里使用“apache”:
docker commit 1db0c9a40c0d user_name/apache
将您的新映像推送到Docker Hub:
docker push user_name/apache
现在可以在您的服务文件中使用此映像。

创建Apache服务模板单元文件

现在,你有一个容器可用,您可以创建一个模板单元文件,以便fleetsystemd可以正确地管理服务。 在我们开始之前,让我们设置一个目录结构,以便我们可以保持组织:
cd ~
mkdir static templates instances
现在,我们可以使我们在模板文件templates目录:
vim templates/apache@.service
将以下信息粘贴到文件中。您可以按照上一指南获取有关每个我们正在使用的选项的详细信息创建灵活的船队单元文件
[Unit]
Description=Apache web server service on port %i

# Requirements
Requires=etcd.service
Requires=docker.service
Requires=apache-discovery@%i.service

# Dependency ordering
After=etcd.service
After=docker.service
Before=apache-discovery@%i.service

[Service]
# Let processes take awhile to start up (for first run Docker containers)
TimeoutStartSec=0

# Change killmode from "control-group" to "none" to let Docker remove
# work correctly.
KillMode=none

# Get CoreOS environmental variables
EnvironmentFile=/etc/environment

# Pre-start and Start
## Directives with "=-" are allowed to fail without consequence
ExecStartPre=-/usr/bin/docker kill apache.%i
ExecStartPre=-/usr/bin/docker rm apache.%i
ExecStartPre=/usr/bin/docker pull user_name/apache
ExecStart=/usr/bin/docker run --name apache.%i -p ${COREOS_PRIVATE_IPV4}:%i:80 \
user_name/apache /usr/sbin/apache2ctl -D FOREGROUND

# Stop
ExecStop=/usr/bin/docker stop apache.%i

[X-Fleet]
# Don't schedule on the same machine as other Apache instances
Conflicts=apache@*.service
我们在这里做的一个修改是使用私人接口,而不是公共接口。由于所有我们的Apache实例将通过 Nginx的反向代理,而不是从开放的网络连接处理传递流量,这是一个好主意。记住,如果你使用DigitalOcean上的私有接口,你启动的服务器必须在创建时选择了“private networking”标志。 此外,请记住改变user_name引用您的Docker Hub的用户名,以便正确地拉下泊坞文件。

创建Sidekick模板单元文件

现在,我们将对sidekick服务执行相同操作。这一点,我们将稍微修改,以预期以后我们将需要的信息。 在编辑器中打开模板文件:
vim templates/apache-discovery@.service
我们将在此文件中使用以下信息:
[Unit]
Description=Apache web server on port %i etcd registration

# Requirements
Requires=etcd.service
Requires=apache@%i.service

# Dependency ordering and binding
After=etcd.service
After=apache@%i.service
BindsTo=apache@%i.service

[Service]

# Get CoreOS environmental variables
EnvironmentFile=/etc/environment

# Start
## Test whether service is accessible and then register useful information
ExecStart=/bin/bash -c '\
  while true; do \
    curl -f ${COREOS_PRIVATE_IPV4}:%i; \
    if [ $? -eq 0 ]; then \
      etcdctl set /services/apache/${COREOS_PRIVATE_IPV4} \'${COREOS_PRIVATE_IPV4}:%i\' --ttl 30; \
    else \
      etcdctl rm /services/apache/${COREOS_PRIVATE_IPV4}; \
    fi; \
    sleep 20; \
  done'

# Stop
ExecStop=/usr/bin/etcdctl rm /services/apache/${COREOS_PRIVATE_IPV4}

[X-Fleet]
# Schedule on the same machine as the associated Apache service
MachineOf=apache@%i.service
上述配置在几个方面与上一个指南中的不同。我们已经调整了设置的值etcdctl set命令。我们不是传递JSON对象,而是设置一个简单的IP地址+端口组合。这样,我们可以直接读取此值,以找到获取此服务所需的连接信息。 我们还调整了信息以指定私有接口,就像我们在其他文件中做的那样。如果您没有此选项可供选择,请将此选项设为公开。

实例化您的服务

现在,让我们创建这些服务的两个实例。 首先,让我们创建符号链接。移动到~/instances创建目录和链接来定义,他们将上运行的端口。我们想要在端口7777上运行一个服务,而在端口8888上运行另一个服务:
cd ~/instances
ln -s ../templates/apache@.service apache@7777.service
ln -s ../templates/apache@.service apache@8888.service
ln -s ../templates/apache-discovery@.service apache-discovery@7777.service
ln -s ../templates/apache-discovery@.service apache-discovery@8888.service
现在,我们可以通过将启动这些服务的~/instances目录fleet
fleetctl start ~/instances/*
在您的实例启动(这可能需要几分钟),你应该能够看到etcd你插袋的条目:
etcdctl ls --recursive /
/coreos.com
/coreos.com/updateengine
/coreos.com/updateengine/rebootlock
/coreos.com/updateengine/rebootlock/semaphore
/services
/services/apache
/services/apache/10.132.249.206
/services/apache/10.132.249.212
如果您要求这些条目中的一个的值,您可以看到您获得一个IP地址和端口号:
etcdctl get /services/apache/10.132.249.206
10.132.249.206:8888
您可以使用curl检索页面,并确保其功能正常。如果您将服务配置为使用专用网络,则此操作只能在您的计算机上工作:
curl 10.132.249.206:8888
<h1>Running from Docker on CoreOS</h1>
我们现在已经设置了后端基础设施。我们下一步是要熟悉confd这样我们就可以观看/services/apache的位置etcd更改,每次重新配置Nginx的。

创建Nginx容器

我们将从我们用于Apache服务的相同的Ubuntu 14.04基础启动Nginx容器。

安装软件

键入以下命令来启动新容器:
docker run -i -t ubuntu:14.04 /bin/bash
更新本地apt包缓存并安装Nginx的。 我们还需要安装curl由于基本图像不包括这一点,我们需要它来得到稳定的confd从GitHub包瞬间:
apt-get update
apt-get install nginx curl -y
现在,我们可以去发布页面confd在GitHub上在我们的浏览器。 我们需要找到到最新稳定版本的链接。 在写这篇文章的时候,那是v0.5.0 ,但这可能会有所改变。右键单击Linux版本工具的链接,然后选择“复制链接地址”或任何类似选项。 现在,回到你的Docker容器中,使用复制的URL下载应用程序。我们将在被把这个/usr/local/bin目录。 我们需要选择confd作为输出文件:
cd /usr/local/bin
curl -L https://github.com/kelseyhightower/confd/releases/download/v0.5.0/confd-0.5.0<^>-linux-amd64 -o confd
现在,使文件可执行,以便我们可以在我们的容器中使用它:
chmod +x confd
我们还应该利用这个机会来创建配置结构confd的期望。 这将是中/etc目录:
mkdir -p /etc/confd/{conf.d,templates}

创建Confd配置文件以读取Etcd值

现在,我们已经安装了我们的应用,我们应该开始配置confd 。我们将从创建配置文件或模板资源文件开始。 在配置文件中confd用于设置服务检查某些etcd值和检测到变化时发起行动。 这些使用TOML文件格式,它很容易使用和非常直观。 我们称为配置目录中中创建的文件开始nginx.toml
vi /etc/confd/conf.d/nginx.toml
我们将在这里建立我们的配置文件。添加以下信息:
[template]

# The name of the template that will be used to render the application's configuration file
# Confd will look in `/etc/conf.d/templates` for these files by default
src = "nginx.tmpl"

# The location to place the rendered configuration file
dest = "/etc/nginx/sites-enabled/app.conf"

# The etcd keys or directory to watch.  This is where the information to fill in
# the template will come from.
keys = [ "/services/apache" ]

# File ownership and mode information
owner = "root"
mode = "0644"

# These are the commands that will be used to check whether the rendered config is
# valid and to reload the actual service once the new config is in place
check_cmd = "/usr/sbin/nginx -t"
reload_cmd = "/usr/sbin/service nginx reload"
上面的文件有一些注释解释一些基本的想法,但我们可以去看下面的选项:
指示 需要? 类型 描述
src 将用于呈现信息的模板的名称。如果这是位于之外/etc/confd/templates ,则应该使用完整路径。
dest 应放置所呈现的配置文件的文件位置。
字符串数组 etcd该模板需要钥匙正确呈现。如果模板设置为处理子键,这可以是目录。
所有者 没有 将被赋予所呈现的配置文件所有权的用户名。
没有 将给予呈现的配置文件的组所有权的组。
模式 没有 应为已渲染的文件设置的八进制权限模式。
check_cmd 没有 应用于检查呈现的配置文件的语法的命令。
reload_cmd 没有 应用于重新加载应用程序配置的命令。
字首 没有 中的一部分etcd在按键之前出现层次keys指令。 这可以用来使.toml文件更灵活。
我们创建的文件告诉我们如何我们一些重要的事情confd实例都将发挥作用。 我们的Nginx容器将使用存储在模板/etc/confd/templates/nginx.conf.tmpl来呈现将被放置在一个配置文件/etc/nginx/sites-enabled/app.conf 。 该文件将被赋予的权限设置0644和所有权将给予root用户。 该confd应用程序将在更改/services/apache节点。 当的变化被看出, confd将查询该节点下的新的信息。然后它将为Nginx渲染一个新的配置。它将检查配置文件的语法错误,并在文件就位后重新加载Nginx服务。 我们现在已经创建了我们的模板资源文件。我们应该在实际的模板文件,将用于渲染我们的Nginx配置文件。

创建Confd模板文件

对于我们的模板文件中,我们将使用来自一个例子confd项目的GitHub的文件让我们开始。 创建我们在上面的配置文件中引用的文件。把这个文件在我们的templates目录:
vi /etc/confd/templates/nginx.tmpl
在这个文件中,我们基本上只是重新创建一个标准的Nginx反向代理配置文件。不过,我们会使用一些 Go 模板语法来代替一些该信息confd从拉etcd 。 首先,我们使用“上游”服务器配置块。此部分用于定义Nginx可以向其发送请求的服务器池。格式一般如下:
upstream pool_name {
    server server_1_IP:port_num;
    server server_2_IP:port_num;
    server server_3_IP:port_num;
}
这使我们可以通过请求到pool_name和Nginx的将选择定义的服务器之一到手的请求。 我们后面的模板文件的想法是解析etcd我们的Apache Web服务器的IP地址和端口号。 因此,不是静态定义我们的上游服务器,我们应该在文件呈现时动态填充此信息。 我们可以通过这样做 Go 模板的动态内容。 为此,我们将使用它作为我们的块:
upstream apache_pool {
{{ range getvs "/services/apache/*" }}
    server {{ . }};
{{ end }}
}
让我们解释一下发生了什么。我们已经开了一个块定义一个名为服务器的上游池apache_pool 。在里面,我们指定我们使用双括号开始一些Go语言代码。 这些括号内,我们指定etcd终点在哪里,我们感兴趣的是保存的值。 我们使用的range ,以使列表可迭代。 我们用它来传递所有从下面的检索项/services/apache的位置etcdrange块。 然后,我们可以使用表示插入值的“{{”和“}}”中的单个点在当前迭代中获取键的值。 我们在范围循环中使用它来填充服务器池。 最后,我们结束与循环{{ end }}指令。 注意 :请记住后添加分号server内环路指令。忘记这将导致非工作配置。 设置服务器池后,我们可以使用代理传递来指向所有连接到该池。这只是一个标准的服务器块作为反向代理。有一件事要注意的是access_log ,它采用,我们将暂时创建一个自定义格式:
upstream apache_pool {
{{ range getvs "/services/apache/*" }}
    server {{ . }};
{{ end }}
}

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    access_log /var/log/nginx/access.log upstreamlog;

    location / {
        proxy_pass http://apache_pool;
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
这将应用到所有连接响应端口80上并传递给服务器在泳池apache_pool是通过观察所生成的etcd条目。 当我们处理这个服务的这个方面,我们应该删除默认的Nginx配置文件,以便我们以后不会遇到冲突。我们将删除启用默认配置的符号链接:
rm /etc/nginx/sites-enabled/default
现在也是一个好时机来配置我们在模板文件中引用的日志格式。这必须在http的配置,这是可以在主配置文件中的块。立即打开:
vi /etc/nginx/nginx.conf
我们将添加一个log_format指令来定义我们要记录的信息。它将记录正在访问的客户端以及请求传递到的后端服务器。我们将记录这些程序需要的时间量的一些数据:
. . .
http {
    ##
    # Basic Settings
    ##
    log_format upstreamlog '[$time_local] $remote_addr passed to: $upstream_addr: $request Upstream Response Time: $upstream_response_time Request time: $request_time';

    sendfile on;
    . . .
保存并在完成后关闭文件。

创建脚本以运行Confd

我们需要创建一个脚本文件,将调用confd与我们的模板资源文件,我们在适当的时候模板文件。 脚本必须做两件事情,我们的服务才能正常工作:
  • 它必须在容器启动时运行,以根据后端基础架构的当前状态设置初始Nginx设置。
  • 它必须继续观察改变etcd注册为Apache服务器,以便它可以基于现有的后端服务器上重新配置Nginx的。
我们将得到我们的脚本马塞尔·德格拉夫的GitHub的页面 。 这是一个不错的,简单的脚本,不正是我们需要的。我们只会对我们的场景做一些小的编辑。 让我们把这个剧本与我们的confd可执行文件。 我们称这个confd-watch
vi /usr/local/bin/confd-watch
我们将开始与传统bash头,以确定我们所需要的解释。 然后,我们会设置一些bash ,这样脚本如果有什么不顺心立即失败选项。它将返回最后一个命令的值失败或运行。
#!/bin/bash

set -eo pipefail
接下来,我们要设置一些变量。通过使用bash参数替代,我们将设置默认值,但建立一定的灵活性,让调用脚本的时候我们覆盖硬编码值。这基本上只是独立地设置连接地址的每个组件,然后将它们组合在一起以获得所需的完整地址。 参数替换用此语法创建的: ${ var_name :- default_value } 这与使用的价值的财产var_name如果给出不为空,否则默认为default_value 。 我们默认为这些值etcd默认的期望。这将允许我们的脚本运行良好,没有额外的信息,但我们可以在调用脚本时根据需要进行自定义:
#!/bin/bash

set -eo pipefail

export ETCD_PORT=${ETCD_PORT:-4001}
export HOST_IP=${HOST_IP:-172.17.42.1}
export ETCD=$HOST_IP:$ETCD_PORT
现在我们将使用confd通过读取值呈现Nginx的配置文件的最初版本etcd时可用此脚本调用。 我们将使用until循环,不断尝试建立初始配置。 万一循环结构可能有必要etcd不可马上或在Nginx的容器在后端服务器之前联机的事件。 这使得它能够轮询etcd反复,直到它最终可以产生一个有效的初始配置。 实际confd我们曾经调用执行,并随后命令退出。 这是我们可以等待5秒,直到下一次运行给我们的后端服务器一个机会注册。 我们连接到全ETCD我们使用默认内置或参数传递变量,我们使用模板资源文件来定义什么,我们想要做的行为:
#!/bin/bash

set -eo pipefail

export ETCD_PORT=${ETCD_PORT:-4001}
export HOST_IP=${HOST_IP:-172.17.42.1}
export ETCD=$HOST_IP:$ETCD_PORT

echo "[nginx] booting container. ETCD: $ETCD"

# Try to make initial configuration every 5 seconds until successful
until confd -onetime -node $ETCD -config-file /etc/confd/conf.d/nginx.toml; do
    echo "[nginx] waiting for confd to create initial nginx configuration"
    sleep 5
done
在初始配置设置之后,我们脚本的下一个任务应该是建立一个持续轮询的机制。我们想确保检测到任何未来的更改,以便Nginx将被更新。 要做到这一点,我们可以调用confd一次。 这一次,我们要设置一个连续的轮询间隔,并将进程放在后台,使其无限期运行。 我们将通过在同一个etcd连接信息和相同的模板资源文件,因为我们的目标仍然是相同的。 把后confd加工成的背景下,我们可以使用被做了配置文件安全启动Nginx的。因为这个脚本将被称为我们的Docker“run”命令,所以我们需要保持它在前台运行,这样容器在这一点上不会退出。我们可以通过拖尾日志,让我们访问我们记录的所有信息:
#!/bin/bash

set -eo pipefail

export ETCD_PORT=${ETCD_PORT:-4001}
export HOST_IP=${HOST_IP:-172.17.42.1}
export ETCD=$HOST_IP:$ETCD_PORT

echo "[nginx] booting container. ETCD: $ETCD."

# Try to make initial configuration every 5 seconds until successful
until confd -onetime -node $ETCD -config-file /etc/confd/conf.d/nginx.toml; do
    echo "[nginx] waiting for confd to create initial nginx configuration."
    sleep 5
done

# Put a continual polling `confd` process into the background to watch
# for changes every 10 seconds
confd -interval 10 -node $ETCD -config-file /etc/confd/conf.d/nginx.toml &
echo "[nginx] confd is now monitoring etcd for changes..."

# Start the Nginx service using the generated config
echo "[nginx] starting nginx service..."
service nginx start

# Follow the logs to allow the script to continue running
tail -f /var/log/nginx/*.log
完成此操作后,保存并关闭文件。 我们需要做的最后一件事是使脚本可执行:
chmod +x /usr/local/bin/confd-watch
现在退出容器以返回到主机系统:
exit

提交并推送容器

现在,我们可以提交容器并将其推送到Docker Hub,以便它可用于我们的机器下拉。 查找容器ID:
docker ps -l
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                          PORTS               NAMES
de4f30617499        ubuntu:14.04        "/bin/bash"         22 hours ago        Exited (0) About a minute ago                       stupefied_albattani
突出显示的字符串是我们需要的容器ID。使用此ID提交容器以及您的Docker Hub用户名和您要用于此映像的名称。我们将在本指南中使用名称“nginx_lb”:
docker commit de4f30617499 user_name/nginx_lb
如有必要,请登录到Docker Hub帐户:
docker login
现在,您应该推送已提交的图片,以便其他主机可以根据需要将其拉下来:
docker push user_name/nginx_lb

构建Nginx静态单元文件

下一步是创建一个单元文件,启动我们刚刚创建的容器。这将让我们用fleet来控制进程。 因为这不会是一个模板,我们将放入~/static ,我们在这个目录的开头创建的目录:
vim static/nginx_lb.service
我们将开始与标准的[Unit]部分来描述服务,并定义的依赖关系和顺序:
[Unit]
Description=Nginx load balancer for web server backends

# Requirements
Requires=etcd.service
Requires=docker.service

# Dependency ordering
After=etcd.service
After=docker.service
接下来,我们需要定义[Service]文件的部分。我们将超时设置为零,并将killmode重新调整为none,就像我们对Apache服务文件所做的那样。我们将再次拉入环境文件,以便我们可以访问此容器正在运行的主机的公有和私有IP地址。 然后我们将清理我们的环境,以确保此容器的任何先前版本被杀死和删除。我们下拉我们刚刚创建的容器,以确保我们总是有最新的版本。 最后,我们将启动容器。这包括启动容器,给它我们在删除引用的名字和kill命令,并通过它正在运行的映射端口80的主机的公网IP地址我们称之为confd-watch ,我们写的脚本运行命令。
[Unit]
Description=Nginx load balancer for web server backends

# Requirements
Requires=etcd.service
Requires=docker.service

# Dependency ordering
After=etcd.service
After=docker.service

[Service]
# Let the process take awhile to start up (for first run Docker containers)
TimeoutStartSec=0

# Change killmode from "control-group" to "none" to let Docker remove
# work correctly.
KillMode=none

# Get CoreOS environmental variables
EnvironmentFile=/etc/environment

# Pre-start and Start
## Directives with "=-" are allowed to fail without consequence
ExecStartPre=-/usr/bin/docker kill nginx_lb
ExecStartPre=-/usr/bin/docker rm nginx_lb
ExecStartPre=/usr/bin/docker pull user_name/nginx_lb
ExecStart=/usr/bin/docker run --name nginx_lb -p ${COREOS_PUBLIC_IPV4}:80:80 \
user_name/nginx_lb /usr/local/bin/confd-watch
现在,所有我们需要理清的是停止命令和fleet调度方向。我们希望此容器仅在未运行其他负载平衡实例或后端Apache服务器的主机上启动。这将允许我们的服务有效地传播负载:
[Unit]
Description=Nginx load balancer for web server backends

# Requirements
Requires=etcd.service
Requires=docker.service

# Dependency ordering
After=etcd.service
After=docker.service

[Service]
# Let the process take awhile to start up (for first run Docker containers)
TimeoutStartSec=0

# Change killmode from "control-group" to "none" to let Docker remove
# work correctly.
KillMode=none

# Get CoreOS environmental variables
EnvironmentFile=/etc/environment

# Pre-start and Start
## Directives with "=-" are allowed to fail without consequence
ExecStartPre=-/usr/bin/docker kill nginx_lb
ExecStartPre=-/usr/bin/docker rm nginx_lb
ExecStartPre=/usr/bin/docker pull user_name/nginx_lb
ExecStart=/usr/bin/docker run --name nginx_lb -p ${COREOS_PUBLIC_IPV4}:80:80 \
user_name/nginx_lb /usr/local/bin/confd-watch

# Stop
ExecStop=/usr/bin/docker stop nginx_lb

[X-Fleet]
Conflicts=nginx.service
Conflicts=apache@*.service
保存并在完成后关闭文件。

运行Nginx负载均衡器

您应该已经有两个Apache实例从本教程的早期运行。您可以通过键入:
fleetctl list-units
UNIT                MACHINE             ACTIVE  SUB
apache-discovery@7777.service   197a1662.../10.132.249.206  active  running
apache-discovery@8888.service   04856ec4.../10.132.249.212  active  running
apache@7777.service     197a1662.../10.132.249.206  active  running
apache@8888.service     04856ec4.../10.132.249.212  active  running
您也可以仔细检查,他们正在用正确注册自己etcd通过键入:
etcdctl ls --recursive /services/apache
/services/apache/10.132.249.206
/services/apache/10.132.249.212
我们现在可以尝试启动我们的Nginx服务:
fleetctl start ~/static/nginx_lb.service
Unit nginx_lb.service launched on 96ec72cf.../10.132.248.177
根据图像下拉的时间长短,服务可能需要一分钟左右才能启动。它启动后,如果您检查与日志fleetctl journal命令,你应该能够看到一些日志信息confd 。它应该看起来像这样:
fleetctl journal nginx_lb.service
-- Logs begin at Mon 2014-09-15 14:54:05 UTC, end at Tue 2014-09-16 17:13:58 UTC. --
Sep 16 17:13:48 lala1 docker[15379]: 2014-09-16T17:13:48Z d7974a70e976 confd[14]: INFO Target config /etc/nginx/sites-enabled/app.conf out of sync
Sep 16 17:13:48 lala1 docker[15379]: 2014-09-16T17:13:48Z d7974a70e976 confd[14]: INFO Target config /etc/nginx/sites-enabled/app.conf has been updated
Sep 16 17:13:48 lala1 docker[15379]: [nginx] confd is monitoring etcd for changes...
Sep 16 17:13:48 lala1 docker[15379]: [nginx] starting nginx service...
Sep 16 17:13:48 lala1 docker[15379]: 2014-09-16T17:13:48Z d7974a70e976 confd[33]: INFO Target config /etc/nginx/sites-enabled/app.conf in sync
Sep 16 17:13:48 lala1 docker[15379]: ==> /var/log/nginx/access.log <==
Sep 16 17:13:48 lala1 docker[15379]: ==> /var/log/nginx/error.log <==
Sep 16 17:13:58 lala1 docker[15379]: 2014-09-16T17:13:58Z d7974a70e976 confd[33]: INFO /etc/nginx/sites-enabled/app.conf has md5sum a8517bfe0348e9215aa694f0b4b36c9b should be 33f42e3b7cc418f504237bea36c8a03e
Sep 16 17:13:58 lala1 docker[15379]: 2014-09-16T17:13:58Z d7974a70e976 confd[33]: INFO Target config /etc/nginx/sites-enabled/app.conf out of sync
Sep 16 17:13:58 lala1 docker[15379]: 2014-09-16T17:13:58Z d7974a70e976 confd[33]: INFO Target config /etc/nginx/sites-enabled/app.conf has been updated
正如你所看到的, confd看着etcd其初始配置。 然后,它开始nginx 。 之后,我们可以看到在线条etcd条目已经重新评估和新的配置文件进行。 如果新生成的文件不匹配md5sum代替文件,该文件被切换出,服务被重新装载。 这允许我们的负载均衡服务最终跟踪我们的Apache后端服务器。如果confd似乎不断更新,这可能是因为你的Apache实例往往令人耳目一新的TTL。您可以增加sidekick模板中的睡眠和TTL值,以避免这种情况。 在行动中看到负载平衡器,可以索要/etc/environments从运行Nginx的服务的主机文件。 它包含主机的公共IP地址。 如果你想使这个配置比较好,考虑运行与登记信息一搭档服务etcd ,就像我们为Apache的实例:
fleetctl ssh nginx_lb cat /etc/environment
COREOS_PRIVATE_IPV4=10.132.248.177
COREOS_PUBLIC_IPV4=104.131.16.222
现在,如果我们在浏览器中访问公共IPv4地址,我们应该看到我们在Apache实例中配置的页面: Apache索引页 现在,如果你在你的日志再看看,你应该能够看到信息,表示其后端服务器实际上是通过了要求:
fleetctl journal nginx_lb
. . .
Sep 16 18:04:38 lala1 docker[18079]: 2014-09-16T18:04:38Z 51c74658196c confd[28]: INFO Target config /etc/nginx/sites-enabled/app.conf in sync
Sep 16 18:04:48 lala1 docker[18079]: 2014-09-16T18:04:48Z 51c74658196c confd[28]: INFO Target config /etc/nginx/sites-enabled/app.conf in sync
Sep 16 18:04:48 lala1 docker[18079]: [16/Sep/2014:18:04:48 +0000] 108.29.37.206 passed to: 10.132.249.212:8888: GET / HTTP/1.1 Upstream Response Time: 0.003 Request time: 0.003

结论

正如你所看到的,也可以设置您的服务来检查etcd配置的详细信息。 像工具confd可以使这个过程变得相对通过允许显著项连续轮询简单。 在本指南中的例子中,我们配置了Nginx的服务来使用etcd生成其初始配置。我们还在后台设置它以连续检查更改。这与基于模板的动态配置生成相结合,使我们能够始终获得我们的后端服务器的最新图片。