Infrastructure as Code (IaC) is one of the biggest revolutions in the cloud computing landscape, as it allows automating the deployment of infrastructure based on its definition in the source code. Using code as the source of truth for infrastructure has several benefits:
- Infrastructure can be versioned as source code normally is, increasing the traceability of the infrastructure deployed.
- Deployments, rollbacks and disaster recovery procedures can be easily automated, reducing the amount of human intervention, thus reducing the likelihood of errors.
- Costs are reduced, as resources can be easily resized to adapt them to the load fluctuations and environments can be switched off when they are not needed.
- Deployment processes are sped up significantly, making the software development life-cycle more efficient, as environments can be deployed when needed.
IaC can be implemented by means of several tools, being Terraform, AWS CloudFormation, Ansible, Chef or Puppet some of the most widely used ones. These tools normally rely on declarative languages (or dialects) using mostly YAML, JSON and JSON-like formatting for the infrastructure definition. Getting to work with these languages and tools can be challenging sometimes, specially for those with a more ‘Developer-like’ background.
Thus, it makes sense to deploy infrastructure using high-level languages, which are more natural to developers. This approach can increase productivity based on the fact that common development patterns can be easily reused. This way of working, enables developers to provision infrastructure easily, without needing to be an infrastructure expert. Besides, developers can provision a complete stack, applications and the underlying infrastructure, by using high-level languages in their IDE of choice. This is particularly useful in medium size and small companies and projects, where just one team is in charge of the management and operation of both the Dev and Ops parts.
In this post, the AWS Cloud Development Kit (CDK) will be reviewed. AWS CDK is a development framework created by AWS, which helps creating and managing cloud infrastructure and applications by using well-known programming languages such as Typescript, Javascript, Python, Java and C#. The following examples were developed using Typescript, but in the future, new posts will be released, testing some other languages. You can find the code used to create the examples that are shown on this post in this repository.
Setting the CDK up
In order to use the AWS CDK with Typescript, Node.js is needed. You can get the appropriate version for your OS in this link. Besides, the AWS CLI can be a useful tool to configure the AWS credentials in your computer. You can get the AWS CLI here. Finally, Typescript itself needs to be installed if it’s not present in your machine. You can get it installed using the Node Package Manager (npm).
The next step is to install the AWS CDK toolkit with npm.
Finally, you can create a Typescript project by issuing the commands below. The cdk init command generates the directory structure, classes, subfolders and installs the core module alongside its dependencies. However, you can download the project we will be using from this this repository. So there’s no need to create a new project from scratch.
Project structure
In order to deploy a test stack you can clone the examples repository. You will need to be working from the typescript directory. Running npm install will fetch all the required modules and dependencies for the stack to work.
After initializing or cloning the project, your folder will contain several directories where the example base code and modules are placed.
- lib is the directory where the infrastructure stack is defined. typescript-stack.ts is the main stack file, where the components will be defined. This file will generate the javascript output typescript-stack.js by means of the transpiler.
- bin contains the entrypoints (both for Javascript and Typescript) for the CDK application. The entrypoints reference the main stack to use.
- package.json contains the npm module manifest
- node_modules contain the dependencies needed by the stack
- cdk.json and tsconfig.json are the CDK toolkit and Typescript configuration files respectively
Deploying the stack
When working with the Typescript stack, it is possible to run the compiler in watch mode, which will automatically compile the changes in the Typescript files into Javascript files. To do so, run the following command in a separate terminal. Otherwise, you will be in charge of compiling each change by hand.
The code below shows the contents of the lib/typescript-stack.ts file. It creates an EC2 instance and configures it to run a simple kubes&clouds static website using an user data script as bootstrap script. Besides, it defines a VPC with a public subnet to launch the instance on, as well as the required Security Groups to enable both HTTP and SSH access to the instance. Notice that a SSH key is specified to access the instance, so, set it to the name of one of the SSH keys existing in your account if you want to access the instance.
Prior to the deployment, you will need to configure your AWS credentials using the AWS CLI. In order to do so, you will need an AWS secret key and access key pair. If you don’t have one yet, you can create a new one in the AWS IAM console. Check this documentation as a guide.
Keep in mind that the user which uses those credentials should have permissions to create the infrastructure specified in the code. For this example you can use the AdministratorAccess managed policy. Store well your credentials, and once this user is no longer needed, remove it, to avoid unnecessary risks.
AWS CDK CLI can be used to generate a CloudFormation stack from the high-level language you are using to define your stack. To do so, issue the following command.
The snippet below, shows a part of the CloudFormation output generated with the cdk synth command.
Prior to your first deployment, you will need to set up the bootstrap stack, which is required by the CDK toolkit in order to to keep track of the deployed resources and templates. The following command carries out the needed setup.
Once the bootstrap procedure is over, everything will be ready to deploy the stack. Issue the following command, and the resources to be created will be prompted, asking for your confirmation. If everything looks good to you confirm your deployment.
If you inspect the CloudFormation stacks in your account once the deployment has succeeded, you will see the different resources created by AWS CDK.
Furthermore, you will notice an additional stack, the CDK toolkit stack that was created during the bootstrap phase by the CDK CLI. This stack creates an S3 bucket where the resource definitions and states are stored.
If you access the public IP of the instance that has just been created using your web browser, you will see that it worked as expected!
Once you are done with the web server, destroy the stack and its resources by issuing the following command.
Terraform equivalent
If you were to deploy the exact same stack using Terraform, you will need something similar to the code below. You can find this file in terraform/main.tf within the example repository. Notice that for this implementation, Terraform registry modules were used with Terraform v0.12.28. This piece of code is added here so that you can compare both ways of defining infrastructure as code, but if you want to try and deploy it, it will work too! Keep in mind that you will have to set your SSH key pair in case you want to access the instance.
Initialise your terraform directory containing the code, then build the deployment plan, and if everything looks good to you, confirm your deployment.
Like in the previous example, by accessing the public IP of the instance, you can check that the deployed web server is working correctly.
Once you have finished testing the Terraform deployment, destroy the previously created resources.
Making it more interesting
Well, the previous example was interesting but yet too basic. Taking into account how much we like Kubernetes on this blog, it would be a great idea to deploy a Kubernetes cluster using AWS CDK. For this purpose we will use one of the examples provided by AWS in their CDK examples repository. In this case, we will be using AWS managed Kubernetes service, known as EKS. The code below can be found in this repository, alongside the typescript configuration files needed for its deployment.
By following the previous steps, the stack can be created on our AWS account. In this case, we will be invoking the typescript compiler manually. Be patient as deploying the cluster may take a while.
After some minutes, the EKS cluster will be up and running.
Once the cluster has been created, the CDK CLI will prompt the command needed to generate a kubeconfig to access the cluster.
Issue the following command to generate the kubeconfig. You can copy it directly from the CDK CLI output.
If everything worked out as it should, you will be able to access your new cluster!
Important
If you get a You must be logged in to the server (Unauthorized) error when accessing the EKS cluster with the generated kubeconfig, you will need to give the AWS CDK user permissions to assume the EKS Cluster creation role. This is a direct consequence of how IAM roles are mapped to the Kubernetes RBAC. When a cluster is created, only the user/role that created the cluster can access it. To solve this problem quickly, just grant the IAM user that was used with the AWS CDK permission to assume the <clustername>-ClusterCreationRole role.
Finally, destroy the EKS cluster and the associated resources so that you don’t have any surprises with your AWS bill!
If you want to learn more about the AWS CDK you can go through the different examples in CDK examples repository. There are quite a lot of interesting use cases, including serverless architectures, using different languages. In the future, new articles with new languages will be published here in Kubes&Clouds.