<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ahmad Bayhaqi</title>
    <description>The latest articles on DEV Community by Ahmad Bayhaqi (@kyuubang).</description>
    <link>https://dev.to/kyuubang</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1023996%2Fc3445c17-9f65-4360-a5f4-6cddf3ee18d2.png</url>
      <title>DEV Community: Ahmad Bayhaqi</title>
      <link>https://dev.to/kyuubang</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kyuubang"/>
    <language>en</language>
    <item>
      <title>What Docker Image Tag Should You Actually Use?</title>
      <dc:creator>Ahmad Bayhaqi</dc:creator>
      <pubDate>Tue, 25 Nov 2025 07:15:59 +0000</pubDate>
      <link>https://dev.to/kyuubang/what-docker-image-tag-should-you-actually-use-f4</link>
      <guid>https://dev.to/kyuubang/what-docker-image-tag-should-you-actually-use-f4</guid>
      <description>&lt;p&gt;I’ve been working with containerized applications for a while, and one thing that always confused me in the beginning was Docker image tagging.&lt;br&gt;
Nobody explained it properly.&lt;/p&gt;

&lt;p&gt;I just followed whatever the team did, pushed images, and hoped things worked.&lt;/p&gt;

&lt;p&gt;But over time.. especially when handling multi-tenant apps, shared registries, and too many deployments. I started to see how bad tagging decisions can &lt;strong&gt;break everything&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So here’s my experience and what I learned the hard way.&lt;/p&gt;

&lt;p&gt;The moment I realized “latest” is a trap&lt;/p&gt;

&lt;p&gt;When I first started using Docker, I thought:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Ah, just push it with latest. Simple.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Until one day, a tenant’s production environment suddenly rolled back to a previous version.&lt;br&gt;
Why?&lt;/p&gt;

&lt;p&gt;Because someone else on the team pushed a new image with the same latest tag. The registry replaced it silently. The cluster pulled it automatically. Chaos.&lt;/p&gt;

&lt;p&gt;That’s the moment I understood:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;latest is not a version&lt;/li&gt;
&lt;li&gt;latest is not safe&lt;/li&gt;
&lt;li&gt;latest will eventually hurt you&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But I didn’t stop there. I kept experimenting with different tagging styles.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Semantic Versioning Phase
&lt;/h2&gt;

&lt;p&gt;After the latest catastrophe, we switched to semantic versioning:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;v1.2.3
v1.2.4
v1.3.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And honestly... it felt clean.&lt;/p&gt;

&lt;p&gt;Every release had a meaning.&lt;/p&gt;

&lt;p&gt;We knew which version fixed what.&lt;/p&gt;

&lt;p&gt;Rollback was easy — just redeploy the previous version.&lt;/p&gt;

&lt;p&gt;But then reality hit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;My team was not disciplined enough.&lt;/li&gt;
&lt;li&gt;People forgot to update the version.&lt;/li&gt;
&lt;li&gt;Someone tagged two different builds with the same version.&lt;/li&gt;
&lt;li&gt;And sometimes we just wanted to test something quickly, but bumping semantic version felt “too heavy”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Semantic versioning worked well for production, but not so much for day-to-day development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Branch-Based Tagging: Easy but Dangerous
&lt;/h2&gt;

&lt;p&gt;Then we tried a simpler approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dev
staging
production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It felt nice.&lt;/p&gt;

&lt;p&gt;Our CI/CD pipeline was clean.&lt;/p&gt;

&lt;p&gt;Each environment had its own tag.&lt;/p&gt;

&lt;p&gt;But later, when our application grew into a multi-tenant product, things got messy.&lt;/p&gt;

&lt;p&gt;Imagine this scenario:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tenant A and Tenant B both use development tag&lt;/li&gt;
&lt;li&gt;You push a new feature for Tenant A&lt;/li&gt;
&lt;li&gt;Cluster for Tenant B also pulls the new development image (because it’s the same tag)&lt;/li&gt;
&lt;li&gt;Tenant B breaks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This happened to us more times than I’m proud of.&lt;br&gt;
And again, older images became “untagged” when new ones reused the same tag.&lt;/p&gt;

