{"__v":16,"_id":"56ccf35a8c4a331d002c1e21","category":{"__v":2,"_id":"56ccf29a431ada1f00e85aae","pages":["56ccf3498c4a331d002c1e1e","56ccf35a8c4a331d002c1e21"],"project":"55c6bec1b9aa4e0d0016c2c3","version":"55c6bec1b9aa4e0d0016c2c6","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2016-02-24T00:00:26.717Z","from_sync":false,"order":4,"slug":"code-labs","title":"Code Labs"},"parentDoc":null,"project":"55c6bec1b9aa4e0d0016c2c3","user":"55c8f42fb79cb30d005b3e48","version":{"__v":8,"_id":"55c6bec1b9aa4e0d0016c2c6","project":"55c6bec1b9aa4e0d0016c2c3","createdAt":"2015-08-09T02:45:21.683Z","releaseDate":"2015-08-09T02:45:21.683Z","categories":["55c6bec2b9aa4e0d0016c2c7","56c14bc5826df10d00e82230","56cceed8723ad71d00cae46c","56ccf29a431ada1f00e85aae","56ccf3c28fa8b01b00b82018","56ce1e6ee538330b0021ac5d","56f97e9a4c612020008f2eaf","5734fafd146eb82000597261"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"1.0.0","version":"1.0"},"updates":["5745ac20a488e817005418df","5745ad8711628d0e009a78cd","57f5686aed06330e00c0cf2f"],"next":{"pages":[],"description":""},"createdAt":"2016-02-24T00:03:38.334Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":2,"body":"In this codelab, you will create a cohesive workflow which takes source code and builds, tests and promotes it to production. You can also watch a videos of this codelab in this [Youtube playlist](https://www.youtube.com/watch?v=N9VnJlKn734&list=PL4yLrwUObNkttE526AAj_ykc5UlIPjz8m&index=1).\n\nThis will be accomplished via 3 pipelines:\n\n* Bake & Deploy to Test\n* Validate Test\n* Promote to Prod\n\nYou will be using a custom-built image that includes sample application source code, a Jenkins instance, a Debian repository (aptly) and a Spinnaker instance.\n\nThis codelab is an extension of the [Hello World Deployment](http://spinnaker.io/documentation/hello-spinnaker.html) tutorial. It runs specifically on the Google Cloud Platform, and requires a billing-enabled GCP project.\n\n## Part 0: Environment Setup\n\n### Install gcloud\n\nIf you have `gcloud` installed, skip to the next section, “[Provision an instance of Spinnaker](#provision-an-instance-of-spinnaker-and-jenkins)”.\n\nInstall `gcloud` by running the following command and following through the prompts:\n\n    curl https://sdk.cloud.google.com | bash\n\nAuthenticate `gcloud` to your account with your email address:\n\n    gcloud auth login <your email address>\n\n### Provision an instance of Spinnaker and Jenkins\n\nWe’ve created a single GCE image that includes Spinnaker, Jenkins, and aptly, along with embedded startup scripts that configure everything together for you. Create an instance of this image by running the following commands.\n\nFill in your project for `$MY_PROJECT`\n\n    MY_PROJECT=<your project>\n    INSTANCE_NAME=spinnaker-codelab\n    ZONE=us-east1-b\n\n    gcloud compute instances create $INSTANCE_NAME \\\n        --project $MY_PROJECT \\\n        --zone $ZONE \\\n        --image spinnaker-codelab \\\n        --image-project marketplace-spinnaker-release \\\n        --machine-type n1-highmem-4 \\\n        --scopes compute-rw,storage-full \\\n        --metadata startup-script=/opt/spinnaker/install/first_codelab_boot.sh\n\nSpinnaker will take a few minutes to auto configure and start up. Take 3 minutes to skim through Part 1 of this codelab below...\n\nOpen an SSH tunnel through which your local workstation will connect to Spinnaker:\n\n    gcloud compute ssh $INSTANCE_NAME \\\n        --project $MY_PROJECT \\\n        --zone $ZONE \\\n        --ssh-flag=\"-L 8084:localhost:8084\" \\\n        --ssh-flag=\"-L 8087:localhost:8087\" \\\n        --ssh-flag=\"-L 9000:localhost:9000\" \\\n        --ssh-flag=\"-L 9090:localhost:9090\"\n\n\n## Part 1: Bake & Deploy to Test\n\nIn this first exercise, you’ll set up a pipeline, named Bake & Deploy to Test, which builds a GCE image, deploys it as a server group to a test cluster, then destroys the previous server group in that cluster (also called the \"Highlander\" strategy). The pipeline is triggered by a Jenkins continuous integration job.\n\nThe workflow is shown in the figure below.\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/WNV4FbeISFKH9jOWTiAT_1-workflow.png\",\n        \"1-workflow.png\",\n        \"792\",\n        \"340\",\n        \"#7bb46e\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n### Create a Spinnaker Application\n\nNavigate to Spinnaker at [http://localhost:9000](http://localhost:9000).\n\nFrom the Spinnaker home page, create a new Spinnaker Application by clicking on the *Actions* drop down at the upper right and clicking on *Create Application*.\n\nIn the *New Application* dialog:\n\n* Enter \"codelab\" for *Name*.\n* Enter your email for *Owner Email*.\n* Click in the *Accounts* field and choose “my-google-account”.\n* Click the *Create* button.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/s0D5VeZtRRuSpDHkckhy_1-new-application.png\",\n        \"1-new-application.png\",\n        \"591\",\n        \"561\",\n        \"#ea542a\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n### Create a Load Balancer\n\nFirst we create a load balancer for your cluster. Navigate to the LOAD BALANCERS tab and click the *Create Load Balancer* button:\n\n* Enter “test” for *Stack*.\n* In the Listener section, set the *Port Range* to be 8080, as that’s the port that our sample application listens on.\n* In the Health Check section, enter “8080” for *Port* and “/hello” for *Path*.\n* Optionally, enter 1 for all advanced settings values so server groups report healthy much faster.\n* Click the *Create* button.\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/3fcK8PNLTDCYWlAEQPhZ_1-create-lb.png\",\n        \"1-create-lb.png\",\n        \"901\",\n        \"1031\",\n        \"#3c5369\",\n        \"\"\n      ],\n      \"sizing\": \"smart\"\n    }\n  ]\n}\n[/block]\n\n### Setup Pipeline: Bake & Deploy to Test Pipeline\n\nThe purpose of this pipeline is to generate a GCE image from a package, and then deploy the image on server groups in the test cluster. We want this pipeline to be kicked off every time the Jenkins continuous integration job completes.\n\nCreate a new pipeline by navigating to the PIPELINES tab and clicking the *New* button\n\n* Name the pipeline “Bake & Deploy to Test”.\n* Click the *Create Pipeline* button.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/3hKr0J8zR1aFbdKXSyfL_1-new-pipeline.png\",\n        \"1-new-pipeline.png\",\n        \"596\",\n        \"266\",\n        \"#2c98b6\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n#### Configure the pipeline\n\nThe first step in setting up a pipeline is to configure the pipeline. In particular, we need to specify an automated trigger that will kick off the pipeline.\n\nWe want this pipeline to kick off every time our Jenkins job completes. In the Automated Triggers section of the pipelines form:\n\n* Click *Add Trigger*.\n* Select “Jenkins” from the drop down menu for *Type*.\n* Specify “CodelabJenkins” for the *Master* Jenkins instance.\n* Specify “Hello-Build” for *Job*.\n\nRefer to the figure below for an illustration of what the pipeline’s Configuration form looks like when we’re done.\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/3PwpwpSfQPiiAIGePCea_1-configuration.png\",\n        \"1-configuration.png\",\n        \"1146\",\n        \"926\",\n        \"#d9592f\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n#### Setup Bake stage\n\nThe purpose of our “Bake” stage is to create a GCE image with the package that was built by the Jenkins job that triggered this pipeline.\n\n* Click *Add stage*.\n* Select “Bake” in the *Type* drop down.\n* Enter the Debian package you wish to include, “hello-karyon-rxnetty”, in the *Package* field.\n* Select \"trusty\" as the *Base OS*.\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/LY9Abn9rSP60PxFlT0RI_1-bake.png\",\n        \"1-bake.png\",\n        \"1141\",\n        \"861\",\n        \"#3a87b1\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n#### Setup Deploy stage\n\nThe purpose of the “Deploy” stage is to take the GCE image constructed in the “Bake” stage and deploy it into a test environment.\n\n* Click *Add stage*.\n* Select “Deploy” in the *Type* drop down.\n* In the *Server group* section, click *Add server group*.\n* In the dialog that appears, click *Continue without a template*.\n* In the Basic Settings section, enter “test” in the *Stack* field.\n* In the Load Balancers section, add your load balancer (\"codelab-test\").\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/Vi48FhX6TEq0fumXuPJR_1-deploy-basic.png\",\n        \"1-deploy-basic.png\",\n        \"901\",\n        \"1036\",\n        \"#3c556e\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\nSecurity groups map to GCP firewall rules, along with the use of target tags to route traffic. There are default firewall rules in place which are sufficient for our use here.\n\n* Click on the *Instance Type* tab on the left.\n* In the Instance Type section, choose “f1-micro” in the drop down.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/3U0D6CA1R5uxxxLC0nAj_1-deploy-instance.png\",\n        \"1-deploy-instance.png\",\n        \"901\",\n        \"1036\",\n        \"#3c5168\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\n* In the Capacity section, leave 1 as the number of instances and click *Add*.\n\n#### Destroy previous server group\n\nIn this tutorial use case, on successive deployments of new server groups to the test cluster, we don’t need the previous server group anymore.\n\n* Click *Add Stage*.\n* Select “Destroy Server Group” for *Type*.\n* Check *us-east1*, the region of the previous test server group that you want to destroy.\n* Enter codelab-test for the *Cluster*.\n* Select “Previous Server Group” for *Target*.\n* Click *Save Changes*.\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/4LywrCmwRf62FTxo1idc_1-destroy.png\",\n        \"1-destroy.png\",\n        \"1141\",\n        \"846\",\n        \"#e64518\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\nThe pipeline is now complete. Take a moment to review the stages of this pipeline that you just built.\n\n### Trying it out\n\nNow let’s run this pipeline. We trigger it by manually running a Build of the Jenkins job.\n\n* Navigate to your Jenkins console at [http://localhost:9090](http://localhost:9090).\n  * Username: admin\n  * Password: admin\n* Click on the \"Hello-Build\" job.\n* Click *Build Now*.\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/mRzrGi3xRBC0AnQBnIU9_1-jenkins.png\",\n        \"1-jenkins.png\",\n        \"811\",\n        \"511\",\n        \"#b94c44\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\nIt may take a while for the polling to trigger the job, but soon in the PIPELINES tab you can see progress, status and details.\n\nThe first time this pipeline is run, the Destroy Server Group stage will fail, because the selector for “Previous Server Group” will find nothing (no server groups presently in the test cluster). The Deploy stage, however, does succeed, so a test cluster will be created.\n\nTry running it again, either by running another Build of the Jenkins job, or by manually triggering from the PIPELINES tab (click *Start Manual Execution*). It will succeed all the way, and your pipeline execution details will look like below:\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/l0YV502iSb2vru5qKlbO_1-pipelines.png\",\n        \"1-pipelines.png\",\n        \"1408\",\n        \"607\",\n        \"#3e596c\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\nYou can now see in the CLUSTERS tab that a new server group has been deployed to the test cluster, and the previous server group is destroyed (i.e. does not exist).\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/3BMTRHEQQ2NxkUEszzAL_1-clusters.png\",\n        \"1-clusters.png\",\n        \"1410\",\n        \"415\",\n        \"#3b566e\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\nYou can also introspect server group details by clicking on a server group. In the details panel on the right, you can see under the PACKAGE section details about how we built this server group. Information like package name, build number, down to commit hash and link to the Jenkins job.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/RcCrm0gSua2rLPBl5tWx_1-cluster-info.png\",\n        \"1-cluster-info.png\",\n        \"305\",\n        \"297\",\n        \"#3a4e67\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n## Part 2: Validate Test\n\nThe second pipeline, named “Validate Test”, is a simple one-stage placeholder to represent some gating function before pushing to prod.\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/BeAjt9mQHoSel669bsIA_2-workflow.png\",\n        \"2-workflow.png\",\n        \"928\",\n        \"291\",\n        \"#90a7b7\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\nFurthermore, we configure the prod deployment to implement the red/black strategy (a.k.a. blue/green), which means that upon verifying health of the new server group it will immediately disable the previous server group in the same cluster. Here we disable rather than destroy, so that rollbacks can be quickly accomplished simply by re-enabling the old server group.\n\n### Setup Pipeline: Validate Test\n\nCreate a new pipeline by navigating to the PIPELINES tab and clicking *Configure*, then *Create New ...*\n\n* Name the pipeline “Validate Test”.\n* Click the *Create Pipeline* button.\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/bsa7AMLJTMWodTBmCjyV_2-new-pipeline-1.png\",\n        \"2-new-pipeline-1.png\",\n        \"596\",\n        \"301\",\n        \"#2d96b2\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n#### Configure the pipeline\n\nWe want this pipeline to kick off when the Bake & Deploy to Test pipeline completes.\n\n* Click *Add Trigger*.\n* Select “Pipeline” from the drop down menu for *Type*.\n* Select your application.\n* Select the “Bake & Deploy to Test” pipeline.\n* Check “successful”.\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/Ix2uVZ9PQHe8oxtr9qdX_2-configuration-1.png\",\n        \"2-configuration-1.png\",\n        \"1136\",\n        \"916\",\n        \"#39657d\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n#### Setup Manual Judgment stage\n\nWe stop and wait for human confirmation to continue:\n\n* Click *Add stage*.\n* Select “Manual Judgment” in the *Type* drop down.\n* Specify *Instructions*, for example “Validate the test cluster”.\n* Click *Save Changes*.\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/z3bZS1QkTbONg8PqqCDL_2-manual-judgment.png\",\n        \"2-manual-judgment.png\",\n        \"1136\",\n        \"836\",\n        \"#378ab1\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n## Part 3: Promote to Prod\n\nThe third pipeline, “Promote to Prod”, takes the image that was deployed in the test cluster, and deploys that image to the prod environment, thereby promoting it.\n\n### Create a Load Balancer\n\nWe create a load balancer for the prod cluster. Navigate to the LOAD BALANCERS tab and click the *Create Load Balancer* button:\n\n* Enter “prod” for *Stack*.\n* In the Listener section, set the *Port Range* to 8080.\n* In the Health Check section, enter “8080” for *Port* and “/hello” for *Path*.\n* Optionally, enter 1 for all health check values.\n* Click the *Create* button.\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/TDqDoZ6yRLeWjTVtzRv5_2-create-lb.png\",\n        \"2-create-lb.png\",\n        \"901\",\n        \"1031\",\n        \"#3b5269\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n### Setup Pipeline: Promote to Prod Pipeline\n\nCreate a new pipeline by navigating to the PIPELINES tab and clicking *Configure*, then *Create New ...*\n\n* Name the pipeline “Promote to Prod”.\n* Click the *Create Pipeline* button.\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/KRlSLWz6SPqI27WgJX0K_2-new-pipeline-2.png\",\n        \"2-new-pipeline-2.png\",\n        \"591\",\n        \"301\",\n        \"#2f95b3\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n#### Configure the pipeline\n\nWe want this pipeline to kick off when the Validate Test pipeline completes.\n\n* Click *Add Trigger*.\n* Select “Pipeline” from the drop down menu for *Type*.\n* Select your application.\n* Select the “Validate Test” pipeline.\n* Check “successful”.\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/9JDp2SAQgSrGi1E3cgIF_2-configuration-2.png\",\n        \"2-configuration-2.png\",\n        \"1136\",\n        \"916\",\n        \"#39657c\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n#### Setup Find Image stage\n\nIn the “Find Image” stage, we select the image that was deployed in the test cluster.\n\nClick the *Add stage* button:\n\n* Select “Find Image” for the stage *Type*.\n* Check the region of the test server group to pick the image from.\n* Enter codelab-test for the *Cluster*.\n* Choose “Newest” for the *Server Group Selection*.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/TOLJThYDRa2Bygc32oCY_2-find-image.png\",\n        \"2-find-image.png\",\n        \"1151\",\n        \"816\",\n        \"#e95328\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n#### Setup the Deploy stage\n\nWe deploy the image that was picked, to the prod cluster.\n\n* Click *Add stage*.\n* Select “Deploy” in the *Type* drop down.\n* In the *Server group* section, click *Add server group*.\n* In the dialog that appears, click *Continue without a template*.\n* In the Basic Settings section, enter “prod” in the *Stack* field.\n* For Strategy, select “Red/Black”.\n* In the Load Balancers section, add your load balancer (\"codelab-prod\").\n* and click the *Instance Type* tab on the left.\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/yoGIsPhRQYGJtRqrkNqE_2-deploy-basic.png\",\n        \"2-deploy-basic.png\",\n        \"896\",\n        \"1036\",\n        \"#3c5770\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n* In the Instance Type section, choose “f1-micro” in the drop down.\n* In the Capacity section, leave 1 as the number of instances and click *Add*.\n* Click *Save Changes* to save your prod pipeline.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/NH2VJThfSwpYlbYM1Bji_2-deploy-type.png\",\n        \"2-deploy-type.png\",\n        \"901\",\n        \"1036\",\n        \"#3c5168\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\n\n\n### Trying it out\n\nNow let’s run through it all. Run a Build in Jenkins.\n\nWhen the Bake & Deploy to Test pipeline completes, the Validate Test pipeline will trigger and wait for user input.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/Pgq9zrZ7RRr4byBPh8kA_2-validation.png\",\n        \"2-validation.png\",\n        \"1413\",\n        \"924\",\n        \"#3b566f\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\nClick *Continue*. This will trigger the Promote to Prod pipeline:\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/V3xrMZLoQzWnEA1W3d04_2-pipelines-all.png\",\n        \"2-pipelines-all.png\",\n        \"1411\",\n        \"1010\",\n        \"#3e596c\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\nIn the CLUSTERS tab, you can see that a server group has been deployed to the prod cluster.\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/H72xOv6DQz6HYA2kHamc_2-clusters.png\",\n        \"2-clusters.png\",\n        \"1411\",\n        \"561\",\n        \"#3b566d\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\nBecause we selected the red/black deployment strategy for the deployment, there should always be only one enabled/active server group resident in the prod cluster cluster, with previous ones disabled (grey), even after successive runs of this pipeline. Try it out by manually invoking the promotion pipeline again.\n\n\n## Extra Stuff\n\n### Roll back\n\nSometimes things go wrong and you need to roll prod back to the previous release. We employed the red/black strategy, which disables the previous server group. In practice, this is disassociating the server group from the load balancer so it takes no traffic, while keeping the nodes in the server group up, standing by.\n\nTo roll back back to the previous server group, first kick off another instance of the Promote to Prod pipeline so that you have a previous disabled server group in the PROD cluster to roll back to. When this pipeline completes, navigate to the CLUSTERS tab and click the active server group.\n\n* In the *Server Group Actions* drop down on the right, click *Rollback*.\n* In the dialog that appears, select the server group you would like restore (roll back to).\n* Type the name of the account to confirm your action.\n* Click *Submit*.\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/gPu9PuIQQySWvBwzwhoE_3-rollback.png\",\n        \"3-rollback.png\",\n        \"596\",\n        \"321\",\n        \"#df5733\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\nWhen the task completes (you can check progress in the TASKS tab), you will see that the specified server group is now the active one, while the previous one is disabled (grey).\n\n### Triggering the Jenkins job by changing source\n\nSo far you’ve been triggering the Jenkins job manually over unchanging source code. Consequently, you’ll notice that all server groups point back to the same Jenkins job. This is because Spinnaker can detect whether a re-bake is necessary, and because there were no changes, it simply returned the same image.\n\nThe image you’re using does have Jenkins polling for updates to the local git repo. If you trigger the Jenkins job as a result of code change, the image that’s built will be different, and you’ll see the build info change throughout the entire pipeline chain.\n\nYou can update source by doing the following from your ssh window:\n\n    sudo su jenkins\n    cd /var/lib/jenkins/hello-karyon-rxnetty\n    vi build.gradle\n    # Change the number on the “release” line.\n    git commit -a -m \"Bump release number\"\n\nYou’ll see the whole sequence again, but with a key difference: a new image will be baked, and the server groups deployed as a result will show different build info.","excerpt":"","slug":"from-source-to-prod","type":"basic","title":"Google Source To Prod"}

Google Source To Prod


In this codelab, you will create a cohesive workflow which takes source code and builds, tests and promotes it to production. You can also watch a videos of this codelab in this [Youtube playlist](https://www.youtube.com/watch?v=N9VnJlKn734&list=PL4yLrwUObNkttE526AAj_ykc5UlIPjz8m&index=1). This will be accomplished via 3 pipelines: * Bake & Deploy to Test * Validate Test * Promote to Prod You will be using a custom-built image that includes sample application source code, a Jenkins instance, a Debian repository (aptly) and a Spinnaker instance. This codelab is an extension of the [Hello World Deployment](http://spinnaker.io/documentation/hello-spinnaker.html) tutorial. It runs specifically on the Google Cloud Platform, and requires a billing-enabled GCP project. ## Part 0: Environment Setup ### Install gcloud If you have `gcloud` installed, skip to the next section, “[Provision an instance of Spinnaker](#provision-an-instance-of-spinnaker-and-jenkins)”. Install `gcloud` by running the following command and following through the prompts: curl https://sdk.cloud.google.com | bash Authenticate `gcloud` to your account with your email address: gcloud auth login <your email address> ### Provision an instance of Spinnaker and Jenkins We’ve created a single GCE image that includes Spinnaker, Jenkins, and aptly, along with embedded startup scripts that configure everything together for you. Create an instance of this image by running the following commands. Fill in your project for `$MY_PROJECT` MY_PROJECT=<your project> INSTANCE_NAME=spinnaker-codelab ZONE=us-east1-b gcloud compute instances create $INSTANCE_NAME \ --project $MY_PROJECT \ --zone $ZONE \ --image spinnaker-codelab \ --image-project marketplace-spinnaker-release \ --machine-type n1-highmem-4 \ --scopes compute-rw,storage-full \ --metadata startup-script=/opt/spinnaker/install/first_codelab_boot.sh Spinnaker will take a few minutes to auto configure and start up. Take 3 minutes to skim through Part 1 of this codelab below... Open an SSH tunnel through which your local workstation will connect to Spinnaker: gcloud compute ssh $INSTANCE_NAME \ --project $MY_PROJECT \ --zone $ZONE \ --ssh-flag="-L 8084:localhost:8084" \ --ssh-flag="-L 8087:localhost:8087" \ --ssh-flag="-L 9000:localhost:9000" \ --ssh-flag="-L 9090:localhost:9090" ## Part 1: Bake & Deploy to Test In this first exercise, you’ll set up a pipeline, named Bake & Deploy to Test, which builds a GCE image, deploys it as a server group to a test cluster, then destroys the previous server group in that cluster (also called the "Highlander" strategy). The pipeline is triggered by a Jenkins continuous integration job. The workflow is shown in the figure below. [block:image] { "images": [ { "image": [ "https://files.readme.io/WNV4FbeISFKH9jOWTiAT_1-workflow.png", "1-workflow.png", "792", "340", "#7bb46e", "" ] } ] } [/block] ### Create a Spinnaker Application Navigate to Spinnaker at [http://localhost:9000](http://localhost:9000). From the Spinnaker home page, create a new Spinnaker Application by clicking on the *Actions* drop down at the upper right and clicking on *Create Application*. In the *New Application* dialog: * Enter "codelab" for *Name*. * Enter your email for *Owner Email*. * Click in the *Accounts* field and choose “my-google-account”. * Click the *Create* button. [block:image] { "images": [ { "image": [ "https://files.readme.io/s0D5VeZtRRuSpDHkckhy_1-new-application.png", "1-new-application.png", "591", "561", "#ea542a", "" ] } ] } [/block] ### Create a Load Balancer First we create a load balancer for your cluster. Navigate to the LOAD BALANCERS tab and click the *Create Load Balancer* button: * Enter “test” for *Stack*. * In the Listener section, set the *Port Range* to be 8080, as that’s the port that our sample application listens on. * In the Health Check section, enter “8080” for *Port* and “/hello” for *Path*. * Optionally, enter 1 for all advanced settings values so server groups report healthy much faster. * Click the *Create* button. [block:image] { "images": [ { "image": [ "https://files.readme.io/3fcK8PNLTDCYWlAEQPhZ_1-create-lb.png", "1-create-lb.png", "901", "1031", "#3c5369", "" ], "sizing": "smart" } ] } [/block] ### Setup Pipeline: Bake & Deploy to Test Pipeline The purpose of this pipeline is to generate a GCE image from a package, and then deploy the image on server groups in the test cluster. We want this pipeline to be kicked off every time the Jenkins continuous integration job completes. Create a new pipeline by navigating to the PIPELINES tab and clicking the *New* button * Name the pipeline “Bake & Deploy to Test”. * Click the *Create Pipeline* button. [block:image] { "images": [ { "image": [ "https://files.readme.io/3hKr0J8zR1aFbdKXSyfL_1-new-pipeline.png", "1-new-pipeline.png", "596", "266", "#2c98b6", "" ] } ] } [/block] #### Configure the pipeline The first step in setting up a pipeline is to configure the pipeline. In particular, we need to specify an automated trigger that will kick off the pipeline. We want this pipeline to kick off every time our Jenkins job completes. In the Automated Triggers section of the pipelines form: * Click *Add Trigger*. * Select “Jenkins” from the drop down menu for *Type*. * Specify “CodelabJenkins” for the *Master* Jenkins instance. * Specify “Hello-Build” for *Job*. Refer to the figure below for an illustration of what the pipeline’s Configuration form looks like when we’re done. [block:image] { "images": [ { "image": [ "https://files.readme.io/3PwpwpSfQPiiAIGePCea_1-configuration.png", "1-configuration.png", "1146", "926", "#d9592f", "" ] } ] } [/block] #### Setup Bake stage The purpose of our “Bake” stage is to create a GCE image with the package that was built by the Jenkins job that triggered this pipeline. * Click *Add stage*. * Select “Bake” in the *Type* drop down. * Enter the Debian package you wish to include, “hello-karyon-rxnetty”, in the *Package* field. * Select "trusty" as the *Base OS*. [block:image] { "images": [ { "image": [ "https://files.readme.io/LY9Abn9rSP60PxFlT0RI_1-bake.png", "1-bake.png", "1141", "861", "#3a87b1", "" ] } ] } [/block] #### Setup Deploy stage The purpose of the “Deploy” stage is to take the GCE image constructed in the “Bake” stage and deploy it into a test environment. * Click *Add stage*. * Select “Deploy” in the *Type* drop down. * In the *Server group* section, click *Add server group*. * In the dialog that appears, click *Continue without a template*. * In the Basic Settings section, enter “test” in the *Stack* field. * In the Load Balancers section, add your load balancer ("codelab-test"). [block:image] { "images": [ { "image": [ "https://files.readme.io/Vi48FhX6TEq0fumXuPJR_1-deploy-basic.png", "1-deploy-basic.png", "901", "1036", "#3c556e", "" ] } ] } [/block] Security groups map to GCP firewall rules, along with the use of target tags to route traffic. There are default firewall rules in place which are sufficient for our use here. * Click on the *Instance Type* tab on the left. * In the Instance Type section, choose “f1-micro” in the drop down. [block:image] { "images": [ { "image": [ "https://files.readme.io/3U0D6CA1R5uxxxLC0nAj_1-deploy-instance.png", "1-deploy-instance.png", "901", "1036", "#3c5168", "" ] } ] } [/block] * In the Capacity section, leave 1 as the number of instances and click *Add*. #### Destroy previous server group In this tutorial use case, on successive deployments of new server groups to the test cluster, we don’t need the previous server group anymore. * Click *Add Stage*. * Select “Destroy Server Group” for *Type*. * Check *us-east1*, the region of the previous test server group that you want to destroy. * Enter codelab-test for the *Cluster*. * Select “Previous Server Group” for *Target*. * Click *Save Changes*. [block:image] { "images": [ { "image": [ "https://files.readme.io/4LywrCmwRf62FTxo1idc_1-destroy.png", "1-destroy.png", "1141", "846", "#e64518", "" ] } ] } [/block] The pipeline is now complete. Take a moment to review the stages of this pipeline that you just built. ### Trying it out Now let’s run this pipeline. We trigger it by manually running a Build of the Jenkins job. * Navigate to your Jenkins console at [http://localhost:9090](http://localhost:9090). * Username: admin * Password: admin * Click on the "Hello-Build" job. * Click *Build Now*. [block:image] { "images": [ { "image": [ "https://files.readme.io/mRzrGi3xRBC0AnQBnIU9_1-jenkins.png", "1-jenkins.png", "811", "511", "#b94c44", "" ] } ] } [/block] It may take a while for the polling to trigger the job, but soon in the PIPELINES tab you can see progress, status and details. The first time this pipeline is run, the Destroy Server Group stage will fail, because the selector for “Previous Server Group” will find nothing (no server groups presently in the test cluster). The Deploy stage, however, does succeed, so a test cluster will be created. Try running it again, either by running another Build of the Jenkins job, or by manually triggering from the PIPELINES tab (click *Start Manual Execution*). It will succeed all the way, and your pipeline execution details will look like below: [block:image] { "images": [ { "image": [ "https://files.readme.io/l0YV502iSb2vru5qKlbO_1-pipelines.png", "1-pipelines.png", "1408", "607", "#3e596c", "" ] } ] } [/block] You can now see in the CLUSTERS tab that a new server group has been deployed to the test cluster, and the previous server group is destroyed (i.e. does not exist). [block:image] { "images": [ { "image": [ "https://files.readme.io/3BMTRHEQQ2NxkUEszzAL_1-clusters.png", "1-clusters.png", "1410", "415", "#3b566e", "" ] } ] } [/block] You can also introspect server group details by clicking on a server group. In the details panel on the right, you can see under the PACKAGE section details about how we built this server group. Information like package name, build number, down to commit hash and link to the Jenkins job. [block:image] { "images": [ { "image": [ "https://files.readme.io/RcCrm0gSua2rLPBl5tWx_1-cluster-info.png", "1-cluster-info.png", "305", "297", "#3a4e67", "" ] } ] } [/block] ## Part 2: Validate Test The second pipeline, named “Validate Test”, is a simple one-stage placeholder to represent some gating function before pushing to prod. [block:image] { "images": [ { "image": [ "https://files.readme.io/BeAjt9mQHoSel669bsIA_2-workflow.png", "2-workflow.png", "928", "291", "#90a7b7", "" ] } ] } [/block] Furthermore, we configure the prod deployment to implement the red/black strategy (a.k.a. blue/green), which means that upon verifying health of the new server group it will immediately disable the previous server group in the same cluster. Here we disable rather than destroy, so that rollbacks can be quickly accomplished simply by re-enabling the old server group. ### Setup Pipeline: Validate Test Create a new pipeline by navigating to the PIPELINES tab and clicking *Configure*, then *Create New ...* * Name the pipeline “Validate Test”. * Click the *Create Pipeline* button. [block:image] { "images": [ { "image": [ "https://files.readme.io/bsa7AMLJTMWodTBmCjyV_2-new-pipeline-1.png", "2-new-pipeline-1.png", "596", "301", "#2d96b2", "" ] } ] } [/block] #### Configure the pipeline We want this pipeline to kick off when the Bake & Deploy to Test pipeline completes. * Click *Add Trigger*. * Select “Pipeline” from the drop down menu for *Type*. * Select your application. * Select the “Bake & Deploy to Test” pipeline. * Check “successful”. [block:image] { "images": [ { "image": [ "https://files.readme.io/Ix2uVZ9PQHe8oxtr9qdX_2-configuration-1.png", "2-configuration-1.png", "1136", "916", "#39657d", "" ] } ] } [/block] #### Setup Manual Judgment stage We stop and wait for human confirmation to continue: * Click *Add stage*. * Select “Manual Judgment” in the *Type* drop down. * Specify *Instructions*, for example “Validate the test cluster”. * Click *Save Changes*. [block:image] { "images": [ { "image": [ "https://files.readme.io/z3bZS1QkTbONg8PqqCDL_2-manual-judgment.png", "2-manual-judgment.png", "1136", "836", "#378ab1", "" ] } ] } [/block] ## Part 3: Promote to Prod The third pipeline, “Promote to Prod”, takes the image that was deployed in the test cluster, and deploys that image to the prod environment, thereby promoting it. ### Create a Load Balancer We create a load balancer for the prod cluster. Navigate to the LOAD BALANCERS tab and click the *Create Load Balancer* button: * Enter “prod” for *Stack*. * In the Listener section, set the *Port Range* to 8080. * In the Health Check section, enter “8080” for *Port* and “/hello” for *Path*. * Optionally, enter 1 for all health check values. * Click the *Create* button. [block:image] { "images": [ { "image": [ "https://files.readme.io/TDqDoZ6yRLeWjTVtzRv5_2-create-lb.png", "2-create-lb.png", "901", "1031", "#3b5269", "" ] } ] } [/block] ### Setup Pipeline: Promote to Prod Pipeline Create a new pipeline by navigating to the PIPELINES tab and clicking *Configure*, then *Create New ...* * Name the pipeline “Promote to Prod”. * Click the *Create Pipeline* button. [block:image] { "images": [ { "image": [ "https://files.readme.io/KRlSLWz6SPqI27WgJX0K_2-new-pipeline-2.png", "2-new-pipeline-2.png", "591", "301", "#2f95b3", "" ] } ] } [/block] #### Configure the pipeline We want this pipeline to kick off when the Validate Test pipeline completes. * Click *Add Trigger*. * Select “Pipeline” from the drop down menu for *Type*. * Select your application. * Select the “Validate Test” pipeline. * Check “successful”. [block:image] { "images": [ { "image": [ "https://files.readme.io/9JDp2SAQgSrGi1E3cgIF_2-configuration-2.png", "2-configuration-2.png", "1136", "916", "#39657c", "" ] } ] } [/block] #### Setup Find Image stage In the “Find Image” stage, we select the image that was deployed in the test cluster. Click the *Add stage* button: * Select “Find Image” for the stage *Type*. * Check the region of the test server group to pick the image from. * Enter codelab-test for the *Cluster*. * Choose “Newest” for the *Server Group Selection*. [block:image] { "images": [ { "image": [ "https://files.readme.io/TOLJThYDRa2Bygc32oCY_2-find-image.png", "2-find-image.png", "1151", "816", "#e95328", "" ] } ] } [/block] #### Setup the Deploy stage We deploy the image that was picked, to the prod cluster. * Click *Add stage*. * Select “Deploy” in the *Type* drop down. * In the *Server group* section, click *Add server group*. * In the dialog that appears, click *Continue without a template*. * In the Basic Settings section, enter “prod” in the *Stack* field. * For Strategy, select “Red/Black”. * In the Load Balancers section, add your load balancer ("codelab-prod"). * and click the *Instance Type* tab on the left. [block:image] { "images": [ { "image": [ "https://files.readme.io/yoGIsPhRQYGJtRqrkNqE_2-deploy-basic.png", "2-deploy-basic.png", "896", "1036", "#3c5770", "" ] } ] } [/block] * In the Instance Type section, choose “f1-micro” in the drop down. * In the Capacity section, leave 1 as the number of instances and click *Add*. * Click *Save Changes* to save your prod pipeline. [block:image] { "images": [ { "image": [ "https://files.readme.io/NH2VJThfSwpYlbYM1Bji_2-deploy-type.png", "2-deploy-type.png", "901", "1036", "#3c5168", "" ] } ] } [/block] ### Trying it out Now let’s run through it all. Run a Build in Jenkins. When the Bake & Deploy to Test pipeline completes, the Validate Test pipeline will trigger and wait for user input. [block:image] { "images": [ { "image": [ "https://files.readme.io/Pgq9zrZ7RRr4byBPh8kA_2-validation.png", "2-validation.png", "1413", "924", "#3b566f", "" ] } ] } [/block] Click *Continue*. This will trigger the Promote to Prod pipeline: [block:image] { "images": [ { "image": [ "https://files.readme.io/V3xrMZLoQzWnEA1W3d04_2-pipelines-all.png", "2-pipelines-all.png", "1411", "1010", "#3e596c", "" ] } ] } [/block] In the CLUSTERS tab, you can see that a server group has been deployed to the prod cluster. [block:image] { "images": [ { "image": [ "https://files.readme.io/H72xOv6DQz6HYA2kHamc_2-clusters.png", "2-clusters.png", "1411", "561", "#3b566d", "" ] } ] } [/block] Because we selected the red/black deployment strategy for the deployment, there should always be only one enabled/active server group resident in the prod cluster cluster, with previous ones disabled (grey), even after successive runs of this pipeline. Try it out by manually invoking the promotion pipeline again. ## Extra Stuff ### Roll back Sometimes things go wrong and you need to roll prod back to the previous release. We employed the red/black strategy, which disables the previous server group. In practice, this is disassociating the server group from the load balancer so it takes no traffic, while keeping the nodes in the server group up, standing by. To roll back back to the previous server group, first kick off another instance of the Promote to Prod pipeline so that you have a previous disabled server group in the PROD cluster to roll back to. When this pipeline completes, navigate to the CLUSTERS tab and click the active server group. * In the *Server Group Actions* drop down on the right, click *Rollback*. * In the dialog that appears, select the server group you would like restore (roll back to). * Type the name of the account to confirm your action. * Click *Submit*. [block:image] { "images": [ { "image": [ "https://files.readme.io/gPu9PuIQQySWvBwzwhoE_3-rollback.png", "3-rollback.png", "596", "321", "#df5733", "" ] } ] } [/block] When the task completes (you can check progress in the TASKS tab), you will see that the specified server group is now the active one, while the previous one is disabled (grey). ### Triggering the Jenkins job by changing source So far you’ve been triggering the Jenkins job manually over unchanging source code. Consequently, you’ll notice that all server groups point back to the same Jenkins job. This is because Spinnaker can detect whether a re-bake is necessary, and because there were no changes, it simply returned the same image. The image you’re using does have Jenkins polling for updates to the local git repo. If you trigger the Jenkins job as a result of code change, the image that’s built will be different, and you’ll see the build info change throughout the entire pipeline chain. You can update source by doing the following from your ssh window: sudo su jenkins cd /var/lib/jenkins/hello-karyon-rxnetty vi build.gradle # Change the number on the “release” line. git commit -a -m "Bump release number" You’ll see the whole sequence again, but with a key difference: a new image will be baked, and the server groups deployed as a result will show different build info.