You are browsing a read-only backup copy of Wikitech. The live site can be found at

Kubernetes/Kubernetes Workshop/Step 2

From Wikitech-static
< Kubernetes‎ | Kubernetes Workshop
Revision as of 06:24, 11 March 2021 by imported>Wolfgang Kandek (Wolfgang Kandek moved page Kubernetes/Kubernetes Workshop Step 2 to Kubernetes/Kubernetes Workshop/Step 2)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Step 2 - Run a service application on k8s

K8s has extensive support for running service applications such as a web server, for example automated restarts, load balancing, dynamic scaling and others.

Let’s use a simple web server to explore some of the options.

Hands on: Make a docker image that serves a simple “Hello World” webpage.

Here is a step by step that uses the apache web server in the docker interactive mode.

We will base it on the ubuntu docker image.

  • Bring up a base ubuntu image and log into the shell docker run -it ubuntu /bin/bash
  • Install apache apt-get update && apt-get install apache2
  • Replace index.html with Hello World vi /var/www/html/index.html - vi not installed: apt-get install vim or maybe echo "<HTML><BODY>Hello World</BODY></HTML>" > /var/www/html/index.html
  • Start Apache - in Docker we typically want to run the server binary in the foreground and not exit as it will terminate the container, so:
    • apachectl -DFOREGROUND
  • If you exit the shell on the docker container it stops running and you lose all work. You can save the progress by running the command docker commit in another window:
    • docker ps to find the id of the container
    • docker commit <id> <name of new image>
    • docker image ls to check
  • docker commit is also used to specify what binary to run on startup. In addition we need to tell the container what port is to be exposed to the outside world.

docker commit --change='CMD ["/usr/sbin/apachectl", "-D FOREGROUND"]' --change='EXPOSE 80'<id> <name of new image>

  • Finally run the container and map the network port to a local port
    • docker run -p 80:80 <name of new image>
    • On the host machine: curl http://localhost will now get the page from the apache running in the container
    • One can “shell” into the container (for debugging for example, check the logs, etc) by
      • docker exec -it <id> /bin/bash
      • Debug, etc
      • Ctrl-d or exit to leave the container
    • docker ps to see what is running
    • docker kill to terminate the container

Hands-on: make a Dockerfile for apache


FROM ubuntu
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update
RUN apt-get install -y apache2
RUN echo '<HTML><BODY>Hello World</BODY></HTML>' >/var/www/html/index.html
CMD ["apachectl","-DFOREGROUND"]
  • docker build . builds the image
    • ENV noninteractive avoids the prompt for location
  • docker run -p 80:80 <container id>
  • (If you have previously started a container using port 80 you will get an error that the

port is already allocated. In that case use “docker ps” and then “docker kill <id>” to shut it down.)

  • curl http://localhost

Hands-on: run service on minikube

Now let’s follow the same workflow on our k8s. We will publish the image on dockerhub, run it as a pod on the only node on minikube and then make it accessible from the outside by creating a service.

Copy the image to the docker hub and launch it in the local minikube.

  • Create a repository “simpleapache” (by clicking the button on
  • Tag the build: docker tag <id> <your user>/simpleapache
  • Upload docker push <your user>/simpleapache:latest
  • minikube start to bring up minikube

FROM ubuntu ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update RUN apt-get install -y apache2 RUN echo '<HTML><BODY>Hello World</BODY></HTML' >/var/www/html/index.html RUN sed -r -i 's?\$\{APACHE_LOG_DIR\}/access.log?/dev/stdout?'  /etc/apache2/sites-available/000-default.conf EXPOSE 80 CMD ["apachectl","-DFOREGROUND"]

  • kubectl run sa --image=<userid>/simpleapache --port=80
  • kubectl expose pod sa --type=LoadBalancer --port=80
    • The pod named “sa” is exposed.
  • minikube service sa --url
  • curl to the url given

To find out more information about the pods and the service, try these commands and see if the returned information makes sense.

  • kubectl get pods
    • kubectl get pods -o wide
  • kubectl get service
    • kubectl get service -o wide
  • kubectl describe pod sa
  • kubectl describe service sa

Hands-on: more replicas on minikube

To assure high availability we typically want to run more than one instance of a service. K8s makes that pretty easy. We have to use a new k8s object called a deployment and can then set the number of replicas we want, i.e. where before we just instructed K8s to run an image, we will now create a deployment object for the image and define its parameters, including the number of replicas.

  • kubectl create deployment <name> --image=<userid>/simpleapache
  • kubectl get pods
  • kubectl get deployments
  • kubectl describe deployment <name>
    • Look for replicas for example
  • kubectl scale --current-replicas=1 --replicas=2 deployment sa
    • kubectl get pods
    • kubectl describe deployment <name>
      • Look for replicas for example

And expose the web servers on the pods through a service

  • kubectl expose deployment sa --type=LoadBalancer --port=80
  • minikube service sa --url
  • Curl on the URL returned to verify functioning

How can we enassure that both pods get exercised? Let’s change the page served on on of the pods

  • kubectl get pods
  • kubectl exec -it <one of the pods> -- /bin/bash
    • cd /var/www/html
    • echo "<HTML><BODY>Hello 2nd World</BODY></HTML>" > ./index.html
    • exit
  • minikube service sa --url
  • Multiple curls on the URL executed to verify functioning. Sample Output:
$ curl
<HTML><BODY>Hello 2nd World</BODY></HTML>

$ curl
<HTML><BODY>Hello 2nd World</BODY></HTML>

$ curl
<HTML><BODY>Hello 2nd World</BODY></HTML>

$ curl
<HTML><BODY>Hello World</BODY></HTML

$ curl
<HTML><BODY>Hello 2nd World</BODY></HTML>

We could also look at the apache log files to see if both servers get hit. K8s has a way to look at the stdout of the pods by using the command kubectl logs, so if we configure apache to log to stdout we can use that to see the log files.

Here is a Dockerfile that redirects the access.log to stdout (the RUN for sed is 1 line including the /etc/apache/sites-available… So exercise a docker build ., local test with docker, docker logs to check, then tag, push to repo, and test on k8s:

  • kubectl get pods
  • kubectl logs <name of pod>.

Dockerfile for apache with stdout instead of access log:

FROM ubuntu
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update
RUN apt-get install -y apache2
RUN echo '<HTML><BODY>Hello World</BODY></HTML' >/var/www/html/index.html
RUN sed -r -i 's?\$\{APACHE_LOG_DIR\}/access.log?/dev/stdout?'  /etc/apache2/sites-available/000-default.conf
CMD ["apachectl","-DFOREGROUND"]

Once done, minikube can be shutdown with minikube stop.