&lt;p&gt;No trace.&lt;br&gt;
git-revert rollback.&lt;br&gt;
I knew we needed something safer. &lt;/p&gt;
&lt;h2&gt;
  
  
  Finally: Branch + Commit Hash
&lt;/h2&gt;

&lt;p&gt;This was the game changer.&lt;br&gt;
Instead of just development, we started tagging like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;development-a1b2c3d
development-f39e2a1
production-c41e162
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just 7 characters of the commit hash, unique, simple, and enough to avoid collisions.&lt;/p&gt;

&lt;p&gt;Suddenly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every image had a unique identity&lt;/li&gt;
&lt;li&gt;Rollbacks became extremely easy&lt;/li&gt;
&lt;li&gt;Multi-tenant setup was safe&lt;/li&gt;
&lt;li&gt;Nothing accidentally overwrote something else&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The only downside?!&lt;/p&gt;

&lt;p&gt;Registry will populate a lot of different tags&lt;/p&gt;

&lt;p&gt;Our container registry filled up fast.&lt;br&gt;
We had to implement retention policies.&lt;/p&gt;

&lt;p&gt;But honestly, compared to breaking tenants?&lt;/p&gt;

&lt;p&gt;I will happily pay for storage.&lt;br&gt;
This tagging style solved everything semantic versioning and branch tagging couldn’t.&lt;/p&gt;
&lt;h2&gt;
  
  
  So what do I actually recommend?
&lt;/h2&gt;

&lt;p&gt;From my own experience,&lt;/p&gt;

&lt;p&gt;For development:&lt;br&gt;
Use branch + commit hash&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;development-7f92c3a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It keeps things safe, traceable, and rollback-friendly. cover frequently changes on development.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tips&lt;br&gt;
keep &lt;code&gt;latest&lt;/code&gt; image (e.g. &lt;code&gt;development-latest&lt;/code&gt;). you may push alternative tag on single commit. &lt;br&gt;
dont worry it doesn't take your storage, just tag. it will help you to trace which latest tag quickly&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For production:&lt;br&gt;
Use semantic versioning&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;v1.4.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clean, stable, professional.&lt;/p&gt;

&lt;p&gt;For personal or hobby projects:&lt;br&gt;
Just use &lt;code&gt;latest&lt;/code&gt; or &lt;code&gt;dev&lt;/code&gt;.&lt;br&gt;
No need to over-engineer.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>Azure: How to Configure SSL Using Cert-Manager with (AGIC) Application Gateway Ingress Controller</title>
      <dc:creator>Ahmad Bayhaqi</dc:creator>
      <pubDate>Mon, 03 Apr 2023 06:10:25 +0000</pubDate>
      <link>https://dev.to/kyuubang/azure-how-to-configure-ssl-using-cert-manager-with-agic-application-gateway-ingress-controller-3l8p</link>
      <guid>https://dev.to/kyuubang/azure-how-to-configure-ssl-using-cert-manager-with-agic-application-gateway-ingress-controller-3l8p</guid>
      <description>&lt;p&gt;Kubernetes has a lot of support and open-source tools to contribute to the cloud-native project. one of the scopes is the ingress, k8s has a support ingress, you might concern nginx ingress that a very famous ingress in k8s. azure has ingress to work well with an azure cloud environment, that is Application Gateway. The Application Gateway Ingress Controller allows &lt;a href="https://azure.microsoft.com/en-us/services/application-gateway/" rel="noopener noreferrer"&gt;Azure Application Gateway&lt;/a&gt; to be used as the ingress for an &lt;a href="https://azure.microsoft.com/en-us/services/kubernetes-service/" rel="noopener noreferrer"&gt;Azure Kubernetes Service&lt;/a&gt; aka AKS cluster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0enwbzigq2vb0aeujl1q.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0enwbzigq2vb0aeujl1q.jpg" alt="banner" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this guide, you'll learn how to configure Secure HTTP with Cert-Manager and AGIC. Before getting starting you should have the following requirements.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AKS Cluster&lt;/li&gt;
