<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Jirawat Uttayaya DevOps Blog]]></title><description><![CDATA[Jirawat Uttayaya DevOps Blog]]></description><link>https://devops-blog.com</link><image><url>https://cdn.hashnode.com/uploads/logos/69c85d2b7cf270651076d644/6f975ee0-6ff9-4ac1-9c67-39eebca8104b.jpg</url><title>Jirawat Uttayaya DevOps Blog</title><link>https://devops-blog.com</link></image><generator>RSS for Node</generator><lastBuildDate>Thu, 10 Sep 2026 10:08:06 GMT</lastBuildDate><atom:link href="https://devops-blog.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Replace your Azure DevOps with Claude]]></title><description><![CDATA[Introduction

Setup: Learn MCP Server

Setup: Developer MCP Server

Behind the Scene

Reduce Hallucinations

Claude for Observability

Claude as Azure Well-Architected Expert

How expensive is this se]]></description><link>https://devops-blog.com/replace-your-azure-devops-with-claude</link><guid isPermaLink="true">https://devops-blog.com/replace-your-azure-devops-with-claude</guid><category><![CDATA[Azure]]></category><category><![CDATA[Devops]]></category><category><![CDATA[AI]]></category><dc:creator><![CDATA[Jirawat Uttayaya]]></dc:creator><pubDate>Wed, 15 Jul 2026 09:20:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/b477dfe0-0ae2-4b25-b347-cf491f38c921.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<ul>
<li><p><a href="#introduction">Introduction</a></p>
</li>
<li><p><a href="#setup-learn-mcp-server">Setup: Learn MCP Server</a></p>
</li>
<li><p><a href="#setup-developer-mcp-server">Setup: Developer MCP Server</a></p>
</li>
<li><p><a href="#behind-the-scene">Behind the Scene</a></p>
</li>
<li><p><a href="#reduce-hallucinations">Reduce Hallucinations</a></p>
</li>
<li><p><a href="#claude-for-observability">Claude for Observability</a></p>
</li>
<li><p><a href="#claude-as-azure-well-architected-expert">Claude as Azure Well-Architected Expert</a></p>
</li>
<li><p><a href="#how-expensive-is-this-setup">How expensive is this setup?</a></p>
</li>
<li><p><a href="#how-secure-is-this-setup">How secure is this setup?</a></p>
</li>
<li><p><a href="#monitoring-your-ai">Monitoring your AI</a></p>
</li>
<li><p><a href="#the-downsides">The Downsides</a></p>
</li>
<li><p><a href="#what-about-gcp-and-aws">What about GCP and AWS?</a></p>
</li>
<li><p><a href="#conclusion">Conclusion</a></p>
</li>
</ul>
<h3>Introduction</h3>
<p>Claude and cloud goes together like peanut butter and jelly. As of July 2026, the easiest way to use Claude for DevOps work on Azure is the two official Microsoft Azure MCP servers. Microsoft separates its MCP Server into two implementations: the <a href="https://learn.microsoft.com/en-us/training/support/mcp">Azure Learn MCP Server</a> for documentation and <a href="https://learn.microsoft.com/en-us/azure/developer/azure-mcp-server/">Azure Developer MCP Server</a> for transactions.</p>
<p>Once you complete this setup, Claude will be your Azure subject matter expert on <a href="https://learn.microsoft.com/en-us/azure/well-architected/">Azure Well-Architected</a> best practices.</p>
<h3>Setup: Learn MCP Server</h3>
<ol>
<li><strong>Add Azure MCP plugin</strong><br />Start <code>claude</code> and enter the commands below to install the Azure Learn MCP server plugin</li>
</ol>
<pre><code class="language-plaintext">/plugin marketplace add microsoftdocs/mcp
/plugin install microsoft-docs@microsoft-docs-marketplace
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/dd527c31-7d5d-4473-b907-c7813a724e7e.png" alt="" style="display:block;margin:0 auto" />

