SaltStack基础设施:为HAProxy负载均衡器创建Salt状态

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

介绍

SaltStack 或 Salt 是一个功能强大的远程执行和配置管理系统,可用于以结构化、可重复的方式轻松管理基础架构。 在本系列中,我们将演示一种从 Salt 部署管理开发、登台和生产环境的方法。 我们将使用 Salt 状态系统来编写和应用可重复的操作。 这将使我们能够安全地破坏我们的任何环境,因为我们知道我们可以在以后轻松地将它们以相同的状态重新上线。

在我们的 上一篇指南 中,我们为安装和配置 Nginx 的 Web 服务器创建了 Salt 状态。 在本指南中,我们将为负载均衡器配置状态,该负载均衡器将位于我们的暂存和生产环境中的 Web 服务器前面。 我们的负载均衡器需要配置 Web 服务器地址才能正确传递流量。

让我们开始吧。

创建主 HAProxy 状态文件

我们的负载均衡器将使用 HAProxy 在环境中所有可用的 Web 服务器之间分配我们应用程序的流量。 与 Nginx 状态文件一样,我们将在 /srv/salt 目录中为此状态创建一个目录:

sudo mkdir /srv/salt/haproxy

我们将使用名称 init.sls 作为此目录中的主状态文件,以便我们可以通过目录名称引用状态:

sudo nano /srv/salt/haproxy/init.sls

在内部,我们可以使用与 Nginx 相同的模式来安装 haproxy 包并确保它正在运行。 我们将确保在包发生更改或 /etc/default/haproxy 文件或 /etc/haproxy/haproxy.cfg 文件发生更改时重新加载服务。 同样,要非常小心间距以避免 YAML 错误:

/srv/salt/haproxy/init.sls

haproxy:
  pkg:
    - installed
  service.running:
    - watch:
      - pkg: haproxy
      - file: /etc/haproxy/haproxy.cfg
      - file: /etc/default/haproxy

我们需要管理 haproxy 服务正在监视的两个文件。 我们可以为每个创建状态。

/etc/haproxy/haproxy.cfg 文件将是一个模板。 该文件将需要提取有关环境的信息,以填充其要向其传递流量的 Web 服务器列表。 我们的网络服务器在每次创建时都不会拥有相同的 IP。 每次应用此状态时,我们都需要动态创建列表。

/etc/default/haproxy 文件只是一个普通文件。 我们正在管理它,因为我们希望确保 HAProxy 在启动时启动。 不过,这不是动态信息,因此我们不需要将其设为模板:

/srv/salt/haproxy/init.sls

haproxy:
  pkg:
    - installed
  service.running:
    - watch:
      - pkg: haproxy
      - file: /etc/haproxy/haproxy.cfg
      - file: /etc/default/haproxy

/etc/haproxy/haproxy.cfg:
  file.managed:
    - source: salt://haproxy/files/etc/haproxy/haproxy.cfg.jinja
    - template: jinja
    - user: root
    - group: root
    - mode: 644

/etc/default/haproxy:
  file.managed:
    - source: salt://haproxy/files/etc/default/haproxy
    - user: root
    - group: root
    - mode: 644

这实际上是我们需要的状态文件本身。 完成后保存并关闭文件。

安装 HAProxy 并将包文件传输到 Salt Master

我们将使用与 Nginx 相同的技术来获取我们需要的基本 HAProxy 文件。 我们将在 minion 上安装包,然后告诉服务器将文件推送回 master。

让我们使用 stage-lb 服务器,因为无论如何这将是这个包的最终目标。 如果您尚未启动并运行暂存机器,请键入:

sudo salt-cloud -P -m /etc/salt/cloud.maps.d/stage-environment.map

一旦您的服务器可用,您可以通过键入以下命令在 stage-lb 服务器上安装 haproxy 软件包:

sudo salt stage-lb pkg.install haproxy

安装完成后,我们可以告诉 minion 将我们需要的两个文件推送到主服务器:

