How-tos

How-To: Running HA IBM DB2 on Kubernetes

Share this post:

What is IBM Cloud Kubernetes Service?

IBM Cloud Kubernetes Service is a managed Kubernetes offering to deliver powerful management tools, an intuitive user experience, and built-in security and isolation to enable rapid delivery of applications—all while leveraging IBM Cloud Services, including cognitive capabilities from Watson. IBM Cloud Kubernetes Service provides native Kubernetes capabilities like intelligent scheduling, self-healing, horizontal scaling, service discovery and load balancing, automated rollouts and rollbacks, and secret and configuration management. Additionally, IBM is adding capabilities to the Kubernetes Service, including simplified cluster management, container security and isolation choices, the ability to design your own cluster and leverage other IBM Cloud services such as Watson for your cognitive applications, completely native Kubernetes CLI and API, and integrated operational tools or support to bring your own tools to ensure operational consistency with other deployments.

Partnering with Portworx

I’m very excited to partner with Joe Gardiner (@grdnrio) from Portworx (@portwx) on this blog post.  Learn more about our partnership here and check out the documentation. The rest of this guide is written by Joe.

IBM Db2

IBM Db2 is a widely used enterprise database and is part of a larger Db2 family with big data, analytics, and data-streaming use cases. IBM has released and supports a number of DB2 container images on the Docker Store, making it easier than ever to deploy Db2 on your container platform.

As with all data services, running Db2 in a container raises the question: How do I handle my persistent data? Running in production requires a lot of forethought and planning. For example:

  • How can I failover my Db2 database in the case of a container host failing?
  • How can I ensure data availability through a snapshot and restore process?
  • How I can I upgrade my database without corrupting my data or disrupting service?
  • How can I migrate my containerized Db2 into another cluster or environment?

The aim of this blog post is to answer the above questions by demonstrating a Db2 deployment architecture on Kubernetes using Portworx persistent volumes. Following this post, you’ll understand how to run Db2 in production on Kubernetes.

Getting started with DB2 on Kubernetes

Before getting into the detail of deploying Db2, let’s summarize the steps:

  1. Chose a multicloud container orchestration platform like Kubernetes.
  2. Install a multicloud container storage solution like Portworx.
  3. For a simple and efficient high availability (HA) setup, run a single instance of Db2 and set container volume replication to repl:”3”.
  4. Set io_priority:”high" to schedule Db2 instance on fast storage medium for better IO performance. Use a journal device with your volumes to speed up performance.
  5. Use the Portworx custom block size parameter to support the Db2 512b requirement.

Read on for more details about running an HA Db2 on Kubernetes.

Achieving HA with Db2 on Kubernetes

This blog post makes use of the developer edition of Db2 from the Docker Store. This is a verified and supported image and is perfect for testing, with enterprise images available for production.

Db2 can run in a single-node configuration and in a clustered configuration as described here.

The preferred replication technique with Db2 is the use of an Active-Passive replication set with a primary instance replicating to secondary and tertiary nodes. It makes use of etcd as a source of truth to avoid split brain should a node fail. You can read more about the architecture here.

With Portworx, each Db2 Master and Secondary can have its PVC  synchronously replicated. This makes recovering database instances a near-zero cost operation, which results in shorter recovery windows and higher total uptime. With Portworx and Kubernetes, database instance recovery can take less than 180 seconds, which is very rapid considering Db2 can take two minutes to start up.

For deployments where you require replication for data protection but where a single database instance is capable of handling the read requests, a single Db2 pod with Portworx replicated volumes offers a simpler and more cost-effective solution to running HA Db2 on Kubernetes.

This is far less complex to manage and configure and requires a third of the Db2 Pods and therefore s third of the CPU and memory because Portworx is already running on your Kubernetes cluster and synchronously replicates data for all of your applications with great efficiency and scale.

Deploying Db2 on Kubernetes

