<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4912226416400969049</id><updated>2026-06-25T13:40:55.976+01:00</updated><category term="DevOps"/><category term="Software Engineering"/><category term="Linux"/><category term="Ubuntu"/><category term="AWS"/><category term="C++"/><category term="Kubernetes"/><category term="Data Science"/><category term="Docker"/><category term="Terraform"/><category term="Python"/><category term="Go"/><category term="Machine Learning"/><category term="C#"/><category term="JavaScript"/><category term="Networking"/><category term="Windows"/><category term="Computer Vision"/><category term="Elasticsearch"/><category term="Security"/><category term="AWS EKS"/><category term="MFC"/><category term="MySQL"/><category term="Unix"/><category term="AWS EC2"/><category term="Node.js"/><category term="VSCode"/><category term="Visual Studio"/><category term="Amazon Elastic Kubernetes Service"/><category term="GUI"/><category term="NSIS"/><category term="DB"/><category term="Design Patterns"/><category term="IIS"/><category term="Interview"/><category term="Jetson"/><category term="SSH"/><category term="TypeScript"/><category term="VirtualBox"/><category term="Async"/><category term="Computer architecture"/><category term="STL"/><category term="git"/><category term="kubectl"/><category term="AI"/><category term="AWS IAM"/><category term="Anaconda"/><category term="Ansible"/><category term="Axis2C"/><category term="DNS"/><category term="Load Balancing"/><category term="System Architecture"/><category term="Bash"/><category term="GCP"/><category term="Google Cloud"/><category term="Helm"/><category term="NVIDIA"/><category term="PostgreSQL"/><category term="Web Services"/><category term="conda"/><category term="logging"/><category term="makefile"/><category term="video"/><category term=".NET"/><category term="AWS EC2 Auto scaling"/><category term="Autoscaling"/><category term="ELK"/><category term="GNU"/><category term="GitHub"/><category term="HTTP"/><category term="Karpenter"/><category term="Mac"/><category term="Minikube"/><category term="OIDC"/><category term="OpenCV"/><category term="Rollup.js"/><category term="System Design"/><category term="Unit Testing"/><category term="Virtualenv"/><category term="WCF"/><category term="environment variables"/><category term="multithreading"/><category term="osx"/><category term="string"/><category term=".NET Core"/><category term="AWS EBS"/><category term="AWS S3"/><category term="Agentic AI"/><category term="Babel"/><category term="Batch file"/><category term="Boost"/><category term="Coursera"/><category term="DB dump"/><category term="DynamoDB"/><category term="EKS"/><category term="ESLint"/><category term="Firewall"/><category term="Grafana"/><category term="Hardware"/><category term="IP"/><category term="JSON"/><category term="JetPack"/><category term="Jetson Nano"/><category term="Jupyter Notebook"/><category term="Kibana"/><category term="Lambda"/><category term="MacOS"/><category term="Monitoring"/><category term="NMAKE"/><category term="OpenID"/><category term="R"/><category term="SQL"/><category term="TCP/IP"/><category term="TDD"/><category term="Unicode"/><category term="Wi-Fi"/><category term="Wireshark"/><category term="XML"/><category term="XML Data Binding"/><category term="YAML"/><category term="cryptography"/><category term="docker-compose"/><category term="g++"/><category term="make"/><category term="nvm"/><category term="AWS EFS"/><category term="AWS ELB"/><category term="AWS Lambda"/><category term="AWS RDS"/><category term="AWS SQS"/><category term="AWS VPC"/><category term="Amazon GuardDuty"/><category term="Amazon Kinesis"/><category term="C"/><category term="CAS"/><category term="CI/CD"/><category term="CMake"/><category term="CUDA"/><category term="Claude Code"/><category term="Cloud Storage"/><category term="CloudWatch"/><category term="Cloudflare"/><category term="Confluence"/><category term="DOS"/><category term="DVD"/><category term="Debugging"/><category term="Deployment"/><category term="Doxygen"/><category term="ECK"/><category term="Endianness"/><category term="Filesystem"/><category term="GPU"/><category term="GParted"/><category term="GitHub Actions"/><category term="Graphviz"/><category term="Hacking"/><category term="IPv6"/><category term="Image Segmentation"/><category term="JupyterLab"/><category term="LLM"/><category term="Linter"/><category term="Meld"/><category term="Merge"/><category term="Metrics"/><category term="Microservices"/><category term="MySQL Workbench"/><category term="NUnit"/><category term="Neural Networks"/><category term="Nmap"/><category term="OOP"/><category term="Object Detection"/><category term="Observability"/><category term="PHP"/><category term="Packer"/><category term="Pingdom"/><category term="QA"/><category term="RStudio"/><category term="Redis"/><category term="Resources"/><category term="SOAP"/><category term="Serverless"/><category term="TPL"/><category term="TeamCity"/><category term="TensorFlow"/><category term="Tools"/><category term="VPC"/><category term="VS Code"/><category term="Vagrant"/><category term="Virtualenvwrapper"/><category term="Vue.js"/><category term="Web Applications"/><category term="Web Server"/><category term="Yarn"/><category term="curl"/><category term="gdb"/><category term="mysqlsh"/><category term="npm"/><category term="psql"/><category term="scp"/><category term="sed"/><category term="vi"/><category term="wget"/><category term="ACL"/><category term="AI Agents"/><category term="AKS"/><category term="API Proxy"/><category term="AWS AMI"/><category term="AWS CLI"/><category term="AWS CodeDeploy"/><category term="AWS ECS"/><category term="AWS Fargate"/><category term="AWS IAM Identity Center"/><category term="AWS S2S VPN"/><category term="AWS SNS"/><category term="AWS Secrets Manager"/><category term="Access Control List"/><category term="Agile"/><category term="Algorithms"/><category term="Alpine"/><category term="Altinity"/><category term="Amazon API Gateway"/><category term="Amazon Bedrock"/><category term="Amazon CloudWatch"/><category term="Amazon ElastiCache"/><category term="Amazon Kinesis Data Streams"/><category term="Amazon Linux"/><category term="Amazon RDS"/><category term="ArgoCD"/><category term="Axios"/><category term="Azure Kubernetes Service"/><category term="Bazel"/><category term="Big  O Notation"/><category term="BitLocker"/><category term="Browser"/><category term="Browserify"/><category term="CDN"/><category term="CI"/><category term="COM"/><category term="CRI"/><category term="Caffe"/><category term="Checkly"/><category term="Chromium"/><category term="Claude"/><category term="Clickhouse"/><category term="Cloud"/><category term="Cloud CDN"/><category term="Cloud DNS"/><category term="CloudFront"/><category term="Cluster Autoscaler"/><category term="CodeSynthesis"/><category term="Coding Practices"/><category term="Compute Engine"/><category term="Containerization"/><category term="Cygwin"/><category term="DLL"/><category term="Data Binding"/><category term="DevSecOps"/><category term="Diff"/><category term="EBS"/><category term="Eclipse"/><category term="Fast R-CNN"/><category term="Faster R-CNN"/><category term="Fiddler"/><category term="Freeware"/><category term="Frontend"/><category term="GKE"/><category term="GPG"/><category term="GStreamer"/><category term="GTK"/><category term="GeminiAI"/><category term="Gimp"/><category term="Ginkgo"/><category term="GitHub CLI"/><category term="GitOps"/><category term="Google"/><category term="Google Colab"/><category term="Google Kubernetes Engine"/><category term="Grafana Loki"/><category term="Gulp"/><category term="Guththila"/><category term="H2O"/><category term="HCP"/><category term="HPA"/><category term="HandBrake"/><category term="HashiCorp Cloud Provider"/><category term="Horizontal Pod Autoscaler"/><category term="IAM"/><category term="IAM Identity Center"/><category term="IEEE802.11"/><category term="INetCfg"/><category term="IPv4"/><category term="IaaS"/><category term="Idiom"/><category term="Image Classification"/><category term="Image Processing"/><category term="Image Recognition"/><category term="Image editor"/><category term="ImageMagick"/><category term="Ingress"/><category term="Instance Segmentation"/><category term="Integration Testing"/><category term="JIRA"/><category term="JQL"/><category term="JSON Spirit"/><category term="Jest"/><category term="Kali Linux"/><category term="Krew"/><category term="KubePug"/><category term="Kubent"/><category term="LAMP"/><category term="Linker"/><category term="Logstash"/><category term="MCP"/><category term="Meetup"/><category term="Memory dump"/><category term="MongoDB"/><category term="NAT"/><category term="NVIDIA DIGITS"/><category term="Ncat"/><category term="NetBIOS"/><category term="Nginx"/><category term="Notepad++"/><category term="Object Localization"/><category term="Object Recognition"/><category term="OpenVpn"/><category term="Overfeat"/><category term="PKA"/><category term="PaaS"/><category term="Pluto"/><category term="Port forwarding"/><category term="Postman"/><category term="Proxy"/><category term="PyDev"/><category term="PyInstaller"/><category term="PyWin32"/><category term="Qt"/><category term="R-CNN"/><category term="RawCap"/><category term="Refactoring"/><category term="RegEx"/><category term="RequireJS"/><category term="Router"/><category term="S3"/><category term="SAML"/><category term="SMB"/><category term="SOA"/><category term="SRE"/><category term="SSD"/><category term="SSO"/><category term="Scrapy"/><category term="Security Group"/><category term="Semantic Segmentation"/><category term="Site24x7"/><category term="Sliding Window"/><category term="Software"/><category term="SourceTree"/><category term="Static Code Analysis"/><category term="Stored Procedure"/><category term="TAP"/><category term="TSLint"/><category term="Taskbar"/><category term="TensorRT"/><category term="Terminal"/><category term="Terraform Cloud"/><category term="Tray icon"/><category term="UAC"/><category term="UML"/><category term="Unsupervised Machine Learning"/><category term="VLC"/><category term="VPN"/><category term="VertexAI"/><category term="Viber"/><category term="Virtualization"/><category term="WAF"/><category term="WSDL"/><category term="Web scraping"/><category term="WinDbg"/><category term="Windows API"/><category term="Xerces"/><category term="YOLO"/><category term="airmon-ng"/><category term="brew"/><category term="chmod"/><category term="chown"/><category term="containerd"/><category term="cron"/><category term="crontab"/><category term="ffmpeg"/><category term="functor"/><category term="gSOAP"/><category term="gcc"/><category term="gh"/><category term="heredoc"/><category term="jq"/><category term="kubeadm"/><category term="manipulator"/><category term="map"/><category term="ngrok"/><category term="node-gyp"/><category term="open-source"/><category term="pgAdmin"/><category term="ping"/><category term="pip"/><category term="pip3"/><category term="read"/><category term="tar"/><category term="templates"/><category term="terraform-docs"/><category term="vim"/><category term="webcam"/><category term="wxPython"/><category term="yq"/><title type='text'>My Public Notepad</title><subtitle type='html'>Bits and bobs about computers and programming</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>521</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-3529066834690095782</id><published>2026-06-25T13:36:56.911+01:00</published><updated>2026-06-25T13:40:55.976+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><category scheme="http://www.blogger.com/atom/ns#" term="Elasticsearch"/><category scheme="http://www.blogger.com/atom/ns#" term="ELK"/><title type='text'>Elastic Fleet</title><content type='html'>&lt;div style=&quot;text-align: left;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7qLkLic0epYIvdZbBJnuqSenEUW6phHFhy7NwIMPStBFpK32N1pDKR1uC3yadR5rHC2lM9Oa1FZ6mwWqa-7_nn_FOywTR8AWHWja8zLzC3zTZPwjW1-mVveRDYf6GkeFmeIcu3WUx7ShhHANRlw5QljhlF4996mm5p8tCFtiIkiMhquW59ixEcZfTUIw/s2400/elasticsearch-logo-png-transparent.png&quot; style=&quot;margin-left: 1em; margin-right: 1em; text-align: center;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;2400&quot; data-original-width=&quot;2400&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7qLkLic0epYIvdZbBJnuqSenEUW6phHFhy7NwIMPStBFpK32N1pDKR1uC3yadR5rHC2lM9Oa1FZ6mwWqa-7_nn_FOywTR8AWHWja8zLzC3zTZPwjW1-mVveRDYf6GkeFmeIcu3WUx7ShhHANRlw5QljhlF4996mm5p8tCFtiIkiMhquW59ixEcZfTUIw/w640-h640/elasticsearch-logo-png-transparent.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Elastic Agents do not strictly require Fleet and Fleet Server. You can deploy them in standalone mode, which allows you to manually configure and manage them using local configuration files.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;However, running Elastic Agents in Fleet-managed mode with a Fleet Server is the recommended best practice for most enterprise environments.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Here is how the two approaches compare:&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;1. Fleet-Managed Mode (Recommended)&lt;/h4&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;In this setup, you use the Fleet UI in Kibana to centrally manage agent policies, roll out upgrades, and apply integrations.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;How it works: Agents connect to a Fleet Server (which is just a specialized Elastic Agent process), which then receives policies from Elasticsearch and pushes them to your endpoints.&lt;/li&gt;&lt;li&gt;Best for: Large-scale deployments, continuous monitoring, and Elastic Security/Endpoint integrations.&lt;/li&gt;&lt;li&gt;Action: To set this up, refer to the official Elastic Agent Installation Guide.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;2. Standalone Mode&lt;/h4&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;In this setup, you manually install the agent and define its inputs, outputs, and integrations directly in a local YAML configuration file.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;How it works: The agent connects directly to outputs like Elasticsearch or Logstash without a Fleet Server intermediary.&lt;/li&gt;&lt;li&gt;Limitations: Central management, automated upgrades, and certain advanced Endpoint Security features are disabled.&lt;/li&gt;&lt;li&gt;Best for: Edge cases, highly air-gapped networks, or evaluating specific integrations.&lt;/li&gt;&lt;li&gt;Action: To configure this, use the steps outlined in the Standalone Elastic Agent Tutorial.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;Example of how an Elastic Fleet can actually be wired&lt;/h1&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Components &amp;amp; where they live&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Everything is in cluster company-prod-elastic-eks (EKS, us-east-2, now on v1.36.2), namespace elastic-system, across 5 nodes in 3 AZs:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;Node&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AZ&amp;nbsp; Node Group&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Runs&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;====&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ==&amp;nbsp; ==========&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;====&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;ip-10-99-44-1&amp;nbsp; &amp;nbsp;2a&amp;nbsp; es MNG (m7g.2xlarge)&amp;nbsp; &amp;nbsp;agent&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;ip-10-99-55-34&amp;nbsp; 2b&amp;nbsp; default MNG (m5.large) agent + Fleet Server pod&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;ip-10-99-55-89&amp;nbsp; 2b&amp;nbsp; es MNG (m7g.2xlarge)&amp;nbsp; &amp;nbsp;agent&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;ip-10-99-66-51&amp;nbsp; 2c&amp;nbsp; es MNG (m7g.2xlarge)&amp;nbsp; &amp;nbsp;agent&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;ip-10-99-66-78&amp;nbsp; 2c&amp;nbsp; default MNG (m5.large) agent&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Fleet Server — Deployment fleet-server-prod, replicas: 1 (single pod, currently on the 2b node). Listens on :8220 HTTPS. Exposed by a NodePort service fleet-server-prod-agent-http (8220 --&amp;gt; 32202 on every node).&lt;/li&gt;&lt;li&gt;Elastic Agents — DaemonSet agent-prod-eck-agent, one pod per node (5 total), spread across all 3 AZs. hostNetwork: true, mode: fleet, FLEET_INSECURE=true. They collect node/pod logs + metrics (hostPath mounts of /var/log/...).&lt;/li&gt;&lt;li&gt;ALB k8s-elastics-eckfleet-a1b2c3d4e5 — internal (not internet-facing), spanning subnets in 2a / 2b / 2c. Created by the AWS LB controller from Ingress eck-fleet-server-prod-ingress. Targets = all 5 nodes&#39; NodePort 32202 (instance mode), backend-protocol: HTTPS, idle_timeout: 300s.&lt;/li&gt;&lt;li&gt;DNS — eck-fleet-server.internal-domain.local (Route53 via external-dns) --&amp;gt;&amp;nbsp; the internal ALB. Elasticsearch is a separate endpoint, elasticsearch.internal-domain.local:443.&lt;/li&gt;&lt;/ul&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Who listens, who initiates&lt;/h4&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The key thing: every connection is initiated by the agent (outbound). Nothing is ever pushed to the agents — that&#39;s why this works with agents behind hostNetwork and no inbound rules of their own.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span style=&quot;font-size: xx-small;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: xx-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;┌───────────────────────────────────────────────┐&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;│ cluster company-prod-elastic-eks / elastic-sys│&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;┌──────────┐&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;│&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;│ Agent&amp;nbsp; &amp;nbsp; │ check-in │&amp;nbsp; &amp;nbsp;internal ALB&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Fleet Server (1 pod)&amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;│ DaemonSet│─────────►│&amp;nbsp; eckfleet-a1b2...&amp;nbsp; &amp;nbsp;┌──────► :8220 (HTTPS)&amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;│ (5 pods, │&amp;nbsp; :443&amp;nbsp; &amp;nbsp; │&amp;nbsp; :443 TLS&amp;nbsp; ─────────┘&amp;nbsp; NodePort 32202→8220&amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;│&amp;nbsp; 3 AZs)&amp;nbsp; │&amp;nbsp; HTTPS&amp;nbsp; &amp;nbsp;│&amp;nbsp; (internal cert)&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;kube-proxy → the 1 pod │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;└────┬─────┘&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;▲&amp;nbsp; re-encrypt HTTPS to a node&#39;s :32202&amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;│&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │ ship data&amp;nbsp; &amp;nbsp; &amp;nbsp; └───────┼─────────────────────┼─────────────────┘&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │ (logs/metrics)&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;│ DNS&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;│ writes .fleet-* / agent&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ▼&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;eck-fleet-server.&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ▼ metadata, reads policy&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp;elasticsearch.&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;internal-domain.local&amp;nbsp; Elasticsearch + Kibana (Fleet app)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp;internal-domain.local:443 ◄──────────────────────&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp;(NOT via the fleet ALB)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Traffic Flows: Breakdown&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;1. Agent --&amp;gt; Fleet Server (Control Plane: Enrollment &amp;amp; Policy Check-in)&lt;/h4&gt;&lt;div&gt;The agent acts as the client, and Fleet Server listens on :8220. The agent dials https://eck-fleet-server.internal-domain.local:443:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Traffic Path:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;agent --&amp;gt; DNS --&amp;gt; internal ALB :443 (TLS termination, internal cert) --&amp;gt; re-encrypt --&amp;gt; a node&#39;s NodePort :32202 --&amp;gt;&amp;nbsp; kube-proxy --&amp;gt; the single Fleet Server pod :8220&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Cross-AZ Routing:&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Because the agent always targets the ALB DNS name (not the pod directly), an agent can land on any node&#39;s NodePort. It is then forwarded by kube-proxy to whichever node is hosting the single Fleet Server pod—making cross-AZ hops standard behavior.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The Long Poll Mechanism: The check-in is a long poll. The agent opens a connection, and Fleet Server holds it open for up to ~5 minutes until a policy change occurs or the poll times out.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The Latency &quot;False Positive&quot;: This held-open duration is exactly what the ALB records as a TargetResponseTime of ~300s, which triggered the false-positive alert. The ALB&#39;s idle_timeout is intentionally set to 300s to support these long polls. Conversely, the health check (/health, expects 404, 300s interval) is a separate lightweight probe, explaining why targets report as perfectly healthy while &quot;latency&quot; metrics look highly skewed.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;2. Agent --&amp;gt; Elasticsearch (Data Plane: Telemetry Shipping)&lt;/h4&gt;&lt;div&gt;This data path does not traverse the Fleet ALB. The Fleet output configuration points agents directly at https://elasticsearch.internal-domain.local:443.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Consequently, the eckfleet ALB only handles control-plane check-in traffic. This explains why its request volume is incredibly low (~3–5 requests/min) while individual request durations hover around 300s. They are two entirely separate paths utilizing two different load balancers.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;3. Fleet Server --&amp;gt; Elasticsearch + Kibana&lt;/h4&gt;&lt;div&gt;Fleet Server (via elasticsearchRefs / kibanaRef) acts as the client here. It writes agent and policy metadata directly into the .fleet-* indices and coordinates with the Kibana Fleet application, where the eck-fleet-server and eck-agent policies are managed.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;One-Line Summary&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Agents (DaemonSet, 5 pods across 2a/2b/2c) long-poll the single Fleet Server pod for policy updates via the internal ALB on :443 --&amp;gt; NodePort 32202 --&amp;gt; :8220, but ship their actual telemetry data directly to Elasticsearch, completely bypassing that ALB. The ALB only processes the slow, held-open control traffic—which is the root cause of the&amp;nbsp; alarm.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Why does fleet server holds connection open for so long? Why it does not reply immediately?&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/h3&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;It&#39;s a deliberate design choice called long polling, and it&#39;s the opposite of a bug. Here&#39;s the reasoning.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The problem Fleet is solving&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Fleet Server&#39;s job is to push policy changes out to agents promptly — a new integration, a changed log path, an output credential rotation. Agents need to find out &quot;has my policy changed?&quot; with low latency.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There are three ways an agent could learn about changes:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; 1. Short polling — agent asks &quot;anything new?&quot; every N seconds, server replies instantly &quot;no&quot;, agent sleeps, repeats.&lt;/div&gt;&lt;div&gt;&amp;nbsp; 2. Server push — server opens a connection to each agent when something changes.&lt;/div&gt;&lt;div&gt;&amp;nbsp; 3. Long polling — agent asks &quot;anything new?&quot;, and the server holds the request open until either something actually changes or a timeout fires.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Fleet uses #3, and the connection sitting open for ~5 minutes is that hold.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Why not reply immediately (short polling)?&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If Fleet answered every check-in instantly with &quot;nothing changed&quot;, then to get fast reaction to a policy change, agents would have to poll very frequently — say every few seconds. With your 5 agents that&#39;s tolerable, but Fleet is built to manage thousands to tens of thousands of agents from one server. At that scale:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; - Frequent short polls = a constant storm of requests, almost all of which return &quot;no change&quot;. Huge wasted CPU/network on both ends.&lt;/div&gt;&lt;div&gt;&amp;nbsp; - To keep reaction time low you&#39;d poll more often, which makes the storm worse. To cut the storm you&#39;d poll less often, which makes policy changes take longer to land. There&#39;s no good setting.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Long polling breaks that trade-off: the agent gets a near-instant reaction to a real change (the server responds the moment policy updates) and there&#39;s almost no idle chatter (one held-open connection per agent instead of hundreds of empty round-trips).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Why not server push (#2)?&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Pushing would mean the server initiating connections inward to every agent. Agents are all over the place — behind NAT, firewalls, in private subnets, on laptops, on hostNetwork pods like yours. The server usually can&#39;t reach them, and you&#39;d need inbound rules everywhere. Long polling flips it: the agent always dials out to the server, the connection is already established and held open, and the server pushes the change down that existing agent-initiated connection the instant it happens. You get push-like latency with poll-like (outbound-only) connectivity. That&#39;s exactly why your agents work behind hostNetwork with no inbound exposure.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;&amp;nbsp;So what&#39;s actually happening in those ~300s&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A check-in is essentially: &quot;Here&#39;s my current state; tell me the moment my policy differs.&quot; The server parks that request. Two things can end it:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; - A policy change occurs → server responds immediately with the new policy (could be 2 seconds in).&lt;/div&gt;&lt;div&gt;&amp;nbsp; - Nothing changes → the server lets the request time out at its poll ceiling (~5 min), responds &quot;no change&quot;, and the agent immediately opens a fresh one.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Since your policies rarely change, almost every check-in runs the full clock and returns at ~300s. That&#39;s the held connection the ALB measures as TargetResponseTime.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Why this specifically fools the ALB&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;From the ALB&#39;s point of view, &quot;request received → response sent&quot; took 300 seconds, so it reports TargetResponseTime ≈ 300s. The ALB can&#39;t tell the difference between &quot;the backend was slow for 300s&quot; (bad) and &quot;the backend intentionally held an idle long-poll for 300s&quot; (normal). That ambiguity is the whole reason your generic 0.8s threshold misfires — and why the right fix (DOP-833) is to exempt this endpoint rather than treat it as latency. It&#39;s also why the Ingress sets idle_timeout.timeout_seconds=300: the ALB has to be told to tolerate the held connection, otherwise it would sever the long poll before the agent&#39;s poll cycle completes.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In short: Fleet holds the connection open so it can deliver policy changes near-instantly without either hammering the server with empty polls or needing to reach inward to firewalled agents. The ~300s is just an idle long-poll waiting for a change that usually never comes during that window — efficient by design, and only a problem for a latency metric that doesn&#39;t know to expect it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;----&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/3529066834690095782/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/3529066834690095782' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/3529066834690095782'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/3529066834690095782'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/06/elastic-fleet.html' title='Elastic Fleet'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7qLkLic0epYIvdZbBJnuqSenEUW6phHFhy7NwIMPStBFpK32N1pDKR1uC3yadR5rHC2lM9Oa1FZ6mwWqa-7_nn_FOywTR8AWHWja8zLzC3zTZPwjW1-mVveRDYf6GkeFmeIcu3WUx7ShhHANRlw5QljhlF4996mm5p8tCFtiIkiMhquW59ixEcZfTUIw/s72-w640-h640-c/elasticsearch-logo-png-transparent.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-3983505050708614579</id><published>2026-06-25T13:11:38.955+01:00</published><updated>2026-06-25T13:11:38.955+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AWS"/><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><category scheme="http://www.blogger.com/atom/ns#" term="Load Balancing"/><title type='text'>AWS EC2: Application Load Balancer</title><content type='html'>&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSJSM-iOPqVmPdDzFbrSufE6r0RkCQc9H_Ikp-NWSKPyua4Yfnj--YE6bWACpd05qpEn4HeACR8OZZwQfuis529r4oKLZk-WSCTleHcEexFaskQedIAbeW-vOuWb50lGGx97E_vRvltlbN1FnN918TC86Ir5GY7dNGoAqAH_xEpbbvPBZtgR_FILSS/s310/alb_routing_1.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;262&quot; data-original-width=&quot;310&quot; height=&quot;338&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSJSM-iOPqVmPdDzFbrSufE6r0RkCQc9H_Ikp-NWSKPyua4Yfnj--YE6bWACpd05qpEn4HeACR8OZZwQfuis529r4oKLZk-WSCTleHcEexFaskQedIAbeW-vOuWb50lGGx97E_vRvltlbN1FnN918TC86Ir5GY7dNGoAqAH_xEpbbvPBZtgR_FILSS/w400-h338/alb_routing_1.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;An &lt;b&gt;Application Load Balancer (ALB)&lt;/b&gt; is a fully managed AWS service that automatically distributes incoming HTTP and HTTPS traffic across multiple backend targets.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It operates at the Application Layer (Layer 7) of the Open Systems Interconnection (OSI) model.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Key Features:&lt;/h3&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Content-Based Routing: Routes traffic based on URL paths (/api vs /images) or hostnames (://example.com).&lt;/li&gt;&lt;li&gt;Container Support: Integrates directly with Amazon ECS and EKS using dynamic port mapping.&lt;/li&gt;&lt;li&gt;Advanced Protocols: Native support for modern protocols like HTTP/2, gRPC, and WebSockets.&lt;/li&gt;&lt;li&gt;Security Integration: Features built-in HTTPS/TLS termination and integrates directly with AWS WAF for web security.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;How Components Work Together&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Listener: Evaluates connection requests from clients using protocols and ports you configure.&lt;/li&gt;&lt;li&gt;Rules: Determines how the load balancer routes requests to its registered targets.&lt;/li&gt;&lt;li&gt;Target Group: Groups backend resources (like EC2 instances, containers, or IP addresses) that receive the traffic&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;How ALB health checks keep applications online?&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;An Application Load Balancer (ALB) keeps your application online by continuously monitoring the health of your backend targets and dynamically redirecting traffic away from failing nodes.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;1. Automatic Traffic Redirection&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The ALB sends periodic ping requests (health checks) to every registered target. If a target fails to respond correctly, the ALB marks it as unhealthy and immediately stops sending user traffic to it. Traffic is rerouted to the remaining healthy nodes with zero downtime for the user.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;2. Auto Scaling Integration&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When paired with an Auto Scaling Group (ASG), ALB health checks can trigger the automatic replacement of broken instances.&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;The Problem: An EC2 instance might be running (healthy at the hardware level), but the web server inside it has crashed (unhealthy at the application level).&lt;/li&gt;&lt;li&gt;The Solution: The ALB tells the ASG that the instance is failing application health checks. The ASG terminates that specific broken instance and launches a fresh, working one.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;3. Graceful Recovery&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When an unhealthy instance recovers, or when a new instance is launched, the ALB does not send traffic to it immediately. It enters an initial state and undergoes consecutive successful health checks. Only when it passes the threshold does the ALB safely introduce it back into the traffic rotation.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;How to Configure an ALB Health Check&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You configure health checks inside the Target Group settings using these parameters:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Parameter&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; What it does&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Recommended Setting&lt;/b&gt;&lt;/div&gt;&lt;div&gt;========&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;=========&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;=================&lt;/div&gt;&lt;div&gt;&lt;b&gt;Health Check Path&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;The URL endpoint the ALB hits&amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (e.g., /health or /index.html).&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; /health&lt;/div&gt;&lt;div&gt;&lt;b&gt;Healthy Threshold&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; Consecutive successes needed to mark a target as healthy.&amp;nbsp; &amp;nbsp; &amp;nbsp; 3&lt;/div&gt;&lt;div&gt;&lt;b&gt;Unhealthy Threshold&lt;/b&gt;&amp;nbsp; Consecutive failures needed to mark a target as unhealthy.&amp;nbsp; &amp;nbsp; &amp;nbsp;2&lt;/div&gt;&lt;div&gt;&lt;b&gt;Timeout&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; How long the ALB waits for a response before failing.&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;5 seconds&lt;/div&gt;&lt;div&gt;&lt;b&gt;Interval&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;The time between individual health check pings.&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 30 seconds&lt;/div&gt;&lt;div&gt;&lt;b&gt;Success Codes&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; The HTTP status codes that prove the app is working.&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 200 (or 200-399)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When you configure an ALB, you do not select an Availability Zone (AZ) directly; instead, you must select at least two subnets in different Availability Zones to ensure high availability.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;How it works: AWS places a &lt;u&gt;load balancer node&lt;/u&gt; in each of the specified subnets.&lt;/li&gt;&lt;li&gt;The AZ link: Because each subnet belongs to exactly one AZ, this fundamentally binds the ALB&#39;s nodes to those corresponding Availability Zones.&lt;/li&gt;&lt;li&gt;Custom routing: You can modify the subnets via the Update Availability Zones settings in the EC2 Console at any time.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Public ALB&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Binding an ALB to public subnets makes it a public (internet-facing) load balancer.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When you create an internet-facing ALB, AWS requires you to select public subnets so the ALB nodes can receive a public IP address and route traffic from the internet.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Key Characteristics:&lt;/h4&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Public DNS: The ALB receives a public DNS name that resolves to public IP addresses.&lt;/li&gt;&lt;li&gt;Internet Gateway: The selected public subnets must have a route to an Internet Gateway (IGW) in their route tables.&lt;/li&gt;&lt;li&gt;Target Routing: Even though the ALB is public, it can still route traffic to EC2 instances living in private subnets&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;An internet-facing ALB routes traffic directly to the individual backend targets (such as EC2 instances or IP addresses), not to the private subnets themselves.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;How Routing Works&lt;/h4&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Target Group Config: You configure the ALB to route traffic to a Target Group.&lt;/li&gt;&lt;li&gt;Direct Node Communication: The ALB nodes in the public subnets communicate directly with the private IP addresses of your backend nodes.&lt;/li&gt;&lt;li&gt;Cross-Subnet Traffic: AWS handles this routing internally via the VPC router, allowing the public ALB to securely traverse into private subnets.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Configuration Checklist&lt;/h4&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;VPC: Both the public subnets (where the ALB lives) and the private subnets (where the nodes live) must be in the same VPC.&lt;/li&gt;&lt;li&gt;Security Groups: The private instances must have a security group that allows inbound traffic from the ALB&#39;s security group&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Private ALB&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;An internal (private) ALB routes traffic in the exact same way as a public ALB, but it is only accessible within your VPC or connected networks.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It routes traffic directly to individual backend targets, not to subnets.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Key Characteristics&lt;/h4&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Private Subnets: You deploy the ALB nodes into private subnets.&lt;/li&gt;&lt;li&gt;Private DNS: The ALB receives a public DNS name, but it resolves exclusively to private IP addresses.&lt;/li&gt;&lt;li&gt;No Internet Access: It cannot receive any traffic from the public internet because it lacks a public IP.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Common Use Cases&lt;/h4&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Internal Microservices: Routing traffic from a public-facing web tier to a private backend API tier.&lt;/li&gt;&lt;li&gt;Hybrid Networks: Routing traffic coming from an on-premises data centre via AWS Direct Connect or a VPN&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Setting Up ALB in AWS Console&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.bojankomazec.com/2023/02/aws-elastic-load-balancing.html&quot;&gt;AWS Elastic Load Balancing&lt;/a&gt; shows basic building blocks of AWS Load Balancer which include listeners and target groups.&amp;nbsp;&lt;/p&gt;&lt;p&gt;To create &lt;b&gt;Application Load Balancer&lt;/b&gt; go to EC2 &amp;gt;&amp;gt; Load balancers &amp;gt;&amp;gt; Create Load balancer &amp;gt;&amp;gt; Select load balancer type (click on &lt;i&gt;Create&lt;/i&gt; under &lt;i&gt;Application Load Balancer&lt;/i&gt;)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlNDq7UJdKgsJNVrw5qECJTe36lkKRM8dOcA6xTQLNO7Ta2iyAd7aKmeC5fQuh88ZM7BbdYrtjsf4unbhnx8k_P8hyLhV9XNnN4MEQCtjD9zk4p4EKCOv0LHIhCFT9sRMWzY8ivKTFRhhyk0GrZMu1bl8dYBzYddNZwR1Igzjs8ufu4zQDweH2_jXx/s1112/Screenshot%20from%202023-02-06%2014-16-55.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;639&quot; data-original-width=&quot;1112&quot; height=&quot;368&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlNDq7UJdKgsJNVrw5qECJTe36lkKRM8dOcA6xTQLNO7Ta2iyAd7aKmeC5fQuh88ZM7BbdYrtjsf4unbhnx8k_P8hyLhV9XNnN4MEQCtjD9zk4p4EKCOv0LHIhCFT9sRMWzY8ivKTFRhhyk0GrZMu1bl8dYBzYddNZwR1Igzjs8ufu4zQDweH2_jXx/w640-h368/Screenshot%20from%202023-02-06%2014-16-55.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQgCIB2W0J79YmDrenBTv2au-Bmk3G4wOFg9-2zcBWDf4im4PQByajNqUI90uIn7ceMjPeQYMkkw1uLVbxS3AmSLBlXcC5uYoY-Swt-RQvewFvLzLHGuubzRTogRsOkEvf0q6Uy8I_BUgmaOleziF5FEKzxMuJJXB98TtCvbuKsvZgTeelYlXPoB5m/s1102/Screenshot%20from%202023-02-06%2014-16-34.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1013&quot; data-original-width=&quot;1102&quot; height=&quot;588&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQgCIB2W0J79YmDrenBTv2au-Bmk3G4wOFg9-2zcBWDf4im4PQByajNqUI90uIn7ceMjPeQYMkkw1uLVbxS3AmSLBlXcC5uYoY-Swt-RQvewFvLzLHGuubzRTogRsOkEvf0q6Uy8I_BUgmaOleziF5FEKzxMuJJXB98TtCvbuKsvZgTeelYlXPoB5m/w640-h588/Screenshot%20from%202023-02-06%2014-16-34.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;Here we can set:&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;Basic configuration&lt;/b&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Name&lt;/b&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Scheme&lt;/b&gt; (cannot be changed after the load balancer is created)&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Internet-facing&lt;/b&gt;. An internet-facing load balancer routes requests from clients over the internet to targets. Requires a public subnet.&amp;nbsp;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Internal&lt;/b&gt;. An internal load balancer routes requests from clients to targets using private IP addresses. &lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;IP address type&lt;/b&gt;. Select the type of IP addresses that your subnets use.&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;IPv4&lt;/b&gt;. Recommended for internal load balancers.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Dualstack&lt;/b&gt;. Includes IPv4 and IPv6 addresses. &lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;Network mapping&lt;/b&gt;. The load balancer routes traffic to targets in the selected subnets, and in accordance with your IP address settings.&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;VPC&lt;/b&gt;. Virtual private cloud for your targets. If balancer is internet-facing, only VPCs with an &lt;b&gt;internet gateway&lt;/b&gt; are enabled for selection. The selected VPC cannot be changed after the load balancer is created. As VPC is &lt;u&gt;region-specific&lt;/u&gt; so is Application Load Balancer.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Mappings&lt;/b&gt;. Once VPC is selected, its &lt;u&gt;availability zones&lt;/u&gt; are listed here and are selectable. Select &lt;u&gt;at least two&lt;/u&gt; Availability Zones and one subnet per zone. The load balancer routes traffic to targets in these Availability Zones only. Availability Zones that are not supported by the load balancer or the VPC are not available for selection. We should select all AZs that we listed in the Auto scaling group (if we used it).&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;Security groups&lt;/b&gt;. A security group is a set of firewall rules that control the traffic to your load balancer. We can select up to 10 security groups.&lt;/li&gt;&lt;ul&gt;&lt;li&gt;If our application is listening for HTTP requests on port 80 we should select a security group with:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Inbound rule: accept HTTP/TCP traffic on port 80 with source Anywhere-IPv4&lt;/li&gt;&lt;li&gt;Outbound rule: allow all traffic for all protocols and port ranges to custom destination 0.0.0.0/0&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;Listeners and routing&lt;/b&gt;. A listener is a process that checks for connection requests using the port and protocol you configure. The rules that you define for a listener determine how the load balancer routes requests to its registered targets.&lt;br /&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Add listener&lt;/b&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Protocol&lt;/b&gt; e.g. HTTP&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Port&lt;/b&gt; e.g. 80. This is a public facing port and it does not need to be the same as the port from the attached target group. E.g. LB can listen on port 80 and forward traffic to target group port 8080. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Default action&lt;/b&gt;: Forward to (select a &lt;b&gt;target group&lt;/b&gt;)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Add &lt;b&gt;listener tags&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;Add-on services&lt;/b&gt; - optional&lt;/li&gt;&lt;ul&gt;&lt;li&gt;AWS Global Accelerator&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;Tags&lt;/b&gt; - optional&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;More info on Scheme, from AWS documentation:&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;/p&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;i&gt;When you create a load balancer, you must choose whether to make it an &lt;b&gt;internal&lt;/b&gt; load balancer or an &lt;b&gt;internet-facing&lt;/b&gt; load balancer.&lt;/i&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;i&gt;&lt;br /&gt;The &lt;b&gt;nodes&lt;/b&gt; of an &lt;u&gt;internet&lt;/u&gt;-facing load balancer have &lt;u&gt;public&lt;/u&gt; IP addresses.&lt;/i&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;i&gt;&lt;br /&gt;The &lt;b&gt;nodes&lt;/b&gt; of an &lt;u&gt;internal&lt;/u&gt; load balancer have only &lt;u&gt;private&lt;/u&gt; IP addresses.&lt;/i&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;i&gt;&lt;br /&gt;Both internet-facing and internal load balancers route requests to your targets using private IP addresses. Therefore, your targets do not need public IP addresses to receive requests from an internal or an internet-facing load balancer.&lt;/i&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;/div&gt;&lt;p&gt;More info on how ALB routes traffic to multiple Availability Zones (and about what Load Balancer Nodes are):&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;i&gt;When you enable an Availability Zone for your load balancer, Elastic Load Balancing creates a &lt;b&gt;load balancer node&lt;/b&gt; in the Availability Zone.&amp;nbsp;&lt;/i&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;The nodes for your load balancer distribute requests from clients to registered targets. When cross-zone load balancing is enabled, each load balancer node distributes traffic across the registered targets in all enabled Availability Zones. When cross-zone load balancing is disabled, each load balancer node distributes traffic only across the registered targets in its Availability Zone.&lt;/i&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;Before a client sends a request to your load balancer, it resolves the load balancer&#39;s domain name using a Domain Name System (DNS) server. The DNS entry is controlled by Amazon, because your load balancers are in the amazonaws.com domain. The Amazon DNS servers return one or more IP addresses to the client. These are the &lt;u&gt;IP addresses of the load balancer nodes for your load balancer&lt;/u&gt;.&lt;/i&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;As traffic to your application changes over time, &lt;u&gt;Elastic Load Balancing scales your load balancer and updates the DNS entry&lt;/u&gt;. The DNS entry also specifies the time-to-live (TTL) of 60 seconds. This helps ensure that the &lt;u&gt;IP addresses can be remapped&lt;/u&gt; quickly in response to changing traffic.&lt;br /&gt;&lt;br /&gt;The client determines which IP address to use to send requests to the load balancer. &lt;u&gt;The load balancer node that receives the request&lt;/u&gt; selects a healthy registered target and sends the request to the target using its private IP address.&lt;/i&gt; &lt;br /&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;p&gt;&lt;i&gt;With Application Load Balancers, the &lt;u&gt;load balancer node that receives the request&lt;/u&gt; uses the following process: &lt;br /&gt;&lt;/i&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote style=&quot;margin-left: 80px; text-align: left;&quot;&gt;&lt;p&gt;&lt;i&gt;1) Evaluates the &lt;b&gt;listener rules&lt;/b&gt; in priority order to determine which rule to apply. &lt;br /&gt;&lt;/i&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote style=&quot;margin-left: 80px; text-align: left;&quot;&gt;&lt;p&gt;&lt;i&gt;2) Selects a &lt;b&gt;target&lt;/b&gt; from the&lt;b&gt; target group&lt;/b&gt; for the rule action, using the routing algorithm configured for the target group. The default routing algorithm is round robin. Routing is performed independently for each target group, even when a target is registered with multiple target groups. &lt;/i&gt;&lt;br /&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;For further info: &lt;a href=&quot;https://docs.aws.amazon.com/elasticloadbalancing/latest/userguide/how-elastic-load-balancing-works.html&quot;&gt;How Elastic Load Balancing works - Elastic Load Balancing&lt;/a&gt;&lt;/p&gt;&lt;p&gt;ALB nodes use &lt;b&gt;Elastic Network Interface&lt;/b&gt; (&lt;a href=&quot;https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html&quot;&gt;Elastic network interfaces - Amazon Elastic Compute Cloud&lt;/a&gt;) which has public IP address:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;i&gt;At least one ENI is created and attached to the 
balancer in each availability zone where the balancer is deployed 
(except NLB, which should only have one per AZ). Over the life of the 
balancer, new ENIs will appear and old ones will disappear, as the 
balancer scales horizontally (number of nodes) and/or vertically 
(capacity of underlying hardware), all of which is handled transparently
 by the infrastructure. Even though you can tag them, the tagging will 
become stale over time.&lt;/i&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Source: &lt;a href=&quot;https://stackoverflow.com/questions/49365691/aws-affect-load-balancers-tags-to-its-network-interfaces-eni&quot;&gt;amazon web services - AWS - Affect Load Balancer&#39;s tags to its Network Interfaces (ENI) - Stack Overflow&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;i&gt;You can determine the IP addresses associated with an internal load balancer or an internet-facing load balancer by resolving the DNS name of the load balancer. These are the IP addresses where the clients should send the requests that are destined for the load balancer. However, Classic Load Balancers and &lt;u&gt;Application Load Balancers use the private IP addresses associated with their elastic network interfaces as the source IP address for requests forwarded to your web servers&lt;/u&gt;.&lt;/i&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Source: &lt;a href=&quot;https://aws.amazon.com/premiumsupport/knowledge-center/elb-find-load-balancer-IP/&quot;&gt;Find the IP address used by a load balancer to forward traffic to web servers&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Load balancer routes requests to the targets in a target group and performs health checks on the targets. Target group is accepting requests from the load balancer and forwards them to targets. These targets can be e.g. EC2 instances created either manually or through auto scaling group.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;How to create a &lt;b&gt;Target Group &lt;/b&gt;used by Load Balancer listeners? (This applies for any type of Load Balancer)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;EC2&lt;/i&gt; &amp;gt;&amp;gt; &lt;i&gt;Target groups&lt;/i&gt; &amp;gt;&amp;gt; &lt;i&gt;Create target group&lt;/i&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;Step 1: Specify group details &lt;br /&gt;&lt;/i&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMrpgIpclkp1DrT1T3-LVBLgZlB7yU1r8td-BsWF70W567usJSZMbeZnuLp6xHLF1nB-GCxJLZv-fqzW1sU-4SmvasIysatT4Kmp7GLL1-AhktdvCcpLlyGsqLE3hoIMryUVqeJZA0xjy8_QrW_a9EfgofsA6EvgbCd_CllcCCi22D7BJWpUYkesNJ/s1097/Screenshot%20from%202023-02-06%2015-52-20.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;997&quot; data-original-width=&quot;1097&quot; height=&quot;582&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMrpgIpclkp1DrT1T3-LVBLgZlB7yU1r8td-BsWF70W567usJSZMbeZnuLp6xHLF1nB-GCxJLZv-fqzW1sU-4SmvasIysatT4Kmp7GLL1-AhktdvCcpLlyGsqLE3hoIMryUVqeJZA0xjy8_QrW_a9EfgofsA6EvgbCd_CllcCCi22D7BJWpUYkesNJ/w640-h582/Screenshot%20from%202023-02-06%2015-52-20.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Here we can set:&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;Basic configuration&lt;/b&gt;. Settings in this section cannot be changed after the target group is created.&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Target type&lt;/b&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Instances&lt;/b&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Supports load balancing to instances within a specific VPC.&lt;/li&gt;&lt;li&gt;Facilitates the use of Amazon EC2 Auto Scaling&amp;nbsp; to manage and scale your EC2 capacity.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;IP addresses&lt;/b&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Supports load balancing to VPC and on-premises resources.&lt;/li&gt;&lt;li&gt;Facilitates routing to multiple IP addresses and network interfaces on the same instance.&lt;/li&gt;&lt;li&gt;Offers flexibility with microservice based architectures, simplifying inter-application communication.&lt;/li&gt;&lt;li&gt;&amp;nbsp;Supports IPv6 targets, enabling end-to-end IPv6 communication, and IPv4-to-IPv6 NAT.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;Lambda function&lt;/b&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Facilitates routing to a single Lambda function.&lt;/li&gt;&lt;li&gt;&amp;nbsp;Accessible to Application Load Balancers only.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;Application Load Balancer&lt;/b&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Offers the flexibility for a Network Load Balancer to accept and route TCP requests within a specific VPC&lt;/li&gt;&lt;li&gt;Facilitates using static IP addresses and PrivateLink with an Application Load Balancer.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;Target group name&lt;/b&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Protocol:Port&lt;/b&gt; e.g. If our application is accepting HTTP requests on port 8080 this would be HTTP:8080&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;VPC&lt;/b&gt; - VPC with the instances that you want to include in the target group.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Protocol version&lt;/b&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;HTTP1&lt;/b&gt;. Send requests to targets using HTTP/1.1. Supported when the request protocol is HTTP/1.1 or HTTP/2.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;HTTP2&lt;/b&gt;. Send requests to targets using HTTP/2. Supported when the request protocol is HTTP/2 or gRPC, but gRPC-specific features are not available.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;gRPC&lt;/b&gt;. Send requests to targets using gRPC. Supported when the request protocol is gRPC.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;Health checks&lt;/b&gt;. The associated load balancer periodically sends requests, per the settings below, to the registered targets to test their status.&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Health check protocol&lt;/b&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;HTTP&lt;/li&gt;&lt;li&gt;HTTPS&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;Health check path&lt;/b&gt;. Use the default path of “/“ to ping the root, or specify a custom path if preferred.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Advanced health check settings&lt;/b&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Port&lt;/b&gt;. The port the load balancer uses when performing health checks on targets. The default is the port on which each target receives traffic from the load balancer, but you can specify a different port.&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Traffic port&lt;/li&gt;&lt;li&gt;Override&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;Healthy threshold&lt;/b&gt;. The number of consecutive health checks successes required before considering an unhealthy target healthy.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Unhealthy threshold&lt;/b&gt;. The number of consecutive health check failures required before considering a target unhealthy.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Timeout&lt;/b&gt;. The amount of time, in seconds, during which no response means a failed health check.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Interval&lt;/b&gt;. The approximate amount of time between health checks of an individual target&lt;/li&gt;&lt;li&gt;&lt;b&gt;Success codes&lt;/b&gt;. The HTTP codes to use when checking for a successful response from a target. You can specify multiple values (for example, &quot;200,202&quot;) or a range of values (for example, &quot;200-299&quot;).&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;Attributes&lt;/b&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Tags&lt;/b&gt; - optional &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;Step 2: Register targets&lt;/i&gt;&lt;/p&gt;&lt;p&gt;This is an optional step to create a target group. However, to ensure that your load balancer routes traffic to this target group you must register your targets. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrSi-7Wrilmvw0PzggsgM1PKdgmc814YTMgfcMnpCxWUtb56nDCflPAz4LNq8Hlc6LnEH742vQyFO5Z0raTO8eJJPFJe3W0qLpWALR_Y7FMIGlFjad1T5kjENfaBFkiN3FtkrF-7FRMsiYSXDLoJXEX6ceu0h7r4tMVNUsX9keYxGIyQu4CttL-eKK/s1789/Screenshot%20from%202023-02-06%2016-58-17.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;947&quot; data-original-width=&quot;1789&quot; height=&quot;338&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrSi-7Wrilmvw0PzggsgM1PKdgmc814YTMgfcMnpCxWUtb56nDCflPAz4LNq8Hlc6LnEH742vQyFO5Z0raTO8eJJPFJe3W0qLpWALR_Y7FMIGlFjad1T5kjENfaBFkiN3FtkrF-7FRMsiYSXDLoJXEX6ceu0h7r4tMVNUsX9keYxGIyQu4CttL-eKK/w640-h338/Screenshot%20from%202023-02-06%2016-58-17.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;After load balancer is created it takes several minutes while it&#39;s in &lt;i&gt;provisioning&lt;/i&gt; state and get into &lt;i&gt;active&lt;/i&gt; state. After this, we can use its DNS name in order to see what it&#39;s doing. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;If we copy its DNS name and paste it to our browser, if we haven&#39;t registered any targets in the target group associated with the load balancer, we&#39;ll get error &lt;b&gt;503 - Service Temporary Unavailable&lt;/b&gt;.&lt;/p&gt;&lt;p&gt;If we&#39;ve registered targets and are getting error 504 Gateway time-out, we should check first if security groups (firewalls) for our EC2 instances (inbound rule - source IP range) are set up correctly as this error usually indicates that inbound traffic is not allowed. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;AWS Terraform provider offers provisioning all these resources:&lt;br /&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Application Load Balancer: &lt;a href=&quot;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb&quot;&gt;aws_lb | Resources | hashicorp/aws | Terraform Registry&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Listener: &lt;a href=&quot;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_listener&quot;&gt;aws_lb_listener | Resources | hashicorp/aws | Terraform Registry&lt;/a&gt;&amp;nbsp;&lt;/li&gt;&lt;li&gt;Target Group: &lt;a href=&quot;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_target_group&quot;&gt;aws_lb_target_group | Resources | hashicorp/aws | Terraform Registry&lt;/a&gt;&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;How is AWS Application Load Balancing usually implemented?&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Let&#39;s say we have our application running on 3 EC2 instances where 2 are in the same region e.g. us-west-2 but in separate availability zones e.g. us-west-2a and us-west-2b. Third EC2 instance is in eu-central-1, in availability zone eu-central-1a.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;VPC is region-specific but can span multiple availability zones (AZ).&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Subnet is an IP address range within VPC.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;VPC can have public and private subnets. &lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;VPC can be divided into multiple subnets but each subnet is AZ-specific.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;AZ can have multiple subnets.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;So, all EC2 instances belong to the same VPC but, as they are in different AZs, each of them belongs to different subnet.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Load balancer must be in the public subnet of VPC as clients communicate with load balancer via internet (public network). &lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Load balancer does not get associated directly with EC2 instances but subnets:&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;resource &quot;aws_lb&quot; &quot;test&quot; {&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;subnets = [&quot;subnet-0001&quot;, &quot;subnet-0002&quot;]&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Target group is associated with VPC:&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;resource &quot;aws_alb_target_group&quot; &quot;test&quot; {&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;vpc_id&amp;nbsp;&amp;nbsp; = var.vpc_id&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; ...&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Difference between ALB and NLB (Network Load Balancer)&lt;/h3&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;An Application Load Balancer (ALB) and a Network Load Balancer (NLB) serve different purposes based on the layer of the network they operate on and the type of traffic they handle.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;The core difference is that an ALB understands application-level traffic (Layer 7) like HTTP/HTTPS headers, while an NLB handles low-level network traffic (Layer 4) like TCP/UDP packets at extreme speeds.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Direct Comparison Matrix&lt;/h4&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;Feature&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Application Load Balancer (ALB)&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Network Load Balancer (NLB)&lt;/b&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;======&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;=========================&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; =======================&lt;/b&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;OSI Layer&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Layer 7 (Application)&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Layer 4 (Transport)&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;Protocols&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;HTTP, HTTPS, HTTP/2, gRPC, WebSockets&amp;nbsp; &amp;nbsp; &amp;nbsp; TCP, UDP, TLS&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;IP Addresses&lt;/b&gt;&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Dynamic IPs (Changes automatically; requires a DNS name)&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Static IPs (Can assign an Elastic IP per AZ)&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;Routing Features&lt;/b&gt;&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;Advanced (Path, Host, Query parameters, Headers)&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Basic (Port and IP protocol routing only)&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;Performance&lt;/b&gt;&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;Optimized for complex web apps (Millions of requests/sec)&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;Optimized for ultra-low latency (Billions of requests/sec)&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Key Technical Differences&lt;/h3&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;1. Smart Routing vs. Raw Speed&lt;/h4&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;ALB (Smart): Can read the contents of your HTTP requests. It can route traffic bound for ://example.com to an API server cluster, and traffic for ://example.com to a storage cluster.&lt;/li&gt;&lt;li&gt;NLB (Fast): Does not look inside the data packet. It simply looks at the target port and forwards the packet instantly. This results in ultra-low latency (measured in milliseconds).&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;2. IP Addresses and DNS&lt;/h4&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;ALB: Scale out dynamically by adding or removing nodes. This causes its underlying IP addresses to change frequently. You must always point your domain name to the ALB&#39;s DNS Name, never to a static IP.&lt;/li&gt;&lt;li&gt;NLB: Gives you a Static IP address per Availability Zone. You can also assign your own Elastic IP addresses. This is critical if your corporate clients need to whitelist specific, unchanging IPs in their firewalls.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;3. Client IP Preservation&lt;/h4&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;ALB: Terminates the connection and makes a new one to your backend instances. The backend see the ALB&#39;s private IP. To find the real user&#39;s IP, your code must read the X-Forwarded-For HTTP header.&lt;/li&gt;&lt;li&gt;NLB: Passes the original TCP packet straight through to your backend server. Your backend instances see the original source IP address of the client natively, without needing extra headers.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;When to Choose Which?&lt;/h3&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Choose an ALB if you are building:&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Standard web applications and microservices.&lt;/li&gt;&lt;li&gt;Containerized apps (ECS/EKS) requiring path-based or host-based routing.&lt;/li&gt;&lt;li&gt;Applications requiring tight integration with AWS Web Application Firewall (WAF).&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Choose an NLB if you are building:&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Non-HTTP applications (e.g., gaming servers, SFTP, MQTT, database clusters).&lt;/li&gt;&lt;li&gt;Architectures requiring fixed, static IP addresses or Elastic IPs.&lt;/li&gt;&lt;li&gt;High-frequency financial applications where sub-millisecond network latency is a hard requirement&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Which alerts should typically be set for AWS ALB?&lt;/h2&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;To keep your applications highly available, you should set up Amazon CloudWatch alarms for a mix of availability, performance, and target health metrics.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;The most critical metrics to monitor for an AWS ALB are grouped by priority below:&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;1. High Priority (Critical Infrastructure Impact)&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;UnHealthyHostCount&lt;/span&gt; (Per Target Group)&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;What it means: The number of backend instances failing health checks Target Group Metrics.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Alert Threshold: &amp;gt; 0 (or &amp;gt; 1 for larger clusters).&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Why it matters: Signals that your servers are crashing or cannot handle traffic.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;HTTPCode_Target_5XX_Count&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;What it means: The number of 5xx server error codes generated by your backend application ALB Metrics.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Alert Threshold: Depends on baseline traffic, typically &amp;gt; 5 failures within a 1-minute to 5-minute window.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Why it matters: Indicates server crashes, database connection timeouts, or unhandled exceptions in your application code.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;HTTPCode_ELB_5XX_Count&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;What it means: The number of 5xx errors generated directly by the ALB itself (not your servers) ALB Metrics.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Alert Threshold: &amp;gt; 0.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Why it matters: Usually means the ALB cannot find any healthy hosts, or it is experiencing a configuration mismatch (e.g., bad TLS handshake with the target).&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;2. Medium Priority (Performance &amp;amp; User Experience)&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;TargetResponseTime&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;What it means: The time elapsed (in seconds) from when the ALB sent the request to the target until the target started responding ALB Metrics.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Alert Threshold: Use the p95 or p99 statistic. Alert if it exceeds your application’s maximum acceptable latency (e.g., &amp;gt; 2.0 seconds).&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Why it matters: Users are experiencing severe application slowdowns, likely due to high CPU/memory usage on your instances.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;RejectedConnectionCount&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;What it means: The load balancer is rejecting connections because it has reached its maximum capacity ALB Metrics.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Alert Threshold: &amp;gt; 0.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Why it matters: Your application is getting sudden traffic spikes and the ALB cannot scale fast enough, or backend targets are failing to keep up.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;3. Low Priority (Anomalies &amp;amp; Security)&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;HTTPCode_Target_4XX_Count&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;What it means: The number of 4xx client errors (like 404 Not Found or 401 Unauthorized) returned by backend targets ALB Metrics.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Alert Threshold: A significant spike above your standard baseline.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Why it matters: A sudden surge might indicate a broken frontend deployment, a bad API update, or a malicious entity scanning your network for vulnerabilities.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Summary Checklist for CloudWatch Alarms&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;Metric Name&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Statistic&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Recommended&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Suggested&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Action&lt;/b&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Period&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Threshold&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/b&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;==========&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ======&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ===========&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;========&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;=====&lt;/b&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;UnHealthyHostCount&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Maximum&amp;nbsp; &amp;nbsp;1 Minute&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;gt; 0&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Page/On-Call&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;HTTPCode_ELB_5XX_Count&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Sum&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;1 Minute&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;gt; 0&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Page/On-Call&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;HTTPCode_Target_5XX_Count&lt;/b&gt;&amp;nbsp; Sum&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 5 Minutes&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;gt; 10 (or &amp;gt; 1% of traffic) Ticket/Slack&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;TargetResponseTime&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;p95&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 5 Minutes&amp;gt; [Your Limit]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Ticket/Slack&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;Resources:&lt;/h1&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;a href=&quot;https://docs.aws.amazon.com/elasticloadbalancing/latest/userguide/how-elastic-load-balancing-works.html&quot;&gt;How Elastic Load Balancing works - Elastic Load Balancing&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/3983505050708614579/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/3983505050708614579' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/3983505050708614579'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/3983505050708614579'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/06/aws-ec2-application-load-balancer.html' title='AWS EC2: Application Load Balancer'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSJSM-iOPqVmPdDzFbrSufE6r0RkCQc9H_Ikp-NWSKPyua4Yfnj--YE6bWACpd05qpEn4HeACR8OZZwQfuis529r4oKLZk-WSCTleHcEexFaskQedIAbeW-vOuWb50lGGx97E_vRvltlbN1FnN918TC86Ir5GY7dNGoAqAH_xEpbbvPBZtgR_FILSS/s72-w400-h338-c/alb_routing_1.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-1233425363097768997</id><published>2026-06-03T11:20:16.303+01:00</published><updated>2026-06-03T11:25:38.957+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Agentic AI"/><category scheme="http://www.blogger.com/atom/ns#" term="AI"/><category scheme="http://www.blogger.com/atom/ns#" term="LLM"/><title type='text'>Some notes on LLMs</title><content type='html'>&lt;p&gt;&amp;nbsp;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8A60re2nD4AwHHSi7LJHj4v0mh7ZeoLzo28cm_iEfN3RTIDA4OyuCTEQL5vs7MR3f4xqW4zxWdYkl-iVA3JoMPWwP4HMsqPseSrtxThyphenhyphenZv7s_4lToQLXv14sFA_kX8HPBNxRP5b0-oJnAMJFx1recQJBziBHM_q78eZUTHLf2rwgn_SzS4gF18TSAevE/s1190/Screenshot%202026-04-08%20at%2012.30.13.png&quot; style=&quot;margin-left: 1em; margin-right: 1em; text-align: center;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;872&quot; data-original-width=&quot;1190&quot; height=&quot;468&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8A60re2nD4AwHHSi7LJHj4v0mh7ZeoLzo28cm_iEfN3RTIDA4OyuCTEQL5vs7MR3f4xqW4zxWdYkl-iVA3JoMPWwP4HMsqPseSrtxThyphenhyphenZv7s_4lToQLXv14sFA_kX8HPBNxRP5b0-oJnAMJFx1recQJBziBHM_q78eZUTHLf2rwgn_SzS4gF18TSAevE/w640-h468/Screenshot%202026-04-08%20at%2012.30.13.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;h3&gt;What does e.g.&amp;nbsp;&lt;i&gt;1M context&lt;/i&gt;&amp;nbsp;mean in a model description?&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&quot;1M context&quot; means the model can handle up to 1 million tokens in its context window — the combined input (your messages, files, tool results, system prompt) plus output it can consider at once. For reference, that&#39;s roughly 750,000 words or a few thousand pages of text, letting it work with very large codebases or long conversations without losing earlier content.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3&gt;What is a LLM&#39;s tool-use loop?&amp;nbsp;&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;An LLM tool-use loop is the pattern where you let a language model drive an investigation by repeatedly choosing tools to call, rather than answering in one shot.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4&gt;The shape&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; 1. Send: system prompt + user request + list of available tools (with JSON schemas)&lt;/div&gt;&lt;div&gt;&amp;nbsp; 2. Model responds with either:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(a) a final text answer&amp;nbsp; -&amp;gt; exit loop&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(b) a&amp;nbsp;&lt;b&gt;&quot;tool_use&quot; block&lt;/b&gt;: { name: &quot;run_aws_cli&quot;, input: { args: [...] } }&lt;/div&gt;&lt;div&gt;&amp;nbsp; 3. Your code executes that tool, captures the result&lt;/div&gt;&lt;div&gt;&amp;nbsp; 4. Append the tool result to the conversation as a &quot;tool_result&quot; message&lt;/div&gt;&lt;div&gt;&amp;nbsp; 5. Send the whole conversation back to the model&lt;/div&gt;&lt;div&gt;&amp;nbsp; 6. Goto 2&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The model never executes anything itself — it just emits requests to call tools. Your code is the runtime that actually runs them and feeds the output back.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4&gt;Why it&#39;s a loop&lt;/h4&gt;&lt;div&gt;Each turn the model sees everything it has learned so far (prior tool calls + their outputs) and decides the next step based on that. So a real run looks like:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; - Turn 1: model calls&amp;nbsp;&lt;span style=&quot;font-family: courier;&quot;&gt;cloudwatch describe-alarms --state-value ALARM&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; - Turn 2: sees 3 alarms, picks the noisiest, calls logs filter-log-events for that log group around the alarm time&lt;/div&gt;&lt;div&gt;&amp;nbsp; - Turn 3: sees an error pattern, calls&amp;nbsp;&lt;span style=&quot;font-family: courier;&quot;&gt;kubectl describe pod&lt;/span&gt;&amp;nbsp;on the affected workload&lt;/div&gt;&lt;div&gt;&amp;nbsp; - Turn 4: emits final Markdown report, no tool call → loop exits&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; The model is doing the planning; your code is the dispatcher.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4&gt;Why you need a budget&lt;/h4&gt;&lt;div&gt;Without limits the loop can spin forever — the model keeps finding &quot;one more thing to check.&quot; Hence in agent.run():&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; - max_iterations=30 — hard cap on turns&lt;/div&gt;&lt;div&gt;&amp;nbsp; - max_tokens_per_turn=12288 — cap on a single response&lt;/div&gt;&lt;div&gt;&amp;nbsp; - Per-tool wall-clock timeouts (60 s for CLI, 30 s for HTTP)&lt;/div&gt;&lt;div&gt;&amp;nbsp; - Output truncation (50 000 char stdout) so a giant tool result doesn&#39;t blow the context window&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4&gt;How it ends&lt;/h4&gt;&lt;div&gt;The loop terminates when the model returns a response with no tool_use block — that&#39;s the &quot;I&#39;m done, here&#39;s the answer&quot; signal (stop_reason: end_turn). Or when you hit a budget limit and force-stop it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4&gt;Where the safety lives&lt;/h4&gt;&lt;div&gt;Because the model can ask for arbitrary tool calls, the loop is only as safe as the tool implementations. That&#39;s why when implementing agents we should have the allowlists (services, verbs, paths) - the model can request&amp;nbsp;&lt;span style=&quot;font-family: courier;&quot;&gt;aws s3 rm&lt;/span&gt;, but the validator rejects it before subprocess.run ever sees it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The &quot;two-pass&quot; design in agent is a refinement: pass 1 is a tool-use loop (gather), pass 2 is a single non-loop call (synthesize). Splitting them lets each prompt focus on one job.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;What are those .md files used by AI Agents?&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;There isn&#39;t a universally agreed official name, but people commonly refer to files like CLAUDE.md, GEMINI.md, AGENTS.md, COPILOT_INSTRUCTIONS.md, and .cursorrules as:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;AI agent instruction files (most generic)&lt;/li&gt;&lt;li&gt;Agent configuration files&lt;/li&gt;&lt;li&gt;Agent context files&lt;/li&gt;&lt;li&gt;LLM instruction files&lt;/li&gt;&lt;li&gt;Repository AI instructions&lt;/li&gt;&lt;li&gt;Project AI guidelines&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In the developer tooling community, &lt;b&gt;&quot;agent instructions&quot;&lt;/b&gt; or &lt;b&gt;&quot;agent context files&quot;&lt;/b&gt; are probably the most widely understood umbrella terms.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For example:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;Tool&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; File&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;----&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;-----&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;Claude Code&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; CLAUDE.md&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;Gemini CLI&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; GEMINI.md&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;GitHub Copilot&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; .github/copilot-instructions.md&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;OpenAI Codex CLI&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; AGENTS.md&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;Cursor&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .cursorrules / project rules&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;Windsurf&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Rules files&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Collectively, you could describe them as:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&quot;Repository-level AI agent instruction files that provide &lt;u&gt;persistent context&lt;/u&gt; and &lt;u&gt;operating rules&lt;/u&gt; for coding assistants.&quot;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you&#39;re building tooling around them (e.g., in your DevOps work), I&#39;d recommend using &lt;b&gt;&quot;agent instructions&quot;&lt;/b&gt; as the generic term because it&#39;s vendor-neutral and easily understood across Claude, Gemini, Copilot, Cursor, Codex, and similar tools.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/1233425363097768997/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/1233425363097768997' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/1233425363097768997'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/1233425363097768997'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/06/some-notes-on-llms.html' title='Some notes on LLMs'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8A60re2nD4AwHHSi7LJHj4v0mh7ZeoLzo28cm_iEfN3RTIDA4OyuCTEQL5vs7MR3f4xqW4zxWdYkl-iVA3JoMPWwP4HMsqPseSrtxThyphenhyphenZv7s_4lToQLXv14sFA_kX8HPBNxRP5b0-oJnAMJFx1recQJBziBHM_q78eZUTHLf2rwgn_SzS4gF18TSAevE/s72-w640-h468-c/Screenshot%202026-04-08%20at%2012.30.13.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-7392176680319035455</id><published>2026-06-03T11:19:38.085+01:00</published><updated>2026-06-03T12:17:21.065+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Agentic AI"/><category scheme="http://www.blogger.com/atom/ns#" term="Claude"/><category scheme="http://www.blogger.com/atom/ns#" term="Claude Code"/><title type='text'>Introduction to Claude by Anthropic</title><content type='html'>&lt;div style=&quot;text-align: left;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiC9dW0-zQI2mqq1qBJRsMkBhGn0O8xcS1fg4osrumfurtxCRS2e1zJwZvGQEe4oWpsIKMUuuaB94vqp1AhyphenhyphenqZIGRRItnTV1ZBaHfDTWV_t_vx-esOMA3McQez0Ij7hCVBKCBSnOHBSuVoQukHxyQyBf5yzU6zpqtZc8D79IU2hqX796qFPiKKZVIN1tHE/s1024/claude-color.png&quot; style=&quot;margin-left: 1em; margin-right: 1em; text-align: center;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1024&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiC9dW0-zQI2mqq1qBJRsMkBhGn0O8xcS1fg4osrumfurtxCRS2e1zJwZvGQEe4oWpsIKMUuuaB94vqp1AhyphenhyphenqZIGRRItnTV1ZBaHfDTWV_t_vx-esOMA3McQez0Ij7hCVBKCBSnOHBSuVoQukHxyQyBf5yzU6zpqtZc8D79IU2hqX796qFPiKKZVIN1tHE/w640-h640/claude-color.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/h3&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;How to give Claude an instruction to apply label &quot;DevOps&quot; whenever it creates a new Linear ticket?&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;It depends on whether you&#39;re creating Linear tickets via:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Linear MCP,&lt;/li&gt;&lt;li&gt;a custom /create-ticket command,&lt;/li&gt;&lt;li&gt;or just asking Claude in chat to create tickets&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;The best location depends on which of those you&#39;re using.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you&#39;re just asking Claude in chat to create tickets: if you want this behavior for all projects, put it in:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;~/.claude/CLAUDE.md&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you want it only for a specific repository/project, put it in:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;lt;repo-root&amp;gt;/CLAUDE.md&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you want it only for yourself in a specific project (without committing it to git), put it in:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;lt;repo-root&amp;gt;/CLAUDE.local.md&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;CLAUDE.local.md&lt;/span&gt; is usually the best place for personal workflow preferences like Linear labels. Claude loads it after the project-level file, so your preference is read later and tends to have more influence.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For example:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;## Linear Ticket Creation&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;When creating new Linear issues:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;- Always apply the &quot;DevOps&quot; label.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;- If multiple labels are appropriate, include &quot;DevOps&quot; in addition to the others.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;- Verify the label exists before creating the issue.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you&#39;re creating tickets through a custom slash command (e.g.&lt;span style=&quot;font-family: courier;&quot;&gt; /create-ticket&lt;/span&gt;) or a Linear MCP workflow, an even more reliable approach is to put the instruction directly in the command definition under:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;~/.claude/commands/create-ticket.md&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;or in a dedicated skill, because the instruction is then attached specifically to the ticket-creation workflow rather than relying on general memory. Many Claude Code users find &lt;u&gt;workflow-specific commands more reliable than large global CLAUDE.md files for things like Linear automation&lt;/u&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;How to instruct Claude to use feature branch name from a Linear ticket when implementing it?&lt;/h2&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Add a specific workflow rule to CLAUDE.md rather than a vague instruction. Claude follows procedural instructions much more reliably.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For example:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;## Linear Ticket Workflow&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;When implementing work from a Linear ticket:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;1. Retrieve the ticket details from Linear.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;2. Check whether the ticket has a suggested branch name.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;3. Before making any code changes, switch to or create a git branch using the Linear branch name.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;4. Do not create an alternative branch name unless the Linear branch name is unavailable.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;5. If the branch already exists remotely, check it out instead of creating a new branch.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;6. Confirm the branch name being used before starting implementation.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Example:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Linear ticket: DEV-123 Add deployment health checks&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Branch: bojan/dev-123-add-deployment-health-checks&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Commands:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;git fetch origin&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;git checkout bojan/dev-123-add-deployment-health-checks || \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;git checkout -b bojan/dev-123-add-deployment-health-checks&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you&#39;re using the &lt;b&gt;Linear MCP server&lt;/b&gt;, I&#39;d make it even more explicit:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;## Branch Naming&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;For any task originating from Linear:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;- Always obtain the branch name from the Linear ticket metadata.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;- Never invent a branch name if Linear provides one.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;- Use the Linear-provided branch name exactly as written.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;- Checkout the branch before planning or implementing changes.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;An even better approach is to create a dedicated command such as &lt;span style=&quot;font-family: courier;&quot;&gt;.claude/commands/implement-ticket.md&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Given a Linear ticket ID:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;1. Load the ticket.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;2. Read the ticket&#39;s branch name.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;3. Checkout the branch.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;4. Implement the work.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;5. Commit using the ticket ID in the commit message.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Workflow-specific commands tend to be more reliable than relying on global instructions in CLAUDE.md, especially for things like branch creation, ticket labeling, and PR naming.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;If I update ~/.claude/CLAUDE.md, do I need to start the new Claude session?&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Usually no restart is strictly required, but it depends on how you’re using Claude:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;If you’re using Claude Code / CLI (most common case)&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;~/.claude/CLAUDE.md&lt;/span&gt; is typically read when a new session starts&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So:&lt;/div&gt;&lt;div&gt;✅ New terminal session / new Claude run → picks up changes&lt;/div&gt;&lt;div&gt;⚠️ Already-running interactive session → may not reliably reload it&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Best practice: restart the Claude session (or re-open the CLI/chat) after changing it if you want to be sure the new rules apply.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;If you’re using a long-running agent session&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(e.g. an ongoing “Claude is working in the repo” process)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It often caches the instructions in memory at session start&lt;/div&gt;&lt;div&gt;So updates won’t consistently apply mid-task&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;If you’re using repo-level CLAUDE.md&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Same rule: loaded at session start or project initialization&lt;/div&gt;&lt;div&gt;Changes apply reliably on next session or re-attach to repo&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Practical rule of thumb&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Changed CLAUDE.md → start a new Claude session to guarantee it applies&lt;/div&gt;&lt;div&gt;Minor edits while actively working → assume they won’t fully apply until restart&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;How to add auto-generated instructions to global context?&lt;/h2&gt;&lt;div&gt;During Claude Code session, it created two memories but they were bound to the current project only:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;Write(/Users/bojan/.claude/projects/-Users-bojan-repos-Company-Project/memory/gh-token-unset.md)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d;&quot;&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; ⎿&amp;nbsp; Wrote 10 lines to /Users/bojan/.claude/projects/-Users-bojan-repos-&lt;/span&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;Company-Project&lt;/span&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;/memory/gh-token-unset.md&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;1 ---&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;2 name: gh-token-unset&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;3 description: gh CLI fails with HTTP 401 Bad credentials unless GH_TOKEN is unset first&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;4 metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;5&amp;nbsp; &amp;nbsp;node_type: memory&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;6&amp;nbsp; &amp;nbsp;type: reference&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;7&amp;nbsp; &amp;nbsp;originSessionId: 9xxx6&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;8 ---&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;9&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 10 In this environment `gh` fails with `HTTP 401: Bad credentials` because a stale `GH_TOKEN` env var overrides the working keyring auth. Run `unset GH_TOKEN` in the same Bash command before any `gh`&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; call — the keyring account (`BojanKomazec`, scopes gist/read:org/repo) then works. Env doesn&#39;t persist between Bash calls, so include the `unset` each time.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d;&quot;&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;⏺ Write(/Users/bojan/.claude/projects/-Users-bojan-repos-&lt;/span&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;Company-Project&lt;/span&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;/memory/precommit-hook-needs-no-verify.md)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d;&quot;&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; ⎿&amp;nbsp; Wrote 10 lines to /Users/bojan/.claude/projects/-Users-bojan-repos-&lt;/span&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;Company-Project&lt;/span&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;/memory/precommit-hook-needs-no-verify.md&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;1 ---&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;2 name: precommit-hook-needs-no-verify&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;3 description: git commit aborts in non-interactive shell; the pre-commit hook prompts on /dev/tty&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;4 metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;5&amp;nbsp; &amp;nbsp;node_type: memory&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;6&amp;nbsp; &amp;nbsp;type: reference&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;7&amp;nbsp; &amp;nbsp;originSessionId: 9xxx6&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;8 ---&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;9&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 10 The global pre-commit hook (`~/.git-templates/hooks/pre-commit`) prompts interactively via `/dev/tty` (&quot;view diff? proceed with commit?&quot;). In a non-interactive shell it errors `/dev/tty: Device no&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;t configured` and aborts the commit. Use `git commit --no-verify` to bypass it when committing programmatically.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d;&quot;&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;⏺ Write(/Users/bojan/.claude/projects/-Users-bojan-repos-&lt;/span&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;Company-Project&lt;/span&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;/memory/MEMORY.md)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d;&quot;&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; ⎿&amp;nbsp; Wrote 2 lines to /Users/bojan/.claude/projects/-Users-bojan-repos-&lt;/span&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;Company-Project&lt;/span&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;/memory/MEMORY.md&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 1 - [gh token unset](gh-token-unset.md) — `unset GH_TOKEN` before any `gh` command or it 401s&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 2 - [pre-commit hook needs --no-verify](precommit-hook-needs-no-verify.md) — commit hook prompts on /dev/tty, aborts non-interactively&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;What you’re looking at in:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;~/.claude/projects/.../memory/MEMORY.md&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;is project-scoped learned memory (auto-generated runtime notes), not the best place to define global rules.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To make something apply to all projects, you should put it in:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;~/.claude/CLAUDE.md&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;How to structure it properly&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Think of&lt;span style=&quot;font-family: courier;&quot;&gt; ~/.claude/CLAUDE.md&lt;/span&gt; as your global “agent operating system”.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can directly migrate those &lt;span style=&quot;font-family: courier;&quot;&gt;MEMORY.md&lt;/span&gt; rules into it like this:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;## Global DevOps / CLI Behavior Rules&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;These rules apply to all projects unless explicitly overridden.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;### GitHub CLI&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;- Always run `unset GH_TOKEN` before executing any `gh` command.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;- Reason: GH_TOKEN causes 401 errors in local CLI authentication.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;### Git commits&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;- When committing changes, always use `--no-verify`.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;- Reason: pre-commit hooks may attempt interactive prompts via /dev/tty and break non-interactive runs.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Important distinction (this is the key part)&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;File&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Scope&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Who writes it&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;Purpose&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;----&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; -----&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; -------------&amp;nbsp; &amp;nbsp; --------&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;~/.claude/CLAUDE.md&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp;Global (all projects)&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;You&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Your permanent rules&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;&amp;lt;repo&amp;gt;/CLAUDE.md&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Per project&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; You/team&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Repo-specific rules&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;~/.claude/projects/.../MEMORY.md&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;Auto-generated&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;Claude&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; Learned behavior, not authoritative&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;👉 Never manually “promote” &lt;span style=&quot;font-family: courier;&quot;&gt;MEMORY.md&lt;/span&gt; as your source of truth&lt;/div&gt;&lt;div&gt;Instead, copy stable patterns into&lt;span style=&quot;font-family: courier;&quot;&gt; ~/.claude/CLAUDE.md&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;For your Linear branch-name requirement&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You’d add it here too:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;## Linear Workflow (Global)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;When working from Linear tickets:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;- Always use the branch name provided by Linear metadata.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;- Never generate custom branch names.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;- Always checkout the Linear branch before implementation.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;One extra improvement (worth doing)&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you want this to be really robust, structure your global file like:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;~/.claude/CLAUDE.md&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;├── Git / GitHub rules&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;├── Linear workflow rules&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;├── Shell safety rules&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;├── CI/CD rules&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Claude responds better to clear domains than long flat lists.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/7392176680319035455/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/7392176680319035455' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/7392176680319035455'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/7392176680319035455'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/06/introduction-to-claude-by-anthropic.html' title='Introduction to Claude by Anthropic'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiC9dW0-zQI2mqq1qBJRsMkBhGn0O8xcS1fg4osrumfurtxCRS2e1zJwZvGQEe4oWpsIKMUuuaB94vqp1AhyphenhyphenqZIGRRItnTV1ZBaHfDTWV_t_vx-esOMA3McQez0Ij7hCVBKCBSnOHBSuVoQukHxyQyBf5yzU6zpqtZc8D79IU2hqX796qFPiKKZVIN1tHE/s72-w640-h640-c/claude-color.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-3669883960912657603</id><published>2026-05-14T15:36:44.566+01:00</published><updated>2026-05-14T15:36:44.566+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Checkly"/><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><category scheme="http://www.blogger.com/atom/ns#" term="Monitoring"/><title type='text'>Introduction to Checkly</title><content type='html'>&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;How Checkly works&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Checkly is a SaaS synthetic monitoring platform — you define &quot;checks&quot; (HTTP requests or browser scripts), Checkly runs them on a schedule from probe locations around the world (or on-demand from CI), records latency/assertions/screenshots, and alerts you when they fail or get slow.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp; Two main check types:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; - &lt;b&gt;API checks&lt;/b&gt; — a single HTTP request with assertions on status, headers, body, response time.&lt;/div&gt;&lt;div&gt;&amp;nbsp; - &lt;b&gt;Browser checks&lt;/b&gt; — a Playwright script run in a real &lt;a href=&quot;https://www.bojankomazec.com/2026/05/intro-to-qa-with-headless-browsers.html&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;headless&lt;/a&gt; Chromium against your deployed app.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There&#39;s also &lt;b&gt;multi-step API checks&lt;/b&gt; (chain requests, e.g. login → use token → logout) and &lt;b&gt;heartbeat checks&lt;/b&gt; (your job pings Checkly; alert if it stops).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;i&gt;Hearbeat vs Ping&amp;nbsp;&lt;/i&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;i&gt;&lt;b&gt;Heartbeats&lt;/b&gt; and &lt;b&gt;pings&lt;/b&gt; are both vital network failure-detection mechanisms, but they differ in purpose: &lt;u&gt;Heartbeats are proactive, periodic &quot;I am alive&quot; messages sent by an application to signal it is healthy&lt;/u&gt;, while &lt;u&gt;Pings are reactive requests to check if a server is reachable&lt;/u&gt;. &lt;u&gt;Heartbeats detect &lt;b&gt;application crashes&lt;/b&gt;&lt;/u&gt;&lt;b&gt;,&lt;/b&gt; &lt;u&gt;while pings detect &lt;b&gt;network downtime&lt;/b&gt;&lt;/u&gt;.&lt;/i&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Checks are typically authored as code (Checkly CLI, TypeScript) and checkly deploy&#39;d to the cloud. You can tag them (tags: [&quot;auth&quot;]), parametrise them with env vars like ENVIRONMENT_URL, and trigger them on-demand from CI — which is exactly what this PR does with npx checkly trigger --tags=auth.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp; Runtime model:&lt;/div&gt;&lt;div&gt;&amp;nbsp; - Scheduled: every N minutes from chosen regions (e.g. us-east-2, eu-west-1) — catches regressions/outages between deploys.&lt;/div&gt;&lt;div&gt;&amp;nbsp; - Triggered from CI: post-deploy smoke test, results gate (or just annotate) the deploy.&lt;/div&gt;&lt;div&gt;&amp;nbsp; - Alerts: Slack/PagerDuty/email on failure, with retry/degraded thresholds to avoid flap.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; ---&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; What it would check for this auth API&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp; Given the auth API&#39;s surface (login, OAuth, JWT issuance, admin endpoints), realistic auth-tagged checks:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; 1. Health endpoint — basic liveness&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; new ApiCheck(&quot;auth-health&quot;, {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; name: &quot;Auth API – health&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; tags: [&quot;auth&quot;],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; frequency: 1, // minute&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; locations: [&quot;us-east-2&quot;, &quot;eu-west-1&quot;],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; request: {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; url: `${process.env.ENVIRONMENT_URL}/health`,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; method: &quot;GET&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; assertions: [&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AssertionBuilder.statusCode().equals(200),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AssertionBuilder.responseTime().lessThan(500),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AssertionBuilder.jsonBody(&quot;$.status&quot;).equals(&quot;ok&quot;),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; });&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; 2. Login flow — happy path, returns a JWT&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; new ApiCheck(&quot;auth-login&quot;, {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; name: &quot;Auth API – login returns JWT&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; tags: [&quot;auth&quot;],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; request: {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; url: `${process.env.ENVIRONMENT_URL}/auth/login`,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; method: &quot;POST&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; headers: [{ key: &quot;Content-Type&quot;, value: &quot;application/json&quot; }],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; body: JSON.stringify({&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; email: process.env.SYNTHETIC_USER_EMAIL,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; password: process.env.SYNTHETIC_USER_PASSWORD,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; assertions: [&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AssertionBuilder.statusCode().equals(200),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AssertionBuilder.responseTime().lessThan(1500),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AssertionBuilder.jsonBody(&quot;$.token&quot;).isNotNull(),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // structural check on JWT shape&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AssertionBuilder.jsonBody(&quot;$.token&quot;).matches(&quot;^eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$&quot;),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; });&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp; 3. Login — wrong password returns 401 (negative path)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; Catches the &quot;accidentally accepts anything&quot; class of regression.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; new ApiCheck(&quot;auth-login-bad-pw&quot;, {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; name: &quot;Auth API – wrong password = 401&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; tags: [&quot;auth&quot;],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; request: {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; url: `${process.env.ENVIRONMENT_URL}/auth/login`,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; method: &quot;POST&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; headers: [{ key: &quot;Content-Type&quot;, value: &quot;application/json&quot; }],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; body: JSON.stringify({ email: process.env.SYNTHETIC_USER_EMAIL, password: &quot;wrong&quot; }),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; assertions: [AssertionBuilder.statusCode().equals(401)],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; });&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp; 4. Multi-step — login then call protected endpoint&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; This is the most useful kind for an auth API, because it proves the token actually works.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; new MultiStepCheck(&quot;auth-token-roundtrip&quot;, {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; name: &quot;Auth API – token works against /me&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; tags: [&quot;auth&quot;],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; code: { entrypoint: path.join(__dirname, &quot;token-roundtrip.spec.ts&quot;) },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; });&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; // token-roundtrip.spec.ts&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; import { test, expect } from &quot;@playwright/test&quot;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; test(&quot;login then /me&quot;, async ({ request }) =&amp;gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; const login = await request.post(`${process.env.ENVIRONMENT_URL}/auth/login`, {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; data: { email: process.env.SYNTHETIC_USER_EMAIL, password: process.env.SYNTHETIC_USER_PASSWORD },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; });&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; expect(login.ok()).toBeTruthy();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; const { token } = await login.json();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; const me = await request.get(`${process.env.ENVIRONMENT_URL}/me`, {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; headers: { Authorization: `Bearer ${token}` },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; });&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; expect(me.status()).toBe(200);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; const body = await me.json();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; expect(body.email).toBe(process.env.SYNTHETIC_USER_EMAIL);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; });&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp; 5. TLS &amp;amp; cert expiry&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; A pure config check — useful because cert rotation is a classic outage cause.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; new ApiCheck(&quot;auth-tls&quot;, {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; name: &quot;Auth API – TLS cert valid &amp;gt; 14d&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; tags: [&quot;auth&quot;],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; request: {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; url: `${process.env.ENVIRONMENT_URL}/health`,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; method: &quot;GET&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; assertions: [AssertionBuilder.statusCode().equals(200)],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;font-size: x-small;&quot;&gt;// Checkly surfaces cert expiry on the run; you set a threshold per check&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; });&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp; 6. Browser check — full login UX&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; expect(login.ok()).toBeTruthy();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; const { token } = await login.json();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; const { token } = await login.json();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; const me = await request.get(`${process.env.ENVIRONMENT_URL}/me`, {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; headers: { Authorization: `Bearer ${token}` },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; });&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; expect(me.status()).toBe(200);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; const body = await me.json();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; expect(body.email).toBe(process.env.SYNTHETIC_USER_EMAIL);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; });&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; 5. TLS &amp;amp; cert expiry&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; A pure config check — useful because cert rotation is a classic outage cause.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; new ApiCheck(&quot;auth-tls&quot;, {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; name: &quot;Auth API – TLS cert valid &amp;gt; 14d&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; tags: [&quot;auth&quot;],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; request: {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; url: `${process.env.ENVIRONMENT_URL}/health`,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; method: &quot;GET&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; assertions: [AssertionBuilder.statusCode().equals(200)],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;font-size: x-small;&quot;&gt;// Checkly surfaces cert expiry on the run; you set a threshold per check&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; 5. TLS &amp;amp; cert expiry&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; A pure config check — useful because cert rotation is a classic outage cause.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; new ApiCheck(&quot;auth-tls&quot;, {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; name: &quot;Auth API – TLS cert valid &amp;gt; 14d&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; tags: [&quot;auth&quot;],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; request: {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; url: `${process.env.ENVIRONMENT_URL}/health`,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; method: &quot;GET&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; assertions: [AssertionBuilder.statusCode().equals(200)],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;font-size: x-small;&quot;&gt;// Checkly surfaces cert expiry on the run; you set a threshold per check&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; });&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; new ApiCheck(&quot;auth-tls&quot;, {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; name: &quot;Auth API – TLS cert valid &amp;gt; 14d&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; tags: [&quot;auth&quot;],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; request: {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; url: `${process.env.ENVIRONMENT_URL}/health`,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; method: &quot;GET&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; assertions: [AssertionBuilder.statusCode().equals(200)],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;font-size: x-small;&quot;&gt;// Checkly surfaces cert expiry on the run; you set a threshold per check&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; });&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; 6. Browser check — full login UX&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; Runs against the front-end but exercises the auth API end-to-end including redirects, cookies, CSRF.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; new BrowserCheck(&quot;auth-ui-login&quot;, {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; name: &quot;Login UI works&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; tags: [&quot;auth&quot;],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; code: { entrypoint: path.join(__dirname, &quot;login.spec.ts&quot;) },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; });&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; import { test, expect } from &quot;@playwright/test&quot;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; test(&quot;user can sign in&quot;, async ({ page }) =&amp;gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; await page.goto(process.env.ENVIRONMENT_URL!);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; await page.getByLabel(&quot;Email&quot;).fill(process.env.SYNTHETIC_USER_EMAIL!);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; await page.getByLabel(&quot;Password&quot;).fill(process.env.SYNTHETIC_USER_PASSWORD!);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; await page.getByRole(&quot;button&quot;, { name: &quot;Sign in&quot; }).click();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; await expect(page.getByText(&quot;Dashboard&quot;)).toBeVisible({ timeout: 10_000 });&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; });&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; 7. OAuth callback reachability&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; Doesn&#39;t fully exercise the Google/Microsoft flow (those need real consent), but checks the callback&lt;/div&gt;&lt;div&gt;&amp;nbsp; endpoint responds correctly to a missing-code request — confirms route + handler are wired.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; new ApiCheck(&quot;auth-oauth-google-callback-shape&quot;, {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; name: &quot;Auth API – Google OAuth callback exists&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; tags: [&quot;auth&quot;],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; request: {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; url: `${process.env.ENVIRONMENT_URL}/auth/google/callback`,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; method: &quot;GET&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; assertions: [&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // 400 for missing `code`, not 404/500 — proves handler is mounted&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AssertionBuilder.statusCode().equals(400),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; });&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/3669883960912657603/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/3669883960912657603' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/3669883960912657603'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/3669883960912657603'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/05/introduction-to-checkly.html' title='Introduction to Checkly'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-1418997202847760203</id><published>2026-05-14T11:14:54.403+01:00</published><updated>2026-05-14T11:14:54.403+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Browser"/><category scheme="http://www.blogger.com/atom/ns#" term="Frontend"/><category scheme="http://www.blogger.com/atom/ns#" term="QA"/><title type='text'>Intro to QA with Headless Browsers</title><content type='html'>&lt;div style=&quot;text-align: left;&quot;&gt;Headless browsers are used in QA to execute automated browser tests faster and more efficiently by eliminating the graphical user interface (GUI). Because &lt;u&gt;they don&#39;t render visuals&lt;/u&gt;, they &lt;u&gt;consume fewer resources&lt;/u&gt;, enabling rapid, parallel testing in CI/CD pipelines, making them ideal for high-volume functional and regression testing.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Key Reasons for Using Headless Browsers in QA:&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Faster Execution: Without the need to render CSS, images, or layout, tests run significantly faster.&lt;/li&gt;&lt;li&gt;CI/CD Integration: They are ideal for server-side environments where a GUI is unavailable, allowing automated tests to run after every code commit.&lt;/li&gt;&lt;li&gt;Lower Resource Usage: They consume significantly less RAM and CPU, allowing for higher parallelization (running many tests simultaneously) without overloading hardware.&lt;/li&gt;&lt;li&gt;Automated Functional Testing: They can accurately simulate user actions such as clicking buttons, submitting forms, and navigating pages.&lt;/li&gt;&lt;li&gt;Regression Testing: Due to speed and efficiency, they are perfect for running large suites of regression tests to ensure new changes haven&#39;t broken existing functionality.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Common tools for headless testing include headless Chrome, Firefox, Puppeteer, and Playwright&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Headless browsers &lt;u&gt;parse, compile, and execute the exact same underlying code as standard browsers, but they skip the final step of painting pixels to a physical screen&lt;/u&gt;.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;What Headless Browsers Still Do&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Construct the DOM: They parse HTML into a full Document Object Model tree.&lt;/li&gt;&lt;li&gt;Apply Styling: They process CSS and calculate layout, element positions, and visibility.&lt;/li&gt;&lt;li&gt;Execute JavaScript: They run a full JS engine (like V8 in Chrome) to handle AJAX, animations, and frontend logic.&lt;/li&gt;&lt;li&gt;Manage Network Traffic: They make real HTTP requests, download cookies, and handle API responses.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;How QA Verifies Visuals Without a Display&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Layout Queries: Code checks if elements are present, hidden, or overlapping by querying their coordinates.&lt;/li&gt;&lt;li&gt;Computed Styles: Scripts verify specific CSS properties, like checking if a button color is exactly rgb(0, 0, 255).&lt;/li&gt;&lt;li&gt;Virtual Screenshots: The browser renders the page into an in-memory buffer, allowing QA tools to save PNGs or perform pixel-by-pixel visual regression comparisons.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;To help tailor using headless browser to our workflow, we need to know:&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Which testing framework we are using (e.g., Playwright, Selenium, Cypress)?&lt;/li&gt;&lt;li&gt;Are we trying to catch functional bugs or visual layout glitches?&lt;/li&gt;&lt;li&gt;Do our tests run on a local machine or a CI/CD server (e.g., GitHub Actions, Jenkins)?&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;---&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/1418997202847760203/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/1418997202847760203' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/1418997202847760203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/1418997202847760203'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/05/intro-to-qa-with-headless-browsers.html' title='Intro to QA with Headless Browsers'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-8038873605182059656</id><published>2026-04-29T14:24:23.579+01:00</published><updated>2026-04-29T14:24:23.580+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AWS"/><category scheme="http://www.blogger.com/atom/ns#" term="AWS SNS"/><category scheme="http://www.blogger.com/atom/ns#" term="AWS SQS"/><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><title type='text'>Introduction to Amazon Simple Notification Service (SNS)</title><content type='html'>&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8SqiQ4Whxspu4ooNEx8jANQ_T4iKjjFWyut0EJ4vbDcAz7oaka7xcDt9hKzdbwWJ8R6ZcRHF6whEWTEaW8Trwnkdr8NJwL4nm3riQdOtM-ngVDmIXkaMZZYVgH0xKUjxg1KSQsGnJSWwLWoIXvLQoUTlDsWfmm6uPvrXxt9IsWwQ2kxLyNmVbX0NLOdM/s1990/Screenshot%202024-08-05%20at%2014.27.37.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;914&quot; data-original-width=&quot;1990&quot; height=&quot;294&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8SqiQ4Whxspu4ooNEx8jANQ_T4iKjjFWyut0EJ4vbDcAz7oaka7xcDt9hKzdbwWJ8R6ZcRHF6whEWTEaW8Trwnkdr8NJwL4nm3riQdOtM-ngVDmIXkaMZZYVgH0xKUjxg1KSQsGnJSWwLWoIXvLQoUTlDsWfmm6uPvrXxt9IsWwQ2kxLyNmVbX0NLOdM/w640-h294/Screenshot%202024-08-05%20at%2014.27.37.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Amazon Simple Notification Service (SNS) is a fully managed messaging service that enables you to decouple microservices, distributed systems, and serverless applications. Here&#39;s how SNS works:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Key Concepts&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Topics&lt;/b&gt;:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A topic is a logical access point and communication channel. Publishers send messages to a topic, and subscribers receive these messages by subscribing to the topic.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Publishers&lt;/b&gt;:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Publishers are entities that send messages to an SNS topic. They could be applications, services, or even other AWS services like Lambda or CloudWatch.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Subscribers&lt;/b&gt;:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Subscribers are endpoints that receive messages from an SNS topic. These can include &lt;u&gt;Amazon SQS queues,&lt;/u&gt; AWS Lambda functions, HTTP/S endpoints, email addresses, and SMS numbers.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Messages&lt;/b&gt;:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Messages are the payload sent by publishers to SNS topics. They can include a variety of data formats, typically JSON.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;How It Works&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Creating a Topic:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First, you create a topic using the AWS Management Console, AWS CLI, or AWS SDKs. This &lt;u&gt;topic acts as a communication channel.&lt;/u&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Subscribing to a Topic:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You then subscribe one or more endpoints to the topic. These endpoints can be other AWS services or external services capable of receiving notifications.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When subscribing, you specify the protocol (such as HTTP, SQS, Lambda, etc.) and the endpoint (like the URL or ARN of the SQS queue).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Publishing a Message:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Publishers send messages to the SNS topic using the Publish API. The message can include a subject, a message body, and optional attributes.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;SNS stores multiple copies of the message for redundancy and high availability.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Message Delivery:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;SNS distributes the message to all subscribed endpoints.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Each endpoint processes the message according to its protocol. For example, an HTTP endpoint receives a POST request with the message content, and an SQS queue receives the message as a new queue entry.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Use Cases&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Fan-out Scenarios:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When a message published to an SNS topic needs to be sent to multiple endpoints, SNS acts as a fan-out service. For example, updating various microservices or notifying multiple systems about an event.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Push Notifications:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;SNS can be used to send push notifications to mobile devices through services like Amazon Device Messaging (ADM), Apple Push Notification Service (APNS), and Google Cloud Messaging (GCM).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Application Alerts:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Sending notifications or alerts to administrators or users via SMS, email, or other endpoints.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Event-Driven Computing:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Integrating with AWS Lambda to trigger functions in response to incoming messages, enabling event-driven processing.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Benefits&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Scalability:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;SNS is designed to handle high-throughput and large volumes of messages, making it suitable for large-scale applications.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Flexibility:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It supports multiple protocols, allowing for versatile messaging architectures.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Reliability:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;With built-in redundancy and fault tolerance, SNS ensures reliable message delivery.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Ease of Use:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The service is fully managed, reducing the operational overhead associated with maintaining messaging infrastructure.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Security&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Access Control:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Using AWS IAM policies, you can control who can publish or subscribe to topics.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Encryption&lt;/b&gt;:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;SNS supports server-side encryption (SSE) for messages at rest and SSL/TLS for messages in transit.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Compliance&lt;/b&gt;:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;SNS is compliant with various industry standards and regulations, ensuring it meets security and compliance requirements.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Amazon SNS is a powerful and flexible tool for building loosely coupled, scalable, and robust messaging solutions in the cloud.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;How does Amazon SNS differ from Amazon SQS?&lt;/h1&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Amazon SNS (Simple Notification Service) and Amazon SQS (Simple Queue Service) are both messaging services provided by AWS, but they serve different purposes and have distinct features. Here&#39;s a comparison highlighting their differences:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Purpose and Use Cases&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Amazon SNS:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Publish/Subscribe Messaging:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;SNS is designed for &lt;u&gt;sending notifications or messages to multiple subscribers&lt;/u&gt;.&lt;/li&gt;&lt;li&gt;It&#39;s ideal for &lt;u&gt;broadcasting messages&lt;/u&gt; to multiple endpoints, such as sending alerts, notifications, or updates to different systems or users.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Use Cases:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Real-time notifications&lt;/li&gt;&lt;li&gt;push notifications&lt;/li&gt;&lt;li&gt;fan-out scenarios (where a message needs to be sent to multiple recipients simultaneously)&lt;/li&gt;&lt;li&gt;application alerts&lt;/li&gt;&lt;li&gt;event-driven architectures&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Amazon SQS:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Message Queuing:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;SQS is designed for decoupling and scaling distributed systems.&amp;nbsp;&lt;/li&gt;&lt;li&gt;It allows you to send, store, and receive messages between software components at any volume, without losing messages or requiring other services to be available.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Use Cases:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Task queues&lt;/li&gt;&lt;li&gt;asynchronous processing&lt;/li&gt;&lt;li&gt;decoupling microservices&lt;/li&gt;&lt;li&gt;job dispatching&lt;/li&gt;&lt;li&gt;buffering messages between producer and consumer systems&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Messaging Patterns&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Amazon SNS:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Push-Based: SNS pushes messages to subscribers. Subscribers can be other AWS services (like Lambda, SQS), HTTP/S endpoints, email addresses, SMS numbers, and mobile push notifications.&lt;/li&gt;&lt;li&gt;Fan-Out: One message can be sent to multiple subscribers.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Amazon SQS:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Pull-Based: Consumers pull messages from the queue. A consumer explicitly retrieves messages from the queue.&lt;/li&gt;&lt;li&gt;Point-to-Point: Each message is delivered to and processed by one consumer.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Message Handling&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Amazon SNS:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Real-Time Delivery: Messages are delivered immediately to all subscribers.&lt;/li&gt;&lt;li&gt;No Message Persistence: Messages are not stored after delivery; if a subscriber is unavailable, the message is lost unless it&#39;s sent to an SQS queue or some other durable store.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Amazon SQS:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Message Persistence: Messages are stored in the queue until they are processed and deleted by a consumer, or until they expire.&lt;/li&gt;&lt;li&gt;Delivery Guarantees: Ensures at least once delivery. With FIFO queues, SQS provides exactly-once processing and message ordering.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Scalability and Performance&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Amazon SNS:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Scalable: Designed to handle massive numbers of messages and deliver them to large numbers of subscribers.&lt;/li&gt;&lt;li&gt;Latency: Typically has very low latency for message delivery.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Amazon SQS:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Scalable: Automatically scales to handle large volumes of messages. Suitable for high-throughput applications.&lt;/li&gt;&lt;li&gt;Latency: Slightly higher latency compared to SNS due to the nature of pull-based consumption.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Features and Capabilities&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Amazon SNS:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Multiple Protocols: Supports multiple delivery protocols including HTTP/S, email, SMS, SQS, Lambda, and mobile push notifications.&lt;/li&gt;&lt;li&gt;Filtering: Allows message filtering, enabling subscribers to receive only the messages that match their filter policies.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Amazon SQS:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Visibility Timeout: Temporarily hides a message from other consumers while it is being processed.&lt;/li&gt;&lt;li&gt;Dead-Letter Queues (DLQ): Allows you to handle messages that can&#39;t be processed successfully.&lt;/li&gt;&lt;li&gt;FIFO Queues: Ensures the order of messages and exactly-once processing.&lt;/li&gt;&lt;li&gt;Delay Queues: Postpones the delivery of new messages to consumers for a specified amount of time.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Pricing&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Amazon SNS:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Pricing Model: Based on the number of requests (publishes, deliveries, and notifications) and data transfer.&lt;/li&gt;&lt;li&gt;Cost Efficiency: More cost-effective for scenarios requiring a high number of subscribers and real-time notifications.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Amazon SQS:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Pricing Model: Based on the number of requests (send, receive, delete) and data transfer.&lt;/li&gt;&lt;li&gt;Cost Efficiency: More cost-effective for decoupling microservices and scenarios requiring message persistence and complex message handling.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Integration and Interoperability&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Amazon SNS:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Integration: Easily integrates with a wide range of AWS services (e.g., Lambda, SQS, HTTP/S endpoints, etc.).&lt;/li&gt;&lt;li&gt;Interoperability: Often used in conjunction with SQS for fan-out scenarios where messages need to be processed asynchronously and stored reliably.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Amazon SQS:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Integration: Commonly used to decouple systems and provide reliable message delivery. Often used with other AWS services like Lambda, ECS, and EC2.&lt;/li&gt;&lt;li&gt;Interoperability: Can be subscribed to SNS topics to receive messages that need persistent storage or further processing.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Summary&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In summary, Amazon SNS is a pub/sub messaging service optimized for real-time notifications and broadcasting messages to multiple subscribers, while Amazon SQS is a message queuing service designed for decoupling distributed systems and ensuring reliable message delivery through persistence and processing guarantees. They are often used together to build scalable, resilient, and flexible messaging architectures in AWS.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;a href=&quot;https://aws.amazon.com/sns/&quot;&gt;Push Notification Service - Amazon Simple Notification Service - AWS&lt;/a&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/8038873605182059656/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/8038873605182059656' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/8038873605182059656'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/8038873605182059656'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/04/introduction-to-amazon-simple.html' title='Introduction to Amazon Simple Notification Service (SNS)'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8SqiQ4Whxspu4ooNEx8jANQ_T4iKjjFWyut0EJ4vbDcAz7oaka7xcDt9hKzdbwWJ8R6ZcRHF6whEWTEaW8Trwnkdr8NJwL4nm3riQdOtM-ngVDmIXkaMZZYVgH0xKUjxg1KSQsGnJSWwLWoIXvLQoUTlDsWfmm6uPvrXxt9IsWwQ2kxLyNmVbX0NLOdM/s72-w640-h294-c/Screenshot%202024-08-05%20at%2014.27.37.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-8196912125955159361</id><published>2026-04-21T13:07:00.002+01:00</published><updated>2026-04-21T13:07:15.131+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AWS EKS"/><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><category scheme="http://www.blogger.com/atom/ns#" term="Kubernetes"/><category scheme="http://www.blogger.com/atom/ns#" term="Terraform"/><title type='text'>Provisioning AWS EKS Cluster with terraform-aws-modules/eks/aws</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpL3UGIwOtt3orHP_dEAx8jM5SFevZLk2BnC6GGcWxyhk7xlnNCeo1oLfWDQsVP21h-OlZamMah3YrDbtKPzUdctuUQx5HXUVZaVCV3p9Ou2BqnQshV0K8zeYt1pHjQCCRrL4QjTTiYRr7NGpV-6wJha2TNZGsSB448SNqosT_i8o2hLKd0wTc3B5OyZA/s728/aws-eks_terraform-1.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;728&quot; data-original-width=&quot;350&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpL3UGIwOtt3orHP_dEAx8jM5SFevZLk2BnC6GGcWxyhk7xlnNCeo1oLfWDQsVP21h-OlZamMah3YrDbtKPzUdctuUQx5HXUVZaVCV3p9Ou2BqnQshV0K8zeYt1pHjQCCRrL4QjTTiYRr7NGpV-6wJha2TNZGsSB448SNqosT_i8o2hLKd0wTc3B5OyZA/w308-h640/aws-eks_terraform-1.png&quot; width=&quot;308&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/terraform-aws-modules/terraform-aws-eks&quot;&gt;terraform-aws-modules/terraform-aws-eks: Terraform module to create Amazon Elastic Kubernetes (EKS) resources&lt;/a&gt;&amp;nbsp;is a popular Terraform module for provisioning AWS EKS cluster.&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;In this article we want to explore and breakdown its key components and their purposes.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;We&#39;d typically use this module like here:&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;module &quot;eks&quot; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; source&amp;nbsp; = &quot;terraform-aws-modules/eks/aws&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; version = &quot;21.15.1&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; ...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Let&#39;s explore this module&#39;s attributes.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;1. Cluster Configuration&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;name&lt;/span&gt;,&amp;nbsp;&amp;nbsp;&lt;span style=&quot;font-family: courier;&quot;&gt;version&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;Sets the name and Kubernetes version for the EKS cluster. Use local and variable values for flexibility.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;endpoint_public_access&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;Set public (Internet) access to the Kubernetes API endpoint (via &lt;span style=&quot;font-family: courier;&quot;&gt;kubectl&lt;/span&gt;). Disable it for enhanced security.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;endpoint_private_access&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;Set private access to the API endpoint, whether only resources within the VPC can access it. If enabled, it is only reachable from within the VPC (Virtual Private Cloud) where your EKS cluster is deployed. There are few ways to access it:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;How to Access the Kubernetes API from VPC&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1. Use a Bastion Host or EC2 Instance in the VPC&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Launch an EC2 instance (bastion host or jump box) in a subnet within the same VPC as your EKS cluster.&lt;/div&gt;&lt;div&gt;SSH into this instance, and from there, use kubectl to access the cluster.&lt;/div&gt;&lt;div&gt;Alternatively, use SSH port forwarding or a VPN to proxy kubectl commands from your local machine through the bastion.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;2. Use AWS Systems Manager (SSM) Session Manager&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If your EC2 instances have the SSM agent and the necessary IAM permissions, you can use AWS SSM Session Manager to start a shell session on an instance in the VPC, then run kubectl from there.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;3. Use a VPN Connection&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Set up a VPN (such as AWS Client VPN or OpenVPN, or Site-to-site VPN for office LAN) that connects your local network to the VPC. Once connected, your local machine will be able to reach the private endpoint.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;4. Use AWS PrivateLink (Interface VPC Endpoints)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For advanced scenarios, you can use AWS PrivateLink to expose the Kubernetes API endpoint privately to other VPCs or on-premises networks.&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;enable_cluster_creator_admin_permissions&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If enabled, grants admin permissions to the user who creates the cluster.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;2. Logging and Add-ons&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;enabled_log_types&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;Enables logging for various Kubernetes components (API, audit, authenticator, controllerManager, scheduler) for monitoring and troubleshooting.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Example:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; enabled_log_types = [&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &quot;api&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &quot;audit&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &quot;authenticator&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &quot;controllerManager&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &quot;scheduler&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; ]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;addons&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;A dictionary-type attribute which installs and configures essential Kubernetes add-ons. Dictionary keys are addon names like:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;coredns&lt;/li&gt;&lt;li&gt;kube-proxy&lt;/li&gt;&lt;li&gt;aws-ebs-csi-driver&lt;/li&gt;&lt;li&gt;vpc-cni&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Dictionary values are objects which attributes are:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;most_recent&lt;/span&gt; - to set using the latest version (set it to &lt;span style=&quot;font-family: courier;&quot;&gt;false&lt;/span&gt; for version pinning)&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;version&lt;/span&gt; - addon version (use it for version pinning)&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;before_compute&lt;/span&gt; - set it to true if addon should be installed and set before nodes (compute layer)&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;service_account_role_arn&lt;/span&gt; - to configure addon with IAM roles for service accounts, enabling secure integration with AWS services.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Example:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;addons = {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; ...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; vpc-cni = {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;b&gt;most_recent&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; = false&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;b&gt;version&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; = &quot;v1.21.1-eksbuild.7&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;b&gt;before_compute&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;= true&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;b&gt;service_account_role_arn&lt;/b&gt; = module.k8s_default_vpc_cni_irsa.iam_role_arn&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; ...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;VPC CNI (Container networking interface) is responsible for allocating IP addresses to the Kubernetes nodes and provides networking to pods. The plugin manage network interfaces (ENIs) on the nodes and uses it to assign IP addresses to pods.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;3. Networking&lt;/h2&gt;&lt;div&gt;We need to integrate the EKS cluster with existing VPC and subnets:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;vpc_id&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;VPC ID&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;subnet_ids&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;Subnets in which nodes (EC2 instances) will be created.&lt;/div&gt;&lt;div&gt;Where your worker nodes (EC2 instances) run.&lt;br /&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;b&gt;control_plane_subnet_ids&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;Where the EKS control plane ENIs (network interfaces) are placed&lt;/div&gt;&lt;div&gt;Defines where the EKS control plane creates its Elastic Network Interfaces (ENIs)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;What it controls:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;The EKS control plane runs in an AWS-managed VPC (you don&#39;t see it)&lt;/li&gt;&lt;li&gt;To communicate with your worker nodes, it creates ENIs in your VPC&lt;/li&gt;&lt;li&gt;These ENIs are placed in the subnets you specify here&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Typical configuration:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;module &quot;eks&quot; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; source&amp;nbsp; = &quot;terraform-aws-modules/eks/aws&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name = &quot;my-cluster&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; # Control plane ENIs go here&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &lt;b&gt;control_plane_subnet_ids&lt;/b&gt; = [&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &quot;subnet-private-1a&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &quot;subnet-private-1b&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &quot;subnet-private-1c&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; ]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Best practices:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Usually private subnets&lt;/li&gt;&lt;li&gt;Should span multiple AZs for high availability (AWS requires at least 2)&lt;/li&gt;&lt;li&gt;Minimum of 2 subnets, maximum of 16&lt;/li&gt;&lt;li&gt;Each subnet needs at least 5 available IP addresses&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What these ENIs do:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Allow the control plane to communicate with worker nodes&lt;/li&gt;&lt;li&gt;Allow worker nodes to communicate with the API server&lt;/li&gt;&lt;li&gt;Handle API server endpoint traffic&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;security_group_additional_rules&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Adds custom security group rules for the cluster, such as allowing node-to-node communication and VPN access for kubectl.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;node_security_group_additional_rules&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Further customizes node security groups, allowing all node-to-node traffic and all outbound traffic.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Understanding EKS Architecture&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;An EKS cluster has two main components:&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;┌─────────────────────────────────────────────────────────┐&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; EKS Cluster&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;│&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;│&amp;nbsp; ┌───────────────────────────────────────┐&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;│&amp;nbsp; │&amp;nbsp; &amp;nbsp;Control Plane (AWS Managed)&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;│&amp;nbsp; │&amp;nbsp; &amp;nbsp;- API Server&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;│&amp;nbsp; │&amp;nbsp; &amp;nbsp;- etcd&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;│&amp;nbsp; │&amp;nbsp; &amp;nbsp;- Scheduler&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;│&amp;nbsp; │&amp;nbsp; &amp;nbsp;- Controller Manager&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;│&amp;nbsp; │&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;│&amp;nbsp; │&amp;nbsp; &amp;nbsp;Runs in AWS-managed account&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;│&amp;nbsp; └──────────────┬────────────────────────┘&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;│&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;│ ENIs in your VPC&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;│ (&lt;b&gt;control_plane_subnet_ids&lt;/b&gt;)&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;│&amp;nbsp; ┌──────────────▼────────────────────────┐&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;│&amp;nbsp; │&amp;nbsp; &amp;nbsp;Your VPC&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;│&amp;nbsp; │&amp;nbsp; &amp;nbsp;┌─────────────────────────────┐&amp;nbsp; &amp;nbsp; &amp;nbsp;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;│&amp;nbsp; │&amp;nbsp; &amp;nbsp;│&amp;nbsp; Worker Nodes (subnet_ids)&amp;nbsp; │&amp;nbsp; &amp;nbsp; &amp;nbsp;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;│&amp;nbsp; │&amp;nbsp; &amp;nbsp;│&amp;nbsp; - EC2 instances&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&amp;nbsp; &amp;nbsp; &amp;nbsp;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;│&amp;nbsp; │&amp;nbsp; &amp;nbsp;│&amp;nbsp; - Your pods run here&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;│&amp;nbsp; &amp;nbsp; &amp;nbsp;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;│&amp;nbsp; │&amp;nbsp; &amp;nbsp;└─────────────────────────────┘&amp;nbsp; &amp;nbsp; &amp;nbsp;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;│&amp;nbsp; └───────────────────────────────────────┘&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;└─────────────────────────────────────────────────────────┘&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;ENI: elastic network interface&lt;/b&gt;. It is a logical networking component in a VPC that represents a &lt;b&gt;virtual network card&lt;/b&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;4. Node Group Configuration&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;node_security_group_tags&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Adds a tag for Karpenter (an open-source Kubernetes node autoscaler) discovery.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;eks_managed_node_group_defaults&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Sets default properties for all managed node groups, including:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Attaching the CNI policy for networking.&lt;/li&gt;&lt;li&gt;Using a specific SSH key.&lt;/li&gt;&lt;li&gt;Associating additional security groups.&lt;/li&gt;&lt;li&gt;Defining block device mappings for EBS volumes.&lt;/li&gt;&lt;li&gt;Attaching the AmazonSSMManagedInstanceCore policy for SSM access.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;eks_managed_node_groups&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Defines a default managed node group with:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;A specific AMI type.&lt;/li&gt;&lt;li&gt;Desired, minimum, and maximum node counts.&lt;/li&gt;&lt;li&gt;Instance types from a variable.&lt;/li&gt;&lt;li&gt;On-demand capacity, EBS optimization, and disk size.&lt;/li&gt;&lt;li&gt;Custom labels for node identification and environment.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;The gold standard for production environments is &lt;b&gt;explicit pinning&lt;/b&gt;. This ensures that our infrastructure only changes when we decide to change the code. In order to pin AMI version used in node groups we need to set two attributes:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;ami_release_version&lt;/span&gt; needs to be set. This prevents nodes from cycling unexpectedly during a routine deployment.&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;use_latest_ami_release_version&lt;/span&gt; needs to be set to false (without this, terraform plan will still show that it wants to upgrade AMI version, even if we&#39;ve set ami_release_version)&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Example:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; eks_managed_node_groups = {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &quot;${local.cluster_name}-v1_33&quot; = {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;b&gt;ami_release_version&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; = &quot;1.33.8-20260224&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;b&gt;use_latest_ami_release_version&lt;/b&gt; = false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;5. Tagging&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;tags&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Applies custom tags to all AWS resources created by the module, supporting cost allocation and resource management.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Summary&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Our configuration sets up a secure, private, and production-ready EKS cluster with managed node groups, essential add-ons, robust logging, and fine-grained network and IAM controls. It leverages best practices for security (private endpoints, IAM roles for service accounts), scalability (managed node groups, Karpenter tags), and maintainability (modular, versioned, and tagged infrastructure).&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;---&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://github.com/terraform-aws-modules/terraform-aws-iam/tree/91c8dbd25d9546d228c2c8030c1463f9b52c9b43/modules/iam-role-for-service-accounts-eks&quot;&gt;&lt;br class=&quot;Apple-interchange-newline&quot; /&gt;terraform-aws-iam/modules/iam-role-for-service-accounts-eks&lt;/a&gt;&amp;nbsp;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/8196912125955159361/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/8196912125955159361' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/8196912125955159361'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/8196912125955159361'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/04/provisioning-aws-eks-cluster-with.html' title='Provisioning AWS EKS Cluster with terraform-aws-modules/eks/aws'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpL3UGIwOtt3orHP_dEAx8jM5SFevZLk2BnC6GGcWxyhk7xlnNCeo1oLfWDQsVP21h-OlZamMah3YrDbtKPzUdctuUQx5HXUVZaVCV3p9Ou2BqnQshV0K8zeYt1pHjQCCRrL4QjTTiYRr7NGpV-6wJha2TNZGsSB448SNqosT_i8o2hLKd0wTc3B5OyZA/s72-w308-h640-c/aws-eks_terraform-1.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-6511924002821933978</id><published>2026-04-15T12:31:00.001+01:00</published><updated>2026-04-15T12:31:29.851+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><category scheme="http://www.blogger.com/atom/ns#" term="DevSecOps"/><category scheme="http://www.blogger.com/atom/ns#" term="Security"/><title type='text'>Core Security Practices in DevSecOps &amp; Software Engineering</title><content type='html'>&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigN0G2_Nss2ejnu7Nzwu9QVUn0D8PMWJfTlUpNZ68bK2HZwjJwMbT3a9IdN07084ukNs6N6LhCQhAqlzyMlAPX5U2kROryXtLmghwSHLXdW8WBKttIfM5JOh5fjvPemGkJVnRZ9BwGW7jFh4h3tSYM0bheMT6VECYuNTB3o3oSSFM2KuHHcFMz3lQEwQQ/s2816/devsecops.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1536&quot; data-original-width=&quot;2816&quot; height=&quot;350&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigN0G2_Nss2ejnu7Nzwu9QVUn0D8PMWJfTlUpNZ68bK2HZwjJwMbT3a9IdN07084ukNs6N6LhCQhAqlzyMlAPX5U2kROryXtLmghwSHLXdW8WBKttIfM5JOh5fjvPemGkJVnRZ9BwGW7jFh4h3tSYM0bheMT6VECYuNTB3o3oSSFM2KuHHcFMz3lQEwQQ/w640-h350/devsecops.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Integrating security into DevOps and software engineering, often called DevSecOps, is a critical shift from treating security as a final checkpoint to embedding it throughout the entire development lifecycle.&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;Here are the best security practices, with a specific focus on secrets management and key rotation.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;Core Security Practices in DevSecOps &amp;amp; Software Engineering&lt;/h1&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;1. Shift Left&lt;/h2&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;This is the foundational principle of DevSecOps. It means introducing security testing and considerations as early as possible in the software development life cycle (SDLC).&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Why: It is significantly cheaper and faster to fix a security flaw during the design or coding phase than it is after deployment.&lt;/li&gt;&lt;li&gt;Action: Conduct threat modeling during design, use secure coding standards, and run security scans on every code commit.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;2. Automate Security Testing&lt;/h2&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Manual security reviews cannot keep up with the speed of DevOps. Automation is essential.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Static Application Security Testing (SAST): Scans your source code for known vulnerabilities (like SQL injection or cross-site scripting) without running the application. Tools: SonarQube, CodeQL.&lt;/li&gt;&lt;li&gt;Dynamic Application Security Testing (DAST): Tests the running application from the outside, mimicking an attacker to find runtime vulnerabilities. Tools: OWASP ZAP, Burp Suite.&lt;/li&gt;&lt;li&gt;Software Composition Analysis (SCA): Analyzes your application’s dependencies (open-source libraries) for known vulnerabilities. Tools: Snyk, Dependabot, OWASP Dependency-Check.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;3. Implement the Principle of Least Privilege (PoLP)&lt;/h2&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Every user, process, and system should have only the minimum permissions necessary to perform its function.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Action:&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Developers should not have administrative access to production environments.&lt;/li&gt;&lt;li&gt;CI/CD pipelines should use dedicated service accounts with tightly scoped permissions (e.g., a pipeline deploying to a specific AWS S3 bucket should only have s3:PutObject permissions on that bucket).&lt;/li&gt;&lt;li&gt;Use Role-Based Access Control (RBAC) to manage permissions.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;4. Secure the CI/CD Pipeline&lt;/h2&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;The pipeline itself is a high-value target for attackers. If they compromise the pipeline, they can inject malicious code into your production application.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Action:&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Lock down pipeline configurations: Require code reviews for any changes to pipeline definition files (e.g., .github/workflows/*.yml).&lt;/li&gt;&lt;li&gt;Use code signing: Digitally sign your build artifacts (containers, binaries) to ensure their integrity and origin.&lt;/li&gt;&lt;li&gt;Monitor pipeline logs: Look for unauthorized changes or suspicious activity.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;/span&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;Best Practices for Secrets Management&lt;/h1&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&quot;Secrets&quot; are non-human privileged credentials, including API keys, database passwords, SSH keys, and cryptographic tokens. The golden rule of secrets management is: Never hardcode secrets in source code. If secret was hardcoded in the code and then it was moved to external secrets vault (like GitHub Secrets or AWS Secrets Manager), rotate (re-generate) that secret as the old value is present in git history!&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Using GitHub Secrets&lt;/h3&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;GitHub Secrets allows you to store sensitive information directly in your GitHub repository, organization, or environment. These secrets are encrypted and only exposed to GitHub Actions workflows.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Best Practices:&lt;/h4&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;Scope Secrets Properly&lt;/b&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Define secrets at the environment level (e.g., production, staging) rather than the repository level whenever possible. This ensures that only workflows deploying to production can access production secrets.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;Use OIDC for Cloud Access&lt;/b&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Instead of storing long-lived cloud credentials (like AWS Access Keys) as GitHub Secrets, use OpenID Connect (OIDC). This allows GitHub Actions to request short-lived, temporary credentials directly from your cloud provider, eliminating the need to manage long-lived secrets.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;Minimize GITHUB_TOKEN Permissions&lt;/b&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;The automatic GITHUB_TOKEN provided to workflows has broad permissions by default. In your workflow YAML, explicitly set the permissions to the minimum required.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;Avoid Printing Secrets to Logs&lt;/b&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Although GitHub attempts to mask secrets in logs, avoid writing code that explicitly prints them. Be careful with debugging commands.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Using AWS Secrets Manager&lt;/h3&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;For applications running on AWS, Secrets Manager provides a more robust, centralized solution for lifecycle management.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Best Practices:&lt;/h4&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;Centralized Storage&lt;/b&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Store all application secrets (database passwords, third-party API keys) in Secrets Manager, not in application configuration files or environment variables.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;IAM Integration&lt;/b&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Use IAM roles and policies to grant specific EC2 instances, Lambda functions, or ECS tasks permission to retrieve only the secrets they need. This perfectly implements Least Privilege.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;Encrypt with Customer Master Keys (CMKs)&lt;/b&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Use AWS Key Management Service (KMS) with a customer-managed key to encrypt your secrets, giving you full control over who can use the key to decrypt the secret.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;Configure Automatic Rotation&lt;/b&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;This is a premier feature of AWS Secrets Manager. You can configure it to automatically rotate secrets (like database credentials) on a schedule, often without any application downtime.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;span&gt;&lt;!--more--&gt;&lt;/span&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Key and Secret Rotation&lt;/h2&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Rotation is the practice of regularly changing a secret or cryptographic key to limit the timeframe an attacker can use it if it is compromised.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Why Rotation is Essential&lt;/h3&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Limits Exposure Window: If a database password is stolen, but rotated every 30 days, the attacker&#39;s window of opportunity is limited.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Enforces Hygiene: Regular rotation ensures that you have a documented, tested process for changing credentials. This is vital during an active security incident.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Best Practices for Rotation&lt;/h3&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Automate Rotation: Manual rotation is error-prone and often neglected. Use tools like AWS Secrets Manager to handle the complexity.&lt;/li&gt;&lt;li&gt;Define Rotation Schedules based on Risk:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Critical Secrets (e.g., Production DB): Every 30-60 days.&lt;/li&gt;&lt;li&gt;High-Risk Secrets (e.g., Third-party API keys with write access): Every 60-90 days.&lt;/li&gt;&lt;li&gt;Lower-Risk Secrets: Every 90-180 days.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Use a &quot;Database/Application First&quot; Approach: When rotating a credential used by an application to connect to a service (like a database):&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Step 1: Create a new credential version in the Secrets Manager.&lt;/li&gt;&lt;li&gt;Step 2: Update the service (database) to accept both the old and new credentials.&lt;/li&gt;&lt;li&gt;Step 3: Update the application to use the new credential.&lt;/li&gt;&lt;li&gt;Step 4: Verify the application is working.&lt;/li&gt;&lt;li&gt;Step 5: Revoke the old credential from the service (database).&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Test the Rotation Process: Periodically perform manual, &quot;out-of-band&quot; rotations to ensure the automated process works as expected and doesn&#39;t cause outages.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;&lt;!--more--&gt;&lt;/span&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/6511924002821933978/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/6511924002821933978' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/6511924002821933978'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/6511924002821933978'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/04/core-security-practices-in-devsecops.html' title='Core Security Practices in DevSecOps &amp; Software Engineering'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigN0G2_Nss2ejnu7Nzwu9QVUn0D8PMWJfTlUpNZ68bK2HZwjJwMbT3a9IdN07084ukNs6N6LhCQhAqlzyMlAPX5U2kROryXtLmghwSHLXdW8WBKttIfM5JOh5fjvPemGkJVnRZ9BwGW7jFh4h3tSYM0bheMT6VECYuNTB3o3oSSFM2KuHHcFMz3lQEwQQ/s72-w640-h350-c/devsecops.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-8966977539884962149</id><published>2026-04-10T16:21:00.003+01:00</published><updated>2026-04-10T17:57:35.230+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI"/><category scheme="http://www.blogger.com/atom/ns#" term="Claude Code"/><title type='text'>How to install and setup Claude Code on MacOS + VS Code</title><content type='html'>&lt;div style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiC9dW0-zQI2mqq1qBJRsMkBhGn0O8xcS1fg4osrumfurtxCRS2e1zJwZvGQEe4oWpsIKMUuuaB94vqp1AhyphenhyphenqZIGRRItnTV1ZBaHfDTWV_t_vx-esOMA3McQez0Ij7hCVBKCBSnOHBSuVoQukHxyQyBf5yzU6zpqtZc8D79IU2hqX796qFPiKKZVIN1tHE/s1024/claude-color.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1024&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiC9dW0-zQI2mqq1qBJRsMkBhGn0O8xcS1fg4osrumfurtxCRS2e1zJwZvGQEe4oWpsIKMUuuaB94vqp1AhyphenhyphenqZIGRRItnTV1ZBaHfDTWV_t_vx-esOMA3McQez0Ij7hCVBKCBSnOHBSuVoQukHxyQyBf5yzU6zpqtZc8D79IU2hqX796qFPiKKZVIN1tHE/w640-h640/claude-color.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Let&#39;s follow steps from&amp;nbsp;&lt;a href=&quot;https://code.claude.com/docs/en/quickstart#step-1-install-claude-code&quot;&gt;Quickstart - Claude Code Docs&lt;/a&gt;:&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;curl -fsSL https://claude.ai/install.sh | bash&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Setting up Claude Code...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;✔ Claude Code successfully installed!&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; Version: 2.1.100&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; Location: ~/.local/bin/claude&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; Next: Run claude --help to get started&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;⚠ Setup notes:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; • Native installation exists but ~/.local/bin is not in your PATH. Run:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; echo &#39;export PATH=&quot;$HOME/.local/bin:$PATH&quot;&#39; &amp;gt;&amp;gt; ~/.zshrc &amp;amp;&amp;amp; source ~/.zshrc&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;✅ Installation complete!&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Let&#39;s add path to bin to PATH, add it to zsh config and reload it:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% echo &#39;export PATH=&quot;$HOME/.local/bin:$PATH&quot;&#39; &amp;gt;&amp;gt; ~/.zshrc &amp;amp;&amp;amp; source ~/.zshrc&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you use Bash:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;source ~/.bashrc&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Verification:&lt;/h2&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;$HOME/.local/bin&lt;/span&gt; is now in &lt;span style=&quot;font-family: courier;&quot;&gt;$PATH&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% echo $PATH&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;/Users/bojan/.local/bin:....&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Let&#39;s check Claude version:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;claude --version&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;2.1.100 (Claude Code)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Let&#39;s also see its CLI arguments:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;claude --help&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;Usage: claude [options] [command] [prompt]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;Claude Code - starts an interactive session by default, use -p/--print for non-interactive output&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;Arguments:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; prompt&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Your prompt&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;Options:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --add-dir &amp;lt;directories...&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Additional directories to allow tool access to&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --agent &amp;lt;agent&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Agent for the current session. Overrides the &#39;agent&#39; setting.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --agents &amp;lt;json&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;JSON object defining custom agents (e.g. &#39;{&quot;reviewer&quot;: {&quot;description&quot;: &quot;Reviews code&quot;, &quot;prompt&quot;: &quot;You are a code&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; reviewer&quot;}}&#39;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --allow-dangerously-skip-permissions&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Enable bypassing all permission checks as an option, without it being enabled by default. Recommended only for&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; sandboxes with no internet access.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --allowedTools, --allowed-tools &amp;lt;tools...&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Comma or space-separated list of tool names to allow (e.g. &quot;Bash(git:*) Edit&quot;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --append-system-prompt &amp;lt;prompt&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Append a system prompt to the default system prompt&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --bare&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Minimal mode: skip hooks, LSP, plugin sync, attribution, auto-memory, background prefetches, keychain reads, and&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; CLAUDE.md auto-discovery. Sets CLAUDE_CODE_SIMPLE=1. Anthropic auth is strictly ANTHROPIC_API_KEY or apiKeyHelper via&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; --settings (OAuth and keychain are never read). 3P providers (Bedrock/Vertex/Foundry) use their own credentials.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Skills still resolve via /skill-name. Explicitly provide context via: --system-prompt[-file],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; --append-system-prompt[-file], --add-dir (CLAUDE.md dirs), --mcp-config, --settings, --agents, --plugin-dir.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --betas &amp;lt;betas...&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Beta headers to include in API requests (API key users only)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --brief&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Enable SendUserMessage tool for agent-to-user communication&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --chrome&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Enable Claude in Chrome integration&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; -c, --continue&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Continue the most recent conversation in the current directory&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --dangerously-skip-permissions&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Bypass all permission checks. Recommended only for sandboxes with no internet access.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; -d, --debug [filter]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Enable debug mode with optional category filtering (e.g., &quot;api,hooks&quot; or &quot;!1p,!file&quot;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --debug-file &amp;lt;path&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Write debug logs to a specific file path (implicitly enables debug mode)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --disable-slash-commands&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Disable all skills&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --disallowedTools, --disallowed-tools &amp;lt;tools...&amp;gt;&amp;nbsp; Comma or space-separated list of tool names to deny (e.g. &quot;Bash(git:*) Edit&quot;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --effort &amp;lt;level&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Effort level for the current session (low, medium, high, max)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --exclude-dynamic-system-prompt-sections&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Move per-machine sections (cwd, env info, memory paths, git status) from the system prompt into the first user&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; message. Improves cross-user prompt-cache reuse. Only applies with the default system prompt (ignored with&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; --system-prompt). (default: false)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --fallback-model &amp;lt;model&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Enable automatic fallback to specified model when default model is overloaded (only works with --print)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --file &amp;lt;specs...&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;File resources to download at startup. Format: file_id:relative_path (e.g., --file file_abc:doc.txt file_def:img.png)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --fork-session&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; When resuming, create a new session ID instead of reusing the original (use with --resume or --continue)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --from-pr [value]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Resume a session linked to a PR by PR number/URL, or open interactive picker with optional search term&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; -h, --help&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Display help for command&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --ide&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Automatically connect to IDE on startup if exactly one valid IDE is available&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --include-hook-events&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Include all hook lifecycle events in the output stream (only works with --output-format=stream-json)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --include-partial-messages&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Include partial message chunks as they arrive (only works with --print and --output-format=stream-json)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --input-format &amp;lt;format&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Input format (only works with --print): &quot;text&quot; (default), or &quot;stream-json&quot; (realtime streaming input) (choices:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;text&quot;, &quot;stream-json&quot;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --json-schema &amp;lt;schema&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; JSON Schema for structured output validation. Example:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&quot;type&quot;:&quot;object&quot;,&quot;properties&quot;:{&quot;name&quot;:{&quot;type&quot;:&quot;string&quot;}},&quot;required&quot;:[&quot;name&quot;]}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --max-budget-usd &amp;lt;amount&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Maximum dollar amount to spend on API calls (only works with --print)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --mcp-config &amp;lt;configs...&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Load MCP servers from JSON files or strings (space-separated)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --mcp-debug&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;[DEPRECATED. Use --debug instead] Enable MCP debug mode (shows MCP server errors)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --model &amp;lt;model&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Model for the current session. Provide an alias for the latest model (e.g. &#39;sonnet&#39; or &#39;opus&#39;) or a model&#39;s full name&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (e.g. &#39;claude-sonnet-4-6&#39;).&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; -n, --name &amp;lt;name&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Set a display name for this session (shown in /resume and terminal title)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --no-chrome&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Disable Claude in Chrome integration&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --no-session-persistence&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Disable session persistence - sessions will not be saved to disk and cannot be resumed (only works with --print)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --output-format &amp;lt;format&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Output format (only works with --print): &quot;text&quot; (default), &quot;json&quot; (single result), or &quot;stream-json&quot; (realtime&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; streaming) (choices: &quot;text&quot;, &quot;json&quot;, &quot;stream-json&quot;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --permission-mode &amp;lt;mode&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Permission mode to use for the session (choices: &quot;acceptEdits&quot;, &quot;auto&quot;, &quot;bypassPermissions&quot;, &quot;default&quot;, &quot;dontAsk&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;plan&quot;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --plugin-dir &amp;lt;path&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Load plugins from a directory for this session only (repeatable: --plugin-dir A --plugin-dir B) (default: [])&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; -p, --print&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Print response and exit (useful for pipes). Note: The workspace trust dialog is skipped when Claude is run with the&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; -p mode. Only use this flag in directories you trust.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --remote-control-session-name-prefix &amp;lt;prefix&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Prefix for auto-generated Remote Control session names (default: hostname)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --replay-user-messages&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Re-emit user messages from stdin back on stdout for acknowledgment (only works with --input-format=stream-json and&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; --output-format=stream-json)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; -r, --resume [value]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Resume a conversation by session ID, or open interactive picker with optional search term&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --session-id &amp;lt;uuid&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Use a specific session ID for the conversation (must be a valid UUID)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --setting-sources &amp;lt;sources&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Comma-separated list of setting sources to load (user, project, local).&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --settings &amp;lt;file-or-json&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Path to a settings JSON file or a JSON string to load additional settings from&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --strict-mcp-config&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Only use MCP servers from --mcp-config, ignoring all other MCP configurations&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --system-prompt &amp;lt;prompt&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; System prompt to use for the session&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --tmux&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Create a tmux session for the worktree (requires --worktree). Uses iTerm2 native panes when available; use&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; --tmux=classic for traditional tmux.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --tools &amp;lt;tools...&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Specify the list of available tools from the built-in set. Use &quot;&quot; to disable all tools, &quot;default&quot; to use all tools,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; or specify tool names (e.g. &quot;Bash,Edit,Read&quot;).&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; --verbose&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Override verbose mode setting from config&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; -v, --version&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Output the version number&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; -w, --worktree [name]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Create a new git worktree for this session (optionally specify a name)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;Commands:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; agents [options]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; List configured agents&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; auth&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Manage authentication&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; auto-mode&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Inspect auto mode classifier configuration&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; doctor&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Check the health of your Claude Code auto-updater. Note: The workspace trust dialog is skipped and stdio servers from&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .mcp.json are spawned for health checks. Only use this command in directories you trust.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; install [options] [target]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Install Claude Code native build. Use [target] to specify version (stable, latest, or specific version)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; mcp&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Configure and manage MCP servers&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; plugin|plugins&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Manage Claude Code plugins&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; setup-token&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Set up a long-lived authentication token (requires Claude subscription)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; update|upgrade&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Check for updates and install if available&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;And finally, let&#39;s launch it:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;claude&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Welcome to Claude Code v2.1.100&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;…………………………………………………………………………………………………………………………………………………………&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;*&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;█████▓▓░&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;*&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;███▓░&amp;nbsp; &amp;nbsp; &amp;nbsp;░░&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ░░░░░░&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ███▓░&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; ░░░&amp;nbsp; &amp;nbsp;░░░░░░░░░░&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ███▓░&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp;░░░░░░░░░░░░░░░░░░░&amp;nbsp; &amp;nbsp; *&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ██▓░░&amp;nbsp; &amp;nbsp; &amp;nbsp; ▓&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;░▓▓███▓▓░&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;*&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;░░░░&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;░░░░░░░░&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;░░░░░░░░░░░░░░░░&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;█████████&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; *&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ██▄█████▄██&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; *&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;█████████&amp;nbsp; &amp;nbsp; &amp;nbsp; *&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;…………………█ █&amp;nbsp; &amp;nbsp;█ █………………………………………………………………………………………………………………&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;Let&#39;s get started.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;Choose the text style that looks best with your terminal&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;To change this later, run /theme&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;❯ 1. Dark mode ✔&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp;2. Light mode&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp;3. Dark mode (colorblind-friendly)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp;4. Light mode (colorblind-friendly)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp;5. Dark mode (ANSI colors only)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp;6. Light mode (ANSI colors only)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; 1&amp;nbsp; function greet() {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; 2 -&amp;nbsp; console.log(&quot;Hello, World!&quot;);&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; 2 +&amp;nbsp; console.log(&quot;Hello, Claude!&quot;);&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; 3&amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; Syntax theme: Monokai Extended (ctrl+t to disable)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After that we need to select a login method:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;❯ 1. Claude account with subscription · Pro, Max, Team, or Enterprise&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp;2. Anthropic Console account · API usage billing&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp;3. 3rd-party platform · Amazon Bedrock, Microsoft Foundry, or Vertex AI&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Option 1 - &lt;b&gt;&lt;u&gt;Claude Accounts&lt;/u&gt;&lt;/b&gt; are for the &lt;b&gt;consumer/pro web interface&lt;/b&gt; (&lt;u&gt;claude.ai&lt;/u&gt;) which is seat-based.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Option 2 - &lt;u&gt;&lt;b&gt;Anthropic Console&lt;/b&gt; &lt;/u&gt;account should be selected if your organization is on an &lt;b&gt;API plan&lt;/b&gt; (pay-as-you-go billing based on token usage).&amp;nbsp;&lt;b&gt;Anthropic Console&lt;/b&gt;&amp;nbsp;(&lt;u&gt;platform.claude.com&lt;/u&gt;) is the hub for managing API keys, billing, and developer organizations.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Option 3 - &lt;b&gt;&lt;u&gt;3rd-party platforms&lt;/u&gt;&lt;/b&gt; are only for when you want to route Claude&#39;s &quot;brain&quot; through your existing AWS (Bedrock) or Google Cloud (Vertex) bills.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;After selecting Anthropic Console, you&#39;ll be taken to page which shows the following:&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;blockquote style=&quot;border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;&quot;&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;&lt;i&gt;Claude Code would like to connect to your Anthropic organization MYORG&lt;/i&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;&lt;i&gt;YOUR ACCOUNT WILL BE USED TO:&lt;/i&gt;&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;ul&gt;&lt;li&gt;&lt;i&gt;Generate API keys on your behalf&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;Access your Anthropic profile information&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;Upload files on your behalf&lt;/i&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;blockquote style=&quot;border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;&quot;&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;&lt;i&gt;Logged in as user@myorg.com&lt;/i&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;&lt;i&gt;Switch account&lt;/i&gt;&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;After clicking on Authorize button, you&#39;ll be redirected to a page which shows:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;blockquote style=&quot;border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;&quot;&gt;&lt;div&gt;&lt;div&gt;&lt;i&gt;Build something great&lt;/i&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;i&gt;You’re all set up for Claude Code.&lt;/i&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;i&gt;You can now close this window.&lt;/i&gt;&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Back in terminal, you&#39;ll see:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Logged in as user@myorg.com&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Login successful. Press Enter to continue…&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After pressing Enter:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;Security notes:&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;1. Claude can make mistakes&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; You should always review Claude&#39;s responses, especially when&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; running code.&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;2. Due to prompt injection risks, only use it with code you trust&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; For more details see:&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; https://code.claude.com/docs/en/security&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;Press Enter to continue…&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After clicking on Enter:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Use Claude Code&#39;s terminal setup?&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;For the optimal coding experience, enable the recommended settings&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;for your terminal: Shift+Enter for newlines&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;❯ 1. Yes, use recommended settings&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp;2. No, maybe later with /terminal-setup&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;Enter to confirm · Esc to skip&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After choosing 1 - recommended settings:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;Accessing workspace:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;/Users/bojan/path/to/project&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;Quick safety check: Is this a project you created or one you trust? (Like your own code, a well-known open source project, or work from your team). If not, take a&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;moment to review what&#39;s in this folder first.&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;Claude Code&#39;ll be able to read, edit, and execute files here.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;Security guide&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;❯ 1. Yes, I trust this folder&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp;2. No, exit&amp;nbsp; &amp;nbsp;&lt;/span&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp;Enter to confirm · Esc to cancel&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After selecting 1:&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;╭─── Claude Code v2.1.100───────────────────────────────────────────────────────────────────────────────────────╮&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │ Tips for getting started&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Welcome back User!&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;│ Run /init to create a CLAUDE.md file with instructions for Claude│&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │ ─────────────────────────────────────────────────────────────────│&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;▐▛███▜▌&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │ Recent activity&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ▝▜█████▛▘&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;│ No recent activity&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;│&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ▘▘ ▝▝&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;│&amp;nbsp; &amp;nbsp;Sonnet 4.6 · API Usage Billing · MYORG&amp;nbsp; &amp;nbsp;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;│&amp;nbsp; &amp;nbsp;~/…/path/to/project&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; │&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────╯&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;─────────────────────────────────────────────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;❯&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;─────────────────────────────────────────────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; ? for shortcuts&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;● high · /effort&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: xx-small;&quot;&gt;&lt;span style=&quot;color: #38761d;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;We can now run various commands, like:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;❯ /stats&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;/stats&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Show your Claude Code usage statistics and activity&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;/status&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Show Claude Code status including version, model, account, API connectivity, and tool statuses&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;/statusline&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Set up Claude Code&#39;s status line UI&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;/ide&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Manage IDE integrations and show status&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If we execute &lt;span style=&quot;font-family: courier;&quot;&gt;/stats&lt;/span&gt; at this point, the output will show:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;❯ /stats&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;────────────────────────────────────────────────────────────&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Status&amp;nbsp; &amp;nbsp;Config&amp;nbsp; &amp;nbsp;Usage&amp;nbsp; &amp;nbsp;Stats&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;No stats available yet. Start using Claude Code!&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In my case Status tab showed, among other things:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: red; font-family: courier;&quot;&gt;&amp;nbsp; IDE: ✘ Error installing VS Code extension: 1: Command failed with ERR_STREAM_PREMATURE_CLOSE: code --force --install-extension anthropic.claude-code&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: red; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Premature close&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: red; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Please restart your IDE and try again.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I restarted VS Code to no avail. I then manually installed Claude Code for VS Code plugin and restarted VD Code but the same error appeared again. There is a related bug, still with Open status:&amp;nbsp;&lt;a href=&quot;https://github.com/anthropics/claude-code/issues/34639&quot;&gt;[BUG] Claude code VS Code extension error in MacOS · Issue #34639 · anthropics/claude-code&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If we try&amp;nbsp;&lt;span style=&quot;font-family: courier;&quot;&gt;/cost&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;❯ /stats&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; ⎿&amp;nbsp; Status dialog dismissed&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;❯ /cost&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; ⎿&amp;nbsp; Total cost:&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $0.0000&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Total duration (API):&amp;nbsp; 0s&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Total duration (wall): 1h 16m 21s&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Total code changes:&amp;nbsp; &amp;nbsp; 0 lines added, 0 lines removed&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Usage:&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;0 input, 0 output, 0 cache read, 0 cache write&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/8966977539884962149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/8966977539884962149' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/8966977539884962149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/8966977539884962149'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/04/how-to-install-claude-code-on-macos.html' title='How to install and setup Claude Code on MacOS + VS Code'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiC9dW0-zQI2mqq1qBJRsMkBhGn0O8xcS1fg4osrumfurtxCRS2e1zJwZvGQEe4oWpsIKMUuuaB94vqp1AhyphenhyphenqZIGRRItnTV1ZBaHfDTWV_t_vx-esOMA3McQez0Ij7hCVBKCBSnOHBSuVoQukHxyQyBf5yzU6zpqtZc8D79IU2hqX796qFPiKKZVIN1tHE/s72-w640-h640-c/claude-color.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-5879915728250357660</id><published>2026-04-08T12:36:00.010+01:00</published><updated>2026-04-08T13:12:18.326+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI"/><category scheme="http://www.blogger.com/atom/ns#" term="MCP"/><title type='text'>Model Context Protocol (MCP)</title><content type='html'>&lt;div style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8A60re2nD4AwHHSi7LJHj4v0mh7ZeoLzo28cm_iEfN3RTIDA4OyuCTEQL5vs7MR3f4xqW4zxWdYkl-iVA3JoMPWwP4HMsqPseSrtxThyphenhyphenZv7s_4lToQLXv14sFA_kX8HPBNxRP5b0-oJnAMJFx1recQJBziBHM_q78eZUTHLf2rwgn_SzS4gF18TSAevE/s1190/Screenshot%202026-04-08%20at%2012.30.13.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;872&quot; data-original-width=&quot;1190&quot; height=&quot;468&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8A60re2nD4AwHHSi7LJHj4v0mh7ZeoLzo28cm_iEfN3RTIDA4OyuCTEQL5vs7MR3f4xqW4zxWdYkl-iVA3JoMPWwP4HMsqPseSrtxThyphenhyphenZv7s_4lToQLXv14sFA_kX8HPBNxRP5b0-oJnAMJFx1recQJBziBHM_q78eZUTHLf2rwgn_SzS4gF18TSAevE/w640-h468/Screenshot%202026-04-08%20at%2012.30.13.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Model Context Protocol (MCP)&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The Model Context Protocol (MCP):&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Open-source standard&lt;/li&gt;&lt;li&gt;Enables AI models to seamlessly connect with external data sources, tools, and software systems&lt;/li&gt;&lt;li&gt;Acts as a universal &quot;USB-C port&quot; for AI, allowing LLMs to securely access local files, databases, and APIs to enhance context-aware responses.&amp;nbsp;&lt;/li&gt;&lt;li&gt;Introduced by Anthropic in late 2024&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Key Aspects of MCP:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;Purpose&lt;/b&gt;: Replaces fragmented, custom integrations with a single, open standard, making it easier to connect &lt;u&gt;AI assistants&lt;/u&gt; to &lt;u&gt;enterprise data&lt;/u&gt;, &lt;u&gt;tools&lt;/u&gt;, and &lt;u&gt;development environments&lt;/u&gt;.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Components&lt;/b&gt;: Consists of:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;MCP Clients&lt;/b&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;MCP Hosts&lt;/b&gt;&amp;nbsp;- AI apps like Claude or coding agents&amp;nbsp;&lt;/li&gt;&lt;li&gt;&lt;b&gt;MCP Servers&lt;/b&gt;&amp;nbsp;- programs that bridge specific data sources&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;Security&lt;/b&gt;: MCP supports secure, two-way connections, allowing developers to control exactly what data is exposed to the AI.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Functionality&lt;/b&gt;: Enables models to read files, query databases, use search engines, and call external APIs, providing live, relevant context for tasks.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Open Standard&lt;/b&gt;: Hosted by the Linux Foundation, the protocol is designed for broad industry adoption.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;MCP differs from RAG (Retrieval-Augmented Generation) by focusing on active, two-way interaction with systems, whereas RAG is focused on retrieving documents for context.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For developers, it provides SDKs in Python and TypeScript.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;MCP clients&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;MCP clients are the components within AI applications (AI Hosts) that manage one-to-one connections with MCP servers, translating AI requests into protocol-standardized messages.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Popular MCP Client Applications&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Several major AI-powered platforms and editors have integrated MCP client support to allow users to pull in their own tools and context:&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;Claude Desktop&lt;/b&gt;: Anthropic’s flagship app provides a built-in interface for managing local and remote MCP servers (e.g., Google Drive, Slack, GitHub).&lt;/li&gt;&lt;li&gt;&lt;b&gt;Cursor&lt;/b&gt;: An AI-native code editor that uses MCP to give its internal AI models direct access to project files, local databases, and custom developer tools.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Windsurf Editor&lt;/b&gt;: A developer environment that supports tool invocation through MCP servers, allowing it to seamlessly interact with external scripts and APIs during coding sessions.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Visual Studio Code (Agent Mode)&lt;/b&gt;: Developers can use extensions to register MCP servers, enabling chat assistants to interact with internal enterprise tools directly within the editor.&lt;/li&gt;&lt;li&gt;&lt;b&gt;JetBrains IDEs&lt;/b&gt;: Platforms like IntelliJ IDEA feature an MCP-client UI where users can paste server configurations to bring external tool catalogues into the AI Assistant pane.&lt;/li&gt;&lt;li&gt;&lt;b&gt;BeeAI&lt;/b&gt;: An open-source desktop AI assistant from IBM that supports tool integration via built-in or custom MCP servers.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Core Client Features&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In the MCP architecture, clients don&#39;t just consume data; they provide specific features that enable complex, &quot;agentic&quot; workflows:&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Sampling: Allows a server to request that the client (and its LLM) generate a completion, enabling the AI to &quot;ask back&quot; for clarification or more information.&lt;/li&gt;&lt;li&gt;Elicitation: Provides a structured way for servers to ask users for specific information (like a password or preference) through the client’s UI.&lt;/li&gt;&lt;li&gt;Roots: Allows the client to define specific file system boundaries, telling servers which directories they are permitted to access for safety and context scoping.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Developer SDKs for Building Clients&amp;nbsp;&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you are building your own AI application, you can implement an MCP client using official software development kits:&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;TypeScript/Node.js SDK: The most comprehensive SDK for building web-based or local Node.js clients using standard JSON-RPC 2.0.&lt;/li&gt;&lt;li&gt;Python SDK: Ideal for data science or automation workflows, allowing easy integration with Python-based AI agents.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;MCP Hosts&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Model Context Protocol (MCP) hosts are AI applications or environments that manage, connect, and run MCP clients to interact with external data sources (servers). Key examples include Claude Desktop, Claude Code, Zed, Replit, Cursor, and Sourcegraph.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Key Roles of MCP Hosts:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Orchestration: Act as the container for AI models to coordinate and communicate with multiple MCP servers.&lt;/li&gt;&lt;li&gt;Security &amp;amp; Permissions: Manage user consent and enforce security policies (e.g., in sandboxed iframes) to control what data servers can access.&lt;/li&gt;&lt;li&gt;Workflow Management: Aggregate user prompts, conversation state, and tool results from various sources to enable seamless interaction.&lt;/li&gt;&lt;li&gt;Session Control: Initialize, maintain, and terminate connections between LLMs and tools via the MCP client.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;Primary MCP Host Examples:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Claude Desktop: Anthropic&#39;s desktop application is a primary implementation of an MCP host, allowing the Claude model to utilize local tools and data.&lt;/li&gt;&lt;li&gt;Claude Code: An AI agentic coding tool that acts as a host to interact with development-focused MCP servers.&lt;/li&gt;&lt;li&gt;AI IDEs (Zed, Cursor, Replit): Integrated Development Environments that use MCP to connect coding assistants with files, documentation, and databases.&lt;/li&gt;&lt;li&gt;Platforms &amp;amp; Agents: Other platforms like Workato or custom agents that orchestrate data access via the protocol.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What&#39;s the difference between mcp host and mcp client?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In the Model Context Protocol (MCP), the Host is the overall application you interact with, while the Client is the specific component inside that application that handles the technical connection to a server.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Key Differences at a Glance&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;What it is&lt;/li&gt;&lt;ul&gt;&lt;li&gt;MCP Host: The end-user application (e.g., Claude Desktop, Cursor).&lt;/li&gt;&lt;li&gt;MCP Client: A protocol handler or &quot;adapter&quot; inside the host.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Primary Role&lt;/li&gt;&lt;ul&gt;&lt;li&gt;MCP Host: Manages the user interface and coordinates multiple clients.&lt;/li&gt;&lt;li&gt;MCP Client: Maintains a 1:1 connection with a single MCP server.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Responsibility&lt;/li&gt;&lt;ul&gt;&lt;li&gt;MCP Host: Security policies, user consent, and aggregating data for the AI model&lt;/li&gt;&lt;li&gt;MCP Client: Translating protocol messages (JSON-RPC) between the host and server.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Hierarchy&lt;/li&gt;&lt;ul&gt;&lt;li&gt;MCP Host: A single Host can contain multiple Clients.&lt;/li&gt;&lt;li&gt;MCP Client: A Client is a subsidiary of the Host.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;The &quot;Restaurant&quot; Analogy&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To make it simpler, imagine a restaurant setting:&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;The Host is the Executive Chef: They decide what needs to be cooked and oversee everything, but they don&#39;t leave the kitchen to buy ingredients.&lt;/li&gt;&lt;li&gt;The Client is the Waiter: They take the Chef&#39;s specific order, run to the source (the Server), and bring back exactly what was requested in a format the Chef can use.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Why the distinction matters&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;While you will often hear people refer to applications like Claude Desktop as &quot;the client,&quot; technically they are hosts. This architecture allows one app to connect to many different data sources (like Google Drive, Slack, and local files) simultaneously by instantiating a separate client for each one.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;What is a MCP Client in Claude Desktop?&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;In Claude Desktop, the MCP client is the internal software layer that allows the app to &quot;talk&quot; to the tools you&#39;ve added. While you might call the whole app &quot;the client,&quot; it actually functions as a host that manages multiple individual client connections.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;How it works in Claude Desktop&lt;/span&gt;&lt;/h4&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;The Translator: When you ask Claude to &quot;read a file,&quot; the client translates that human request into a technical JSON-RPC message that the Filesystem server understands.&lt;/li&gt;&lt;li&gt;The Connection Manager: Claude Desktop can run several clients at once. For example, one client might be connected to a GitHub server while another is connected to a Google Drive server.&lt;/li&gt;&lt;li&gt;Permission Gatekeeper: The client facilitates the security handshake. Before a tool executes, the client triggers the UI popup in Claude Desktop asking for your explicit permission.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;p style=&quot;text-align: left;&quot;&gt;How to see them&lt;/p&gt;&lt;div&gt;You can see your active MCP clients and their available tools by clicking the &quot;hammer&quot; or &quot;plug&quot; icon (the MCP server indicator) in the bottom-right corner of the chat input box.&amp;nbsp;&lt;/div&gt;&lt;p style=&quot;text-align: left;&quot;&gt;Configuration&lt;/p&gt;&lt;div&gt;Claude Desktop&#39;s clients are configured via a local JSON file (claude_desktop_config.json). This file tells the internal clients exactly how to launch and communicate with your servers.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Config File Location:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;macOS: ~/Library/Application Support/Claude/claude_desktop_config.json&lt;/li&gt;&lt;li&gt;Windows: %APPDATA%\Claude\claude_desktop_config.json&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;MCP Servers&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;Model Context Protocol (MCP) servers:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Lightweight programs that connect&amp;nbsp;&lt;b&gt;AI models&lt;/b&gt;&amp;nbsp;(like Claude or ChatGPT) to&lt;b&gt;&amp;nbsp;external data sources and tools&lt;/b&gt;, such as local files, databases, GitHub, or Slack&lt;/li&gt;&lt;li&gt;Provide a standardized interface, enabling AI agents to securely access, read, and manipulate&amp;nbsp;&lt;u&gt;data beyond their training sets&lt;/u&gt;.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Key Aspects of MCP Servers:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Functionality&lt;/b&gt;: They expose specific capabilities—resources, prompts, and tools—to AI applications.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Use Cases&lt;/b&gt;: Common implementations include file system access for documentation, database querying, and API interactions for services like GitHub or Google Tasks.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Security&lt;/b&gt;: They provide controlled, authorized access to local or remote resources, with user permission required for actions.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Architecture&lt;/b&gt;: As part of the Model Context Protocol, they act as the &quot;server&quot; in a client-server model, connecting to &quot;hosts&quot; like desktop apps.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Common MCP Server Examples:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Local File System&lt;/b&gt;: Allows AI to read, write, and organize local documents.&lt;/li&gt;&lt;li&gt;&lt;b&gt;GitHub/GitLab&lt;/b&gt;: Enables AI to manage repositories, create issues, and pull code.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Database/API Connectors&lt;/b&gt;: Connects AI to SQL databases, HubSpot CRM, or AWS services.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Developer Tools&lt;/b&gt;: Includes servers for Terraform, Angular CLI, and Home Assistant.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can build your own MCP server using Python or TypeScript, often utilizing tools like uv for environment setup.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/5879915728250357660/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/5879915728250357660' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/5879915728250357660'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/5879915728250357660'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/04/model-context-protocol-mcp.html' title='Model Context Protocol (MCP)'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8A60re2nD4AwHHSi7LJHj4v0mh7ZeoLzo28cm_iEfN3RTIDA4OyuCTEQL5vs7MR3f4xqW4zxWdYkl-iVA3JoMPWwP4HMsqPseSrtxThyphenhyphenZv7s_4lToQLXv14sFA_kX8HPBNxRP5b0-oJnAMJFx1recQJBziBHM_q78eZUTHLf2rwgn_SzS4gF18TSAevE/s72-w640-h468-c/Screenshot%202026-04-08%20at%2012.30.13.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-8926137244429965471</id><published>2026-04-08T12:18:00.001+01:00</published><updated>2026-04-08T12:18:36.734+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Agentic AI"/><category scheme="http://www.blogger.com/atom/ns#" term="AI"/><category scheme="http://www.blogger.com/atom/ns#" term="AI Agents"/><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><title type='text'>How to start using Agentic AI in DevOps and Platform Engineering</title><content type='html'>&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzEizcTut4CUALNC7kusHybE0C7j__caL5uqFdI1-Yy8MHt6_elpRkasMxJY4Liw-_N_o5vsOlutTtBFlyfDKJaO5YV0R60cmQpx6EuXzb5rwP70HSWfmUBkHKYf3-4CxB8r8lrV6SUT-NF54iQeCZiAa9jxcWU_2WXD-Gyxvhk7nGU0bO_SaLOBwLCrM/s2298/agentic_ai_in_devops_gemini.heic&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1856&quot; data-original-width=&quot;2298&quot; height=&quot;516&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzEizcTut4CUALNC7kusHybE0C7j__caL5uqFdI1-Yy8MHt6_elpRkasMxJY4Liw-_N_o5vsOlutTtBFlyfDKJaO5YV0R60cmQpx6EuXzb5rwP70HSWfmUBkHKYf3-4CxB8r8lrV6SUT-NF54iQeCZiAa9jxcWU_2WXD-Gyxvhk7nGU0bO_SaLOBwLCrM/w640-h516/agentic_ai_in_devops_gemini.heic&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt;The next frontier of DevOps and Platform Engineering is &lt;b&gt;Agentic AI&lt;/b&gt;. We need to learn how autonomous agents reason and adapt to reduce cognitive load and accelerate the SDLC as we want to move beyond simple automation to build self-optimizing ecosystems that scale with confidence, innovation, and enterprise governance. &lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We should be able to:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Explain the shift from automation to agentic AI and articulate what makes an AI system truly&lt;/li&gt;&lt;li&gt;“agentic”&lt;/li&gt;&lt;li&gt;Design agent-aware workflows in GitHub Actions, integrating LLMs with events, logs, APIs, and quality gates to create intelligent CI/CD pipelines&lt;/li&gt;&lt;li&gt;Build AI-powered diagnostic loops that ingest failure context, reason about root causes, and generate structured remediation proposals or self-healing fixes&lt;/li&gt;&lt;li&gt;Implement intelligent release decisions using multi-signal quality gates (test coverage, performance, security, cost) and generate auditable release rationale reports&lt;/li&gt;&lt;li&gt;Deploy our own end-to-end platform engineering agent, capable of diagnosing pipeline failures, evaluating release readiness, and autonomously opening a fix PR or escalating with structured context.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Learning while Doing&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Identify Platform engineering pain points and the AI opportunity&lt;/li&gt;&lt;ul&gt;&lt;li&gt;How can we get from static scripts and CI/CD automation to agentic AI&lt;/li&gt;&lt;li&gt;Make a comparison of manual vs. AI-driven diagnosis&lt;/li&gt;&lt;li&gt;Understand how platform engineering is evolving from static automation toward AI-driven systems that proactively diagnose and resolve operational issues&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Agentic AI fundamentals - how agents reason and act?&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Learn about core agent components (LLMs, memory, and tools)&lt;/li&gt;&lt;li&gt;Compare event-driven vs. polling architectures&lt;/li&gt;&lt;li&gt;Balance autonomous actions with human oversight&lt;/li&gt;&lt;li&gt;Understand how agentic systems combine reasoning, memory, and tools to perceive events, make decisions, and act within engineering workflows&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;How to setup the environment and create our first agentic workflow&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Set up an agentic runtime that responds to CI/CD events&lt;/li&gt;&lt;li&gt;Connect an AI agent to our pipeline&#39;s event stream and context&lt;/li&gt;&lt;li&gt;Trigger our first agent run and interpret its reasoning logs&lt;/li&gt;&lt;li&gt;Learn how to connect AI agents to CI/CD events and platform context to trigger automated reasoning and actions in real time&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;AI-powered diagnosis and remediation&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Compare manual vs. AI-driven incident diagnosis&amp;nbsp;&lt;/li&gt;&lt;li&gt;Build agents that read logs, reason about failures, and propose fixes&amp;nbsp;&lt;/li&gt;&lt;li&gt;Define escalation boundaries: when the agent self-heals vs. asks a human&lt;/li&gt;&lt;li&gt;Understand how AI agents analyze logs, diagnose failures, and determine whether to self-heal or escalate issues to humans&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Intelligent CI/CD &amp;amp; adaptive delivery&lt;/li&gt;&lt;ul&gt;&lt;li&gt;How to move beyond pass/fail pipelines to AI-driven release decision&lt;/li&gt;&lt;li&gt;Automate rollback decisions using AI quality gates&lt;/li&gt;&lt;li&gt;Query pipeline state and release history using natural language&lt;/li&gt;&lt;li&gt;How AI transforms CI/CD pipelines into adaptive systems that make context-aware release and rollback decisions&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Operational intelligence &amp;amp; conversational observability&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Replace complex dashboards with AI anomaly detection&lt;/li&gt;&lt;li&gt;Check platform health via chat interfaces&lt;/li&gt;&lt;li&gt;Shift from reactive alerts to predictive management&lt;/li&gt;&lt;li&gt;Understand how AI enables conversational access to platform health and detects anomalies to support proactive operations.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Multi-agent coordination &amp;amp; implementation strategy&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Architect multi-agent systems for our platform workflows&lt;/li&gt;&lt;li&gt;Handle agent conflicts, failures, and graceful degradation&amp;nbsp;&lt;/li&gt;&lt;li&gt;Design a phased enterprise rollout with guardrails and audit trails&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Build our platform engineering agent&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Learn how to design coordinated multi-agent systems that handle complex platform workflows with governance and reliability&lt;/li&gt;&lt;li&gt;Wire together diagnosis, quality gates, and observability into one agent pipeline&lt;/li&gt;&lt;li&gt;Implement self-healing PRs with confidence thresholds&lt;/li&gt;&lt;li&gt;Shift our role from platform operator to AI supervisor&lt;/li&gt;&lt;li&gt;Learn how to combine diagnosis, delivery intelligence, and observability into a unified agent that automates key platform workflows&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;---&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/8926137244429965471/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/8926137244429965471' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/8926137244429965471'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/8926137244429965471'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/04/how-to-start-using-agentic-ai-in-devops.html' title='How to start using Agentic AI in DevOps and Platform Engineering'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzEizcTut4CUALNC7kusHybE0C7j__caL5uqFdI1-Yy8MHt6_elpRkasMxJY4Liw-_N_o5vsOlutTtBFlyfDKJaO5YV0R60cmQpx6EuXzb5rwP70HSWfmUBkHKYf3-4CxB8r8lrV6SUT-NF54iQeCZiAa9jxcWU_2WXD-Gyxvhk7nGU0bO_SaLOBwLCrM/s72-w640-h516-c/agentic_ai_in_devops_gemini.heic" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-622365749798614224</id><published>2026-04-02T11:08:00.006+01:00</published><updated>2026-04-02T11:22:40.371+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><category scheme="http://www.blogger.com/atom/ns#" term="Kubernetes"/><title type='text'>Kubernetes StatefulSet</title><content type='html'>&lt;div style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEi8WwmUAx8p5XNQtaUg3CDEWtdFb70hoHgNBw3rxEbkiGpH-WPnvz0Ya09qE8B5a82wYui3oJ641ylIM-pXNUY6EV3C1uovGGLNe3oZ-LJQgWPS8HNi89nVLlTlCQRsniIwRaEsbxSAJq6rdmJap9mDX91dAYDb5UBicVZfrFk-hOrcwifBx8K36NVD3Nk&quot; style=&quot;margin-left: 1em; margin-right: 1em; text-align: center;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;639&quot; data-original-width=&quot;638&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEi8WwmUAx8p5XNQtaUg3CDEWtdFb70hoHgNBw3rxEbkiGpH-WPnvz0Ya09qE8B5a82wYui3oJ641ylIM-pXNUY6EV3C1uovGGLNe3oZ-LJQgWPS8HNi89nVLlTlCQRsniIwRaEsbxSAJq6rdmJap9mDX91dAYDb5UBicVZfrFk-hOrcwifBx8K36NVD3Nk=w640-h640&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;In Kubernetes, a StatefulSet is a specialized workload API object designed to manage stateful applications. Unlike standard Deployments, where Pods are interchangeable &quot;cattle,&quot; StatefulSets treat Pods as unique &quot;pets&quot; with a persistent identity that is maintained even if they are rescheduled or restarted.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Key Features&lt;/h2&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;Stable Network Identity&lt;/b&gt;: Each Pod is assigned a unique, ordinal index (e.g., web-0, web-1) and a corresponding stable DNS name through a Headless Service.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Stable Storage&lt;/b&gt;: By using volumeClaimTemplates, each Pod is automatically paired with its own PersistentVolume. If a Pod dies, the replacement Pod with the same identity will automatically remount the same storage.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Ordered Deployment&lt;/b&gt;: Pods are created and scaled sequentially from 0 to N-1. Kubernetes ensures that the previous Pod is &quot;Running and Ready&quot; before starting the next one.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Ordered Termination&lt;/b&gt;: Scaling down or deleting the StatefulSet occurs in reverse order, starting from the highest ordinal (e.g., web-2 is deleted before web-1).&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;When to Use StatefulSets&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;StatefulSets are the standard choice for applications that require consistent data and unique identities, such as:&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;Databases&lt;/b&gt;: Systems like MySQL, PostgreSQL, MongoDB, and Cassandra.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Distributed Systems&lt;/b&gt;: Tools like ZooKeeper, Kafka, and Elasticsearch that need a quorum or master election.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Clustered Applications&lt;/b&gt;: Any software where instances need to know each other’s specific addresses to sync data.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Comparison: StatefulSet vs. Deployment&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Feature &lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; StatefulSet&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Deployment&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;----------&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;--------------&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;---------------&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Pod Identity:&lt;/b&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;Unique and stable (ordinal names)&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Randomly generated and ephemeral&lt;/div&gt;&lt;div&gt;&lt;b&gt;Storage:&lt;/b&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Dedicated volume per Pod (via template)&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;Typically shared or transient&lt;/div&gt;&lt;div&gt;&lt;b&gt;Network:&lt;/b&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;Fixed DNS per Pod (via Headless Service)&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;Single Load Balancer for the whole set&lt;/div&gt;&lt;div&gt;&lt;b&gt;Scaling:&lt;/b&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Sequential (0, then 1, then 2...)&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Parallel (multiple Pods at once)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Best Practices&lt;/h2&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;Use Headless Services&lt;/b&gt;: Always pair our StatefulSet with a Service that has &lt;b&gt;clusterIP: None&lt;/b&gt; to ensure Pods are individually addressable.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Persistent Storage&lt;/b&gt;: Ensure our StorageClass is correctly configured for dynamic provisioning so that each Pod gets its own disk automatically.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Manual Data Sync&lt;/b&gt;: Note that while Kubernetes manages the infrastructure, we are still responsible for configuring internal application logic like data replication or master/slave sync.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;YAML manifest example for a basic MySQL StatefulSet&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Below is a standard YAML manifest for a MySQL StatefulSet. It includes a Headless Service for network identity and a volumeClaimTemplate to automatically provision unique storage for each replica.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;apiVersion: v1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kind: &lt;b&gt;Service&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name: mysql&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; labels:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; app: mysql&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; ports:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; - port: 3306&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; name: mysql&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &lt;b&gt;clusterIP: None&lt;/b&gt; # Defines this as a &lt;b&gt;Headless Service&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; selector:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; app: mysql&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;---&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;apiVersion: apps/v1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kind: &lt;b&gt;StatefulSet&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name: mysql&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; selector:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; matchLabels:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; app: mysql&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; serviceName: &quot;mysql&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; replicas: 3&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; template:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; labels:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; app: mysql&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; containers:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - name: mysql&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; image: mysql:8.0&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; env:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - name: MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; value: &quot;password&quot; # Use Secrets in production!&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ports:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - containerPort: 3306&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; name: mysql&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; volumeMounts:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - name: mysql-data&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; mountPath: /var/lib/mysql&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &lt;b&gt;volumeClaimTemplates&lt;/b&gt;:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; - metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; name: mysql-data&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; accessModes: [ &quot;ReadWriteOnce&quot; ]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; resources:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; requests:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; storage: 1Gi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Why this works:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;Stable DNS&lt;/b&gt;: Each Pod gets a predictable name: mysql-0.mysql, mysql-1.mysql, etc.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Unique Storage&lt;/b&gt;: Kubernetes creates three separate PersistentVolumeClaims. mysql-0 will always mount the first disk, even after a reboot.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Ordered Startup&lt;/b&gt;: Pods launch one after another (0, then 1, then 2), which is critical for forming database clusters.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To use a Kubernetes Secret (like mysql-secret) instead of hardcoding passwords, we need to create a Secret object and then reference it in our StatefulSet. This is the standard practice for distributing credentials securely in Kubernetes.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;1. Create the Secret&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We can define our password in a YAML file. Note that values in the data field must be base64 encoded.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;apiVersion: v1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kind: Secret&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name: mysql-secret&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;type: Opaque&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;data:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; # &#39;password&#39; encoded in base64 is &#39;cGFzc3dvcmQ=&#39;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; root-password: cGFzc3dvcmQ=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Alternatively, we can use stringData to provide the password in plain text; Kubernetes will handle the encoding for us when we apply it:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;apiVersion: v1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kind: Secret&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name: mysql-secret&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;type: Opaque&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;stringData:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; root-password: &quot;our-secure-password&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;2. Update the StatefulSet&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Modify the env section of our MySQL container to use valueFrom and secretKeyRef. This tells the Pod to pull the value of MYSQL_ROOT_PASSWORD from the secret we just created.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;containers:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - name: mysql&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; image: mysql:8.0&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; env:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - name: MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; valueFrom:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; secretKeyRef:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; name: mysql-secret&amp;nbsp; &amp;nbsp;# Name of our Secret object&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; key: root-password&amp;nbsp; &amp;nbsp;# The specific key inside the Secret&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Key Considerations&lt;/h4&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Initialization Only: For MySQL, the MYSQL_ROOT_PASSWORD environment variable is typically only used during the first-time initialization of the data directory. Changing the Secret later will not automatically update the root password in an existing database.&lt;/li&gt;&lt;li&gt;Security: Ensure our cluster has encryption at rest enabled for Secrets to truly protect sensitive data.&lt;/li&gt;&lt;li&gt;Alternative for Multiple Variables: If we have many credentials (user, password, DB name), we can use envFrom to map all keys in a Secret to environment variables at once.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Changing Storage Spec&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Changing spec.volumeClaimTemplate updates the StatefulSet template but will not resize already-created PVCs. If the goal is to fix an existing CrashLoopBackOff due to disk-full, we still need to expand the current PVC(s) (and ensure the general StorageClass allows volume expansion), or recreate the PVC/StatefulSet so the new size takes effect.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;References:&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/&quot;&gt;StatefulSets | Kubernetes&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/622365749798614224/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/622365749798614224' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/622365749798614224'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/622365749798614224'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/04/kubernetes-statefulset.html' title='Kubernetes StatefulSet'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/a/AVvXsEi8WwmUAx8p5XNQtaUg3CDEWtdFb70hoHgNBw3rxEbkiGpH-WPnvz0Ya09qE8B5a82wYui3oJ641ylIM-pXNUY6EV3C1uovGGLNe3oZ-LJQgWPS8HNi89nVLlTlCQRsniIwRaEsbxSAJq6rdmJap9mDX91dAYDb5UBicVZfrFk-hOrcwifBx8K36NVD3Nk=s72-w640-h640-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-4969955158946284640</id><published>2026-03-19T13:56:56.248+00:00</published><updated>2026-03-19T15:05:10.799+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AWS"/><category scheme="http://www.blogger.com/atom/ns#" term="AWS EBS"/><category scheme="http://www.blogger.com/atom/ns#" term="AWS EKS"/><category scheme="http://www.blogger.com/atom/ns#" term="Cloud Storage"/><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><category scheme="http://www.blogger.com/atom/ns#" term="Kubernetes"/><title type='text'> Amazon EBS CSI Driver </title><content type='html'>&lt;div style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUSoHhTkdMp-bDFAzL3ZsMkP5CQCufHkAtoqZ11WbkUIC1vmqr_Firvb1cXlfY5E_GWl69UF700wGpbYCbph90IOlmfZrRtwJ75EKGjAzhC8lDcBsLG3iMGFI5cO0RT2vXOTqMb2kd49PeS0DEnwwBgIeuPf_g2nmA-Ursgv-ClOPpJ3RysBu5E6y-eUg/s320/eks.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;320&quot; data-original-width=&quot;320&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUSoHhTkdMp-bDFAzL3ZsMkP5CQCufHkAtoqZ11WbkUIC1vmqr_Firvb1cXlfY5E_GWl69UF700wGpbYCbph90IOlmfZrRtwJ75EKGjAzhC8lDcBsLG3iMGFI5cO0RT2vXOTqMb2kd49PeS0DEnwwBgIeuPf_g2nmA-Ursgv-ClOPpJ3RysBu5E6y-eUg/s1600/eks.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;The Amazon EBS CSI Driver is a standard interface that allows Amazon Elastic Kubernetes Service (EKS) clusters to manage the full lifecycle of Amazon EBS volumes as persistent storage for containers. It replaces the older, deprecated &quot;in-tree&quot; Kubernetes storage plugin with a more flexible, decoupled model.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Key Features&lt;/h2&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Dynamic Provisioning: Automatically creates and attaches EBS volumes when a PersistentVolumeClaim (PVC) is made.&lt;/li&gt;&lt;li&gt;Volume Lifecycle Management: Handles the creation, attachment, mounting, and deletion of volumes.&lt;/li&gt;&lt;li&gt;Resizing &amp;amp; Snapshots: Supports online volume resizing (for gp3 and others) and taking volume snapshots for data backup.&lt;/li&gt;&lt;li&gt;EKS Auto Mode Support: In EKS Auto Mode, routine block storage tasks are automated, and you don&#39;t even need to manually install the driver.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Deployment Methods&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can install and manage the driver through several channels:&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;EKS Managed Add-on (Recommended): Simplifies installation and updates via the AWS Console, CLI, or Terraform.&lt;/li&gt;&lt;li&gt;Helm Chart: Provides highly customizable installation options.&lt;/li&gt;&lt;li&gt;Kustomize: Direct deployment using manifests from the official GitHub repository.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Core Requirements&lt;/h2&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;IAM Permissions: The driver requires an IAM role with the AmazonEBSCSIDriverPolicy to interact with EBS resources.&lt;/li&gt;&lt;li&gt;Service Accounts: Typically uses IAM Roles for Service Accounts (IRSA) to securely provide AWS credentials to the driver pods.&lt;/li&gt;&lt;li&gt;Compatibility: Supports Linux and Windows worker nodes, as well as ARM64 architectures.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Driver Components&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The driver is typically deployed into the kube-system namespace and consists of two main parts:&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Controller Deployment: Runs as a set of replicas (ebs-csi-controller) to communicate with the AWS EC2 API and manage volume operations.&lt;/li&gt;&lt;li&gt;Node DaemonSet: Runs on every worker node (ebs-csi-node) to handle the actual mounting and unmounting of volumes to pods on that specific host.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;In the Amazon EBS CSI driver architecture, the ebs-csi-controller and ebs-csi-node are the two primary components that work together to manage the lifecycle of EBS volumes in a Kubernetes cluster.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Core Feature Differences&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;ebs-csi-controller&lt;/h4&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Deployment Type:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Deployment&lt;/b&gt; (typically 2 replicas for HA)&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Main Function:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Control Plane operations: Creating, deleting, attaching, and detaching volumes&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;AWS Interaction:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Calls the AWS EC2 API to manage EBS resources&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;IAM Permissions:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Requires an IAM role with permissions like ec2:CreateVolume and ec2:AttachVolume&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;ebs-csi-node&lt;/h4&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Deployment Type:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;DaemonSet (runs on every worker node)&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Main Function:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Node-level operations: Mounting and unmounting volumes to the local filesystem&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;AWS Interaction:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Interacts with the local OS (privileged system calls) to handle block devices&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;IAM Permissions:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Generally requires fewer/no AWS API permissions, as it mostly performs local mount actions&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;How They Work Together&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Provisioning &amp;amp; Attachment: When you create a PersistentVolumeClaim (PVC), the ebs-csi-controller watches the request and calls the AWS API to create the EBS volume and attach it to the correct EC2 instance.&lt;/li&gt;&lt;li&gt;Mounting: Once the volume is physically attached to the EC2 instance, the ebs-csi-node pod running on that specific node detects the new block device and mounts it into the container’s path so your application can use it.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Key Considerations&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Security: For better security, you can schedule the ebs-csi-controller on hardened management nodes, while the ebs-csi-node must run everywhere your workloads need storage.&lt;/li&gt;&lt;li&gt;Fargate: You can run the controller on Fargate nodes, but the ebs-csi-node (as a DaemonSet) only runs on EC2 instances.&lt;/li&gt;&lt;li&gt;Troubleshooting: If a volume fails to &quot;attach,&quot; check the controller logs; if it fails to &quot;mount&quot; or &quot;format,&quot; check the node logs.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Pods for both the ebs-csi-controller and ebs-csi-node typically share the same value for the app.kubernetes.io/name label.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In standard deployments (such as via the official Helm chart or EKS add-on), both components use this label to identify that they belong to the same overarching application: the Amazon EBS CSI Driver.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Label Comparisons&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;While they share the same application name, they use the app.kubernetes.io/component label to distinguish between their specific roles.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;Label Key &lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ebs-csi-controller Pods&amp;nbsp; &amp;nbsp; &amp;nbsp;ebs-csi-node Pods&lt;/b&gt;&lt;/div&gt;&lt;div&gt;------------&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ------------------------------&amp;nbsp; &amp;nbsp; ----------------------&lt;/div&gt;&lt;div&gt;app.kubernetes.io/name&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; aws-ebs-csi-driver&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; aws-ebs-csi-driver&lt;/div&gt;&lt;div&gt;app.kubernetes.io/instance&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; aws-ebs-csi-driver&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; aws-ebs-csi-driver&lt;/div&gt;&lt;div&gt;app.kubernetes.io/component&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; csi-driver (or controller)&amp;nbsp; &amp;nbsp; &amp;nbsp;csi-driver (or node)&lt;/div&gt;&lt;div&gt;app (Legacy label)&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ebs-csi-controller&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ebs-csi-node&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;How to Verify in Your Cluster&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can check these labels yourself using kubectl. This is useful if you are writing Prometheus rules or network policies that need to target the entire driver or just one part of it.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To see labels for all EBS CSI pods:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kubectl get pods -n kube-system -l app.kubernetes.io/name=aws-ebs-csi-driver --show-labels&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To target only the controller:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kubectl get pods -n kube-system -l app=ebs-csi-controller&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;---&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/4969955158946284640/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/4969955158946284640' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/4969955158946284640'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/4969955158946284640'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/03/amazon-ebs-csi-driver.html' title=' Amazon EBS CSI Driver '/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUSoHhTkdMp-bDFAzL3ZsMkP5CQCufHkAtoqZ11WbkUIC1vmqr_Firvb1cXlfY5E_GWl69UF700wGpbYCbph90IOlmfZrRtwJ75EKGjAzhC8lDcBsLG3iMGFI5cO0RT2vXOTqMb2kd49PeS0DEnwwBgIeuPf_g2nmA-Ursgv-ClOPpJ3RysBu5E6y-eUg/s72-c/eks.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-3971438138599901568</id><published>2026-03-19T10:37:52.290+00:00</published><updated>2026-04-30T12:03:28.482+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><category scheme="http://www.blogger.com/atom/ns#" term="Monitoring"/><category scheme="http://www.blogger.com/atom/ns#" term="Observability"/><title type='text'>Monitoring and Observability</title><content type='html'>&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgABnRMS8MEYULk3ZzfCFcQTMLdhmorAk7-EaraXAGQuxBCPPy-uEUhx_tNpsnKY0idB6o-zJe-xIGYl8v9_SPcwwRmkz7cK57pdbhVsd2JNz4eanhuHEzb88i3HceUGD2agH9fGqlXOqST2FVefC41THvmMRV2xks0JrJ7H3dLnWDMjCYK9rUTT6qDT3M/s612/magnifier-612x612.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;612&quot; data-original-width=&quot;612&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgABnRMS8MEYULk3ZzfCFcQTMLdhmorAk7-EaraXAGQuxBCPPy-uEUhx_tNpsnKY0idB6o-zJe-xIGYl8v9_SPcwwRmkz7cK57pdbhVsd2JNz4eanhuHEzb88i3HceUGD2agH9fGqlXOqST2FVefC41THvmMRV2xks0JrJ7H3dLnWDMjCYK9rUTT6qDT3M/w640-h640/magnifier-612x612.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;h2 style=&quot;clear: both; text-align: left;&quot;&gt;Monitoring vs Observability&lt;/h2&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;In the world of IT and DevOps, monitoring and observability are two related but distinct concepts used to manage system health and performance.&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;clear: both; text-align: left;&quot;&gt;Core Difference&lt;/h4&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;The simplest way to distinguish them is:&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Monitoring tells you what is happening (and when). It is reactive and focuses on known problems using predefined metrics.&lt;/li&gt;&lt;li&gt;Observability tells you why it is happening. It is proactive and uses the system&#39;s outputs to understand its internal state, especially for &quot;unknown unknowns&quot;.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;clear: both; text-align: left;&quot;&gt;Key Comparison Table&lt;/h4&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;b&gt;Feature &lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Monitoring&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Observability&lt;/b&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;----------&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;---------------&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; -----------------&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Purpose&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Detect known issues&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;Diagnose root causes&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Perspective&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;External (symptoms)&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;Internal (system state)&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Question&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;Is the system healthy?&quot;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&quot;Why is it behaving this way?&quot;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Approach&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;Reactive&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Proactive&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Focus&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;Known knowns&quot;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;Unknown unknowns&quot;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Data Types&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;Metrics, logs&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Metrics, logs, and traces&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;clear: both; text-align: left;&quot;&gt;Analogy: The Car&lt;/h4&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Monitoring is your dashboard. It has dials for speed and fuel, and a &quot;check engine&quot; light. It tells you if you are speeding or if something is broken.&lt;/li&gt;&lt;li&gt;Observability is the mechanic’s diagnostic tool. When the &quot;check engine&quot; light comes on, the mechanic plugs in a tool to see exactly which sensor failed and why, without having to take the entire engine apart.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;clear: both; text-align: left;&quot;&gt;Common Tools&lt;/h3&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Monitoring Tools: Nagios, Zabbix, &lt;b&gt;Prometheus&lt;/b&gt;.&lt;/li&gt;&lt;li&gt;Observability Platforms: Datadog, New Relic, Honeycomb, Dynatrace.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;clear: both; text-align: left;&quot;&gt;Three Pillars of Observability&lt;/h2&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;The three pillars of observability—metrics, logs, and traces—are essential &lt;u&gt;telemetry data types &lt;/u&gt;used to understand the internal state of complex, distributed systems. They enable teams to detect, investigate, and resolve performance issues by providing high-level trends, granular event details, and full request-flow paths.&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;clear: both; text-align: left;&quot;&gt;Metrics&lt;/h3&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Quantitative measurements over time (e.g., CPU usage, error rates).&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Numerical measurements that describe the health, performance, and behavior of a system over time (e.g., CPU usage, error rates, throughput). They are ideal for alerting, capacity planning, and spotting trends or symptoms.&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;clear: both; text-align: left;&quot;&gt;Logs&lt;/h3&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Granular, timestamped records of discrete events.&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Timestamped, granular records of discrete events. They provide the detailed context (text or structured data) necessary to understand exactly what happened within an application or service.&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;clear: both; text-align: left;&quot;&gt;Traces&lt;/h3&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;End-to-end journeys of a single request through a distributed system, showing how different&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Records showing the journey of a single request as it travels through a distributed system, encompassing multiple services. They are critical for pinpointing bottlenecks, latency, or failures in microservices architectures.&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;clear: both; text-align: left;&quot;&gt;Why They Are Used Together&lt;/h3&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;While metrics indicate that a problem exists, logs provide the context of why it happened, and traces show where it is occurring. Correlating these three data types provides actionable insights rather than just raw data.&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;clear: both; text-align: left;&quot;&gt;Are Logs concern of Monitoring or Observabilty?&lt;/h2&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Both monitoring and observability deal with logs, but they do so in fundamentally different ways, representing a shift from simply knowing something is broken to understanding why.&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;b&gt;Monitoring&lt;/b&gt; is generally used to &lt;u&gt;detect &lt;b&gt;known&lt;/b&gt; issues using logs&lt;/u&gt;. It is &lt;u&gt;reactive&lt;/u&gt; and focuses on &lt;u&gt;pre-defined metrics or alert thresholds&lt;/u&gt;, such as alerting when error logs spike or when a specific error code appears.&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;b&gt;Observability&lt;/b&gt; is used to investigate and understand the &quot;why&quot; behind issues by &lt;u&gt;exploring logs, metrics, and traces together&lt;/u&gt;. It is &lt;u&gt;proactive&lt;/u&gt;, allowing you to debug complex, distributed systems without needing to know every question ahead of time.&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;clear: both; text-align: left;&quot;&gt;Comparison: Logs in Monitoring vs. Observability&lt;/h4&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;b&gt;Feature &lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Log Monitoring&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Log Observability&lt;/b&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;----------&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ---------------------&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; -------------------------&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Primary Question&amp;nbsp; &amp;nbsp;What went wrong?&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Why did it go wrong?&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Approach&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Reactive: Alerts when logs meet criteria&amp;nbsp; &amp;nbsp;Proactive: Explores data to find root causes&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Log Handling&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Searchable, indexed logs for active alerts&amp;nbsp; Contextualized, correlated logs (with traces)&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Data Usage&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; Simple monitoring and basic dashboards&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; Deep, ad-hoc, and exploratory analysis&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Typical Usage&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;Error rate &amp;gt; 5%&quot;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;Why did this transaction fail?&quot;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;clear: both; text-align: left;&quot;&gt;How They Work Together&lt;/h4&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Logs are one of the &quot;three pillars&quot; of &lt;b&gt;observability&lt;/b&gt;—alongside metrics and traces—that provide the detailed, granular context necessary for troubleshooting, notes Grafana.&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;b&gt;Monitoring&lt;/b&gt; tells you the system is unhealthy (e.g., an alert fires because of high error rates in log files).&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;b&gt;Observability&lt;/b&gt; allows you to use tools like Splunk or Datadog to dive into the logs and traces to &lt;u&gt;find the specific line of code or database failure causing the issue&lt;/u&gt;.&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;In short, monitoring is a component of observability—you cannot have true observability without comprehensive logging.&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;clear: both; text-align: left;&quot;&gt;Monitoring vs Observability on the example of AWS Lambda&lt;/h2&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;For AWS Lambda, monitoring identifies what is wrong (e.g., an execution failed), while observability reveals why it happened by connecting logs, metrics, and traces across your entire serverless architecture.&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;clear: both; text-align: left;&quot;&gt;Monitoring AWS Lambda: Detecting the Known&lt;/h4&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Monitoring focuses on pre-defined health indicators. You use it to track &quot;known-knowns&quot; and trigger reactive alerts when thresholds are breached.&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Key Tool: Amazon CloudWatch collects standard metrics automatically.&lt;/li&gt;&lt;li&gt;Monitored Metrics:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Invocations: The total number of times your function runs.&lt;/li&gt;&lt;li&gt;Errors: The count of failed executions.&lt;/li&gt;&lt;li&gt;Duration: How long your function takes to run.&lt;/li&gt;&lt;li&gt;Throttles: Occurrences where invocations are blocked due to concurrency limits.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Example Scenario: You set a CloudWatch Alarm to notify you if your Lambda&#39;s error rate exceeds 5%. Monitoring tells you there is a problem, but not the specific line of code that caused it.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;clear: both; text-align: left;&quot;&gt;Observability in AWS Lambda: Investigating the Unknown&lt;/h4&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Observability is a property of the system that allows you to understand its internal state from external outputs. It uses high-cardinality telemetry to investigate complex, distributed issues.&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Key Tool: AWS X-Ray provides distributed tracing to visualize the request path across multiple services.&lt;/li&gt;&lt;li&gt;Key Elements:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Distributed Traces: Seeing a &quot;waterfall&quot; view of a request as it moves from API Gateway to Lambda, then to DynamoDB.&lt;/li&gt;&lt;li&gt;Log Insights: Using CloudWatch Logs Insights to run ad-hoc queries across massive log volumes to find specific patterns.&lt;/li&gt;&lt;li&gt;Enhanced Instrumentation: Using libraries like AWS Lambda Powertools to add structured logging and context to your telemetry.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Example Scenario: You notice high latency in a specific user&#39;s request. Using X-Ray, you see that the Lambda function itself is fast, but it is waiting 2 seconds for a downstream third-party API call. Observability provided the &quot;why&quot;.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;clear: both; text-align: left;&quot;&gt;Comparison Summary for Lambda&lt;/h4&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;b&gt;Feature &lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; Monitoring (CloudWatch)&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Observability (X-Ray + Logs + Metrics)&lt;/b&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;----------&amp;nbsp; &amp;nbsp; &amp;nbsp;---------------------------------&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ---------------------------------------------------&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Goal&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; Track health against thresholds.&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; Understand root causes and behavior.&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Questions&amp;nbsp; &quot;Is my function failing?&quot;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;Why is this specific request slow?&quot;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Visibility&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; Isolated metrics for one function.&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; Request paths across multiple services.&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;Action&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; Reactive (Alarms/Notifications).&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; Proactive (Debugging/Optimisation).&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;---&lt;p&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/3971438138599901568/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/3971438138599901568' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/3971438138599901568'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/3971438138599901568'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/03/monitoring-and-observability.html' title='Monitoring and Observability'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgABnRMS8MEYULk3ZzfCFcQTMLdhmorAk7-EaraXAGQuxBCPPy-uEUhx_tNpsnKY0idB6o-zJe-xIGYl8v9_SPcwwRmkz7cK57pdbhVsd2JNz4eanhuHEzb88i3HceUGD2agH9fGqlXOqST2FVefC41THvmMRV2xks0JrJ7H3dLnWDMjCYK9rUTT6qDT3M/s72-w640-h640-c/magnifier-612x612.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-3852292873815390165</id><published>2026-03-16T17:29:00.001+00:00</published><updated>2026-03-16T18:02:39.956+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><category scheme="http://www.blogger.com/atom/ns#" term="Kubernetes"/><category scheme="http://www.blogger.com/atom/ns#" term="System Architecture"/><title type='text'>How to architecture highly available and fault tolerant AWS EKS Kubernetes cluster</title><content type='html'>&lt;div style=&quot;text-align: left;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEi8WwmUAx8p5XNQtaUg3CDEWtdFb70hoHgNBw3rxEbkiGpH-WPnvz0Ya09qE8B5a82wYui3oJ641ylIM-pXNUY6EV3C1uovGGLNe3oZ-LJQgWPS8HNi89nVLlTlCQRsniIwRaEsbxSAJq6rdmJap9mDX91dAYDb5UBicVZfrFk-hOrcwifBx8K36NVD3Nk&quot; style=&quot;margin-left: 1em; margin-right: 1em; text-align: center;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;639&quot; data-original-width=&quot;638&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEi8WwmUAx8p5XNQtaUg3CDEWtdFb70hoHgNBw3rxEbkiGpH-WPnvz0Ya09qE8B5a82wYui3oJ641ylIM-pXNUY6EV3C1uovGGLNe3oZ-LJQgWPS8HNi89nVLlTlCQRsniIwRaEsbxSAJq6rdmJap9mDX91dAYDb5UBicVZfrFk-hOrcwifBx8K36NVD3Nk=w640-h640&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;We should follow a layered approach—from the network up to the application.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;The &quot;Highly Available EKS&quot; Design Framework&lt;/h3&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;1. Networking &amp;amp; Control Plane (The Foundation)&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;Multi-AZ VPC&lt;/b&gt;:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Design a VPC with&lt;u&gt; at least 3 Private Subnets across 3 different Availability Zones (AZs)&lt;/u&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;EKS Endpoint (API server endpoint) Access&lt;/b&gt;:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Enable &quot;Private Access&quot; for the EKS control plane so &lt;u&gt;worker nodes communicate with API sever within the VPC, reducing exposure and latency&lt;/u&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9T7si_mhhqroPKODQQuv-UQ_bY0TYFJHTfY4OKV8EjdER9FhWxnXJAuS4pISShsAKflmll3wAhMmVNXPrmqDMtNr-7aMvVHznQPaBGelrrwsPXiTSA1w06Xc9SoyVKM5iA8Xw19GwQdtsbZEcpL8oQt3E0IJM5qPFp_q_TGTwmOGl2i6iR7dyA6bHOp4/s630/Screenshot%202026-03-16%20at%2017.46.53.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;206&quot; data-original-width=&quot;630&quot; height=&quot;210&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9T7si_mhhqroPKODQQuv-UQ_bY0TYFJHTfY4OKV8EjdER9FhWxnXJAuS4pISShsAKflmll3wAhMmVNXPrmqDMtNr-7aMvVHznQPaBGelrrwsPXiTSA1w06Xc9SoyVKM5iA8Xw19GwQdtsbZEcpL8oQt3E0IJM5qPFp_q_TGTwmOGl2i6iR7dyA6bHOp4/w640-h210/Screenshot%202026-03-16%20at%2017.46.53.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;NAT Gateways&lt;/b&gt;:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Use &lt;u&gt;one NAT Gateway per AZ &lt;/u&gt;(3 total) to ensure that if one AZ fails, the nodes in other zones still have outbound internet access for image pulls. This means that we need to have 3 public subnets, one per each AZ.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;span&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;/span&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;To use a NAT Gateway, you must place it in a public subnet (a subnet with a route to an Internet Gateway). If your goal is to have one NAT Gateway per Availability Zone (AZ) for high availability, you need a corresponding public subnet in each of those three AZs to host them.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Why this structure is necessary&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The architecture follows a specific &quot;dependency chain&quot; to ensure that an issue in one data center doesn&#39;t take down your entire outbound connectivity:&lt;/div&gt;&lt;div&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;AZ Independence&lt;/b&gt;: NAT Gateways are zone-redundant by design, but they physically reside in a specific AZ. If AZ-a goes down, the NAT Gateway inside it goes down too.&lt;/li&gt;&lt;li&gt;&lt;b&gt;The Public Subnet Requirement&lt;/b&gt;: A NAT Gateway needs a Public IP (EIP) and a route to the Internet Gateway (IGW). Only subnets configured as &quot;public&quot; can provide this.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Cross-Zone Resilience&lt;/b&gt;: By having three public subnets (one in each AZ), you can place a NAT Gateway in each. Then, you point the private subnets in AZ-a to the NAT Gateway in AZ-a, the private subnets in AZ-b to the one in AZ-b, and so on.&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The Standard Setup&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you are following the recommendation for a 3-AZ deployment, your VPC structure will typically look like this:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Component&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;AZ-1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AZ-2&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AZ-3&lt;/b&gt;&lt;/div&gt;&lt;div&gt;-----------------&amp;nbsp; &amp;nbsp;----------------------&amp;nbsp; &amp;nbsp;---------------------&amp;nbsp; &amp;nbsp; ---------------------&lt;/div&gt;&lt;div&gt;Public Subnet&amp;nbsp; &amp;nbsp;Subnet-Pub-1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Subnet-Pub-2&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Subnet-Pub-3&lt;/div&gt;&lt;div&gt;NAT Gateway&amp;nbsp; &amp;nbsp;NAT-GW-1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; NAT-GW-2&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;NAT-GW-3&lt;/div&gt;&lt;div&gt;Private Subnet&amp;nbsp; &amp;nbsp;Nodes/Workloads&amp;nbsp; &amp;nbsp;Nodes/Workloads&amp;nbsp; &amp;nbsp;Nodes/Workloads&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Note on Cost:&amp;nbsp;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;While this is the &quot;Gold Standard&quot; for reliability (preventing &quot;cross-zone data charges&quot; and ensuring 100% uptime during an AZ failure), keep in mind that AWS charges per hour for each NAT Gateway. Running three of them is significantly more expensive than running one.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;A Common Misconception&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You could technically have 3 private subnets and only 1 public subnet (with 1 NAT Gateway). In that case, all nodes in all 3 AZs would send their traffic to that single NAT Gateway.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The Risk: If the AZ containing that lone NAT Gateway fails, your nodes in the other two healthy AZs will lose their ability to pull images or talk to the internet, effectively &quot;breaking&quot; your cluster even though the nodes themselves are fine.&lt;/div&gt;&lt;span&gt;&lt;!--more--&gt;&lt;/span&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;2. Compute &amp;amp; Data Plane (The Muscle)&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;Managed Node Groups&lt;/b&gt;:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Node groups implement basic compute scaling through EC2 Auto Scaling groups.&lt;/li&gt;&lt;li&gt;Use EKS Managed Node Groups spread across those 3 subnets.&amp;nbsp;Select multiple subnets for a node group to &lt;u&gt;provision nodes across multiple Availability Zones&lt;/u&gt;.&lt;/li&gt;&lt;li&gt;Amazon EKS managed node groups make it easy to provision compute capacity for your cluster. managed node groups consist of one or more Amazon EC2 instances running the latest EKS-optimized AMIs. All nodes are provisioned as part of an Amazon EC2 Auto Scaling group that is managed for you by Amazon EKS and all resources including EC2 instances and autoscaling groups run within your AWS account.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;Auto Scaling Groups (ASG)&lt;/b&gt;:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;u&gt;Set the &lt;span style=&quot;font-family: courier;&quot;&gt;min_size&lt;/span&gt; to 3&lt;/u&gt;. This ensures that &lt;u&gt;even if a node fails, the ASG replaces it immediately.&lt;/u&gt;&amp;nbsp;&lt;/li&gt;&lt;li&gt;This is NOT Kubernetes Cluster Autoscaler (or Karpenter), which, if we want to use it, needs to be installed separately.&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;CAS and ASG both control same node groups and can get in conflict. Solution: disable scaling policies on the ASG so CAS takes control&lt;/li&gt;&lt;li&gt;Karpenter and ASG might get in conflict only if they control the same nodes. But in a well-architected EKS cluster, we usually have two different &quot;families&quot; of nodes:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;static: for&amp;nbsp;small, fixed-size Managed Node Group&amp;nbsp;To run &quot;System&quot; pods (CoreDNS, CNI, Karpenter itself)&lt;/li&gt;&lt;li&gt;dynamic: Karpenter-managed node group which runs actual workload, with dynamic number of nodes, depending on the current usage&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;Instance Diversity&lt;/b&gt;:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Mention using multiple instance types (e.g., m5.large and m6g.large) to avoid &quot;insufficient capacity&quot; errors in a specific AWS zone.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;3. Traffic Management (The Entry Point)&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;AWS Load Balancer Controller&lt;/b&gt;:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Use the &lt;span style=&quot;font-family: courier;&quot;&gt;aws-load-balancer-controller&lt;/span&gt; to provision an &lt;b&gt;Application Load Balancer (ALB)&lt;/b&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;Cross-Zone Load Balancing&lt;/b&gt;:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Ensure this is enabled so the ALB can &lt;u&gt;route traffic to healthy pods in any AZ&lt;/u&gt;, even if the &quot;local&quot; node in its own zone is struggling.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;4. Pod-Level Availability (The Brains)&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;Pod Anti-Affinity&lt;/b&gt;:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;To ensure replicas don&#39;t land on the same node.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;Topology Spread Constraints&lt;/b&gt;:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;To force an equal distribution of pods across the 3 AZs.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;Pod Disruption Budgets (PDB)&lt;/b&gt;:&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;To prevent the Cluster Autoscaler or AWS maintenance from taking down too many replicas at once.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;3 Pillars of High Availability&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Component:&amp;nbsp;&lt;b&gt;Multi-AZ ASG&lt;/b&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Layer: Infrastructure&lt;/li&gt;&lt;li&gt;Goal: Survive an entire AWS Data Center outage.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Component:&amp;nbsp;&lt;b&gt;PDBs &amp;amp; Rollouts&lt;/b&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Layer: Orchestration&lt;/li&gt;&lt;li&gt;Goal: Survive maintenance and human error (updates).&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Component:&amp;nbsp;&lt;b&gt;Spread Constraints&lt;/b&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Layer: Application&lt;/li&gt;&lt;li&gt;Goal: Survive individual EC2 instance crashes.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;---&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/3852292873815390165/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/3852292873815390165' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/3852292873815390165'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/3852292873815390165'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/03/how-to-architecture-highly-available.html' title='How to architecture highly available and fault tolerant AWS EKS Kubernetes cluster'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/a/AVvXsEi8WwmUAx8p5XNQtaUg3CDEWtdFb70hoHgNBw3rxEbkiGpH-WPnvz0Ya09qE8B5a82wYui3oJ641ylIM-pXNUY6EV3C1uovGGLNe3oZ-LJQgWPS8HNi89nVLlTlCQRsniIwRaEsbxSAJq6rdmJap9mDX91dAYDb5UBicVZfrFk-hOrcwifBx8K36NVD3Nk=s72-w640-h640-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-483828855240935203</id><published>2026-03-09T18:24:00.132+00:00</published><updated>2026-03-15T19:37:56.620+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><category scheme="http://www.blogger.com/atom/ns#" term="Kubernetes"/><title type='text'>Application Pod Disruption Budget (PDB) in Kubernetes</title><content type='html'>&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEi8WwmUAx8p5XNQtaUg3CDEWtdFb70hoHgNBw3rxEbkiGpH-WPnvz0Ya09qE8B5a82wYui3oJ641ylIM-pXNUY6EV3C1uovGGLNe3oZ-LJQgWPS8HNi89nVLlTlCQRsniIwRaEsbxSAJq6rdmJap9mDX91dAYDb5UBicVZfrFk-hOrcwifBx8K36NVD3Nk&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;639&quot; data-original-width=&quot;638&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEi8WwmUAx8p5XNQtaUg3CDEWtdFb70hoHgNBw3rxEbkiGpH-WPnvz0Ya09qE8B5a82wYui3oJ641ylIM-pXNUY6EV3C1uovGGLNe3oZ-LJQgWPS8HNi89nVLlTlCQRsniIwRaEsbxSAJq6rdmJap9mDX91dAYDb5UBicVZfrFk-hOrcwifBx8K36NVD3Nk=w640-h640&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;A &lt;b&gt;Pod Disruption Budget (PDB)&lt;/b&gt; in Kubernetes:&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;It&#39;s an API object&lt;/li&gt;&lt;li&gt;Sets for an &lt;u&gt;application&lt;/u&gt; deployed in cluster:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Either&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Minimum number of pods an application needs to function smoothly...&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Or&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Maximum number of replicated pods that are down simultaneously...&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;...during &lt;b&gt;voluntary disruptions &lt;/b&gt;(e.g., node upgrades, maintenance, draining)&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Ensures &lt;u&gt;high availability&lt;/u&gt; by guaranteeing a minimum number or percentage of pods remain active.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Key Aspects of PDBs:&lt;/h2&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;In general, disruptions can be:&lt;/div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b style=&quot;font-weight: bold;&quot;&gt;voluntary&lt;/b&gt;, such as maintenance operations or node scaling, or&lt;/li&gt;&lt;li&gt;&lt;b style=&quot;font-weight: bold;&quot;&gt;involuntary&lt;/b&gt;, such as hardware failures or system crashes&lt;/li&gt;&lt;/ul&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;Voluntary Focus&lt;/b&gt;: &lt;u&gt;PDBs only protect against voluntary disruptions&lt;/u&gt;, such as kubectl drain or node repairs, not against involuntary, unavoidable failures.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;b&gt;Configuration&lt;/b&gt;: You define a PDB using either&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;u&gt;either&lt;/u&gt; &lt;/span&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;b&gt;minAvailable&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;minimum pods that must run&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;u&gt;or&lt;/u&gt;&lt;/span&gt;&lt;span style=&quot;font-family: courier;&quot;&gt; &lt;b&gt;maxUnavailable&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;maximum pods allowed to be down&lt;/li&gt;&lt;li&gt;PDB configuration setting defining the maximum number of pods that can be voluntarily taken down simultaneously.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;b&gt;Use Case&lt;/b&gt;: Ideal for quorum-based applications (e.g., Elasticsearch, Zookeeper) to ensure quorum is never lost during node maintenance.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;b&gt;Mechanism&lt;/b&gt;: When a cluster administrator drains a node, the system checks the PDB. If removing a pod violates the budget, the action is delayed until enough replicas are available elsewhere.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Example PDB Configuration:&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;apiVersion: policy/v1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kind: PodDisruptionBudget&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name: web-pdb&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &lt;b&gt;minAvailable&lt;/b&gt;: 2 &lt;/span&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;# At least 2 pods must remain running&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; selector:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;b&gt;matchLabels&lt;/b&gt;:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; app: web-app&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Name is usually set to refer to the application for which PDB is created (&quot;web&quot; in the example above).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Best Practice:&amp;nbsp;&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Use PDBs in conjunction with pod anti-affinity rules to ensure pods are spread across nodes.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;How to check PDB in cluster?&lt;/h2&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Example:&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;kubectl get pdb -A&amp;nbsp;&lt;/b&gt; &lt;/span&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;NAMESPACE&amp;nbsp; &amp;nbsp; &amp;nbsp;NAME&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;b&gt;MIN AVAILABLE&amp;nbsp; &amp;nbsp;MAX UNAVAILABLE&amp;nbsp; &amp;nbsp;ALLOWED DISRUPTIONS&amp;nbsp;&lt;/b&gt; &amp;nbsp;AGE&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;clickhouse&amp;nbsp; &amp;nbsp; chi-clickhouse-ch&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;N/A&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;132d&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;kube-system&amp;nbsp; &amp;nbsp;ws-cluster-autoscaler&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;N/A&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;133d&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;kube-system&amp;nbsp; &amp;nbsp;coredns&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;N/A&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;140d&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;kube-system&amp;nbsp; &amp;nbsp;ebs-csi-controller&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; N/A&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;140d&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: xx-small;&quot;&gt;kube-system&amp;nbsp; &amp;nbsp;karpenter&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;N/A&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;139d&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;b&gt;ALLOWED DISRUPTIONS:&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;dynamic value, constantly re-calculated by the&amp;nbsp;&lt;b&gt;disruption controller&lt;/b&gt;&lt;/li&gt;&lt;li&gt;the real-time status indicator&amp;nbsp;&lt;/li&gt;&lt;li&gt;showing how many pods can currently be evicted without violating the set&amp;nbsp;&lt;b&gt;maxUnavailable&lt;/b&gt;&amp;nbsp;or&amp;nbsp;&lt;b&gt;minAvailable&lt;/b&gt;&amp;nbsp;constraints&lt;/li&gt;&lt;li&gt;The non-zero value means that the disruption controller has seen the pods, counted the matching pods, and updated the status of the PDB&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To see the number of current and desired healthy pods (and how &lt;span style=&quot;font-family: courier;&quot;&gt;ALLOWED DISRUPTIONS&lt;/span&gt; is actually calculated) run this command (in the example below it was for &lt;span style=&quot;font-family: courier;&quot;&gt;karpenter&lt;/span&gt; application):&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;kubectl get poddisruptionbudgets karpenter -n kube-system -o yaml&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;apiVersion: policy/v1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kind: PodDisruptionBudget&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; annotations:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; meta.helm.sh/release-name: karpenter&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; meta.helm.sh/release-namespace: kube-system&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; creationTimestamp: &quot;2025-10-21T14:05:33Z&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; generation: 1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; labels:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; app.kubernetes.io/instance: karpenter&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; app.kubernetes.io/managed-by: Helm&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; app.kubernetes.io/name: karpenter&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; app.kubernetes.io/version: 1.3.2&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; helm.sh/chart: karpenter-1.3.2&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name: karpenter&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; namespace: kube-system&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; resourceVersion: &quot;2664456&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; uid: 2b58340a-fd07-4567-95a9-2a43b5dd4bca&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; maxUnavailable: 1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; selector:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; matchLabels:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; app.kubernetes.io/instance: karpenter&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; app.kubernetes.io/name: karpenter&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;status:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; conditions:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; - lastTransitionTime: &quot;2025-10-27T10:52:01Z&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; message: &quot;&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; observedGeneration: 1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; reason: SufficientPods&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; status: &quot;True&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; type: DisruptionAllowed&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;b&gt;&amp;nbsp; currentHealthy: 2&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;b&gt;&amp;nbsp; desiredHealthy: 1&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;b&gt;&amp;nbsp; disruptionsAllowed: 1&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;b&gt;&amp;nbsp; expectedPods: 2&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;b&gt;&amp;nbsp; observedGeneration: 1&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;PDB and Rolling Update of Node Group&lt;/h2&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;b&gt;ALLOWED DISRUPTIONS = 1&lt;/b&gt;&lt;/span&gt; is generally the safest and most standard setting for a rolling node group update (which can be triggered if we e.g. upgrade k8s version of &lt;a href=&quot;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;aws_eks_node_group&lt;/a&gt;), especially for high-availability workloads.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Key Considerations for maxUnavailable: 1&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Safety First&lt;/b&gt;: &lt;u&gt;This setting ensures only one node is updated at a time (node - if all pod replicas are distribute across all nodes)&lt;/u&gt;. This is ideal for maintaining quorum in stateful applications like databases (e.g., Consul or ZooKeeper) where losing multiple nodes&amp;nbsp;&lt;/div&gt;&lt;div&gt;simultaneously could cause data loss or service failure.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Default Behavior&lt;/b&gt;: In Amazon EKS managed node groups, &lt;span style=&quot;font-family: courier;&quot;&gt;maxUnavailable&lt;/span&gt; defaults to 1 if not specified.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Resource Availability&lt;/b&gt;: For this to work, your cluster must have enough spare capacity (CPU/Memory) on the remaining nodes to host the pods evicted from the node being updated.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Update Speed&lt;/b&gt;: While safe, updating one node at a time is the slowest method. For very large clusters, you might consider a higher absolute number or a percentage (e.g., 10%) to speed up the process.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;When 1 is NOT Enough&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Blocking Drains&lt;/b&gt;: If you have a Pod Disruption Budget (PDB) where &lt;span style=&quot;font-family: courier;&quot;&gt;minAvailable&lt;/span&gt; equals your total replicas, the node drain will be blocked, and the update will stall because no pods can be legally moved.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Timeouts&lt;/b&gt;: Amazon EKS has a 15-minute timeout for draining pods. If pods take too long to terminate, the update may fail unless you have configured pre-stop hooks or adjusted your PDBs.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;In-Depth Explanation&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;In a Pod Disruption Budget (PDB), the setting ALLOWED DISRUPTIONS = 1 (which results from either maxUnavailable: 1 or a minAvailable value that leaves one &quot;slot&quot; free) acts as a safety valve that synchronizes infrastructure changes with application health.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here is exactly how it makes a rolling node group update safe:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;1. It Hooks into the &quot;Eviction API&quot;&amp;nbsp;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When a node group update begins, the automation doesn&#39;t just &quot;kill&quot; pods; it calls the Kubernetes Eviction API.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The Check: &lt;u&gt;Before a pod is removed from a node being updated, the Eviction API checks your PDB&lt;/u&gt;.&lt;/div&gt;&lt;div&gt;The Logic: &lt;u&gt;If ALLOWED DISRUPTIONS is 1, the API allows exactly one pod to be terminated. Once that pod is gone, the &quot;Allowed Disruptions&quot; counter drops to 0.&amp;nbsp;&lt;/u&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;2. It Forces a Sequential Wait&amp;nbsp;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is the most critical safety feature. If a second pod eviction is requested while the first one is still being replaced:&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;The Block: &lt;u&gt;The API sees ALLOWED DISRUPTIONS = 0 and rejects the eviction request&lt;/u&gt;.&lt;/li&gt;&lt;li&gt;The Wait: &lt;u&gt;The node &quot;drain&quot; process pauses and retries. It will stay paused until the first pod&#39;s replacement is scheduled on a different node and passes its Readiness Probe.&lt;/u&gt;&lt;/li&gt;&lt;li&gt;The Reset: Only when the new pod is &quot;Ready&quot; does the ALLOWED DISRUPTIONS count return to 1, allowing the next pod to be safely evicted.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;3. It Prevents &quot;Brain-Dead&quot; Automation&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Without this PDB setting, a node group update might try to drain a node that holds all replicas of your app.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Without PDB: The node drains, kills all pods at once, and you have a total outage.&lt;/li&gt;&lt;li&gt;With ALLOWED DISRUPTIONS = 1: The automation is physically unable to kill the second pod until the first one is safely back online elsewhere, ensuring your app always has at least some capacity.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Summary of the &quot;Safety Loop&quot;&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Step&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;Action&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; PDB State (Allowed Disruptions)&lt;/div&gt;&lt;div&gt;1&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;Node update starts; first pod eviction requested&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;1 → Eviction granted&lt;/div&gt;&lt;div&gt;2&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;First pod is terminating; replacement is starting&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;0 → All further evictions blocked&lt;/div&gt;&lt;div&gt;3&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;Replacement pod passes Readiness Probe&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 0 → 1 → Block lifted&lt;/div&gt;&lt;div&gt;4&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;Next pod eviction requested&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 1 → Process repeats&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Important Note: If your app only has 1 replica total, a PDB with minAvailable: 1 will block the node update forever because it can never safely evict that single pod. You generally need at least 2 replicas for this safety mechanism to work without stalling your updates.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Can pod disruption budget be defined in deployment manifest?&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;No, a Pod Disruption Budget (PDB) cannot be defined directly inside a Deployment manifest. In Kubernetes, a PDB is a separate API resource (Kind: PodDisruptionBudget) that exists independently of the Deployment.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;While they are separate resources, they are linked by a Label Selector. You define the PDB to target specific pods by matching the labels specified in your Deployment&#39;s pod template.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Why they are separate?&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Decoupled Lifecycle: You can create, update, or delete a PDB without needing to redeploy your application or trigger a rolling update of your pods.&lt;/li&gt;&lt;li&gt;Multiple Controllers: A single PDB can protect pods across multiple Deployments, ReplicaSets, or StatefulSets as long as they share the same labels.&lt;/li&gt;&lt;li&gt;Administrative Control: Cluster administrators may manage PDBs separately from application developers to ensure cluster-wide stability during maintenance like node drains.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;How to link them?&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To make them work together, ensure the spec.selector.matchLabels in your PDB YAML matches the spec.template.metadata.labels in your Deployment YAML.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Deployment snippet:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; labels:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; app: my-app&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; template:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; labels:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #ffa400; font-family: courier;&quot;&gt;app: my-app&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;PDB snippet:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; selector:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;b&gt;matchLabels&lt;/b&gt;:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #ffa400; font-family: courier;&quot;&gt;app: my-app&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &lt;b&gt;minAvailable&lt;/b&gt;: 2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here is an example of a complete multi-resource YAML that includes both the Deployment and the PDB:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;apiVersion: apps/v1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kind: Deployment&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name: web-server&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; labels:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #ffa400; font-family: courier;&quot;&gt;app: nginx&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; replicas: 3&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; selector:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; matchLabels:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; app: nginx&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; template:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; labels:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; app: nginx&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; containers:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - name: nginx&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; image: nginx:latest&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ports:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - containerPort: 80&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;---&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;apiVersion: policy/v1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kind: PodDisruptionBudget&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name: web-server-pdb&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; # The PDB finds the pods using this selector&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; selector:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; matchLabels:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #ffa400; font-family: courier;&quot;&gt;app: nginx&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; # Ensures at least 2 pods stay up during voluntary disruptions&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &lt;b&gt;minAvailable&lt;/b&gt;: 2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Key Takeaways:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;The Link&lt;/b&gt;: The spec.selector.matchLabels in the PDB must exactly match the spec.template.metadata.labels in the Deployment.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Voluntary Disruptions&lt;/b&gt;: This PDB will protect your pods during actions like node drains or cluster upgrades, but it won&#39;t prevent &quot;involuntary&quot; issues like a hardware crash.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Using &lt;span style=&quot;font-family: courier;&quot;&gt;maxUnavailable&lt;/span&gt; is often better for autoscaling environments because it scales with your replica count. Instead of saying &quot;I need X pods alive,&quot; you’re saying &quot;I can afford to lose X pods.&quot;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here is the updated manifest:&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;apiVersion: apps/v1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kind: Deployment&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name: web-server&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; replicas: 5&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; selector:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; matchLabels:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; app: nginx&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; template:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; labels:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; app: nginx&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; containers:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - name: nginx&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; image: nginx:latest&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;---&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;apiVersion: policy/v1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kind: PodDisruptionBudget&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name: web-server-pdb&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; selector:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; matchLabels:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; app: nginx&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; # Only 1 pod can be taken down at a time during maintenance&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &lt;b&gt;maxUnavailable&lt;/b&gt;: 1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Pro Tips for &lt;span style=&quot;font-family: courier;&quot;&gt;maxUnavailable&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;Absolute Number&lt;/b&gt;: Using 1 ensures that even if you have 100 replicas, Kubernetes will only drain one node at a time for this app.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Percentage:&lt;/b&gt; You can use a string like &quot;25%&quot; if you want the &quot;allowed downtime&quot; to grow or shrink as your Deployment scales.&lt;/li&gt;&lt;li&gt;&lt;b&gt;The &quot;One&quot; Rule&lt;/b&gt;: You cannot use both &lt;span style=&quot;font-family: courier;&quot;&gt;minAvailable&lt;/span&gt; and &lt;span style=&quot;font-family: courier;&quot;&gt;maxUnavailable&lt;/span&gt; in the same PDB; you have to pick one strategy.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;How to use a percentage to make the PDB more flexible for Horizontal Pod Autoscaling (HPA)?&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Using percentages for a Pod Disruption Budget (PDB) is highly recommended when combined with a Horizontal Pod Autoscaler (HPA). This allows the disruption budget to scale dynamically as your application grows or shrinks based on traffic.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Dynamic YAML Example (Deployment + HPA + PDB)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This configuration ensures that no matter how many replicas the HPA creates, at least 80% of them will always remain available during maintenance.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;apiVersion: apps/v1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kind: Deployment&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name: dynamic-app&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; replicas: 2 # Initial count&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; selector:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; matchLabels:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; app: web&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; template:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; labels:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; app: web&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; containers:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - name: nginx&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; image: nginx:latest&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;---&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;apiVersion: autoscaling/v2&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kind: HorizontalPodAutoscaler&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name: web-hpa&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; scaleTargetRef:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; apiVersion: apps/v1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; kind: Deployment&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; name: dynamic-app&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; minReplicas: 2&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; maxReplicas: 10&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; metrics:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; - type: Resource&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; resource:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; name: cpu&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; target:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; type: Utilization&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; averageUtilization: 50&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;---&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;apiVersion: policy/v1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kind: PodDisruptionBudget&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name: web-pdb&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; selector:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; matchLabels:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; app: web&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; # Scales with HPA: if HPA scales to 10 pods, 8 must stay up.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; minAvailable: 80%&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Key Behaviours to Note:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Rounding Logic: Kubernetes always rounds up the result of the percentage to the nearest integer. For example, if you have 7 pods and set minAvailable: 50%, Kubernetes requires 4 pods to remain available.&lt;/li&gt;&lt;li&gt;Maintenance Blockers: Be careful with 100% or 0%. Setting minAvailable: 100% or maxUnavailable: 0% will completely block node drains, preventing cluster administrators from performing upgrades or maintenance.&lt;/li&gt;&lt;li&gt;Single Replica Limitation: If your HPA scales down to 1 replica, a PDB with minAvailable: 1 or 100% will prevent that single pod from being evicted, which can stall cluster maintenance.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;How to troubleshoot a node drain that is stuck because of a PDB?&lt;/h2&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;A kubectl drain typically gets stuck because the ALLOWED DISRUPTIONS for a specific PDB is 0. This means evicting even one more pod would violate your availability rules.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;1. Identify the Blocking PDB&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Run this command to see which PDB is preventing the drain:&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kubectl get pdb -A&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Look for any PDB where &lt;span style=&quot;font-family: courier;&quot;&gt;ALLOWED DISRUPTIONS&lt;/span&gt; is 0. If it’s 0, the &lt;u&gt;eviction API&lt;/u&gt; will &lt;u&gt;reject any attempt to move those pods&lt;/u&gt;, and the &lt;u&gt;drain will wait indefinitely&lt;/u&gt;.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;2. Common Reasons for &quot;Allowed Disruptions: 0&quot;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;Too Few Replicas&lt;/b&gt;: You have &lt;span style=&quot;font-family: courier;&quot;&gt;minAvailable: 1&lt;/span&gt; but only 1 pod is currently running.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Unhealthy Pods&lt;/b&gt;: Your PDB requires 3 pods to be &lt;u&gt;healthy&lt;/u&gt;, but one is crashing or not yet &quot;Ready.&quot; The &lt;u&gt;PDB won&#39;t allow any more to be removed until that one is fixed&lt;/u&gt;.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Misconfiguration&lt;/b&gt;: You set &lt;span style=&quot;font-family: courier;&quot;&gt;minAvailable&lt;/span&gt; equal to your total replicas (e.g., 3 out of 3), meaning you&#39;ve effectively told Kubernetes &quot;never take a pod down&quot;.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;3. How to Unstick the Drain&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Depending on your situation, use one of these three strategies:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Strategy: Scale Up&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Command:&amp;nbsp; kubectl scale deployment &amp;lt;name&amp;gt; --replicas=&amp;lt;current+1&amp;gt;&lt;/li&gt;&lt;li&gt;Best For: Safest: Adds a new pod on a different node so the PDB is satisfied.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Strategy:&amp;nbsp;Relax PDB&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Command: kubectl edit pdb &amp;lt;pdb-name&amp;gt;&lt;/li&gt;&lt;li&gt;Best For:&amp;nbsp;Cleanest: Temporarily lower minAvailable or increase maxUnavailable.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Strategy:&amp;nbsp;Temporary Delete&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Command: kubectl delete pdb &amp;lt;pdb-name&amp;gt;&lt;/li&gt;&lt;li&gt;Best For:&amp;nbsp;Emergency: Delete the PDB, finish the drain, then re-apply the PDB later.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Warning: The &quot;Force&quot; Flag&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Using kubectl drain &amp;lt;node&amp;gt; --force does not bypass PDBs. It only forces the deletion of pods not managed by a controller (like standalone pods) or pods using emptyDir. To truly bypass a PDB, you must either delete the PDB or manually kubectl delete pod the blocking pods&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;How to&amp;nbsp;find all pods on a specific node that are currently protected by a PDB?&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;To find pods on a specific node that are protected by a Pod Disruption Budget (PDB), you need to cross-reference the pods on that node with the label selectors defined in your PDBs.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Option 1: The Quickest Way (Manual Check)&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The most direct way to see all pods on a node and identify their labels is to use the describe node command.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kubectl describe node &amp;lt;node-name&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Look for the &lt;b&gt;Non-terminated&lt;/b&gt; Pods section. You can then check if those pods&#39; labels match your PDB selectors.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Option 2: Filtered Search (Best for Large Nodes)&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If the node has many pods, use this command to list all pods on that node along with their labels:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kubectl get pods -A \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp;-o wide \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp;--field-selector spec.nodeName=&amp;lt;node-name&amp;gt; \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp;--show-labels&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-A: Searches across all namespaces.&lt;/div&gt;&lt;div&gt;--field-selector spec.nodeName: Limits results to the specific node.&lt;/div&gt;&lt;div&gt;--show-labels: Displays the labels you need to compare against your PDB&#39;s spec.selector.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Option 3: Identifying the PDB Selector&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To see exactly what labels a PDB is looking for, run:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kubectl get pdb &amp;lt;pdb-name&amp;gt; \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp;-o jsonpath=&#39;{.spec.selector.matchLabels}&#39;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Any pod on your node that has these exact labels is protected by that PDB.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Summary of Useful Flags&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Flag &lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Purpose&lt;/b&gt;&lt;/div&gt;&lt;div&gt;-----------------&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;----------&lt;/div&gt;&lt;div&gt;-o wide&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Shows the NODE column to verify where pods are running.&lt;/div&gt;&lt;div&gt;--field-selector&lt;span style=&quot;white-space: pre;&quot;&gt;         &lt;/span&gt;Filters the list server-side by the node name.&lt;/div&gt;&lt;div&gt;-l or --selector&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Filters pods by specific labels (e.g., kubectl get pods -l app=nginx).&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;---&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/483828855240935203/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/483828855240935203' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/483828855240935203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/483828855240935203'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/03/application-pod-disruption-budget-pdb.html' title='Application Pod Disruption Budget (PDB) in Kubernetes'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/a/AVvXsEi8WwmUAx8p5XNQtaUg3CDEWtdFb70hoHgNBw3rxEbkiGpH-WPnvz0Ya09qE8B5a82wYui3oJ641ylIM-pXNUY6EV3C1uovGGLNe3oZ-LJQgWPS8HNi89nVLlTlCQRsniIwRaEsbxSAJq6rdmJap9mDX91dAYDb5UBicVZfrFk-hOrcwifBx8K36NVD3Nk=s72-w640-h640-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-1710786838978241612</id><published>2026-03-05T11:50:00.006+00:00</published><updated>2026-03-05T13:20:04.951+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Altinity"/><category scheme="http://www.blogger.com/atom/ns#" term="Clickhouse"/><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><category scheme="http://www.blogger.com/atom/ns#" term="Kubernetes"/><title type='text'>How to install Clickhouse in AWS EKS cluster via Altinity Helm charts and Terraform</title><content type='html'>&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIoJUC3ruc8P4B4sQhb-4Uzyxm5MDkD-Lc_s7bTOQZc2gkcS2jJcCof0St5glwjSviWGw1TjWZ1xIQfHPkNupq9vNTfdifpBSzDY1ZYjcKRku5SgmV_flV6OxkQ7OHIxus0ME748BxHjdhyphenhyphenQK2xDewGE2xP9WEcHCVZ1g8dDFHDCyH8XhpaEMg4Rk_E70/s1344/Screenshot%202026-03-05%20at%2011.46.05.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;972&quot; data-original-width=&quot;1344&quot; height=&quot;462&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIoJUC3ruc8P4B4sQhb-4Uzyxm5MDkD-Lc_s7bTOQZc2gkcS2jJcCof0St5glwjSviWGw1TjWZ1xIQfHPkNupq9vNTfdifpBSzDY1ZYjcKRku5SgmV_flV6OxkQ7OHIxus0ME748BxHjdhyphenhyphenQK2xDewGE2xP9WEcHCVZ1g8dDFHDCyH8XhpaEMg4Rk_E70/w640-h462/Screenshot%202026-03-05%20at%2011.46.05.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Installing ClickHouse on an AWS EKS cluster using Terraform and the Altinity Helm charts typically involves two stages:&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Installing the Altinity ClickHouse Operator&lt;/li&gt;&lt;li&gt;Deploying a ClickHouse Installation (CHI)&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;The Altinity Helm repository is located at &lt;a href=&quot;https://helm.altinity.com&quot;&gt;https://helm.altinity.com&lt;/a&gt;.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Prerequisites&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Ensure your Terraform environment is configured with the following providers:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;aws&lt;/span&gt;: To manage EKS and underlying infrastructure.&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;kubernetes&lt;/span&gt;: To interact with the EKS cluster.&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;helm&lt;/span&gt;: To install the operator.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Terraform Configuration&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The following example uses the &lt;span style=&quot;font-family: courier;&quot;&gt;helm_release&lt;/span&gt; resource to install the operator and the &lt;span style=&quot;font-family: courier;&quot;&gt;kubernetes_manifest&lt;/span&gt; resource to deploy the actual ClickHouse cluster.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Step A: Install the Altinity Operator&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The operator is the &quot;brain&quot; that &lt;u&gt;manages ClickHouse instances&lt;/u&gt; on Kubernetes.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;resource &quot;helm_release&quot; &quot;clickhouse_operator&quot; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;= &quot;clickhouse-operator&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; repository&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;= &quot;https://helm.altinity.com&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; chart&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; = &quot;altinity-clickhouse-operator&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; namespace&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; = &quot;clickhouse-operator&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; create_namespace = true&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; # Optional: Enable metrics for Prometheus&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; set {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; name&amp;nbsp; = &quot;metrics.enabled&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; value = &quot;true&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Step B: Deploy a ClickHouse Cluster (CHI)&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Once the operator is running, you define your &lt;i&gt;ClickHouse cluster&lt;/i&gt; using a Custom Resource (CRD). In Terraform, you use &lt;span style=&quot;font-family: courier;&quot;&gt;kubernetes_manifest&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;resource &quot;kubernetes_manifest&quot; &quot;clickhouse_cluster&quot; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; depends_on = [helm_release.clickhouse_operator]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; manifest = {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; apiVersion = &quot;clickhouse.altinity.com/v1&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; kind&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;= &quot;ClickHouseInstallation&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; metadata = {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; name&amp;nbsp; &amp;nbsp; &amp;nbsp; = &quot;simple-clickhouse&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; namespace = &quot;clickhouse-operator&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; spec = {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; configuration = {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; clusters = [&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; name = &quot;cluster1&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; layout = {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; shardsCount&amp;nbsp; &amp;nbsp;= 1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; replicasCount = 1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Production Considerations for EKS&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When running ClickHouse on EKS, you should consider storage and networking:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;Storage Class&lt;/b&gt;: Use AWS gp3 volumes for a good balance of price and performance. You can specify a &lt;span style=&quot;font-family: courier;&quot;&gt;volumeClaimTemplate&lt;/span&gt; in your &lt;span style=&quot;font-family: courier;&quot;&gt;kubernetes_manifest&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Node Affinity&lt;/b&gt;: It is recommended to run ClickHouse on specific node groups (e.g., using &lt;span style=&quot;font-family: courier;&quot;&gt;i3&lt;/span&gt; or &lt;span style=&quot;font-family: courier;&quot;&gt;r5&lt;/span&gt; instances) to ensure it doesn&#39;t compete with other workloads for IOPS.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Zookeeper/Keeper&lt;/b&gt;: For multi-node shards or replicas, you will need a Zookeeper cluster or the ClickHouse Keeper (also available via Altinity charts).&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;EKS Module&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Altinity maintains a dedicated Terraform EKS ClickHouse module that automates the entire VPC, EKS, and ClickHouse setup if you prefer a pre-packaged solution.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;How to view Clickhouse Installation Configuration?&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;kubectl get chi -n clickhouse -o yaml&amp;nbsp;&lt;/b&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;apiVersion: v1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;items:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;- apiVersion: &lt;b&gt;clickhouse.altinity.com/v1&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; kind: &lt;b&gt;ClickHouseInstallation&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; annotations:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; kubectl.kubernetes.io/last-applied-configuration: |&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;{&quot;apiVersion&quot;:&quot;clickhouse.altinity.com/v1&quot;,&quot;kind&quot;:&quot;ClickHouseInstallation&quot;,&quot;metadata&quot;:....}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; creationTimestamp: &quot;2025-01-28T14:35:46Z&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; finalizers:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; - finalizer.clickhouseinstallation.altinity.com&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; generation: 12&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; name: clickhouse&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; namespace: clickhouse&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; resourceVersion: &quot;67251031&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; uid: 9fxxxx1-81e7-429b-9cf7-ffxxxxxxef&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; configuration:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; clusters:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - layout:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; replicasCount: 1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; shardsCount: 1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; name: ch&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; templates:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; dataVolumeClaimTemplate: ch-data&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; podTemplate: ch-pod&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; serviceTemplate: ch-svc&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; users:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; admin/grants/query: GRANT ALL ON *.*&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; admin/networks/ip: 0.0.0.0/0&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;b&gt;admin/password&lt;/b&gt;: my-admin-password&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;(or&amp;nbsp; &amp;nbsp; &amp;nbsp;admin/password_sha256_hex:&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: small;&quot;&gt;my-admin-password-in-sha256&lt;/span&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; admin/profile: xxxx&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; admin/quota: xxxxx&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; admin/settings/enable_http_compression: 1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;b&gt;default/k8s_secret_password_sha256_hex&lt;/b&gt;: &amp;lt;namespace/secretName/key&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; default/profile: default&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; default/quota: default&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; templates:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; podTemplates:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - name: ch-pod&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; containers:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - image: altinity/clickhouse-server:24.8.14.10544.altinitystable&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; name: clickhouse&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - args:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - server&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; env:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - name: LOG_LEVEL&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; value: info&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - name: API_LISTEN&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; value: 0.0.0.0:7171&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - name: API_CREATE_INTEGRATION_TABLES&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; value: &quot;true&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - name: REMOTE_STORAGE&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; value: s3&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - name: BACKUPS_TO_KEEP_REMOTE&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; value: &quot;2&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - name: S3_BUCKET&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; value: my-clickhouse-backups&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - name: S3_REGION&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; value: us-east-1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - name: CLICKHOUSE_HOST&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; value: localhost&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - name: CLICKHOUSE_USERNAME&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; value: xxxxx&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - name: CLICKHOUSE_PASSWORD&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; value: xxxx&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; image: altinity/clickhouse-backup:latest&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; imagePullPolicy: IfNotPresent&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; name: clickhouse-backup&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; serviceAccountName: clickhouse-backup&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; tolerations:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - effect: NoSchedule&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; key: karpenter/clickhouse&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; operator: Exists&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; serviceTemplates:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; annotations:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; service.beta.kubernetes.io/aws-load-balancer-ip-address-type: ipv4&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; service.beta.kubernetes.io/aws-load-balancer-name: my-clickhouse-nlb&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; service.beta.kubernetes.io/aws-load-balancer-scheme: internal&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; service.beta.kubernetes.io/aws-load-balancer-type: nlb&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; name: clickhouse&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; name: ch-svc&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ports:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - name: http&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; port: 8123&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; targetPort: 8123&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - name: native&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; port: 9000&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; targetPort: 9000&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; type: LoadBalancer&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; volumeClaimTemplates:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - name: ch-data&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; accessModes:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - ReadWriteOnce&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; resources:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; requests:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; storage: 100Gi&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; status:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; chop-commit: 9abcd12&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; chop-date: 2025-01-24T08:40:12&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; chop-ip: 10.x.x.x&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; chop-version: 0.25.5&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; clusters: 1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; endpoint: clickhouse-clickhouse.clickhouse.svc.cluster.local&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; fqdns:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; - chi-clickhouse-ch-0-0.clickhouse.svc.cluster.local&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; hosts: 1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; hostsWithTablesCreated:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; - chi-clickhouse-ch-0-0.clickhouse.svc.cluster.local&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; pods:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; - chi-clickhouse-ch-0-0-0&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; shards: 1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; status: Completed&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; taskID: auto-1xxxxd2-5ba4-4c3a-9daa-baxxxxx850&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; taskIDsCompleted:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; - auto-1fxxxxxd2-5ba4-4c3a-9daa-baxxxxxx50&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; - auto-bbxxxx6-31e3-4a4c-b04b-e5xxxxxx91&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; taskIDsStarted:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; - auto-31xxxxx37-492f-4109-b515-4axxxxxx6c8&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ...&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; - auto-b8xxxxx7-0396-41e0-b5d1-95xxxxd48&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;kind: List&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; resourceVersion: &quot;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Users section shows users config in form &lt;span style=&quot;font-family: courier;&quot;&gt;USER_NAME/ATTRIBUTE&lt;/span&gt;. In the example above we have two users: &lt;span style=&quot;font-family: courier;&quot;&gt;admin&lt;/span&gt; and &lt;span style=&quot;font-family: courier;&quot;&gt;default&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;USER_NAME/password&lt;/span&gt; values is plain text password. This is very convenient for debugging (though usually a security &quot;no-no&quot; for production, especially if that&#39;s &lt;span style=&quot;font-family: courier;&quot;&gt;admin&lt;/span&gt; or &lt;span style=&quot;font-family: courier;&quot;&gt;default&lt;/span&gt; user!).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;USER_NAME/password_sha256_hex&lt;/span&gt; is a SHA256 hashed password.&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;USER_NAME/k8s_secret_password_sha256_hex: &amp;lt;namespace/SECRET_NAME/KEY_NAME&amp;nbsp;&amp;gt;&lt;/span&gt;&amp;nbsp;shows that&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: courier; font-weight: normal;&quot;&gt;USER_NAME&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;&amp;nbsp;ClickHouse user is secured using a Kubernetes Secret. This maps the default user&#39;s password to a specific Kubernetes Secret.&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;USER_NAME/k8s_secret_password_sha256_hex&lt;/span&gt;: Specifies that for the user named USER_NAME, the password should be read from a Kubernetes Secret as a SHA256 hex string.&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;lt;namespace/&lt;span style=&quot;font-family: Times;&quot;&gt;SECRET_NAME&lt;/span&gt;/&lt;span style=&quot;font-family: Times;&quot;&gt;KEY_NAME&amp;nbsp;&lt;/span&gt;&amp;gt;&lt;/span&gt;: This is the reference to the &lt;b&gt;secret&lt;/b&gt; itself, structured as &lt;span style=&quot;font-family: courier;&quot;&gt;namespace/SECRET_NAME/KEY_NAME&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Purpose&lt;/b&gt;: This allows for secure, GitOps-friendly password management, preventing plain-text passwords from appearing in Kubernetes manifests.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Implementation&lt;/b&gt;: The ClickHouse Operator reads this secret and places the hashed password into the users.xml file for the ClickHouse server.&amp;nbsp;Operator reads the secret, hashes the password (if necessary), and writes it into a file called /etc/clickhouse-server/users.d/chop-generated-users.xml inside your ClickHouse pod.&amp;nbsp;If you have External Secrets installed, this secret is likely being pulled from AWS Secrets Manager.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Alternative&lt;/b&gt;: You can also use &lt;span style=&quot;font-family: courier;&quot;&gt;k8s_secret_env_password_sha256_hex&lt;/span&gt; to load the password via an environment variable.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In the Altinity Operator, the syntax&amp;nbsp;&lt;span style=&quot;font-family: courier;&quot;&gt;USER_NAME&lt;/span&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;/k8s_secret_password_sha256_hex &lt;/span&gt;is a pointer. It tells the operator to look into a specific secret to find the password hash for the&amp;nbsp;&lt;span style=&quot;font-family: courier;&quot;&gt;USER_NAME&lt;/span&gt;&amp;nbsp;user.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To get the password:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% kubectl get secret &amp;lt;SECRET_NAME&amp;gt; \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;-n &amp;lt;NAMESPACE&amp;gt; \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;-o jsonpath=&quot;{.data.&amp;lt;KEY_NAME&amp;gt;}&quot; \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;| base64 -d&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;NAMESPACE is usually &lt;span style=&quot;font-family: courier;&quot;&gt;clickhouse&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;How to check Clickhouse health?&lt;/h2&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Since ClickHouse is running in our cluster, the best way to verify it&#39;s &quot;working fine&quot; is to move beyond just checking the Pod status and actually query the database engine itself.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here is a 3-step approach to verify health, connectivity, and data integrity.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;1. The &quot;Internal&quot; Health Check&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The quickest way is to execute a command directly inside the pod using the clickhouse-client. This bypasses networking issues and tells you if the engine is responsive. Run this command:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kubectl exec -it chi-clickhouse-ch-0-0 \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;-n clickhouse \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;-- clickhouse-client &lt;/span&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;--query &quot;SELECT version(), uptime()&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;chi-clickhouse-ch-0-0&lt;/span&gt; is the name of the pod, it can also be like &lt;span style=&quot;font-family: courier;&quot;&gt;chi-clickhouse-ch-0-0-0&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;If this returns data, it means ClickHouse is successfully reading from its system tables on the EBS volume.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;What to look for: It should return the version string and the number of seconds the server has been up. If this fails, the DB engine itself is hung.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you are using &lt;span style=&quot;font-family: courier;&quot;&gt;default&lt;/span&gt; user which has a password, or, &lt;span style=&quot;font-family: courier;&quot;&gt;default&lt;/span&gt; user was disabled, the output might show the error similar to this:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% kubectl exec -it chi-clickhouse-ch-0-0-0 -n clickhouse -- clickhouse-client --query &quot;SELECT version(), uptime()&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: red; font-family: courier; font-size: x-small;&quot;&gt;Defaulted container &quot;clickhouse&quot; out of: clickhouse, clickhouse-backup&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: red; font-family: courier; font-size: x-small;&quot;&gt;Code: 516. DB::Exception: Received from localhost:9000. DB::Exception: default: Authentication failed: password is incorrect, or there is no user with such name.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: red; font-family: courier; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: red; font-family: courier; font-size: x-small;&quot;&gt;If you have installed ClickHouse and forgot password you can reset it in the configuration file.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: red; font-family: courier; font-size: x-small;&quot;&gt;The password for default user is typically located at /etc/clickhouse-server/users.d/default-password.xml&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: red; font-family: courier; font-size: x-small;&quot;&gt;and deleting this file will reset the password.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: red; font-family: courier; font-size: x-small;&quot;&gt;See also /etc/clickhouse-server/users.xml on the server where ClickHouse is installed.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: red; font-family: courier; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: red; font-family: courier; font-size: x-small;&quot;&gt;. (AUTHENTICATION_FAILED)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: red; font-family: courier; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: red; font-family: courier; font-size: x-small;&quot;&gt;command terminated with exit code 4&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Seeing an &lt;span style=&quot;font-family: courier;&quot;&gt;AUTHENTICATION_FAILED&lt;/span&gt; error instead of a &lt;span style=&quot;font-family: courier;&quot;&gt;Connection Refused&lt;/span&gt; error is actually a positive result for this check:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Networking works: Your kubectl exec reached the pod.&lt;/li&gt;&lt;li&gt;Process is alive: The ClickHouse server is running and actively rejecting bad logins.&lt;/li&gt;&lt;li&gt;Storage is mounted: ClickHouse can&#39;t check credentials if it can&#39;t read its config files from disk.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;If we know the Clickhouse credentials, we can perform the health check:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% kubectl exec -it chi-clickhouse-ch-0-0-0 -n clickhouse -- clickhouse-client --user USER --password PASS --query &quot;SELECT version(), uptime(), name FROM system.clusters&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;Defaulted container &quot;clickhouse&quot; out of: clickhouse, clickhouse-backup&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;24.8.14.10544.altinitystable&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;501389&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;all-clusters&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;24.8.14.10544.altinitystable&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;501389&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;all-replicated&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;24.8.14.10544.altinitystable&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;501389&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;all-sharded&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;24.8.14.10544.altinitystable&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;501389&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;ch&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;24.8.14.10544.altinitystable&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;501389&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;default&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The output above is exactly what we wanted to see. The database is responsive, healthy, and has an uptime of ~5.8 days (501,389 seconds). The version 24.8.14.10544.altinitystable indicates we are on a very recent, stable Altinity build.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;2. Check Replication and Disk Health&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Since you are using the Altinity Operator, ClickHouse is likely managing data across disks. You want to ensure the &quot;System&quot; tables report no errors. Run this to check if the disks are mounted and have space:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;kubectl exec -it chi-clickhouse-ch-0-0-0 \&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;b&gt;-n clickhouse \&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;b&gt;-- clickhouse-client&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;b style=&quot;color: #38761d; font-family: courier;&quot;&gt;--user USER --password PASS \&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b style=&quot;color: #38761d; font-family: courier;&quot;&gt;--query &quot;SELECT name, path, formatReadableSize(free_space) AS free, formatReadableSize(total_space) AS total FROM system.disks&quot;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Defaulted container &quot;clickhouse&quot; out of: clickhouse, clickhouse-backup&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;default&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;/var/lib/clickhouse/&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;89.60 GiB&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;95.80 GiB&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you have multiple replicas (e.g., a ch-0-1 pod), check for replication lag:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;kubectl exec -it chi-clickhouse-ch-0-0-0 \&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;b&gt;-n clickhouse \&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;b&gt;-- clickhouse-client --user&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;USER&lt;/span&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;--password&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;PASS&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;b&gt;&amp;nbsp;\&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;b&gt;--query &quot;SELECT type, last_exception, num_tries FROM system.replication_queue WHERE last_exception != &#39;&#39;&quot;&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Defaulted container &quot;clickhouse&quot; out of: clickhouse, clickhouse-backup&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Result: This should ideally be empty (or as above) . If you see exceptions here, your nodes aren&#39;t syncing correctly.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;3. Verify the &quot;Operator&quot; View&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The Altinity Operator provides a &quot;Status&quot; field in its Custom Resource that summarizes the health of the entire installation.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;kubectl get chi -n clickhouse&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;NAME&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;CLUSTERS&amp;nbsp; &amp;nbsp;HOSTS&amp;nbsp; &amp;nbsp;STATUS&amp;nbsp; &amp;nbsp; &amp;nbsp; HOSTS-COMPLETED&amp;nbsp; &amp;nbsp;AGE&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;clickhouse&amp;nbsp; &amp;nbsp;1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;b&gt;Completed&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;123d&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What to look for: Look for the &lt;span style=&quot;font-family: courier;&quot;&gt;STATUS&lt;/span&gt; column. It should say &lt;span style=&quot;font-family: courier;&quot;&gt;Completed&lt;/span&gt;. &lt;u&gt;If it says &lt;span style=&quot;font-family: courier;&quot;&gt;InProgress&lt;/span&gt; or &lt;span style=&quot;font-family: courier;&quot;&gt;Error&lt;/span&gt;, the Operator is struggling to configure the cluster.&lt;/u&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;4. Check the Backup (Safety Net)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Since you saw clickhouse-backup pods earlier, verify that the last backup actually succeeded. This is your &quot;point of no return&quot; check before the upgrade.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kubectl logs -n clickhouse -l job-name=clickhouse-backup-cron-&amp;lt;TIMESTAMP&amp;gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(Replace &amp;lt;TIMESTAMP&amp;gt; with one of the strings from your previous get all output, e.g., 29543400).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Look for: &lt;span style=&quot;font-family: courier;&quot;&gt;Done&lt;/span&gt;, &lt;span style=&quot;font-family: courier;&quot;&gt;Success&lt;/span&gt;, or &lt;span style=&quot;font-family: courier;&quot;&gt;Upload finished&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;5. Check the Status of All Replicas&amp;nbsp;&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To be absolutely sure the cluster is &quot;Green&quot; before you start the EKS upgrade, run this to check the status of all replicas in the cluster:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% kubectl exec -it chi-clickhouse-ch-0-0-0 -n clickhouse -- clickhouse-client --user USER --password PASS --query &quot;SELECT replica_path, is_leader, is_readonly, future_parts FROM system.replicas&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;is_readonly&lt;/span&gt;: Should be 0. If it&#39;s 1, the node can&#39;t write data (usually a Zookeeper issue).&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;is_leader&lt;/span&gt;: One of your replicas should be 1.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Summary Checklist&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;b&gt;Test&amp;nbsp; &amp;nbsp; &amp;nbsp; Command Goal&amp;nbsp; &amp;nbsp; &amp;nbsp;Good Result&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;Ping&amp;nbsp; &amp;nbsp; &amp;nbsp; SELECT&amp;nbsp; 1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;Uptime&amp;nbsp; &amp;nbsp; SELECT uptime()&amp;nbsp; &amp;gt;0&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;Storage&amp;nbsp; &amp;nbsp;system.disks&amp;nbsp; &amp;nbsp; &amp;nbsp;Free space &amp;gt; 10%&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;Operator&amp;nbsp; kubectl get chi&amp;nbsp; Completed&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Resources:&lt;/h2&gt;&lt;div&gt;&lt;a href=&quot;https://altinity.com/&quot;&gt;Altinity | Run Open Source ClickHouse® Better&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/1710786838978241612/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/1710786838978241612' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/1710786838978241612'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/1710786838978241612'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/03/how-to-install-clickhouse-in-aws-eks.html' title='How to install Clickhouse in AWS EKS cluster via Altinity Helm charts and Terraform'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIoJUC3ruc8P4B4sQhb-4Uzyxm5MDkD-Lc_s7bTOQZc2gkcS2jJcCof0St5glwjSviWGw1TjWZ1xIQfHPkNupq9vNTfdifpBSzDY1ZYjcKRku5SgmV_flV6OxkQ7OHIxus0ME748BxHjdhyphenhyphenQK2xDewGE2xP9WEcHCVZ1g8dDFHDCyH8XhpaEMg4Rk_E70/s72-w640-h462-c/Screenshot%202026-03-05%20at%2011.46.05.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-7356867261205328947</id><published>2026-03-05T00:46:00.007+00:00</published><updated>2026-05-14T11:05:25.246+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ArgoCD"/><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><category scheme="http://www.blogger.com/atom/ns#" term="GitOps"/><category scheme="http://www.blogger.com/atom/ns#" term="Kubernetes"/><title type='text'>Introduction to ArgoCD</title><content type='html'>&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh57Cb8KVuMGmR6-zI6g4vdXhvMvMb5a_oTCHcJf8JMoiR_EIceQ481St7I0upE-Ml-SQWSbyv0ZW5L4a8t-A-BqONVBw0Cvqrk71SDL75lDEmapvdGCq7d41rF9BG9gfbCDFwZjQihMvFKLzCyEwnYPX7f5Pd9-2sGWVT7tAgIUa_zVrTMjXnQr3Ndb2Y/s600/argocd.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;600&quot; data-original-width=&quot;600&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh57Cb8KVuMGmR6-zI6g4vdXhvMvMb5a_oTCHcJf8JMoiR_EIceQ481St7I0upE-Ml-SQWSbyv0ZW5L4a8t-A-BqONVBw0Cvqrk71SDL75lDEmapvdGCq7d41rF9BG9gfbCDFwZjQihMvFKLzCyEwnYPX7f5Pd9-2sGWVT7tAgIUa_zVrTMjXnQr3Ndb2Y/w640-h640/argocd.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;a href=&quot;https://argo-cd.readthedocs.io/en/stable/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;ArgoCD&lt;/a&gt; is a tool for deploying applications in Kubernetes cluster following the GitOps principles.&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;Argo CD is a declarative, GitOps-based continuous delivery (CD) tool designed specifically for Kubernetes. It acts as a controller that monitors running applications, compares their &lt;u&gt;live state&lt;/u&gt; to the &lt;u&gt;desired state defined in a Git repository&lt;/u&gt;, and automatically &lt;u&gt;syncs&lt;/u&gt; them to ensure consistency.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Key Aspects of an Argo CD Application:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;GitOps Source of Truth&lt;/b&gt;: Git repositories hold the desired state (manifests, Helm charts, Kustomize configs), which Argo CD pulls to apply to clusters.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Automated Synchronization&lt;/b&gt;: It automatically detects &quot;&lt;b&gt;OutOfSync&lt;/b&gt;&quot; applications—where the live cluster state differs from Git—and can automatically or manually sync them to match.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Continuous Monitoring&lt;/b&gt;: It acts as a Kubernetes controller that continuously monitors applications.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Visualization &amp;amp; Management&lt;/b&gt;: It provides a web UI to visualize application structure, monitor status, and manage rollbacks.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Key Capabilities&lt;/b&gt;: Supports automated deployment, drift detection, and easy rollbacks.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Argo CD is often used to ensure that the actual state of a Kubernetes cluster matches the configuration stored in a Git repository, making the deployment process more reliable and transparent.&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;ArgoCD GitOps flow:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Commit and push infra code changes (Terraform, Helm values etc) to the &lt;b&gt;main&lt;/b&gt; branch of your GitHub repository.&lt;/li&gt;&lt;li&gt;ArgoCD Sync:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Manual: Log in to our ArgoCD Dashboard and click the &quot;Sync&quot; or &quot;Refresh&quot; button on the psmdb-default-sharded application.&lt;/li&gt;&lt;li&gt;Automatic: If &quot;Self-Heal&quot; or &quot;Auto-Sync&quot; is enabled, ArgoCD will detect the Git change within ~3 minutes and apply it to the cluster automatically.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Monitor the Operator: Once ArgoCD syncs, infra will get changed e.g. operators will see the updated custom resources and then trigger the further actions.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Installation&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Installing ArgoCD in a Kubernetes cluster is primarily done using manifests or Helm charts. The most common and recommended approach for beginners is using the Official Argo CD Manifests.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Prerequisites:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;A running Kubernetes cluster (v1.22 or later).&lt;/li&gt;&lt;li&gt;kubectl command-line tool installed and configured to your cluster.&lt;/li&gt;&lt;li&gt;At least 2GB of available memory in your cluster.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Applications&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;ArgoCD defines custom Kubernetes objects like&amp;nbsp;&lt;span style=&quot;font-family: courier;&quot;&gt;Application&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;font-family: courier;&quot;&gt;AppProject&lt;/span&gt;, settings...which can be defined declaratively using Kubernetes manifests and deployed via&amp;nbsp;&lt;span style=&quot;font-family: courier;&quot;&gt;kubectl apply&lt;/span&gt;&amp;nbsp;to the ArgoCD namespace which is&amp;nbsp;&lt;span style=&quot;font-family: courier;&quot;&gt;argocd&lt;/span&gt;&amp;nbsp;by default.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To check ArgoCD applications:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% kubectl get applications -A&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;NAMESPACE&amp;nbsp; &amp;nbsp;NAME&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; SYNC STATUS&amp;nbsp; &amp;nbsp;HEALTH STATUS&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;argocd&amp;nbsp; &amp;nbsp; &amp;nbsp; my-app&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Synced&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Progressing&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Dashboard&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;If you don&#39;t know the url of the ArgoCD dashboard, find the IP of the ArgoCD server and port-forward it:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% kubectl get svc argocd-server -n argocd&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;NAME&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; TYPE&amp;nbsp; &amp;nbsp; &amp;nbsp; CLUSTER-IP&amp;nbsp; &amp;nbsp; EXTERNAL-IP PORT(S)&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AGE&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;argocd-server ClusterIP 172.21.103.127 &amp;lt;none&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;80/TCP,443/TCP 1d&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;By default, ArgoCD includes a built-in &lt;span style=&quot;font-family: courier;&quot;&gt;admin&lt;/span&gt; user with full super-user access. For better security practices, it is recommended that you use the admin account only for the initial configuration, then disable it once all required users have been added.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For this example, we can stick to this default &lt;span style=&quot;font-family: courier;&quot;&gt;admin&lt;/span&gt; user. Its password can be obtain via this command:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% kubectl get secret \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;argocd-initial-admin-secret \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;-n argocd \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;-o jsonpath=&quot;{.data.password}&quot; \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;| base64 -d&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Port forwarding:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% kubectl port-forward svc/argocd-server -n argocd 8080:443&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Forwarding from 127.0.0.1:8080 -&amp;gt; 8080&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Forwarding from [::1]:8080 -&amp;gt; 8080&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Handling connection for 8080&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Handling connection for 8080&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Handling connection for 8080&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Handling connection for 8080&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Handling connection for 8080&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Handling connection for 8080&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We can now open the address &lt;span style=&quot;font-family: courier;&quot;&gt;http://localhost:8080/&lt;/span&gt; in the browser to get the ArgoCD dashboard and log in with credentials above.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If there are no application registered with ArgoCD, we will see something like this:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7c2Z_irXgj2-B9W5RfTT1E0BthgIn3pxU2JLIxFkWVCJay_jI9M7ZksCd9cyTvP6xTAltDuQ1cSCFRtkFK1_5G-bL1rm83fZiOk2qGWJoXsmbinlt1w8milOwGvmJxrVnotDIPdDnoFoD_nEQqpPcltotUvFzW4Wpb3m9f2f3ejAhsHAq7WE4e-HJ6LY/s1920/Screenshot%202026-03-04%20at%2018.13.28.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;557&quot; data-original-width=&quot;1920&quot; height=&quot;186&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7c2Z_irXgj2-B9W5RfTT1E0BthgIn3pxU2JLIxFkWVCJay_jI9M7ZksCd9cyTvP6xTAltDuQ1cSCFRtkFK1_5G-bL1rm83fZiOk2qGWJoXsmbinlt1w8milOwGvmJxrVnotDIPdDnoFoD_nEQqpPcltotUvFzW4Wpb3m9f2f3ejAhsHAq7WE4e-HJ6LY/w640-h186/Screenshot%202026-03-04%20at%2018.13.28.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;application.yaml vs applicationset.yaml&lt;/h1&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In the world of Argo CD and Kubernetes GitOps, these two files represent different levels of automation.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;1. application.yaml&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;An &lt;b&gt;Application&lt;/b&gt; is the basic unit of Argo CD. This file defines a single link between a specific Git repository (the source) and a specific Kubernetes cluster/namespace (the destination).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;The Goal: To tell Argo CD: &quot;Take the code from this folder and make sure it looks like that in my cluster.&quot;&lt;/li&gt;&lt;li&gt;Key Components:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Project&lt;/b&gt;: The logical group it belongs to.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Source&lt;/b&gt;:&amp;nbsp;Argo CD needs three pieces of information to find our files:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;repoURL&lt;/span&gt;: Git URL.&amp;nbsp;Which &quot;building&quot; (repository) do I go to?&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;targetRevision&lt;/span&gt;: revision (branch/tag),&amp;nbsp;Which &quot;floor&quot; (branch/tag/commit) am I looking at?&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;path&lt;/span&gt; (mandatory): path to the manifests.&amp;nbsp;Which &quot;room&quot; (folder) contains the manifests?&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;b&gt;Destination&lt;/b&gt;: The target cluster URL and namespace.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Sync Policy&lt;/b&gt;: Whether to automatically sync changes or require a manual button press.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Example Snippet:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;apiVersion: argoproj.io/v1alpha1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kind: Application&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name: guestbook-app&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; project: default&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; source:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; repoURL: https://github.com/argoproj/argocd-example-apps.git&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;targetRevision: main&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; path: guestbook&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; destination:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; server: https://kubernetes.default.svc&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; namespace: default&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;div&gt;&amp;nbsp; syncPolicy:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; automated:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; selfHeal: true&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; prune: true&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Argo CD is completely &quot;tool-agnostic.&quot; It doesn&#39;t care if you use Helm, Kustomize, or just a folder full of .yaml files; it just needs to know where they are.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;How Argo CD Decides&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When Argo CD looks at the path you provided, it follows this logic:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Does it see &lt;span style=&quot;font-family: courier;&quot;&gt;Chart.yaml&lt;/span&gt;? -&amp;gt; It uses Helm.&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Argo CD uses &lt;span style=&quot;font-family: courier;&quot;&gt;values.yaml&lt;/span&gt; by default if it detects that the directory specified in the &lt;span style=&quot;font-family: courier;&quot;&gt;path&lt;/span&gt; is a Helm chart.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Does it see &lt;span style=&quot;font-family: courier;&quot;&gt;kustomization.yaml&lt;/span&gt;? -&amp;gt; It uses Kustomize.&lt;/li&gt;&lt;li&gt;Does it see only &lt;span style=&quot;font-family: courier;&quot;&gt;.yaml&lt;/span&gt; or &lt;span style=&quot;font-family: courier;&quot;&gt;.json &lt;/span&gt;files? -&amp;gt; It uses Plain Manifests.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;/span&gt;&lt;div&gt;Custom Helm Charts&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;At an absolute minimum, a Helm chart requires a directory containing these three things:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;my-app/&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # The &quot;path&quot; referenced in Argo CD&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;├── Chart.yaml&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;# Metadata about the chart (Required)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;├── values.yaml&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Default configuration variables (Required)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;└── templates/&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;# The folder for your Kubernetes manifests (Required)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; └── deployment.yaml # At least one manifest to actually deploy something&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;&lt;!--more--&gt;&lt;/span&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;2. applicationset.yaml&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The &lt;b&gt;ApplicationSet&lt;/b&gt; is a controller that acts as a &lt;u&gt;factory for &lt;b&gt;Applications&lt;/b&gt;&lt;/u&gt;. Instead of manually creating 50 &lt;span style=&quot;font-family: courier;&quot;&gt;application.yaml&lt;/span&gt; files for 50 different microservices or 10 different clusters, you write one ApplicationSet.&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;The Goal: To automate the creation, update, and deletion of multiple Argo CD &lt;b&gt;Applications&lt;/b&gt; at scale.&lt;/li&gt;&lt;li&gt;How it works: It uses &lt;b&gt;Generators&lt;/b&gt; to decide how many Applications to create.&lt;/li&gt;&lt;ul&gt;&lt;li&gt;List Generator: Hardcode a list of clusters or environments.&lt;/li&gt;&lt;li&gt;Git Generator: Automatically create an App for every folder found in a Git repo.&lt;/li&gt;&lt;li&gt;Cluster Generator: Automatically deploy an App to every cluster registered in Argo CD.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Key Advantage: It follows the &quot;DRY&quot; (Don&#39;t Repeat Yourself) principle. If you add a new cluster to your fleet, the ApplicationSet detects it and automatically deploys your apps there.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Example Snippet:&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;apiVersion: argoproj.io/v1alpha1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kind: ApplicationSet&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name: guestbook-factory&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; generators:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; - list:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; elements:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - cluster: engineering-dev&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - cluster: engineering-prod&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; template: &lt;u&gt;# This looks exactly like a standard &lt;b&gt;Application&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; name: &#39;{{cluster}}-guestbook&#39;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; project: default&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; source:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; repoURL: https://github.com/argoproj/argocd-example-apps.git&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; path: guestbook&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; destination:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; server: https://{{cluster}}-api.com&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; namespace: guestbook&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Example with Pull Request Generator&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Using the &lt;b&gt;Pull Request Generator&lt;/b&gt; is the &quot;gold standard&quot; for enabling &lt;b&gt;ephemeral (preview) environments&lt;/b&gt;. It allows Argo CD to &lt;u&gt;watch your GitHub repository for open PRs and automatically spin up a dedicated version of your app for testing.&lt;/u&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The following parameters are &lt;b&gt;dynamic variables&lt;/b&gt; provided by the generator based on the metadata of the PR:&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;{{ number }}&amp;nbsp;-&amp;nbsp;PR number from GitHub API&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Role: Unique Identifier.&lt;/li&gt;&lt;li&gt;Usage: Since &lt;u&gt;PR numbers are unique and immutable in GitHub&lt;/u&gt;, this is &lt;u&gt;the safest way to name your Application and Namespace&lt;/u&gt;.&lt;/li&gt;&lt;li&gt;Result: Prevents naming collisions when multiple developers are testing different features simultaneously.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;{{ branch }} -&amp;nbsp;Head branch name of the PR&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Role: Git Reference.&lt;/li&gt;&lt;li&gt;Usage: This tells Argo CD exactly which commit to look at. Without this, Argo CD would try to deploy from &lt;span style=&quot;font-family: courier;&quot;&gt;main&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;Result: Your ephemeral environment stays in sync with every push to that specific feature branch.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;{{ branch_slug }} -&amp;nbsp;URL-safe version of branch name&amp;nbsp;&lt;/li&gt;&lt;li&gt;{{ head_sha }} -&amp;nbsp;&amp;nbsp;Commit SHA at the tip of the branch&lt;/li&gt;&lt;li&gt;{{ labels }} -&amp;nbsp;&amp;nbsp;List of all labels on the PR e.g.&amp;nbsp;[&quot;preview&quot;, &quot;staging&quot;]&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Role: Filter &amp;amp; Logic.&lt;/li&gt;&lt;li&gt;Usage: In the example above, we use the filters block. The generator will ignore any PR that doesn&#39;t have the feature-test-deployment label.&lt;/li&gt;&lt;li&gt;Advanced Tip: You can also use labels in the template. For example, if you have labels like size:large or db:postgres, you could map those to Helm values to provision different resources for that specific PR.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;The Lifecycle Workflow&lt;/h4&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Developer opens a PR in GitHub.&lt;/li&gt;&lt;li&gt;Developer adds the label feature-test-deployment.&lt;/li&gt;&lt;li&gt;Argo CD detects the label, triggers the ApplicationSet, and creates a new Application named my-app-pr-42.&lt;/li&gt;&lt;li&gt;Argo CD creates the namespace preview-pr-42 and deploys the code from the feature branch.&lt;/li&gt;&lt;li&gt;Developer closes the PR or removes the label.&lt;/li&gt;&lt;li&gt;Argo CD automatically deletes the Application and cleans up the resources (garbage collection).&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The ApplicationSet Configuration&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This ApplicationSet will scan your repository, filter for the specific label, and then use the PR details to name the application and target the correct branch.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;apiVersion: argoproj.io/v1alpha1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kind: ApplicationSet&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name: ephemeral-preview-apps&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; namespace: argocd&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; generators:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; - pullRequest:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; github:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; owner: my-organization&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; repo: my-app-repo&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Use a secret for your GitHub Token to avoid rate limits&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; tokenRef:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; secretName: github-token&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; key: token&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # This filters the PRs based on the label&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; filters:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - labels:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - feature-test-deployment&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; requeueAfterSeconds: 60&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; template:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; # Use .number to ensure a unique app name per PR (e.g., my-app-pr-42)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; name: &#39;my-app-pr-{{number}}&#39;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; project: default&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; source:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; repoURL: https://github.com/my-organization/my-app-repo.git&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Use .branch to pull code from the specific feature branch&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; targetRevision: &#39;{{branch}}&#39;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; path: kubernetes/manifests&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; helm:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; parameters:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; # You can pass the PR number or labels into your app&#39;s code/config&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - name: &quot;envName&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; value: &quot;pr-{{number}}&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; destination:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; server: https://kubernetes.default.svc&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Create a unique namespace for the ephemeral environment&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; namespace: &#39;preview-pr-{{number}}&#39;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; syncPolicy:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; automated:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; prune: true&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; selfHeal: true&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; syncOptions:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - CreateNamespace=true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;The &lt;span style=&quot;font-family: courier;&quot;&gt;requeueAfterSeconds: 60&lt;/span&gt; means ArgoCD polls GitHub every 60 seconds - when a PR is opened with the &lt;span style=&quot;font-family: courier;&quot;&gt;feature-test-deployment&lt;/span&gt; label, within a minute ArgoCD picks it up, injects these variables into the template, and creates the child &lt;b&gt;Application&lt;/b&gt;. When the PR is closed or the label is removed, ArgoCD deletes the child Application (and &lt;span style=&quot;font-family: courier;&quot;&gt;prune: true&lt;/span&gt; tears down the K8s resources).&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Go template engine&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;By enabling the Go template engine (&lt;span style=&quot;font-family: courier;&quot;&gt;goTemplate: true&lt;/span&gt;), Argo CD switches from simple string replacement to a full Go templating context. In this mode, all parameters from the generator are nested under a root object, meaning you must use the leading dot to access them.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here is the rewritten example using &lt;span style=&quot;font-family: courier;&quot;&gt;goTemplate: true&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;apiVersion: argoproj.io/v1alpha1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kind: ApplicationSet&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name: ephemeral-preview-apps&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; # This enables the standard Go template engine&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; goTemplate: true&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; goTemplateOptions: [&quot;missingkey=error&quot;]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; generators:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; - pullRequest:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; github:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; owner: my-organization&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; repo: my-app-repo&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; tokenRef:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; secretName: github-token&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; key: token&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; filters:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - labels:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - feature-test-deployment&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; template:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; # Now using the leading dot because goTemplate is true&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; name: &#39;my-app-pr-{{.number}}&#39;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; project: default&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; source:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; repoURL: https://github.com/my-organization/my-app-repo.git&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; targetRevision: &#39;{{.branch}}&#39;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; path: kubernetes/manifests&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; helm:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; parameters:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - name: &quot;envName&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; value: &quot;pr-{{.number}}&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # goTemplate allows us to use range to iterate over labels&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - name: &quot;appliedLabels&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; value: &quot;{{range .labels}}{{.}},{{end}}&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; destination:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; server: https://kubernetes.default.svc&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; namespace: &#39;preview-pr-{{.number}}&#39;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; syncPolicy:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; automated:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; prune: true&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; selfHeal: true&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; syncOptions:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - CreateNamespace=true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Key Changes with goTemplate: true&lt;/div&gt;&lt;div&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;The Dot Prefix: Since the parameters are now passed as a data structure to the Go template engine, you access them as fields of the root object: {{.number}}, {{.branch}}, and {{.labels}}.&lt;/li&gt;&lt;li&gt;Missing Key Error: With goTemplateOptions: [&quot;missingkey=error&quot;], if you make a typo (e.g., {{.numbr}}), the ApplicationSet controller will explicitly error out rather than just rendering an empty string. This is much safer for production.&lt;/li&gt;&lt;li&gt;Iteration/Logic: You can now use standard Go template functions. For instance, in the example above, I used a range loop to iterate through the .labels list:&lt;/li&gt;&lt;/ol&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;{{range .labels}}{{.}},{{end}} loops through each label and prints it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;Why use this over the default?&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;While it requires the extra . syntax, &lt;span style=&quot;font-family: courier;&quot;&gt;goTemplate: true&lt;/span&gt; is much more powerful. It &lt;u&gt;allows you to use if/else logic&lt;/u&gt; (e.g., &quot;if label is &#39;large&#39;, request more CPU&quot;) and complex string manipulations that the default &quot;fast replacement&quot; engine cannot handle.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you omit the dot while &lt;span style=&quot;font-family: courier;&quot;&gt;goTemplate: true&lt;/span&gt; is active, the template will fail to render because it will look for a global variable instead of a field in the provided data object.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;u&gt;Using &lt;span style=&quot;font-family: courier;&quot;&gt;goTemplate: true&lt;/span&gt; opens up a world of &quot;smart&quot; deployments where your PR labels can act as configuration switches&lt;/u&gt;. This prevents you from needing a separate ApplicationSet for every minor variation.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here is how you can use conditional logic to adjust resources or features based on the labels found on a PR.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Example: Advanced Conditional ApplicationSet&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In this scenario, if a PR has the label &lt;span style=&quot;font-family: courier;&quot;&gt;env:large&lt;/span&gt;, we increase the resource limits. If it has &lt;span style=&quot;font-family: courier;&quot;&gt;feature:postgres&lt;/span&gt;, we enable a database flag.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;apiVersion: argoproj.io/v1alpha1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kind: ApplicationSet&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name: smart-ephemeral-apps&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; goTemplate: true&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; goTemplateOptions: [&quot;missingkey=error&quot;]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; generators:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; - pullRequest:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; github:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; owner: my-org&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; repo: my-repo&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; tokenRef:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; secretName: github-token&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; key: token&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; filters:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - labels:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - feature-test-deployment&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; template:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; name: &#39;app-pr-{{.number}}&#39;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; project: default&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; source:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; repoURL: https://github.com/my-org/my-repo.git&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; targetRevision: &#39;{{.branch}}&#39;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; path: charts/my-app&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; helm:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; values: |&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; replicaCount: {{ if (contains &quot;env:high-availability&quot; (join &quot;,&quot; .labels)) }}3{{ else }}1{{ end }}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; resources:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {{- if (contains &quot;size:large&quot; (join &quot;,&quot; .labels)) }}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; limits:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; cpu: &quot;1000m&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; memory: &quot;2Gi&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {{- else }}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; limits:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; cpu: &quot;200m&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; memory: &quot;512Mi&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {{- end }}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; experimentalFeatures:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; enabled: {{ contains &quot;feature:beta&quot; (join &quot;,&quot; .labels) }}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; destination:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; server: https://kubernetes.default.svc&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; namespace: &#39;pr-{{.number}}&#39;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;Pro-Tips for this Setup&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;The &quot;Contains&quot; Trick&lt;/b&gt;: In Go templating, searching a list directly can be clunky. By using (join &quot;,&quot; .labels), we turn the list into a single string (e.g., &quot;feature-test-deployment,size:large&quot;) and then use contains to check for our specific trigger labels.&lt;/li&gt;&lt;li&gt;&lt;b&gt;The Root App Advantage&lt;/b&gt;: Because this logic is inside your &lt;span style=&quot;font-family: courier;&quot;&gt;infrastructure/&lt;/span&gt; folder (managed by your Root App), you can test changes to this logic on a branch. You can actually have a &lt;b&gt;&quot;Development Root App&quot;&lt;/b&gt; that points to your branch to see if your new if/else logic works before merging it to main.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Cleanup&lt;/b&gt;: When you merge the PR and delete the branch in GitHub, the PR Generator sees the PR is closed. It removes the generated Application, and Argo CD&#39;s prune logic deletes the namespace and all associated resources automatically.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Summary of the Flow&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;Management&lt;/b&gt;: The Root App (application.yaml) monitors the repo for automation changes.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Automation&lt;/b&gt;: The ApplicationSet (applicationset.yaml) monitors GitHub for new PRs with specific labels.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Deployment&lt;/b&gt;: The Ephemeral App (the child application.yaml) is created with specific CPU/RAM settings dictated by those PR labels.&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;How do they work together?&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;In many production GitOps setups, they must exist together to create a functional hierarchy. In Argo CD, this is often referred to as the &lt;b&gt;&quot;App of Apps&quot; pattern&lt;/b&gt; or a &lt;b&gt;&quot;Management Repo&quot; structure&lt;/b&gt;.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;How They Interact&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Think of the relationship as Infrastructure vs. Implementation:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;The ApplicationSet (applicationset.yaml)&lt;/b&gt;: Acts as the automation engine. It lives in your management folder and its job is to watch the repository and &quot;spawn&quot; Applications.&lt;/li&gt;&lt;li&gt;&lt;b&gt;The Application (application.yaml)&lt;/b&gt;: These are the individual instances created by the ApplicationSet. You might also have a manual application.yaml for a unique service that doesn&#39;t fit the &quot;factory&quot; mold of the ApplicationSet.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;Recommended Repository Structure&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To keep things clean, teams usually organize their repository like this:&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;my-gitops-repo/&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;├── bootstrap/&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;│&amp;nbsp; &amp;nbsp;├── root-app.yaml&amp;nbsp; &lt;span style=&quot;font-size: x-small;&quot;&gt;# A manual Application that points to this folder&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;│&amp;nbsp; &amp;nbsp;└── cluster-addons-set.yaml&amp;nbsp;&lt;span style=&quot;font-size: x-small;&quot;&gt;# An ApplicationSet for things like ingress, monitoring&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;├── projects/&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;│&amp;nbsp; &amp;nbsp;└── microservices-set.yaml&amp;nbsp; &lt;span style=&quot;font-size: x-small;&quot;&gt;# Your PR Generator ApplicationSet&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;├── apps/&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;│&amp;nbsp; &amp;nbsp;├── my-unique-legacy-app/&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;│&amp;nbsp; &amp;nbsp;│&amp;nbsp; &amp;nbsp;└── application.yaml&amp;nbsp; &amp;nbsp; &lt;span style=&quot;font-size: x-small;&quot;&gt;# A one-off manual Application&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;│&amp;nbsp; &amp;nbsp;└── templates/&amp;nbsp; &amp;nbsp; &lt;span style=&quot;font-size: x-small;&quot;&gt;# The base manifests the ApplicationSet points to&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;├── deployment.yaml&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;│&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;└── service.yaml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;Common Scenarios for Co-existence&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;1. The &quot;Bootstrap&quot; Application&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You often have a single, manually created application.yaml (sometimes called the Root App) whose only job is to deploy the applicationset.yaml.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Why? This allows you to manage your automation via GitOps. If you update the ApplicationSet logic in Git, the Root App syncs it, and the factory settings update automatically.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;2. The &quot;Hybrid&quot; Approach&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You might use an ApplicationSet to handle 50 identical microservices across 3 clusters, but keep a standard Application for a third-party tool (like a database or a legacy monolith) that requires very specific, manual configuration that doesn&#39;t fit a template.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Important Collision Warning ⚠️&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;While they can exist together, you should avoid a &quot;Circular Dependency&quot; or &quot;Ownership Fight&quot;:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Don&#39;t have an ApplicationSet generate an Application with the exact same name as a manually created application.yaml in the same namespace.&lt;/li&gt;&lt;li&gt;Management: If an ApplicationSet creates an app, it &quot;owns&quot; it. If you try to manually edit that child app in the Argo CD UI, the ApplicationSet controller will immediately revert your changes to match its template.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Summary: They are complementary tools. Use application.yaml for specific, static deployments and applicationset.yaml for templated, dynamic, or multi-environment deployments. Using them together is the standard way to achieve full &quot;Cluster as Code.&quot;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;The &quot;Root App&quot; (or App-of-Apps) pattern is the ultimate way to manage your Argo CD instance. It allows you to manage your automation through the same GitOps workflow as your code.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;The &quot;Root&quot; Application Structure&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The Root App is a standard application.yaml that points to a folder in your Git repo containing your ApplicationSet files. Once you apply this one file manually, Argo CD takes over and manages all your &quot;factories&quot; automatically.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So there are two separate layers here that do different jobs, and it&#39;s easy to conflate them.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;1.&amp;nbsp;Layer 1 — Bootstrap Application (The Root Application) (root-app.yaml)&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is the only file you apply with &lt;span style=&quot;font-family: courier;&quot;&gt;kubectl apply -f&lt;/span&gt;. It tells Argo CD to watch the &lt;span style=&quot;font-family: courier;&quot;&gt;infrastructure/&lt;/span&gt; directory for any &lt;b&gt;ApplicationSets&lt;/b&gt; or other &lt;b&gt;Applications&lt;/b&gt;. It manages the ArgoCD-level resources: ApplicationSet, other Applications, ExternalSecrets.... Its only job is to keep the e.g. ApplicationSet definition in sync with the repo. This is what the targetRevision in root-app.yaml controls.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;apiVersion: argoproj.io/v1alpha1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kind: &lt;b&gt;Application&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;metadata:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name: root-management-app&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; namespace: argocd&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;spec:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; project: default&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; source:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; repoURL: https://github.com/your-org/gitops-control-plane.git&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;b&gt;targetRevision&lt;/b&gt;: HEAD&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; path: &lt;b&gt;infrastructure&lt;/b&gt;&amp;nbsp; # Folder where your ApplicationSets live&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; destination:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; server: https://kubernetes.default.svc&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; namespace: argocd&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; syncPolicy:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; automated:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; prune: true&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; selfHeal: true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;2. Layer 2 — ApplicationSet (pr-generator-set.yaml)&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;br /&gt;This is the pull-request generator. It watches GitHub for open PRs with the preview label and creates a child &lt;b&gt;Application&lt;/b&gt; per PR. Each child Application it creates points at {{ .branch }} — the PR&#39;s own&lt;br /&gt;branch:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;targetRevision: &quot;{{ .branch }}&quot;&lt;br /&gt;path: deploy/helm-chart&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;The Directory Layout&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To make this work seamlessly, organize your repository so the Root App can find its &quot;children&quot; without getting confused.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;gitops-control-plane/&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;├── root-app.yaml&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span style=&quot;font-size: x-small;&quot;&gt;# Managed manually (once)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;└── infrastructure/&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span style=&quot;font-size: x-small;&quot;&gt;# Managed by Root App&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; ├── pr-generator-set.yaml&amp;nbsp; &amp;nbsp;&lt;span style=&quot;font-size: x-small;&quot;&gt;# Your PR Generator with goTemplate: true&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; ├── production-cluster-set.yaml&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; └── global-monitoring-app.yaml &lt;span style=&quot;font-size: x-small;&quot;&gt;# A standard Application for Prometheus&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Why this is powerful:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Self-Healing Infrastructure: If someone accidentally deletes your ApplicationSet from the cluster, the Root App will see the discrepancy and recreate it instantly.&lt;/li&gt;&lt;li&gt;Version Controlled Automation: If you want to update your goTemplate logic or change a github-token reference, you just submit a PR to the infrastructure/ folder. Once merged, the Root App updates the ApplicationSet, which then updates all your ephemeral environments.&lt;/li&gt;&lt;li&gt;Single Source of Truth: You can look at one Git folder and see exactly what automation logic is governing your entire cluster fleet.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;So the two layers are independent:&lt;/div&gt;&lt;div&gt;   &lt;br /&gt;  root-app.yaml (tracks main)                                                                                                                                                                            &lt;br /&gt;    └─ manages: ApplicationSet (in cluster)&lt;br /&gt;                  &lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;└─ polls GitHub PRs with specified label                                                                                                                                                  &lt;br /&gt;                       &lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;├─ PR #1 → Application → branch: feat1-branch → deploy/helm-chart&lt;br /&gt;                       &lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;└─ PR #2 → Application → branch: feat2-branch → deploy/helm-chart                                                                                                             &lt;br /&gt;                  &lt;br /&gt;  Changing root-app.yaml&#39;s targetRevision to main only affects whether the ApplicationSet definition itself stays in sync with main. It has zero effect on how individual PR previews are deployed —     &lt;br /&gt;  those are handled entirely by the generator using each PR&#39;s own branch.&lt;br /&gt;                                                                                                                                                                                                            &lt;br /&gt;  The hardcoded branch in root-app.yaml is only necessary during development of this feature branch so that iterative changes to applicationset.yaml were picked up live. Once merged to main, main is  &lt;br /&gt;  the correct target.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One Final Pro-Tip for PR Generators&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When using the PR Generator inside a Root App structure, ensure your github-token Secret is already created in the argocd namespace. The ApplicationSet needs that token to &quot;talk&quot; to the GitHub API to see which PRs have the feature-test-deployment label.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Summary Comparison&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Feature&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Application (.yaml)&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;ApplicationSet (.yaml)&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;----------&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; -------------------------&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;-----------------------------&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Scope&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Manages one app in one environment.&amp;nbsp; &amp;nbsp; Manages many apps across many environments.&lt;/div&gt;&lt;div&gt;Manual Effort&amp;nbsp; High (must create a file for every app).&amp;nbsp; &amp;nbsp;Low (one template handles everything).&lt;/div&gt;&lt;div&gt;Use Case&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Simple setups or unique, one-off apps.&amp;nbsp; &amp;nbsp;Microservices, multi-tenant, or multi-cluster&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; environments.&lt;/div&gt;&lt;div&gt;Relationship&amp;nbsp; &amp;nbsp; The &quot;Child&quot; object.&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;The &quot;Parent&quot; (Factory) that creates children.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;---&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Resources:&lt;/h2&gt;&lt;div&gt;&lt;a href=&quot;https://argo-cd.readthedocs.io/en/stable/&quot;&gt;Argo CD - Declarative GitOps CD for Kubernetes&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://docs.aws.amazon.com/eks/latest/userguide/argocd.html&quot;&gt;Continuous Deployment with Argo CD - Amazon EKS&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/7356867261205328947/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/7356867261205328947' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/7356867261205328947'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/7356867261205328947'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/03/introduction-to-argocd.html' title='Introduction to ArgoCD'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh57Cb8KVuMGmR6-zI6g4vdXhvMvMb5a_oTCHcJf8JMoiR_EIceQ481St7I0upE-Ml-SQWSbyv0ZW5L4a8t-A-BqONVBw0Cvqrk71SDL75lDEmapvdGCq7d41rF9BG9gfbCDFwZjQihMvFKLzCyEwnYPX7f5Pd9-2sGWVT7tAgIUa_zVrTMjXnQr3Ndb2Y/s72-w640-h640-c/argocd.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-7241423173796574006</id><published>2026-02-26T15:42:00.001+00:00</published><updated>2026-02-26T15:47:42.490+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><category scheme="http://www.blogger.com/atom/ns#" term="kubectl"/><category scheme="http://www.blogger.com/atom/ns#" term="KubePug"/><category scheme="http://www.blogger.com/atom/ns#" term="Kubernetes"/><title type='text'>Introduction to KubePug (Kubernetes tool)</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkIR8lF1DIWDWeizFBBYSUqIzvoFP5rglXWGsybk_bh3byjh5cKFdy933jrItHUh0h2YW74461QtBPD7eQxRuYAvNUOJuP3AFyz3Jcqwanm1rbFBAezG0LvrVQtRIxpbGXyH0v8UnX6rh6bLBdH0hWCqEkyrXoct9v_jjiv_qlgSQQI1w2uGAHonLn8LA/s366/kubepug.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;262&quot; data-original-width=&quot;366&quot; height=&quot;458&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkIR8lF1DIWDWeizFBBYSUqIzvoFP5rglXWGsybk_bh3byjh5cKFdy933jrItHUh0h2YW74461QtBPD7eQxRuYAvNUOJuP3AFyz3Jcqwanm1rbFBAezG0LvrVQtRIxpbGXyH0v8UnX6rh6bLBdH0hWCqEkyrXoct9v_jjiv_qlgSQQI1w2uGAHonLn8LA/w640-h458/kubepug.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;What is KubePug?&lt;/h2&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;KubePug (Kubernetes PreUpGrade Checker) is an open-source kubectl plugin and CLI tool designed to identify deprecated or deleted APIs in your Kubernetes cluster or manifest files before you perform an upgrade.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Key Features&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;b&gt;Deprecation Detection&lt;/b&gt;: Scans your live cluster or static YAML manifests to find resources using APIs that are slated for removal in future Kubernetes versions.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Replacement Guidance&lt;/b&gt;: Not only flags outdated APIs but also suggests the recommended replacement API and specifies the exact version where the deprecation or deletion occurs.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Version Targeting&lt;/b&gt;: Allows you to specify a target Kubernetes version (e.g., v1.31) to validate your current resources against that specific future release.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Flexible Data Source&lt;/b&gt;: It automatically downloads a frequently updated API definition file (every 30 minutes) to stay current with the latest Kubernetes releases.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Why Use It?&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As Kubernetes evolves, APIs are moved from alpha/beta to stable (GA), and older versions are eventually removed. If you upgrade your cluster without updating your manifests, those resources will fail to deploy or operate. KubePug provides a &quot;pre-flight&quot; check to prevent these breaking changes from reaching production.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Installation &amp;amp; Usage&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can install KubePug via Krew (where it is listed under the name deprecations) or as a standalone binary.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Method&amp;nbsp;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Command&lt;/div&gt;&lt;div&gt;---------&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; -------------&lt;/div&gt;&lt;div&gt;Install via Krew&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;kubectl krew install deprecations&lt;/div&gt;&lt;div&gt;Scan Live Cluster&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;kubectl deprecations --k8s-version=v1.30&lt;/div&gt;&lt;div&gt;Scan Manifest File&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;kubepug --input-file=./my-manifest.yaml&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Installation via Krew&lt;/h3&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;kubectl krew install deprecations&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Updated the local copy of plugin index.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Installing plugin: deprecations&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Installed plugin: deprecations&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;| Use this plugin:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;| &lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;kubectl deprecations&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;| Documentation:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;| &lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;https://github.com/rikatz/kubepug&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;| Caveats:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;| \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;|&amp;nbsp; | * By default, deprecations finds deprecated object relative to the current kubernetes&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;|&amp;nbsp; | master branch. To target a different kubernetes release, use the --k8s-version&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;|&amp;nbsp; | argument.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;|&amp;nbsp; |&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;|&amp;nbsp; | * Deprecations needs permission to GET all objects in the Cluster&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;| /&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;/&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #ffa400; font-family: courier;&quot;&gt;WARNING: You installed plugin &quot;deprecations&quot; from the krew-index plugin repository.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #ffa400; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp;These plugins are not audited for security by the Krew maintainers.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #ffa400; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp;Run them at your own risk.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Execution&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Once installed, the plugin is invoked using &lt;span style=&quot;font-family: courier;&quot;&gt;kubectl deprecations&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Scan Current Cluster&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Check your live cluster for deprecated APIs against a specific target Kubernetes version:&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;%&amp;nbsp;&lt;/span&gt;&lt;b style=&quot;color: #38761d; font-family: courier;&quot;&gt;kubectl deprecations --k8s-version=v1.33&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;&lt;/b&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: red; font-family: courier;&quot;&gt;Error: failed to get apiservices: apiservices.apiregistration.k8s.io is forbidden: User &quot;sso:user&quot; cannot list resource &quot;apiservices&quot; in API group &quot;apiregistration.k8s.io&quot; at the cluster scope&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: red; font-family: courier;&quot;&gt;time=&quot;2026-02-26T14:20:19Z&quot; level=error msg=&quot;An error has occurred: failed to get apiservices: apiservices.apiregistration.k8s.io is forbidden: User \&quot;sso:user\&quot; cannot list resource \&quot;apiservices\&quot; in API group \&quot;apiregistration.k8s.io\&quot; at the cluster scope&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;KubePug requires running user to have &quot;list&quot; permissions on resource &quot;apiservices&quot; in API group &quot;apiregistration.k8s.io&quot; at the cluster scope as otherwise the above error will appear.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If required permissions are in place:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;kubectl deprecations --k8s-version=v1.33&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;No deprecated or deleted APIs found&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Kubepug validates the APIs using Kubernetes markers. To know what are the deprecated and deleted APIS it checks, please go to https://kubepug.xyz/status/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Scan Local Manifest Files&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Validate static YAML files before applying them to a cluster:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kubectl deprecations --input-file=./my-manifests/&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;View Results in Different Formats&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Output the findings in json or yaml for automated processing:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kubectl deprecations --format=json&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Check for Help and Flags&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;See all available configuration options, such as using a custom database file or setting error codes:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;kubectl deprecations --help&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Key Parameters&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;--k8s-version&lt;/span&gt;: The Kubernetes release you intend to upgrade to (defaults to the latest stable).&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;--error-on-deprecated&lt;/span&gt;: Forces the command to exit with an error code if deprecated APIs are found, which is useful for CI/CD pipelines.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;---&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/7241423173796574006/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/7241423173796574006' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/7241423173796574006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/7241423173796574006'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/02/introduction-to-kubepug-kubernetes-tool.html' title='Introduction to KubePug (Kubernetes tool)'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkIR8lF1DIWDWeizFBBYSUqIzvoFP5rglXWGsybk_bh3byjh5cKFdy933jrItHUh0h2YW74461QtBPD7eQxRuYAvNUOJuP3AFyz3Jcqwanm1rbFBAezG0LvrVQtRIxpbGXyH0v8UnX6rh6bLBdH0hWCqEkyrXoct9v_jjiv_qlgSQQI1w2uGAHonLn8LA/s72-w640-h458-c/kubepug.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-6942889768486125371</id><published>2026-02-26T14:15:00.008+00:00</published><updated>2026-02-26T14:15:55.195+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><category scheme="http://www.blogger.com/atom/ns#" term="Krew"/><category scheme="http://www.blogger.com/atom/ns#" term="kubectl"/><category scheme="http://www.blogger.com/atom/ns#" term="Kubernetes"/><title type='text'>Introduction to Krew (Kubernetes tool)</title><content type='html'>&lt;div style=&quot;text-align: left;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-8zz_xMb_zIJVWsT1O8qq_3uwCjifRGudwea3z99R_qnccY-s-QRiGG4nFPCbBdSHrnEPoFeHhJp40B66Hda-wmK7oX7HQf63BFuzkacRl4EthdYf0315E2ft-0URBpfUaD6M40KEI5OzOG2zeUaexS3PuLdaVfDb4wr4zjAYOlDWULomA2TGNXH9DcM/s1542/Screenshot%202026-02-26%20at%2014.13.13.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;542&quot; data-original-width=&quot;1542&quot; height=&quot;224&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-8zz_xMb_zIJVWsT1O8qq_3uwCjifRGudwea3z99R_qnccY-s-QRiGG4nFPCbBdSHrnEPoFeHhJp40B66Hda-wmK7oX7HQf63BFuzkacRl4EthdYf0315E2ft-0URBpfUaD6M40KEI5OzOG2zeUaexS3PuLdaVfDb4wr4zjAYOlDWULomA2TGNXH9DcM/w640-h224/Screenshot%202026-02-26%20at%2014.13.13.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;Krew is the official plugin manager for the kubectl command-line tool. Much like apt for Debian or Homebrew for macOS, it allows users to easily discover, install, and manage custom extensions that add new subcommands to Kubernetes.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Core Functionality&lt;/h2&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Discovery: Users can search a community-curated index of over 200 plugins designed for tasks like security auditing, resource visualization, and cluster management.&lt;/li&gt;&lt;li&gt;Lifecycle Management: It automates the process of installing, updating, and removing plugins across different operating systems (Linux, macOS, and Windows).&lt;/li&gt;&lt;li&gt;Unified Interface: Once a plugin is installed via Krew, it is invoked directly through kubectl (e.g., kubectl &amp;lt;plugin-name&amp;gt;).&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Installation&lt;/h2&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;MacOS example output:&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;b&gt;&amp;nbsp; set -x; cd &quot;$(mktemp -d)&quot; &amp;amp;&amp;amp;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;b&gt;&amp;nbsp; OS=&quot;$(uname | tr &#39;[:upper:]&#39; &#39;[:lower:]&#39;)&quot; &amp;amp;&amp;amp;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;b&gt;&amp;nbsp; ARCH=&quot;$(uname -m | sed -e &#39;s/x86_64/amd64/&#39; -e &#39;s/\(arm\)\(64\)\?.*/\1\2/&#39; -e &#39;s/aarch64$/arm64/&#39;)&quot; &amp;amp;&amp;amp;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;b&gt;&amp;nbsp; KREW=&quot;krew-${OS}_${ARCH}&quot; &amp;amp;&amp;amp;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;b&gt;&amp;nbsp; curl -fsSLO &quot;https://github.com/kubernetes-sigs/krew/releases/latest/download/${KREW}.tar.gz&quot; &amp;amp;&amp;amp;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;b&gt;&amp;nbsp; tar zxvf &quot;${KREW}.tar.gz&quot; &amp;amp;&amp;amp;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;b&gt;&amp;nbsp; ./&quot;${KREW}&quot; install krew&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;+-zsh:142&amp;gt; mktemp -d&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;+-zsh:142&amp;gt; cd /var/folders/8j/60m6_18j359_39ls0sr9ccvm0000gp/T/tmp.LKDSyQcO10&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;+-zsh:143&amp;gt; OS=+-zsh:143&amp;gt; uname&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;+-zsh:143&amp;gt; OS=+-zsh:143&amp;gt; tr &#39;[:upper:]&#39; &#39;[:lower:]&#39;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;+-zsh:143&amp;gt; OS=darwin&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;+-zsh:144&amp;gt; ARCH=+-zsh:144&amp;gt; uname -m&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;+-zsh:144&amp;gt; ARCH=+-zsh:144&amp;gt; sed -e s/x86_64/amd64/ -e &#39;s/\(arm\)\(64\)\?.*/\1\2/&#39; -e &#39;s/aarch64$/arm64/&#39;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;+-zsh:144&amp;gt; ARCH=arm64&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;+-zsh:145&amp;gt; KREW=krew-darwin_arm64&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;+-zsh:146&amp;gt; curl -fsSLO https://github.com/kubernetes-sigs/krew/releases/latest/download/krew-darwin_arm64.tar.gz&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;+-zsh:147&amp;gt; tar zxvf krew-darwin_arm64.tar.gz&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;x ./LICENSE&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;x ./krew-darwin_arm64&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;+-zsh:148&amp;gt; ./krew-darwin_arm64 install krew&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;Adding &quot;default&quot; plugin index from https://github.com/kubernetes-sigs/krew-index.git.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;Updated the local copy of plugin index.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;Installing plugin: krew&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;Installed plugin: krew&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;| Use this plugin:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;| &lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;kubectl krew&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;| Documentation:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;| &lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;https://krew.sigs.k8s.io/&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;| Caveats:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;| \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;|&amp;nbsp; | krew is now installed! To start using kubectl plugins, you need to add&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;|&amp;nbsp; | krew&#39;s installation directory to your PATH:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;|&amp;nbsp; |&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;|&amp;nbsp; |&amp;nbsp; &amp;nbsp;* macOS/Linux:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;|&amp;nbsp; |&amp;nbsp; &amp;nbsp; &amp;nbsp;- Add the following to your ~/.bashrc or ~/.zshrc:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;|&amp;nbsp; |&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;export PATH=&quot;${KREW_ROOT:-$HOME/.krew}/bin:$PATH&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;|&amp;nbsp; |&amp;nbsp; &amp;nbsp; &amp;nbsp;- Restart your shell.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;|&amp;nbsp; |&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;|&amp;nbsp; |&amp;nbsp; &amp;nbsp;* Windows: Add %USERPROFILE%\.krew\bin to your PATH environment variable&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;|&amp;nbsp; |&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;|&amp;nbsp; | To list krew commands and to get help, run:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;|&amp;nbsp; |&amp;nbsp; &amp;nbsp;$ kubectl krew&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;|&amp;nbsp; | For a full list of available plugins, run:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;|&amp;nbsp; |&amp;nbsp; &amp;nbsp;$ kubectl krew search&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;|&amp;nbsp; |&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;|&amp;nbsp; | You can find documentation at&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;|&amp;nbsp; |&amp;nbsp; &amp;nbsp;https://krew.sigs.k8s.io/docs/user-guide/quickstart/.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;| /&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;/&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Add Krew path to PATHs:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;vi ~/.zshrc&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;cat ~/.zshrc&amp;nbsp; &amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;export PATH=&quot;${KREW_ROOT:-$HOME/.krew}/bin:$PATH&quot; &lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;&amp;lt;-- added manually&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Reload .zshrc configuration file within the currently running Zsh terminal (or just restart the terminal):&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;source ~/.zshrc&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Installation verification:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;kubectl krew&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;krew is the kubectl plugin manager.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;You can invoke krew through kubectl: &quot;kubectl krew [command]...&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Usage:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; kubectl krew [command]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Available Commands:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; help&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Help about any command&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; index&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Manage custom plugin indexes&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; info&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Show information about an available plugin&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; install&amp;nbsp; &amp;nbsp; &amp;nbsp;Install kubectl plugins&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; list&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; List installed kubectl plugins&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; search&amp;nbsp; &amp;nbsp; &amp;nbsp; Discover kubectl plugins&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; uninstall&amp;nbsp; &amp;nbsp;Uninstall plugins&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; update&amp;nbsp; &amp;nbsp; &amp;nbsp; Update the local copy of the plugin index&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; upgrade&amp;nbsp; &amp;nbsp; &amp;nbsp;Upgrade installed plugins to newer versions&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; version&amp;nbsp; &amp;nbsp; &amp;nbsp;Show krew version and diagnostics&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Flags:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; -h, --help&amp;nbsp; &amp;nbsp; &amp;nbsp; help for krew&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; -v, --v Level&amp;nbsp; &amp;nbsp;number for the log level verbosity&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;Use &quot;kubectl krew [command] --help&quot; for more information about a command.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Common Commands&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To use Krew, you must first install it as a kubectl plugin itself. Key commands include:&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;kubectl krew update&lt;/span&gt;: Updates the local list of available plugins.&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;kubectl krew search&lt;/span&gt;: Finds plugins in the official Krew index.&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;kubectl krew install &amp;lt;plugin&amp;gt;&lt;/span&gt;: Installs a specific plugin.&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;kubectl krew list&lt;/span&gt;: Displays all plugins currently installed through Krew.&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;kubectl krew upgrade&lt;/span&gt;: Updates all installed plugins to their latest versions.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Example:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;kubectl krew install deprecations&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;Updated the local copy of plugin index.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;Installing plugin: deprecations&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;Installed plugin: deprecations&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;| Use this plugin:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;| &lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;kubectl deprecations&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;| Documentation:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;| &lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;https://github.com/rikatz/kubepug&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;| Caveats:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;| \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;|&amp;nbsp; | * By default, deprecations finds deprecated object relative to the current kubernetes&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;|&amp;nbsp; | master branch. To target a different kubernetes release, use the --k8s-version&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;|&amp;nbsp; | argument.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;|&amp;nbsp; |&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;|&amp;nbsp; | * Deprecations needs permission to GET all objects in the Cluster&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp;| /&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;/&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #ffa400; font-family: courier; font-size: x-small;&quot;&gt;WARNING: You installed plugin &quot;deprecations&quot; from the krew-index plugin repository.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #ffa400; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp;These plugins are not audited for security by the Krew maintainers.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #ffa400; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp;Run them at your own risk.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Popular Plugins Managed by Krew&amp;nbsp;&lt;/h2&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;ctx / ns: Rapidly switch between Kubernetes contexts and namespaces.&lt;/li&gt;&lt;li&gt;tree: Visualizes the hierarchy of Kubernetes resources in a tree view.&lt;/li&gt;&lt;li&gt;access-matrix: Displays an RBAC (Role-Based Access Control) matrix for server resources.&lt;/li&gt;&lt;li&gt;get-all: Lists all resources in a namespace, including those often missed by kubectl get all.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Note on Security (!)&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Plugins in the Krew index are community-contributed and are not audited for security by the Kubernetes maintainers; you should only install plugins from sources you trust.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;---&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/6942889768486125371/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/6942889768486125371' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/6942889768486125371'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/6942889768486125371'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/02/introduction-to-krew-kubernetes-tool.html' title='Introduction to Krew (Kubernetes tool)'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-8zz_xMb_zIJVWsT1O8qq_3uwCjifRGudwea3z99R_qnccY-s-QRiGG4nFPCbBdSHrnEPoFeHhJp40B66Hda-wmK7oX7HQf63BFuzkacRl4EthdYf0315E2ft-0URBpfUaD6M40KEI5OzOG2zeUaexS3PuLdaVfDb4wr4zjAYOlDWULomA2TGNXH9DcM/s72-w640-h224-c/Screenshot%202026-02-26%20at%2014.13.13.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-773533718585702891</id><published>2026-02-26T13:03:00.001+00:00</published><updated>2026-03-19T15:14:56.410+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><category scheme="http://www.blogger.com/atom/ns#" term="Kubernetes"/><category scheme="http://www.blogger.com/atom/ns#" term="Pluto"/><title type='text'>Introduction to Pluto (Kubernetes tool)</title><content type='html'>&lt;div style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgctFZO1cikInSdsmgyQvuhLMC4EFcsz_1174ueKDzd1XZ2lnKkVkmnKn9pPG5thoCx2Tgjp03mCuce0B6eVKpSEX5Tyb8EmGxhCXx6JlE2X6j8ND06QZQsrLcwk3ImfSmvqq_ncs6zkfhtq4M38_x0Z-SOSCtNlkiVorHc6lk3_Ei3f8_vDXJB2zMp65U/s914/pluto-logo.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;380&quot; data-original-width=&quot;914&quot; height=&quot;266&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgctFZO1cikInSdsmgyQvuhLMC4EFcsz_1174ueKDzd1XZ2lnKkVkmnKn9pPG5thoCx2Tgjp03mCuce0B6eVKpSEX5Tyb8EmGxhCXx6JlE2X6j8ND06QZQsrLcwk3ImfSmvqq_ncs6zkfhtq4M38_x0Z-SOSCtNlkiVorHc6lk3_Ei3f8_vDXJB2zMp65U/w640-h266/pluto-logo.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;a href=&quot;https://github.com/FairwindsOps/pluto?tab=readme-ov-file&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Pluto&lt;/a&gt; is:&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;CLI tool that helps users find deprecated Kubernetes API versions in your code repositories and Helm releases.&amp;nbsp;&lt;/li&gt;&lt;li&gt;It&#39;s especially useful when upgrading Kubernetes clusters, as it identifies resources that need updating before the upgrade.&lt;/li&gt;&lt;li&gt;It works against:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Live clusters&lt;/li&gt;&lt;li&gt;Helm charts&lt;/li&gt;&lt;li&gt;Raw YAML&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Pluto will show which APIs are deprecated or removed, what version they were deprecated in, and what the replacement API should be.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Installation on Mac (https://pluto.docs.fairwinds.com/installation/#homebrew-tap):&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;brew install FairwindsOps/tap/pluto&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Let&#39;s see its CLI arguments:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;pluto&lt;/b&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;You must specify a sub-command.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;A tool to detect Kubernetes apiVersions&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;Usage:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; pluto [flags]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; pluto [command]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;Available Commands:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; completion&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Generate the autocompletion script for the specified shell&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; detect&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Checks a single file or stdin for deprecated apiVersions.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; detect-all-in-cluster run all in-cluster detections&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; detect-api-resources&amp;nbsp; detect-api-resources&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; detect-files&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; detect-files&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; detect-helm&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;detect-helm&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; help&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Help about any command&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; list-versions&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Outputs a JSON object of the versions that Pluto knows about.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; version&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Prints the current version of the tool.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;Flags:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; -f, --additional-versions string&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Additional deprecated versions file to add to the list. Cannot contain any existing versions&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; --columns strings&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;A list of columns to print. Mandatory when using --output custom, optional with --output markdown&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; --components strings&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; A list of components to run checks for. If nil, will check for all found in versions.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; -h, --help&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; help for pluto&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; --ignore-deprecations&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Ignore the default behavior to exit 2 if deprecated apiVersions are found. (Only show removed APIs, not just deprecated ones)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; --ignore-removals&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Ignore the default behavior to exit 3 if removed apiVersions are found. (Only show deprecated APIs, not removed ones)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; --ignore-unavailable-replacements&amp;nbsp; &amp;nbsp;Ignore the default behavior to exit 4 if deprecated but unavailable apiVersions are found.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; -H, --no-headers&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; When using the default or custom-column output format, don&#39;t print headers (default print headers).&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; -r, --only-show-removed&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Only display the apiVersions that have been removed in the target version.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &lt;b&gt;-o&lt;/b&gt;, --output string&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;The output format to use. (normal|&lt;b&gt;wide&lt;/b&gt;|custom|json|yaml|markdown|csv) (default &quot;normal&quot;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; -t, &lt;b&gt;--target-versions&lt;/b&gt; stringToString&amp;nbsp; &amp;nbsp; A map of targetVersions to use. This flag supersedes all defaults in version files. (default [])&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; -v, --v Level&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;number for the log level verbosity&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;Use &quot;pluto [command] --help&quot; for more information about a command.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;detect-files&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If we want to scan local Helm charts or manifest files before they are deployed, we can use &lt;span style=&quot;font-family: courier;&quot;&gt;pluto detect-files&lt;/span&gt; or &lt;span style=&quot;font-family: courier;&quot;&gt;pluto detect&lt;/span&gt;, which do require us to be in the correct directory or provide a file path.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To scan and detect deprecated APIs in manifest files in a directory:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;pluto detect-files -d /path/to/your/manifests&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;detect-files&lt;/span&gt; is for checking YAML files in our repositories/filesystem before deploying them - that&#39;s separate from detect-helm and&amp;nbsp;detect-all-in-cluster cluster commands.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To target particular k8s version:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;pluto detect-files -d . --target-versions k8s=v1.33.0&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If we use Terraform to deploy Helm charts, we might want to keep chart values in separate files (.yaml or .yaml.tpl) as otherwise we won&#39;t be able to use Pluto directly (we&#39;d need to extract values into files first). For more details, see&amp;nbsp;&lt;a href=&quot;https://www.bojankomazec.com/2026/02/where-to-keep-helm-chart-values-in.html&quot;&gt;Where to keep Helm chart values in Terraform projects | My Public Notepad&lt;/a&gt;.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;detect-helm&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To check Helm releases in the cluster (already deployed):&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;pluto detect-helm -owide&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To target particular k8s version:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;pluto detect-helm -owide --target-versions k8s=v1.33.0&amp;nbsp;&lt;/b&gt; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;There were no resources found with known deprecated apiVersions.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;detect-helm&lt;/span&gt; specifically checks Helm release metadata stored in our cluster (in secrets or configmaps) after Helm chart have been deployed. It looks at the manifests that Helm used to install releases, which might contain deprecated APIs even if they haven&#39;t been applied yet or are stored in Helm&#39;s history.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This command can be run from any directory. This is because the &lt;span style=&quot;font-family: courier;&quot;&gt;detect-helm&lt;/span&gt; command scans live Helm releases currently deployed in our Kubernetes cluster, rather than looking for local files on our machine. Instead of relying on our current working directory, the command depends on our Kubernetes context (the cluster our CLI is currently pointed at) and our local Helm configuration to communicate with the cluster.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;While the directory doesn&#39;t matter, the following must be true for the command to work:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Active Kubernetes Context: Your kubectl context must be set to the target cluster.&lt;/li&gt;&lt;li&gt;Cluster Permissions: You must have sufficient RBAC permissions to read Secrets in the namespaces you wish to scan, as Helm 3 stores release information in cluster secrets.&lt;/li&gt;&lt;li&gt;Target Versioning: The --target-versions k8s=v1.33.0 flag tells Pluto to check for APIs that are deprecated or removed specifically in Kubernetes version 1.33.0, regardless of what version the cluster is actually running&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;detect-all-in-cluster&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To check all resources in the cluster:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% pluto &lt;b&gt;detect-all-in-cluster&lt;/b&gt; -o wide&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;I0226 12:01:02.279788&amp;nbsp; &amp;nbsp;47100 warnings.go:110] &quot;Warning: v1 ComponentStatus is deprecated in v1.19+&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;There were no resources found with known deprecated apiVersions.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;detect-all-in-cluster&lt;/span&gt; scans all live resources currently running in our cluster by querying the Kubernetes API directly. It checks deployments, services, pods, etc. that are actively deployed.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;detect-all-in-cluster&lt;/span&gt; does NOT include &lt;span style=&quot;font-family: courier;&quot;&gt;detect-helm&lt;/span&gt; or &lt;span style=&quot;font-family: courier;&quot;&gt;detect-files&lt;/span&gt;. Here&#39;s why they&#39;re separate:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;detect-all-in-cluster sees the current state of resources&lt;/li&gt;&lt;li&gt;detect-helm sees Helm&#39;s stored templates and history, which may include:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Templated manifests that haven&#39;t been rendered yet&lt;/li&gt;&lt;li&gt;Old release revisions&lt;/li&gt;&lt;li&gt;Chart templates with deprecated APIs&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Run both to get complete coverage!&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Target a specific Kubernetes version:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% pluto detect-all-in-cluster --target-versions k8s=v1.33.0&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;I0226 12:02:26.551401&amp;nbsp; &amp;nbsp;47113 warnings.go:110] &quot;Warning: v1 ComponentStatus is deprecated in v1.19+&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;There were no resources found with known deprecated apiVersions.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;The warning message:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #ffa400; font-family: courier;&quot;&gt;Warning: v1 ComponentStatus is deprecated in v1.19+&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is just Pluto itself triggering a Kubernetes API warning while scanning - it&#39;s not something wrong with our cluster resources.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The main result:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;There were no resources found with known deprecated apiVersions.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This means all our cluster resources are using API versions that are still valid in Kubernetes v1.33.0 (our target version). This means:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Our cluster resources are already compatible with k8s v1.33.0&lt;/li&gt;&lt;li&gt;No manifests need updating before upgrading&lt;/li&gt;&lt;li&gt;No deprecated APIs that would be removed in v1.33.0&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To be thorough before a k8s upgrade, we need to run all three commands:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;detect-files&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;detect-helm&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;detect-all-in-cluster&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;---&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/773533718585702891/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/773533718585702891' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/773533718585702891'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/773533718585702891'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/02/introduction-to-pluto-kubernetes-tool.html' title='Introduction to Pluto (Kubernetes tool)'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgctFZO1cikInSdsmgyQvuhLMC4EFcsz_1174ueKDzd1XZ2lnKkVkmnKn9pPG5thoCx2Tgjp03mCuce0B6eVKpSEX5Tyb8EmGxhCXx6JlE2X6j8ND06QZQsrLcwk3ImfSmvqq_ncs6zkfhtq4M38_x0Z-SOSCtNlkiVorHc6lk3_Ei3f8_vDXJB2zMp65U/s72-w640-h266-c/pluto-logo.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-2547510545340306160</id><published>2026-02-26T13:02:00.001+00:00</published><updated>2026-02-26T13:02:33.302+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><category scheme="http://www.blogger.com/atom/ns#" term="Helm"/><category scheme="http://www.blogger.com/atom/ns#" term="Kubernetes"/><category scheme="http://www.blogger.com/atom/ns#" term="Terraform"/><title type='text'>Where to keep Helm chart values in Terraform projects</title><content type='html'>&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEiTiPvI-D1ZteSQf2ADyvs1WFtBgeC-S8tPZM1jSMVk-cs7Vs_wsrvckPiG3nnCJwCsJbfaaLEyW1adfeEbB7RJOaZkUOf39eNOo-8rnSe36blaSFeA0FUJTXxhF6CMhxxtaUoFVoO93I4vJN0l8mbIY3qCpyfvZfR88T-uvH1XDbsK0N0aQk5TjrXj7XU&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;512&quot; data-original-width=&quot;512&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEiTiPvI-D1ZteSQf2ADyvs1WFtBgeC-S8tPZM1jSMVk-cs7Vs_wsrvckPiG3nnCJwCsJbfaaLEyW1adfeEbB7RJOaZkUOf39eNOo-8rnSe36blaSFeA0FUJTXxhF6CMhxxtaUoFVoO93I4vJN0l8mbIY3qCpyfvZfR88T-uvH1XDbsK0N0aQk5TjrXj7XU=w640-h640&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;div&gt;If we use Terraform to deploy Helm charts, we might be using one of these strategies to keep chart values:&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Values are in inline YAML string&lt;/li&gt;&lt;li&gt;Values in separate .yaml file&lt;/li&gt;&lt;li&gt;Values in separate&amp;nbsp;YAML Template files (.yaml.tpl)&lt;/li&gt;&lt;li&gt;Use Helm&#39;s set for Dynamic Values&lt;/li&gt;&lt;li&gt;Multiple Values Files&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;(1) Values in inline YAML string&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is not ideal as problems with Inline YAML in Terraform include:&lt;br /&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;No syntax highlighting or validation - Easy to break YAML formatting&lt;/li&gt;&lt;li&gt;Hard to review in diffs - Changes are messy in PRs&lt;/li&gt;&lt;li&gt;Can&#39;t use standard tooling - No yamllint,&amp;nbsp;&lt;b&gt;Pluto&lt;/b&gt;, or other YAML tools&lt;/li&gt;&lt;li&gt;Mixing concerns - Infrastructure code mixed with application config&lt;/li&gt;&lt;li&gt;Escaping nightmares - Terraform string interpolation conflicts with Helm templating&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Example:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;resource &quot;helm_release&quot; &quot;app&quot; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; values = [&amp;lt;&amp;lt;-EOT&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; replicaCount: ${var.replicas}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; image:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; repository: myapp&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; tag: ${var.tag}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; service:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; type: LoadBalancer&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; EOT&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; ]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;(2) Separate Values Files&amp;nbsp;&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Keep values in YAML files, reference them in Terraform.&lt;/div&gt;&lt;div&gt;This is a better approach because:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Clean separation&lt;/li&gt;&lt;li&gt;Easy to validate with standard tools&lt;/li&gt;&lt;li&gt;Better diffs&lt;/li&gt;&lt;li&gt;Can use Pluto directly: pluto detect-files -d .&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Example:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;main.tf:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;resource &quot;helm_release&quot; &quot;my_app&quot; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;= &quot;my-app&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; chart&amp;nbsp; &amp;nbsp; &amp;nbsp; = &quot;my-chart&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; repository = &quot;https://charts.example.com&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; values = [&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; file(&quot;${path.module}/helm-values.yaml&quot;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; ]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;(3) Templated Values Files&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;p class=&quot;font-claude-response-body break-words whitespace-normal leading-[1.7]&quot;&gt;Use Terraform&#39;s &lt;span style=&quot;font-family: courier;&quot;&gt;templatefile()&lt;/span&gt; to inject dynamic values:&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;helm-values.yaml.tpl:&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;replicaCount: ${replica_count}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;image:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; repository: ${image_repo}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; tag: ${image_tag}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;ingress:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; enabled: ${enable_ingress}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; host: ${hostname}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;main.tf:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;resource &quot;helm_release&quot; &quot;my_app&quot; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name&amp;nbsp; = &quot;my-app&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; chart = &quot;my-chart&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; values = [&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; templatefile(&quot;${path.module}/helm-values.yaml.tpl&quot;, {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; replica_count&amp;nbsp; = var.replica_count&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; image_repo&amp;nbsp; &amp;nbsp; &amp;nbsp;= var.image_repository&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; image_tag&amp;nbsp; &amp;nbsp; &amp;nbsp; = var.image_tag&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; enable_ingress = var.enable_ingress&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; hostname&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;= var.hostname&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; })&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; ]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;p class=&quot;font-claude-response-body break-words whitespace-normal leading-[1.7]&quot;&gt;Pros:&lt;/p&gt;&lt;ul class=&quot;[li_&amp;amp;]:mb-0 [li_&amp;amp;]:mt-1 [li_&amp;amp;]:gap-1 [&amp;amp;:not(:last-child)_ul]:pb-1 [&amp;amp;:not(:last-child)_ol]:pb-1 list-disc flex flex-col gap-1 pl-8 mb-3&quot;&gt;&lt;li class=&quot;whitespace-normal break-words pl-2&quot;&gt;Still gets variable injection&lt;/li&gt;&lt;li class=&quot;whitespace-normal break-words pl-2&quot;&gt;Can be validated as YAML (with placeholders)&lt;/li&gt;&lt;li class=&quot;whitespace-normal break-words pl-2&quot;&gt;Clean and readable&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;(4) Use Helm&#39;s set for Dynamic Values&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Keep static config in files, override specific values:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;resource &quot;helm_release&quot; &quot;my_app&quot; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;= &quot;my-app&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; chart&amp;nbsp; &amp;nbsp; &amp;nbsp; = &quot;my-chart&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; # Base values from file&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; values = [&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; file(&quot;${path.module}/helm-values.yaml&quot;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; ]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; # Override specific values dynamically&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; set {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; name&amp;nbsp; = &quot;image.tag&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; value = var.image_tag&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; set {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; name&amp;nbsp; = &quot;replicaCount&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; value = var.replica_count&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; set_sensitive {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; name&amp;nbsp; = &quot;secret.password&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; value = var.db_password&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Pros:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Clear what&#39;s dynamic vs static&lt;/li&gt;&lt;li&gt;Base values file can be validated&lt;/li&gt;&lt;li&gt;Sensitive values handled properly&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Here is the example how we can migrate inline YAML from the above to templated file:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;helm-values.yaml:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;image:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; repository: myapp&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;service:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; type: LoadBalancer&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;main.tf:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;resource &quot;helm_release&quot; &quot;app&quot; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; values = [&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; file(&quot;${path.module}/helm-values.yaml&quot;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; ]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; set {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; name&amp;nbsp; = &quot;replicaCount&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; value = var.replicas&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; set {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; name&amp;nbsp; = &quot;image.tag&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; value = var.tag&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now we can run:&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% pluto detect-files -f helm-values.yaml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;(5) Multiple Values Files&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We can layer our configuration:&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;resource &quot;helm_release&quot; &quot;my_app&quot; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; name&amp;nbsp; = &quot;my-app&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; chart = &quot;my-chart&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; values = [&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; file(&quot;${path.module}/helm-values-base.yaml&quot;),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; file(&quot;${path.module}/helm-values-${var.environment}.yaml&quot;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; ]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;---&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/2547510545340306160/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/2547510545340306160' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/2547510545340306160'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/2547510545340306160'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/02/where-to-keep-helm-chart-values-in.html' title='Where to keep Helm chart values in Terraform projects'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/a/AVvXsEiTiPvI-D1ZteSQf2ADyvs1WFtBgeC-S8tPZM1jSMVk-cs7Vs_wsrvckPiG3nnCJwCsJbfaaLEyW1adfeEbB7RJOaZkUOf39eNOo-8rnSe36blaSFeA0FUJTXxhF6CMhxxtaUoFVoO93I4vJN0l8mbIY3qCpyfvZfR88T-uvH1XDbsK0N0aQk5TjrXj7XU=s72-w640-h640-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-1967285022205863794</id><published>2026-02-26T11:07:00.002+00:00</published><updated>2026-02-26T11:21:01.135+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><category scheme="http://www.blogger.com/atom/ns#" term="Kubent"/><category scheme="http://www.blogger.com/atom/ns#" term="Kubernetes"/><title type='text'>Introduction to Kubent (Kube No Trouble)</title><content type='html'>&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguB41-QWSneCrCvtgpyBbniO0DArgmPNDic2AZzdU4lS8EVVV2U9mLvD0yk0eTLdrkNEN9YG8JxBcutax1G-i6QG6Ch9o0RoHOhBYuebUswUGy1WHY_PZiBghkShaki9YJN-s-eBHBu8dIxPiFsyPxgGLC73qwHSGE1yZshXRl-POtBSqpQguWs8QhQoM/s2206/Screenshot%202026-02-26%20at%2007.50.05.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1320&quot; data-original-width=&quot;2206&quot; height=&quot;382&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguB41-QWSneCrCvtgpyBbniO0DArgmPNDic2AZzdU4lS8EVVV2U9mLvD0yk0eTLdrkNEN9YG8JxBcutax1G-i6QG6Ch9o0RoHOhBYuebUswUGy1WHY_PZiBghkShaki9YJN-s-eBHBu8dIxPiFsyPxgGLC73qwHSGE1yZshXRl-POtBSqpQguWs8QhQoM/w640-h382/Screenshot%202026-02-26%20at%2007.50.05.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;Kubent&amp;nbsp;(Kube No Trouble)&amp;nbsp; [this link was the original repo, see comments below] is a tool which scans k8s cluster and reports resources that use deprecated or removed Kubernetes APIs, based on the target Kubernetes version. It’s especially useful before upgrading (e.g., EKS 1.32 → 1.33)&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;WARNING: Development at project&#39;s original repo (&lt;a href=&quot;https://github.com/doitintl/kube-no-trouble&quot;&gt;https://github.com/doitintl/kube-no-trouble&lt;/a&gt;) is not active anymore as the last commit was in January 2025. The original author announced &lt;a href=&quot;https://github.com/doitintl/kube-no-trouble/issues/732&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt; that they would be moving development to&amp;nbsp;&lt;a href=&quot;https://github.com/dark0dave/kube-no-trouble &quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;https://github.com/dark0dave/kube-no-trouble &lt;/a&gt;and that repo is ssemingly active as of today (last change was ) BUT&amp;nbsp;&lt;a href=&quot;https://github.com/dark0dave/kube-no-trouble/tree/301e5783904de5966f79b217a956651146630f50/pkg/rules/rego&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;https://github.com/dark0dave/kube-no-trouble/tree/301e5783904de5966f79b217a956651146630f50/pkg/rules/rego&lt;/a&gt; shows that rulesets only up to v1.32 were added (!).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Kube No Trouble relies on static Rego rule files in the repo. If new Kubernetes versions (e.g., &amp;gt;1.32) don’t have updated rules, then:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;It won’t know about newly deprecated APIs&lt;/li&gt;&lt;li&gt;It won’t know about newly removed APIs&lt;/li&gt;&lt;li&gt;--target-version becomes unreliable for newer releases&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For modern upgrades (especially 1.32 → 1.33+), kubent is no longer the safest tool.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;&lt;/p&gt;&lt;div&gt;To install it:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;sh -c &quot;$(curl -sSL https://git.io/install-kubent)&quot;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;gt;&amp;gt;&amp;gt; kubent installation script &amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;gt; Detecting latest version&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;gt; Downloading version 0.7.3&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;Target directory (/usr/local/bin) is not writable, trying to use sudo&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;Password:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; % Total&amp;nbsp; &amp;nbsp; % Received % Xferd&amp;nbsp; Average Speed&amp;nbsp; &amp;nbsp;Time&amp;nbsp; &amp;nbsp; Time&amp;nbsp; &amp;nbsp; &amp;nbsp;Time&amp;nbsp; Current&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Dload&amp;nbsp; Upload&amp;nbsp; &amp;nbsp;Total&amp;nbsp; &amp;nbsp;Spent&amp;nbsp; &amp;nbsp; Left&amp;nbsp; Speed&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; 0&amp;nbsp; &amp;nbsp; &amp;nbsp;0&amp;nbsp; &amp;nbsp; 0&amp;nbsp; &amp;nbsp; &amp;nbsp;0&amp;nbsp; &amp;nbsp; 0&amp;nbsp; &amp;nbsp; &amp;nbsp;0&amp;nbsp; &amp;nbsp; &amp;nbsp; 0&amp;nbsp; &amp;nbsp; &amp;nbsp; 0 --:--:-- --:--:-- --:--:--&amp;nbsp; &amp;nbsp; &amp;nbsp;0&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;100 12.4M&amp;nbsp; 100 12.4M&amp;nbsp; &amp;nbsp; 0&amp;nbsp; &amp;nbsp; &amp;nbsp;0&amp;nbsp; 14.7M&amp;nbsp; &amp;nbsp; &amp;nbsp; 0 --:--:-- --:--:-- --:--:-- 13.2M&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;gt; Done. kubent was installed to /usr/local/bin/.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To verify installation:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;kubent --version&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;7:48AM INF version 0.7.3 (git sha 57480c07b3f91238f12a35d0ec88d9368aae99aa)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To check CLI arguments:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;kubent --help&amp;nbsp; &lt;/b&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;Usage of kubent:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; -A, --additional-annotation strings&amp;nbsp; &amp;nbsp;additional annotations that should be checked to determine the last applied config&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; -a, --additional-kind strings&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;additional kinds of resources to report in Kind.version.group.com format&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; -c, --cluster&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;enable Cluster collector (default true)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; -x, --context string&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; kubeconfig context&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; -e, --exit-error&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; exit with non-zero code when issues are found&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; -f, --filename strings&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; manifests to check, use - for stdin&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; --helm3&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;enable Helm v3 collector (default true)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; -k, --kubeconfig string&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;path to the kubeconfig file&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; -l, --log-level string&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; set log level (trace, debug, info, warn, error, fatal, panic, disabled) (default &quot;info&quot;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; -o, --output string&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;output format - [text|json|csv] (default &quot;text&quot;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; -O, --output-file string&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; output file, use - for stdout (default &quot;-&quot;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; -t, --target-version string&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;target K8s version in SemVer format (autodetected by default)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;&amp;nbsp; -v, --version&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;prints the version of kubent and exits&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier; font-size: x-small;&quot;&gt;pflag: help requested&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It looks at&amp;nbsp;default &lt;span style=&quot;font-family: courier;&quot;&gt;~/.kube/config&lt;/span&gt; file in order to find the current context, otherwise use &lt;span style=&quot;font-family: courier;&quot;&gt;-k &lt;/span&gt;to specify kubeconfig at non-default location.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;kubent&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;7:59AM INF &amp;gt;&amp;gt;&amp;gt; Kube No Trouble `kubent` &amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;7:59AM INF version 0.7.3 (git sha 57480c07b3f91238f12a35d0ec88d9368aae99aa)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;7:59AM INF Initializing collectors and retrieving data&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;7:59AM INF Target K8s version is 1.32.11-eks-ac2d5a0&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;7:59AM INF Retrieved 12 resources from collector name=Cluster&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:00AM INF Retrieved 361 resources from collector name=&quot;Helm v3&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:00AM INF Loaded ruleset name=custom.rego.tmpl&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:00AM INF Loaded ruleset name=deprecated-1-16.rego&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:00AM INF Loaded ruleset name=deprecated-1-22.rego&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:00AM INF Loaded ruleset name=deprecated-1-25.rego&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:00AM INF Loaded ruleset name=deprecated-1-26.rego&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:00AM INF Loaded ruleset name=deprecated-1-27.rego&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:00AM INF Loaded ruleset name=deprecated-1-29.rego&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:00AM INF Loaded ruleset name=deprecated-1-32.rego&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:00AM INF Loaded ruleset name=deprecated-future.rego&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Running &lt;span style=&quot;font-family: courier;&quot;&gt;kubent&lt;/span&gt; with no other arguments:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Connects to your current kube-context&lt;/li&gt;&lt;li&gt;Detects your cluster version automatically&lt;/li&gt;&lt;li&gt;Scans all namespaces&lt;/li&gt;&lt;li&gt;Compares resources against deprecations for that version&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Before the upgrade to v1.33, we want kubent to scan the resources against that next k8s version so we need to specify it with &lt;span style=&quot;font-family: courier;&quot;&gt;--target-version&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;% &lt;b&gt;kubent --target-version=1.33&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:02AM INF &amp;gt;&amp;gt;&amp;gt; Kube No Trouble `kubent` &amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:02AM INF version 0.7.3 (git sha 57480c07b3f91238f12a35d0ec88d9368aae99aa)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:02AM INF Initializing collectors and retrieving data&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:02AM INF Target K8s version is 1.33.0&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:02AM INF Retrieved 12 resources from collector name=Cluster&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:03AM INF Retrieved 361 resources from collector name=&quot;Helm v3&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:03AM INF Loaded ruleset name=custom.rego.tmpl&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:03AM INF Loaded ruleset name=deprecated-1-16.rego&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:03AM INF Loaded ruleset name=deprecated-1-22.rego&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:03AM INF Loaded ruleset name=deprecated-1-25.rego&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:03AM INF Loaded ruleset name=deprecated-1-26.rego&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:03AM INF Loaded ruleset name=deprecated-1-27.rego&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:03AM INF Loaded ruleset name=deprecated-1-29.rego&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:03AM INF Loaded ruleset name=deprecated-1-32.rego&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;8:03AM INF Loaded ruleset name=deprecated-future.rego&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;---&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/1967285022205863794/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/1967285022205863794' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/1967285022205863794'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/1967285022205863794'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/02/introduction-to-kubent-kube-no-trouble.html' title='Introduction to Kubent (Kube No Trouble)'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguB41-QWSneCrCvtgpyBbniO0DArgmPNDic2AZzdU4lS8EVVV2U9mLvD0yk0eTLdrkNEN9YG8JxBcutax1G-i6QG6Ch9o0RoHOhBYuebUswUGy1WHY_PZiBghkShaki9YJN-s-eBHBu8dIxPiFsyPxgGLC73qwHSGE1yZshXRl-POtBSqpQguWs8QhQoM/s72-w640-h382-c/Screenshot%202026-02-26%20at%2007.50.05.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4912226416400969049.post-3687026977627844117</id><published>2026-02-23T11:59:00.001+00:00</published><updated>2026-02-23T11:59:12.013+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><category scheme="http://www.blogger.com/atom/ns#" term="Grafana"/><category scheme="http://www.blogger.com/atom/ns#" term="Grafana Loki"/><title type='text'>Introduction to Grafana Loki</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEik-xO6FZGcQhAZpOz1riTcrmV-UyV16h2RrmaIwn98641pyb5UXFVrd63FCnIvpJd1u2ZKg5lZq4A70vOXXs2mDOepoJOnIabKAjdKF2w8VPf0dFFmCxQfwKmXv6UdqqjSZntGEUzAsK4qbsnztH27jFXCVGEM4unHPv-hgoV3bfx567qcQlZ9R8TyDgg/s512/loki.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;512&quot; data-original-width=&quot;512&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEik-xO6FZGcQhAZpOz1riTcrmV-UyV16h2RrmaIwn98641pyb5UXFVrd63FCnIvpJd1u2ZKg5lZq4A70vOXXs2mDOepoJOnIabKAjdKF2w8VPf0dFFmCxQfwKmXv6UdqqjSZntGEUzAsK4qbsnztH27jFXCVGEM4unHPv-hgoV3bfx567qcQlZ9R8TyDgg/w640-h640/loki.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Grafana Loki:&lt;br /&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Log aggregation system. Like Prometheus, but for logs&lt;/li&gt;&lt;li&gt;Repo:&amp;nbsp;&lt;a href=&quot;https://github.com/grafana/loki&quot;&gt;https://github.com/grafana/loki&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;These are the notes from Loki Helm chart:&amp;nbsp;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;***********************************************************************&lt;/div&gt;&lt;div&gt;&amp;nbsp; Welcome to Grafana Loki&lt;/div&gt;&lt;div&gt;&amp;nbsp; Chart version: 6.31.0&lt;/div&gt;&lt;div&gt;&amp;nbsp; Chart Name: loki&lt;/div&gt;&lt;div&gt;&amp;nbsp; Loki version: 3.5.0&lt;/div&gt;&lt;div&gt;***********************************************************************&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Tip:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Watch the deployment status using the command: kubectl get pods -w --namespace grafana-loki&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If pods are taking too long to schedule make sure pod affinity can be fulfilled in the current cluster.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;***********************************************************************&lt;/div&gt;&lt;div&gt;Installed components:&lt;/div&gt;&lt;div&gt;***********************************************************************&lt;/div&gt;&lt;div&gt;* gateway&lt;/div&gt;&lt;div&gt;* read&lt;/div&gt;&lt;div&gt;* write&lt;/div&gt;&lt;div&gt;* backend&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;***********************************************************************&lt;/div&gt;&lt;div&gt;Sending logs to Loki&lt;/div&gt;&lt;div&gt;***********************************************************************&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Loki has been configured with a gateway (nginx) to support reads and writes from a single component.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can send logs from inside the cluster using the cluster DNS:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;http://loki-gateway.grafana-loki.svc.cluster.local/loki/api/v1/push&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can test to send data from outside the cluster by port-forwarding the gateway to your local machine:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;&amp;nbsp; kubectl port-forward --namespace grafana-loki svc/loki-gateway 3100:80 &amp;amp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And then using &lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;http://127.0.0.1:3100/loki/api/v1/push&lt;/span&gt; URL as shown below:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;curl \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;-H &quot;Content-Type: application/json&quot; \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;-XPOST \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;-s &quot;http://127.0.0.1:3100/loki/api/v1/push&quot;&amp;nbsp; \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;--data-raw &quot;{\&quot;streams\&quot;: [{\&quot;stream\&quot;: {\&quot;job\&quot;: \&quot;test\&quot;}, \&quot;values\&quot;: [[\&quot;$(date +%s)000000000\&quot;, \&quot;fizzbuzz\&quot;]]}]}&quot; \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;-H X-Scope-OrgId:foo&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Then verify that Loki did receive the data using the following command:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;curl &quot;http://127.0.0.1:3100/loki/api/v1/query_range&quot; \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;--data-urlencode &#39;query={job=&quot;test&quot;}&#39; \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;-H X-Scope-OrgId:foo | jq .data.result&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;***********************************************************************&lt;/div&gt;&lt;div&gt;Connecting Grafana to Loki&lt;/div&gt;&lt;div&gt;***********************************************************************&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If Grafana operates within the cluster, you&#39;ll set up a new Loki datasource by utilizing the following URL:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #38761d; font-family: courier;&quot;&gt;http://loki-gateway.grafana-loki.svc.cluster.local/&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;***********************************************************************&lt;/div&gt;&lt;div&gt;Multi-tenancy&lt;/div&gt;&lt;div&gt;***********************************************************************&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Loki is configured with auth enabled (multi-tenancy) and expects tenant headers (`X-Scope-OrgID`) to be set for all API calls.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You must configure Grafana&#39;s Loki datasource using the `HTTP Headers` section with the `X-Scope-OrgID` to target a specific tenant.&lt;/div&gt;&lt;div&gt;For each tenant, you can create a different datasource.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The agent of your choice must also be configured to propagate this header.&lt;/div&gt;&lt;div&gt;For example, when using Promtail you can use the `tenant` stage. https://grafana.com/docs/loki/latest/send-data/promtail/stages/tenant/&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When not provided with the `X-Scope-OrgID` while auth is enabled, Loki will reject reads and writes with a 404 status code `no org id`.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can also use a reverse proxy, to automatically add the `X-Scope-OrgID` header as suggested by https://grafana.com/docs/loki/latest/operations/authentication/&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For more information, read our documentation about multi-tenancy: https://grafana.com/docs/loki/latest/operations/multi-tenancy/&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;gt; When using curl you can pass `X-Scope-OrgId` header using `-H X-Scope-OrgId:foo` option, where foo can be replaced with the tenant of your choice.&lt;/div&gt;&lt;div&gt;EOT -&amp;gt; (known after apply)&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;---&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.bojankomazec.com/feeds/3687026977627844117/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4912226416400969049/3687026977627844117' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/3687026977627844117'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4912226416400969049/posts/default/3687026977627844117'/><link rel='alternate' type='text/html' href='http://www.bojankomazec.com/2026/02/introduction-to-grafana-loki.html' title='Introduction to Grafana Loki'/><author><name>Bojan Komazec</name><uri>http://www.blogger.com/profile/05437236807206825832</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEik-xO6FZGcQhAZpOz1riTcrmV-UyV16h2RrmaIwn98641pyb5UXFVrd63FCnIvpJd1u2ZKg5lZq4A70vOXXs2mDOepoJOnIabKAjdKF2w8VPf0dFFmCxQfwKmXv6UdqqjSZntGEUzAsK4qbsnztH27jFXCVGEM4unHPv-hgoV3bfx567qcQlZ9R8TyDgg/s72-w640-h640-c/loki.png" height="72" width="72"/><thr:total>0</thr:total></entry></feed>