Угадай, данную статью написал ChatGPT или нет?
Хотите потестировать приложение, или опробовать в работе инструмент? В этой статье опишу то, как организовал тестовый стенд на Linux. Стенд поддерживает работу с доменами, умеет генерировать TLS сертификаты, легко масштабируется, окружение строится по принципе IaaC, не требует много ресурсов, легко разворачивается скриптами или SCM, есть UI, не зависит от внешних сервисов.
Я являюсь системным инженером и наиболее эффективным языком для инструкций считаю "птичий" технический язык. Содержимое представляет собой последовательность команд с вкраплением комментариев, по которым коллега может однозначно понять этапы построения окружения без лишних слов. А дополнительную информацию о перечисленных инструментах можно легко получить уже из документации и после чего внести правки для тестового стенда. Кроме примеров кода и команд опишу те плюсы и те минусы, которые свойственны этой архитектуре, как бы громко это не звучало.
Конфигурация обыденная и не представляет ценности или сложности с точки зрения моего опыта, но может пригодится начинающим инженерам или даже опытным программистам, которые пишут код для сервисов или используют сервисную архитектуру для решения задач, но не погружаются в технические детали.
Используемые инструменты
Nomad — https://www.nomadproject.io
Consul — https://www.consul.io
Vault — https://www.vaultproject.io
Traefik — https://traefik.io
Packer — https://www.packer.io
Docker — http://docker.io
Плюсы
Набор инструментов с легкостью умещается на небольшой виртуальной машине
Инженер использует на практике современные подходы по релизу и выкладке программного обеспечения
В случае необходимости стенд легко масштабируется в боевое окружение. Отлично подходит для MVP проекта
Минусы
Не подходит для отладки "на лету", но такая возможность есть
Не пользуется популярностью
Краткое описание
Код приложения собирается с помощью Packer в образ и размещается на локальном сервере (аналог Docker Registry). На данном этапе можно потренироваться с версионированием и работой в различных окружениях.
Приложение запускается в виде контейнера Docker и вместе с тем появляется возможность оркестрации, т. е. множественных запусков и стратегий обновления контейнеров с помощью Nomad. Секретные данные передаются в контейнер шаблонами go-template или через переменные окружения из Vault.
В случае Web-приложения или приложения с административным интерфейсом в Traefik создаются точки входа HTTPS с сертификатами TLS от Let'sEncrypt.
Как будет проходить настройка
Я буду приводить примеры установки и настройки сервера для Ubuntu, но различия с другими дистрибутивами будут только на этапе установки пакетов.
Виртуальная машина
Для тестового стенда подойдет виртуальная машина с 2 ядрами, 4Г памяти и диском объемом 20Г. Можете оценить объем используемой памяти на примере моего стенда:
3236 root traefik traefik N/A 1.37% 1.37% 1.37%
3488 root bin/console bot run N/A 1.16% 1.28% 1.42%
3416 root bin/console bot run N/A 1.17% 1.28% 1.42%
858 root /usr/bin/containerd N/A 1.49% 1.49% 1.52%
3300 nobody /bin/prometheus --config.fi N/A 1.56% 1.56% 1.56%
986 root /usr/bin/dockerd -H unix:// N/A 2.13% 2.13% 2.21%
928 consul /usr/bin/consul agent -conf N/A 2.35% 2.35% 2.35%
3840 root /usr/bin/nomad agent -confi N/A 1.57% 1.67% 2.48%
934 vault /usr/bin/vault server -conf N/A 5.45% 5.45% 5.45%
-------------------------------------------------------------------------------
88 12 N/A 25.49% 28.31% 45.90%
Это полностью запущенный стенд состоящий из 5 сервисов на 4Г памяти (45% занято). Дороже всего обходится секретность.
Установка инструментов и репозиториев
https://developer.hashicorp.com/nomad/downloads
https://docs.docker.com/engine/install/ubuntu/
Hidden text
Я не учитываю блокировки доступа из России.
mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
curl -fsSL https://apt.releases.hashicorp.com/gpg | gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com \
$(lsb_release -cs) main" > /etc/apt/sources.list.d/hashicorp.list
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list
Устанавливаем пакеты
apt update
apt install nomad vault consul docker-ce docker-compose packer jq
Настройка Docker + Docker Registry
systemctl start docker
Сейчас нам нужно запустить локальное хранилище образов, которое будет работать идентично публичному облаку или внутреннему в компании.
Создаем файл с описанием сервиса docker-compose.yml
cat >docker-compose.yml <<EndOfText
version: "3.9"
services:
registry:
container_name: registry
image: registry:2
ports:
- 5000:5000
volumes:
- ./config.yml:/etc/docker/registry/config.yml
- /var/lib/registry:/var/lib/registry
EndOfText
И файл с конфигурацией сервиса config.yml
cat >config.yml <<EndOfText
version: 0.1
log:
fields:
service: registry
storage:
cache:
blobdescriptor: inmemory
filesystem:
rootdirectory: /var/lib/registry
http:
addr: :5000
headers:
X-Content-Type-Options: [nosniff]
health:
storagedriver:
enabled: true
interval: 10s
threshold: 3
EndOfText
После запуска наши образы будут храниться в папке /var/lib/registry
Запускаем
docker-compose up -d
Настройка Consul
Генерируем ключ шифрования
CONSUL_KEY=$(consul keygen)
Создаем файл /etc/consul.d/lab_consul.hcl
cat >/etc/consul.d/lab_consul.hcl <<EndOfText
client_addr = "0.0.0.0"
acl {
enabled = true
}
ui_config {
enabled = true
}
bind_addr = "127.0.0.1"
bootstrap_expect = 1
server = true
encrypt = "$CONSUL_KEY"
EndOfText
Запускаем
systemctl restart consul; sleep 10
consul acl bootstrap --format json > ./acl-token-bootstrap-consul.json
export CONSUL_HTTP_TOKEN=`cat ./acl-token-bootstrap-consul.json | jq -r ".SecretID"`
Проверяем
# consul members
Node Address Status Type Build Protocol DC Partition Segment
test 127.0.0.1:8301 alive server 1.14.0 2 dc1 default <all>
Панель по адресу
echo "http://$(curl -s ifconfig.me):8500"
Настройка Vault
Создаем файл /etc/vault.d/vault.hcl
cat >/etc/vault.d/vault.hcl <<EndOfText
ui = true
storage "file" {
path = "/opt/vault/data"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = "true"
}
api_addr = "http://127.0.0.1:8200"
cluster_addr = "https://127.0.0.1:8201"
EndOfText
Запускаем
systemctl restart vault; sleep 10
export VAULT_ADDR='http://127.0.0.1:8200'
vault operator init -key-threshold 1 -key-shares 1 -format json > ./acl-token-bootstrap-vault.json
export VAULT_TOKEN=$(cat ./acl-token-bootstrap-vault.json | jq -r ".root_token")
export VAULT_UNSEAL_KEY=$(cat ./acl-token-bootstrap-vault.json | jq -r ".unseal_keys_b64 | .[]")
vault operator unseal $VAULT_UNSEAL_KEY
vault login $VAULT_TOKEN
В Vault нам потребуется подключить модуль для хранения наших секретов
vault secrets enable -version=2 kv
Теперь сохраним токен Consul в хранилище Vault
vault kv put kv/consul/token value=$CONSUL_HTTP_TOKEN
Панель по адресу
echo "http://$(curl -s ifconfig.me):8200"
Настройка Nomad
Создаем файл /etc/nomad.d/lab_nomad.hcl
cat >/etc/nomad.d/lab_nomad.hcl <<EndOfText
consul {
address = "127.0.0.1:8500"
token = "$CONSUL_HTTP_TOKEN"
}
acl {
enabled = true
}
telemetry {
publish_allocation_metrics = true
publish_node_metrics = true
}
plugin "docker" {
config {
volumes {
enabled = true
}
}
}
vault {
enabled = true
address = "http://localhost:8200"
token = "$VAULT_TOKEN"
}
EndOfText
Запускаем
systemctl restart nomad; sleep 10
nomad acl bootstrap -json > ./acl-token-bootstrap-nomad.json
export NOMAD_TOKEN=`cat ./acl-token-bootstrap-nomad.json | jq -r ".SecretID"`
Панель по адресу
echo "http://$(curl -s ifconfig.me):4646"
Запуск Traefik
Создаем файл traefik.nomad
export MY_MAIL="some@domain.ltd"
cat >traefik.nomad <<EndOfText
job "traefik" {
datacenters = ["dc1"]
type = "service"
group "traefik" {
count = 1
network {
port "http" {static = 80}
port "https" {static = 443}
port "api" {static = 8081}
}
service {
name = "traefik"
port = "api"
tags = ["traefik.enable=true", "traefik.port=8081"]
}
task "traefik" {
driver = "docker"
config {
image = "traefik:v2.2"
network_mode = "host"
volumes = [ "local/traefik.yaml:/etc/traefik/traefik.yaml" ]
}
template {
destination = "local/traefik.yaml"
data = <<EOF
entryPoints:
http:
address: ':80'
https:
address: ':443'
traefik:
address: ':8081'
api:
dashboard: true
insecure: true
log:
level: DEBUG
certificatesResolvers:
myresolver:
acme:
email: $MY_MAIL
storage: /data/acme.json
httpChallenge:
entryPoint: http
providers:
consulCatalog:
prefix: traefik
exposedByDefault: false
endpoint:
address: 127.0.0.1:8500
scheme: http
token: {{with secret "kv/consul/token"}}{{.Data.data.value}}{{end}}
tls:
insecureSkipVerify: true
EOF
}
}
}
}
EndOfText
Проверяем наш конфиг и применяем
nomad plan traefik.nomad
nomad run traefik.nomad
Панель по адресу
echo "http://$(curl -s ifconfig.me):8081"
Сборка приложения
Создаем файл whoami.pkr.hcl
cat >whoami.pkr.hcl <<EndOfText
packer {
required_plugins {
docker = {
version = ">= 1.0.1"
source = "github.com/hashicorp/docker"
}
}
}
source "docker" "whoami" {
image = "traefik/whoami"
commit = true
run_command = [
"-d", "-i", "--rm", "-t", "--", "{{.Image}}"
]
}
build {
sources = ["source.docker.whoami"]
post-processors {
post-processor "docker-tag" {
repository = "localhost:5000/dev/whoami"
tags = ["0.0.1"]
}
post-processor "docker-push" {}
}
}
EndOfText
И запускаем сборку
packer init .
packer build .
В конце сборки будет указан адрес образа для следующего шага
Запуск тестового приложения
Создаем файл whoami.nomad
cat >whoami.nomad <<EndOfText
job "whoami" {
datacenters = ["dc1"]
type = "service"
group "whoami" {
count = 1
network {
port "http" {to = 80}
}
service {
name = "whoami"
port = "http"
tags = [
"traefik.enable=true",
"traefik.http.routers.whoami.entrypoints=http",
"traefik.http.routers.whoami.rule=host(\`$(curl -s ifconfig.me)\`)",
"traefik.http.routers.whoami.middlewares=whoami-to-https",
"traefik.http.middlewares.whoami-to-https.redirectscheme.scheme=https",
"traefik.http.middlewares.whoami-to-https.redirectscheme.permanent=true",
"traefik.http.routers.whoami-https.entrypoints=https",
"traefik.http.routers.whoami-https.rule=host(\`$(curl -s ifconfig.me)\`)",
"traefik.http.routers.whoami-https.tls.certresolver=myresolver"]
}
task "whoami" {
driver = "docker"
config {
image = "localhost:5000/dev/whoami:0.0.1"
ports = ["http"]
}
}
}
}
EndOfText
Проверяем и запускаем наш сервис
nomad plan whoami.nomad
nomad run whoami.nomad
Проверить можно по адресу
echo "http://$(curl -s ifconfig.me)"
После запуска обработать напильником...
Думаю на примере готового приложения дальше будет разобраться попроще.
Пример скрипта для быстрой настройки стенда
Скрипт не идемпотентный, будте осторожны! Запускайте только на новой виртуальной машине с Ubuntu.
curl https://git.sr.ht/~wilful/Shared/blob/master/init.sh | bash -x
Посмотреть все доступные адреса панелей можно так
journalctl -t laboratory -xe
Что можно улучшить?
https://www.waypointproject.io?
Оригинал тут
Комментарии (8)
Dart55
21.01.2023 17:43Угадай, данную статью написал ChatGPT или нет?
По моему мнению ChatGPT просто инструмент, такой же как googl или карандаш. Если автор использует ChatGPT для написания статьи, статья всё равно написана автором.
develmax
21.01.2023 18:27Вот если интегрировать ChatGPT с хабром и настроить интеграцию на написание статей раз в некоторое время, то никто и не заметит)) так же как и можно отвечать на комментарии под статьей, используя ChatGPT без участия человека.
texder
21.01.2023 18:26+1Угадай, данную статью написал ChatGPT или нет?
ChatGPT, конечно, изумительный, но когда его загоняешь в угол, начинает формулировать по кругу, либо пересказывать твой же вопрос в виде ответа. Такое вот перекидывание мячика получается.
Вот так играл сегодня. Осторожно, много картинок
Простите, что поделился. Интересный диалог получился, но не писать же из-за этого статью )
dimitrii_z
21.01.2023 23:27Сам я не админ и не совсем спец в теме, но даже по беглому просмотру текста бросаются в глаза:
странные технически неуместные фразы ("Дороже всего обходится секретность.", "...публичному облаку или внутреннему в компании", "для хранения наших секретов" и пр.), незавершённые команды с пропущенными словами ("Панель по адресу")
элементарные ошибки (но может пригодится, Let'sEncrypt, 4Г памяти и диском объемом 20Г и пр.)
ну и вишенка: Скрипт не идемпотентный, будте осторожны!
В итоге: на 99% уверен, что статью писал ИИ, ну или очень косноязычный админ после весёлой пятницы ))
perfect_genius
22.01.2023 19:19Такими темпами кто-то 1 апреля ради шутки выложит статью, написанную им самим, а не нейросетью.
gionet
Пора открывать на хабре отдельную рубрику, где как в советском документальном фильме будем вместе решать - ИИ написал\нарисовал, или человек ...
Wiljaeden Автор
Не могу не поддержать, ситуация веет тм, что мы отключим комменты. Я же знаю вы ли это написали... ;)