<ol>
<li><strong>Connect the plugin</strong><br />Type the command below to start using the Azure Learn MCP server in Claude</li>
</ol>
<pre><code class="language-plaintext">/reload-plugins
</code></pre>
<p>The Learn MCP server is free to the public and does not require authentication.</p>
<p>Alternatively, if you choose to manually configure the Claude JSON configuration file, below is the <code>mcpServers</code> block.</p>
<pre><code class="language-json">{
  "mcpServers": {
    "microsoft-learn": {
      "type": "http",
      "url": "https://learn.microsoft.com/api/mcp"
    }
  }
}
</code></pre>
<h3>Setup: Developer MCP Server</h3>
<ol>
<li><p><strong>Create Entra Accounts for AI</strong><br />For infrastructure safety, do not use your regular Azure login for your AI agents. Create separate read-only and read-write <a href="https://learn.microsoft.com/en-us/entra/fundamentals/what-is-entra">Azure Entra IDs</a> for each of your subscriptions. For this example, I created 2 IDs: <code>ai-readonly</code> and <code>ai-readwrite</code>.</p>
<p>For the read-only ID, I assign it the <a href="https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/general#reader">Reader</a> built-in Azure role. For the read-write ID, I assign it the <a href="https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/privileged#owner">Owner</a> role because for any realistic scenario, Claude will need to create and assign IAM. To prevent accidental infrastructure deletions, you can <a href="https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/lock-resources?tabs=json">lock your resources</a> or use <a href="https://learn.microsoft.com/en-us/azure/governance/policy/concepts/effect-deny-action">Azure denyAction policies</a>.</p>
</li>
<li><p><strong>Install npx</strong><br /><a href="https://docs.npmjs.com/cli/v11/commands/npx">npx</a> is the Node.js Package Executor. It runs Node.js packages without installing it locally. The best way to i<a href="https://docs.npmjs.com/downloading-and-installing-node-js-and-npm#using-a-node-version-manager-to-install-nodejs-and-npm">nstall npx</a> is via <a href="https://github.com/nvm-sh/nvm">nvm</a> (Node.js Version Manager)</p>
<pre><code class="language-shell">curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.5/install.sh | bash
source ~/.zshrc
nvm install 24
npx --version
</code></pre>
</li>
<li><p><strong>Configure Claude to use the Azure Developer MCP Server</strong><br />Run the command below to add the Azure Developer MCP Server to Claude AI.</p>
<pre><code class="language-shell">claude mcp add azure-mcp --scope user -- npx -y @azure/mcp@2.0.3 server start
</code></pre>
<p>Confirm the Azure MCP was successfully added</p>
<pre><code class="language-shell">claude mcp list
</code></pre>
</li>
<li><p><strong>Sign into the Azure CLI</strong><br />The Azure Developer MCP Server uses the local <a href="https://learn.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest">Azure CLI (<code>az</code>)</a>, the <a href="https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/install-azd?tabs=winget-windows%2Cbrew-mac%2Cscript-linux&amp;pivots=os-windows">Azure Developer CLI</a> (<code>azd</code>), and the Azure Core Tools (<code>func</code>) to access and modify your Azure resources. Install or upgrade these CLI tools as needed.</p>
<p>Sign in via <code>az login</code> to the correct Azure subscription with the proper Entra ID created on step one.</p>
</li>
</ol>
<h3>Behind the Scene</h3>
<p>The Azure Model Context Protocol (MCP) Server acts as a translator between Claude and Azure. The Learn MCP Server searches the latest Microsoft Learn documentation for the most current answers. The Developer MCP Server configures the Azure CLI commands and executes it locally from your computer.</p>
<p>The Learn MCP server requires no authentication while the Developer MCP server uses the local <code>az login</code> Entra account.</p>
<h3>Reduce Hallucinations</h3>
<p>Claude's knowledge ends on the training date cutoff of the AI model. For example, <a href="https://www.anthropic.com/transparency">Sonnet 4.6</a> training date cutoff was May 2025. If you ask Sonnet 4.6 about Azure HorizonDB](<a href="https://azure.microsoft.com/en-us/products/horizondb">https://azure.microsoft.com/en-us/products/horizondb</a>), it will think it is a fake product since it was first previewed in November 2025.</p>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/86fa252f-99c7-4832-bb31-35f46766b10c.png" alt="" style="display:block;margin:0 auto" />

<p>If you use the Azure Learn MCP server, Claude will use the most current Azure documentation and give you the correct answer about HorizonDB. (I do appreciate the little apology Claude gave me for the first wrong answer).</p>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/3a8f9f43-0def-43af-8653-cdb1d5bf30a9.png" alt="" style="display:block;margin:0 auto" />

<h3>Claude for Observability</h3>
<p>Claude can use your read-only Azure credentials to analyze your Azure infrastructure. As a simple example, I asked Claude to list all my storage accounts buckets. As other examples, you can ask Claude:</p>
<ul>
<li><p><em>"Search Application Insights for errors from the Azure Function my-message-broker"</em></p>
</li>
<li><p><em>"Find all VMs using more than 90% CPU"</em></p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/37884c7e-3cc1-4303-b617-fe9cb7662f01.png" alt="" style="display:block;margin:0 auto" />

<h3>Claude as Azure Well-Architected Expert</h3>
<p>Microsoft published an official set of <a href="https://github.com/MicrosoftDocs/Agent-Skills">AI Skills for Azure</a>. The Azure MCP Servers automatically load these skills without you having to do any additional complicated setup.</p>
<p>Using Claude and the <a href="https://github.com/MicrosoftDocs/Agent-Skills/blob/main/skills/azure-functions/SKILL.md">azure-functions skill,</a> I was able to create and deploy an Azure Function coded with Node.js with full Azure Bicep infrastructure-as-code in about 8 minutes. If I did this by hand before AI, it would have taken me much longer than 8 minutes with equivalent results.</p>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/947c9c3a-ed55-40b1-8c17-191a5bd7ca78.png" alt="" style="display:block;margin:0 auto" />

<h3>How expensive is this setup?</h3>
<p>Good news, it's free (mostly).</p>
<p>The Azure MCP servers are free to use. Of course, you still pay for Claude token usage and any Azure resources created. You can estimate Azure cost via the official <a href="https://azure.microsoft.com/en-us/pricing/calculator/">pricing calculator</a>.</p>
<h3>How secure is this setup?</h3>
<p>This setup passed rigorous review by the Microsoft security team. In summary, the communication is end-to-end encrypted and uses your Entra ID permission setup. In addition, no information is permanently stored on Microsoft servers.</p>
<h3>Monitoring your AI</h3>
<p>Commands executed by the Azure MCP servers on your Azure subscription are auditable in Activity Monitor.</p>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/ffba0096-bdd5-4347-bef6-7ed4439a8924.png" alt="" style="display:block;margin:0 auto" />

