Kubernetes CKAD weekly challenge #7 Migrate a Service

Kim Wuestkamp
codeburst
Published in
4 min readMay 6, 2019

--

CKS Exam Series | CKA Exam Series | CKAD Exam Series

#####################################

THIS CHALLENGE WON’T BE UPDATED HERE AND MOVED TO:

https://killercoda.com/killer-shell-ckad

######################################

Challenges:

Overview and Tips

  1. Creating Pods
  2. Namespaces, Deployments and Services
  3. CronJobs and Volumes
  4. Deployment Rollout Rollback
  5. Secrets and ConfigMaps
  6. NetworkPolicy
  7. Service Migration
  8. (moved to CKA challenge series)
  9. Logging Sidecar
  10. Deployment Hacking
  11. SecurityContexts
  12. Various Environment Variables
  13. ReplicaSet without Downtime

Rules!

  1. be fast, avoid creating yaml manually from scratch
  2. use only kubernetes.io/docs for help.
  3. check my solution after you did yours. You probably have a better one!

Notices

Todays Task: Simulate migration phase of external service

Let’s say we have a running cluster but one service is still outside. We pretend www.google.com:80 is our external service which we would like to migrate into the cluster in a few phases. Between each phase there could be days or weeks passing, but we simulate this in one go today.

  1. Create a deployment called compute of three replicas of image byrnedo/alpine-curl which keep running for a while. Make sure they can reach our external service: curl www.google.com:80
  2. We will move this external service soon inside the cluster. But till then we create an ExternalName service called webapi which points to www.google.com. Make sure our pods can reach that internal service and get forwarded to our external one. curl webapi --header “Host: www.google.com"
  3. Create a deployment called nginx of image nginx. We pretend this is a replica of our external www.google.com:80
  4. Change the internal webapi service to no longer point to the external DNS but our internal nginx pod. Test the connection from compute pods to webapi service: curl webapi

Solution

1. Cluster connected to external service

use kubectl >= 1.18alias k=kubectlk run --helpk create deploy compute --image=byrnedo/alpine-curl --dry-run=client -oyaml > compute.yaml# DEPRECATED and won't work no more with 1.18
k run compute --image=byrnedo/alpine-curl --replicas=3 --command -- /bin/sh -c "sleep 10d"

Now edit in vim:

apiVersion: apps/v1
kind: Deployment
metadata:
name:
compute
spec:
replicas:
3
selector:
matchLabels:
app:
compute
template:
metadata:
labels:
app:
compute
spec:
containers:
- command:
- /bin/sh
- -c
- sleep 10d
image: byrnedo/alpine-curl
name: compute

And run and exec:

k create -f compute.yamlk exec compute-66f769c5d9-6chc9 -- curl www.google.com:80

We now have a running cluster which can reach our external web service.

2 Migration phase with ExternalName service

k create svc --helpk create svc externalname --helpk create svc externalname webapi --external-name www.google.comk describe svc webapik exec compute-fd98796c6-27w65 -- ping webapik exec compute-fd98796c6-27w65 -- curl webapi --header "Host: www.google.com" # we can reach home of www.google.com

Instead of using the external DNS name we can now use our internal service name webapi. This means we can redirect all internal requests already to this dns name although it’s still outside the cluster.

3 Migrate the external service inside the cluster

k create deploy nginx --image=nginx # we simulate the migration# DEPRECATED from 1.18 this will create a single pod and no deployment:
k run nginx --image=nginx

We imagine the internal nginx deployment is a running replica of our external service www.google.com:80, both are now running simultaneously in this transitioning phase.

4 Point webapi service to internal nginx

Now it’s time to no longer send requests to www.google.com:80 but our internal nginx pod.

k get svc webapi -o yaml > webapi.yaml# DEPRECATED and might not work in the real exam
k get svc webapi -o yaml --export > webapi.yaml

Now edit webapi.yaml to remove all unnecessary data, to like something like this (we change the service type from ExternalName to ClusterIP):

apiVersion: v1
kind: Service
metadata:
name:
webapi
spec:
selector:
app:
nginx
ports:
- name: "80"
port: 80
targetPort: 80
type: ClusterIP

Make sure the selector refers to the correct labels of your nginx pod. Then apply the changes and check connectivity:

k delete -f webapi.yamlk create -f webapi.yamlk exec compute-fd98796c6-27w65 -- ping webapik exec compute-fd98796c6-27w65 -- curl webapi

The curl webapi did still point to www.google.com, probably because of some DNS caching on the pod I thought. So I tried recreating all pods (kubectl delete pod --all) but this didn’t change. The webapi name was still resolved even if I removed the webapi service completely! So it must be Kubernetes dns caching.

To flush dns resolution I identified the kube-dns pod and forced its recreation:

k get pod -n kube-system | grep dnsk delete pod kube-dns-86f4d74b45-z8lnsk exec compute-fd98796c6-27w65 -- curl webapi # this now returns the default nginx page instead of www.google.com !

Nice, we finished the migration. As with all good migrations we had some little hiccups but were able to solve this by “clearing” the kube dns cache (aka killing the kube-dns pod). Let me know if there is a cleaner solution for this!

Now we can shut down our outside service www.google.com:80 ;)

End

The ExternalName service is really useful when migrating an existing infrastructure into Kubernetes. You can already create your whole service structure and use internal name resolution. Then, step by step, you can change the services to point to inside objects just by changing the service type.

ALL CHALLENGES AND TIPS

More on

https://killer.sh

--

--

killercoda.com | killer.sh (CKS CKA CKAD Simulator) | Software Engineer, Infrastructure Architect, Certified Kubernetes