&lt;li&gt;Azure Subscriptions&lt;/li&gt;
&lt;li&gt;kubectl installed on your local machine&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 1 -- Create application gateway
&lt;/h3&gt;

&lt;p&gt;Create  public ip to used by application gateway as front end IP.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az network public-ip create &lt;span class="nt"&gt;-n&lt;/span&gt; myPublicIp &lt;span class="nt"&gt;-g&lt;/span&gt; myResourceGroup &lt;span class="nt"&gt;--allocation-method&lt;/span&gt; Static &lt;span class="nt"&gt;--sku&lt;/span&gt; Standard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create new subnet within AKS vnet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az network vnet subnet create &lt;span class="nt"&gt;-g&lt;/span&gt; MyResourceGroup &lt;span class="nt"&gt;--vnet-name&lt;/span&gt; MyVnet &lt;span class="nt"&gt;-n&lt;/span&gt; MySubnet &lt;span class="nt"&gt;--address-prefixes&lt;/span&gt; 10.226.0.0/24 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create Application gateway within AKS vnet, with different subnet. this guide you will create application gateway with Tier Standard, which is isn't act as WAF.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az network application-gateway create &lt;span class="nt"&gt;-n&lt;/span&gt; myApplicationGateway &lt;span class="nt"&gt;-l&lt;/span&gt; eastus &lt;span class="nt"&gt;-g&lt;/span&gt; myResourceGroup &lt;span class="nt"&gt;--sku&lt;/span&gt; Standard_v2 &lt;span class="nt"&gt;--public-ip-address&lt;/span&gt; myPublicIp &lt;span class="nt"&gt;--vnet-name&lt;/span&gt; myVnet &lt;span class="nt"&gt;--subnet&lt;/span&gt; mySubnet &lt;span class="nt"&gt;--priority&lt;/span&gt; 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2 -- Enable add-ons to AKS
&lt;/h3&gt;

&lt;p&gt;after success create app gateway, you need to enable the application gateway with AKS cluster,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;appgwId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;az network application-gateway show &lt;span class="nt"&gt;-n&lt;/span&gt; myApplicationGateway &lt;span class="nt"&gt;-g&lt;/span&gt; myResourceGroup &lt;span class="nt"&gt;-o&lt;/span&gt; tsv &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; 
az aks enable-addons &lt;span class="nt"&gt;-n&lt;/span&gt; myCluster &lt;span class="nt"&gt;-g&lt;/span&gt; myResourceGroup &lt;span class="nt"&gt;-a&lt;/span&gt; ingress-appgw &lt;span class="nt"&gt;--appgw-id&lt;/span&gt; &lt;span class="nv"&gt;$appgwId&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2 -- Deploy sample app
&lt;/h3&gt;

&lt;p&gt;Create deployment and service app, you will deploy sample HTML 5 game.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clumsy-bird&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clumsy-bird&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clumsy-bird&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clumsy-bird&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clumsy-bird&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bayhaqisptr/clumsy-bird:latest&lt;/span&gt;
        &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8001&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clumsy-service&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clumsy-service&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterIp&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8001&lt;/span&gt;
    &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clumsy-bird&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3 -- Create Ingress
&lt;/h3&gt;

&lt;p&gt;Create ingress, you might notice the annotations &lt;code&gt;kubernetes.io/ingress.class&lt;/code&gt; make sure its use &lt;code&gt;azure/application-gateway&lt;/code&gt; to tell AKS to use application gateway as Ingress.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Ingress&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clumsy-agic&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;kubernetes.io/ingress.class&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;azure/application-gateway&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;tls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;appgw-test.example.test&lt;/span&gt;
    &lt;span class="na"&gt;secretName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clumsy-tls&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;appgw-test.example.test&lt;/span&gt;
    &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
        &lt;span class="na"&gt;pathType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Prefix&lt;/span&gt;
        &lt;span class="na"&gt;backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clumsy-service&lt;/span&gt;
            &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8001&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4 -- Create Issuer (Staging)
&lt;/h3&gt;

