Using Kubernetes with Docker for Mac

kubernetes_for_mac

If you just awoke from a few months worth of slumber (three months to be exact), this might be a bit of a shocker—Kubernetes? On Docker?  So, yes—last October Docker announced at DockerCon Europe that future EE versions are going to support Kubernetes integration.

This has been somewhat of a big topic for debate in the world of containers and orchestration, and for good reason. Since Docker offers an orchestration tool of its own, Docker Swarm, this move has given rise to article titles such as “Docker give into the inevitable” or “Kubernetes has won.”

While one can argue about the unequivocal tone used in these titles, there is little doubt that 2017 was a watershed year for Kubernetes, and in many ways for Docker as well. The announcement signified a major strategic decision by Docker, and it was followed up by the release of Docker for Mac with Kubernetes a few weeks ago.

What does this release mean?

Well, you can now build their containerized applications and deploy them to Kubernetes, locally and on the same Docker instance. As part of the deal, you get a single-node Kubernetes cluster using the latest version of Docker as the container runtime, and the ability to deploy to Kubernetes using Docker Compose or Kubernetes manifest files.

This article reviews this new release and takes you through some steps to get a simple demo application running–and yes, there is some logging  involved as well.

Downloading and installing Docker for Mac

For now, Kubernetes is only available on Docker for Mac 17.12 CE Edge (special Docker version for new and experimental features), so make sure you install the Edge version.

On your Mac, double-click the Docker.dmg file and begin the installation process as instructed.

This process takes a few minutes, at the end of which Docker is installed and launched. You will also see the little Docker whale icon appear at the top of your Mac’s screen.  Open your terminal and enter the docker info command to verify.

Kubernetes is not enabled by default. To enable it, click on the Docker icon, go to Preferences | Kubernetes, select the Enable Kubernetes checkbox and hit Apply.

After a few minutes, Kubernetes will be enabled, as reflected by the green statuses at the bottom of the preferences dialog.

Kubernetes

Exploring our Kubernetes installation

Let’s enter some kubectl commands to find out more about the installation.

We’ll start with:

kubectl version 

Client Version: version.Info{Major:"1", 
Minor:"8", GitVersion:"v1.8.2", 
GitCommit:"bdaeafa71f6c7c04636251031f93464384d54963", 
GitTreeState:"clean", BuildDate:"2017-10-24T19:48:57Z", 
GoVersion:"go1.8.3", Compiler:"gc", Platform:"darwin/amd64"}

Server Version: version.Info{Major:"1", Minor:"8", 
GitVersion:"v1.8.2", 
GitCommit:"bdaeafa71f6c7c04636251031f93464384d54963", 
GitTreeState:"clean", BuildDate:"2017-10-24T19:38:10Z", 
GoVersion:"go1.8.3", Compiler:"gc", Platform:"linux/amd64"}

Next, let’s find out about the single-node cluster:

kubectl cluster-info

Kubernetes master is running at https://localhost:6443
KubeDNS is running at https://localhost:6443/api/v1/namespaces/kube-system/services/kube-dns/proxy

And:

kubectl get nodes

NAME                 STATUS    ROLES     AGE       VERSION
docker-for-desktop   Ready     master    1d       v1.8.2

For management purposes, I’m also going to install the Kubernetes dashboard:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-rc7/aio/deploy/recommended.yaml

And the result:

namespace/kubernetes-dashboard created
serviceaccount/kubernetes-dashboard created
service/kubernetes-dashboard created
secret/kubernetes-dashboard-certs created
secret/kubernetes-dashboard-csrf created
secret/kubernetes-dashboard-key-holder created
configmap/kubernetes-dashboard-settings created
role.rbac.authorization.k8s.io/kubernetes-dashboard created
clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard created
rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created
clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created
deployment.apps/kubernetes-dashboard created
service/dashboard-metrics-scraper created
deployment.apps/dashboard-metrics-scraper created

Since the dashboard pod is deployed under the kube-system namespace, I’m going to use the following command to see the pod:

kubectl get pods --namespace kube-system  


NAME                          READY   STATUS    RESTARTS   AGE
coredns-6955765f44-kxqmm      1/1     Running   0          1d
coredns-6955765f44-mtwx5      1/1     Running   0          1d
etcd-m01                      1/1     Running   0          1d
fluentd-logzio-cskdg          1/1     Running   0          1d
kube-apiserver-m01            1/1     Running   0          1d
kube-controller-manager-m01   1/1     Running   0          1d
kube-proxy-sctqh              1/1     Running   0          1d
kube-scheduler-m01            1/1     Running   0          1d
storage-provisioner           1/1     Running   0          1d