<h3>The Downsides</h3>
<ul>
<li><p>As an official Microsoft service, this AI setup uses <code>azd</code> and Azure Bicep as the infrastructure-as-code language. Like 97% of the DevOps community, you most likely use Terraform/OpenTofu. Additional steps are required to convert the answer into Terraform HCL</p>
</li>
<li><p>You may not like the answers if you disagree with the Azure Well-Architected framework.</p>
</li>
<li><p>Claude and most AI systems still offer questionable advice about Day 2 infrastructure operations such as upgrades and maintenance of existing resources. It will sometimes advise to delete infrastructure like databases instead of attempting to modify it.</p>
</li>
</ul>
<h3>What about GCP and AWS?</h3>
<p>Check out our <a href="https://devops-blog.com/series/devops-ai">DevOps AI</a> section for information how to set up MCP servers for GCP and AWS.</p>
<h3>Conclusion</h3>
<p>By powering up Claude with the Azure MCP Servers, it feels like having an Azure DevOps expert sit next to you and offer knowledgeable answers. On top of that, Claude can do the mundane task of creating, deploying, and monitoring Azure infrastructure. This frees you to concentrate on the important stuff, like creative ideas and business strategies.</p>
]]></content:encoded></item><item><title><![CDATA[Replace your AWS DevOps with Claude]]></title><description><![CDATA[Introduction

Setup

Behind the Scene

Reduce Hallucinations

Claude for Observability

Claude as AWS Well-Architected Expert

How expensive is this setup?

How secure is this setup?

Monitoring your ]]></description><link>https://devops-blog.com/replace-your-aws-devops-with-claude</link><guid isPermaLink="true">https://devops-blog.com/replace-your-aws-devops-with-claude</guid><category><![CDATA[AI]]></category><category><![CDATA[AWS]]></category><category><![CDATA[claude]]></category><dc:creator><![CDATA[Jirawat Uttayaya]]></dc:creator><pubDate>Wed, 24 Jun 2026 04:13:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/9f298f65-7a46-4930-95fb-32f8f0b11308.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<ul>
<li><p><a href="#introduction">Introduction</a></p>
</li>
<li><p><a href="#setup">Setup</a></p>
</li>
<li><p><a href="#behind-the-scene">Behind the Scene</a></p>
</li>
<li><p><a href="#reduce-hallucinations">Reduce Hallucinations</a></p>
</li>
<li><p><a href="#claude-for-observability">Claude for Observability</a></p>
</li>
<li><p><a href="#claude-as-aws-well-architected-expert">Claude as AWS Well-Architected Expert</a></p>
</li>
<li><p><a href="#how-expensive-is-this-setup">How expensive is this setup?</a></p>
</li>
<li><p><a href="#how-secure-is-this-setup">How secure is this setup?</a></p>
</li>
<li><p><a href="#monitoring-your-ai">Monitoring your AI</a></p>
</li>
<li><p><a href="#the-downsides">The Downsides</a></p>
</li>
<li><p><a href="#what-about-gcp-and-azure">What about GCP and Azure?</a></p>
</li>
<li><p><a href="#conclusion">Conclusion</a></p>
</li>
</ul>
<h3>Introduction</h3>
<p>Claude and cloud goes together like chocolate and peanut butter. As of June 2026, the easiest and cheapest way to use Claude for AWS DevOps is the official <a href="https://docs.aws.amazon.com/agent-toolkit/latest/userguide/mcp-server.html">AWS MCP Server</a>. This recommended setup bypasses all the hassle of <a href="https://code.claude.com/docs/en/amazon-bedrock">AWS Bedrock</a> or <a href="https://aws.amazon.com/marketplace/pp/prodview-azcxbb24erpd4">AWS Marketplace</a>.</p>
<p>Once you complete this setup, Claude will be your AWS subject matter expert on <a href="https://aws.amazon.com/architecture/well-architected/">AWS Well-Architected</a> best practices.</p>
<h3>Setup</h3>
<ol>
<li><p><strong>Create IAM Roles for AI</strong><br />For infrastructure safety, do not use your regular AWS login for your AI agents. Create separate read-only and read-write <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create.html">AWS IAM roles</a> for each of your environments. For this example, I created 4 roles: <code>ai-dev-ro</code> , <code>ai-dev-rw</code>, <code>ai-prod-ro</code>, and <code>ai-prod-rw</code>.</p>
<p>For the read-only role, I assign it the <a href="https://docs.aws.amazon.com/aws-managed-policy/latest/reference/ReadOnlyAccess.html">ReadOnlyAccess</a> policy. For the read-write role, I assign it the <a href="https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AdministratorAccess.html">AdministratorAccess</a> policy and attach a custom <code>DenyDeleteForAwsMcp</code> IAM policy to prevent accidental deletions.</p>
<pre><code class="language-json">{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DenyDeleteForAwsMcp",
            "Effect": "Deny",
            "Action": [
                "ec2:Terminate*",
                "ec2:Delete*",
                "s3:Delete*",
                "rds:Delete*",
                "dynamodb:Delete*",
                "iam:Delete*"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "aws:CalledViaAWSMCP": "aws-mcp.amazonaws.com"
                }
            }
        }
    ]
}
</code></pre>
<p>Set up authentication configuration the same way as the <a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-authentication.html">AWS CLI</a>.</p>
</li>
<li><p><strong>Install uv</strong><br /><a href="https://github.com/astral-sh/uv">uv</a> is the modern Python package manager. We need it to download and manage the <a href="https://github.com/aws/mcp-proxy-for-aws">MCP Proxy for AWS</a>.</p>
<p>On macOS and Linux</p>
<pre><code class="language-shell">curl -LsSf https://astral.sh/uv/install.sh | sh
</code></pre>
<p>On Windows</p>
<pre><code class="language-shell">powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
</code></pre>
</li>
<li><p><strong>Configure Claude to use the AWS MCP Server</strong><br />Run the command below to add the AWS MCP Server to Claude AI. Replace <code>AWS_MCP_PROXY_PROFILES</code> with the IAM roles created in step 1 and <code>AWS_REGION</code> with the default AWS region.<br />If you are not in the US, replace the URL with <code>https://aws-mcp.eu-central-1.api.aws/mcp</code></p>
<pre><code class="language-shell">claude mcp add aws-mcp --scope user \
  --env AWS_MCP_PROXY_PROFILES="ai-dev-ro ai-dev-rw ai-prod-ro ai-prod-rw" \
  -- uvx mcp-proxy-for-aws==1.6.2 https://aws-mcp.us-east-1.api.aws/mcp \
  --metadata AWS_REGION=us-west-1
