<?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: Peter Koech </title>
    <description>The latest articles on DEV Community by Peter Koech  (@petekip).</description>
    <link>https://dev.to/petekip</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F170563%2F986b1442-c573-4b90-ab26-ee957e87da3c.jpg</url>
      <title>DEV Community: Peter Koech </title>
      <link>https://dev.to/petekip</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/petekip"/>
    <language>en</language>
    <item>
      <title>Running Our AWS Deployments From Slack With Amazon Q (and the Things Nobody Tells You)</title>
      <dc:creator>Peter Koech </dc:creator>
      <pubDate>Fri, 11 Sep 2026 09:47:33 +0000</pubDate>
      <link>https://dev.to/petekip/running-our-aws-deployments-from-slack-with-amazon-q-and-the-things-nobody-tells-you-2b6p</link>
      <guid>https://dev.to/petekip/running-our-aws-deployments-from-slack-with-amazon-q-and-the-things-nobody-tells-you-2b6p</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwrg08vjowyrdlxrvlucv.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwrg08vjowyrdlxrvlucv.png" alt=" " width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the last couple of years, most of the day-to-day deployment work on one of the platforms I look after has happened inside a single private Slack channel. Nobody opens the CodePipeline console to kick off a staging build. Nobody SSHs anywhere to restart a container. A developer types something like this and gets on with their day:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Amazon Q run start-pipeline-dev2
@Amazon Q run switch-branch-dev1 feature/my-branch
@Amazon Q run cont-restart api-cluster api-stg5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The service behind this is Amazon Q Developer in chat applications, which most of us still call by its older name, AWS Chatbot. (AWS has renamed it more than once. The console currently lists it under "ChatOps for AWS". I'll mostly say Chatbot here because that's what everyone on the team says.)&lt;/p&gt;

&lt;p&gt;I recently wrote an internal manual on how our setup actually works, because too much of it lived in my head and in one colleague's Slack history. This post is a cleaned-up version of that document with names and identifiers replaced. If you're thinking about ChatOps on AWS, or you inherited a Chatbot setup and want to understand it, this should save you some digging.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it actually is
&lt;/h2&gt;

&lt;p&gt;Chatbot is a thin, authenticated proxy between a Slack channel and the AWS SDK. That's the whole mental model. It takes a message, resolves it to an API call, checks whether the call is allowed, makes the call under an IAM role, and posts results back. There is no agent running in your account, no secrets stored in Slack, no database of commands.&lt;/p&gt;

&lt;p&gt;Two independent flows are worth keeping separate in your head:&lt;/p&gt;

&lt;p&gt;Commands are synchronous. Slack → Chatbot → AWS service. You type it, it runs.&lt;/p&gt;

&lt;p&gt;Notifications are asynchronous. AWS service → SNS topic → Chatbot → Slack. Pipeline stage changes, CloudWatch alarms and so on get published to an SNS topic that the channel configuration is subscribed to. Chatbot formats the payload and drops it in the channel.&lt;/p&gt;

&lt;p&gt;Once you internalise that the second path is just an SNS subscription, a lot of troubleshooting gets easier. When notifications stop arriving, it's almost always the subscription or the topic, not Chatbot itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  The message pipeline, step by step
&lt;/h2&gt;

&lt;p&gt;When someone mentions the bot in the channel, this happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slack forwards the message event to the Chatbot endpoint via the registered Slack App.&lt;/li&gt;
&lt;li&gt;Chatbot looks up the alias. start-pipeline-prod expands to something like codepipeline start-pipeline-execution --name myapp-prod --region us-east-1.&lt;/li&gt;
&lt;li&gt;Chatbot evaluates the action against both the IAM role it runs under and the guardrail policies attached to the channel. Fail either one and you get an access denied message in Slack.&lt;/li&gt;
&lt;li&gt;The SDK call is made directly against the service. For standard commands there's no Lambda in the middle.&lt;/li&gt;
&lt;li&gt;State changes flow back through SNS as described above.
One thing that surprised a few people on the team: Chatbot doesn't keep command history. If you need to know who stopped the staging pipeline on Tuesday, the answer is in CloudTrail, filtered by the Chatbot role. Slack's own history helps too, but CloudTrail is the record.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Two permission layers, and why you want both
&lt;/h2&gt;

