🚀 Executive Summary

TL;DR: Creating Kubernetes manifests for new microservices often leads to error-prone copy-pasting and configuration drift due to raw YAML’s lack of reusability. The article outlines a progression from manual grunt work to robust templating with Helm or Kustomize, ultimately advocating for a self-service platform to abstract Kubernetes entirely from developers, enhancing consistency and velocity.

🎯 Key Takeaways

  • Raw Kubernetes YAML is inherently not designed for reusability, leading to significant ‘configuration drift’ and error-prone manual copy-pasting when deploying new microservices.
  • Templating solutions like Helm and Kustomize provide a scalable approach by abstracting common Kubernetes patterns into reusable charts or bases, allowing developers to define services through simple `values.yaml` files.
  • The ‘Platform Engineering’ endgame involves building a self-service tool (e.g., web UI or CLI) that fully abstracts Kubernetes manifest generation, automating boilerplate code and CI/CD setup, significantly boosting developer velocity and operational consistency.

Writing K8s manifests for a new microservice — what's your team's actual process?

Struggling with creating Kubernetes manifests for new microservices? This guide explores the common pitfalls and offers three battle-tested strategies, from quick-and-dirty copy-pasting to robust templating with Helm and building a self-service platform.

So, You Need K8s Manifests for a New Microservice? Let’s Talk Process.

I still remember the pager going off at 2 AM. A junior engineer, let’s call him Alex, had just deployed his first new microservice, the `notification-service`. Except, he hadn’t. He’d accidentally re-deployed the `auth-service` with the notification image because he copy-pasted the manifests and forgot to change the `metadata.name` field. For ten minutes, every login attempt on our platform failed. It was a simple, innocent mistake born from a broken process, and it taught me a valuable lesson: how your team creates Kubernetes manifests is one of the most critical, and often overlooked, parts of your delivery pipeline.

The “Why”: YAML is a Liar

The root of the problem isn’t that developers are careless. The problem is that raw Kubernetes YAML, while declarative and powerful, isn’t designed for reusability. It encourages the exact opposite: you end up with dozens of files (`deployment.yaml`, `service.yaml`, `ingress.yaml`, `hpa.yaml`…) for every single microservice. Each file is 90% boilerplate and 10% unique configuration. This leads to what I call “configuration drift,” where subtle differences between services creep in, making the whole system brittle and impossible to manage at scale.

So, when a developer is tasked with spinning up a new service, what’s their path of least resistance? Find the closest existing service, copy the whole directory, and start a painstaking `CTRL+F` marathon. That’s not a process; it’s a liability waiting for a 2 AM wake-up call.

The Fixes: From Field Expedient to Future-Proof

Over the years, my teams and I have been through the wringer on this. We’ve settled on a few patterns that work. Let’s break them down from the quick-and-dirty to the truly scalable.

Solution 1: The “Honest Grunt Work” (Copy-Paste-Pray)

Let’s be honest, we’ve all done it. You’re in a hurry, it’s just one service, and you’re not ready to boil the ocean. You `cp -r ../auth-service ./new-shiny-service` and get to work.

The Process:

  1. Find a similar, existing service’s manifest directory.
  2. Copy it wholesale.
  3. Painstakingly go through every file and change names, labels, image paths, resource limits, config map names, and port numbers.
  4. Pray you didn’t miss one.

Here’s a tiny snippet of what you’re up against in just one file:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: auth-service-v1 # <-- CHANGE THIS
  labels:
    app: auth-service # <-- CHANGE THIS
spec:
  replicas: 3
  selector:
    matchLabels:
      app: auth-service # <-- AND THIS
  template:
    metadata:
      labels:
        app: auth-service # <-- AND THIS
    spec:
      containers:
      - name: auth-service-container # <-- AND THIS
        image: our-registry/auth-service:1.4.2 # <-- AND THIS
        ports:
        - containerPort: 8080
        resources:
          limits:
            cpu: "500m"
            memory: "512Mi"
          requests:
            cpu: "250m"
            memory: "256Mi"

Pro Tip: This method is acceptable only if you have one or two services total. The moment you have a third, you’ve created a technical debt bomb. It’s not scalable, it’s error-prone, and it guarantees that `prod-db-01` and `prod-db-02` will have slightly different resource limits for no good reason. Use this as a stopgap, not a strategy.

Solution 2: The “Sensible Architect” (Templating with Helm/Kustomize)

This is where most professional teams should be. Instead of copying manifests, you create an abstraction—a template or a set of bases—that represents a “standard microservice” at your company. Developers then only need to provide the values that are unique to their service.

