Basic Kubernetes Infrastructure for Microservice-powered Projects

A Long Foreword

If you’re thinking about starting a new project which is to take advantage of microservice-based architecture, one of the very first things you’ll have to take into consideration is organizing all necessary surroundings. Let’s assume your project is supposed to keep some sort of information. This need can be solved in a couple of ways, of course, but probably the most popular way to store your data is employing a relational database. There are lots of such applications you can choose from, but this time again, let’s stick to the most universal and widely accepted example—PostgreSQL.

Nowadays, it’s super easy to setup a PostgreSQL instance with Kubernetes (or even with Docker only), but it hasn’t always been like that. Without any software that enables you to design your infrastructure in a declarative way, you had to make sure all the software prerequisites are present on your machine. As for PostgreSQL, it means you had to install it manually first, making your fresh copy somewhat global within your OS. If you were OK with that approach, you would write a bunch of custom deployment scripts, set up a new Git repo to store them all, and so on. Then you had your infrastructure project ready.

But here comes another problem: a database instance is shared not only with all your dev projects, but also with virtually everything else running on your machine that requires it. To cope with such a problem, an extra layer of management has to be added: PostgreSQL user & database management, which increases complexity and calls for more SQL management scrips. This is how it looked before the advent of software containerization, but fortunately, now it’s history.

How Containerization Can Help

The central point which containerization software is organized around seems to be the notion of separation. Each container instance is like a separate PC connected to a network. You can start tens of such PCs and everything is running on your laptop. Then you can pick up a single PC (container) from the pool, and order it to run PostgreSQL. You can organize a few containers into a group called namespace and it gives you a separated playground for your project. If you switch to another project, you start using a different namespace associated with it. This namespace runs its own copy of a database which means nothing is shared. It’s like having dedicated laptops to work with many projects.

A Few Words About Declarative Approach

Contemporary deployment tools are operated with help of so-called declarative languages. They are used to write scripts that don’t contain instructions to tell computers what to do but what you’d like to achieve instead and let the software associated with these languages work constantly to secure you are getting your desired infrastructure as soon as possible, right after you’ve submitted your changes. It is the software agent that is responsible for knowing how to do it (what instructions to execute) and you only have to describe what to do using a dedicated language. This is very convenient. However, it comes at a small cost: traditional (so-called imperative) scripts are far more flexible than declarative ones because they don’t limit your deployment. Basically you can do whatever you want with all the possible low-level OS commands. If you decide to use declarative scripts, you are restricted to modelling your deployment after some pre-defined framework. Nevertheless, it shouldn’t be a problem as long as all you need to do doesn’t go too far away from common deployment scenarios.

The First Example: PostgreSQL Deployment with Docker

Starting a Container

If you have Docker installed and want to run PostgreSQL, all you have to do is opening a new terminal session and issuing the following Docker command:

1
docker run --name postgres -d --rm -p 5432:5432 -e "POSTGRES_PASSWORD=postgres" postgres

Let’s describe each parameter.

The main command is docker and run is a subcommand that tells Docker to start a new container instance out of a named predefined image.

The third component is made up of two words: --name postgres. This optional parameter allows you to assign the container instance a name (the name can be anything you can think of).

The short option -d stands for detach. If you put it, Docker will run the container in background and no container logs will be printed but only a container ID (just like the container name, it’s another method of referencing a container). The command will exit immediately right after it.

The option --rm stands for remove. If you use it, the container will be removed from Docker when it finishes its execution (otherwise you would keep the list of dead container instances growing).

The parameter -p 5432:5432 makes Docker bind port 5432 of PostgreSQL container to port 5432 of the local host. Note that it makes it possible to run multiple containers from the same image by binding the same container port to two different host ports.

The parameter -e "POSTGRES_PASSWORD=postgres" allows to set environment variables for the container. Here we’re using it in order to configure PostgreSQL password, which is enough for development purposes.

The last part is probably the most important one (postgres) since it’s the name of Docker image to make a container instance out of.

As soon as you hit Enter, Docker will respond with an ID similar to what you can see below:

1
a284486d8e5bddaa357e2c1270452eb8a9e51d8de8f562dea4d04bf93ac27139

Listing Active Containers

If you’d like to find out what are the names and IDs of running containers, type the following:

1
docker ps

The response will look like:

1
2
CONTAINER ID   IMAGE      COMMAND                  CREATED         STATUS         PORTS                                       NAMES
a284486d8e5b postgres "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp postgres

The command gives you a lot of useful information, including container IDs, names, port bindings, source image identifiers, and many others.

Stopping a Container

If you’d like to switch off your PostgresSQL database, the following command does what you need:

1
docker kill postgres

You can use either a container ID or a name. When you let it go with Enter, the response will contain just the name:

1
postgres

Conclusion

In this blog post, I covered the very basics of Docker, which can help in designing infrastructure for development purposes. This way, I’d like to start a series of articles to expand the topic by showing examples of Docker Compose and Kubernetes.