&lt;p&gt;Create Issuer staging with Let's Encrypt with cert-manager&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cert-manager.io/v1&lt;/span&gt;
   &lt;span class="s"&gt;kind&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Issuer&lt;/span&gt;
   &lt;span class="s"&gt;metadata&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
     &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;letsencrypt-staging&lt;/span&gt;
   &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="na"&gt;acme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
       &lt;span class="c1"&gt;# The ACME server URL&lt;/span&gt;
       &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://acme-staging-v02.api.letsencrypt.org/directory&lt;/span&gt;
       &lt;span class="c1"&gt;# Email address used for ACME registration&lt;/span&gt;
       &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;user@example.com&lt;/span&gt;
       &lt;span class="c1"&gt;# Name of a secret used to store the ACME account private key&lt;/span&gt;
       &lt;span class="na"&gt;privateKeySecretRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
         &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;letsencrypt-staging&lt;/span&gt;
       &lt;span class="c1"&gt;# Enable the HTTP-01 challenge provider&lt;/span&gt;
       &lt;span class="na"&gt;solvers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
       &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;http01&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
           &lt;span class="na"&gt;ingress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
             &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;azure/application-gateway&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5 -- Create Issuer (Prod)
&lt;/h3&gt;

&lt;p&gt;Create Issuer staging with Let's Encrypt with cert-manager&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cert-manager.io/v1&lt;/span&gt;
   &lt;span class="s"&gt;kind&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Issuer&lt;/span&gt;
   &lt;span class="s"&gt;metadata&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
     &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;letsencrypt-prod&lt;/span&gt;
   &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="na"&gt;acme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
       &lt;span class="c1"&gt;# The ACME server URL&lt;/span&gt;
       &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://acme-v02.api.letsencrypt.org/directory&lt;/span&gt;
       &lt;span class="c1"&gt;# Email address used for ACME registration&lt;/span&gt;
       &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;user@example.com&lt;/span&gt;
       &lt;span class="c1"&gt;# Name of a secret used to store the ACME account private key&lt;/span&gt;
       &lt;span class="na"&gt;privateKeySecretRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
         &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;letsencrypt-prod&lt;/span&gt;
       &lt;span class="c1"&gt;# Enable the HTTP-01 challenge provider&lt;/span&gt;
       &lt;span class="na"&gt;solvers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
       &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;http01&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
           &lt;span class="na"&gt;ingress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
             &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;azure/application-gateway&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 6 -- Ingress TLS
&lt;/h3&gt;

&lt;p&gt;after success create issuer with cert-manager, you can enable https connection to handle acme challenge.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Ingress&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mokita-agic&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;kubernetes.io/ingress.class&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;azure/application-gateway&lt;/span&gt;
    &lt;span class="na"&gt;cert-manager.io/issuer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;letsencrypt-prod-agic&lt;/span&gt;
    &lt;span class="na"&gt;cert-manager.io/acme-challenge-type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http01&lt;/span&gt;
    &lt;span class="na"&gt;acme.cert-manager.io/http01-edit-in-place&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;tls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;appgw-test-16769.southeastasia.cloudapp.azure.com&lt;/span&gt;
    &lt;span class="na"&gt;secretName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mokita-agic&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;appgw-test-16769.southeastasia.cloudapp.azure.com&lt;/span&gt;
    &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
        &lt;span class="na"&gt;pathType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Prefix&lt;/span&gt;
        &lt;span class="na"&gt;backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mokita-service&lt;/span&gt;
            &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In Cloud Native world has many project available to explore. for example k8s has many ingress support to use, link nginx ingress, ingress nginx, kong, agic, etc.&lt;/p&gt;

