One role that syncs a payload and brings the stack up, configured entirely through stack_* variables, plus six playbooks that each demonstrate one part of that contract. Every playbook runs standalone and is tagged with its stack name, so site.yml --tags <stack> works. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
69 lines
2.9 KiB
YAML
69 lines
2.9 KiB
YAML
---
|
|
# One stack, both hosts, one payload.
|
|
#
|
|
# Demonstrates three things:
|
|
# - stack_src pointing outside the per-host convention, so two hosts share a
|
|
# single payload instead of keeping duplicate copies in step by hand;
|
|
# - a per-host variable map, which is how a play covers hosts that differ
|
|
# without growing a second playbook or a `when:` on every task;
|
|
# - stack_dirs entries that set ownership, and ones that only set a mode.
|
|
- name: Deploy metrics
|
|
hosts:
|
|
- edge
|
|
- app
|
|
gather_facts: false
|
|
tags: [metrics]
|
|
|
|
vars:
|
|
# Only the app host runs anything worth proxying a dashboard to, so only it
|
|
# joins the private backend network. Keyed by inventory_hostname and looked
|
|
# up below — adding a host means adding a line here, not a branch.
|
|
metrics_networks:
|
|
edge:
|
|
- proxy-net
|
|
app:
|
|
- proxy-net
|
|
- backend
|
|
|
|
metrics_dirs:
|
|
# The Grafana image runs as uid 472 and this is a bind mount, so the
|
|
# directory has to be owned by that uid on the host. `recurse: true` with
|
|
# no `mode`: recursing a mode here would rewrite the permissions of
|
|
# Grafana's SQLite database, which holds hashed credentials and datasource
|
|
# secrets.
|
|
#
|
|
# This belongs in stack_dirs rather than a pre_tasks chown. pre_tasks run
|
|
# before the role creates the stack directory, and an escalated
|
|
# ansible.builtin.file on a child stamps its owner onto every parent it
|
|
# creates on the way down — which would leave the payload sync, running as
|
|
# the deploy user, unable to write into the stack's own directory on a host
|
|
# where metrics has never been deployed.
|
|
- path: "{{ stack_root }}/metrics/grafana-data"
|
|
owner: "472"
|
|
group: "472"
|
|
recurse: true
|
|
# Written by the prometheus container, which runs as nobody (65534). A mode
|
|
# rather than an owner because the uid is not stable across image versions.
|
|
# Narrow this to an owner once you have confirmed the uid on your hosts.
|
|
- path: "{{ stack_root }}/metrics/prometheus-data"
|
|
mode: "0777"
|
|
|
|
roles:
|
|
- role: compose_stack
|
|
vars:
|
|
stack_name: metrics
|
|
# Both hosts run the same thing, so the payload lives under server/shared/
|
|
# rather than being copied into server/edge/ and server/app/.
|
|
stack_src: "{{ repo_root }}/server/shared/metrics"
|
|
stack_networks: "{{ metrics_networks[inventory_hostname] }}"
|
|
stack_dirs: "{{ metrics_dirs }}"
|
|
|
|
post_tasks:
|
|
- name: Reload prometheus so a changed scrape configuration takes effect
|
|
# prometheus.yml is bind-mounted, so Compose never recreates the container
|
|
# for a change to it. Prometheus re-reads its configuration on SIGHUP.
|
|
ansible.builtin.command:
|
|
cmd: docker kill --signal=SIGHUP prometheus
|
|
when: compose_stack_synced | default(false)
|
|
changed_when: true
|