<?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>Forem: Erik</title>
    <description>The latest articles on Forem by Erik (@lesteenman).</description>
    <link>https://forem.com/lesteenman</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%2F859754%2F6e40ede5-dffd-4e4d-b762-5bfd20ba2ac4.jpeg</url>
      <title>Forem: Erik</title>
      <link>https://forem.com/lesteenman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/lesteenman"/>
    <language>en</language>
    <item>
      <title>SIMPLE AWS DEPLOYMENTS ACROSS REGIONS AND ACCOUNTS WITH CDK</title>
      <dc:creator>Erik</dc:creator>
      <pubDate>Tue, 07 Feb 2023 10:08:22 +0000</pubDate>
      <link>https://forem.com/aws-builders/simple-aws-deployments-across-regions-and-accounts-with-cdk-ogi</link>
      <guid>https://forem.com/aws-builders/simple-aws-deployments-across-regions-and-accounts-with-cdk-ogi</guid>
      <description>&lt;p&gt;Infrastructure as Code has made it possible to consistently repeat deployments and keep track of the details in version control. AWS CDK, the Cloud Development Kit, is a native Infrastructure as Code solution by AWS that allows you to write you infrastructure definitions in normal programming languages. Deploying a collection of cloud resources with it is as simple as running &lt;code&gt;cdk deploy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Well, simple... It is simple, as long as your solution spans a single AWS Account and Region. Things tend to become more complicated when multiple regions or other accounts are involved. Regions and accounts are isolated in AWS. Coordinating multi-region or multi-account deployments has often required us to write custom deployment scripts. However, CDK offers us the right set of tools to perform these kinds of deployments in a clear and concise manner.&lt;/p&gt;

&lt;p&gt;In this post, we will show how we can use CDK to pick up this tangle of cross-environment deployments and make them simple! By defining our environments either with files in our version control, or with environment variables, we will show a variety of methods. No matter how you want to deploy your code, this post will show you how to do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  A quick primer on definitions
&lt;/h2&gt;

&lt;p&gt;Two core concepts in CDK are &lt;em&gt;Stacks&lt;/em&gt; and &lt;em&gt;Apps&lt;/em&gt;. AWS describes a Stack as a "unit of deployment", and an App as "a container for one or more stacks".&lt;/p&gt;

