# AItrackwalker 离线 Kubernetes 部署

该目录是离线部署项目的首个实施增量，目标是使用同一套入口支持：

- `single`：单节点 RKE2，内置单实例数据服务，用于测试和验收；
- `ha`：3 个或更多 RKE2 server 加 worker，数据服务由独立 Chart/Operator 或外部服务提供；
- 目标节点无公网访问，所有二进制、镜像、Chart、OS 包和模型来自已校验离线包。

总体设计见 [离线 Kubernetes 一键部署项目方案](../docs/offline-kubernetes-deployment-project-plan.md)。

## 当前实现范围

已实现：

- 站点配置、秘密配置和单机/多机 inventory 示例；
- 配置、CIDR、节点数量、口令和版本锁预检；
- 离线包 SHA-256/签名验证入口；
- Linux 基线、RKE2 air-gap 制品分发、server/agent 安装的 Ansible roles；
- RKE2 内置分布式 OCI 镜像分发配置；
- 平台 Helm Chart：
  - frontend
  - backend
  - uav-access-service
  - vision-inference
  - pointcloud-analysis
  - artifact-installer
  - 单机内置 PostGIS、Redis、Kafka、MinIO、Prometheus
  - 可选 EMQX
- Longhorn 和 NVIDIA GPU Operator 离线 Chart 安装入口；
- 集群和工作负载基础验收脚本。

尚未宣称完成：

- PostGIS/Kafka/MinIO 的生产 HA Operator；
- kube-vip、MetalLB 和云 LB 的自动配置；
- 后端多副本改造；
- 模型从对象存储同步到 Pod 本地缓存；
- 联网发布工厂自动拉取和扫描全部依赖；
- 生产版本兼容矩阵。`versions.lock.yaml` 在完成 M0 验证前保持 `validated: false`。

## 目录

```text
deploy/
├── config/                 # 站点配置、秘密示例和 schema
├── inventories/            # single/ha inventory 示例
├── ansible/                # Linux 与 RKE2 自动化
├── charts/trackwalker/     # 平台 Helm Chart
├── addons/                 # 第三方 Chart 的离线 values
├── scripts/                # 部署、校验、验收、bundle 构建
├── tests/                  # 不依赖集群的静态测试
└── versions.lock.yaml      # 版本与镜像锁
```

## 离线包约定

部署入口默认认为 bundle 根目录结构如下：

```text
trackwalker-offline-<version>/
├── deploy/
├── tools/
│   └── bin/
│       ├── ansible-playbook
│       ├── helm
│       ├── kubectl
│       ├── yq
│       ├── sops
│       └── cosign
├── rke2/
│   ├── install.sh
│   ├── rke2.linux-amd64.tar.gz
│   ├── rke2-images.linux-amd64.tar.zst
│   └── sha256sum-amd64.txt
├── images/
│   ├── platform-images.oci.tar.zst
│   └── addon-images.oci.tar.zst
├── os-packages/
│   └── ubuntu/
├── charts/
│   └── third-party/
├── models/
├── SHA256SUMS
├── SHA256SUMS.sig
```

离线目标机不运行 Maven、npm、pip 或 Docker build。

## 准备配置

```bash
cp deploy/config/site.example.yaml deploy/config/site.yml
cp deploy/config/secrets.example.yaml deploy/config/secrets.yaml
cp deploy/inventories/single/hosts.example.yml deploy/inventories/single/hosts.yml
```

HA 环境改用 `deploy/config/site-ha.example.yaml` 和
`deploy/inventories/ha/hosts.example.yml` 作为模板。HA 示例假设 API
负载均衡/VIP、DNS、TLS Secret 和外部有状态服务已经准备完成。

修改三个文件：

- `site.yml`：CIDR、入口、存储、运行档案和 Helm 覆盖值；
- `secrets.yaml`：RKE2 token、数据库、MinIO 和内部服务口令；
- `hosts.yml`：节点 IP、SSH 用户和角色。

生产环境应加密秘密：

```bash
sops --encrypt deploy/config/secrets.yaml > deploy/config/secrets.sops.yaml
rm deploy/config/secrets.yaml
```

示例秘密包含 `CHANGE_ME`，部署预检会主动拒绝。

## 配置预检

```bash
python3 deploy/scripts/validate_config.py \
  --site deploy/config/site.yml \
  --inventory deploy/inventories/single/hosts.yml \
  --secrets deploy/config/secrets.sops.yaml \
  --versions deploy/versions.lock.yaml
```

加密秘密由 `deploy.sh` 先解密后再交给预检程序。

## 一键部署

开发/M0 阶段尚未生成签名 bundle 时：

```bash
deploy/scripts/deploy.sh \
  --profile single \
  --inventory deploy/inventories/single/hosts.yml \
  --config deploy/config/site.yml \
  --secrets deploy/config/secrets.sops.yaml \
  --allow-development-bundle
```

正式发布需另外提供由部署控制机预置、且位于 bundle 目录之外的发布公钥：

```bash
deploy/scripts/deploy.sh ... \
  --trusted-public-key /etc/trackwalker/release-signing.pub
```

正式离线包不得使用 `--allow-development-bundle`，并要求：

- `versions.lock.yaml` 已设置 `validated: true`；
- 所有镜像包含 digest；
- `SHA256SUMS` 校验通过；
- `SHA256SUMS.sig` 使用 bundle 外的可信公钥验证。

常用模式：

```bash
# 只执行预检
deploy/scripts/deploy.sh ... --preflight-only

# 从 RKE2 阶段继续
deploy/scripts/deploy.sh ... --resume-from rke2

# 只部署集群，不安装应用
deploy/scripts/deploy.sh ... --skip-app

# 只执行验收
deploy/scripts/deploy.sh ... --verify-only
```

## HA inventory 规则

- `rke2_servers` 必须为奇数，生产最少 3 个；
- 第一个 server 是 bootstrap server；
- `rke2_agents` 可以为空；
- GPU 节点同时加入 `gpu_workers`；
- 每个节点必须显式设置 `rke2_node_ip`；
- `ha` 默认关闭 Chart 内置数据服务，端点由 `helmValues.endpoints` 指定。

## 安全约束

- 默认口令、短 Token、`latest` 和未解析镜像 digest 在正式发布时被拒绝；
- Secret 不写入 Helm values 和 Helm release history，由部署入口创建既有 Kubernetes Secret；
- 目标节点上的 RKE2 token、kubeconfig 和秘密临时文件权限为 `0600`；
- 卸载和数据销毁不在当前入口中，避免误删 PVC；
- `artifact-installer` 保持单副本；
- 后端在完成分布式任务/SSE 改造前保持单副本。

## 本地静态测试

```bash
python3 -m unittest discover -s deploy/tests -p "test_*.py"
python3 deploy/tests/validate_project.py
```

测试发现 Helm 时会额外渲染单机和 HA Chart；如果 Helm 不在 `PATH`
中，可设置 `HELM_BINARY=/absolute/path/to/helm`。

有 Helm 的环境还应执行：

```bash
helm lint deploy/charts/trackwalker
helm template trackwalker deploy/charts/trackwalker \
  -f deploy/charts/trackwalker/values-single.yaml >/tmp/trackwalker.yaml
```
