Installing and Running a Local Kubernetes Environment on macOS

how to install and run a local kubernetes environment on macos

Background

For a local installation of Kubernetes on macOS the getting started guide recommends minikube is used. This page details the various installation steps required to install this.

Prerequisites

Ensure that the software below is installed on the host macOS machine before continuing.
* Docker for Mac
* Homebrew

Installing minikube

As per the minikube documentation

“Minikube is a tool that makes it easy to run Kubernetes locally. Minikube runs a single-node Kubernetes cluster inside a VM on your laptop for users looking to try out Kubernetes or develop with it day-to-day.”

To install minikube, follow the instructions at https://github.com/kubernetes/minikube/releases. At the time of writing, version v0.15.0 is the latest release; the appropriate installation commands for this version are as follows:

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

Installing the xhyve Driver

By default, minikube uses VirtualBox to host the Kubernetes environment. However, as Docker for Mac uses xhyve, it makes more sense to use the same hypervisor to host our Kubernetes environment.

For this we need to install the appropriate xhyve driver as detailed at https://github.com/kubernetes/minikube/blob/master/DRIVERS.md#xhyve-driver

At the time of writing, the appropriate installation commands for this are as follows:

$ brew install docker-machine-driver-xhyve
$ sudo chown root:wheel $(brew --prefix)/opt/docker-machine-driver-xhyve/bin/docker-machine-driver-xhyve
$ sudo chmod u+s $(brew --prefix)/opt/docker-machine-driver-xhyve/bin/docker-machine-driver-xhyve

Installing kubectl

In order to control Kubernetes from the command-line, the kubectl tool is used. Refer to https://kubernetes.io/docs/user-guide/kubectl for more information.

To install kubectl, follow the instructions at https://kubernetes.io/docs/user-guide/prereqs. At the time of writing the latest stable version is v1.5.2; the appropriate installation commands for this version are as follows:

$ curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl
$ chmod +x ./kubectl
$ sudo mv ./kubectl /usr/local/bin/kubectl

Starting, Verifying, Inspecting and Stopping minikube

Starting minikube is trivial, as shown below. The first time this command is executed will take longer than for subsequent calls as it will pull the ISO, storing in ~/.minikube/cache/iso/.

$ minikube start --vm-driver=xhyve
Starting local Kubernetes cluster...
Downloading Minikube ISO
 68.95 MB / 68.95 MB [==============================================] 100.00% 0s
Kubectl is now configured to use the cluster.

Verify the status of minikube:

$ minikube status
minikubeVM: Running
localkube: Running

Inspect the environment by bringing up the dashboard, which will open up in the browser.

$ minikube dashboard
Opening kubernetes dashboard in default browser...

Stop the minikube environment:

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

Getting Started with golang on macOS

how to install golang using homebrew and how to set the necessary environment variables

Installing golang using Homebrew

First install golang using Homebrew as follows:

$ brew install golang

This will install to the following location:

$ which go
/usr/local/bin/go

Setting GOROOT

The golang binary distributions expect to be installed to the standard location of /usr/local/go. This will not be the case, as Homebrew installs into /usr/local/bin/go, so we need to manually set the GOROOT environment variable to point the correct location as follows:

export GOROOT=/usr/local/opt/go/libexec

See https://golang.org/doc/install#tarball_non_standard for more information on GOROOT.

Setting GOPATH

First set a DEVELOPMENT_HOME environment variable. This will point to the top-level directory under which all code artefacts will exist, regardless of language.

export DEVELOPMENT_HOME=$HOME/Development

Next, set the GOPATH environment variable. This will point to the root directory where all golang-related artefacts will exist. Make this a direct subdirectory of the DEVELOPMENT_HOME directory.

export GOPATH=$DEVELOPMENT_HOME/golang

See https://golang.org/cmd/go/#hdr-GOPATH_environment_variable for information on GOPATH.

Appending GOPATH to PATH

Finally, add GOPATH to PATH as follows:

export PATH=$PATH:$GOPATH/bin

Test the Installation

$ go get github.com/golang/example/hello

$ ls $GOPATH/src/github.com/golang/example/hello
hello.go

$ ls $GOPATH/bin/hello
-rwxr-xr-x  1 paul  staff   1603584  9 Dec 18:03 hello

$ $GOPATH/bin/hello
Hello, Go examples!

See https://golang.org/doc/code.html#remote for more information.

Creating a Custom/Alternative Maven Lifecycle

how to create a custom/alternative maven lifecycle

Creating a custom lifecycle in Maven is pretty straightforward, although there doesn’t seem to be many examples available online. This post details how to create a custom lifecycle – i.e. not one of the default three Maven lifecycles – and optionally set default goals for the phases.

The complete source code for the examples below can pulled from the https://github.com/nextmetaphor/maven repository.

Create a Plugin

To create your own custom lifecycle you need to create a Maven plugin which only requires two files: pom.xml and components.xml

Setting up the Directory Structure

The diagram below shows where these files should be located. Note that this directory structure also contains the CustomLifecyclePluginPhase1Mojo.java mojo; this is not actually required for the custom lifecycle, and is simply used to validate when a particular phase is called later on.

