k8s集群中部署canal集群

k8s集群中部署canal集群

canal原理详见[wiki](Home · alibaba/canal Wiki · GitHub),简单理解为

1、 canal将自己伪装成一个mysql的从服务器,向主服务器发送dump协议
2、 mysql主服务器收到dump协议后,推送binlog日志给canal
3、 canal解析binlog日志流

角色及功能

角色 功能
mysql 存储canal-admin、canal-server相关数据
zookeeper 存储集群、客户端、消费位点等相关信息。负责canal-server之间的负载调度
canal-admin 提供可视化界面,管理canal-server
canal-server 工作节点

前置条件

  • mysql

  • zookeeper

注意事项

  • 使用canal监听的mysql必须开启binlog,且必须是row模式

  • canal-clent必须使用四层网络连接到canal-server

  • canal-admin使用mysql存储数据信息;如果不指定外部数据库的话,canal-admin会在本地启一个mysql用作数据存储

  • 如使用外部数据库,需要对数据库进行初始化操作,可以到[github](GitHub - alibaba/canal: 阿里巴巴 MySQL binlog 增量订阅&消费组件)上获取初始化脚本

  • canal-admin的web页面的默认登陆用户密码是:admin/123456

  • canal-admin 与 canal-server采用双向验证的方式保证连接

  • canal-server仅作为工作节点,不存储任何数据

  • instance的监控位点信息存储在zookeeper中

  • 新建的instance名称需要在该zookeeper保持唯一

一、部署canal-admin

1.1、初始化数据库

  • 需要两个库,一个用来存放canal-admin的数据,需要使用sql进行初始化操作;另一个用来存放canal-server工作时instance监听的库的数据结构信息,无需初始化

canal-admin的初始化sql如下

CREATE DATABASE /*!32312 IF NOT EXISTS*/ `canal_manager` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_bin */;

USE `canal_manager`;

SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for canal_adapter_config
-- ----------------------------
DROP TABLE IF EXISTS `canal_adapter_config`;
CREATE TABLE `canal_adapter_config` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `category` varchar(45) NOT NULL,
  `name` varchar(45) NOT NULL,
  `status` varchar(45) DEFAULT NULL,
  `content` text NOT NULL,
  `modified_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for canal_cluster
-- ----------------------------
DROP TABLE IF EXISTS `canal_cluster`;
CREATE TABLE `canal_cluster` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(63) NOT NULL,
  `zk_hosts` varchar(255) NOT NULL,
  `modified_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for canal_config
-- ----------------------------
DROP TABLE IF EXISTS `canal_config`;
CREATE TABLE `canal_config` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `cluster_id` bigint(20) DEFAULT NULL,
  `server_id` bigint(20) DEFAULT NULL,
  `name` varchar(45) NOT NULL,
  `status` varchar(45) DEFAULT NULL,
  `content` text NOT NULL,
  `content_md5` varchar(128) NOT NULL,
  `modified_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `sid_UNIQUE` (`server_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for canal_instance_config
-- ----------------------------
DROP TABLE IF EXISTS `canal_instance_config`;
CREATE TABLE `canal_instance_config` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `cluster_id` bigint(20) DEFAULT NULL,
  `server_id` bigint(20) DEFAULT NULL,
  `name` varchar(45) NOT NULL,
  `status` varchar(45) DEFAULT NULL,
  `content` text NOT NULL,
  `content_md5` varchar(128) DEFAULT NULL,
  `modified_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `name_UNIQUE` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for canal_node_server
-- ----------------------------
DROP TABLE IF EXISTS `canal_node_server`;
CREATE TABLE `canal_node_server` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `cluster_id` bigint(20) DEFAULT NULL,
  `name` varchar(63) NOT NULL,
  `ip` varchar(63) NOT NULL,
  `admin_port` int(11) DEFAULT NULL,
  `tcp_port` int(11) DEFAULT NULL,
  `metric_port` int(11) DEFAULT NULL,
  `status` varchar(45) DEFAULT NULL,
  `modified_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for canal_user
-- ----------------------------
DROP TABLE IF EXISTS `canal_user`;
CREATE TABLE `canal_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(31) NOT NULL,
  `password` varchar(128) NOT NULL,
  `name` varchar(31) NOT NULL,
  `roles` varchar(31) NOT NULL,
  `introduction` varchar(255) DEFAULT NULL,
  `avatar` varchar(255) DEFAULT NULL,
  `creation_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

