Spinnaker by Example: Part 2
By: John Tucker
Tags: Kubernetes, Spinnaker, Continuous Integration

Continuing our step-by-step walk-through with a couple of post-installation configuration items.

This is part of a series starting with my article Spinnaker by Example: Part 1, which provides a step-by-step walk-through of installing and using Spinnaker to deploy applications to a Google Kubernetes Engine (GKE) cluster. The final set of configuration files provided throughout this series of articles is available for download.

As you can see, there are a number of things we are instructed to set up.

You’ve installed and configured Spinnaker, but there are still a few other things to set up: - Configure your image bakery

- Enable security (auth/auth) for your Spinnaker installation

- Set up continuous integration

- Enable monitoring

— Spinnaker — Configure Everything Else

Configure the Image Bakery

Since the concept of Immutable Infrastructure is core to Spinnaker, we provide an image bakery powered by Hashicorp’s Packer to help you produce machine images.

— Spinnaker — Configure the Image Bakery

Because we are deploying containers onto a GKE cluster, we do not need to mess with this feature.

Back-Up Your Config

A quick side-bar into backing up your Halyard state. It turns out that Halyard does indeed maintain state on the machine it runs on; albeit in a crude way.

Most of Halyard’s state is stored in the ~/.hal directory for every deployment of Spinnaker that it’s managing. However, things like credential files or paths to user data may appear in different folders on your file system. This makes backing up the state of Spinnaker via Halyard tricky to do by hand… luckily, Halyard has a solution.

— Spinnaker — Back Up Your Config

The general idea is that every time we make a change to Halyard (these are the hal commands we executed earlier), we need to create a backup (a tar file in the current directory).

$ hal backup create

Then copy the file off the instance (hint: use gcloud compute scp).

Later if we need to recreate the halyard GCE instance, we would install Halyard, copy the backup to the instance, and execute:

$ hal backup restore --backup-path [REPLACE]

Crude but effective.

Expose the Spinnaker UI

In addition to authentication and authorization, security also includes securely exposing the Spinnaker UI. To reach the Spinner UI (if you recall) we currently have to tunnel HTTP traffic through the halyard GCE instance; a real pain. Here we want to expose the Spinnaker UI over HTTPS (either internally or externally over the Internet).

There are broadly two approaches to this:

A common practice is to offload SSL-related bits to outside of the server in question. This is fully supported in Spinnaker, but it does affect the authentication configuration slightly.

— Spinnaker — SSL

Terminating SSL within the Gate server is the de-facto way to enable SSL for Spinnaker. This works with or without a load balancer proxying traffic to this instance.

— Spinnaker — SSL

Given that we have deployed Spinnaker onto a GKE cluster, a natural way of exposing the frontend UI (the spin-deck service) and the backend API (the spin-gate service) is using an ingress for external load balancing over HTTPS. For the internally available approach, there is Configuring Ingress for Internal HTTP(S) Load Balancing.

To keep things simple for this article, we will simply expose these services over HTTP using a LoadBalancer per service.

The first step here is to change the spin-deck and spin-gate services from ClusterIP to LoadBalancer. The challenge here, however, is that Halyard created and presumably manages these services. But…

The key point is, Halyard does not touch any of the Kubernetes Service objects once they are created. You can change their type to NodePort, or LoadBalancer, front them with Ingress resources, or manage them like any other Kubernetes service and expose them however you like.

— Spinnaker — Halyard FAQ

So, we can simply use the following command from our workstation to edit the spin-gate service (changing the type from ClusterIP to LoadBalancer):

$ kubectl edit service spin-gate -n spinnaker

and

$ kubectl edit service spin-deck -n spinnaker

We can confirm the change with:

$ kubectl get services -n spinnaker

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

spin-clouddriver ClusterIP 192.168.35.184 <none> 7002/TCP 153m

spin-deck LoadBalancer 192.168.79.158 35.188.129.8 9000:30013/TCP 153m

spin-echo ClusterIP 192.168.119.254 <none> 8089/TCP 153m

spin-front50 ClusterIP 192.168.10.143 <none> 8080/TCP 153m

spin-gate LoadBalancer 192.168.74.186 35.202.58.89 8084:31100/TCP 153m

spin-orca ClusterIP 192.168.128.236 <none> 8083/TCP 153m

spin-redis ClusterIP 192.168.247.102 <none> 6379/TCP 153m

spin-rosco ClusterIP 192.168.181.83 <none> 8087/TCP 153m

At this point, we can access the Spinner UI (spin-deck) using the external IP, e.g., http://35.188.129.8:9000

The problem, however, here is that the web application is still trying to access the backend API (spin-gate) using http://localhost:8084 instead of http://35.202.58.89:8084 provided by the LoadBalancer. The failed network calls in red are our clue.

Luckily, the URLs for both the UI (spin-deck) and API (spin-gate) services are configurable:

Regardless, you still need to set the API & UI baseUrls so CORS and login redirects happen correctly, this is done with the commands hal config security ui edit — override-base-url <full ui url> and hal config security api edit — override-base-url <full api url>.

— Spinnaker — Halyard FAQ

We login to the halyard GCE instance:

$ gcloud compute ssh halyard

We then configure the base URL for spin-deck service using; e.g. replacing in my case with http://35.188.129.8:9000

$ hal config security ui edit --override-base-url [REPLACE]

and the base URL for the spin-gate service using; e.g., replacing in my case with http://35.202.58.89:8084

$ hal config security api edit --override-base-url [REPLACE]

We now deploy the changes:

$ hal deploy apply

Now when we try to load the UI, the API calls succeed.

Please note: You will need to wait awhile for all the updated deployments to start and you might need to do a hard reload to refresh the browser’s cache.

Authentication an Authorization

Spinnaker offers all whole host of authentication methods:

- OAuth 2.0/OIDC — The main examples are Google & GitHub endpoints.

- SAML — Lots of examples on this with one of the most prevalent being Okta.

- LDAP — This covers Active Directory and other LDAP servers, such as OpenLDAP.

- X.509 — Often used for client or application communications. Can operate in conjunction with other authentication methods.

— Spinnaker — Authentication

and similarly authorization methods:

- SAML

- LDAP/Active Directory

- GitHub Teams

- Google Groups

— Spinnaker — Authorization

Because the specifics of each method are very specific (and detail-oriented), for the purposes of this article we will forgo authentication and authorization all together. Whew, dodged a bullet here (SMILE)!

Next Steps

In the next article in the series, Spinnaker by Example: Part 3, we will use Spinnaker to deploy an application to our GKE cluster.