<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.1.1">Jekyll</generator><link href="https://cloud-blog.kustner.nl/feed.xml" rel="self" type="application/atom+xml" /><link href="https://cloud-blog.kustner.nl/" rel="alternate" type="text/html" /><updated>2021-05-09T06:51:43+02:00</updated><id>https://cloud-blog.kustner.nl/feed.xml</id><title type="html">cloud-blog.kustner.nl</title><subtitle>If I have seen further, it is by standing on the shoulders of giants. -- Isaac Newton</subtitle><entry><title type="html">AWS Lambda Container Image support with CDK</title><link href="https://cloud-blog.kustner.nl/aws/cloud/containers/serverless/cdk/2021/01/26/aws-lambda-container-images.html" rel="alternate" type="text/html" title="AWS Lambda Container Image support with CDK" /><published>2021-01-26T10:50:41+01:00</published><updated>2021-01-26T10:50:41+01:00</updated><id>https://cloud-blog.kustner.nl/aws/cloud/containers/serverless/cdk/2021/01/26/aws-lambda-container-images</id><content type="html" xml:base="https://cloud-blog.kustner.nl/aws/cloud/containers/serverless/cdk/2021/01/26/aws-lambda-container-images.html">&lt;h1 id=&quot;aws-lambda-container-image-support-with-cdk&quot;&gt;AWS Lambda Container Image support with CDK&lt;/h1&gt;

&lt;p&gt;During AWS Re:invent 2020, &lt;a href=&quot;https://aws.amazon.com/blogs/aws/new-for-aws-lambda-container-image-support/&quot;&gt;AWS announced Container Image support for deploying Lambda functions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My plan is to try to use the AWS Cloud Development Kit (CDK) to deploy a python Lambda function as a container image. To proof the functionality, I will build the following:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;A Lambda function that translates a string from English to Italian using Amazon Translate&lt;/li&gt;
  &lt;li&gt;An API Gateway which calls this Lambda so I have a way to test this with a browser&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/assets/container-images.png&quot; alt=&quot;Architecture&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;creating-the-function&quot;&gt;Creating the function&lt;/h1&gt;

&lt;p&gt;I’m using the CDK &lt;a href=&quot;https://docs.aws.amazon.com/cdk/api/latest/python/aws_cdk.aws_lambda/DockerImageFunction.html&quot;&gt;DockerImageFunction construct&lt;/a&gt; to create the function from a local Dockerfile.&lt;/p&gt;

&lt;p&gt;The only thing I need to do in my (typescript) code:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;const dockerfile = path.join(__dirname, &quot;../src&quot;);
const backend = new Lambda.DockerImageFunction(this, &quot;function&quot;, {
    code: Lambda.DockerImageCode.fromImageAsset(dockerfile)
});
backend
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The code above loads the Dockerfile from “../src” to create the container image with Docker.
This construct also takes care of setting up an Amazon Elastic Container Registry (ECR) to store the container image and setup the Lambda executing role for the function.&lt;/p&gt;

&lt;p&gt;The Dockerfile:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;FROM public.ecr.aws/lambda/python:3.8
COPY src/ .
CMD [ &quot;lambda.handler&quot; ]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The FROM retrieves the base image from the public ECR which has been prepared for using with Lambda containers. The COPY command copies the Python lambda code to the container. The CMD runs the Lambda handler when the process is started.&lt;/p&gt;

&lt;p&gt;Linking the Lambda function to apigateway is pretty simple:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;new apigateway.LambdaRestApi(this, 'myapi', {
    handler: backend,
});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;local-testing&quot;&gt;Local testing&lt;/h1&gt;

&lt;p&gt;The process of updating the Lambda is now:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Update local code&lt;/li&gt;
  &lt;li&gt;“cdk deploy” will push the update container image to ECR and replace the Lambda function&lt;/li&gt;
  &lt;li&gt;After the stack update finishes, I can test the URL of the API Gateway&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This process takes almost 2 minutes, which is a lot of time if you want to try a small change.&lt;/p&gt;

&lt;p&gt;So, we want to be able to run the container in a local Docker engine. We can do this like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run -p 9000:8080 -d -v ~/.aws:/root/.aws -e AWS_PROFILE='ricardo' 27a2f4510276
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The AWS Lambda Runtime Interface Emulator (RIE) is a proxy for the Lambda Runtime API that allows you to &lt;a href=&quot;https://docs.aws.amazon.com/lambda/latest/dg/images-test.html&quot;&gt;locally test your Lambda function packaged as a container image&lt;/a&gt;. The RIE is already packaged in our container so we don’t need to do anything for that.&lt;/p&gt;