</code></pre>
<p>Confirm the AWS MCP was successfully added</p>
<pre><code class="language-shell">claude mcp list
</code></pre>
</li>
<li><p><strong>Edit CLAUDE.md</strong><br />Ensure Claude uses AWS best practices by adding the official AWS AI agent rules. Edit <code>~/.claude/CLAUDE.md</code> and add the contents of <a href="https://github.com/aws/agent-toolkit-for-aws/blob/main/rules/aws-agent-rules.md?plain=1">aws-agent-rules.md</a>.</p>
</li>
</ol>
<h3>Behind the Scene</h3>
<p>The AWS Model Context Protocol (MCP) Server acts as a translator between Claude and AWS. It searches the latest AWS documentation for the most current answers and can execute AWS API calls on your behalf. In order to access your AWS infrastructure, Claude passes your configured AWS IAM authentication credentials to the AWS MCP Server via the MCP Proxy for AWS using the <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html">SigV4</a> protocol.</p>
<h3>Reduce Hallucinations</h3>
<p>Claude's knowledge ends on the training date cutoff of the AI model. For example, <a href="https://www.anthropic.com/transparency">Sonnet 4.6</a> training date cutoff was May 2025. If you ask Sonnet 4.6 the maximum size of an S3 object, it will answer 5 TB, which was the correct answer on May 2025.</p>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/c3ad38f5-d3a6-4bf0-a526-5562ef863ff1.png" alt="" style="display:block;margin:0 auto" />

<p>However in December 2025, AWS increased the maximum S3 object size to <a href="https://aws.amazon.com/about-aws/whats-new/2025/12/amazon-s3-maximum-object-size-50-tb/">50 TB</a>. If you use the AWS MCP Server, Claude will use the most current official AWS documentation to give you the correct answer. (I do appreciate the little apology Claude gave me for the first wrong answer).</p>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/6e5a1bff-6532-4bcc-bbdf-3f0eb865c7d2.png" alt="" style="display:block;margin:0 auto" />

<h3>Claude for Observability</h3>
<p>Claude can use your read-only AWS credentials to analyze your AWS infrastructure. As a simple example, I asked Claude to list all my Simple Storage Service (S3) buckets using the read-only AWS dev account. As other examples, you can ask Claude:</p>
<ul>
<li><p><em>"Search for CloudWatch log errors in the Lambda function my-message-broker"</em></p>
</li>
<li><p><em>"Find all EC2 VMs using more than 90% CPU"</em></p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/1dfd4ed4-72e2-4695-b052-0e0a5882897f.png" alt="" style="display:block;margin:0 auto" />

<h3>Claude as AWS Well-Architected Expert</h3>
<p>Amazon publishes an official set of <a href="https://github.com/aws/agent-toolkit-for-aws/tree/main/skills">AI skills for AWS</a>. The AWS MCP Server automatically loads these skills without you having to do any additional complicated setup.<br />Using Claude and the aws-serverless skill, I was able to create and deploy a Lambda function coded with Node.js with full AWS CDK infrastructure-as-code in about 6 minutes. If I did this by hand before AI, it would have taken me much longer than 6 minutes with equivalent results.</p>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/c2d81982-9be0-4728-ad4b-65c77c082fbd.png" alt="" style="display:block;margin:0 auto" />

<h3>How expensive is this setup?</h3>
<p>Good news, it's free (mostly).</p>
<p>The AWS MCP server is free to use. Of course, you still pay for Claude token usage and any AWS resources created. Sometimes, the MCP Server will need to create an S3 bucket to store objects in your account.</p>
<h3>How secure is this setup?</h3>
<p>This setup passed rigorous review by the AWS security team. You can read the <a href="https://docs.aws.amazon.com/agent-toolkit/latest/userguide/security.html">full technical details</a>. In summary, the communication is end-to-end encrypted and uses your IAM permission setup. In addition, no information is permanently stored on AWS servers.</p>
<h3>Monitoring your AI</h3>
<p>The AWS MCP Server stores its metrics under <code>CloudWatch &gt; AWS-MCP &gt; ToolName</code> .</p>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/e76366d9-0624-4bb1-b6fe-40d85a9c90f2.png" alt="" style="display:block;margin:0 auto" />

