<?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: iaps</title>
    <description>The latest articles on DEV Community by iaps (@eternaldstudent).</description>
    <link>https://dev.to/eternaldstudent</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1083478%2F74e90ff2-7063-424b-9e4d-0540bdf9ddf0.jpg</url>
      <title>DEV Community: iaps</title>
      <link>https://dev.to/eternaldstudent</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/eternaldstudent"/>
    <language>en</language>
    <item>
      <title>12 factor Microservice applications — on Kubernetes</title>
      <dc:creator>iaps</dc:creator>
      <pubDate>Wed, 01 Jul 2026 10:28:51 +0000</pubDate>
      <link>https://dev.to/eternaldstudent/12-factor-microservice-applications-on-kubernetes-3g76</link>
      <guid>https://dev.to/eternaldstudent/12-factor-microservice-applications-on-kubernetes-3g76</guid>
      <description>&lt;p&gt;The &lt;a href="https://12factor.net/" rel="noopener noreferrer"&gt;12-factor methodology&lt;/a&gt; has been widely adopted for building modern, scalable, maintainable applications. While there is a wealth of knowledge available on these principles, what’s often missing is practical guidance on implementing them in the context of microservices. This article aims to bridge that gap. We’ll explore how to utilize the 12-factor methodology for designing microservices, the tooling choices, and how to bootstrap a 12-factor microservice application(s) on Kubernetes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges and Goals
&lt;/h2&gt;

&lt;p&gt;Our goal is straightforward yet challenging: we aim to bootstrap a 12-factor microservice application(s) with a dashboard, and identify the leanest toolkit required for the task. The selected tools should align with the principles of the 12-factor methodology.&lt;/p&gt;

&lt;h2&gt;
  
  
  First Factor: Codebase
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;One codebase tracked in revision control, many deploys.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The first factor of the 12-factor methodology dictates that there should be “one codebase tracked in revision control, with many deploys”.&lt;/p&gt;

&lt;p&gt;To manage our Codebase we need a VCS! Version control systems (VCS) are integral to any modern software development process. They help teams manage changes to source code over time, allowing multiple people to collaborate, track modifications, and revert changes when necessary.&lt;/p&gt;

&lt;p&gt;When it comes to choosing the right VCS, there are several factors to consider, primary among them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Branching&lt;/strong&gt;: is a core feature of a version control system that allows developers to diverge from the main line of development and create isolated environments to work on features or fix bugs. Each branch represents an independent line of development that does not affect other branches, allowing many developers to work simultaneously on different features.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Actions and Workflows&lt;/strong&gt;: Branching becomes even more powerful when combined with a strategy, like Actions and/or Workflows. These strategies define a set of rules on how and which step functions are executed, when a codebase is committed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Other factors: Ease of use, community and support, and integrations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this purpose, we’re going to use Git, coupled with Git Actions and Git Workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Role of Git in Our Design
&lt;/h2&gt;

&lt;p&gt;In our design, both backend and frontend developers will utilize Git, and stretch it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backend&lt;/strong&gt; developers will write the business logic within application(s), which can be coded in any preferred language. The development process will involve&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;scaffolding the application on a “feature” environment,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;writing tests first (a practice referred to as Test-Driven Development or TDD),&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;writing the business logic (BL), and&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;finally submitting a Pull Request (PR).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Frontend&lt;/strong&gt; developers will follow a similar pattern, writing frontend business logic using APIs served by the application. Like the backend, frontend applications can be coded in any language, require scaffolding, and follow similar branch and promotion criteria.&lt;/p&gt;

&lt;p&gt;We’ll create a Git repository for each microservice and front-end application(s). This allows us to use branches like development, staging, and main (or feature branches, if necessary) for our development topology. Each microservice will have “deployment manifests” in addition to the actual source code. These manifests are necessary for deploying the application(s) to &lt;strong&gt;Kubernetes&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker and a Docker Registry
&lt;/h2&gt;

&lt;p&gt;A necessary diversion here to mention Docker and it’s Registry for hosting application images!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Docker&lt;/strong&gt; is an open-source platform designed to automate the deployment, scaling, and management of applications. It uses &lt;em&gt;containerization&lt;/em&gt; to encapsulate applications and their dependencies into a standardized unit for software development and ensures that the application runs seamlessly in any environment, whether it’s a local machine, a private data center, or the public cloud.&lt;/p&gt;

