Weaveworks 2022.03 release featuring Magalix PaC | Learn more
Balance innovation and agility with security and compliance
risks using a 3-step process across all cloud infrastructure.
Step up business agility without compromising
security or compliance
Everything you need to become a Kubernetes expert.
Always for free!
Everything you need to know about Magalix
culture and much more
Spinnaker is an open-source, multi-cloud deployment tool for releasing software changes reliably. You can deploy and automate your application release across multiple cloud environments including Kubernetes, AWS EC2, Google Computer Engine, Google App Engine, Microsoft Azure and many more.
In this post, we will focus on the installation of Spinnaker in a kubernetes cluster using Halyard. Halyard is a command-line administration tool that manages the lifecycle of your Spinnaker deployment, and it's a recommended way to install, configure and update Spinnaker.
At the end of this “How-to” guide, you will have a production-grade Spinnaker which can be used to create your deployment pipelines for one or more Kubernetes clusters.
We will use Google Cloud for demonstration, the process would be the same for other cloud providers with slight modifications in commands and resources.
We will create all these resources in subsequent steps. Kindly replace your-project with your actual project in required commands.
You can skip this step if you already have one. We will use a “one node” single-zone cluster for demonstration:
gcloud beta container clusters create "kubernetes-cluster-01" \
--zone "asia-southeast1-a" --machine-type "n1-standard-1" \
--num-nodes "1" --no-enable-stackdriver-kubernetes \
--project "your-project"
gcloud compute instances create "spinnaker-halyard" \
--async \
--boot-disk-size "10GB" \
--image-family "ubuntu-1804-lts" \
--image-project "ubuntu-os-cloud" \
--machine-type "n1-standard-1" \
--zone "asia-southeast1-a" \
--project "your-project"
gcloud beta compute ssh --zone "asia-southeast1-a" "spinnaker-halyard" --project "your-project"
sudo -i
sudo apt-get update && sudo apt-get install -y apt-transport-https
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubectl
Add spinnaker user and switch to the spinnaker user, then install Halyard:
adduser spinnaker
echo "spinnaker ALL=(ALL:ALL) NOPASSWD:ALL" > spinnaker && chmod 440 spinnaker && mv spinnaker /etc/sudoers.d/
su - spinnaker
curl -O https://raw.githubusercontent.com/spinnaker/halyard/master/install/debian/InstallHalyard.sh
sudo bash InstallHalyard.sh --user spinnaker (Press Enter and keep default option when it will prompt)
. /home/spinnaker/.bashrc
hal -v
spinnaker@spinnaker-halyard:~$ hal -v
1.31.1-20200207105616
We have successfully installed the Halyard after completion of this step.
Spinnaker will use this service account to access persistent GCS storage:
gcloud iam service-accounts create spinnaker \
--display-name "spinnaker" \
--project your-project
gcloud iam service-accounts keys create ~/.gcp/key.json \
--iam-account spinnaker@your-project.iam.gserviceaccount.com \
--project "your-project"
If you want to persist data generated by Spinnaker, you will need to create a storage bucket with the proper access rights. You will need to give the right permissions on this bucket to the Spinnaker service account created in Step 5. Feel free to change BUCKET_NAME as storage buckets are Global resources and must be unique:
BUCKET_NAME=spin-hal-bucket
gsutil mb -l asia-southeast1 -p your-project gs://$BUCKET_NAME/
gsutil iam ch serviceAccount:spinnaker@your-project.iam.gserviceaccount.com:legacyBucketWriter gs://$BUCKET_NAME
gcloud beta container clusters get-credentials "kubernetes-cluster-01" --zone "asia-southeast1-a" --project "your-project"
Create spinnaker-service-account and assign ClusterAdmin role to this service account.
CONTEXT=$(kubectl config current-context)
kubectl apply --context $CONTEXT -f https://spinnaker.io/downloads/kubernetes/service-account.yml
TOKEN=$(kubectl get secret --context $CONTEXT $(kubectl get serviceaccount spinnaker-service-account --context $CONTEXT -n spinnaker -o jsonpath='{.secrets[0].name}') -n spinnaker -o jsonpath='{.data.token}' | base64 --decode)
kubectl config set-credentials ${CONTEXT}-token-user --token $TOKEN
kubectl config set-context $CONTEXT --user ${CONTEXT}-token-user
hal config provider kubernetes enable
hal config provider kubernetes account add kubernetes-cluster-01 --provider-version v2 --context $(kubectl config current-context)
hal config features edit --artifacts true
Repeat steps 7 to 9 for each of the clusters in-which you want to manage using Spinnaker or want to install Spinnaker in.
ACCOUNT=kubernetes-cluster-01
hal config deploy edit --type distributed --account-name $ACCOUNT
hal config storage gcs edit --bucket $BUCKET_NAME --project your-project --json-path ~/.gcp/key.json
hal config storage edit --type gcs
Now List the available spinnaker versions. Note that this will list the latest available version of Spinnaker and not Halyard:
hal version list
spinnaker@spinnaker-halyard:~$ hal version list
+ Get current deployment
Success
+ Get Spinnaker version
Success
+ Get released versions
Success
+ You are on version "", and the following are available:
- 1.16.7 (SecretObsession):
Changelog: https://gist.github.com/spinnaker-release/170d178708b56e83b0289452cb83f347
Published: Mon Mar 09 19:34:31 UTC 2020
(Requires Halyard >= 1.17)
- 1.17.7 (LlamaLlama):
Changelog: https://gist.github.com/spinnaker-release/eea8c2434c8dcf77de8506ffec705246
Published: Mon Mar 09 19:37:42 UTC 2020
(Requires Halyard >= 1.17)
- 1.18.5 (Longmire):
Changelog: https://gist.github.com/spinnaker-release/2cfb72a46883b82a657b4e4b8cba6f62
Published: Mon Mar 09 19:44:00 UTC 2020
(Requires Halyard >= 1.29)
- 1.19.0 (Gilmore Girls A Year in the Life):
Changelog: https://gist.github.com/spinnaker-release/dbc44ac411d5076002b5db7c64b8c63e
Published: Wed Mar 11 20:22:58 UTC 2020
(Requires Halyard >= 1.32)
Set VERSION with one of the listed versions:
VERSION=1.16.7
hal config version edit --version $VERSION
hal deploy apply
After this step, Spinnaker would have been deployed in the spinnaker namespace of kubernetes cluster. Note that before hal deploy apply, each configuration was added in hal configuration only and would be applicable on running spinnaker after hal deploy apply command.
We can check all Spinnaker microservices running in spinnaker namespace:
kubectl get all -n spinnaker
spinnaker@spinnaker-halyard:~$ kubectl get all -n spinnaker
NAME READY STATUS RESTARTS AGE
pod/spin-clouddriver-78f5977c8b-6wll2 1/1 Running 0 45m
pod/spin-deck-7d86cd5c56-bnjlt 1/1 Running 0 45m
pod/spin-echo-7d9dcb8894-ggln4 1/1 Running 0 45m
pod/spin-front50-78996dfbf4-g5g2m 1/1 Running 0 45m
pod/spin-gate-5dfd759658-rwxr5 1/1 Running 0 45m
pod/spin-orca-76d64868db-lb7cp 1/1 Running 0 45m
pod/spin-redis-c9b94cd9c-5lz5z 1/1 Running 0 45m
pod/spin-rosco-64544867b8-vzvz8 1/1 Running 0 45m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/spin-clouddriver ClusterIP 10.43.254.196 7002/TCP 10d
service/spin-deck ClusterIP 10.43.240.189 9000/TCP 10d
service/spin-echo ClusterIP 10.43.252.206 8089/TCP 10d
service/spin-front50 ClusterIP 10.43.250.115 8080/TCP 10d
service/spin-gate ClusterIP 10.43.248.203 8084/TCP 10d
service/spin-orca ClusterIP 10.43.247.203 8083/TCP 10d
service/spin-redis ClusterIP 10.43.242.44 6379/TCP 10d
service/spin-rosco ClusterIP 10.43.253.57 8087/TCP 10d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/spin-clouddriver 1/1 1 1 10d
deployment.apps/spin-deck 1/1 1 1 10d
deployment.apps/spin-echo 1/1 1 1 10d
deployment.apps/spin-front50 1/1 1 1 10d
deployment.apps/spin-gate 1/1 1 1 10d
deployment.apps/spin-orca 1/1 1 1 10d
deployment.apps/spin-redis 1/1 1 1 10d
deployment.apps/spin-rosco 1/1 1 1 10d
NAME DESIRED CURRENT READY AGE
replicaset.apps/spin-clouddriver-78f5977c8b 1 1 1 10d
replicaset.apps/spin-deck-7d86cd5c56 1 1 1 10d
replicaset.apps/spin-echo-7d9dcb8894 1 1 1 10d
replicaset.apps/spin-front50-78996dfbf4 1 1 1 10d
replicaset.apps/spin-gate-5dfd759658 1 1 1 10d
replicaset.apps/spin-orca-76d64868db 1 1 1 10d
replicaset.apps/spin-redis-c9b94cd9c 1 1 1 10d
replicaset.apps/spin-rosco-64544867b8 1 1 1 10d
Deck is the browser-based UI for spinnaker management. We need to expose the deck outside the Kubernetes cluster to access this from our browser. We would achieve this by editing spin-deck service and making it a type of Internal load balancer.
kubectl edit svc spin-deck -n spinnaker
Add the following parameter in the spin-deck yaml file according to kubernetes convention.
annotations:
cloud.google.com/load-balancer-type: Internal
- port: 80
type: LoadBalancer
apiVersion: v1
kind: Service
metadata:
annotations:
cloud.google.com/load-balancer-type: Internal
labels:
app: spin
cluster: spin-deck
name: spin-deck
namespace: spinnaker
spec:
clusterIP: 10.43.240.189
externalTrafficPolicy: Cluster
ports:
- port: 80
protocol: TCP
targetPort: 9000
selector:
app: spin
cluster: spin-deck
sessionAffinity: None
type: LoadBalancer
Gate is the API gateway for spinnaker. All api callers communicate with Spinnaker via Gate.
kubectl edit svc spin-gate -n spinnaker
Similar to Step 13 add following in spin-gate yaml
annotations:
cloud.google.com/load-balancer-type: Internal
- port: 80
type: LoadBalancer
apiVersion: v1
kind: Service
metadata:
annotations:
cloud.google.com/load-balancer-type: Internal
labels:
app: spin
cluster: spin-gate
name: spin-gate
namespace: spinnaker
spec:
clusterIP: 10.43.248.203
externalTrafficPolicy: Cluster
ports:
- port: 80
protocol: TCP
targetPort: 8084
selector:
app: spin
cluster: spin-gate
sessionAffinity: None
type: LoadBalancer
We can check if both deck and gate have the same type of Internal Load balancer service now.
kubectl get svc -n spinnaker
spinnaker@spinnaker-halyard:~$ kubectl get svc -n spinnaker
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/spin-clouddriver ClusterIP 10.43.254.196 7002/TCP 10d
service/spin-deck LoadBalancer 10.43.240.189 10.148.0.49 80:32261/TCP 10d
service/spin-echo ClusterIP 10.43.252.206 8089/TCP 10d
service/spin-front50 ClusterIP 10.43.250.115 8080/TCP 10d
service/spin-gate LoadBalancer 10.43.248.203 10.148.0.50 80:31320/TCP 10d
service/spin-orca ClusterIP 10.43.247.203 8083/TCP 10d
service/spin-redis ClusterIP 10.43.242.44 6379/TCP 10d
service/spin-rosco ClusterIP 10.43.253.57 8087/TCP 10d
Assign domains on both decks’ and gates’ Load balancer IPs, then add these domains in Halyard config. Let’s use the following domains for the rest of the tutorial, replace these domains with your actual domains in respective commands.
spin-deck -> spinnaker-ui.example.com
spin-gate -> spinnaker-api.example.com
Add these domains in halyard config and deploy them again:
hal config security ui edit --override-base-url http://spinnaker-ui.example.com
hal config security api edit --override-base-url http://spinnaker-api.example.com
hal deploy apply
After this step you would be able to access Spinnaker using http://spinnaker-ui.example.com domain.
We will add Google OAuth for Login into Spinnaker and will allow Login for particular domains only. We would need Google OAuth client Id and secret for this setup. To generate them, follow the steps below:
CLIENT_ID=CLIENT_ID_GENERATED_IN_STEP_16
CLIENT_SECRET=CLIENT_SECRET_GENERATED_IN_STEP_16
PROVIDER=google
DOMAIN=example.com
hal config security authn oauth2 edit --client-id $CLIENT_ID --client-secret $CLIENT_SECRET --provider $PROVIDER --user-info-requirements hd=$DOMAIN
hal config security authn oauth2 enable
hal deploy apply
After this step, We have successfully set up Authentication for our Spinnaker UI. We can open our Spinnaker UI Domain at http://spinnaker-ui.example.com and can Login with our example.com Email Id.
Feel free to get in touch if you encounter any challenge during the installation process, or if you need any help or have helpful suggestions. Happy Reading :)
Vikas Saini is a part of the Magalix Write For Cloud-Native Community Expert Program, and Can be Found On Social Media at Linkedin, Twitter, and Github.
Self-service developer platform is all about creating a frictionless development process, boosting developer velocity, and increasing developer autonomy. Learn more about self-service platforms and why it’s important.
Explore how you can get started with GitOps using Weave GitOps products: Weave GitOps Core and Weave GitOps Enterprise. Read more.
More and more businesses are adopting GitOps. Learn about the 5 reasons why GitOps is important for businesses.
Implement the proper governance and operational excellence in your Kubernetes clusters.
Comments and Responses