基本框架
This commit is contained in:
197
ansible/playbooks/k3s-init-and-install.yml
Normal file
197
ansible/playbooks/k3s-init-and-install.yml
Normal file
@@ -0,0 +1,197 @@
|
||||
---
|
||||
- name: Init base system
|
||||
hosts: k3s_nodes
|
||||
become: true
|
||||
tasks:
|
||||
# 检查当前节点上 firewalld 的运行状态,供后续条件判断使用
|
||||
- name: Check if firewalld is running
|
||||
ansible.builtin.command: firewall-cmd --state
|
||||
register: firewalld_state
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
# 根据全局 timezone 变量设置系统时区(可选)
|
||||
- name: Set timezone
|
||||
ansible.builtin.command: timedatectl set-timezone {{ timezone }}
|
||||
when: timezone is defined and timezone != ""
|
||||
|
||||
# 安装 k3s 所需的基础工具包(curl、git 等)
|
||||
- name: Install basic packages
|
||||
ansible.builtin.package:
|
||||
name:
|
||||
- curl
|
||||
- git
|
||||
state: present
|
||||
|
||||
# 确保 /etc/hosts 中包含所有 k3s 节点的主机名解析(可选)
|
||||
- name: Ensure /etc/hosts has entries for all k3s nodes
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/hosts
|
||||
regexp: '^\S+\s+{{ item }}\s*$'
|
||||
line: "{{ hostvars[item]['ansible_host'] }} {{ item }}"
|
||||
state: present
|
||||
loop: "{{ groups['k3s_nodes'] }}"
|
||||
when:
|
||||
- k3s_manage_hosts | default(true) | bool
|
||||
- hostvars[item]['ansible_host'] is defined
|
||||
|
||||
# k3s 所需端口:8472/udp(flannel VXLAN)全部节点;6443/tcp(API)仅 server
|
||||
# 必须在安装 k3s 前开放,否则 worker 无法连接、flannel 无法建立 overlay
|
||||
# 在所有 k3s 节点上开放 flannel VXLAN 所需的 8472/udp 端口
|
||||
- name: Open flannel VXLAN port (8472/udp) on all k3s nodes
|
||||
ansible.builtin.command: firewall-cmd --permanent --add-port=8472/udp
|
||||
when:
|
||||
- k3s_manage_firewalld | default(true) | bool
|
||||
- firewalld_state.stdout | default('') == 'running'
|
||||
|
||||
# 在 server 节点上开放 k3s API 端口 6443/tcp
|
||||
- name: Open k3s API port (6443/tcp) on server
|
||||
ansible.builtin.command: firewall-cmd --permanent --add-port=6443/tcp
|
||||
when:
|
||||
- k3s_manage_firewalld | default(true) | bool
|
||||
- inventory_hostname in groups['k3s_server']
|
||||
- firewalld_state.stdout | default('') == 'running'
|
||||
|
||||
# 在完成端口放行后重新加载 firewalld 规则
|
||||
- name: Reload firewalld after opening k3s ports
|
||||
ansible.builtin.command: firewall-cmd --reload
|
||||
when:
|
||||
- k3s_manage_firewalld | default(true) | bool
|
||||
- firewalld_state.stdout | default('') == 'running'
|
||||
|
||||
- name: Install k3s server
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
tasks:
|
||||
# 在 server 节点上下载安装并启动 k3s server 进程
|
||||
- name: Download and install k3s server
|
||||
ansible.builtin.shell: |
|
||||
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server --data-dir={{ k3s_data_dir }}" sh -
|
||||
args:
|
||||
creates: "{{ k3s_data_dir }}/server"
|
||||
|
||||
- name: Install k3s agent (workers)
|
||||
hosts: k3s_worker
|
||||
become: true
|
||||
serial: 1 # 逐台安装,减轻并行下载对网络的压力
|
||||
tasks:
|
||||
# 从首个 server 节点读取集群 token(仅执行一次)
|
||||
- name: Read k3s token from first server
|
||||
ansible.builtin.slurp:
|
||||
src: "{{ k3s_data_dir }}/server/token"
|
||||
delegate_to: "{{ groups['k3s_server'][0] }}"
|
||||
run_once: true
|
||||
register: k3s_token_from_server
|
||||
|
||||
# 在各 worker 节点上保存解码后的 token 供后续安装使用
|
||||
- name: Set fact for k3s token on workers
|
||||
ansible.builtin.set_fact:
|
||||
k3s_token: "{{ k3s_token_from_server.content | b64decode | trim }}"
|
||||
|
||||
# 在每个 worker 节点上下载安装并启动 k3s agent 进程
|
||||
- name: Install k3s agent
|
||||
ansible.builtin.shell: |
|
||||
curl -sfL https://get.k3s.io | K3S_URL=https://{{ k3s_server_ip }}:6443 K3S_TOKEN={{ k3s_token }} INSTALL_K3S_EXEC="agent --data-dir={{ k3s_data_dir }}" sh -
|
||||
args:
|
||||
creates: "{{ k3s_data_dir }}/agent"
|
||||
async: 600
|
||||
poll: 15
|
||||
|
||||
- name: Configure firewalld baseline for k3s (flannel.1 / cni0 -> trusted)
|
||||
hosts: k3s_nodes
|
||||
become: true
|
||||
tasks:
|
||||
# 为 k3s 配置 firewalld 基线:将 flannel.1 / cni0 加入 trusted 区域
|
||||
- block:
|
||||
# 检查节点上 firewalld 是否可用
|
||||
- name: Check if firewalld is available
|
||||
ansible.builtin.command: firewall-cmd --state
|
||||
register: firewalld_check
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
# 等待 CNI 接口 flannel.1 和 cni0 出现(k3s 启动并创建完成)
|
||||
- name: Wait for CNI interfaces (flannel.1, cni0) to appear
|
||||
ansible.builtin.shell: |
|
||||
for i in $(seq 1 120); do
|
||||
ip link show flannel.1 >/dev/null 2>&1 && ip link show cni0 >/dev/null 2>&1 && exit 0
|
||||
sleep 1
|
||||
done
|
||||
exit 1
|
||||
when: firewalld_check.stdout == 'running'
|
||||
|
||||
# 将 flannel.1 / cni0 接口加入 firewalld trusted 区域(运行时和永久)
|
||||
- name: Add flannel.1 and cni0 to firewalld trusted zone (runtime + permanent)
|
||||
ansible.builtin.shell: |
|
||||
firewall-cmd --zone=trusted --add-interface={{ item }}
|
||||
firewall-cmd --permanent --zone=trusted --add-interface={{ item }}
|
||||
loop:
|
||||
- flannel.1
|
||||
- cni0
|
||||
when: firewalld_check.stdout == 'running'
|
||||
|
||||
# 更新 firewalld 配置使新接口规则立即生效
|
||||
- name: Reload firewalld
|
||||
ansible.builtin.command: firewall-cmd --reload
|
||||
when: firewalld_check.stdout == 'running'
|
||||
when: k3s_manage_firewalld | default(true) | bool
|
||||
|
||||
- name: 安装后验证 - traefik / nodes / curl
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
tasks:
|
||||
# 安装后为控制节点打 control-plane 标签(02-05 矩阵 M1 需此标签才能调度),节点名与 inventory 短主机名一致(ylc61~ylc64)
|
||||
- name: Label control-plane nodes (k3s 不默认打标,M1 需此标签)
|
||||
ansible.builtin.shell: |
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl label node {{ item }} node-role.kubernetes.io/control-plane= --overwrite
|
||||
loop: "{{ groups['k3s_server'] | default([]) }}"
|
||||
|
||||
# 可选:为工作节点打 worker 标签(02-05 矩阵 M3 需要)
|
||||
- name: 可选 - 为工作节点打 worker 标签(02-05 矩阵 M3 需要)
|
||||
ansible.builtin.shell: |
|
||||
KUBECONFIG={{ k3s_kubeconfig }} kubectl label node {{ item }} node-role.kubernetes.io/worker= --overwrite
|
||||
loop: "{{ groups['k3s_worker'] | default([]) }}"
|
||||
when: k3s_manage_role_labels | default(true) | bool
|
||||
|
||||
# 查看 kube-system 命名空间中与 Traefik / svclb 相关的 Pod 列表
|
||||
- name: kubectl get pods -n kube-system(traefik / svclb)
|
||||
ansible.builtin.shell: KUBECONFIG={{ k3s_kubeconfig }} kubectl get pods -n kube-system -o wide | grep -E 'NAME|traefik|svclb'
|
||||
register: verify_traefik
|
||||
changed_when: false
|
||||
|
||||
# 打印上一步查询到的 Traefik 相关 Pod 信息
|
||||
- name: ">>> Traefik 相关 Pods"
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ item }}"
|
||||
loop: "{{ verify_traefik.stdout_lines }}"
|
||||
|
||||
# 查询当前集群中的节点列表
|
||||
- name: kubectl get nodes
|
||||
ansible.builtin.shell: KUBECONFIG={{ k3s_kubeconfig }} kubectl get nodes
|
||||
register: verify_nodes
|
||||
changed_when: false
|
||||
|
||||
# 打印节点列表结果,方便确认节点状态与角色
|
||||
- name: ">>> kubectl get nodes"
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ item }}"
|
||||
loop: "{{ verify_nodes.stdout_lines }}"
|
||||
|
||||
# 通过 curl 测试每个节点 80 与 443 入口连通性
|
||||
- name: curl 测试各节点 80/443 可达性
|
||||
ansible.builtin.shell: |
|
||||
for ip in {{ groups['k3s_nodes'] | map('extract', hostvars) | map(attribute='ansible_host') | join(' ') }}; do
|
||||
c80=$(curl -sk -o /dev/null -w "%{http_code}" --connect-timeout 2 http://$ip 2>/dev/null) || c80="fail"
|
||||
c443=$(curl -sk -o /dev/null -w "%{http_code}" --connect-timeout 2 https://$ip 2>/dev/null) || c443="fail"
|
||||
echo "$ip: 80=$c80 443=$c443"
|
||||
done
|
||||
register: verify_curl
|
||||
changed_when: false
|
||||
|
||||
- name: ">>> curl 结果"
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ item }}"
|
||||
loop: "{{ verify_curl.stdout_lines }}"
|
||||
166
ansible/playbooks/nginx-matrix-deploy.yml
Normal file
166
ansible/playbooks/nginx-matrix-deploy.yml
Normal file
@@ -0,0 +1,166 @@
|
||||
---
|
||||
# Ansible 一键部署 nginx 矩阵(M1~M4)
|
||||
# 对应文档:docs/02-05-nginx-验证矩阵-一键部署.md(02-01~02-04 分篇已整合)
|
||||
#
|
||||
# 说明:复制 manifests → kubectl apply → 等待 Pod 就绪 → 验证 Pod 节点分布 → curl 16 目标
|
||||
# manifests:ansible/files/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
|
||||
# 或在仓库根目录:
|
||||
# ansible-playbook -i ansible/inventory.ini ansible/playbooks/nginx-matrix-deploy.yml
|
||||
- name: Deploy nginx matrix (M1~M4)
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
vars:
|
||||
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
# manifests 在 ansible/files/nginx-matrix/,与 playbook 同项目
|
||||
manifests_path: "{{ playbook_dir }}/../files/nginx-matrix"
|
||||
tasks:
|
||||
- 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
|
||||
|
||||
# 部署前确保 control-plane/worker 标签存在(M1/M3 需此才能调度),节点名为短主机名(ylc61~ylc64)
|
||||
- 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 manifests to server
|
||||
ansible.builtin.copy:
|
||||
src: "{{ manifests_path }}/"
|
||||
dest: /tmp/nginx-matrix/
|
||||
mode: '0644'
|
||||
|
||||
# 先删全部 nginx 矩阵 Deployment 再 apply,避免旧 ReplicaSet 导致任一 Mx 仍显示默认页
|
||||
- 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(' ') }}"
|
||||
paths="/demo-m1 /demo-m2 /demo-m3 /demo-m4"
|
||||
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 }}"
|
||||
188
ansible/playbooks/nginx-matrix-tls-deploy.yml
Normal file
188
ansible/playbooks/nginx-matrix-tls-deploy.yml
Normal file
@@ -0,0 +1,188 @@
|
||||
---
|
||||
# Ansible 一键部署 nginx 矩阵 TLS 版(M1~M4,HTTPS)
|
||||
# 对应文档: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 矩阵验证(test01~test04.jackadam.top)
|
||||
# manifests:ansible/files/nginx-matrix-tls/,域名为 test01~test04.jackadam.top,M2/M4 hostname 按实际修改;Ingress/IngressRoute 中 TLS 路由仅绑定 websecure,HTTP-only 路由仅绑定 web
|
||||
# 前置:已按 03-02 配置 ACME(Secret + traefik-acme.yaml),且 test01~test04.jackadam.top 已解析到入口 IP
|
||||
#
|
||||
# 执行(在 ansible/ 目录下):
|
||||
# ansible-playbook -i inventory.ini playbooks/nginx-matrix-tls-deploy.yml
|
||||
# 或在仓库根目录:
|
||||
# ansible-playbook -i ansible/inventory.ini ansible/playbooks/nginx-matrix-tls-deploy.yml
|
||||
# 验证时对所有 k3s_nodes 做 HTTPS 请求(所有节点均为入口点,与 02-05 HTTP 矩阵一致)
|
||||
- name: Deploy or cleanup nginx matrix TLS (M1~M4, HTTPS)
|
||||
hosts: k3s_server
|
||||
become: true
|
||||
run_once: true
|
||||
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"
|
||||
tls_domains:
|
||||
- test01.jackadam.top
|
||||
- test02.jackadam.top
|
||||
- test03.jackadam.top
|
||||
- test04.jackadam.top
|
||||
tasks:
|
||||
- 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
|
||||
|
||||
# 部署前确保 control-plane/worker 标签存在(M1/M3 需此才能调度),节点名为短主机名(ylc61~ylc64)
|
||||
- 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'
|
||||
|
||||
# 若存在不含 TLS 的 nginx 矩阵(02-05),先删掉,避免与 TLS 版 Ingress 冲突或残留
|
||||
- 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
|
||||
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 TLS resources
|
||||
ansible.builtin.shell: KUBECONFIG={{ k3s_kubeconfig }} kubectl get pod,svc,ing,ingressroute -n default -o wide
|
||||
register: verify
|
||||
changed_when: false
|
||||
|
||||
- name: ">>> nginx matrix TLS 资源"
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ item }}"
|
||||
loop: "{{ verify.stdout_lines }}"
|
||||
|
||||
- name: 验证 M1~M4 标识(Pod 内 index.html 含 Mx、响应头 X-Backend,取首个入口节点)
|
||||
ansible.builtin.shell: |
|
||||
first_ip="{{ 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 (入口 $first_ip) ==="
|
||||
curl -sI "https://test0$id.jackadam.top/" --resolve "test0$id.jackadam.top:443:$first_ip" -k 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: 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"
|
||||
register: curl_http_result
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: ">>> HTTP curl 矩阵(HTTP-only)"
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ item }}"
|
||||
loop: "{{ curl_http_result.stdout_lines }}"
|
||||
|
||||
- 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"
|
||||
register: curl_result
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: ">>> HTTPS curl 矩阵"
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ item }}"
|
||||
loop: "{{ curl_result.stdout_lines }}"
|
||||
|
||||
- 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
|
||||
47
ansible/playbooks/nodejs-demo-apply.yml
Normal file
47
ansible/playbooks/nodejs-demo-apply.yml
Normal file
@@ -0,0 +1,47 @@
|
||||
---
|
||||
# 一键应用 Node.js demo 清单(与 docs/04-01~04-13 + ansible/files/nodejs-demo 对齐)
|
||||
#
|
||||
# 执行(在仓库根目录):
|
||||
# ansible-playbook -i ansible/inventory.ini ansible/playbooks/nodejs-demo-apply.yml \
|
||||
# -e nodejs_demo_manifest=04-01-nodejs-demo.yaml
|
||||
#
|
||||
# 默认清单:04-01-nodejs-demo.yaml
|
||||
- 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/nodejs-demo"
|
||||
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: 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
|
||||
Reference in New Issue
Block a user