《OpenShift 4.x HOL教程汇总》
说明:本文已经在OpenShift 4.6环境中验证
$ oc new-project debezium-demo
!include /etc/my.cnf
[mysqld]
server-id = 223344
server_id = 223344
log_bin = ON
binlog_format = ROW
binlog_row_image = full
binlog_rows_query_log_events = ON
expire_logs_days = 10
gtid_mode = ON
enforce_gtid_consistency = ON
$ oc create configmap db-config --from-file=debezium.cnf
CREATE USER IF NOT EXISTS 'debezium'@'%' IDENTIFIED WITH mysql_native_password BY 'debezium';
GRANT SELECT, RELOAD, SHOW DATABASES, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'debezium'@'%';
FLUSH PRIVILEGES;
$ oc create configmap db-init --from-file=initdb.sql
$ oc create secret generic db-creds --from-literal=database-name=music --from-literal=database-password=music --from-literal=database-user=music --from-literal=database-admin-password=music
kind: DeploymentConfig
apiVersion: apps.openshift.io/v1
metadata:
name: spring-music-db
labels:
application: spring-music
app: spring-music
app.kubernetes.io/part-of: spring-music
app.openshift.io/runtime: mysql-database
spec:
replicas: 1
strategy:
type: Recreate
recreateParams:
post:
failurePolicy: Abort
execNewPod:
command:
- /bin/sh
- '-c'
- sleep 10 && MYSQL_PWD="$MYSQL_ROOT_PASSWORD" $MYSQL_PREFIX/bin/mysql -h $SPRING_MUSIC_DB_SERVICE_HOST -u root < /config/initdb.d/initdb.sql
containerName: spring-music-db
volumes:
- db-init
selector:
name: spring-music-db
template:
metadata:
name: spring-music-db
labels:
name: spring-music-db
spec:
volumes:
- name: db-data
emptyDir: {}
- name: db-init
configMap:
name: db-init
- name: db-config
configMap:
name: db-config
containers:
- env:
- name: MYSQL_DEFAULTS_FILE
value: /config/configdb.d/my-debezium.cnf
- name: MYSQL_USER
valueFrom:
secretKeyRef:
name: db-creds
key: database-user
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: db-creds
key: database-password
- name: MYSQL_DATABASE
valueFrom:
secretKeyRef:
name: db-creds
key: database-name
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: db-creds
key: database-admin-password
name: spring-music-db
image: ' '
imagePullPolicy: IfNotPresent
volumeMounts:
- name: db-data
mountPath: /var/lib/mysql/data
- name: db-init
mountPath: /config/initdb.d
- name: db-config
mountPath: /config/configdb.d
ports:
- containerPort: 3306
protocol: TCP
livenessProbe:
failureThreshold: 3
initialDelaySeconds: 30
periodSeconds: 10
successThreshold: 1
tcpSocket:
port: 3306
timeoutSeconds: 1
readinessProbe:
exec:
command:
- /bin/sh
- -i
- -c
- MYSQL_PWD="$MYSQL_PASSWORD" mysql -h 127.0.0.1 -u $MYSQL_USER -D $MYSQL_DATABASE -e 'SELECT 1'
failureThreshold: 3
initialDelaySeconds: 5
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
resources:
limits:
memory: 512Mi
securityContext:
privileged: false
triggers:
- type: ConfigChange
- type: ImageChange
imageChangeParams:
automatic: true
containerNames:
- spring-music-db
from:
kind: ImageStreamTag
name: mysql:8.0
namespace: openshift
---
kind: Service
apiVersion: v1
metadata:
name: spring-music-db
labels:
application: spring-music
app: spring-music
annotations:
template.openshift.io/expose-uri: mysql://{.spec.clusterIP}:{.spec.ports[?(.name=="mysql")].port}
spec:
ports:
- name: mysql
port: 3306
protocol: TCP
targetPort: 3306
selector:
name: spring-music-db
$ oc create -f mysql.yml
AMQ Streams Operator是RedHat官方提供的,Strimzi Operator是社区提供的,使用两者任何一个都可以。
kind: Kafka
apiVersion: kafka.strimzi.io/v1beta1
metadata:
name: db-events
namespace: debezium-demo
labels:
app: spring-music-cdc
template: spring-music-cdc
app.kubernetes.io/part-of: spring-music-cdc
spec:
kafka:
replicas: 3
listeners:
plain: {}
jvmOptions:
gcLoggingEnabled: false
config:
auto.create.topics.enable: "true"
num.partitions: 1
offsets.topic.replication.factor: 3
default.replication.factor: 3
transaction.state.log.replication.factor: 3
transaction.state.log.min.isr: 2
storage:
type: persistent-claim
size: 100Gi
deleteClaim: true
template:
statefulset:
metadata:
labels:
app.kubernetes.io/part-of: spring-music-cdc
app: spring-music-cdc
template: spring-music-cdc
annotations:
app.openshift.io/connects-to: db-events-zookeeper
zookeeper:
replicas: 3
storage:
type: persistent-claim
size: 100Gi
deleteClaim: true
template:
statefulset:
metadata:
labels:
app.kubernetes.io/part-of: spring-music-cdc
app: spring-music-cdc
template: spring-music-cdc
entityOperator:
topicOperator: {}
userOperator: {}
可以直接使用“quay.io/edeandrea/kafka-connect-debezium-mysql:amq-streams-1.4.0-dbz-1.1.0.Final”镜像,也可以根据以下步骤生成该容器镜像。
FROM registry.redhat.io/amq7/amq-streams-kafka-24-rhel7:1.4.0
USER root:root
COPY ./plugins/ /opt/kafka/plugins
USER jboss:jboss
kind: KafkaConnect
apiVersion: kafka.strimzi.io/v1beta1
metadata:
name: db-events
namespace: debezium-demo
labels:
app: spring-music-cdc
template: spring-music-cdc
annotations:
strimzi.io/use-connector-resources: "true"
spec:
replicas: 1
image: "quay.io/edeandrea/kafka-connect-debezium-mysql:amq-streams-1.4.0-dbz-1.1.0.Final"
bootstrapServers: "db-events-kafka-bootstrap:9092"
jvmOptions:
gcLoggingEnabled: false
config:
group.id: spring-music-db
offset.storage.topic: spring-music-db-offsets
config.storage.topic: spring-music-db-configs
status.storage.topic: spring-music-db-status
config.storage.replication.factor: 1
offset.storage.replication.factor: 1
status.storage.replication.factor: 1
config.providers: file
config.providers.file.class: org.apache.kafka.common.config.provider.FileConfigProvider
externalConfiguration:
volumes:
- name: connector-config
secret:
secretName: db-connector-creds
template:
deployment:
metadata:
labels:
app: spring-music-cdc
app.kubernetes.io/part-of: spring-music-cdc
template: spring-music-cdc
annotations:
app.openshift.io/connects-to: db-events-kafka,spring-music-db
kind: KafkaConnector
apiVersion: kafka.strimzi.io/v1alpha1
metadata:
name: db-events
namespace: debezium-demo
labels:
app: spring-music-cdc
strimzi.io/cluster: db-events
spec:
class: io.debezium.connector.mysql.MySqlConnector
tasksMax: 1
config:
database.hostname: spring-music-db
database.port: 3306
database.user: "${file:/opt/kafka/external-configuration/connector-config/connector.properties:dbUsername}"
database.password: "${file:/opt/kafka/external-configuration/connector-config/connector.properties:dbPassword}"
database.dbname: music
database.server.name: spring-music
database.server.id: 223344
database.whitelist: music
database.allowPublicKeyRetrieval: true
database.history.kafka.bootstrap.servers: db-events-kafka-bootstrap:9092
database.history.kafka.topic: dbhistory.music
table.whitelist: music.outbox_events
tombstones.on.delete : false
transforms: outbox
transforms.outbox.type: io.debezium.transforms.outbox.EventRouter
transforms.outbox.route.topic.replacement: "outbox.${routedByValue}.events"
transforms.outbox.table.field.event.id: event_id
transforms.outbox.table.field.event.key: aggregate_id
transforms.outbox.table.field.event.timestamp: event_timestamp
transforms.outbox.table.field.event.type: event_type
transforms.outbox.table.field.event.payload.id: aggregate_id
transforms.outbox.route.by.field: aggregate_type
transforms.outbox.table.fields.additional.placement: "event_id:envelope:eventId,event_timestamp:envelope:eventTimestamp,aggregate_id:envelope:aggregateId,aggregate_type:envelope:aggregateType"
$ bin/kafka-console-consumer.sh --bootstrap-server db-events-kafka-bootstrap:9092 --topic outbox.Album.events --from-beginning
3. 在新的界面中打开部署的应用,点击“add an album”链接添加一个新的album数据,然后ok提交数据。
4. 界面中提示保存成功
5. 返回Terminal,确认出现一行新的数据。格式化后为以下内容,其中在“payload”部分是我们提交的新数据内容。
{
"schema": {
"type": "struct",
"fields": [{
"type": "string",
"optional": true,
"name": "io.debezium.data.Json",
"version": 1,
"field": "payload"
}, {
"type": "string",
"optional": false,
"field": "eventType"
}, {
"type": "int64",
"optional": false,
"field": "eventId"
}, {
"type": "int64",
"optional": false,
"name": "io.debezium.time.MicroTimestamp",
"version": 1,
"field": "eventTimestamp"
}, {
"type": "string",
"optional": false,
"field": "aggregateId"
}, {
"type": "string",
"optional": false,
"field": "aggregateType"
}],
"optional": false
},
"payload": {
"payload": "{\"album\":{\"id\":\"f8f1ad92-f724-45bc-b0ca-e968c369a9c0\",\"genre\":\"Rock\",\"title\":\"Test\",\"artist\":\"Test\",\"albumId\":null,\"trackCount\":0,\"releaseYear\":\"2020\"},\"eventType\":\"ALBUM_CREATED\"}",
"eventType": "ALBUM_CREATED",
"eventId": 30,
"eventTimestamp": 1617626600716385,
"aggregateId": "f8f1ad92-f724-45bc-b0ca-e968c369a9c0",
"aggregateType": "Album"
}
}
https://dzone.com/articles/change-data-capture-with-debezium-a-simple-how-to