update registrar.sh

This commit is contained in:
2025-10-05 19:02:44 +08:00
parent 748fc22fa5
commit c08211a99c
3 changed files with 195 additions and 7 deletions

View File

@@ -1,4 +1,158 @@
3) 外部 Agent 使用示例 ## gitea 中使用 woodpecker
### 放哪里
Woodpecker 会按顺序找你的配置:
.woodpecker/*.{yaml,yml}(文件夹里每个 yml 是一个独立 workflow
.woodpecker.yaml仓库根的单文件
.woodpecker.yml仓库根的单文件
你也可以在项目设置里改成自定义路径(如果填成目录,必须以 / 结尾,如 .woodpecker/)。
### 启用仓库
在 Woodpecker Web 打开你的仓库,点 Enable 后它会自动在 Gitea 里装好 webhook。之后你只要往仓库推代码、开 PR、打 tag就会触发 CI。最简单的是在根目录放 .woodpecker.yml。
### 通用模板(单文件 .woodpecker.yml
```bash
# 触发条件main/dev 分支的 push 和 PR打 tag 时发布
when:
- event: push
branch:
- main
- dev
- event: pull_request
- event: tag
# (推荐)完整 clone需要时
clone:
git:
image: woodpeckerci/plugin-git
settings:
depth: 0
steps:
- name: lint-and-test
image: node:20
environment:
NODE_ENV: test
commands:
- node -v
- npm ci
- npm run lint
- npm test
# 用 buildx 构建并推镜像(示例,需在 UI 里创建对应 secrets
- name: docker-build
image: quay.io/thegeeklab/wp-docker-buildx
privileged: true
when:
event:
- push
- tag
branch:
- main
settings:
repo: registry.example.com/myorg/myapp
tags: latest
username:
from_secret: docker_username
password:
from_secret: docker_password
```
要点:
secrets 现在统一通过 environment/settings -> from_secret 注入,不再用旧的 secrets: 块3.x 迁移规则)。
“你的第一个流水线”示例 & from_secret 的写法,官方文档也有。
上面用的 wp-docker-buildx 是常见的多架构镜像构建插件(需要 privileged: true
多文件结构(文件夹 .woodpecker/
如果你想把 CI 拆开管理,就在仓库根新建目录:
```bash
.woodpecker/
ci.yaml # 普通 CI
release.yaml # 发布
gpu.yaml # 需要 GPU 的任务(示例见下)
```
Woodpecker 会把每个 yml 当成一个独立 workflow 来跑。
适合 90% 项目push/PR 都跑、用 secrets、再给个 Docker 构建示例。
### 增加agent
外部/跨机器 agent 一律用 ci-agent.jmsu.top:443。
ci.jmsu.topWeb UI + REST API 的域名人用浏览器访问、OAuth 回调等)。不是 gRPC 入口。
ci-agent.jmsu.topgRPCTCP 的域名,你的 Traefik TCP 路由会把它转到 server 的 9000 端口——agent 该连这里。
在你现在的架构里:
内网/同 Compose 里的 agent → WOODPECKER_SERVER=woodpecker-server:9000容器内直连
跨机器/公网(或 tailnetagent → WOODPECKER_SERVER=ci-agent.jmsu.top:443走 Traefik TCP
只要机器能连通 ci-agent.jmsu.top:443并且你给了正确的 WOODPECKER_AGENT_SECRET它就能注册成为 agent。
(可选)如果 agent 在你的 tailnet 内,也可以直连 100.64.0.27:8419那就把 WOODPECKER_GRPC_SECURE=false因为这是你映射出来的明文 gRPC 端口)。
#### GPU agent + GPU 流水线
GPU Agent 的 docker-compose.yml放在有 NVIDIA 显卡的那台机器上)
```yaml
services:
woodpecker-agent-gpu:
image: woodpeckerci/woodpecker-agent:latest
container_name: woodpecker-agent-gpu
restart: unless-stopped
environment:
WOODPECKER_SERVER=ci-agent.jmsu.top:443
WOODPECKER_GRPC_SECURE=true
WOODPECKER_GRPC_VERIFY=true
WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}
# 给 agent 打标签,供 workflow 定向调度
WOODPECKER_AGENT_LABELS=gpu=true,location=gpu-node-01,backend=docker
# 并发数(按需)
WOODPECKER_MAX_WORKFLOWS=2
volumes:
- /var/run/docker.sock:/var/run/docker.sock
```
前置:这台 GPU 主机要装 NVIDIA Container Toolkit 并启用 Docker runtime
sudo nvidia-ctk runtime configure --runtime=docker && sudo systemctl restart docker。官方指引推荐这样配置。
GPU 专用工作流(.woodpecker/gpu.yaml
```bash
# 只有带 gpu=true 标签的 agent 会接单
labels:
gpu: "true"
when:
- event: push
branch:
- main
- dev
- event: manual
steps:
- name: cuda-smoke
image: nvidia/cuda:12.4.1-base-ubuntu22.04
commands:
- nvidia-smi
```
要点workflow 顶层的 labels 会作为调度选择器,只会派给拥有相同标签的 agent你刚才在 GPU agent 用 WOODPECKER_AGENT_LABELS=gpu=true,... 打过标签)。
## 3) 外部 Agent 使用示例
在其他机器(非同一 docker 网络)的 agent 在其他机器(非同一 docker 网络)的 agent

View File

@@ -38,7 +38,10 @@ services:
- woodpecker - woodpecker
environment: environment:
# 内网 agent 仍然走容器网络直连 server:9000 # 内网 agent 仍然走容器网络直连 server:9000
- "WOODPECKER_SERVER=woodpecker-server:9000" # - "WOODPECKER_SERVER=woodpecker-server:9000"
- WOODPECKER_SERVER=ci-agent.jmsu.top:4443
- WOODPECKER_GRPC_SECURE=true
- WOODPECKER_GRPC_VERIFY=true
- "WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}" - "WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}"
volumes: volumes:
- "/var/run/docker.sock:/var/run/docker.sock" - "/var/run/docker.sock:/var/run/docker.sock"
@@ -55,13 +58,16 @@ services:
- SERVICE_NAME=woodpecker-grpc - SERVICE_NAME=woodpecker-grpc
- SERVICE_ADDR=${LOCAL_TS_IP} - SERVICE_ADDR=${LOCAL_TS_IP}
- SERVICE_PORT=8419 # 对外注册用 8419 - SERVICE_PORT=8419 # 对外注册用 8419
- ROUTE_HOST=${WOODPECKER_GRPC_HOST}
- SERVICE_PROTOCOL=tcp - SERVICE_PROTOCOL=tcp
- CHECK_TYPE=tcp - CHECK_TYPE=tcp
- CHECK_INTERVAL=${CHECK_INTERVAL} - CHECK_INTERVAL=${CHECK_INTERVAL}
- CHECK_TIMEOUT=${CHECK_TIMEOUT} - CHECK_TIMEOUT=${CHECK_TIMEOUT}
- DEREG_AFTER=${DEREG_AFTER} - DEREG_AFTER=${DEREG_AFTER}
- TRAEFIK_TCP_ENTRYPOINT=${TRAEFIK_TCP_ENTRYPOINT} - TRAEFIK_TCP_ENTRYPOINT=${TRAEFIK_TCP_ENTRYPOINT} # 你在 traefik.yml 里把 :4443 命名为 tcp.env 已经配置为 tcp
- SERVICE_PROTOCOL=tcp
- ROUTE_HOST=${WOODPECKER_GRPC_HOST} # ci-agent.jmsu.top
- TLS_MODE=terminating # ★ A 方案Traefik 终止 TLS
- TRAEFIK_CERT_RESOLVER=alidns # ★ 用你已有的 alidns ACME
volumes: volumes:
- ./registrar.sh:/registrar.sh:ro - ./registrar.sh:/registrar.sh:ro
entrypoint: ["/bin/sh","/registrar.sh"] entrypoint: ["/bin/sh","/registrar.sh"]

View File

@@ -15,6 +15,8 @@ CHECK_TIMEOUT="${CHECK_TIMEOUT:-2s}"
DEREG_AFTER="${DEREG_AFTER:-1m}" DEREG_AFTER="${DEREG_AFTER:-1m}"
TRAEFIK_HTTP_ENTRYPOINT="${TRAEFIK_HTTP_ENTRYPOINT:-websecure}" TRAEFIK_HTTP_ENTRYPOINT="${TRAEFIK_HTTP_ENTRYPOINT:-websecure}"
TRAEFIK_TCP_ENTRYPOINT="${TRAEFIK_TCP_ENTRYPOINT:-tcp}" TRAEFIK_TCP_ENTRYPOINT="${TRAEFIK_TCP_ENTRYPOINT:-tcp}"
TRAEFIK_CERT_RESOLVER="${TRAEFIK_CERT_RESOLVER:-alidns}"
TLS_MODE="${TLS_MODE:-terminating}" # terminating | passthrough | plaintext
# TRAEFIK_CERT_RESOLVER="${TRAEFIK_CERT_RESOLVER:-cf}" # TRAEFIK_CERT_RESOLVER="${TRAEFIK_CERT_RESOLVER:-cf}"
echo "[registrar] consul: $CONSUL, service: $SERVICE_NAME@$SERVICE_ADDR:$SERVICE_PORT" echo "[registrar] consul: $CONSUL, service: $SERVICE_NAME@$SERVICE_ADDR:$SERVICE_PORT"
@@ -47,9 +49,35 @@ if [ "$SERVICE_PROTOCOL" = "http" ]; then
# 如需 ACME 证书解析器可再加一行(取消注释) # 如需 ACME 证书解析器可再加一行(取消注释)
# TAGS="$TAGS${NL}traefik.http.routers.${SERVICE_NAME}.tls.certresolver=${TRAEFIK_CERT_RESOLVER}" # TAGS="$TAGS${NL}traefik.http.routers.${SERVICE_NAME}.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
elif [ "$SERVICE_PROTOCOL" = "tcp" ]; then elif [ "$SERVICE_PROTOCOL" = "tcp" ]; then
TAGS="$TAGS${NL}traefik.tcp.routers.${SERVICE_NAME}.rule=HostSNI(\`${ROUTE_HOST}\`)" case "$TLS_MODE" in
TAGS="$TAGS${NL}traefik.tcp.routers.${SERVICE_NAME}.entrypoints=${TRAEFIK_TCP_ENTRYPOINT}" # ATraefik 终止 TLS推荐公网
TAGS="$TAGS${NL}traefik.tcp.services.${SERVICE_NAME}.loadbalancer.server.port=${SERVICE_PORT}" terminating)
TAGS="$TAGS${NL}traefik.tcp.routers.${SERVICE_NAME}.rule=HostSNI(\`${ROUTE_HOST}\`)"
TAGS="$TAGS${NL}traefik.tcp.routers.${SERVICE_NAME}.entrypoints=${TRAEFIK_TCP_ENTRYPOINT}"
TAGS="$TAGS${NL}traefik.tcp.routers.${SERVICE_NAME}.tls=true"
TAGS="$TAGS${NL}traefik.tcp.routers.${SERVICE_NAME}.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
TAGS="$TAGS${NL}traefik.tcp.services.${SERVICE_NAME}.loadbalancer.server.port=${SERVICE_PORT}"
;;
# A-备用:后端自己终止 TLS需要给 woodpecker-server 配 cert/key
passthrough)
TAGS="$TAGS${NL}traefik.tcp.routers.${SERVICE_NAME}.rule=HostSNI(\`${ROUTE_HOST}\`)"
TAGS="$TAGS${NL}traefik.tcp.routers.${SERVICE_NAME}.entrypoints=${TRAEFIK_TCP_ENTRYPOINT}"
TAGS="$TAGS${NL}traefik.tcp.routers.${SERVICE_NAME}.tls.passthrough=true"
TAGS="$TAGS${NL}traefik.tcp.services.${SERVICE_NAME}.loadbalancer.server.port=${SERVICE_PORT}"
;;
# B明文 TCP仅内网/Tailscale用 * 兜底)
plaintext)
TAGS="$TAGS${NL}traefik.tcp.routers.${SERVICE_NAME}.rule=HostSNI(\`*\`)"
TAGS="$TAGS${NL}traefik.tcp.routers.${SERVICE_NAME}.entrypoints=${TRAEFIK_TCP_ENTRYPOINT}"
TAGS="$TAGS${NL}traefik.tcp.routers.${SERVICE_NAME}.priority=1"
TAGS="$TAGS${NL}traefik.tcp.services.${SERVICE_NAME}.loadbalancer.server.port=${SERVICE_PORT}"
;;
*)
echo "unsupported TLS_MODE=$TLS_MODE" >&2; exit 2;;
esac
else else
echo "unsupported SERVICE_PROTOCOL=$SERVICE_PROTOCOL" >&2; exit 2 echo "unsupported SERVICE_PROTOCOL=$SERVICE_PROTOCOL" >&2; exit 2
fi fi