Kompose

Docker Compose to Kubernetes with Kompose

Kompose is a great tool, billed as the meeting ground of Docker Compose and Kubernetes (Kubernetes + Compose = Kompose). In this article we will give a brief overview of using Kompose to move workloads from Docker Compose to Kubernetes.

Docker to Kubernetes with Kompose

You can download Kompose from their official site or their github page.

To get started, let’s use a simple Docker compose file for an echo service. This is a simple container that  echo bad the request information, for example the requested path and headers. 

version: "3"
services:
  echo-server:
    image: gcr.io/kubernetes-e2e-test-images/echoserver:2.2
    ports:
      - 32000:8080

Run this container to make sure we get the desired results.

$ docker compose -f docker-compse.yaml up -d

Now, curl to your host over port 32000 to confirm it is working.

$ curl http://localhost:32000

Hostname: 45e6784e1cc5

Pod Information:
        -no pod information available-

Server values:
        server_version=nginx: 1.12.2 - lua: 10010

Request Information:
        client_address=172.27.0.1
        method=GET
        real path=/
        query=
        request_version=1.1
        request_scheme=http
        request_uri=http://localhost:8080/

Request Headers:
        accept=*/*  
        host=localhost:32000  
        user-agent=curl/7.64.1  

Request Body:
        -no body in request-

Time to convert this to a set of Kubernetes manifests. Running with the convert subcommand and no parameters will pick up your docker-compose.yaml.

$ kompose convert
INFO Kubernetes file "echo-server-service.yaml" created 
INFO Kubernetes file "echo-server-deployment.yaml" created 

You will now notice two new files got created in your folder, echo-server-service.yaml & echo-server-deployment.yaml.

echo-server-service.yaml translates the services.echo-server.ports from our compose to a Kubernetes service exposing the ports. echo-server-deployment.yaml translates the container information to pods wrapped in a deployment.

Compose:

ports:– 32000:8080

Manifest

apiVersion: v1
kind: Service
metadata:
  labels:
    io.kompose.service: echo-server
  name: echo-server
spec:
  ports:
    - name: "32000"
      port: 32000
      targetPort: 8080
  selector:
    io.kompose.service: echo-server
status:
  loadBalancer: {}

Keep in mind, this defaults to exposing your service as a ClusterIP so it will only work inside your cluster. Addressing this will be part of our clean up efforts after converting it. We will see a bit later some changes that can be made ahead of time to the compose to affect this as well

Now for our container definition, in the compose we simply defined the image.

Compose:

    image: gcr.io/kubernetes-e2e-test-images/echoserver:2.2

Once we convert this however it is wrapped in a Kubernetes deployment.

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    kompose.cmd: kompose convert
    kompose.version: 1.23.0 (bc7d9f4f)
  creationTimestamp: null
  labels:
    io.kompose.service: echo-server
  name: echo-server
spec:
  replicas: 1
  selector:
    matchLabels:
      io.kompose.service: echo-server
  strategy: {}
  template:
    metadata:
      annotations:
        kompose.cmd: kompose convert
        kompose.version: 1.23.0 (bc7d9f4f)
      creationTimestamp: null
      labels:
        io.kompose.service: echo-server
    spec:
      containers:
        - image: gcr.io/kubernetes-e2e-test-images/echoserver:2.2
          name: echo-server
          ports:
            - containerPort: 8080
          resources: {}
      restartPolicy: Always
status: {}

Without making any modifications at the moment, we are free to create these objects in Kubernetes. What we end up with is a Kubernetes Deployment running a single replica of the Echo container exposed as a ClusterIP address.

$ kubectl create -f echo-server-deployment.yaml -f echo-server-service.yaml
deployment.apps/echo-server created
service/echo-server created

Nice and easy, we have now moved a simple compose file to Kubernetes. But what if you wanted to expose that Kubernetes service as a NodePort instead of the default ClusterIP? Kompose supports about 15 custom labels that can control the output. Simply add the labels to your compose file, in this example we will add kompose.service.type and kompose.service.nodeport.port to our docker-compose.yaml.

version: "3"
services:
  echo-server:
    image: gcr.io/kubernetes-e2e-test-images/echoserver:2.2
    ports:
      - 32000:8080
    labels:
      kompose.service.type: nodeport
      kompose.service.nodeport.port: "32087"	

If you run kompose convert again, it will resulted in the updated manifest:

apiVersion: v1
kind: Service
metadata:
  annotations:
    kompose.cmd: kompose convert
    kompose.service.nodeport.port: "32087"
    kompose.service.type: nodeport
    kompose.version: 1.23.0 (bc7d9f4f)
  creationTimestamp: null
  labels:
    io.kompose.service: echo-server
  name: echo-server
spec:
  ports:
    - name: "32000"
      nodePort: 32087
      port: 32000
      targetPort: 8080
  selector:
    io.kompose.service: echo-server
  type: NodePort
status:
  loadBalancer: {}

The Kompose labels provide a bit more flexibility in defining the generated resources’ behavior upon conversion. They can be used on define healthchecks (readiness/liveness probes), pull secrets, services, volumes, etc.

As you can see, Kompose adds a fair amount of annotations to the converted files, but the majority of these can easily be removed by passing the the parmeter “–with-kompose-annotation=false”

kompose convert  --with-kompose-annotation=false

One final comment, you may notice that if your docker-compose has a restart policy if “on-failure” it will convert to a Kuberentes Pod as opposed to a deployment. You could change the restart policy to “always” instead, but it can also be override through the controller command line parameter.

kompose convert --controller deployment

This parameter supports values of deployment, daemonSet and replicationController. That’s it for this post, hopefully it provided a good overview of the power of Kompose.