sudo salt stage-lb cp.push /etc/default/haproxy
sudo salt stage-lb cp.push /etc/haproxy/haproxy.cfg

minion 文件系统的相关部分将在 /var/cache/salt/master/minions/minion_id/files 目录中重新创建。 在这种情况下,minion ID 为 stage-lb。 将整个 minion 文件结构复制到我们的 HAProxy 状态目录:

sudo cp -r /var/cache/salt/master/minions/stage-lb/files /srv/salt/haproxy

我们可以通过键入以下内容来查看文件结构:

find /srv/salt/haproxy -printf "%P\n"
Outputfiles
files/etc
files/etc/default
files/etc/default/haproxy
files/etc/haproxy
files/etc/haproxy/haproxy.cfg
init.sls

现在我们已经有了 Minion 的文件,我们可以销毁负载平衡服务器:

sudo salt-cloud -d stage-lb

然后,我们可以在后台重新创建服务器,以便我们稍后可以进行最终测试和确认。 使用此命令定位您的 Salt 主服务器,因为它可以访问相关的云文件:

sudo salt --async sm cloud.profile stage-lb stage-lb

当服务器正在重建时,我们可以继续对我们正在管理的 HAProxy 文件进行必要的修改。

配置 /etc/default/haproxy 文件

我们可以从 /etc/default/haproxy 文件开始。 在 Salt Master 上的 HAProxy 状态目录中,移动到包含默认文件的目录:

cd /srv/salt/haproxy/files/etc/default

将文件复制到 haproxy.orig 以便我们可以将文件保留为最初打包时的样子:

sudo cp haproxy haproxy.orig

现在,打开文件进行编辑:

sudo nano haproxy

ENABLED 更改为“1”。 这将告诉 Ubuntu 的初始化系统 Upstart 在服务器启动时启动 HAProxy 服务:

/srv/salt/haproxy/文件/etc/default/haproxy

# Set ENABLED to 1 if you want the init script to start haproxy.
ENABLED=1
# Add extra flags here.
#EXTRAOPTS="-de -m 16"

这是我们唯一需要做的改变。 保存并关闭文件。

配置 /etc/haproxy/haproxy.cfg 模板文件

接下来,让我们处理主 HAProxy 配置文件。 移动到 Salt Master 服务器上的相应目录:

cd /srv/salt/haproxy/files/etc/haproxy

同样,让我们复制配置以保存其原始状态:

sudo cp haproxy.cfg haproxy.cfg.orig

然后,重命名文件以反映这是一个 Jinja 模板文件:

sudo mv haproxy.cfg haproxy.cfg.jinja

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

sudo nano haproxy.cfg.jinja

在文件的顶部,我们可以从设置 Jinja 变量开始。 我们需要使用 network.interface_ip 执行函数来获取负载均衡器运行的环境。 稍后我们将使用它来使用来自同一环境的 Web 服务器填充服务器列表:

/srv/salt/haproxy/files/etc/haproxy/haproxy.cfg.jinja

{%- set env = salt['grains.get']('env') -%}
global
        log /dev/log    local0
        log /dev/log    local1 notice
        chroot /var/lib/haproxy
        . . .

跳到文件的“默认”部分。 我们需要将 mode 更改为“tcp”,将第一个 option 更改为“tcplog”:

/srv/salt/haproxy/files/etc/haproxy/haproxy.cfg.jinja

. . .

defaults
    . . .
    mode    tcp
    option  tcplog
    . . .

在文件的底部,我们需要创建我们的实际配置。 我们需要创建一个“前端”部分,它将描述 HAProxy 如何接受连接。 我们将此部分标记为“www”。

我们想将此绑定到服务器的公共 IP 地址。 我们可以使用带有 eth0 参数的 network.interface_ip 执行模块函数来获取它。 Web 请求将从端口 80 进入。 我们可以使用 default_backend 选项指定要传递给的默认后端。 我们将调用我们的后端 nginx_pool

/srv/salt/haproxy/files/etc/haproxy/haproxy.cfg.jinja

. . .

