Introdução
Recentemente, a popularidade do Kubernetes tem crescido rapidamente - cada vez mais projetos estão sendo implementados. Queria abordar um orquestrador como o Nomad: é perfeito para projetos que já utilizam outras soluções da HashiCorp, por exemplo, Vault e Consul, e os projetos em si não são complexos em termos de infraestrutura. Este material conterá instruções para instalar o Nomad, combinar dois nós em um cluster, bem como integrar o Nomad ao Gitlab.
bancada de teste
Um pouco sobre a bancada de testes: são utilizados três servidores virtuais com características de 2 CPU, 4 RAM, SSD de 50 Gb, unidos em uma rede local comum. Seus nomes e endereços IP:
- nomad-livelinux-01 172.30.0.5
- nomad-livelinux-02 172.30.0.10
- cônsul-livelinux-01 172.30.0.15
Instalação de Nomad, Cônsul. Criando um cluster Nomad
Vamos começar com a instalação básica. Embora a configuração tenha sido simples, vou descrevê-la para fins de integridade do artigo: ela foi essencialmente criada a partir de rascunhos e notas para acesso rápido quando necessário.
Antes de iniciarmos a prática, discutiremos a parte teórica, pois nesta fase é importante compreender a estrutura futura.
Temos dois nós nômades e queremos combiná-los em um cluster, e no futuro também precisaremos de escalonamento automático de cluster - para isso precisaremos do Consul. Com esta ferramenta, agrupar e adicionar novos nós torna-se uma tarefa muito simples: o nó Nomad criado conecta-se ao agente Consul e, em seguida, conecta-se ao cluster Nomad existente. Portanto, inicialmente iremos instalar o servidor Consul, configurar a autorização http básica para o painel web (é sem autorização por padrão e pode ser acessado em um endereço externo), bem como os próprios agentes Consul nos servidores Nomad, após o que prosseguiremos apenas para Nomad.
A instalação das ferramentas da HashiCorp é muito simples: essencialmente, basta mover o arquivo binário para o diretório bin, configurar o arquivo de configuração da ferramenta e criar seu arquivo de serviço.
Baixe o arquivo binário Consul e descompacte-o no diretório inicial do usuário:
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/
Agora temos um binário cônsul pronto para configuração adicional.
Para trabalhar com o Consul, precisamos criar uma chave exclusiva usando o comando keygen:
root@consul-livelinux-01:~# consul keygen
Vamos prosseguir com a configuração do Consul, criando um diretório /etc/consul.d/ com a seguinte estrutura:
/etc/consul.d/
├── bootstrap
│ └── config.json
O diretório bootstrap conterá um arquivo de configuração config.json - nele definiremos as configurações do Consul. Seu conteúdo:
{
"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"]
}
Vejamos as principais diretivas e seus significados separadamente:
- inicialização: verdadeiro. Habilitamos a adição automática de novos nós se eles estiverem conectados. Observo que não indicamos aqui o número exato de nós esperados.
- servidor: verdadeiro. Ative o modo servidor. O Consul nesta máquina virtual atuará como o único servidor e mestre no momento, a VM do Nomad serão os clientes.
- data centers: dc1. Especifique o nome do datacenter para criar o cluster. Deve ser idêntico em clientes e servidores.
- criptografar: sua chave. A chave, que também deve ser exclusiva e corresponder a todos os clientes e servidores. Gerado usando o comando cônsul keygen.
- start_join. Nesta lista indicamos uma lista de endereços IP aos quais será feita a conexão. No momento deixamos apenas nosso próprio endereço.
Neste ponto podemos executar consul usando a linha de comando:
root@consul-livelinux-01:~# /usr/local/bin/consul agent -config-dir /etc/consul.d/bootstrap -ui
Esta é uma boa maneira de depurar agora, no entanto, você não poderá usar esse método continuamente por motivos óbvios. Vamos criar um arquivo de serviço para gerenciar o Consul via systemd:
root@consul-livelinux-01:~# nano /etc/systemd/system/consul.service
Conteúdo do arquivo 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
Inicie o Consul via systemctl:
root@consul-livelinux-01:~# systemctl start consul
Vamos verificar: nosso serviço deve estar rodando, e ao executar o comando consul member devemos ver nosso servidor:
root@consul-livelinux:/etc/consul.d# consul members
consul-livelinux 172.30.0.15:8301 alive server 1.5.0 2 dc1 <all>
Próxima etapa: instalação do Nginx e configuração de proxy e autorização http. Instalamos o nginx através do gerenciador de pacotes e no diretório /etc/nginx/sites-enabled criamos um arquivo de configuração consul.conf com o seguinte conteúdo:
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";
}
}
Não se esqueça de criar um arquivo .htpasswd e gerar um nome de usuário e senha para ele. Este item é necessário para que o painel web não fique disponível para todos que conhecem nosso domínio. Porém, ao configurar o Gitlab, teremos que abandonar isso - caso contrário, não poderemos implantar nosso aplicativo no Nomad. No meu projeto, tanto o Gitlab quanto o Nomad estão apenas na web cinza, então não existe esse problema aqui.
Nos dois servidores restantes instalamos agentes Consul de acordo com as instruções a seguir. Repetimos os passos com o arquivo binário:
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/
Por analogia com o servidor anterior, criamos um diretório para arquivos de configuração /etc/consul.d com a seguinte estrutura:
/etc/consul.d/
├── client
│ └── config.json
Conteúdo do arquivo 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
}
Salve as alterações e prossiga com a configuração do arquivo de serviço, seu conteúdo:
/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
Lançamos cônsul no servidor. Agora, após o lançamento, devemos ver o serviço configurado nos membros do nsul. Isso significará que ele se conectou com êxito ao cluster como cliente. Repita o mesmo no segundo servidor e depois disso podemos começar a instalar e configurar o Nomad.
A instalação mais detalhada do Nomad é descrita em sua documentação oficial. Existem dois métodos tradicionais de instalação: baixando um arquivo binário e compilando a partir do código-fonte. Vou escolher o primeiro método.
Nota: O projeto está se desenvolvendo muito rapidamente, novas atualizações são lançadas com frequência. Talvez uma nova versão seja lançada quando este artigo for concluído. Portanto, antes de ler, recomendo verificar a versão atual do Nomad no momento e baixá-la.
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
Após descompactar, receberemos um arquivo binário Nomad pesando 65 MB - ele deve ser movido para /usr/local/bin.
Vamos criar um diretório de dados para o Nomad e editar seu arquivo de serviço (provavelmente não existirá no início):
root@nomad-livelinux-01:~# mkdir --parents /opt/nomad
root@nomad-livelinux-01:~# nano /etc/systemd/system/nomad.service
Cole as seguintes linhas lá:
[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
No entanto, não temos pressa em lançar o nomad - ainda não criamos seu arquivo de configuração:
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
A estrutura final do diretório será a seguinte:
/etc/nomad.d/
├── nomad.hcl
└── server.hcl
O arquivo nomad.hcl deve conter a seguinte configuração:
datacenter = "dc1"
data_dir = "/opt/nomad"
Conteúdo do arquivo 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
}
Não se esqueça de alterar o arquivo de configuração no segundo servidor - aí você precisará alterar o valor da diretiva http.
A última coisa neste estágio é configurar o Nginx para proxy e configurar a autorização http. Conteúdo do arquivo 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";
}
}
Agora podemos acessar o painel web através de uma rede externa. Conecte-se e vá para a página dos servidores:
Imagem 1. Lista de servidores no cluster Nomad
Ambos os servidores são exibidos com sucesso no painel, veremos a mesma coisa na saída do comando nomad node status:
Imagem 2. Saída do comando de status do nó nomad
E o Cônsul? Vamos dar uma olhada. Acesse o painel de controle do Consul, na página de nós:
Imagem 3. Lista de nós no cluster Consul
Agora temos um Nômade preparado trabalhando em conjunto com o Cônsul. Na etapa final, chegaremos à parte divertida: configurar a entrega dos contêineres Docker do Gitlab para o Nomad, e também falar sobre alguns de seus outros diferenciais.
Criando Gitlab Runner
Para implantar imagens docker no Nomad, usaremos um executor separado com o arquivo binário do Nomad dentro (a propósito, aqui podemos observar outro recurso dos aplicativos Hashicorp - individualmente eles são um único arquivo binário). Faça upload para o diretório do executor. Vamos criar um Dockerfile simples para ele com o seguinte conteúdo:
FROM alpine:3.9
RUN apk add --update --no-cache libc6-compat gettext
COPY nomad /usr/local/bin/nomad
No mesmo projeto criamos .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}
Como resultado teremos uma imagem do runner Nomad disponível no Gitlab Registry, agora podemos ir diretamente ao repositório do projeto, criar um Pipeline e configurar o nomad job do Nomad.
Configuração do projeto
Vamos começar com o arquivo de trabalho do Nomad. Meu projeto neste artigo será bastante primitivo: consistirá em uma tarefa. O conteúdo de .gitlab-ci será o seguinte:
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
Aqui a implantação ocorre manualmente, mas você pode configurá-la para alterar o conteúdo do diretório do projeto. O pipeline consiste em duas etapas: montagem da imagem e sua implantação no nomad. Na primeira etapa montamos uma imagem docker e colocamos em nosso Registro, e na segunda lançamos nosso trabalho no 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" {}
}
}
}
}
}
Observe que tenho um registro privado e, para obter uma imagem do Docker com êxito, preciso fazer login nele. A melhor solução neste caso é inserir login e senha no Vault e depois integrá-lo ao Nomad. O Nomad oferece suporte nativo ao Vault. Mas primeiro, vamos instalar as políticas necessárias para o Nomad no próprio Vault; elas podem ser baixadas:
# 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
Agora, criadas as políticas necessárias, adicionaremos a integração com o Vault no bloco de tarefas do arquivo job.nomad:
vault {
enabled = true
address = "https://vault.domain.name:8200"
token = "token"
}
Eu utilizo a autorização por token e registro diretamente aqui, também existe a opção de especificar o token como variável ao iniciar o agente nômade:
$ VAULT_TOKEN=<token> nomad agent -config /path/to/config
Agora podemos usar as chaves com o Vault. O princípio de funcionamento é simples: criamos um arquivo no Nomad job que irá armazenar os valores das variáveis, por exemplo:
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
}
Com esta abordagem simples, você pode configurar a entrega de contêineres ao cluster Nomad e trabalhar com ele no futuro. Direi que simpatizo até certo ponto com o Nomad - é mais adequado para pequenos projetos onde o Kubernetes pode causar complexidade adicional e não realizará todo o seu potencial. Além disso, o Nomad é perfeito para iniciantes – é fácil de instalar e configurar. No entanto, ao testar alguns projetos, encontro um problema com suas versões anteriores - muitas funções básicas simplesmente não estão disponíveis ou não funcionam corretamente. No entanto, acredito que o Nomad continuará a desenvolver-se e no futuro irá adquirir as funções que todos necessitam.
Autor: Ilya Andreev, editado por Alexey Zhadan e a equipe Live Linux
Fonte: habr.com