Files
Git-install/Readme
2026-01-13 00:11:31 +03:00

311 lines
60 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Вот несколько реальных и достаточно популярных подходов в 20252026 годах, как организовать доставку **бинарников**, **конфигов** и **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)
#### Вариант А — Самый простой и быстрый (очень популярен в 20252026)
```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**, который раз в 15 минут проверяет новую версию и ставит её
Пример минимального 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 (выше) | ★☆☆ | 13 дня | ~0€ | Хотите самый быстрый старт |
| Ansible-pull из git каждые 5 мин | ★★☆ | 37 дней | ~0€ | Хотите более идемпотентно и конфиги в git |
| Terraform + null_resource/ssh | ★★★ | 514 дней | ~0€ | Уже активно используете terraform для серверов|
| Самопальный tiny-agent (curl+bash+systemd timer) | ★★☆ | 410 дней | ~0€ | Очень не любите внешние зависимости |
| Docker + docker-compose pull | ★★☆ | 412 дней | ~0€ | Готовы перейти на контейнеры (рекомендую!) |
### Краткий совет по приоритетам
1. Сделайте сначала **один** сервер по схеме выше (очень быстро)
2. Добавьте простейшую проверку здоровья после рестарта
`systemctl is-active --quiet myapp && curl -f http://localhost:8080/health || exit 1`
3. Только после этого масштабируйте на остальные 9 серверов
4. Параллельно думайте о переходе на **docker + docker compose pull** — это следующий логичный и очень популярный шаг для команд 38 человек в 2026 году (даже без kubernetes)
Если скажете, на каком языке написано приложение и есть ли уже docker — смогу дать ещё более точный вариант.