Commit 1a481edd authored by BO ZHANG's avatar BO ZHANG 🏀
Browse files

docs: 重构 README 以明确运维入口和配置结构

parent 5cdaaa78
Loading
Loading
Loading
Loading
+136 −146
Original line number Diff line number Diff line
@@ -6,218 +6,208 @@

- 已安装 Docker 和 Docker Compose
- **目标机器账号权限要求**:用于部署的执行账号(无论是手动执行 `make` 的当前用户,还是 Ansible Inventory 中的 `ansible_user`**必须具有免 `sudo` 执行 Docker 命令的权限**(即该用户已加入 `docker` 用户组),或者拥有完整的 `root/sudo` 权限。
- Git
- Make
- Git、Make、Ansible
- Linux 环境(因涉及权限与路径映射)

## 部署步骤
## 核心运维入口说明 (Operations Entry Points)
本系统将所有的日常运维操作抽象为了两个高度内聚的工具入口:
1. **`make`**:负责上游开发侧的镜像构建、重命名与交付入库(Push)。
2. **`ansible`**:负责下游实施侧的环境预检、配置分发与集群容器生命周期管理。

本系统支持两种部署方式:**基于 Make 的单机/手动部署****基于 Ansible 的多节点自动化部署**

### 方式一:Ansible 多节点一键部署(推荐用于生产环境)

如果您需要在真实的集群(1个 Master 节点 + 多个 Worker 节点)上部署该系统,我们提供了开箱即用的 Ansible Playbooks。由于我们有多个不同的部署环境(如 `p368`, `csu`, `zjlab`),我们为每个环境准备了专属的 Ansible Inventory 文件。

**💡 进阶:为每个 Worker 单独指定并发度**
您可以直接在 Inventory 文件(例如 `inventory.p368.ini`)的每个 Worker 节点条目上设置 `worker_concurrency`,从而让不同机器使用不同的 Celery 并发数:

```ini
[worker]
worker-a ansible_host=192.168.25.19 ansible_user=root deploy_dir=/opt/csst-airflow-worker-a worker_concurrency=16
worker-b ansible_host=192.168.25.20 ansible_user=root deploy_dir=/opt/csst-airflow-worker-b worker_concurrency=64
worker-c ansible_host=192.168.25.21 ansible_user=root deploy_dir=/opt/csst-airflow-worker-c worker_concurrency=8
```
---

- `worker_concurrency`:该节点上 Airflow Celery Worker 的并发槽位数。
- 建议按机器 CPU / 内存资源分别设置,不要所有 Worker 都使用同一个值。
- 如无特殊需要,请在每个 Worker 上显式写出该值,避免依赖默认值。
### 1. 镜像的构建与交付 (`make` 命令组)

#### 1. 准备工作
- **安装 Ansible**:如果您的执行机(通常是您的本地电脑或 Master 节点)尚未安装 Ansible,请先通过以下命令安装:
在有外网环境的机器或 CI/CD 系统中,通过 `make` 命令将业务自定义镜像和第三方依赖镜像全部构建并同步到私有 Harbor 镜像仓库。所有需要拉取的官方依赖镜像都显式地定义在根目录的 `required-images.txt` 中。

  **Ubuntu / Debian:**
您可以随时在项目根目录运行 `make help` 查看说明:
```bash
  sudo apt update
  sudo apt install -y software-properties-common
  sudo apt-add-repository --yes --update ppa:ansible/ansible
  sudo apt install -y ansible
make help
```
*(系统会自动打印出即将处理的全部 12 个镜像列表,包含 postgres、redis 等 9 个第三方镜像,以及 airflow、api-gateway 等 3 个自建镜像。)*

#### 常用构建命令
为了简化操作,建议在执行 `make` 之前,**先在终端导出目标环境变量**,后续的所有 `make` 命令都可以直接复用这些变量而无需每次指定:

  **Python pip (跨平台推荐):**
```bash
  pip3 install ansible
# 【方案一:常规部署环境,如 p368】
# 设置部署环境名称 (例如 p368)
export ENV=p368
# 设置镜像推送的 Harbor 仓库地址前缀 (必须以斜杠结尾)
export HARBOR_PROJECT=harbor.csst.nao:10443/csst/
# 设置构建镜像的版本号
export IMAGE_TAG=test
# 设置内部构建号 (将展示在 Portal 前端),如果不设置将默认使用 IMAGE_TAG 的值
export BUILD_NUMBER=123456

# ----------------------------------------
# 【方案二:本地单机开发测试环境】
# 如果是本地开发机直接打包运行,不需要推送到远端 Harbor,可留空
export ENV=local
export HARBOR_PROJECT=
export IMAGE_TAG=latest
export BUILD_NUMBER=dev
```

- **配置 SSH 免密与权限**:确保执行机配置了到所有目标节点(Master & Workers)的 SSH 免密登录。此外,清单中配置的 `ansible_user` 用户必须在目标机器上具有执行 `docker``docker compose` 命令的权限(将其加入 docker 组或具有 sudo 权限)。

#### 2. 配置环境对应的 Inventory 文件
根据您要部署的环境,编辑 `ansible/inventories/` 目录下对应的清单文件(例如 `inventory.csu.ini`)。
配置好环境变量后,您可以执行以下精简命令:

**关于部署路径 (`deploy_dir`) 的重要说明:**
为了确保在各种环境(尤其是包含 NFS/NAS 共享存储,或者单机混合部署)下不会产生文件覆盖与权限冲突,**我们强烈推荐在 Inventory 中为每个节点(或组)显式指定独立的 `deploy_dir`**

即使您的 Master 和 Worker 在不同的物理机上,如果在 `/opt/` 下挂载了同一块共享存储,不区分路径也会导致容器配置被互相覆盖。
```bash
# 1. 仅拉取外部依赖
# 从 required-images.txt 清单中拉取 13 个基础和组件依赖镜像(自动跳过已存在的)
make pull

推荐部署示例(为不同角色或节点指定不同路径与别名):
```ini
[master]
# node-master 为节点的别名,后续可通过 ansible node-master 进行针对性操作
node-master ansible_host=192.168.25.18 ansible_user=root deploy_dir=/opt/csst-airflow-master
# 2. 仅构建 (不推送到私有仓库)
# 基于依赖镜像构建业务镜像,并将所有镜像重命名为统一样式 (例如 harbor.../csst-airflow:v0.0.0)
make build

[worker]
node-worker1 ansible_host=192.168.25.19 ansible_user=root deploy_dir=/opt/csst-airflow-worker1 worker_concurrency=16
node-worker2 ansible_host=192.168.25.20 ansible_user=root deploy_dir=/opt/csst-airflow-worker2 worker_concurrency=32
# 3. 仅推送
# 将已打好 Tag 的全量 16 个镜像推送到远端 Harbor
make push

[all:vars]
env_name=csu
# 全局默认部署路径(仅在未明确指定的节点上生效)
deploy_dir=/opt/csst-airflow
# 4. 一键完成全套交付 (最常用)
# 依次执行清理旧镜像、拉取依赖、构建业务镜像到全量推送,一气呵成
make all
```
*(在构建和推送过程中,终端会以 `[BUILD/TAG] Processing Postgres...` 或 `[PUSH] Pushing harbor.csst.nao...` 的形式清晰打印当前进度。)*

如果多个 Worker 机器规格相同,也可以在 `[worker:vars]` 中统一配置默认值,再在个别节点上单独覆盖:

```ini
[worker:vars]
worker_concurrency=16

[worker]
node-worker1 ansible_host=192.168.25.19 ansible_user=root deploy_dir=/opt/csst-airflow-worker1
node-worker2 ansible_host=192.168.25.20 ansible_user=root deploy_dir=/opt/csst-airflow-worker2
node-worker3 ansible_host=192.168.25.21 ansible_user=root deploy_dir=/opt/csst-airflow-worker3 worker_concurrency=32
```
---

上述配置会在部署时写入目标节点的 `.env`,并在启动 Worker 容器时传递给 `AIRFLOW__CELERY__WORKER_CONCURRENCY`,因此只需要修改 Inventory 后重新执行 Ansible 部署或更新即可生效。
### 2. 自动化部署与启停 (`ansible` 命令组)

#### 3. 配置环境变量
为了让集群中的所有组件(特别是 Worker 节点)能够正确找到主节点和其他依赖,您需要为该环境配置专用的 `.env` 文件。
`envs/` 目录下,复制或编辑对应环境的 `.env` 文件(例如 `envs/csu.env`)。您**必须**修改 `MASTER_IP``HARBOR` 这两个关键变量:
本系统**唯一推荐**的部署方式为基于 Ansible 的一键部署。所有多环境(如 `p368`, `csu`, `zjlab`)的配置都已严格隔离在 `deploy_configs/<env>/` 目录下。

```env
# --- Airflow Core Config ---
AIRFLOW_IMAGE_NAME=apache/airflow:3.0.5
AIRFLOW_UID=50000
为了简化操作,建议在执行部署前,**先在终端导出目标环境名称变量**,后续的所有 Ansible 命令都可以直接复用该变量:

# --- Cluster & Network Config ---
# 必须修改:将其替换为 Master 节点的实际 IP 地址
MASTER_IP=192.168.25.18
# 必须修改:将其替换为您当前环境使用的镜像仓库地址
HARBOR=csu-harbor.csst.nao:10443

# --- API Gateway Config (其余端口和内部 IP 默认会自动引用 MASTER_IP,通常无需修改) ---
POSTGRES_HOST=${MASTER_IP}
AIRFLOW_HOST=${MASTER_IP}
REDIS_HOST=${MASTER_IP}
ELASTICSEARCH_HOST=${MASTER_IP}
```bash
# 例如要部署 p368 环境,只需执行一次:
export ENV=p368
```

#### 4. 一键部署集群
`docker-celery-3.0.5` 目录下执行(以 `csu` 环境为例):
目前为您内置了 5 个不同场景的自动化剧本(Playbook),设置好变量后即可运行:

#### ① 部署前环境预检 (`check.yml`)
在正式部署前,验证网络连通性及基础环境是否齐备。它会自动 ping 所有节点、检查 Docker 和 Compose 插件是否安装,并校验目标机器的部署路径与磁盘剩余空间:
```bash
# 1. 部署所有节点的基础组件与服务容器
ansible-playbook -i ansible/inventories/inventory.csu.ini ansible/deploy.yml

# 2. 同步 DAGs 代码到所有节点 (仅更新 DAGs 业务代码时执行此命令即可)
ansible-playbook -i ansible/inventories/inventory.csu.ini ansible/sync_dags.yml
ansible-playbook ansible/check.yml -i deploy_configs/${ENV}/inventory.ini
```

#### 5. 软件升级与更新
当您在 Master 节点上通过 `git pull` 拉取了最新的框架代码、修改了 `docker-compose.yaml` 或者是更新了自定义的镜像版本后,您只需要执行以下一键更新命令:

#### ② 首次部署或全量更新部署 (`deploy.yml` 或 `playbook.yml`)
自动分发环境配置、解析变量、拉取最新镜像(支持 fallback 到本地镜像),并从零拉起所有 Master 和 Worker 节点的容器集群:
```bash
ansible-playbook -i ansible/inventories/inventory.csu.ini ansible/update.yml
ansible-playbook ansible/deploy.yml -i deploy_configs/${ENV}/inventory.ini
```
*(该脚本会自动将最新的代码同步给所有集群节点,并让各节点拉取最新镜像、重启发生了变更的服务容器,而不会中断未发生变更的服务。)*

---

### 方式二:基于 Make 的单机或手动部署

#### 1. 初始化目录与权限

#### ③ 软件升级与全量重启 (`update.yml`)
当修改了 `docker-compose.yaml` 或者是更新了镜像版本后,此命令会优雅地下线旧容器,拉取最新配置并启动新容器。特别是结合 `make build` 之后,利用此剧本能完美重启集群并应用新镜像:
```bash
make mkdir
make fix-permission
ansible-playbook ansible/update.yml -i deploy_configs/${ENV}/inventory.ini
```
> **注意**: `fix-permission` 会使用 `sudo` 修复 Elasticsearch 数据目录的归属,以防启动时因无权写入数据而失败。

#### 2. 选择部署环境

本系统支持通过 Makefile 动态指定环境变量配置文件。您可以随时通过以下命令查看当前支持的所有环境模板:
#### ④ 业务代码轻量更新 (`sync_dags.yml`)
如果只修改了 `dags/` 目录下的 Python 脚本,无需全量重启容器,直接执行轻量级同步即可将脚本分发给所有节点:
```bash
ansible-playbook ansible/sync_dags.yml -i deploy_configs/${ENV}/inventory.ini
```

#### ⑤ 停止与卸载服务 (`down.yml`)
完全停止并移除所有节点上的服务(等价于在所有机器上批量执行 `docker compose down`):
```bash
make list-envs
ansible-playbook ansible/down.yml -i deploy_configs/${ENV}/inventory.ini
```
*(系统将自动读取 `envs/` 目录下的 `*.env` 文件)*

#### 3. 初始化 Airflow 数据库
---

## 配置环境参数 (部署前的必要准备)
在为一个新的环境(例如 `p368`)进行部署前,您必须了解 `deploy_configs/` 目录下的 **4 份**配置文件的作用:

在首次部署的**主控节点**上执行数据库初始化(假设您使用的是 `csu` 环境):
### 一、全局静态配置 (通常无需修改)

```bash
make init ENV=csu
#### ① `deploy_configs/airflow.env` (必需)
**作用**:存放所有环境通用的底层系统级静态配置(例如 `AIRFLOW_UID=50000`)。
**注意**:由于它是静态的,我们将其放置在 `deploy_configs/` 根目录下,由所有环境共享。Ansible 部署时会自动将此文件分发给对应环境。
```env
# --- Airflow 核心静态配置 ---
AIRFLOW_UID=50000
AIRFLOW_PROJ_DIR=.
_AIRFLOW_WWW_USER_USERNAME=airflow
_AIRFLOW_WWW_USER_PASSWORD=airflow
```

#### 4. 启动核心服务
### 二、环境特异性配置 (每个环境独立维护)

> **⚠️ 部署强烈建议**:
> 系统采用 Master/Worker 分离架构,主节点负责调度与监控网关,子节点负责计算。
#### ② `deploy_configs/<env>/inventory.ini` (必需:定义 Ansible 部署拓扑与变量)
**作用**:这是基础设施配置的**唯一入口**。它不仅决定了集群机器拓扑,还控制了镜像来源与核心安全密钥,您**只需修改这一个文件**即可适配不同环境。
**配置指南**
- 配置 Master/Worker 节点的 IP (`ansible_host`)、SSH 用户。系统会自动将 `master` 组内第一个节点的 IP 作为集群内部通信的 `MASTER_IP`**无需再手动指定**
- **`deploy_dir`**:为避免冲突,强烈建议为每个节点显式指定独立的部署路径。例如 `/opt/csst-airflow`
- **`worker_concurrency`**:控制该节点上 Celery Worker 的并发处理能力。
- **环境声明**:必须在该文件底部的 `[all:vars]` 中声明当前的环境名称。
- **`harbor_project` 与 `image_tag`**: 强烈建议利用环境变量与 `make all` 的工作流生成带动态 Tag 的镜像,然后在 `inventory.ini` 中填写。Ansible 会结合这两个变量自动组装镜像名称,拉取最新版本。
- **JWT 密钥**:通过 `jwt_secret` 指定,用于 API Gateway 与 Airflow Apiserver 通信。

##### 主控节点 (Master Node) 部署:
在作为 Master 的机器上执行,此命令会启动数据库、消息队列、API Gateway、Prometheus/Grafana 监控大盘以及 Airflow 控制平面:
```ini
[master]
p368-master ansible_host=127.0.0.1 ansible_connection=local

```bash
make up-master ENV=csu
```
[worker]
p368-worker1 ansible_host=127.0.0.1 ansible_connection=local

##### 计算节点 (Worker Node) 部署:
在提供算力的机器上执行,此命令**仅启动** Celery Worker 和该机器专属的日志采集与监控探针 (Filebeat / cAdvisor / Node Exporter):
[all:vars]
env=p368
deploy_dir=/opt/csst-airflow

```bash
make up-worker ENV=csu
# 镜像仓库前缀 (以斜杠结尾)
harbor_project=harbor.csst.nao:10443/csst/
image_tag=test

# API Gateway 与 Airflow Apiserver 通信所用的 JWT 密钥
jwt_secret=eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVC...
```
> **提示**: 探针会自动启动,以供 Master 节点的 Prometheus 和 ES 抓取该 Worker 机器的资源与日志状态。

---
#### ③ `deploy_configs/<env>/variables.toml` (可选:定义 Airflow 业务环境变量)
**作用**:存放与外部系统(如 DFS、CCDS、OSS/S3 对象存储等)交互的业务级环境变量。Ansible 部署时会自动将该 TOML 文件解析,并通过 `airflow variables import` 命令导入到 Airflow 的 Postgres 数据库中。
**配置指南**
相比 JSON,TOML 格式更易于阅读和维护,您可以使用 section `[块]` 的方式对不同服务的变量进行分组:
```toml
[dfs]
gateway = "10.80.1.22:28000"
timeout = 30

[oss]
endpoint_url = "http://10.80.1.10:9000"
bucket = "csst-data"
```

## Makefile 命令速查
#### ④ `deploy_configs/<env>/connections.json` (可选:定义 Airflow 加密连接)
如果需要预置 Airflow 的连接配置,可将其存放在这里,Ansible 部署时会自动将这些配置导入到 Airflow 的 DB 中。

| 命令 | 描述 |
|------|------|
| `make list-envs` | 列出 `envs/` 目录下所有可用的环境名称 |
| `make mkdir` | 创建所有必需的挂载目录 |
| `make fix-permission` | 修复 `es_data` 目录的属主权限 (UID 50000) |
| `make init ENV=<env>` | 初始化 Airflow 数据库 |
| `make up-master ENV=<env>` | 启动主控节点 (包含网关与所有监控大盘) |
| `make up-worker ENV=<env>` | 启动计算节点 (仅包含 Worker 和监控探针) |
| `make down ENV=<env>` | 停止并移除指定环境的容器 |
| `make clean ENV=<env>` | 停止服务并清理容器 |
| `make ps ENV=<env>` | 列出当前运行中的服务 |
> **💡 容错机制说明 (Local Fallback)**:
> 部署脚本在启动容器前会执行 `docker compose pull` 从 Harbor 拉取镜像。如果当前环境无法连接外网/Harbor,只要该节点上预先 `make build` 过本地镜像,`pull` 失败的报错会被自动忽略并直接使用本地镜像启动服务。

## 访问服务与系统端口映射

在完整的分布式或单机部署中,各个组件所占用的宿主机端口如下。**请在部署前确保宿主机的这些防火墙端口已开放且未被占用**

### 主控节点 (Master Node)
执行 `make up` 或 `make up-master` 的机器上将暴露以下核心服务端口:
执行 Ansible 部署后,主节点机器上将暴露以下核心服务端口:

| 服务组件 | 宿主机端口 | 用途说明 | 访问地址示例 |
| :--- | :--- | :--- | :--- |
| **Task Portal** | `38501` | **统一任务与监控控制台**。提供带进度预估的 JSON 筛选及 Grafana 资源大盘内嵌页 | `http://<MASTER_IP>:38501` |
| **API Gateway** | `38000` | **业务系统唯一对接入口**。提供高并发任务提交、任务控制(取消/重试)与状态检索 | `http://<MASTER_IP>:38000` |
| **Airflow Web UI** | `38080` | Airflow 原生控制台与官方 API (已开启 `SimpleAuthManager` 免密 Admin 登录) | `http://<MASTER_IP>:38080` |
| **Airflow Apiserver** | `38080` | Airflow 3 原生控制台与官方 API (已开启 `SimpleAuthManager` 免密 Admin 登录) | `http://<MASTER_IP>:38080` |
| **Grafana** | `33000` | 时间序列数据监控与仪表盘可视化 (账号密码默认: `admin`/`admin`) | `http://<MASTER_IP>:33000` |
| **Prometheus** | `39090` | 集群监控指标拉取服务器 | `http://<MASTER_IP>:39090` |
| **Kibana** | `35601` | 集中式日志可视化中心 (直接在 Discover 页面选择 `airflow-*` 视图检索日志) | `http://<MASTER_IP>:35601` |
| **Flower** | `35555` | Celery 集群状态监控面板 (**仅在执行 `make up-master` 时启动**) | `http://<MASTER_IP>:35555` |
| **Flower** | `35555` | Celery 集群状态监控面板 | `http://<MASTER_IP>:35555` |
| **Elasticsearch** | `39200` | 存储运行日志的底层搜索引擎 API | `http://<MASTER_IP>:39200` |
| **PostgreSQL** | `35432` | 核心元数据库,存储 Airflow 数据及 API Gateway 的 `csst_task_records` 表 | `postgresql://<MASTER_IP>:35432` |
| **Redis** | `36379` | Celery 消息队列中间件 | `redis://<MASTER_IP>:36379` |

### 计算节点 (Worker Node)
执行 `make up-worker ENV=<env>` 的机器
Worker 节点
*   **不暴露核心业务端口**,仅暴露 `cAdvisor` (38081) 和 `Node Exporter` (通过 Host 网络) 供主节点拉取监控指标。
*   Worker 节点只需通过 `*.env` 中的 `MASTER_IP` 环境变量,主动连接到主控节点的 Redis 和 Postgres 即可静默消费任务。
*   Worker 节点只需通过 `system.env` 中的 `MASTER_IP` 环境变量,主动连接到主控节点的 Redis 和 Postgres 即可静默消费任务。

---

@@ -231,10 +221,10 @@ make up-worker ENV=csu
## 故障排除

- 确保 Docker 正在运行
- 确保宿主机端口未被占用:`38080` (Airflow), `39200` (ES), `35601` (Kibana)
- 若 Elasticsearch 启动失败 (Unhealthy),请查看权限问题,再次执行 `make fix-permission` 并 `docker compose restart elasticsearch` (或 `docker-compose restart elasticsearch`)
- 确保宿主机端口未被占用:`38080` (Airflow), `39200` (ES), `35601` (Kibana) 等
- **Celery Worker 监控数据丢失**:如果在 Flower 面板看不到 Worker 或在 Task Portal 的 Workers 列表中为空,请确保在部署 Worker 的 `docker-compose` 里的 `${HOSTNAME}` 等变量配置了正确的双美元符(`$$`)转义,以免在宿主机上被提前解析。
- 若 Elasticsearch 启动失败 (Unhealthy),系统可能会存在权限问题,Ansible 脚本在执行时通常会自动修复(将 `es_data` 属主设为 50000)。如遇意外,可尝试手动执行 `sudo chown -R 50000:0 volumes/es_data` 并重启容器。
- 检查容器日志以了解错误:
  ```bash
  docker compose logs -f
  # 或者使用老版本:docker-compose logs -f
  ```