<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Yi Ai</title>
    <description>The latest articles on DEV Community by Yi Ai (@yia333).</description>
    <link>https://dev.to/yia333</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F156990%2F6ac4e593-9151-41af-b282-fcb2567315e0.jpeg</url>
      <title>DEV Community: Yi Ai</title>
      <link>https://dev.to/yia333</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yia333"/>
    <language>en</language>
    <item>
      <title>Creating an Instance Scheduler using AWS CDK</title>
      <dc:creator>Yi Ai</dc:creator>
      <pubDate>Fri, 14 Aug 2020 13:15:00 +0000</pubDate>
      <link>https://dev.to/aws-builders/creating-an-instance-scheduler-using-aws-cdk-1i9l</link>
      <guid>https://dev.to/aws-builders/creating-an-instance-scheduler-using-aws-cdk-1i9l</guid>
      <description>&lt;p&gt;The AWS CDK is a software development framework used to define cloud infrastructure as code and provision it through CloudFormation. The CDK integrates fully with AWS services and allows developers to use a high-level construct to define cloud infrastructure in code.&lt;/p&gt;

&lt;p&gt;In this article, we will build a CDK version of the AWS EC2 Instance Scheduler solution that enables us to easily configure custom start and stop schedules for our Amazon EC2 and Amazon RDS instances.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;By the end of this article, we will have a pipeline to deploy a serverless solution that starts and stops Amazon EC2 instances in an autoscaling group and Amazon RDS instances based on a schedule.&lt;/p&gt;

&lt;p&gt;Here’s the architecture diagram:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b2v8gnrz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/aw3q4ui6uegckxkoadq1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b2v8gnrz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/aw3q4ui6uegckxkoadq1.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Through the article we will be covering the following actions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploying an AWS Step Function with two parallel tasks.&lt;/li&gt;
&lt;li&gt;Creating an SNS topic to send notifications.&lt;/li&gt;
&lt;li&gt;Creating a Cloudeatch event rule which will trigger Step Function based on a schedule.&lt;/li&gt;
&lt;li&gt;Creating a CI/CD pipeline with CodeBuild and CodePipeline.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To deploy the CDK application, there are a few prerequisites that need to be met:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setup an AWS account.&lt;/li&gt;
&lt;li&gt;Install the latest &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/installing.html"&gt;aws-cli&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Install &lt;a href="https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html"&gt;AWS CDK CLI&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/yai333/cdkexample/blob/master/WordPress_Multi_AZ.template"&gt;Deploy a multi-AZ WordPress website with RDS (optional)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Before you begin
&lt;/h2&gt;

&lt;p&gt;First, create an AWS CDK project by entering the following commands at the command line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$mkdir cdk-sample 
$cd cdk-sample cdk init --language=javascript
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Next, install CDK modules, we will use the below modules in our project.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$npm install @aws-cdk/core @aws-cdk/aws-codebuild @aws-cdk/aws-codepipeline @aws-cdk/aws-codepipeline-actions @aws-cdk/aws-events @aws-cdk/aws-events-targets @aws-cdk/aws-iam @aws-cdk/aws-lambda @aws-cdk/aws-sns @aws-cdk/aws-ssm @aws-cdk/aws-stepfunctions @aws-cdk/aws-stepfunctions-tasks
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We need to add a stage parameter because we want to deploy our stack to multiple stages (dev and production).&lt;br&gt;
Let’s add &lt;code&gt;DEP_ENV&lt;/code&gt; in &lt;code&gt;bin/cdk-sample.js&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h2&gt;
  
  
  Define the base stack class
&lt;/h2&gt;

&lt;p&gt;Now let’s define our base stack class. In the base stack class, we’ll add the code to instantiate three separate stacks: SNS stack, StepFunction stack, and CodePipeline stack.&lt;/p&gt;

&lt;p&gt;Make the code look like the following.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We can set the optional environment variable MANUAL_DEPLOY to true if we want to deploy only step function locally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$export MANUAL_DEPLOY=true &amp;amp;&amp;amp; cdk deploy Stepfunction-dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Define SNS stack
&lt;/h2&gt;

&lt;p&gt;We’ll add the code (&lt;code&gt;lib/sns-stack.js&lt;/code&gt;) to create an SNS topic and subscribe to an email to the created topic.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h2&gt;
  
  
  Define Step function and Lambdas
&lt;/h2&gt;

&lt;p&gt;Now we’ll expand our &lt;code&gt;lib/lambda-stack.js&lt;/code&gt; file and add Lambda functions and Step function.&lt;/p&gt;

