= Kubernetes - Setup Local Development Environment
:toc:
:icons:
:linkcss:
:imagesdir: ../../resources/images

For local development purposes, you can create a one-node cluster using https://github.com/kubernetes/minikube[Minikube].
Hosted solutions or cloud-based solutions provide the scalability and higher availability for staging or production purposes.
A complete list of solutions to create a Kubernetes cluster is explained at http://kubernetes.io/docs/getting-started-guides/.

This section will explain how to create and shutdown a development Kubernetes cluster using Minikube.

== Download and Install

Minikube runs a single-node Kubernetes cluster inside a VM on your laptop.
This allows you to easily try out Kubernetes on your local machine.
Minikube packages and configures a Linux VM, the container runtime, and all Kubernetes components - optimized for local development.

Complete installation instructions are available at https://github.com/kubernetes/minikube. Here are quick instructions:

=== Setup on macOS

Provision and install a local Kubernetes cluster on a Mac OS via https://brew.sh/[homebrew].

. Install VirtualBox

    $ brew cask install virtualbox

. Install (or update) minikube
+
*If you've never installed minikube before:*
+
    brew cask install minikube
+
Verify the version:
+
    $ minikube version
    minikube version: v0.24.1
+
*If you already have minikube:*
+
    brew cask reinstall minikube
+
[NOTE]
====
If you receive this error:

    ==> Installing Cask minikube
    Error: It seems there is already a Binary at '/usr/local/bin/minikube'; not linking.

Run this command:

    $ sudo cp ~/Library/Caches/Homebrew/Cask/minikube--0.24.1 /usr/local/bin/minikube
====
+
Verify the version:

    $ minikube version
    minikube version: v0.24.1
+
Finally delete the previous minikube ISO:

    minikube delete

=== Setup on Windows

. Download and install https://www.virtualbox.org/wiki/Downloads[VirtualBox].
. Download the https://storage.googleapis.com/minikube/releases/latest/minikube-windows-amd64.exe[minikube-windows-amd64.exe] file, and rename it to `minikube.exe`. Verify the version:
+
    $ minikube version
    minikube version: v0.24.1
+
. Download kubectl CLI with cmd.exe
+
    curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.goo \
    gleapis.com/kubernetes-release/release/stable.txt)/bin/windows/amd64/kubectl.exe

Latest instructions are also available at https://kubernetes.io/docs/tasks/tools/install-kubectl/#before-you-begin.

=== Setup on Linux

. Download and install https://www.virtualbox.org/wiki/Downloads[VirtualBox].
. Install minikube:

    curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/

. Verify the version:

    $ minikube version
    minikube version: v0.24.1

=== Setup on EC2 (if you do not virtualbox on your laptop)

. Launch an EC2 (at least 4GB Memory) with an "Ubuntu Server 16.04 LTS (HVM)" AMI, make sure you have a public IP and can SSH into this instance.
. SSH into the EC2 (the port forwarding is for the minikube dashboard):

    $ ssh -L30000:localhost:30000 ubuntu@<IP Address of EC2>

. Install docker

    $ sudo -i
    $ apt-get update -y &&  apt-get install -y docker.io

. Install minikube:

    $ curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/

. Verify the version:

    $ minikube version
    minikube version: v0.24.1

. Install or Upgrade Kubectl CLI:

    $ curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/v1.8.0/bin/linux/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/

. Add kubectl autocompletion to your current shell

    $ source <(kubectl completion bash)

== Start Kubernetes cluster

We are using the VirtualBox driver which is the default selection for minikube. If you would prefer you can use an alternate supported component (xhyve driver or VMware Fusion) using the `--vm-driver=xxx` flag.

Start a single-node Kubernetes cluster on your local machine:

    $ minikube start

if you have installed minikube on a EC2, start it with the `--vm-driver=none` flag

    $ minikube start --vm-driver=none

