:icons: :linkcss: :imagesdir: ./images
= Code Service - Continuous Deployment Reference Architecture for Kubernetes
The Code Service Continuous Deployment reference architecture demonstrates how to achieve continuous deployment of an application to a Kubernetes cluster using AWS CodePipeline, AWS CodeCommit, AWS CodeBuild and AWS Lambda.
Launching this AWS CloudFormation stack provisions a continuous deployment process that uses AWS CodePipeline to monitor an AWS CodeCommit repository for new commits, AWS CodeBuild to create a new Docker container image and to push it into Amazon ECR. Finally an AWS Lambda function with the Kubernetes Python SDK updates a Kubernetes deployment in a live cluster.
When you deploy the cloudformation stack there will be four parameters that are specific to your Kubernetes cluster. You will need the API endpoint (enter only the subdomain and omit 'api'), Certificate Authority Data, Client Certificate Data and Client Key Data. The last of these three are sensitive, the cloudformation parameter is marked with the "NoEcho" property set to true so that the contents are not exposed through cloudformation. In addition those strings are encrypted with the account default KMS key and stored in parameter store. The Lambda function that authenticates to your Kubernetes API endpoint is assigned an IAM role that has permission to access those keys. The Lambda function builds a config file in the tmpfs directory of the Lambda which is in memory so that when the Lambda function terminates the secrets are gone.
image::architecture.png[Architecture]
=== Pre-Requisites
A functioning Kubernetes cluster and config file to authenticate to the cluster, by default this is located at ~/.kube/config
Clone this repository
git clone https://github.com/aws-samples/aws-kube-code-service
This creates a directory named aws-kube-code-service
in your current directory, which contains the code we need for this tutorial. Change to this directory.
=== Application - initial deployment and service Provisioning
kubectl apply -f ./kube-manifests/deploy-first.yml
Find the service endpoint to view the application:
kubectl get svc code-service-demo -o wide
If you copy and paste the External IP from the code-service-demo service into a browser you should see the nginx homepage.
=== Deploy the CloudFormation stack
Note, deploy this stack in the same region as your k8s cluster. Your cluster nodes will require access via an IAM profile to download images from ECR. If you deployed this cluster through KOPS this will be already take care of for you.
|===
|Region | Launch Template for Kubernetes | Launch Template for Amazon EKS | N. Virginia (us-east-1) a| image::./deploy-to-aws.png[link=https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?stackName=Codesuite-Demo&templateURL=https://s3.amazonaws.com/code-service-demo-public/aws-refarch-code-service-kubernetes.yaml] a| image::./deploy-to-aws.png[link=https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?stackName=Codesuite-Demo&templateURL=https://s3-us-west-2.amazonaws.com/aws-eks-code-service/aws-refarch-code-service-kubernetes.yaml]
| Ohio (us-east-2) a| image::./deploy-to-aws.png[link=https://console.aws.amazon.com/cloudformation/home?region=us-east-2#/stacks/new?stackName=Codesuite-Demo&templateURL=https://s3.amazonaws.com/code-service-demo-public/aws-refarch-code-service-kubernetes.yaml] a|
| Oregon (us-west-2) a| image::./deploy-to-aws.png[link=https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?stackName=Codesuite-Demo&templateURL=https://s3.amazonaws.com/code-service-demo-public/aws-refarch-code-service-kubernetes.yaml] a| image::./deploy-to-aws.png[link=https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?stackName=Codesuite-Demo&templateURL=https://s3-us-west-2.amazonaws.com/aws-eks-code-service/aws-refarch-code-service-kubernetes.yaml]
| Ireland (eu-west-1) a| image::./deploy-to-aws.png[link=https://console.aws.amazon.com/cloudformation/home?region=eu-west-1#/stacks/new?stackName=Codesuite-Demo&templateURL=https://s3.amazonaws.com/code-service-demo-public/aws-refarch-code-service-kubernetes.yaml] a| image::./deploy-to-aws.png[link=https://console.aws.amazon.com/cloudformation/home?region=eu-west-1#/stacks/new?stackName=Codesuite-Demo&templateURL=https://s3-us-west-2.amazonaws.com/aws-eks-code-service/aws-refarch-code-service-kubernetes.yaml]
| Frankfurt (eu-central-1) a| image::./deploy-to-aws.png[link=https://console.aws.amazon.com/cloudformation/home?region=eu-central-1#/stacks/new?stackName=Codesuite-Demo&templateURL=https://s3.amazonaws.com/code-service-demo-public/aws-refarch-code-service-kubernetes.yaml] a|
| Singapore (ap-southeast-1) a| image::./deploy-to-aws.png[link=https://console.aws.amazon.com/cloudformation/home?region=ap-southeast-1#/stacks/new?stackName=Codesuite-Demo&templateURL=https://s3.amazonaws.com/code-service-demo-public/aws-refarch-code-service-kubernetes.yaml] a|
| Sydney (ap-southeast-2) a| image::./deploy-to-aws.png[link=https://console.aws.amazon.com/cloudformation/home?region=ap-southeast-2#/stacks/new?stackName=Codesuite-Demo&templateURL=https://s3.amazonaws.com/code-service-demo-public/aws-refarch-code-service-kubernetes.yaml] a|
| Tokyo (ap-northeast-1) a| image::./deploy-to-aws.png[link=https://console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stacks/new?stackName=Codesuite-Demo&templateURL=https://s3.amazonaws.com/code-service-demo-public/aws-refarch-code-service-kubernetes.yaml] a|
|===
If you are deploying this architecture to an Amazon EKS cluster, you would need to give the Lambda execution role permissions in Amazon EKS cluster. You can get the ARN of your Lambda execution role from the Outputs tab in the CloudFormation template. Refer to this link:https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html[User Guide] for detailed instructions.
Edit the aws-auth
ConfigMap of your cluster.
kubectl -n kube-system edit configmap/aws-auth
Add your Lambda execution role to the config
# apiVersion: v1 data: mapRoles: |
=== Test CI/CD platform
Install credential helper
git config --global credential.helper '!aws codecommit credential-helper $@'
git config --global credential.UseHttpPath true
Clone CodeCommit Repository (url will be in CloudFormation Output), change directories up one level cd ..
so that both repositories are at the same directory structure.
Check the outputs page for your CloudFormation stack:
git clone <name_of_your_codecommit_repository>
This creates a directory named code-service-demo
in your current directory.
Copy contents from aws-kube-code-service/sample-app to this repository folder.
cp aws-kube-code-service/sample-app/* code-service-demo/
Make a change to the code-service-demo/hello.py
file and then change into that directory cd code-service-demo
Add, commit and push:
git add . && git commit -m "test Code Service" && git push origin master
To view the pipeline in the AWS console go to the outputs tab for the pipeline cloudformation template and click on the Pipeline URL link:
image::pipeline-url.png[pipeline-url]
You can then see the pipeline move through the various stages:
image::pipeline.png[pipeline]
Once the final Lambda stage is complete you should be able to see the new deployment exposed through the same service load balancer.
kubectl get svc code-service-demo -o wide
Now if you copy and paste the External IP from the code-service-demo service into a browser you should see the flask page reflecting the changes you applied.
=== Cleaning up the example resources
To remove all resources created by this example do the following:
== CloudFormation template resources
The following section explains all of the resources created the CloudFormation template provided with this example.
link:/templates/lambda-copy.yaml[lambda-copy]
This creates a Lambda function that copies the Lambda code from the central account into the user account.
link:/templates/ssm-inject.yaml[ssm-inject]
Deploys a custom resource via Lambda which creates secure string key value pairs for all of the secrets required to authenticate to the Kubernetes cluster.
link:/templates/deployment-pipeline.yaml[deployment-pipeline]
Resources that compose the deployment pipeline include the CodeBuild project, the CodePipeline pipeline, an S3 bucket for deployment artifacts, and ECR repository for the container images and all necessary IAM roles used by those services.
== License Summary
This sample code is made available under a modified MIT license. See the LICENSE file.