基本框架
This commit is contained in:
5
ansible/ansible.cfg
Normal file
5
ansible/ansible.cfg
Normal file
@@ -0,0 +1,5 @@
|
||||
[defaults]
|
||||
# 首次连接时跳过 host key 确认(实验室环境可接受)
|
||||
host_key_checking = False
|
||||
# 使用 inventory 同目录
|
||||
inventory = inventory.ini
|
||||
11
ansible/files/01-08-haproxy/README.md
Normal file
11
ansible/files/01-08-haproxy/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# 01-08 HAProxy 配置
|
||||
|
||||
用于 `docs/01-08-openwrt-haproxy.md`,可与 Ansible 共用(复制到 OpenWrt 或通过 playbook 下发)。
|
||||
|
||||
| 文件 | 说明 |
|
||||
|------|------|
|
||||
| haproxy.cfg | 基础配置,TCP 健康检查 |
|
||||
| haproxy-proxy.cfg | 启用 send-proxy-v2(Traefik 真实 IP) |
|
||||
| haproxy-proxy-http-tls.cfg | HTTP 检查 + TLS 检查 + PROXY 组合 |
|
||||
|
||||
按实际节点 IP 修改 `192.168.2.61`~`192.168.2.64`。80/443 被封时可将 `bind *:80` / `bind *:443` 改为 `*:18080` / `*:18443`。
|
||||
39
ansible/files/01-08-haproxy/haproxy-proxy-http-tls.cfg
Normal file
39
ansible/files/01-08-haproxy/haproxy-proxy-http-tls.cfg
Normal file
@@ -0,0 +1,39 @@
|
||||
# 01-08 HAProxy - 健康检查升级(HTTP+TLS)+ PROXY Protocol
|
||||
# 组合:k3s_http 用 option httpchk,k3s_https 用 ssl-hello-chk,均带 send-proxy-v2
|
||||
# 文档:docs/01-08-openwrt-haproxy.md 第 5 节「健康检查与 PROXY 组合」
|
||||
global
|
||||
log /dev/log local0
|
||||
maxconn 4096
|
||||
|
||||
defaults
|
||||
mode http
|
||||
option httplog
|
||||
timeout connect 5s
|
||||
timeout client 30s
|
||||
timeout server 30s
|
||||
|
||||
frontend http_in
|
||||
bind *:80
|
||||
default_backend k3s_http
|
||||
|
||||
frontend https_in
|
||||
bind *:443
|
||||
mode tcp
|
||||
default_backend k3s_https
|
||||
|
||||
backend k3s_http
|
||||
option httpchk GET /
|
||||
balance roundrobin
|
||||
server ylc61 192.168.2.61:80 check send-proxy-v2
|
||||
server ylc62 192.168.2.62:80 check send-proxy-v2
|
||||
server ylc63 192.168.2.63:80 check send-proxy-v2
|
||||
server ylc64 192.168.2.64:80 check send-proxy-v2
|
||||
|
||||
backend k3s_https
|
||||
mode tcp
|
||||
option ssl-hello-chk
|
||||
balance roundrobin
|
||||
server ylc61 192.168.2.61:443 check send-proxy-v2
|
||||
server ylc62 192.168.2.62:443 check send-proxy-v2
|
||||
server ylc63 192.168.2.63:443 check send-proxy-v2
|
||||
server ylc64 192.168.2.64:443 check send-proxy-v2
|
||||
37
ansible/files/01-08-haproxy/haproxy-proxy.cfg
Normal file
37
ansible/files/01-08-haproxy/haproxy-proxy.cfg
Normal file
@@ -0,0 +1,37 @@
|
||||
# 01-08 HAProxy - 启用 PROXY Protocol(send-proxy-v2)
|
||||
# 用于 Traefik 获取真实客户端 IP,需配合 Traefik trustedIPs
|
||||
# 文档:docs/01-08-openwrt-haproxy.md 第 5 节
|
||||
global
|
||||
log /dev/log local0
|
||||
maxconn 4096
|
||||
|
||||
defaults
|
||||
mode http
|
||||
option httplog
|
||||
timeout connect 5s
|
||||
timeout client 30s
|
||||
timeout server 30s
|
||||
|
||||
frontend http_in
|
||||
bind *:80
|
||||
default_backend k3s_http
|
||||
|
||||
frontend https_in
|
||||
bind *:443
|
||||
mode tcp
|
||||
default_backend k3s_https
|
||||
|
||||
backend k3s_http
|
||||
balance roundrobin
|
||||
server ylc61 192.168.2.61:80 check send-proxy-v2
|
||||
server ylc62 192.168.2.62:80 check send-proxy-v2
|
||||
server ylc63 192.168.2.63:80 check send-proxy-v2
|
||||
server ylc64 192.168.2.64:80 check send-proxy-v2
|
||||
|
||||
backend k3s_https
|
||||
mode tcp
|
||||
balance roundrobin
|
||||
server ylc61 192.168.2.61:443 check send-proxy-v2
|
||||
server ylc62 192.168.2.62:443 check send-proxy-v2
|
||||
server ylc63 192.168.2.63:443 check send-proxy-v2
|
||||
server ylc64 192.168.2.64:443 check send-proxy-v2
|
||||
38
ansible/files/01-08-haproxy/haproxy.cfg
Normal file
38
ansible/files/01-08-haproxy/haproxy.cfg
Normal file
@@ -0,0 +1,38 @@
|
||||
# 01-08 OpenWrt HAProxy 负载均衡 - 基础配置
|
||||
# 文档:docs/01-08-openwrt-haproxy.md
|
||||
# 将 192.168.2.61~64 按实际 K3s 节点 IP 修改
|
||||
global
|
||||
log /dev/log local0
|
||||
maxconn 4096
|
||||
# 部分 OpenWrt 需 daemon / pidfile,按发行版调整;若无 /dev/log 可改 log 127.0.0.1 local0
|
||||
|
||||
defaults
|
||||
mode http
|
||||
option httplog
|
||||
timeout connect 5s
|
||||
timeout client 30s
|
||||
timeout server 30s
|
||||
|
||||
frontend http_in
|
||||
bind *:80
|
||||
default_backend k3s_http
|
||||
|
||||
frontend https_in
|
||||
bind *:443
|
||||
mode tcp
|
||||
default_backend k3s_https
|
||||
|
||||
backend k3s_http
|
||||
balance roundrobin
|
||||
server ylc61 192.168.2.61:80 check
|
||||
server ylc62 192.168.2.62:80 check
|
||||
server ylc63 192.168.2.63:80 check
|
||||
server ylc64 192.168.2.64:80 check
|
||||
|
||||
backend k3s_https
|
||||
mode tcp
|
||||
balance roundrobin
|
||||
server ylc61 192.168.2.61:443 check
|
||||
server ylc62 192.168.2.62:443 check
|
||||
server ylc63 192.168.2.63:443 check
|
||||
server ylc64 192.168.2.64:443 check
|
||||
37
ansible/files/cloudflare-tunnel/cloudflared.yaml
Normal file
37
ansible/files/cloudflare-tunnel/cloudflared.yaml
Normal file
@@ -0,0 +1,37 @@
|
||||
# docs/03-04-k3s-cloudflare-tunnel-配置接入.md — 替换 TUNNEL_TOKEN 后应用
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: cloudflared-credentials
|
||||
namespace: kube-system
|
||||
type: Opaque
|
||||
stringData:
|
||||
TUNNEL_TOKEN: "<YOUR_TUNNEL_TOKEN>"
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: cloudflared
|
||||
namespace: kube-system
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: cloudflared
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: cloudflared
|
||||
spec:
|
||||
containers:
|
||||
- name: cloudflared
|
||||
image: cloudflare/cloudflared:latest
|
||||
args:
|
||||
- tunnel
|
||||
- run
|
||||
env:
|
||||
- name: TUNNEL_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: cloudflared-credentials
|
||||
key: TUNNEL_TOKEN
|
||||
9
ansible/files/gitlab/README.md
Normal file
9
ansible/files/gitlab/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# GitLab CI 示例(与 docs 对照)
|
||||
|
||||
| 文件 | 文档 |
|
||||
|------|------|
|
||||
| `gitlab-ci-minimal.example.yml` | `docs/05-04-k3s-配置gitlab-cicd.md` |
|
||||
| `gitlab-ci-multi-arch-deploy.example.yml` | `docs/05-04-k3s-配置gitlab-cicd.md` |
|
||||
| `gitlab-ci-runner-tags.example.yml` | `docs/05-03-k3s-安装gitlab-含runner.md` |
|
||||
|
||||
复制为 `.gitlab-ci.yml` 或 `include` 引用;变量与 Runner 以文档为准。
|
||||
20
ansible/files/gitlab/gitlab-ci-minimal.example.yml
Normal file
20
ansible/files/gitlab/gitlab-ci-minimal.example.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
# docs/05-04-k3s-配置gitlab-cicd.md — 最小 .gitlab-ci.yml 示例
|
||||
stages:
|
||||
- lint
|
||||
- deploy
|
||||
|
||||
variables:
|
||||
KUBECONFIG: "/builds/${CI_PROJECT_PATH}/kubeconfig"
|
||||
|
||||
lint:
|
||||
stage: lint
|
||||
script:
|
||||
- yamllint manifests || true
|
||||
|
||||
deploy:
|
||||
stage: deploy
|
||||
script:
|
||||
- echo "$KUBE_CONFIG_CONTENT" > "$KUBECONFIG"
|
||||
- kubectl --kubeconfig="$KUBECONFIG" apply -f manifests/
|
||||
only:
|
||||
- main
|
||||
14
ansible/files/gitlab/gitlab-ci-multi-arch-deploy.example.yml
Normal file
14
ansible/files/gitlab/gitlab-ci-multi-arch-deploy.example.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
# docs/05-04-k3s-配置gitlab-cicd.md — 多架构 Runner tags 示例
|
||||
deploy_x86:
|
||||
stage: deploy
|
||||
tags: [x86]
|
||||
script:
|
||||
- echo "$KUBE_CONFIG_CONTENT" > "$KUBECONFIG"
|
||||
- kubectl --kubeconfig="$KUBECONFIG" apply -f manifests/x86/
|
||||
|
||||
deploy_arm64:
|
||||
stage: deploy
|
||||
tags: [arm64]
|
||||
script:
|
||||
- echo "$KUBE_CONFIG_CONTENT" > "$KUBECONFIG"
|
||||
- kubectl --kubeconfig="$KUBECONFIG" apply -f manifests/arm64/
|
||||
15
ansible/files/gitlab/gitlab-ci-runner-tags.example.yml
Normal file
15
ansible/files/gitlab/gitlab-ci-runner-tags.example.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
# docs/05-03-k3s-安装gitlab-含runner.md — Runner tag 与 job 对应示例
|
||||
build_x86:
|
||||
tags: [x86]
|
||||
script:
|
||||
- echo "build for x86"
|
||||
|
||||
build_arm64:
|
||||
tags: [arm64]
|
||||
script:
|
||||
- echo "build for arm64"
|
||||
|
||||
build_armv7:
|
||||
tags: [armv7]
|
||||
script:
|
||||
- echo "build for armv7"
|
||||
53
ansible/files/homer/homer.yaml
Normal file
53
ansible/files/homer/homer.yaml
Normal file
@@ -0,0 +1,53 @@
|
||||
# docs/05-01-k3s-部署homer首页面板.md — 按需修改 host
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: homer
|
||||
namespace: homer
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: homer
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: homer
|
||||
spec:
|
||||
containers:
|
||||
- name: homer
|
||||
image: b4bz/homer:latest
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: homer
|
||||
namespace: homer
|
||||
spec:
|
||||
selector:
|
||||
app: homer
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: homer
|
||||
namespace: homer
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||
spec:
|
||||
rules:
|
||||
- host: home.example.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: homer
|
||||
port:
|
||||
number: 80
|
||||
38
ansible/files/local-path-demo/local-path-pvc-demo.yaml
Normal file
38
ansible/files/local-path-demo/local-path-pvc-demo.yaml
Normal file
@@ -0,0 +1,38 @@
|
||||
# docs/03-05-k3s-local-path-pvc.md
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: local-pvc-demo
|
||||
namespace: default
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-local-pvc-demo
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx-local-pvc-demo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx-local-pvc-demo
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:alpine
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /usr/share/nginx/html
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: local-pvc-demo
|
||||
27
ansible/files/nfs-demo/nfs-pv-pvc-demo.yaml
Normal file
27
ansible/files/nfs-demo/nfs-pv-pvc-demo.yaml
Normal file
@@ -0,0 +1,27 @@
|
||||
# docs/03-06-k3s-使用nfs存储.md — 按环境修改 server/path
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: nfs-pv-demo
|
||||
spec:
|
||||
capacity:
|
||||
storage: 20Gi
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
nfs:
|
||||
server: 192.168.2.22
|
||||
path: /data/nfs
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: nfs-pvc-demo
|
||||
namespace: default
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
resources:
|
||||
requests:
|
||||
storage: 5Gi
|
||||
volumeName: nfs-pv-demo
|
||||
115
ansible/files/nginx-matrix-tls/01-control-ingress.yaml
Normal file
115
ansible/files/nginx-matrix-tls/01-control-ingress.yaml
Normal file
@@ -0,0 +1,115 @@
|
||||
# 03-02 TLS: M1 控制节点 + Ingress,路径 /(根路径),域名 test01.jackadam.top
|
||||
# ConfigMap:首页 + default.conf(单文件 subPath 挂载,与 M2~M4 一致)
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nginx-m1-html
|
||||
namespace: default
|
||||
data:
|
||||
index.html: |
|
||||
<!DOCTYPE html>
|
||||
<html><head><meta charset="utf-8"><title>M1</title></head>
|
||||
<body><h1>M1</h1><p>控制节点 + Ingress</p><p><strong>Backend: M1</strong></p></body></html>
|
||||
default.conf: |
|
||||
server { listen 80 default_server; server_name _; root /usr/share/nginx/html; index index.html; location / { add_header X-Backend "M1"; try_files $uri $uri/ /index.html; } }
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-m1
|
||||
namespace: default
|
||||
labels:
|
||||
app: nginx-m1
|
||||
matrix: "03-02-m1"
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx-m1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx-m1
|
||||
spec:
|
||||
nodeSelector:
|
||||
node-role.kubernetes.io/control-plane: ""
|
||||
tolerations:
|
||||
- key: node-role.kubernetes.io/control-plane
|
||||
operator: Exists
|
||||
effect: NoSchedule
|
||||
volumes:
|
||||
- name: html
|
||||
configMap:
|
||||
name: nginx-m1-html
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:alpine
|
||||
ports:
|
||||
- containerPort: 80
|
||||
volumeMounts:
|
||||
- name: html
|
||||
mountPath: /usr/share/nginx/html/index.html
|
||||
subPath: index.html
|
||||
readOnly: true
|
||||
- name: html
|
||||
mountPath: /etc/nginx/conf.d/default.conf
|
||||
subPath: default.conf
|
||||
readOnly: true
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nginx-m1
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: nginx-m1
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nginx-m1
|
||||
namespace: default
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||
traefik.ingress.kubernetes.io/router.tls.certresolver: cloudflare
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- test01.jackadam.top
|
||||
rules:
|
||||
- host: test01.jackadam.top
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nginx-m1
|
||||
port:
|
||||
number: 80
|
||||
---
|
||||
# 03-02 HTTP-only:M1 路由(仅 web,无 TLS),与 nginx-m1 共用 Service
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nginx-m1-http
|
||||
namespace: default
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||
spec:
|
||||
rules:
|
||||
- host: test01.jackadam.top
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nginx-m1
|
||||
port:
|
||||
number: 80
|
||||
98
ansible/files/nginx-matrix-tls/02-control-ingressroute.yaml
Normal file
98
ansible/files/nginx-matrix-tls/02-control-ingressroute.yaml
Normal file
@@ -0,0 +1,98 @@
|
||||
# 03-02 TLS: M2 控制节点 + IngressRoute,路径 /(根路径),域名 test02.jackadam.top
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nginx-m2-html
|
||||
namespace: default
|
||||
data:
|
||||
index.html: |
|
||||
<!DOCTYPE html>
|
||||
<html><head><meta charset="utf-8"><title>M2</title></head>
|
||||
<body><h1>M2</h1><p>控制节点 + IngressRoute</p></body></html>
|
||||
default.conf: |
|
||||
server { listen 80; server_name localhost; root /usr/share/nginx/html; index index.html; location / { add_header X-Backend "M2"; try_files $uri $uri/ /index.html; } }
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-m2
|
||||
namespace: default
|
||||
labels:
|
||||
app: nginx-m2
|
||||
matrix: "03-02-m2"
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx-m2
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx-m2
|
||||
spec:
|
||||
nodeSelector:
|
||||
kubernetes.io/hostname: ylc61
|
||||
volumes:
|
||||
- name: html
|
||||
configMap:
|
||||
name: nginx-m2-html
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:alpine
|
||||
ports:
|
||||
- containerPort: 80
|
||||
volumeMounts:
|
||||
- name: html
|
||||
mountPath: /usr/share/nginx/html/index.html
|
||||
subPath: index.html
|
||||
readOnly: true
|
||||
- name: html
|
||||
mountPath: /etc/nginx/conf.d/default.conf
|
||||
subPath: default.conf
|
||||
readOnly: true
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nginx-m2
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: nginx-m2
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
---
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: nginx-m2
|
||||
namespace: default
|
||||
spec:
|
||||
entryPoints:
|
||||
- websecure
|
||||
routes:
|
||||
- match: Host(`test02.jackadam.top`)
|
||||
kind: Rule
|
||||
services:
|
||||
- name: nginx-m2
|
||||
port: 80
|
||||
tls:
|
||||
certResolver: cloudflare
|
||||
---
|
||||
# 03-02 HTTP-only:M2 路由(仅 web,无 TLS),与 nginx-m2 共用 Service
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: nginx-m2-http
|
||||
namespace: default
|
||||
spec:
|
||||
entryPoints:
|
||||
- web
|
||||
routes:
|
||||
- match: Host(`test02.jackadam.top`)
|
||||
kind: Rule
|
||||
services:
|
||||
- name: nginx-m2
|
||||
port: 80
|
||||
110
ansible/files/nginx-matrix-tls/03-worker-ingress.yaml
Normal file
110
ansible/files/nginx-matrix-tls/03-worker-ingress.yaml
Normal file
@@ -0,0 +1,110 @@
|
||||
# 03-02 TLS: M3 工作节点 + Ingress,路径 /(根路径),域名 test03.jackadam.top
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nginx-m3-html
|
||||
namespace: default
|
||||
data:
|
||||
index.html: |
|
||||
<!DOCTYPE html>
|
||||
<html><head><meta charset="utf-8"><title>M3</title></head>
|
||||
<body><h1>M3</h1><p>工作节点 + Ingress</p></body></html>
|
||||
default.conf: |
|
||||
server { listen 80; server_name localhost; root /usr/share/nginx/html; index index.html; location / { add_header X-Backend "M3"; try_files $uri $uri/ /index.html; } }
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-m3
|
||||
namespace: default
|
||||
labels:
|
||||
app: nginx-m3
|
||||
matrix: "03-02-m3"
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx-m3
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx-m3
|
||||
spec:
|
||||
nodeSelector:
|
||||
node-role.kubernetes.io/worker: ""
|
||||
volumes:
|
||||
- name: html
|
||||
configMap:
|
||||
name: nginx-m3-html
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:alpine
|
||||
ports:
|
||||
- containerPort: 80
|
||||
volumeMounts:
|
||||
- name: html
|
||||
mountPath: /usr/share/nginx/html/index.html
|
||||
subPath: index.html
|
||||
readOnly: true
|
||||
- name: html
|
||||
mountPath: /etc/nginx/conf.d/default.conf
|
||||
subPath: default.conf
|
||||
readOnly: true
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nginx-m3
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: nginx-m3
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nginx-m3
|
||||
namespace: default
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||
traefik.ingress.kubernetes.io/router.tls.certresolver: cloudflare
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- test03.jackadam.top
|
||||
rules:
|
||||
- host: test03.jackadam.top
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nginx-m3
|
||||
port:
|
||||
number: 80
|
||||
---
|
||||
# 03-02 HTTP-only:M3 路由(仅 web,无 TLS),与 nginx-m3 共用 Service
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nginx-m3-http
|
||||
namespace: default
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||
spec:
|
||||
rules:
|
||||
- host: test03.jackadam.top
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nginx-m3
|
||||
port:
|
||||
number: 80
|
||||
98
ansible/files/nginx-matrix-tls/04-worker-ingressroute.yaml
Normal file
98
ansible/files/nginx-matrix-tls/04-worker-ingressroute.yaml
Normal file
@@ -0,0 +1,98 @@
|
||||
# 03-02 TLS: M4 工作节点 + IngressRoute,路径 /(根路径),域名 test04.jackadam.top
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nginx-m4-html
|
||||
namespace: default
|
||||
data:
|
||||
index.html: |
|
||||
<!DOCTYPE html>
|
||||
<html><head><meta charset="utf-8"><title>M4</title></head>
|
||||
<body><h1>M4</h1><p>工作节点 + IngressRoute</p></body></html>
|
||||
default.conf: |
|
||||
server { listen 80; server_name localhost; root /usr/share/nginx/html; index index.html; location / { add_header X-Backend "M4"; try_files $uri $uri/ /index.html; } }
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-m4
|
||||
namespace: default
|
||||
labels:
|
||||
app: nginx-m4
|
||||
matrix: "03-02-m4"
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx-m4
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx-m4
|
||||
spec:
|
||||
nodeSelector:
|
||||
kubernetes.io/hostname: ylc64
|
||||
volumes:
|
||||
- name: html
|
||||
configMap:
|
||||
name: nginx-m4-html
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:alpine
|
||||
ports:
|
||||
- containerPort: 80
|
||||
volumeMounts:
|
||||
- name: html
|
||||
mountPath: /usr/share/nginx/html/index.html
|
||||
subPath: index.html
|
||||
readOnly: true
|
||||
- name: html
|
||||
mountPath: /etc/nginx/conf.d/default.conf
|
||||
subPath: default.conf
|
||||
readOnly: true
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nginx-m4
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: nginx-m4
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
---
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: nginx-m4
|
||||
namespace: default
|
||||
spec:
|
||||
entryPoints:
|
||||
- websecure
|
||||
routes:
|
||||
- match: Host(`test04.jackadam.top`)
|
||||
kind: Rule
|
||||
services:
|
||||
- name: nginx-m4
|
||||
port: 80
|
||||
tls:
|
||||
certResolver: cloudflare
|
||||
---
|
||||
# 03-02 HTTP-only:M4 路由(仅 web,无 TLS),与 nginx-m4 共用 Service
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: nginx-m4-http
|
||||
namespace: default
|
||||
spec:
|
||||
entryPoints:
|
||||
- web
|
||||
routes:
|
||||
- match: Host(`test04.jackadam.top`)
|
||||
kind: Rule
|
||||
services:
|
||||
- name: nginx-m4
|
||||
port: 80
|
||||
100
ansible/files/nginx-matrix/01-control-ingress.yaml
Normal file
100
ansible/files/nginx-matrix/01-control-ingress.yaml
Normal file
@@ -0,0 +1,100 @@
|
||||
# 02-05: Nginx + 控制节点 + Ingress(M1)
|
||||
# 路径 /demo-m1,随机一台控制节点(nodeSelector + toleration,控制节点常有 NoSchedule 污点)
|
||||
# ConfigMap:首页 + default.conf(单文件 subPath 挂载,与 M2~M4 一致,便于 nginx 后续扩展)
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nginx-m1-html
|
||||
namespace: default
|
||||
data:
|
||||
index.html: |
|
||||
<!DOCTYPE html>
|
||||
<html><head><meta charset="utf-8"><title>M1</title></head>
|
||||
<body><h1>M1</h1><p>控制节点 + Ingress</p><p><strong>Backend: M1</strong></p></body></html>
|
||||
default.conf: |
|
||||
server { listen 80 default_server; server_name _; root /usr/share/nginx/html; index index.html; location / { add_header X-Backend "M1"; try_files $uri $uri/ /index.html; } }
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-m1
|
||||
namespace: default
|
||||
labels:
|
||||
app: nginx-m1
|
||||
matrix: "02-05-m1"
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx-m1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx-m1
|
||||
spec:
|
||||
nodeSelector:
|
||||
node-role.kubernetes.io/control-plane: ""
|
||||
tolerations:
|
||||
- key: node-role.kubernetes.io/control-plane
|
||||
operator: Exists
|
||||
effect: NoSchedule
|
||||
volumes:
|
||||
- name: html
|
||||
configMap:
|
||||
name: nginx-m1-html
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:alpine
|
||||
ports:
|
||||
- containerPort: 80
|
||||
volumeMounts:
|
||||
- name: html
|
||||
mountPath: /usr/share/nginx/html/index.html
|
||||
subPath: index.html
|
||||
readOnly: true
|
||||
- name: html
|
||||
mountPath: /etc/nginx/conf.d/default.conf
|
||||
subPath: default.conf
|
||||
readOnly: true
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nginx-m1
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: nginx-m1
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
---
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: stripprefix-m1
|
||||
namespace: default
|
||||
spec:
|
||||
stripPrefix:
|
||||
prefixes:
|
||||
- /demo-m1
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nginx-m1
|
||||
namespace: default
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.middlewares: default-stripprefix-m1@kubernetescrd
|
||||
spec:
|
||||
rules:
|
||||
- http:
|
||||
paths:
|
||||
- path: /demo-m1
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nginx-m1
|
||||
port:
|
||||
number: 80
|
||||
94
ansible/files/nginx-matrix/02-control-ingressroute.yaml
Normal file
94
ansible/files/nginx-matrix/02-control-ingressroute.yaml
Normal file
@@ -0,0 +1,94 @@
|
||||
# 03-02: Nginx + 控制节点 + IngressRoute(M2)
|
||||
# 路径 /demo-m2,指定一台控制节点(按实际 FQDN 修改 kubernetes.io/hostname)
|
||||
# ConfigMap:首页 + default.conf,X-Backend: M2 便于区分
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nginx-m2-html
|
||||
namespace: default
|
||||
data:
|
||||
index.html: |
|
||||
<!DOCTYPE html>
|
||||
<html><head><meta charset="utf-8"><title>M2</title></head>
|
||||
<body><h1>M2</h1><p>控制节点 + IngressRoute</p></body></html>
|
||||
default.conf: |
|
||||
server { listen 80; server_name localhost; root /usr/share/nginx/html; index index.html; location / { add_header X-Backend "M2"; try_files $uri $uri/ /index.html; } }
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-m2
|
||||
namespace: default
|
||||
labels:
|
||||
app: nginx-m2
|
||||
matrix: "02-05-m2"
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx-m2
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx-m2
|
||||
spec:
|
||||
nodeSelector:
|
||||
kubernetes.io/hostname: ylc61
|
||||
volumes:
|
||||
- name: html
|
||||
configMap:
|
||||
name: nginx-m2-html
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:alpine
|
||||
ports:
|
||||
- containerPort: 80
|
||||
volumeMounts:
|
||||
- name: html
|
||||
mountPath: /usr/share/nginx/html/index.html
|
||||
subPath: index.html
|
||||
readOnly: true
|
||||
- name: html
|
||||
mountPath: /etc/nginx/conf.d/default.conf
|
||||
subPath: default.conf
|
||||
readOnly: true
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nginx-m2
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: nginx-m2
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
---
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: stripprefix-m2
|
||||
namespace: default
|
||||
spec:
|
||||
stripPrefix:
|
||||
prefixes:
|
||||
- /demo-m2
|
||||
---
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: nginx-m2
|
||||
namespace: default
|
||||
spec:
|
||||
entryPoints:
|
||||
- web
|
||||
routes:
|
||||
- match: PathPrefix(`/demo-m2`)
|
||||
kind: Rule
|
||||
middlewares:
|
||||
- name: stripprefix-m2
|
||||
services:
|
||||
- name: nginx-m2
|
||||
port: 80
|
||||
96
ansible/files/nginx-matrix/03-worker-ingress.yaml
Normal file
96
ansible/files/nginx-matrix/03-worker-ingress.yaml
Normal file
@@ -0,0 +1,96 @@
|
||||
# 03-03: Nginx + 工作节点 + Ingress(M3)
|
||||
# 路径 /demo-m3,随机一台工作节点(nodeSelector: node-role.kubernetes.io/worker)
|
||||
# ConfigMap:首页 + default.conf,X-Backend: M3 便于区分
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nginx-m3-html
|
||||
namespace: default
|
||||
data:
|
||||
index.html: |
|
||||
<!DOCTYPE html>
|
||||
<html><head><meta charset="utf-8"><title>M3</title></head>
|
||||
<body><h1>M3</h1><p>工作节点 + Ingress</p></body></html>
|
||||
default.conf: |
|
||||
server { listen 80; server_name localhost; root /usr/share/nginx/html; index index.html; location / { add_header X-Backend "M3"; try_files $uri $uri/ /index.html; } }
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-m3
|
||||
namespace: default
|
||||
labels:
|
||||
app: nginx-m3
|
||||
matrix: "02-05-m3"
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx-m3
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx-m3
|
||||
spec:
|
||||
nodeSelector:
|
||||
node-role.kubernetes.io/worker: ""
|
||||
volumes:
|
||||
- name: html
|
||||
configMap:
|
||||
name: nginx-m3-html
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:alpine
|
||||
ports:
|
||||
- containerPort: 80
|
||||
volumeMounts:
|
||||
- name: html
|
||||
mountPath: /usr/share/nginx/html/index.html
|
||||
subPath: index.html
|
||||
readOnly: true
|
||||
- name: html
|
||||
mountPath: /etc/nginx/conf.d/default.conf
|
||||
subPath: default.conf
|
||||
readOnly: true
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nginx-m3
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: nginx-m3
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
---
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: stripprefix-m3
|
||||
namespace: default
|
||||
spec:
|
||||
stripPrefix:
|
||||
prefixes:
|
||||
- /demo-m3
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nginx-m3
|
||||
namespace: default
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.middlewares: default-stripprefix-m3@kubernetescrd
|
||||
spec:
|
||||
rules:
|
||||
- http:
|
||||
paths:
|
||||
- path: /demo-m3
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nginx-m3
|
||||
port:
|
||||
number: 80
|
||||
94
ansible/files/nginx-matrix/04-worker-ingressroute.yaml
Normal file
94
ansible/files/nginx-matrix/04-worker-ingressroute.yaml
Normal file
@@ -0,0 +1,94 @@
|
||||
# 03-04: Nginx + 工作节点 + IngressRoute(M4)
|
||||
# 路径 /demo-m4,指定一台工作节点(按实际 FQDN 修改 kubernetes.io/hostname)
|
||||
# ConfigMap:首页 + default.conf,X-Backend: M4 便于区分
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nginx-m4-html
|
||||
namespace: default
|
||||
data:
|
||||
index.html: |
|
||||
<!DOCTYPE html>
|
||||
<html><head><meta charset="utf-8"><title>M4</title></head>
|
||||
<body><h1>M4</h1><p>工作节点 + IngressRoute</p></body></html>
|
||||
default.conf: |
|
||||
server { listen 80; server_name localhost; root /usr/share/nginx/html; index index.html; location / { add_header X-Backend "M4"; try_files $uri $uri/ /index.html; } }
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-m4
|
||||
namespace: default
|
||||
labels:
|
||||
app: nginx-m4
|
||||
matrix: "02-05-m4"
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx-m4
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx-m4
|
||||
spec:
|
||||
nodeSelector:
|
||||
kubernetes.io/hostname: ylc64
|
||||
volumes:
|
||||
- name: html
|
||||
configMap:
|
||||
name: nginx-m4-html
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:alpine
|
||||
ports:
|
||||
- containerPort: 80
|
||||
volumeMounts:
|
||||
- name: html
|
||||
mountPath: /usr/share/nginx/html/index.html
|
||||
subPath: index.html
|
||||
readOnly: true
|
||||
- name: html
|
||||
mountPath: /etc/nginx/conf.d/default.conf
|
||||
subPath: default.conf
|
||||
readOnly: true
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nginx-m4
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: nginx-m4
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
---
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: stripprefix-m4
|
||||
namespace: default
|
||||
spec:
|
||||
stripPrefix:
|
||||
prefixes:
|
||||
- /demo-m4
|
||||
---
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: nginx-m4
|
||||
namespace: default
|
||||
spec:
|
||||
entryPoints:
|
||||
- web
|
||||
routes:
|
||||
- match: PathPrefix(`/demo-m4`)
|
||||
kind: Rule
|
||||
middlewares:
|
||||
- name: stripprefix-m4
|
||||
services:
|
||||
- name: nginx-m4
|
||||
port: 80
|
||||
12
ansible/files/nginx-matrix/README.md
Normal file
12
ansible/files/nginx-matrix/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Nginx 矩阵 manifests
|
||||
|
||||
用于 `ansible/playbooks/nginx-matrix-deploy.yml` 一键部署。
|
||||
|
||||
| 文件 | 场景 | 路径 | 节点 |
|
||||
|------|------|------|------|
|
||||
| 01-control-ingress.yaml | M1 控制+Ingress | /demo-m1 | 无 nodeSelector |
|
||||
| 02-control-ingressroute.yaml | M2 控制+IngressRoute | /demo-m2 | 无 nodeSelector |
|
||||
| 03-worker-ingress.yaml | M3 工作+Ingress | /demo-m3 | nodeSelector=worker(随机) |
|
||||
| 04-worker-ingressroute.yaml | M4 工作+IngressRoute | /demo-m4 | nodeSelector=ylc64 |
|
||||
|
||||
M4 默认指定 ylc64,M3 随机工作节点;按实际修改。
|
||||
54
ansible/files/nodejs-demo/04-01-nodejs-demo.yaml
Normal file
54
ansible/files/nodejs-demo/04-01-nodejs-demo.yaml
Normal file
@@ -0,0 +1,54 @@
|
||||
# 对应文档:docs/04-01-k3s-nodejs-高级部署.md
|
||||
# 累积:基线(Deployment + Service + Ingress)
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nodejs-demo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nodejs-demo
|
||||
spec:
|
||||
containers:
|
||||
- name: nodejs-demo
|
||||
image: node:18-alpine
|
||||
command: ["node", "-e", "require('http').createServer((req,res)=>res.end('Hello World from Node.js')).listen(3000)"]
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: nodejs-demo
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 3000
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||
spec:
|
||||
rules:
|
||||
- http:
|
||||
paths:
|
||||
- path: /node
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nodejs-demo
|
||||
port:
|
||||
number: 80
|
||||
58
ansible/files/nodejs-demo/04-02-nodejs-demo.yaml
Normal file
58
ansible/files/nodejs-demo/04-02-nodejs-demo.yaml
Normal file
@@ -0,0 +1,58 @@
|
||||
# 对应文档:docs/04-02-nodejs-镜像与运行命令.md
|
||||
# 累积:04-01 + 固定镜像 tag、imagePullPolicy、command/args
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nodejs-demo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nodejs-demo
|
||||
spec:
|
||||
containers:
|
||||
- name: nodejs-demo
|
||||
image: node:18.20-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
command: ["node"]
|
||||
args:
|
||||
- "-e"
|
||||
- "require('http').createServer((req,res)=>res.end('Hello from pinned image')).listen(3000)"
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: nodejs-demo
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 3000
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||
spec:
|
||||
rules:
|
||||
- http:
|
||||
paths:
|
||||
- path: /node
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nodejs-demo
|
||||
port:
|
||||
number: 80
|
||||
75
ansible/files/nodejs-demo/04-03-nodejs-demo.yaml
Normal file
75
ansible/files/nodejs-demo/04-03-nodejs-demo.yaml
Normal file
@@ -0,0 +1,75 @@
|
||||
# 对应文档:docs/04-03-nodejs-环境变量与配置注入.md
|
||||
# 累积:04-02 + ConfigMap + 通过 env 注入 APP_MSG(镜像仍用 18.20-alpine 与 04-02 一致)
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nodejs-demo-config
|
||||
namespace: default
|
||||
data:
|
||||
APP_MSG: "Hello from ConfigMap"
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nodejs-demo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nodejs-demo
|
||||
spec:
|
||||
containers:
|
||||
- name: nodejs-demo
|
||||
image: node:18.20-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
env:
|
||||
- name: APP_MSG
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: nodejs-demo-config
|
||||
key: APP_MSG
|
||||
command:
|
||||
- node
|
||||
- "-e"
|
||||
- |
|
||||
const http=require('http');
|
||||
const msg=process.env.APP_MSG||'no env';
|
||||
http.createServer((q,s)=>s.end(msg)).listen(3000);
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: nodejs-demo
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 3000
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||
spec:
|
||||
rules:
|
||||
- http:
|
||||
paths:
|
||||
- path: /node
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nodejs-demo
|
||||
port:
|
||||
number: 80
|
||||
75
ansible/files/nodejs-demo/04-04-nodejs-demo.yaml
Normal file
75
ansible/files/nodejs-demo/04-04-nodejs-demo.yaml
Normal file
@@ -0,0 +1,75 @@
|
||||
# 对应文档:docs/04-04-nodejs-端口与Service.md
|
||||
# 累积:04-03 + 容器与进程改监听 8080,Service targetPort 对齐
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nodejs-demo-config
|
||||
namespace: default
|
||||
data:
|
||||
APP_MSG: "Hello from ConfigMap"
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nodejs-demo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nodejs-demo
|
||||
spec:
|
||||
containers:
|
||||
- name: nodejs-demo
|
||||
image: node:18.20-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
env:
|
||||
- name: APP_MSG
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: nodejs-demo-config
|
||||
key: APP_MSG
|
||||
command:
|
||||
- node
|
||||
- "-e"
|
||||
- |
|
||||
const http=require('http');
|
||||
const msg=process.env.APP_MSG||'no env';
|
||||
http.createServer((q,s)=>s.end(msg)).listen(8080);
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: nodejs-demo
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||
spec:
|
||||
rules:
|
||||
- http:
|
||||
paths:
|
||||
- path: /node
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nodejs-demo
|
||||
port:
|
||||
number: 80
|
||||
82
ansible/files/nodejs-demo/04-05-nodejs-demo.yaml
Normal file
82
ansible/files/nodejs-demo/04-05-nodejs-demo.yaml
Normal file
@@ -0,0 +1,82 @@
|
||||
# 对应文档:docs/04-05-nodejs-资源请求与限制.md
|
||||
# 累积:04-04 + resources.requests/limits
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nodejs-demo-config
|
||||
namespace: default
|
||||
data:
|
||||
APP_MSG: "Hello from ConfigMap"
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nodejs-demo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nodejs-demo
|
||||
spec:
|
||||
containers:
|
||||
- name: nodejs-demo
|
||||
image: node:18.20-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
env:
|
||||
- name: APP_MSG
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: nodejs-demo-config
|
||||
key: APP_MSG
|
||||
command:
|
||||
- node
|
||||
- "-e"
|
||||
- |
|
||||
const http=require('http');
|
||||
const msg=process.env.APP_MSG||'no env';
|
||||
http.createServer((q,s)=>s.end(msg)).listen(8080);
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
resources:
|
||||
requests:
|
||||
cpu: "50m"
|
||||
memory: "64Mi"
|
||||
limits:
|
||||
cpu: "500m"
|
||||
memory: "256Mi"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: nodejs-demo
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||
spec:
|
||||
rules:
|
||||
- http:
|
||||
paths:
|
||||
- path: /node
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nodejs-demo
|
||||
port:
|
||||
number: 80
|
||||
94
ansible/files/nodejs-demo/04-06-nodejs-demo.yaml
Normal file
94
ansible/files/nodejs-demo/04-06-nodejs-demo.yaml
Normal file
@@ -0,0 +1,94 @@
|
||||
# 对应文档:docs/04-06-nodejs-探针与健康检查.md
|
||||
# 累积:04-05 + livenessProbe/readinessProbe(端口 8080,路径 /)
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nodejs-demo-config
|
||||
namespace: default
|
||||
data:
|
||||
APP_MSG: "Hello from ConfigMap"
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nodejs-demo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nodejs-demo
|
||||
spec:
|
||||
containers:
|
||||
- name: nodejs-demo
|
||||
image: node:18.20-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
env:
|
||||
- name: APP_MSG
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: nodejs-demo-config
|
||||
key: APP_MSG
|
||||
command:
|
||||
- node
|
||||
- "-e"
|
||||
- |
|
||||
const http=require('http');
|
||||
const msg=process.env.APP_MSG||'no env';
|
||||
http.createServer((q,s)=>s.end(msg)).listen(8080);
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
resources:
|
||||
requests:
|
||||
cpu: "50m"
|
||||
memory: "64Mi"
|
||||
limits:
|
||||
cpu: "500m"
|
||||
memory: "256Mi"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 3
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 2
|
||||
periodSeconds: 5
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: nodejs-demo
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||
spec:
|
||||
rules:
|
||||
- http:
|
||||
paths:
|
||||
- path: /node
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nodejs-demo
|
||||
port:
|
||||
number: 80
|
||||
96
ansible/files/nodejs-demo/04-07-nodejs-demo.yaml
Normal file
96
ansible/files/nodejs-demo/04-07-nodejs-demo.yaml
Normal file
@@ -0,0 +1,96 @@
|
||||
# 对应文档:docs/04-07-nodejs-调度与亲和.md
|
||||
# 累积:04-06 + nodeSelector(默认 ylc62,请改为本集群节点短主机名)
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nodejs-demo-config
|
||||
namespace: default
|
||||
data:
|
||||
APP_MSG: "Hello from ConfigMap"
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nodejs-demo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nodejs-demo
|
||||
spec:
|
||||
nodeSelector:
|
||||
kubernetes.io/hostname: ylc62
|
||||
containers:
|
||||
- name: nodejs-demo
|
||||
image: node:18.20-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
env:
|
||||
- name: APP_MSG
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: nodejs-demo-config
|
||||
key: APP_MSG
|
||||
command:
|
||||
- node
|
||||
- "-e"
|
||||
- |
|
||||
const http=require('http');
|
||||
const msg=process.env.APP_MSG||'no env';
|
||||
http.createServer((q,s)=>s.end(msg)).listen(8080);
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
resources:
|
||||
requests:
|
||||
cpu: "50m"
|
||||
memory: "64Mi"
|
||||
limits:
|
||||
cpu: "500m"
|
||||
memory: "256Mi"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 3
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 2
|
||||
periodSeconds: 5
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: nodejs-demo
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||
spec:
|
||||
rules:
|
||||
- http:
|
||||
paths:
|
||||
- path: /node
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nodejs-demo
|
||||
port:
|
||||
number: 80
|
||||
109
ansible/files/nodejs-demo/04-08-nodejs-demo.yaml
Normal file
109
ansible/files/nodejs-demo/04-08-nodejs-demo.yaml
Normal file
@@ -0,0 +1,109 @@
|
||||
# 对应文档:docs/04-08-nodejs-安全上下文.md
|
||||
# 累积:04-07 + pod securityContext.fsGroup、容器 securityContext、只读根、/tmp emptyDir
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nodejs-demo-config
|
||||
namespace: default
|
||||
data:
|
||||
APP_MSG: "Hello from ConfigMap"
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nodejs-demo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nodejs-demo
|
||||
spec:
|
||||
nodeSelector:
|
||||
kubernetes.io/hostname: ylc62
|
||||
securityContext:
|
||||
fsGroup: 1000
|
||||
containers:
|
||||
- name: nodejs-demo
|
||||
image: node:18.20-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
readOnlyRootFilesystem: true
|
||||
env:
|
||||
- name: APP_MSG
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: nodejs-demo-config
|
||||
key: APP_MSG
|
||||
command:
|
||||
- node
|
||||
- "-e"
|
||||
- |
|
||||
const http=require('http');
|
||||
const msg=process.env.APP_MSG||'no env';
|
||||
http.createServer((q,s)=>s.end(msg)).listen(8080);
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
resources:
|
||||
requests:
|
||||
cpu: "50m"
|
||||
memory: "64Mi"
|
||||
limits:
|
||||
cpu: "500m"
|
||||
memory: "256Mi"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 3
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 2
|
||||
periodSeconds: 5
|
||||
volumeMounts:
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: nodejs-demo
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||
spec:
|
||||
rules:
|
||||
- http:
|
||||
paths:
|
||||
- path: /node
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nodejs-demo
|
||||
port:
|
||||
number: 80
|
||||
127
ansible/files/nodejs-demo/04-09-nodejs-demo.yaml
Normal file
127
ansible/files/nodejs-demo/04-09-nodejs-demo.yaml
Normal file
@@ -0,0 +1,127 @@
|
||||
# 对应文档:docs/04-09-nodejs-存储与卷.md
|
||||
# 累积:04-08 + PVC nodejs-demo-data(默认 storageClassName: local-path,可按集群改为 longhorn 等)+ 挂载 /data
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: nodejs-demo-data
|
||||
namespace: default
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: local-path
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nodejs-demo-config
|
||||
namespace: default
|
||||
data:
|
||||
APP_MSG: "Hello from ConfigMap"
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nodejs-demo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nodejs-demo
|
||||
spec:
|
||||
nodeSelector:
|
||||
kubernetes.io/hostname: ylc62
|
||||
securityContext:
|
||||
fsGroup: 1000
|
||||
containers:
|
||||
- name: nodejs-demo
|
||||
image: node:18.20-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
readOnlyRootFilesystem: true
|
||||
env:
|
||||
- name: APP_MSG
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: nodejs-demo-config
|
||||
key: APP_MSG
|
||||
command:
|
||||
- node
|
||||
- "-e"
|
||||
- |
|
||||
const http=require('http');
|
||||
const msg=process.env.APP_MSG||'no env';
|
||||
http.createServer((q,s)=>s.end(msg)).listen(8080);
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
resources:
|
||||
requests:
|
||||
cpu: "50m"
|
||||
memory: "64Mi"
|
||||
limits:
|
||||
cpu: "500m"
|
||||
memory: "256Mi"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 3
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 2
|
||||
periodSeconds: 5
|
||||
volumeMounts:
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
- name: data
|
||||
mountPath: /data
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: nodejs-demo-data
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: nodejs-demo
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||
spec:
|
||||
rules:
|
||||
- http:
|
||||
paths:
|
||||
- path: /node
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nodejs-demo
|
||||
port:
|
||||
number: 80
|
||||
128
ansible/files/nodejs-demo/04-10-nodejs-demo.yaml
Normal file
128
ansible/files/nodejs-demo/04-10-nodejs-demo.yaml
Normal file
@@ -0,0 +1,128 @@
|
||||
# 对应文档:docs/04-10-nodejs-Ingress与Traefik.md
|
||||
# 累积:04-09 + Ingress 增加 host、path 改为 /api(访问需 Host: app.example.local)
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: nodejs-demo-data
|
||||
namespace: default
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: local-path
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nodejs-demo-config
|
||||
namespace: default
|
||||
data:
|
||||
APP_MSG: "Hello from ConfigMap"
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nodejs-demo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nodejs-demo
|
||||
spec:
|
||||
nodeSelector:
|
||||
kubernetes.io/hostname: ylc62
|
||||
securityContext:
|
||||
fsGroup: 1000
|
||||
containers:
|
||||
- name: nodejs-demo
|
||||
image: node:18.20-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
readOnlyRootFilesystem: true
|
||||
env:
|
||||
- name: APP_MSG
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: nodejs-demo-config
|
||||
key: APP_MSG
|
||||
command:
|
||||
- node
|
||||
- "-e"
|
||||
- |
|
||||
const http=require('http');
|
||||
const msg=process.env.APP_MSG||'no env';
|
||||
http.createServer((q,s)=>s.end(msg)).listen(8080);
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
resources:
|
||||
requests:
|
||||
cpu: "50m"
|
||||
memory: "64Mi"
|
||||
limits:
|
||||
cpu: "500m"
|
||||
memory: "256Mi"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 3
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 2
|
||||
periodSeconds: 5
|
||||
volumeMounts:
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
- name: data
|
||||
mountPath: /data
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: nodejs-demo-data
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: nodejs-demo
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||
spec:
|
||||
rules:
|
||||
- host: app.example.local
|
||||
http:
|
||||
paths:
|
||||
- path: /api
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nodejs-demo
|
||||
port:
|
||||
number: 80
|
||||
133
ansible/files/nodejs-demo/04-11-nodejs-demo.yaml
Normal file
133
ansible/files/nodejs-demo/04-11-nodejs-demo.yaml
Normal file
@@ -0,0 +1,133 @@
|
||||
# 对应文档:docs/04-11-nodejs-副本与滚动发布.md
|
||||
# 累积:04-10 + replicas: 3 + RollingUpdate(maxSurge:1 maxUnavailable:0)
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: nodejs-demo-data
|
||||
namespace: default
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: local-path
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nodejs-demo-config
|
||||
namespace: default
|
||||
data:
|
||||
APP_MSG: "Hello from ConfigMap"
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 3
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 0
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nodejs-demo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nodejs-demo
|
||||
spec:
|
||||
nodeSelector:
|
||||
kubernetes.io/hostname: ylc62
|
||||
securityContext:
|
||||
fsGroup: 1000
|
||||
containers:
|
||||
- name: nodejs-demo
|
||||
image: node:18.20-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
readOnlyRootFilesystem: true
|
||||
env:
|
||||
- name: APP_MSG
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: nodejs-demo-config
|
||||
key: APP_MSG
|
||||
command:
|
||||
- node
|
||||
- "-e"
|
||||
- |
|
||||
const http=require('http');
|
||||
const msg=process.env.APP_MSG||'no env';
|
||||
http.createServer((q,s)=>s.end(msg)).listen(8080);
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
resources:
|
||||
requests:
|
||||
cpu: "50m"
|
||||
memory: "64Mi"
|
||||
limits:
|
||||
cpu: "500m"
|
||||
memory: "256Mi"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 3
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 2
|
||||
periodSeconds: 5
|
||||
volumeMounts:
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
- name: data
|
||||
mountPath: /data
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: nodejs-demo-data
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: nodejs-demo
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||
spec:
|
||||
rules:
|
||||
- host: app.example.local
|
||||
http:
|
||||
paths:
|
||||
- path: /api
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nodejs-demo
|
||||
port:
|
||||
number: 80
|
||||
140
ansible/files/nodejs-demo/04-12-nodejs-demo.yaml
Normal file
140
ansible/files/nodejs-demo/04-12-nodejs-demo.yaml
Normal file
@@ -0,0 +1,140 @@
|
||||
# 对应文档:docs/04-12-nodejs-TLS与证书.md
|
||||
# 累积:04-11 + Ingress TLS(websecure、secretName: nodejs-demo-tls)
|
||||
# 应用前请先创建 TLS Secret,例如:
|
||||
# kubectl create secret tls nodejs-demo-tls --cert=fullchain.pem --key=privkey.pem -n default
|
||||
# 证书 SAN 须覆盖 app.example.local(与 rules.host / tls.hosts 一致)
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: nodejs-demo-data
|
||||
namespace: default
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: local-path
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nodejs-demo-config
|
||||
namespace: default
|
||||
data:
|
||||
APP_MSG: "Hello from ConfigMap"
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 3
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 0
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nodejs-demo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nodejs-demo
|
||||
spec:
|
||||
nodeSelector:
|
||||
kubernetes.io/hostname: ylc62
|
||||
securityContext:
|
||||
fsGroup: 1000
|
||||
containers:
|
||||
- name: nodejs-demo
|
||||
image: node:18.20-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
readOnlyRootFilesystem: true
|
||||
env:
|
||||
- name: APP_MSG
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: nodejs-demo-config
|
||||
key: APP_MSG
|
||||
command:
|
||||
- node
|
||||
- "-e"
|
||||
- |
|
||||
const http=require('http');
|
||||
const msg=process.env.APP_MSG||'no env';
|
||||
http.createServer((q,s)=>s.end(msg)).listen(8080);
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
resources:
|
||||
requests:
|
||||
cpu: "50m"
|
||||
memory: "64Mi"
|
||||
limits:
|
||||
cpu: "500m"
|
||||
memory: "256Mi"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 3
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 2
|
||||
periodSeconds: 5
|
||||
volumeMounts:
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
- name: data
|
||||
mountPath: /data
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: nodejs-demo-data
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: nodejs-demo
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- app.example.local
|
||||
secretName: nodejs-demo-tls
|
||||
rules:
|
||||
- host: app.example.local
|
||||
http:
|
||||
paths:
|
||||
- path: /api
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nodejs-demo
|
||||
port:
|
||||
number: 80
|
||||
157
ansible/files/nodejs-demo/04-13-nodejs-demo.yaml
Normal file
157
ansible/files/nodejs-demo/04-13-nodejs-demo.yaml
Normal file
@@ -0,0 +1,157 @@
|
||||
# 对应文档:docs/04-13-nodejs-HPA.md
|
||||
# 累积:04-12 + HorizontalPodAutoscaler(CPU 50%,min 1 max 5)
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: nodejs-demo-data
|
||||
namespace: default
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: local-path
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nodejs-demo-config
|
||||
namespace: default
|
||||
data:
|
||||
APP_MSG: "Hello from ConfigMap"
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 3
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 0
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nodejs-demo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nodejs-demo
|
||||
spec:
|
||||
nodeSelector:
|
||||
kubernetes.io/hostname: ylc62
|
||||
securityContext:
|
||||
fsGroup: 1000
|
||||
containers:
|
||||
- name: nodejs-demo
|
||||
image: node:18.20-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
readOnlyRootFilesystem: true
|
||||
env:
|
||||
- name: APP_MSG
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: nodejs-demo-config
|
||||
key: APP_MSG
|
||||
command:
|
||||
- node
|
||||
- "-e"
|
||||
- |
|
||||
const http=require('http');
|
||||
const msg=process.env.APP_MSG||'no env';
|
||||
http.createServer((q,s)=>s.end(msg)).listen(8080);
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
resources:
|
||||
requests:
|
||||
cpu: "50m"
|
||||
memory: "64Mi"
|
||||
limits:
|
||||
cpu: "500m"
|
||||
memory: "256Mi"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 3
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 2
|
||||
periodSeconds: 5
|
||||
volumeMounts:
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
- name: data
|
||||
mountPath: /data
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: nodejs-demo-data
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: nodejs-demo
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- app.example.local
|
||||
secretName: nodejs-demo-tls
|
||||
rules:
|
||||
- host: app.example.local
|
||||
http:
|
||||
paths:
|
||||
- path: /api
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nodejs-demo
|
||||
port:
|
||||
number: 80
|
||||
---
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: nodejs-demo
|
||||
namespace: default
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: nodejs-demo
|
||||
minReplicas: 1
|
||||
maxReplicas: 5
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 50
|
||||
42
ansible/files/nodejs-demo/README.md
Normal file
42
ansible/files/nodejs-demo/README.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Node.js demo 清单(与 docs/04-01~04-14 对齐)
|
||||
|
||||
**唯一真源**:本目录下 YAML 与 `docs/` 中说明一致;文档内不重复贴全文,避免漂移。
|
||||
|
||||
## 累积规则
|
||||
|
||||
- `04-0N-nodejs-demo.yaml` 表示:从 `04-01` 起顺序做完 **04-01~04-0N** 各篇能力后的 **一份** 可 `kubectl apply -f` 的完整状态(多资源用 `---` 分隔)。
|
||||
- **可直接跳到最后一份** 做实验,不必逐文件 apply;若要理解每步增量,可按编号顺序阅读文档并对照相邻两个 YAML 的差异。
|
||||
- **04-14**(GitOps/CI)无独立清单,见 `docs/04-14-nodejs-GitOps与CI流水线.md` 与 `docs/05-04-k3s-配置gitlab-cicd.md`、`docs/03-09-k3s-gitops-集群配置管理.md`。
|
||||
|
||||
## 文件与文档对照
|
||||
|
||||
| 文件 | 文档 | 备注 |
|
||||
|------|------|------|
|
||||
| `04-01-nodejs-demo.yaml` | `docs/04-01-k3s-nodejs-高级部署.md` | 基线:3000、`/node`、无 host |
|
||||
| `04-02-nodejs-demo.yaml` | `docs/04-02-nodejs-镜像与运行命令.md` | 固定镜像 tag、`imagePullPolicy` |
|
||||
| `04-03-nodejs-demo.yaml` | `docs/04-03-nodejs-环境变量与配置注入.md` | + ConfigMap;Secret 示例见文末 `nodejs-demo-secret.example.yaml` |
|
||||
| `04-04-nodejs-demo.yaml` | `docs/04-04-nodejs-端口与Service.md` | 监听改 **8080**(自 04-04 起探针与后续均用 8080) |
|
||||
| `04-05-nodejs-demo.yaml` | `docs/04-05-nodejs-资源请求与限制.md` | + resources |
|
||||
| `04-06-nodejs-demo.yaml` | `docs/04-06-nodejs-探针与健康检查.md` | + 探针 |
|
||||
| `04-07-nodejs-demo.yaml` | `docs/04-07-nodejs-调度与亲和.md` | + `nodeSelector`(默认 **ylc62**,请改为本机节点名) |
|
||||
| `04-08-nodejs-demo.yaml` | `docs/04-08-nodejs-安全上下文.md` | + 非 root、只读根、`/tmp` emptyDir |
|
||||
| `04-09-nodejs-demo.yaml` | `docs/04-09-nodejs-存储与卷.md` | + PVC `nodejs-demo-data`(默认 **local-path**) |
|
||||
| `04-10-nodejs-demo.yaml` | `docs/04-10-nodejs-Ingress与Traefik.md` | Ingress:`host` + `/api`,curl 需 **Host** |
|
||||
| `04-11-nodejs-demo.yaml` | `docs/04-11-nodejs-副本与滚动发布.md` | replicas=3 + RollingUpdate |
|
||||
| `04-12-nodejs-demo.yaml` | `docs/04-12-nodejs-TLS与证书.md` | **websecure** + TLS;须先创建 `nodejs-demo-tls` Secret |
|
||||
| `04-13-nodejs-demo.yaml` | `docs/04-13-nodejs-HPA.md` | + HPA(需 metrics-server) |
|
||||
|
||||
## 应用方式
|
||||
|
||||
```bash
|
||||
# 仓库根目录
|
||||
kubectl apply -f ansible/files/nodejs-demo/04-01-nodejs-demo.yaml
|
||||
```
|
||||
|
||||
或使用 Ansible:`ansible/playbooks/nodejs-demo-apply.yml`,变量 `nodejs_demo_manifest` 指定文件名。
|
||||
|
||||
## dry-run
|
||||
|
||||
```bash
|
||||
kubectl apply --dry-run=client -f ansible/files/nodejs-demo/04-01-nodejs-demo.yaml
|
||||
```
|
||||
@@ -0,0 +1,8 @@
|
||||
# 示例:勿将真实密钥提交到公开仓库。对应 docs/04-03 Secret 示意。
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: nodejs-demo-secret
|
||||
namespace: default
|
||||
stringData:
|
||||
API_TOKEN: "replace-me"
|
||||
43
ansible/files/onenav/onenav-proxy.yaml
Normal file
43
ansible/files/onenav/onenav-proxy.yaml
Normal file
@@ -0,0 +1,43 @@
|
||||
# docs/05-02-onenav首页面板.md — 修改 Endpoints IP 与 Ingress host
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: onenav-external
|
||||
namespace: default
|
||||
spec:
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 7070
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Endpoints
|
||||
metadata:
|
||||
name: onenav-external
|
||||
namespace: default
|
||||
subsets:
|
||||
- addresses:
|
||||
- ip: 192.168.2.22
|
||||
ports:
|
||||
- port: 7070
|
||||
name: http
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: onenav
|
||||
namespace: default
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||
spec:
|
||||
rules:
|
||||
- host: onenav.example.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: onenav-external
|
||||
port:
|
||||
number: 80
|
||||
74
ansible/files/openclaw/openclaw-k3s-experimental.yaml
Normal file
74
ansible/files/openclaw/openclaw-k3s-experimental.yaml
Normal file
@@ -0,0 +1,74 @@
|
||||
# docs/05-08-openclaw-k3s-实验部署.md — 实验用;替换镜像与域名
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: openclaw
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: openclaw-gateway
|
||||
namespace: openclaw
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: openclaw-gateway
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: openclaw-gateway
|
||||
spec:
|
||||
containers:
|
||||
- name: openclaw-gateway
|
||||
image: registry.local/openclaw:local
|
||||
imagePullPolicy: IfNotPresent
|
||||
env:
|
||||
- name: OPENCLAW_GATEWAY_MODE
|
||||
value: "local"
|
||||
ports:
|
||||
- containerPort: 18789
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /home/node/.openclaw
|
||||
- name: workspace
|
||||
mountPath: /home/node/.openclaw/workspace
|
||||
volumes:
|
||||
- name: config
|
||||
emptyDir: {}
|
||||
- name: workspace
|
||||
emptyDir: {}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: openclaw-gateway
|
||||
namespace: openclaw
|
||||
spec:
|
||||
selector:
|
||||
app: openclaw-gateway
|
||||
ports:
|
||||
- port: 18789
|
||||
targetPort: 18789
|
||||
protocol: TCP
|
||||
name: http
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: openclaw-gateway
|
||||
namespace: openclaw
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||
spec:
|
||||
rules:
|
||||
- host: openclaw-k3s.example.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: openclaw-gateway
|
||||
port:
|
||||
number: 18789
|
||||
43
ansible/files/openclaw/openclaw-proxy.yaml
Normal file
43
ansible/files/openclaw/openclaw-proxy.yaml
Normal file
@@ -0,0 +1,43 @@
|
||||
# docs/05-07-openclaw应用部署.md — 修改 IP / host
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: openclaw-external
|
||||
namespace: default
|
||||
spec:
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 18789
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Endpoints
|
||||
metadata:
|
||||
name: openclaw-external
|
||||
namespace: default
|
||||
subsets:
|
||||
- addresses:
|
||||
- ip: 192.168.2.70
|
||||
ports:
|
||||
- port: 18789
|
||||
name: http
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: openclaw
|
||||
namespace: default
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||
spec:
|
||||
rules:
|
||||
- host: openclaw.example.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: openclaw-external
|
||||
port:
|
||||
number: 80
|
||||
27
ansible/files/openlist/app-data-backup-cronjob.yaml
Normal file
27
ansible/files/openlist/app-data-backup-cronjob.yaml
Normal file
@@ -0,0 +1,27 @@
|
||||
# docs/06-03-k3s-自动备份与恢复-openlist-webdav.md — 替换镜像、hostPath、远端名
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: app-data-backup
|
||||
namespace: default
|
||||
spec:
|
||||
schedule: "0 3 * * *"
|
||||
jobTemplate:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: app-data-backup
|
||||
image: your-registry/app-backup:latest
|
||||
args:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- rclone sync /data openlist-webdav:backups/app-data
|
||||
volumeMounts:
|
||||
- name: app-data
|
||||
mountPath: /data
|
||||
volumes:
|
||||
- name: app-data
|
||||
hostPath:
|
||||
path: /data/app
|
||||
restartPolicy: OnFailure
|
||||
24
ansible/files/openlist/app-data-restore-job.yaml
Normal file
24
ansible/files/openlist/app-data-restore-job.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
# docs/06-03-k3s-自动备份与恢复-openlist-webdav.md — 一次性恢复 Job
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: app-data-restore
|
||||
namespace: default
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: app-data-restore
|
||||
image: your-registry/app-backup:latest
|
||||
args:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- rclone sync openlist-webdav:backups/app-data /data
|
||||
volumeMounts:
|
||||
- name: app-data
|
||||
mountPath: /data
|
||||
volumes:
|
||||
- name: app-data
|
||||
hostPath:
|
||||
path: /data/app
|
||||
restartPolicy: OnFailure
|
||||
27
ansible/files/openlist/openlist-backup-cronjob.yaml
Normal file
27
ansible/files/openlist/openlist-backup-cronjob.yaml
Normal file
@@ -0,0 +1,27 @@
|
||||
# docs/05-06-openlist挂载网盘与自动备份.md — 替换镜像与 PVC 名
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: openlist-backup
|
||||
namespace: default
|
||||
spec:
|
||||
schedule: "0 3 * * *"
|
||||
jobTemplate:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: openlist-backup
|
||||
image: your-registry/openlist-backup:latest
|
||||
args:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- /backup.sh
|
||||
volumeMounts:
|
||||
- name: backup-target
|
||||
mountPath: /backup
|
||||
volumes:
|
||||
- name: backup-target
|
||||
persistentVolumeClaim:
|
||||
claimName: openlist-backup-pvc
|
||||
restartPolicy: OnFailure
|
||||
38
ansible/files/traefik-acme/traefik-acme.yaml
Normal file
38
ansible/files/traefik-acme/traefik-acme.yaml
Normal file
@@ -0,0 +1,38 @@
|
||||
# 03-02 Traefik ACME 配置(HelmChartConfig)
|
||||
# 含:ACME(Cloudflare DNS-01)、ping 健康检查(websecure)、PROXY protocol trustedIPs
|
||||
# 使用前:替换 <YOUR_REAL_EMAIL>,创建 cloudflare-api-token Secret,按实际修改 nodeSelector/trustedIPs
|
||||
# 部署:kubectl apply -f traefik-acme.yaml(或复制到 K3s manifests 目录)
|
||||
---
|
||||
apiVersion: helm.cattle.io/v1
|
||||
kind: HelmChartConfig
|
||||
metadata:
|
||||
name: traefik
|
||||
namespace: kube-system
|
||||
spec:
|
||||
valuesContent: |-
|
||||
additionalArguments:
|
||||
- "--log.level=INFO"
|
||||
- "--certificatesresolvers.cloudflare.acme.dnschallenge.resolvers=1.1.1.1:53,1.0.0.1:53"
|
||||
- "--certificatesresolvers.cloudflare.acme.email=<YOUR_REAL_EMAIL>"
|
||||
- "--certificatesresolvers.cloudflare.acme.storage=/data/acme.json"
|
||||
# - "--certificatesresolvers.cloudflare.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory" # 测试用,上线前删除
|
||||
- "--certificatesresolvers.cloudflare.acme.dnschallenge.provider=cloudflare"
|
||||
- "--certificatesresolvers.cloudflare.acme.dnschallenge.propagation.delayBeforeChecks=600"
|
||||
|
||||
# 健康检查:GET /ping 在 443(HTTPS) 返回 200,供 HAProxy 对 443 做 option httpchk + ssl
|
||||
- "--ping=true"
|
||||
- "--ping.entryPoint=websecure"
|
||||
|
||||
# PROXY protocol:trustedIPs 需包含 HAProxy 所在 IP/网段
|
||||
- "--entrypoints.web.proxyProtocol.trustedIPs=192.168.2.0/24"
|
||||
- "--entrypoints.websecure.proxyProtocol.trustedIPs=192.168.2.0/24"
|
||||
|
||||
env:
|
||||
- name: CF_DNS_API_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: cloudflare-api-token
|
||||
key: api-token
|
||||
|
||||
nodeSelector:
|
||||
kubernetes.io/hostname: ylc61
|
||||
25
ansible/files/traefik-custom-ports/traefik-custom-ports.yaml
Normal file
25
ansible/files/traefik-custom-ports/traefik-custom-ports.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
apiVersion: helm.cattle.io/v1
|
||||
kind: HelmChartConfig
|
||||
metadata:
|
||||
name: traefik
|
||||
namespace: kube-system
|
||||
spec:
|
||||
valuesContent: |-
|
||||
ports:
|
||||
web:
|
||||
expose: true
|
||||
websecure:
|
||||
expose: true
|
||||
# 自定义 HTTP 入口(示例 18080)
|
||||
web18080:
|
||||
port: 18080
|
||||
expose:
|
||||
default: true
|
||||
exposedPort: 18080
|
||||
# 自定义 HTTPS 入口(示例 18443)
|
||||
websecure18443:
|
||||
port: 18443
|
||||
expose:
|
||||
default: true
|
||||
exposedPort: 18443
|
||||
60
ansible/files/traefik-dashboard-acme/tomcat-acme-test05.yaml
Normal file
60
ansible/files/traefik-dashboard-acme/tomcat-acme-test05.yaml
Normal file
@@ -0,0 +1,60 @@
|
||||
# docs/03-03 第 5 节:Tomcat + test05.jackadam.top 验证 HTTPS(请按需改域名)
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: tomcat-test05
|
||||
namespace: default
|
||||
labels:
|
||||
app: tomcat-test05
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: tomcat-test05
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: tomcat-test05
|
||||
spec:
|
||||
containers:
|
||||
- name: tomcat
|
||||
image: tomcat:9.0
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: tomcat-test05
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: tomcat-test05
|
||||
ports:
|
||||
- port: 8080
|
||||
targetPort: 8080
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: tomcat-test05-acme
|
||||
namespace: default
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||
traefik.ingress.kubernetes.io/router.tls.certresolver: cloudflare
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- test05.jackadam.top
|
||||
rules:
|
||||
- host: test05.jackadam.top
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: tomcat-test05
|
||||
port:
|
||||
number: 8080
|
||||
@@ -0,0 +1,49 @@
|
||||
# 03-03 Traefik Dashboard + ACME 合并配置(HelmChartConfig)
|
||||
# 含:Dashboard、ACME(Cloudflare DNS-01)、ping、PROXY protocol(与 03-02 一致)
|
||||
# 使用前:替换 <YOUR_REAL_EMAIL>,创建 cloudflare-api-token Secret,按实际修改 nodeSelector/trustedIPs
|
||||
# 部署:kubectl apply -f traefik-dashboard-acme.yaml
|
||||
---
|
||||
apiVersion: helm.cattle.io/v1
|
||||
kind: HelmChartConfig
|
||||
metadata:
|
||||
name: traefik
|
||||
namespace: kube-system
|
||||
spec:
|
||||
valuesContent: |-
|
||||
ports:
|
||||
web:
|
||||
expose: true
|
||||
websecure:
|
||||
expose: true
|
||||
|
||||
additionalArguments:
|
||||
- "--api.dashboard=true"
|
||||
- "--api.insecure=true"
|
||||
|
||||
- "--log.level=INFO"
|
||||
- "--certificatesresolvers.cloudflare.acme.dnschallenge.resolvers=1.1.1.1:53,1.0.0.1:53"
|
||||
- "--certificatesresolvers.cloudflare.acme.email=<YOUR_REAL_EMAIL>"
|
||||
- "--certificatesresolvers.cloudflare.acme.storage=/data/acme.json"
|
||||
# - "--certificatesresolvers.cloudflare.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory" # 测试用,上线前删除
|
||||
- "--certificatesresolvers.cloudflare.acme.dnschallenge.provider=cloudflare"
|
||||
- "--certificatesresolvers.cloudflare.acme.dnschallenge.propagation.delayBeforeChecks=600"
|
||||
|
||||
- "--ping=true"
|
||||
- "--ping.entryPoint=websecure"
|
||||
|
||||
- "--entrypoints.web.proxyProtocol.trustedIPs=192.168.2.0/24"
|
||||
- "--entrypoints.websecure.proxyProtocol.trustedIPs=192.168.2.0/24"
|
||||
|
||||
env:
|
||||
- name: CF_DNS_API_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: cloudflare-api-token
|
||||
key: api-token
|
||||
|
||||
nodeSelector:
|
||||
kubernetes.io/hostname: ylc61
|
||||
|
||||
ingressRoute:
|
||||
dashboard:
|
||||
enabled: true
|
||||
37
ansible/files/traefik-dashboard/traefik-dashboard.yaml
Normal file
37
ansible/files/traefik-dashboard/traefik-dashboard.yaml
Normal file
@@ -0,0 +1,37 @@
|
||||
# 03-01 Traefik Dashboard(HelmChartConfig + IngressRoute)
|
||||
# 部署:kubectl apply -f traefik-dashboard.yaml(或复制到 K3s server/manifests/)
|
||||
---
|
||||
apiVersion: helm.cattle.io/v1
|
||||
kind: HelmChartConfig
|
||||
metadata:
|
||||
name: traefik
|
||||
namespace: kube-system
|
||||
spec:
|
||||
valuesContent: |-
|
||||
ports:
|
||||
web:
|
||||
expose: true
|
||||
websecure:
|
||||
expose: true
|
||||
traefik:
|
||||
expose: true
|
||||
|
||||
additionalArguments:
|
||||
- "--api.dashboard=true"
|
||||
- "--api.insecure=true"
|
||||
|
||||
---
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: traefik-dashboard
|
||||
namespace: kube-system
|
||||
spec:
|
||||
entryPoints:
|
||||
- web
|
||||
routes:
|
||||
- match: PathPrefix(`/dashboard`) || PathPrefix(`/api`)
|
||||
kind: Rule
|
||||
services:
|
||||
- name: api@internal
|
||||
kind: TraefikService
|
||||
22
ansible/group_vars/all.yml
Normal file
22
ansible/group_vars/all.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
# 使用 root SSH 连接(setup-k3s-workers-ssh.sh 已将同一公钥写入各节点 root)
|
||||
ansible_user: root
|
||||
|
||||
timezone: "Asia/Shanghai"
|
||||
|
||||
# k3s 相关
|
||||
k3s_version: "" # 为空表示用 get.k3s.io 默认最新
|
||||
k3s_data_dir: "/storage"
|
||||
k3s_server_ip: "192.168.2.61"
|
||||
|
||||
# 可选:是否管理 /etc/hosts、firewalld 基线
|
||||
k3s_manage_hosts: true
|
||||
k3s_manage_firewalld: true
|
||||
|
||||
#(入口节点选择已改为手动 kubectl 打标,不再通过 Ansible 管理 Traefik 入口标签)
|
||||
|
||||
## 角色标签(自动打标开关)
|
||||
# 若希望 Ansible 在安装后自动为节点打 control-plane / worker 角色标签,用于 02-05 矩阵等场景,
|
||||
# 可开启此开关;默认 true 表示自动按 inventory 中的 k3s_server / k3s_worker 分组打标。
|
||||
# 如需完全手动管理角色标签,可改为 false,并参考 `01-02-k3s-工作节点.md` 中的 kubectl 示例。
|
||||
k3s_manage_role_labels: true
|
||||
14
ansible/inventory.ini
Normal file
14
ansible/inventory.ini
Normal file
@@ -0,0 +1,14 @@
|
||||
[k3s_server]
|
||||
# root SSH 连接,setup-k3s-workers-ssh.sh 会配置所有节点(含控制节点)
|
||||
ylc61 ansible_host=192.168.2.61 ansible_ssh_private_key_file=~/.ssh/id_ed25519_k3s_192.168.2.61
|
||||
|
||||
[k3s_worker]
|
||||
# 使用 setup-k3s-workers-ssh.sh 生成的每节点密钥,路径需与控制机实际一致
|
||||
ylc62 ansible_host=192.168.2.62 ansible_ssh_private_key_file=~/.ssh/id_ed25519_k3s_192.168.2.62
|
||||
ylc63 ansible_host=192.168.2.63 ansible_ssh_private_key_file=~/.ssh/id_ed25519_k3s_192.168.2.63
|
||||
ylc64 ansible_host=192.168.2.64 ansible_ssh_private_key_file=~/.ssh/id_ed25519_k3s_192.168.2.64
|
||||
|
||||
[k3s_nodes:children]
|
||||
k3s_server
|
||||
k3s_worker
|
||||
|
||||
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