主题
Canal 部署(集群 192.168.122.31 / RKE2)
使用私有仓库镜像在 K8s 集群部署 Canal v1.1.8(MySQL binlog 增量订阅与消费组件)。
架构
┌──────────────────────────────────────────────┐
│ namespace: canal │
NodePort │ ┌─────────────┐ ┌────────────────┐ │
:30889 ──────► │ │ canal-admin │◄────────►│ canal-server-0 │ │
(Web UI) │ │ :8089 │ 11110 │ 11111/11110/ │ │
│ └──────┬──────┘ │ 11112 │ │
│ │ └───────┬────────┘ │
└─────────┼─────────────────────────┼──────────┘
│ JDBC (canal_manager 库) │ binlog 伪装从库
▼ ▼
┌─────────────────────────────────────────────┐
│ namespace: mysql │
│ mysql-primary.mysql.svc.cluster.local:3306 │
└─────────────────────────────────────────────┘| 组件 | 说明 | 端口 |
|---|---|---|
| canal-server | canal deployer,伪装 MySQL slave 拉取 binlog | 11111 (客户端 TCP) / 11110 (admin) / 11112 (metrics) |
| canal-admin | 管理控制台 Web UI | 8089 → NodePort 30889 |
前置条件(已完成)
- 镜像已推送私有仓库:
192.168.122.156:30000/canal/canal-admin:v1.1.8192.168.122.156:30000/canal/canal-server:v1.1.8- (Harbor
canal公共项目,ddn-k8s/docker.io/canal/*同步而来)
- RKE2 节点
/etc/rancher/rke2/registries.yaml已配置私有仓库认证(HTTP + insecure_skip_verify),拉取无需 imagePullSecret。 - MySQL 8.4(复用
mysql命名空间已有主从集群):log_bin=ON、binlog_format=ROW、binlog_row_image=FULL✅- 已创建
canal用户(caching_sha2_password,Canal 1.1.5+ 自研协议与 mysql-connector-j 8.0.33 均支持;无需开启已禁用的mysql_native_password)。 - 已导入
canal_manager元数据库(脚本来自 canal-admin 镜像内置/home/admin/canal-admin/conf/canal_manager.sql)。
公网访问(HTTPS)
地址:https://ai-ear.cn:30889/(公网出口经 Traefik TLS 终止 + basicAuth)
外网 → https://ai-ear.cn:30889
→ 公网 8.153.84.140 Traefik v3(ep30889,TLS 终止 + basic-auth 中间件)
→ 127.0.0.1:19089(frps 隧道,remotePort)
→ 本机 frpc(systemd user service: frpc-canal-admin.service)
→ 192.168.122.31:30889(K8s NodePort → canal-admin Pod:8089)| 层 | 位置 | 配置 |
|---|---|---|
| 公网反向代理 | 8.153.84.140:/etc/traefik/traefik.yaml | entryPoint ep30889: ":30889" |
| 路由/服务 | 8.153.84.140:/etc/traefik/dynamic.yaml | router canal-admin-30889(basic-auth + tls)→ service svc-19089 → http://127.0.0.1:19089 |
| frp 隧道 | 本机 /home/xxx/config/frp/frpc-canal-admin.toml | remotePort=19089 → localIP=192.168.122.31 localPort=30889 |
| frpc 服务 | 本机 ~/.config/systemd/user/frpc-canal-admin.service | systemctl --user status frpc-canal-admin |
访问凭据(两层):
- basicAuth(Traefik 层):\1xxx\2(
/etc/traefik/.htpasswd,与其他 9xxx 服务共用) - canal-admin 应用登录:\1xxx\2
bash
# 验证
curl -sk -o /dev/null -w '%{http_code}\n' https://ai-ear.cn:30889/ # 401(无 basicAuth)
curl -sk -u 'admin:xxx' -o /dev/null -w '%{http_code}\n' \
https://ai-ear.cn:30889/ # 200文件清单
canal/
├── README.md # 本文档
├── 00-namespace.yaml # namespace canal
├── 01-secret.yaml # 三个密码(mysql/admin 登录/server admin 端口)
├── 02-canal-server.yaml # ConfigMap + StatefulSet + Service(PVC 持久化位点)
├── 03-canal-admin.yaml # ConfigMap + Deployment + NodePort Service
└── mysql-init/
├── init-user.sql # canal 用户创建与授权(已执行,留档)
└── canal_manager.sql # canal-admin 元数据库表结构(已执行,留档)关键实现细节
1. 为什么用 initContainer 注入配置?
- canal-admin:启动脚本用
perl读取spring.datasource.address这类带点号的环境变量,而 K8s env 名称必须是[A-Za-z_][A-Za-z0-9_]*(不允许点号),无法直接注入 → 由 initContainer 渲染application.yml后整目录挂载。 - canal-server:镜像内
conf/example/instance.properties为硬编码值(无${ENV}占位符),同样由 initContainer 从 ConfigMap 注入并替换密码占位符。 - initContainer 仅首次启动复制镜像默认配置,之后只更新配置文件,PVC 中的
meta.dat位点数据得以保留,Pod 重启不丢位点。
2. MySQL 8.4 认证兼容
- MySQL 8.4 默认禁用
mysql_native_password插件(SHOW PLUGINS为 DISABLED,且无法运行时安装)。 - canal-server binlog 连接使用 Canal 自研 MySQL 协议(1.1.5+ 支持
caching_sha2_passwordRSA 公钥交换)。 - canal-admin 携带
mysql-connector-j-8.0.33,JDBC URL 需追加allowPublicKeyRetrieval=true(无 SSL 场景下caching_sha2_password首次认证需取服务端 RSA 公钥)。
3. 端口规划
| 服务 | 类型 | 端口 |
|---|---|---|
| canal-admin | NodePort | 30889 → 8089 |
| canal-server | ClusterIP | 11111 / 11110 / 11112 |
凭证
| 用途 | 账号 | 密码 | xxx |
|---|---|---|---|
MySQL canal 用户 | canal | kFiuzPs1I7sU9i6zpXeh | Secret canal-secret/mysql-password |
| canal-admin Web 登录 | admin | Canal@2026#Admin | Secret canal-secret/admin-login-password |
| canal-server admin 端口 (11110) | admin | xxx | Secret canal-secret/server-admin-password |
部署/更新
bash
export KUBECONFIG=~/.kube/config-122.31
kubectl apply -f 00-namespace.yaml -f 01-secret.yaml -f 02-canal-server.yaml -f 03-canal-admin.yaml
kubectl -n canal get pods -wMySQL 初始化(仅新环境需要):
bashkubectl exec -i -n mysql mysql-primary-0 -c mysql -- mysql -uroot -p'<root密码>' < mysql-init/init-user.sql # canal_manager.sql 可从 canal-admin 镜像提取,本目录已留档 kubectl exec -i -n mysql mysql-primary-0 -c mysql -- mysql -uroot -p'<root密码>' < mysql-init/canal_manager.sql
验证
bash
# 1. Pod 状态(两者均 1/1 Running)
kubectl -n canal get pods
# 2. canal-server 日志(出现 "the canal server is running now" 即成功)
kubectl -n canal exec canal-server-0 -- tail -20 /home/admin/canal-server/logs/canal/canal.log
# example instance 连接成功标志:
# find start position successfully, EntryPosition[journalName=mysql-bin.xxxxx...]
# 3. 登录 API 验证(返回 code:20000 与 token)
curl -s -X POST http://<节点IP>:30889/api/v1/user/login \
-H 'Content-Type: application/json' \
-d '{"username":"admin","password":"Canal@2026#Admin"}'
# 4. 端到端 binlog 捕获验证: 向 MySQL 写数据后查看 produce 计数增长
kubectl -n canal exec canal-server-0 -- wget -qO- 'http://127.0.0.1:11112/metrics?dest=example' \
| grep canal_instance_store_produce_seqcanal-admin 登录密码的存储格式(重要)
canal_manager.sql 预置 admin 用户(官方默认密码 xxx),密码列存储为 大写十六进制的双重 SHA1:SHA1(SHA1(password))(登录比对采用 MySQL-4.1.1 scramble 认证,SecurityUtil.scramble411/scrambleServerAuth)。
application.yml 中的 canal.adminPasswd 仅当数据库中不存在 admin 用户时 才作为初始化密码生效;本部署已导入预置用户,故直接更新数据库:
bash
HASH=$(python3 -c "import hashlib; print(hashlib.sha1(hashlib.sha1(b'<新密码>').digest()).hexdigest().upper())")
kubectl exec -n mysql mysql-primary-0 -c mysql -- \
mysql -uroot -p'<root密码>' -e "UPDATE canal_manager.canal_user SET password='xxx' WHERE username='xxx';"
# 注意: canal-admin 有 EBean L2 缓存,更新后需重启 Pod: kubectl -n canal delete pod -l app=canal-admin在 canal-admin 中纳管 canal-server
- 登录 Web UI(http://<节点IP>:30889)
- Canal Server → 主机管理 → 新建:
- 主机地址:
canal-server.canal.svc(或 Pod IP),端口11110 - 账号:xxx
server-admin-password)
- 主机地址:
- 新建 Instance:名称
example,数据源指向mysql-primary.mysql.svc.cluster.local:3306,dbUsername/dbPassword 使用 canal 用户,投放到该 Server。 (本部署 canal-server 已通过 ConfigMap 内置exampleinstance,可直接在界面查看运行状态。)
客户端连接示例
地址: canal-server.canal.svc.cluster.local:11111
destination: example常用运维
bash
# 查看 binlog 位点
kubectl -n canal exec canal-server-0 -- cat /home/admin/canal-server/conf/example/meta.dat
# 重启(位点保留在 PVC)
kubectl -n canal rollout restart statefulset/canal-server
# 完全重建(会重新从 binlog 起始位置消费,慎用)
kubectl -n canal delete pvc conf-canal-server-0 && kubectl -n canal delete sts canal-server
kubectl apply -f 02-canal-server.yaml