-
Notifications
You must be signed in to change notification settings - Fork 0
/
page-data.json
1 lines (1 loc) · 37.3 KB
/
page-data.json
1
{"componentChunkName":"component---src-templates-blog-post-js","path":"/ci-cd-deploy-to-aws-github-actions/","result":{"data":{"site":{"siteMetadata":{"title":"My ideas' home"}},"markdownRemark":{"id":"6fa76286-0304-5ea1-acbc-a7a298e000af","excerpt":"Recently at work, we decided to build a CI/CD pipeline that deploys our application directly to AWS. I had never worked with AWS, and it was a missing point on…","html":"<p>Recently at work, we decided to build a CI/CD pipeline that deploys our application directly to AWS. I had never worked with AWS, and it was a missing point on my CV which demonstrates that I have some DevOps skills. I decided to search for some tutorials online and I was not lucky to get what we needed at work. I decided to write this guide by getting something working from various tutorials I found online.</p>\n<h3>What you will learn from this series.</h3>\n<p>In this 3 parts tutorial, we will learn how to Create an AWS architecture where you can deploy an application, how to convert a docker-compose file in a Task Definition and how to deploy a Task Definition to an AWS Architecture using GitHub Actions.</p>\n<h3>Who is this series for ?</h3>\n<p>This tutorial is for developers who are familiar with docker and have an application with docker-compose. Although the series was written by a Python developer and using Python, the concepts can be applied to other programming languages.</p>\n<h3>Which application will we deploy?</h3>\n<p>In this tutorial, we will deploy a Python application that has a celery worker, a celery scheduler, and a Redis database for task messaging and task queues.</p>\n<p>I will not talk about celery and task queues and how to use those tools but you can get start with them <a href=\"%5Bhttps://medium.com/analytics-vidhya/python-celery-distributed-task-queue-demystified-for-beginners-to-professionals-part-1-b27030912fea%5D(https://medium.com/analytics-vidhya/python-celery-distributed-task-queue-demystified-for-beginners-to-professionals-part-1-b27030912fea)\">here</a>, and to get started with docker you can use <a href=\"https://dev.to/javascriptcoff1/what-is-docker-3be2\">this one</a> ,and <a href=\"https://adamtheautomator.com/docker-compose-tutorial/\">this one</a> to be familiar with docker-compose.</p>\n<p>This series is not based on any popular Python web framework such as Django, Flask, or FastAPi but you can adapt this tutorial to them and I am sure it will work like a charm.</p>\n<p>The application skeleton can be downloaded from <a href=\"https://github.com/espoirMur/deploy_python_to_aws_github_actions\">this link</a> to get started.</p>\n<p>In this first part of the tutorial, we will learn how to create the Cloudformation stack.</p>\n<h3>What is AWS CloudFormation?</h3>\n<p>From <a href=\"https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html\">the official documentation</a>, Cloudformation is defined as :</p>\n<blockquote>\n<p>AWS CloudFormation is a service that helps you model and set up your Amazon Web Services resources so that you can spend less time managing those resources and more time focusing on your applications that run in AWS. You create a template that describes all the AWS resources that you want (like Amazon EC2 instances or Amazon RDS DB instances), and CloudFormation takes care of provisioning and configuring those resources for you. You don’t need to individually create and configure AWS resources and figure out what’s dependent on what; CloudFormation handles all of that.</p>\n</blockquote>\n<h3>Creating the AWS Architecture</h3>\n<p>Make sure that you have created an AWS account and you have your credentials; the access key, and the application secret key.</p>\n<p>Most of the services used in this tutorial are available within an AWS free tier.</p>\n<p>We will deploy our application using the AWS ECS Fargate launch type which will pull docker images from the Elastic Container Registry aka ECR.</p>\n<h4>Why Fargate and not EC2?</h4>\n<p><img src=\"https://media.giphy.com/media/3o7btPCcdNniyf0ArS/giphy.gif\" alt=\"Alt Text\"></p>\n<p>AWS provides us basically two launch types which are the Fargate launch type and the EC2.</p>\n<p>Amazon Elastic Compute Cloud (Amazon EC2) provides scalable computing capacity in the Amazon Web Services (AWS) Cloud. Using Amazon EC2 eliminates the need to invest in hardware upfront, so you can develop and deploy applications faster. You can use Amazon EC2 to launch as many or as few virtual servers as you need. It allows you to configure security and networking, and manage storage yourself. With EC2 you don’t have to worry about the hardware, the hardware is managed by AWS.</p>\n<p>AWS Fargate is a technology that you can use with Amazon ECS to run <a href=\"https://aws.amazon.com/what-are-containers\">containers</a> without having to manage servers or clusters of Amazon EC2 instances. The advantage of Fargate over EC2 is the fact that you don’t have to configure, provision, or scale cluster instances and don’t have to worry about the virtual machines.</p>\n<p>In a nutshell :</p>\n<p>With a virtual machine, someone still has to manage the hardware, but with EC2 that someone is AWS and you never even see the hardware.</p>\n<p>With ECS on EC2, someone still has to manage the instances, but with ECS on Fargate that someone is AWS and you never even see the EC2 instances.</p>\n<p>ECS has a “launch type” of either EC2 (if you want to manage the instances yourself) or Fargate (if you want AWS to manage the instances). <a href=\"https://www.reddit.com/r/aws/comments/dvl601/eli5_aws_fargate/f7ddkup?utm_source=share&utm_medium=web2x&context=3\">Source</a>.</p>\n<h4>The objects we need :</h4>\n<p>To deploy the application we need the following objects: a cluster, a service, a task definition with containers definition, cloud watch for logging, and IAM roles. The below picture illustrates how those AWS objects interact with each other.</p>\n<p><img src=\"https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k5bcp5zjq6ssob06mgyt.png\" alt=\"Alt Text\"></p>\n<p>Let us define some of those objects and then we will investigate how to create a stack, containing them, using Python cdk.</p>\n<ul>\n<li><strong>A cluster</strong>: It is a logical group of container instances that ECS can use for deploying Docker containers. It provides computing power to run application container instances. In practice, a cluster is usually attached to an AWS Instance.</li>\n<li><strong>A service</strong>: It enables us to run and maintain a specified number of instances of a task definition simultaneously in an Amazon ECS cluster. ie. It helps us run single or multiple containers all using the same Task Definition.</li>\n<li><strong>The task definition</strong>: A task definition is a specification. You use it to define one or more containers (with image URIs) that you want to run together, along with other details such as environment variables, CPU/memory requirements, etc. The task definition doesn’t actually run anything, it’s a description of how things will be set up when something does run. The task definition shares some similarities with the docker-compose file. In the second part of this tutorial, we will convert a docker-compose file into a task definition.</li>\n<li><strong>A task</strong>: A task is an actual thing that is running. ECS uses the task definition to run the task; it downloads the container images, configures the runtime environment based on other details in the task definition. You can run one or many tasks for any given task definition. Each running task is a set of one or more running containers - containers in a task all run on the same instance.</li>\n<li><strong>cloudwatch</strong>: CloudWatch is a monitoring service, we are using it in this stack to get and visualize logs from the docker containers.</li>\n</ul>\n<p>With all the objects described, we can now learn how to create them using the Python CDK.</p>\n<h4>Creating the architecture:</h4>\n<p>To build the infrastructure, we will leverage the <a href=\"https://aws.amazon.com/cdk/\">AWS Cloud Development Kit (CDK)</a>. If you are new to CDK, see <a href=\"https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html\">Getting Started with AWS CDK</a>, it is simple and straightforward to install. In this post, we will be using the CDK with Python 3.7. Another alternative to the CDK is to create the application via the AWS console. However, I found the CDK to be the simplest approach because it allows you to have control over the code you are writing.</p>\n<p>After installing the CDK check if it is working with the following command:</p>\n<ul>\n<li><code class=\"language-text\">cdk --version</code> should output your CDK version.</li>\n</ul>\n<h5>Initializing the AWS CLI :</h5>\n<p>Make sure you have AWS CLI installed on your computer. <a href=\"https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html\">Configure your AWS CLI</a> with an IAM user that has permissions to create the resources (VPC, ECS, ECR, IAM Role) described in the template below. After the configuration you should have the AWS keys stored in your computer at the following location :</p>\n<ul>\n<li><code class=\"language-text\">~/.aws/credentials</code>: if you are using Mac or Linux</li>\n<li><code class=\"language-text\">C:\\Users\\</code>USERNAME<code class=\"language-text\">\\.aws\\config</code>: if you are on Windows</li>\n</ul>\n<p>The content of that file should look like this one:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">[default]\n\nregion=your region\n\naws_access_key_id = *********************************\n\naws_secret_access_key = ******************************</code></pre></div>\n<p>With the credentials, the cli client and the CDK installed let us move to the second step about creating the architecture.</p>\n<h4>Initializing The CDK Project :</h4>\n<p>To initialize the CDK we will create a new Python project which will contain the code to create the architecture.</p>\n<p><em>Step 1</em>: Creating the project</p>\n<p>Run the following command to create a new CDK project:</p>\n<p><code class=\"language-text\">mkdir ecs-devops-cdk</code></p>\n<p>Enter the project using:</p>\n<p><code class=\"language-text\">cd ecs-devops-cdk</code></p>\n<p>Or if you are using VSCode you can open the project with vs code using:</p>\n<p><code class=\"language-text\">code ecs-devops-cdk</code></p>\n<ul>\n<li><em>Step 2</em>: Initialize the python CDK project :</li>\n</ul>\n<p>To initialize the CDK project run the following command:</p>\n<p><code class=\"language-text\">cdk init --language python</code></p>\n<p>The command will create a new python CDK project and we will be editing it in the next step to build our stack.</p>\n<p>After a quick look you should see a structure like this in your project:</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token builtin class-name\">.</span>\n\n├── README.md\n\n├── app.py\n\n├── cdk.json\n\n├── ecs_devops_cdk\n\n│ ├── __init__.py\n\n│ └── ecs_devops_cdk_stack.py\n\n├── requirements.txt\n\n├── setup.py\n\n└── source.bat</code></pre></div>\n<ul>\n<li><em>Step 3</em>: activate virtual environment :</li>\n</ul>\n<p>You can activate your virtual environment using the following command :</p>\n<p>On mac and linux : <code class=\"language-text\">source .env/bin/activate</code></p>\n<p>For windows : <code class=\"language-text\">.env\\Scripts\\activate.bat</code></p>\n<ul>\n<li><em>step 4</em>: Installing dependencies:</li>\n</ul>\n<p>With the virtual environment created we can now install the dependencies :</p>\n<p><code class=\"language-text\">pip install -r requirements.txt</code>and<code class=\"language-text\">pip install aws_cdk.aws_ec2 aws_cdk.aws_ecs aws_cdk.aws_ecr aws_cdk.aws_iam</code></p>\n<p>With the project initialized we can now move to the next step where we will be creating our components.</p>\n<h4>Creating the objects :</h4>\n<p>We can now move to the stack creation step</p>\n<p>If you open the file under <code class=\"language-text\">ecs_devops_cdk/ecs_devops_cdk_stack.py</code> you should be able to see the followings :</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">from</span> aws_cdk <span class=\"token keyword\">import</span> core\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">EcsDevopsCdkStack</span><span class=\"token punctuation\">(</span>core<span class=\"token punctuation\">.</span>Stack<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">__init__</span> <span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> scope<span class=\"token punctuation\">:</span> core<span class=\"token punctuation\">.</span>Construct<span class=\"token punctuation\">,</span> construct_id<span class=\"token punctuation\">:</span> <span class=\"token builtin\">str</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">**</span>kwargs<span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span><span class=\"token operator\">></span> <span class=\"token boolean\">None</span><span class=\"token punctuation\">:</span>\n\n<span class=\"token builtin\">super</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span> __init__ <span class=\"token punctuation\">(</span>scope<span class=\"token punctuation\">,</span> construct_id<span class=\"token punctuation\">,</span> <span class=\"token operator\">**</span>kwargs<span class=\"token punctuation\">)</span></code></pre></div>\n<p>It is basically a class that will contain the code defining our stack.</p>\n<p><strong>step 1</strong>: Import the core functionality</p>\n<p>Edit the first line to import the code we need to create the following stack:</p>\n<p>`python</p>\n<p>from aws<em>cdk import (core, aws</em>ecs as ecs, aws<em>ecr as ecr, aws</em>ec2 as ec2, aws<em>iam as iam, aws</em>logs)`</p>\n<p><strong>step 2</strong>: Create the container repository</p>\n<p>To create a container repository you can use the following command :</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">ecr_repository <span class=\"token operator\">=</span> ecr<span class=\"token punctuation\">.</span>Repository<span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> <span class=\"token string\">\"ecs-devops-repository\"</span><span class=\"token punctuation\">,</span> repository_name<span class=\"token operator\">=</span><span class=\"token string\">\"ecs-devops-repository\"</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p><strong>step 3</strong>: Creating the VPC :</p>\n<p>We can either create a vpc or use an existing vpc. To create a vpc use can add the following code the <code class=\"language-text\">__init__</code> method.</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">vpc <span class=\"token operator\">=</span> ec2<span class=\"token punctuation\">.</span>Vpc<span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> <span class=\"token string\">\"ecs-devops-vpc\"</span><span class=\"token punctuation\">,</span> max_azs<span class=\"token operator\">=</span><span class=\"token number\">3</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>You can also use an existing vpc , if that is the case for you use the following lines:</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">vpc <span class=\"token operator\">=</span> ec2<span class=\"token punctuation\">.</span>Vpc<span class=\"token punctuation\">.</span>from_lookup<span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> <span class=\"token string\">\"ecs-devops-vpc\"</span><span class=\"token punctuation\">,</span>vpc_id<span class=\"token operator\">=</span><span class=\"token string\">'vpc-number'</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>For this, you need the vpc name and the corresponding id.</p>\n<p><em>step 4:</em> Cluster Creation :</p>\n<p>With the vpc created we can attach the cluster to it . To create the cluster we can use the following code :</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">cluster <span class=\"token operator\">=</span> ecs<span class=\"token punctuation\">.</span>Cluster<span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span>\n\n<span class=\"token string\">\"ecs-devops-cluster\"</span><span class=\"token punctuation\">,</span>\n\ncluster_name<span class=\"token operator\">=</span><span class=\"token string\">\"ecs-devops-cluster\"</span><span class=\"token punctuation\">,</span>\n\nvpc<span class=\"token operator\">=</span>vpc<span class=\"token punctuation\">)</span></code></pre></div>\n<p><em>step 5:</em> Creating the Role:</p>\n<p>Let us create the role, the role will give the service permission to perform tasks.</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">execution_role <span class=\"token operator\">=</span> iam<span class=\"token punctuation\">.</span>Role<span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> <span class=\"token string\">\"ecs-devops-execution-role\"</span><span class=\"token punctuation\">,</span> assumed_by<span class=\"token operator\">=</span>iam<span class=\"token punctuation\">.</span>ServicePrincipal<span class=\"token punctuation\">(</span><span class=\"token string\">\"ecs-tasks.amazonaws.com\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> role_name<span class=\"token operator\">=</span><span class=\"token string\">\"ecs-devops-execution-role\"</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>With the execution role created we can attach policy to it to give it the permission it needs.</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">execution_role<span class=\"token punctuation\">.</span>add_to_policy<span class=\"token punctuation\">(</span>iam<span class=\"token punctuation\">.</span>PolicyStatement<span class=\"token punctuation\">(</span> effect<span class=\"token operator\">=</span>iam<span class=\"token punctuation\">.</span>Effect<span class=\"token punctuation\">.</span>ALLOW<span class=\"token punctuation\">,</span> resources<span class=\"token operator\">=</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"*\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> actions<span class=\"token operator\">=</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"ecr:GetAuthorizationToken\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"ecr:BatchCheckLayerAvailability\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"ecr:GetDownloadUrlForLayer\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"ecr:BatchGetImage\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"logs:CreateLogStream\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"logs:PutLogEvents\"</span><span class=\"token punctuation\">]</span> <span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>With the IAM role created we can attach a task definition to it</p>\n<p><em>Step 6</em>: Creating the task definition :</p>\n<p>Here is the code we used to create the task definition ;</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">task_definition <span class=\"token operator\">=</span> ecs<span class=\"token punctuation\">.</span>FargateTaskDefinition<span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> <span class=\"token string\">\"ecs-devops-task-definition\"</span><span class=\"token punctuation\">,</span> execution_role<span class=\"token operator\">=</span>execution_role<span class=\"token punctuation\">,</span> family<span class=\"token operator\">=</span><span class=\"token string\">\"ecs-devops-task-definition\"</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>And the container :</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">container <span class=\"token operator\">=</span> task_definition<span class=\"token punctuation\">.</span>add_container<span class=\"token punctuation\">(</span><span class=\"token string\">\"ecs-devops-sandbox\"</span><span class=\"token punctuation\">,</span> image<span class=\"token operator\">=</span>ecs<span class=\"token punctuation\">.</span>ContainerImage<span class=\"token punctuation\">.</span>from_registry<span class=\"token punctuation\">(</span><span class=\"token string\">\"amazon/amazon-ecs-sample\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">)</span></code></pre></div>\n<p>In the code above, we are initially specifying the Task Definition to run with an example container from a public AWS sample registry. This sample container is replaced with our application container when our CI/CD pipeline updates the Task Definition. We are using the container from the sample registry to allow the Service to stabilize before any application container images are added to our ECR repository.</p>\n<p>With the task definition created we can attach a service that will be running it.</p>\n<p><em>step 7:</em> Creating the service :</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">service <span class=\"token operator\">=</span> ecs<span class=\"token punctuation\">.</span>FargateService<span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> <span class=\"token string\">\"ecs-devops-service\"</span><span class=\"token punctuation\">,</span> cluster<span class=\"token operator\">=</span>cluster<span class=\"token punctuation\">,</span> task_definition<span class=\"token operator\">=</span>task_definition<span class=\"token punctuation\">,</span> service_name<span class=\"token operator\">=</span><span class=\"token string\">\"ecs-devops-service\"</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>The service uses the task definition and you can see it is attached to our created cluster.</p>\n<p>PS: When your AWS instance is in a public subnet , you need to auto-assign public IP addresses to the containers to grant them internet access. This will help your service to download a docker image from a public repository. In that case, you can use the following code when creating the service. :</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">service <span class=\"token operator\">=</span> ecs<span class=\"token punctuation\">.</span>FargateService<span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span>\n\n<span class=\"token string\">\"service-name\"</span><span class=\"token punctuation\">,</span>\n\ncluster<span class=\"token operator\">=</span>cluster<span class=\"token punctuation\">,</span>\n\ntask_definition<span class=\"token operator\">=</span>task_definition<span class=\"token punctuation\">,</span>\n\nservice_name<span class=\"token operator\">=</span><span class=\"token string\">\"service-name\"</span><span class=\"token punctuation\">,</span>\n\nassign_public_ip<span class=\"token operator\">=</span><span class=\"token boolean\">True</span><span class=\"token punctuation\">,</span> <span class=\"token comment\"># this is important</span>\n\nsecurity_groups<span class=\"token operator\">=</span><span class=\"token punctuation\">[</span><span class=\"token builtin\">list</span> of security groups <span class=\"token punctuation\">,</span> also important<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n\nvpc_subnets<span class=\"token operator\">=</span><span class=\"token punctuation\">[</span><span class=\"token builtin\">list</span> of subnets<span class=\"token punctuation\">]</span>\n\n<span class=\"token punctuation\">)</span></code></pre></div>\n<p>Note the assign<em>public</em>ip , the security group and the VPC subnets.</p>\n<p><em>Step 8</em>: Creating the cloudwatch Log group:</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">log_group <span class=\"token operator\">=</span> aws_logs<span class=\"token punctuation\">.</span>LogGroup<span class=\"token punctuation\">(</span>\n\n \n\nself<span class=\"token punctuation\">,</span>\n\n \n\n<span class=\"token string\">\"ecs-devops-service-logs-groups\"</span><span class=\"token punctuation\">,</span>\n\n \n\nlog_group_name<span class=\"token operator\">=</span><span class=\"token string\">\"ecs-devops-service-logs\"</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>As stated before we will be transferring the docker logs to our log group created in Cloudwatch.</p>\n<p>With all the objects created let us make sure that we have all the ingredients for our stack in the following updated file.</p>\n<p><code class=\"language-text\">ecs_devops_cdk/ecs_devops_cdk_stack.py</code></p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">from</span> aws_cdk <span class=\"token keyword\">import</span> <span class=\"token punctuation\">(</span>core<span class=\"token punctuation\">,</span> aws_ecs <span class=\"token keyword\">as</span> ecs<span class=\"token punctuation\">,</span> aws_ecr <span class=\"token keyword\">as</span> ecr<span class=\"token punctuation\">,</span> aws_ec2 <span class=\"token keyword\">as</span> ec2<span class=\"token punctuation\">,</span> aws_iam <span class=\"token keyword\">as</span> iam<span class=\"token punctuation\">,</span> aws_logs<span class=\"token punctuation\">)</span>\n\n \n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">EcsDevopsCdkStack</span><span class=\"token punctuation\">(</span>core<span class=\"token punctuation\">.</span>Stack<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">__init__</span> <span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> scope<span class=\"token punctuation\">:</span> core<span class=\"token punctuation\">.</span>Construct<span class=\"token punctuation\">,</span> construct_id<span class=\"token punctuation\">:</span> <span class=\"token builtin\">str</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">**</span>kwargs<span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span><span class=\"token operator\">></span> <span class=\"token boolean\">None</span><span class=\"token punctuation\">:</span>\n\n \n\n<span class=\"token builtin\">super</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span> __init__ <span class=\"token punctuation\">(</span>scope<span class=\"token punctuation\">,</span> construct_id<span class=\"token punctuation\">,</span> <span class=\"token operator\">**</span>kwargs<span class=\"token punctuation\">)</span>\n\necr_repository <span class=\"token operator\">=</span> ecr<span class=\"token punctuation\">.</span>Repository<span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> <span class=\"token string\">\"ecs-devops-repository\"</span><span class=\"token punctuation\">,</span> repository_name<span class=\"token operator\">=</span><span class=\"token string\">\"ecs-devops-repository\"</span><span class=\"token punctuation\">)</span>\n\nvpc <span class=\"token operator\">=</span> ec2<span class=\"token punctuation\">.</span>Vpc<span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> <span class=\"token string\">\"ecs-devops-vpc\"</span><span class=\"token punctuation\">,</span> max_azs<span class=\"token operator\">=</span><span class=\"token number\">3</span><span class=\"token punctuation\">)</span>\n\ncluster <span class=\"token operator\">=</span> ecs<span class=\"token punctuation\">.</span>Cluster<span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> <span class=\"token string\">\"ecs-devops-cluster\"</span><span class=\"token punctuation\">,</span> cluster_name<span class=\"token operator\">=</span><span class=\"token string\">\"ecs-devops-cluster\"</span><span class=\"token punctuation\">,</span> vpc<span class=\"token operator\">=</span>vpc<span class=\"token punctuation\">)</span>\n\nexecution_role <span class=\"token operator\">=</span> iam<span class=\"token punctuation\">.</span>Role<span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> <span class=\"token string\">\"ecs-devops-execution-role\"</span><span class=\"token punctuation\">,</span> assumed_by<span class=\"token operator\">=</span>iam<span class=\"token punctuation\">.</span>ServicePrincipal<span class=\"token punctuation\">(</span><span class=\"token string\">\"ecs-tasks.amazonaws.com\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> role_name<span class=\"token operator\">=</span><span class=\"token string\">\"ecs-devops-execution-role\"</span><span class=\"token punctuation\">)</span>\n\nexecution_role<span class=\"token punctuation\">.</span>add_to_policy<span class=\"token punctuation\">(</span>iam<span class=\"token punctuation\">.</span>PolicyStatement<span class=\"token punctuation\">(</span>\n\neffect<span class=\"token operator\">=</span>iam<span class=\"token punctuation\">.</span>Effect<span class=\"token punctuation\">.</span>ALLOW<span class=\"token punctuation\">,</span> resources<span class=\"token operator\">=</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"*\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n\nactions<span class=\"token operator\">=</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"ecr:GetAuthorizationToken\"</span><span class=\"token punctuation\">,</span>\n\n<span class=\"token string\">\"ecr:BatchCheckLayerAvailability\"</span><span class=\"token punctuation\">,</span>\n\n<span class=\"token string\">\"ecr:GetDownloadUrlForLayer\"</span><span class=\"token punctuation\">,</span>\n\n<span class=\"token string\">\"ecr:BatchGetImage\"</span><span class=\"token punctuation\">,</span>\n\n \n\n<span class=\"token string\">\"logs:CreateLogStream\"</span><span class=\"token punctuation\">,</span>\n\n \n\n<span class=\"token string\">\"logs:PutLogEvents\"</span> <span class=\"token punctuation\">]</span> <span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n \n\ntask_definition <span class=\"token operator\">=</span> ecs<span class=\"token punctuation\">.</span>FargateTaskDefinition<span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> <span class=\"token string\">\"ecs-devops-task-definition\"</span><span class=\"token punctuation\">,</span> execution_role<span class=\"token operator\">=</span>execution_role<span class=\"token punctuation\">,</span>\n\nfamily<span class=\"token operator\">=</span><span class=\"token string\">\"ecs-devops-task-definition\"</span><span class=\"token punctuation\">)</span>\n\ncontainer <span class=\"token operator\">=</span> task_definition<span class=\"token punctuation\">.</span>add_container<span class=\"token punctuation\">(</span><span class=\"token string\">\"ecs-devops-sandbox\"</span><span class=\"token punctuation\">,</span> image<span class=\"token operator\">=</span>ecs<span class=\"token punctuation\">.</span>ContainerImage<span class=\"token punctuation\">.</span>from_registry<span class=\"token punctuation\">(</span><span class=\"token string\">\"amazon/amazon-ecs-sample\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\nservice <span class=\"token operator\">=</span> ecs<span class=\"token punctuation\">.</span>FargateService<span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> <span class=\"token string\">\"ecs-devops-service\"</span><span class=\"token punctuation\">,</span> cluster<span class=\"token operator\">=</span>cluster<span class=\"token punctuation\">,</span> task_definition<span class=\"token operator\">=</span>task_definition<span class=\"token punctuation\">,</span> service_name<span class=\"token operator\">=</span><span class=\"token string\">\"ecs-devops-service\"</span><span class=\"token punctuation\">)</span>\n\nlog_group <span class=\"token operator\">=</span> aws_logs<span class=\"token punctuation\">.</span>LogGroup<span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> <span class=\"token string\">\"ecs-devops-service-logs-groups\"</span><span class=\"token punctuation\">,</span> log_group_name<span class=\"token operator\">=</span><span class=\"token string\">\"ecs-devops-service-logs\"</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Before creating the stack open the file <code class=\"language-text\">app.py</code></p>\n<p>You should see something like this :</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">from</span> aws_cdk <span class=\"token keyword\">import</span> core\n\n<span class=\"token keyword\">from</span> ecs_devops_cdk<span class=\"token punctuation\">.</span>ecs_devops_cdk_stack <span class=\"token keyword\">import</span> EcsDevopsCdkStack\n\napp <span class=\"token operator\">=</span> core<span class=\"token punctuation\">.</span>App<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\n \n\nEcsDevopsCdkStack<span class=\"token punctuation\">(</span>app<span class=\"token punctuation\">,</span> <span class=\"token string\">\"ecs-devops-cdk\"</span><span class=\"token punctuation\">)</span>\n\napp<span class=\"token punctuation\">.</span>synth<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Replace the line where your stack is instantiated, 4th line, with the following :</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">EcsDevopsCdkStack<span class=\"token punctuation\">(</span>app<span class=\"token punctuation\">,</span> <span class=\"token string\">\"ecs-devops-cdk\"</span><span class=\"token punctuation\">,</span> env<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>\n\n \n\n<span class=\"token string\">'account'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\" **************\"</span><span class=\"token punctuation\">,</span>\n\n \n\n<span class=\"token string\">'region'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"your region\"</span>\n\n \n\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>With this set; you can now create your stack. With the code created we can now run the following command to create our stack.</p>\n<p><code class=\"language-text\">cdk deploy</code></p>\n<p>If everything goes well you should have your stack created. As a result, you will have a cluster, running a service that deploys a task definition, and a Cloudwatch log group created.</p>\n<p>You can check your stack from the AWS console by navigating to the following <a href=\"https://us-east-2.console.aws.amazon.com/cloudformation/home?region=us-east-2#/stacks?filteringStatus=active&filteringText=&viewNested=true&hideStacks=false\">link</a>.</p>\n<p>If you want, you can check this project on GitHub <a href=\"https://github.com/espoirMur/ecs-devops-cdk\">here</a>.</p>\n<p>That is all for this first part, we managed to build our ship and added the most important objects to it.</p>\n<p>We are now ready to pack containers and deliver our content to our client.</p>\n<p>In the second part of this series, we will learn how to convert our docker-compose file to a task definition described in this tutorial. See you then!</p>","frontmatter":{"title":"How to use the AWS Python CDK to create an infrastructure on ECS.","date":"26 February, 2021","description":null,"cover_image":null}}},"pageContext":{"slug":"/ci-cd-deploy-to-aws-github-actions/","previous":{"fields":{"slug":"/ielts-how-it-went/"},"frontmatter":{"title":"I sat for the IELTS today , here is how it went"}},"next":{"fields":{"slug":"/book-recomendations/"},"frontmatter":{"title":"My books recommendations to enhance your Soft Skills as a developer"}}}},"staticQueryHashes":["4211413508","63159454"]}