Install Armory Enterprise for Spinnaker in the Azure Kubernetes Service (AKS)
Armory Enterprise requires a license. For more information, contact Armory.
Overview of installing Armory Enterprise in AKS
This guide walks you through creating and using the following Azure resources:
- An AKS cluster. You can also use an existing cluster.
- An AZS (Azure Storage) bucket. You can also use an existing bucket.
- An NGINX Ingress controller in your AKS cluster. This resource is only needed if your cluster doesn’t already have an ingress installed. Note that the examples on this page for NGINX only work on Kubernetes version 1.14 or later.
This document does not cover the following:
- TLS Encryption
- Authentication and authorization
- Add K8s accounts to deploy to
- Add cloud accounts to deploy to
See Next Steps for resources related to these topics.
This document focuses on Armory’s extended Spinnaker for enterprises and uses the Armory-extended version of Halyard (referred to as ‘Halyard’ in this doc). You can install open source Spinnaker by using an open source Halyard container and a corresponding open source Spinnaker version.
Prerequisites for installing Armory Enterprise
To follow the steps described in this guide, make sure you have met the following prerequisites:
- You have login credentials to Azure that allow you to create resources
- You have an Azure subscription defined where you will install Spinnaker
- You have
az
(the Azure CLI tool) and a recent version ofkubectl
(the Kubernetes CLI tool) on a machine (referred to as theworkstation machine
). - You have Docker available and can run containers on a machine (referred to as the
Halyard machine
). An easy way to install Docker on your machine is with Docker Desktop. - You can transfer files created on the
workstation machine
to the Docker container that runs Halyard on theHalyard machine
. - The
workstation
andHalyard
machines can be the same machine
Workstation machine details
On the workstation machine
, you need both az
and kubectl
installed to create and manage Azure and Kubernetes resources.
With az
, you create and manage the following resources:
- AKS clusters
- AZS buckets
With kubectl
, you need to
- Have a persistent working directory in which to work in. This guide uses
~/aks-spinnaker
- Create AKS resources, such as service accounts that will be permanently associated with your Spinnaker cluster
Halyard machine details
Armory-extended Halyard (the tool used to install and manage Armory) runs in a Docker container on the Halyard machine
. To make this process more seamless, this guide describes how to configure the following volume mounts, which need persisted or preserved to manage your Spinnaker cluster:
.hal
directory (mounted to/home/spinnaker/.hal
) - Stores all Halyard Spinnaker configurations in a.hal/config
YAML file and assorted subdirectories.secret
directory (mounted to/home/spinnaker/.secret
) Stores all external secret keys and files used by Halyard. This includes thekubeconfig
files and Azure IAM service account keys you create as part of this guide.resources
directory (mounted to/home/spinnaker/resources
Installation Summary
In order to install Armory, this document covers the following things:
- Generating a
kubeconfig
file, which is a Kubernetes credential file that Halyard and Spinnaker uses to communicate with the Kubernetes cluster where Spinnaker gets installed - Creating an AZS bucket for Spinnaker to store persistent configurations in
- Running the Halyard daemon in a Docker container
- Persistent configuration directories from the workstation/host get mounted into the container
- Running the
hal
client interactively in the same Docker container to perform the following actions:- Build out the Halyard config YAML file (
.hal/config
) - Configure Armory/Halyard to use the
kubeconfig
to install Spinnaker - Configure Armory with IAM credentials and bucket information
- Turn on other recommended settings (artifacts and http artifact provider)
- Install Armory
- Expose Armory
- Build out the Halyard config YAML file (
Create the AKS cluster
This guide assumes you have already installed the az
CLI on your workstation and are familiar with its use. For more information about az
, see The Azure Command-Line Interface.
This creates a minimal AKS cluster. Follow the official AKS instructions to set up a different type of AKS cluster.
To create an AKS cluster, perform the following steps on the workstation machine
, which has az
and kubectl
installed:
-
Create the local working directory:
mkdir ~/aks-spinnaker cd ~/aks-spinnaker
For this guide, use the
~/aks-spinnaker
directory, but this can be any persistent directory on any Linux or OSX machine. -
Run the following commands to set up the
az
CLI:az login az account list az account set --subscription <your-subscription-id>
-
Determine which Azure locations (like
westus
) are available for your account:az account list-locations --query "[].name"
-
Create a resource group for your AKS cluster in a location available for your account.
RESOURCE_GROUP="Spinnaker" az group create --name ${RESOURCE_GROUP} --location <location>
-
Skip this step if you are using an existing AKS cluster. Create the AKS cluster:
az aks create --resource-group ${RESOURCE_GROUP} --name spinnaker-cluster --node-count 2 --enable-addons monitoring --generate-ssh-keys
-
Configure the Kubernetes context so that
kubectl
uses your AKS cluster:To use the cluster created in the previous step, run the following command:
export KUBECONFIG=kubeconfig-aks az aks get-credentials --resource-group ${RESOURCE_GROUP} --name spinnaker-cluster --file ${KUBECONFIG}
To use an existing AKS cluster, run the following command:
export KUBECONFIG=kubeconfig-aks az aks get-credentials --resource-group <your-resource-group> --name <your-cluster-name> --file ${KUBECONFIG}
-
Verify that you have access to the cluster:
kubectl --kubeconfig kubeconfig-aks get nodes
Create a kubeconfig
file for Halyard and Spinnaker
In this guide, we install Armory in its own namespace (spinnaker-system
) in your AKS cluster; you can use a different namespace for this.
This section of the guide describes how to do create the following:
- A namespace called
spinnaker-system
to install Armory in - A service account for that namespace
- A role and rolebinding in that namespace, granting permissions to the service account
- A kubeconfig containing credentials for the service account
Halyard uses this kubeconfig
file to create the Kubernetes deployment objects that create the microservices that compose Spinnaker. This same kubeconfig is passed to Spinnaker so that Spinnaker can see and manage its own resources.
We use the Armory spinnaker-tools
Go CLI (available on Github) to create many of these resources. There are separate instructions to perform these steps manually.
-
Obtain the
spinnaker-tools
CLI tool. Go to https://github.com/armory/spinnaker-tools/releases, and download the latest release for your operating system (OSX and Linux available). Alternatively, run the following commands::# If you're not already in the directory cd ~/aks-spinnaker # If you're on Linux instead of OSX, use this URL instead: # https://github.com/armory/spinnaker-tools/releases/download/0.0.7/spinnaker-tools-linux curl -L https://github.com/armory/spinnaker-tools/releases/download/0.0.7/spinnaker-tools-darwin -o spinnaker-tools chmod +x spinnaker-tools
-
Run
spinnaker-tools
. You can substitute other values for the parameters:SOURCE_KUBECONFIG=kubeconfig-aks CONTEXT=$(kubectl --kubeconfig ${SOURCE_KUBECONFIG} config current-context) DEST_KUBECONFIG=kubeconfig-spinnaker-system-sa SPINNAKER_NAMESPACE=spinnaker-system SPINNAKER_SERVICE_ACCOUNT_NAME=spinnaker-service-account ./spinnaker-tools create-service-account \ --kubeconfig ${SOURCE_KUBECONFIG} \ --context ${CONTEXT} \ --output ${DEST_KUBECONFIG} \ --namespace ${SPINNAKER_NAMESPACE} \ --service-account-name ${SPINNAKER_SERVICE_ACCOUNT_NAME}
The commands create a file called kubeconfig-spinnaker-system-sa
(or something similar if you’re using a different namespace for Spinnaker).
Create an AZS source for Armory
Armory uses an AZS bucket to store persistent configuration (such as pipeline definitions). This section walks you through creating a storage resource group and a storage account.
-
Create a resource group for your storage account in a location available for your account:
STORAGE_RESOURCE_GROUP="SpinnakerStorage" az group create --name ${STORAGE_RESOURCE_GROUP} --location <location>
-
Create a storage account using a globally unique name:
STORAGE_ACCOUNT_NAME=<unique-storage-account-name> az storage account create --resource-group ${STORAGE_RESOURCE_GROUP} --sku STANDARD_LRS --name ${STORAGE_ACCOUNT_NAME} STORAGE_ACCOUNT_KEY=$(az storage account keys list --resource-group ${STORAGE_RESOURCE_GROUP} --account-name ${STORAGE_ACCOUNT_NAME} --query "[0].value" | tr -d '"')
Keep the following Azure requirements in mind when defining
STORAGE_ACCOUNT_NAME
:- The name must be between 3 and 24 characters
- Only numbers and lowercase characters are valid
Stage files on the Halyard machine
In the aks-spinnaker
working directory, create the following folders:
.hal
.secret
resources
WORKING_DIRECTORY=~/aks-spinnaker/
mkdir -p ${WORKING_DIRECTORY}/.hal
mkdir -p ${WORKING_DIRECTORY}/.secret
mkdir -p ${WORKING_DIRECTORY}/resources
The aks-spinnaker
working directory should contain the following file:
- A kubeconfig file (
kubeconfig-spinnaker-system-sa
) with the credentials for a service account in your aks cluster
Copy the file into .secret
so that it is available to your Halyard Docker container:
cp kubeconfig-spinnaker-system-sa ${WORKING_DIRECTORY}/.secret
Start the Halyard container
Visit the Armory-extended Halyard Release Notes page for a list of available Armory-extended Halyard versions and their release notes. You can view version differences as well as which versions are compatible with which Armory releases.
On the Halyard machine
, start the Halyard container.
If you want to install OSS Spinnaker instead, use gcr.io/spinnaker-marketplace/halyard:stable
for the Docker Halyard image reference in substitution of armory/halyard-armory:<image_version>
in the commands below
Before you execute the command below, you need to set permissions on the host (local) directories mapped to the Docker container. These directories must allow for modification from within the container. The
~/.hal
folder within the host (local) system directory needs write permissions (chmod 777 ~/.hal
), or you will encounter issues when attempting to execute ahal deploy apply
from within the container.
docker run --name armory-halyard -it --rm \
-v ${WORKING_DIRECTORY}/.hal:/home/spinnaker/.hal \
-v ${WORKING_DIRECTORY}/.secret:/home/spinnaker/.secret \
-v ${WORKING_DIRECTORY}/resources:/home/spinnaker/resources \
armory/halyard-armory:<image_version>
Note: For image version, you must enter a valid version number, such as 1.8.1. Do not use latest
.
Enter the Halyard container
From a separate terminal session on your halyard machine
, create a second bash/shell session on the Docker container:
docker exec -it armory-halyard bash
# Once in the container, you can run these commands for a friendlier environment to:
# - prompt with information
# - alias for ls
# - cd to the home directory
export PS1="\h:\w \u\$ "
alias ll='ls -alh'
cd ~
Add the kubeconfig and cloud provider to Spinnaker (via Halyard)
From the docker exec
terminal session, add (re-export) the relevant environment variables:
###### Use the same values as the start of the document
# Enter the namespace that you want to install Spinnaker in. This should have been created in the previous step.
export NAMESPACE="spinnaker-system"
# Enter the name you want Spinnaker to use to identify the cloud provider account
export ACCOUNT_NAME="spinnaker"
# Update this with the full path to your kubeconfig inside the container)
export KUBECONFIG_FULL=/home/spinnaker/.secret/kubeconfig-spinnaker-system-sa
Use the Halyard hal
command line tool to add a Kubernetes account using your minified kubeconfig:
# Enable the Kubernetes cloud provider
hal config provider kubernetes enable
# Add account
hal config provider kubernetes account add ${ACCOUNT_NAME} \
--provider-version v2 \
--kubeconfig-file ${KUBECONFIG_FULL} \
--only-spinnaker-managed true \
--namespaces ${NAMESPACE}
Configure Armory to install in Kubernetes
Important: The --location
limits your Armory to deploying to the namespace specified. If you want to be able to deploy to other namespaces, either add a second cloud provider target or remove the --location
flag.
Use the Halyard hal
command line tool to configure Halyard to install Armory in your Kubernetes cluster
hal config deploy edit \
--type distributed \
--account-name ${ACCOUNT_NAME} \
--location ${NAMESPACE}
Enable artifacts
Within Armory, ‘artifacts’ are consumable references to items that live outside of Armory. An artifact can be a file in a git repository or a file in an S3 bucket. This feature must be explicitly turned on.
Enable the “Artifacts” feature and the “http” artifact artifact provider:
# Enable artifacts
hal config features edit --artifacts true
hal config artifact http enable
To add specific types of artifacts, additional configuration must be completed. For now, it is sufficient to just turn on the
artifacts feature with the http
artifact provider. This allows Spinnaker to retrieve files via unauthenticated http.
Configure Armory to use your AZS bucket
Use the Halyard hal
command line tool to configure Spinnaker to use your AZS storage account.
storage-container-name
is optional and has a default value of “spinnaker”. If you’re using a pre-existing container, update storage-container-name
with the name of that container.
####### Inside the armory-halyard container
hal config storage azs edit \
--storage-account-name <storage_account_name> \
--storage-account-key <storage_account_key> \
--storage-container-name <name>
# test connection to azs storage
hal config storage azs
# Set the storage source to AZS
hal config storage edit --type azs
Choose the Armory version
Before Halyard installs Armory, you should specify the version of Armory you want to use.
Get a list of available versions of spinnaker with this command:
hal version list
Note that Armory uses a major version numbering scheme that is one version higher than Open Source Spinnaker. For example, Armory 2.x.x
correlates to Open Source Spinnaker 1.x.x
.
After you decide on a version, run the following commands to specify the version:
# Replace with version of choice:
export VERSION=<version>
hal config version edit --version $VERSION
Replace <version>
with a valid version, such as 2.18
.
Install Armory
Now that your hal
config is configured, install Spinnaker with the following hal
command:
hal deploy apply
Once this is complete, congratulations! Spinnaker is installed. Now we have to access and expose it.
Connect to Armory using kubectl port-forward
Test connecting to Armory from your workstation machine:
NAMESPACE=spinnaker-system
DECK_POD=$(kubectl -n ${NAMESPACE} get pod -l cluster=spin-deck -ojsonpath='{.items[0].metadata.name}')
GATE_POD=$(kubectl -n ${NAMESPACE} get pod -l cluster=spin-gate -ojsonpath='{.items[0].metadata.name}')
kubectl -n ${NAMESPACE} port-forward ${DECK_POD} 9000 &
kubectl -n ${NAMESPACE} port-forward ${GATE_POD} 8084 &
Then, you can access Armory at http://localhost:9000
.
Trying to connect from a remote machine will not work because your browser attempts to access localhost on your local workstation rather than on the remote machine where the port is forwarded.
Note: Even if the hal deploy apply
command returns successfully, the
installation may not be complete yet. This is especially the case with
distributed Kubernetes installs. If you see errors such as Connection refused
,
the containers may not be available yet. Either wait and try again
or check the status of all of the containers using the command for your cloud provider,
such as kubectl get pods --namespace spinnaker
.
Once the pods are running and Armory is available, you can access Deck (Spinnaker’s UI) at http://localhost:9000.
Note that trying to connect from a remote machine will not work because your browser attempts to access localhost on your local workstation rather than on the remote machine where the port is forwarded.
Install the NGINX ingress controller
In order to expose Spinnaker to end users, you have perform the following actions:
- Expose the spin-deck (UI) Kubernetes service on some URL endpoint
- Expose the spin-gate (API) Kubernetes service on some URL endpoint
- Update Armory (via Halyard) to be aware of the new endpoints
We’re going to install the NGINX ingress controller on AKS because of these limitations of the built-in aks Ingress controller:
- It only exposes NodePort services
- It only exposes services that respond with an
HTTP 200
to aGET
on/
or have areadinessProbe
configured
If you already have an NGINX ingress controller installed on your cluster, skip this step.
Both of these are configurable with Spinnaker, but the NGINX ingress controller is also generally much more configurable.
From the workstation machine
where kubectl
is installed:
If you are using Kubernetes version 1.14 or later, install the NGINX ingress controller components:
kubectl --kubeconfig kubeconfig-gke apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.35.0/deploy/static/provider/cloud/deploy.yaml
If you are using a Kubernetes version earlier than 1.14, perform the following steps:
-
Download this NGINX file: mandatory.yaml
-
Change
kubernetes.io/os
tobeta.kubernetes.io/os
on line 217 ofmandatory.yaml
. -
Run
kubectl apply -f
using the file you modified:kubectl apply -f <modified-mandatory-file>.yaml
Then, install the NGINX ingress controller AKS-specific service:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/cloud-generic.yaml
Set up the ingress for spin-deck
and spin-gate
Identify the URLs you will use to expose Spinnaker’s UI and API.
# Replace with actual values
SPIN_DECK_ENDPOINT=<spinnaker.some-url.com>
SPIN_GATE_ENDPOINT=<api.some-url.com>
NAMESPACE=spinnaker-system
Create a Kubernetes Ingress manifest to expose spin-deck and spin-gate (change your hosts and namespace accordingly):
tee spin-ingress.yaml <<-'EOF'
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: spin-ingress
namespace: NAMESPACE
labels:
app: spin
cluster: spin-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: SPIN_DECK_ENDPOINT
http:
paths:
- backend:
serviceName: spin-deck
servicePort: 9000
path: /
- host: SPIN_GATE_ENDPOINT
http:
paths:
- backend:
serviceName: spin-gate
servicePort: 8084
path: /
EOF
sed -i.bak \
-e "s|NAMESPACE|${NAMESPACE}|g" \
-e "s|SPIN_DECK_ENDPOINT|${SPIN_DECK_ENDPOINT}|g" \
-e "s|SPIN_GATE_ENDPOINT|${SPIN_GATE_ENDPOINT}|g" \
spin-ingress.yaml
Create the Ingress
kubectl apply -f spin-ingress.yaml
Configure Armory to be aware of its endpoints
Armory must be aware of its endpoints to work properly.
This should be done from the halyard container:
SPIN_DECK_ENDPOINT=spinnaker.some-url.com
SPIN_GATE_ENDPOINT=api.some-url.com
SPIN_DECK_URL=http://${SPIN_DECK_ENDPOINT}
SPIN_GATE_URL=http://${SPIN_GATE_ENDPOINT}
hal config security ui edit --override-base-url ${SPIN_DECK_URL}
hal config security api edit --override-base-url ${SPIN_GATE_URL}
hal deploy apply
Set up DNS
Once the ingress is up (this may take some time), you can get the IP address for the ingress:
$ kubectl describe -n spinnaker-system ingress spin-ingress
Name: spinnaker-nginx-ingress
Namespace: spinnaker
Address: 35.233.216.189
Default backend: default-http-backend:80 (10.36.2.7:8080)
Rules:
Host Path Backends
---- ---- --------
spinnaker.some-url.com
/ spin-deck:9000 (<none>)
api.some-url.com
/ spin-gate:8084 (<none>)
Annotations:
kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{"kubernetes.io/ingress.class":"nginx"},"name":"spinnaker-nginx-ingress","namespace":"spinnaker"},"spec":{"rules":[{"host":"spinnaker.some-url.com","http":{"paths":[{"backend":{"serviceName":"spin-deck","servicePort":9000},"path":"/"}]}},{"host":"api.some-url.com","http":{"paths":[{"backend":{"serviceName":"spin-gate","servicePort":8084},"path":"/"}]}}]}}
kubernetes.io/ingress.class: nginx
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal CREATE 28s nginx-ingress-controller Ingress spinnaker/spinnaker-nginx-ingress
Normal UPDATE 20s nginx-ingress-controller Ingress spinnaker/spinnaker-nginx-ingress
Set up DNS so that your two URLs point to the IP address for the ingress (in the above, configure spinnaker.some-url.com
and api.some-url.com
to point to 35.233.216.189
). This can be done via whatever your organization uses for DNS.
Configure TLS Certificates
Configuration of TLS certificates for ingresses is often very organization-specific. In general, you want to do the following:
-
Add certificate(s) so that your ingress controller can use them
-
Configure the ingress(es) so that NGINX (or your ingress) terminates TLS using the certificate(s)
-
Update Armory to be aware of the new TLS endpoints (note
https
instead ofhttp
)SPIN_DECK_ENDPOINT=spinnaker.some-url.com SPIN_GATE_ENDPOINT=api.some-url.com SPIN_DECK_URL=https://${SPIN_DECK_ENDPOINT} SPIN_GATE_URL=https://${SPIN_GATE_ENDPOINT} hal config security ui edit --override-base-url ${SPIN_DECK_URL} hal config security api edit --override-base-url ${SPIN_GATE_URL} hal deploy apply
Next steps
Now that you have Spinnaker up and running, here are some of the next things you may want to do:
- Configuration of certificates to secure your cluster (see this section for notes on this)
- Configuration of Authentication/Authorization (see the Open Source Spinnaker documentation)
- Add Kubernetes accounts to deploy applications to (see Creating and Adding a Kubernetes Account to Spinnaker as a Deployment Target)
- Add Azure accounts to deploy applications to (see the Open Source Spinnaker documentation)
- Add GCP accounts to deploy applications to (see the Open Source Spinnaker documentation)
- Add AWS accounts to deploy applications to (see the Open Source Spinnaker documentation)
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.