Setting up a Kubernetes Cluster

In this article, we will cover the following recipes:

  • Setting up a Kubernetes cluster
  • Scaling up and down in a Kubernetes cluster
  • Setting up WordPress with a Kubernetes cluster

(For more resources related to this topic, see here.)

Introduction

Running Docker on a single host may be good for the development environment, but the real value comes when we span multiple hosts. However, this is not an easy task. You have to orchestrate these containers. So, in this article, we'll discuss Kubernetes, an orchestration tool.

Google started Kubernetes (http://kubernetes.io/) for Docker orchestration. Kubernetes provides mechanisms for application deployment, scheduling, updating, maintenance, and scaling.

Setting up a Kubernetes cluster

Kubernetes is an open source container orchestration tool across multiple nodes in the cluster. Currently, it only supports Docker. It was started by Google, and now developers from other companies are contributing to it. It provides mechanisms for application deployment, scheduling, updating, maintenance, and scaling. Kubernetes' auto-placement, auto-restart, auto-replication features make sure that the desired state of the application is maintained, which is defined by the user. Users define applications through YAML or JSON files, which we'll see later in the recipe. These YAML and JSON files also contain the API Version (the apiVersion field) to identify the schema. The following is the architectural diagram of Kubernetes:

https://raw.githubusercontent.com/GoogleCloudPlatform/kubernetes/master/docs/architecture.png

Let's look at some of the key components and concepts of Kubernetes.

  • Pods: A pod, which consists of one or more containers, is the deployment unit of Kubernetes. Each container in a pod shares different namespaces with other containers in the same pod. For example, each container in a pod shares the same network namespace, which means they can all communicate through localhost.
  • Node/Minion: A node, which was previously known as a minion, is a worker node in the Kubernetes cluster and is managed through master. Pods are deployed on a node, which has the necessary services to run them:
    • docker, to run containers
    • kubelet, to interact with master
    • proxy (kube-proxy), which connects the service to the corresponding pod
  • Master: Master hosts cluster-level control services such as the following:
    • API server: This has RESTful APIs to interact with master and nodes. This is the only component that talks to the etcd instance.
    • Scheduler: This schedules jobs in clusters, such as creating pods on nodes.
    • Replication controller: This ensures that the user-specified number of pod replicas is running at any given time. To manage replicas with replication controller, we have to define a configuration file with the replica count for a pod.

    Master also communicates with etcd, which is a distributed key-value pair. etcd is used to store the configuration information, which is used by both master and nodes. The watch functionality of etcd is used to notify the changes in the cluster. etcd can be hosted on master or on a different set of systems.

  • Services: In Kubernetes, each pod gets its own IP address, and pods are created and destroyed every now and then based on the replication controller configuration. So, we cannot rely on a pod's IP address to cater an app. To overcome this problem, Kubernetes defines an abstraction, which defines a logical set of pods and policies to access them. This abstraction is called a service. Labels are used to define the logical set, which a service manages.
  • Labels: Labels are key-value pairs that can be attached to objects like, using which we select a subset of objects. For example, a service can select all pods with the label mysql.
  • Volumes: A volume is a directory that is accessible to the containers in a pod. It is similar to Docker volumes but not the same. Different types of volumes are supported in Kubernetes, some of which are EmptyDir (ephemeral), HostDir, GCEPersistentDisk, and NFS. Active development is happening to support more types of volumes. More details can be found at https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/volumes.md.

Kubernetes can be installed on VMs, physical machines, and the cloud. For the complete matrix, take a look at https://github.com/GoogleCloudPlatform/kubernetes/tree/master/docs/getting-started-guides. In this recipe, we'll see how to install it on VMs, using Vagrant with VirtualBox provider. This recipe and the following recipes on Kubernetes, were tried on v0.17.0 of Kubernetes.

Getting ready

  1. Install latest Vagrant >= 1.6.2 from http://www.vagrantup.com/downloads.html.
  2. Install the latest VirtualBox from https://www.virtualbox.org/wiki/Downloads.

How to do it…

  • Run the following command to set up Kubernetes on Vagrant VMs:
    $ export KUBERNETES_PROVIDER=vagrant
    $ export VAGRANT_DEFAULT_PROVIDER=virtualbox
    $ curl -sS https://get.k8s.io | bash

How it works…

The bash script downloaded from the curl command, first downloads the latest Kubernetes release and then runs the ./kubernetes/cluster/kube-up.sh bash script to set up the Kubernetes environment. As we have specified Vagrant as KUBERNETES_PROVIDER, the script first downloads the Vagrant images and then, using Salt (http://saltstack.com/), configures one master and one node (minion) VM. Initial setup takes a few minutes to run.

Vagrant creates a credential file in ~/.kubernetes_vagrant_auth for authentication.

There's more…

Similar to ./cluster/kube-up.sh, there are other helper scripts to perform different operations from the host machine itself. Make sure you are in the kubernetes directory, which was created with the preceding installation, while running the following commands:

  • Get the list of nodes:
    $ ./cluster/kubectl.sh get nodes
  • Get the list of pods:
    $ ./cluster/kubectl.sh get pods
  • Get the list of services:
    $ ./cluster/kubectl.sh get services
  • Get the list of replication controllers:
    $ ./cluster/kubectl.sh get replicationControllers
  • Destroy the vagrant cluster:
    $ ./cluster/kube-down.sh
  • Then bring back the vagrant cluster:
    $ ./cluster/kube-up.sh

You will see some pods, services, and replicationControllers listed, as Kubernetes creates them for internal use.

See also

Scaling up and down in a Kubernetes cluster

In the previous section, we mentioned that the replication controller ensures that the user-specified number of pod replicas is running at any given time. To manage replicas with the replication controller, we have to define a configuration file with the replica count for a pod. This configuration can be changed at runtime.

Getting ready

Make sure the Kubernetes setup is running as described in the preceding recipe and that you are in the kubernetes directory, which was created with the preceding installation.

How to do it…

  1. Start the nginx container with a replica count of 3:
    $ ./cluster/kubectl.sh run-container my-nginx --image=nginx --replicas=3 --port=80

    This will start three replicas of the nginx container. List the pods to get the status:

    $ ./cluster/kubectl.sh get pods
  2. Get the replication controller configuration:
    $ ./cluster/kubectl.sh get replicationControllers

    As you can see, we have a my-nginx controller, which has a replica count of 3. There is a replication controller for kube-dns, which we will explore in next recipe.

  3. Request the replication controller service to scale down to replica of 1 and update the replication controller:
    $ ./cluster/kubectl.sh resize rc my-nginx –replicas=1
    $ ./cluster/kubectl.sh get rc

  4. Get the list of pods to verify; you should see only one pod for nginx:
    $ ./cluster/kubectl.sh get pods

How it works…

We request the replication controller service running on master to update the replicas for a pod, which updates the configuration and requests nodes/minions to act accordingly to honor the resizing.

There's more…

Get the services:

$ ./cluster/kubectl.sh get services

As you can see, we don't have any service defined for our nginx containers started earlier. This means that though we have a container running, we cannot access them from outside because the corresponding service is not defined.

See also

Setting up WordPress with a Kubernetes cluster

In this recipe, we will use the WordPress example given in the Kubernetes GitHub (https://github.com/GoogleCloudPlatform/kubernetes/tree/master/examples/mysql-wordpress-pd). The given example requires some changes, as we'll be running it on the Vagrant environment instead of the default Google Compute engine. Also, instead of using the helper functions (for example, <kubernetes>/cluster/kubectl.sh), we'll log in to master and use the kubectl binary.

Getting ready

  • Make sure the Kubernetes cluster has been set up as described in the previous recipe.
  • In the kubernetes directory that was downloaded during the setup, you will find an examples directory that contains many examples. Let's go to the mysql-wordpress-pd directory:
    $ cd kubernetes/examples/mysql-wordpress-pd
    $  ls *.yaml
    mysql-service.yaml mysql.yaml wordpress-service.yaml  wordpress.yaml
  • These .yaml files describe pods and services for mysql and wordpress respectively.
  • In the pods files (mysql.yaml and wordpress.yaml), you will find the section on volumes and the corresponding volumeMount file. The original example assumes that you have access to Google Compute Engine and that you have the corresponding storage setup. For simplicity, we will not set up that and instead use ephemeral storage with the EmptyDir volume option. For reference, our mysql.yaml will look like the following:
  • Make the similar change to wordpress.yaml.

How to do it…

  1. With SSH, log in to the master node and look at the running pods:
    $ vagrant ssh master
    $ kubectl get pods

    The kube-dns-7eqp5 pod consists of three containers: etcd, kube2sky, and skydns, which are used to configure an internal DNS server for service name to IP resolution. We'll see it in action later in this recipe.

    The Vagrantfile used in this example is created so that the kubernetes directory that we created earlier is shared under /vagrant on VM, which means that the changes we made to the host system will be visible here as well.

  2. From the master node, create the mysql pod and check the running pods:
    $ kubectl create -f /vagrant/examples/mysql-wordpress-pd/mysql.yaml
    $ kubectl get pods

    As we can see, a new pod with the mysql name has been created and it is running on host 10.245.1.3, which is our node (minion).

  3. Now let's create the service for mysql and look at all the services:
    $ kubectl create -f /vagrant/examples/mysql-wordpress-pd/mysql-service.yaml
    $ kubectl get services

    As we can see, a service named mysql has been created. Each service has a Virtual IP. Other than the kubernetes services, we see a service named kube-dns, which is used as the service name for the kube-dns pod we saw earlier.

  4. Similar to mysql, let's create a pod for wordpress:
    $ kubectl create -f /vagrant/examples/mysql-wordpress-pd/wordpress.yaml

    With this command, there are a few things happening in the background:

    • The wordpress image gets downloaded from the official Docker registry and the container runs.
    • By default, whenever a pod starts, information about all the existing services is exported as environment variables. For example, if we log in to the wordpress pod and look for MYSQL-specific environment variables, we will see something like the following:
    • When the WordPress container starts, it runs the /entrypoint.sh script, which looks for the environment variables mentioned earlier to start the service. https://github.com/docker-library/wordpress/blob/master/docker-entrypoint.sh.
    • With the kube-dns service, PHP scripts of wordpress are able to the reserve lookup to proceed forward.
  5. After starting the pod, the last step here is to set up the wordpress service. In the default example, you will see an entry like the following in the service file (/vagrant/examples/mysql-wordpress-pd/mysql-service.yaml):
    createExternalLoadBalancer: true

    This has been written to keep in mind that this example will run on the Google Compute Engine. So it is not valid here. In place of that, we will need to make an entry like the following:

    publicIPs:
       - 10.245.1.3

    We have replaced the load-balancer entry with the public IP of the node, which in our case is the IP address of the node (minion). So, the wordpress file would look like the following:

  6. To start the wordpress service, run the following command from the master node:
    $ kubectl create -f /vagrant/examples/mysql-wordpress-pd/wordpress-service.yaml

    We can see here that our service is also available through the node (minion) IP.

  7. To verify if everything works fine, we can install the links package on master by which we can browse a URL through the command line and connect to the public IP we mentioned:
    $ sudo yum install links -y
    $ links 10.245.1.3

    With this, you should see the wordpress installation page.

How it works…

In this recipe, we first created a mysql pod and service. Later, we connected it to a wordpress pod, and to access it, we created a wordpress service. Each YAML file has a kind key that defines the type of object it is. For example, in pod files, the kind is set to pod and in service files, it is set to service.

There's more…

  • In this example setup, we have only one Node (minion). If you log in to it, you will see all the running containers:
    $ vagrant ssh minion-1
    $ sudo docker ps
  • In this example, we have not configured replication controllers. We can extend this example by creating them.

See also

Summary

Docker and its ecosystem are evolving at a very high pace, so it is very important to understand the basics and build group up to adopt to new concepts and tools.

For more information you can refer to:

Resources for Article:


Further resources on this subject:

You've been reading an excerpt of:

Docker Cookbook

Explore Title