ansible: fix container name and git user, refuse to start a second agent
The real container on the validators is named validator-agent (the image is cloud-ip-validator-validator-agent); the playbook used the image name as the container name, so it would have started a second agent next to the old one with the same validator_id. The clone on the validators is owned by root, so git must run as root (git_user), otherwise fetch fails with "cannot open .git/FETCH_HEAD: Permission denied". Preflight now stops when the host has another container of this agent (by name or image) besides container_name. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
49890ff5de
commit
cf4a883363
3 files changed
+42
-9
No files matched your search
@@ -1,7 +1,7 @@
|
|||||||
# Доставка validator-agent на валидаторы (Ansible)
|
# Доставка validator-agent на валидаторы (Ansible)
|
||||||
|
|
||||||
Сценарий запускается с jump-хоста и на каждой ВМ-валидаторе: обновляет git-клон в `/opt/cloud-ip-validator`,
|
Сценарий запускается с jump-хоста и на каждой ВМ-валидаторе: обновляет git-клон в `/opt/cloud-ip-validator`,
|
||||||
**собирает образ на самом хосте**, останавливает и удаляет старый контейнер `cloud-ip-validator-validator-agent`
|
**собирает образ на самом хосте**, останавливает и удаляет старый контейнер `validator-agent` (образ — `cloud-ip-validator-validator-agent`)
|
||||||
и поднимает на его месте новый. Параметры запуска агента вынесены в env-файл.
|
и поднимает на его месте новый. Параметры запуска агента вынесены в env-файл.
|
||||||
|
|
||||||
Порядок безопасен: сначала проверки, обновление кода и сборка образа, и только потом замена контейнера. Если что-то
|
Порядок безопасен: сначала проверки, обновление кода и сборка образа, и только потом замена контейнера. Если что-то
|
||||||
@@ -66,8 +66,9 @@ ansible-playbook playbooks/deploy-validator-agent.yml -e deploy_ref=<преды
|
|||||||
|
|
||||||
1. **preflight** — env-файл на jump-хосте существует и в нём задан `VALIDATOR_AGENT_CONTROL_API_URL` (адрес-пример
|
1. **preflight** — env-файл на jump-хосте существует и в нём задан `VALIDATOR_AGENT_CONTROL_API_URL` (адрес-пример
|
||||||
`example.com` не принимается); на валидаторе отвечает Docker, есть git и клон, архитектура x86_64; `validator_id` из inventory совпадает
|
`example.com` не принимается); на валидаторе отвечает Docker, есть git и клон, архитектура x86_64; `validator_id` из inventory совпадает
|
||||||
с `validator_id` работающего контейнера. Показывает текущий контейнер.
|
с `validator_id` работающего контейнера; на хосте нет другого контейнера этого агента (по имени или образу) — иначе рядом со старым
|
||||||
2. **git** — `fetch`, затем клон сбрасывается на `deploy_ref` (`checkout --force`). Через `git`, а не модуль `git`:
|
запустился бы второй с тем же `validator_id`. Показывает текущий контейнер.
|
||||||
|
2. **git** — от имени `git_user` (на валидаторах `root`: клон принадлежит ему) `fetch`, затем клон сбрасывается на `deploy_ref` (`checkout --force`). Через `git`, а не модуль `git`:
|
||||||
учётные данные, уже настроенные в клоне, не трогаются. Локальные правки отслеживаемых файлов в клоне будут сброшены;
|
учётные данные, уже настроенные в клоне, не трогаются. Локальные правки отслеживаемых файлов в клоне будут сброшены;
|
||||||
неотслеживаемые и игнорируемые (`.env.*`) — нет.
|
неотслеживаемые и игнорируемые (`.env.*`) — нет.
|
||||||
3. **build** — проверка `bin/validator-agent` по `bin/SHA256SUMS`; `docker build --platform linux/amd64` с контекстом в корне репозитория,
|
3. **build** — проверка `bin/validator-agent` по `bin/SHA256SUMS`; `docker build --platform linux/amd64` с контекстом в корне репозитория,
|
||||||
@@ -100,8 +101,10 @@ ansible-playbook playbooks/deploy-validator-agent.yml -e deploy_ref=<преды
|
|||||||
неверно для этого хоста: исправьте inventory (контейнер при этом не тронут).
|
неверно для этого хоста: исправьте inventory (контейнер при этом не тронут).
|
||||||
- **Контейнер не прошёл проверку** — в сообщении последние строки лога. `registration failed` — control-api недоступен с валидатора
|
- **Контейнер не прошёл проверку** — в сообщении последние строки лога. `registration failed` — control-api недоступен с валидатора
|
||||||
или `validator_id` не заведён в control-api. Контейнер остаётся на хосте для разбора (`docker logs`).
|
или `validator_id` не заведён в control-api. Контейнер остаётся на хосте для разбора (`docker logs`).
|
||||||
- **`dubious ownership`, `could not read Username`** — клон принадлежит другому пользователю или учётные данные git есть у другого:
|
- **`Permission denied` на `.git/FETCH_HEAD`, `dubious ownership`, `could not read Username`** — git запущен не от владельца клона или
|
||||||
задайте `git_user`.
|
учётные данные есть у другого пользователя: задайте `git_user` (на валидаторах — `root`).
|
||||||
|
- **«найден другой контейнер агента»** — на хосте есть контейнер с похожим именем или образом, не совпадающий с `container_name`:
|
||||||
|
проверьте имя (`docker ps -a`) и при необходимости удалите лишний контейнер вручную.
|
||||||
- **`bin/validator-agent` не совпадает с суммой** — в репозитории устарел `bin/SHA256SUMS`: пересоберите бинарник и обновите сумму.
|
- **`bin/validator-agent` не совпадает с суммой** — в репозитории устарел `bin/SHA256SUMS`: пересоберите бинарник и обновите сумму.
|
||||||
- **Сборка падает на `FROM alpine:3.20` / `apk add`** — с валидатора нет доступа к Docker Hub / репозиториям Alpine.
|
- **Сборка падает на `FROM alpine:3.20` / `apk add`** — с валидатора нет доступа к Docker Hub / репозиториям Alpine.
|
||||||
- **Старый образ другого имени остаётся** — сценарий чистит только образы `image_name`; образ с прежним именем удалите вручную (`docker rmi`).
|
- **Старый образ другого имени остаётся** — сценарий чистит только образы `image_name`; образ с прежним именем удалите вручную (`docker rmi`).
|
||||||
@@ -15,13 +15,15 @@ repo_dir: /opt/cloud-ip-validator
|
|||||||
repo_remote: origin
|
repo_remote: origin
|
||||||
# Ветка, тег или коммит, который нужно выкатить (откат: -e deploy_ref=<коммит>).
|
# Ветка, тег или коммит, который нужно выкатить (откат: -e deploy_ref=<коммит>).
|
||||||
deploy_ref: main
|
deploy_ref: main
|
||||||
# Пользователь, у которого в клоне настроен доступ к репозиторию (git fetch).
|
# Пользователь, от имени которого выполняется git в клоне (через sudo): владелец
|
||||||
# Пусто — git работает от SSH-пользователя без sudo.
|
# клона. На валидаторах клон принадлежит root, репозиторий читается без учётных
|
||||||
git_user: ""
|
# данных. Пусто — git работает от SSH-пользователя без sudo.
|
||||||
|
git_user: root
|
||||||
|
|
||||||
# --- образ и контейнер --------------------------------------------------
|
# --- образ и контейнер --------------------------------------------------
|
||||||
image_name: cloud-ip-validator-validator-agent
|
image_name: cloud-ip-validator-validator-agent
|
||||||
container_name: cloud-ip-validator-validator-agent
|
# Имя контейнера на валидаторах (имя образа — другое, см. image_name).
|
||||||
|
container_name: validator-agent
|
||||||
platform: linux/amd64
|
platform: linux/amd64
|
||||||
dockerfile: deploy/docker/validator-agent/Dockerfile
|
dockerfile: deploy/docker/validator-agent/Dockerfile
|
||||||
# Сколько образов с метками ревизий хранить (кроме latest); старые удаляются.
|
# Сколько образов с метками ревизий хранить (кроме latest); старые удаляются.
|
||||||
|
|||||||
@@ -85,6 +85,34 @@
|
|||||||
failed_when: false
|
failed_when: false
|
||||||
check_mode: false
|
check_mode: false
|
||||||
|
|
||||||
|
# Защита от второго агента: если на хосте уже есть другой контейнер этого
|
||||||
|
# агента (по имени или по образу), сценарий остановится, а не запустит
|
||||||
|
# рядом ещё один с тем же validator_id.
|
||||||
|
- name: List containers on the validator
|
||||||
|
ansible.builtin.command: docker ps -a --format {% raw %}'{{.Names}}|{{.Image}}'{% endraw %}
|
||||||
|
register: all_containers
|
||||||
|
changed_when: false
|
||||||
|
check_mode: false
|
||||||
|
|
||||||
|
- name: Check that there is no other agent container
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that: (other_agents | from_json) | length == 0
|
||||||
|
fail_msg: >-
|
||||||
|
{{ inventory_hostname }}: найден другой контейнер агента: {{ (other_agents | from_json) | join(', ') }}.
|
||||||
|
Сценарий заменяет только контейнер {{ container_name }}. Проверьте container_name в
|
||||||
|
inventory/group_vars/validators.yml или удалите лишний контейнер вручную.
|
||||||
|
quiet: true
|
||||||
|
vars:
|
||||||
|
other_agents: >-
|
||||||
|
{%- set found = [] -%}
|
||||||
|
{%- for line in all_containers.stdout_lines -%}
|
||||||
|
{%- set row = line.split('|') -%}
|
||||||
|
{%- if row[0] != container_name and ('validator-agent' in row[0] or row[1] == image_name or row[1].startswith(image_name ~ ':')) -%}
|
||||||
|
{%- set _ = found.append(row[0] ~ ' (' ~ row[1] ~ ')') -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
{{- found | to_json -}}
|
||||||
|
|
||||||
# validator_id работающего контейнера — эталон: если он отличается от
|
# validator_id работающего контейнера — эталон: если он отличается от
|
||||||
# inventory, заменять контейнер нельзя (агент зарегистрировался бы под чужим
|
# inventory, заменять контейнер нельзя (агент зарегистрировался бы под чужим
|
||||||
# именем, адреса привязывались бы к порту другой ВМ). Выводится только он,
|
# именем, адреса привязывались бы к порту другой ВМ). Выводится только он,
|
||||||
|
|||||||
Reference in new issue
Block a user