&lt;p&gt;This guide cover some step to configure let's encrypt with agic ingress&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://azure.github.io/application-gateway-kubernetes-ingress/" rel="noopener noreferrer"&gt;https://azure.github.io/application-gateway-kubernetes-ingress/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cert-manager.io/docs/tutorials/acme/nginx-ingress/" rel="noopener noreferrer"&gt;https://cert-manager.io/docs/tutorials/acme/nginx-ingress/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>azure</category>
      <category>kubernetes</category>
      <category>cloudnative</category>
    </item>
    <item>
      <title>Rolling update in Kubernetes</title>
      <dc:creator>Ahmad Bayhaqi</dc:creator>
      <pubDate>Wed, 15 Feb 2023 08:42:07 +0000</pubDate>
      <link>https://dev.to/kyuubang/rolling-update-in-kubernetes-1oj0</link>
      <guid>https://dev.to/kyuubang/rolling-update-in-kubernetes-1oj0</guid>
      <description>&lt;p&gt;Rolling Update is a way of updating your application running in Kubernetes without causing downtime. It gradually replaces the old version with the new version one by one, so that users can still access the application while the update is happening. This makes updates more reliable and easier to manage, and helps ensure that your application remains available and responsive to users.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 -- Create deployment and Service
&lt;/h3&gt;

&lt;p&gt;create file named rolling-app.yaml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;cat &amp;gt; rolling-app.yaml &amp;lt;&amp;lt; EOF&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-app&lt;/span&gt;
 &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rolling&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
 &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
   &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-app&lt;/span&gt;
 &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
   &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
       &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-app&lt;/span&gt;
   &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
       &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
         &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bayhaqisptr/nginx-canary:v1&lt;/span&gt;
         &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
           &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
             &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
         &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
           &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
             &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;100m&lt;/span&gt;
             &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;50Mi&lt;/span&gt;
           &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
             &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;200m&lt;/span&gt;
             &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;100Mi&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-app&lt;/span&gt;
 &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rolling&lt;/span&gt;
 &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
   &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-app&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NodePort&lt;/span&gt;
 &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
   &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
   &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
 &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
   &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-app&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create namespace &lt;code&gt;rolling&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl create ns rolling
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and apply &lt;code&gt;rolling-app.yaml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; rolling-app.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2 -- Set image with another version tag
&lt;/h3&gt;

&lt;p&gt;use command &lt;code&gt;kubectl set image&lt;/code&gt; to set image in existing deployment&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;set &lt;/span&gt;image deployment.v1.apps/my-app my-app&lt;span class="o"&gt;=&lt;/span&gt;bayhaqisptr/nginx-canary:v2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;see rollout status with following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl rollout status deployments/my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;show available changes that made&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜  rolling kubectl rollout &lt;span class="nb"&gt;history &lt;/span&gt;deployment.apps/my-app &lt;span class="nt"&gt;-n&lt;/span&gt; rolling                               
deployment.apps/my-app 
REVISION  CHANGE-CAUSE
2         &amp;lt;none&amp;gt;
3         &amp;lt;none&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;check service will be responses with version 2&lt;/p&gt;

&lt;p&gt;access app with node ip and node port has been created&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜ curl 172.23.0.5:31374 
&amp;lt;html&amp;gt;
&amp;lt;h1&amp;gt;Hello World!&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;This is version 2&amp;lt;/p&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3 -- Rollback deployment
&lt;/h3&gt;

&lt;p&gt;rolling back to one previous version&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl rolling undo deployment/my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;rolling back to specific revisions&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl rolling undo deployment/my-app &lt;span class="nt"&gt;--revision&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>kubernetes</category>
      <category>deployment</category>
    </item>
    <item>
      <title>How to recreate MONs out of quorum on Ceph</title>
      <dc:creator>Ahmad Bayhaqi</dc:creator>
      <pubDate>Fri, 10 Feb 2023 03:16:41 +0000</pubDate>
      <link>https://dev.to/kyuubang/how-to-recreate-mons-out-of-quorum-on-ceph-1ic6</link>
      <guid>https://dev.to/kyuubang/how-to-recreate-mons-out-of-quorum-on-ceph-1ic6</guid>
      <description>&lt;p&gt;MONs are recommended to ensure fault tolerance and maintainability. If a cluster's MONs cannot form a quorum, which happens if not enough of the provisioned MONs are up, then new clients won't be able to connect to the system.&lt;/p&gt;

