311 lines
60 KiB
Plaintext
311 lines
60 KiB
Plaintext
|
||
Вот несколько реальных и достаточно популярных подходов в 2025–2026 годах, как организовать доставку **бинарников**, **конфигов** и **systemd**-юнитов на сервер с использованием **Git + Terraform** (без полного перехода на контейнеры).
|
||
|
||
| № | Подход | Сложность | Идемпотентность | Скорость деплоя | Рекомендую в 2026 |
|
||
|----|--------------------------------------|-----------|------------------|------------------|--------------------|
|
||
| 1 | Terraform provisioner + git clone | ★☆☆ | Плохая | Средняя | Нет (только PoC) |
|
||
| 2 | Terraform + cloud-init/user-data | ★★☆ | Средняя | Медленно | Иногда (новые VM) |
|
||
| 3 | Git → Artifact (zip/tar) → S3/HTTPS → systemd-tmpfiles + remote-exec | ★★★ | Хорошая | Быстро | Да, классика |
|
||
| 4 | GitOps через Flux/ArgoCD | ★★★★ | Отличная | Очень быстро | Если уже есть k8s |
|
||
| 5 | Git → CI → rsync/scp + webhook/reloader | ★★☆ | Средняя–хорошая | Очень быстро | Самый простой живой вариант сейчас |
|
||
| 6 | Git → CI → deb/rpm → apt/yum + systemd | ★★★★ | Отличная | Средняя | Лучший долгосрочный вариант |
|
||
|
||
### Самые живые и практичные варианты на сегодня (январь 2026)
|
||
|
||
#### Вариант А — Самый простой и быстрый (очень популярен в 2025–2026)
|
||
|
||
```bash
|
||
# Структура репозитория
|
||
my-service/
|
||
├── bin/
|
||
│ └── myapp # ← бинарник
|
||
├── config/
|
||
│ └── config.yaml
|
||
├── systemd/
|
||
│ └── myapp.service
|
||
├── deploy.sh # опционально
|
||
└── .github/workflows/deploy.yml
|
||
```
|
||
|
||
`.github/workflows/deploy.yml` пример:
|
||
|
||
```yaml
|
||
name: Deploy to server
|
||
|
||
on:
|
||
push:
|
||
branches: [ main ]
|
||
|
||
jobs:
|
||
deploy:
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Pack artifact
|
||
run: tar czf artifact.tar.gz bin/ config/ systemd/
|
||
|
||
- name: Copy to server
|
||
uses: appleboy/scp-action@v0.1.7
|
||
with:
|
||
host: ${{ secrets.SERVER_IP }}
|
||
username: deploy
|
||
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||
source: "artifact.tar.gz"
|
||
target: "/opt/my-service.new"
|
||
|
||
- name: Deploy & restart
|
||
uses: appleboy/ssh-action@v1.0.3
|
||
with:
|
||
host: ${{ secrets.SERVER_IP }}
|
||
username: deploy
|
||
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||
script: |
|
||
set -e
|
||
cd /opt/my-service.new
|
||
sudo rm -rf /opt/my-service.old
|
||
sudo mv /opt/my-service /opt/my-service.old || true
|
||
sudo mv /opt/my-service.new /opt/my-service
|
||
sudo cp systemd/myapp.service /etc/systemd/system/
|
||
sudo systemctl daemon-reload
|
||
sudo systemctl enable --now myapp.service
|
||
```
|
||
|
||
**Плюсы**: быстро, дёшево, понятно
|
||
**Минусы**: не совсем идемпотентно, нет отката версий «из коробки»
|
||
|
||
#### Вариант Б — Terraform как оркестратор (очень чистый и воспроизводимый)
|
||
|
||
```hcl
|
||
variable "app_version" { default = "v1.2.3" }
|
||
|
||
data "http" "release" {
|
||
url = "https://github.com/your-org/my-service/releases/download/${var.app_version}/artifact.tar.gz"
|
||
}
|
||
|
||
resource "null_resource" "deploy" {
|
||
triggers = {
|
||
version = var.app_version
|
||
}
|
||
|
||
connection {
|
||
type = "ssh"
|
||
user = "deploy"
|
||
private_key = file("~/.ssh/id_ed25519_deploy")
|
||
host = "your-server.example.com"
|
||
}
|
||
|
||
provisioner "file" {
|
||
content = data.http.release.response_body
|
||
destination = "/tmp/artifact-${var.app_version}.tar.gz"
|
||
}
|
||
|
||
provisioner "remote-exec" {
|
||
inline = [
|
||
"set -e",
|
||
"mkdir -p /opt/my-service",
|
||
"tar xzf /tmp/artifact-${var.app_version}.tar.gz -C /opt/my-service",
|
||
"sudo cp /opt/my-service/systemd/myapp.service /etc/systemd/system/",
|
||
"sudo systemctl daemon-reload",
|
||
"sudo systemctl enable --now myapp.service",
|
||
"rm -f /tmp/artifact-*.tar.gz"
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
Или ещё чище — положить артефакт в **S3**/**Artifactory**/**GHCR** и тянуть по https.
|
||
|
||
#### Вариант В — Золотой стандарт на 2026 год (если позволяет время и масштаб)
|
||
|
||
1. CI делает deb/rpm-пакет (или tar.gz + manifest.json)
|
||
2. Публикует в Artifactory / Packagecloud / GitHub Releases / S3
|
||
3. Terraform только управляет инфраструктурой и желаемой версией
|
||
4. На сервере работает **tiny agent** (systemd-таймер + curl + bash) или **ansible-pull**, который раз в 1–5 минут проверяет новую версию и ставит её
|
||
|
||
Пример минимального systemd-таймера + сервиса-апдейтера:
|
||
|
||
```ini
|
||
# /etc/systemd/system/myapp-updater.timer
|
||
[Unit]
|
||
Description=Update myapp every 5 minutes
|
||
|
||
[Timer]
|
||
OnBootSec=3min
|
||
OnUnitActiveSec=5min
|
||
Unit=myapp-updater.service
|
||
|
||
[Install]
|
||
WantedBy=timers.target
|
||
```
|
||
|
||
```ini
|
||
# /etc/systemd/system/myapp-updater.service
|
||
[Service]
|
||
Type=oneshot
|
||
ExecStart=/opt/myapp/update.sh
|
||
```
|
||
|
||
### Краткие рекомендации
|
||
|
||
Ситуация | Что выбрать в 2026
|
||
-------------------------------------|-------------------------
|
||
Один-два сервера, быстро надо | Вариант А (GitHub Actions + scp + ssh)
|
||
Средний проект, много серверов | Вариант Б (Terraform + releases) или Вариант А + Ansible-pull
|
||
Хотите «по-взрослому», надолго | deb/rpm + свой маленький apt/yum репозиторий
|
||
Уже есть Kubernetes | Flux/ArgoCD + kustomize/helm + git
|
||
|
||
Удачи с деплоем! 🚀
|
||
Какой у тебя сейчас масштаб и какие ограничения (деньги, время, команда)? Могу предложить более точный вариант.
|
||
]
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
ри 3 людях в команде, нулевом/очень маленьком бюджете и ~10 серверах самая разумная стратегия на 2026 год выглядит так:
|
||
|
||
**Цель**: минимизировать время поддержки + количество мест, где может что-то сломаться
|
||
**Принцип**: один раз настроил → дальше почти всё через git push
|
||
|
||
### Рекомендуемый вариант (топ-1 для вашей ситуации)
|
||
|
||
**GitHub Actions → scp/rsync + atomic переключение + systemd**
|
||
|
||
Почему именно это:
|
||
|
||
- Стоимость ≈ 0 € (GitHub Actions free tier 2000 минут/месяц хватает с огромным запасом)
|
||
- Минимум новых технологий
|
||
- Работает на любых linux-серверах (даже очень старых)
|
||
- Легко откатывать (оставляем предыдущую версию)
|
||
- 3 человека реально поддерживают без боли
|
||
|
||
#### Структура репозитория (самая практичная)
|
||
|
||
```
|
||
my-project/
|
||
├── app/ # исходники
|
||
│ └── main.go
|
||
├── deploy/
|
||
│ ├── bin/ # сюда кладём готовый бинарник при релизе (опционально)
|
||
│ ├── config/
|
||
│ │ └── prod.yaml
|
||
│ ├── systemd/
|
||
│ │ └── myapp.service
|
||
│ └── versions/
|
||
│ └── current.txt # просто номер версии или git sha
|
||
└── .github/workflows/
|
||
└── deploy.yml
|
||
```
|
||
|
||
#### Самый простой и надёжный deploy.yml (2026 версия)
|
||
|
||
```yaml
|
||
name: Deploy to all servers
|
||
|
||
on:
|
||
push:
|
||
branches: [ main ]
|
||
workflow_dispatch: # можно запускать вручную
|
||
|
||
jobs:
|
||
build:
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Set up Go
|
||
uses: actions/setup-go@v5
|
||
with:
|
||
go-version: '1.23' # или ваша версия
|
||
|
||
- name: Build binary
|
||
run: |
|
||
GOOS=linux GOARCH=amd64 go build -trimpath -ldflags="-s -w" \
|
||
-o deploy/bin/myapp ./app
|
||
|
||
- name: Pack artifact
|
||
run: |
|
||
cd deploy
|
||
tar czf artifact.tar.gz bin/ config/ systemd/ versions/
|
||
|
||
- name: Upload artifact
|
||
uses: actions/upload-artifact@v4
|
||
with:
|
||
name: deployment-artifact
|
||
path: deploy/artifact.tar.gz
|
||
|
||
deploy:
|
||
needs: build
|
||
runs-on: ubuntu-latest
|
||
strategy:
|
||
matrix:
|
||
server: [ "10.10.1.11", "10.10.1.12", "..." ] # ваши 10 ip/доменов
|
||
# или лучше через переменные/файл, но для начала так проще
|
||
|
||
steps:
|
||
- uses: actions/download-artifact@v4
|
||
with:
|
||
name: deployment-artifact
|
||
|
||
- name: Deploy to ${{ matrix.server }}
|
||
uses: appleboy/scp-action@v0.1.7
|
||
with:
|
||
host: ${{ matrix.server }}
|
||
username: deploy
|
||
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||
source: "artifact.tar.gz"
|
||
target: "/opt/myapp.new"
|
||
strip_components: 0
|
||
|
||
- name: Atomic switch & restart
|
||
uses: appleboy/ssh-action@v1.0.3
|
||
with:
|
||
host: ${{ matrix.server }}
|
||
username: deploy
|
||
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||
script: |
|
||
set -euo pipefail
|
||
cd /opt/myapp.new
|
||
sudo tar xzf artifact.tar.gz
|
||
|
||
# Проверка что бинарник запускается (очень важно!)
|
||
sudo /opt/myapp.new/bin/myapp --version || exit 1
|
||
|
||
sudo rm -rf /opt/myapp.old
|
||
sudo mv /opt/myapp /opt/myapp.old 2>/dev/null || true
|
||
sudo mv /opt/myapp.new /opt/myapp
|
||
|
||
sudo cp /opt/myapp/systemd/myapp.service /etc/systemd/system/
|
||
sudo systemctl daemon-reload
|
||
sudo systemctl enable myapp.service
|
||
sudo systemctl restart myapp.service
|
||
|
||
# Опционально: чистка старых версий через 1 день
|
||
# find /opt -maxdepth 1 -name 'myapp.old.*' -mtime +1 -exec rm -rf {} \;
|
||
```
|
||
|
||
### Альтернативы (если описанное выше по каким-то причинам не подходит)
|
||
|
||
| Вариант | Сложность | Время настройки | Стоимость | Подходит если... |
|
||
|-------------------------------|-----------|------------------|-----------|-----------------------------------------------|
|
||
| GitHub Actions + scp (выше) | ★☆☆ | 1–3 дня | ~0€ | Хотите самый быстрый старт |
|
||
| Ansible-pull из git каждые 5 мин | ★★☆ | 3–7 дней | ~0€ | Хотите более идемпотентно и конфиги в git |
|
||
| Terraform + null_resource/ssh | ★★★ | 5–14 дней | ~0€ | Уже активно используете terraform для серверов|
|
||
| Самопальный tiny-agent (curl+bash+systemd timer) | ★★☆ | 4–10 дней | ~0€ | Очень не любите внешние зависимости |
|
||
| Docker + docker-compose pull | ★★☆ | 4–12 дней | ~0€ | Готовы перейти на контейнеры (рекомендую!) |
|
||
|
||
### Краткий совет по приоритетам
|
||
|
||
1. Сделайте сначала **один** сервер по схеме выше (очень быстро)
|
||
2. Добавьте простейшую проверку здоровья после рестарта
|
||
`systemctl is-active --quiet myapp && curl -f http://localhost:8080/health || exit 1`
|
||
3. Только после этого масштабируйте на остальные 9 серверов
|
||
4. Параллельно думайте о переходе на **docker + docker compose pull** — это следующий логичный и очень популярный шаг для команд 3–8 человек в 2026 году (даже без kubernetes)
|
||
|
||
Если скажете, на каком языке написано приложение и есть ли уже docker — смогу дать ещё более точный вариант. |