&lt;p&gt;This is the part I'd read twice if you're setting this up.&lt;/p&gt;

&lt;p&gt;The IAM role is the execution boundary. Chatbot assumes it for every API call. It defines the ceiling of everything that could possibly happen through any channel using that role. Ours was created from the "policies from a template" option in the console and then trimmed.&lt;/p&gt;

&lt;p&gt;The guardrail policies are the channel boundary. They're attached to a specific channel configuration, and they only ever restrict. They never grant. The effective permission set is the intersection of the two.&lt;/p&gt;

&lt;p&gt;Why bother with the second layer? Because you can share one IAM role across several channels and give each channel a different effective scope. Our production channel and a wider engineering channel can point at the same role while only one of them is allowed to touch prod pipelines. It also means a Slack user who gets added to the wrong channel by accident can't do anything the guardrail doesn't already allow for that channel.&lt;/p&gt;

&lt;p&gt;The cost is that "access denied" now has two possible causes. When it happens, go to CloudTrail, find the denied action, and check which layer is missing it. Don't guess.&lt;/p&gt;

&lt;p&gt;Aliases are what make it usable&lt;/p&gt;

&lt;p&gt;Chatbot accepts raw SDK commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Amazon Q codepipeline start-pipeline-execution --name myapp-prod --region eu-west-1

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nobody wants to type that. Aliases map a short name to the full command, and you can pass parameters through at runtime. @Amazon Q alias list shows everything registered, with the expansions.&lt;/p&gt;

&lt;h2&gt;
  
  
  When a single SDK call isn't enough: Lambda aliases
&lt;/h2&gt;

&lt;p&gt;Some things can't be expressed as one API call. Branch switching is the obvious example. To repoint a pipeline's source stage at a different branch you have to &lt;code&gt;GetPipeline&lt;/code&gt;, edit the source stage in the returned definition, and &lt;code&gt;UpdatePipeline&lt;/code&gt; with the modified document. That's a small Lambda function.&lt;/p&gt;

&lt;p&gt;Chatbot handles this fine. The alias just becomes &lt;code&gt;lambda invoke --function-name branch-switch-fn&lt;/code&gt;, and the function does the multi-step work and returns a message.&lt;/p&gt;

&lt;p&gt;The detect-changes family works the same way. It flips PollForSourceChanges on the source stage so a pipeline stops auto-triggering on push. We use it when a staging environment needs to be frozen for QA while people keep merging into the branch. Set it to false, test, set it back to true.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wiring an existing Lambda into Chatbot
&lt;/h2&gt;

&lt;p&gt;This bit trips people up, so here's the order that works.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Fix the Lambda's resource-based policy:&lt;/strong&gt; The function has to trust the Chatbot service principal explicitly. Having &lt;code&gt;lambda:InvokeFunction&lt;/code&gt; on the IAM role is not enough.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws lambda get-policy &lt;span class="nt"&gt;--function-name&lt;/span&gt; FUNCTION_NAME &lt;span class="nt"&gt;--region&lt;/span&gt; eu-west-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If chatbot.amazonaws.com isn't in there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws lambda add-permission &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--function-name&lt;/span&gt; FUNCTION_NAME &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--statement-id&lt;/span&gt; AllowChatbot &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--action&lt;/span&gt; lambda:InvokeFunction &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--principal&lt;/span&gt; chatbot.amazonaws.com &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; eu-west-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Update the guardrail:&lt;/strong&gt; In the channel configuration, make sure the guardrail policy includes &lt;code&gt;lambda:InvokeFunction&lt;/code&gt; scoped to the function ARN. Without this, the role can permit it all day and Chatbot will still refuse.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;3. Register the alias in Slack:&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Amazon Q alias add switch-branch-dev1 lambda invoke --function-name branch-switch-fn --region eu-west-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Test it and check the CloudWatch log group:&lt;/strong&gt; for the function to confirm the invocation actually arrived. If the command fails silently, it's step 1 nine times out of ten.&lt;/p&gt;