To start a Db2 deployment, we first need to create a Storage Class. Here we can define how we want to handle the storage for DB2.

kind: StorageClass
apiVersion: storage.k8s.io/v1beta1
metadata:
name: db2-sc
provisioner: kubernetes.io/portworx-volume
parameters:
repl: "3"
block_size: "512b"
io_profile: "db"
allowVolumeExpansion: true

Note the following parameters in the above Storage Class:

  • Repl 3: This specifies how many replicated volumes we want across worker nodes in our Kubernetes cluster.
  • Block_size 512b:  This meets the 512 KiB requirement for a relational database in Db2.
  • Io_profile: db: This implements a write-back flush coalescing algorithm. This algorithm attempts to coalesce multiple syncs that occur within a 50ms window into a single sync.
  • allowVolumeExpansion: true: This parameter allows us to resize the volume live without any disruption or pod restarts.

Along with the above parameters, we can add Kubernetes snapshot schedules and Kubernetes data encryption policies directly in this storage class definition. This declarative style of configuration is exactly what modern cloud-native infrastructure is all about. No more snowflakes; you can recreate whole environments from source code, including the automation of your common data management tasks.

Next, we need to create the Persistent Volume Claim.

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
   name: db2-pvc
   annotations:
     volume.beta.kubernetes.io/storage-class: db2-sc
spec:
   accessModes:
     - ReadWriteOnce
   resources:
     requests:
       storage: 5Gi

In the above, we are referencing the StorageClass name we created earlier and our storage requirements. Remember, we can resize this later as necessary.

When it comes to deploying Db2, there are a number of things to consider, as shown in the following deployment spec:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: db2
spec:
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  replicas: 1
  template:
    metadata:
      labels:
        app: db2
    spec:
      schedulerName: stork
      containers:
      - name: db2
        image: store/ibmcorp/db2_developer_c:11.1.3.3b-x86_64
        imagePullPolicy: "IfNotPresent"
        ports:
        - containerPort: 50000
        env:
        - name: DB2INST1_PASSWORD
          value: "somepasswd!"
        - name: LICENSE
          value: "accept"
        - name: TO_CREATE_SAMPLEDB
          value: "true"
        - name: DB2INSTANCE
          value: "db2inst1"
        volumeMounts:
        - mountPath: /database
          name: db2data
        securityContext:
          privileged: true
      securityContext:
        fsGroup: 1000
      imagePullSecrets:
      - name: regcred
      volumes:
      - name: db2data
        persistentVolumeClaim:
          claimName: db2-pvc

Firstly, note the image being used. This is available from the Docker Store, but it requires Docker credentials to access it. You can see we’re using an imagePullSecrets parameter with a regcred secret. Follow the Kubernetes docs to set this up.

Next, take note of the environment variables. These are documented on the image docs page once you have access via the Docker Store. Here are the values you can set:

LICENSE=accept
DB2INSTANCE=db2inst1
DB2INST1_PASSWORD=password
DBNAME=testdb
BLU=false
ENABLE_ORACLE_COMPATIBILITY=false
UPDATEAVAIL=NO
TO_CREATE_SAMPLEDB=false
REPODB=false
IS_OSXFS=false
PERSISTENT_HOME=true
HADR_ENABLED=false
ETCD_ENDPOINT=
ETCD_USERNAME=
ETCD_PASSWORD=

HADR and ETCD values above are used for an HA pod deployment scenario, whereas the approach in this blog is to run a single pod and reply on Portworx and Kubernetes rescheduling to provide resilience.

In the example, TO_CREATE_SAMPLEDB is set to true. This is to give us some sample data to work with when proving replication and snapshotting. In a real-world scenario, you will probably want to disable this.

You may also notice that we’re setting a fsgroup. The group ID for the db2inst1 user is 1000, so we’re ensuring ownership is set correctly for the volume /database mountpoint. This will allow new databases to be created at this location using the db2 cli with kubectl exec.

Testing Db2 failover

