feat(agent-call): add repeatable Asterisk bootstrap
This commit is contained in:
@@ -120,6 +120,8 @@ Mock多实例、固定端口和媒体关联方式存在简化,顺序成功不
|
||||
|
||||
推荐初版:A/B分别运行在独立Linux主机,Asterisk使用host network;中间件通过管理网访问ARI,媒体组件与节点双向可达。这样避免将仓库同一Docker私网中的音频可达性误认为真实外网可达性。
|
||||
|
||||
单个真实 SIP 测试 Cell 的可重复 ECS UserData 安装流程已落地于`docs/真实SIP_Asterisk快速部署_v1.0.md`,脚本为`deploy/asterisk_bootstrap.sh`和`deploy/build_asterisk_userdata.py`;本文件保留手工部署与验收边界,不把示例参数当成已授权生产线路。
|
||||
|
||||
同机运行两个host-network节点会争用5060、8088和RTP端口,不允许直接照搬。若必须同机双节点,需另行设计完整端口/地址及NAT映射,不能只改变ARI端口。
|
||||
|
||||
| 流向 | 放通与限制 |
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
# 真实 SIP/Asterisk 快速部署(v1.0)
|
||||
|
||||
本流程用于在北京 `cn-beijing` 使用固定 EIP `123.56.71.98` 部署单个真实 SIP 测试 Cell。默认只计划,不创建资源;只有明确执行 `--apply` 才会创建/绑定 ECS。
|
||||
|
||||
> 这是单路联调底座,不是生产 1000 路容量方案。竞价实例使用 `SpotAsPriceGo` 时可能被回收并中断通话。
|
||||
|
||||
## 1. 已落地脚本
|
||||
|
||||
| 文件 | 用途 |
|
||||
| --- | --- |
|
||||
| `deploy/render_asterisk.py` | 校验并生成 `http.conf`、`ari.conf`、`pjsip.conf`、`rtp.conf`、`extensions.conf` |
|
||||
| `deploy/asterisk_bootstrap.sh` | ECS UserData:安装 Docker、拉取 digest 镜像、安装配置、启动并检查 Asterisk |
|
||||
| `deploy/build_asterisk_userdata.py` | 将渲染配置安全嵌入 UserData;输出包含 ARI 密钥,必须放在 600 权限的本地目录 |
|
||||
| `deploy/aliyun_host.py` | 北京 ECS/EIP 只读计划与显式 `--apply` 创建/绑定,支持 `SpotAsPriceGo` |
|
||||
| `deploy/asterisk.sh` | 本地 Compose 配置检查;只有 `up` 才启动服务 |
|
||||
|
||||
## 2. 准备本地受限目录
|
||||
|
||||
不要把 ARI 密钥、SIP 密码、SSH 私钥写入仓库、命令日志或聊天。以下目录已被 `.gitignore` 忽略:
|
||||
|
||||
```bash
|
||||
set -euo pipefail
|
||||
umask 077
|
||||
mkdir -p .local/agent-call
|
||||
openssl rand -hex 32 > .local/agent-call/ari-password
|
||||
chmod 600 .local/agent-call/ari-password
|
||||
```
|
||||
|
||||
准备 `.local/agent-call/asterisk.json`。下面只放线路参数,不放密码;`from_user`/`caller_id` 必须按供应商规则确认:
|
||||
|
||||
```json
|
||||
{
|
||||
"public_ip": "123.56.71.98",
|
||||
"transport": "udp",
|
||||
"local_net": "172.16.0.0/12",
|
||||
"ari_bind": "127.0.0.1",
|
||||
"primary": {
|
||||
"host": "61.132.228.221",
|
||||
"port": 5060,
|
||||
"auth_mode": "ip",
|
||||
"register": false,
|
||||
"from_user": "BD93205882",
|
||||
"caller_id": "BD93205882 <BD93205882>"
|
||||
},
|
||||
"backup": null
|
||||
}
|
||||
```
|
||||
|
||||
生成一次性 UserData。镜像必须是已批准的 immutable digest:
|
||||
|
||||
```bash
|
||||
python3 deploy/build_asterisk_userdata.py \
|
||||
--config .local/agent-call/asterisk.json \
|
||||
--image 'git.ipao.vip/rogee/asterisk-real@sha256:0f5e3cd0e9a86bc9dc4750929abee9ba1faae11ed39739f3e75343d39d837e41' \
|
||||
--ari-password-file .local/agent-call/ari-password \
|
||||
--output .local/agent-call/asterisk-user-data.sh
|
||||
bash -n .local/agent-call/asterisk-user-data.sh
|
||||
```
|
||||
|
||||
## 3. ECS 配置与部署
|
||||
|
||||
先查询固定 EIP、全部现有实例和项目标签;不要复用无项目归属的实例。使用专用 VSwitch、安全组、SSH KeyPair,安全组只允许供应商 SIP/RTP 来源:
|
||||
|
||||
```bash
|
||||
python3 deploy/aliyun_host.py \
|
||||
--config .local/agent-call/aliyun.json \
|
||||
--state .local/agent-call/host-state.json
|
||||
```
|
||||
|
||||
创建配置 `.local/agent-call/aliyun.json` 时至少填写:
|
||||
|
||||
```json
|
||||
{
|
||||
"region": "cn-beijing",
|
||||
"public_ip": "123.56.71.98",
|
||||
"project_tag": "agent-call",
|
||||
"image_id": "ubuntu_24_04_x64_20G_alibase_20260828.vhd",
|
||||
"instance_type": "ecs.e-c1m1.large",
|
||||
"vswitch_id": "<approved-vswitch-id>",
|
||||
"security_group_id": "<dedicated-security-group-id>",
|
||||
"key_pair_name": "<approved-key-pair>",
|
||||
"spot_strategy": "SpotAsPriceGo",
|
||||
"system_disk_category": "cloud_essd",
|
||||
"system_disk_gib": 40,
|
||||
"system_disk_performance_level": "PL1",
|
||||
"user_data_file": ".local/agent-call/asterisk-user-data.sh"
|
||||
}
|
||||
```
|
||||
|
||||
确认计划无误后才执行一次:
|
||||
|
||||
```bash
|
||||
python3 deploy/aliyun_host.py \
|
||||
--config .local/agent-call/aliyun.json \
|
||||
--state .local/agent-call/host-state.json \
|
||||
--apply
|
||||
```
|
||||
|
||||
`SpotAsPriceGo` 不填写 `spot_price_limit`;创建后脚本会等待 ECS Running,再绑定既有 EIP。创建/绑定失败时保留 state 中的实例 ID,禁止自动再创建第二台。
|
||||
|
||||
## 4. 验证与单次外呼
|
||||
|
||||
UserData 完成后通过 Cloud Assistant 执行只读检查,确认容器健康、Asterisk 版本、PJSIP contact 和出站 dialplan:
|
||||
|
||||
```bash
|
||||
# RunCommand 的实例数组使用 --InstanceId.1,不要传 JSON 数组给 --InstanceId
|
||||
aliyun ecs RunCommand --RegionId cn-beijing \
|
||||
--InstanceId.1 <instance-id> \
|
||||
--Type RunShellScript \
|
||||
--Name agent-call-readiness \
|
||||
--CommandContent 'docker ps --format "{{.Names}} {{.Status}}"; docker exec agent-call-asterisk asterisk -rx "core show version"; docker exec agent-call-asterisk asterisk -rx "pjsip show endpoint provider-primary"; docker exec agent-call-asterisk asterisk -rx "dialplan show outbound"' \
|
||||
--ContentEncoding PlainText \
|
||||
--Timeout 60 \
|
||||
--RepeatMode Once \
|
||||
--KeepCommand false
|
||||
```
|
||||
|
||||
确认供应商已经冻结目标号码、前缀、From 域、PAI 和编解码后,一次只测试一个号码;不自动重试:
|
||||
|
||||
```bash
|
||||
docker exec agent-call-asterisk asterisk -rx \
|
||||
'channel originate Local/<7089+原始被叫>@outbound application Wait 30'
|
||||
```
|
||||
|
||||
记录完整 SIP 状态、`Reason`、RTP/录音结果和 `call_id`。`Avail`/OPTIONS 只证明探活,不证明外呼接通。
|
||||
|
||||
## 5. 更新与回收
|
||||
|
||||
- 配置变更:生成新的 UserData/配置目录,核对后再重启容器;不要覆盖正在使用的配置目录。
|
||||
- 竞价回收:活动通话可能中断;EIP、实例状态、未上传录音和 outbox 必须单独对账。
|
||||
- 测试环境若需回收,只删除明确标记为 `project=agent-call` 的本次实例;不要释放或解绑固定 EIP,不能删除无关实例。
|
||||
- 当前供应商返回过 `488 / Q.850 cause=88 INCOMPATIBLE_DESTINATION`;未确认线路规则前不要重复拨号。
|
||||
+3
-1
@@ -33,6 +33,8 @@ services/asr-web/ ASR-only Go服务及Web页面
|
||||
deploy/aliyun_host.py 阿里云CLI只读计划/显式apply
|
||||
deploy/aliyun.example.json 实例/预算/网络参数占位
|
||||
deploy/render_asterisk.py 受控配置生成
|
||||
deploy/asterisk_bootstrap.sh ECS UserData安装Docker并启动Asterisk
|
||||
deploy/build_asterisk_userdata.py 将配置安全嵌入UserData
|
||||
deploy/asterisk.example.json SIP接入参数占位
|
||||
deploy/asterisk.sh 默认检查;显式up才启动
|
||||
tests/ 离线部署逻辑及PCM测试
|
||||
@@ -167,7 +169,7 @@ python3 deploy/render_asterisk.py --config .local/asterisk.json
|
||||
|
||||
### 5.2 镜像与安全组
|
||||
|
||||
`.env`中的ASTERISK_IMAGE必须为批准镜像的`@sha256:`引用。本轮R1使用内部Registry中的固定digest镜像并实测Asterisk 22.10.1;该镜像验证仅覆盖单路底座,不等于生产镜像批准或容量验收。配置读取权限按镜像实际UID/GID修正为必要的组读权限,未使用chmod 777。
|
||||
`.env`中的ASTERISK_IMAGE必须为批准镜像的`@sha256:`引用。本轮R1使用内部Registry中的固定digest镜像并实测Asterisk 22.10.1;该镜像验证仅覆盖单路底座,不等于生产镜像批准或容量验收。配置读取权限按镜像实际UID/GID修正为必要的组读权限,未使用chmod 777。ECS UserData快速部署步骤见`docs/真实SIP_Asterisk快速部署_v1.0.md`,生成文件包含ARI密钥,只能放在`.local/`并保持600权限。
|
||||
|
||||
确认:SIP服务端IP/协议/端口、RTP回程、EIP/NAT、实际VPC网段、管理来源、录音卷目录和权限。安全组只按来源和用途开放;不公开裸ARI,不清空既有防火墙。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user