Ubuntu 22.04 安装 OpenZiti 指南
Ubuntu 22.04 安装 OpenZiti v2.0.8 全流程实测:二进制部署 controller/router/tunneler 与 APT 软件包安装 ziti-edge-tunnel 双方案、systemd 托管、端到端服务验证,以及 11 条 v2.0 部署排障实录。
Ubuntu 22.04 安装 OpenZiti 指南
一、环境信息
本文所有命令与回显均在以下环境实测(2026-10-20),其他环境请按实际情况替换 IP、主机名与口令:
| 项目 | 值 |
|---|---|
| 操作系统 | Ubuntu 22.04.5 LTS(x86_64,systemd 249.11 托管服务) |
| 主机名 / 地址 | ziti-srv / 10.89.57.2(内网静态地址,请按实际替换) |
| OpenZiti 版本 | ziti v2.0.8(2026-10-20 官方最新稳定版,GitHub releases/latest 重定向实测) |
| ziti-edge-tunnel 版本 | v1.18.7(二进制与 APT 软件包均为该版本) |
| 基础工具 | bash 5.1.16、curl 7.81.0、GNU tar 1.34 |
| 安装路径 | 二进制 /usr/local/bin/ziti;配置与数据 /opt/ziti/;软件包形态的隧道器 /opt/openziti/ |
| 端口规划 | controller 1280(API)、6262(集群控制通道);router 3022(边缘接入)、10080(链路) |
版本选择说明:OpenZiti v2.0 起默认启用基于 Raft 的 HA 控制器,移除了 v1 的
ziti controller init引导命令,v1 时代的多数安装教程已不适用。本文按 v2.0.8 的官方流程组织。
二、前置条件
- 一台具有 sudo 权限的 Ubuntu 22.04 服务器,能访问公网(下载二进制或软件包);
- 已安装
curl(本例 7.81.0);方案 B 还需要gnupg; - 若需要客户端隧道器接管系统 DNS,系统使用 systemd-resolved(Ubuntu 22.04 默认启用);
- 服务器时间已同步(证书校验对时间敏感)。
三、安装方案 A:官方二进制包安装(含 controller/router/tunneler 全组件)
3.1 下载并安装 ziti CLI
# 下载官方 Linux amd64 包
curl -sL -o /tmp/ziti.tar.gz "https://github.com/openziti/ziti/releases/download/v2.0.8/ziti-linux-amd64-2.0.8.tar.gz"
# 校验并查看包内容
sha256sum /tmp/ziti.tar.gz
tar -tf /tmp/ziti.tar.gz
实测回显:
cf016a9fa19124f1932c1d73435e68e398bae15d6d5c3fef9688a22df61f7aba /tmp/ziti.tar.gz
ziti
包内只有一个 ziti 可执行文件,解压并安装到 PATH:
cd /tmp && tar -xzf ziti.tar.gz
mv ziti /usr/local/bin/ziti
chmod +x /usr/local/bin/ziti
ziti version
实测回显:
v2.0.8
3.2 规划目录
mkdir -p /opt/ziti/controller /opt/ziti/router /opt/ziti/tunnel
注意:后续所有
ziti create config命令都必须在设置了ZITI_HOME的会话中执行,否则生成的配置文件里证书路径会变成//raft、/ziti-srv.key这类空根路径,controller 启动直接失败(见第八节排障 2)。
3.3 生成 controller 配置
export ZITI_HOME=/opt/ziti/controller
ziti create config controller --ctrlPort 6262 --output $ZITI_HOME/controller.yaml
生成的 controller.yaml 关键内容(逐字段解读见《OpenZiti 2.0.8 配置参数详解》):
v: 3
cluster:
dataDir: "/opt/ziti/controller/raft"
identity:
cert: "/opt/ziti/controller/ziti-srvclient.chain.cert"
server_cert: "/opt/ziti/controller/ziti-srv.server.chain.cert"
key: "/opt/ziti/controller/ziti-srv.key"
ca: "/opt/ziti/controller/ziti-srv.ca"
ctrl:
options:
advertiseAddress: tls:ziti-srv:6262
listener: tls:0.0.0.0:6262
edge:
api:
sessionTimeout: 30m
address: ziti-srv:1280
enrollment:
signingCert:
cert: /opt/ziti/controller/ziti-srv.signing.cert
key: /opt/ziti/controller/ziti-srv.signing.key
edgeIdentity:
duration: 180m
edgeRouter:
duration: 180m
web:
- name: client-management
bindPoints:
- interface: 0.0.0.0:1280
address: ziti-srv:1280
identity:
ca: "/opt/ziti/controller/ziti-srv.ca"
key: "/opt/ziti/controller/ziti-srv.key"
server_cert: "/opt/ziti/controller/ziti-srv.server.chain.cert"
cert: "/opt/ziti/controller/ziti-srvclient.chain.cert"
options:
minTLSVersion: TLS1.2
maxTLSVersion: TLS1.3
apis:
- binding: edge-management
- binding: edge-client
- binding: fabric
- binding: edge-oidc
生成配置中 identity、web[].identity、edge.enrollment.signingCert 都引用 ZITI_HOME 下待生成的证书文件——下一步先用 ziti pki 生成它们,再把路径替换为实际位置。
3.4 生成 controller 证书(PKI)
v2.0 官方引导流程要求 controller 证书携带 SPIFFE ID(spiffe://<信任域>/controller/<控制器ID>),单节点部署按以下命令生成:
cd $ZITI_HOME
ziti pki create ca --trust-domain ziti.example.com --pki-root pki --ca-file root-ca --ca-name "Ziti Root CA"
ziti pki create intermediate --pki-root pki --ca-name root-ca --intermediate-file ziti-srv --intermediate-name "Ziti Controller Signing Cert"
ziti pki create server --pki-root pki --ca-name ziti-srv --dns "localhost,ziti-srv" --ip "127.0.0.1,::1" --server-name ziti-srv --spiffe-id "controller/ziti-srv"
三条命令的实测回显格式相同(各为两行):
Success
Using CA name: ziti-srv
生成结果位于 pki/ 目录(实测文件树节选):
pki/root-ca/certs/root-ca.cert
pki/ziti-srv/certs/server.chain.pem
pki/ziti-srv/certs/server.cert
pki/ziti-srv/certs/ziti-srv.cert
pki/ziti-srv/certs/ziti-srv.chain.pem
pki/ziti-srv/keys/server.key
pki/ziti-srv/keys/ziti-srv.key
OpenZiti 的 PKI 工具生成的证书不限制 ExtKeyUsage,服务端证书可直接当客户端证书使用(官方文档"单证书双角色"变体),因此本例不再单独生成 client 证书,identity.cert 与 identity.server_cert 都指向 server.chain.pem,避免客户端/服务端证书密钥错配。
把配置中的占位路径替换为实际文件(sed 或手工编辑均可):
sed -i -e "s|/opt/ziti/controller/ziti-srvclient.chain.cert|/opt/ziti/controller/pki/ziti-srv/certs/server.chain.pem|g" \
-e "s|/opt/ziti/controller/ziti-srv.server.chain.cert|/opt/ziti/controller/pki/ziti-srv/certs/server.chain.pem|g" \
-e "s|/opt/ziti/controller/ziti-srv.key|/opt/ziti/controller/pki/ziti-srv/keys/server.key|g" \
-e "s|/opt/ziti/controller/ziti-srv.ca|/opt/ziti/controller/pki/ziti-srv/certs/ziti-srv.chain.pem|g" \
-e "s|/opt/ziti/controller/ziti-srv.signing.cert|/opt/ziti/controller/pki/ziti-srv/certs/ziti-srv.cert|g" \
-e "s|/opt/ziti/controller/ziti-srv.signing.key|/opt/ziti/controller/pki/ziti-srv/keys/ziti-srv.key|g" \
$ZITI_HOME/controller.yaml
3.5 启动 controller 并初始化管理员
v2.0 的引导顺序是:先启动 controller(此时它处于等待初始化状态),再用 ziti agent cluster init 创建默认管理员。
export ZITI_HOME=/opt/ziti/controller
ziti controller run $ZITI_HOME/controller.yaml > $ZITI_HOME/controller.log 2>&1 &
sleep 12
grep -m1 checkEdgeInitialized $ZITI_HOME/controller.log
实测日志(未初始化状态的关键行,JSON 格式日志):
{"file":"github.com/openziti/ziti/v2/controller/server/controller.go:275","func":"github.com/openziti/ziti/v2/controller/server.(*Controller).checkEdgeInitialized","level":"warning","msg":"the controller has not yet been initialized, no default admin exists. Add this node to a cluster using 'ziti agent cluster add tls:ziti-srv:16262' against an existing cluster member, or if this is the bootstrap node, run 'ziti agent cluster init' to configure the default admin and bootstrap the cluster","time":"2026-10-20T16:57:08.215Z"}
提示:日志地址中的端口随配置而异(上例来自备用端口 16262 的复现实例),只要出现
has not yet been initialized即为正常等待状态。初始化集群管理员(口令按等保要求自行设定):
ziti agent cluster init admin 'q1w2e3r4' ziti-srv
初始化完成后再执行 ziti agent cluster list 验证。注意:本机同时跑着 controller 与 router 时,agent 类命令需要用 -i <控制器ID> 指定目标,否则报 too many processes found matching filter:
ziti agent cluster list -i ziti-srv
实测回显:
╭──────────┬───────────────────┬───────┬────────┬─────────┬───────────┬───────────╮
│ ID │ ADDRESS │ VOTER │ LEADER │ VERSION │ CONNECTED │ PREFERRED │
├──────────┼───────────────────┼───────┼────────┼─────────┼───────────┼───────────┤
│ ziti-srv │ tls:ziti-srv:6262 │ true │ true │ v2.0.8 │ true │ false │
╰──────────┴───────────────────┴───────┴────────┴─────────┴───────────┴───────────╯
登录验证:
ziti login https://127.0.0.1:1280 -u admin -p 'q1w2e3r4' -y
实测回显:
Saving identity 'default' to /root/.config/ziti/ziti-cli.json
-y表示信任自签名证书。登录态保存在/root/.config/ziti/ziti-cli.json,后续 CLI 命令无需重复登录。
3.6 创建并注册边缘路由器
export ZITI_HOME=/opt/ziti/router
# 在控制面注册路由器并签发注册 JWT(-t 表示启用隧道器绑定)
ziti create edge-router ziti-er1 -t -o $ZITI_HOME/ziti-er1.jwt
# 生成路由器配置(此命令成功时无输出)
ziti create config router edge --routerName ziti-er1 --tunnelerMode host --output $ZITI_HOME/ziti-er1.yaml
第一条命令实测回显:
New edge router ziti-er1 created with id: X1fqRSZEB-
Enrollment expires at 2026-10-20T19:49:32.838Z
注册 JWT 有效期 24 小时(回显的到期时间),过期需重新创建。随后用 JWT 完成注册并启动:
ziti router enroll $ZITI_HOME/ziti-er1.yaml -j $ZITI_HOME/ziti-er1.jwt
ziti router run $ZITI_HOME/ziti-er1.yaml > $ZITI_HOME/router.log 2>&1 &
sleep 12
grep -c '"level":"error"' $ZITI_HOME/router.log || true
注册命令实测回显(节选最后 2 行):
{"file":"github.com/openziti/ziti/v2/router/enroll/enroll.go:233","func":"github.com/openziti/ziti/v2/router/enroll.(*RestEnroller).Enroll","level":"info","msg":"deleting existing router data model save file","path":"/opt/ziti/router/ziti-er1.yaml.proto.gzip","time":"2026-10-20T16:49:32.952Z"}
{"file":"github.com/openziti/ziti/v2/router/enroll/enroll.go:242","func":"github.com/openziti/ziti/v2/router/enroll.(*RestEnroller).Enroll","level":"info","msg":"registration complete","time":"2026-10-20T16:49:32.952Z"}
验证路由器上线:
ziti list edge-routers
实测回显:
╭────────────┬──────────┬────────┬───────────────┬──────┬────────────╮
│ ID │ NAME │ ONLINE │ ALLOW TRANSIT │ COST │ ATTRIBUTES │
├────────────┼──────────┼────────┼───────────────┼──────┼────────────┤
│ X1fqRSZEB- │ ziti-er1 │ true │ true │ 0 │ │
╰────────────┴──────────┴────────┴───────────────┴──────┴────────────╯
results: 1-1 of 1
3.7 安装 ziti-edge-tunnel 隧道器
# 下载官方 Linux x86_64 包(与 ziti 主程序无强制版本绑定,取官方最新即可)
curl -sL -o /tmp/zt.zip "https://github.com/openziti/ziti-tunnel-sdk-c/releases/download/v1.18.7/ziti-edge-tunnel-Linux_x86_64.zip"
unzip -o /tmp/zt.zip -d /opt/ziti/tunnel
chmod +x /opt/ziti/tunnel/ziti-edge-tunnel
解压产物(实测):
Archive: /tmp/zt.zip
inflating: /opt/ziti/tunnel/config.json
inflating: /opt/ziti/tunnel/ziti-edge-tunnel
创建客户端身份并注册:
ziti create identity ziti-tun1 -a dialers -o /opt/ziti/tunnel/ziti-tun1.jwt
cd /opt/ziti/tunnel
./ziti-edge-tunnel enroll -j ziti-tun1.jwt -i ziti-tun1.json -n ziti-tun1
创建身份的实测回显:
New identity ziti-tun1 created with id: z-AqRSZEB
Enrollment expires at 2026-10-20T19:50:03.440Z
注册的实测回显(退出码 0):
(5692)[ 0.000] INFO ziti-sdk:utils.c:200 ziti_log_set_level() set log level: root=3/INFO
(5692)[ 0.000] INFO ziti-sdk:utils.c:171 ziti_log_init() Ziti C SDK version 1.18.7 @gabc980e(HEAD) starting at (2026-10-20T16:50:18.543)
(5692)[ 0.000] INFO ziti-sdk:ziti_enroll.c:124 ziti_enroll() Ziti C SDK version 1.18.7 @gabc980e(HEAD) starting enrollment at (2026-10-20T16:50:18.543)
(5692)[ 0.002] INFO ziti-sdk:ziti_ctrl.c:643 ziti_ctrl_init() ctrl[https://ziti-srv:1280] controller initialized
(5692)[ 0.009] INFO ziti-sdk:ziti_ctrl.c:643 ziti_ctrl_init() ctrl[https://ziti-srv:1280] controller initialized
注册成功会生成身份私钥文件
ziti-tun1.json(0600 权限),请妥善备份;对已存在的 JSON 重复执行 enroll 会报failed to open file ziti-tun1.json: File exists(见第八节排障 7)。
运行隧道器(需要 root 与 /dev/net/tun):
mkdir -p /dev/net && [ -e /dev/net/tun ] || mknod /dev/net/tun c 10 200
chmod 666 /dev/net/tun
nohup ./ziti-edge-tunnel run -i ziti-tun1.json > tunnel.log 2>&1 &
sleep 8
ip -br addr | grep ziti
实测回显:
ziti0 UNKNOWN 100.64.0.1/32
隧道器会接管服务名 DNS:系统若启用 systemd-resolved 会自动注册;否则把 100.64.0.2(隧道器内置 DNS)放到解析链首位,详见 7.5 节。
四、安装方案 B:软件仓库安装(仅 ziti-edge-tunnel)
官方维护 Ubuntu/Debian APT 仓库,提供 ziti-edge-tunnel 及其 systemd 服务,适合"只做接入端"的服务器。
4.1 添加仓库并安装
apt-get update && apt-get install -y gnupg
# 导入签名公钥
curl -sSLf https://get.openziti.io/tun/package-repos.gpg | gpg --dearmor --output /usr/share/keyrings/openziti.gpg
chmod -c +r /usr/share/keyrings/openziti.gpg
# 配置 jammy(Ubuntu 22.04)仓库源
echo "deb [signed-by=/usr/share/keyrings/openziti.gpg] https://packages.openziti.org/zitipax-openziti-deb-stable jammy main" | tee /etc/apt/sources.list.d/openziti.list
apt-get update
apt-cache policy ziti-edge-tunnel
实测回显(节选):
ziti-edge-tunnel:
Installed: (none)
Candidate: 1.18.7
Version table:
1.18.7 500
500 https://packages.openziti.org/zitipax-openziti-deb-stable jammy/main amd64 Packages
apt-get install -y ziti-edge-tunnel
安装完成后(实测):
- 二进制:
/usr/bin/ziti-edge-tunnel(ziti-edge-tunnel version输出v1.18.7); - 专用系统用户与用户组:
ziti; - 配置目录:
/opt/openziti/(身份目录/opt/openziti/etc/identities); - systemd 单元:
ziti-edge-tunnel.service(WantedBy=multi-user.target)。
4.2 启用服务并添加身份
systemctl enable --now ziti-edge-tunnel.service
systemctl is-active ziti-edge-tunnel.service
# 用注册 JWT 添加身份(无需重启服务)
ziti-edge-tunnel add --jwt "$(< /opt/ziti/tunnel/ziti-tun2.jwt)" --identity ziti-tun2
第三条命令实测回显:
{
"Success":true,
"Code":0
}
添加后隧道器创建 TUN 接口(实测接口名 ziti1,接口编号在多个隧道器实例间递增),查看:
ip -br addr | grep ziti
ziti1 UNKNOWN 100.64.0.1/32
两种形态区别:软件包版以
ziti用户运行并配合--identity-dir /opt/openziti/etc/identities自动加载目录下全部身份;二进制版以 root 手工运行、逐个指定身份 JSON。生产建议用软件包版。add成功后身份 JSON 会出现在/opt/openziti/etc/identities/目录,服务重启时自动加载。
五、方案对比与选择建议
| 维度 | 方案 A:二进制包 | 方案 B:APT 软件仓库 |
|---|---|---|
| 组件范围 | controller / router / ziti-edge-tunnel 全组件 | 仅 ziti-edge-tunnel |
| 版本 | GitHub Releases 任意版本可固定 | 仓库最新版(1.18.7) |
| 升级方式 | 替换二进制 | apt 升级 |
| 服务托管 | 需自写 systemd 单元(第六节) | 官方单元开箱即用 |
| 适用角色 | 服务端(控制器/路由器)与客户端均适用 | 仅客户端接入 |
建议:服务端用方案 A 固定版本部署,客户端用方案 B 获取自动更新。
六、systemd 服务托管(controller 与 router)
方案 A 的 controller/router 建议托管为 systemd 服务。单元文件(实测可用):
/etc/systemd/system/ziti-controller.service:
[Unit]
Description=OpenZiti Controller
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
Environment=ZITI_HOME=/opt/ziti/controller
ExecStart=/usr/local/bin/ziti controller run /opt/ziti/controller/controller.yaml
Restart=on-failure
RestartSec=5
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
/etc/systemd/system/ziti-router.service:
[Unit]
Description=OpenZiti Edge Router
After=network-online.target ziti-controller.service
Wants=network-online.target
[Service]
Type=simple
User=root
Environment=ZITI_HOME=/opt/ziti/router
ExecStart=/usr/local/bin/ziti router run /opt/ziti/router/ziti-er1.yaml
Restart=on-failure
RestartSec=5
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
启用并验证:
systemctl daemon-reload
systemctl enable ziti-controller.service ziti-router.service
systemctl start ziti-controller.service && sleep 10
systemctl start ziti-router.service && sleep 8
systemctl status ziti-controller.service --no-pager -n 3
实测回显(节选):
Synchronizing state of ziti-controller.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable ziti-controller
Created symlink /etc/systemd/system/multi-user.target.wants/ziti-controller.service → /etc/systemd/system/ziti-controller.service.
Created symlink /etc/systemd/system/multi-user.target.wants/ziti-router.service → /etc/systemd/system/ziti-router.service.
● ziti-controller.service - OpenZiti Controller
Loaded: loaded (/etc/systemd/system/ziti-controller.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2026-10-20 04:44:23 UTC; 15s ago
Main PID: 6724 (ziti)
Tasks: 14 (limit: 4543)
Memory: 40.0M
CPU: 1.366s
CGroup: /system.slice/ziti-controller.service
└─6724 /usr/local/bin/ziti controller run /opt/ziti/controller/controller.yaml
注意:如果手工 nohup 拉起过 controller/router,托管前先停掉旧进程,避免端口冲突。停止 ziti 进程请用 pkill -x ziti(精确匹配进程名);pkill -f "ziti controller run" 会匹配到执行命令的 shell 自身导致误杀(实测返回退出码 143)。systemd 托管后日志进入 journal,用 journalctl -u ziti-router -f 查看,不再写入 nohup 时代的 router.log。
七、验证与快速开始
7.1 检查监听端口
ss -ltn | grep -E ':(1280|6262|3022|10080) '
实测回显:
LISTEN 0 4096 *:10080 *:*
LISTEN 0 4096 *:3022 *:*
LISTEN 0 4096 *:1280 *:*
LISTEN 0 4096 *:6262 *:*
7.2 发布第一个服务(服务端承载)
在本机起一个测试后端,并创建服务与策略:
nohup python3 -m http.server 8000 --bind 127.0.0.1 > /opt/ziti/http80.log 2>&1 &
ziti create config webtest-host host.v1 '{"protocol":"tcp","address":"127.0.0.1","port":8000}'
ziti create config webtest-int intercept.v1 '{"protocols":["tcp"],"addresses":["webtest.svc.ziti"],"portRanges":[{"low":80,"high":80}]}'
ziti create service webtest -a webtest -c webtest-host,webtest-int
ziti create service-policy webtest-bind Bind --service-roles "#webtest" --identity-roles "@ziti-er1"
ziti create service-policy webtest-dial Dial --service-roles "#webtest" --identity-roles "#dialers"
# v2.0 必须显式创建以下两类路由器策略,否则拨号报 NO_EDGE_ROUTERS_AVAILABLE(见第八节排障 5)
ziti create service-edge-router-policy all-serp --edge-router-roles "#all" --service-roles "#all"
ziti create edge-router-policy all-erp --edge-router-roles "#all" --identity-roles "#all"
各命令实测回显:
New config webtest-host created with id: 77agKDQb3R65BgGueKRF1C
New config webtest-int created with id: 70syNFnSyoE2KaSyG89VjP
New service webtest created with id: 5ns6cgf8tyRZe6UUn7mUhb
New service policy webtest-bind created with id: 4QScvLu1UTPggnZSOSesPq
New service policy webtest-dial created with id: 3pfhBNDsOMZNNSVOfmop9S
New service edge router policy all-serp created with id: SLoYjHlJZEMHrrUh0VnzB
New edge router policy all-erp created with id: 5Spnyax9gnotI6FLeoPvZl
host.v1 配置若使用
forwardAddress: true等透明转发字段,会触发 if/then 模式校验(要求配套 allowedProtocols 等字段),最小可用写法就是上面这种静态protocol/address/port组合。
7.3 端到端拨号验证
隧道器身份 ziti-tun1/ziti-tun2 携带 #dialers 属性并已注册,等待策略同步与终结器建立(实测约 20~40 秒)后验证:
dig +short webtest.svc.ziti
for i in 1 2 3; do curl -s -o /dev/null -w "第${i}次: HTTP %{http_code} %{time_total}s\n" http://webtest.svc.ziti/ --max-time 20; done
实测回显:
100.64.0.3
第1次: HTTP 200 0.044270s
第2次: HTTP 200 0.080374s
第3次: HTTP 200 0.080529s
访问 http://webtest.svc.ziti/ 返回的正是 8000 端口后端的响应(python http.server 的目录页 HTML),链路为 curl → ziti-edge-tunnel(TUN 拦截)→ edge router → host.v1 转发 → 127.0.0.1:8000,服务端全程未暴露任何公网端口。
7.4 策略诊断
若拨号不通,用策略顾问检查"身份 → 服务"链路:
ziti edge policy-advisor identities ziti-tun2 | tail -1
正常时实测回显:
OKAY : ziti-tun2 (1) -> webtest (1) Common Routers: (1/1) Dial: Y Bind: N
7.5 DNS 解析模型
隧道器在 TUN 网段内置 DNS(默认 100.64.0.2),负责把授权服务名解析为拦截地址:
- systemd-resolved 启用时:隧道器自动注册,无需手工配置;
- 未启用或需要显式控制时:把隧道器 DNS 放到解析链第一位,未匹配的服务名查询会被隧道器以 REFUSE 拒绝、解析器继续问后续上游。
/etc/systemd/resolved.conf.d/upstream.conf示例(实测):
[Resolve]
DNS=100.64.0.2 8.8.8.8 1.1.1.1
实测两种域名都正常解析:dig +short webtest.svc.ziti → 100.64.0.3,dig +short github.com → 20.205.243.166。
八、常见问题与排障实录
1. ziti controller init 命令不存在
v2.0 移除了该命令(ziti controller --help 子命令列表中无 init),改为启动 controller 后执行 ziti agent cluster init <用户名> <口令> <名称>。v1 教程照抄会一直停在"controller 未初始化"日志。
2. 生成的配置里路径是 //raft、/ziti-srv.key
ziti create config 按环境变量 ZITI_HOME 展开路径,未设置时占位符为空。实测启动报错:
unable to load identity (no file found at [/opt/ziti/controller/ziti-srv.key] but a new key spec was not provided)
解决:export ZITI_HOME=/opt/ziti/controller 后重新生成配置,并按 3.3/3.4 节替换证书路径。
3. controller 启动即退出,日志只有 identity 加载失败
原因是配置引用的证书文件不存在。确认 3.4 节三条 ziti pki 命令都已执行、find pki -type f 能看到 server.cert/server.key/server.chain.pem/ziti-srv.cert 等文件,再核对 controller.yaml 中 identity 与 web[].identity 的路径。
4. ziti pki create client 报 a bundle already exists for the name ... within CA ...
PKI 工具不允许覆盖同名 bundle。对策:改用别的名称(如 ziti-srv-client),或直接采用 3.4 节"单证书双角色"变体,用 server 证书兼任 client 证书(OpenZiti 证书不限制 ExtKeyUsage,官方文档认可此做法)。
5. 拨号报 NO_EDGE_ROUTERS_AVAILABLE - No edge routers are assigned and ...
v2.0 不再默认创建 #all 的 Edge Router Policy 与 Service-Edge-Router Policy(实测 ziti list edge-router-policies 仅有路由器自建的一条)。按 7.2 节补建 all-erp 与 all-serp 后恢复。诊断路径:ziti edge policy-advisor identities <身份名>,若显示 Identity has no edge routers assigned 即身份侧缺 ERP。
6. 策略正确但仍报 service ... has no terminators
承载端(bind)需要边缘路由器数据模型同步完成才能建立终结器,实测从创建策略到终结器可用约 20~40 秒,期间隧道器日志持续出现 failed to connect, reason=service ... has no terminators;路由器 journal 中 queuing terminator → terminator established 即就绪,等待后重测即可。
7. ziti-edge-tunnel enroll 报 failed to open file ...: File exists
enroll 不覆盖已存在的身份 JSON。删除同名 JSON 后重新执行,或换名注册。
8. 同机多个隧道器实例互相抢占路由
手工运行的隧道器被杀后 TUN 接口(如 ziti0)可能残留并持有 100.64.0.0/10 路由,新实例(ziti1)的拨号会被路由到死接口,表现为 curl 秒失败(实测 0.0008s 返回 HTTP 000)。排查:ip route | grep 100.64 看路由落在哪个接口,ip link del ziti0 删除残留接口后重启隧道服务。多实例场景建议只保留软件包服务这一种形态。
9. 软件包隧道器启动失败 failed to open network interface: open /dev/net/tun failed
服务以 ziti 用户运行,需要 /dev/net/tun 对其可读写(常规桌面/服务器由 udev 置为 0666)。最小化环境若手工 mknod 创建过设备,执行 chmod 666 /dev/net/tun 后 systemctl restart ziti-edge-tunnel.service。
10. 服务名解析 NXDOMAIN
隧道器 DNS 未生效或未被优先查询。确认 resolvectl status ziti0(或对应接口)能看到 DNS Servers 100.64.0.2,并按 7.5 节把 100.64.0.2 置首;也可直接向隧道器 DNS 查询验证:dig +short webtest.svc.ziti @100.64.0.2。
11. 批量停止 ziti 进程时 shell 被误杀
pkill -f "ziti controller run" 会匹配到包含该字符串的命令行(包括正在执行的 shell),实测返回 143。用 pkill -x ziti(按进程名精确匹配)替代。
九、卸载与清理
# 停止并移除 systemd 单元
pkill -x ziti || true
systemctl disable --now ziti-controller.service ziti-router.service 2>/dev/null
rm -f /etc/systemd/system/ziti-controller.service /etc/systemd/system/ziti-router.service
systemctl daemon-reload
# 方案 A 产物
rm -f /usr/local/bin/ziti
rm -rf /opt/ziti
# 方案 B 产物
systemctl disable --now ziti-edge-tunnel.service 2>/dev/null
apt-get remove -y ziti-edge-tunnel
rm -f /etc/apt/sources.list.d/openziti.list /usr/share/keyrings/openziti.gpg
rm -rf /opt/openziti
apt-get update
十、参考链接
- OpenZiti 官方下载页(含 get.openziti.io 安装脚本说明):https://openziti.io/docs/downloads/
- HA 集群初始化文档(
ziti agent cluster init):https://openziti.io/docs/reference/ha/bootstrapping/initialization/ - 控制器证书与 SPIFFE 信任域文档:https://netfoundry.io/docs/openziti/reference/ha/bootstrapping/certificates
- Linux 隧道器 Debian 软件包文档(仓库与 resolver 配置):https://openziti.io/docs/reference/tunnelers/linux/debian-package/
- ziti v2.0.8 发布页:https://github.com/openziti/ziti/releases/tag/v2.0.8
- ziti-edge-tunnel v1.18.7 发布页:https://github.com/openziti/ziti-tunnel-sdk-c/releases/tag/v1.18.7
- 站内相关文档:《OpenZiti 介绍与选型指南》、《OpenZiti 2.0.8 配置参数详解》、《OpenZiti 2.0.8 常用 CLI 命令详解(ziti CLI)》