使用 Consul 设置 Nomad 集群并与 Gitlab 集成

介绍

最近,Kubernetes 的受欢迎程度正在迅速增长——越来越多的项目正在实施它。 我想接触一下像Nomad这样的编排器:它非常适合已经使用HashiCorp其他解决方案的项目,例如Vault和Consul,而且项目本身在基础设施方面并不复杂。 本材料将包含安装 Nomad、将两个节点组合成集群以及将 Nomad 与 Gitlab 集成的说明。

使用 Consul 设置 Nomad 集群并与 Gitlab 集成

测试台

关于测试平台的一些信息:使用三台虚拟服务器,具有 2 个 CPU、4 个 RAM、50 Gb SSD 的特性,联合到一个公共本地网络中。 他们的姓名和 IP 地址:

  1. nomad-livelinux-01:172.30.0.5
  2. nomad-livelinux-02:172.30.0.10
  3. 领事-livelinux-01:172.30.0.15

安装Nomad、Consul。 创建Nomad集群

让我们从基本安装开始。 尽管设置很简单,但为了文章的完整性,我将对其进行描述:它本质上是根据草稿和注释创建的,以便在需要时快速访问。

在开始实践之前,我们将讨论理论部分,因为在这个阶段了解未来的结构很重要。

我们有两个游牧节点,我们想将它们组合成一个集群,将来我们还需要自动集群扩展 - 为此我们需要 Consul。 有了这个工具,集群和添加新节点就变成了一个非常简单的任务:创建的Nomad节点连接到Consul代理,然后连接到现有的Nomad集群。 因此,一开始我们要安装Consul服务器,为Web面板配置基本的http授权(默认是无授权的,可以通过外部地址访问),以及Nomad服务器上的Consul代理本身,之后我们只会前往Nomad。

安装 HashiCorp 的工具非常简单:本质上,我们只需将二进制文件移动到 bin 目录,设置工具的配置文件,并创建其服务文件。

下载 Consul 二进制文件并将其解压到用户的主目录中:

root@consul-livelinux-01:~# wget https://releases.hashicorp.com/consul/1.5.0/consul_1.5.0_linux_amd64.zip
root@consul-livelinux-01:~# unzip consul_1.5.0_linux_amd64.zip
root@consul-livelinux-01:~# mv consul /usr/local/bin/

现在我们有一个现成的 consul 二进制文件用于进一步配置。

要使用 Consul,我们需要使用 keygen 命令创建一个唯一的密钥:

root@consul-livelinux-01:~# consul keygen

让我们继续设置 Consul 配置,创建一个具有以下结构的目录 /etc/consul.d/ :

/etc/consul.d/
├── bootstrap
│   └── config.json

bootstrap 目录将包含一个配置文件 config.json - 我们将在其中设置 Consul 设置。 其内容:

{
"bootstrap": true,
"server": true,
"datacenter": "dc1",
"data_dir": "/var/consul",
"encrypt": "your-key",
"log_level": "INFO",
"enable_syslog": true,
"start_join": ["172.30.0.15"]
}

让我们分别看看主要指令及其含义:

  • 引导: 真的。 如果新节点已连接,我们会自动添加它们。 我注意到,我们在这里没有指出预期节点的确切数量。
  • 服务器: 真的。 启用服务器模式。 该虚拟机上的 Consul 目前将充当唯一的服务器和主服务器,Nomad 的 VM 将是客户端。
  • 数据中心:DC1。 指定创建集群的数据中心名称。 它在客户端和服务器上必须相同。
  • 加密:你的钥匙。 密钥也必须是唯一的并且在所有客户端和服务器上都匹配。 使用 consul keygen 命令生成。
  • 开始加入。 在此列表中,我们指示将建立连接的 IP 地址列表。 目前我们只留下我们自己的地址。

此时我们可以使用命令行运行consul:

root@consul-livelinux-01:~# /usr/local/bin/consul agent -config-dir /etc/consul.d/bootstrap -ui

这是现在调试的好方法,但是,由于显而易见的原因,您将无法持续使用此方法。 让我们创建一个服务文件来通过 systemd 管理 Consul:

root@consul-livelinux-01:~# nano /etc/systemd/system/consul.service

consul.service 文件的内容:

[Unit]
Description=Consul Startup process
After=network.target
 
[Service]
Type=simple
ExecStart=/bin/bash -c '/usr/local/bin/consul agent -config-dir /etc/consul.d/bootstrap -ui' 
TimeoutStartSec=0
 