Plugin Directory Structure

Configuring the pom.xml File

The pom.xml file is very straightforward, we are simply creating a maven-plugin.

    <project xmlns="http://maven.apache.org/POM/4.0.0" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
        http://maven.apache.org/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>

      <groupId>com.nextmetaphor.plugin</groupId>
      <artifactId>CustomLifecyclePlugin</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>maven-plugin</packaging>
      <name>Custom Lifecycle Plugin</name>

      <dependencies>
        <dependency>
          <groupId>org.apache.maven</groupId>
          <artifactId>maven-plugin-api</artifactId>
          <version>2.0</version>
        </dependency>
      </dependencies>
    </project>

Configuring the components.xml File

Configuring the components.xml file is also straightforward, the interesting fields are explained in more detail below:

    <component-set>
      <components>
        <component>
          <role>org.apache.maven.lifecycle.Lifecycle</role>
          <role-hint>customLifecyclePlugin_PackagingType</role-hint>
          <implementation>org.apache.maven.lifecycle.Lifecycle</implementation>
          <configuration>
            <id>customLifecyclePlugin_LifecycleID</id>
            <phases>
              <phase>phase1</phase>
              <phase>phase2</phase>
              <phase>phase3</phase>
            </phases>
            <default-phases>
              <phase1>com.nextmetaphor.plugin:CustomLifecyclePlugin:phase1Goal</phase1>
            </default-phases>
          </configuration>
        </component>
      </components>
    </component-set>

For this particular example, the actual value of role-hint doesn’t appear to be used, although it looks to be a mandatory field and therefore cannot be removed. More useful is the id field, this is the name of the custom lifecycle being created, to complement the existing Maven lifecycles of clean, default and site.

The various phase elements detail the phases for the lifecycle in the order they will run. Finally, any phase that should default to a particular plugin goal should be defined in the default-phases section. In the example above, the first phase of the custom lifecycle – phase1 – will by default call the phase1Goal on the CustomLifecyclePlugin in the com.nextmetaphor.plugin group.

And that’s all there is to it! Simply mvn install this plugin and we can use the new custom lifecycle from another project.

Create A Project To Use The Custom Lifecycle

This demonstration project consists solely of a simple pom.xml file.

Configuring the pom.xml File

Here the custom lifecycle is introduced by the plugin reference. Note that the extensions property must be set to true for the custom lifecycle to become available to us.

    <project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
        http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>

      <groupId>com.nextmetaphor.project</groupId>
      <artifactId>CustomLifecycleProject</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>jar</packaging>
      <name>Custom Lifecycle Project</name>

      <build>
        <plugins>
          <plugin>
              <groupId>com.nextmetaphor.plugin</groupId>
              <artifactId>CustomLifecyclePlugin</artifactId>
              <version>1.0-SNAPSHOT</version>
              <extensions>true</extensions>
          </plugin>
        </plugins>
      </build> 
    </project>

Confirming the Custom Lifecycle is Available

Invoke the clean phase on the project with verbose debug on using mvn clean -X. This should complete successfully. Scroll back through the logs until the available lifecycles are listed:

    [INFO] ------------------------------------------------------------------------
    [INFO] Building Custom Lifecycle Project 1.0-SNAPSHOT
    [INFO] ------------------------------------------------------------------------
    [DEBUG] Lifecycle default -> [validate, initialize, generate-sources,
            process-sources, generate-resources, process-resources, compile,
            process-classes, generate-test-sources, process-test-sources, 
            generate-test-resources, process-test-resources, test-compile, 
            process-test-classes, test, prepare-package, package, 
            pre-integration-test, integration-test, post-integration-test, 
            verify, install, deploy]
    [DEBUG] Lifecycle clean -> [pre-clean, clean, post-clean]
    [DEBUG] Lifecycle site -> [pre-site, site, post-site, site-deploy]
    [DEBUG] Lifecycle customLifecyclePlugin_LifecycleID -> [phase1, 
            phase2, phase3]

Invoking the Custom Lifecycle

As a final test we’ll invoke the phase3 phase which should invoke the preceding phases: phase1 and phase2. Only phase1 has been set up with a default goal, in this case to call a mojo which will simply output some text.

    [CustomLifecycleProject]$ mvn phase3
    [INFO] Scanning for projects...
    [INFO]                                                                         
    [INFO] ------------------------------------------------------------------------
    [INFO] Building Custom Lifecycle Project 1.0-SNAPSHOT
    [INFO] ------------------------------------------------------------------------
    [INFO] 
    [INFO] --- 
           CustomLifecyclePlugin:1.0-SNAPSHOT:phase1Goal(default-phase1Goal)
           @ CustomLifecycleProject ---
    [INFO] Doing Phase 1 stuff. Oh yeah baby.
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 0.755s
    [INFO] Finished at: Tue Jan 28 01:00:58 GMT 2014
    [INFO] Final Memory: 5M/141M
    [INFO] ------------------------------------------------------------------------