frontend www
    bind {{ salt['network.interface_ip']('eth0') }}:80
    default_backend nginx_pool

接下来,我们需要添加 nginx_pool 后端。 我们将使用传统的循环平衡模型并再次将模式设置为“tcp”。

之后,我们需要从我们的环境中填充后端 Web 服务器列表。 我们可以在 Jinja 中使用“for”循环来做到这一点。 我们可以使用mine.get执行模块函数来获取internal_ip挖矿函数的值。 我们将匹配 Web 服务器角色和环境。 ~ env 会将我们之前设置的 env 变量的值连接到它之前的匹配字符串。

对于循环的每次迭代,此查找的结果将存储在 serveraddr 变量中。 在循环中,我们将使用这些循环变量添加服务器的详细信息。 最终结果如下所示:

/srv/salt/haproxy/files/etc/haproxy/haproxy.cfg.jinja

. . .

frontend www
    bind {{ salt['network.interface_ip']('eth0') }}:80
    default_backend nginx_pool

backend nginx_pool
    balance roundrobin
    mode tcp
    {% for server, addr in salt['mine.get']('G@role:webserver and G@env:' ~ env, 'internal_ip', expr_form='compound').items() -%}
    server {{ server }} {{ addr }}:80 check
    {% endfor -%}

完成后保存并关闭文件。

测试 HAProxy 状态文件

我们的负载平衡状态是相当基本的,但很完整。 我们现在可以继续测试它。

首先,让我们使用 state.show_sls 来显示文件排序:

sudo salt stage-lb state.show_sls haproxy

我们可以通过输出中各种“order”值的顺序来判断包将被安装,服务将被启动,然后两个文件将被应用。 这是我们所期望的。 由于我们配置的“监视”设置,文件更改将触发服务重新加载。

接下来,我们可以对状态应用程序进行试运行。 这将捕获一些(但不是全部)会导致状态在运行时失败的错误:

sudo salt stage-lb state.apply haproxy test=True

检查所有状态是否都已通过。 无论底部的故障计数或输出如何,向上滚动并查看每个状态的“注释”行。 有时,这将包括有关潜在问题的额外信息,即使测试被标记为成功。

修复测试命令期间出现的任何问题后,您可以将您的状态应用到负载均衡器服务器。 确保在应用状态之前运行并配置了后端 Nginx Web 服务器:

sudo salt-cloud -P -m /etc/salt/cloud.maps.d/stage-environment.map
sudo salt -G 'role:webserver' state.apply nginx

当您的 Web 服务器正在运行时,应用 haproxy 状态:

sudo salt -G 'role:lbserver' state.apply haproxy

您现在应该能够通过负载均衡器的公共 IP 地址访问您的两个后端 Web 服务器之一。 您可以使用以下命令显示负载均衡器的公共 IP 地址:

sudo salt -G 'role:lbserver' network.interface_ip eth0

如果你使用浏览器,它看起来像这样:

使用 curl 更容易看到负载均衡器在后端服务器之间传递流量:

curl load_balancer_public_IP
Output<!DOCTYPE html>
<html>
<head>
<title>Welcome from stage-www2</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>Hello!  This is being served from:</p>

<h2>stage-www2</h2>

</body>
</html>

如果您再次键入该命令几次,它应该在您的两台服务器之间交换:

curl load_balancer_public_IP
Output<!DOCTYPE html>
<html>
<head>
<title>Welcome from stage-www1</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>Hello!  This is being served from:</p>

<h2>stage-www1</h2>

</body>
</html>

如您所见,服务请求的服务器发生了变化,这意味着我们的负载均衡器运行正常。

结论

在这一点上,我们有一个正常工作的 HAProxy 状态,可以应用于我们的负载均衡器机器。 这可用于在所有后端 Nginx 服务器之间拆分我们应用程序的传入流量。 我们可以轻松地销毁负载均衡器,然后根据可用的 Web 服务器重建它们。

下一个指南 中,我们将专注于让 MySQL 启动并作为我们的后端数据库系统运行。 这将用于在我们的各种环境中存储应用程序数据。