[Install]
WantedBy=default.target

通过 systemctl 启动 Consul:

root@consul-livelinux-01:~# systemctl start consul

让我们检查一下:我们的服务必须正在运行,通过执行 consul Members 命令我们应该看到我们的服务器:

root@consul-livelinux:/etc/consul.d# consul members
consul-livelinux    172.30.0.15:8301  alive   server  1.5.0  2         dc1  <all>

下一阶段:安装 Nginx 并设置代理和 http 授权。 我们通过包管理器安装 nginx,并在 /etc/nginx/sites-enabled 目录中创建一个配置文件 consul.conf,其中包含以下内容:

upstream consul-auth {
    server localhost:8500;
}

server {

    server_name consul.doman.name;
    
    location / {
      proxy_pass http://consul-auth;
      proxy_set_header Host $host;
      auth_basic_user_file /etc/nginx/.htpasswd;
      auth_basic "Password-protected Area";
    }
}

不要忘记创建 .htpasswd 文件并为其生成用户名和密码。 此项目是必需的,以便网络面板不适用于所有知道我们域的人。 然而,在设置 Gitlab 时,我们将不得不放弃这一点 - 否则我们将无法将我们的应用程序部署到 Nomad。 在我的项目中,Gitlab和Nomad都只在灰网上,所以这里不存在这个问题。

在剩下的两台服务器上,我们根据以下说明安装 Consul 代理。 我们对二进制文件重复这些步骤:

root@nomad-livelinux-01:~# wget https://releases.hashicorp.com/consul/1.5.0/consul_1.5.0_linux_amd64.zip
root@nomad-livelinux-01:~# unzip consul_1.5.0_linux_amd64.zip
root@nomad-livelinux-01:~# mv consul /usr/local/bin/

与之前的服务器类比,我们创建一个配置文件/etc/consul.d的目录,其结构如下:

/etc/consul.d/
├── client
│   └── config.json

config.json 文件的内容:

{
    "datacenter": "dc1",
    "data_dir": "/opt/consul",
    "log_level": "DEBUG",
    "node_name": "nomad-livelinux-01",
    "server": false,
    "encrypt": "your-private-key",
    "domain": "livelinux",
    "addresses": {
      "dns": "127.0.0.1",
      "https": "0.0.0.0",
      "grpc": "127.0.0.1",
      "http": "127.0.0.1"
    },
    "bind_addr": "172.30.0.5", # локальный адрес вм
    "start_join": ["172.30.0.15"], # удаленный адрес консул сервера
    "ports": {
      "dns": 53
     }

保存更改并继续设置服务文件,其内容:

/etc/systemd/system/consul.service:

[Unit]
Description="HashiCorp Consul - A service mesh solution"
Documentation=https://www.consul.io/
Requires=network-online.target
After=network-online.target

[Service]
User=root
Group=root
ExecStart=/usr/local/bin/consul agent -config-dir=/etc/consul.d/client
ExecReload=/usr/local/bin/consul reload
KillMode=process
Restart=on-failure

[Install]
WantedBy=multi-user.target

我们在服务器上启动 consul。 现在,启动后,我们应该在 nsul 成员中看到配置的服务。 这意味着它已作为客户端成功连接到集群。 在第二台服务器上重复相同的操作,之后我们就可以开始安装和配置 Nomad。

Nomad 的更详细安装在其官方文档中有描述。 传统的安装方法有两种:下载二进制文件和从源代码编译。 我会选择第一种方法。

注意:项目发展很快,经常发布新的更新。 也许在本文完成时会发布新版本。 因此,在阅读之前,我建议检查目前 Nomad 的当前版本并下载。

root@nomad-livelinux-01:~# wget https://releases.hashicorp.com/nomad/0.9.1/nomad_0.9.1_linux_amd64.zip
root@nomad-livelinux-01:~# unzip nomad_0.9.1_linux_amd64.zip
root@nomad-livelinux-01:~# mv nomad /usr/local/bin/
root@nomad-livelinux-01:~# nomad -autocomplete-install
root@nomad-livelinux-01:~# complete -C /usr/local/bin/nomad nomad
root@nomad-livelinux-01:~# mkdir /etc/nomad.d

解压后,我们将收到一个大小为 65 MB 的 Nomad 二进制文件 - 必须将其移至 /usr/local/bin。

让我们为 Nomad 创建一个数据目录并编辑其服务文件(它很可能一开始就不存在):

root@nomad-livelinux-01:~# mkdir --parents /opt/nomad
root@nomad-livelinux-01:~# nano /etc/systemd/system/nomad.service

将以下行粘贴到此处:

[Unit]
Description=Nomad
Documentation=https://nomadproject.io/docs/
Wants=network-online.target
After=network-online.target

[Service]
ExecReload=/bin/kill -HUP $MAINPID
ExecStart=/usr/local/bin/nomad agent -config /etc/nomad.d
KillMode=process
KillSignal=SIGINT
LimitNOFILE=infinity
LimitNPROC=infinity
Restart=on-failure
RestartSec=2
StartLimitBurst=3
StartLimitIntervalSec=10
TasksMax=infinity

[Install]
WantedBy=multi-user.target

然而,我们并不急于启动 nomad - 我们还没有创建它的配置文件:

root@nomad-livelinux-01:~# mkdir --parents /etc/nomad.d
root@nomad-livelinux-01:~# chmod 700 /etc/nomad.d
root@nomad-livelinux-01:~# nano /etc/nomad.d/nomad.hcl
root@nomad-livelinux-01:~# nano /etc/nomad.d/server.hcl

最终的目录结构如下:

/etc/nomad.d/
├── nomad.hcl
└── server.hcl

nomad.hcl 文件应包含以下配置:

datacenter = "dc1"
data_dir = "/opt/nomad"

server.hcl 文件的内容:

server {
  enabled = true
  bootstrap_expect = 1
}

consul {
  address             = "127.0.0.1:8500"
  server_service_name = "nomad"
  client_service_name = "nomad-client"
  auto_advertise      = true
  server_auto_join    = true
  client_auto_join    = true
}

bind_addr = "127.0.0.1" 

advertise {
  http = "172.30.0.5"
}

client {
  enabled = true
}

不要忘记更改第二个服务器上的配置文件 - 您需要更改 http 指令的值。

此阶段的最后一件事是配置 Nginx 进行代理并设置 http 授权。 nomad.conf 文件的内容:

upstream nomad-auth {
        server 172.30.0.5:4646;
}

server {

        server_name nomad.domain.name;
        
        location / {
	        proxy_pass http://nomad-auth;
	        proxy_set_header Host $host;
	        auth_basic_user_file /etc/nginx/.htpasswd;
		   auth_basic "Password-protected Area";
        }
        
}

现在我们可以通过外部网络访问网页面板了。 连接并转到服务器页面:

使用 Consul 设置 Nomad 集群并与 Gitlab 集成
图片1 Nomad集群中的服务器列表

两台服务器都成功显示在面板中,我们将在 nomad node status 命令的输出中看到相同的内容:

使用 Consul 设置 Nomad 集群并与 Gitlab 集成
图片2 nomad 节点状态命令的输出

领事呢? 我们来看看吧。 进入Consul控制面板,进入节点页面:
使用 Consul 设置 Nomad 集群并与 Gitlab 集成
图片3 Consul集群中的节点列表

现在我们有一个准备好的Nomad 与Consul 一起工作。 在最后阶段,我们将进入有趣的部分:设置 Docker 容器从 Gitlab 到 Nomad 的交付,并讨论它的一些其他独特功能。

创建 Gitlab 运行器

要将 docker 镜像部署到 Nomad,我们将使用一个单独的运行程序,其中包含 Nomad 二进制文件(在这里,顺便说一句,我们可以注意到 Hashicorp 应用程序的另一个功能 - 它们单独是一个二进制文件)。 将其上传到运行器目录。 让我们为其创建一个简单的 Dockerfile,其中包含以下内容:


FROM alpine:3.9
RUN apk add --update --no-cache libc6-compat gettext
COPY nomad /usr/local/bin/nomad

在同一个项目中,我们创建 .gitlab-ci.yml:

variables:
  DOCKER_IMAGE: nomad/nomad-deploy
  DOCKER_REGISTRY: registry.domain.name
 

stages:
  - build

build:
  stage: build
  image: ${DOCKER_REGISTRY}/nomad/alpine:3
  script:
    - tag=${DOCKER_REGISTRY}/${DOCKER_IMAGE}:latest
    - docker build --pull -t ${tag} -f Dockerfile .
    - docker push ${tag}

这样,我们就可以在 Gitlab 注册表中获得 Nomad 运行器的可用镜像,现在我们可以直接进入项目存储库,创建 Pipeline 并配置 Nomad 的 nomad 作业。

项目设置

让我们从 Nomad 的作业文件开始。 我在本文中的项目将非常原始:它将包含一项任务。 .gitlab-ci 的内容如下:

variables:
  NOMAD_ADDR: http://nomad.address.service:4646
  DOCKER_REGISTRY: registry.domain.name
  DOCKER_IMAGE: example/project

stages:
  - build
  - deploy

build:
  stage: build
  image: ${DOCKER_REGISTRY}/nomad-runner/alpine:3
  script:
    - tag=${DOCKER_REGISTRY}/${DOCKER_IMAGE}:${CI_COMMIT_SHORT_SHA}
    - docker build --pull -t ${tag} -f Dockerfile .
    - docker push ${tag}


deploy:
  stage: deploy
  image: registry.example.com/nomad/nomad-runner:latest
  script:
    - envsubst '${CI_COMMIT_SHORT_SHA}' < project.nomad > job.nomad
    - cat job.nomad
    - nomad validate job.nomad
    - nomad plan job.nomad || if [ $? -eq 255 ]; then exit 255; else echo "success"; fi
    - nomad run job.nomad
  environment:
    name: production
  allow_failure: false
  when: manual

这里的部署是手动进行的,但您可以对其进行配置以更改项目目录的内容。 管道由两个阶段组成:图像组装及其部署到游牧者。 在第一阶段,我们组装一个 docker 镜像并将其推送到我们的注册表中,第二阶段我们在 Nomad 中启动我们的工作。

job "monitoring-status" {
    datacenters = ["dc1"]
    migrate {
        max_parallel = 3
        health_check = "checks"
        min_healthy_time = "15s"
        healthy_deadline = "5m"
    }

    group "zhadan.ltd" {
        count = 1
        update {
            max_parallel      = 1
            min_healthy_time  = "30s"
            healthy_deadline  = "5m"
            progress_deadline = "10m"
            auto_revert       = true
        }
        task "service-monitoring" {
            driver = "docker"

            config {
                image = "registry.domain.name/example/project:${CI_COMMIT_SHORT_SHA}"
                force_pull = true
                auth {
                    username = "gitlab_user"
                    password = "gitlab_password"
                }
                port_map {
                    http = 8000
                }
            }
            resources {
                network {
                    port "http" {}
                }
            }
        }
    }
}

请注意,我有一个私有注册表,要成功提取 Docker 映像,我需要登录它。 在这种情况下,最好的解决方案是在 Vault 中输入登录名和密码,然后将其与 Nomad 集成。 Nomad 原生支持 Vault。 但首先,让我们在 Vault 中安装 Nomad 所需的策略;可以下载它们:

# Download the policy and token role
$ curl https://nomadproject.io/data/vault/nomad-server-policy.hcl -O -s -L
$ curl https://nomadproject.io/data/vault/nomad-cluster-role.json -O -s -L

# Write the policy to Vault
$ vault policy write nomad-server nomad-server-policy.hcl

# Create the token role with Vault
$ vault write /auth/token/roles/nomad-cluster @nomad-cluster-role.json

现在,创建了必要的策略后,我们将在 job.nomad 文件的任务块中添加与 Vault 的集成:

vault {
  enabled = true
  address = "https://vault.domain.name:8200"
  token = "token"
}

我使用令牌授权并直接在这里注册它,还有启动 nomad 代理时将令牌指定为变量的选项:

$ VAULT_TOKEN=<token> nomad agent -config /path/to/config

现在我们可以将密钥与 Vault 一起使用。 操作原理很简单:我们在Nomad作业中创建一个文件,用于存储变量的值,例如:

template {
                data = <<EOH
{{with secret "secrets/pipeline-keys"}}
REGISTRY_LOGIN="{{ .Data.REGISTRY_LOGIN }}"
REGISTRY_PASSWORD="{{ .Data.REGISTRY_LOGIN }}{{ end }}"

EOH
    destination = "secrets/service-name.env"
    env = true
}

通过这种简单的方法,您可以配置容器到 Nomad 集群的交付并在将来使用它。 我想说,在某种程度上我同情Nomad——它更适合小型项目,在这些项目中,Kubernetes 可能会导致额外的复杂性,并且无法充分发挥其潜力。 另外,Nomad 非常适合初学者——它易于安装和配置。 然而,在对一些项目进行测试时,我遇到了其早期版本的问题——许多基本功能根本不存在或者无法正常工作。 不过,我相信Nomad会继续发展,未来它会获得大家需要的功能。

作者:Ilya Andreev,由 Alexey Zhadan 和 Live Linux 团队编辑


来源: habr.com

添加评论