&lt;p&gt;The docker run above does the following:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;exposes port 9000 locally to port 8080 on the container (this is the RIE webserver)&lt;/li&gt;
  &lt;li&gt;“-d” runs the docker in the backgroun&lt;/li&gt;
  &lt;li&gt;with “-v” I’m mounting my local AWS credentials to the container&lt;/li&gt;
  &lt;li&gt;I’m setting my AWS_PROFILE to tell the AWS SDK which profile to use for my credentials&lt;/li&gt;
  &lt;li&gt;27a2f4510276 is the name of the image that recently created&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By going to this URL, I can test my function locally:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl -XPOST &quot;http://localhost:9000/2015-03-31/functions/function/invocations&quot; -d '{}'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The “/2015-03-31/functions/function/invocations” part is required to talk to your function.&lt;/p&gt;

&lt;p&gt;In this case, the function needs permissions to contact the AWS Translate service but since my AWS credentials have full admin access I don’t need to worry about not having enough permissions (But you could argue this is not the best practise to run my container with Admin privileges).&lt;/p&gt;</content><author><name></name></author><category term="aws" /><category term="cloud" /><category term="containers" /><category term="serverless" /><category term="cdk" /><summary type="html">AWS Lambda Container Image support with CDK</summary></entry><entry><title type="html">Welcome to my Cloud Blog!</title><link href="https://cloud-blog.kustner.nl/aws/cloud/2020/10/05/welcome-to-jekyll.html" rel="alternate" type="text/html" title="Welcome to my Cloud Blog!" /><published>2020-10-05T11:50:41+02:00</published><updated>2020-10-05T11:50:41+02:00</updated><id>https://cloud-blog.kustner.nl/aws/cloud/2020/10/05/welcome-to-jekyll</id><content type="html" xml:base="https://cloud-blog.kustner.nl/aws/cloud/2020/10/05/welcome-to-jekyll.html">&lt;p&gt;This blog serves a couple of purposes for me:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Proof of concept for using the AWS Cloud Development with TypeScript&lt;/li&gt;
  &lt;li&gt;Experiment with Jekyll for a fully static blog which I can update with code&lt;/li&gt;
  &lt;li&gt;Place for me to ramble about Cloud and AWS technology in particular&lt;/li&gt;
&lt;/ul&gt;</content><author><name></name></author><category term="aws" /><category term="cloud" /><summary type="html">This blog serves a couple of purposes for me:</summary></entry><entry><title type="html">Static site with AWS CDK</title><link href="https://cloud-blog.kustner.nl/aws/cloud/cdk/cloudfront/2020/10/05/static-site-with-aws-cdk.html" rel="alternate" type="text/html" title="Static site with AWS CDK" /><published>2020-10-05T11:50:41+02:00</published><updated>2020-10-05T11:50:41+02:00</updated><id>https://cloud-blog.kustner.nl/aws/cloud/cdk/cloudfront/2020/10/05/static-site-with-aws-cdk</id><content type="html" xml:base="https://cloud-blog.kustner.nl/aws/cloud/cdk/cloudfront/2020/10/05/static-site-with-aws-cdk.html">&lt;h1 id=&quot;static-site-with-aws-cdk&quot;&gt;Static site with AWS CDK&lt;/h1&gt;