Let’s now walk through a failover scenario. We can simulate a failover by cordoning the node on which Db2 is running and then deleting the Pod. This will force Kubernetes to reschedule the pod.

Once Kubernetes identifies that the pod needs to be rescheduled, it will work with Portworx’s Kubernetes scheduler extender, STORK, to identify which node is best suited to host the restarted pod. In our small environment, any of the two remaining nodes will do because we have a copy of the data on all three nodes. In reality, you will likely have much larger clusters, and that’s when STORK will benefit you by making sure the pod starts on a node where a copy of the data is locally stored. In the unlikely event that your pod cannot be started on one of those nodes, it will be able to start on any of the cluster nodes and access its data seamlessly through the Portworx storage fabric.

This failover should all happen within a very short time window, which is very similar to the Db2 replication configuration described above. This failover is depicted in the figure below:

Db2 storage operations

So it seems that just for Reliability and High Availability alone, it would be worth running Db2 on Kubernetes and Portworx. But, there is a lot more that you can do. So many of the data management operations that are error-prone and time consuming are now going to be fully automated the same way in any cloud environment. First, we’ll show how volumes can be dynamically expanded without reconfiguring or restarting Db2 and then we will show how Snapshots can be easily restored.

Resize DB2 volume on Kubernetes

Data management tasks like these need to be predictable and automatable when it makes sense to do so. Since Portworx volumes are virtual and carved out of your aggregate storage pool on your cluster, we thinly provision the volumes so that the expansion doesn’t immediately require you to add more storage capacity to your cluster.

Setting the allowVolumeResize parameter in the StorageClass means we can do this through the Kubernetes CLI by editing the yaml. You can either do this directly with a kubectl edit pvc/db2-pvc or you can edit the spec directly and then reapply it. Either way, you will be able to check the volume and see that it is now 10GB without any disruption being caused to the running application.

Snapshot DB2 on Kubernetes

Snapshots can be scheduled as part of your storage class definition by using the Portworx command line interface (pxctl), or they can be taken on demand by using Stork. Stork uses the external-storage project from kubernetes-incubator to add support for snapshots. The following example shows you how to take a snapshot on demand using yaml in Kubernetes:

apiVersion: volumesnapshot.external-storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: db2-snapshot
  namespace: default
spec:
  persistentVolumeClaimName: db2-pvc

To learn more about Db2 snapshot schedules, please refer to our docs page.

Stork allows a snapshot to be used as a base from a which a clone PVC can be created. This allows a fresh Db2 deployment containing the snapshot data. You can read more about restoring from a snapshot using Stork in our docs.

Conclusion

As we’ve just seen, you can easily run an HA Db2 container on Kubernetes using Portworx for replication, snapshots, backups, volume resizing, and even encryption. You can see a demo of this in action!

Contact IBM

If you have questions, engage our team via Slack by registering here and join the discussion in the #general channel on our public IBM Cloud Kubernetes Service Slack.

Program Director, Offering Management, IBM Kubernetes Service & IBM Container Registry

Joe Gardiner

Solutions Lead EMEA – Portworx

More How-tos stories
April 11, 2019

How to Automate TLS Certificate Rotation to Avoid Outages

In this post, we'll share how you can make sure you have end-to-end protection for data in transit without running into any TLS certificate expiry issues.

Continue reading

April 5, 2019

Node.js 502 Bad Gateway Issues and How To Resolve Them

In December of 2018, many Node.js users noticed that their applications randomly returned an HTTP status code 502 "Bad Gateway" error. In this post, we'll show you how to resolve this issue if you have been affected.

Continue reading

April 3, 2019

Managing IBM Cloud Resources with a Service ID Through the Command Line Interface

We are excited to announce that you can now log into IBM Cloud with a service ID in v0.15.0 of the IBM Cloud CLI. This enables users to manage IBM Cloud resources with a service ID created within an account through the command line interface.

Continue reading