Analysis / Top Stories / Tutorials

Get Started with Spinnaker on Kubernetes

5 Jan 2018 6:01am, by

In the previous installment of the series, we introduced Spinnaker as the multicloud deployment tool. We will explore how to setup Spinnaker on the Kubernetes open source container orchestration engine and deploy your first application through it.

In this tutorial, I will walk you through how to setup and configure Spinnaker on Minikube. Once it is up and running, we will deploy and scale a containerized application running in Kubernetes.

Spinnaker is usually installed in a VM running Ubuntu 14.04 LTS. Thanks to the Helm community, it is now available as a Chart to install with just one command.

Install and Configure Minikube

Spinnaker is architected as a cloud-native, microservices application. It comes with a set of containers that are resource intensive. Typical Minikube installation doesn’t provide enough power for Spinnaker to run locally. We will customize Minikube configuration to make it powerful enough to host Spinnaker.

Alternatively, you can install Spinnaker on a Kubernetes cluster where the Nodes have at least 4GB RAM. Google Kubernetes Engine or Azure Container Service for Managed Kubernetes are ideal candidates for this configuration. Since Minikube is free and simple, we are using that to configure Spinnaker. This configuration is not recommended for production use.

Run the following commands to install Minikube on macOS.

$ curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.24.1/minikube-darwin-amd64

$ chmod +x ./minikube 

$ sudo mv ./minikube /usr/local/bin/

We also need the latest version of Kubectl to manage the Kubernetes cluster. The following steps will install it.

$ 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

With the prerequisites in place, let’s start Minikube.

Firstly, we need to make sure that Minikube VM is configured with at least 4GB RAM and 4 CPU cores. We do this with the below commands.

$ minikube config set memory 4096

These changes will take effect upon a minikube delete and then a minikube start

$ minikube config set cpus 4

These changes will take effect upon a minikube delete and then a minikube start

If you don’t want to persistent the configuration, you can also launch Minikube with the following parameters:

$ minikube start --memory 4096 --cpus 4

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.25 MB / 148.25 MB [============================================] 100.00% 0s
 0 B / 65 B [----------------------------------------------------------]   0.00%
 65 B / 65 B [======================================================] 100.00% 0s
Setting up certs...
Connecting to cluster...
Setting up kubeconfig...
Starting cluster components...
Kubectl is now configured to use the cluster.
Loading cached images from config file.

Wait for the single node Kubernetes cluster to start, and the verify the installation. If this is the first time you are launching Minikube, it will download the ISO file before starting the cluster.

$ kubectl version

Client Version: version.Info{Major:"1", Minor:"9", GitVersion:"v1.9.0", GitCommit:"925c127ec6b946659ad0fd596fa959be43f0cc05", GitTreeState:"clean", BuildDate:"2017-12-15T21:07:38Z", GoVersion:"go1.9.2", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"8", GitVersion:"v1.8.0", GitCommit:"0b9efaeb34a2fc51ff8e4d34ad9bc6375459c4a4", GitTreeState:"clean", BuildDate:"2017-11-29T22:43:34Z", GoVersion:"go1.9.1", Compiler:"gc", Platform:"linux/amd64"}

$ kubectl get cs

NAME                 STATUS    MESSAGE              ERROR

scheduler            Healthy   ok

controller-manager   Healthy   ok

etcd-0               Healthy   {"health": "true"}

Install Helm

Helm makes installing applications in Kubernetes extremely easy. Each application is packaged as a Chart, a deployable unit of Helm. Before installing Spinnaker Chart, we need to set up Helm on Kubernetes.

Download the latest release of Helm binary and move it to the bin folder

$ wget https://storage.googleapis.com/kubernetes-helm/helm-v2.7.2-darwin-amd64.tar.gz

--2018-01-03 10:55:06--  https://storage.googleapis.com/kubernetes-helm/helm-v2.7.2-darwin-amd64.tar.gz

Resolving storage.googleapis.com (storage.googleapis.com)... 172.217.31.208

Connecting to storage.googleapis.com (storage.googleapis.com)|172.217.31.208|:443... connected.

HTTP request sent, awaiting response... 200 OK

Length: 12091997 (12M) [application/x-tar]

Saving to: 'helm-v2.7.2-darwin-amd64.tar.gz'
helm-v2.7.2-darwin- 100%[===================>]  11.53M  3.10MB/s    in 3.8s