The first start of minikube will download the ISO file and then start the cluster. It shows the following output:

  $ minikube start
  Starting local Kubernetes v1.8.0 cluster...
  Starting VM...
  Downloading Minikube ISO
   140.01 MB / 140.01 MB [============================================] 100.00% 0s
  Getting VM IP address...
  Moving files into cluster...
  Downloading localkube binary
   148.56 MB / 148.56 MB [============================================] 100.00% 0s
  Setting up certs...
  Connecting to cluster...
  Setting up kubeconfig...
  Starting cluster components...
  Kubectl is now configured to use the cluster.

Now you can start to develop and test your application.

=== Check status

Check the status of minikube to get the status of your local Kubernetes cluster:

  $ minikube status
  minikube: Running
  cluster: Running
  kubectl: Correctly Configured: pointing to minikube-vm at 192.168.99.100

Kubectl CLI is configured to talk to this cluster.

== Get information about the minikube cluster

Now that we have a local development cluster up and running we can start issuing some basic commands to see its status.

=== View service webpage

This minikube command will display the service for you in a web page:

    $ minikube service web

This opened a browser with an IP address and the port that the service was exposed on. It looks like as shown:

image::nginx-welcome-page.png[]

This is a convenient feature of minikube. But what if you wanted to find this information yourself?

You can view the IP address of a node in your cluster with these steps, first find all of the nodes in your cluster:

    $ kubectl get nodes

Once you have the nodes (in minikubes case there will be only one), we can describe all of the attribute of that node with:

    $ kubectl describe node <node-name>

Where `<node-name>` is the output from the previous command. This shows a lot of information about the node:

```
$ kubectl describe node minikube
Name:               minikube
Roles:              <none>
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/hostname=minikube
Annotations:        alpha.kubernetes.io/provided-node-ip=192.168.99.100
                    node.alpha.kubernetes.io/ttl=0
                    volumes.kubernetes.io/controller-managed-attach-detach=true
Taints:             <none>
CreationTimestamp:  Sun, 15 Oct 2017 17:22:22 -0400
Conditions:
  Type             Status  LastHeartbeatTime                 LastTransitionTime                Reason                       Message
  ----             ------  -----------------                 ------------------                ------                       -------
  OutOfDisk        False   Sun, 22 Oct 2017 21:26:44 -0400   Mon, 16 Oct 2017 19:28:57 -0400   KubeletHasSufficientDisk     kubelet has sufficient disk space available
  MemoryPressure   False   Sun, 22 Oct 2017 21:26:44 -0400   Mon, 16 Oct 2017 19:28:57 -0400   KubeletHasSufficientMemory   kubelet has sufficient memory available
  DiskPressure     False   Sun, 22 Oct 2017 21:26:44 -0400   Mon, 16 Oct 2017 19:28:57 -0400   KubeletHasNoDiskPressure     kubelet has no disk pressure
  Ready            True    Sun, 22 Oct 2017 21:26:44 -0400   Mon, 16 Oct 2017 19:28:57 -0400   KubeletReady                 kubelet is posting ready status
Addresses:
  InternalIP:  192.168.99.100
  Hostname:    minikube
Capacity:
 cpu:     2
 memory:  2048484Ki
 pods:    110
Allocatable:
 cpu:     2
 memory:  1946084Ki
 pods:    110
System Info:
 Machine ID:                 6756b9ba9cd3480fa019cf553d4fea04
 System UUID:                AC4BE6D4-7896-46EF-B921-44BD0BC92D0D
 Boot ID:                    66a504af-ce10-4d45-ad50-334f21a2063e
 Kernel Version:             4.7.2
 OS Image:                   Buildroot 2016.08
 Operating System:           linux
 Architecture:               amd64
 Container Runtime Version:  docker://1.11.1
 Kubelet Version:            v1.7.5
 Kube-Proxy Version:         v1.7.5
ExternalID:                  minikube
Non-terminated Pods:         (4 in total)
  Namespace                  Name                           CPU Requests  CPU Limits  Memory Requests  Memory Limits
  ---------                  ----                           ------------  ----------  ---------------  -------------
  default                    nginx-4217019353-h7mns         0 (0%)        0 (0%)      0 (0%)           0 (0%)
  kube-system                kube-addon-manager-minikube    5m (0%)       0 (0%)      50Mi (2%)        0 (0%)
  kube-system                kube-dns-1326421443-tbzqc      260m (13%)    0 (0%)      110Mi (5%)       170Mi (8%)
  kube-system                kubernetes-dashboard-zqd7w     0 (0%)        0 (0%)      0 (0%)           0 (0%)
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  CPU Requests  CPU Limits  Memory Requests  Memory Limits
  ------------  ----------  ---------------  -------------
  265m (13%)    0 (0%)      160Mi (8%)       170Mi (8%)
Events:
  Type     Reason                   Age              From                  Message
  ----     ------                   ----             ----                  -------
  Normal   Starting                 6d               kubelet, minikube     Starting kubelet.
  Normal   NodeAllocatableEnforced  6d               kubelet, minikube     Updated Node Allocatable limit across pods
  Warning  Rebooted                 6d               kubelet, minikube     Node minikube has been rebooted, boot id: d80f975d-2373-4fd0-9d11-3262049e1f39
  Normal   NodeNotReady             6d               kubelet, minikube     Node minikube status is now: NodeNotReady
  Normal   Starting                 6d               kube-proxy, minikube  Starting kube-proxy.
  Normal   NodeHasSufficientDisk    6d (x2 over 6d)  kubelet, minikube     Node minikube status is now: NodeHasSufficientDisk
  Normal   NodeHasSufficientMemory  6d (x2 over 6d)  kubelet, minikube     Node minikube status is now: NodeHasSufficientMemory
  Normal   NodeHasNoDiskPressure    6d (x2 over 6d)  kubelet, minikube     Node minikube status is now: NodeHasNoDiskPressure
  Normal   NodeReady                6d (x2 over 6d)  kubelet, minikube     Node minikube status is now: NodeReady
  Normal   Starting                 8m               kubelet, minikube     Starting kubelet.
  Normal   NodeAllocatableEnforced  8m               kubelet, minikube     Updated Node Allocatable limit across pods
  Normal   NodeHasSufficientDisk    8m               kubelet, minikube     Node minikube status is now: NodeHasSufficientDisk
  Normal   NodeHasSufficientMemory  8m               kubelet, minikube     Node minikube status is now: NodeHasSufficientMemory
  Normal   NodeHasNoDiskPressure    8m               kubelet, minikube     Node minikube status is now: NodeHasNoDiskPressure
  Warning  Rebooted                 8m               kubelet, minikube     Node minikube has been rebooted, boot id: 66a504af-ce10-4d45-ad50-334f21a2063e
  Normal   Starting                 8m               kube-proxy, minikube  Starting kube-proxy.
```

