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

介绍

CoreOS 允许您在多台机器中轻松地在 Docker 容器中运行服务. 这样做的过程通常涉及启动一个或多个服务实例,然后将每个实例注册到 CoreOS 的分布式关键值存储etcd

通过利用这种模式,相关服务可以获取有关基础设施状态的有价值信息,并利用这些知识来告知其自身行为,从而使服务能够在重要的etcd值发生变化时动态配置。

在本指南中,我们将讨论一个名为confd的工具,该工具专门用于监控分布式关键值存储的变化,它从Docker容器内部运行,用于触发配置更改和服务重新加载。

前提和目标

为了通过本指南工作,您应该对CoreOS及其组件有基本的了解. 在以前的指南中,我们设置了CoreOS集群并熟悉一些用于管理集群的工具。

下面是您在开始这篇文章之前应该阅读的指南,我们将修改这些指南中描述的一些服务的行为,因此虽然了解材料很重要,但您应该在使用本指南时重新开始:

此外,为了更熟悉我们将使用的一些管理工具,您希望通过这些指南:

如何创建灵活服务指南对于本指南尤为重要,因为模板主 + sidekick 服务将作为我们将在本指南中设置的前端服务的基础。

在本教程中,我们将专注于使用 Nginx 创建一个新的应用程序容器,这将作为我们可以从我们的模板文件中生成的各种 Apache 实例的反向代理。

我们将从我们在这个系列中使用的相同的三台机器集群开始。

  • coreos-1
  • coreos-2
  • coreos-3

当你完成阅读前面的指南,并有你的三个机器集群可用时,继续。

配置 Apache 后端服务

我们将从设置我们的后端Apache服务开始,这将主要反映上面的指南的最后一部分,但由于一些微妙的差异,我们将通过整个程序在这里运行。

登录您的 CoreOS 机器之一以启动:

1ssh -A core@ip_address

Apache 集装箱设置

我们将从创建基本的Apache容器开始,这实际上与上一个指南相同,所以如果您已经在您的Docker Hub帐户中拥有该图像,您不必再这样做。

我们可以拉下基础图像并通过键入启动一个容器实例:

1docker run -i -t ubuntu:14.04 /bin/bash

一旦容器启动,您将被放入一个bash会话中,从这里,我们将更新本地的apt包索引并安装apache2:

1apt-get update
2apt-get install apache2 -y

我们还会设置默认页面:

1echo "<h1>Running from Docker on CoreOS</h1>" > /var/www/html/index.html

我们现在可以离开容器,因为它处于我们需要的状态:

1exit

登录或创建您的 Docker Hub 帐户,键入:

1docker login

您需要为您的 Docker Hub 帐户提供您的用户名、密码和电子邮件地址。

接下来,获取您刚刚离开的实例的容器ID:

1docker ps -l
1CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
21db0c9a40c0d ubuntu:14.04        "/bin/bash"         2 minutes ago Exited (0) 4 seconds ago jolly_pare

上面突出的字段是容器 ID. 复制您在自己的计算机上看到的输出。

现在,使用该容器ID、您的Docker Hub用户名和图像的名称进行承诺,我们将在这里使用apache:

1docker commit 1db0c9a40c0d user_name/apache

将新图像推到 Docker Hub:

1docker push user_name/apache

现在可以在服务文件中使用此图像。

创建 Apache 服务模板单元文件

现在你有一个容器可用,你可以创建一个模板单元文件,以便fleetsystemd可以正确地管理服务。

在我们开始之前,让我们设置一个目录结构,以便我们可以保持组织:

1cd ~
2mkdir static templates instances

现在,我们可以在模板目录中创建我们的模板文件:

1vim templates/[email protected]

您可以通过遵循前面关于 创建灵活舰队单元文件的指南获取我们正在使用的每个选项的详细信息:

 1[Unit]
 2Description=Apache web server service on port %i
 3
 4# Requirements
 5Requires=etcd.service
 6Requires=docker.service
 7Requires=apache-discovery@%i.service
 8
 9# Dependency ordering