<p>All commands executed by the AWS MCP server on your AWS account are auditable in CloudTrail under Event Source <code>aws-mcp.amazonaws.com</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/2a106a19-e2e5-4aa1-b1b8-fc0866086c96.png" alt="" style="display:block;margin:0 auto" />

<h3>The Downsides</h3>
<ul>
<li><p>As an official AWS service, this AI setup uses CloudFormation/SAM/CDK as the infrastructure-as-code language. Like 97% of the DevOps community, you most likely use Terraform/OpenTofu. Additional steps are required to convert the answer into Terraform HCL</p>
</li>
<li><p>You may not like the answers if you disagree with the AWS Well-Architected framework.</p>
</li>
<li><p>Claude and most AI systems still offer questionable advice about Day 2 infrastructure operations such as upgrades and maintenance of existing resources. It will sometimes advise to delete infrastructure like databases instead of attempting to modify it.</p>
</li>
</ul>
<h3>What about GCP and Azure?</h3>
<p>Check out our <a href="https://devops-blog.com/series/devops-ai">DevOps AI</a> section for information how to set up MCP servers for GCP and Azure.</p>
<h3>Conclusion</h3>
<p>By powering up Claude with the AWS MCP Server, it feels like having an AWS DevOps expert sit next to you and offer knowledgeable answers. On top of that, Claude can do the mundane task of creating, deploying, and monitoring AWS infrastructure. This frees you to concentrate on the important stuff, like creative ideas and business strategies.</p>
]]></content:encoded></item><item><title><![CDATA[My DEPT® Engineering Blog]]></title><description><![CDATA[As of July 2026, it is my 5th anniversary working at DEPT® Agency and I continue to love my tenure there.
I used to post at the DEPT® Engineering Blog. I still post there, but I used to too.
While you]]></description><link>https://devops-blog.com/my-dept-engineering-blog</link><guid isPermaLink="true">https://devops-blog.com/my-dept-engineering-blog</guid><dc:creator><![CDATA[Jirawat Uttayaya]]></dc:creator><pubDate>Mon, 15 Jun 2026 05:21:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/f2afbe95-a2af-4b55-a0bc-4b823b06a225.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As of July 2026, it is my 5th anniversary working at <a href="https://www.deptagency.com/">DEPT® Agency</a> and I continue to love my tenure there.</p>
<p>I used to post at the <a href="https://engineering.deptagency.com/author/jirawat">DEPT® Engineering Blog</a>. I still post there, but I used to too.</p>
<p>While you are there, check out some of the other great articles from my colleagues.</p>
]]></content:encoded></item><item><title><![CDATA[DevOps Quick Fix: GCP outgoing connection issues]]></title><description><![CDATA[Originally published athttps://engineering.deptagency.com/fix-gcp-connection-issues
Problem
From Google Cloud Platform (GCP), your outgoing HTTPS connections to third-party REST APIs are slow or dropp]]></description><link>https://devops-blog.com/devops-quick-fix-gcp-outgoing-connection-issues</link><guid isPermaLink="true">https://devops-blog.com/devops-quick-fix-gcp-outgoing-connection-issues</guid><category><![CDATA[GCP]]></category><dc:creator><![CDATA[Jirawat Uttayaya]]></dc:creator><pubDate>Wed, 23 Aug 2023 14:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/343fe887-f7c7-4463-af62-39b4fe7d86f5.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Originally published at<br /><a href="https://engineering.deptagency.com/fix-gcp-connection-issues">https://engineering.deptagency.com/fix-gcp-connection-issues</a></p>
<h2><strong>Problem</strong></h2>
<p>From Google Cloud Platform (GCP), your outgoing HTTPS connections to third-party REST APIs are slow or dropping.</p>
<h2>Solution</h2>
<h3><strong>Preamble</strong></h3>
<p>The cause of the issue is most likely GCP Cloud NAT port exhaustion.</p>
<p>If you are using private network Compute Engine, GKE, or any of the GCP serverless services like Cloud Run, your outgoing connections are going through Cloud NAT.</p>
<p>Cloud NAT needs a unique 5-tuple [source IP, source port, destination IP/port/protocol] to make an outgoing connection. If all the 5-tuples are used, the connections are slowed or dropped. This is known as NAT port exhaustion.</p>
<h3><strong>Turn off Endpoint-Independent Mapping</strong></h3>
<p>You can read the gnarly technical details about <a href="https://docs.cloud.google.com/nat/docs/ports-and-addresses#example-conflict-eim">Endpoint-Independent Mapping conflicts</a>, but bottom-line, EIM is more trouble that it is worth. Turn EIM off and increase the "Minimum ports per VM instances" setting (2048 is a good starting option).</p>
<p>Steps:</p>
<ol>
<li><p>In the GCP console, go to <a href="https://console.cloud.google.com/net-services/nat/list">Cloud NAT</a></p>
</li>
<li><p>Click your Cloud NAT Gateway link</p>
</li>
<li><p>Click the "Edit" button on top, then click "<strong>Advanced Configuration</strong>"</p>
</li>
<li><p>Uncheck "<strong>Enable Endpoint-Independent Mapping</strong>" and increase the "<strong>Minimum port per VM instance"</strong> value</p>
</li>
<li><p>Click the "<strong>Save</strong>" button at the bottom</p>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/5affaa9c-6831-44b8-aecc-b900e72379e5.png" alt="" style="display:block;margin:0 auto" /></li>
</ol>
<h3>Optional: Enable Dynamic Port Allocation</h3>
<p><a href="https://cloud.google.com/nat/docs/ports-and-addresses#dynamic-port">Dynamic Port Allocation</a> will scale up the number of VM ports when it senses port exhaustion. The main issue is connections can drop during scaling. I usually prefer to turn it off and set the "Minimum ports per VM instance" to a high number.</p>
<p>If you prefer to turn on "Dynamic Port Allocation", set the minimum port high to reduce the chance of dropped connections.</p>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/7a8e928d-e429-4c67-8095-ca754c06c552.png" alt="" style="display:block;margin:0 auto" />