SET FOREIGN_KEY_CHECKS = 1;

-- ----------------------------
-- Records of canal_user
-- ----------------------------
BEGIN;
INSERT INTO `canal_user` VALUES (1, 'admin', '6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9', 'Canal Manager', 'admin', NULL, NULL, '2019-07-14 00:05:28');
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;

1.2、部署canal-admin

官方提供了canal-admin的镜像,可以使用官方镜像直接进行部署

部署时需要使用ENV的方式定义一些acnal-admin中的参数

        - env:
            # 服务端口
            - name: server.port
              value: '8089'
            # 外部数据的URL
            - name: spring.datasource.address
              value: '192.168.31.204:3306'
            # 数据库名称
            - name: spring.datasource.database
              value: canal_admin
            # 数据库用户名
            - name: spring.datasource.username
              value: canal_admin
            # 数据库密码
            - name: spring.datasource.password
              value: 123qwe!@#QWE
            # 用来与canal-server连接的用户名
            - name: canal.adminUser
              value: admin
            # 用来与canal-server连接的密码(明文)
            - name: canal.adminPasswd
              value: admin

1.3、创建集群

1、canal-admin部署完成之后,浏览器访问服务端口即可进入管理后台(默认用户名密码 admin/123456)

2、在集群管理中选择新建集群,填写集群名称ZK地址后,点击确定即可创建新的canal-server集群

3、在集群管理中选择集群,操作-->主配置,修改集群的主配置文件

需要修改的配置项如下:

# canal-server连接的canal-admin的用户名
canal.admin.user = admin
# canal-server连接的canal-admin的密码(密文)
canal.admin.passwd = 4ACFE3202A5FF5CF467898FC58AAB1D615029441
# canal-server的模式,主要为tcp或mq
canal.serverMode = tcp

# 全局的spring配置方式的组件文件
# 所有组件的数据都选择内存模式,速度快,但无数据存储,重启后又会回到初始位点进行解析
#canal.instance.global.spring.xml = classpath:spring/memory-instance.xml
# 基于file的持久化模式,支持单点canal,无HA,简单易用,会将位点信息写到meta.dat文件中
#canal.instance.global.spring.xml = classpath:spring/file-instance.xml
# store选择了内存模式,其余的parser/sink依赖的位点管理选择了持久化模式,目前持久化的方式主要是写入zookeeper,保证数据集群共享
canal.instance.global.spring.xml = classpath:spring/default-instance.xml

# 是否开启tablemeta的tsdb能力
canal.instance.tsdb.enable = true
canal.instance.tsdb.dir = ${canal.file.data.dir:../conf}/${canal.instance.destination:}
# tsdb的数据库连接地址
canal.instance.tsdb.url = jdbc:mysql://192.168.31.204:3306/canal_config?useSSL=false&useUnicode=true&characterEncoding=UTF-8
# tsdb的数据库用户名
canal.instance.tsdb.dbUsername = canal_admin
# tsdb的数据库密码
canal.instance.tsdb.dbPassword = 123qweQWE!@#
# v1.0.25版本新增,全局的tsdb配置方式的组件文件
#canal.instance.tsdb.spring.xml = classpath:spring/tsdb/h2-tsdb.xml
canal.instance.tsdb.spring.xml = classpath:spring/tsdb/mysql-tsdb.xml

配置文件全文详解如下:

#################################################
#########         common argument        #############
#################################################
# tcp bind ip
canal.ip =
# register ip to zookeeper
canal.register.ip =
# canal-server的服务端口
canal.port = 11111
canal.metrics.pull.port = 11112
# canal instance user/passwd
# canal.user = canal
# canal.passwd = E3619321C1A937C46A0D8BD1DAC39F93B27D4458

# canal admin config
#canal.admin.manager = 127.0.0.1:8089
# canal-server连接的canal-admin的端口
canal.admin.port = 11110
# canal-server连接的canal-admin的用户名
canal.admin.user = admin
# canal-server连接的canal-admin的密码(密文)
canal.admin.passwd = 4ACFE3202A5FF5CF467898FC58AAB1D615029441
# admin auto register
#canal.admin.register.auto = true
#canal.admin.register.cluster =
#canal.admin.register.name =