&lt;h2&gt;
  
  
  Things that have bitten us
&lt;/h2&gt;

&lt;p&gt;I'll finish with the troubleshooting table from the manual, because it's the part I look at most.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bot doesn't respond at all:&lt;/strong&gt; The Slack App authorisation expired or the OAuth token was revoked. Reconnect the Slack client in the Chatbot console.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access denied:&lt;/strong&gt; Check CloudTrail for the exact denied action, then figure out which of the two permission layers is missing it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pipeline notifications stopped:&lt;/strong&gt; Someone deleted the SNS subscription or recreated the topic. Re-subscribe the channel configuration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get-logs gives an expired link:&lt;/strong&gt; The pre-signed S3 URL lives for ten minutes. Our failure notifications include a pre-filled get-logs command for exactly this reason. Run it as soon as you see the red message.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lambda alias fails silently:&lt;/strong&gt; Resource-based policy is missing the Chatbot principal. See above.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Branch switch does nothing:&lt;/strong&gt; Usually a typo in the branch name, occasionally an expired GitHub token inside the function. The Lambda logs will tell you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;detect-changes false didn't stop auto-triggering:&lt;/strong&gt; Confirm with GetPipeline that the flag actually changed. Run it again and check with pipeline-status.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Was it worth it?
&lt;/h2&gt;

&lt;p&gt;Yes, with one caveat. The setup took an afternoon. The value came from being disciplined about aliases and guardrails, and from writing down where everything lives, since the Chatbot console, the IAM role, the SNS topic, and the Slack channel ID are spread across four different places and none of them link to each other.&lt;/p&gt;

&lt;p&gt;If you run a small team where developers regularly need to deploy to shared environments, this removes a surprising amount of friction and a surprising number of interruptions. Just decide early that CloudTrail is your audit log and the guardrail is your safety net, and you'll be fine.&lt;/p&gt;

&lt;p&gt;Happy to answer questions in the comments if you're setting something similar up.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>chatops</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Amazon S3 + Cloudflare Cloud Connector magic</title>
      <dc:creator>Peter Koech </dc:creator>
      <pubDate>Sat, 25 Jan 2025 09:06:30 +0000</pubDate>
      <link>https://dev.to/petekip/amazon-s3-cloudflare-cloud-connector-magic-392f</link>
      <guid>https://dev.to/petekip/amazon-s3-cloudflare-cloud-connector-magic-392f</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/aws-builders" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&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%2Forganization%2Fprofile_image%2F2794%2F88da75b6-aadd-4ea1-8083-ae2dfca8be94.png" alt="AWS Community Builders " width="350" height="350"&gt;
      &lt;div class="ltag__link__user__pic"&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%2Fuser%2Fprofile_image%2F170563%2F986b1442-c573-4b90-ab26-ee957e87da3c.jpg" alt="" width="800" height="800"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/aws-builders/securely-host-your-static-website-in-amazon-s3-using-cloudflares-cloudconnector-2mkn" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Securely host your static website in Amazon S3 using Cloudflare's CloudConnector&lt;/h2&gt;
      &lt;h3&gt;Peter Koech  for AWS Community Builders  ・ Jan 25&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#aws&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#s3&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#cloudflarechallenge&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#cloudcomputing&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>aws</category>
      <category>cloudcomputing</category>
      <category>cloudflare</category>
    </item>
    <item>
      <title>Securely host your static app in Amazon S3 using Cloudflare's CloudConnector</title>
      <dc:creator>Peter Koech </dc:creator>
      <pubDate>Sat, 25 Jan 2025 09:00:06 +0000</pubDate>
      <link>https://dev.to/aws-builders/securely-host-your-static-website-in-amazon-s3-using-cloudflares-cloudconnector-2mkn</link>
      <guid>https://dev.to/aws-builders/securely-host-your-static-website-in-amazon-s3-using-cloudflares-cloudconnector-2mkn</guid>
      <description>&lt;p&gt;I am going to demonstrate how to use Amazon S3 to host your objects or a static website and use Cloudflare as a Content Distribution Network (CDN).&lt;/p&gt;