<h3>Optional: Assign more IPs to Cloud NAT</h3>
<p>If you are using static reserved IPs for Cloud NAT because of third-party API firewall allow-lists, you can manually add more reserved IPs to reduce port exhaustion.</p>
<p>Steps:</p>
<ol>
<li><p>In GCP console, go to <a href="https://console.cloud.google.com/net-services/nat/list">Cloud NAT</a>AT</p>
</li>
<li><p>Click your <strong>Cloud NAT Gateway</strong> link</p>
</li>
<li><p>Click the "<strong>Edit</strong>" button on top, then go to the "<strong>Cloud NAT mapping"</strong> section.</p>
</li>
<li><p>Click the "<strong>+ ADD IP ADDRESS</strong>" button to add more IPs to Cloud NAT</p>
</li>
<li><p>Click the "<strong>Save</strong>" button at the bottom</p>
</li>
</ol>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/99aaf3ef-39bd-464c-9168-9d71457eb2da.png" alt="" style="display:block;margin:0 auto" />]]></content:encoded></item><item><title><![CDATA[Add hard disk to VMware Linux VM]]></title><description><![CDATA[There are two easy steps to add a hard disk for a VMware Linux VM.

Assign a new hard disk in VMware vSphere

Configure the new hard disk in CentOS


This example assigns a new 5 GB hard disk as the /]]></description><link>https://devops-blog.com/add-disk-vmware-linux</link><guid isPermaLink="true">https://devops-blog.com/add-disk-vmware-linux</guid><category><![CDATA[vmware]]></category><category><![CDATA[Linux]]></category><category><![CDATA[centos]]></category><dc:creator><![CDATA[Jirawat Uttayaya]]></dc:creator><pubDate>Fri, 26 Oct 2018 05:21:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/194e3a78-1c86-40b0-9ae0-95ab75f78eff.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There are two easy steps to add a hard disk for a VMware Linux VM.</p>
<ol>
<li><p>Assign a new hard disk in VMware vSphere</p>
</li>
<li><p>Configure the new hard disk in CentOS</p>
</li>
</ol>
<p>This example assigns a new 5 GB hard disk as the <code>/backup</code> directory on CentOS 7</p>
<h2><strong>Assign hard disk in vSphere</strong></h2>
<ol>
<li><p>In VMware vSphere, right click on the VM and select <strong>"Edit Settings..."</strong></p>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/336c55cd-cc38-48ee-9739-ca126a1409c8.webp" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>In the <strong>"New device:"</strong> section, select <strong>"SCSI Controller"</strong>, and click the <strong>"OK"</strong> button. Note, there is a hard limit of 4 SCSI Controllers per VM.</p>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/5f3676d0-ee96-4428-957d-7c6a5fa23d33.webp" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>Right click <strong>"Edit Settings..."</strong> again and select <strong>"New Hard Disk"</strong></p>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/a604baf0-a0e1-465a-a471-50332ee75ede.webp" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>Input the byte size of the new hard disk (in this example, 5 GB). In the <strong>"Virtual Device Node"</strong> section, assign the new SCSI controller number. Click the <strong>"OK"</strong> button.</p>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/acc3fbef-44fd-4e2d-8149-5e2a275ea0f1.webp" alt="" style="display:block;margin:0 auto" /></li>
</ol>
<h2><strong>Configure new hard disk in CentOS</strong></h2>
<ol>
<li><p>SSH into the CentOS VM and sudo to root<br /><code>sudo su -</code></p>
</li>
<li><p>List the block device to see the newly assigned vSphere hard disk.<br /><code>lsblk</code>  </p>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/c60f5aaa-fa3c-4717-b623-48616bce19e9.webp" alt="" style="display:block;margin:0 auto" />

<p>If you do not see the vSphere hard disk, force a rescan</p>
<pre><code class="language-shell">for host in $(ls -1d /sys/class/scsi_host/);
  do echo "- - -" &gt; ${host}/scan
done

for device in $(ls -1d /sys/class/scsi_disk/);
  do echo "1" &gt; ${device}/device/rescan
done
</code></pre>
</li>
<li><p>Format the disk partition. Get the device name from the previous <em>lsblk</em> output<br /><code>fdisk /dev/sdb</code><br />See the screenshot for the options you should pick<br /><em>n (new partition)<br />p (primary)<br />(Press ENTER) (Use default partition number)<br />(Press ENTER) (Use default first sector)<br />(Press ENTER) (Use default last sector)<br />t (change the partition type)<br />8e (Linux LVM)<br />w (write)</em></p>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/6ea93cef-06ae-420f-b064-8482ae535531.webp" alt="" />