# canal-admin中定义的集群的zk地址
canal.zkServers = zookeeper-svc:2181
# flush data to zk
# canal-server持久化数据到zookeeper上的更新频率,单位毫秒
canal.zookeeper.flush.period = 1000
canal.withoutNetty = false
# tcp, kafka, rocketMQ, rabbitMQ
# canal-server的模式,主要为tcp或mq
canal.serverMode = tcp
# flush meta cursor/parse position to file
# 主要针对h2-tsdb.xml时对应h2文件的存放目录,默认为conf/xx/h2.mv.db
canal.file.data.dir = ${canal.conf.dir}
canal.file.flush.period = 1000
## memory store RingBuffer size, should be Math.pow(2,n)
# canal内存store中可缓存buffer记录数,需要为2的指数
canal.instance.memory.buffer.size = 16384
## memory store RingBuffer used memory unit size , default 1kb
# 内存记录的单位大小,默认1KB,和buffer.size组合决定最终的内存使用大小
canal.instance.memory.buffer.memunit = 1024 
## meory store gets mode used MEMSIZE or ITEMSIZE
# canal内存store中数据缓存模式
# 1、ITEMSIZE : 根据buffer.size进行限制,只限制记录的数量
# 2、MEMSIZE : 根据buffer.size * buffer.memunit的大小,限制缓存记录的大小
canal.instance.memory.batch.mode = MEMSIZE
canal.instance.memory.rawEntry = true

## detecing config
# 是否开启心跳检查
canal.instance.detecting.enable = false
#canal.instance.detecting.sql = insert into retl.xdual values(1,now()) on duplicate key update x=now()
# 心跳检查sql
canal.instance.detecting.sql = select 1
# 跳检查频率,单位秒
canal.instance.detecting.interval.time = 3
# 心跳检查失败重试次数
canal.instance.detecting.retry.threshold = 3
# 心跳检查失败后,是否开启自动mysql自动切换
# 说明:比如心跳检查失败超过阀值后,如果该配置为true,canal就会自动链到mysql备库获取binlog数据
canal.instance.detecting.heartbeatHaEnable = false

# support maximum transaction size, more than the size of the transaction will be cut into multiple transactions delivery
canal.instance.transaction.size =  1024
# mysql fallback connected to new master should fallback times
# canal发生mysql切换时,在新的mysql库上查找binlog时需要往前查找的时间,单位秒
# 说明:mysql主备库可能存在解析延迟或者时钟不统一,需要回退一段时间,保证数据不丢
canal.instance.fallbackIntervalInSeconds = 60

# network config
# 网络链接参数,SocketOptions.SO_RCVBUF
canal.instance.network.receiveBufferSize = 16384
# 网络链接参数,SocketOptions.SO_SNDBUF
canal.instance.network.sendBufferSize = 16384
# 网络链接参数,SocketOptions.SO_TIMEOUT
canal.instance.network.soTimeout = 30

# binlog filter config
# 是否使用druid处理所有的ddl解析来获取库和表名
canal.instance.filter.druid.ddl = true
# 是否忽略dcl语句
canal.instance.filter.query.dcl = false
# 是否忽略dml语句(mysql5.6之后,在row模式下每条DML语句也会记录SQL到binlog中,可参考MySQL文档)
canal.instance.filter.query.dml = false
# 是否忽略ddl语句
canal.instance.filter.query.ddl = false
# 是否忽略binlog表结构获取失败的异常(主要解决回溯binlog时,对应表已被删除或者表结构和binlog不一致的情况)
canal.instance.filter.table.error = false
# 是否dml的数据变更事件(主要针对用户只订阅ddl/dcl的操作)
canal.instance.filter.rows = false
# 是否忽略事务头和尾,比如针对写入kakfa的消息时,不需要写入TransactionBegin/Transactionend事件
canal.instance.filter.transaction.entry = false
canal.instance.filter.dml.insert = false
canal.instance.filter.dml.update = false
canal.instance.filter.dml.delete = false