&lt;p&gt;Amazon S3 is an industry-leading object storage service offering unrivaled scalability, performance, and availability. &lt;/p&gt;

&lt;p&gt;Cloudflare is one of the leading stand-alone Content Distribution Network (CDN), Amazon CloudFront is AWS's service that offers CDN and a host of other powerful features. &lt;/p&gt;

&lt;p&gt;Normally users would use Amazon S3 and CloudFront to achieve the demo below, but some organizations have deployed Cloudflare as a dedicated CDN service in their infrastructure &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%2Fncp61e0lg5cojo3jab7w.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%2Fncp61e0lg5cojo3jab7w.png" alt=" " width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Amazon S3
&lt;/h3&gt;

&lt;p&gt;We will create a simple static website: &lt;a href="http://stellar-landing.s3-website-us-east-1.amazonaws.com" rel="noopener noreferrer"&gt;http://stellar-landing.s3-website-us-east-1.amazonaws.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's usually a breeze using AWS CLI or SDK since you only run a couple of commands to get up and running. As you may be aware, every service in AWS can be interacted with through an API call. &lt;/p&gt;

&lt;p&gt;So let me demonstrate, how we can set up &lt;em&gt;stellar-landing&lt;/em&gt; bucket using AWS CLI.&lt;/p&gt;