My teams have had great success with Helm. We create a “company-standard” chart that handles the Deployment, Service, Ingress, and HPA. When a developer needs a new service, they don’t touch any YAML manifests. They just create a single `values.yaml` file.

The Process:

  1. The DevOps/Platform team maintains a central Helm chart for your standard application pattern.
  2. The developer creates a new `values.yaml` file for their microservice.
  3. The CI/CD pipeline runs `helm template` or `helm install` using the central chart and the service-specific values file to generate the final manifests.

The developer’s entire contribution might look like this:

# values.yaml for 'billing-service'
replicaCount: 2

image:
  repository: our-registry/billing-service
  tag: "1.0.0"

service:
  port: 80
  targetPort: 3000

ingress:
  enabled: true
  hosts:
    - billing.techresolve.com

resources:
  limits:
    cpu: "1"
    memory: "1Gi"
  requests:
    cpu: "500m"
    memory: "512Mi"

Here’s a quick comparison of the two main players in this space:

Tool Pros Cons
Helm Powerful templating (Go templates), package management, hooks, and a huge public chart ecosystem. Great for complex logic. Can feel complex (Tiller in older versions, Go templating syntax). Sometimes feels like “programming in YAML”.
Kustomize YAML-native (no new language), patch-based system is very explicit. Built into `kubectl`. Simpler to start with. Less powerful for complex logic/conditionals. Can lead to a confusing web of overlays and bases if not managed well.

Warning: The biggest failure mode here is creating a “god chart” with a million `if/else` conditions. Keep your chart focused on the 80% use case. If a service is a special snowflake, let it be its own chart or use Kustomize patches; don’t ruin the simplicity of the main template for one edge case.

Solution 3: The “Platform Engineering” Endgame (Self-Service)

This is the holy grail for organizations with dozens or hundreds of microservices. At this scale, even creating a `values.yaml` file is too much friction. The goal here is to abstract Kubernetes away from the developer entirely.

The Process:

  1. The Platform team builds a service, often a web UI (like Backstage) or a custom CLI tool.
  2. A developer runs a command like `tr-cli service create –name=inventory-service –language=go`.
  3. The tool asks a few simple questions: “What team owns this?”, “What port does it listen on?”.
  4. Behind the scenes, the tool scaffolds a new Git repo with boilerplate code, creates the CI/CD pipeline, and generates the necessary `values.yaml` (or Kustomize overlays) from its internal templates. The developer never even sees the Kubernetes manifests.

This approach treats your platform as a product. It’s a massive investment in tooling and people, but the payoff in developer velocity and operational consistency is equally massive. It codifies your best practices and makes doing the “right thing” the “easy thing”.

My Final Take

If you’re just starting, it’s okay to do the grunt work for your first couple of services. But have a plan to move to Solution 2 as soon as possible. Templating is the sweet spot for most companies. It balances power, flexibility, and maintainability perfectly. Don’t let your team drown in a sea of copy-pasted YAML. Your on-call engineers, and your future self, will thank you.

Darian Vance - Lead Cloud Architect

Darian Vance

Lead Cloud Architect & DevOps Strategist

With over 12 years in system architecture and automation, Darian specializes in simplifying complex cloud infrastructures. An advocate for open-source solutions, he founded TechResolve to provide engineers with actionable, battle-tested troubleshooting guides and robust software alternatives.


🤖 Frequently Asked Questions

❓ What are the primary issues with manually creating Kubernetes manifests for new microservices?

Manually creating manifests often leads to extensive copy-pasting, which is error-prone and causes ‘configuration drift’ where subtle differences between services accumulate, making the system brittle and difficult to manage at scale.

❓ How do Helm and Kustomize differ as templating solutions for Kubernetes manifests?

Helm offers powerful templating using Go templates, package management, and a vast chart ecosystem, ideal for complex logic. Kustomize is YAML-native, patch-based, built into `kubectl`, and simpler for explicit modifications, but less powerful for complex conditionals.

❓ What is a common pitfall when implementing a company-standard Helm chart?

A common pitfall is creating an overly complex ‘god chart’ with too many `if/else` conditions to cover every edge case. This undermines the chart’s simplicity and maintainability; it’s better to keep charts focused on the 80% use case and handle special snowflakes separately.

Leave a Reply

Discover more from TechResolve - SaaS Troubleshooting & Software Alternatives

Subscribe now to keep reading and get access to the full archive.

Continue reading