# binlog format/image check
# # 支持的binlog format格式列表(otter会有支持format格式限制)
canal.instance.binlog.format = ROW,STATEMENT,MIXED 
# 支持的binlog image格式列表(otter会有支持format格式限制)
canal.instance.binlog.image = FULL,MINIMAL,NOBLOB

# binlog ddl isolation
# ddl语句是否单独一个batch返回(比如下游dml/ddl如果做batch内无序并发处理,会导致结构不一致)
canal.instance.get.ddl.isolation = false

# parallel parser config
# 是否开启binlog并行解析模式
canal.instance.parser.parallel = true
## concurrent thread number, default 60% available processors, suggest not to exceed Runtime.getRuntime().availableProcessors()
#canal.instance.parser.parallelThreadSize = 16
## disruptor ringbuffer size, must be power of 2
# binlog并行解析的异步ringbuffer队列(必须为2的指数)
canal.instance.parser.parallelBufferSize = 256

# table meta tsdb info
# 是否开启tablemeta的tsdb能力
canal.instance.tsdb.enable = true
canal.instance.tsdb.dir = ${canal.file.data.dir:../conf}/${canal.instance.destination:}
# tsdb的数据库连接地址
canal.instance.tsdb.url = jdbc:mysql://192.168.31.204:3306/canal_config?useSSL=false&useUnicode=true&characterEncoding=UTF-8
# tsdb的数据库用户名
canal.instance.tsdb.dbUsername = canal_admin
# tsdb的数据库密码
canal.instance.tsdb.dbPassword = 123qweQWE!@#
# dump snapshot interval, default 24 hour
canal.instance.tsdb.snapshot.interval = 24
# purge snapshot expire , default 360 hour(15 days)
canal.instance.tsdb.snapshot.expire = 360

#################################################
#########         destinations        #############
#################################################
# 当前server上部署的instance列表,多个使用逗号分隔
canal.destinations =
# conf root dir
# conf/目录所在的路径
canal.conf.dir = ../conf
# auto scan instance dir add/remove and start/stop instance
# 开启instance自动扫描
# 如果配置为true,canal.conf.dir目录下的instance配置变化会自动触发
canal.auto.scan = true
# instance自动扫描的间隔时间,单位秒
canal.auto.scan.interval = 5
# set this value to 'true' means that when binlog pos not found, skip to latest.
# WARN: pls keep 'false' in production env, or if you know what you want.
canal.auto.reset.latest.pos.mode = false

# v1.0.25版本新增,全局的tsdb配置方式的组件文件
#canal.instance.tsdb.spring.xml = classpath:spring/tsdb/h2-tsdb.xml
canal.instance.tsdb.spring.xml = classpath:spring/tsdb/mysql-tsdb.xml

# 全局配置加载方式
canal.instance.global.mode = manager
# 全局lazy模式
canal.instance.global.lazy = false
# 全局的manager配置方式的链接信息
canal.instance.global.manager.address = ${canal.admin.manager}
# 全局的spring配置方式的组件文件
# 所有组件的数据都选择内存模式,速度快,但无数据存储,重启后又会回到初始位点进行解析
#canal.instance.global.spring.xml = classpath:spring/memory-instance.xml
# 基于file的持久化模式,支持单点canal,无HA,简单易用,会将位点信息写到meta.dat文件中
#canal.instance.global.spring.xml = classpath:spring/file-instance.xml
# store选择了内存模式,其余的parser/sink依赖的位点管理选择了持久化模式,目前持久化的方式主要是写入zookeeper,保证数据集群共享
canal.instance.global.spring.xml = classpath:spring/default-instance.xml

##################################################
#########           MQ Properties      #############
##################################################
# aliyun ak/sk , support rds/mq
canal.aliyun.accessKey =
canal.aliyun.secretKey =
canal.aliyun.uid=

canal.mq.flatMessage = true
canal.mq.canalBatchSize = 50
canal.mq.canalGetTimeout = 100
# Set this value to "cloud", if you want open message trace feature in aliyun.
canal.mq.accessChannel = local

canal.mq.database.hash = true
canal.mq.send.thread.size = 30
canal.mq.build.thread.size = 8

