DEV Community

Mohammad Reza Karimi
Mohammad Reza Karimi

Posted on

[TechStory]: Migrating services and databases from an OpenShift (or K8s) cluster to another

Welcome Friends to another TechStory!

My first experience with OpenShift was with a task which was kind of a heavy task, I didn't know anything about OpenShift or K8s! but I was in charge of migrating resources from a cluster to one another! (twice!)

But I learned a lot of things in the middle, so let's have a look at some of those.

Before going deep dive, you may wonder what is OpenShift and why do I put its name beside K8s everytime, It's actually becuase Openshift is built on top of K8s and it's kind of the same (+few more features), so don't worry about the difference.

So, What's the problem?

As I told you before, I had to move resources such as Applications (pods+services+routes), Databases (+their data) from an OKD3 cluster to an OKD4 cluster (different versions of OpenShift)

The reason of this migration? I'm not sure!
To be honest, this was already decided and it was on the board,
Also in some companies, Kubernetes has two sides, cloud side and developer side, we (developers) don't lunch Kubernetes, instead, we lunch our services on it.

Where did I start?

I asked two question on Stackoverflow because it was not clear for me what to do at the first place, and there were a lot of suggestions, which I just mention:

Note: Unfortunately I can't provide a link to questions, although they were well received but a moderator deleted them 🤔

I also found and provided my answer, I followed it and I think it taught me a lot of things and there is nothing wrong with it, but it was not good enough solution for this case.

Not good enough solution!

For making resources in a K8s cluster you should be careful about their priority,

First things to make are secrets and config maps, because they don't depend on anything but everything can depend on them!

And last things are routes, guess why? because they depend on services but nothing depends on them!

So the priority is:

  • Secrets and ConfigMaps
  • StatefulSets
  • Deployments
  • Services
  • Routes

You may not need to move pods directly, because they are usually made and controlled by other resources such as
Deployments or StatefulSets.

Steps to follow:

  • Login to the first cluster:
oc login --token="your-token-for-first-server" --server="your-first-server"
Enter fullscreen mode Exit fullscreen mode
  • Export your resources:
oc get -o yaml cm > configmaps.yaml
oc get -o yaml secrets > secrets.yaml
...
Enter fullscreen mode Exit fullscreen mode

There are also some default ConfigMaps and Secrets which you don't need to copy, you can erase them from generated yaml files.

  • Login to the second cluster:
oc login --token="your-token-for-second-server" --server="your-second-server"
Enter fullscreen mode Exit fullscreen mode

If you forget this step, you may get an error that says resource already exists, but be careful not to forget this step.

  • Load resources to the second cluster
oc create -f configmaps.yaml
oc create -f secrets.yaml
...
Enter fullscreen mode Exit fullscreen mode

Better solutions

There was a better solution, we can use Templates and process them for different clusters, environments or namespaces.

Also, combining them with CI/CD pipelines, helps us to move our resources by just changing some variables!

Helm works even better! I personally prefer Helm over basic templating.

I improved our CI/CD pipelines and Helmified (used Helm 😁) our applications for easier, clean and seamless deployments.

What about DB?

DB is also another important & long discussion here, but not the database application itself, we can easily create that, but what should we do about the data? data is everything!

In my case, they were two scenarios:

  • Production
  • Stage (testing environment - production with fake data)

In Production, we had a managed Database controlled and owned by DBA team, we just had URL for Accessing it and that was enough.

So in cases that your accessing data which is in an external database (out of cluster), you don't need any extra work.

But in Stage, our data was stored in a PVC attached to a Pod controlled by a StatefulSet.

Note: We had MySQL, you may have something else, but the fellow is almost the same.

Steps to follow:

Step 1: Login and port-forward

Login to the first Openshift cluster:

oc login --token=<YOUR-TOKEN> --server=<YOUR-SERVER>
Enter fullscreen mode Exit fullscreen mode

List all pods and select your db pod (if replicated, choose master (0)) and copy it:

oc get pods
Enter fullscreen mode Exit fullscreen mode

Make a port-forwarding to your local computer:

oc port-forward <MYSQL-POD-NAME> <desired-local-port>:<mysql-on-server-port>
Enter fullscreen mode Exit fullscreen mode

So your server database is now (like) your local database! and any change you want on server can be done on localhost.

This method is the same for all databases and also applications.


Step 2: tools

Install mysql command line tools (if you have them installed, skip this step).
Specifically, we need mysqldump and mysql commands.

To do so, on macos run:

brew install mysql-client
Enter fullscreen mode Exit fullscreen mode

I needed to add them to path (it usually happens automatically), run command below and add /opt/homebrew/opt/mysql-client/bin to the end of the file:

sudo nano /etc/paths 
Enter fullscreen mode Exit fullscreen mode

Other editors such as vscode (type code in terminal) can be used instead of nano.

Read here and here for more information.


Step 3: take a dump

mysqldump --column-statistics=0 --no-create-info -P <local-port> -h 127.0.0.1 -u <YOUR-USERNAME> -p "YOUR-DATABASE-NAME" > file_name.sql
Enter fullscreen mode Exit fullscreen mode

Then you'll be asked to enter the database password for .

In my case, I previously ran migration scripts so I didn't want my dump to include CREATE TABLE... queries, so I added --no-create-info argument, but you may want to erase it.

Also, I was facing with Unknown table 'COLUMN_STATISTICS' in information_schema (1109) error, so I added --column-statistics=0 argument.
For more information, read here and here.

About the host IP, do not use localhost, it probably connects by socket rather than by port.


Step 4: load the dump

Now, login to the second cluster, make the StatefulSet, and port-forward its database as explained before,
(you can run your migration scripts here on this local-like database and they will be done on the cluster as well)

Then, load the dump with below command:

mysql -P <local-port> -h 127.0.0.1 -u <YOUR-USERNAME> -p -f "YOUR-DATABASE-NAME" < file_name.sql
Enter fullscreen mode Exit fullscreen mode

In my case, I had some unimportant errors, I've passed -f argument to skip them, but be careful when using this argument as it forces the database to follow your introduction defined on file_name.sql.

Conclusion

TechStories are my real job experiences, they might be confusing as they include a lot of information and links to other articles, that's my point! we (developers) don't work in the way people see in usual articles and tutorials, so I want to share my knowledge beside teaching a lot of different tips that get related in my task.

I hope you enjoyed! 🥳✌🏼

Top comments (0)