&lt;p&gt;Docker accomplishes this by using a lightweight container runtime that isolates the application’s processes from the rest of the system. Each Docker container runs independently and includes everything it needs to run the application: code, runtime, system tools, libraries, and settings.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;Docker Registry&lt;/strong&gt; is a storage and distribution system for named Docker images. These images are the building blocks of Docker &lt;em&gt;containers&lt;/em&gt;. They contain the application, its dependencies, and some metadata describing what the container should do when it’s run.&lt;/p&gt;

&lt;p&gt;Key features of any Docker Registry include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Version control&lt;/strong&gt;: Every time you push an image to the registry, it creates a new version. This allows you to roll back to an earlier version if necessary.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Access control&lt;/strong&gt;: You can control who has access to read from or write to your registry, and what they can do.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integration&lt;/strong&gt;: Docker registries can be integrated with your CI/CD pipeline, ensuring that the images used for deployment are always up to date.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If Docker images are the means for packaging software, then the next natural question is how will the docker images be deployed? How will they run in multiple envs; like stage, qa, production?&lt;/p&gt;

&lt;p&gt;Without a way to deploy the docker images (to run them as &lt;em&gt;containers&lt;/em&gt;) the images themselves are useless. So, what does it mean by “a way to deploy the docker images”?&lt;/p&gt;