##################################################
#########              Kafka              #############
##################################################
kafka.bootstrap.servers = 127.0.0.1:6667
kafka.acks = all
kafka.compression.type = none
kafka.batch.size = 16384
kafka.linger.ms = 1
kafka.max.request.size = 1048576
kafka.buffer.memory = 33554432
kafka.max.in.flight.requests.per.connection = 1
kafka.retries = 0

kafka.kerberos.enable = false
kafka.kerberos.krb5.file = "../conf/kerberos/krb5.conf"
kafka.kerberos.jaas.file = "../conf/kerberos/jaas.conf"

##################################################
#########             RocketMQ         #############
##################################################
rocketmq.producer.group = test
rocketmq.enable.message.trace = false
rocketmq.customized.trace.topic =
rocketmq.namespace =
rocketmq.namesrv.addr = 127.0.0.1:9876
rocketmq.retry.times.when.send.failed = 0
rocketmq.vip.channel.enabled = false
rocketmq.tag = 

##################################################
#########             RabbitMQ         #############
##################################################
rabbitmq.host =
rabbitmq.virtual.host =
rabbitmq.exchange =
rabbitmq.username =
rabbitmq.password =
rabbitmq.deliveryMode =

二、部署canal-server

官方提供了canal-server的镜像,可以直接使用官方镜像进行部署

容器重启后pod的IP会变化,自动注册到canal-admin上后,使用旧IP注册的server节点还是存在,并不会自动删除,会造成canadl-admin上有很多过期无用的server节点,所以需要使用StatefulSet方式进行部署

2.1、部署canal-server

部署时需要使用ENV的方式定义一些acnal-server中的参数

        - env:
            # 取StatefulSet中的字段
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: metadata.name
            # 取StatefulSet中的字段
            - name: SERVICE_NAME
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: 'metadata.labels[''app'']'
            # 取StatefulSet中的字段
            - name: STS_NAMESPACE
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: metadata.namespace
            # 使用#取到的StatefulSet中的字段,定义为canal-server的IP,用来连接canal-admin
            - name: canal.register.ip
              value: $(POD_NAME).$(SERVICE_NAME)-headless-svc.$(STS_NAMESPACE)
            # canal-admin的连接地址(配置该值后,canal-server会自动选择sh startup.sh local进行启动)
            - name: canal.admin.manager
              value: 'canal-admin-svc.mid:8089'
            # canal-admin服务的通信端口
            - name: canal.admin.port
              value: '11110'
            # canal-admin用户名(用来与canal-admin双向验证)
            - name: canal.admin.user
              value: admin
            # canal-admin密码 密文形式,与canal-admin的canal.adminPasswd的值相同(用来与canal-admin双向验证)
            - name: canal.admin.passwd
              value: 4ACFE3202A5FF5CF467898FC58AAB1D615029441
            # 自动加入canal-admin集群
            - name: canal.admin.register.auto
              value: 'true'
            # 取StatefulSet中的字段,用作在canal-admin中显示的名字
            - name: canal.admin.register.name
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: metadata.name
            # 加入canal-admin中的哪个集群
            - name: canal.admin.register.cluster
              value: canal-server-beta
            # 开启instance自动扫描
            - name: canal.auto.scan
              value: 'true'

三、canal在zookeeper中的数据结构

  • 使用canal-admin集群模式的部署,canal的消费位点等信息会被记录在zookeeper中

  • 修改canal消费位点数据时,应该先停止对应的instance

  • 使用zookeeper自带的zkCli.sh工具,操作zk的数据

  • canal默认在zookeeper中存储的数据位置为:/otter/canal

canal在zk中的具体数据结构如下

# canal的根目录
/otter/canal

#整个canal server的集群列表(服务端节点信息)
/otter/canal/cluster

# destination的根目录(instance列表)
/otter/canal/destinations

# 针对某个instance的服务端节点列表
/otter/canal/destinations/{instance}/cluster

# 某个instance正在运行的节点信息
/otter/canal/destinations/{instance}/running

# 客户端信息目录
/otter/canal/destinations/{instance}/1001

# 客户端binlog同步信息(包含消费位点)
/otter/canal/destinations/{instance}/1001/cursor

# 客户端拦截器配置信息
/otter/canal/destinations/{instance}/1001/filter
posted @ 2022-10-13 21:54  大胡萝卜没有须  阅读(2742)  评论(0编辑  收藏  举报