opswarden-git/opswarden-ops

GitHub: opswarden-git/opswarden-ops

OpsWarden 平台的基础设施仓库,通过 Terraform 和 Kubernetes 在 DigitalOcean 上实现端到端可重现的生产部署。

Stars: 0 | Forks: 0

OpsWarden # OpsWarden — Ops

Ops CI Release License: Apache 2.0 Status: baseline


[![Kubernetes](https://img.shields.io/badge/Kubernetes-326CE5?style=for-the-badge&logo=kubernetes&logoColor=white)](https://kubernetes.io/) [![Terraform](https://img.shields.io/badge/Terraform-7B42BC?style=for-the-badge&logo=terraform&logoColor=white)](https://www.terraform.io/) [![Traefik](https://img.shields.io/badge/Traefik-24A1C1?style=for-the-badge&logo=traefikproxy&logoColor=white)](https://traefik.io/) [![DigitalOcean](https://img.shields.io/badge/DigitalOcean-0080FF?style=for-the-badge&logo=digitalocean&logoColor=white)](https://www.digitalocean.com/) [![Nix](https://img.shields.io/badge/Nix-5277C3?style=for-the-badge&logo=nixos&logoColor=white)](https://nixos.org/)

Reference cluster topology 参考集群拓扑 — 将由 OpsWarden 自己的图表替换。

## 关于 `opswarden-ops` 是 OpsWarden 的**基础设施与部署**仓库: 部署在 **DigitalOcean (DOKS)** 上的 Kubernetes,端到端由 **Terraform** 配置,由 **Traefik** 进行路由,并通过 **Nix** 提供可重现的开发环境。 它**独立于产品**(`opswarden-app`)且**有意设计为可选**: OpsWarden 只需运行一次 `docker compose up` 即可启动。本仓库是**作品集云展示** — 它绝不应成为运行该产品的前提条件。 ## 项目结构 ``` opswarden-ops/ │ ├── k8s/ │ ├── server/ # OpsWarden server (Rust/Axum) + HPA/PDB — manifest ready │ ├── client-web/ # Next.js client + ingress — manifest ready │ ├── postgres/ # PostgreSQL + encrypted off-cluster backups │ ├── redis/ # Redis — ready │ ├── traefik/ # ingress controller & LB (+ IngressClass, PDB) — ready │ └── observability/ # cAdvisor (+ prom/grafana/loki) — partial │ ├── terraform/ # DOKS cluster provisioning (main/outputs/providers/variables.tf) ├── scripts/ # smoke.sh, load.sh, soft-affinity.sh (ops helpers) ├── Makefile # single runner: provision → deploy → harden → verify → destroy + fmt/validate/lint ├── flake.nix / flake.lock # Nix dev shell (kubectl, terraform, k9s, helm…) ├── .env # API tokens (git-ignored) ├── LICENSE / NOTICE # Apache-2.0 └── README.md ``` ## 服务 | 服务 | 技术 | 状态 | | -------------- | :-----------------------------------------------------------------------------: | -------------------------------------- | | **server** | Rust / Axum | 本地已验证 — 待发布 | | **client-web** | Next.js | 本地已验证 — 待发布/TLS 配置 | | **PostgreSQL** | PostgreSQL 18 | 本地已验证 — 备份自动化 | | **Redis** | Redis 8 | 就绪 — 不可变镜像 | | **Traefik** | Traefik 3.7 | 就绪 — 不可变镜像 | | **cAdvisor** | monitoring | 就绪 — `k8s/observability/` | 多副本服务使用 **preferred pod anti-affinity** 以实现跨节点分布。 共享配置存在于 **ConfigMaps** 中;在正式部署前,凭据通过 SOPS 加密的 **Secrets** 提供。 ## 参考部署 可重用的技术栈已在 **DigitalOcean Kubernetes (DOKS)** 上得到**验证** — 这是一个由 Terraform 在 `fra1` 区域端到端配置的 2 节点池 (`s-2vcpu-4gb`)。下方的截图来自该参考运行;OpsWarden 自己的截图将在应用部署后替换掉应用层级的截图。
**Node pool — 2 / 2 节点运行中** DOKS node pool status — 2/2 running

**Worker pool 详情 — 由 Terraform 配置并打标签** Worker pool nodes running on DigitalOcean

**集群洞察 — CPU、负载、内存、磁盘及 I/O** DigitalOcean cluster insights graphs

**Traefik — 路由与服务健康,`:80` / `:8080` 成功率 100%** Traefik dashboard — routers and services healthy
## 安装与配置 ### 前置条件 - [Nix](https://nixos.org/download.html) 包管理器 - 拥有 API token 的 [DigitalOcean](https://www.digitalocean.com/) 账户 - 启用了版本控制的 DigitalOcean Spaces bucket 以及用于 Terraform state 的受限访问密钥 - [Git](https://git-scm.com/) ### 1 — 克隆并进入环境 ``` git clone git@github.com:opswarden-git/opswarden-ops.git && cd opswarden-ops cp .env.example .env # add credentials and a reviewed TF_VAR_kubernetes_version nix develop # loads kubectl, terraform, k9s, helm… ``` ### 2 — 初始化远程 state 并配置集群 ``` cp terraform/backend.hcl.example terraform/backend.hcl # 使用 bucket 和 Spaces region 编辑本地的 git 忽略文件 backend.hcl。 # AWS_ACCESS_KEY_ID 和 AWS_SECRET_ACCESS_KEY 从 .env 中加载。 make infra TF_BACKEND_CONFIG=terraform/backend.hcl export KUBECONFIG=$(pwd)/kubeconfig ``` 后端使用 Spaces S3 兼容 API 以及原生的 Terraform lockfiles。 在首次 apply 之前请启用 bucket 版本控制。如果本地 state 已存在, `make backend-init` 会停止并打印出明确的迁移命令,而不会 默默地将其丢弃。 ### 3 — 引导 Secrets (SOPS) ``` # 1. 将你的私有 age key 提供给 SOPS export SOPS_AGE_KEY_FILE=~/.config/sops/age/keys.txt # 2. 显式选择你的目标环境 export EXPECTED_CONTEXT=minikube export NAMESPACE=opswarden # 3. 根据目标集群验证解密的 secret make secrets-dry-run \ EXPECTED_CONTEXT="$EXPECTED_CONTEXT" \ NAMESPACE="$NAMESPACE" # 4. 将解密的 secret 应用到集群 make secrets-apply \ EXPECTED_CONTEXT="$EXPECTED_CONTEXT" \ NAMESPACE="$NAMESPACE" \ CONFIRM=APPLY_POSTGRES_SECRET ``` ### 4 — 部署基础设施层 ``` make deploy \ EXPECTED_CONTEXT="$EXPECTED_CONTEXT" \ NAMESPACE="$NAMESPACE" ``` ### 5 — 部署常规应用后端 这种常规的生产环境拆分是有意为之:`client-web` 运行在 Vercel 上的 `app.opswarden.dev`;Rust、PostgreSQL、Redis 和 Traefik 运行在 DOKS 上。请先创建 由 SOPS 管理的 `opswarden-server-secret`。生产环境仅接受 不可变的服务器摘要和 HTTPS 源。 ``` make deploy-server \ EXPECTED_CONTEXT="$EXPECTED_CONTEXT" \ NAMESPACE="$NAMESPACE" \ SERVER_IMAGE="ghcr.io/opswarden-git/opswarden-server@sha256:" \ PUBLIC_ORIGIN="https://app.opswarden.dev" \ API_ORIGIN="https://api.opswarden.dev" ``` 使用根目录 `client-web` 配置 Vercel 项目, `OPSWARDEN_API_ORIGIN=https://api.opswarden.dev`,以及 `NEXT_PUBLIC_WS_URL=wss://api.opswarden.dev`。已提交至仓库的 Kubernetes web Deployment 是一条通过 `make deploy-self-hosted-web` 暴露的可选自托管路径; 它不属于生产环境 CD 的一部分。 ### 6 — 启用公共 TLS 在负载均衡器地址已知且 `api.opswarden.dev` 指向该地址之后: ``` make tls \ EXPECTED_CONTEXT="$EXPECTED_CONTEXT" \ NAMESPACE="$NAMESPACE" \ ACME_EMAIL="ops@example.com" \ CONFIRM=ENABLE_PUBLIC_TLS ``` ### 7 — 启用加密的集群外备份 根据示例创建并使用 SOPS 加密 `k8s/postgres/postgres-backup.secret.sops.yaml`。 其 rclone crypt 密码必须独立于数据库凭据。 ``` make secret-apply \ SECRET_FILE=k8s/postgres/postgres-backup.secret.sops.yaml \ EXPECTED_CONTEXT="$EXPECTED_CONTEXT" NAMESPACE="$NAMESPACE" \ CONFIRM=APPLY_SOPS_SECRET make backup-enable \ EXPECTED_CONTEXT="$EXPECTED_CONTEXT" NAMESPACE="$NAMESPACE" \ BACKUP_BUCKET="opswarden-backups" \ BACKUP_ENDPOINT="https://fra1.digitaloceanspaces.com" \ CONFIRM=ENABLE_BACKUPS # 验证上传、解密以及独立的 PostgreSQL 恢复。 make backup-run EXPECTED_CONTEXT="$EXPECTED_CONTEXT" NAMESPACE="$NAMESPACE" make backup-verify \ EXPECTED_CONTEXT="$EXPECTED_CONTEXT" NAMESPACE="$NAMESPACE" \ CONFIRM=VERIFY_LATEST_BACKUP ``` ### 8 — 配置受保护的生产环境交付 创建一个名为 `production` 的 GitHub 环境,启用必需的审查者并 定义: - secret `KUBE_CONFIG_B64`:base64 编码的、最小权限的生产环境 kubeconfig; - variable `KUBE_CONTEXT`:该 kubeconfig 中的确切 context 名称; - variable `KUBE_NAMESPACE`:应用 namespace; - variable `FRONTEND_ORIGIN`:`https://app.opswarden.dev`; - variable `API_ORIGIN`:`https://api.opswarden.dev`。 在 `main` 分支上使用服务器 GHCR 摘要和字面确认 `DEPLOY_PRODUCTION` 运行 **Deploy production**。如果启用了备份,工作流会在发布前 进行一次备份。如果发布失败或 API/WebSocket 冒烟测试失败,将恢复之前的 服务器镜像。Vercel 拥有其自己的部署和回滚历史记录。 ### 销毁 ``` make destroy TF_BACKEND_CONFIG=terraform/backend.hcl ``` ## 生产环境强化 从参考部署移植的可重用模式,通过 `make harden` 应用: - **干扰预算** — [`k8s/traefik/traefik.pdb.yaml`](k8s/traefik/traefik.pdb.yaml) 确保在节点排空期间保留 ≥1 个 Traefik 副本;[`k8s/server/server.pdb.yaml`](k8s/server/server.pdb.yaml) 保护 API server。 - **自动伸缩** — [`k8s/server/server.hpa.yaml`](k8s/server/server.hpa.yaml) 是一个基于 CPU 的 HPA,通过 `requests.cpu` + metrics-server 启用 (`make metrics` / `make load`)。 - **现代 ingress** — [`k8s/traefik/traefik.ingressclass.yaml`](k8s/traefik/traefik.ingressclass.yaml) 替换了已弃用的 `kubernetes.io/ingress.class` 注解;应用 Ingress 使用 `spec.ingressClassName: traefik`。 - **感知可用性的放置** — 多副本服务默认采用首选的 跨节点反亲和性,因此滚动更新不会在双节点集群上死锁。 [`scripts/soft-affinity.sh`](scripts/soft-affinity.sh) 可以在节点容量充足的情况下强制执行 每个节点严格放置一个副本的策略。 - **冒烟与负载测试** — [`scripts/smoke.sh`](scripts/smoke.sh) 检查公共 路径(Traefik + 应用路由,兼容 NixOS/minikube)并且 [`scripts/load.sh`](scripts/load.sh) 驱动自动伸缩。 受保护的生产环境工作流会应用服务器 HPA/PDB,验证公共 API 和 WebSocket 路径,并在失败时回滚服务器镜像。 ## 许可证 OpsWarden 在 **Apache License 2.0** 下分发。参见 [LICENSE](LICENSE)。
标签:ECS, Terraform, 子域名突变, 持续集成/部署, 搜索引擎查询, 测试用例, 自定义请求头, 运维