Re-structure

This commit is contained in:
Yaojia Wang
2026-03-21 11:31:31 +01:00
parent e61baf7e4e
commit cdba2497a7
30 changed files with 299 additions and 251 deletions

View File

@@ -0,0 +1,334 @@
---
created: "2026-03-10"
type: resource
tags: [resource, infrastructure, homelab, kubernetes, ci-cd, gitops]
source: "HomeLab 部署实践"
---
# HomeLab 基础设施文档
## 网络拓扑概览
```
[NAS (192.168.68.x)] ── Gitea (Docker), AdGuard Home (DNS)
|
[192.168.68.x 内网]
|
[K8s Cluster]
├── k8s-cp1 (Control Plane) ── 192.168.68.11
├── k8s-w1 (Worker) ── 192.168.68.21
└── k8s-w2 (Worker) ── 192.168.68.22
├── Docker Registry ── NodePort 30500
├── Drone CI ── NodePort 30344 (webhook), Ingress drone.k8s.home
├── ArgoCD ── Ingress argocd.k8s.home
├── ingress-nginx ── LoadBalancer 192.168.68.240
└── 应用 (invest-api 等)
```
## DNS (AdGuard Home)
DNS 服务器: `192.168.68.63`
### DNS 重写规则
| 域名 | IP | 说明 |
|------|-----|------|
| `invest-api.k8s.home` | 192.168.68.240 | OpenBB 投资分析 API |
| `drone.k8s.home` | 192.168.68.240 | Drone CI |
| `argocd.k8s.home` | 192.168.68.240 | ArgoCD |
注意: 所有 `*.k8s.home` 域名都应指向 ingress-nginx 的 LoadBalancer IP `192.168.68.240`(由 MetalLB 分配),而不是节点 IP。
### K8s 节点网络配置
K8s 节点 DNS 使用 `8.8.8.8`(绕过 OpenClash fake-ip否则会导致 ImagePullBackOff。
网关统一指向 `192.168.68.63`iStoreOS 主网关)。
OpenClash 配置了 `SRC-IP-CIDR` 规则让三个节点流量直连。
配置文件: `/etc/netplan/50-cloud-init.yaml`(每个节点)
## 已部署应用
| 应用 | URL | 命名空间 | 说明 |
|------|-----|----------|------|
| OpenBB Invest API | `https://invest-api.k8s.home` | invest-api | 投资分析 REST API50 端点)|
| Drone CI | `https://drone.k8s.home` | drone | CI/CD |
| ArgoCD | `https://argocd.k8s.home` | argocd | GitOps 部署 |
| Swagger UI | `https://invest-api.k8s.home/docs` | invest-api | API 文档 |
## Kubernetes 集群
### 节点信息
| 节点 | 角色 | IP | 说明 |
|------|------|----|------|
| k8s-cp1 | Control Plane | 192.168.68.11 | API Server, etcd, scheduler |
| k8s-w1 | Worker | 192.168.68.21 | 应用负载 |
| k8s-w2 | Worker | 192.168.68.22 | 应用负载 |
### 集群组件
| 组件 | 版本/说明 |
|------|----------|
| Kubernetes | v1.35.0 |
| 容器运行时 | containerd 1.7.28 |
| CNI | 默认 |
| 负载均衡 | MetalLB (分配 IP: 192.168.68.240) |
| Ingress | ingress-nginx (External IP: 192.168.68.240) |
| 存储 | Proxmox CSI |
| 证书管理 | cert-manager |
### kubeconfig
- API Server: `https://192.168.68.11:6443`
- 认证方式: 证书认证 (admin 用户)
- 本地配置: `C:\Users\yaoji\.kube\config`
- 获取方式: 从 Control Plane `/etc/kubernetes/admin.conf` 拷贝
### 已部署命名空间
| 命名空间 | 用途 |
|----------|------|
| argocd | ArgoCD GitOps |
| drone | Drone CI/CD |
| registry | Docker Registry |
| ingress-nginx | Ingress 控制器 |
| cert-manager | TLS 证书管理 |
| metallb-system | 负载均衡 |
| csi-proxmox / proxmox-csi | 存储 |
| invest-api | OpenBB 投资分析 API |
---
## Git 服务 (Gitea)
| 项目 | 值 |
|------|-----|
| 部署位置 | NAS Docker |
| URL | `https://git.colacoder.com` |
| SSH | `ssh://git@git.colacoder.com:2200/` |
| 管理员用户 | kai |
| 邮箱 | wangyaojia@gmail.com |
### Gitea 配置注意事项
`app.ini` 中需要的配置:
```ini
[webhook]
ALLOWED_HOST_LIST = private
SKIP_TLS_VERIFY = true
```
- `ALLOWED_HOST_LIST = private` — 允许 webhook 发送到内网地址
- `SKIP_TLS_VERIFY = true` — 允许连接自签名证书的服务
- 修改后需要重启 Gitea 容器
### 仓库列表
| 仓库 | 用途 |
|------|------|
| kai/openbb-invest-api | OpenBB 投资分析 API |
---
## CI/CD (Drone CI)
### 部署信息
| 项目 | 值 |
|------|-----|
| 命名空间 | drone |
| 版本 | 2.12.1 |
| Ingress | `https://drone.k8s.home` |
| Runner 类型 | Kubernetes Runner |
| Runner 容量 | 4 并发 |
### 访问方式
| 方式 | 地址 |
|------|------|
| Web UI | `https://drone.k8s.home` |
| Webhook (给 Gitea 用) | `http://192.168.68.21:30344/hook` |
| API | `http://192.168.68.21:30344/api/` |
| API Token | `c7hDypuu5p41r5k6svR0x6QomInqrE6f` |
### Drone Server 配置 (ConfigMap: drone)
| 键 | 值 |
|-----|-------|
| DRONE_GITEA_SERVER | `https://git.colacoder.com/` |
| DRONE_GITEA_CLIENT_ID | `c95249a5-9cad-4813-89b4-3f4f9f7d3cee` |
| DRONE_SERVER_HOST | drone.k8s.home |
| DRONE_SERVER_PROTO | https |
| DRONE_USER_CREATE | username:kai,admin:true |
### Drone Runner 配置 (ConfigMap: drone-runner-drone-runner-kube)
| 键 | 值 |
|-----|-------|
| DRONE_RPC_HOST | drone.drone.svc.cluster.local:8080 |
| DRONE_RPC_PROTO | http |
| DRONE_NAMESPACE_DEFAULT | drone |
| DRONE_RUNNER_CAPACITY | 4 |
### RBAC
Runner ServiceAccount (`drone:drone-runner-drone-runner-kube`) 需要在 `drone` namespace 有以下权限:
- secrets: create, delete
- pods, pods/log: get, create, delete, list, watch, update
Helm 安装时 RBAC 错误地创建在 `default` namespace需要手动在 `drone` namespace 创建 Role 和 RoleBinding。
### Gitea Webhook 配置
| 项目 | 值 |
|------|-----|
| Target URL | `http://192.168.68.21:30344/hook` |
| Content Type | application/json |
| Secret | `KE0HQksXhJ53ojiLwgAIp0JC4QCl1NsE` |
| Events | Push |
注意: Drone 无法自动在 Gitea 创建 webhookOAuth 权限问题),需要手动创建。
### Pipeline 模板 (.drone.yml)
使用 kaniko 构建Kubernetes Runner 不支持 privileged 模式的 `plugins/docker`:
```yaml
kind: pipeline
type: kubernetes
name: build-and-push
trigger:
branch: [main, develop]
event: [push, custom]
steps:
- name: build-and-push
image: gcr.io/kaniko-project/executor:debug
commands:
- >
/kaniko/executor
--context=/drone/src
--dockerfile=Dockerfile
--destination=192.168.68.11:30500/IMAGE_NAME:${DRONE_COMMIT_SHA:0:8}
--destination=192.168.68.11:30500/IMAGE_NAME:latest
--insecure
--skip-tls-verify
```
---
## Docker Registry
| 项目 | 值 |
|------|-----|
| 命名空间 | registry |
| 镜像 | registry:2 |
| Service | NodePort 30500 |
| 存储 | PVC 10Gi |
| 访问地址 | `http://192.168.68.11:30500` |
| 基础设施仓库 | `C:\Users\yaoji\git\ColaCoder\k8s-infra\registry\` |
### Registry API
```bash
# 查看所有镜像
curl http://192.168.68.11:30500/v2/_catalog
# 查看镜像 tags
curl http://192.168.68.11:30500/v2/IMAGE_NAME/tags/list
```
### Worker 节点 containerd 配置
两个 Worker 节点 `/etc/containerd/config.toml` 中添加:
```toml
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."192.168.68.11:30500"]
endpoint = ["http://192.168.68.11:30500"]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.registry.svc.cluster.local:5000"]
endpoint = ["http://registry.registry.svc.cluster.local:5000"]
```
修改后需要 `sudo systemctl restart containerd`。Control Plane 不需要配置。
### 本地 Docker Desktop 配置
`C:\Users\yaoji\.docker\daemon.json`:
```json
{
"insecure-registries": ["192.168.68.11:30500"]
}
```
修改后需要重启 Docker Desktop。
---
## ArgoCD
| 项目 | 值 |
|------|-----|
| 命名空间 | argocd |
| 同步策略 | 自动 (prune + selfHeal) |
| CreateNamespace | true |
### 已注册应用
| 应用 | 源仓库 | 路径 | 分支 | 目标命名空间 |
|------|--------|------|------|-------------|
| invest-api | `https://git.colacoder.com/kai/openbb-invest-api.git` | k8s/base | main | invest-api |
---
## 完整部署流程 (GitOps)
```
开发者 git push
Gitea 接收代码
↓ (webhook)
Drone CI 触发构建
↓ (kaniko)
Docker 镜像推送到 Registry (192.168.68.11:30500)
ArgoCD 检测 k8s manifest 变化
↓ (自动同步)
K8s 拉取镜像并部署
```
---
## 踩坑记录
### Gitea Webhook
1. **webhook 被拒**: Gitea 默认不允许发送 webhook 到内网地址,需要 `ALLOWED_HOST_LIST = private`
2. **TLS 验证失败**: 内网自签名证书需要 `SKIP_TLS_VERIFY = true`
3. **403 Forbidden**: Drone OAuth2 应用丢失需要重新创建webhook 手动创建时需要填写正确的 secret
### Drone CI
1. **Runner 无法连接 Server**: Service 端口 8080 但 Runner 连的默认 80需要在 `DRONE_RPC_HOST``:8080`
2. **手动触发无反应**: `.drone.yml` trigger event 需要包含 `custom`
3. **RBAC 权限不足**: Helm 把 Role 创建在 `default` namespace需要手动在 `drone` namespace 创建
4. **不能用 plugins/docker**: Kubernetes Runner 不支持 privileged 模式,改用 kaniko
### Docker 镜像
1. **OpenBB 需要 home 目录**: `nobody` 用户没有 home需要创建 `appuser` 并预建 `.openbb_platform` 目录
2. **OpenBB 需要写入 site-packages**: 启动时写 `.build.lock`,需要 `chown -R appuser:appuser /usr/local/lib/python3.12/site-packages/openbb`
### DNS / Ingress
1. **Ingress IP 不是节点 IP**: `*.k8s.home` 域名必须指向 MetalLB 分配的 LoadBalancer IP (`192.168.68.240`),不是节点 IP (`192.168.68.22`)
---
## Related
- [[OpenBB Invest API - K8s Infrastructure]]
- [[OpenBB Invest API]]