IP address information can be obtained by looking at the `InternalIP` field:

    $ echo $(kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}')

This gives us the IP address where the service is hosted. Now, we need to get the port that the service is exposed on. This can be found using the following command:

    $ echo $(kubectl get service web -o jsonpath='{.spec.ports[*].nodePort}')

We can combine these two commands with curl to access the service from the cli:
```
$ curl $(kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}'):$(kubectl get service web -o jsonpath='{.spec.ports[*].nodePort}')
```

The host and the port are the exact same values where minikube opened the service page in the browser.

=== Kubernetes dashboard

Kubernetes dashboard is a general purpose, web-based UI for Kubernetes clusters. It provides an overview of applications running on the cluster, as well as the ability to create or modify individual Kubernetes resources and workloads, such as replica sets, jobs, services, and pods. The dashboard can be used to manage the cluster as well.

Kubernetes dashboard with minikube can be easily viewed using the following command ( Do not run this if you have minikube on EC2, instead just point your browser to http://127.0.0.1:30000):

    $ minikube dashboard

It looks like this:

image::minikube-dashboard.png[]

Look around the dashboard and become familiar with some of the Kubernetes terminology. This will be explained in the subsequent chapters.

=== Shutdown cluster

The cluster can be shutdown using the following command:

    $ minikube stop
    Stopping local Kubernetes cluster...
    Machine stopped.


You are now ready to continue on with the workshop!

:frame: none
:grid: none
:valign: top

[align="center", cols="1", grid="none", frame="none"]
|=====
|image:button-continue-developer.png[link=../../03-path-application-development/302-app-discovery]
|link:../../developer-path.adoc[Go to Developer Index]
|=====
