/ DevOps

Build a CI/CD pipeline on AWS using Spinnaker (multi-cloud continuous delivery platform)

Overview

In this blog, we are going learn about deploying the HelloWorld app on AWS provider using multi-cloud continuous delivery platform Spinnaker. Starting from setting up necessary configuration on AWS provider in order to spinnaker access the resources in AWS provider and also will be showing how to create a pipeline in spinnaker to deploy the demo app.

Prerequisites

  • Following components need to be setup in AWS provider.
    • AWS Account
    • VPC
    • EC2 IAM Role
    • EC2 Key Pair
    • S3 Bucket
    • Access Keys
    • Adding account to spinnaker
  • Running Spinnaker instance.

Configre AWS Provider

There are two types of accounts in the Spinnaker AWS provider; however, the distinction is not made in how they are configured using Halyard, but instead how they are configured in AWS.

  1. Managing accounts There is always exactly one managing account, this account is what Spinnaker authenticates as, and if necessary, assumes roles in the managed accounts.
  2. Managed accounts Every account that you want to modify resources in is a managed account. These will be configured to grant AssumeRole access to the managed account. This includes the managing account!
    Note: Throughout the blog, I am going to use AWS region as a us-east-1 (N.Virginia).
    AWS
    Ref: Spinnaker.io

Setup VPC:

Setup EC2 IAM Role

  • First, create an EC2 BaseIAMRole role this is the role instance is launched or deployed with spinnaker.
    IAM-BaseIAM
  • Create a managing account policy with a name of SpinnakerAssumeRolePolicy using below json script.
{
    "Version": "2012-10-17",
    "Statement": [{
        "Action": "sts:AssumeRole",
        "Resource": [
            "arn:aws:iam::${MANAGING_ACCOUNT_ID}:role/spinnakerManaged",
            "arn:aws:iam::${MANAGED_ACCOUNT_ID}:role/spinnakerManaged"
        ],
        "Effect": "Allow"
    }]
}
  • Create a user with a name of Spinnaker to authenticate with accesskeyID and secreatkeyID. Add the PowerUserAccess and SpinnakerAssumeRolePolicy to the user while creating. Remember to download the secret access key from the user and also copy the user ARN.
    Spi-User
  • Create a Spinnaker managed policy with a name of SpinnakerPassRole using below json script.
{
    "Version": "2012-10-17",
    "Statement": [{
        "Effect": "Allow",
        "Action": [ "ec2:*" ],
        "Resource": "*"
    },
    {
        "Effect": "Allow",
        "Action": "iam:PassRole",
        "Resource": "arn:aws:iam::${MANAGING_ACCOUNT_ID}:role/BaseIAMRole"
    }]
}

Ref: Github/Spinnakercourse

  • Create a SpinnakerManaged role in IAM.
    Spinnaker-Managed
  • Update the trust relationship in spinnakerManaged role using the below json script mentioning the Spinnaker user ARN which we copied priviously.
{
    "Version": "2012-10-17",
    "Statement": [{
        "Sid": "1",
        "Effect": "Allow",
        "Principal": {
            "AWS": "${AUTH_ARN}"
        },
    "Action": "sts:AssumeRole"
    }]
}

Setup EC2 Keypair

  • Here, I created a keypair with a name of SpinnakerAWS as we needed to ssh to the instance.
    AWS-Keypair
    Setup S3 Bucket
  • Spinnaker need an external storage to store the application settings and configure a pipeline, In this we are going to use S3 as a storage. Create a bucket with preferred name.
    AWS-S3
    Adding S3 Persistence Storage to Spinnaker
  • Use the below command to authenticate with AWS to access S3, use the access secret key which we got from spinnaker user.
ubuntu@spinnaker:~$ hal config storage s3 edit --access-key-id AKIAIVW7V2T4VTHXD7GQ --secret-access-key
Your AWS Secret Key.:
+ Get current deployment
  Success
+ Get persistent store
  Success
+ Edit persistent store
  Success
+ Successfully edited persistent store "s3".
ubuntu@spinnaker:~$

Add AWS Provider to Spinnaker

  • Authenticate AWS provider with access secret key.
ubuntu@spinnaker:~$ hal config provider aws edit --access-key-id AKIAIVW7V2T4VTHXD7GQ --secret-access-key
Your AWS Secret Key.. Note that if you are baking AMI's via Rosco, you may also need to set the secret key on the AWS bakery default options.:
+ Get current deployment
  Success
+ Get the aws provider
  Success
+ Edit the aws provider
  Success
+ Successfully edited provider aws.
ubuntu@spinnaker:~$
  • Add the AWS provider to spinnaker.
ubuntu@spinnaker:~$ hal config provider aws account add karthik-production --account-id 227181981646 --assume-role role/spinnakerManaged
+ Get current deployment
  Success
+ Add the karthik-production account
  Success
Problems in default.provider.aws.karthik-production:
- WARNING No validation for the AWS provider has been
  implemented.

+ Successfully added account karthik-production for provider
  aws.
ubuntu@spinnaker:~$
ubuntu@spinnaker:~$ hal config provider aws account edit karthik-production --regions us-east-1
+ Get current deployment
  Success
+ Get karthik-production account
  Success
+ Edit the karthik-production account
  Success
Problems in default.provider.aws.karthik-production:
- WARNING No validation for the AWS provider has been
  implemented.

+ Successfully edited account karthik-production for provider
  aws.
