Richard Li CEO and Co-Founder

Quick Take on Docker for Mac with Kubernetes (and some tips on using Ingress)

On January 8, Docker released a beta version of Docker that includes Kubernetes support. I was excited to try it out on my Mac. Here are my notes and observations from experimenting with Docker for Mac with Kubernetes.

Installation

The Docker folks usually do a great job with a simple user experience, and installation was no exception. I downloaded the edge installer for Docker, which uninstalled my stable version of Docker. In the preferences pane, I enabled Kubernetes, and shortly thereafter, I had a working Kubernetes cluster.

Installing Docker for Mac with Kubernetes

I was also able to use the preexisting kubectl on my laptop. The installer assumes your Kubernetes configuration is stored in $HOME/.kube/config . If you have set KUBECONFIG to a different file, you’ll want to point it back to config .

Docker for Mac and Ingress

I decided to try installing Ambassador, our open source API Gateway built on the Envoy Proxy. Ambassador strives to be as idiomatic to Kubernetes as possible (e.g., it’s configured via annotations), so it’s a good real-world test for a Kubernetes implementation.

Docker for Mac is based on Kubernetes 1.8.2, so I installed Ambassador with RBAC:

Copy --- apiVersion: v1 kind: Service metadata: labels: service: ambassador-admin name: ambassador-admin spec: type: NodePort ports: - name: ambassador-admin port: 8877 targetPort: 8877 selector: service: ambassador --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRole metadata: name: ambassador rules: - apiGroups: [""] resources: - services verbs: ["get", "list", "watch"] - apiGroups: [""] resources: - configmaps verbs: ["create", "update", "patch", "get", "list", "watch"] - apiGroups: [""] resources: - secrets verbs: ["get", "list", "watch"] --- apiVersion: v1 kind: ServiceAccount metadata: name: ambassador --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: ambassador roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: ambassador subjects: - kind: ServiceAccount name: ambassador namespace: default --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: ambassador spec: replicas: 1 template: metadata: labels: service: ambassador spec: serviceAccountName: ambassador containers: - name: ambassador image: datawire/ambassador:0.21.0 imagePullPolicy: Always resources: limits: cpu: 1 memory: 400Mi requests: cpu: 200m memory: 100Mi env: - name: AMBASSADOR_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace livenessProbe: httpGet: path: /ambassador/v0/check_alive port: 8877 initialDelaySeconds: 3 periodSeconds: 3 readinessProbe: httpGet: path: /ambassador/v0/check_ready port: 8877 initialDelaySeconds: 3 periodSeconds: 3 - name: statsd-sink image: datawire/prom-statsd-exporter:0.6.0 restartPolicy: Always

I then deployed an Ambassador LoadBalancer service:

Copy --- apiVersion: v1 kind: Service metadata: labels: service: ambassador name: ambassador spec: type: LoadBalancer ports: - name: ambassador port: 80 targetPort: 80 selector: service: ambassador

I wanted to try to connect to Ambassador, but this is what I saw:

$ kubectl get svc NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE ambassador 10.106.236.196 <pending> 80:30612/TCP 45m ambassador-admin 10.102.220.182 <nodes> 8877:31079/TCP 4h kubernetes 10.96.0.1 <none> 443/TCP 4h

Note that the ambassador service has been running for 45 minutes, and it was still for an external IP. Hopping on the Docker Slack channel, I found out that the service controller doesn’t update the service object (yet). It turns out that the service is actually exposed locally. So the following worked:

$ curl localhost:80

I added a mapping for Ambassador to route /httpbin/ to the httpbin.org service with the following configuration YAML:

Copy apiVersion: v1 kind: Service metadata: name: httpbin annotations: getambassador.io/config: | --- apiVersion: ambassador/v0 kind: Mapping name: httpbin_mapping prefix: /httpbin/ service: httpbin.org:80 host_rewrite: httpbin.org spec: ports: - port: 80

And it worked perfectly:

$ curl localhost:80/httpbin/ip { "origin": "65.217.185.138" }

Some other notes on Ingress

In some conversations on the Slack channel, I learned a few other quirks:

To get a list of open ports, you can compile this binary. I haven’t tried this.

The service controller does not yet handle collisions between competing services. So the last service will win.

Docker Stacks and CRDs

Docker includes a native integration between Docker Swarm and Kubernetes with a stack custom resource definition. I’ve heard from many users how they love the simplicity of Docker Compose , and the stack CRD seems like a compelling approach.

Conclusion

Docker for Mac with Kubernetes has a lot of promise. While there are the rough edges you’d expect with any beta software, the Docker team has done an amazing job of building a useful alternative to Minikube. In addition, I’m excited to see how they’ve thought through how to make the experience idiomatic for Kubernetes users. I’m looking forward to updates!