brunoandClaude 0ec52c4865 feat: 添加 Kubernetes 集群全自动运维功能
实现完整的自动化运维方案,包括自动启动、健康检查和数据备份。

## 新增功能

### 1. OrbStack 自动启动
- macOS 登录时自动启动 OrbStack
- 等待 Kubernetes 集群就绪
- 检查关键服务状态
- 配置文件:scripts/auto-start-orbstack.sh
- LaunchAgent:scripts/com.orbstack.auto-start.plist

### 2. 定时健康检查
- 每 15 分钟自动检查集群状态
- 检查所有关键 Pod、Service、Ingress
- 自动重启异常的 Deployment/StatefulSet
- 详细日志记录
- 脚本:scripts/health-check.sh

### 3. 定时数据备份
- 每天凌晨 2:00 自动备份
- 备份内容:
  - PostgreSQL 所有数据库
  - Redis RDB 快照
  - Kubernetes 配置(Ingress, ConfigMap, Secret, PVC)
  - Helm Values 文件
- 自动压缩和清理(保留 7 天)
- 脚本:scripts/auto-backup.sh

### 4. 一键配置脚本
- scripts/setup-automation.sh
- 自动配置所有 LaunchAgent 和 crontab
- 测试所有脚本运行状态
- 显示配置摘要

## 文档

- 新增详细文档:docs/automation-guide.md
- 包含使用说明、故障排查、高级配置
- 更新 README.md 添加自动化部分

## 使用方法

```bash
# 一键配置所有自动化功能
./scripts/setup-automation.sh

# 手动运行各个脚本
./scripts/health-check.sh      # 健康检查
./scripts/auto-backup.sh       # 立即备份
```

## 日志位置

- OrbStack 自动启动:~/.orbstack-auto-start.log
- 健康检查:~/.k8s-health-check.log
- 数据备份:~/k8s-backups/backup.log

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
2025-11-25 07:07:01 +08:00

OrbStack Kubernetes 基础设施

这是一套完整的 Kubernetes 基础设施方案,运行在 OrbStack 自带的 k8s 上,为所有业务线(健康平台、股票推荐、学习助手、AI 服务等)提供统一的基础层。

整体架构

分层设计

┌─────────────────────────────────────────────────────────────┐
│ L0: 宿主机层(Mac Studio)                                   │
│  - Gitea(代码仓库)                                         │
│  - Gitea Runner(CI/CD)                                    │
│  - Harbor(镜像仓库 + Docker Hub Proxy)                     │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│ L1: Kubernetes 核心层(infra namespace)                     │
│  - ingress-nginx(统一入口,监听 30080 端口)                │
│  - StorageClass(持久化存储)                                │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│ L2: 数据服务层(data namespace)                             │
│  - PostgreSQL(主力数据库)                                  │
│  - Redis(缓存 + Session + 队列)                            │
│  - MySQL(可选,仅在有依赖时安装)                           │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│ L3: 可观测性层(observability namespace)                    │
│  - Prometheus + Grafana(监控 + 可视化)                     │
│  - Loki + Promtail(日志采集 + 查询)                        │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│ 业务应用层                                                    │
│  - 健康平台(health namespace)                              │
│  - 股票推荐(stock namespace)                               │
│  - 学习助手(learn namespace)                               │
│  - AI 服务(ai namespace)                                   │
└─────────────────────────────────────────────────────────────┘

流量路径

外网请求
  ↓
Contabo Nginx(反向代理)
  ↓
WireGuard VPN(10.7.0.0/24)
  ↓
Mac Studio:30080(ingress-nginx)
  ↓
各业务 Service(根据域名路由)

快速开始

前置要求

  1. OrbStack:已安装并启动 OrbStack,Kubernetes 功能已开启
  2. Helm:版本 >= 3.0
  3. kubectl:已配置好 OrbStack k8s 的 context

检查环境

# 检查 kubectl 连接
kubectl cluster-info

# 检查 Helm
helm version

# 确认当前 context 是 OrbStack
kubectl config current-context

一键部署

# 进入项目目录
cd orbstack-k8s-infra

# 运行初始化脚本(不安装 MySQL)
./init-orbstack-k8s-infra.sh

# 如果需要 MySQL,添加 --enable-mysql 参数
./init-orbstack-k8s-infra.sh --enable-mysql

脚本会自动:

  1. 创建所需的 namespace(infra, data, observability)
  2. 添加并更新 Helm 仓库
  3. 按顺序部署所有组件
  4. 验证部署状态
  5. 打印访问信息