&lt;h3&gt;
  
  
  Requirements for “A way to deploy docker images”
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;a way to specify where to run the docker images — a set of virtual machines on which the docker images will be deployed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a way to specify how to run the docker images — the resources required to run the image (ex. Memory/CPU/GPU, disk, etc.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a way to route traffic to the docker container (nginx-ingress)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a way to monitor if the docker container is healthy (health checks)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a way to restart the docker container if it fails/crashes (rollout, restarts)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a way to maintain a desired set of replicas of the container&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of the above features are bare minimum for the deployment of docker images successfully. This “way to deploy docker images” is called &lt;strong&gt;Container Orchestration&lt;/strong&gt;, and we use &lt;strong&gt;Kubernetes&lt;/strong&gt; for all this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Embracing Kubernetes
&lt;/h2&gt;

&lt;p&gt;In our design, we’ve chosen Kubernetes as the orchestration platform for our microservices. &lt;a href="https://kubernetes.io/" rel="noopener noreferrer"&gt;Kubernetes&lt;/a&gt; is an open-source system for automating the deployment, scaling, and management of containerized applications. It provides a platform to run distributed systems resiliently, scaling and recovering applications as needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Declarative Instructions
&lt;/h2&gt;

&lt;p&gt;Our application manifests are declarative YAML files that contain all the useful information about our microservices, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Application metadata (name, port)&lt;/strong&gt;: Helps identify the specific microservice from the pool.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Specs (replicas, image, resource limits, etc.)&lt;/strong&gt;: Provides sizing and scaling information.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ingress rules&lt;/strong&gt;: Establishes routing information to direct incoming requests to the correct API or frontend application.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’ll host our application manifests in a separate Git repository. This approach allows us to link the corresponding infrastructure repository with the repository containing the actual source code, providing a clean separation of concerns.&lt;/p&gt;

&lt;p&gt;Our directory structure for the customizable manifests will look 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;    ~/manifests-index develop &amp;gt; tree -L 1 infra/k8s   
    infra/k8s  
    ├── auth  
    ├── auth-mongo  
    ├── ingress  
    ├── kafka  
    ├── posts  
    └── posts-mongo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A Closer Look at Manifests
&lt;/h2&gt;

&lt;p&gt;Inside each of the folders designated for each microservice (or its associated database), we’ll keep customizable manifests for all our named environments with base specifications and overlays for development, staging, or any other (say feature).&lt;/p&gt;

&lt;p&gt;Design Decision: &lt;a href="https://kustomize.io/" rel="noopener noreferrer"&gt;Kustomize&lt;/a&gt; to build manifests&lt;/p&gt;

&lt;p&gt;We’ve chosen to use Kustomize to “build” our manifests, which offers a template-free way to customize application configuration. It allows us to create a base set of resources and apply a set of customizations as needed for each environment.&lt;/p&gt;

&lt;p&gt;Here’s what our Kustomize directory structure will look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    ~/manifests-index develop &amp;gt; tree -L 4 infra/k8s/auth  
    infra/k8s/auth  
    ├── README.md  
    ├── base  
    │   ├── deployment.yaml  
    │   ├── kustomization.yaml  
    │   └── service.yaml  
    └── overlays  
        └── development  
            ├── build-version-patch.yaml  
            └── kustomization.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the deployment, service and applied kustomization!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: auth-depl
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: auth
      template:
        metadata:
          labels:
            app: auth
        spec:
          containers:
            - name: auth
              image: xx-xxx-docker.pkg.dev/labs-xxxxx/auth/auth:development
              env: 
                - name: API_VERSION
                  value: 'v1'
                - name: MONGO_URI
                  value: 'mongodb://auth-mongo-srv:27017/auth'
                - name: JWT_KEY
                  valueFrom:
                    secretKeyRef:
                      name: jwt-secret
                      key: JWT_KEY  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: v1
    kind: Service
    metadata:
      name: auth-srv
    spec:
      selector:
        app: auth
      ports:
      - name: auth
        protocol: TCP
        port: 3000
        targetPort: 3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: kustomize.config.k8s.io/v1beta1
    kind: Kustomization

    bases:
      - ../../base

    namespace: development

    patchesStrategicMerge:
      - build-version-patch.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In affect kustomize build should fetch us all the deployment manifests for a microservice, for a named target environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kustomize build infra/k8s/&amp;lt;microservice&amp;gt;/overlays/&amp;lt;overlay&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kustomize build infra/k8s/auth/overlays/development
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why is there a &lt;code&gt;build-version-patch.yaml&lt;/code&gt; ? More on it later …&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Ingress and Kafka Manifests?
&lt;/h2&gt;

&lt;p&gt;We treat &lt;code&gt;ingress&lt;/code&gt; as an application to provide fine-grained routing control, allowing us to customize routing rules for any given branch or namespace.&lt;/p&gt;

&lt;p&gt;Treating &lt;code&gt;Kafka&lt;/code&gt; as an application allows us to boot up an instance of Kafka with all its topics per namespace (using &lt;a href="https://strimzi.io/" rel="noopener noreferrer"&gt;Strimzi&lt;/a&gt;, will do a post on it). This approach provides a scalable, distributed event streaming platform that our microservices can use for communication. However, note that hosting Kafka per namespace can get expensive, so larger teams may prefer to use a central development Kafka instance instead.&lt;/p&gt;

&lt;p&gt;Ingress and it’s base!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/_workspace/manifests-index develop &amp;gt; tree -L 3  infra/k8s/ingress 
    infra/k8s/ingress
    ├── README.md
    ├── argo
    │   ├── base
    │   │   ├── application.yaml
    │   │   └── kustomization.yaml
    │   └── overlays
    │       └── development
    ├── base
    │   ├── ingress-srv.yaml
    │   └── kustomization.yaml
    └── overlays
        └── development
            └── kustomization.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: ingress-service
      annotations:
        kubernetes.io/ingress.class: nginx
        nginx.ingress.kubernetes.io/use-regex: "true"
    spec:
      rules:
        - host: dev.xxxx.io
          http:
            paths:
              - path: /api/v1/users/?(.*)
                pathType: Prefix
                backend:
                  service:
                    name: auth-srv
                    port:
                      number: 3000
              - path: /api/v1/posts/?(.*)
                pathType: Prefix
                backend:
                  service:
                    name: posts-srv
                    port:
                      number: 3000
              - path: /?(.*)
                pathType: Prefix
                backend:
                  service:
                    name: dashboard
                    port:
                      number: 80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kafka and it’s base!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/_workspace/manifests-index develop &amp;gt; tree -L 3  infra/k8s/kafka
    infra/k8s/kafka
    ├── argo
    │   ├── README.md
    │   ├── base
    │   │   ├── application.yaml
    │   │   └── kustomization.yaml
    │   └── overlays
    │       └── development
    ├── base
    │   ├── deployment.yaml
    │   ├── kustomization.yaml
    │   └── topics.yaml
    └── overlays
        └── development
            └── kustomization.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    metadata:
      name: kafka-cluster
    spec:
      kafka:
        version: 3.3.1
        replicas: 1
        listeners:
          - name: plain
            port: 9092
            type: internal
            tls: false
          - name: tls
            port: 9093
            type: internal
            tls: true
        config:
          offsets.topic.replication.factor: 1
          transaction.state.log.replication.factor: 1
          transaction.state.log.min.isr: 1
          default.replication.factor: 1
          min.insync.replicas: 1
          inter.broker.protocol.version: "3.3"
        storage:
          type: ephemeral
      zookeeper:
        replicas: 3
        storage:
          type: ephemeral
      entityOperator:
        topicOperator: {}
        userOperator: {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we are using Strimzi as our Kafka orchestrator per namespace, a benefit accrued is that we can have unique topics per developer requirement!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaTopic
    metadata:
      name: comment
      labels:
        strimzi.io/cluster: kafka-cluster
    spec:
      partitions: 1
      replicas: 1
      config:
        retention.ms: 900000
        segment.bytes: 1073741824
    ---
    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaTopic
    metadata:
      name: post
      labels:
        strimzi.io/cluster: kafka-cluster
    spec:
      partitions: 1
      replicas: 1
      config:
        retention.ms: 900000
        segment.bytes: 1073741824
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Index Repository Overview
&lt;/h2&gt;

&lt;p&gt;Here is what it looks like …&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/manifests-index develop &amp;gt; tree -L 1
    .
    ├── README.md
    ├── auth
    ├── infra
    ├── npm-commons
    ├── posts
    ├── frontend
    ├── .gitignore
    └── skaffold.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;auth&lt;/code&gt; and &lt;code&gt;posts&lt;/code&gt; directories are dedicated repositories for the authentication and posts microservices.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;npm-commons&lt;/code&gt; is a node commons library with shared middlewares, events, errors among others.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;there are frontend applications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;and there’s scaffolding instructions in &lt;code&gt;skaffold.yaml&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a &lt;code&gt;.gitignore&lt;/code&gt; which excludes all except the &lt;code&gt;infra&lt;/code&gt; and &lt;code&gt;skaffold&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Can do a detailed post on this section, if enough votes!&lt;/p&gt;

&lt;h2&gt;
  
  
  Scaffolding with Skaffold
&lt;/h2&gt;

&lt;p&gt;In our design, developers (whether backend or frontend) will use &lt;a href="https://skaffold.dev/" rel="noopener noreferrer"&gt;Skaffold&lt;/a&gt; to bootstrap an environment for their work. Skaffold is a command-line tool that facilitates continuous development for Kubernetes applications.&lt;/p&gt;

&lt;p&gt;Here’s an example of our Skaffold configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: skaffold/v2beta29
    kind: Config
    deploy:
      kubectl: 
        manifests:
          - ./infra/k8s/auth/overlays/"{{.IMAGE_TAG}}"
          - ./infra/k8s/posts/overlays/"{{.IMAGE_TAG}}"
    build:
        tagPolicy:
          envTemplate:
            template: "{{.IMAGE_TAG}}"
      artifacts:
        - image: xx-xxx-docker.pkg.dev/labs-xxxxx/auth/auth
          context: auth
          docker:
            dockerfile: Dockerfile
          sync:
           manual:
             - dest: .
               src: 'src/**/*.ts'
        - image: xx-xxx-docker.pkg.dev/labs-xxxxx/posts/posts
          context: posts
          docker:
            dockerfile: Dockerfile
          sync:
           manual:
             - dest: .
               src: 'src/**/*.ts'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;IMAGE_TAG&lt;/code&gt; environment variable, helps skaffold identify the namespace to deploy to.&lt;/p&gt;

&lt;p&gt;Let’s create a namespace eg: &lt;code&gt;development&lt;/code&gt; , and export an &lt;code&gt;IMAGE_TAG&lt;/code&gt; environment variable also as &lt;code&gt;development&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create namespace development
export IMAGE_TAG=development
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From here on a simple &lt;code&gt;skaffold dev&lt;/code&gt; will bring up the development environment.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Git Workflow and IAM Considerations
&lt;/h2&gt;

&lt;p&gt;One of our Git Workflows will include steps for&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;cloning the manifests repository,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;substituting variables in our manifest files, and&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;commit to the index reconciliation repository.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will also include IAM considerations and use organization repository secrets for managing sensitive data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;commit:
        name: Commit to Reconciliation repository
        needs: [build-and-push]
        runs-on: ubuntu-latest
        if: ${{ needs.build-and-push.result == 'success' }}
        steps:
          - name: Echo
            id: echo-sha
            run: |
              echo "github_sha: " $GITHUB_SHA 
              echo "::set-output name=sha_short::${GITHUB_SHA::7}"
          - name: Clone
            run: |
              git config --global user.email ${{ secrets.GH_USER_EMAIL }}
              git config --global user.name ${{ secrets.GH_USER_NAME }}
              git clone -b develop https://.:${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}@github.com/&amp;lt;your-org&amp;gt;/manifests-index.git
              echo "clone repo success"
          - name: Substitute
            run: |
              sed -i "s/value.*$/value\: $GITHUB_SHA/"  manifests-index/infra/k8s/&amp;lt;microservice&amp;gt;/overlays/development/deploy-version-patch.yaml
          - name: Commit
            run: |
              cd manifests-index &amp;amp;&amp;amp; git add . &amp;amp;&amp;amp; git commit -m '${{ github.event.repository.name }} updated with ${{ steps.echo-sha.outputs.sha_short }} on branch ${{ github.head_ref }}' &amp;amp;&amp;amp; git push origin develop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another workflow will build and push docker images!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;env:
      PROJECT_ID: ${{ secrets.GKE_PROJECT }}
      REGION: ${{ secrets.GKE_REGION }}
      IMAGE_NAME: auth #Rule: same as repository name
      IMAGE_TAG: development #${{ github.sha }} #Rule: same as branch name
      GCP_SA_KEY: ${{ secrets.GCP_SA_KEY }} # reqd for update docker image to ggl Artifact Repository

    jobs:
      build-and-push:
        runs-on: ubuntu-latest

        # Add "id-token" with the intended permissions.
        permissions:
          contents: 'read'
          id-token: 'write'

        steps:
        - name: Checkout code
          uses: actions/checkout@v3

        # Authentication for gcloud Artifact Registry via credentials json
        - id: 'auth'
          uses: 'google-github-actions/auth@v1'
          with:
            credentials_json: '${{ secrets.GCP_SA_KEY }}'

        # Setup gcloud
        - name: Set up Google Cloud SDK
          uses: google-github-actions/setup-gcloud@v1
          with:
            project_id: ${{ env.PROJECT_ID }}
            service_account_key: ${{ env.GCP_SA_KEY }}
            export_default_credentials: true

        - name: Configure Docker
          run: |
            gcloud auth configure-docker

        - name: Configure Artifact Registry
          run: |
            gcloud auth configure-docker \
            ${{ env.REGION }}-docker.pkg.dev

        - name: Build and push Docker
          uses: docker/build-push-action@v2
          with:
            push: true
            tags: ${{ env.REGION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/${{ env.IMAGE_NAME }}/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Application Reconciliation and Achieving “One Codebase, Many Deploys”
&lt;/h2&gt;

&lt;p&gt;Why is there a &lt;code&gt;build-version-patch.yaml&lt;/code&gt; ?&lt;/p&gt;

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

&lt;p&gt;With every successful build of any application, we will patch the build version on the named overlay, triggering application reconciliation. This process ensures that the desired state of our application defined in the Git repository matches the actual state in our environment. It plays a significant role in achieving the “one codebase, many deploys” principle of the 12-factor methodology.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- name: Substitute
      run: |
        sed -i "s/value.*$/value\: $GITHUB_SHA/"  manifests-index/infra/k8s/&amp;lt;microservice&amp;gt;/overlays/&amp;lt;overlay&amp;gt;/deploy-version-patch.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Administration and ArgoCD
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://argo-cd.readthedocs.io/en/stable/" rel="noopener noreferrer"&gt;ArgoCD&lt;/a&gt;, a declarative, GitOps continuous delivery tool for Kubernetes, will also play a crucial part in our setup. We will install and configure ArgoCD as per the official documentation and create an application for each of our microservices in ArgoCD.&lt;/p&gt;

&lt;p&gt;ArgoCD configuration will look like this, eg auth:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: argoproj.io/v1alpha1  
    kind: Application  
    metadata:  
      name: auth  
    spec:  
      destination:  
        namespace: development  
        server: https://kubernetes.default.svc  
      source:  
        repoURL: https://github.com/&amp;lt;your-org&amp;gt;/manifests-index.git  
        targetRevision: develop  
        path: infra/k8s/auth/overlays/development  
      project: default  
      syncPolicy:  
        automated: {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this manifest too can be included in our index&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/_workspace/manifests-index develop &amp;gt; tree -L 4 infra/k8s/auth  
    infra/k8s/auth  
    ├── README.md  
    ├── argo  
    │   ├── README.md  
    │   ├── base  
    │   │   ├── application.yaml  
    │   │   └── kustomization.yaml  
    │   └── overlays  
    │       └── development  
    │           └── kustomization.yaml  
    ├── base  
    │   ├── deployment.yaml  
    │   ├── kustomization.yaml  
    │   └── service.yaml  
    └── overlays  
        └── development  
            ├── build-version-patch.yaml  
            └── kustomization.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And from now on, an argo specific &lt;code&gt;kustomize build&lt;/code&gt; will generate the argo manifest for an application. Automate everything!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kustomize build infra/k8s/&amp;lt;microservice&amp;gt;/argo/overlays/&amp;lt;overlay&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kustomize build infra/k8s/auth/argo/overlays/development
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that &lt;a href="https://fluxcd.io/" rel="noopener noreferrer"&gt;FluxCD&lt;/a&gt; is a powerful alternative!&lt;/p&gt;

&lt;h2&gt;
  
  
  Templating for Automation
&lt;/h2&gt;

&lt;p&gt;It’s a good practice to templatize the primary manifests, to facilitate future automation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/_workspace/manifests-index develop &amp;gt; tree -L 3  infra/templates  
    infra/templates
    ├── application.yaml
    ├── deployment.yaml
    ├── ingress.yaml
    └── service.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Phew! That was just one of the 12-factors! and how we could use Git creatively for our &lt;strong&gt;Codebase&lt;/strong&gt;. Stay tuned for the next 11!&lt;/p&gt;

&lt;p&gt;Did we achieve “one codebase many deploys”? And which tools did we add to our hip belt?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you wish to make an apple pie from scratch, you must first invent the universe.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Carl Sagan meant it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up and Looking Ahead
&lt;/h2&gt;

&lt;p&gt;In this blog post, we’ve journeyed through the practical implementation of (the first factor?) 12-factor microservices applications on Kubernetes. We’ve examined the intricacies of using Git as a version control system, discussed the significance of Docker and its registry, and emphasized the role of Kubernetes in the deployment of Docker images. All these components come together to create a solid foundation for the development, deployment, and management of microservices.&lt;/p&gt;

&lt;p&gt;We’ve also shed light on the importance of a streamlined Git workflow, the judicious use of Git branches, the interplay between Docker images and Kubernetes, and the critical role of container orchestration. We’ve highlighted the leanest toolkit required to bootstrap a 12-factor microservice application, underscoring the significance of each tool in the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;As next steps, I encourage you to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Experiment&lt;/strong&gt;: Apply these principles and tools to your own projects. There’s no better way to understand these concepts than by putting them to use.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Expand your knowledge&lt;/strong&gt;: Dive deeper into each tool and technology we’ve discussed. Each one has much more to offer than what we’ve been able to cover in this post.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stay updated&lt;/strong&gt;: The cloud-native ecosystem is rapidly changing. Keep an eye on new developments, and don’t hesitate to explore new tools and practices that could improve your development workflow.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Remember, the ultimate goal is to build applications that are scalable, maintainable, and resilient. The tools and practices we’ve discussed here are a means to that end. Happy coding! Do reach out with questions!&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