View File

@@ -0,0 +1,140 @@
---
created: "2026-03-09"
type: resource
tags: [resource, kubernetes, infrastructure, devops, drone-ci, argocd, docker-registry, homelab]
source: "openbb-invest-api 项目部署实践"
---
# OpenBB Invest API - K8s 基础设施
## 概述
OpenBB Invest API 的完整 Kubernetes 部署架构包含集群信息、CI/CD 流水线和 GitOps 配置。
## 集群
| 节点 | 角色 | IP |
|------|------|----|
| k8s-cp1 | control-plane | 192.168.68.11 |
| k8s-w1 | worker | 192.168.68.21 |
| k8s-w2 | worker | 192.168.68.22 |
- Kubernetes v1.35.0
- 容器运行时: containerd 1.7.28
- 负载均衡: MetalLB
- Ingress: ingress-nginx
- 存储: Proxmox CSI
- 证书管理: cert-manager
## kubeconfig
- 位置: `C:\Users\yaoji\.kube\config`
- 认证: 证书认证 (admin 用户)
- API server: `https://192.168.68.11:6443`
## Docker Registry
- 命名空间: `registry`
- 镜像: `registry:2`
- 服务: NodePort 30500
- 持久卷: 10Gi
- 访问地址: `http://192.168.68.11:30500`
- 基础设施仓库: `C:\Users\yaoji\git\ColaCoder\k8s-infra\registry\`
### Worker 节点 containerd 配置
两个 worker 节点的 `/etc/containerd/config.toml`:
```toml
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."192.168.68.11:30500"]
endpoint = ["http://192.168.68.11:30500"]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.registry.svc.cluster.local:5000"]
endpoint = ["http://registry.registry.svc.cluster.local:5000"]
```
Control plane 不需要配置(有 taintpod 不会调度到上面)。
## Drone CI
- 命名空间: `drone`
- Server: 容器端口 80Service 端口 8080
- Runner: Kubernetes runner容量 4
- Ingress: `drone.k8s.home`
### Runner ConfigMap
| 键 | 值 |
|-----|-------|
| DRONE_RPC_HOST | drone.drone.svc.cluster.local:8080 |
| DRONE_RPC_PROTO | http |
| DRONE_NAMESPACE_DEFAULT | drone |
### 流水线 (.drone.yml)
使用 kaniko 构建k8s runner 不支持 privileged 模式):
```yaml
kind: pipeline
type: kubernetes
name: build-and-push
trigger:
branch: [main, develop]
event: [push, custom]
steps:
- name: build-and-push
image: gcr.io/kaniko-project/executor:debug
commands:
- /kaniko/executor
--context=/drone/src
--dockerfile=Dockerfile
--destination=192.168.68.11:30500/invest-api:${DRONE_COMMIT_SHA:0:8}
--destination=192.168.68.11:30500/invest-api:latest
--insecure --skip-tls-verify
```
## ArgoCD
- 命名空间: `argocd`
- Application: `invest-api`
- 源仓库: `https://git.colacoder.com/kai/openbb-invest-api.git`,路径 `k8s/base`
- 目标分支: `main`,命名空间 `invest-api`
- 同步策略: 自动prune + selfHeal + CreateNamespace
## Gitea
- URL: `https://git.colacoder.com`
- 仓库: `kai/openbb-invest-api`
- SSH: `ssh://git@git.colacoder.com:2200/kai/openbb-invest-api.git`
## 部署流程
1. `git push` 到 Giteamain/develop 分支)
2. Gitea webhook 触发 Drone CI
3. Drone/kaniko 构建 Docker 镜像并推送到 `192.168.68.11:30500`
4. ArgoCD 检测 `k8s/base/` 中的 manifest 变化并自动同步
5. k8s 从 registry 拉取镜像并部署
## invest-api K8s Manifests (k8s/base/)
- 命名空间: `invest-api`
- Deployment: 镜像 `192.168.68.11:30500/invest-api:latest`100m-500m CPU256Mi-512Mi 内存,健康检查 `/health:8000`
- Service: ClusterIP 端口 8000
- Secret: `invest-api-secrets`(可选,用于 API 密钥)
## 本地 Docker Desktop
`C:\Users\yaoji\.docker\daemon.json`:
```json
{"insecure-registries": ["192.168.68.11:30500"]}
```
## 踩坑记录
- **Drone Runner RPC 连接超时**: Runner 默认连接端口 80但 Service 暴露的是 8080。通过 patch configmap 添加 `:8080` 修复。
- **Drone 手动触发无反应**: UI 手动触发发送的 event 是 `custom`,需要在 `.drone.yml` trigger 中添加 `custom` event。
- **kubeconfig 传输损坏**: 通过聊天传输 RSA 私钥会被截断/损坏,需要通过 SSH 直接传输文件。
## Related
- [[OpenBB Invest API]]