2018-01-03 10:55:11 (3.01 MB/s) - 'helm-v2.7.2-darwin-amd64.tar.gz' saved [12091997/12091997]

$ tar -zxvf helm-v2.7.2-darwin-amd64.tar.gz

x darwin-amd64/

x darwin-amd64/README.md

x darwin-amd64/LICENSE

x darwin-amd64/helm
$ chmod +x ./darwin-amd64/helm

$ mv ./darwin-amd64/helm /usr/local/bin/

We will now install Helm and verify it.

$ helm init
 Creating /Users/janakiramm/.helm
 Creating /Users/janakiramm/.helm/repository
 Creating /Users/janakiramm/.helm/repository/cache
 Creating /Users/janakiramm/.helm/repository/local
 Creating /Users/janakiramm/.helm/plugins
 Creating /Users/janakiramm/.helm/starters
 Creating /Users/janakiramm/.helm/cache/archive
 Creating /Users/janakiramm/.helm/repository/repositories.yaml
 Adding stable repo with URL: https://kubernetes-charts.storage.googleapis.com
 Adding local repo with URL: http://127.0.0.1:8879/charts
 $HELM_HOME has been configured at /Users/janakiramm/.helm.

Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.
Happy Helming!

$ helm version

Client: &version.Version{SemVer:"v2.7.2", GitCommit:"8478fb4fc723885b155c924d1c8c410b7a9444e6", GitTreeState:"clean"}

Server: &version.Version{SemVer:"v2.7.2", GitCommit:"8478fb4fc723885b155c924d1c8c410b7a9444e6", GitTreeState:"clean"}

The above output confirms that Helm and Tiller, the server-side component of Helm are properly installed. Tiller runs as a Kubernetes Pod and Service within the kube-system namespace.

Installing Spinnaker

With Minikube and Helm up and running, it’s time for us to install Spinnaker. Since it is available as a Helm Chart, we will get this done through a couple of steps.

Before we deploy Spinnaker, we need a configuration file in YAML format, which will provide the initial set of configuration values. Grab this file from the Github Spinnaker Helm Chart repository.

$ curl -Lo values.yaml https://raw.githubusercontent.com/kubernetes/charts/master/stable/spinnaker/values.yaml

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current

                                 Dload  Upload   Total   Spent    Left  Speed

100  2950  100  2950    0     0   2950      0  0:00:01 --:--:--  0:00:01 10535

It’s time to install Spinnaker. Run the below command to deploy it in Kubernetes cluster.

$ helm install -n kubelive stable/spinnaker -f values.yaml --timeout 300  --version 0.3.5 --namespace spinnaker

The -f parameter points the installation to the default configuration saved in values.yaml. The –timeout parameter will force Helm to wait for at least five minutes before aborting with a timeout error. This tutorial is tested with version 0.3.5 which is mentioned by –version switch. Finally, we are installing the Helm Chart in a dedicated namespace called spinnaker configured through the –namespace switch.

After a few minutes, we should see the following output, which confirms the installation of Spinnaker.

NAME:   kubelive

LAST DEPLOYED: Wed Jan  3 11:26:12 2018

NAMESPACE: spinnaker

STATUS: DEPLOYED

RESOURCES:

…..
NOTES:

You will need to create 2 port forwarding tunnels in order to access the Spinnaker UI:
export DECK_POD=$(kubectl get pods --namespace spinnaker -l "component=deck,app=kubelive-spinnaker" -o jsonpath="{.items[0].metadata.name}")
kubectl port-forward --namespace spinnaker $DECK_POD 9000

Visit the Spinnaker UI by opening your browser to: http://127.0.0.1:9000
For more info on the Kubernetes integration for Spinnaker, visit:
http://www.spinnaker.io/docs/kubernetes-source-to-prod

In case you see a timeout error, delete the chart with helm del –purge kubelive command and run the install command again.

All the assets related to Spinnaker are deployed in the spinnaker namespace of the Kubernetes cluster. We can verify it with the below command.

$  kubectl get pod --namespace=spinnaker

NAME                                              READY     STATUS    RESTARTS   AGE

kubelive-jenkins-67bb8f6b96-w5rdp                 1/1       Running   0          53m

kubelive-minio-5946fc9bcc-fcvv8                   1/1       Running   0          53m