Next, I’m going to configure port forwarding for the pod (be sure to change the name in the command):

kubectl port-forward kubernetes-dashboard-7798c48646-ctrtl 8443:8443 --namespace=kube-system

Forwarding from 127.0.0.1:8443 -> 8443

We can now access the dashboard at https://localhost:8443 (just skip the warning messages that are displayed).

Deploying a demo application to Kubernetes

It’s time to deploy a demo application. I will use the demo application used for the announcement at DockerCon Europe, which includes three containers — a Postgres database, a Java REST API for reading from the database and a simple Go app that calls the API to build cute sentences.

To deploy, we’re first going to clone the app:

git clone https://github.com/dockersamples/k8s-wordsmith-demo

We are then going to use Docker Compose to build the project:

cd k8s-wordsmith-demo
docker-compose build

This will take a few minutes, but once done, all we have to do to deploy to our Kubernetes cluster is use the supplied manifest:

kubectl apply -f kube-deployment.yml

Let’s review the deployed services:

kubectl get svc

NAME         TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
db           ClusterIP      None            <none>        5432/TCP         2h
kubernetes   ClusterIP      10.96.0.1       <none>        443/TCP          10d
web          LoadBalancer   10.105.194.57   <pending>     8081:32218/TCP   2h
words        ClusterIP      None            <none>        8080/TCP         2h

We can now browse to http://localhost:8081 to see the beautiful app in action in our browser:

blocks

The Kubernetes management dashboard will now show the relevant information about the deployment:

workload

Adding logging into the mix

You didn’t think I would end this article without mentioning logging, did you? Let’s take a look at a simple way to hook up our newly installed Kubernetes with Logz.io for a simple logging workflow (feel free to skip to the summary if logging is of no interest).

To do this, we will use the Docker log collector created by Logz.io. This lightweight Docker container will ship container logs, as well as Docker stats and daemon events. In production, you will need to use it per cluster node, but in our case we only have one node so it’s an easy and quick fix.

Create a manifest file, and use the following example (insert your Logz.io token where relevant):

sudo vim logzio.yml 

---
kind: Pod
apiVersion: v1
metadata:
  name: logzio-docker-logs-shipper
  namespace: kube-system
  creationTimestamp:
  labels:
    component: logzio-docker-logs-shipper
spec:
  containers:
  - name: logzio-docker-logs-shipper
    image: logzio/logzio-docker
    imagePullPolicy: IfNotPresent
    resources:
      limits:
        cpu: 100m
        memory: 128Mi
      requests:
        cpu: 20m
        memory: 64Mi
    args:
    - "--token=<LogzioToken>"
    - "-a env=dev"
    - "--no-secure"
    - "--endpoint=listener.logz.io"
    - "--matchByName=.*"
    env:
    - name: HOSTNAME
      value: kube-for-mac
    volumeMounts:
    - mountPath: /var/run/docker.sock
      name: dockersock
  volumes:
  - name: dockersock
    hostPath:
      path: /var/run/docker.sock

Create the manifest:

kubectl create -f logzio.yml

pod "logzio-docker-logs-shipper" created

Within a few seconds, the container will be running under the kube-system namespace:

kubectl get pods --namespace kube-system

NAME                                         READY     STATUS             RESTARTS   AGE
etcd-docker-for-desktop                      1/1       Running            0          1d
kube-apiserver-docker-for-desktop            1/1       Running            0          1d
kube-controller-manager-docker-for-desktop   1/1       Running            0          1d
kube-dns-545bc4bfd4-rrlgf                    3/3       Running            0          1d
kube-proxy-bjsjw                             1/1       Running            0          1d
kube-scheduler-docker-for-desktop            1/1       Running            0          1d
kubernetes-dashboard-747d579ff5-vhkl7        1/1       Running            0          3h
logzio-docker-logs-shipper                   1/1       Running            0          1m

logz.io

Endnotes

More than anything, the main benefit of this release is making Kubernetes more accessible. The installation and setup process is seamless. In just a few minutes, you can have a Kubernetes cluster, albeit consisting of a single node, up and running in your local dev environment. With all due respect to Minikube, Docker for Mac with Kubernetes is probably one of the easiest ways to set up a Kubernetes dev environment.

It will be interesting to see where Docker takes this in 2018. What will happen to Docker Swarm? There are still plenty of Swarm users out there. The ability to deploy Docker stacks to Kubernetes will help those contemplating a migration from Swarm but might also hasten its demise. Will Docker work on a tighter Kubernetes integration in CE/EE?

And one last note — be sure to have the charger for your Mac handy.

Enjoy!

Get started for free

Completely free for 14 days, no strings attached.