&lt;p&gt;A CDK Stack is roughly equivalent to a CloudFormation stack. &lt;br&gt;
It is a template you deploy to a region on an AWS account. A stack can contain many types of AWS resources, but they all exist in the same account and region (with &lt;a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudfront.experimental.EdgeFunction.html" rel="noopener noreferrer"&gt;some exceptions&lt;/a&gt; for special region-bound resources). So a Stack is the &lt;em&gt;smallest, indivisible unit&lt;/em&gt; of deployment.&lt;/p&gt;

&lt;p&gt;When we want to deploy a single project across regions or even accounts, we have to deploy multiple &lt;em&gt;Stacks&lt;/em&gt;. Using CDK, we have a logical abstraction of a project that consists of multiple stacks: an App. After all, it is a collection of stacks - nothing says it has to be in one region or even in one account.&lt;/p&gt;

&lt;p&gt;In CDK lingo, a combination of an &lt;em&gt;account&lt;/em&gt; and a &lt;em&gt;region&lt;/em&gt; is an &lt;em&gt;Environment&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  A cross-environment Application
&lt;/h2&gt;

&lt;p&gt;We will first show how to define an Application that spans multiple Environments.&lt;/p&gt;

&lt;p&gt;For the examples in this post, we will be using Python, but the concepts can easily be applied to the other supported languages. The CDK documentation that we will link to shows an example of each individual concept in every supported language.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.aws.amazon.com/cdk/v2/guide/environments.html" rel="noopener noreferrer"&gt;AWS Documentation&lt;/a&gt; describes the way you can pass arguments to Stack Construct to target an account or region in various programming languages. For demonstration purposes, we will assume we have two different stacks, each of which needs to go to a different account and region. Maybe we are demonstrating a cross-account notification system, with one stack being the sender, and the other being the subscriber in the demo!&lt;/p&gt;

&lt;p&gt;The simplest example uses static accounts and regions for its environments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;aws_cdk&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;cdk&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;demo.event_publisher_stack&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;EventPublisherStack&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;demo.event_receiver_stack&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;EventReceiverStack&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nc"&gt;EventPublisherStack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EventPublisherStack&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;111111111111&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;eu-west-1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nc"&gt;EventReceiverStack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EventReceiverStack&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                       &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;222222222222&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;eu-west-1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;synth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can deploy all stacks in this application in one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Option A: deploy each stack in one command&lt;/span&gt;
cdk deploy &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or with multiple separate commands, which can be beneficial if you need to assume another role for each stack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Option B: deploy each stack individually&lt;/span&gt;
cdk deploy EventPublisherStack
cdk deploy EventReceiverStack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a simple demo, using static account ids and regions in your Environments might be good enough. But if this is an Application that will end up in production, you should not hardcode these values.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.aws.amazon.com/cdk/v2/guide/environments.html" rel="noopener noreferrer"&gt;CDK documentation&lt;/a&gt; has good details on the concepts we will show, though it helps to have a starting point. Because CDK is written in a full programming language, you can use any method you normally would to pass the configuration to it.&lt;/p&gt;

&lt;p&gt;To get you started, we have prepared a few short examples showing two approaches you can take.&lt;/p&gt;

&lt;h3&gt;
  
  
  Method 1: Environment variables
&lt;/h3&gt;

&lt;p&gt;Environment variables provide a lot of flexibility.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;aws_cdk&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;cdk&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;demo.event_publisher_stack&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;EventPublisherStack&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;demo.event_receiver_stack&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;EventReceiverStack&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nc"&gt;EventPublisherStack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EventPublisherStack&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;TARGET_ACCOUNT_PUBLISHER&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                        &lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;TARGET_REGION_PUBLISHER&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                    &lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nc"&gt;EventReceiverStack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EventReceiverStack&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                       &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;TARGET_ACCOUNT_RECEIVER&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                       &lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;TARGET_REGION_RECEIVER&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                   &lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;synth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where they truly shine is in deployment pipelines. You can define these variables as properties of the target environment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F40vqsq90m202cl3mew0b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F40vqsq90m202cl3mew0b.png" alt="A screenshot of the environment secrets in Github Actions" width="630" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When deploying from your local command line, a deployment command will likely look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;TARGET_ACCOUNT_PUBLISHER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;111111111111 &lt;span class="nv"&gt;TARGET_REGION_PUBLISHER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;eu-west-1 &lt;span class="nv"&gt;TARGET_ACCOUNT_RECEIVER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;222222222222 &lt;span class="nv"&gt;TARGET_REGION_RECEIVER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;eu-west-1 pipenv run cdk deploy &lt;span class="nt"&gt;--all&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Very concise, we know. That's one disadvantage of using environment variables: when run from your local development machine, the deployment commands can become a bit verbose.&lt;/p&gt;

&lt;h3&gt;
  
  
  Method 2: Configuration files
&lt;/h3&gt;

&lt;p&gt;By putting your environments in configuration files, you make it simpler to see the intended result in the code itself. This does mean putting your account id's in your code. The debate whether this is a security risk has been responded to by AWS (and &lt;a href="https://www.lastweekinaws.com/blog/are-aws-account-ids-sensitive-information/" rel="noopener noreferrer"&gt;commented on&lt;/a&gt; by others in the community), and this should pose no security risk.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;aws_cdk&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;cdk&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;demo.event_publisher_stack&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;EventPublisherStack&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;demo.event_receiver_stack&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;EventReceiverStack&lt;/span&gt;

&lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;app&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;environment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ENVIRONMENT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;environment&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Make sure a valid environment is specified in the ENVIRONMENT env var.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;config_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;configs/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;environment&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;config_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_file&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Make sure the config file for the given ENVIRONMENT exists in ./configs/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;environment&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.json and is readable.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;config_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nc"&gt;EventPublisherStack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EventPublisherStack&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;publisher&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;account_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                        &lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;publisher&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;region&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                    &lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nc"&gt;EventReceiverStack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EventReceiverStack&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                       &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;receiver&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;account_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                       &lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;receiver&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;region&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                   &lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;synth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can define our configurations for our deployment stages by placing json files in &lt;code&gt;./configs&lt;/code&gt;. Our developers can define their own configuration file in there, and keep it out of version control if they do not want to clutter the project with their account ids.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;ls&lt;/span&gt; ./configs
acceptance.json
dev.json
production.json
test.json

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;cat&lt;/span&gt; ./configs/test.json
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"publisher"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"account_id"&lt;/span&gt;: &lt;span class="s2"&gt;"111111111111"&lt;/span&gt;,
    &lt;span class="s2"&gt;"region"&lt;/span&gt;: &lt;span class="s2"&gt;"eu-west-1"&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;,
  &lt;span class="s2"&gt;"receiver"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"account_id"&lt;/span&gt;: &lt;span class="s2"&gt;"222222222222"&lt;/span&gt;,
    &lt;span class="s2"&gt;"region"&lt;/span&gt;: &lt;span class="s2"&gt;"eu-west-1"&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we then run &lt;code&gt;CONFIG=test cdk deploy --all&lt;/code&gt;, our publisher stack will be deployed to account &lt;em&gt;111111111111&lt;/em&gt;, and our receiver stack to account &lt;em&gt;222222222222&lt;/em&gt;, both in region eu-west-1.&lt;/p&gt;

&lt;p&gt;An added benefit of this approach is that you can store other configuration in these json files as well. Examples might be the names of artifact buckets or external services that differ depending on the target environment. These can then be &lt;a href="https://docs.aws.amazon.com/cdk/v2/guide/constructs.html#constructs_config" rel="noopener noreferrer"&gt;passed to the Stacks&lt;/a&gt; as extra configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bootstrapping all your environments for deployment
&lt;/h2&gt;

&lt;p&gt;To deploy to any Environment, that environment must first be &lt;a href="https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping.html" rel="noopener noreferrer"&gt;bootstrapped by CDK&lt;/a&gt;. During bootstrapping, CDK creates the resources it needs to deploy to an environment, such as S3 buckets for artifacts, but also IAM roles and policies that are assumed during deployment. When you run &lt;code&gt;cdk deploy&lt;/code&gt;, the CDK command line will attempt to assume one of these roles in the target environment to perform the deployment.&lt;/p&gt;

&lt;p&gt;If all your stacks live in the same account, or if you deploy each stack individually, a simple &lt;code&gt;cdk bootstrap&lt;/code&gt; in every environment is enough. But if your application spans account, we need a bit more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployments to multiple &lt;em&gt;accounts&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;If your Application spans accounts, and not just regions, being able to deploy with a &lt;code&gt;cdk deploy --all&lt;/code&gt; is a little more involved. You will need to extend &lt;em&gt;trust&lt;/em&gt; to assume the CDK IAM resources from one account to another. To do so, modify your &lt;code&gt;cdk bootstrap&lt;/code&gt; as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# This will deploy to account 222222222222, so make sure your CLI has a valid login session for that account.&lt;/span&gt;
cdk bootstrap aws://222222222222/eu-west-1 &lt;span class="nt"&gt;--trust&lt;/span&gt; 111111111111 &lt;span class="nt"&gt;--cloudformation-execution-policies&lt;/span&gt; &lt;span class="s2"&gt;"arn:aws:iam::aws:policy/YOUR_CDK_POLICY"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By specifying the trusted account with &lt;code&gt;--trust&lt;/code&gt;, the IAM role in account &lt;em&gt;222222222222&lt;/em&gt; will be modified to be assumed by roles in account &lt;em&gt;111111111111&lt;/em&gt;. If the role or user you assume in account &lt;em&gt;111111111111&lt;/em&gt; &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_common-scenarios_aws-accounts.html" rel="noopener noreferrer"&gt;are then allowed to assume this role&lt;/a&gt;, you can deploy to the environment of account &lt;em&gt;1111111111&lt;/em&gt; and account &lt;em&gt;2222222222&lt;/em&gt; at the same time.&lt;/p&gt;

&lt;p&gt;Do note the explicit &lt;code&gt;--cloudformation-execution-policies&lt;/code&gt; in this command. When deploying with CDK, the deployment role will assume this policy to perform the deployment. With an unchanged &lt;code&gt;cdk bootstrap&lt;/code&gt;, this will default to &lt;em&gt;AdministratorAccess&lt;/em&gt;. When bootstrapping an account with a &lt;code&gt;--trust&lt;/code&gt; of another account, CDK chooses to make you explicitly choose this role. Using the default of &lt;em&gt;AdministratorAccess&lt;/em&gt; carries potential security risks, &lt;em&gt;especially&lt;/em&gt; when you allow other accounts to assume this role as well. Create a role with the minimal permissions required to deploy your applications and pass that role to &lt;code&gt;--cloudformation-execution-policies&lt;/code&gt; when bootstrapping your environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking back
&lt;/h2&gt;

&lt;p&gt;CDK offers us powerful abstractions and tools to manage complex applications. These help us truly unlock the promise and power of the cloud. Infrastructure that spans multiple regions is one of these promises, that have been a hard concept to do encapsulate in your Infrastructure as Code for too long a time. By correctly using the capabilities of CDK, we truly unlock this promise.&lt;/p&gt;

&lt;p&gt;In this post, we have given you some handholds to get started with these types of deployments. We have shown two approaches to defining your multi-account or -region environments: By using configuration files, we define our environments in a way that's easy to include in our codebase. Alternatively, by using environment variables, we can easily deploy our apps to varying environments.&lt;/p&gt;

&lt;p&gt;Of course, there's nothing stopping using another method entirely - that's what having a real programming language to back your Infrastructure as Code definitions enables you to do!&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>crypto</category>
      <category>web3</category>
      <category>devto</category>
    </item>
    <item>
      <title>How Infrastructure as Code empowers developers</title>
      <dc:creator>Erik</dc:creator>
      <pubDate>Thu, 17 Nov 2022 08:11:01 +0000</pubDate>
      <link>https://forem.com/lesteenman/how-infrastructure-as-code-empowers-developers-fmf</link>
      <guid>https://forem.com/lesteenman/how-infrastructure-as-code-empowers-developers-fmf</guid>
      <description>&lt;p&gt;Managing infrastructure has been a challenge for a long time. Traditionally, it involved a large amount of manually entered commands, mouse clicks and other human-driven labor.&lt;/p&gt;

&lt;p&gt;As more and more companies work with large amounts of servers and duplicated infrastructure across environments, we're running into the limits of this approach. This manual way of working has multiple problems. It is error-prone, as performing actions in a slightly different way can result in large differences. It can be slow, especially when we want multiple copies of each server. Plus, the approach relies on very accurate documentation of the state of each piece of infrastructure, server and procedure. In many cases, this documentation is not kept up-to-date as well as it should be, resulting in problems during development or production.&lt;/p&gt;

&lt;p&gt;Infrastructure as Code is all about applying modern practices of software development to the management of your IT infrastructure. It empowers you to do your job as easily as possible. How? By making use of the best aspect of working with computers: automation. It enables consistent rollouts of your software, frequent updates of your servers and it frees up your developers for actual improvements instead of just keeping the existing servers afloat.&lt;/p&gt;

&lt;p&gt;This post is intended as an introduction to the concept of Infrastructure as Code. While there are some examples, we will not explain how to write it. We will show various types of Infrastructure as Code that are in active use, and show the ways of working they enable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Traditional server configuration
&lt;/h2&gt;

&lt;p&gt;Let's start by looking at a very important component of our infrastructure: a server.&lt;/p&gt;

&lt;p&gt;In general, a server is just a computer that we run somewhere in a closet or similar to do some serious things. So not your personal laptop or your gaming computer at home, but the ones serving websites, steam downloads, Discord voice calls and so on. Similar to your personal laptop, you install some programs on it when you get it, install updates over time, and add on other programs you want.&lt;/p&gt;

&lt;p&gt;Sooner or later, you need to reinstall it - either it's getting too slow, it has malware, or you simply need a backup server. For a PC, it does not matter much if this 2nd installation looks slightly different. But for professional servers, that can lead to nasty surprises. Websites that behave slightly differently, crashes that you had solved on the old installation by changing some obscure configuration. By starting from scratch, we risk forgetting important details.&lt;/p&gt;

&lt;p&gt;This means that we need to keep extensive documentation on its installation. Something most people do not like doing.&lt;br&gt;
But it's essential to have consistent installs, and to make a system that others can work with as well.&lt;/p&gt;

&lt;p&gt;So we need to find a way to make our setup reproducible, to make it scale.&lt;/p&gt;
&lt;h2&gt;
  
  
  Repetition, repetition, repetition.
&lt;/h2&gt;

&lt;p&gt;Let's imagine the simplest way we could automate this.&lt;/p&gt;

&lt;p&gt;You've gone through the process of setting up a server once.&lt;br&gt;
By keeping careful step-by-step documentation, you described exactly what commands you had to enter to set this server up. Well, then we're already very close to a shell script, aren't we?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Running setup script...'&lt;/span&gt;

&lt;span class="c"&gt;# Install the server&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install &lt;/span&gt;mysql-server

&lt;span class="c"&gt;# Copy the config file if it does not yet exist&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /etc/my.cnf &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; /mnt/usbdrive/my.cnf /etc/my.cnf
&lt;span class="k"&gt;fi

&lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;mysqld
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every major computer OS has at least one language that you can use out-of-the-box for automation. Maybe it's Bash, maybe it's Powershell, that depends on your operating system of choice. But all of them boil down to being a list of commands that get executed when you run the script.&lt;/p&gt;

&lt;p&gt;But of course, we later realize we need some changes in the setup of this server.&lt;/p&gt;

&lt;p&gt;It's easy to change the script so a next server looks differently. But you'd prefer to have one central script to execute both for existing servers, that need to be changed, and for new ones. You could solve this by creating a sequential list of scripts. Each one changes the "output" of the last, until we arrive at one central server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-lh&lt;/span&gt; ./install-scripts
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;  1 34K  Jan 06 16:30 setup-1.sh
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;  1 187B Mar 20 16:30 setup-2.sh
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;  1 20B  May 31 16:30 setup-3.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could go ahead and make a central script that runs all of them. Then we would need to keep track of what the last executed script was on this server. So now we need to keep our own state... This will get tricky quickly.&lt;/p&gt;

&lt;p&gt;But! &lt;br&gt;
There's a better way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install Mysql package&lt;/span&gt;
  &lt;span class="na"&gt;yum&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql-server&lt;/span&gt;
    &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;installed&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Create Mysql configuration file&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my.cnf.j2&lt;/span&gt;
    &lt;span class="na"&gt;dest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/etc/my.cnf&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Start Mysql Service&lt;/span&gt;
  &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysqld&lt;/span&gt;
    &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;started&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an example of Ansible, one of many &lt;em&gt;Desired State Configuration&lt;/em&gt; tools. The core idea behind desired state configuration like this is that you state &lt;em&gt;what&lt;/em&gt; you want the end result to be, not how it should be achieved. The tool, Ansible in this case, will check the current situation, and run the correct commands.&lt;/p&gt;

&lt;p&gt;Tools like Ansible even have ways to encapsulate common classes of behaviour in "classes" or "roles". So you can say that a server is "monitored by tool A", and "runs Docker images", and Ansible will apply the correct sets of instructions for both. This means we get to apply some concepts we like to use in programming, like composition, in our infrastructure management!&lt;/p&gt;

&lt;p&gt;After converting our commands to desired state in Ansible, we have something we can easily put in version control. Effectively, we've converted the configuration of our server to code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deleting everything. Constantly.
&lt;/h2&gt;

&lt;p&gt;Imagine not having to keep a server up and healthy as long as possible. Using modern technologies, it's easy to build your system out of virtual servers that only exist until they need to be changed next. We can create &lt;em&gt;images&lt;/em&gt; of a server we've created once, then deploy it as often as we want. If there updates to the operating system or our application, we create a new image, and deploy that.&lt;/p&gt;

&lt;p&gt;So we throw away server whenever something needs to change.&lt;/p&gt;

&lt;p&gt;What does this look like in practice?&lt;/p&gt;

&lt;p&gt;One way is to manually create these images. You can manually boot up a fresh Linux install, go through the motions to set everything up you need &lt;em&gt;except&lt;/em&gt; for your application code itself. So you add Nginx, Mysql, a monitoring agent. Then, you create a snapshot of that OS, create servers from it, and all you need to do after that is put your application on it - and done! This is much faster than going through the motion to install all packages from the internet each time, because you effectively only have a single compressed archive you're unpacking - the image.&lt;/p&gt;

&lt;p&gt;But we've seen that scripting these steps is easier. There's a very big player in the market that boils down to doing this: Docker Containers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# syntax=docker/dockerfile:1&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:12-alpine&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;apk add &lt;span class="nt"&gt;--no-cache&lt;/span&gt; python2 g++ make

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;yarn &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--production&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["node", "src/index.js"]&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We write something that vaguely resembles our shell scripts, and after running it, we get an image that we can deploy as often as we want. It's made to be easy to automate, and you can include almost any setup step in these Dockerfiles.&lt;/p&gt;

&lt;p&gt;Where we might have been proud of servers with half a year of uptime, nowadays, virtual machines that don't live longer than a day are not uncommon at all. The main reason for that is not because we hate long uptimes. The real reason these have started existing is to make it possible to scale up rapidly. Being able to create servers in seconds and delete them when you don't need them anymore makes it possible to pay exactly for what you're using, or to run very large jobs every night without paying thousands of dollars a month to keep the servers running constantly.&lt;/p&gt;

&lt;p&gt;We call these &lt;em&gt;immutable servers&lt;/em&gt;, and the concept in general &lt;em&gt;immutable infrastructure&lt;/em&gt;. The alternative we saw before is called &lt;em&gt;mutable&lt;/em&gt; infrastructure. Infrastructure as Code is a big enabler of this immutability, and for many solutions, it is easier to maintain than systems we keep tweaking over a period of months or years.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;em&gt;Infrastructure&lt;/em&gt; as Code
&lt;/h2&gt;

&lt;p&gt;So far, we've only talked about servers. Infrastructure is, of course, a lot more than just this. We also have networking, storage, the underlying hardware of the server, and so on.&lt;/p&gt;

&lt;p&gt;In practice, any component that is virtual (as opposed to, say, a physical you have to plug in by hand) can be automated, and all the major Cloud providers have virtualized almost anything you can think of. And it's here, in the cloud, that Infrastructure as Code - true infrastructure, not just servers - truly starts to shine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcml0xtr0m2nf3fsgll1j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcml0xtr0m2nf3fsgll1j.png" alt="The AWS Console"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you first start out working with a cloud provider, you might log on to their web console, launch a virtual machine or two, create a managed databases and connecting them. &lt;br&gt;
But then, you need to do it again for your production environment, and you have to make the exact same clicks so the environments are similar enough.&lt;/p&gt;

&lt;p&gt;But you can automate this.&lt;/p&gt;

&lt;p&gt;Cloud providers have done something awesome: they created and published API's with which you can do nearly anything you can do manually in their web consoles.&lt;/p&gt;

&lt;p&gt;One approach would be to write another shell script. This time, it runs a series of HTTPS calls to your cloud provider.&lt;br&gt;
But: we've learnt about the power of desired state configuration. So we know there is something better.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;StaticFilesBucket&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::S3::Bucket&lt;/span&gt;

  &lt;span class="na"&gt;ServerlessWebHandler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::Lambda::Function&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Runtime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python3.9&lt;/span&gt;
      &lt;span class="na"&gt;CodeUri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;s3://my-example-bucket/serverless-web-handler/v1.zip&lt;/span&gt;
      &lt;span class="na"&gt;Environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;STATIC_FILES_BUCKET&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;StaticFilesBucket&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is Cloudformation. It's the official language of Amazon Webservices, to define our cloud infrastructure as desired state.&lt;/p&gt;

&lt;p&gt;We can put this in a GitHub repository and automatically deploy it to the correct AWS account - test or production - at the push of a button. You change your code, automated checks verify it, someone looks if it's functionally, you merge it. You run your CI/CD pipeline, and minutes later your AWS account is up-to-date with the new environment.&lt;br&gt;
It created virtualized, managed databases, message queues, networks and servers based on a bit of configuration.&lt;br&gt;
And after testing it, you click another button, and it replaces your production environment in-place, without downtime.&lt;/p&gt;

&lt;p&gt;So there you have it: we can now create complete, complicated, multi-tier application infrastructure as YAML.&lt;/p&gt;
&lt;h2&gt;
  
  
  Infrastructure as &lt;em&gt;real&lt;/em&gt; Code
&lt;/h2&gt;

&lt;p&gt;If you're like me, you might feel a bit deceived about hearing "code" and seeing YAML. The good news is, we have much better alternatives nowadays. For most Cloud Providers, there are development kits that allow you to write normal code - like Python, Java or C# - and generate your infrastructure from that!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aws_cdk&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;aws_lambda&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;aws_s3&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;constructs&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Construct&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyExampleStack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Construct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;construct_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;static_files_bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aws_s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;StaticFilesBucket&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;serverless_web_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aws_lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ServerlessWebHandler&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;aws_lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PYTHON_3_9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;aws_lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;./functions/web-handler/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;environment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;STATIC_FILES_BUCKET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;static_files_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucketName&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;static_files_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;grantRead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serverless_web_handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What you see here is CDK: the AWS Cloud Development Kit. CDK is a collection of libraries and tools you can use to create cloud infrastructures. It's available in multiple languages - so far in Javascript, Typescript, Python, Java, C# and Go. &lt;/p&gt;

&lt;p&gt;It can generate all the same infrastructure you can with CloudFormation. But instead of plain old YAML, you can use a real programming language.&lt;/p&gt;

&lt;p&gt;YAML has some distinct disadvantages compared to a real programming language. The lack of custom functions, for/while loops, easily reusable libraries and much more. By putting our infrastructure definition in actual code, the &lt;em&gt;intent&lt;/em&gt; of our definition is much more readable.&lt;/p&gt;

&lt;p&gt;By "synthesizing", or running, a CDK project, the underlying CloudFormation will be generated. In that way, the step from CloudFormation to CDK feels similar to other steps forward we've made from low-level programming languages to high-level ones! But in this case, we still often run into the "Assembly" variant of the code: CloudFormation. That makes it a good idea to check the CloudFormation that is generated by your CDK code.&lt;/p&gt;

&lt;p&gt;At the time of writing, we highly recommend anyone getting started with Infrastructure as Code on AWS to try out CDK.&lt;/p&gt;

&lt;h2&gt;
  
  
  The power of the automated cloud
&lt;/h2&gt;

&lt;p&gt;So far, we've seen a few steps of automation. From shell scripts, to desired state configuration of long-living servers, to immutable servers, and on to complete immutable infrastructures defined as desired state. But you may still be wondering - what's all the fuss about?&lt;/p&gt;

&lt;p&gt;So let's take a little more time to envision something that becomes possible with the automated cloud.&lt;/p&gt;

&lt;p&gt;Imagine a company running a couple of webservices that are used by customers to send large sets of data and to retrieve analyzed results. They're already running these in Docker containers - which means that, because creating the "server" these services run on is automated, we can easily recreate these in various environments.&lt;/p&gt;

&lt;p&gt;We create an AWS account for each environment - test, acceptance and production - and spin up each service in each environment. Changing the "size" of each underlying resource, such as CPU, memory and storage, is a matter of passing along different parameters in a few fields of our Infrastructure as Code. That makes it incredibly easy to have otherwise identical services in each account, with differing amount of compute resources. This makes it easy to save money in the test environment. &lt;em&gt;One step further would be to use _serverless&lt;/em&gt; services, where we only pay for what we use - but that's a different topic!_&lt;/p&gt;

&lt;p&gt;The services can place the submitted datasets in a managed storage location for processing.&lt;/p&gt;

&lt;p&gt;Next, we have a few worker processes that pick up this data and generate the information our customers want from us.&lt;br&gt;
Thanks to the ease with which we can automatically create and delete servers, we actually scale the number of workers up and down depending on the amount of work to be done.&lt;br&gt;
This means we can run cheap when it's calm, and still work very fast during the busier days.&lt;/p&gt;

&lt;p&gt;We now have an autoscaling environment with barely any maintenance to the underlying system. Thanks to the automated cloud. But it gets better.&lt;/p&gt;

&lt;p&gt;We can create an AWS account for each developer, which means they can all work completely isolated from each other when they want. And after each merge to our integration branch - after a developer finished a bug or feature - we can automatically test the code in a real environment. We deploy the entire stack to another AWS account, and run automated tests against it as if we were our customers. After finishing up the test run, we delete all the resources again, and barely spent any money for a true end-to-end test.&lt;/p&gt;

&lt;p&gt;All the while, the developers were focused on what they enjoy doing - building things - instead of keeping the systems running, tweaking the configuration of our message queues, adding and removing storage, etcetera. Setups like these have been possible for a long time. But we've only recently arrived at a point where it's become feasible for companies of any size to implement this, without spending much more money on resources or extra developers.&lt;/p&gt;

&lt;p&gt;And none of this is hypothetical.&lt;br&gt;
We've seen and helped our own customers create setups just like this. This is actually used - a lot - in production, and while it will take some getting used to, it will speed up your development enormously. &lt;/p&gt;

&lt;p&gt;Good Infrastructure as Code empowers you, as a developer, and as a company.&lt;/p&gt;

</description>
      <category>infrastructureascode</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