部署时间

首次部署大约需要 10-15 分钟,主要时间花在:

  • 下载 Helm charts
  • 拉取容器镜像
  • 等待 Pod 就绪

🤖 配置全自动运行(可选)

一键配置所有自动化功能:

./scripts/setup-automation.sh

这将配置:

  • ✅ OrbStack 登录时自动启动
  • ✅ 每 15 分钟健康检查和自动修复
  • ✅ 每天凌晨 2:00 自动备份数据

📚 详细说明请参考:自动化运维指南

登录信息汇总

⚠️ 安全提示:以下为开发环境的默认密码,生产环境务必修改!

PostgreSQL

项目 值
服务地址(集群内) postgres-postgresql.data.svc.cluster.local:5432
服务地址(端口转发) localhost:5432
管理员用户 postgres
管理员密码 admin123
应用用户 appuser
应用密码 appuser123
预置数据库 health_db, stock_db, learn_db, ai_db

连接示例:

# 集群内连接
postgresql://appuser:[email protected]:5432/health_db

# 端口转发后连接
kubectl port-forward -n data svc/postgres-postgresql 5432:5432
psql -h localhost -U appuser -d health_db
# 密码: appuser123

Redis

项目 值
服务地址(集群内) redis-master.data.svc.cluster.local:6379
服务地址(端口转发) localhost:6379
密码 redis123
DB 0 健康平台 (health)
DB 1 股票推荐 (stock)
DB 2 学习助手 (learn)
DB 3 AI 服务 (ai)
DB 4-15 预留

连接示例:

# 集群内连接
redis://:[email protected]:6379/0

# 端口转发后连接
kubectl port-forward -n data svc/redis-master 6379:6379
redis-cli -h localhost -a redis123
# 选择数据库: SELECT 0

MySQL(可选)

项目 值
服务地址(集群内) mysql.data.svc.cluster.local:3306
服务地址(端口转发) localhost:3306
Root 密码 root123
应用用户 appuser
应用密码 appuser123
默认数据库 appdb

连接示例:

# 集群内连接
mysql://appuser:[email protected]:3306/appdb

# 端口转发后连接
kubectl port-forward -n data svc/mysql 3306:3306
mysql -h localhost -u appuser -p
# 密码: appuser123

监控服务(统一域名访问)

🌐 统一访问入口: https://monitor.omniverseai.net

服务 路径 说明
Grafana / 或 /grafana 监控仪表板(默认)
Prometheus /prometheus 指标查询和浏览
Alertmanager /alertmanager 告警管理

访问方式 1:域名访问(推荐)

# Grafana(默认路径会自动重定向到 /grafana)
https://monitor.omniverseai.net/
https://monitor.omniverseai.net/grafana

# Prometheus
https://monitor.omniverseai.net/prometheus

# Alertmanager
https://monitor.omniverseai.net/alertmanager

访问方式 2:端口转发

# Grafana
kubectl port-forward -n observability svc/monitoring-grafana 3000:80
# 浏览器访问: http://localhost:3000

# Prometheus
kubectl port-forward -n observability svc/monitoring-kube-prometheus-prometheus 9090:9090
# 浏览器访问: http://localhost:9090

# Alertmanager
kubectl port-forward -n observability svc/monitoring-kube-prometheus-alertmanager 9093:9093
# 浏览器访问: http://localhost:9093

登录信息(Grafana):

  • 用户名:admin
  • 密码:admin123

预置数据源:

  • Prometheus(默认):http://monitoring-kube-prometheus-prometheus.observability.svc.cluster.local:9090
  • Loki:http://loki.observability.svc.cluster.local:3100

快速测试路由:

# 运行测试脚本
./scripts/test-monitoring-routes.sh

📝 详细的路由配置说明请参考:docs/monitoring-ingress-setup.md

Loki(日志查询)

项目 值
服务地址(集群内) loki.observability.svc.cluster.local:3100
查询界面 通过 Grafana → Explore → 选择 Loki 数据源

查询示例:

# 在 Grafana Explore 中使用 LogQL 查询:

# 查看所有 data namespace 的日志
{namespace="data"}

# 查看 PostgreSQL 日志
{namespace="data", pod=~"postgres-.*"}

# 查看包含错误的日志
{namespace="data"} |= "error"

# 按时间范围查询
{namespace="data"} | json | level="error"

Harbor(镜像仓库,L0 层宿主机)

