feat: 按 doc_id 重组 ansible/files 与验证框架

- ansible/files 改为与文档 XX-YY 对齐的目录结构,更新相关 playbook 路径
- 新增 scripts/verify.sh 与 ansible/playbooks/verify/*.yml,移除单体 verify-matrix.yml
- 补充 docs/00-02 矩阵状态、00-05 验证框架与流程、00-04 环境与 ylc65 工作机说明
- 增加 k3s 存储准备、Longhorn、local-path 等 playbook 与辅助脚本

Made-with: Cursor
This commit is contained in:
2026-03-26 07:01:14 +08:00
parent a67788de56
commit 8c43761962
192 changed files with 4006 additions and 320 deletions

View File

@@ -0,0 +1,37 @@
---
# 仅应用本仓库 local-path 实验室 ConfigMap不安装 Longhorn。在 k3s_server 上执行。
# 与 docs/03-05 中「方法一」一致真源ansible/files/03-05-local-path-config/local-path-config-lab.json
- name: Apply local-path-config lab JSON
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: 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

View File

@@ -1,4 +1,33 @@
---
- name: Verify /storage is a separate mount (optional)
hosts: k3s_nodes
become: true
tasks:
- name: Check / and /storage mount sources
when: k3s_verify_storage_mount | default(false) | bool
block:
- name: Get mount source for /
ansible.builtin.command: findmnt -n -o SOURCE /
register: mnt_root
changed_when: false
- name: Get mount source for /storage
ansible.builtin.command: findmnt -n -o SOURCE /storage
register: mnt_storage
changed_when: false
failed_when: false
- name: Assert /storage is mounted on a different device than /
ansible.builtin.assert:
that:
- mnt_storage.rc == 0
- (mnt_root.stdout | trim | length) > 0
- (mnt_storage.stdout | trim | length) > 0
- (mnt_root.stdout | trim) != (mnt_storage.stdout | trim)
fail_msg: >-
/storage must be a mount point on a block device different from /.
See docs/00-04-部署环境说明.md and docs/01-06-节点初始化-ansible-实践.md
- name: Init base system
hosts: k3s_nodes
become: true

View File

@@ -0,0 +1,106 @@
---
# 可选在空白数据盘上创建单分区、ext4、fstab 并挂载到 k3s_data_dir默认 /storage
# 启用前在 group_vars/all.yml 设置 k3s_prepare_storage: true 与 k3s_data_disk_device如 /dev/vdb
# 会清空该磁盘上的数据。若 /storage 已是挂载点则跳过。
- name: Prepare data disk and mount to k3s_data_dir
hosts: k3s_nodes
become: true
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

View File

@@ -0,0 +1,251 @@
---
# Helm 安装 Longhorn与 docs/03-07 一致)。在控制节点执行,依赖 KUBECONFIG=/etc/rancher/k3s/k3s.yaml
# 变量group_vars/all.yml 中 longhorn_chart_version、longhorn_install_node_packages、longhorn_apply_local_path_lab
- 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-longhorn/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) to avoid Helm ownership conflicts
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 }}
# 有些失败/中断的安装会把 release secret 留在 default 或 longhorn-system导致后续
# - "cannot re-use a name that is still in use"
# - cluster-scoped 资源的 meta.helm.sh/release-namespace 注解冲突
for ns in longhorn-system default; do
if helm -n "$ns" list --all 2>/dev/null | grep -q '^longhorn'; then
# uninstall 可能卡住(例如 uninstall job / hook避免阻塞整个自动化流程
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

View File

@@ -3,7 +3,7 @@
# 对应文档docs/02-05-nginx-验证矩阵-一键部署.md02-0102-04 分篇已整合)
#
# 说明:复制 manifests → kubectl apply → 等待 Pod 就绪 → 验证 Pod 节点分布 → curl 16 目标
# manifestsansible/files/nginx-matrix/M1 control-plane / M2 ylc61 / M3 worker / M4 ylc64按实际修改 02/04 hostname
# manifestsansible/files/02-05-nginx-matrix/M1 control-plane / M2 ylc61 / M3 worker / M4 ylc64按实际修改 02/04 hostname
#
# 执行(在 ansible/ 目录下):
# ansible-playbook -i inventory.ini playbooks/nginx-matrix-deploy.yml
@@ -15,8 +15,8 @@
run_once: true
vars:
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
# manifests 在 ansible/files/nginx-matrix/,与 playbook 同项目
manifests_path: "{{ playbook_dir }}/../files/nginx-matrix"
# manifests 在 ansible/files/02-05-nginx-matrix/,与 playbook 同项目
manifests_path: "{{ playbook_dir }}/../files/02-05-nginx-matrix"
tasks:
- name: Ensure manifests path exists
ansible.builtin.stat:

View File

@@ -3,7 +3,7 @@
# 对应文档docs/03-02-k3s-traefik-acme.md
#
# 说明:复制 TLS + HTTP-only manifests → 自动删除已存在的不含 TLS 的 nginx 矩阵02-05→ kubectl apply含 TLS 与 HTTP-only 共 8 个路由)→ 等待 Pod 就绪 → HTTP-only / HTTPS curl 矩阵验证test01test04.jackadam.top
# manifestsansible/files/nginx-matrix-tls/,域名为 test01test04.jackadam.topM2/M4 hostname 按实际修改Ingress/IngressRoute 中 TLS 路由仅绑定 websecureHTTP-only 路由仅绑定 web
# manifestsansible/files/03-02-nginx-matrix-tls/,域名为 test01test04.jackadam.topM2/M4 hostname 按实际修改Ingress/IngressRoute 中 TLS 路由仅绑定 websecureHTTP-only 路由仅绑定 web
# 前置:已按 03-02 配置 ACMESecret + traefik-acme.yaml且 test01test04.jackadam.top 已解析到入口 IP
#
# 执行(在 ansible/ 目录下):
@@ -18,7 +18,7 @@
vars:
# mode 由 -e mode=cleanup 传入,未传时默认为 deploy勿在 vars 中写 mode: "{{ mode | default('deploy') }}" 会递归)
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
manifests_path: "{{ playbook_dir }}/../files/nginx-matrix-tls"
manifests_path: "{{ playbook_dir }}/../files/03-02-nginx-matrix-tls"
tls_domains:
- test01.jackadam.top
- test02.jackadam.top

View File

@@ -1,5 +1,5 @@
---
# 一键应用 Node.js demo 清单(与 docs/04-0104-13 + ansible/files/nodejs-demo 对齐)
# 一键应用 Node.js demo 清单(与 docs/04-0104-13 + ansible/files/04-01-nodejs-demo 对齐)
#
# 执行(在仓库根目录):
# ansible-playbook -i ansible/inventory.ini ansible/playbooks/nodejs-demo-apply.yml \
@@ -13,7 +13,7 @@
vars:
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
nodejs_demo_manifest: "04-01-nodejs-demo.yaml"
manifests_dir: "{{ playbook_dir }}/../files/nodejs-demo"
manifests_dir: "{{ playbook_dir }}/../files/04-01-nodejs-demo"
tasks:
- name: Ensure manifest file exists
ansible.builtin.stat:

View File

@@ -0,0 +1,10 @@
- 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"

View File

@@ -0,0 +1,10 @@
- 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"

View File

@@ -0,0 +1,24 @@
- name: "01-01 k3s baseline verify (nodes + core deploys)"
hosts: k3s_server
become: true
run_once: true
vars:
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
tasks:
- name: kubectl get nodes
ansible.builtin.shell: KUBECONFIG={{ k3s_kubeconfig }} kubectl get nodes -o wide
changed_when: false
- name: kube-system pods summary
ansible.builtin.shell: KUBECONFIG={{ k3s_kubeconfig }} kubectl get pods -n kube-system -o wide
changed_when: false
- name: Assert core components exist (coredns, traefik)
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n kube-system get deploy coredns
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n kube-system get deploy traefik
args:
executable: /bin/bash
changed_when: false

View File

@@ -0,0 +1,11 @@
- name: "01-02 k3s baseline verify (nodes)"
hosts: k3s_server
become: true
run_once: true
vars:
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
tasks:
- name: kubectl get nodes
ansible.builtin.shell: KUBECONFIG={{ k3s_kubeconfig }} kubectl get nodes -o wide
changed_when: false

View File

@@ -0,0 +1,10 @@
- name: "01-03 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "01-03"
doc_filename: "01-03-armv7-standalone-docker.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- 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"

View File

@@ -0,0 +1,10 @@
- name: "01-05 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "01-05"
doc_filename: "01-05-armv7-nfs服务安装.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,11 @@
- name: "01-06 k3s baseline verify (kube-system pods)"
hosts: k3s_server
become: true
run_once: true
vars:
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
tasks:
- name: kube-system pods summary
ansible.builtin.shell: KUBECONFIG={{ k3s_kubeconfig }} kubectl get pods -n kube-system -o wide
changed_when: false

View File

@@ -0,0 +1,10 @@
- name: "01-07 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "01-07"
doc_filename: "01-07-openwrt-haproxy.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- 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"

View File

@@ -0,0 +1,77 @@
- name: Deploy 02-01 nginx control + Ingress (M1)
hosts: k3s_server
become: true
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_dest: /tmp/nginx-m1.yaml
tasks:
- name: Copy manifest
ansible.builtin.copy:
src: "{{ manifest_src }}"
dest: "{{ manifest_dest }}"
mode: "0644"
- name: Apply manifest
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ manifest_dest }}
args:
executable: /bin/bash
changed_when: true
- name: Verify 02-01 nginx control + Ingress (M1)
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) }}"
tasks:
- name: Rollout status nginx-m1
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nginx-m1 -n default --timeout=180s
args:
executable: /bin/bash
changed_when: false
- name: HTTP check /demo-m1 (retry 503 for convergence)
ansible.builtin.shell: |
set -e
base="{{ verify_entry_base | trim | regex_replace('/+$','') }}"
url="$base/demo-m1/"
ok=0
for i in 1 2 3 4 5 6 7 8 9 10; do
code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
echo "try $i: $url -> $code"
if [ "$code" = "200" ]; then ok=1; break; fi
sleep 2
done
test "$ok" = "1"
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')
echo "X-Backend=$backend"
test "$backend" = "M1"
args:
executable: /bin/bash
changed_when: false
- name: Teardown 02-01 nginx control + Ingress (M1)
hosts: k3s_server
become: true
run_once: true
vars:
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
manifest_dest: /tmp/nginx-m1.yaml
tasks:
- name: Delete resources when VERIFY_TEARDOWN=1
when: verify_teardown == "1"
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f {{ manifest_dest }} --ignore-not-found=true
args:
executable: /bin/bash
changed_when: true

View File

@@ -0,0 +1,81 @@
---
# 02-02-nginx-control-ingressroute.md
# nginx M2控制节点 + IngressRoute路径 /demo-m2
- name: Deploy 02-02 nginx control + IngressRoute (M2)
hosts: k3s_server
become: true
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_dest: /tmp/nginx-m2.yaml
tasks:
- name: Copy manifest
ansible.builtin.copy:
src: "{{ manifest_src }}"
dest: "{{ manifest_dest }}"
mode: "0644"
- name: Apply manifest
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ manifest_dest }}
args:
executable: /bin/bash
changed_when: true
- name: Verify 02-02 nginx control + IngressRoute (M2)
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) }}"
tasks:
- name: Rollout status nginx-m2
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nginx-m2 -n default --timeout=180s
args:
executable: /bin/bash
changed_when: false
- name: HTTP check /demo-m2 (retry 503 for convergence)
ansible.builtin.shell: |
set -e
base="{{ verify_entry_base | trim | regex_replace('/+$','') }}"
url="$base/demo-m2/"
ok=0
for i in 1 2 3 4 5 6 7 8 9 10; do
code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
echo "try $i: $url -> $code"
if [ "$code" = "200" ]; then ok=1; break; fi
sleep 2
done
test "$ok" = "1"
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')
echo "X-Backend=$backend"
test "$backend" = "M2"
args:
executable: /bin/bash
changed_when: false
- name: Teardown 02-02 nginx control + IngressRoute (M2)
hosts: k3s_server
become: true
run_once: true
vars:
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
manifest_dest: /tmp/nginx-m2.yaml
tasks:
- name: Delete resources when VERIFY_TEARDOWN=1
when: verify_teardown == "1"
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f {{ manifest_dest }} --ignore-not-found=true
args:
executable: /bin/bash
changed_when: true

View File

@@ -0,0 +1,77 @@
- name: Deploy 02-03 nginx worker + Ingress (M3)
hosts: k3s_server
become: true
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_dest: /tmp/nginx-m3.yaml
tasks:
- name: Copy manifest
ansible.builtin.copy:
src: "{{ manifest_src }}"
dest: "{{ manifest_dest }}"
mode: "0644"
- name: Apply manifest
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ manifest_dest }}
args:
executable: /bin/bash
changed_when: true
- name: Verify 02-03 nginx worker + Ingress (M3)
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) }}"
tasks:
- name: Rollout status nginx-m3
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nginx-m3 -n default --timeout=180s
args:
executable: /bin/bash
changed_when: false
- name: HTTP check /demo-m3 (retry 503 for convergence)
ansible.builtin.shell: |
set -e
base="{{ verify_entry_base | trim | regex_replace('/+$','') }}"
url="$base/demo-m3/"
ok=0
for i in 1 2 3 4 5 6 7 8 9 10; do
code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
echo "try $i: $url -> $code"
if [ "$code" = "200" ]; then ok=1; break; fi
sleep 2
done
test "$ok" = "1"
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')
echo "X-Backend=$backend"
test "$backend" = "M3"
args:
executable: /bin/bash
changed_when: false
- name: Teardown 02-03 nginx worker + Ingress (M3)
hosts: k3s_server
become: true
run_once: true
vars:
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
manifest_dest: /tmp/nginx-m3.yaml
tasks:
- name: Delete resources when VERIFY_TEARDOWN=1
when: verify_teardown == "1"
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f {{ manifest_dest }} --ignore-not-found=true
args:
executable: /bin/bash
changed_when: true

View File

@@ -0,0 +1,77 @@
- name: Deploy 02-04 nginx worker + IngressRoute (M4)
hosts: k3s_server
become: true
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_dest: /tmp/nginx-m4.yaml
tasks:
- name: Copy manifest
ansible.builtin.copy:
src: "{{ manifest_src }}"
dest: "{{ manifest_dest }}"
mode: "0644"
- name: Apply manifest
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ manifest_dest }}
args:
executable: /bin/bash
changed_when: true
- name: Verify 02-04 nginx worker + IngressRoute (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) }}"
tasks:
- name: Rollout status nginx-m4
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nginx-m4 -n default --timeout=180s
args:
executable: /bin/bash
changed_when: false
- name: HTTP check /demo-m4 (retry 503 for convergence)
ansible.builtin.shell: |
set -e
base="{{ verify_entry_base | trim | regex_replace('/+$','') }}"
url="$base/demo-m4/"
ok=0
for i in 1 2 3 4 5 6 7 8 9 10; do
code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 --max-time 8 "$url" 2>/dev/null || echo "000")
echo "try $i: $url -> $code"
if [ "$code" = "200" ]; then ok=1; break; fi
sleep 2
done
test "$ok" = "1"
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')
echo "X-Backend=$backend"
test "$backend" = "M4"
args:
executable: /bin/bash
changed_when: false
- name: Teardown 02-04 nginx worker + IngressRoute (M4)
hosts: k3s_server
become: true
run_once: true
vars:
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
manifest_dest: /tmp/nginx-m4.yaml
tasks:
- name: Delete resources when VERIFY_TEARDOWN=1
when: verify_teardown == "1"
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f {{ manifest_dest }} --ignore-not-found=true
args:
executable: /bin/bash
changed_when: true

View File

@@ -0,0 +1,65 @@
- import_playbook: "{{ playbook_dir }}/../nginx-matrix-deploy.yml"
- name: Verify 02-05 nginx matrix (HTTP paths)
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) }}"
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: 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: 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"
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f /tmp/nginx-matrix/ -R --ignore-not-found=true
args:
executable: /bin/bash
changed_when: true

View File

@@ -0,0 +1,65 @@
- name: Deploy 03-01 Traefik Dashboard
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_dest: /tmp/traefik-dashboard.yaml
tasks:
- name: Copy manifest
ansible.builtin.copy:
src: "{{ manifest_src }}"
dest: "{{ manifest_dest }}"
mode: "0644"
- name: Apply manifest + restart traefik
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
hosts: k3s_server
become: true
run_once: true
vars:
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
tasks:
- name: Wait traefik rollout
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n kube-system rollout status deploy/traefik --timeout=180s
args:
executable: /bin/bash
changed_when: false
- name: Assert traefik-dashboard IngressRoute exists
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n kube-system get ingressroute.traefik.io/traefik-dashboard
args:
executable: /bin/bash
changed_when: false
- name: Teardown 03-01 Traefik Dashboard (optional)
hosts: k3s_server
become: true
run_once: true
vars:
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
manifest_dest: /tmp/traefik-dashboard.yaml
tasks:
- name: Delete resources when VERIFY_TEARDOWN=1
when: verify_teardown == "1"
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f {{ manifest_dest }} --ignore-not-found=true
args:
executable: /bin/bash
changed_when: true

View File

@@ -0,0 +1,98 @@
- name: Deploy 03-02 Traefik ACME (gated)
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_dest: /tmp/traefik-acme.yaml
acme_email: "{{ ACME_EMAIL | default('') }}"
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: 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
- name: Apply manifest + restart traefik
when: acme_gate.rc == 0
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)
hosts: k3s_server
become: true
run_once: true
vars:
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
acme_email: "{{ ACME_EMAIL | default('') }}"
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: Wait traefik rollout
when: acme_gate.rc == 0
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n kube-system rollout status deploy/traefik --timeout=180s
args:
executable: /bin/bash
changed_when: false
- name: Teardown 03-02 Traefik ACME (optional)
hosts: k3s_server
become: true
run_once: true
vars:
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
manifest_dest: /tmp/traefik-acme.yaml
acme_email: "{{ ACME_EMAIL | default('') }}"
tasks:
- 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

View File

@@ -0,0 +1,10 @@
- name: "03-03 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "03-03"
doc_filename: "03-03-k3s-traefik-dashboard-acme.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "03-04 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "03-04"
doc_filename: "03-04-k3s-cloudflare-tunnel-配置接入.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,66 @@
- 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-demo/local-path-pvc-demo.yaml"
manifest_dest: /tmp/local-path-pvc-demo.yaml
tasks:
- name: Copy manifest to server
ansible.builtin.copy:
src: "{{ manifest_src }}"
dest: "{{ manifest_dest }}"
mode: "0644"
- name: kubectl apply
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ manifest_dest }}
args:
executable: /bin/bash
changed_when: true
- 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
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl rollout status deployment/nginx-local-pvc-demo -n default --timeout=180s
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)
hosts: k3s_server
become: true
run_once: true
vars:
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
manifest_dest: /tmp/local-path-pvc-demo.yaml
tasks:
- name: Delete resources when VERIFY_TEARDOWN=1
when: verify_teardown == "1"
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f {{ manifest_dest }} --ignore-not-found=true
args:
executable: /bin/bash
changed_when: true

View File

@@ -0,0 +1,94 @@
- name: Deploy 03-06 NFS PV/PVC demo (gated)
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_dest: /tmp/nfs-pv-pvc-demo.yaml
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: 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
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ manifest_dest }}
args:
executable: /bin/bash
changed_when: true
- name: Verify 03-06 NFS PV/PVC demo (gated)
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('') }}"
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: 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)
hosts: k3s_server
become: true
run_once: true
vars:
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
manifest_dest: /tmp/nfs-pv-pvc-demo.yaml
nfs_server_ip: "{{ NFS_SERVER_IP | default('') }}"
nfs_export_path: "{{ NFS_EXPORT_PATH | default('') }}"
tasks:
- 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

View File

@@ -0,0 +1,41 @@
- import_playbook: "{{ playbook_dir }}/../longhorn-install.yml"
- name: Verify 03-07 Longhorn (namespace pods)
hosts: k3s_server
become: true
run_once: true
vars:
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
longhorn_ns: "{{ longhorn_namespace | default('longhorn-system') }}"
tasks:
- name: Check longhorn pods
ansible.builtin.shell: |
set -e
KUBECONFIG={{ k3s_kubeconfig }} kubectl get pods -n {{ longhorn_ns }} -o wide
args:
executable: /bin/bash
changed_when: false
- name: Teardown 03-07 Longhorn (optional)
hosts: k3s_server
become: true
run_once: true
vars:
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
longhorn_ns: "{{ longhorn_namespace | default('longhorn-system') }}"
tasks:
- name: Uninstall longhorn helm release when VERIFY_TEARDOWN=1
when: verify_teardown == "1"
ansible.builtin.shell: |
set -e
export KUBECONFIG={{ k3s_kubeconfig }}
if helm -n {{ longhorn_ns }} list 2>/dev/null | grep -q longhorn; then
timeout 180s helm -n {{ longhorn_ns }} uninstall longhorn --no-hooks || true
fi
kubectl delete ns {{ longhorn_ns }} --ignore-not-found=true --wait=false || true
args:
executable: /bin/bash
changed_when: true
failed_when: false

View File

@@ -0,0 +1,10 @@
- name: "03-08 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "03-08"
doc_filename: "03-08-k3s-ha-集群配置与切换.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "03-09 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "03-09"
doc_filename: "03-09-k3s-gitops-集群配置管理.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "03-10 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "03-10"
doc_filename: "03-10-k3s-traefik-custom-ports.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,49 @@
- import_playbook: "{{ playbook_dir }}/../nodejs-demo-apply.yml"
- name: Verify 04-01 nodejs demo (rollout + HTTP)
hosts: k3s_server
become: true
run_once: true
vars:
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
verify_entry_base: "{{ nodejs_entry_base | default('http://' ~ k3s_server_ip) }}"
tasks:
- 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: HTTP check /node (expect 200 and Hello World)
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")
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

View File

@@ -0,0 +1,10 @@
- name: "04-02 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "04-02"
doc_filename: "04-02-nodejs-镜像与运行命令.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "04-03 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "04-03"
doc_filename: "04-03-nodejs-环境变量与配置注入.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "04-04 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "04-04"
doc_filename: "04-04-nodejs-端口与Service.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "04-05 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "04-05"
doc_filename: "04-05-nodejs-资源请求与限制.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "04-06 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "04-06"
doc_filename: "04-06-nodejs-探针与健康检查.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "04-07 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "04-07"
doc_filename: "04-07-nodejs-调度与亲和.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "04-08 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "04-08"
doc_filename: "04-08-nodejs-安全上下文.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "04-09 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "04-09"
doc_filename: "04-09-nodejs-存储与卷.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "04-10 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "04-10"
doc_filename: "04-10-nodejs-Ingress与Traefik.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "04-11 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "04-11"
doc_filename: "04-11-nodejs-副本与滚动发布.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "04-12 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "04-12"
doc_filename: "04-12-nodejs-TLS与证书.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "04-13 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "04-13"
doc_filename: "04-13-nodejs-HPA.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "04-14 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "04-14"
doc_filename: "04-14-nodejs-GitOps与CI流水线.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "05-01 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "05-01"
doc_filename: "05-01-k3s-部署homer首页面板.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "05-02 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "05-02"
doc_filename: "05-02-onenav首页面板.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "05-03 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "05-03"
doc_filename: "05-03-k3s-安装gitlab-含runner.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "05-04 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "05-04"
doc_filename: "05-04-k3s-配置gitlab-cicd.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "05-05 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "05-05"
doc_filename: "05-05-prometheus与grafana.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "05-06 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "05-06"
doc_filename: "05-06-openlist挂载网盘与自动备份.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "05-07 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "05-07"
doc_filename: "05-07-openclaw应用部署.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "05-08 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "05-08"
doc_filename: "05-08-openclaw-k3s-实验部署.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "05-09 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "05-09"
doc_filename: "05-09-openclaw-web-小游戏网页平台.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "06-01 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "06-01"
doc_filename: "06-01-k3s-networkpolicy-故障排查.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "06-02 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "06-02"
doc_filename: "06-02-运维小结.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,10 @@
- name: "06-03 noop verify"
hosts: localhost
gather_facts: false
vars:
repo_root: "{{ playbook_dir }}/../../.."
doc_id: "06-03"
doc_filename: "06-03-k3s-自动备份与恢复-openlist-webdav.md"
tasks:
- ansible.builtin.import_tasks: "{{ playbook_dir }}/_noop-tasks.yml"

View File

@@ -0,0 +1,32 @@
- 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 }}"