ubuntu@spinnaker:~$
ubuntu@spinnaker:~$ hal config provider aws enable
+ Get current deployment
  Success
+ Edit the aws provider
  Success
Problems in default.provider.aws.karthik-production:
- WARNING No validation for the AWS provider has been
  implemented.

+ Successfully enabled aws
ubuntu@spinnaker:~$
  • Finally run the command sudo hal deploy apply to update the changes to spinnaker.

Altering the Necessary Configuration

  • I have Helloword demo app as a Debian package on my local machine where spinnaker is running.
ubuntu@spinnaker:~/demoapp$ ls
dists  pool
ubuntu@spinnaker:~/demoapp$
  • Now I am going to sync this Debian package to S3 bucket spinnaker-repo-karthi which I created.
  • AWS CLI needs to be installed and configured in order access S3.
ubuntu@spinnaker:~/demoapp$ aws configure --profile default
AWS Access Key ID [None]: AKIAIVW7V2T4VTHXD7GQ
AWS Secret Access Key [None]: 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
Default region name [None]: us-east-1
Default output format [None]:
ubuntu@spinnaker:~/demoapp$
  • The below command will sync the local demoapp Debian package to s3.
ubuntu@spinnaker:~/demoapp$ aws s3 sync . s3://spinnaker-repo-karthi
upload: dists/xenial/InRelease to s3://spinnaker-repo-karthi/dists/xenial/InRelease
upload: dists/xenial/main/binary-amd64/Packages.bz2 to s3://spinnaker-repo-karthi/dists/xenial/main/binary-amd64/Packages.bz2
upload: dists/xenial/main/binary-amd64/Release to s3://spinnaker-repo-karthi/dists/xenial/main/binary-amd64/Release
upload: dists/xenial/main/Contents-amd64.gz to s3://spinnaker-repo-karthi/dists/xenial/main/Contents-amd64.gz
upload: dists/xenial/Release to s3://spinnaker-repo-karthi/dists/xenial/Release
upload: dists/xenial/main/binary-amd64/Packages.gz to s3://spinnaker-repo-karthi/dists/xenial/main/binary-amd64/Packages.gz
upload: dists/xenial/Release.gpg to s3://spinnaker-repo-karthi/dists/xenial/Release.gpg
upload: dists/xenial/main/binary-amd64/Packages to s3://spinnaker-repo-karthi/dists/xenial/main/binary-amd64/Packages
upload: pool/main/n/node-demo-app/node-demo-app_0.0.1_amd64.deb to s3://spinnaker-repo-karthi/pool/main/n/node-demo-app/node-demo-app_0.0.1_amd64.deb
ubuntu@spinnaker:~/demoapp$
  • As we can see below the Debian package sync to S3.
    AWS-Debian

  • Make the below Debian packages to public.

    • AmazonS3/spinnaker-repo-karthi/pool/main/n/node-demo-app/node-demo-app_0.0.1_amd64.deb
    • AmazonS3/spinnaker-repo-karthi/dists/xenial/main/binary-amd64
  • Next step, Create a two EC2 security group one is to allow external traffic to hit a demo app and then another one allow communication between the ALB and EC2.
    AWS-SG1
    AWS-SG2

  • Let's copy the Rosco file and do the necessary changes where the spinnaker is running. Basically, Rosco is a bakery which will allow spinnaker to create the image.

    • cp /opt/rosco/config/rosco.yml .hal/default/profiles
    • Edit the rosco.yml with the below changes.
    • Change the configDir: /opt/rosco/config/packer/
    • Add the debian repository as a S3 debianRepository: https://s3.amazonaws.com/spinnaker-debian-repo-jorn/ xenial main.
    • Enable the AWS provider as true enabled: true
    • Add the below script to build a image for the app to run on and also edit the source AMI id for the respective region.
    - baseImage:
          id: ubuntu xenial
          shortDescription: v16.04
          detailedDescription: Ubuntu Xenial 16.04 LTS
          packageType: deb
          # You can specify the templateFile used for this baseImage.
          # If not specified, the default templateFile will be used.
          templateFile: aws-ebs.json
        virtualizationSettings:
        - region: us-east-1
          virtualizationType: hvm
          instanceType: t2.micro
          sourceAmi: ami-43a15f3e
          sshUserName: ubuntu
          spotPrice: 0
          spotPriceAutoProduct: Linux/UNIX (Amazon VPC)
    

    Ref: Github/Spinnakercourse

    Let's Deploy the Demoapp using Spinnaker Pipeline

  • Create a demo application in spinnaker.
    CreateApplication

  • Now we need to create a load balancer selecting the VPC and security group accordingly which we created in AWS account.
    Select-ALB
    Lb1-1
    lb2

  • Next step we are going to create a pipeline with bake and deploy stages.
    *First stage create a bake pipeline mentioning the package name.
    *Second stage create Deploy section with necessary settings enabled. Need to configure deployment cluster as well as below.
    Pipeline
    Add-stage
    Configure-deploymnet-clus
    clus
    clus-1
    cluster4

  • Now we are good to go and start the manual execution of the pipeline.
    Running-a-bake
    deply-success

  • The HelloWorld app has been deployed successfully on AWS provider using spinnaker pipeline. Please find the below running EC2 instance where our demo app deployed which is launched by spinnaker.
    Helloworlapp-EC2

  • Let's try accessing the HelloWorld app using ELB DNS name demoapp-1886362877.us-east-1.elb.amazonaws.com.
    Elb-Dns-link