IntroductionIt is now possible to create/maintain Kubernetes clusters on Digital Ocean quite easily.
In this post I will show you how to create a cluster with a pod that has a public endpoint; this endpoint will be secured with a Let’s Encrypt SSL certificate.
Some basic Kubernetes knowledge is assumed so i won’t go into detail explaining what a deployment, service or pod is, or how to work with kubectl. N.B. Kubernetes support on Digital Ocean is still in beta, so it maybe not available to you.
OverviewThe application we are going to deploy is called ‘whoami’ which has an endpoint that outputs some information about the request that is
sent to it.
We will expose this endpoint through https://whoami.example.com (N.B. example.com is a fake domain name and is used for illustration purposes, replace it with domain you actually own)
In the picture below is the end result is shown: The parts that are of interest for external access are the ingress, ingress controller and the load balancer.
An ingress is a Kubernetes object defined in our application namespace that defines the rules to which service (or pod) external requests are routed.
In this case we define an ingress with the following rule:
“If an incoming request contains ‘whoami.example.com’ in the host header, the request is routed to the whoami service.”
The actual routing is done by an ingress controller which in most cases uses also a load balancer to route incoming requests.
The controller we will use is Traefik, which also handles SSL termination. This means also that the traffic between the controller and the service/pod is flowing through HTTP.
Traefik also handles the automatic acquiring and renewal of the Let’s Encrypt certificates
- You have a Digital Ocean account and created a project in the control panel.
- You own the domain example.com and you are able to adminster its DNS records through Digital Ocean.
- You have kubectl installed on your computer.
- A Digital Ocean API token with read/write access, which is needed later for the configuration for the acquiring of the certificate.
Setting up a cluster in Digital OceanThrough the Digital Ocean control panel create a cluster with 1 node to keep things simple (and cheap):
- Choose ‘Kubernetes’ in the left navigation bar.
- Click ‘Create’ and select ‘Clusters’.
- Select datacenter AMS3.
- Under ‘Add node pool’ select from the ‘Standard node pool’ the ‘$5 month plan’ and set the number of nodes to 1.
- For the name type ‘k8s-test’.
- Click ‘Create cluster’ and a new cluster will be provisioned.
- When the cluster is provisioned go to the cluster control panel and click ‘Download’.
- Copy this file to your ~/.kube directory and name the file ‘config’. This makes kubectl point to the just created cluster.
- We need to create a default service account with full rights (needed for the Helm package manager and for the Traefik package be able to deploy its stuff to the cluster,
you probably don’t want to do this in production (at least have a dedicated user). )
- Paste the following to a file and execute ‘kubectl apply -f filename’ to deploy it to the cluster.
apiVersion: v1 kind: ServiceAccount metadata: name: default namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: default roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: default namespace: kube-system
TraefikTo install the Traefik ingress controller:
- Install Helm, this is a package manager for Kubernetes which makes installation of Traefik very easy.
- Run ‘helm init’ to initialize Helm on the client and on the cluster.
- Run ‘helm install –name traefik-thingie -f values.yaml stable/traefik –namespace kube-system’.
The values.yaml file contain the configuration for Traefik. A more detailed explanation is provided below.
- Wait until Traefik is deployed. (it creates also a L4 load balancer in Digital Ocean)
- In the DO control panel look up the IP address of the load balancer just created and create an A record in the Domain section with the whoami.mydomain.com domain pointing to this IP address.
ConfigurationBelow is the configuration of the Traefik helm chart which is used in this example. For more information about all options see here.
Save this file as ‘values.yaml’ and use it during installation of Traefik. (see above)
ssl: enabled: true # Enables SSL enforced: true # Redirects HTTP to HTTPS acme: enabled: true # Enables Let's Encrypt certificates staging: true # Use Lets Encrypt staging area for this example. For production purposes set this to false email: email@example.com # Email address that Let's Encrypt uses to notify about certificate expiry etc. challengeType: "dns-01" dnsProvider: name: digitalocean # This is why you need your domain to be under Digital Ocean control digitalocean: DO_AUTH_TOKEN: "INSERT_API_TOKEN_HERE" domains: enabled: true domainsList: - main: "example.mydomain.com" # Name of the domain that belongs to this certificate
ApplicationThe application is deployed on the cluster using a simple service and deployment.
Paste this to a file and use (again) ‘kubectl apply -f filename.yaml’ to deploy it to the cluster.
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: whoami-deployment spec: replicas: 1 selector: matchLabels: app: whoami template: metadata: labels: app: whoami spec: containers: - name: whoami-container image: containous/whoami ---- apiVersion: v1 kind: Service metadata: name: whoami-service spec: ports: - name: http targetPort: 80 port: 80 selector: app: whoami
IngressThe important part however is the definition of the ingress.
The interesting bits are here:
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: whoami-ingress annotations: kubernetes.io/ingress.class: traefik spec: rules: - host: whoami.example.com http: paths: - path: / backend: serviceName: whoami-service servicePort: http
- The annotation kubernetes.io/ingress.class should be set to ‘traefik’, so that the Traefik ingress controller is aware of our ingress (remember, an ingress is just a routing rule which the ingress controller should enforce)
- The ‘host’ field should be set to our domain, and the ‘backend’ should be set to our service defined above.
Showtime!If all of the above went well, go to https://whoami.example.com and you should see a page with the content like below (note the X-Forwarded-Port and X-Forwarded-Proto which indicates that the request was coming through https. )
GET / HTTP/1.1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:63.0) Gecko/20100101 Firefox/63.0
Accept-Encoding: gzip, deflate, br