256 lines
8.8 KiB
YAML
256 lines
8.8 KiB
YAML
---
|
||
# AWOOOI Ansible — 192.168.0.110 DevOps 金庫完整狀態描述
|
||
# 執行: ansible-playbook -i inventory/hosts.yml playbooks/110-devops.yml
|
||
#
|
||
# 預期狀態:
|
||
# swap: 8GB (swap.img 3.8G + swap2.img 4G)
|
||
# harbor: running (docker compose, port 5000)
|
||
# sentry: running (docker compose, 0 restarting)
|
||
# gitea: running (port 3001)
|
||
# langfuse: running (port 3100)
|
||
# bitan: running docker (port 3003)
|
||
# wooo-aiops: running PM2 (port 3000)
|
||
# runners: 5x GitHub Actions runners (systemd)
|
||
# nginx: harbor conf -> 127.0.0.1:5000
|
||
# keepalived: BACKUP priority 90 VIP:200
|
||
|
||
- name: "192.168.0.110 DevOps 金庫 — 預期狀態收斂"
|
||
hosts: host_110
|
||
become: true
|
||
vars:
|
||
ansible_become_pass: "{{ vault_sudo_password | default(omit) }}"
|
||
|
||
roles:
|
||
- role: cold-start-monitor
|
||
tags: cold_start_monitor
|
||
- role: runner-guardrails
|
||
tags: runner_guardrails
|
||
- role: host-textfile-exporters
|
||
vars:
|
||
host_textfile_user: wooo
|
||
host_textfile_host_label: "110"
|
||
host_textfile_manage_runaway_process: true
|
||
host_textfile_manage_systemd_units: true
|
||
host_textfile_systemd_unit_glob: "actions.runner.*.service"
|
||
host_textfile_systemd_units:
|
||
- docker.service
|
||
- nginx.service
|
||
- prometheus.service
|
||
- alertmanager.service
|
||
- gitea.service
|
||
tags: textfile_exporters
|
||
|
||
tasks:
|
||
# ========================================================================
|
||
# Swap 檢查
|
||
# ========================================================================
|
||
- name: "Swap | 確認 swap.img 存在"
|
||
ansible.builtin.stat:
|
||
path: /swap.img
|
||
register: swap1_stat
|
||
tags: swap
|
||
|
||
- name: "Swap | 確認 swap2.img 存在"
|
||
ansible.builtin.stat:
|
||
path: /swap2.img
|
||
register: swap2_stat
|
||
tags: swap
|
||
|
||
- name: "Swap | 建立 swap2.img (若不存在)"
|
||
ansible.builtin.command:
|
||
cmd: "fallocate -l 4G /swap2.img"
|
||
creates: /swap2.img
|
||
when: not swap2_stat.stat.exists
|
||
tags: swap
|
||
|
||
- name: "Swap | 格式化 swap2.img (若剛建立)"
|
||
ansible.builtin.command:
|
||
cmd: "mkswap /swap2.img"
|
||
changed_when: true
|
||
when: not swap2_stat.stat.exists
|
||
tags: swap
|
||
|
||
- name: "Swap | 設定 swap2.img 權限"
|
||
ansible.builtin.file:
|
||
path: /swap2.img
|
||
mode: "0600"
|
||
tags: swap
|
||
|
||
- name: "Swap | 加入 swap2.img 到 fstab"
|
||
ansible.builtin.lineinfile:
|
||
path: /etc/fstab
|
||
line: "/swap2.img none swap sw 0 0"
|
||
state: present
|
||
tags: swap
|
||
|
||
- name: "Swap | 啟用 swap"
|
||
ansible.builtin.command:
|
||
cmd: "swapon --all"
|
||
changed_when: false
|
||
tags: swap
|
||
|
||
# ========================================================================
|
||
# Docker 服務健康檢查
|
||
# ========================================================================
|
||
- name: "Docker | 確認 Harbor 容器運作中"
|
||
ansible.builtin.command:
|
||
cmd: "docker ps --filter name=harbor --filter status=running --format '{{ '{{' }}.Names{{ '}}' }}'"
|
||
register: harbor_status
|
||
changed_when: false
|
||
tags: docker
|
||
|
||
- name: "Docker | Harbor 狀態警告"
|
||
ansible.builtin.debug:
|
||
msg: "⚠️ Harbor 容器未完全運作,請手動檢查 /opt/harbor"
|
||
when: harbor_status.stdout == ""
|
||
tags: docker
|
||
|
||
- name: "Docker | 確認 Gitea 容器運作中"
|
||
ansible.builtin.command:
|
||
cmd: "docker ps --filter name=gitea --filter status=running --format '{{ '{{' }}.Names{{ '}}' }}'"
|
||
register: gitea_status
|
||
changed_when: false
|
||
tags: docker
|
||
|
||
- name: "Docker | 確認 Sentry 無 restart 容器"
|
||
ansible.builtin.command:
|
||
cmd: "docker ps --filter status=restarting --filter name=sentry --format '{{ '{{' }}.Names{{ '}}' }}'"
|
||
register: sentry_restarting
|
||
changed_when: false
|
||
tags: docker
|
||
|
||
- name: "Docker | Sentry crash loop 警告"
|
||
ansible.builtin.debug:
|
||
msg: "⚠️ Sentry 容器 crash loop: {{ sentry_restarting.stdout }}"
|
||
when: sentry_restarting.stdout != ""
|
||
tags: docker
|
||
|
||
# ========================================================================
|
||
# bitan pharmacy Docker 服務
|
||
# ========================================================================
|
||
- name: "Bitan | 確認 bitan container 運作中"
|
||
ansible.builtin.command:
|
||
cmd: "docker ps --filter name=bitan --filter status=running --format '{{ '{{' }}.Names{{ '}}' }}'"
|
||
register: bitan_status
|
||
changed_when: false
|
||
tags: bitan
|
||
|
||
- name: "Bitan | 若停止則啟動"
|
||
ansible.builtin.command:
|
||
cmd: "docker compose up -d"
|
||
chdir: /home/wooo/apps/bitan-pharmacy
|
||
changed_when: true
|
||
when: bitan_status.stdout == ""
|
||
tags: bitan
|
||
|
||
# ========================================================================
|
||
# GitHub Runners
|
||
# ========================================================================
|
||
- name: "Runners | 確認 runner 服務狀態"
|
||
ansible.builtin.systemd:
|
||
name: "github-runner-{{ item }}"
|
||
register: runner_status
|
||
loop: "{{ range(1, github_runner_count + 1) | list }}"
|
||
ignore_errors: true
|
||
tags: runners
|
||
|
||
# ========================================================================
|
||
# keepalived
|
||
# ========================================================================
|
||
- name: "Keepalived | 確認服務運作中"
|
||
ansible.builtin.systemd:
|
||
name: keepalived
|
||
register: keepalived_status
|
||
tags: keepalived
|
||
|
||
- name: "Keepalived | 警告:keepalived 未運作"
|
||
ansible.builtin.debug:
|
||
msg: "⚠️ keepalived 未運作,VIP 200 可能失效"
|
||
when: keepalived_status.status.ActiveState != "active"
|
||
tags: keepalived
|
||
|
||
# ========================================================================
|
||
# Nginx harbor conf 指向確認
|
||
# ========================================================================
|
||
- name: "Nginx | 確認 harbor nginx conf 存在"
|
||
ansible.builtin.stat:
|
||
path: /etc/nginx/sites-enabled/harbor.conf
|
||
register: harbor_nginx
|
||
tags: nginx
|
||
|
||
- name: "Nginx | 確認 harbor conf 指向 :5000 (非 :5050)"
|
||
ansible.builtin.command:
|
||
cmd: "grep -c ':5050' /etc/nginx/sites-enabled/harbor.conf"
|
||
register: harbor_conf_check
|
||
changed_when: false
|
||
failed_when: false
|
||
when: harbor_nginx.stat.exists
|
||
tags: nginx
|
||
|
||
- name: "Nginx | 警告:harbor conf 仍指向 :5050"
|
||
ansible.builtin.debug:
|
||
msg: "⚠️ harbor nginx conf 仍有 :5050,請確認已修正為 :5000"
|
||
when: harbor_nginx.stat.exists and harbor_conf_check.stdout != "0"
|
||
tags: nginx
|
||
|
||
# ========================================================================
|
||
# Backup / offsite source-of-truth
|
||
# ========================================================================
|
||
- name: "Backup | 確認 /backup/scripts 存在"
|
||
ansible.builtin.file:
|
||
path: /backup/scripts
|
||
state: directory
|
||
owner: wooo
|
||
group: wooo
|
||
mode: "0755"
|
||
tags: backup_jobs
|
||
|
||
- name: "Backup | 部署 110 備份腳本"
|
||
ansible.builtin.copy:
|
||
src: "{{ playbook_dir }}/../../../scripts/backup/{{ item }}"
|
||
dest: "/backup/scripts/{{ item }}"
|
||
owner: wooo
|
||
group: wooo
|
||
mode: "0755"
|
||
loop:
|
||
- common.sh
|
||
- backup-all.sh
|
||
- backup-status.sh
|
||
- backup-gitea.sh
|
||
- backup-harbor.sh
|
||
- backup-momo.sh
|
||
- backup-awoooi.sh
|
||
- backup-awoooi-frequent.sh
|
||
- backup-configs.sh
|
||
- sync-offsite-backups.sh
|
||
- offsite-escrow-evidence-report.sh
|
||
- verify-offsite-full-sync.sh
|
||
tags: backup_jobs
|
||
|
||
- name: "Backup | 安裝 AWOOOI daily backup Telegram heartbeat"
|
||
ansible.builtin.cron:
|
||
name: "AWOOOI daily backup Telegram heartbeat"
|
||
user: wooo
|
||
minute: "5"
|
||
hour: "6"
|
||
job: "/backup/scripts/backup-status.sh >/tmp/awoooi-backup-status.cron.log 2>&1"
|
||
tags: backup_jobs
|
||
|
||
- name: "Backup | 安裝 offsite escrow evidence report cron"
|
||
ansible.builtin.cron:
|
||
name: "AWOOOI offsite escrow evidence report"
|
||
user: wooo
|
||
minute: "10"
|
||
hour: "7"
|
||
job: "/backup/scripts/offsite-escrow-evidence-report.sh --no-color >/tmp/awoooi-offsite-escrow-evidence.cron.log 2>&1"
|
||
tags: backup_jobs
|
||
|
||
- name: "Backup | 安裝 offsite full sync verifier cron"
|
||
ansible.builtin.cron:
|
||
name: "AWOOOI offsite full sync verifier"
|
||
user: wooo
|
||
minute: "20"
|
||
hour: "7"
|
||
job: "/backup/scripts/verify-offsite-full-sync.sh --write-textfile --no-color >/tmp/awoooi-offsite-full-sync-verify.cron.log 2>&1"
|
||
tags: backup_jobs
|