โ† Back to DevBytes

Spinnaker: Complete Configuration Guide

Introduction to Spinnaker

Spinnaker is an open-source, multi-cloud continuous delivery platform created by Netflix and later co-developed with Google. It is designed to release software changes with high velocity and confidence across multiple cloud providers such as AWS, Google Cloud Platform, Microsoft Azure, Kubernetes, and more. Unlike traditional CI tools, Spinnaker focuses exclusively on continuous delivery (CD), enabling teams to orchestrate complex deployment pipelines, manage cloud resources, and implement progressive delivery strategies like blue/green and canary deployments.

Why Spinnaker Matters

Modern applications are deployed across distributed environments with frequent releases. Spinnaker matters because it decouples deployment from build, integrates natively with cloud providers, and provides a unified API for managing deployments. It reduces deployment risk through automated rollbacks, deployment windows, and granular approval workflows. For organizations scaling microservices, Spinnaker offers a battle-tested solution that has been proven at Netflix-scale.

Spinnaker Architecture Overview

Spinnaker is composed of several microservices, each responsible for a specific function. Understanding these components is essential before configuring the platform.

Installing Spinnaker

The fastest way to install Spinnaker is using Halyard, the official command-line administration tool. Halyard manages the configuration and lifecycle of your Spinnaker deployment.

Installing Halyard

On a Linux or macOS machine, install Halyard with the following commands:

curl -O https://raw.githubusercontent.com/spinnaker/halyard/master/install/debian/InstallHalyard.sh
sudo bash InstallHalyard.sh
hal --version

After installation, verify that Halyard is running:

hal --version

Choosing a Storage Provider

Spinnaker requires a persistent storage backend to store application and pipeline metadata. Supported options include Amazon S3, Google Cloud Storage, Azure Blob Storage, and Minio. For this guide, we will use S3.

hal config storage s3 edit \
  --endpoint https://s3.amazonaws.com \
  --bucket my-spinnaker-bucket \
  --access-key-id YOUR_ACCESS_KEY \
  --secret-access-key YOUR_SECRET_KEY

hal config storage edit --type s3

Configuring Cloud Providers

Spinnaker supports multiple cloud providers. You must enable and configure at least one provider to deploy applications.

Configuring Kubernetes

Kubernetes is the most common provider for modern Spinnaker deployments. First, enable the Kubernetes provider:

hal config provider kubernetes enable

Next, add a Kubernetes account. You will need a kubeconfig file with access to your cluster:

hal config provider kubernetes account add my-k8s-account \
  --context my-cluster-context \
  --kubeconfig-file ~/.kube/config \
  --only-spinnaker-managed true \
  --namespaces default,production,staging

hal config provider kubernetes account delete default

The --only-spinnaker-managed flag ensures Spinnaker only modifies resources it created, preventing accidental changes to manually created resources.

Configuring AWS

To deploy to AWS, enable the AWS provider and configure an account with appropriate credentials:

hal config provider aws enable

hal config provider aws account add my-aws-account \
  --access-key-id YOUR_ACCESS_KEY \
  --secret-access-key YOUR_SECRET_KEY \
  --regions us-east-1,us-west-2

hal config provider aws bakery edit \
  --aws-access-key-id YOUR_ACCESS_KEY \
  --aws-secret-access-key YOUR_SECRET_KEY \
  --aws-default-region us-east-1

Deploying Spinnaker

Once your storage and cloud providers are configured, you need to choose a deployment environment. Spinnaker can be deployed to a local machine, a distributed environment, or Kubernetes.

Deploying to Kubernetes

For production deployments, Kubernetes is recommended. Configure Halyard to deploy Spinnaker to Kubernetes:

hal config deploy edit --type distributed --account-name my-k8s-account

Set the Spinnaker version you want to deploy:

hal config version edit --version 1.33.0

Finally, deploy Spinnaker:

hal deploy apply

This command generates Kubernetes manifests and applies them to your cluster. Monitor the deployment with:

kubectl get pods -n spinnaker

Configuring Authentication and Authorization

For production deployments, you must secure Spinnaker with authentication and role-based access control.

Configuring GitHub OAuth

Spinnaker supports multiple identity providers. To configure GitHub OAuth, first create an OAuth application in GitHub, then configure Gate:

hal config security authn oauth2 edit \
  --client-id YOUR_GITHUB_CLIENT_ID \
  --client-secret YOUR_GITHUB_CLIENT_SECRET \
  --provider github \
  --pre-established-redirect-uri https://spinnaker.example.com/login

hal config security authn oauth2 enable

Configuring RBAC with Fiat

Role-based access control is managed by Fiat. Enable Fiat and configure role providers:

hal config security authz enable

hal config security authz github edit \
  --organization my-organization \
  --access-organization my-organization

hal deploy apply

You can then define role-based permissions in a YAML file:

roles:
  - name: developers
    description: Development team members
  - name: ops
    description: Operations team members

policies:
  - name: developer-policy
    description: Read-only access to applications
    role: developers
    permissions:
      - resource: application:my-app
        actions: READ
  - name: ops-policy
    description: Full access to applications
    role: ops
    permissions:
      - resource: application:my-app
        actions: READ,WRITE,EXECUTE

Creating Applications and Pipelines

Applications are the top-level organizational unit in Spinnaker. Each application contains pipelines that define deployment workflows.

Creating an Application

You can create an application through the Deck UI or via the API. Here is an example using the API:

curl -X POST https://spinnaker.example.com/applications/my-app \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-app",
    "email": "team@example.com",
    "description": "My sample application",
    "cloudProviders": ["kubernetes"],
    "instancePort": 80
  }'

Defining a Pipeline

Pipelines are defined as JSON documents. The following example creates a pipeline that triggers on a Docker image push, deploys to a staging namespace, runs a manual judgment, and then deploys to production:

{
  "name": "deploy-to-production",
  "application": "my-app",
  "stages": [
    {
      "name": "Deploy to Staging",
      "type": "deployManifest",
      "account": "my-k8s-account",
      "namespace": "staging",
      "manifests": [
        {
          "apiVersion": "apps/v1",
          "kind": "Deployment",
          "metadata": {
            "name": "my-app"
          },
          "spec": {
            "replicas": 3,
            "selector": {
              "matchLabels": {
                "app": "my-app"
              }
            },
            "template": {
              "metadata": {
                "labels": {
                  "app": "my-app"
                }
              },
              "spec": {
                "containers": [
                  {
                    "name": "my-app",
                    "image": "registry.example.com/my-app:${trigger.artifact.version}",
                    "ports": [
                      {
                        "containerPort": 80
                      }
                    ]
                  }
                ]
              }
            }
          }
        }
      ]
    },
    {
      "name": "Manual Judgment",
      "type": "manualJudgment",
      "instructions": "Review the staging deployment and approve for production.",
      "judgmentInputs": []
    },
    {
      "name": "Deploy to Production",
      "type": "deployManifest",
      "account": "my-k8s-account",
      "namespace": "production",
      "manifests": [
        {
          "apiVersion": "apps/v1",
          "kind": "Deployment",
          "metadata": {
            "name": "my-app"
          },
          "spec": {
            "replicas": 5,
            "selector": {
              "matchLabels": {
                "app": "my-app"
              }
            },
            "template": {
              "metadata": {
                "labels": {
                  "app": "my-app"
                }
              },
              "spec": {
                "containers": [
                  {
                    "name": "my-app",
                    "image": "registry.example.com/my-app:${trigger.artifact.version}",
                    "ports": [
                      {
                        "containerPort": 80
                      }
                    ]
                  }
                ]
              }
            }
          }
        }
      ]
    }
  ],
  "triggers": [
    {
      "type": "docker",
      "account": "my-docker-registry",
      "repository": "registry.example.com/my-app"
    }
  ]
}

Save this JSON to a file and create the pipeline via the API:

curl -X POST https://spinnaker.example.com/pipelines \
  -H "Content-Type: application/json" \
  -d @pipeline.json

Configuring CI Integration

Spinnaker integrates with CI systems to trigger pipelines based on build events. Jenkins is a common integration point.

Adding a Jenkins Master

hal config ci jenkins enable

hal config ci jenkins master add my-jenkins \
  --address https://jenkins.example.com \
  --username spinnaker \
  --password YOUR_JENKINS_API_TOKEN

hal deploy apply

Once configured, you can add a Jenkins trigger to any pipeline:

{
  "type": "jenkins",
  "master": "my-jenkins",
  "job": "my-app-build",
  "propertyFile": "build.properties"
}

Implementing Deployment Strategies

Spinnaker supports several deployment strategies out of the box. The most common are blue/green and canary deployments.

Blue/Green Deployment

Blue/green deployments are configured using the red/black strategy in Spinnaker. This strategy deploys a new server group, waits for it to become healthy, and then disables the previous server group:

{
  "name": "Blue/Green Deploy",
  "type": "deploy",
  "clusters": [
    {
      "account": "my-aws-account",
      "application": "my-app",
      "strategy": "redblack",
      "stack": "production",
      "freeFormDetails": "v${trigger.buildNumber}",
      "capacity": {
        "desired": 3,
        "min": 3,
        "max": 3
      },
      "loadBalancers": ["my-app-elb"],
      "securityGroups": ["sg-12345678"],
      "instanceType": "t3.medium"
    }
  ]
}

Canary Deployment with Kayenta

Canary deployments gradually shift traffic to a new version while monitoring metrics. Kayenta performs automated canary analysis using signals from monitoring systems like Prometheus or Datadog.

First, configure Kayenta with a metrics provider:

hal config canary prometheus enable

hal config canary prometheus account add my-prometheus \
  --base-url http://prometheus.example.com:9090

hal config canary edit \
  --enabled true \
  --default-metrics-account my-prometheus \
  --default-storage-account my-s3-account

hal deploy apply

Then define a canary config that specifies the metrics to evaluate:

{
  "name": "my-app-canary",
  "description": "Canary analysis for my-app",
  "metrics": [
    {
      "name": "request-latency",
      "query": {
        "type": "prometheus",
        "customInlineTemplate": "avg(http_request_duration_seconds{app=\"my-app\"}) by (version)"
      },
      "analysisConfigurations": {
        "canary": {
          "direction": "DECREASE"
        }
      }
    },
    {
      "name": "error-rate",
      "query": {
        "type": "prometheus",
        "customInlineTemplate": "rate(http_requests_total{app=\"my-app\",status=~\"5..\"}[5m]) by (version)"
      },
      "analysisConfigurations": {
        "canary": {
          "direction": "DECREASE"
        }
      }
    }
  ],
  "scoreThresholds": {
    "pass": 95,
    "marginal": 75,
    "fail": 75
  }
}

Configuring Notifications

Spinnaker can send notifications through Slack, email, and other channels when pipeline events occur. To configure Slack notifications:

hal config notification slack edit \
  --bot-name spinnaker-bot \
  --token YOUR_SLACK_API_TOKEN

hal config notification slack enable

hal deploy apply

Add a notification stage to your pipeline:

{
  "name": "Notify Slack",
  "type": "slack",
  "message": "Deployment of my-app completed successfully.",
  "channel": "#deployments"
}

Best Practices

Backing Up and Restoring Configuration

Spinnaker configuration managed by Halyard is stored in ~/.hal. Regularly back up this directory:

tar -czf spinnaker-hal-backup-$(date +%Y%m%d).tar.gz ~/.hal

To restore, extract the archive and redeploy:

tar -xzf spinnaker-hal-backup-20240101.tar.gz -C ~/
hal deploy apply

For application and pipeline data stored in Front50, ensure your storage backend (S3, GCS) has versioning and lifecycle policies configured for disaster recovery.

Conclusion

Spinnaker is a powerful continuous delivery platform that enables teams to deploy applications reliably across multiple cloud environments. By understanding its architecture, properly configuring cloud providers, securing access with authentication and RBAC, and implementing progressive deployment strategies, organizations can achieve high deployment velocity without sacrificing stability. Following best practices such as version-controlling pipeline definitions, using immutable artifacts, and maintaining separate staging instances will help you get the most out of Spinnaker. While the initial setup requires careful planning, the long-term benefits of automated, auditable, and reversible deployments make Spinnaker an excellent choice for teams operating at scale.

๐Ÿ›  Tools from DevBytes

Inventory Tracker Pro โ€” Excel inventory system, low-stock alerts ยท $19
AI Dev Kit for Mac โ€” local AI dev environment templates ยท $9.99
KeyMapper for Mac โ€” custom keyboard shortcut toolkit ยท $7.99

โ† Back to all articles