</li>
<li><p>List the block device again to display the new disk partition /dev/sdb1<br /><code>lsblk</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/2b4fe6d3-03f4-4b15-97d5-37c19eb60c0c.webp" alt="" />
</li>
<li><p>Initialize the physical volume<br /><code>pvcreate /dev/sdb1</code><br /><em>T</em>o display the new physical volume<br /><code>pvs</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/27e18c16-daed-4364-9354-e06bef4c01a8.webp" alt="" />
</li>
<li><p>Create the volume group<br />Note: vgBackup is just an name for this example. The volume group name can be whatever you want<br /><code>vgcreate vgBackup /dev/sdb1</code><br />To display the volume group<br /><code>vgs</code></p>
</li>
<li><p>Create the logical volume for the volume group<br />Note: lvBackup is just an name for this example. The logical volume name can be whatever you want<br /><code>lvcreate -n lvBackup -l +100%FREE vgBackup</code><br />To display the logical volume<br /><code>lvs</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/b1de7bb2-6c45-4597-b02a-e4c44a542525.webp" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>Construct an XFS filesystem on the new logical volume<br /><code>mkfs.xfs /dev/vgBackup/lvBackup</code>  </p>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/f4234b3b-f600-4af9-bb60-4bd5992d8261.webp" alt="" style="display:block;margin:0 auto" />

  
</li>
<li><p>Edit the text file <strong>/etc/fstab</strong> and add the line below:</p>
<pre><code class="language-plaintext">/dev/vgBackup/lvBakup /backup xfs defaults 1 2
</code></pre>
</li>
<li><p>Mount a Unix directory to the logical volume<br /><code>mkdir -p /backup</code><br /><code>mount /backup</code></p>
</li>
<li><p>You now have a new 5 GB hard disk assigned as the <code>/backup</code> directory</p>
<img src="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/bfccc567-b487-4636-8473-08bccf6e2af9.webp" alt="" style="display:block;margin:0 auto" /></li>
</ol>
<p>To learn more about Unix Logical Volumes, go to official <a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/logical_volume_manager_administration/lvm_definition">RedHat LVM docs</a></p>
]]></content:encoded></item><item><title><![CDATA[Debugging a mystery Unix server]]></title><description><![CDATA[I was given an Unix server to administer with no runbook. The immediate task was to find the application listening on port 8888, make some modifications, and restart.
Step 1: Find process listening on]]></description><link>https://devops-blog.com/debugging-a-mystery-unix-server</link><guid isPermaLink="true">https://devops-blog.com/debugging-a-mystery-unix-server</guid><category><![CDATA[unix]]></category><dc:creator><![CDATA[Jirawat Uttayaya]]></dc:creator><pubDate>Tue, 22 Jan 2013 06:21:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/fadebe93-d548-477c-8233-7a533d574428.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I was given an Unix server to administer with no runbook. The immediate task was to find the application listening on port 8888, make some modifications, and restart.</p>
<h3>Step 1: Find process listening on port 8888</h3>
<p>The <a href="https://man7.org/linux/man-pages/man8/netstat.8.html">netstat</a> command shows the network statistics on a Unix server, including which process is listening to what port</p>
<p><code>netstat -plan | grep 8888</code>  </p>
<p>The output is</p>
<blockquote>
<p>tcp     0   0 :::8888   :::*    LISTEN      2700/java </p>
</blockquote>
<p>This shows that a java program with Process ID (PID) 2700 is listening on port 8888</p>
<h3>Step 2: Find process info of PID 2700</h3>
<p>The <a href="https://man7.org/linux/man-pages/man1/ps.1.html">ps</a> command shows the current process snapshot.</p>
<p><code>ps -fp 2700</code>  </p>
<p>The output is</p>
<blockquote>
<p>oracle  2700   1  0 18:55 ?     0:00:02 <br />java -Dapex.port=8888 -jar /home/oracle/listener/apex.war</p>
</blockquote>
<p>PID 2700 is a Java program executing apex.war as the Unix user oracle. A quick Google search reveals that Oracle publishes a product called <a href="https://www.oracle.com/apex/">Oracle Apex</a>.</p>
<h3>Step 3: Find the configuration and log files</h3>
<p>The <a href="https://man7.org/linux/man-pages/man8/lsof.8.html">lsof</a> command lists open files by PID. This can help us find configuration files and log directories.</p>
<p><code>lsof -p 2700</code></p>
<p>The output is</p>
<blockquote>
<p>java    2700 oracle    2w   REG 3,1 1700 1796967 /tmp/apex_listener.log<br />java    2700 oracle    3r   REG. 3,65. 9828505  134585 /home/oracle/listener/apex.war<br />java    2700 oracle    4r   REG 3,1 51796975  361047 /usr/java/jdk1.6.0_20/jre/lib/rt.jar<br />java    2700 oracle    5r   REG. 3,65  186902  132940 /home/oracle/config/apex.xml</p>
</blockquote>
<p>With a bit of deductive reasoning, we know the configuration file is at /home/oracle/config/apex.xml and the log file is located at /tmp/apex_listener.log</p>
<h3>Step 4: Stop and start the server</h3>
<p>After editing the apex.xml configuration file, most java programs require a restart to apply the new settings. If you scroll back up to Step 2 and look at the <code>ps</code> output, the number after PID 2700 in the third column is the parent PID 1.</p>
<p>The command</p>
<p><code>ps -fp 1</code></p>
<p>gives the output</p>
<blockquote>
<p>root    1     0  0 18:54 ?    00:00:00 init [5]</p>
</blockquote>
<p>The <a href="https://linux.die.net/man/8/init">init</a> command is the process that executes when Unix first boots up.  The startup scripts are in directory <em><strong>/etc/init.d</strong></em></p>
<div>
<div>💡</div>
<div>Note from 2026: This article was first written in 2013, hence the XML config file and the init command. In 2026, it would be YML config files and systemd at PID 1.</div>
</div>

