对齐文件规范
This commit is contained in:
@@ -1,10 +0,0 @@
|
||||
- name: "00-01 noop verify"
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
doc_id: "00-01"
|
||||
doc_filename: "00-01-k3s-基础概念.md"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
- name: "00-04 noop verify"
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
doc_id: "00-04"
|
||||
doc_filename: "00-04-部署环境说明.md"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
|
||||
@@ -1,10 +1,128 @@
|
||||
- name: "01-03 noop verify"
|
||||
# SKIP_ARMV7=1(默认):仅 noop(文档 + ansible/files)。
|
||||
# SKIP_ARMV7=0 且设置 ARMV7_SSH:经 SSH 在 armv7/arm32 主机上 dnf 安装 docker 并校验(Fedora/RHEL 系,见 docs/01-03)。
|
||||
- name: 01-03 armv7 Docker(矩阵 + 可选远程安装)
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
doc_id: "01-03"
|
||||
doc_filename: "01-03-armv7-standalone-docker.md"
|
||||
skip_armv7: "{{ lookup('env', 'SKIP_ARMV7') | default('1', true) | trim }}"
|
||||
armv7_ssh: "{{ lookup('env', 'ARMV7_SSH') | default('', true) | trim }}"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
- name: Baseline docs/files checks
|
||||
block:
|
||||
- name: Assert docs file exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ repo_root }}/docs/{{ doc_filename }}"
|
||||
register: _doc_stat
|
||||
|
||||
- name: Fail when docs file missing
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- _doc_stat.stat.exists
|
||||
fail_msg: "docs file missing: docs/{{ doc_filename }}"
|
||||
|
||||
- name: Find matching ansible/files doc_id directory
|
||||
ansible.builtin.find:
|
||||
paths: "{{ repo_root }}/ansible/files"
|
||||
file_type: directory
|
||||
patterns: "{{ doc_id }}"
|
||||
use_regex: false
|
||||
register: _files_dirs
|
||||
|
||||
- name: Fail when ansible/files doc_id directory missing
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- _files_dirs.matched | int >= 1
|
||||
fail_msg: "ansible/files missing doc_id directory: ansible/files/{{ doc_id }}"
|
||||
|
||||
- name: Show noop verification summary
|
||||
ansible.builtin.debug:
|
||||
msg:
|
||||
- "doc_id={{ doc_id }}"
|
||||
- "doc={{ doc_filename }}"
|
||||
- "files_dirs={{ _files_dirs.files | map(attribute='path') | list }}"
|
||||
|
||||
- name: Verify cluster reachable (kubectl get nodes) [runbook baseline]
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
KUBECONFIG={{ k3s_kubeconfig | default('/etc/rancher/k3s/k3s.yaml') }} kubectl get nodes
|
||||
args:
|
||||
executable: /bin/bash
|
||||
delegate_to: "{{ groups['k3s_server'][0] }}"
|
||||
become: true
|
||||
run_once: true
|
||||
changed_when: false
|
||||
|
||||
- name: Verify core namespace exists (kube-system) [runbook baseline]
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
KUBECONFIG={{ k3s_kubeconfig | default('/etc/rancher/k3s/k3s.yaml') }} kubectl get ns kube-system
|
||||
args:
|
||||
executable: /bin/bash
|
||||
delegate_to: "{{ groups['k3s_server'][0] }}"
|
||||
become: true
|
||||
run_once: true
|
||||
changed_when: false
|
||||
|
||||
- name: Find YAML manifests under ansible/files doc_id dirs
|
||||
ansible.builtin.find:
|
||||
paths: "{{ _files_dirs.files | map(attribute='path') | list }}"
|
||||
file_type: file
|
||||
patterns:
|
||||
- "*.yml"
|
||||
- "*.yaml"
|
||||
recurse: true
|
||||
use_regex: false
|
||||
register: _files_manifests
|
||||
|
||||
- name: Show manifest count summary
|
||||
ansible.builtin.debug:
|
||||
msg:
|
||||
- "doc_id={{ doc_id }}"
|
||||
- "manifest_files={{ _files_manifests.matched | default(0) }}"
|
||||
- "manifest_paths={{ (_files_manifests.files | map(attribute='path') | list)[:12] }}"
|
||||
|
||||
- name: Server-side dry-run apply (kubectl apply --dry-run=server) [doc assertion]
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
KUBECONFIG={{ k3s_kubeconfig | default('/etc/rancher/k3s/k3s.yaml') }} \
|
||||
kubectl apply --dry-run=server -f "{{ item.path }}"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
loop: "{{ _files_manifests.files }}"
|
||||
loop_control:
|
||||
label: "{{ item.path }}"
|
||||
delegate_to: "{{ groups['k3s_server'][0] }}"
|
||||
become: true
|
||||
run_once: true
|
||||
changed_when: false
|
||||
when: (_files_manifests.matched | default(0) | int) > 0
|
||||
|
||||
- name: Fail when SKIP_ARMV7=0 but ARMV7_SSH empty
|
||||
ansible.builtin.fail:
|
||||
msg: "SKIP_ARMV7=0 但未设置 ARMV7_SSH(见 scripts/.env.verify.example)"
|
||||
when: skip_armv7 == '0' and armv7_ssh | length == 0
|
||||
|
||||
- name: Note skipping remote arm install
|
||||
ansible.builtin.debug:
|
||||
msg: "SKIP_ARMV7={{ skip_armv7 }}:跳过 arm 远程安装。若需安装:SKIP_ARMV7=0 且 export ARMV7_SSH='ssh -o BatchMode=yes user@arm-host'"
|
||||
when: skip_armv7 != '0' or armv7_ssh | length == 0
|
||||
|
||||
- name: Remote Docker install (dnf on arm)
|
||||
when: skip_armv7 == '0' and armv7_ssh | length > 0
|
||||
block:
|
||||
- name: Check docker on armv7 host
|
||||
ansible.builtin.shell: "{{ armv7_ssh }} docker version"
|
||||
register: armv7_docker_check
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Install Docker and enable service (dnf)
|
||||
ansible.builtin.shell: "{{ armv7_ssh }} 'sudo dnf install -y docker && sudo systemctl enable --now docker'"
|
||||
when: armv7_docker_check.rc != 0
|
||||
|
||||
- name: Verify docker version and ps
|
||||
ansible.builtin.shell: "{{ armv7_ssh }} docker version && {{ armv7_ssh }} docker ps -a"
|
||||
changed_when: false
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
- name: "01-04 noop verify"
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
doc_id: "01-04"
|
||||
doc_filename: "01-04-双控制节点ha.md"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
|
||||
@@ -1,10 +1,145 @@
|
||||
- name: "01-05 noop verify"
|
||||
# SKIP_ARMV7=1(默认):仅 noop。
|
||||
# SKIP_ARMV7=0 且 ARMV7_NFS_SSH 或 ARMV7_SSH:经 SSH 在 arm 上 dnf 装 nfs-utils、写 /etc/exports、exportfs(见 docs/01-05)。
|
||||
# 导出路径/网段:ARMV7_NFS_EXPORT_PATH(默认 /sdcard)、ARMV7_NFS_CLIENT_SUBNET(默认 192.168.2.0/24)
|
||||
- name: 01-05 armv7 NFS(矩阵 + 可选远程安装)
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
doc_id: "01-05"
|
||||
doc_filename: "01-05-armv7-nfs服务安装.md"
|
||||
skip_armv7: "{{ lookup('env', 'SKIP_ARMV7') | default('1', true) | trim }}"
|
||||
armv7_ssh: "{{ lookup('env', 'ARMV7_SSH') | default('', true) | trim }}"
|
||||
armv7_nfs_export_path: "{{ lookup('env', 'ARMV7_NFS_EXPORT_PATH') | default('/sdcard', true) | trim }}"
|
||||
armv7_nfs_client_subnet: "{{ lookup('env', 'ARMV7_NFS_CLIENT_SUBNET') | default('192.168.2.0/24', true) | trim }}"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
- name: Resolve ARMV7_NFS_SSH from env
|
||||
ansible.builtin.set_fact:
|
||||
armv7_nfs_ssh: >-
|
||||
{% set n = lookup('env', 'ARMV7_NFS_SSH') | default('', true) | trim %}
|
||||
{% set b = lookup('env', 'ARMV7_SSH') | default('', true) | trim %}
|
||||
{{ n if n | length > 0 else b }}
|
||||
|
||||
- name: Baseline docs/files checks
|
||||
block:
|
||||
- name: Assert docs file exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ repo_root }}/docs/{{ doc_filename }}"
|
||||
register: _doc_stat
|
||||
|
||||
- name: Fail when docs file missing
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- _doc_stat.stat.exists
|
||||
fail_msg: "docs file missing: docs/{{ doc_filename }}"
|
||||
|
||||
- name: Find matching ansible/files doc_id directory
|
||||
ansible.builtin.find:
|
||||
paths: "{{ repo_root }}/ansible/files"
|
||||
file_type: directory
|
||||
patterns: "{{ doc_id }}"
|
||||
use_regex: false
|
||||
register: _files_dirs
|
||||
|
||||
- name: Fail when ansible/files doc_id directory missing
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- _files_dirs.matched | int >= 1
|
||||
fail_msg: "ansible/files missing doc_id directory: ansible/files/{{ doc_id }}"
|
||||
|
||||
- name: Show noop verification summary
|
||||
ansible.builtin.debug:
|
||||
msg:
|
||||
- "doc_id={{ doc_id }}"
|
||||
- "doc={{ doc_filename }}"
|
||||
- "files_dirs={{ _files_dirs.files | map(attribute='path') | list }}"
|
||||
|
||||
- name: Verify cluster reachable (kubectl get nodes) [runbook baseline]
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
KUBECONFIG={{ k3s_kubeconfig | default('/etc/rancher/k3s/k3s.yaml') }} kubectl get nodes
|
||||
args:
|
||||
executable: /bin/bash
|
||||
delegate_to: "{{ groups['k3s_server'][0] }}"
|
||||
become: true
|
||||
run_once: true
|
||||
changed_when: false
|
||||
|
||||
- name: Verify core namespace exists (kube-system) [runbook baseline]
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
KUBECONFIG={{ k3s_kubeconfig | default('/etc/rancher/k3s/k3s.yaml') }} kubectl get ns kube-system
|
||||
args:
|
||||
executable: /bin/bash
|
||||
delegate_to: "{{ groups['k3s_server'][0] }}"
|
||||
become: true
|
||||
run_once: true
|
||||
changed_when: false
|
||||
|
||||
- name: Find YAML manifests under ansible/files doc_id dirs
|
||||
ansible.builtin.find:
|
||||
paths: "{{ _files_dirs.files | map(attribute='path') | list }}"
|
||||
file_type: file
|
||||
patterns:
|
||||
- "*.yml"
|
||||
- "*.yaml"
|
||||
recurse: true
|
||||
use_regex: false
|
||||
register: _files_manifests
|
||||
|
||||
- name: Show manifest count summary
|
||||
ansible.builtin.debug:
|
||||
msg:
|
||||
- "doc_id={{ doc_id }}"
|
||||
- "manifest_files={{ _files_manifests.matched | default(0) }}"
|
||||
- "manifest_paths={{ (_files_manifests.files | map(attribute='path') | list)[:12] }}"
|
||||
|
||||
- name: Server-side dry-run apply (kubectl apply --dry-run=server) [doc assertion]
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
KUBECONFIG={{ k3s_kubeconfig | default('/etc/rancher/k3s/k3s.yaml') }} \
|
||||
kubectl apply --dry-run=server -f "{{ item.path }}"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
loop: "{{ _files_manifests.files }}"
|
||||
loop_control:
|
||||
label: "{{ item.path }}"
|
||||
delegate_to: "{{ groups['k3s_server'][0] }}"
|
||||
become: true
|
||||
run_once: true
|
||||
changed_when: false
|
||||
when: (_files_manifests.matched | default(0) | int) > 0
|
||||
|
||||
- name: Fail when SKIP_ARMV7=0 but no ARMV7_SSH / ARMV7_NFS_SSH
|
||||
ansible.builtin.fail:
|
||||
msg: "SKIP_ARMV7=0 但未设置 ARMV7_SSH(或 ARMV7_NFS_SSH 指向 NFS 所在 arm 主机)"
|
||||
when: skip_armv7 == '0' and armv7_nfs_ssh | length == 0
|
||||
|
||||
- name: Note skipping remote NFS setup
|
||||
ansible.builtin.debug:
|
||||
msg: "SKIP_ARMV7={{ skip_armv7 }}:跳过 arm NFS 远程配置。"
|
||||
when: skip_armv7 != '0' or armv7_nfs_ssh | length == 0
|
||||
|
||||
- name: Remote NFS install (dnf on arm)
|
||||
when: skip_armv7 == '0' and armv7_nfs_ssh | length > 0
|
||||
block:
|
||||
- name: Install nfs-utils and enable nfs-server
|
||||
ansible.builtin.shell: "{{ armv7_nfs_ssh }} 'sudo dnf install -y nfs-utils && sudo systemctl enable --now nfs-server'"
|
||||
|
||||
- name: Check if export path already in /etc/exports
|
||||
ansible.builtin.shell: "{{ armv7_nfs_ssh }} sudo grep -qF {{ armv7_nfs_export_path | quote }} /etc/exports"
|
||||
register: armv7_exports_grep
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
|
||||
- name: Append NFS export line
|
||||
ansible.builtin.shell: "{{ armv7_nfs_ssh }} bash -c 'echo \"{{ armv7_nfs_export_path }} {{ armv7_nfs_client_subnet }}(rw,sync,no_subtree_check,no_root_squash)\" | sudo tee -a /etc/exports'"
|
||||
when: armv7_exports_grep.rc != 0
|
||||
|
||||
- name: Apply exportfs
|
||||
ansible.builtin.shell: "{{ armv7_nfs_ssh }} sudo exportfs -rav"
|
||||
changed_when: true
|
||||
|
||||
- name: Verify showmount
|
||||
ansible.builtin.shell: "{{ armv7_nfs_ssh }} showmount -e localhost"
|
||||
changed_when: false
|
||||
|
||||
@@ -1,3 +1,138 @@
|
||||
---
|
||||
# 单文件化说明:
|
||||
# - 01-06.yml 默认仍做“最小 verify”(kube-system pods)
|
||||
# - 如需“准备数据盘/安装 K3s”,必须显式开启开关:
|
||||
# -e k3s_do_prepare_storage=true # 内联原 01-06-prepare-storage.yml
|
||||
# -e k3s_do_install=true # 内联原 01-06-install.yml
|
||||
|
||||
- name: Prepare data disk and mount to k3s_data_dir (opt-in)
|
||||
hosts: k3s_nodes
|
||||
become: true
|
||||
vars:
|
||||
k3s_do_prepare_storage: "{{ k3s_do_prepare_storage | default(false) | bool }}"
|
||||
pre_tasks:
|
||||
- name: Gate - skip prepare storage when k3s_do_prepare_storage=false
|
||||
when: not k3s_do_prepare_storage
|
||||
block:
|
||||
- ansible.builtin.debug:
|
||||
msg: "[GATE] skipped doc_id=01-06 action=prepare-storage var=k3s_do_prepare_storage"
|
||||
- meta: end_play
|
||||
tasks:
|
||||
- name: Skip notice when storage prep disabled
|
||||
ansible.builtin.debug:
|
||||
msg: "k3s_prepare_storage is false — skipping (see group_vars/all.yml)"
|
||||
when: not (k3s_prepare_storage | default(false) | bool)
|
||||
|
||||
- name: Prepare block storage for k3s_data_dir
|
||||
when: k3s_prepare_storage | default(false) | bool
|
||||
block:
|
||||
- name: Require k3s_data_disk_device when k3s_prepare_storage is true
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- k3s_data_disk_device is defined
|
||||
- (k3s_data_disk_device | string | length) > 0
|
||||
fail_msg: "Set k3s_data_disk_device (e.g. /dev/vdb) in group_vars or host_vars"
|
||||
|
||||
- name: Verify k3s_data_disk_device is a block device
|
||||
ansible.builtin.command: test -b {{ k3s_data_disk_device }}
|
||||
changed_when: false
|
||||
|
||||
- name: Check whether k3s_data_dir is already a mountpoint
|
||||
ansible.builtin.command: mountpoint -q {{ k3s_data_dir }}
|
||||
register: mp_k3s
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Skip when k3s_data_dir already mounted
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ k3s_data_dir }} already mounted — skipping partitioning on {{ inventory_hostname }}"
|
||||
when: mp_k3s.rc == 0
|
||||
|
||||
- name: Install partitioning and filesystem tools
|
||||
ansible.builtin.package:
|
||||
name:
|
||||
- parted
|
||||
- e2fsprogs
|
||||
state: present
|
||||
when: mp_k3s.rc != 0
|
||||
|
||||
- name: Compute first partition path (nvme*n* -> p1, else 1)
|
||||
ansible.builtin.set_fact:
|
||||
k3s_data_partition: >-
|
||||
{{ k3s_data_disk_device }}{{ 'p1' if (k3s_data_disk_device | regex_search('nvme[0-9]+n[0-9]+$')) else '1' }}
|
||||
when: mp_k3s.rc != 0
|
||||
|
||||
- name: Create GPT and single ext4 partition
|
||||
ansible.builtin.command: >-
|
||||
parted -s {{ k3s_data_disk_device }} mklabel gpt mkpart primary ext4 0% 100%
|
||||
args:
|
||||
creates: "{{ k3s_data_partition }}"
|
||||
when: mp_k3s.rc != 0
|
||||
|
||||
- name: Wait for partition node in /dev
|
||||
ansible.builtin.wait_for:
|
||||
path: "{{ k3s_data_partition }}"
|
||||
state: present
|
||||
timeout: 60
|
||||
when: mp_k3s.rc != 0
|
||||
|
||||
- name: Detect existing filesystem on partition
|
||||
ansible.builtin.command: blkid -s TYPE -o value {{ k3s_data_partition }}
|
||||
register: fs_type
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
when: mp_k3s.rc != 0
|
||||
|
||||
- name: Create ext4 on partition
|
||||
ansible.builtin.command: mkfs.ext4 -F {{ k3s_data_partition }}
|
||||
when:
|
||||
- mp_k3s.rc != 0
|
||||
- (fs_type.stdout | default('') | trim | length) == 0
|
||||
|
||||
- name: Read UUID of partition
|
||||
ansible.builtin.command: blkid -s UUID -o value {{ k3s_data_partition }}
|
||||
register: blk_uuid
|
||||
changed_when: false
|
||||
when: mp_k3s.rc != 0
|
||||
|
||||
- name: Ensure mount directory exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ k3s_data_dir }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
when: mp_k3s.rc != 0
|
||||
|
||||
- name: Add fstab entry for k3s_data_dir
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/fstab
|
||||
regexp: "^UUID={{ blk_uuid.stdout | trim }}\\s"
|
||||
line: "UUID={{ blk_uuid.stdout | trim }} {{ k3s_data_dir }} ext4 defaults,nofail 0 2"
|
||||
create: true
|
||||
mode: "0644"
|
||||
when: mp_k3s.rc != 0
|
||||
|
||||
- name: Mount all from fstab
|
||||
ansible.builtin.command: mount -a
|
||||
changed_when: true
|
||||
when: mp_k3s.rc != 0
|
||||
|
||||
- name: Install K3s (opt-in)
|
||||
hosts: k3s_nodes
|
||||
become: true
|
||||
vars:
|
||||
k3s_do_install: "{{ k3s_do_install | default(false) | bool }}"
|
||||
pre_tasks:
|
||||
- name: Gate - skip install when k3s_do_install=false
|
||||
when: not k3s_do_install
|
||||
block:
|
||||
- ansible.builtin.debug:
|
||||
msg: "[GATE] skipped doc_id=01-06 action=install var=k3s_do_install"
|
||||
- meta: end_play
|
||||
tasks:
|
||||
- name: Placeholder (install content inlined in following plays)
|
||||
ansible.builtin.debug:
|
||||
msg: "[RUN] doc_id=01-06 action=install-start"
|
||||
|
||||
- name: "01-06 k3s baseline verify (kube-system pods)"
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
doc_id: "01-07"
|
||||
doc_filename: "01-07-openwrt-haproxy.md"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
|
||||
- name: Include noop doc verify tasks
|
||||
ansible.builtin.include_tasks: tasks/noop-doc-verify.yml
|
||||
|
||||
26
ansible/playbooks/verify/01-08.yml
Normal file
26
ansible/playbooks/verify/01-08.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
- name: "01-08 noop verify"
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
doc_id: "01-08"
|
||||
doc_filename: "01-08-双控制节点ha.md"
|
||||
tasks:
|
||||
- name: Assert docs file exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ repo_root }}/docs/{{ doc_filename }}"
|
||||
register: _doc
|
||||
|
||||
- name: Fail when docs file missing
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- _doc.stat.exists
|
||||
fail_msg: "docs missing: docs/{{ doc_filename }}"
|
||||
|
||||
- name: Summary
|
||||
ansible.builtin.debug:
|
||||
msg:
|
||||
- "doc_id={{ doc_id }} (manual runbook / HA exercise)"
|
||||
- "This verify case only asserts docs file exists."
|
||||
- "HA join/switch must be exercised manually per docs/{{ doc_filename }}."
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
- name: "02-00 noop verify"
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
doc_id: "02-00"
|
||||
doc_filename: "02-00-nginx-系列说明.md"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
run_once: true
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
manifest_src: "{{ playbook_dir }}/../../files/02-05-nginx-matrix/01-control-ingress.yaml"
|
||||
manifest_src: "{{ playbook_dir }}/../../files/02-05/01-control-ingress.yaml"
|
||||
manifest_dest: /tmp/nginx-m1.yaml
|
||||
tasks:
|
||||
- name: Copy manifest
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
run_once: true
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
manifest_src: "{{ playbook_dir }}/../../files/02-05-nginx-matrix/02-control-ingressroute.yaml"
|
||||
manifest_src: "{{ playbook_dir }}/../../files/02-05/02-control-ingressroute.yaml"
|
||||
manifest_dest: /tmp/nginx-m2.yaml
|
||||
tasks:
|
||||
- name: Copy manifest
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
run_once: true
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
manifest_src: "{{ playbook_dir }}/../../files/02-05-nginx-matrix/03-worker-ingress.yaml"
|
||||
manifest_src: "{{ playbook_dir }}/../../files/02-05/03-worker-ingress.yaml"
|
||||
manifest_dest: /tmp/nginx-m3.yaml
|
||||
tasks:
|
||||
- name: Copy manifest
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
run_once: true
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
manifest_src: "{{ playbook_dir }}/../../files/02-05-nginx-matrix/04-worker-ingressroute.yaml"
|
||||
manifest_src: "{{ playbook_dir }}/../../files/02-05/04-worker-ingressroute.yaml"
|
||||
manifest_dest: /tmp/nginx-m4.yaml
|
||||
tasks:
|
||||
- name: Copy manifest
|
||||
|
||||
@@ -1,65 +1,165 @@
|
||||
- import_playbook: "{{ playbook_dir }}/../nginx-matrix-deploy.yml"
|
||||
---
|
||||
# 合并说明:
|
||||
# - 原 02-05.yml 仅 import 02-05-deploy.yml + 02-01..02-04
|
||||
# - 现已把 02-05-deploy.yml 内联到本文件,保持 scripts/verify.sh run 02-05 的语义不变
|
||||
|
||||
- name: Verify 02-05 nginx matrix (HTTP paths)
|
||||
- name: Deploy nginx matrix (M1~M4)
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
verify_entry_base: "{{ nginx_entry_base | default('http://' ~ k3s_server_ip) }}"
|
||||
manifests_path: "{{ playbook_dir }}/../../files/02-05"
|
||||
tasks:
|
||||
- name: Verify M1~M4 deployments ready
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nginx-m1 -n default --timeout=120s
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nginx-m2 -n default --timeout=120s
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nginx-m3 -n default --timeout=180s
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nginx-m4 -n default --timeout=180s
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
- name: Ensure manifests path exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ manifests_path }}"
|
||||
register: manifests_stat
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
|
||||
- name: HTTP check 4 paths (expect 200 and X-Backend marker)
|
||||
ansible.builtin.shell: |
|
||||
set +e
|
||||
base="{{ verify_entry_base | trim | regex_replace('/+$','') }}"
|
||||
fail=0
|
||||
for id in 1 2 3 4; do
|
||||
url="$base/demo-m$id/"
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
echo "$url -> $code"
|
||||
if [ "$code" != "200" ]; then
|
||||
echo "$url -> unexpected http_code=$code"
|
||||
fail=1
|
||||
continue
|
||||
fi
|
||||
backend=$(curl -sS -D - -o /dev/null --connect-timeout 3 --max-time 8 "$url" 2>/dev/null \
|
||||
| awk -F': ' '/^X-Backend:/{print $2; exit}' \
|
||||
| tr -d '\r' || true)
|
||||
echo "$url -> X-Backend: ${backend:-<empty>}"
|
||||
if [ "$backend" != "M$id" ]; then
|
||||
fail=1
|
||||
fi
|
||||
done
|
||||
exit $fail
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
- name: Fail if manifests not found
|
||||
ansible.builtin.fail:
|
||||
msg: "manifests 未找到: {{ manifests_path }},请从仓库根目录或 ansible 同级执行"
|
||||
when: not manifests_stat.stat.exists
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
|
||||
- name: Teardown 02-05 nginx matrix (optional)
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
|
||||
tasks:
|
||||
- name: Delete nginx matrix resources when VERIFY_TEARDOWN=1
|
||||
when: verify_teardown == "1"
|
||||
- name: Ensure control-plane label on k3s_server nodes (for M1)
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f /tmp/nginx-matrix/ -R --ignore-not-found=true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl label node {{ item }} node-role.kubernetes.io/control-plane= --overwrite
|
||||
loop: "{{ groups['k3s_server'] | default([]) }}"
|
||||
|
||||
- name: Ensure worker label on k3s_worker nodes (for M3)
|
||||
ansible.builtin.shell: |
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl label node {{ item }} node-role.kubernetes.io/worker= --overwrite
|
||||
loop: "{{ groups['k3s_worker'] | default([]) }}"
|
||||
|
||||
- name: Copy nginx matrix manifests to server
|
||||
ansible.builtin.copy:
|
||||
src: "{{ manifests_path }}/"
|
||||
dest: /tmp/nginx-matrix/
|
||||
mode: "0644"
|
||||
|
||||
- name: Delete all nginx matrix deployments before apply
|
||||
ansible.builtin.shell: KUBECONFIG={{ k3s_kubeconfig }} kubectl delete deployment nginx-m1 nginx-m2 nginx-m3 nginx-m4 -n default --ignore-not-found=true
|
||||
register: del_nginx
|
||||
changed_when: "'deleted' in del_nginx.stdout"
|
||||
|
||||
- name: kubectl apply nginx matrix
|
||||
ansible.builtin.shell: KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f /tmp/nginx-matrix/ -R
|
||||
register: k8s_apply
|
||||
changed_when: "'configured' in k8s_apply.stdout or 'created' in k8s_apply.stdout"
|
||||
|
||||
- name: Restart nginx deployments so pods pick up ConfigMap (M1~M4 标识)
|
||||
ansible.builtin.shell: KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout restart deployment nginx-m1 nginx-m2 nginx-m3 nginx-m4 -n default
|
||||
register: restart_out
|
||||
changed_when: true
|
||||
|
||||
- name: Wait for nginx pods to be ready
|
||||
ansible.builtin.shell: |
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl wait --for=condition=ready pod \
|
||||
-l app=nginx-m1 --timeout=60s
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl wait --for=condition=ready pod \
|
||||
-l app=nginx-m2 --timeout=60s
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl wait --for=condition=ready pod \
|
||||
-l app=nginx-m3 --timeout=120s
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl wait --for=condition=ready pod \
|
||||
-l app=nginx-m4 --timeout=120s
|
||||
register: wait_result
|
||||
changed_when: false
|
||||
|
||||
- name: Verify nginx matrix
|
||||
ansible.builtin.shell: KUBECONFIG={{ k3s_kubeconfig }} kubectl get pod,svc,ing,ingressroute -n default -o wide
|
||||
register: verify
|
||||
changed_when: false
|
||||
|
||||
- name: ">>> nginx matrix 资源"
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ item }}"
|
||||
loop: "{{ verify.stdout_lines }}"
|
||||
|
||||
- name: 验证 Pod 节点分布(M1/M2 应在控制节点,M3/M4 应在工作节点)
|
||||
ansible.builtin.shell: |
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl get pod -n default -o custom-columns='NAME:.metadata.name,APP:.metadata.labels.app,NODE:.spec.nodeName' | grep -E '^(NAME|nginx-m)'
|
||||
register: pod_placement
|
||||
changed_when: false
|
||||
|
||||
- name: ">>> Pod 节点分布"
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ item }}"
|
||||
loop: "{{ pod_placement.stdout_lines }}"
|
||||
|
||||
- name: M1 容器内诊断(排查为何仍为 nginx 欢迎页)
|
||||
ansible.builtin.shell: |
|
||||
echo "========== 1. M1 容器内 /usr/share/nginx/html/ 目录 =========="
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl exec -n default deployment/nginx-m1 -- ls -la /usr/share/nginx/html/ 2>/dev/null || echo "(exec 失败)"
|
||||
echo ""
|
||||
echo "========== 2. M1 容器内 index.html 内容(前 5 行)=========="
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl exec -n default deployment/nginx-m1 -- cat /usr/share/nginx/html/index.html 2>/dev/null | head -5 || echo "(exec 失败)"
|
||||
echo ""
|
||||
echo "========== 3. M1 容器内 /etc/nginx/conf.d/ 目录 =========="
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl exec -n default deployment/nginx-m1 -- ls -la /etc/nginx/conf.d/ 2>/dev/null || echo "(exec 失败)"
|
||||
echo ""
|
||||
echo "========== 4. M1 容器内 default.conf 内容 =========="
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl exec -n default deployment/nginx-m1 -- cat /etc/nginx/conf.d/default.conf 2>/dev/null || echo "(exec 失败)"
|
||||
echo ""
|
||||
echo "========== 5. M1 容器内 nginx 生效配置中的 server 块(前 40 行)=========="
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl exec -n default deployment/nginx-m1 -- nginx -T 2>/dev/null | grep -A 200 "server {" | head -40 || echo "(exec 失败)"
|
||||
register: m1_diag
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: ">>> M1 容器内诊断结果(若 M1 仍为欢迎页,请根据此处输出排查)"
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ item }}"
|
||||
loop: "{{ m1_diag.stdout_lines }}"
|
||||
|
||||
- name: 验证 M1~M4 标识(Pod 内 index.html 含 Mx、响应头 X-Backend)
|
||||
ansible.builtin.shell: |
|
||||
base="{{ groups['k3s_nodes'] | map('extract', hostvars) | map(attribute='ansible_host') | first }}"
|
||||
for id in 1 2 3 4; do
|
||||
echo "=== M$id Pod 内 index.html 前 2 行 ==="
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl exec -n default deployment/nginx-m$id -- cat /usr/share/nginx/html/index.html 2>/dev/null | head -2 || echo "(exec 失败)"
|
||||
echo "=== M$id 响应头 X-Backend ==="
|
||||
curl -sI "http://$base/demo-m$id/" 2>/dev/null | grep -i x-backend || echo "(未看到 X-Backend)"
|
||||
echo ""
|
||||
done
|
||||
register: m_check
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: ">>> M1~M4 验证"
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ item }}"
|
||||
loop: "{{ m_check.stdout_lines }}"
|
||||
|
||||
- name: curl 验证(16 个目标:4 节点 × 4 路径)
|
||||
ansible.builtin.shell: |
|
||||
bases="{{ groups['k3s_nodes'] | map('extract', hostvars) | map(attribute='ansible_host') | join(' ') }}"
|
||||
count=0
|
||||
ok=0
|
||||
echo "=== 16 个目标 (4 节点 × 4 路径) ==="
|
||||
echo "节点 M1(控制+Ingress) M2(控制+IR) M3(工作+Ingress) M4(工作+IR)"
|
||||
for base in $bases; do
|
||||
m1=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 2 http://$base/demo-m1 2>/dev/null) || m1="fail"
|
||||
m2=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 2 http://$base/demo-m2 2>/dev/null) || m2="fail"
|
||||
m3=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 2 http://$base/demo-m3 2>/dev/null) || m3="fail"
|
||||
m4=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 2 http://$base/demo-m4 2>/dev/null) || m4="fail"
|
||||
printf "%-12s %-16s %-11s %-16s %s\n" "$base" "$m1" "$m2" "$m3" "$m4"
|
||||
for c in $m1 $m2 $m3 $m4; do count=$((count+1)); [ "$c" = "200" ] && ok=$((ok+1)); done
|
||||
done
|
||||
echo "---"
|
||||
echo "共验证 $count 个目标,$ok 个返回 200"
|
||||
register: curl_result
|
||||
changed_when: false
|
||||
|
||||
- name: ">>> curl 矩阵"
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ item }}"
|
||||
loop: "{{ curl_result.stdout_lines }}"
|
||||
|
||||
- import_playbook: 02-01.yml
|
||||
- import_playbook: 02-02.yml
|
||||
- import_playbook: 02-03.yml
|
||||
- import_playbook: 02-04.yml
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
- name: Deploy 03-01 Traefik Dashboard
|
||||
---
|
||||
- name: Deploy 03-01 Traefik Dashboard (HelmChartConfig + IngressRoute)
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
manifest_src: "{{ playbook_dir }}/../../files/03-01-traefik-dashboard/traefik-dashboard.yaml"
|
||||
manifest_src: "{{ playbook_dir }}/../../files/03-01/traefik-dashboard.yaml"
|
||||
manifest_dest: /tmp/traefik-dashboard.yaml
|
||||
tasks:
|
||||
- name: Copy manifest
|
||||
@@ -13,34 +14,41 @@
|
||||
dest: "{{ manifest_dest }}"
|
||||
mode: "0644"
|
||||
|
||||
- name: Apply manifest + restart traefik
|
||||
- name: Apply manifest
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ manifest_dest }}
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n kube-system rollout restart deploy/traefik || true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
- name: Verify 03-01 Traefik Dashboard
|
||||
- name: Verify 03-01 Traefik Dashboard (resource existence + rollout)
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
tasks:
|
||||
- name: Wait traefik rollout
|
||||
- name: Rollout status traefik (kube-system)
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n kube-system rollout status deploy/traefik --timeout=180s
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/traefik -n kube-system --timeout=240s
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert traefik-dashboard IngressRoute exists
|
||||
- name: Assert HelmChartConfig exists
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n kube-system get ingressroute.traefik.io/traefik-dashboard
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n kube-system get helmchartconfig traefik
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert IngressRoute traefik-dashboard exists
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n kube-system get ingressroute traefik-dashboard
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
@@ -1,74 +1,212 @@
|
||||
- name: Deploy 03-02 Traefik ACME (gated)
|
||||
---
|
||||
- name: Deploy 03-02 Traefik ACME (HelmChartConfig)
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
manifest_src: "{{ playbook_dir }}/../../files/03-02-traefik-acme/traefik-acme.yaml"
|
||||
manifest_src: "{{ playbook_dir }}/../../files/03-02/traefik-acme.yaml"
|
||||
manifest_dest: /tmp/traefik-acme.yaml
|
||||
acme_email: "{{ ACME_EMAIL | default('') }}"
|
||||
acme_email: "{{ lookup('env', 'ACME_EMAIL') | default('', true) }}"
|
||||
tasks:
|
||||
- name: "Gate - require ACME_EMAIL and cloudflare-api-token secret"
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
test -n "{{ acme_email }}"
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n kube-system get secret cloudflare-api-token >/dev/null
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: acme_gate
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
- name: "Gate - skip apply when ACME_EMAIL missing"
|
||||
when: acme_email | trim == ""
|
||||
block:
|
||||
- ansible.builtin.debug:
|
||||
msg: "[GATE] skipped doc_id=03-02 reason=missing_env missing=ACME_EMAIL"
|
||||
- meta: end_play
|
||||
|
||||
- name: Copy manifest
|
||||
when: acme_gate.rc == 0
|
||||
ansible.builtin.copy:
|
||||
src: "{{ manifest_src }}"
|
||||
dest: "{{ manifest_dest }}"
|
||||
mode: "0644"
|
||||
|
||||
- name: Replace ACME email placeholder
|
||||
when: acme_gate.rc == 0
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
sed -i "s/<YOUR_REAL_EMAIL>/{{ acme_email | replace('/', '\\/') }}/g" {{ manifest_dest }}
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
ansible.builtin.replace:
|
||||
path: "{{ manifest_dest }}"
|
||||
regexp: "<YOUR_REAL_EMAIL>"
|
||||
replace: "{{ acme_email | trim }}"
|
||||
|
||||
- name: Apply manifest + restart traefik
|
||||
when: acme_gate.rc == 0
|
||||
- name: Apply manifest
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ manifest_dest }}
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n kube-system rollout restart deploy/traefik || true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
- name: Verify 03-02 Traefik ACME (gated)
|
||||
- name: Deploy or cleanup nginx matrix TLS (opt-in)
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
acme_email: "{{ ACME_EMAIL | default('') }}"
|
||||
nginx_matrix_tls_enable: "{{ nginx_matrix_tls_enable | default(false) | bool }}"
|
||||
manifests_path: "{{ playbook_dir }}/../../files/03-02"
|
||||
tls_domains:
|
||||
- test01.jackadam.top
|
||||
- test02.jackadam.top
|
||||
- test03.jackadam.top
|
||||
- test04.jackadam.top
|
||||
pre_tasks:
|
||||
- name: Gate - skip nginx matrix TLS when nginx_matrix_tls_enable=false
|
||||
when: not nginx_matrix_tls_enable
|
||||
block:
|
||||
- ansible.builtin.debug:
|
||||
msg: "[GATE] skipped doc_id=03-02 action=nginx-matrix-tls var=nginx_matrix_tls_enable"
|
||||
- meta: end_play
|
||||
tasks:
|
||||
- name: "Gate - require ACME_EMAIL and cloudflare-api-token secret"
|
||||
- name: Deploy nginx matrix TLS (mode=deploy)
|
||||
when: (mode | default('deploy')) == 'deploy'
|
||||
block:
|
||||
- name: Ensure manifests path exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ manifests_path }}"
|
||||
register: manifests_stat
|
||||
|
||||
- name: Fail if manifests not found
|
||||
ansible.builtin.fail:
|
||||
msg: "manifests 未找到: {{ manifests_path }},请从仓库根目录或 ansible 同级执行"
|
||||
when: not manifests_stat.stat.exists
|
||||
|
||||
- name: Ensure control-plane label on k3s_server nodes (for M1)
|
||||
ansible.builtin.shell: |
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl label node {{ item }} node-role.kubernetes.io/control-plane= --overwrite
|
||||
loop: "{{ groups['k3s_server'] | default([]) }}"
|
||||
|
||||
- name: Ensure worker label on k3s_worker nodes (for M3)
|
||||
ansible.builtin.shell: |
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl label node {{ item }} node-role.kubernetes.io/worker= --overwrite
|
||||
loop: "{{ groups['k3s_worker'] | default([]) }}"
|
||||
|
||||
- name: Copy nginx matrix TLS manifests to server
|
||||
ansible.builtin.copy:
|
||||
src: "{{ manifests_path }}/"
|
||||
dest: /tmp/nginx-matrix-tls/
|
||||
mode: "0644"
|
||||
|
||||
- name: Delete non-TLS nginx matrix if present (deployments, ingress, ingressroute, middleware, configmaps)
|
||||
ansible.builtin.shell: |
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete deployment,svc -n default nginx-m1 nginx-m2 nginx-m3 nginx-m4 --ignore-not-found=true
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete ingress -n default nginx-m1 nginx-m3 --ignore-not-found=true
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete ingressroute -n default nginx-m2 nginx-m4 --ignore-not-found=true
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete middleware -n default stripprefix-m1 stripprefix-m2 stripprefix-m3 stripprefix-m4 --ignore-not-found=true
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete configmap -n default nginx-m1-html nginx-m2-html nginx-m3-html nginx-m4-html --ignore-not-found=true
|
||||
register: del_non_tls
|
||||
changed_when: "'deleted' in del_non_tls.stdout"
|
||||
|
||||
- name: kubectl apply nginx matrix TLS + HTTP-only
|
||||
ansible.builtin.shell: KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f /tmp/nginx-matrix-tls/ -R
|
||||
register: k8s_apply
|
||||
changed_when: "'configured' in k8s_apply.stdout or 'created' in k8s_apply.stdout"
|
||||
|
||||
- name: Restart nginx deployments so pods pick up ConfigMap (M1~M4 标识)
|
||||
ansible.builtin.shell: KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout restart deployment nginx-m1 nginx-m2 nginx-m3 nginx-m4 -n default
|
||||
changed_when: true
|
||||
|
||||
- name: Wait for nginx pods to be ready
|
||||
ansible.builtin.shell: |
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl wait --for=condition=ready pod -l app=nginx-m1 --timeout=60s
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl wait --for=condition=ready pod -l app=nginx-m2 --timeout=60s
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl wait --for=condition=ready pod -l app=nginx-m3 --timeout=120s
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl wait --for=condition=ready pod -l app=nginx-m4 --timeout=120s
|
||||
changed_when: false
|
||||
|
||||
- name: Verify nginx matrix TLS resources
|
||||
ansible.builtin.shell: KUBECONFIG={{ k3s_kubeconfig }} kubectl get pod,svc,ing,ingressroute -n default -o wide
|
||||
register: verify_tls
|
||||
changed_when: false
|
||||
|
||||
- name: ">>> nginx matrix TLS 资源"
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ item }}"
|
||||
loop: "{{ verify_tls.stdout_lines }}"
|
||||
|
||||
- name: HTTP curl 验证(HTTP-only:16 个目标,所有节点 × 4 域名)
|
||||
ansible.builtin.shell: |
|
||||
bases="{{ groups['k3s_nodes'] | map('extract', hostvars) | map(attribute='ansible_host') | join(' ') }}"
|
||||
count=0
|
||||
ok=0
|
||||
echo "=== 16 个目标 (4 节点 × 4 域名) HTTP ==="
|
||||
echo "节点 M1(test01) M2(test02) M3(test03) M4(test04)"
|
||||
for base in $bases; do
|
||||
m1=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 http://test01.jackadam.top/ --resolve "test01.jackadam.top:80:$base" 2>/dev/null) || m1="fail"
|
||||
m2=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 http://test02.jackadam.top/ --resolve "test02.jackadam.top:80:$base" 2>/dev/null) || m2="fail"
|
||||
m3=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 http://test03.jackadam.top/ --resolve "test03.jackadam.top:80:$base" 2>/dev/null) || m3="fail"
|
||||
m4=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 http://test04.jackadam.top/ --resolve "test04.jackadam.top:80:$base" 2>/dev/null) || m4="fail"
|
||||
printf "%-12s %-14s %-14s %-14s %s\n" "$base" "$m1" "$m2" "$m3" "$m4"
|
||||
for c in $m1 $m2 $m3 $m4; do count=$((count+1)); [ "$c" = "200" ] && ok=$((ok+1)); done
|
||||
done
|
||||
echo "---"
|
||||
echo "共验证 $count 个目标,$ok 个返回 200"
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: HTTPS curl 验证(16 个目标:所有节点 × 4 域名,所有节点均为入口点)
|
||||
ansible.builtin.shell: |
|
||||
bases="{{ groups['k3s_nodes'] | map('extract', hostvars) | map(attribute='ansible_host') | join(' ') }}"
|
||||
count=0
|
||||
ok=0
|
||||
echo "=== 16 个目标 (4 节点 × 4 域名) HTTPS ==="
|
||||
echo "节点 M1(test01) M2(test02) M3(test03) M4(test04)"
|
||||
for base in $bases; do
|
||||
m1=$(curl -sk -o /dev/null -w "%{http_code}" --connect-timeout 5 https://test01.jackadam.top/ --resolve "test01.jackadam.top:443:$base" 2>/dev/null) || m1="fail"
|
||||
m2=$(curl -sk -o /dev/null -w "%{http_code}" --connect-timeout 5 https://test02.jackadam.top/ --resolve "test02.jackadam.top:443:$base" 2>/dev/null) || m2="fail"
|
||||
m3=$(curl -sk -o /dev/null -w "%{http_code}" --connect-timeout 5 https://test03.jackadam.top/ --resolve "test03.jackadam.top:443:$base" 2>/dev/null) || m3="fail"
|
||||
m4=$(curl -sk -o /dev/null -w "%{http_code}" --connect-timeout 5 https://test04.jackadam.top/ --resolve "test04.jackadam.top:443:$base" 2>/dev/null) || m4="fail"
|
||||
printf "%-12s %-14s %-14s %-14s %s\n" "$base" "$m1" "$m2" "$m3" "$m4"
|
||||
for c in $m1 $m2 $m3 $m4; do count=$((count+1)); [ "$c" = "200" ] && ok=$((ok+1)); done
|
||||
done
|
||||
echo "---"
|
||||
echo "共验证 $count 个目标,$ok 个返回 200"
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Cleanup nginx matrix TLS (mode=cleanup)
|
||||
when: (mode | default('deploy')) == 'cleanup'
|
||||
block:
|
||||
- name: Delete nginx matrix TLS + HTTP-only resources (deployments, ingress, ingressroute, configmaps)
|
||||
ansible.builtin.shell: |
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete deployment,svc -n default nginx-m1 nginx-m2 nginx-m3 nginx-m4 --ignore-not-found=true
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete ingress -n default nginx-m1 nginx-m3 nginx-m1-http nginx-m3-http --ignore-not-found=true
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete ingressroute -n default nginx-m2 nginx-m4 nginx-m2-http nginx-m4-http --ignore-not-found=true
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete configmap -n default nginx-m1-html nginx-m2-html nginx-m3-html nginx-m4-html --ignore-not-found=true
|
||||
register: del_tls
|
||||
changed_when: "'deleted' in del_tls.stdout"
|
||||
|
||||
- name: Remove copied nginx matrix TLS manifests directory
|
||||
ansible.builtin.file:
|
||||
path: /tmp/nginx-matrix-tls
|
||||
state: absent
|
||||
|
||||
- name: Verify 03-02 Traefik ACME (rollout + secret)
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
acme_email: "{{ lookup('env', 'ACME_EMAIL') | default('', true) }}"
|
||||
tasks:
|
||||
- name: "Gate - skip verify when ACME_EMAIL missing"
|
||||
when: acme_email | trim == ""
|
||||
block:
|
||||
- ansible.builtin.debug:
|
||||
msg: "[GATE] skipped doc_id=03-02 reason=missing_env missing=ACME_EMAIL"
|
||||
- meta: end_play
|
||||
|
||||
- name: Assert Cloudflare token secret exists
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
test -n "{{ acme_email }}"
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n kube-system get secret cloudflare-api-token >/dev/null
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n kube-system get secret cloudflare-api-token
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: acme_gate
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Wait traefik rollout
|
||||
when: acme_gate.rc == 0
|
||||
- name: Rollout status traefik (kube-system)
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n kube-system rollout status deploy/traefik --timeout=180s
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/traefik -n kube-system --timeout=300s
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
@@ -80,19 +218,19 @@
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
|
||||
acme_email: "{{ lookup('env', 'ACME_EMAIL') | default('', true) }}"
|
||||
manifest_dest: /tmp/traefik-acme.yaml
|
||||
acme_email: "{{ ACME_EMAIL | default('') }}"
|
||||
tasks:
|
||||
- name: Skip teardown when gated
|
||||
when: acme_email | trim == ""
|
||||
meta: end_play
|
||||
|
||||
- name: Delete resources when VERIFY_TEARDOWN=1
|
||||
when: verify_teardown == "1"
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
# gated:只有在 deploy gate 通过且文件存在时才清理;否则跳过,避免 fail-fast。
|
||||
test -n "{{ acme_email }}"
|
||||
test -f "{{ manifest_dest }}"
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f {{ manifest_dest }} --ignore-not-found=true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
failed_when: false
|
||||
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
doc_id: "03-03"
|
||||
doc_filename: "03-03-k3s-traefik-dashboard-acme.md"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
|
||||
- name: Include noop doc verify tasks
|
||||
ansible.builtin.include_tasks: tasks/noop-doc-verify.yml
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
doc_id: "03-04"
|
||||
doc_filename: "03-04-k3s-cloudflare-tunnel-配置接入.md"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
|
||||
- name: Include noop doc verify tasks
|
||||
ansible.builtin.include_tasks: tasks/noop-doc-verify.yml
|
||||
|
||||
@@ -1,19 +1,62 @@
|
||||
- name: Deploy 03-05 local-path PVC demo
|
||||
---
|
||||
- name: Apply local-path-config lab JSON (opt-in)
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
manifest_src: "{{ playbook_dir }}/../../files/03-05-local-path-demo/local-path-pvc-demo.yaml"
|
||||
local_path_apply_lab_config_enabled: "{{ local_path_apply_lab_config | default(false) | bool }}"
|
||||
local_path_json_src: "{{ playbook_dir }}/../../files/03-05/local-path-config-lab.json"
|
||||
local_path_json_dest: /root/local-path-config-lab.json
|
||||
pre_tasks:
|
||||
- name: Gate - skip apply local-path lab config when local_path_apply_lab_config=false
|
||||
when: not local_path_apply_lab_config_enabled
|
||||
block:
|
||||
- ansible.builtin.debug:
|
||||
msg: "[GATE] skipped doc_id=03-05 action=apply-local-path-config var=local_path_apply_lab_config"
|
||||
- meta: end_play
|
||||
tasks:
|
||||
- name: Copy local-path lab json
|
||||
ansible.builtin.copy:
|
||||
src: "{{ local_path_json_src }}"
|
||||
dest: "{{ local_path_json_dest }}"
|
||||
mode: "0644"
|
||||
|
||||
- name: Apply local-path-config ConfigMap
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n kube-system create configmap local-path-config \
|
||||
--from-file=config.json={{ local_path_json_dest }} \
|
||||
--dry-run=client -o yaml | KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f -
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
- name: Restart local-path-provisioner if present
|
||||
ansible.builtin.shell: |
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n kube-system rollout restart deploy/local-path-provisioner
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: lp_restart
|
||||
failed_when: false
|
||||
changed_when: lp_restart.rc == 0
|
||||
|
||||
- name: Deploy 03-05 local-path pvc demo
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
manifest_src: "{{ playbook_dir }}/../../files/03-05/local-path-pvc-demo.yaml"
|
||||
manifest_dest: /tmp/local-path-pvc-demo.yaml
|
||||
tasks:
|
||||
- name: Copy manifest to server
|
||||
- name: Copy manifest
|
||||
ansible.builtin.copy:
|
||||
src: "{{ manifest_src }}"
|
||||
dest: "{{ manifest_dest }}"
|
||||
mode: "0644"
|
||||
|
||||
- name: kubectl apply
|
||||
- name: Apply manifest
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ manifest_dest }}
|
||||
@@ -21,32 +64,34 @@
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
- name: Verify 03-05 local-path PVC demo
|
||||
- name: Verify 03-05 local-path pvc demo
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
tasks:
|
||||
- name: Wait nginx-local-pvc-demo deployment ready
|
||||
- name: Wait pvc Bound
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nginx-local-pvc-demo -n default --timeout=180s
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl get pvc local-pvc-demo -n default -o jsonpath='{.status.phase}'
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: pvc_phase
|
||||
changed_when: false
|
||||
until: pvc_phase.stdout | trim == "Bound"
|
||||
retries: 30
|
||||
delay: 2
|
||||
|
||||
- name: Rollout status nginx-local-pvc-demo
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nginx-local-pvc-demo -n default --timeout=240s
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert PVC is Bound
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
phase=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get pvc local-pvc-demo -n default -o jsonpath='{.status.phase}')
|
||||
echo "pvc phase=$phase"
|
||||
test "$phase" = "Bound"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Teardown 03-05 local-path PVC demo (optional)
|
||||
- name: Teardown 03-05 local-path pvc demo (optional)
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
|
||||
@@ -1,34 +1,41 @@
|
||||
- name: Deploy 03-06 NFS PV/PVC demo (gated)
|
||||
---
|
||||
- name: Deploy 03-06 nfs pv+pvc demo (gated by env)
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
nfs_server_ip: "{{ NFS_SERVER_IP | default('') }}"
|
||||
nfs_export_path: "{{ NFS_EXPORT_PATH | default('') }}"
|
||||
manifest_src: "{{ playbook_dir }}/../../files/03-06-nfs-demo/nfs-pv-pvc-demo.yaml"
|
||||
manifest_src: "{{ playbook_dir }}/../../files/03-06/nfs-pv-pvc-demo.yaml"
|
||||
manifest_dest: /tmp/nfs-pv-pvc-demo.yaml
|
||||
nfs_server_ip: "{{ lookup('env', 'NFS_SERVER_IP') | default('', true) }}"
|
||||
nfs_export_path: "{{ lookup('env', 'NFS_EXPORT_PATH') | default('', true) }}"
|
||||
tasks:
|
||||
- name: "Gate - require NFS_SERVER_IP and NFS_EXPORT_PATH"
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
test -n "{{ nfs_server_ip }}"
|
||||
test -n "{{ nfs_export_path }}"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: nfs_gate
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
- name: "Gate - skip apply when NFS vars missing"
|
||||
when: (nfs_server_ip | trim == "") or (nfs_export_path | trim == "")
|
||||
block:
|
||||
- ansible.builtin.debug:
|
||||
msg: "[GATE] skipped doc_id=03-06 reason=missing_env missing=NFS_SERVER_IP,NFS_EXPORT_PATH"
|
||||
- meta: end_play
|
||||
|
||||
- name: Copy manifest
|
||||
when: nfs_gate.rc == 0
|
||||
ansible.builtin.copy:
|
||||
src: "{{ manifest_src }}"
|
||||
dest: "{{ manifest_dest }}"
|
||||
mode: "0644"
|
||||
|
||||
- name: kubectl apply
|
||||
when: nfs_gate.rc == 0
|
||||
- name: Replace NFS placeholders
|
||||
ansible.builtin.replace:
|
||||
path: "{{ manifest_dest }}"
|
||||
regexp: "<NFS_SERVER_IP>"
|
||||
replace: "{{ nfs_server_ip | trim }}"
|
||||
|
||||
- name: Replace NFS export path placeholder
|
||||
ansible.builtin.replace:
|
||||
path: "{{ manifest_dest }}"
|
||||
regexp: "<NFS_EXPORT_PATH>"
|
||||
replace: "{{ nfs_export_path | trim }}"
|
||||
|
||||
- name: Apply manifest
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ manifest_dest }}
|
||||
@@ -36,59 +43,55 @@
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
- name: Verify 03-06 NFS PV/PVC demo (gated)
|
||||
- name: Verify 03-06 nfs pvc demo (Bound)
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
nfs_server_ip: "{{ NFS_SERVER_IP | default('') }}"
|
||||
nfs_export_path: "{{ NFS_EXPORT_PATH | default('') }}"
|
||||
nfs_server_ip: "{{ lookup('env', 'NFS_SERVER_IP') | default('', true) }}"
|
||||
nfs_export_path: "{{ lookup('env', 'NFS_EXPORT_PATH') | default('', true) }}"
|
||||
tasks:
|
||||
- name: "Gate - require NFS_SERVER_IP and NFS_EXPORT_PATH"
|
||||
- name: "Gate - skip verify when NFS vars missing"
|
||||
when: (nfs_server_ip | trim == "") or (nfs_export_path | trim == "")
|
||||
block:
|
||||
- ansible.builtin.debug:
|
||||
msg: "[GATE] skipped doc_id=03-06 reason=missing_env missing=NFS_SERVER_IP,NFS_EXPORT_PATH"
|
||||
- meta: end_play
|
||||
|
||||
- name: Wait pvc Bound
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
test -n "{{ nfs_server_ip }}"
|
||||
test -n "{{ nfs_export_path }}"
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl get pvc nfs-pvc-demo -n default -o jsonpath='{.status.phase}'
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: nfs_gate
|
||||
register: pvc_phase
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
until: pvc_phase.stdout | trim == "Bound"
|
||||
retries: 40
|
||||
delay: 3
|
||||
|
||||
- name: Assert PVC Bound
|
||||
when: nfs_gate.rc == 0
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
phase=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl -n default get pvc nfs-pvc-demo -o jsonpath='{.status.phase}')
|
||||
echo "pvc phase=$phase"
|
||||
test "$phase" = "Bound"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Teardown 03-06 NFS PV/PVC demo (optional)
|
||||
- name: Teardown 03-06 nfs pv+pvc demo (optional)
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
|
||||
nfs_server_ip: "{{ lookup('env', 'NFS_SERVER_IP') | default('', true) }}"
|
||||
nfs_export_path: "{{ lookup('env', 'NFS_EXPORT_PATH') | default('', true) }}"
|
||||
manifest_dest: /tmp/nfs-pv-pvc-demo.yaml
|
||||
nfs_server_ip: "{{ NFS_SERVER_IP | default('') }}"
|
||||
nfs_export_path: "{{ NFS_EXPORT_PATH | default('') }}"
|
||||
tasks:
|
||||
- name: Skip teardown when gated
|
||||
when: (nfs_server_ip | trim == "") or (nfs_export_path | trim == "")
|
||||
meta: end_play
|
||||
|
||||
- name: Delete resources when VERIFY_TEARDOWN=1
|
||||
when: verify_teardown == "1"
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
# gated:只有在 deploy gate 通过且文件存在时才清理;否则跳过,避免 fail-fast。
|
||||
test -n "{{ nfs_server_ip }}"
|
||||
test -n "{{ nfs_export_path }}"
|
||||
test -f "{{ manifest_dest }}"
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f {{ manifest_dest }} --ignore-not-found=true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
failed_when: false
|
||||
|
||||
|
||||
@@ -1,4 +1,248 @@
|
||||
- import_playbook: "{{ playbook_dir }}/../longhorn-install.yml"
|
||||
---
|
||||
- name: Longhorn node packages (iSCSI, NFS client)
|
||||
hosts: k3s_nodes
|
||||
become: true
|
||||
tasks:
|
||||
- name: Install Longhorn OS dependencies
|
||||
when: longhorn_install_node_packages | default(true) | bool
|
||||
block:
|
||||
- name: Install iscsi + nfs (dnf/yum)
|
||||
ansible.builtin.package:
|
||||
name:
|
||||
- iscsi-initiator-utils
|
||||
- nfs-utils
|
||||
state: present
|
||||
|
||||
- name: Enable iscsid
|
||||
ansible.builtin.systemd:
|
||||
name: iscsid
|
||||
enabled: true
|
||||
state: started
|
||||
|
||||
- name: Ensure Longhorn data subdirectory exists on all nodes
|
||||
ansible.builtin.file:
|
||||
path: "{{ k3s_data_dir }}/longhorn"
|
||||
state: directory
|
||||
mode: "0700"
|
||||
|
||||
- name: Pre-pull Longhorn images on all nodes (optional, avoid DockerHub EOF/ImagePullBackOff)
|
||||
when: longhorn_prepull_images | default(true) | bool
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
CTR="ctr --address /run/k3s/containerd/containerd.sock -n k8s.io"
|
||||
|
||||
imgs=(
|
||||
"docker.io/longhornio/longhorn-manager:v{{ longhorn_chart_version }}"
|
||||
"docker.io/longhornio/longhorn-ui:v{{ longhorn_chart_version }}"
|
||||
"docker.io/longhornio/longhorn-share-manager:v{{ longhorn_chart_version }}"
|
||||
"docker.io/longhornio/longhorn-engine:v{{ longhorn_chart_version }}"
|
||||
"docker.io/longhornio/longhorn-instance-manager:v{{ longhorn_chart_version }}"
|
||||
"docker.io/longhornio/backing-image-manager:v{{ longhorn_chart_version }}"
|
||||
"docker.io/longhornio/support-bundle-kit:v0.0.45"
|
||||
)
|
||||
|
||||
for img in "${imgs[@]}"; do
|
||||
ok=0
|
||||
for i in 1 2 3 4 5; do
|
||||
echo "[pull] $img (try $i/5)"
|
||||
if $CTR images pull "$img"; then
|
||||
ok=1
|
||||
break
|
||||
fi
|
||||
sleep $((i * 3))
|
||||
done
|
||||
if [ "$ok" -ne 1 ]; then
|
||||
echo "[ERR] failed pulling $img after retries"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
- name: Install Longhorn with Helm on first server
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
longhorn_values_src: "{{ playbook_dir }}/../../files/03-07/values-lab.yaml"
|
||||
longhorn_values_dest: /root/longhorn-values-lab.yaml
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
tasks:
|
||||
- name: Install helm package (Fedora/RHEL family)
|
||||
ansible.builtin.package:
|
||||
name: helm
|
||||
state: present
|
||||
ignore_errors: true
|
||||
register: helm_pkg
|
||||
|
||||
- name: Hint if helm package install failed (install Helm 3 manually if needed)
|
||||
ansible.builtin.debug:
|
||||
msg: "dnf/yum 未装上 helm 时,请见 https://helm.sh/docs/intro/install/"
|
||||
when: helm_pkg.failed | default(false)
|
||||
|
||||
- name: Fail if helm binary still unavailable
|
||||
ansible.builtin.command: which helm
|
||||
register: helm_which
|
||||
changed_when: false
|
||||
failed_when: helm_which.rc != 0
|
||||
|
||||
- name: Copy lab values to server
|
||||
ansible.builtin.copy:
|
||||
src: "{{ longhorn_values_src }}"
|
||||
dest: "{{ longhorn_values_dest }}"
|
||||
mode: "0600"
|
||||
|
||||
- name: Ensure longhorn-system namespace is not stuck Terminating (force finalize if needed)
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
export KUBECONFIG={{ k3s_kubeconfig }}
|
||||
ns="longhorn-system"
|
||||
phase="$(kubectl get ns "$ns" -o jsonpath='{.status.phase}' 2>/dev/null || true)"
|
||||
if [ "$phase" = "Terminating" ]; then
|
||||
echo "[WARN] namespace $ns is Terminating; force finalize to unblock install"
|
||||
kubectl get ns "$ns" -o json > /tmp/ns.json
|
||||
python3 -c "import json; obj=json.load(open('/tmp/ns.json')); obj.setdefault('spec',{}); obj['spec']['finalizers']=[]; json.dump(obj, open('/tmp/ns-finalize.json','w'))"
|
||||
kubectl replace --raw \"/api/v1/namespaces/$ns/finalize\" -f /tmp/ns-finalize.json >/dev/null
|
||||
fi
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
failed_when: false
|
||||
|
||||
- name: Ensure longhorn Helm repo
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
if ! helm repo list 2>/dev/null | grep -q '^longhorn'; then
|
||||
helm repo add longhorn https://charts.longhorn.io
|
||||
fi
|
||||
helm repo update
|
||||
environment:
|
||||
KUBECONFIG: "{{ k3s_kubeconfig }}"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
- name: Delete leftover longhorn PriorityClass (cluster-scoped) to avoid Helm ownership conflicts
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete priorityclass longhorn-critical --ignore-not-found=true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
failed_when: false
|
||||
|
||||
- name: Delete leftover Longhorn CRDs (cluster-scoped, opt-in)
|
||||
when: longhorn_force_crd_reset | default(false) | bool
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
export KUBECONFIG={{ k3s_kubeconfig }}
|
||||
crd_list=\"$(kubectl get crd -o name 2>/dev/null | grep 'longhorn.io' || true)\"
|
||||
if [ -n \"$crd_list\" ]; then
|
||||
echo \"$crd_list\" | while read -r crd; do
|
||||
[ -z \"$crd\" ] && continue
|
||||
timeout 20s kubectl delete \"$crd\" --ignore-not-found=true || true
|
||||
done
|
||||
fi
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
failed_when: false
|
||||
|
||||
- name: Delete leftover Longhorn ClusterRole/ClusterRoleBinding (cluster-scoped)
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
export KUBECONFIG={{ k3s_kubeconfig }}
|
||||
|
||||
role_list=\"$(kubectl get clusterrole -o name 2>/dev/null | grep 'longhorn' || true)\"
|
||||
if [ -n \"$role_list\" ]; then
|
||||
echo \"$role_list\" | while read -r role; do
|
||||
[ -z \"$role\" ] && continue
|
||||
timeout 20s kubectl delete \"$role\" --ignore-not-found=true || true
|
||||
done
|
||||
fi
|
||||
|
||||
binding_list=\"$(kubectl get clusterrolebinding -o name 2>/dev/null | grep 'longhorn' || true)\"
|
||||
if [ -n \"$binding_list\" ]; then
|
||||
echo \"$binding_list\" | while read -r binding; do
|
||||
[ -z \"$binding\" ] && continue
|
||||
timeout 20s kubectl delete \"$binding\" --ignore-not-found=true || true
|
||||
done
|
||||
fi
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
failed_when: false
|
||||
|
||||
- name: Cleanup leftover Helm release records for Longhorn (default + longhorn-system)
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
export KUBECONFIG={{ k3s_kubeconfig }}
|
||||
|
||||
for ns in longhorn-system default; do
|
||||
if helm -n \"$ns\" list --all 2>/dev/null | grep -q '^longhorn'; then
|
||||
timeout 120s helm -n \"$ns\" uninstall longhorn --no-hooks || true
|
||||
fi
|
||||
|
||||
sec_list=\"$(kubectl -n \"$ns\" get secret -o name 2>/dev/null | grep '^secret/sh\\.helm\\.release\\.v1\\.longhorn\\.' || true)\"
|
||||
if [ -n \"$sec_list\" ]; then
|
||||
echo \"$sec_list\" | xargs -n1 kubectl -n \"$ns\" delete --ignore-not-found=true
|
||||
fi
|
||||
done
|
||||
environment:
|
||||
KUBECONFIG: "{{ k3s_kubeconfig }}"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
failed_when: false
|
||||
|
||||
- name: Helm upgrade/install Longhorn(失败兜底:install --replace)
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
helm upgrade --install longhorn longhorn/longhorn --namespace longhorn-system --create-namespace -f {{ longhorn_values_dest }} --version {{ longhorn_chart_version }} --wait --timeout 15m || helm install --replace longhorn longhorn/longhorn --namespace longhorn-system --create-namespace -f {{ longhorn_values_dest }} --version {{ longhorn_chart_version }} --wait --timeout 15m
|
||||
environment:
|
||||
KUBECONFIG: "{{ k3s_kubeconfig }}"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: helm_longhorn
|
||||
changed_when: true
|
||||
|
||||
- name: Apply local-path-config lab defaults (optional)
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
local_path_json_src: "{{ playbook_dir }}/../../files/03-05-local-path-config/local-path-config-lab.json"
|
||||
local_path_json_dest: /root/local-path-config-lab.json
|
||||
tasks:
|
||||
- name: Apply local-path-config lab defaults (optional)
|
||||
when: longhorn_apply_local_path_lab | default(false) | bool
|
||||
block:
|
||||
- name: Copy local-path lab json
|
||||
ansible.builtin.copy:
|
||||
src: "{{ local_path_json_src }}"
|
||||
dest: "{{ local_path_json_dest }}"
|
||||
mode: "0644"
|
||||
|
||||
- name: Apply local-path-config ConfigMap
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n kube-system create configmap local-path-config \
|
||||
--from-file=config.json={{ local_path_json_dest }} \
|
||||
--dry-run=client -o yaml | KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f -
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
- name: Restart local-path-provisioner if present
|
||||
ansible.builtin.shell: |
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n kube-system rollout restart deploy/local-path-provisioner
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: lp_restart
|
||||
failed_when: false
|
||||
changed_when: lp_restart.rc == 0
|
||||
|
||||
- name: Verify 03-07 Longhorn (namespace pods)
|
||||
hosts: k3s_server
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
doc_id: "03-08"
|
||||
doc_filename: "03-08-k3s-ha-集群配置与切换.md"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
|
||||
- name: Include noop doc verify tasks
|
||||
ansible.builtin.include_tasks: tasks/noop-doc-verify.yml
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
doc_id: "03-09"
|
||||
doc_filename: "03-09-k3s-gitops-集群配置管理.md"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
|
||||
- name: Include noop doc verify tasks
|
||||
ansible.builtin.include_tasks: tasks/noop-doc-verify.yml
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
doc_id: "03-10"
|
||||
doc_filename: "03-10-k3s-traefik-custom-ports.md"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
|
||||
- name: Include noop doc verify tasks
|
||||
ansible.builtin.include_tasks: tasks/noop-doc-verify.yml
|
||||
|
||||
@@ -1,6 +1,45 @@
|
||||
- import_playbook: "{{ playbook_dir }}/../nodejs-demo-apply.yml"
|
||||
---
|
||||
- name: Apply nodejs-demo Kubernetes manifests
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
nodejs_demo_manifest: "04-01-nodejs-demo.yaml"
|
||||
manifests_dir: "{{ playbook_dir }}/../../files/04-01"
|
||||
tasks:
|
||||
- name: Ensure manifest file exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ manifests_dir }}/{{ nodejs_demo_manifest }}"
|
||||
register: nodejs_manifest_stat
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
|
||||
- name: Verify 04-01 nodejs demo (rollout + HTTP)
|
||||
- name: Fail if manifest not found
|
||||
ansible.builtin.fail:
|
||||
msg: "未找到 {{ manifests_dir }}/{{ nodejs_demo_manifest }},请从仓库根检查文件名"
|
||||
when: not nodejs_manifest_stat.stat.exists
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
|
||||
- name: Copy manifest to control plane
|
||||
ansible.builtin.copy:
|
||||
src: "{{ manifests_dir }}/{{ nodejs_demo_manifest }}"
|
||||
dest: "/tmp/{{ nodejs_demo_manifest }}"
|
||||
mode: "0644"
|
||||
|
||||
- name: kubectl apply nodejs-demo manifest
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f /tmp/{{ nodejs_demo_manifest }}
|
||||
register: nodejs_apply
|
||||
changed_when: "'configured' in nodejs_apply.stdout or 'created' in nodejs_apply.stdout"
|
||||
|
||||
- name: Show kubectl apply output
|
||||
ansible.builtin.debug:
|
||||
var: nodejs_apply.stdout_lines
|
||||
|
||||
- name: Verify 04-01 nodejs base (HTTP 200)
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
@@ -11,39 +50,21 @@
|
||||
- name: Rollout status nodejs-demo
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nodejs-demo -n default --timeout=180s
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nodejs-demo -n default --timeout=240s
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: HTTP check /node (expect 200 and Hello World)
|
||||
- name: HTTP check /node
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
base="{{ verify_entry_base | trim | regex_replace('/+$','') }}"
|
||||
url="$base/node"
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 --max-time 10 "$url" 2>/dev/null || echo "000")
|
||||
echo "$url -> $code"
|
||||
test "$code" = "200"
|
||||
body=$(curl -sS --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || true)
|
||||
echo "$body" | grep -q "Hello World from Node.js"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Teardown 04-01 nodejs demo (optional)
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
|
||||
tasks:
|
||||
- name: Delete nodejs-demo resources when VERIFY_TEARDOWN=1
|
||||
when: verify_teardown == "1"
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete deploy/nodejs-demo svc/nodejs-demo ing/nodejs-demo -n default --ignore-not-found=true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
- name: "04-02 noop verify"
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
- name: Deploy+Verify 04-02 nodejs ports + Service
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
doc_id: "04-02"
|
||||
doc_filename: "04-02-nodejs-镜像与运行命令.md"
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
|
||||
nodejs_manifest_src: "{{ playbook_dir }}/../../files/04-01/04-02-nodejs-demo.yaml"
|
||||
nodejs_manifest_dest: /tmp/nodejs-demo-04-02.yaml
|
||||
nodejs_verify_entry_base: "{{ nodejs_entry_base | default('http://' ~ k3s_server_ip) }}"
|
||||
nodejs_verify_path: "/node"
|
||||
nodejs_expected_target_port: 3000
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
- name: Include nodejs deploy+verify template
|
||||
ansible.builtin.include_tasks: tasks/nodejs-demo-deploy-verify.yml
|
||||
|
||||
|
||||
@@ -1,10 +1,91 @@
|
||||
- name: "04-03 noop verify"
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
- name: Deploy+Verify 04-03 nodejs image + command/args
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
doc_id: "04-03"
|
||||
doc_filename: "04-03-nodejs-环境变量与配置注入.md"
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
|
||||
nodejs_manifest_src: "{{ playbook_dir }}/../../files/04-01/04-03-nodejs-demo.yaml"
|
||||
nodejs_manifest_dest: /tmp/nodejs-demo-04-03.yaml
|
||||
nodejs_verify_entry_base: "{{ nodejs_entry_base | default('http://' ~ k3s_server_ip) }}"
|
||||
nodejs_verify_path: "/node"
|
||||
nodejs_expected_target_port: 8080
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
- name: Copy nodejs demo manifest
|
||||
ansible.builtin.copy:
|
||||
src: "{{ nodejs_manifest_src }}"
|
||||
dest: "{{ nodejs_manifest_dest }}"
|
||||
mode: "0644"
|
||||
|
||||
- name: Apply nodejs demo manifest
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ nodejs_manifest_dest }}
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
- name: Rollout status nodejs-demo
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nodejs-demo -n default --timeout=180s
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Service targetPort matches expected (optional)
|
||||
when: nodejs_expected_target_port is defined and (nodejs_expected_target_port | int) > 0
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
exp="{{ nodejs_expected_target_port | int }}"
|
||||
got=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get svc nodejs-demo -n default -o jsonpath='{.spec.ports[0].targetPort}')
|
||||
echo "svc/nodejs-demo targetPort=$got expected=$exp"
|
||||
test "$got" = "$exp"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Endpoints exist
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
eps=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get endpoints nodejs-demo -n default -o jsonpath='{.subsets[0].addresses[0].ip}' 2>/dev/null || true)
|
||||
echo "endpoints.ip=$eps"
|
||||
test -n "$eps"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: HTTP check nodejs demo (path/host optional)
|
||||
when: nodejs_http_check_enabled | default(true)
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
base="{{ nodejs_verify_entry_base | trim | regex_replace('/+$','') }}"
|
||||
path="{{ nodejs_verify_path | default('/node') }}"
|
||||
url="$base${path}"
|
||||
host="{{ nodejs_verify_host | default('') | trim }}"
|
||||
|
||||
ok=0
|
||||
for i in 1 2 3 4 5 6 7 8 9 10; do
|
||||
if [ -n "$host" ]; then
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" -H "Host: ${host}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
else
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
fi
|
||||
echo "try $i: $url host=${host:-<none>} -> $code"
|
||||
if [ "$code" = "200" ]; then ok=1; break; fi
|
||||
sleep 2
|
||||
done
|
||||
test "$ok" = "1"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Teardown when VERIFY_TEARDOWN=1
|
||||
when: verify_teardown == "1"
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f {{ nodejs_manifest_dest }} --ignore-not-found=true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
|
||||
@@ -1,10 +1,91 @@
|
||||
- name: "04-04 noop verify"
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
- name: Deploy+Verify 04-04 nodejs env + config injection
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
doc_id: "04-04"
|
||||
doc_filename: "04-04-nodejs-端口与Service.md"
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
|
||||
nodejs_manifest_src: "{{ playbook_dir }}/../../files/04-01/04-04-nodejs-demo.yaml"
|
||||
nodejs_manifest_dest: /tmp/nodejs-demo-04-04.yaml
|
||||
nodejs_verify_entry_base: "{{ nodejs_entry_base | default('http://' ~ k3s_server_ip) }}"
|
||||
nodejs_verify_path: "/node"
|
||||
nodejs_expected_target_port: 8080
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
- name: Copy nodejs demo manifest
|
||||
ansible.builtin.copy:
|
||||
src: "{{ nodejs_manifest_src }}"
|
||||
dest: "{{ nodejs_manifest_dest }}"
|
||||
mode: "0644"
|
||||
|
||||
- name: Apply nodejs demo manifest
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ nodejs_manifest_dest }}
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
- name: Rollout status nodejs-demo
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nodejs-demo -n default --timeout=180s
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Service targetPort matches expected (optional)
|
||||
when: nodejs_expected_target_port is defined and (nodejs_expected_target_port | int) > 0
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
exp="{{ nodejs_expected_target_port | int }}"
|
||||
got=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get svc nodejs-demo -n default -o jsonpath='{.spec.ports[0].targetPort}')
|
||||
echo "svc/nodejs-demo targetPort=$got expected=$exp"
|
||||
test "$got" = "$exp"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Endpoints exist
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
eps=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get endpoints nodejs-demo -n default -o jsonpath='{.subsets[0].addresses[0].ip}' 2>/dev/null || true)
|
||||
echo "endpoints.ip=$eps"
|
||||
test -n "$eps"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: HTTP check nodejs demo (path/host optional)
|
||||
when: nodejs_http_check_enabled | default(true)
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
base="{{ nodejs_verify_entry_base | trim | regex_replace('/+$','') }}"
|
||||
path="{{ nodejs_verify_path | default('/node') }}"
|
||||
url="$base${path}"
|
||||
host="{{ nodejs_verify_host | default('') | trim }}"
|
||||
|
||||
ok=0
|
||||
for i in 1 2 3 4 5 6 7 8 9 10; do
|
||||
if [ -n "$host" ]; then
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" -H "Host: ${host}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
else
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
fi
|
||||
echo "try $i: $url host=${host:-<none>} -> $code"
|
||||
if [ "$code" = "200" ]; then ok=1; break; fi
|
||||
sleep 2
|
||||
done
|
||||
test "$ok" = "1"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Teardown when VERIFY_TEARDOWN=1
|
||||
when: verify_teardown == "1"
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f {{ nodejs_manifest_dest }} --ignore-not-found=true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
|
||||
@@ -1,10 +1,91 @@
|
||||
- name: "04-05 noop verify"
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
- name: Deploy+Verify 04-05 nodejs probes
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
doc_id: "04-05"
|
||||
doc_filename: "04-05-nodejs-资源请求与限制.md"
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
|
||||
nodejs_manifest_src: "{{ playbook_dir }}/../../files/04-01/04-05-nodejs-demo.yaml"
|
||||
nodejs_manifest_dest: /tmp/nodejs-demo-04-05.yaml
|
||||
nodejs_verify_entry_base: "{{ nodejs_entry_base | default('http://' ~ k3s_server_ip) }}"
|
||||
nodejs_verify_path: "/node"
|
||||
nodejs_expected_target_port: 8080
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
- name: Copy nodejs demo manifest
|
||||
ansible.builtin.copy:
|
||||
src: "{{ nodejs_manifest_src }}"
|
||||
dest: "{{ nodejs_manifest_dest }}"
|
||||
mode: "0644"
|
||||
|
||||
- name: Apply nodejs demo manifest
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ nodejs_manifest_dest }}
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
- name: Rollout status nodejs-demo
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nodejs-demo -n default --timeout=180s
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Service targetPort matches expected (optional)
|
||||
when: nodejs_expected_target_port is defined and (nodejs_expected_target_port | int) > 0
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
exp="{{ nodejs_expected_target_port | int }}"
|
||||
got=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get svc nodejs-demo -n default -o jsonpath='{.spec.ports[0].targetPort}')
|
||||
echo "svc/nodejs-demo targetPort=$got expected=$exp"
|
||||
test "$got" = "$exp"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Endpoints exist
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
eps=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get endpoints nodejs-demo -n default -o jsonpath='{.subsets[0].addresses[0].ip}' 2>/dev/null || true)
|
||||
echo "endpoints.ip=$eps"
|
||||
test -n "$eps"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: HTTP check nodejs demo (path/host optional)
|
||||
when: nodejs_http_check_enabled | default(true)
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
base="{{ nodejs_verify_entry_base | trim | regex_replace('/+$','') }}"
|
||||
path="{{ nodejs_verify_path | default('/node') }}"
|
||||
url="$base${path}"
|
||||
host="{{ nodejs_verify_host | default('') | trim }}"
|
||||
|
||||
ok=0
|
||||
for i in 1 2 3 4 5 6 7 8 9 10; do
|
||||
if [ -n "$host" ]; then
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" -H "Host: ${host}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
else
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
fi
|
||||
echo "try $i: $url host=${host:-<none>} -> $code"
|
||||
if [ "$code" = "200" ]; then ok=1; break; fi
|
||||
sleep 2
|
||||
done
|
||||
test "$ok" = "1"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Teardown when VERIFY_TEARDOWN=1
|
||||
when: verify_teardown == "1"
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f {{ nodejs_manifest_dest }} --ignore-not-found=true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
|
||||
@@ -1,10 +1,91 @@
|
||||
- name: "04-06 noop verify"
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
- name: Deploy+Verify 04-06 nodejs replicas + rolling update
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
doc_id: "04-06"
|
||||
doc_filename: "04-06-nodejs-探针与健康检查.md"
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
|
||||
nodejs_manifest_src: "{{ playbook_dir }}/../../files/04-01/04-06-nodejs-demo.yaml"
|
||||
nodejs_manifest_dest: /tmp/nodejs-demo-04-06.yaml
|
||||
nodejs_verify_entry_base: "{{ nodejs_entry_base | default('http://' ~ k3s_server_ip) }}"
|
||||
nodejs_verify_path: "/node"
|
||||
nodejs_expected_target_port: 8080
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
- name: Copy nodejs demo manifest
|
||||
ansible.builtin.copy:
|
||||
src: "{{ nodejs_manifest_src }}"
|
||||
dest: "{{ nodejs_manifest_dest }}"
|
||||
mode: "0644"
|
||||
|
||||
- name: Apply nodejs demo manifest
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ nodejs_manifest_dest }}
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
- name: Rollout status nodejs-demo
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nodejs-demo -n default --timeout=180s
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Service targetPort matches expected (optional)
|
||||
when: nodejs_expected_target_port is defined and (nodejs_expected_target_port | int) > 0
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
exp="{{ nodejs_expected_target_port | int }}"
|
||||
got=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get svc nodejs-demo -n default -o jsonpath='{.spec.ports[0].targetPort}')
|
||||
echo "svc/nodejs-demo targetPort=$got expected=$exp"
|
||||
test "$got" = "$exp"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Endpoints exist
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
eps=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get endpoints nodejs-demo -n default -o jsonpath='{.subsets[0].addresses[0].ip}' 2>/dev/null || true)
|
||||
echo "endpoints.ip=$eps"
|
||||
test -n "$eps"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: HTTP check nodejs demo (path/host optional)
|
||||
when: nodejs_http_check_enabled | default(true)
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
base="{{ nodejs_verify_entry_base | trim | regex_replace('/+$','') }}"
|
||||
path="{{ nodejs_verify_path | default('/node') }}"
|
||||
url="$base${path}"
|
||||
host="{{ nodejs_verify_host | default('') | trim }}"
|
||||
|
||||
ok=0
|
||||
for i in 1 2 3 4 5 6 7 8 9 10; do
|
||||
if [ -n "$host" ]; then
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" -H "Host: ${host}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
else
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
fi
|
||||
echo "try $i: $url host=${host:-<none>} -> $code"
|
||||
if [ "$code" = "200" ]; then ok=1; break; fi
|
||||
sleep 2
|
||||
done
|
||||
test "$ok" = "1"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Teardown when VERIFY_TEARDOWN=1
|
||||
when: verify_teardown == "1"
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f {{ nodejs_manifest_dest }} --ignore-not-found=true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
|
||||
@@ -1,10 +1,91 @@
|
||||
- name: "04-07 noop verify"
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
- name: Deploy+Verify 04-07 nodejs Ingress + Traefik
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
doc_id: "04-07"
|
||||
doc_filename: "04-07-nodejs-调度与亲和.md"
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
|
||||
nodejs_manifest_src: "{{ playbook_dir }}/../../files/04-01/04-07-nodejs-demo.yaml"
|
||||
nodejs_manifest_dest: /tmp/nodejs-demo-04-07.yaml
|
||||
nodejs_verify_entry_base: "{{ nodejs_entry_base | default('http://' ~ k3s_server_ip) }}"
|
||||
nodejs_verify_path: "/api/"
|
||||
nodejs_verify_host: "{{ nodejs_verify_host | default('app.example.local') }}"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
- name: Copy nodejs demo manifest
|
||||
ansible.builtin.copy:
|
||||
src: "{{ nodejs_manifest_src }}"
|
||||
dest: "{{ nodejs_manifest_dest }}"
|
||||
mode: "0644"
|
||||
|
||||
- name: Apply nodejs demo manifest
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ nodejs_manifest_dest }}
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
- name: Rollout status nodejs-demo
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nodejs-demo -n default --timeout=180s
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Service targetPort matches expected (optional)
|
||||
when: nodejs_expected_target_port is defined and (nodejs_expected_target_port | int) > 0
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
exp="{{ nodejs_expected_target_port | int }}"
|
||||
got=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get svc nodejs-demo -n default -o jsonpath='{.spec.ports[0].targetPort}')
|
||||
echo "svc/nodejs-demo targetPort=$got expected=$exp"
|
||||
test "$got" = "$exp"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Endpoints exist
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
eps=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get endpoints nodejs-demo -n default -o jsonpath='{.subsets[0].addresses[0].ip}' 2>/dev/null || true)
|
||||
echo "endpoints.ip=$eps"
|
||||
test -n "$eps"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: HTTP check nodejs demo (path/host optional)
|
||||
when: nodejs_http_check_enabled | default(true)
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
base="{{ nodejs_verify_entry_base | trim | regex_replace('/+$','') }}"
|
||||
path="{{ nodejs_verify_path | default('/node') }}"
|
||||
url="$base${path}"
|
||||
host="{{ nodejs_verify_host | default('') | trim }}"
|
||||
|
||||
ok=0
|
||||
for i in 1 2 3 4 5 6 7 8 9 10; do
|
||||
if [ -n "$host" ]; then
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" -H "Host: ${host}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
else
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
fi
|
||||
echo "try $i: $url host=${host:-<none>} -> $code"
|
||||
if [ "$code" = "200" ]; then ok=1; break; fi
|
||||
sleep 2
|
||||
done
|
||||
test "$ok" = "1"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Teardown when VERIFY_TEARDOWN=1
|
||||
when: verify_teardown == "1"
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f {{ nodejs_manifest_dest }} --ignore-not-found=true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
|
||||
@@ -1,10 +1,91 @@
|
||||
- name: "04-08 noop verify"
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
- name: Deploy+Verify 04-08 nodejs resources requests/limits
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
doc_id: "04-08"
|
||||
doc_filename: "04-08-nodejs-安全上下文.md"
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
|
||||
nodejs_manifest_src: "{{ playbook_dir }}/../../files/04-01/04-08-nodejs-demo.yaml"
|
||||
nodejs_manifest_dest: /tmp/nodejs-demo-04-08.yaml
|
||||
nodejs_verify_entry_base: "{{ nodejs_entry_base | default('http://' ~ k3s_server_ip) }}"
|
||||
nodejs_verify_path: "/node"
|
||||
nodejs_expected_target_port: 8080
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
- name: Copy nodejs demo manifest
|
||||
ansible.builtin.copy:
|
||||
src: "{{ nodejs_manifest_src }}"
|
||||
dest: "{{ nodejs_manifest_dest }}"
|
||||
mode: "0644"
|
||||
|
||||
- name: Apply nodejs demo manifest
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ nodejs_manifest_dest }}
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
- name: Rollout status nodejs-demo
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nodejs-demo -n default --timeout=180s
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Service targetPort matches expected (optional)
|
||||
when: nodejs_expected_target_port is defined and (nodejs_expected_target_port | int) > 0
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
exp="{{ nodejs_expected_target_port | int }}"
|
||||
got=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get svc nodejs-demo -n default -o jsonpath='{.spec.ports[0].targetPort}')
|
||||
echo "svc/nodejs-demo targetPort=$got expected=$exp"
|
||||
test "$got" = "$exp"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Endpoints exist
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
eps=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get endpoints nodejs-demo -n default -o jsonpath='{.subsets[0].addresses[0].ip}' 2>/dev/null || true)
|
||||
echo "endpoints.ip=$eps"
|
||||
test -n "$eps"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: HTTP check nodejs demo (path/host optional)
|
||||
when: nodejs_http_check_enabled | default(true)
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
base="{{ nodejs_verify_entry_base | trim | regex_replace('/+$','') }}"
|
||||
path="{{ nodejs_verify_path | default('/node') }}"
|
||||
url="$base${path}"
|
||||
host="{{ nodejs_verify_host | default('') | trim }}"
|
||||
|
||||
ok=0
|
||||
for i in 1 2 3 4 5 6 7 8 9 10; do
|
||||
if [ -n "$host" ]; then
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" -H "Host: ${host}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
else
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
fi
|
||||
echo "try $i: $url host=${host:-<none>} -> $code"
|
||||
if [ "$code" = "200" ]; then ok=1; break; fi
|
||||
sleep 2
|
||||
done
|
||||
test "$ok" = "1"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Teardown when VERIFY_TEARDOWN=1
|
||||
when: verify_teardown == "1"
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f {{ nodejs_manifest_dest }} --ignore-not-found=true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
|
||||
@@ -1,10 +1,91 @@
|
||||
- name: "04-09 noop verify"
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
- name: Deploy+Verify 04-09 nodejs scheduling/affinity
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
doc_id: "04-09"
|
||||
doc_filename: "04-09-nodejs-存储与卷.md"
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
|
||||
nodejs_manifest_src: "{{ playbook_dir }}/../../files/04-01/04-09-nodejs-demo.yaml"
|
||||
nodejs_manifest_dest: /tmp/nodejs-demo-04-09.yaml
|
||||
nodejs_verify_entry_base: "{{ nodejs_entry_base | default('http://' ~ k3s_server_ip) }}"
|
||||
nodejs_verify_path: "/node"
|
||||
nodejs_expected_target_port: 8080
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
- name: Copy nodejs demo manifest
|
||||
ansible.builtin.copy:
|
||||
src: "{{ nodejs_manifest_src }}"
|
||||
dest: "{{ nodejs_manifest_dest }}"
|
||||
mode: "0644"
|
||||
|
||||
- name: Apply nodejs demo manifest
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ nodejs_manifest_dest }}
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
- name: Rollout status nodejs-demo
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nodejs-demo -n default --timeout=180s
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Service targetPort matches expected (optional)
|
||||
when: nodejs_expected_target_port is defined and (nodejs_expected_target_port | int) > 0
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
exp="{{ nodejs_expected_target_port | int }}"
|
||||
got=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get svc nodejs-demo -n default -o jsonpath='{.spec.ports[0].targetPort}')
|
||||
echo "svc/nodejs-demo targetPort=$got expected=$exp"
|
||||
test "$got" = "$exp"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Endpoints exist
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
eps=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get endpoints nodejs-demo -n default -o jsonpath='{.subsets[0].addresses[0].ip}' 2>/dev/null || true)
|
||||
echo "endpoints.ip=$eps"
|
||||
test -n "$eps"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: HTTP check nodejs demo (path/host optional)
|
||||
when: nodejs_http_check_enabled | default(true)
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
base="{{ nodejs_verify_entry_base | trim | regex_replace('/+$','') }}"
|
||||
path="{{ nodejs_verify_path | default('/node') }}"
|
||||
url="$base${path}"
|
||||
host="{{ nodejs_verify_host | default('') | trim }}"
|
||||
|
||||
ok=0
|
||||
for i in 1 2 3 4 5 6 7 8 9 10; do
|
||||
if [ -n "$host" ]; then
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" -H "Host: ${host}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
else
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
fi
|
||||
echo "try $i: $url host=${host:-<none>} -> $code"
|
||||
if [ "$code" = "200" ]; then ok=1; break; fi
|
||||
sleep 2
|
||||
done
|
||||
test "$ok" = "1"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Teardown when VERIFY_TEARDOWN=1
|
||||
when: verify_teardown == "1"
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f {{ nodejs_manifest_dest }} --ignore-not-found=true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
|
||||
@@ -1,10 +1,91 @@
|
||||
- name: "04-10 noop verify"
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
- name: Deploy+Verify 04-10 nodejs securityContext
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
doc_id: "04-10"
|
||||
doc_filename: "04-10-nodejs-Ingress与Traefik.md"
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
|
||||
nodejs_manifest_src: "{{ playbook_dir }}/../../files/04-01/04-10-nodejs-demo.yaml"
|
||||
nodejs_manifest_dest: /tmp/nodejs-demo-04-10.yaml
|
||||
nodejs_verify_entry_base: "{{ nodejs_entry_base | default('http://' ~ k3s_server_ip) }}"
|
||||
nodejs_verify_path: "/node"
|
||||
nodejs_expected_target_port: 8080
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
- name: Copy nodejs demo manifest
|
||||
ansible.builtin.copy:
|
||||
src: "{{ nodejs_manifest_src }}"
|
||||
dest: "{{ nodejs_manifest_dest }}"
|
||||
mode: "0644"
|
||||
|
||||
- name: Apply nodejs demo manifest
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ nodejs_manifest_dest }}
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
- name: Rollout status nodejs-demo
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nodejs-demo -n default --timeout=180s
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Service targetPort matches expected (optional)
|
||||
when: nodejs_expected_target_port is defined and (nodejs_expected_target_port | int) > 0
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
exp="{{ nodejs_expected_target_port | int }}"
|
||||
got=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get svc nodejs-demo -n default -o jsonpath='{.spec.ports[0].targetPort}')
|
||||
echo "svc/nodejs-demo targetPort=$got expected=$exp"
|
||||
test "$got" = "$exp"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Endpoints exist
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
eps=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get endpoints nodejs-demo -n default -o jsonpath='{.subsets[0].addresses[0].ip}' 2>/dev/null || true)
|
||||
echo "endpoints.ip=$eps"
|
||||
test -n "$eps"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: HTTP check nodejs demo (path/host optional)
|
||||
when: nodejs_http_check_enabled | default(true)
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
base="{{ nodejs_verify_entry_base | trim | regex_replace('/+$','') }}"
|
||||
path="{{ nodejs_verify_path | default('/node') }}"
|
||||
url="$base${path}"
|
||||
host="{{ nodejs_verify_host | default('') | trim }}"
|
||||
|
||||
ok=0
|
||||
for i in 1 2 3 4 5 6 7 8 9 10; do
|
||||
if [ -n "$host" ]; then
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" -H "Host: ${host}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
else
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
fi
|
||||
echo "try $i: $url host=${host:-<none>} -> $code"
|
||||
if [ "$code" = "200" ]; then ok=1; break; fi
|
||||
sleep 2
|
||||
done
|
||||
test "$ok" = "1"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Teardown when VERIFY_TEARDOWN=1
|
||||
when: verify_teardown == "1"
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f {{ nodejs_manifest_dest }} --ignore-not-found=true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
|
||||
@@ -1,10 +1,91 @@
|
||||
- name: "04-11 noop verify"
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
- name: Deploy+Verify 04-11 nodejs storage/volumes
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
doc_id: "04-11"
|
||||
doc_filename: "04-11-nodejs-副本与滚动发布.md"
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
|
||||
nodejs_manifest_src: "{{ playbook_dir }}/../../files/04-01/04-11-nodejs-demo.yaml"
|
||||
nodejs_manifest_dest: /tmp/nodejs-demo-04-11.yaml
|
||||
nodejs_verify_entry_base: "{{ nodejs_entry_base | default('http://' ~ k3s_server_ip) }}"
|
||||
nodejs_verify_path: "/node"
|
||||
nodejs_expected_target_port: 8080
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
- name: Copy nodejs demo manifest
|
||||
ansible.builtin.copy:
|
||||
src: "{{ nodejs_manifest_src }}"
|
||||
dest: "{{ nodejs_manifest_dest }}"
|
||||
mode: "0644"
|
||||
|
||||
- name: Apply nodejs demo manifest
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ nodejs_manifest_dest }}
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
- name: Rollout status nodejs-demo
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nodejs-demo -n default --timeout=180s
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Service targetPort matches expected (optional)
|
||||
when: nodejs_expected_target_port is defined and (nodejs_expected_target_port | int) > 0
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
exp="{{ nodejs_expected_target_port | int }}"
|
||||
got=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get svc nodejs-demo -n default -o jsonpath='{.spec.ports[0].targetPort}')
|
||||
echo "svc/nodejs-demo targetPort=$got expected=$exp"
|
||||
test "$got" = "$exp"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Endpoints exist
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
eps=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get endpoints nodejs-demo -n default -o jsonpath='{.subsets[0].addresses[0].ip}' 2>/dev/null || true)
|
||||
echo "endpoints.ip=$eps"
|
||||
test -n "$eps"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: HTTP check nodejs demo (path/host optional)
|
||||
when: nodejs_http_check_enabled | default(true)
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
base="{{ nodejs_verify_entry_base | trim | regex_replace('/+$','') }}"
|
||||
path="{{ nodejs_verify_path | default('/node') }}"
|
||||
url="$base${path}"
|
||||
host="{{ nodejs_verify_host | default('') | trim }}"
|
||||
|
||||
ok=0
|
||||
for i in 1 2 3 4 5 6 7 8 9 10; do
|
||||
if [ -n "$host" ]; then
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" -H "Host: ${host}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
else
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
fi
|
||||
echo "try $i: $url host=${host:-<none>} -> $code"
|
||||
if [ "$code" = "200" ]; then ok=1; break; fi
|
||||
sleep 2
|
||||
done
|
||||
test "$ok" = "1"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Teardown when VERIFY_TEARDOWN=1
|
||||
when: verify_teardown == "1"
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f {{ nodejs_manifest_dest }} --ignore-not-found=true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
|
||||
@@ -1,10 +1,101 @@
|
||||
- name: "04-12 noop verify"
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
- name: Deploy+Verify 04-12 nodejs TLS Ingress
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
doc_id: "04-12"
|
||||
doc_filename: "04-12-nodejs-TLS与证书.md"
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
|
||||
nodejs_manifest_src: "{{ playbook_dir }}/../../files/04-01/04-12-nodejs-demo.yaml"
|
||||
nodejs_manifest_dest: /tmp/nodejs-demo-04-12.yaml
|
||||
# 默认不强行跑 HTTPS curl(需要 DNS/证书/入口);提供环境变量时再启用
|
||||
nodejs_http_check_enabled: "{{ (NODEJS_TLS_ENTRY_BASE is defined) and (NODEJS_TLS_HOST is defined) }}"
|
||||
nodejs_verify_entry_base: "{{ NODEJS_TLS_ENTRY_BASE | default('https://app.example.local') }}"
|
||||
nodejs_verify_path: "/api/"
|
||||
nodejs_verify_host: "{{ NODEJS_TLS_HOST | default('app.example.local') }}"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
- name: Assert TLS secret exists (nodejs-demo-tls)
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n default get secret nodejs-demo-tls
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Copy nodejs demo manifest
|
||||
ansible.builtin.copy:
|
||||
src: "{{ nodejs_manifest_src }}"
|
||||
dest: "{{ nodejs_manifest_dest }}"
|
||||
mode: "0644"
|
||||
|
||||
- name: Apply nodejs demo manifest
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ nodejs_manifest_dest }}
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
- name: Rollout status nodejs-demo
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nodejs-demo -n default --timeout=180s
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Service targetPort matches expected (optional)
|
||||
when: nodejs_expected_target_port is defined and (nodejs_expected_target_port | int) > 0
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
exp="{{ nodejs_expected_target_port | int }}"
|
||||
got=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get svc nodejs-demo -n default -o jsonpath='{.spec.ports[0].targetPort}')
|
||||
echo "svc/nodejs-demo targetPort=$got expected=$exp"
|
||||
test "$got" = "$exp"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Endpoints exist
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
eps=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get endpoints nodejs-demo -n default -o jsonpath='{.subsets[0].addresses[0].ip}' 2>/dev/null || true)
|
||||
echo "endpoints.ip=$eps"
|
||||
test -n "$eps"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: HTTP check nodejs demo (path/host optional)
|
||||
when: nodejs_http_check_enabled | default(true)
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
base="{{ nodejs_verify_entry_base | trim | regex_replace('/+$','') }}"
|
||||
path="{{ nodejs_verify_path | default('/node') }}"
|
||||
url="$base${path}"
|
||||
host="{{ nodejs_verify_host | default('') | trim }}"
|
||||
|
||||
ok=0
|
||||
for i in 1 2 3 4 5 6 7 8 9 10; do
|
||||
if [ -n "$host" ]; then
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" -H "Host: ${host}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
else
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
fi
|
||||
echo "try $i: $url host=${host:-<none>} -> $code"
|
||||
if [ "$code" = "200" ]; then ok=1; break; fi
|
||||
sleep 2
|
||||
done
|
||||
test "$ok" = "1"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Teardown when VERIFY_TEARDOWN=1
|
||||
when: verify_teardown == "1"
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f {{ nodejs_manifest_dest }} --ignore-not-found=true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
|
||||
@@ -1,10 +1,99 @@
|
||||
- name: "04-13 noop verify"
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
- name: Deploy+Verify 04-13 nodejs HPA
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
doc_id: "04-13"
|
||||
doc_filename: "04-13-nodejs-HPA.md"
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
|
||||
nodejs_manifest_src: "{{ playbook_dir }}/../../files/04-01/04-13-nodejs-demo.yaml"
|
||||
nodejs_manifest_dest: /tmp/nodejs-demo-04-13.yaml
|
||||
nodejs_verify_entry_base: "{{ nodejs_entry_base | default('http://' ~ k3s_server_ip) }}"
|
||||
nodejs_verify_path: "/node"
|
||||
nodejs_expected_target_port: 8080
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
- name: Copy nodejs demo manifest
|
||||
ansible.builtin.copy:
|
||||
src: "{{ nodejs_manifest_src }}"
|
||||
dest: "{{ nodejs_manifest_dest }}"
|
||||
mode: "0644"
|
||||
|
||||
- name: Apply nodejs demo manifest
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ nodejs_manifest_dest }}
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
- name: Rollout status nodejs-demo
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nodejs-demo -n default --timeout=180s
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Service targetPort matches expected (optional)
|
||||
when: nodejs_expected_target_port is defined and (nodejs_expected_target_port | int) > 0
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
exp="{{ nodejs_expected_target_port | int }}"
|
||||
got=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get svc nodejs-demo -n default -o jsonpath='{.spec.ports[0].targetPort}')
|
||||
echo "svc/nodejs-demo targetPort=$got expected=$exp"
|
||||
test "$got" = "$exp"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Endpoints exist
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
eps=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get endpoints nodejs-demo -n default -o jsonpath='{.subsets[0].addresses[0].ip}' 2>/dev/null || true)
|
||||
echo "endpoints.ip=$eps"
|
||||
test -n "$eps"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: HTTP check nodejs demo (path/host optional)
|
||||
when: nodejs_http_check_enabled | default(true)
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
base="{{ nodejs_verify_entry_base | trim | regex_replace('/+$','') }}"
|
||||
path="{{ nodejs_verify_path | default('/node') }}"
|
||||
url="$base${path}"
|
||||
host="{{ nodejs_verify_host | default('') | trim }}"
|
||||
|
||||
ok=0
|
||||
for i in 1 2 3 4 5 6 7 8 9 10; do
|
||||
if [ -n "$host" ]; then
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" -H "Host: ${host}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
else
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
fi
|
||||
echo "try $i: $url host=${host:-<none>} -> $code"
|
||||
if [ "$code" = "200" ]; then ok=1; break; fi
|
||||
sleep 2
|
||||
done
|
||||
test "$ok" = "1"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Teardown when VERIFY_TEARDOWN=1
|
||||
when: verify_teardown == "1"
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f {{ nodejs_manifest_dest }} --ignore-not-found=true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
- name: Assert HPA exists
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n default get hpa nodejs-demo
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
- name: "04-14 noop verify"
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
doc_id: "04-14"
|
||||
doc_filename: "04-14-nodejs-GitOps与CI流水线.md"
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
|
||||
nodejs_manifest_src: "{{ playbook_dir }}/../../files/04-01/04-14-nodejs-demo.yaml"
|
||||
nodejs_manifest_dest: /tmp/nodejs-demo-04-14.yaml
|
||||
nodejs_http_check_enabled: false
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
- name: Include nodejs deploy+verify template
|
||||
ansible.builtin.include_tasks: tasks/nodejs-demo-deploy-verify.yml
|
||||
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
doc_id: "05-01"
|
||||
doc_filename: "05-01-k3s-部署homer首页面板.md"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
|
||||
- name: Include noop doc verify tasks
|
||||
ansible.builtin.include_tasks: tasks/noop-doc-verify.yml
|
||||
@@ -6,5 +6,5 @@
|
||||
doc_id: "05-02"
|
||||
doc_filename: "05-02-onenav首页面板.md"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
|
||||
- name: Include noop doc verify tasks
|
||||
ansible.builtin.include_tasks: tasks/noop-doc-verify.yml
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
doc_id: "05-03"
|
||||
doc_filename: "05-03-k3s-安装gitlab-含runner.md"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
|
||||
- name: Include noop doc verify tasks
|
||||
ansible.builtin.include_tasks: tasks/noop-doc-verify.yml
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
doc_id: "05-04"
|
||||
doc_filename: "05-04-k3s-配置gitlab-cicd.md"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
|
||||
- name: Include noop doc verify tasks
|
||||
ansible.builtin.include_tasks: tasks/noop-doc-verify.yml
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
doc_id: "05-05"
|
||||
doc_filename: "05-05-prometheus与grafana.md"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
|
||||
- name: Include noop doc verify tasks
|
||||
ansible.builtin.include_tasks: tasks/noop-doc-verify.yml
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
doc_id: "05-06"
|
||||
doc_filename: "05-06-openlist挂载网盘与自动备份.md"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
|
||||
- name: Include noop doc verify tasks
|
||||
ansible.builtin.include_tasks: tasks/noop-doc-verify.yml
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
doc_id: "05-07"
|
||||
doc_filename: "05-07-openclaw应用部署.md"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
|
||||
- name: Include noop doc verify tasks
|
||||
ansible.builtin.include_tasks: tasks/noop-doc-verify.yml
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
doc_id: "05-08"
|
||||
doc_filename: "05-08-openclaw-k3s-实验部署.md"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
|
||||
- name: Include noop doc verify tasks
|
||||
ansible.builtin.include_tasks: tasks/noop-doc-verify.yml
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
doc_id: "05-09"
|
||||
doc_filename: "05-09-openclaw-web-小游戏网页平台.md"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
|
||||
- name: Include noop doc verify tasks
|
||||
ansible.builtin.include_tasks: tasks/noop-doc-verify.yml
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
doc_id: "06-01"
|
||||
doc_filename: "06-01-k3s-networkpolicy-故障排查.md"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
|
||||
- name: Include noop doc verify tasks
|
||||
ansible.builtin.include_tasks: tasks/noop-doc-verify.yml
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
doc_id: "06-02"
|
||||
doc_filename: "06-02-运维小结.md"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
|
||||
- name: Include noop doc verify tasks
|
||||
ansible.builtin.include_tasks: tasks/noop-doc-verify.yml
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
doc_id: "06-03"
|
||||
doc_filename: "06-03-k3s-自动备份与恢复-openlist-webdav.md"
|
||||
tasks:
|
||||
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"
|
||||
|
||||
- name: Include noop doc verify tasks
|
||||
ansible.builtin.include_tasks: tasks/noop-doc-verify.yml
|
||||
|
||||
10
ansible/playbooks/verify/07-01.yml
Normal file
10
ansible/playbooks/verify/07-01.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
- name: "07-01 noop verify"
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
doc_id: "07-01"
|
||||
doc_filename: "07-01-k3s-calico-dualstack.md"
|
||||
tasks:
|
||||
- name: Include noop doc verify tasks
|
||||
ansible.builtin.include_tasks: tasks/noop-doc-verify.yml
|
||||
10
ansible/playbooks/verify/07-02.yml
Normal file
10
ansible/playbooks/verify/07-02.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
- name: "07-02 noop verify"
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
doc_id: "07-02"
|
||||
doc_filename: "07-02-k3s-cilium-dualstack-ebpf.md"
|
||||
tasks:
|
||||
- name: Include noop doc verify tasks
|
||||
ansible.builtin.include_tasks: tasks/noop-doc-verify.yml
|
||||
@@ -1,32 +0,0 @@
|
||||
- name: Assert docs file exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ repo_root }}/docs/{{ doc_filename }}"
|
||||
register: _doc_stat
|
||||
|
||||
- name: Fail when docs file missing
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- _doc_stat.stat.exists
|
||||
fail_msg: "docs file missing: docs/{{ doc_filename }}"
|
||||
|
||||
- name: Find matching ansible/files doc_id directory
|
||||
ansible.builtin.find:
|
||||
paths: "{{ repo_root }}/ansible/files"
|
||||
file_type: directory
|
||||
patterns: "{{ doc_id }}-*"
|
||||
use_regex: false
|
||||
register: _files_dirs
|
||||
|
||||
- name: Fail when ansible/files doc_id directory missing
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- _files_dirs.matched | int >= 1
|
||||
fail_msg: "ansible/files missing doc_id directory: ansible/files/{{ doc_id }}-*"
|
||||
|
||||
- name: Show noop verification summary
|
||||
ansible.builtin.debug:
|
||||
msg:
|
||||
- "doc_id={{ doc_id }}"
|
||||
- "doc={{ doc_filename }}"
|
||||
- "files_dirs={{ _files_dirs.files | map(attribute='path') | list }}"
|
||||
|
||||
77
ansible/playbooks/verify/tasks/nodejs-demo-deploy-verify.yml
Normal file
77
ansible/playbooks/verify/tasks/nodejs-demo-deploy-verify.yml
Normal file
@@ -0,0 +1,77 @@
|
||||
- name: Copy nodejs demo manifest
|
||||
ansible.builtin.copy:
|
||||
src: "{{ nodejs_manifest_src }}"
|
||||
dest: "{{ nodejs_manifest_dest }}"
|
||||
mode: "0644"
|
||||
|
||||
- name: Apply nodejs demo manifest
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ nodejs_manifest_dest }}
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
|
||||
- name: Rollout status nodejs-demo
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nodejs-demo -n default --timeout=180s
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Service targetPort matches expected (optional)
|
||||
when: nodejs_expected_target_port is defined and (nodejs_expected_target_port | int) > 0
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
exp="{{ nodejs_expected_target_port | int }}"
|
||||
got=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get svc nodejs-demo -n default -o jsonpath='{.spec.ports[0].targetPort}')
|
||||
echo "svc/nodejs-demo targetPort=$got expected=$exp"
|
||||
test "$got" = "$exp"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Assert Endpoints exist
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
eps=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get endpoints nodejs-demo -n default -o jsonpath='{.subsets[0].addresses[0].ip}' 2>/dev/null || true)
|
||||
echo "endpoints.ip=$eps"
|
||||
test -n "$eps"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: HTTP check nodejs demo (path/host optional)
|
||||
when: nodejs_http_check_enabled | default(true)
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
base="{{ nodejs_verify_entry_base | trim | regex_replace('/+$','') }}"
|
||||
path="{{ nodejs_verify_path | default('/node') }}"
|
||||
url="$base${path}"
|
||||
host="{{ nodejs_verify_host | default('') | trim }}"
|
||||
|
||||
ok=0
|
||||
for i in 1 2 3 4 5 6 7 8 9 10; do
|
||||
if [ -n "$host" ]; then
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" -H "Host: ${host}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
else
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
|
||||
fi
|
||||
echo "try $i: $url host=${host:-<none>} -> $code"
|
||||
if [ "$code" = "200" ]; then ok=1; break; fi
|
||||
sleep 2
|
||||
done
|
||||
test "$ok" = "1"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: false
|
||||
|
||||
- name: Teardown when VERIFY_TEARDOWN=1
|
||||
when: verify_teardown == "1"
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f {{ nodejs_manifest_dest }} --ignore-not-found=true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
changed_when: true
|
||||
87
ansible/playbooks/verify/tasks/noop-doc-verify.yml
Normal file
87
ansible/playbooks/verify/tasks/noop-doc-verify.yml
Normal file
@@ -0,0 +1,87 @@
|
||||
- name: Assert docs file exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ repo_root }}/docs/{{ doc_filename }}"
|
||||
register: _doc_stat
|
||||
|
||||
- name: Fail when docs file missing
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- _doc_stat.stat.exists
|
||||
fail_msg: "docs file missing: docs/{{ doc_filename }}"
|
||||
|
||||
- name: Find matching ansible/files doc_id directory
|
||||
ansible.builtin.find:
|
||||
paths: "{{ repo_root }}/ansible/files"
|
||||
file_type: directory
|
||||
patterns: "{{ doc_id }}"
|
||||
use_regex: false
|
||||
register: _files_dirs
|
||||
|
||||
- name: Fail when ansible/files doc_id directory missing
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- _files_dirs.matched | int >= 1
|
||||
fail_msg: "ansible/files missing doc_id directory: ansible/files/{{ doc_id }}"
|
||||
|
||||
- name: Show noop verification summary
|
||||
ansible.builtin.debug:
|
||||
msg:
|
||||
- "doc_id={{ doc_id }}"
|
||||
- "doc={{ doc_filename }}"
|
||||
- "files_dirs={{ _files_dirs.files | map(attribute='path') | list }}"
|
||||
|
||||
- name: Verify cluster reachable (kubectl get nodes) [runbook baseline]
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
KUBECONFIG={{ k3s_kubeconfig | default('/etc/rancher/k3s/k3s.yaml') }} kubectl get nodes
|
||||
args:
|
||||
executable: /bin/bash
|
||||
delegate_to: "{{ groups['k3s_server'][0] }}"
|
||||
become: true
|
||||
run_once: true
|
||||
changed_when: false
|
||||
|
||||
- name: Verify core namespace exists (kube-system) [runbook baseline]
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
KUBECONFIG={{ k3s_kubeconfig | default('/etc/rancher/k3s/k3s.yaml') }} kubectl get ns kube-system
|
||||
args:
|
||||
executable: /bin/bash
|
||||
delegate_to: "{{ groups['k3s_server'][0] }}"
|
||||
become: true
|
||||
run_once: true
|
||||
changed_when: false
|
||||
|
||||
- name: Find YAML manifests under ansible/files doc_id dirs
|
||||
ansible.builtin.find:
|
||||
paths: "{{ _files_dirs.files | map(attribute='path') | list }}"
|
||||
file_type: file
|
||||
patterns:
|
||||
- "*.yml"
|
||||
- "*.yaml"
|
||||
recurse: true
|
||||
use_regex: false
|
||||
register: _files_manifests
|
||||
|
||||
- name: Show manifest count summary
|
||||
ansible.builtin.debug:
|
||||
msg:
|
||||
- "doc_id={{ doc_id }}"
|
||||
- "manifest_files={{ _files_manifests.matched | default(0) }}"
|
||||
- "manifest_paths={{ (_files_manifests.files | map(attribute='path') | list)[:12] }}"
|
||||
|
||||
- name: Server-side dry-run apply (kubectl apply --dry-run=server) [doc assertion]
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
KUBECONFIG={{ k3s_kubeconfig | default('/etc/rancher/k3s/k3s.yaml') }} \
|
||||
kubectl apply --dry-run=server -f "{{ item.path }}"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
loop: "{{ _files_manifests.files }}"
|
||||
loop_control:
|
||||
label: "{{ item.path }}"
|
||||
delegate_to: "{{ groups['k3s_server'][0] }}"
|
||||
become: true
|
||||
run_once: true
|
||||
changed_when: false
|
||||
when: (_files_manifests.matched | default(0) | int) > 0
|
||||
Reference in New Issue
Block a user