CICD Spinnaker
Introduction
Spinnaker is an open-source, multi-cloud continuous delivery platform initially developed by Netflix and now maintained by a community including Google, Microsoft, and Amazon. It's designed to help teams release software changes with high velocity and confidence.
Unlike many CI/CD tools that focus primarily on building and testing code, Spinnaker specializes in the deployment part of the pipeline - taking your built artifacts and safely deploying them to your target environments, whether they're virtual machines, containers, or serverless functions.
What Makes Spinnaker Special?
Spinnaker stands out from other CI/CD tools because of its:
- Multi-cloud support: Deploy to AWS, GCP, Azure, Kubernetes, and more from a single platform
- Deployment strategies: Advanced deployment techniques like blue/green and canary deployments built-in
- Pipeline visualization: Clear visual representation of your deployment pipelines
- Manual judgments: Ability to add approval gates at critical points in your pipeline
- Deployment history: Track when and how services were deployed
Spinnaker Architecture
Spinnaker has a microservices architecture composed of several components:
Each service has specific responsibilities:
- Deck: User interface for creating and managing pipelines
- Gate: API gateway to the Spinnaker services
- Orca: Orchestrates pipelines and tasks
- Clouddriver: Interfaces with various cloud providers
- Igor: Triggers pipelines from CI systems
- Echo: Handles notifications and webhooks
- Front50: Stores and retrieves metadata about applications, pipelines, etc.
Setting Up Spinnaker
Spinnaker can be deployed in various ways, but the most common approach for beginners is using Halyard, a command-line tool that manages Spinnaker's lifecycle.
Prerequisites
- Kubernetes cluster (for hosting Spinnaker)
- kubectl configured
- Minimum 4GB RAM, 2 vCPUs
- Storage provider (S3, GCS, etc.)
Basic Installation Steps
- Install Halyard on your machine:
curl -O https://raw.githubusercontent.com/spinnaker/halyard/master/install/debian/InstallHalyard.sh
sudo bash InstallHalyard.sh
- Set up a storage provider (Example with S3):
hal config storage s3 edit \
--access-key-id $AWS_ACCESS_KEY_ID \
--secret-access-key $AWS_SECRET_ACCESS_KEY \
--region us-west-2 \
--bucket spinnaker-artifacts
hal config storage edit --type s3
- Add a Kubernetes account:
hal config provider kubernetes enable
hal config provider kubernetes account add my-k8s \
--context $(kubectl config current-context)
- Choose which Spinnaker version to deploy:
hal version list
hal config version edit --version 1.28.0
- Deploy Spinnaker:
hal deploy apply
- Connect to the UI:
hal deploy connect
This will forward Spinnaker's UI to http://localhost:9000.
Creating Your First Pipeline
Now that you have Spinnaker installed, let's create a basic deployment pipeline.
Step 1: Create an Application
- Open Spinnaker UI at http://localhost:9000
- Click on "Applications" then "Create Application"
- Fill in details:
- Name: my-first-app
- Email: [email protected]
- Cloud Providers: select Kubernetes
- Click "Create"
Step 2: Create a Pipeline
- Inside your application, go to "Pipelines" and click "Create"
- Name your pipeline "Deploy to Dev"
- Click "Create"
Step 3: Add a Trigger
- In the pipeline configuration, click "Add Trigger"
- Select "Docker Registry" trigger type
- Configure details:
- Registry: DockerHub
- Organization: your-org
- Image: your-image
- Tag: latest
Step 4: Add a Deploy Stage
- Click "Add Stage"
- Select "Deploy (Manifest)" for Kubernetes deployment
- Configure the stage:
- Account: my-k8s
- Manifest Source: Text
- In the Manifest YAML, paste a Kubernetes deployment definition:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: ${trigger['registry']}/${trigger['organization']}/${trigger['repository']}:${trigger['tag']}
ports:
- containerPort: 80
- Save the pipeline
Your pipeline will now automatically trigger whenever a new image with the "latest" tag is pushed to your Docker registry.
Advanced Deployment Strategies
Spinnaker excels at implementing advanced deployment strategies that minimize risk.
Blue/Green Deployment
In this strategy, you maintain two identical environments (blue and green). One serves production traffic while the other is updated.
To implement this in Spinnaker:
- Create a pipeline with two Deploy Manifest stages
- First stage deploys the new version to the inactive environment
- Add a Manual Judgment stage for verification
- Add a final stage using "Patch Manifest" to update the service to point to the new deployment
Canary Deployment
With canary deployments, you roll out changes to a small subset of users before full deployment.
Spinnaker's Kayenta service supports automated canary analysis by comparing metrics between your baseline and canary deployments.
Integration with CI Tools
Spinnaker works best when integrated with CI tools that handle building and testing. Here's how to integrate with some popular CI tools:
Jenkins Integration
- Enable the Jenkins integration:
hal config ci jenkins enable
- Add your Jenkins master:
hal config ci jenkins master add my-jenkins \
--address http://jenkins.example.com \
--username myuser \
--password
- In your pipeline, you can now add a "Jenkins" trigger that will start your pipeline when a Jenkins job completes.
GitHub Actions Integration
For GitHub Actions, you can use webhooks to trigger Spinnaker pipelines:
- Enable Echo's webhook support:
hal config features edit --webhook-notifications true
- Add a webhook trigger to your pipeline
- In your GitHub Actions workflow, add a step to call the webhook when builds complete:
- name: Trigger Spinnaker Pipeline
run: |
curl -X POST \
https://your-spinnaker-gate-url/webhooks/webhook/your-webhook-id \
-H "Content-Type: application/json" \
-d '{"artifacts": [{"name": "my-app", "version": "${{ github.sha }}", "type": "github/file"}]}'
Real-World Example: Microservices Deployment
Let's walk through a complete example of deploying a microservices application using Spinnaker.
Scenario
We have three microservices:
- Frontend UI (React)
- Authentication Service (Node.js)
- Product Service (Java Spring Boot)
Each service has its own repository and CI pipeline that builds Docker images.
Implementation
-
Create an Application in Spinnaker
- Name: e-commerce-app
- Add all team members as owners
-
Create a Shared Pipeline Template
- Define common deployment logic
- Parameterize service-specific values
-
Create Service-Specific Pipelines
-
Frontend UI Pipeline:
- Trigger on new Docker image
- Deploy to dev namespace
- Run integration tests
- Manual approval for production
- Canary deployment to production (10% traffic)
- Gradually increase traffic
-
Authentication & Product Service Pipelines:
- Similar flow but with blue/green deployment instead of canary
-
-
Create Orchestration Pipeline
- Trigger when all services are ready
- Ensure version compatibility
- Update API Gateway routes
- Run system-wide tests
- Send notifications to Slack
- Trigger when all services are ready
This approach allows you to deploy each service independently but also coordinate when needed for major releases.
Monitoring Deployments
Spinnaker integrates with popular monitoring tools to help you observe your deployments:
Prometheus Integration
- Configure Spinnaker to send metrics to Prometheus
- Create dashboards to monitor deployment health
- Set up alerts for deployment failures
Adding Automated Canary Analysis
stage:
type: canary
analysisType: realTime
canaryConfig:
lifetimeHours: 1
metricsAccountName: prometheus
storageAccountName: s3
scoreThresholds:
marginal: 75
pass: 90
metrics:
- name: latency
query: 'avg(rate(http_request_duration_seconds_sum{job="my-app"}[2m])) / avg(rate(http_request_duration_seconds_count{job="my-app"}[2m]))'
metricSourceType: prometheus
Best Practices
- Standardize Pipelines: Create templates for common patterns to ensure consistency
- Implement Controls: Add manual judgments for critical environments
- Automate Rollbacks: Configure automatic rollbacks based on monitoring
- Version Your Infrastructure: Keep Spinnaker configurations in version control
- Secure Your Pipelines: Implement role-based access control
- Monitor Pipeline Executions: Set up alerts for failed pipelines
- Optimize For Speed: Balance safety with velocity by parallelizing when possible
Troubleshooting Common Issues
Pipeline Not Triggering
- Check the trigger configuration
- Verify the Docker registry connectivity
- Check Echo service logs:
bash
kubectl logs -n spinnaker deployment/spin-echo -f
Deployment Failures
- Look at the task output in the UI
- Check Clouddriver logs:
bash
kubectl logs -n spinnaker deployment/spin-clouddriver -f
- Validate your Kubernetes manifest
Performance Issues
- Increase resource allocations:
bash
hal config deploy edit --type distributed --account-name my-k8s
hal config deploy component edit clouddriver --resources cpu=2,memory=2Gi
hal deploy apply
Summary
Spinnaker offers a powerful platform for implementing continuous delivery across multiple cloud providers. Its key strengths include:
- Visual pipeline management
- Advanced deployment strategies
- Multi-cloud support
- Integration with CI tools
- Extensible architecture
While it has a steeper learning curve than some CI/CD tools, the flexibility and capabilities it provides make it worth the investment for teams looking to implement sophisticated deployment pipelines.
Additional Resources
Exercise: Create Your First Spinnaker Pipeline
- Set up a local Spinnaker instance using Minnaker (a lightweight Spinnaker distribution)
- Create an application for a simple web service
- Build a pipeline that:
- Triggers on a Git commit
- Deploys to a dev environment
- Runs integration tests
- Requires manual approval for production
- Deploys to production using a blue/green strategy
- Trigger the pipeline and observe the deployment process
- Modify the pipeline to include a notification when deployment completes
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)