&lt;p&gt;quorum is fundamental to all consensus algorithms that are designed to&lt;br&gt;
access information in a fault-tolerant distributed system. Minimum number of votes achieve consensus among a set of nodes called quorum.&lt;/p&gt;

&lt;p&gt;Sometime you had Ceph MONs are down, and return &lt;code&gt;out of quorum&lt;/code&gt; status. This tutorial you will learn How to recreate MON daemon on Ceph.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyyew56m23b7dalkaw673.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyyew56m23b7dalkaw673.png" alt="preview" width="800" height="276"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1 -- Remove MONs
&lt;/h3&gt;

&lt;p&gt;first step you need to see the status of cluster. based on the information below, you have 1/3 mons down, and return &lt;code&gt;out of quorum&lt;/code&gt; status and everything else is safe.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ceph status
  cluster:
    &lt;span class="nb"&gt;id&lt;/span&gt;:     4664a822-3fac-11ed-b14c-5bcb09093cfa
    health: HEALTH_WARN
            1/3 mons down, quorum pod-bayhaqisptr04-ceph1,pod-bayhaqisptr04-ceph2

  services:
    mon: 3 daemons, quorum pod-bayhaqisptr04-ceph1,pod-bayhaqisptr04-ceph2 &lt;span class="o"&gt;(&lt;/span&gt;age 0.343641s&lt;span class="o"&gt;)&lt;/span&gt;, out of quorum: pod-bayhaqisptr04-ceph3
    mgr: pod-bayhaqisptr04-ceph1.ufgzyk&lt;span class="o"&gt;(&lt;/span&gt;active, since 3d&lt;span class="o"&gt;)&lt;/span&gt;, standbys: pod-bayhaqisptr04-ceph2.qcmvuo
    osd: 6 osds: 6 up &lt;span class="o"&gt;(&lt;/span&gt;since 117m&lt;span class="o"&gt;)&lt;/span&gt;, 6 &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;since 117m&lt;span class="o"&gt;)&lt;/span&gt;

  data:
    pools:   1 pools, 1 pgs
    objects: 2 objects, 449 KiB
    usage:   105 MiB used, 30 GiB / 30 GiB avail
    pgs:     1 active+clean
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you should remove mon from the ceph cluster. you can type with command below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ceph mon remove pod-bayhaqisptr04-ceph3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Info&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ID of MONs is ussually the host name that are provisioned daemon.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;after successful remove mon from cluster you need check again health. The Health will be OK. Because no one MONs down, you already remove it. health are OK but MON decrease 2 daemon in cluster&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ceph status
  cluster:
    &lt;span class="nb"&gt;id&lt;/span&gt;:     4664a822-3fac-11ed-b14c-5bcb09093cfa
    health: HEALTH_OK

  services:
    mon: 2 daemons, quorum pod-bayhaqisptr04-ceph1,pod-bayhaqisptr04-ceph2 &lt;span class="o"&gt;(&lt;/span&gt;age 3s&lt;span class="o"&gt;)&lt;/span&gt;
    mgr: pod-bayhaqisptr04-ceph1.ufgzyk&lt;span class="o"&gt;(&lt;/span&gt;active, since 3d&lt;span class="o"&gt;)&lt;/span&gt;, standbys: pod-bayhaqisptr04-ceph2.qcmvuo
    osd: 6 osds: 6 up &lt;span class="o"&gt;(&lt;/span&gt;since 2h&lt;span class="o"&gt;)&lt;/span&gt;, 6 &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;since 2h&lt;span class="o"&gt;)&lt;/span&gt;

  data:
    pools:   1 pools, 1 pgs
    objects: 2 objects, 449 KiB
    usage:   105 MiB used, 30 GiB / 30 GiB avail
    pgs:     1 active+clean
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2 -- Make sure daemon are removed on Node
&lt;/h3&gt;

