From 7ee2360d6e3dfd5d3d233583ad8a0a77ebb3d1a9 Mon Sep 17 00:00:00 2001 From: Jakub Cechacek Date: Wed, 11 Oct 2023 12:39:56 +0200 Subject: [PATCH] DBZ-7025 Debezium Operator blogpost --- _data/authors.yaml | 9 +- ...zium-Operator-Takes-off-to-the-Clouds.adoc | 433 ++++++++++++++++++ assets/images/jcechace.jpg | Bin 0 -> 19866 bytes 3 files changed, 441 insertions(+), 1 deletion(-) create mode 100644 _posts/2023-10-10-Debezium-Operator-Takes-off-to-the-Clouds.adoc create mode 100644 assets/images/jcechace.jpg diff --git a/_data/authors.yaml b/_data/authors.yaml index acbfdcc5f92..8437b26ab9c 100644 --- a/_data/authors.yaml +++ b/_data/authors.yaml @@ -204,4 +204,11 @@ indrashukla: bio: "Indra is a Senior software developer at Red Hat. He has extensive experiance in UI development. He lives in Bangalore, India." github: indraraj linkedin: indra-shukla - avatar: indra.jpg \ No newline at end of file + avatar: indra.jpg + +jcechace: + name: "Čecháček Jakub" + bio: "Jakub is a Principal Software Engineer at Red Hat. He lives in Czech Republic." + github: jcechace + linkedin: jcechace + avatar: jcechace.jpg \ No newline at end of file diff --git a/_posts/2023-10-10-Debezium-Operator-Takes-off-to-the-Clouds.adoc b/_posts/2023-10-10-Debezium-Operator-Takes-off-to-the-Clouds.adoc new file mode 100644 index 00000000000..dbf7fd82d57 --- /dev/null +++ b/_posts/2023-10-10-Debezium-Operator-Takes-off-to-the-Clouds.adoc @@ -0,0 +1,433 @@ +--- +layout: post +title: "Debezium Operator Takes off to the Clouds" +date: 2023-10-10 11:11:11 +0100 +tags: [ debezium, features, kubernetes, operator, debezium-server ] +featured: true +author: jcechace +--- + +With Debezium 2.3 we introduced the preview of the brand new Debezium Operator with the aim to provide seamless deployment of Debezium Server to Kubernetes (k8s) clusters. Debezium 2.4.0.Final release brings the next step towards the full support of this component. With this release we are happy to announce that Debezium Operator is now available in the OperatorHub https://operatorhub.io/operator/debezium-operator[catalog] for Kubernetes as well as in the community operator catalog embedded in OpenShift and OKD distributions. For now the operator still remains in the inclubation phase, however the full support of this component is approaching fast. + +++++++ + +== The Goal + +In this article we will demonstrate how to stream changes from PostgreSQL database into Apache Kafaka using Debezium Server deployed in Kubernetes cluster. We will also demonstrate some of the capabilities of our new k8s integration. For conveninece all code snippets and kubernetes manifests used in the tutorial are also available in our https://github.com/debezium/debezium-examples/tree/main/operator/tutorial-postgresql-kafka[GitHub repository for examples]. + +== Preparing the Environment + +Before we get to deploying the operator and consequently Debezium Server itself, we first need an environment to deploy into. In this section we will showcase how to provision a local Kubernetes cluster with running PostgreSQL database and Apache Kafka broker. Note that it is not required for the database and/or the Kafka broker to run inside Kubernetes, we just chose to do so for the purpose of this demonstration. + +=== Running a Local Kubernetes Cluster +You can skip this part if you already have a running Kubernetes cluster available, however make sure you posses a cluster-admin permissions as these are required for operator instalaltion. If not, then read on. + +There are multiple tools available to run a local k8s cluster, such as https://minikube.sigs.k8s.io/docs/[Minikube], https://kind.sigs.k8s.io/[Kind], or https://docs.docker.com/desktop/kubernetes/[Docker Desktop]. In ths article we will be using Kind to create a local single node cluster. + + +**Prerequisities** + +1. https://kubernetes.io/docs/tasks/tools/#kubectl[Install] `kubectl` distribution for your platform +2. https://kind.sigs.k8s.io/docs/user/quick-start/#installation[Install] `Kind` distribution for your platform. + +Once you have both, `kubectl` and `kind` installed, create a local Kubernetes cluster by executing the following: + +[source, bash] +---- +kind create cluster --name debezium +---- + +We can now configure the cluster context for `kubectl` and check the status of our new k8s environment by running the following command: + +[source, bash] +---- +$ kubectl cluster-info --context kind-debezium + +Kubernetes control plane is running at https://127.0.0.1:64815 +CoreDNS is running at https://127.0.0.1:64815/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy +---- + +As the last step of our cluster deployment we will create a new namespace for the required infrastructure + +[source, bash] +---- +kubectl create namespace debezium +---- + +=== Deploying the infrastructure +In this section we will prepare the required infrastructure -- PostgreSQL database as well as an instance of Kafka broker. + +==== PostgreSQL Database +Lets start with deploying the PostgreSQL database by executing the command bellow. + +[CAUTION] +For simplicity we are using an ephemeral volume mounts which means that any modification done to our database instance will not persist when the pod is recreated. + +[source, bash] +---- +kubect create -f https://raw.githubusercontent.com/debezium/debezium-examples/main/operator/tutorial-postgresql-kafka/infra/001_postgresql.yml -n debezium +---- + +The yaml file fed to `kubectl` contains several kubernetes manifests: + +.001_postgresql.yml +[source, yaml] +---- +apiVersion: v1 <1> +kind: Secret +metadata: + name: postgresql-credentials +type: opaque +data: + POSTGRES_DB: ZGViZXppdW0= + POSTGRES_USER: ZGViZXppdW0= + POSTGRES_PASSWORD: ZGViZXppdW0= +--- +kind: Deployment <2> +apiVersion: apps/v1 +metadata: + name: postgresql + labels: + app: postgresql +spec: + replicas: 1 + selector: + matchLabels: + app: postgresql + deployment: postgresql + template: + metadata: + labels: + app: postgresql + deployment: postgresql + spec: + containers: + - resources: {} + name: postgresql + envFrom: + - secretRef: + name: postgresql-credentials + ports: + - containerPort: 5432 + protocol: TCP + imagePullPolicy: IfNotPresent + livenessProbe: + initialDelaySeconds: 30 + tcpSocket: + port: 5432 + timeoutSeconds: 1 + readinessProbe: + exec: + command: + - "/bin/sh" + - "-i" + - "-c" + - "PGPASSWORD=${POSTGRES_PASSWORD} /usr/bin/psql -w -U ${POSTGRES_USER} -d ${POSTGRES_DB} -c 'SELECT 1'" + initialDelaySeconds: 5 + timeoutSeconds: 1 + terminationMessagePolicy: File + terminationMessagePath: /dev/termination-log + image: quay.io/debezium/example-postgres:latest + restartPolicy: Always + terminationGracePeriodSeconds: 30 + dnsPolicy: ClusterFirst + strategy: + type: Recreate +--- +apiVersion: v1 <3> +kind: Service +metadata: + name: postgresql +spec: + selector: + app: postgresql + deployment: postgresql + ports: + - name: db + port: 5432 + targetPort: 5432 +---- +<1> Secret providing database credentials. +<2> Database Deployment. +<3> Database Service. + +The secret is not only attached as environment variables to database pod, but it will be also used later to reference these credentials in connector configuration. + +You can check that your PostgreSQL database was deployed correctly by running: + +[source, bash] +---- +$ kubectl get deployments -n debezium + +NAME READY UP-TO-DATE AVAILABLE +postgresql 1/1 1 1 +---- + +==== Kafka Broker +To deploy a Kafka broker instance we will take an advantage of the https://strimzi.io/[Strimzi Operator]. + +So first we will deploy the Strimzi operator itself by running the command bellow. Please not the `namespace` parameter in the URL -- it's importnat as it ensures that Kubernetes objects required by Strimzi are created in the correct namespace. + +[source, bash] +---- +kubectl create -f https://strimzi.io/install/latest?namespace=debezium +---- + +After a bit of time you can check that your Strimzi operator is running + +[source, bash] +---- +$ kubectl get deployments -n debezium + +NAME READY UP-TO-DATE AVAILABLE +strimzi-cluster-operator 1/1 1 1 +---- + +With the Strimzi operator installed we can deploy an instance of Kafka broker. + +[source, bash] +---- +kubectl create -f https://raw.githubusercontent.com/debezium/debezium-examples/main/operator/tutorial-postgresql-kafka/infra/002_kafka-ephemeral.yml -n debezium +---- + +This command deploys a minimal working configuration of Kafka Broker as described in the used yaml file. + +.002_kafka-ephemeral.yml +[source, yaml] +---- +apiVersion: kafka.strimzi.io/v1beta2 +kind: Kafka +metadata: + name: dbz-kafka +spec: + kafka: + version: 3.4.0 + replicas: 1 + listeners: + - name: plain + port: 9092 + type: internal + tls: false + - name: tls + port: 9093 + type: internal + tls: true + config: + offsets.topic.replication.factor: 1 + transaction.state.log.replication.factor: 1 + transaction.state.log.min.isr: 1 + default.replication.factor: 1 + min.insync.replicas: 1 + inter.broker.protocol.version: "3.4" + storage: + type: ephemeral + zookeeper: + replicas: 1 + storage: + type: ephemeral + entityOperator: + topicOperator: {} + userOperator: {} +---- + +[CAUTION] +Once again this configuration uses an ephemeral storage and only a single replica of Kafka broker -- a configuration not suitable for production. + + +To check your Kafka deployment execute the following + +[source, bash] +---- +$ kubectl get pods -n debezium + +NAME READY STATUS RESTARTS +dbz-kafka-entity-operator-844ffdcd54-cdq92 3/3 Running 0 +dbz-kafka-kafka-0 1/1 Running 0 +dbz-kafka-zookeeper-0 1/1 Running 0 +---- + +Deploying Debezium Operator +--- +With a kubernetes environment and required infrastructure at our disposal we can now move onto the main star of the tutorial -- the brand new Debezium Operator. There are currently two ways to deploy the operator to your Kubernetes cluster. You can either apply a set of kubernetes manifests to your cluster (similarly to what we did with the database and Strimzi operator) or directly from the https://operatorhub.io/[OperatorHub] operator catalog. + + +=== Deploying Debezium Operator from Operator Catalog +In this section we will use the https://olm.operatorframework.io/[Operator Lifecycle Manager] to create a subscription to an operator available in the https://operatorhub.io/[OperatorHub catalog]. As we mentioned previously, Debezium is one of the https://operatorhub.io/operator/debezium-operator[available operators]. + +Besides other things, using OLM also allows you to configure the scope of namespaces watched by the operator from a single namespace to the entire cluster. However https://olm.operatorframework.io/docs/advanced-tasks/operator-scoping-with-operatorgroups/[this configuration] is out of the scope (pun intended!) for this tutorial. The process bellow will install the operator into the `operators` namespace -- which is by default intended for cluster-wide operators. + +First we need to install OLM itself by running the following shell commands -- skip this if OLM is already instaled in your cluster. + +[Note] +This is a one time process and any production k8s cluster which provides access to operator catalogs would already have OLM installed + +[source, bash] +---- +curl -L https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.25.0/install.sh -o install.sh +chmod +x install.sh +./install.sh v0.25.0 +---- + +Once OLM is up and running in your cluster you can subscribe to Debezium operator. + +[source, bash] +---- +kubectl create -f https://raw.githubusercontent.com/debezium/debezium-examples/main/operator/tutorial-postgresql-kafka/infra/010_debezium-subscription.yml +---- + +Once again we will examine the contents of the `subscription.yml` file in order to get a better understand of what we just did. + +[source, bash] +---- +apiVersion: operators.coreos.com/v1alpha1 +kind: Subscription <1> +metadata: + name: debezium-operator-subscription + namespace: operators <2> +spec: + installPlanApproval: Automatic + name: debezium-operator <3> + source: operatorhubio-catalog <4> + sourceNamespace: olm <5> + startingCSV: debezium-operator.v2.4.0 +---- +<1> The `Subscription` object instructs OLM to install an operator from operator catalog. +<2> The target namespace for operator installation. +<3> Name of the installed operator. +<4> Name of the operator catalog. +<5> The namespace containing the operator catalog. + +You learn more about installing operators through OLM subscription in the https://olm.operatorframework.io/docs/tasks/install-operator-with-olm/[OLM documentation]. + +You should now have a Debezium Operator ready to manage Debezium Server deployments across your entire Kubernetes cluster. You can check that the operator is indeed up and running with the following command + +[source, bash] +---- +$ kubectl get deployments -n operators + +NAME READY UP-TO-DATE AVAILABLE +debezium-operator 1/1 1 1 +---- + +[TIP] +In previous section we chose to deploy Strimzi operator by directly applying a set of k8s manifests to our cluster. However Strimzi is also one of the operators available in OperatorHub catalog and as such could be also installed via OLM. + +=== Using Raw Kubernetes Manifests to Deploy Debezium Operator +This options allows deployment of Debezium Operator into any Kubernetes cluster without the need for OLM. + +[IMPORTANT] +Debezium Operator depoyed this way will be limitted to managing Debezium Server instances **only in the same namespace as the operator**. + +To deploy the Debezium Operator we need to execute the following commands + +[source, bash] +---- +kubectl create -f https://raw.githubusercontent.com/debezium/debezium-operator/2.4/k8/debeziumservers.debezium.io-v1.yml +kubectl create -f https://raw.githubusercontent.com/debezium/debezium-operator/2.4/k8/kubernetes.yml -n debezium +---- + +The first command installs the https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#customresourcedefinitions[Custom Resource Definitons] for the resources required by Debezium Operator, while the second execution of `kubectl` deploys the operator itself. + +With the operator deployed you can now move to deploying the Debezium Server instance to start streaming changes from your database. + + +== Deploying Debezium Server to the K8s Cluster + +With Debezium Operator deployed one way or the other, we can now deploy the Debezium Server itself! + +[source, bash] +---- +kubectl create -f https://raw.githubusercontent.com/debezium/debezium-examples/main/operator/tutorial-postgresql-kafka/infra/011_debezium-server-ephemeral.yml -n debezium +---- + +Once again, lets look closely at the kubernetes manifest we just deployed + + +.011_debezium-server-ephemeral.yml +[source, yaml] +---- +apiVersion: debezium.io/v1alpha1 +kind: DebeziumServer <1> +metadata: + name: my-debezium <2> +spec: + image: quay.io/debezium/server:2.4.0.Final <3> + quarkus: <4> + config: + log.console.json: false + kubernetes-config.enabled: true + kubernetes-config.secrets: postgresql-credentials + sink: <5> + type: kafka + config: + producer.bootstrap.servers: dbz-kafka-kafka-bootstrap:9092 + producer.key.serializer: org.apache.kafka.common.serialization.StringSerializer + producer.value.serializer: org.apache.kafka.common.serialization.StringSerializer + source: <6> + class: io.debezium.connector.postgresql.PostgresConnector + config: + offset.storage.file.filename: /debezium/data/offsets.dat + database.history: io.debezium.relational.history.FileDatabaseHistory + database.hostname: postgresql + database.port: 5432 + database.user: ${POSTGRES_USER} + database.password: ${POSTGRES_PASSWORD} + database.dbname: ${POSTGRES_DB} + topic.prefix: inventory + schema.include.list: inventory +---- +<1> Resource type monitored by Debezium Operator. +<2> Name of the deployed Debezium Server instance. +<3> Optional property specifying the container image . +<4> Quarkus configuration used by Debezium Server. +<5> Kafka sink configuration. +<6> PostgreSQL source connector configuration. + +The `spec` part of the manifest will likely be familiar to anybody with previous Debezium Server experience as it is a more structured variant of Debezium Server property configuration. In our case the `image` property is particularly redundant as it uses the default image for installed operator version. + +The quarkus part of the `spec` provides Debezium Server with access to previously deployed `postgresql-credentials` secret containg the credentials to our database. You can see the `POSTGRES_USER` and other variables referenced later on in the configuration. + + + +A bit more detailed description of the `DebeziumServer` custom resource can be found at https://github.com/debezium/debezium-operator/tree/2.4#debeziumserverspec-reference[GitHub]. + +=== Under the Hood +Debezium Operator will take care of creating everything required to run Debezium Server insinde Kubernetes. + +- A service account used to run Debezium Server +- Roles and role bindings allowing the read of config maps and secrets in the namespace where Debezium Server is being deployed +- A config map containing the raw configuration for DebeziumServer +- The deployment itself + + +=== Verifying the Deployment +You can check the that the deployed Debezium Server instance in running with the following command + +[source, bash] +---- +$ kubectl get deployments -n debezium + +NAME READY UP-TO-DATE AVAILABLE +my-debezium 1/1 1 1 +---- + +Witht Debezium Server running we can verify that it consumed all initial data from the database with the following command. + +[source, bash] +---- +kubectl exec dbz-kafka-kafka-0 -n debezium -- /opt/kafka/bin/kafka-console-consumer.sh \ + --bootstrap-server localhost:9092 \ + --from-beginning \ + --property print.key=true \ + --topic inventory.inventory.orders +---- + + +== The Future and Our Request + +This is it for now. Before the operator gets full support we intend to provied a more detailed documentation as well as the ability to further configure the deployment with things such as custom pull secrets in order to suport customized Debezium Server images stored in secured registries. + +In future, there are further plans to improve the structure of `DebeziumServer` resources, provide the ability to declaratively assemble tailored distribution of Debezium Server and maybe even improve our integration with knative eventing. We are also planning improvements to the embedded engine and conseqently Debezium Server which will some day allow us to take advantage of horizontal scaling capabilities of Kubernetes. + +=== You can Help us! +Would like to ask you, our wonderful Debezium community, to test the operator and let us know what you like, what you dislike and what features you miss. This way, we will be able to shape this component according to your needs, and together we will bring Debezium closer to provide cloud native CDC capabilities. \ No newline at end of file diff --git a/assets/images/jcechace.jpg b/assets/images/jcechace.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7e8fbe4c4b9ed7455338e2aa6cde5f756435e856 GIT binary patch literal 19866 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 T0pkbpqZtP@9;Ey9pb!7qCa^)8 literal 0 HcmV?d00001