&lt;p&gt;In this post I will explain how I have setup the AWS CDK and used it to deploy a static site (&lt;em&gt;this site you are looking at!&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html&quot;&gt;AWS CDK Getting Started Guide&lt;/a&gt; has clear instructions on how to get started.&lt;/p&gt;

&lt;p&gt;Recently, I used the Python wrappers for the CDK to setup a PoC with Kinesis Firehose and Amazon ElasticSearch which was fun to do, but the missing documentation on CDK+Python made it a bit challenging and time consuming. So for this experiment I decided to use the “native” TypeScript engine instead.&lt;/p&gt;

&lt;p&gt;My highlevel plan is to:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Use &lt;a href=&quot;https://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt; to deploy this blog you are reading as a static site&lt;/li&gt;
  &lt;li&gt;Use the CDK to:
    &lt;ul&gt;
      &lt;li&gt;Deploy the static content generated by Jekyll to a S3 Bucket&lt;/li&gt;
      &lt;li&gt;Setup the S3 bucket as static hosting&lt;/li&gt;
      &lt;li&gt;Setup a CloudFront distribution that points to this bucket&lt;/li&gt;
      &lt;li&gt;Use AWS Certificate Manager to host the content as https://cloud-blog.kustner.nl&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/assets/cdk-static-site.png&quot; alt=&quot;Architecture&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;jekyll&quot;&gt;Jekyll&lt;/h1&gt;

&lt;p&gt;To get Jekyll installed on my mac, I had to install a newer version of Ruby. It’s been a while since I played with Ruby, but I used the &lt;a href=&quot;https://rvm.io/rvm/about&quot;&gt;Ruby Version Manager&lt;/a&gt; to get the newest version installed.&lt;/p&gt;

&lt;p&gt;Once Jekyll was installed, I created the basic structure for my static blog site:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bundle exec jekyll new myblog
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I could test my site locally (on http://localhost:4000) with:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bundle exec jekyll serve
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To generate static content&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bundle exec jekyll build
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;cdk-static-content-to-s3&quot;&gt;CDK: Static content to S3&lt;/h1&gt;

&lt;p&gt;So, I have a way to create static content locally. Next, I need to get this uploaded to S3.&lt;/p&gt;

&lt;p&gt;With the CDK I need to use these libraries:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npm install @aws-cdk/aws-s3
npm install @aws-cdk/aws-s3-deployment
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;aws-s3 is just like you expect needed for deploying a S3 bucket:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    const websiteBucket = new s3.Bucket(this, 'cloud-blog.kustner.nl', {
      bucketName: 'cloud-blog.kustner.nl',
      versioned: true,
      websiteIndexDocument: 'index.html',
      websiteErrorDocument: 'error.html',
      publicReadAccess: true
    });
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.aws.amazon.com/cdk/api/latest/docs/aws-s3-deployment-readme.html&quot;&gt;aws-s3-deployment&lt;/a&gt; is an &lt;em&gt;experimental&lt;/em&gt; CDK construct which I will be using to upload the static content to the bucket.&lt;/p&gt;

&lt;p&gt;code used to create upload the static assets to my bucket (the Jekyll static site is stored in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./cloud.rkustner.nl/_site/&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   new s3deploy.BucketDeployment(this, 'bucketDeployment', {
      sources: [s3deploy.Source.asset('./cloud.rkustner.nl/_site/')],
      destinationBucket: websiteBucket
    });
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once the static content has been built with Jekyll, I could just run a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cdk deploy&lt;/code&gt; to get the newest content uploaded to S3.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gotcha&lt;/strong&gt;! I still need to get used that you need to compile TypeScript. So I need to do a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm run build&lt;/code&gt; before doing a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cdk deploy&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm run build &amp;amp;&amp;amp; cdk deploy&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Deploying the CDK changes involves running CloudFormation stack updates, which can take a couple of minutes. 
This is not perfect, but since I can test changes locally with the Jekyll “serve” option that is not a big issue.&lt;/p&gt;

&lt;h1 id=&quot;cdk-cloudfront-distribution--certificate&quot;&gt;CDK: CloudFront distribution &amp;amp; Certificate&lt;/h1&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npm install @aws-cdk/aws-cloudfront
npm install @aws-cdk/aws-certificate-manager
npm install @aws-cdk/aws-cloudfront-origins
npm install @aws-cdk/aws-cloudfront-route53
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;As a true professional I want to run my site with https server side encryption.&lt;/p&gt;

&lt;p&gt;First I create the certificate:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    const myCertificate = new acm.Certificate(this, 'CloudKustnerNLCert', {
      domainName: 'cloud-blog.kustner.nl',
      validation: acm.CertificateValidation.fromDns(myHostedZone),
    });
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Another &lt;strong&gt;gotcha&lt;/strong&gt; : If you want to use your own ACM Certificate with CloudFront, you need to deploy the certifcate in the &lt;em&gt;us-east-1&lt;/em&gt; region.&lt;/p&gt;

&lt;p&gt;Next we can create the CloudFront distribution with this certificate and point it to our static bucket:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    const distribution = new cloudfront.Distribution(this, 'BlogDistribution', {
      defaultBehavior: { origin: new origins.S3Origin(websiteBucket) },
      domainNames: ['cloud-blog.kustner.nl'],
      certificate: myCertificate,
    });
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We will also create an ALIAS record that points cloud-blog.rkustner.nl to the new distribution:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    const aliasRecord = new route53.ARecord(this, 'MyAliasRecord', {
      target: route53.RecordTarget.fromAlias(new targets.CloudFrontTarget(distribution)),
      zone: myHostedZone,
      recordName: 'cloud-blog',
    });
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Last but not least, the DefaultTtl for a CloudFront distribution is 36000 seconds, or 10 hours. 
So I want to send an “invalidation” request to CloudFront after the new content is uploaded (this will make sure your visitors see your latest blog content). This is something s3-deployment can also do for you, simply by including the distribution in the deployment call:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    new s3deploy.BucketDeployment(this, 'bucketDeployment', {
      sources: [s3deploy.Source.asset('./cloud.rkustner.nl/_site/')],
      distribution,
      distributionPaths: ['/*'],
      destinationBucket: websiteBucket
    });
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name></name></author><category term="aws" /><category term="cloud" /><category term="cdk" /><category term="cloudfront" /><summary type="html">Static site with AWS CDK</summary></entry></feed>