<p>The <a href="https://man7.org/linux/man-pages/man1/find.1.html">find</a> command to find which script stops and starts Oracle Apex</p>
<p><code>find /etc/init.d -type f -exec grep -Hi apex {} \;</code></p>
<p>The output is</p>
<blockquote>
<p>/etc/init.d/oracle-apex:   su - oracle -c "/home/oracle/apex/listener.sh start"</p>
<p>/etc/init.d/oracle-apex:   su - oracle -c "/home/oracle/apex/listener.sh restart"</p>
<p>/etc/init.d/oracle-apex:   su - oracle -c "/home/oracle/apex/listener.sh stop"</p>
</blockquote>
<p>Reading the <code>oracle-apex</code> Bash script, the command to restart Oracle Apex is</p>
<p><code>/etc/init.d/oracle-apex restart</code></p>
]]></content:encoded></item><item><title><![CDATA[Optimize Java DNS Lookup]]></title><description><![CDATA[Prefer IPv4
Starting with version 4, Java performs both IPv6 and IPv4 DNS lookups. If the DNS server is not set up to properly respond to IPv6 queries, then Java will wait for the IPv6 query to time o]]></description><link>https://devops-blog.com/optimize-java-dns-lookup</link><guid isPermaLink="true">https://devops-blog.com/optimize-java-dns-lookup</guid><category><![CDATA[Java]]></category><dc:creator><![CDATA[Jirawat Uttayaya]]></dc:creator><pubDate>Tue, 08 Jan 2013 06:21:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/9ffa0ae7-a0a8-4184-9142-a615a9587c0f.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3><strong>Prefer IPv4</strong></h3>
<p>Starting with version 4, Java performs both IPv6 and IPv4 DNS lookups. If the DNS server is not set up to properly respond to IPv6 queries, then Java will wait for the IPv6 query to time out. This can manifest in what looks like network slowdowns.</p>
<p>To bypass IPv6 DNS lookups, set the Java System property <code>java.net.preferIPv4Stack</code> to true.</p>
<p>You can set it on the command line</p>
<p><code>java -Djava.net.preferIPv4Stack=true ...</code></p>
<p>Or you can set the propery in the Java Code itself </p>
<pre><code class="language-java">System.setProperty("java.net.preferIPv4Stack","true");
</code></pre>
<h3><code>   </code>I<strong>ncrease cache time</strong></h3>
<p>When a Java 6 security manager is not set, the default DNS cache is 30 seconds.  To reduce network DNS queries, the number of seconds of DNS cache can be increased by setting the <code>networkaddress.cache.ttl</code> System property.  Set this property to <code>-1</code> to never expire the DNS cache.  </p>
<p>Command line:  </p>
<p><code>java -Dnetworkaddress.cache.ttl=-1 ...</code></p>
<p>Java code:</p>
<pre><code class="language-java">System.setProperty("networkaddress.cache.ttl","-1");
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Find Unused Unix Ports]]></title><description><![CDATA[Problem
You need to bring up another Unix web server but port 443 is already in use. How do you find another unused Unix port?
Solution
Use the netstat command to discover which ports are already used]]></description><link>https://devops-blog.com/find-unused-unix-ports</link><guid isPermaLink="true">https://devops-blog.com/find-unused-unix-ports</guid><category><![CDATA[unix]]></category><dc:creator><![CDATA[Jirawat Uttayaya]]></dc:creator><pubDate>Mon, 07 Jan 2013 06:21:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69c85d2b7cf270651076d644/f0b7a765-0d6e-47cb-91df-85efeb35c1cc.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Problem</strong></p>
<p>You need to bring up another Unix web server but port 443 is already in use. How do you find another unused Unix port?</p>
<p>Solution</p>
<p>Use the <a href="https://man7.org/linux/man-pages/man8/netstat.8.html">netstat</a> command to discover which ports are already used</p>
<p><code>netstat -ln | grep LISTEN | awk '{print $4}' | grep ":" | sort | uniq</code></p>
<p>Breakdown of commands</p>
<p><code>netstal -ln</code> : List all the numerical Unix ports that are listening for network traffic</p>
<p><code>grep LISTEN</code> : Display the output lines that are in LISTEN status</p>
<p><code>awk '{print $4}</code> : Print the fourth column of the output that has the port numbers that Unix processed are LISTENING</p>
<p><code>sort | uniq</code> : Sort the output and only show unique values</p>
<p>You will get an output similar to</p>
<blockquote>
<p>0.0.0.0:443</p>
<p>0.0.0.0:5353<br />0.0.0.0:68<br />0.0.0.0:80<br />10.0.2.15:123<br />::1:10089<br />::1:123</p>
</blockquote>
<p>The number after the last colon is the port in use, e.g. 443, 80, 123, 5353.  Pick any Unix port not already in use and assigned.</p>
]]></content:encoded></item></channel></rss>