&lt;h4&gt;
  
  
  Create the bucket using AWS CLI
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;aws s3 mb s3://stellar-landing&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Access the console and enable public access for the bucket, allowing you to run the subsequent commands. 
&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%2F17eqn7yxinsj8l9ln0xl.png" alt=" " width="800" height="281"&gt;
&lt;/li&gt;
&lt;li&gt;On your terminal, create a json file, we can name it "public-read.json" and inside it, you can place this policy which tells the bucket to allow everyone on the internet denoted by principal "*" to GET objects
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
{
  "Version":"2012-10-17",
  "Statement":[
    {
      "Sid":"PublicReadGetObject",
      "Effect":"Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource":"arn:aws:s3:::stellar-landing/*"
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We need to run a  &lt;strong&gt;put-bucket-policy&lt;/strong&gt; that updates the bucket's policy to allow for accessibility to the public.&lt;br&gt;
&lt;br&gt;
&lt;code&gt;aws s3api put-bucket-policy --bucket stellar-landing --policy file://public-read.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To configure the bucket for static web hosting, you can use the put-bucket-website command:&lt;br&gt;
&lt;br&gt;
&lt;code&gt;aws s3 website s3://stellar-landing/ --index-document index.html --error-document error.html&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, AWS CLI only has three commands to get a static site hosted. I can demonstrate how to do the same via the Console (point and click)&lt;/p&gt;

&lt;h4&gt;
  
  
  Create the bucket using AWS Console
&lt;/h4&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%2Ffem1fjl3gy5ekz22sxtj.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%2Ffem1fjl3gy5ekz22sxtj.png" alt=" " width="800" height="275"&gt;&lt;/a&gt;&lt;br&gt;
Log into the console, then search for Amazon S3, click on it and the click on Create Bucket. Give it a name and leave the other options as is.&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%2Fqzjkb332f4rf4b6ne80l.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%2Fqzjkb332f4rf4b6ne80l.png" alt=" " width="800" height="281"&gt;&lt;/a&gt;&lt;br&gt;
Go to the permissions tab, then uncheck the checkbox for &lt;em&gt;block all public access&lt;/em&gt; &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%2Fz0efkm4wneb6x8jn8eaw.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%2Fz0efkm4wneb6x8jn8eaw.png" alt=" " width="800" height="321"&gt;&lt;/a&gt;&lt;br&gt;
Attach the bucket policy to enable &lt;strong&gt;GetObjet&lt;/strong&gt; requests for all users (principals)&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%2F48ys6ikx0wvdbcjqic6s.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%2F48ys6ikx0wvdbcjqic6s.png" alt=" " width="800" height="324"&gt;&lt;/a&gt;&lt;br&gt;
Go to the properties tab; you will need to make two key change, under &lt;em&gt;Static website hosting&lt;/em&gt; select on &lt;strong&gt;Enable&lt;/strong&gt; then under &lt;em&gt;Hosting type&lt;/em&gt; select &lt;strong&gt;Host a static website&lt;/strong&gt;&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%2Fe5h1pb1fkgxlvqj5gv7l.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%2Fe5h1pb1fkgxlvqj5gv7l.png" alt=" " width="800" height="219"&gt;&lt;/a&gt;&lt;br&gt;
Afterwards, you'll notice an endpoint provisioned for your public bucket, it follows this pattern; the name of the bucket &lt;em&gt;stellar-landing&lt;/em&gt; followed by &lt;em&gt;s3-website-us-east-1.amazonaws.com&lt;/em&gt; thus the final link &lt;a href="http://stellar-landing.s3-website-us-east-1.amazonaws.com" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  CloudFlare CDN
&lt;/h3&gt;

&lt;p&gt;Now that we have our bucket up and running, before Cloudflare's connector service, it was nearly impossible to use CloudFlare as a CDN for Amazon S3 buckets to be hosted in CloudFlare, most methods were too complex as detailed in this link by Jaroslav &lt;a href="https://medium.com/@hranicka/hosting-a-static-website-amazon-s3-cloudflare-127b57a13461" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then came Cloud Connector &lt;a href="https://developers.cloudflare.com/rules/cloud-connector/" rel="noopener noreferrer"&gt;Link&lt;/a&gt; from CloudFlare, a service that enables us to route matching incoming traffic from our static website hosted in Amazon S3 bucket &lt;a href="http://stellar-landing.s3-website-us-east-1.amazonaws.com" rel="noopener noreferrer"&gt;Link&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Steps to enable and configure Cloud Connector
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt;&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%2F88yu6fhedln6lw3trhrp.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%2F88yu6fhedln6lw3trhrp.png" alt=" " width="800" height="475"&gt;&lt;/a&gt;&lt;br&gt;
Log in to your CloudFlare console, then under Rules, click on Select Amazon S3&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt;&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%2Fa99rrdtsci737482cjil.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%2Fa99rrdtsci737482cjil.png" alt=" " width="800" height="439"&gt;&lt;/a&gt;&lt;br&gt;
Enter your bucket URL where your traffic can be directed to the URL via CNAME, select your bucket URL from your Amazon S3 console, it should be &lt;code&gt;stellar-landing.s3-website-us-east-1.amazonaws.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3&lt;/strong&gt;&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%2F79ohi2ulx1e2jkz55rzp.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%2F79ohi2ulx1e2jkz55rzp.png" alt=" " width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configure your Cloud Connector, give it a name such as &lt;code&gt;stellar-landing-cdn&lt;/code&gt; under &lt;em&gt;If incoming requests match&lt;/em&gt; Select custom filter expression &lt;/li&gt;
&lt;li&gt;Under &lt;em&gt;When incoming requests match&lt;/em&gt;; Select &lt;strong&gt;&lt;em&gt;Field&lt;/em&gt;&lt;/strong&gt; as &lt;em&gt;URI Full&lt;/em&gt;, then under &lt;strong&gt;&lt;em&gt;Operator&lt;/em&gt;&lt;/strong&gt; select &lt;em&gt;Contains&lt;/em&gt;, then for &lt;strong&gt;&lt;em&gt;Value&lt;/em&gt;&lt;/strong&gt;  enter your preferred friendly URL that you wish your bucket to be referred to e.g &lt;code&gt;https://stellar-landing.nation.africa&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;** Step 4**&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%2Fdm4nlon5oeycuqdah291.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%2Fdm4nlon5oeycuqdah291.png" alt=" " width="800" height="297"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Still in Cloudflare under DNS menu on the left, select Records&lt;/li&gt;
&lt;li&gt;Then click on &lt;strong&gt;&lt;em&gt;Add record&lt;/em&gt;&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;For &lt;em&gt;**Type&lt;/em&gt;* select &lt;em&gt;CNAME&lt;/em&gt;, then under &lt;strong&gt;&lt;em&gt;Name&lt;/em&gt;&lt;/strong&gt; provide an ideal name for your Amazon S3 hosted website e.g &lt;code&gt;stellar-landing&lt;/code&gt; and finally under &lt;strong&gt;&lt;em&gt;Target&lt;/em&gt;&lt;/strong&gt;, enter your S3 bucket endpoint &lt;code&gt;stellar-landing.s3-website-us-east-1.amazonaws.com&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;To enable SSL for your new endpoint on Cloudflare, click the &lt;strong&gt;&lt;em&gt;Proxy status&lt;/em&gt;&lt;/strong&gt; toggle; it should change to orange. This indicates that requests will now be proxied securely through CloudFlare.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can now securely access your statically hosted website via this link &lt;a href="https://stellar-landing.nation.africa" rel="noopener noreferrer"&gt;Link&lt;/a&gt; i.e &lt;code&gt;https://stellar-landing.nation.africa&lt;/code&gt; as opposed to non secure Amazon S3 endpoint: &lt;code&gt;http://stellar-landing.s3-website-us-east-1.amazonaws.com/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;PS: &lt;em&gt;The template for the static website is owned by @ajlkn &lt;a href="https://twitter.com/ajlkn" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>s3</category>
      <category>cloudflarechallenge</category>
      <category>cloudcomputing</category>
    </item>
    <item>
      <title>Scaling down the storage of a MySQL RDS database with zero downtime using AWS Blue/Green Deployment</title>
      <dc:creator>Peter Koech </dc:creator>
      <pubDate>Tue, 21 Jan 2025 21:29:24 +0000</pubDate>
      <link>https://dev.to/aws-builders/scaling-down-the-size-of-a-mysql-rds-database-with-zero-downtime-using-aws-bluegreen-deployment-46al</link>
      <guid>https://dev.to/aws-builders/scaling-down-the-size-of-a-mysql-rds-database-with-zero-downtime-using-aws-bluegreen-deployment-46al</guid>
      <description>&lt;p&gt;As a DevOps engineer, you will find yourself optimizing and tinkering the RDS databases powering your workloads, you probably know the struggle with updating databases especially if you have heavy workloads depending on them. The risk of experiencing downtime during production is high. Traditional database management often leads to a catch-22 situation where you want to update your database for better performance but fear database downtime. &lt;/p&gt;

&lt;p&gt;Well, worry no more! In this article, we will explore the AWS Blue/Green Deployment method that allows you to change your Relational Database Service (RDS) with &lt;em&gt;zero downtime&lt;/em&gt;. Yes, you read that right: &lt;strong&gt;ZERO downtime&lt;/strong&gt;, and it works like magic!&lt;/p&gt;

&lt;p&gt;From explaining the Blue/Green Deployment strategy to providing a step-by-step guide on how you can utilize this in AWS, this article covers everything you need to know when updating your RDS database instance without compromising availability.&lt;/p&gt;

&lt;p&gt;So, let's dive straight in!&lt;/p&gt;

&lt;h3&gt;
  
  
  Preparation
&lt;/h3&gt;

&lt;p&gt;You need to identify a time when your dev team will not be performing any releases and also an ideal time when you have the least traffic on your workloads. &lt;/p&gt;

&lt;p&gt;It's a good DevOps practice to notify the larger team of what time you schedule to perform such changes. &lt;/p&gt;

&lt;p&gt;I will demonstrate downscaling DB's instance storage volume in this case while using Blue/Green deployment with zero downtime. &lt;/p&gt;

&lt;p&gt;The same exercise can be achieved using either &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS RDS Console&lt;/li&gt;
&lt;li&gt;AWS CLI&lt;/li&gt;
&lt;li&gt;AWS SDK&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For our exercise, we will use the &lt;strong&gt;AWS RDS Console&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;NB&lt;/strong&gt; &lt;em&gt;Before performing Blue/Green deployments for either a MySQL or Mariad-based RDS instance, please enable &lt;strong&gt;automated backups&lt;/strong&gt;  &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithAutomatedBackups.Enabling.html" rel="noopener noreferrer"&gt;link&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1
&lt;/h4&gt;

&lt;p&gt;For our demo, we will scale the storage space from 400 GB to 200 GB. Our database cluster is made up of a master and 3 replicas as shown below. &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%2F2bz47ga1gke7ujji472p.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%2F2bz47ga1gke7ujji472p.png" alt="Image description" width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the master database from the cluster&lt;/li&gt;
&lt;li&gt;Click on &lt;em&gt;actions&lt;/em&gt; then click on &lt;em&gt;Create Blue/Green Deployment&lt;/em&gt; from the drop-down menu to open the "Blue" screen&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Step 2
&lt;/h4&gt;

&lt;p&gt;We need to create a copy of the production environment, here referred to as the Blue environment to a staging environment referred to as Green&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%2F2o0el06a3bfz64phpm0o.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%2F2o0el06a3bfz64phpm0o.png" alt="Image description" width="800" height="305"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Give your Blue/Green deployment an identifier name, remember the identifier is case-insensitive, but is stored as all lowercase.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 3
&lt;/h4&gt;

&lt;p&gt;The next step is configuring the Blue/Green deployment by specifying the ideal database engine and the parameter group for your Green environment.&lt;/p&gt;

&lt;p&gt;For our case, since we are interested in downsizing the storage size, we will use the same engine version and parameter group as the Blue environment (Production DB)&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%2Fiu24k6ew3dnv7zkyi9ga.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%2Fiu24k6ew3dnv7zkyi9ga.png" alt="Image description" width="800" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 4
&lt;/h4&gt;

&lt;p&gt;This step entails configuring your Green instance database type; for our case, we will use use the same instance as Blue.&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%2Fjjhx2y9yosusbwmvvk62.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%2Fjjhx2y9yosusbwmvvk62.png" alt="Image description" width="800" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 5
&lt;/h4&gt;

&lt;p&gt;Our main task is focussing on downsizing the allocated storage for the Green deployment.&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%2Fj85eavt5lty25lsfwdqj.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%2Fj85eavt5lty25lsfwdqj.png" alt="Image description" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The configuration update on AWS console will be done on one screen and will be replicated across the entire database cluster. &lt;/p&gt;

&lt;p&gt;Remember we are scaling down storage for the master database and it's 3 replicas as shown in the figures below.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Side-by-side view of the Blue and Green master Deployments highlighting the updates.&lt;/li&gt;
&lt;/ul&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%2Frrotihbe1um4nczsm31z.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%2Frrotihbe1um4nczsm31z.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Side-by-side view of the Blue/Green database replicas highlighting the changes made&lt;/li&gt;
&lt;/ul&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%2Fjgqale0tixwa9myalxbb.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%2Fjgqale0tixwa9myalxbb.png" alt="Image description" width="800" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you confirm all is looking good, a few things to note at this stage is that the cost of the Green deployment will be shown before you hit the &lt;em&gt;create&lt;/em&gt; button. &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%2F5cktkq8xyvzh20y8af2r.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%2F5cktkq8xyvzh20y8af2r.png" alt="Image description" width="800" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Blue/Green will take anything between a few minutes to hours, this is dictated by factors such as the size of the database, how busy the workloads running off the database are, and the number of replicas. &lt;/p&gt;

&lt;p&gt;For our case, it took about 5 hours for the Green deployment to be ready and it worked like &lt;strong&gt;magic&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Zero downtime, only a bit of lag on the Primary cluster (Blue) environment. &lt;/p&gt;

&lt;p&gt;A lot of the magic happens under the hood, AWS handles renaming the Green deployment's DB cluster naming convention to match Blue environment, including updating the Endpoints for the Master and Replicas. &lt;/p&gt;

&lt;p&gt;You won't need to update your application's configuration, the most I did is notifying the dev team via Slack about this exercise.&lt;/p&gt;

</description>
      <category>bluegreen</category>
      <category>rds</category>
      <category>aws</category>
      <category>mysql</category>
    </item>
  </channel>
</rss>