10After=etcd.service
11After=docker.service
12Before=apache-discovery@%i.service
13
14[Service]
15# Let processes take awhile to start up (for first run Docker containers)
16TimeoutStartSec=0
17
18# Change killmode from "control-group" to "none" to let Docker remove
19# work correctly.
20KillMode=none
21
22# Get CoreOS environmental variables
23EnvironmentFile=/etc/environment
24
25# Pre-start and Start
26## Directives with "=-" are allowed to fail without consequence
27ExecStartPre=-/usr/bin/docker kill apache.%i
28ExecStartPre=-/usr/bin/docker rm apache.%i
29ExecStartPre=/usr/bin/docker pull user_name/apache
30ExecStart=/usr/bin/docker run --name apache.%i -p ${COREOS_PRIVATE_IPV4}:%i:80 \
31user_name/apache /usr/sbin/apache2ctl -D FOREGROUND
32
33# Stop
34ExecStop=/usr/bin/docker stop apache.%i
35
36[X-Fleet]
37# Don't schedule on the same machine as other Apache instances
38Conflicts=apache@*.service

我们在这里做的一个修改是使用私人接口而不是公共接口. 由于我们所有的Apache实例都会通过流量 through Nginx反向代理代码而不是处理来自开放的网络的连接,这是一个好主意。

此外,请记住更改user_name以引用您的 Docker Hub 用户名,以便正确拖下 Docker 文件。

创建 Sidekick 模板单元文件

现在,我们将对 sidekick 服务做同样的事情,我们将稍微修改此服务,以预见我们以后需要的信息。

在您的编辑器中打开模板文件:

1vim templates/[email protected]

我们将在此文件中使用以下信息:

 1[Unit]
 2Description=Apache web server on port %i etcd registration
 3
 4# Requirements
 5Requires=etcd.service
 6Requires=apache@%i.service
 7
 8# Dependency ordering and binding
 9After=etcd.service
10After=apache@%i.service
11BindsTo=apache@%i.service
12
13[Service]
14
15# Get CoreOS environmental variables
16EnvironmentFile=/etc/environment
17
18# Start
19## Test whether service is accessible and then register useful information
20ExecStart=/bin/bash -c '\
21  while true; do \
22    curl -f ${COREOS_PRIVATE_IPV4}:%i; \
23    if [ $? -eq 0 ]; then \
24      etcdctl set /services/apache/${COREOS_PRIVATE_IPV4} \'${COREOS_PRIVATE_IPV4}:%i\' --ttl 30; \
25    else \
26      etcdctl rm /services/apache/${COREOS_PRIVATE_IPV4}; \
27    fi; \
28    sleep 20; \
29  done'
30
31# Stop
32ExecStop=/usr/bin/etcdctl rm /services/apache/${COREOS_PRIVATE_IPV4}
33
34[X-Fleet]
35# Schedule on the same machine as the associated Apache service
36MachineOf=apache@%i.service

上面的配置与前面指南中的配置有几种不同,我们已经调整了由etcdctl set命令设置的值,而不是传递一个JSON对象,我们正在设置一个简单的IP地址 +端口组合。

我们还调整了信息,以指定私人界面,就像我们在我们的其他文件中一样。

即时化您的服务

现在,让我们创建这些服务的两个实例。

首先,让我们创建符号链接。移动到您创建的~/instances目录并链接,以定义它们将运行在哪个端口上。

1cd ~/instances
2ln -s ../templates/[email protected] [email protected]
3ln -s ../templates/[email protected] [email protected]
4ln -s ../templates/[email protected] [email protected]
5ln -s ../templates/[email protected] [email protected]

现在,我们可以通过将~/instances目录转移到fleet来启动这些服务:

1fleetctl start ~/instances/*

您的实例启动后(这可能需要几分钟),您应该能够看到您的 sidekicks 创建的etcd条目:

1etcdctl ls --recursive /
1/coreos.com
2/coreos.com/updateengine
3/coreos.com/updateengine/rebootlock
4/coreos.com/updateengine/rebootlock/semaphore
5/services
6/services/apache
7/services/apache/10.132.249.206
8/services/apache/10.132.249.212

如果您询问这些条目中的一个值,您可以看到您得到一个IP地址和一个端口号:

1etcdctl get /services/apache/10.132.249.206
110.132.249.206:8888

您可以使用curl来获取页面并确保它正确运作,如果您配置了该服务以使用私人网络,则此功能只会从您的机器内部运作:

1curl 10.132.249.206:8888
1<h1>Running from Docker on CoreOS</h1>

我们的下一步是熟悉confd,以便我们可以在etcd中查看/services/apache位置进行更改,并每次重新配置 Nginx。

使用 Nginx 集装箱

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

安装软件

通过键入开始一个新的容器:

1docker run -i -t ubuntu:14.04 /bin/bash

更新您的本地apt包缓存并安装 Nginx. 我们还需要安装curl,因为基本图像不包括此,我们需要它来从GitHub获得稳定的confd包:

1apt-get update
2apt-get install nginx curl -y

现在,我们可以在我们的浏览器中访问 发布页面以便在GitHub上找到confd. 我们需要找到最新的稳定版本的链接. 在这篇文章写作时,它是 v0.5.0,但这可能已经改变了。右键单击工具的Linux版本的链接,然后选择复制链接地址或任何类似的选项。

现在,回到您的 Docker 容器中,使用复制的 URL 来下载应用程序. 我们将把这个放在 /usr/local/bin 目录中. 我们需要选择 confd 作为输出文件:

1cd /usr/local/bin
2curl -L https://github.com/kelseyhightower/confd/releases/download/v0.5.0/confd-0.5.0-linux-amd64 -o confd

现在,使该文件可执行,以便我们可以在我们的容器中使用它:

1chmod +x confd

我们也应该利用这个机会来创建confd所期望的配置结构。

1mkdir -p /etc/confd/{conf.d,templates}

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

现在我们已经安装了我们的应用程序,我们应该开始配置confd

confd中的配置文件用于设置服务,以检查某些etcd值,并在发现更改时启动操作,这些文件使用 TOML文件格式,这是易于使用和相当直观的。

首先,在我们的配置目录中创建一个名为nginx.toml的文件:

1vi /etc/confd/conf.d/nginx.toml

我们将在这里构建我们的配置文件. 添加以下信息:

 1[template]
 2
 3# The name of the template that will be used to render the application's configuration file
 4# Confd will look in `/etc/conf.d/templates` for these files by default
 5src = "nginx.tmpl"
 6
 7# The location to place the rendered configuration file
 8dest = "/etc/nginx/sites-enabled/app.conf"
 9
10# The etcd keys or directory to watch. This is where the information to fill in
11# the template will come from.
12keys = [ "/services/apache" ]
13
14# File ownership and mode information
15owner = "root"
16mode = "0644"
17
18# These are the commands that will be used to check whether the rendered config is
19# valid and to reload the actual service once the new config is in place
20check_cmd = "/usr/sbin/nginx -t"
21reload_cmd = "/usr/sbin/service nginx reload"

上面的文件有评论解释了一些基本的想法,但我们可以谈谈下面的选项:

需要指示吗? QQ 类型 QQ 描述 ___________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________ 如果位于/etc/confd/templates'之外,则应使用整个路径。 _ _ 已实现的配置文件应当放置的文件位置 。 _ _ _ 键 是 + 字符串 + 模板需要正确渲染的etcd' 键 。 如果模板是用来处理子密钥的,这可以成为目录. _ __%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% QQ QQ 前缀 QQ 字符串 QQ 等级法的一部分, 位于 指令中键前。 这可以用来使 ".toml " 文件更加灵活。 |

我们的 Nginx 容器将使用存储在 /etc/confd/templates/nginx.conf.tmpl 的模板来渲染一个配置文件,将放置在 /etc/nginx/sites-enabled/app.conf`。

「confd」應用程式會在「/services/apache」節點尋找變更。當看到變更時,「confd」會在該節點下尋找新的資訊,然後會為 Nginx 顯示新的配置。

我们现在已经创建了我们的模板资源文件,我们应该在实际的模板文件上工作,该文件将用于渲染我们的 Nginx 配置文件。

创建 Confd 模板文件

对于我们的模板文件,我们将使用一个例子从confd项目的 GitHub 文档让我们开始。

创建我们在上面的配置文件中提到的文件. 将此文件放入我们的模板目录:

1vi /etc/confd/templates/nginx.tmpl

在此文件中,我们基本上只是重新创建一个标准的 Nginx 反向代理配置文件,但是我们会使用一些 Go 模板语法来代替一些信息,而confd 正在从etcd中提取。

首先,我们将区块配置为上游服务器,此部分用于定义 Nginx 可以发送请求的服务器群。

1upstream pool_name {
2    server server_1_IP:port_num;
3    server server_2_IP:port_num;
4    server server_3_IP:port_num;
5}

这允许我们将请求传递到pool_name,Nginx将选择一个定义的服务器来传递请求。

我们的模板文件背后的想法是对我们的Apache Web 服务器的 IP 地址和端口号进行etcd分析,因此,而不是静态地定义我们的上游服务器,我们应该动态地填写此信息,当该文件被渲染时。

为了做到这一点,我们将使用这个作为我们的块:

1upstream apache_pool {
2{{ range getvs "/services/apache/*" }}
3    server {{ . }};
4{{ end }}
5}

我们打开了一个块来定义一个名为apache_pool的上游服务器组。

在这些支架中,我们指定了我们感兴趣的值被保留的etcd终端点,我们正在使用范围来使列表可重复。

我们使用此方法将从etcd中的/services/apache位置下方获取的所有条目传输到range块中,然后我们可以使用{{}}中的单个点来获取当前迭代中的密钥值,这表示已插入的值。

** 注意**:请记住在循环中添加服务器指令之后的半字符号。

设置服务器池后,我们可以简单地使用代理传输来将所有连接导向到该池. 这只会是一个标准的服务器块作为一个反向代理。 唯一要注意的是access_log,它使用了一个定制的格式,我们会暂时创建:

 1upstream apache_pool {
 2{{ range getvs "/services/apache/*" }}
 3    server {{ . }};
 4{{ end }}
 5}
 6
 7server {
 8    listen 80 default_server;
 9    listen [::]:80 default_server ipv6only=on;
10
11    access_log /var/log/nginx/access.log upstreamlog;
12
13    location / {
14        proxy_pass http://apache_pool;
15        proxy_redirect off;
16        proxy_set_header Host $host;
17        proxy_set_header X-Real-IP $remote_addr;
18        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
19    }
20}

这将响应在端口80上的所有连接,并将其传送到以apache_pool为中心的服务器群,该群通过查看etcd条目来生成。

虽然我们正在处理该服务的这一方面,我们应该删除默认的 Nginx 配置文件,这样我们以后就不会遇到冲突,我们只会删除允许默认配置的象征链接:

1rm /etc/nginx/sites-enabled/default

现在也是配置我们在模板文件中提到的日志格式的好时机. 这必须进入配置的http块,这是在主配置文件中可用的。

1vi /etc/nginx/nginx.conf

我们会添加一个log_format指令来定义我们想要登录的信息,它会登录正在访问的客户端以及请求传递给的后端服务器。

1. . .
2http {
3    ##
4    # Basic Settings
5    ##
6    log_format upstreamlog '[$time_local] $remote_addr passed to: $upstream_addr: $request Upstream Response Time: $upstream_response_time Request time: $request_time';
7
8    sendfile on;
9    . . .

保存并关闭文件,当你完成。

创建一个脚本来运行 Confd

我们需要创建一个脚本文件,在适当的时间与我们的模板资源文件和我们的模板文件一起调用confd

脚本必须做两件事,使我们的服务正常工作:

  • 它必须在容器启动时运行,以根据后端基础设施的当前状态设置初始的 Nginx 设置。
  • 它必须继续监视 Apache 服务器的 etcd 注册的更改,以便根据可用的后端服务器重新配置 Nginx。

我们将从Marcel de Graaf的GitHub页面(https://github.com/marceldegraaf/blog-coreos-1/blob/master/nginx/boot.sh)获取我们的脚本。

让我们把这个脚本放在我们的confd可执行的旁边,我们将称之为confd-watch:

1vi /usr/local/bin/confd-watch

我们将从常规的bash头开始,以识别我们需要的解释器,然后我们将设置一些bash选项,以便脚本立即失败,如果有什么不对劲,它将返回最后一个命令失败或运行的值。

1#!/bin/bash
2
3set -eo pipefail

接下来,我们想设置一些变量. 通过使用bash参数替换,我们将设置默认值,但构建一些灵活性,使我们在调用脚本时超出硬编码的值. 这基本上只会独立设置连接地址的每个组件,然后将它们组合在一起以获得所需的完整地址。

参数替换是用以下语法创建的: ${var_name:-default_value}. 这具有使用 var_name' 值的属性,如果它是给定的,而不是 null,否则默认为 `default_value'。

默认情况下,我们正在对etcd预期的值进行默认设置,这将允许我们的脚本在没有额外信息的情况下正常工作,但在调用脚本时我们可以根据需要进行定制:

1#!/bin/bash
2
3set -eo pipefail
4
5export ETCD_PORT=${ETCD_PORT:-4001}
6export HOST_IP=${HOST_IP:-172.17.42.1}
7export ETCD=$HOST_IP:$ETCD_PORT

我们现在将使用confd来渲染 Nginx 配置文件的初始版本,通过读取这个脚本被调用时可用的etcd中的值。

如果etcd不立即可用,或如果 Nginx 容器在后端服务器之前被带到线,则可能需要进行循环构造,从而允许它反复对etcd进行调查,直到它能够最终产生有效的初始配置。

我们正在调用的实际confd命令执行一次,然后退出,这样我们就可以等待5秒,直到下一个运行,以便给我们的后端服务器一个注册的机会。

 1#!/bin/bash
 2
 3set -eo pipefail
 4
 5export ETCD_PORT=${ETCD_PORT:-4001}
 6export HOST_IP=${HOST_IP:-172.17.42.1}
 7export ETCD=$HOST_IP:$ETCD_PORT
 8
 9echo "[nginx] booting container. ETCD: $ETCD"
10
11# Try to make initial configuration every 5 seconds until successful
12until confd -onetime -node $ETCD -config-file /etc/confd/conf.d/nginx.toml; do
13    echo "[nginx] waiting for confd to create initial nginx configuration"
14    sleep 5
15done

设置初始配置后,我们脚本的下一个任务应该是建立一个持续投票机制,我们希望确保未来的任何更改都被检测到,以便 Nginx 得到更新。

要做到这一点,我们可以再次呼叫confd。这次,我们要设置一个连续的投票间隔,并将过程放置在背景中,以便无限期运行。

将confd进程放到后台后,我们可以安全地使用创建的配置文件启动 Nginx. 由于这个脚本将被称为我们的Docker运行命令,我们需要保持在前台运行,以便容器在此时不会退出。

 1#!/bin/bash
 2
 3set -eo pipefail
 4
 5export ETCD_PORT=${ETCD_PORT:-4001}
 6export HOST_IP=${HOST_IP:-172.17.42.1}
 7export ETCD=$HOST_IP:$ETCD_PORT
 8
 9echo "[nginx] booting container. ETCD: $ETCD."
10
11# Try to make initial configuration every 5 seconds until successful
12until confd -onetime -node $ETCD -config-file /etc/confd/conf.d/nginx.toml; do
13    echo "[nginx] waiting for confd to create initial nginx configuration."
14    sleep 5
15done
16
17# Put a continual polling `confd` process into the background to watch
18# for changes every 10 seconds
19confd -interval 10 -node $ETCD -config-file /etc/confd/conf.d/nginx.toml &
20echo "[nginx] confd is now monitoring etcd for changes..."
21
22# Start the Nginx service using the generated config
23echo "[nginx] starting nginx service..."
24service nginx start
25
26# Follow the logs to allow the script to continue running
27tail -f /var/log/nginx/*.log

完成此操作后,保存并关闭文件。

我们需要做的最后一件事是使脚本可执行:

1chmod +x /usr/local/bin/confd-watch

现在退出容器以返回主机系统:

1exit

承诺并推动容器

现在,我们可以委托容器并将其推向Docker Hub,以便我们的机器可以将其拉下来。

查找集装箱ID:

1docker ps -l
1CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2de4f30617499 ubuntu:14.04        "/bin/bash"         22 hours ago Exited (0) About a minute ago stupefied_albattani

突出列出的字符串是我们需要的容器ID。 使用此ID与您的Docker Hub用户名以及您想为此图像使用的名称一起承诺容器。 我们将在本指南中使用名称nginx_lb:

1docker commit de4f30617499 user_name/nginx_lb

如有必要,登录您的 Docker Hub 帐户:

1docker login

现在,你应该推动你的承诺图像,以便你的其他主机可以根据需要把它拉下来:

1docker push user_name/nginx_lb

构建 Nginx 静态单元文件

下一步是构建一个单元文件,将启动我们刚刚创建的容器,这将使我们能够使用舰队来控制这个过程。

由于这不是一个模板,我们会将其放入我们在本目录开始时创建的~/static目录:

1vim static/nginx_lb.service

我们将从标准[单位]部分开始,以描述服务并定义依赖和订单:

 1[Unit]
 2Description=Nginx load balancer for web server backends
 3
 4# Requirements
 5Requires=etcd.service
 6Requires=docker.service
 7
 8# Dependency ordering
 9After=etcd.service
10After=docker.service

接下来,我们需要定义文件的[服务]部分,我们将时隔设置为零,并将 killmode 重新调整为无,就像我们在Apache服务文件中一样。

然后我们将清理我们的环境,以确保此容器的任何以前版本都被杀死和删除,我们将把我们刚刚创建的容器拉下来,以确保我们总是有最新的版本。

最后,我们将启动容器. 这涉及启动容器,给它在删除和杀死命令中提到的名称,并将它传递给正在运行的主机的公共IP地址到地图端口80。

 1[Unit]
 2Description=Nginx load balancer for web server backends
 3
 4# Requirements
 5Requires=etcd.service
 6Requires=docker.service
 7
 8# Dependency ordering
 9After=etcd.service
10After=docker.service
11
12[Service]
13# Let the process take awhile to start up (for first run Docker containers)
14TimeoutStartSec=0
15
16# Change killmode from "control-group" to "none" to let Docker remove
17# work correctly.
18KillMode=none
19
20# Get CoreOS environmental variables
21EnvironmentFile=/etc/environment
22
23# Pre-start and Start
24## Directives with "=-" are allowed to fail without consequence
25ExecStartPre=-/usr/bin/docker kill nginx_lb
26ExecStartPre=-/usr/bin/docker rm nginx_lb
27ExecStartPre=/usr/bin/docker pull user_name/nginx_lb
28ExecStart=/usr/bin/docker run --name nginx_lb -p ${COREOS_PUBLIC_IPV4}:80:80 \
29user_name/nginx_lb /usr/local/bin/confd-watch

现在,我们需要排序的只是停止命令和舰队的时间安排指令,我们希望这个容器只能在不运行其他负载平衡实例或Apache后端服务器的主机上启动。

 1[Unit]
 2Description=Nginx load balancer for web server backends
 3
 4# Requirements
 5Requires=etcd.service
 6Requires=docker.service
 7
 8# Dependency ordering
 9After=etcd.service
10After=docker.service
11
12[Service]
13# Let the process take awhile to start up (for first run Docker containers)
14TimeoutStartSec=0
15
16# Change killmode from "control-group" to "none" to let Docker remove
17# work correctly.
18KillMode=none
19
20# Get CoreOS environmental variables
21EnvironmentFile=/etc/environment
22
23# Pre-start and Start
24## Directives with "=-" are allowed to fail without consequence
25ExecStartPre=-/usr/bin/docker kill nginx_lb
26ExecStartPre=-/usr/bin/docker rm nginx_lb
27ExecStartPre=/usr/bin/docker pull user_name/nginx_lb
28ExecStart=/usr/bin/docker run --name nginx_lb -p ${COREOS_PUBLIC_IPV4}:80:80 \
29user_name/nginx_lb /usr/local/bin/confd-watch
30
31# Stop
32ExecStop=/usr/bin/docker stop nginx_lb
33
34[X-Fleet]
35Conflicts=nginx.service
36Conflicts=apache@*.service

保存并关闭文件,当你完成。

使用 Nginx 负载平衡器

您应该已经在教程中之前运行了两个Apache实例,您可以通过键入来检查:

1fleetctl list-units
1UNIT				MACHINE				ACTIVE	SUB
2[email protected]	197a1662.../10.132.249.206	active	running
3[email protected]	04856ec4.../10.132.249.212	active	running
4[email protected]		197a1662.../10.132.249.206	active	running
5[email protected]		04856ec4.../10.132.249.212	active	running

您还可以通过键入双重检查他们是否正确地注册自己etcd:

1etcdctl ls --recursive /services/apache
1/services/apache/10.132.249.206
2/services/apache/10.132.249.212

我们现在可以尝试启动我们的 Nginx 服务:

1fleetctl start ~/static/nginx_lb.service
1Unit nginx_lb.service launched on 96ec72cf.../10.132.248.177

服务启动可能需要一分钟或更长时间,这取决于图像被拖下来需要多长时间。启动后,如果使用fleetctl journal命令检查日志,您应该能够从confd看到一些日志信息。

1fleetctl journal nginx_lb.service
 1-- Logs begin at Mon 2014-09-15 14:54:05 UTC, end at Tue 2014-09-16 17:13:58 UTC. --
 2Sep 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
 3Sep 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
 4Sep 16 17:13:48 lala1 docker[15379]: [nginx] confd is monitoring etcd for changes...
 5Sep 16 17:13:48 lala1 docker[15379]: [nginx] starting nginx service...
 6Sep 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
 7Sep 16 17:13:48 lala1 docker[15379]: ==> /var/log/nginx/access.log <==
 8Sep 16 17:13:48 lala1 docker[15379]: ==> /var/log/nginx/error.log <==
 9Sep 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
10Sep 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
11Sep 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的条目被重新评估,并创建了一个新的配置文件。

这允许我们的负载平衡服务最终跟踪我们的Apache后端服务器。如果confd似乎不断更新,可能是因为你的Apache实例经常更新他们的TTL。

要看到负载平衡器在运作中,您可以从运行 Nginx 服务的主机请求 /etc/environments 文件. 此内容包含主机的公共 IP 地址. 如果您想使此配置更好,请考虑运行一个 sidekick 服务,该服务将此信息与 etcd 注册,就像我们对 Apache 实例一样:

1fleetctl ssh nginx_lb cat /etc/environment
1COREOS_PRIVATE_IPV4=10.132.248.177
2COREOS_PUBLIC_IPV4=104.131.16.222

现在,如果我们在浏览器中访问公共IPv4地址,我们应该看到我们在Apache实例中配置的页面:

Apache index page

现在,如果您再次查看您的日志,您应该能够看到指示哪个后端服务器实际上传递了请求的信息:

1fleetctl journal nginx_lb
1. . .
2Sep 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
3Sep 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
4Sep 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来生成其初始配置,我们还将其设置在背景中,以持续检查变化。

Published At
Categories with 技术
comments powered by Disqus