&lt;p&gt;In this example, we will create two lambda functions, &lt;a href="https://github.com/yai333/cdkexample/tree/master/src"&gt;updateScalingGroupFn&lt;/a&gt; to update auto-scaling group and &lt;a href="https://github.com/yai333/cdkexample/tree/master/src"&gt;updateDBClusterFn&lt;/a&gt; to start/stop RDS instances.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
Next, we will continue by adding our step function definitions. Add the following code to &lt;code&gt;lib/lambda-stack.js&lt;/code&gt; .&lt;br&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;As we can see, for each Lambda there is a corresponding taskEvent. We only want to parallelize the Lamba workload (one task for the ec2 autoscaling group and another task for RDS instances). Hence we will add a chain to our workflow by calling the &lt;code&gt;branch()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;To send a notification to the Amazon SNS topic if the Lambda fails, we can add an error handling chain to the workflow by calling &lt;code&gt;addCatch()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Finally, let’s define a CloudWatch Events rule, CloudWatch is triggering execution of state machine workflow every day at 7 am and 6 pm (UTC). Add the following code to &lt;code&gt;lib/lambda-stack.js&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;new Rule(this, 'Rule', {
  schedule: Schedule.expression('cron(0 7,18 * * ? *)'),
  targets: [new SfnStateMachine(toggleAWSServices)],
});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Define pipeline stack
&lt;/h2&gt;

&lt;p&gt;We define our final stack, codepiepeline-stack. It has a source Action targeting the Github repository, a build Action that builds previously defined stacks, and finally a deploy Action that uses AWS CloudFormation. It takes the Cloudformation template (CDK.out/*.template.json) generated by the AWS CDK build action and passes it to AWS CloudFormation for deployment.&lt;/p&gt;

&lt;p&gt;Create lib/codepipeline-stack.js and put the following code in it.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Next, create a dev branch and check the code into Git then push it to Github repo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$git branch dev
$git checkout dev
$git add .
$git commit -m "xxxx"
$git push
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Deploying the pipeline
&lt;/h2&gt;

&lt;p&gt;Now we can deploy the pipeline with multiple Stages.&lt;br&gt;
Deploy pipeline to &lt;code&gt;dev&lt;/code&gt; stage, source action targets the Github repository &lt;code&gt;dev&lt;/code&gt; branch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$export DEPLOY_ENV=dev &amp;amp;&amp;amp; cdk deploy CodepipelienStack-dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Deploy pipeline to the production stage, source action targets the Github repository master branch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$export DEPLOY_ENV=production &amp;amp;&amp;amp; cdk deploy CodepipelienStack-production
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After the deployment finishes, we should have a three-stage pipeline that looks like the following.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VQzoJJXu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/39pkmv11w82y55d7uhwb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VQzoJJXu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/39pkmv11w82y55d7uhwb.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once all stacks have deployed, we can explore it in the AWS Console and give it a try. Navigate to the Step Function in the console and click “Start execution”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iFGpdNq3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/l7j6wjvqal5m8ov44nf9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iFGpdNq3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/l7j6wjvqal5m8ov44nf9.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We should see that it passes. Let’s check the EC2 autoscaling group’s DesiredCapacity and RDS instance's status.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$aws rds describe-db-instances
"DBInstances": [
{
"DBInstanceIdentifier": "cxxxxxx",
"DBInstanceClass": "db.t2.small",
"Engine": "mysql",
"DBInstanceStatus": "stopped"
...
$aws rds describe-db-instances
"AutoScalingGroups": [
{
"AutoScalingGroupName": "cdk-sample-WebServerGroup-xxxxxx",
"MinSize": 0,
"MaxSize": 0,
"DesiredCapacity": 0,
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, let’s check the cloud watch event rule. We should see the cloud watch event rule looks like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$aws events list-rules
{
"Rules": [
{
"Name": "StepfunctionStack-dev-Rulexxxxxxx",
"Arn": "arn:aws:events:ap-southeast-2:xxxxxxx:rule/StepfunctionStack-dev-Rulexxxxxxx-xxxxxxx",
"State": "ENABLED",
"ScheduleExpression": "cron(0 7,18 * * ? *)",
"EventBusName": "default"
}
  ]
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That’s about it, Thanks for reading! You can find the complete project in my &lt;a href="https://github.com/yai333/cdkexample"&gt;GitHub repo&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>aws</category>
      <category>cdk</category>
      <category>iac</category>
    </item>
  </channel>
</rss>
