Add k3s cluster expansion documentation and scripts

- Complete expansion guide for 2/4/6 node scenarios
- Quick join scripts for worker and master nodes
- Health check and diagnostic scripts
- Quick reference card for common operations
This commit is contained in:
K3s Admin
2026-01-21 09:02:47 +00:00
parent b29c7aa904
commit a725f0f933
20 changed files with 2056 additions and 2 deletions

5
.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
.claude/
*.swp
*.swo
*~
.DS_Store

844
K3S-CLUSTER-EXPANSION.md Normal file
View File

@@ -0,0 +1,844 @@
# K3s 集群扩展指南
## 📋 目录
- [当前集群状态](#当前集群状态)
- [前置条件](#前置条件)
- [架构设计方案](#架构设计方案)
- [2节点集群1 Master + 2 Worker](#2节点集群1-master--2-worker)
- [4节点集群3 Master + 4 Worker](#4节点集群3-master--4-worker)
- [6节点集群3 Master + 6 Worker](#6节点集群3-master--6-worker)
- [节点加入步骤](#节点加入步骤)
- [高可用配置](#高可用配置)
- [存储配置](#存储配置)
- [验证和测试](#验证和测试)
- [故障排查](#故障排查)
---
## 📊 当前集群状态
```
Master 节点: vmus9
IP 地址: 134.195.210.237
k3s 版本: v1.34.3+k3s1
节点令牌: K109d35a131f48b4d40b162398a828b766d60735f29dd7b4a37b030c1d1c0e26b23::server:72e04c3a9e3e762cbdefffc96f348a2d
```
**重要**: 请妥善保管节点令牌,这是其他节点加入集群的凭证!
---
## ✅ 前置条件
### 所有新节点需要满足:
#### 1. 硬件要求
```
最低配置:
- CPU: 2 核
- 内存: 2GB (建议 4GB+)
- 磁盘: 20GB (Longhorn 存储建议 50GB+)
推荐配置:
- CPU: 4 核
- 内存: 8GB
- 磁盘: 100GB SSD
```
#### 2. 操作系统
```bash
# 支持的系统
- Ubuntu 20.04/22.04/24.04
- Debian 10/11/12
- CentOS 7/8
- RHEL 7/8
# 检查系统版本
cat /etc/os-release
```
#### 3. 网络要求
```bash
# 所有节点之间需要能够互相访问
# 需要开放的端口:
Master 节点:
- 6443: Kubernetes API Server
- 10250: Kubelet metrics
- 2379-2380: etcd (仅 HA 模式)
Worker 节点:
- 10250: Kubelet metrics
- 30000-32767: NodePort Services
所有节点:
- 8472: Flannel VXLAN (UDP)
- 51820: Flannel WireGuard (UDP)
```
#### 4. 系统准备
在每个新节点上执行:
```bash
# 1. 更新系统
sudo apt update && sudo apt upgrade -y
# 2. 禁用 swap (k8s 要求)
sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab
# 3. 配置主机名 (每个节点不同)
sudo hostnamectl set-hostname worker-node-1
# 4. 配置时间同步
sudo apt install -y chrony
sudo systemctl enable --now chrony
# 5. 安装必要工具
sudo apt install -y curl wget git
# 6. 配置防火墙 (如果启用)
# Ubuntu/Debian
sudo ufw allow 6443/tcp
sudo ufw allow 10250/tcp
sudo ufw allow 8472/udp
sudo ufw allow 51820/udp
```
---
## 🏗️ 架构设计方案
### 方案一2节点集群1 Master + 2 Worker
**适用场景**: 开发/测试环境,小型应用
```
┌─────────────────────────────────────────────────┐
│ 负载均衡 (可选) │
│ *.u9.net3w.com (Traefik) │
└─────────────────────────────────────────────────┘
┌─────────────┼─────────────┐
│ │ │
┌───────▼──────┐ ┌────▼─────┐ ┌────▼─────┐
│ Master │ │ Worker-1 │ │ Worker-2 │
│ vmus9 │ │ │ │ │
│ Control Plane│ │ 应用负载 │ │ 应用负载 │
│ + etcd │ │ │ │ │
│ 134.195.x.x │ │ 新节点1 │ │ 新节点2 │
└──────────────┘ └──────────┘ └──────────┘
```
**特点**:
- ✅ 简单易维护
- ✅ 成本低
- ❌ Master 单点故障
- ❌ 不适合生产环境
**资源分配建议**:
- Master: 4C8G (运行控制平面 + 部分应用)
- Worker-1: 4C8G (运行应用负载)
- Worker-2: 4C8G (运行应用负载)
---
### 方案二4节点集群3 Master + 4 Worker
**适用场景**: 生产环境,中等规模应用
```
┌──────────────────────────────────────────────────┐
│ 外部负载均衡 (必需) │
│ HAProxy/Nginx/云厂商 LB │
│ *.u9.net3w.com │
└──────────────────────────────────────────────────┘
┌─────────────┼─────────────┬─────────────┐
│ │ │ │
┌───────▼──────┐ ┌────▼─────┐ ┌────▼─────┐ ┌─────▼────┐
│ Master-1 │ │ Master-2 │ │ Master-3 │ │ Worker-1 │
│ vmus9 │ │ │ │ │ │ │
│ Control Plane│ │ Control │ │ Control │ │ 应用负载 │
│ + etcd │ │ + etcd │ │ + etcd │ │ │
└──────────────┘ └──────────┘ └──────────┘ └──────────┘
┌──────────┐
│ Worker-2 │
│ 应用负载 │
└──────────┘
┌──────────┐
│ Worker-3 │
│ 应用负载 │
└──────────┘
┌──────────┐
│ Worker-4 │
│ 应用负载 │
└──────────┘
```
**特点**:
- ✅ 高可用 (HA)
- ✅ Master 节点冗余
- ✅ 适合生产环境
- ✅ 可承载中等规模应用
- ⚠️ 需要外部负载均衡
**资源分配建议**:
- Master-1/2/3: 4C8G (仅运行控制平面)
- Worker-1/2/3/4: 8C16G (运行应用负载)
**etcd 集群**: 3 个 Master 节点组成 etcd 集群,可容忍 1 个节点故障
---
### 方案三6节点集群3 Master + 6 Worker
**适用场景**: 大规模生产环境,高负载应用
```
┌──────────────────────────────────────────────────┐
│ 外部负载均衡 (必需) │
│ HAProxy/Nginx/云厂商 LB │
│ *.u9.net3w.com │
└──────────────────────────────────────────────────┘
┌─────────────┼─────────────┬─────────────┐
│ │ │ │
┌───────▼──────┐ ┌────▼─────┐ ┌────▼─────┐ │
│ Master-1 │ │ Master-2 │ │ Master-3 │ │
│ vmus9 │ │ │ │ │ │
│ Control Plane│ │ Control │ │ Control │ │
│ + etcd │ │ + etcd │ │ + etcd │ │
└──────────────┘ └──────────┘ └──────────┘ │
┌─────────────┬─────────────┬─────────────┘
│ │ │
┌───────▼──────┐ ┌────▼─────┐ ┌────▼─────┐
│ Worker-1 │ │ Worker-2 │ │ Worker-3 │
│ Web 应用层 │ │ Web 层 │ │ Web 层 │
└──────────────┘ └──────────┘ └──────────┘
┌──────────────┐ ┌──────────┐ ┌──────────┐
│ Worker-4 │ │ Worker-5 │ │ Worker-6 │
│ 数据库层 │ │ 缓存层 │ │ 存储层 │
└──────────────┘ └──────────┘ └──────────┘
```
**特点**:
- ✅ 高可用 + 高性能
- ✅ 可按功能分层部署
- ✅ 支持大规模应用
- ✅ Longhorn 存储性能最佳
- ⚠️ 管理复杂度较高
- ⚠️ 成本较高
**资源分配建议**:
- Master-1/2/3: 4C8G (专用控制平面)
- Worker-1/2/3: 8C16G (Web 应用层)
- Worker-4: 8C32G (数据库层,高内存)
- Worker-5: 8C16G (缓存层)
- Worker-6: 4C8G + 200GB SSD (存储层)
**节点标签策略**:
```bash
# Web 层
kubectl label nodes worker-1 node-role=web
kubectl label nodes worker-2 node-role=web
kubectl label nodes worker-3 node-role=web
# 数据库层
kubectl label nodes worker-4 node-role=database
# 缓存层
kubectl label nodes worker-5 node-role=cache
# 存储层
kubectl label nodes worker-6 node-role=storage
```
---
## 🚀 节点加入步骤
### 场景 A: 加入 Worker 节点(适用于 2 节点方案)
#### 在新节点上执行:
```bash
# 1. 设置 Master 节点信息
export MASTER_IP="134.195.210.237"
export NODE_TOKEN="K109d35a131f48b4d40b162398a828b766d60735f29dd7b4a37b030c1d1c0e26b23::server:72e04c3a9e3e762cbdefffc96f348a2d"
# 2. 安装 k3s agent (Worker 节点)
curl -sfL https://get.k3s.io | K3S_URL=https://${MASTER_IP}:6443 \
K3S_TOKEN=${NODE_TOKEN} \
sh -
# 3. 验证安装
sudo systemctl status k3s-agent
# 4. 检查节点是否加入
# (在 Master 节点执行)
kubectl get nodes
```
#### 为 Worker 节点添加标签:
```bash
# 在 Master 节点执行
kubectl label nodes <worker-node-name> node-role.kubernetes.io/worker=worker
kubectl label nodes <worker-node-name> workload=application
```
---
### 场景 B: 加入 Master 节点(适用于 4/6 节点 HA 方案)
#### 前提条件:需要外部负载均衡器
##### 1. 配置外部负载均衡器
**选项 1: 使用 HAProxy**
在一台独立服务器上安装 HAProxy
```bash
# 安装 HAProxy
sudo apt install -y haproxy
# 配置 HAProxy
sudo tee /etc/haproxy/haproxy.cfg > /dev/null <<EOF
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
defaults
log global
mode tcp
option tcplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
frontend k3s-api
bind *:6443
mode tcp
default_backend k3s-masters
backend k3s-masters
mode tcp
balance roundrobin
option tcp-check
server master-1 134.195.210.237:6443 check fall 3 rise 2
server master-2 <MASTER-2-IP>:6443 check fall 3 rise 2
server master-3 <MASTER-3-IP>:6443 check fall 3 rise 2
EOF
# 重启 HAProxy
sudo systemctl restart haproxy
sudo systemctl enable haproxy
```
**选项 2: 使用 Nginx**
```bash
# 安装 Nginx
sudo apt install -y nginx
# 配置 Nginx Stream
sudo tee /etc/nginx/nginx.conf > /dev/null <<EOF
stream {
upstream k3s_servers {
server 134.195.210.237:6443 max_fails=3 fail_timeout=5s;
server <MASTER-2-IP>:6443 max_fails=3 fail_timeout=5s;
server <MASTER-3-IP>:6443 max_fails=3 fail_timeout=5s;
}
server {
listen 6443;
proxy_pass k3s_servers;
}
}
EOF
# 重启 Nginx
sudo systemctl restart nginx
```
##### 2. 在第一个 Master 节点(当前节点)启用 HA
```bash
# 在当前 Master 节点执行
export LB_IP="<负载均衡器IP>"
# 重新安装 k3s 为 HA 模式
curl -sfL https://get.k3s.io | sh -s - server \
--cluster-init \
--tls-san=${LB_IP} \
--write-kubeconfig-mode 644
# 获取新的 token
sudo cat /var/lib/rancher/k3s/server/node-token
```
##### 3. 加入第二个 Master 节点
```bash
# 在新的 Master 节点执行
export MASTER_IP="134.195.210.237" # 第一个 Master
export LB_IP="<负载均衡器IP>"
export NODE_TOKEN="<新的 token>"
curl -sfL https://get.k3s.io | sh -s - server \
--server https://${MASTER_IP}:6443 \
--token ${NODE_TOKEN} \
--tls-san=${LB_IP} \
--write-kubeconfig-mode 644
```
##### 4. 加入第三个 Master 节点
```bash
# 在第三个 Master 节点执行(同上)
export MASTER_IP="134.195.210.237"
export LB_IP="<负载均衡器IP>"
export NODE_TOKEN="<token>"
curl -sfL https://get.k3s.io | sh -s - server \
--server https://${MASTER_IP}:6443 \
--token ${NODE_TOKEN} \
--tls-san=${LB_IP} \
--write-kubeconfig-mode 644
```
##### 5. 验证 HA 集群
```bash
# 检查所有 Master 节点
kubectl get nodes
# 检查 etcd 集群状态
kubectl get pods -n kube-system | grep etcd
# 检查 etcd 成员
sudo k3s etcd-snapshot save --etcd-s3=false
```
---
### 场景 C: 混合加入(先加 Master 再加 Worker
**推荐顺序**:
1. 配置外部负载均衡器
2. 转换第一个节点为 HA 模式
3. 加入第 2、3 个 Master 节点
4. 验证 Master 集群正常
5. 依次加入 Worker 节点
---
## 💾 存储配置
### Longhorn 多节点配置
当集群有 3+ 节点时Longhorn 可以提供分布式存储和数据冗余。
#### 1. 在所有节点安装依赖
```bash
# 在每个节点执行
sudo apt install -y open-iscsi nfs-common
# 启动 iscsid
sudo systemctl enable --now iscsid
```
#### 2. 配置 Longhorn 副本数
```bash
# 在 Master 节点执行
kubectl edit settings.longhorn.io default-replica-count -n longhorn-system
# 修改为:
# value: "3" # 3 副本(需要至少 3 个节点)
# value: "2" # 2 副本(需要至少 2 个节点)
```
#### 3. 为节点添加存储标签
```bash
# 标记哪些节点用于存储
kubectl label nodes worker-1 node.longhorn.io/create-default-disk=true
kubectl label nodes worker-2 node.longhorn.io/create-default-disk=true
kubectl label nodes worker-3 node.longhorn.io/create-default-disk=true
# 排除某些节点(如纯计算节点)
kubectl label nodes worker-4 node.longhorn.io/create-default-disk=false
```
#### 4. 配置存储路径
```bash
# 在每个存储节点创建目录
sudo mkdir -p /var/lib/longhorn
sudo chmod 700 /var/lib/longhorn
```
#### 5. 访问 Longhorn UI
```bash
# 创建 Ingress (如果还没有)
kubectl apply -f k3s/my-blog/longhorn-ingress.yaml
# 访问: https://longhorn.u9.net3w.com
```
---
## ✅ 验证和测试
### 1. 检查节点状态
```bash
# 查看所有节点
kubectl get nodes -o wide
# 查看节点详细信息
kubectl describe node <node-name>
# 查看节点资源使用
kubectl top nodes
```
### 2. 测试 Pod 调度
```bash
# 创建测试 Deployment
kubectl create deployment nginx-test --image=nginx --replicas=6
# 查看 Pod 分布
kubectl get pods -o wide
# 清理测试
kubectl delete deployment nginx-test
```
### 3. 测试存储
```bash
# 创建测试 PVC
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: test-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn
resources:
requests:
storage: 1Gi
EOF
# 检查 PVC 状态
kubectl get pvc test-pvc
# 清理
kubectl delete pvc test-pvc
```
### 4. 测试高可用(仅 HA 集群)
```bash
# 模拟 Master 节点故障
# 在一个 Master 节点执行
sudo systemctl stop k3s
# 在另一个节点检查集群是否正常
kubectl get nodes
# 恢复节点
sudo systemctl start k3s
```
### 5. 测试网络连通性
```bash
# 在 Master 节点创建测试 Pod
kubectl run test-pod --image=busybox --restart=Never -- sleep 3600
# 进入 Pod 测试网络
kubectl exec -it test-pod -- sh
# 在 Pod 内测试
ping 8.8.8.8
nslookup kubernetes.default
# 清理
kubectl delete pod test-pod
```
---
## 🔧 故障排查
### 问题 1: 节点无法加入集群
**症状**: `k3s-agent` 服务启动失败
**排查步骤**:
```bash
# 1. 检查服务状态
sudo systemctl status k3s-agent
# 2. 查看日志
sudo journalctl -u k3s-agent -f
# 3. 检查网络连通性
ping <MASTER_IP>
telnet <MASTER_IP> 6443
# 4. 检查 token 是否正确
echo $NODE_TOKEN
# 5. 检查防火墙
sudo ufw status
```
**解决方案**:
```bash
# 重新安装
sudo /usr/local/bin/k3s-agent-uninstall.sh
curl -sfL https://get.k3s.io | K3S_URL=https://${MASTER_IP}:6443 \
K3S_TOKEN=${NODE_TOKEN} sh -
```
---
### 问题 2: 节点状态为 NotReady
**症状**: `kubectl get nodes` 显示节点 NotReady
**排查步骤**:
```bash
# 1. 检查节点详情
kubectl describe node <node-name>
# 2. 检查 kubelet 日志
# 在问题节点执行
sudo journalctl -u k3s-agent -n 100
# 3. 检查网络插件
kubectl get pods -n kube-system | grep flannel
```
**解决方案**:
```bash
# 重启 k3s 服务
sudo systemctl restart k3s-agent
# 如果是网络问题,检查 CNI 配置
sudo ls -la /etc/cni/net.d/
```
---
### 问题 3: Pod 无法调度到新节点
**症状**: Pod 一直 Pending 或只调度到旧节点
**排查步骤**:
```bash
# 1. 检查节点污点
kubectl describe node <node-name> | grep Taints
# 2. 检查节点标签
kubectl get nodes --show-labels
# 3. 检查 Pod 的调度约束
kubectl describe pod <pod-name>
```
**解决方案**:
```bash
# 移除污点
kubectl taint nodes <node-name> node.kubernetes.io/not-ready:NoSchedule-
# 添加标签
kubectl label nodes <node-name> node-role.kubernetes.io/worker=worker
```
---
### 问题 4: Longhorn 存储无法使用
**症状**: PVC 一直 Pending
**排查步骤**:
```bash
# 1. 检查 Longhorn 组件
kubectl get pods -n longhorn-system
# 2. 检查节点是否满足要求
kubectl get nodes -o jsonpath='{.items[*].status.conditions[?(@.type=="Ready")].status}'
# 3. 检查 iscsid 服务
sudo systemctl status iscsid
```
**解决方案**:
```bash
# 在新节点安装依赖
sudo apt install -y open-iscsi
sudo systemctl enable --now iscsid
# 重启 Longhorn manager
kubectl rollout restart deployment longhorn-driver-deployer -n longhorn-system
```
---
### 问题 5: etcd 集群不健康HA 模式)
**症状**: Master 节点无法正常工作
**排查步骤**:
```bash
# 1. 检查 etcd 成员
sudo k3s etcd-snapshot ls
# 2. 检查 etcd 日志
sudo journalctl -u k3s -n 100 | grep etcd
# 3. 检查 etcd 端口
sudo netstat -tlnp | grep 2379
```
**解决方案**:
```bash
# 从快照恢复(谨慎操作)
sudo k3s server \
--cluster-reset \
--cluster-reset-restore-path=/var/lib/rancher/k3s/server/db/snapshots/<snapshot-name>
```
---
## 📚 快速参考
### 常用命令
```bash
# 查看集群信息
kubectl cluster-info
kubectl get nodes -o wide
kubectl get pods -A
# 查看节点资源
kubectl top nodes
kubectl describe node <node-name>
# 管理节点
kubectl cordon <node-name> # 标记为不可调度
kubectl drain <node-name> # 驱逐 Pod
kubectl uncordon <node-name> # 恢复调度
# 删除节点
kubectl delete node <node-name>
# 在节点上卸载 k3s
# Worker 节点
sudo /usr/local/bin/k3s-agent-uninstall.sh
# Master 节点
sudo /usr/local/bin/k3s-uninstall.sh
```
### 节点标签示例
```bash
# 角色标签
kubectl label nodes <node> node-role.kubernetes.io/worker=worker
kubectl label nodes <node> node-role.kubernetes.io/master=master
# 功能标签
kubectl label nodes <node> workload=database
kubectl label nodes <node> workload=web
kubectl label nodes <node> workload=cache
# 区域标签
kubectl label nodes <node> topology.kubernetes.io/zone=zone-a
kubectl label nodes <node> topology.kubernetes.io/region=us-east
```
---
## 🎯 最佳实践
### 1. 节点命名规范
```
master-1, master-2, master-3
worker-1, worker-2, worker-3, ...
```
### 2. 逐步扩展
- 先加入 1 个节点测试
- 验证正常后再批量加入
- 避免同时加入多个节点
### 3. 监控和告警
```bash
# 部署 Prometheus + Grafana
kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/setup/
kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/
```
### 4. 定期备份
```bash
# 备份 etcd
sudo k3s etcd-snapshot save --name backup-$(date +%Y%m%d-%H%M%S)
# 查看备份
sudo k3s etcd-snapshot ls
```
### 5. 资源预留
```bash
# 为系统组件预留资源
kubectl apply -f - <<EOF
apiVersion: v1
kind: ResourceQuota
metadata:
name: system-quota
namespace: kube-system
spec:
hard:
requests.cpu: "2"
requests.memory: 4Gi
EOF
```
---
## 📞 获取帮助
- k3s 官方文档: https://docs.k3s.io
- Longhorn 文档: https://longhorn.io/docs
- Kubernetes 文档: https://kubernetes.io/docs
---
**文档版本**: v1.0
**最后更新**: 2026-01-21
**适用于**: k3s v1.34.3+k3s1

161
QUICK-REFERENCE.md Normal file
View File

@@ -0,0 +1,161 @@
# K3s 集群扩展快速参考
## 🚀 快速开始
### 当前集群信息
```
Master IP: 134.195.210.237
Token: K109d35a131f48b4d40b162398a828b766d60735f29dd7b4a37b030c1d1c0e26b23::server:72e04c3a9e3e762cbdefffc96f348a2d
```
### 一键加入脚本
#### Worker 节点(最简单)
```bash
# 在新节点上执行
sudo bash scripts/join-worker.sh
```
#### Master 节点HA 模式)
```bash
# 在新节点上执行
sudo bash scripts/join-master.sh
```
---
## 📊 扩展方案对比
| 方案 | 节点配置 | 适用场景 | 高可用 | 成本 |
|------|---------|---------|--------|------|
| **2节点** | 1M + 2W | 开发/测试 | ❌ | 💰 |
| **4节点** | 3M + 4W | 生产环境 | ✅ | 💰💰💰 |
| **6节点** | 3M + 6W | 大规模生产 | ✅ | 💰💰💰💰 |
M = Master, W = Worker
---
## 🔧 手动加入命令
### Worker 节点
```bash
export MASTER_IP="134.195.210.237"
export NODE_TOKEN="K109d35a131f48b4d40b162398a828b766d60735f29dd7b4a37b030c1d1c0e26b23::server:72e04c3a9e3e762cbdefffc96f348a2d"
curl -sfL https://get.k3s.io | K3S_URL=https://${MASTER_IP}:6443 \
K3S_TOKEN=${NODE_TOKEN} sh -
```
### Master 节点(需要先配置负载均衡器)
```bash
export FIRST_MASTER="134.195.210.237"
export LB_IP="<负载均衡器IP>"
export NODE_TOKEN="K109d35a131f48b4d40b162398a828b766d60735f29dd7b4a37b030c1d1c0e26b23::server:72e04c3a9e3e762cbdefffc96f348a2d"
curl -sfL https://get.k3s.io | sh -s - server \
--server https://${FIRST_MASTER}:6443 \
--token ${NODE_TOKEN} \
--tls-san=${LB_IP} \
--write-kubeconfig-mode 644
```
---
## ✅ 验证命令
```bash
# 查看节点
kubectl get nodes -o wide
# 健康检查
bash scripts/check-node-health.sh
# 查看节点详情
kubectl describe node <node-name>
# 查看资源使用
kubectl top nodes
```
---
## 🏷️ 节点标签
```bash
# Worker 节点
kubectl label nodes <node> node-role.kubernetes.io/worker=worker
# 功能标签
kubectl label nodes <node> workload=web
kubectl label nodes <node> workload=database
kubectl label nodes <node> workload=cache
```
---
## 🔥 常见问题
### 节点无法加入?
```bash
# 检查网络
ping 134.195.210.237
telnet 134.195.210.237 6443
# 查看日志
sudo journalctl -u k3s-agent -f
```
### 节点 NotReady
```bash
# 重启服务
sudo systemctl restart k3s-agent
# 检查详情
kubectl describe node <node-name>
```
### 删除节点
```bash
# 在 Master 节点
kubectl drain <node-name> --ignore-daemonsets
kubectl delete node <node-name>
# 在要删除的节点
sudo /usr/local/bin/k3s-agent-uninstall.sh
```
---
## 📚 详细文档
- 完整扩展指南: [K3S-CLUSTER-EXPANSION.md](K3S-CLUSTER-EXPANSION.md)
- GitOps 自动部署: [README.md](README.md)
---
## 🎯 推荐流程
### 2节点扩展开发环境
1. ✅ 准备 2 台新 VPS
2. ✅ 执行 `join-worker.sh`
3. ✅ 验证节点状态
4. ✅ 测试应用部署
### 4节点扩展生产环境
1. ✅ 配置外部负载均衡器
2. ✅ 转换第一个节点为 HA 模式
3. ✅ 加入 2 个 Master 节点
4. ✅ 加入 4 个 Worker 节点
5. ✅ 配置 Longhorn 多副本
6. ✅ 测试高可用
### 6节点扩展大规模
1. ✅ 同 4 节点方案
2. ✅ 按功能分层部署
3. ✅ 配置节点亲和性
4. ✅ 优化资源分配
---
**快速帮助**: 遇到问题?运行 `bash scripts/check-node-health.sh` 进行诊断

68
biji.md Normal file
View File

@@ -0,0 +1,68 @@
k3s集群部署完成!
📊 部署总结
✅ 集群状态
- k3s版本: v1.34.3+k3s1
- 节点状态: Ready (control-plane)
- 运行中的Pods: 35个
- 存储系统: Longhorn (分布式存储)
- 证书管理: cert-manager + Let's Encrypt
🚀 已部署的服务
所有服务都已实现无状态化部署,数据和存储完全解耦:
┌─────────────────┬───────────────────────────────┬────────────┬─────────────┬─────────────────┐
│ 服务 │ 域名 │ 状态 │ 存储 │ HTTPS │
├─────────────────┼───────────────────────────────┼────────────┼─────────────┼─────────────────┤
│ WordPress博客 │ https://blog.u9.net3w.com │ ✅ Running │ 2Gi (MySQL) │ ✅ │
├─────────────────┼───────────────────────────────┼────────────┼─────────────┼─────────────────┤
│ Docker Registry │ https://registry.u9.net3w.com │ ✅ Running │ 20Gi │ ⏳ (证书申请中) │
├─────────────────┼───────────────────────────────┼────────────┼─────────────┼─────────────────┤
│ n8n工作流 │ https://n8n.u9.net3w.com │ ✅ Running │ 5Gi │ ✅ │
├─────────────────┼───────────────────────────────┼────────────┼─────────────┼─────────────────┤
│ Gitea代码仓库 │ https://git.u9.net3w.com │ ✅ Running │ 10Gi │ ✅ │
├─────────────────┼───────────────────────────────┼────────────┼─────────────┼─────────────────┤
│ Uptime Kuma监控 │ https://status.u9.net3w.com │ ✅ Running │ 2Gi │ ✅ │
├─────────────────┼───────────────────────────────┼────────────┼─────────────┼─────────────────┤
│ 导航页 │ https://nav.u9.net3w.com │ ✅ Running │ - │ ✅ │
└─────────────────┴───────────────────────────────┴────────────┴─────────────┴─────────────────┘
💾 存储配置
所有数据都使用Longhorn持久化存储,实现了容器与数据的完全解耦:
- MySQL数据库: 2Gi独立存储卷
- Docker镜像仓库: 20Gi独立存储卷
- Gitea代码仓库: 10Gi独立存储卷
- n8n工作流数据: 5Gi独立存储卷
- Uptime Kuma监控数据: 2Gi独立存储卷
🔐 安全配置
- ✅ 自动HTTPS证书(Let's Encrypt)
- ✅ Traefik Ingress Controller
- ✅ Docker Registry认证(用户名: admin, 密码: 123456)
📝 常用命令
# 查看所有服务
kubectl get pods -A
# 查看存储卷
kubectl get pvc -A
# 查看域名和证书
kubectl get ingress -A
kubectl get certificate -A
# 查看Longhorn UI (可选)
kubectl get svc -n longhorn-system
⚠️ 注意事项
1. Registry证书: registry.u9.net3w.com的SSL证书还在申请中,稍等几分钟会自动完成
2. DNS解析: 确保所有*.u9.net3w.com子域名都已正确解析到 134.195.210.237
3. 数据持久化: 所有数据都存储在Longhorn卷中,容器重启不会丢失数据
所有服务已成功实现无状态化部署,可以随时重启、扩容或迁移! 🎊

View File

@@ -6,8 +6,8 @@ metadata:
annotations: annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod cert-manager.io/cluster-issuer: letsencrypt-prod
traefik.ingress.kubernetes.io/router.entrypoints: websecure traefik.ingress.kubernetes.io/router.entrypoints: websecure
nginx.ingress.kubernetes.io/ssl-passthrough: "true" traefik.ingress.kubernetes.io/service.serversscheme: https
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" traefik.ingress.kubernetes.io/service.serverstransport: insecure@file
spec: spec:
tls: tls:
- hosts: - hosts:

View File

@@ -5,6 +5,10 @@ metadata:
name: wordpress-service name: wordpress-service
namespace: demo-space namespace: demo-space
spec: spec:
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800 # 3 hours
ports: ports:
- port: 80 - port: 80
selector: selector:
@@ -48,6 +52,9 @@ spec:
} }
/* Force SSL for admin */ /* Force SSL for admin */
define('FORCE_SSL_ADMIN', true); define('FORCE_SSL_ADMIN', true);
/* Redis session storage for multi-replica support */
@ini_set('session.save_handler', 'redis');
@ini_set('session.save_path', 'tcp://redis-service:6379');
/* Fix cookie issues */ /* Fix cookie issues */
@ini_set('session.cookie_httponly', true); @ini_set('session.cookie_httponly', true);
@ini_set('session.cookie_secure', true); @ini_set('session.cookie_secure', true);

View File

@@ -9,6 +9,9 @@ metadata:
annotations: annotations:
# ▼▼▼ 关键注解:我要申请证书 ▼▼▼ # ▼▼▼ 关键注解:我要申请证书 ▼▼▼
cert-manager.io/cluster-issuer: letsencrypt-prod cert-manager.io/cluster-issuer: letsencrypt-prod
# ▼▼▼ Traefik sticky session 配置 ▼▼▼
traefik.ingress.kubernetes.io/affinity: "true"
traefik.ingress.kubernetes.io/session-cookie-name: "wordpress-session"
spec: spec:
rules: rules:
- host: blog.u9.net3w.com # 您的域名 - host: blog.u9.net3w.com # 您的域名

40
k3s/my-blog/04-redis.yaml Normal file
View File

@@ -0,0 +1,40 @@
# 04-redis.yaml - Redis for WordPress session storage
apiVersion: v1
kind: Service
metadata:
name: redis-service
namespace: demo-space
spec:
ports:
- port: 6379
targetPort: 6379
selector:
app: redis
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
namespace: demo-space
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7-alpine
ports:
- containerPort: 6379
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"

8
k3s/my-blog/Dockerfile Normal file
View File

@@ -0,0 +1,8 @@
# Custom WordPress image with Redis PHP extension
FROM wordpress:latest
# Install Redis PHP extension
RUN pecl install redis && docker-php-ext-enable redis
# Verify installation
RUN php -m | grep redis

22
php-test/Database.php Normal file
View File

@@ -0,0 +1,22 @@
<?php
require_once 'config.php';
class Database {
private static ?PDO $instance = null;
public static function getConnection(): PDO {
if (self::$instance === null) {
try {
$dsn = "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET;
self::$instance = new PDO($dsn, DB_USER, DB_PASS, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]);
} catch (PDOException $e) {
die("数据库连接失败: " . $e->getMessage());
}
}
return self::$instance;
}
}

11
php-test/config.php Normal file
View File

@@ -0,0 +1,11 @@
<?php
// 数据库配置
define('DB_HOST', 'localhost');
define('DB_NAME', 'test_db');
define('DB_USER', 'root');
define('DB_PASS', '');
define('DB_CHARSET', 'utf8mb4');
// 错误报告设置(开发环境)
error_reporting(E_ALL);
ini_set('display_errors', 1);

210
php-test/index.php Normal file
View File

@@ -0,0 +1,210 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PHP MySQL 测试表单</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.container {
background: white;
padding: 40px;
border-radius: 10px;
box-shadow: 0 10px 40px rgba(0,0,0,0.2);
max-width: 500px;
width: 100%;
}
h1 {
color: #333;
margin-bottom: 30px;
text-align: center;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
color: #555;
font-weight: 500;
}
input, textarea {
width: 100%;
padding: 12px;
border: 2px solid #e0e0e0;
border-radius: 5px;
font-size: 14px;
transition: border-color 0.3s;
}
input:focus, textarea:focus {
outline: none;
border-color: #667eea;
}
textarea {
resize: vertical;
min-height: 100px;
}
button {
width: 100%;
padding: 14px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 5px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: transform 0.2s;
}
button:hover {
transform: translateY(-2px);
}
.message {
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
display: none;
}
.message.success {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
display: block;
}
.message.error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
display: block;
}
.records {
margin-top: 30px;
padding-top: 30px;
border-top: 2px solid #e0e0e0;
}
.records h2 {
color: #333;
margin-bottom: 15px;
font-size: 20px;
}
.record-item {
background: #f8f9fa;
padding: 15px;
border-radius: 5px;
margin-bottom: 10px;
border-left: 4px solid #667eea;
}
.record-item strong {
color: #667eea;
}
.record-item p {
margin: 5px 0;
color: #555;
}
</style>
</head>
<body>
<div class="container">
<h1>📝 数据库测试表单</h1>
<?php
require_once 'Database.php';
// 显示提交结果消息
if (isset($_GET['status'])) {
if ($_GET['status'] === 'success') {
echo '<div class="message success">✅ 数据提交成功!</div>';
} elseif ($_GET['status'] === 'error') {
$error = htmlspecialchars($_GET['msg'] ?? '未知错误');
echo '<div class="message error">❌ 提交失败: ' . $error . '</div>';
}
}
?>
<form action="submit.php" method="POST">
<div class="form-group">
<label for="name">姓名 *</label>
<input type="text" id="name" name="name" required placeholder="请输入您的姓名">
</div>
<div class="form-group">
<label for="email">邮箱 *</label>
<input type="email" id="email" name="email" required placeholder="example@email.com">
</div>
<div class="form-group">
<label for="message">留言</label>
<textarea id="message" name="message" placeholder="请输入您的留言..."></textarea>
</div>
<button type="submit">提交数据</button>
</form>
<div class="records">
<h2>📊 最近提交的数据</h2>
<?php
try {
$db = Database::getConnection();
$stmt = $db->query("SELECT * FROM test_data ORDER BY created_at DESC LIMIT 5");
$records = $stmt->fetchAll();
if (count($records) > 0) {
foreach ($records as $record) {
echo '<div class="record-item">';
echo '<p><strong>姓名:</strong> ' . htmlspecialchars($record['name']) . '</p>';
echo '<p><strong>邮箱:</strong> ' . htmlspecialchars($record['email']) . '</p>';
if (!empty($record['message'])) {
echo '<p><strong>留言:</strong> ' . htmlspecialchars($record['message']) . '</p>';
}
echo '<p><strong>提交时间:</strong> ' . $record['created_at'] . '</p>';
echo '</div>';
}
} else {
echo '<p style="color: #999; text-align: center;">暂无数据</p>';
}
} catch (Exception $e) {
echo '<p style="color: #dc3545;">数据库查询失败: ' . htmlspecialchars($e->getMessage()) . '</p>';
}
?>
</div>
</div>
<!-- 热更新脚本 -->
<script>
let lastModified = null;
function checkForUpdates() {
fetch(window.location.href, {
method: 'HEAD',
cache: 'no-cache'
})
.then(response => {
const modified = response.headers.get('Last-Modified');
if (lastModified && modified && lastModified !== modified) {
console.log('检测到文件更新,正在刷新页面...');
window.location.reload();
}
lastModified = modified;
})
.catch(err => console.error('检查更新失败:', err));
}
// 每2秒检查一次更新
setInterval(checkForUpdates, 2000);
checkForUpdates();
</script>
</body>
</html>

13
php-test/schema.sql Normal file
View File

@@ -0,0 +1,13 @@
-- 创建数据库
CREATE DATABASE IF NOT EXISTS test_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE test_db;
-- 创建测试表
CREATE TABLE IF NOT EXISTS test_data (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) NOT NULL,
message TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

50
php-test/submit.php Normal file
View File

@@ -0,0 +1,50 @@
<?php
require_once 'Database.php';
header('Content-Type: application/json; charset=utf-8');
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
header('Location: index.php');
exit;
}
try {
// 获取表单数据
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
$message = trim($_POST['message'] ?? '');
// 验证必填字段
if (empty($name) || empty($email)) {
throw new Exception('姓名和邮箱为必填项');
}
// 验证邮箱格式
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new Exception('邮箱格式不正确');
}
// 获取数据库连接
$db = Database::getConnection();
// 准备SQL语句
$sql = "INSERT INTO test_data (name, email, message) VALUES (:name, :email, :message)";
$stmt = $db->prepare($sql);
// 绑定参数并执行
$stmt->execute([
':name' => $name,
':email' => $email,
':message' => $message
]);
// 重定向到首页并显示成功消息
header('Location: index.php?status=success');
exit;
} catch (Exception $e) {
// 重定向到首页并显示错误消息
$errorMsg = urlencode($e->getMessage());
header('Location: index.php?status=error&msg=' . $errorMsg);
exit;
}

84
scripts/check-node-health.sh Executable file
View File

@@ -0,0 +1,84 @@
#!/bin/bash
#
# 节点健康检查脚本
# 使用方法: bash check-node-health.sh
#
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${BLUE}================================${NC}"
echo -e "${BLUE}K3s 集群健康检查${NC}"
echo -e "${BLUE}================================${NC}"
echo ""
# 1. 检查节点状态
echo -e "${YELLOW}[1/8] 检查节点状态...${NC}"
kubectl get nodes -o wide
echo ""
# 2. 检查节点资源
echo -e "${YELLOW}[2/8] 检查节点资源使用...${NC}"
kubectl top nodes 2>/dev/null || echo -e "${YELLOW}⚠ metrics-server 未就绪${NC}"
echo ""
# 3. 检查系统 Pods
echo -e "${YELLOW}[3/8] 检查系统组件...${NC}"
kubectl get pods -n kube-system
echo ""
# 4. 检查 Longhorn
echo -e "${YELLOW}[4/8] 检查 Longhorn 存储...${NC}"
kubectl get pods -n longhorn-system | head -10
echo ""
# 5. 检查 PVC
echo -e "${YELLOW}[5/8] 检查持久化存储卷...${NC}"
kubectl get pvc -A
echo ""
# 6. 检查应用 Pods
echo -e "${YELLOW}[6/8] 检查应用 Pods...${NC}"
kubectl get pods -A | grep -v "kube-system\|longhorn-system\|cert-manager" | head -20
echo ""
# 7. 检查 Ingress
echo -e "${YELLOW}[7/8] 检查 Ingress 配置...${NC}"
kubectl get ingress -A
echo ""
# 8. 检查证书
echo -e "${YELLOW}[8/8] 检查 SSL 证书...${NC}"
kubectl get certificate -A
echo ""
# 统计信息
echo -e "${BLUE}================================${NC}"
echo -e "${BLUE}集群统计信息${NC}"
echo -e "${BLUE}================================${NC}"
TOTAL_NODES=$(kubectl get nodes --no-headers | wc -l)
READY_NODES=$(kubectl get nodes --no-headers | grep " Ready " | wc -l)
TOTAL_PODS=$(kubectl get pods -A --no-headers | wc -l)
RUNNING_PODS=$(kubectl get pods -A --no-headers | grep "Running" | wc -l)
TOTAL_PVC=$(kubectl get pvc -A --no-headers | wc -l)
BOUND_PVC=$(kubectl get pvc -A --no-headers | grep "Bound" | wc -l)
echo -e "节点总数: ${GREEN}${TOTAL_NODES}${NC} (就绪: ${GREEN}${READY_NODES}${NC})"
echo -e "Pod 总数: ${GREEN}${TOTAL_PODS}${NC} (运行中: ${GREEN}${RUNNING_PODS}${NC})"
echo -e "PVC 总数: ${GREEN}${TOTAL_PVC}${NC} (已绑定: ${GREEN}${BOUND_PVC}${NC})"
echo ""
# 健康评分
if [ $READY_NODES -eq $TOTAL_NODES ] && [ $RUNNING_PODS -gt $((TOTAL_PODS * 80 / 100)) ]; then
echo -e "${GREEN}✓ 集群健康状态: 良好${NC}"
elif [ $READY_NODES -gt $((TOTAL_NODES / 2)) ]; then
echo -e "${YELLOW}⚠ 集群健康状态: 一般${NC}"
else
echo -e "${RED}✗ 集群健康状态: 异常${NC}"
fi
echo ""

113
scripts/generate-join-script.sh Executable file
View File

@@ -0,0 +1,113 @@
#!/bin/bash
#
# 快速配置脚本生成器
# 为新节点生成定制化的加入脚本
#
# 颜色输出
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
echo -e "${GREEN}================================${NC}"
echo -e "${GREEN}K3s 节点加入脚本生成器${NC}"
echo -e "${GREEN}================================${NC}"
echo ""
# 获取当前配置
MASTER_IP="134.195.210.237"
NODE_TOKEN="K109d35a131f48b4d40b162398a828b766d60735f29dd7b4a37b030c1d1c0e26b23::server:72e04c3a9e3e762cbdefffc96f348a2d"
echo -e "${YELLOW}当前 Master 节点信息:${NC}"
echo "IP: $MASTER_IP"
echo "Token: ${NODE_TOKEN:0:20}..."
echo ""
# 选择节点类型
echo "请选择要加入的节点类型:"
echo "1) Worker 节点 (推荐用于 2 节点方案)"
echo "2) Master 节点 (用于 HA 高可用方案)"
echo ""
read -p "请输入选项 (1 或 2): " NODE_TYPE
if [ "$NODE_TYPE" == "1" ]; then
SCRIPT_NAME="join-worker-custom.sh"
echo ""
echo -e "${GREEN}生成 Worker 节点加入脚本...${NC}"
cat > $SCRIPT_NAME << 'EOFWORKER'
#!/bin/bash
set -e
# 配置信息
MASTER_IP="134.195.210.237"
NODE_TOKEN="K109d35a131f48b4d40b162398a828b766d60735f29dd7b4a37b030c1d1c0e26b23::server:72e04c3a9e3e762cbdefffc96f348a2d"
echo "开始加入 Worker 节点..."
# 系统准备
swapoff -a
sed -i '/ swap / s/^/#/' /etc/fstab
apt-get update -qq
apt-get install -y curl open-iscsi nfs-common
systemctl enable --now iscsid
# 安装 k3s agent
curl -sfL https://get.k3s.io | K3S_URL=https://${MASTER_IP}:6443 \
K3S_TOKEN=${NODE_TOKEN} sh -
echo "Worker 节点加入完成!"
echo "在 Master 节点执行: kubectl get nodes"
EOFWORKER
chmod +x $SCRIPT_NAME
elif [ "$NODE_TYPE" == "2" ]; then
SCRIPT_NAME="join-master-custom.sh"
echo ""
read -p "请输入负载均衡器 IP: " LB_IP
echo -e "${GREEN}生成 Master 节点加入脚本...${NC}"
cat > $SCRIPT_NAME << EOFMASTER
#!/bin/bash
set -e
# 配置信息
FIRST_MASTER_IP="134.195.210.237"
LB_IP="$LB_IP"
NODE_TOKEN="K109d35a131f48b4d40b162398a828b766d60735f29dd7b4a37b030c1d1c0e26b23::server:72e04c3a9e3e762cbdefffc96f348a2d"
echo "开始加入 Master 节点 (HA 模式)..."
# 系统准备
swapoff -a
sed -i '/ swap / s/^/#/' /etc/fstab
apt-get update -qq
apt-get install -y curl open-iscsi nfs-common
systemctl enable --now iscsid
# 安装 k3s server
curl -sfL https://get.k3s.io | sh -s - server \\
--server https://\${FIRST_MASTER_IP}:6443 \\
--token \${NODE_TOKEN} \\
--tls-san=\${LB_IP} \\
--write-kubeconfig-mode 644
echo "Master 节点加入完成!"
echo "在任意 Master 节点执行: kubectl get nodes"
EOFMASTER
chmod +x $SCRIPT_NAME
else
echo "无效的选项"
exit 1
fi
echo ""
echo -e "${GREEN}✓ 脚本已生成: $SCRIPT_NAME${NC}"
echo ""
echo "使用方法:"
echo "1. 将脚本复制到新节点"
echo "2. 在新节点上执行: sudo bash $SCRIPT_NAME"
echo ""

137
scripts/join-master.sh Executable file
View File

@@ -0,0 +1,137 @@
#!/bin/bash
#
# K3s Master 节点快速加入脚本 (用于 HA 集群)
# 使用方法: sudo bash join-master.sh
#
set -e
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
echo -e "${GREEN}================================${NC}"
echo -e "${GREEN}K3s Master 节点加入脚本 (HA)${NC}"
echo -e "${GREEN}================================${NC}"
echo ""
# 检查是否为 root
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}错误: 请使用 sudo 运行此脚本${NC}"
exit 1
fi
# 配置信息
FIRST_MASTER_IP="134.195.210.237"
NODE_TOKEN="K109d35a131f48b4d40b162398a828b766d60735f29dd7b4a37b030c1d1c0e26b23::server:72e04c3a9e3e762cbdefffc96f348a2d"
echo -e "${YELLOW}第一个 Master 节点 IP: ${FIRST_MASTER_IP}${NC}"
echo ""
# 获取负载均衡器 IP
read -p "请输入负载均衡器 IP 地址: " LB_IP
if [ -z "$LB_IP" ]; then
echo -e "${RED}错误: 负载均衡器 IP 不能为空${NC}"
exit 1
fi
echo -e "${YELLOW}负载均衡器 IP: ${LB_IP}${NC}"
echo ""
# 1. 检查网络连通性
echo -e "${YELLOW}[1/6] 检查网络连通性...${NC}"
if ping -c 2 ${FIRST_MASTER_IP} > /dev/null 2>&1; then
echo -e "${GREEN}✓ 可以连接到第一个 Master 节点${NC}"
else
echo -e "${RED}✗ 无法连接到第一个 Master 节点 ${FIRST_MASTER_IP}${NC}"
exit 1
fi
if ping -c 2 ${LB_IP} > /dev/null 2>&1; then
echo -e "${GREEN}✓ 可以连接到负载均衡器${NC}"
else
echo -e "${RED}✗ 无法连接到负载均衡器 ${LB_IP}${NC}"
exit 1
fi
# 2. 检查端口
echo -e "${YELLOW}[2/6] 检查端口...${NC}"
if timeout 5 bash -c "cat < /dev/null > /dev/tcp/${FIRST_MASTER_IP}/6443" 2>/dev/null; then
echo -e "${GREEN}✓ Master 节点端口 6443 可访问${NC}"
else
echo -e "${RED}✗ Master 节点端口 6443 无法访问${NC}"
exit 1
fi
# 3. 系统准备
echo -e "${YELLOW}[3/6] 准备系统环境...${NC}"
# 禁用 swap
swapoff -a
sed -i '/ swap / s/^/#/' /etc/fstab
echo -e "${GREEN}✓ 已禁用 swap${NC}"
# 安装依赖
apt-get update -qq
apt-get install -y curl open-iscsi nfs-common > /dev/null 2>&1
systemctl enable --now iscsid > /dev/null 2>&1
echo -e "${GREEN}✓ 已安装必要依赖${NC}"
# 4. 设置主机名
echo -e "${YELLOW}[4/6] 配置主机名...${NC}"
read -p "请输入此节点的主机名 (例如: master-2): " HOSTNAME
if [ -n "$HOSTNAME" ]; then
hostnamectl set-hostname $HOSTNAME
echo -e "${GREEN}✓ 主机名已设置为: $HOSTNAME${NC}"
else
echo -e "${YELLOW}⚠ 跳过主机名设置${NC}"
fi
# 5. 安装 k3s server
echo -e "${YELLOW}[5/6] 安装 k3s server (HA 模式)...${NC}"
echo -e "${YELLOW}这可能需要几分钟时间...${NC}"
curl -sfL https://get.k3s.io | sh -s - server \
--server https://${FIRST_MASTER_IP}:6443 \
--token ${NODE_TOKEN} \
--tls-san=${LB_IP} \
--write-kubeconfig-mode 644 > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo -e "${GREEN}✓ k3s server 安装成功${NC}"
else
echo -e "${RED}✗ k3s server 安装失败${NC}"
exit 1
fi
# 6. 验证安装
echo -e "${YELLOW}[6/6] 验证安装...${NC}"
sleep 15
if systemctl is-active --quiet k3s; then
echo -e "${GREEN}✓ k3s 服务运行正常${NC}"
else
echo -e "${RED}✗ k3s 服务未运行${NC}"
echo -e "${YELLOW}查看日志: sudo journalctl -u k3s -f${NC}"
exit 1
fi
echo ""
echo -e "${GREEN}================================${NC}"
echo -e "${GREEN}✓ Master 节点加入成功!${NC}"
echo -e "${GREEN}================================${NC}"
echo ""
echo -e "${YELLOW}下一步操作:${NC}"
echo -e "1. 在任意 Master 节点执行以下命令查看节点状态:"
echo -e " ${GREEN}kubectl get nodes${NC}"
echo ""
echo -e "2. 检查 etcd 集群状态:"
echo -e " ${GREEN}kubectl get pods -n kube-system | grep etcd${NC}"
echo ""
echo -e "3. 查看节点详细信息:"
echo -e " ${GREEN}kubectl describe node $HOSTNAME${NC}"
echo ""
echo -e "4. 更新负载均衡器配置,添加此节点的 IP"
echo ""

116
scripts/join-worker.sh Executable file
View File

@@ -0,0 +1,116 @@
#!/bin/bash
#
# K3s Worker 节点快速加入脚本
# 使用方法: sudo bash join-worker.sh
#
set -e
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
echo -e "${GREEN}================================${NC}"
echo -e "${GREEN}K3s Worker 节点加入脚本${NC}"
echo -e "${GREEN}================================${NC}"
echo ""
# 检查是否为 root
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}错误: 请使用 sudo 运行此脚本${NC}"
exit 1
fi
# 配置信息
MASTER_IP="134.195.210.237"
NODE_TOKEN="K109d35a131f48b4d40b162398a828b766d60735f29dd7b4a37b030c1d1c0e26b23::server:72e04c3a9e3e762cbdefffc96f348a2d"
echo -e "${YELLOW}Master 节点 IP: ${MASTER_IP}${NC}"
echo ""
# 1. 检查网络连通性
echo -e "${YELLOW}[1/6] 检查网络连通性...${NC}"
if ping -c 2 ${MASTER_IP} > /dev/null 2>&1; then
echo -e "${GREEN}✓ 网络连通正常${NC}"
else
echo -e "${RED}✗ 无法连接到 Master 节点 ${MASTER_IP}${NC}"
exit 1
fi
# 2. 检查端口
echo -e "${YELLOW}[2/6] 检查 Master 节点端口 6443...${NC}"
if timeout 5 bash -c "cat < /dev/null > /dev/tcp/${MASTER_IP}/6443" 2>/dev/null; then
echo -e "${GREEN}✓ 端口 6443 可访问${NC}"
else
echo -e "${RED}✗ 端口 6443 无法访问,请检查防火墙${NC}"
exit 1
fi
# 3. 系统准备
echo -e "${YELLOW}[3/6] 准备系统环境...${NC}"
# 禁用 swap
swapoff -a
sed -i '/ swap / s/^/#/' /etc/fstab
echo -e "${GREEN}✓ 已禁用 swap${NC}"
# 安装依赖
apt-get update -qq
apt-get install -y curl open-iscsi nfs-common > /dev/null 2>&1
systemctl enable --now iscsid > /dev/null 2>&1
echo -e "${GREEN}✓ 已安装必要依赖${NC}"
# 4. 设置主机名
echo -e "${YELLOW}[4/6] 配置主机名...${NC}"
read -p "请输入此节点的主机名 (例如: worker-1): " HOSTNAME
if [ -n "$HOSTNAME" ]; then
hostnamectl set-hostname $HOSTNAME
echo -e "${GREEN}✓ 主机名已设置为: $HOSTNAME${NC}"
else
echo -e "${YELLOW}⚠ 跳过主机名设置${NC}"
fi
# 5. 安装 k3s agent
echo -e "${YELLOW}[5/6] 安装 k3s agent...${NC}"
echo -e "${YELLOW}这可能需要几分钟时间...${NC}"
curl -sfL https://get.k3s.io | K3S_URL=https://${MASTER_IP}:6443 \
K3S_TOKEN=${NODE_TOKEN} \
sh - > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo -e "${GREEN}✓ k3s agent 安装成功${NC}"
else
echo -e "${RED}✗ k3s agent 安装失败${NC}"
exit 1
fi
# 6. 验证安装
echo -e "${YELLOW}[6/6] 验证安装...${NC}"
sleep 10
if systemctl is-active --quiet k3s-agent; then
echo -e "${GREEN}✓ k3s-agent 服务运行正常${NC}"
else
echo -e "${RED}✗ k3s-agent 服务未运行${NC}"
echo -e "${YELLOW}查看日志: sudo journalctl -u k3s-agent -f${NC}"
exit 1
fi
echo ""
echo -e "${GREEN}================================${NC}"
echo -e "${GREEN}✓ Worker 节点加入成功!${NC}"
echo -e "${GREEN}================================${NC}"
echo ""
echo -e "${YELLOW}下一步操作:${NC}"
echo -e "1. 在 Master 节点执行以下命令查看节点状态:"
echo -e " ${GREEN}kubectl get nodes${NC}"
echo ""
echo -e "2. 为节点添加标签 (在 Master 节点执行):"
echo -e " ${GREEN}kubectl label nodes $HOSTNAME node-role.kubernetes.io/worker=worker${NC}"
echo ""
echo -e "3. 查看节点详细信息:"
echo -e " ${GREEN}kubectl describe node $HOSTNAME${NC}"
echo ""

68
笔记/biji.md Normal file
View File

@@ -0,0 +1,68 @@
k3s集群部署完成!
📊 部署总结
✅ 集群状态
- k3s版本: v1.34.3+k3s1
- 节点状态: Ready (control-plane)
- 运行中的Pods: 35个
- 存储系统: Longhorn (分布式存储)
- 证书管理: cert-manager + Let's Encrypt
🚀 已部署的服务
所有服务都已实现无状态化部署,数据和存储完全解耦:
┌─────────────────┬───────────────────────────────┬────────────┬─────────────┬─────────────────┐
│ 服务 │ 域名 │ 状态 │ 存储 │ HTTPS │
├─────────────────┼───────────────────────────────┼────────────┼─────────────┼─────────────────┤
│ WordPress博客 │ https://blog.u9.net3w.com │ ✅ Running │ 2Gi (MySQL) │ ✅ │
├─────────────────┼───────────────────────────────┼────────────┼─────────────┼─────────────────┤
│ Docker Registry │ https://registry.u9.net3w.com │ ✅ Running │ 20Gi │ ⏳ (证书申请中) │
├─────────────────┼───────────────────────────────┼────────────┼─────────────┼─────────────────┤
│ n8n工作流 │ https://n8n.u9.net3w.com │ ✅ Running │ 5Gi │ ✅ │
├─────────────────┼───────────────────────────────┼────────────┼─────────────┼─────────────────┤
│ Gitea代码仓库 │ https://git.u9.net3w.com │ ✅ Running │ 10Gi │ ✅ │
├─────────────────┼───────────────────────────────┼────────────┼─────────────┼─────────────────┤
│ Uptime Kuma监控 │ https://status.u9.net3w.com │ ✅ Running │ 2Gi │ ✅ │
├─────────────────┼───────────────────────────────┼────────────┼─────────────┼─────────────────┤
│ 导航页 │ https://nav.u9.net3w.com │ ✅ Running │ - │ ✅ │
└─────────────────┴───────────────────────────────┴────────────┴─────────────┴─────────────────┘
💾 存储配置
所有数据都使用Longhorn持久化存储,实现了容器与数据的完全解耦:
- MySQL数据库: 2Gi独立存储卷
- Docker镜像仓库: 20Gi独立存储卷
- Gitea代码仓库: 10Gi独立存储卷
- n8n工作流数据: 5Gi独立存储卷
- Uptime Kuma监控数据: 2Gi独立存储卷
🔐 安全配置
- ✅ 自动HTTPS证书(Let's Encrypt)
- ✅ Traefik Ingress Controller
- ✅ Docker Registry认证(用户名: admin, 密码: 123456)
📝 常用命令
# 查看所有服务
kubectl get pods -A
# 查看存储卷
kubectl get pvc -A
# 查看域名和证书
kubectl get ingress -A
kubectl get certificate -A
# 查看Longhorn UI (可选)
kubectl get svc -n longhorn-system
⚠️ 注意事项
1. Registry证书: registry.u9.net3w.com的SSL证书还在申请中,稍等几分钟会自动完成
2. DNS解析: 确保所有*.u9.net3w.com子域名都已正确解析到 134.195.210.237
3. 数据持久化: 所有数据都存储在Longhorn卷中,容器重启不会丢失数据
所有服务已成功实现无状态化部署,可以随时重启、扩容或迁移! 🎊

94
笔记/gitops.md Normal file
View File

@@ -0,0 +1,94 @@
完美GitOps 自动部署环境已经完全配置好了!
🎉 GitOps 实现条件评估结果
✅ 所有条件已满足!
┌────────────────┬──────┬──────────────────────────────┐
│ 条件 │ 状态 │ 说明 │
├────────────────┼──────┼──────────────────────────────┤
│ k3s 集群 │ ✅ │ v1.34.3+k3s1 运行中 │
├────────────────┼──────┼──────────────────────────────┤
│ Git 仓库 │ ✅ │ 本地仓库已初始化,配置已提交 │
├────────────────┼──────┼──────────────────────────────┤
│ Gitea 代码托管 │ ✅ │ https://git.u9.net3w.com │
├────────────────┼──────┼──────────────────────────────┤
│ ArgoCD │ ✅ │ https://argocd.u9.net3w.com │
├────────────────┼──────┼──────────────────────────────┤
│ 自动同步配置 │ ✅ │ argocd-app.yaml 已创建 │
├────────────────┼──────┼──────────────────────────────┤
│ HTTPS 证书 │ ✅ │ Let's Encrypt 自动签发 │
└────────────────┴──────┴──────────────────────────────┘
🚀 下一步操作指南
1⃣ 访问 Gitea 创建仓库
访问: https://git.u9.net3w.com
1. 注册账号(首次访问)
2. 创建新仓库: k3s-configs
3. 记录仓库 URL
2⃣ 推送代码到 Gitea
# 添加远程仓库(替换为你的用户名)
git remote add origin
https://git.u9.net3w.com/你的用户名/k3s-configs.git
# 推送代码
git push -u origin master
3⃣ 配置 ArgoCD
访问: https://argocd.u9.net3w.com
用户名: admin
密码: R5ALO8NIRi4KoN8Q
步骤:
1. Settings → Repositories → Connect Repo
2. 填入 Gitea 仓库信息
3. 应用 ArgoCD Application:
kubectl apply -f k3s/argocd-app.yaml
4⃣ 测试自动部署
# 修改任意配置文件
vim k3s/my-blog/02-wordpress.yaml
# 提交并推送
git add .
git commit -m "Test auto-sync"
git push
# ArgoCD 会在 3 分钟内自动同步到集群!
📊 当前部署状态
✅ k3s 集群: 运行中 (35+ pods)
✅ ArgoCD: https://argocd.u9.net3w.com
✅ Gitea: https://git.u9.net3w.com
✅ WordPress: https://blog.u9.net3w.com
✅ Docker Registry: https://registry.u9.net3w.com
✅ n8n: https://n8n.u9.net3w.com
✅ Uptime Kuma: https://status.u9.net3w.com
✅ 导航页: https://nav.u9.net3w.com
🎯 GitOps 工作流
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 修改 YAML │ ───> │ Git Push │ ───> │ Gitea │
└─────────────┘ └─────────────┘
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ k3s 集群 │ <─── │ ArgoCD │ <─── │ 自动检测 │
│ 更新完成 │ │ 自动同步 │ │ 变更 │
└─────────────┘ └─────────────┘
所有实现条件已满足! 你现在可以实现:
- ✅ 更新 YAML 到 Git
- ✅ 自动同步到生产环境
- ✅ 版本控制和快速回滚
- ✅ 完整的审计追踪
详细使用说明请查看 README.md 文件!🎊
✻ Churned for 4m 47s