&lt;p&gt;MONs might removed from cluster, but what about the Node itself? you need to checkout to host.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ssh ceph3
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;cephadm &lt;span class="nb"&gt;ls&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;mon
        &lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"mon.pod-bayhaqisptr04-ceph3"&lt;/span&gt;,
        &lt;span class="s2"&gt;"systemd_unit"&lt;/span&gt;: &lt;span class="s2"&gt;"ceph-4664a822-3fac-11ed-b14c-5bcb09093cfa@mon.pod-bayhaqisptr04-ceph3"&lt;/span&gt;,
        &lt;span class="s2"&gt;"service_name"&lt;/span&gt;: &lt;span class="s2"&gt;"mon"&lt;/span&gt;,
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if you see like this output that means daemon was stopped but daemon still registered on cephadm host. to remove it you can use rm-daemon subcommand on cephadm.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;cephadm rm-daemon &lt;span class="nt"&gt;--name&lt;/span&gt; mon.pod-bayhaqisptr04-ceph3 &lt;span class="nt"&gt;--fsid&lt;/span&gt; 35de853b-3a4e-4568-b698-f223c8382bb8 &lt;span class="nt"&gt;--force&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;after success remove, check again that are still available or not.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;cephadm &lt;span class="nb"&gt;ls&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;mon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to get your fsid use this command to grep you cluster id&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ceph status | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'/id:/ {print $2}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;it might take a few minutes to update entire database of cephadm before you can redeploy new Ceph MON&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 -- Redeploy Ceph MON
&lt;/h3&gt;

&lt;p&gt;after daemon are removed you need to redeploy daemon. to reliaze it you can set mon to unmanaged mode&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ceph orch apply mon &lt;span class="nt"&gt;--unmanaged&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and redeploy new daemon with given spesific host and address&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ceph orch daemon add mon pod-bayhaqisptr04-ceph3:10.9.9.30

Deployed mon.pod-bayhaqisptr04-ceph3 on host &lt;span class="s1"&gt;'pod-bayhaqisptr04-ceph3'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;verify its work properly&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ceph status

student@pod-bayhaqisptr04-ceph1:~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ceph status
  cluster:
    &lt;span class="nb"&gt;id&lt;/span&gt;:     4664a822-3fac-11ed-b14c-5bcb09093cfa
    health: HEALTH_OK

  services:
    mon: 3 daemons, quorum pod-bayhaqisptr04-ceph1,pod-bayhaqisptr04-ceph2,pod-bayhaqisptr04-ceph3 &lt;span class="o"&gt;(&lt;/span&gt;age 55s&lt;span class="o"&gt;)&lt;/span&gt;
    mgr: pod-bayhaqisptr04-ceph1.ufgzyk&lt;span class="o"&gt;(&lt;/span&gt;active, since 3d&lt;span class="o"&gt;)&lt;/span&gt;, standbys: pod-bayhaqisptr04-ceph2.qcmvuo
    osd: 6 osds: 6 up &lt;span class="o"&gt;(&lt;/span&gt;since 2h&lt;span class="o"&gt;)&lt;/span&gt;, 6 &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;since 2h&lt;span class="o"&gt;)&lt;/span&gt;

  data:
    pools:   1 pools, 1 pgs
    objects: 2 objects, 449 KiB
    usage:   105 MiB used, 30 GiB / 30 GiB avail
    pgs:     1 active+clean
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congrats! you have recreate and bringing up you Ceph MON.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;The ceph cluster uses several daemons to build its system. and registered on cluster and host itself. ceph mon is responsible for ensuring all daemons are in good working order.&lt;/p&gt;

&lt;p&gt;This guide cover some common cephadm command to operate remove daemon &lt;code&gt;cephadm rm-daemon&lt;/code&gt;, and also learn how to recreate it &lt;code&gt;ceph orch daemon add&lt;/code&gt;. the link below might be as useful reference&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.ceph.com/en/quincy/cephadm/services/mon/#deploying-monitors-on-a-particular-network" rel="noopener noreferrer"&gt;https://docs.ceph.com/en/quincy/cephadm/services/mon/#deploying-monitors-on-a-particular-network&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/69488109/how-to-restart-a-mon-in-a-ceph-cluster" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/69488109/how-to-restart-a-mon-in-a-ceph-cluster&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>discuss</category>
    </item>
  </channel>
</rss>
