Development Kubernetes Docker Cloud
Things doesn’t always turn out as planned. This is specially true when it comes
to this series, on how to setup Kubernetes on Scaleway. The plan was that
part 2 would be about setting up an ingress-controller and securing the
api-server and dashboard. But in the meantime, while I was struggling with
getting weave working on ARM and re-writing my own little project sloop,
Kubernetes v1.4.0 was released with the kubeadm tool.
With the tool kubeadm, you can easily install a secure Kubernetes cluster. It
makes projects like my own Sloop unnecessary, and that’s a good thing.
In this post I will show how to setup Kubernetes using kubeadm and setting up
an ingress-controller and how to secure your api-server and dashboard. We
won’t be using ARM for this, that’s a topic for another blog post.
Here’s the recipe:
1 Scaleway account
2 VC1S servers
1 wildcard certificate
2 kubeadm
1 DaemonSet weave-kube CNI plugin
1 traefik reverse proxy (http://traefik.io)
1 traefik ingress-controller
1 domain name
1 DNS A record
You can replace the domain and DNS A record with entries in your hosts file
if you just want to try this out.
Let’s get started!
Creating your Kubernetes cluster using kubeadm is described excellent in this
guide. I only
include the steps here for completeness.
First thing is to create the k8s-master node:
# Create your master node:
$ scw start -w $(scw create --name="k8s-master" --commercial-type="VC1S"  Docker)
$ scw ps
Login to your k8s-master node and install the Kubernetes components:
$ curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
$ cat <<EOF > /etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF
$ apt-get update
$ apt-get install -y kubelet kubeadm kubectl kubernetes-cni
$ kubeadm init
Repeat the steps from installing the k8s-master but name the node: k8s-node1
and use the join command:
$ kubeadm join --token <token> <k8s-master IP>
$ kubectl apply -f https://git.io/weave-kube
daemonset "weave-net" created
If you run kubectl get nodes, on your master, you should now see two nodes:
$ kubectl get nodes
NAME         STATUS    AGE
k8s-master   Ready     1d
k8s-node1    Ready     1d
Install the latest dashboard and find the service ip:
$ kubectl create -f https://rawgit.com/kubernetes/dashboard/master/src/deploy/kubernetes-dashboard.yaml
$ kubectl get svc -n kube-system | grep dashboard
kubernetes-dashboard   100.xx.xx.xxx    <nodes>       80/TCP          2h
We will be using the dashboard service ip later on. That was easy, don’t you
think? You now have your own Kubernetes cluster running.
traefik as ingress-controller and reverse proxyUsing CNI for the pod network comes with a price tag. You can’t use hostPort
in your pods right know. Im sure this will be fixed in later versions but right
now that’s a problem. A ingress-controller uses hostPort to expose the
cluster.
The solution I found is to use a reverse proxy running as a static pod on one
of the nodes (I choose k8s-node1) and configuring it with hostNetwork: true.
Traefik is a reverse proxy written in Go and we will be using it for securing
the dashboard with basic authentication and for proxying request to the
ingress-controller which happens also be traefik.
Let’s start with installing traefik as ingress-controller:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    k8s-app: traefik-ingress-lb
  name: traefik-lb
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: traefik-ingress-lb
  template:
    metadata:
      creationTimestamp: null
      labels:
        k8s-app: traefik-ingress-lb
    spec:
      containers:
      - args:
        - --kubernetes
        image: traefik:v1.0.0
        imagePullPolicy: IfNotPresent
        name: traefik-lb
        ports:
        - containerPort: 80
          name: web
          protocol: TCP
As you can see there’s no hostPort. Next step is to expose the traefik-lb
as a service:
$ kubectl expose deployment traefik-lb --port=80 --target-port=80 -n kube-system
$ kubectl get svc -n kube-system | grep traefik-lb
traefik-lb          100.xx.xxx.xxx   <none>        80/TCP          1d
We now have two services kubernetes-dashboard and traefik-lb. These are
the backends for our traefik reverse proxy.
Here’s the traefik.toml file for our proxy:
logLevel = "DEBUG"
defaultEntryPoints = ["http", "https"]
[entryPoints]
  [entryPoints.http]
  address = ":80"
    [entryPoints.http.redirect]
    entryPoint = "https"
  [entryPoints.https]
  address = ":443"
    [entryPoints.https.tls]
      [[entryPoints.https.tls.certificates]]
      CertFile = "/etc/traefik/server.crt"
      KeyFile = "/etc/traefik/server.key"
  [entryPoints.https2]
  address = ":8443"
    [entryPoints.https2.tls]
      [[entryPoints.https2.tls.certificates]]
      CertFile = "/etc/traefik/server.crt"
      KeyFile = "/etc/traefik/server.key"
    [entryPoints.https2.auth.basic]
    users = [ "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/" ]
[web]
address = ":6443"
CertFile = "/etc/traefik/server.crt"
KeyFile = "/etc/traefik/server.key"
ReadOnly = true
  [web.auth.basic]
  users = [ "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/" ]
[file]
filename = "/etc/traefik/rules.toml"
watch = true
Save the file to /etc/traefik directory on the k8s-node1.
Use htpasswd to generate a user name and password and edit the file. Change
the CertFile: and KeyFile: to point to your wildcard certificate and key.
We’re using three entryPoints. Port 80 and 443 is reserved for our
services in the cluster, 8443 is used for the kubernetes-dashboard and port
6443 is used for the traefik webui.
Next we need to configure traefik frontend:s and backend:s in a configuration
file: /etc/traefik/rules.toml
[frontends]
  [frontends.frontend1]
  passHostHeader = true
  backend = "dashboard-backend"
  entrypoints = ["https2"]
    [frontends.frontend1.routes.test_1]
    rule = "Host:dashboard.mydomain.com"
  [frontends.frontend2]
  passHostHeader = true
  backend = "k8s"
    [frontends.frontend2.routes.default]
    rule = "HostRegexp:{subdomain:[a-z]+}.mydomain.com"
[backends]
  [backends.dashboard-backend]
    [backends.dashboard-backend.LoadBalancer]
    method = "wrr"
    [backends.dashboard-backend.servers.server1]
    url = "http://100.xx.xx.xxx:80"
   [backends.k8s]
     [backends.k8s.LoadBalancer]
     method = "wrr"
     [backends.k8s.servers.server1]
     url = "http://100.xx.xx.xxx:80"
Change the ip of the backends.dashboard-backend.servers.server1 url to your
kubernetes-dashboard service and change the ip of the
backends.k8s.servers.server1 url to the traefik-lb service. You also need
to edit the domain so that it matches your wildcard certificate.
Now it’s time to create our static pod. Copy the following to
/etc/kubernetes/manifests/traefik.yaml:
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: traefik
  name: traefik
  namespace: kube-system
spec:
  containers:
  - image: traefik:v1.1.0-rc1
    imagePullPolicy: IfNotPresent
    name: traefik
    resources: {}
    volumeMounts:
    - mountPath: /etc/traefik
      name: config
      readOnly: false
    ports:
    - name: http
      containerPort: 80
      hostPort: 80
      protocol: TCP
    - name: https
      containerPort: 443
      hostPort: 443
      protocol: TCP
    - name: webui
      containerPort: 6443
      hostPort: 6443
      protocol: TCP
    - name: dashboard
      containerPort: 8443
      hostPort: 8443
      protocol: TCP
  hostNetwork: true
  restartPolicy: Always
  securityContext: {}
  volumes:
  - name: config
    hostPath:
      path: /etc/traefik
The final step is to create a DNS A record pointing to the k8s-node1:s public
IP.
Time to check if everything is working:
$ # The dashbord requires authentication
$ curl -s https://dashbord.mydomain.com:8443
401 Unauthorized
$
$ # The traefik webui also requires authentication
$ curl -s https://webui.mydomain.com:6443
401 Unauthorized
$
$ # All other requests on port 80 and 443 is forward to k8s and traefik-lb
$ curl -s http://anyapp.mydomain.com.org
404 page not found
$ curl -s https://anyapp.mydomain.com.org
404 page not found
Ok, it seems to work. I leave it up to you to explore the dashboard and
traefik webui in you favorite browser.
We now got a secured Kubernetes cluster that we can use for hosting all our apps
and services. In the last post in this series we will setup PersistentVolume:s
using GlusterFS.
9 Oct 2016 #Development #Docker #Kubernetes #Traefik #Scaleway