项目 值
Web UI https://harbor.omniverseai.net
用户名 根据 Harbor 部署配置
密码 根据 Harbor 部署配置
Docker 登录 docker login harbor.omniverseai.net

Gitea(代码仓库,L0 层宿主机)

项目 值
Web UI https://gitea.omniverseai.net
用户名 根据 Gitea 配置
密码 根据 Gitea 配置

快速访问命令

# 一键打开所有端口转发
cat > /tmp/port-forward-all.sh << 'EOF'
#!/bin/bash
kubectl port-forward -n data svc/postgres-postgresql 5432:5432 &
kubectl port-forward -n data svc/redis-master 6379:6379 &
kubectl port-forward -n observability svc/monitoring-grafana 3000:80 &
kubectl port-forward -n observability svc/monitoring-kube-prometheus-prometheus 9090:9090 &
kubectl port-forward -n observability svc/monitoring-kube-prometheus-alertmanager 9093:9093 &
echo "所有端口转发已启动!"
echo "PostgreSQL: localhost:5432 (appuser/appuser123)"
echo "Redis: localhost:6379 (密码: redis123)"
echo "Grafana: http://localhost:3000 (admin/admin123)"
echo "Prometheus: http://localhost:9090"
echo "AlertManager: http://localhost:9093"
echo ""
echo "按 Ctrl+C 停止所有端口转发"
wait
EOF

chmod +x /tmp/port-forward-all.sh
/tmp/port-forward-all.sh

组件说明

L1: 核心层

ingress-nginx

  • 作用:统一的 HTTP/HTTPS 入口,负责路由流量到各业务服务
  • 监听端口:30080(HTTP)、30443(HTTPS)
  • 配置文件:values/ingress-nginx-values.yaml
  • 关键特性:
    • 使用 hostNetwork 模式,直接监听宿主机端口
    • 支持大文件上传(100MB)
    • 自动暴露 metrics 给 Prometheus

验证:

# 检查服务状态
kubectl get pods -n infra

# 测试本地访问(应返回 404)
curl http://127.0.0.1:30080

# 从 Contabo 测试(需先配置 WireGuard)
curl http://10.7.0.2:30080

L2: 数据服务层

PostgreSQL

  • 作用:统一的关系型数据库,支持多业务
  • 配置文件:values/postgres-values.yaml
  • 连接信息:
    • 主机:postgres-postgresql.data.svc.cluster.local
    • 端口:5432
    • 管理员用户:postgres / admin123
    • 应用用户:appuser / appuser123

预置数据库:

  • health_db:健康平台
  • stock_db:股票推荐
  • learn_db:学习助手
  • ai_db:AI 服务

连接示例:

# 从集群内连接
kubectl run -it --rm psql --image=postgres:15 --restart=Never -- \
  psql -h postgres-postgresql.data.svc.cluster.local \
       -U appuser -d health_db

# 端口转发到本地
kubectl port-forward -n data svc/postgres-postgresql 5432:5432

# 使用本地工具连接
psql -h localhost -U appuser -d health_db

Redis

  • 作用:统一的缓存、Session 存储、简单队列
  • 配置文件:values/redis-values.yaml
  • 连接信息:
    • 主机:redis-master.data.svc.cluster.local
    • 端口:6379
    • 密码:redis123

DB 分配:

  • DB 0:健康平台
  • DB 1:股票推荐
  • DB 2:学习助手
  • DB 3:AI 服务
  • DB 4-15:预留

连接示例:

# 从集群内连接
kubectl run -it --rm redis-cli --image=redis:7 --restart=Never -- \
  redis-cli -h redis-master.data.svc.cluster.local -a redis123

# 端口转发到本地
kubectl port-forward -n data svc/redis-master 6379:6379

# 使用本地 redis-cli 连接
redis-cli -h localhost -a redis123

MySQL(可选)

  • 作用:仅在有历史项目或三方依赖时安装
  • 配置文件:values/mysql-values.yaml
  • 连接信息:
    • 主机:mysql.data.svc.cluster.local
    • 端口:3306
    • 用户:appuser / appuser123

L3: 可观测性层

Prometheus + Grafana

  • 作用:监控所有 k8s 资源和业务指标
  • 配置文件:values/kube-prometheus-stack-values.yaml

Grafana 访问:

# 方式 1:域名访问(需配置 DNS 和 Ingress)
# https://monitor.omniverseai.net

# 方式 2:端口转发
kubectl port-forward -n observability svc/monitoring-grafana 3000:80

# 访问 http://localhost:3000
# 用户名:admin
# 密码:admin123