kubelive-redis-7bb9d95468-kt2vq                   1/1       Running   1          53m

kubelive-spinnaker-clouddriver-6cd89c9bd5-8rwln   1/1       Running   1          53m

kubelive-spinnaker-deck-7846d6497-bjg7b           1/1       Running   0          53m

kubelive-spinnaker-echo-6fd649469d-2pxzd          1/1       Running   1          53m

kubelive-spinnaker-front50-85dd9fd58c-ktj6j       1/1       Running   1          53m

kubelive-spinnaker-gate-5868d9f8ff-hjpvg          1/1       Running   0         53m

kubelive-spinnaker-igor-fdbdcc9c8-hldsk           1/1       Running   0          53m

kubelive-spinnaker-orca-dd79c8bc7-xmwc7           1/1       Running   0          53m

kubelive-spinnaker-rosco-7b9f77b5bb-drxhs         1/1       Running   0          53m

Before we access the Spinnaker dashboard from the browser, we need to enable port forwarding by running the below commands. This exposes the Pod that runs the Spinnaker web UI to the host.

$ export DECK_POD=$(kubectl get pods --namespace spinnaker -l "component=deck,app=kubelive-spinnaker" -o jsonpath="{.items[0].metadata.name}")

$ kubectl port-forward --namespace spinnaker $DECK_POD 9000

Spinnaker can now be accessed from the browser by visiting http://localhost:9000.

Deploying and Scaling a Containerized Application through Spinnaker

Let’s get familiar with Spinnaker concepts and terminology by deploying a simple Nginx web server.

Start by creating an application by clicking on Create Application under the Actions menu on the right top corner. An “application” here is a logical collection of various resources such as Load Balancers, Security Groups, Server Groups, and Clusters.

Let’s create a Load Balancer through which the application can be accessed. Click on the Load Balancer on the top menu bar, and then click on the Create Load Balancer button.

 

When creating a new Load Balancer, type prod as the stack name, 80 for Target Port, and choose NodePort as Type. Click on Create button when done.

Under Clusters, click on Create Server Group.

 

 

When creating a new Server Group, type prod as the stack name. Choose nginx:latest as the container from the dropdown. Choose nginx-prod as the Load Balancer, which we created in the previous step. Type 10 as capacity.

 

Under the Container setting, select Probes to create Readiness Probe and Liveness Probe with defaults. Finally, click on the Create button.

Wait for the instances under the Server Group to become available. The red colored blocks indicate that the instances are not ready yet.

Switch to the terminal, and run the following command to get the NodePort of the Service.

$ kubectl get svc

NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE

kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP        50m

nginx-prod   NodePort    10.99.164.47   <none>        80:31728/TCP   18m

The Load Balancer created in Spinnaker is translated to a NodePort Service in Kubernetes. We now access this directly through the Minikube command.

$ minikube service nginx-prod

Opening kubernetes service default/nginx-prod in default browser...

Running kubectl get pods shows that there are 10 Pods created from Nginx container.

$ kubectl get pods

NAME                    READY     STATUS    RESTARTS   AGE

nginx-prod-v000-6m642   1/1       Running   0          9m

nginx-prod-v000-9kxtv   1/1       Running   0          9m

nginx-prod-v000-bpzw4   1/1       Running   0          9m

nginx-prod-v000-f87gn   1/1       Running   0          9m

nginx-prod-v000-h629g   1/1       Running   0          9m

nginx-prod-v000-hkhjc   1/1       Running   0          9m

nginx-prod-v000-jhnv2   1/1       Running   0          9m

nginx-prod-v000-jmkgx   1/1       Running   0          9m

nginx-prod-v000-s59pm   1/1       Running   0          9m

nginx-prod-v000-ssz85   1/1       Running   0          9m

Expanding the Server Group in Spinnaker dashboard confirms the same.

This tutorial covered all the steps involved in getting Spinnaker up and running in a development environment. In the next part of the Spinnaker series, we will build an end-to-end CI/CD pipeline for Blue/Green deployments through Spinnaker. Stay tuned!

Additional editions of this series on learning Spinnaker will be found here

Google and Microsoft are sponsors of The New Stack.

Feature image via Pixabay.


A digest of the week’s most important stories & analyses.

View / Add Comments

Please stay on topic and be respectful of others. Review our Terms of Use.