预置 Dashboard:

  • Kubernetes Cluster Overview(ID: 7249)
  • Node Exporter(ID: 1860)
  • Ingress Nginx(ID: 9614)

Loki + Promtail

  • 作用:采集和查询所有 Pod 日志
  • 配置文件:values/loki-values.yaml
  • 访问:通过 Grafana 的 Explore 功能

查询日志示例:

# 在 Grafana 中切换到 Loki 数据源,使用 LogQL 查询:

# 查看某个 namespace 的日志
{namespace="data"}

# 查看某个 Pod 的日志
{namespace="data", pod="postgres-postgresql-0"}

# 查看包含错误的日志
{namespace="data"} |= "error"

# 查看特定容器的日志
{namespace="data", container="postgresql"}

业务应用接入

1. 创建业务 Namespace

# 以健康平台为例
kubectl create namespace health

2. 部署应用

使用 Helm 或直接 apply YAML:

# health-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: health-api
  namespace: health
spec:
  replicas: 2
  selector:
    matchLabels:
      app: health-api
  template:
    metadata:
      labels:
        app: health-api
    spec:
      containers:
      - name: api
        image: harbor.omniverseai.net/health/api:latest
        env:
        - name: DATABASE_URL
          value: postgresql://appuser:[email protected]:5432/health_db
        - name: REDIS_URL
          value: redis://:[email protected]:6379/0
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: health-api
  namespace: health
spec:
  selector:
    app: health-api
  ports:
  - port: 80
    targetPort: 8080

3. 配置 Ingress

# health-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: health-ingress
  namespace: health
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"  # 如有 cert-manager
spec:
  ingressClassName: nginx
  rules:
  - host: health.omniverseai.net
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: health-api
            port:
              number: 80
  tls:
  - hosts:
    - health.omniverseai.net
    secretName: health-tls

4. 在 Contabo 配置反向代理

在 Contabo 的 Nginx 配置中添加:

# /etc/nginx/sites-available/health.omniverseai.net
server {
    listen 80;
    server_name health.omniverseai.net;

    location / {
        proxy_pass http://10.7.0.2:30080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

运维操作

查看资源状态

# 查看所有 Pod
kubectl get pods -A

# 查看所有 Service
kubectl get svc -A

# 查看所有 Ingress
kubectl get ingress -A

# 查看存储
kubectl get pvc -A

查看日志

# 查看 Pod 日志
kubectl logs -n data postgres-postgresql-0

# 实时查看日志
kubectl logs -n data postgres-postgresql-0 -f

# 查看前一个容器的日志(容器崩溃时)
kubectl logs -n data postgres-postgresql-0 --previous

备份和恢复

PostgreSQL 备份

# 备份单个数据库
kubectl exec -n data postgres-postgresql-0 -- \
  pg_dump -U appuser health_db > health_db_backup.sql

# 备份所有数据库
kubectl exec -n data postgres-postgresql-0 -- \
  pg_dumpall -U postgres > all_databases_backup.sql

Redis 备份

# 手动触发持久化
kubectl exec -n data redis-master-0 -- redis-cli -a redis123 BGSAVE

# 复制 RDB 文件
kubectl cp data/redis-master-0:/data/dump.rdb ./redis_backup.rdb

更新配置

修改 values/*.yaml 文件后,重新部署:

# 更新 ingress-nginx
helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
  -n infra \
  -f values/ingress-nginx-values.yaml

# 更新 Postgres
helm upgrade postgres bitnami/postgresql \
  -n data \
  -f values/postgres-values.yaml

扩缩容

# 扩容 Deployment
kubectl scale deployment -n health health-api --replicas=5

# 查看 HPA(如已配置)
kubectl get hpa -n health

故障排查

ingress-nginx 无法访问

# 检查 Pod 状态
kubectl get pods -n infra

# 查看日志
kubectl logs -n infra -l app.kubernetes.io/name=ingress-nginx

# 检查端口监听
ss -tlnp | grep 30080

# 测试内部访问
kubectl run -it --rm curl --image=curlimages/curl --restart=Never -- \
  curl http://ingress-nginx-controller.infra.svc.cluster.local

数据库连接失败

# 检查 Pod 状态
kubectl get pods -n data

# 查看详细信息
kubectl describe pod -n data postgres-postgresql-0

# 检查 Service
kubectl get svc -n data

# 测试 DNS 解析
kubectl run -it --rm busybox --image=busybox --restart=Never -- \
  nslookup postgres-postgresql.data.svc.cluster.local

Prometheus/Grafana 无法访问

# 检查 Pod 状态
kubectl get pods -n observability

# 查看 Grafana 日志
kubectl logs -n observability -l app.kubernetes.io/name=grafana

# 重置 Grafana 密码
kubectl exec -n observability -it \
  $(kubectl get pod -n observability -l app.kubernetes.io/name=grafana -o name) -- \
  grafana-cli admin reset-admin-password newpassword

重新初始化

如果需要完全重置:

方式 1:删除 Helm Releases

# 删除所有组件
helm uninstall loki -n observability
helm uninstall monitoring -n observability
helm uninstall mysql -n data  # 如已安装
helm uninstall redis -n data
helm uninstall postgres -n data
helm uninstall ingress-nginx -n infra

# 删除 PVC(会删除数据!)
kubectl delete pvc -n data --all
kubectl delete pvc -n observability --all

# 删除 namespace
kubectl delete namespace infra data observability

# 重新运行初始化脚本
./init-orbstack-k8s-infra.sh

方式 2:重置 OrbStack k8s

在 OrbStack UI 中:

  1. 停止 Kubernetes
  2. 选择 Reset / Recreate Cluster
  3. 重新启动 Kubernetes
  4. 运行初始化脚本
./init-orbstack-k8s-infra.sh

扩展功能

添加 cert-manager(自动 TLS 证书)

# 安装 cert-manager
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.yaml

# 创建 Let's Encrypt Issuer
kubectl apply -f - <<EOF
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: [email protected]
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
    - http01:
        ingress:
          class: nginx
EOF

添加本地路径存储(如需)

# 安装 local-path-provisioner
kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/v0.0.24/deploy/local-path-storage.yaml

# 设为默认 StorageClass
kubectl patch storageclass local-path -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

安全建议

生产环境务必修改以下默认密码:

  1. PostgreSQL:postgres-values.yaml 中的 postgresPassword 和 password
  2. Redis:redis-values.yaml 中的 password
  3. MySQL:mysql-values.yaml 中的 rootPassword 和 password
  4. Grafana:kube-prometheus-stack-values.yaml 中的 adminPassword

建议使用 Kubernetes Secret 管理密码:

# 创建 Secret
kubectl create secret generic postgres-secret \
  -n data \
  --from-literal=postgres-password='strong-password-here' \
  --from-literal=password='strong-password-here'

# 在 values.yaml 中引用
# existingSecret: postgres-secret

资源需求

最小配置

  • CPU:4 核
  • 内存:8 GB
  • 存储:100 GB

推荐配置(Mac Studio 已满足)

  • CPU:8+ 核
  • 内存:16+ GB
  • 存储:500 GB SSD

文件结构

orbstack-k8s-infra/
├── README.md                               # 本文档
├── init-orbstack-k8s-infra.sh             # 一键初始化脚本
├── values/                                 # Helm values 配置
│   ├── ingress-nginx-values.yaml
│   ├── postgres-values.yaml
│   ├── redis-values.yaml
│   ├── mysql-values.yaml
│   ├── kube-prometheus-stack-values.yaml
│   └── loki-values.yaml
├── scripts/                                # 辅助脚本(预留)
└── docs/                                   # 文档目录(预留)

常见问题

Q: 为什么选择 OrbStack 而不是 k3s?

A: OrbStack 自带的 k8s 对 Mac 集成度更好,资源占用更少,且已经满足开发环境需求。k3s 可以作为备选方案。

Q: 能否在生产环境使用这套方案?

A: 不建议。这套方案是为开发/测试环境设计的单节点部署。生产环境建议使用:

  • 多节点 k8s 集群(3+ master,多 worker)
  • 托管 k8s 服务(如 EKS、GKE、AKS)
  • 数据库使用云服务或专业 DBA 管理

Q: 如何备份整个集群?

A: 可以使用 Velero 进行集群级别的备份:

# 安装 Velero
brew install velero

# 配置备份到本地或云存储
velero install --provider aws --bucket my-backup-bucket ...

Q: 如何监控资源使用?

A: 通过 Grafana Dashboard:

  1. 访问 Grafana(http://localhost:3000)
  2. 导入 Dashboard ID: 7249(Kubernetes Cluster)
  3. 查看 CPU、内存、存储、网络使用情况

参考链接

贡献

欢迎提交 Issue 和 Pull Request!

许可证

MIT License


作者:Bruno Gao 更新时间:2025-01-22

S
Description
No description provided
Readme
105 KiB
Languages
Shell 100%