CI/CD Pipeline Integration in Kubernetes

CI/CD Pipeline Integration in Kubernetes

A plain-English, production-minded guide to getting code from a developer's laptop into a running cluster safely, repeatedly and without late-night heroics.

Imagine a bakery that makes one special cake a day. The baker mixes everything by hand, carries the cake to the shop window, and hopes nobody notices the missing sugar. Now imagine the same bakery growing into a business that ships a thousand cakes a day to fifty shops. Hand-carrying cakes no longer works. You need a conveyor belt: ingredients are checked, the cake is baked the same way every time, a taster approves it, and a van delivers it, with a quick way to pull a bad batch back from the shelves.

Software teams face the very same step-up. A small app can be copied to a server by hand. A busy product that changes dozens of times a day, running as many containers across many machines, cannot. That conveyor belt is called a CI/CD pipeline, and Kubernetes is the place where its finished packages are delivered and kept running. This guide explains how the two fit together, what happens inside each step, and how to build a pipeline that teams can trust.

1Why Shipping Software Needs a Pipeline

Before any tool, feel the pain that pipelines remove.

Without a pipeline, releasing software is a ceremony. Someone builds the program on their own laptop. Someone else logs in to a server and copies files. A third person remembers a special command that only works on Tuesdays. Every step depends on human memory, and humans forget. The result is that releases are rare, scary and slow, so changes pile up, and the bigger the pile, the more likely something inside it is broken.

A pipeline turns that ceremony into a boring routine. The steps are written down as code. They run the same way each time, on a clean machine, with nobody typing secret commands. When something fails, it fails early and loudly, on a small change that is easy to understand, instead of quietly in front of customers.

Three terms people mix up

  • Continuous Integration (CI). Every time a developer shares a change, the system automatically builds the software and runs tests. The goal is to learn within minutes whether the change breaks anything.
  • Continuous Delivery (CD). Every change that passes the tests is automatically prepared and made ready to release. A human still presses the final button.
  • Continuous Deployment. The same as delivery, except the final button is pressed by the system. Every passing change goes live on its own.
flowchart LR
  A["Developer writes code"] --> B["Change shared in Git"]
  B --> C["CI builds and tests"]
  C --> D["Package stored in a registry"]
  D --> E["CD updates the cluster"]
  E --> F["Users get the new version"]
  F --> G["Monitoring gives feedback"]
  G --> A
    
Figure 1: The delivery loop from idea to customer and back again.
Everyday Analogy

Think of a school exam system. Small weekly quizzes (CI) tell students quickly where they are weak, so problems are fixed early. The final exam and the certificate (CD) confirm that the student is ready to move up. Nobody waits until the last day of the year to find out that the whole subject was misunderstood.

Minutes
target time to learn if a change is broken
Same steps
every run, on a clean machine, every time
Small batches
small changes are easier to test and undo
i
Remember

A pipeline is not a tool you buy. It is an agreement, written as code, about how software travels from a commit to a customer.

2Core Concepts From Zero

A short dictionary. Once these words feel friendly, every later chapter is easy.

Concept

Commit

A saved snapshot of changes in a version control system such as Git. Every pipeline run starts from one.

Concept

Build

The step that turns source code into something runnable, such as a compiled program or a packaged application.

Concept

Container Image

A sealed package holding your program and everything it needs to run. The same image behaves the same on any machine.

Concept

Registry

A storage service for container images, like a warehouse where finished packages wait to be shipped.

Concept

Manifest

A text file describing what you want Kubernetes to run: which image, how many copies, which settings.

Concept

Pipeline

An ordered set of automated stages that a change must pass on its way to production.

Concept

Runner or Agent

The worker machine or container that actually executes the pipeline steps.

Concept

Environment

A separate place where software runs, such as development, staging and production, each with its own settings.

Two ideas worth tattooing on your brain

The first is immutability. A container image should never be changed after it is built. If something needs to change, you build a new image with a new label. The image that passed testing is then the exact same image that goes to production, not a lookalike built later.

The second is declarative configuration. In Kubernetes you do not tell the cluster to “start three servers, then connect them”. You describe the end state you want, “three copies of this image, reachable on this address”, and Kubernetes keeps working until reality matches the description. A pipeline’s job is therefore not to run a long list of commands inside the cluster. Its job is to change the description, and let Kubernetes do the rest.

Everyday Analogy

A manifest is like a restaurant order slip, not a cooking lesson. You write “two pizzas, no onions” and hand it to the kitchen. You do not stand behind the cook explaining how to stretch the dough. If a pizza falls on the floor, the kitchen makes another to match the slip.

!
Watch Out

“Works on my machine” is the most expensive sentence in software. Containers and pipelines exist so that the machine on which it works is the same one on which it ships.

3The Kubernetes Pieces a Pipeline Touches

You do not need to master Kubernetes to build a pipeline, but you must know which objects the pipeline will change.

ObjectWhat it isWhy a pipeline cares
PodThe smallest running unit, holding one or more containersWhere your new image finally runs
DeploymentA controller that keeps a chosen number of identical pods running and replaces them graduallyThe most common thing a pipeline updates
ReplicaSetA helper made by a Deployment, one per versionOld ones are kept so rollback is fast
ServiceA stable address in front of changing podsLets users reach the app while pods are replaced
Ingress or GatewayRules that bring outside traffic into ServicesUsed for canary and blue-green traffic shifts
ConfigMap and SecretSettings and sensitive values given to podsDiffer per environment, must be delivered safely
NamespaceA named room inside a clusterOften one per team, environment or preview build
ServiceAccount and RBACIdentities and permissions inside the clusterDecide what a pipeline is allowed to change
Job and CronJobOne-off and scheduled tasksUsed for migrations and post-deploy checks

The Deployment is the star

When a pipeline “deploys” an application, it usually just changes one line in a Deployment: the name of the image. Kubernetes notices the difference between the old description and the new one, creates a new ReplicaSet for the new version, starts new pods, waits until they are healthy, and stops the old ones step by step. Your users keep getting answers during the whole process. That gentle swap is called a rolling update, and we study it closely in a later chapter.

The cluster has a front door

Anyone or anything that changes the cluster talks to the Kubernetes API server. A person uses a command-line tool, a pipeline uses a service account, and a GitOps agent uses its own identity. All of them go through the same checks: who are you, and are you allowed to do this? That is why permissions matter so much, a topic we return to in the security chapters.

Everyday Analogy

A Deployment is a shift manager at a call centre. You tell the manager, “I want ten agents on the phones, all using the new script.” The manager brings in agents using the new script a few at a time, sends old-script agents home once the new ones are ready, and never leaves the phones unattended.

i
Good to Know

Everything in Kubernetes is an object with a name, a description and a status. Pipelines work by editing descriptions and reading statuses. Learn to read the status of a Deployment and you can tell almost instantly whether a release is healthy.

4Architecture of a Delivery Pipeline

Every pipeline, however fancy, is built from the same handful of building blocks.

The picture below shows a typical modern setup. A developer pushes code to a Git host. A CI system notices, builds and tests the code, and stores a new image in a registry. A second repository holds the cluster descriptions. The pipeline, or a tool living inside the cluster, updates those descriptions. The cluster then pulls the new image and rolls it out.

flowchart LR
  DEV["Developer"] -->|"push code"| GIT["App Git repository"]
  GIT -->|"webhook"| CI["CI system and runners"]
  CI -->|"test and build"| REG["Container registry"]
  CI -->|"update image tag"| CFG["Config Git repository"]
  CFG -->|"watched by"| CD["CD controller"]
  CD -->|"apply desired state"| API["Kubernetes API server"]
  API --> NODES["Worker nodes run pods"]
  NODES -->|"pull image"| REG
  NODES -->|"metrics and logs"| OBS["Monitoring and alerts"]
    
Figure 2: One common pipeline architecture, with separate code and config repositories.

The building blocks

Block

Source Control

Holds code and configuration, records who changed what, and triggers pipelines through webhooks.

Block

CI System

Runs the build and test steps on clean workers each time a change arrives.

Block

Artifact Registry

Stores images and other build outputs with versions, so any release can be found again.

Block

Config Repository

Holds the manifests that describe what each environment should run.

Block

CD Engine

Pushes or pulls the described state into the cluster, and reports whether it worked.

Block

Policy Layer

Rules that block unsafe changes, such as unsigned images or containers running as the root user.

Block

Secrets Store

A safe place for passwords and keys, so they never live inside code.

Block

Observability

Metrics, logs and alerts that show whether a release is healthy after it lands.

Why two repositories?

Many teams keep application code in one repository and deployment descriptions in another. The reason is simple. Code changes constantly and is reviewed by developers. Deployment descriptions change when releasing, scaling or fixing configuration, and may need approval from operations or security staff. Separate repositories keep these conversations apart, and make it easier to give each group the right permissions. Smaller teams often keep both together at first, and that works too.

Everyday Analogy

Picture a publishing house. Authors write manuscripts (code). A printing press (CI) turns manuscripts into books (images). A warehouse (registry) stores them. A shipping schedule (config repository) says which bookshops get which edition, and delivery trucks (CD) follow that schedule exactly. The author does not drive the truck.

5Continuous Integration, Stage by Stage

The first half of the pipeline answers one question: is this change good enough to package?

flowchart TD
  A["Commit arrives"] --> B["Check out the code"]
  B --> C["Static checks and lint"]
  C --> D["Unit tests"]
  D --> E["Build container image"]
  E --> F["Scan image and dependencies"]
  F --> G{"All checks passed?"}
  G -->|"No"| H["Fail fast and notify the author"]
  G -->|"Yes"| I["Push image to registry"]
  I --> J["Sign image and record details"]
    
Figure 3: A typical CI flow. Cheap, fast checks come first.
1

Check out the code

The runner downloads exactly the commit that triggered the run, so results are tied to one precise version.

2

Static checks

Formatters and linters catch style problems and obvious mistakes in seconds, without running anything.

3

Unit tests

Small, quick tests check individual pieces of logic. They should finish in a few minutes at most.

4

Build the image

The application is packaged into a container image using a recipe file, and labelled with a unique tag.

5

Scan

Tools look for known security problems in libraries and the base operating system inside the image.

6

Publish and sign

The image is pushed to the registry and, ideally, signed so that later stages can verify where it came from.

The golden rule: fail fast

Order the steps from cheapest to most expensive. A formatting error found in ten seconds is far better than one found after a twenty-minute test run. Run independent steps side by side, for instance unit tests and a security scan, to shorten the total time. Developers lose focus when feedback takes more than about ten minutes, so speed is a feature, not a luxury.

Make runs repeatable

  • Pin versions. Fix the versions of build tools and libraries, so tomorrow’s run matches today’s.
  • Use clean workers. A fresh container for each run prevents leftovers from an earlier run changing the result.
  • Cache wisely. Reuse downloaded libraries and image layers between runs to save time, but never let a cache hide a real problem.
  • Treat flaky tests as bugs. A test that sometimes fails for no reason teaches people to ignore red results.
Everyday Analogy

Airport security puts the quick checks first. A boarding pass scan takes a second, the bag scanner a bit longer, and a full manual search is kept for the rare suspicious case. If your boarding pass is invalid, nobody wastes time searching your luggage.

i
Tip

Keep the main branch always releasable. When the shared branch is green by default, every developer starts from a safe place, and any red result clearly belongs to the latest change.

6Building Good Container Images

The image is the package your whole pipeline carries. A careless package causes trouble at every later stop.

An image is built in layers, each layer being the result of one instruction in a recipe file. Layers are cached, so unchanged layers are reused and only changed ones are rebuilt. Understanding this makes builds both faster and smaller.

Habits of good images

Habit

Multi-Stage Builds

Compile in one stage with heavy tools, then copy only the finished program into a slim final stage. The shipped image carries no compilers.

Habit

Small Base Images

Start from a minimal base. Fewer packages mean fewer downloads, faster pod starts and fewer security findings.

Habit

Run as Non-Root

Use an ordinary user inside the container. If an attacker breaks in, they do not start with the keys to everything.

Habit

Order Layers by Change

Put rarely changing steps, like installing libraries, before frequently changing ones, like copying source files, so the cache helps.

Habit

One Process, One Job

Keep each container focused. Logs go to standard output, and configuration comes from the environment.

Habit

Record the Contents

Generate a software bill of materials listing every library inside, so you can answer “are we affected?” within minutes of a new alert.

Tagging: how to name releases

A tag is a label on an image, such as a version number. Tags can be moved to a different image, which is dangerous. The famous tag called latest is the worst offender, because it points to something different over time and tells you nothing about what is running. Better choices are listed here.

StyleExample ideaVerdict
Git commit hashShort hash of the commit that built itExcellent, traces directly to the code
Semantic versionMajor, minor and patch numbersGood for libraries and public releases
Build numberCounter from the CI systemFine, but ties you to one CI tool
Image digestLong content hash, never changesStrongest, guarantees exact bytes
LatestA moving labelAvoid for anything deployed
Everyday Analogy

A tag like “latest” is like a sticky note saying “the good milk” on a fridge shelf. Tomorrow someone swaps the bottle and the note still says the same. A commit hash is like a batch number printed on the bottle itself: it tells you exactly which one you are holding.

!
Watch Out

If a Deployment refers to a moving tag, two pods of the same Deployment can end up running different code after a restart. Always deploy by an immutable tag or, better, by digest.

7Registries and Artifact Management

Images are your product. Treat the warehouse that holds them with respect.

A registry stores images and serves them to the nodes that need to run them. Every time a pod starts on a node that does not have the image, the node pulls it from the registry. That means the registry sits directly in the path of every deployment, every scale-up and every recovery after a failure. If it is down or slow, your pods cannot start.

Choosing a registry

  • Cloud registries such as Amazon ECR, Google Artifact Registry and Azure Container Registry sit close to your cluster, integrate with cloud identity, and usually offer built-in scanning.
  • Platform registries bundled with Git hosts, such as those from GitHub and GitLab, keep code and images together under one login.
  • Self-hosted registries such as Harbor give you full control, replication, and policy features, at the cost of running them yourself.
  • Public registries such as Docker Hub are convenient for base images, but apply limits to anonymous pulls and may change terms. Many teams mirror the images they depend on into their own registry.

Housekeeping that saves money and pain

  • Retention rules. Delete untagged and very old images automatically, but keep what is currently deployed and recent rollback targets.
  • Immutable tags. Many registries can refuse to overwrite an existing tag, which protects the rule that a tag means one image forever.
  • Close to the cluster. Pull from a registry in the same region as your nodes. It is faster and avoids data transfer charges.
  • Pull credentials. Nodes or pods need permission to pull from private registries. Prefer cloud identity over long-lived passwords stored in Secrets.
  • Promote, do not rebuild. When software moves from staging to production, copy or re-label the exact same image. Never rebuild it, because a rebuild can differ in subtle ways.
Everyday Analogy

A registry is a distribution warehouse. If the warehouse is far away, trucks take longer to reach the shops. If it has no stock rules, old boxes pile up and cost rent. If anyone can swap boxes on the shelves, shops may receive the wrong goods. Good warehouses are near, tidy and tamper-evident.

i
Good to Know

Image pulling is part of why new pods take time to start. Small images, regional registries and nodes that already hold common layers all make rollouts and autoscaling noticeably faster.

8Describing Deployments: Manifests, Helm and Kustomize

Plain manifests work, but real teams need a way to reuse them across environments.

A manifest for one application in one environment is easy. The trouble starts when you have forty applications and three environments. Most of each file is identical, and only a few values differ: the number of copies, the memory size, the web address. Copying and editing files by hand leads to drift, where production slowly stops matching staging. Two popular tools solve this in different ways.

Helm: charts and values

Helm packages Kubernetes manifests into a chart, a folder of templates with blanks in them. You fill the blanks using a values file. Installing a chart produces a release, and Helm remembers every revision of that release, which makes rollback a single command. Helm is also the standard way to install third-party software, because thousands of ready-made charts exist.

Kustomize: base and overlays

Kustomize takes the opposite approach. There are no templates. You keep a plain, valid base set of manifests, and describe small overlays that patch it for each environment, such as “in production, use five replicas”. Kustomize is built into the standard Kubernetes command-line tool, so no extra software is needed.

QuestionPlain manifestsHelmKustomize
Reuse across environmentsCopy and editTemplates plus values filesBase plus overlay patches
Learning curveLowestMedium, new template languageLow to medium
Packaging and sharingNoneStrong, charts and repositoriesLimited
Release historyKept by Git onlyBuilt in, with rollbackKept by Git only
Readability of resultExcellentCan be hard with heavy templatingGood, files stay valid

Many teams combine the two: install third-party software with Helm, and manage their own applications with Kustomize, or use Helm for both and keep environment values in separate files. There is no single winner. Choose the simplest approach that stops you copying files by hand.

Everyday Analogy

Helm is like a form letter with blanks: “Dear ____, your order of ____ ships on ____.” Kustomize is like a standard letter plus small sticky notes saying “for this customer, change the third line”. Both save you from retyping the whole letter every time.

i
Tip

Validate rendered output in the pipeline. Check manifests against the Kubernetes schema and your own policies before they ever reach a cluster. A typo caught in CI costs seconds, while the same typo caught in production costs an incident.

9Push-Based Versus Pull-Based Delivery

The biggest design choice in CD is who touches the cluster: the pipeline, or the cluster itself.

Push-based delivery

In the classic model, the CI system finishes its work and then runs a final step that connects to the cluster and applies the new manifests. The pipeline holds a credential for the cluster. It is simple and easy to follow, and it works with any CI tool.

Pull-based delivery

In the pull model, a small controller runs inside the cluster. It watches a Git repository holding the desired state. When the repository changes, the controller pulls the change and applies it. The pipeline never needs a credential to the cluster at all. It only needs permission to write to Git.

flowchart LR
  subgraph PUSH["Push model"]
    P1["CI pipeline"] -->|"holds cluster credentials"| P2["Kubernetes API"]
  end
  subgraph PULL["Pull model"]
    Q1["CI pipeline"] -->|"commits new image tag"| Q2["Git config repository"]
    Q3["Controller inside cluster"] -->|"watches and pulls"| Q2
    Q3 -->|"applies changes"| Q4["Kubernetes API"]
  end
    
Figure 4: In the pull model, credentials stay inside the cluster.

Pull-based strengths

  • No cluster credentials stored in CI systems.
  • The controller keeps correcting drift continuously.
  • Git history is the audit trail of every change.
  • Works well across many clusters.

Pull-based costs

  • One more component to install and operate.
  • Extra concepts for newcomers to learn.
  • Feedback to the pipeline is indirect.
  • Needs a plan for updating image tags in Git.

Push is easier to start with. Pull is easier to secure and to scale. Smaller teams on a single cluster often begin with push and move to pull as they grow, while larger organisations choose pull from the start.

Everyday Analogy

Push is like a courier who has a key to your house and delivers the parcel inside. Pull is like you having a locked parcel box: the courier leaves the parcel in a public spot, and you collect it yourself. The second way means strangers never hold your key.

10GitOps in Depth

GitOps is the pull model with a clear philosophy attached.

The word GitOps was popularised around 2017 by the team at Weaveworks. The idea is that Git is the single source of truth for what should run. You never change the cluster by hand. You change Git, and software makes the cluster agree. The four ideas behind it are that the system is described declaratively, the description is versioned and immutable in Git, approved changes are applied automatically, and software agents continuously check that reality matches the description.

flowchart TD
  A["Desired state in Git"] --> B["Controller reads Git"]
  B --> C["Controller reads live cluster state"]
  C --> D{"Do they match?"}
  D -->|"Yes"| E["Report Synced and healthy"]
  D -->|"No"| F["Apply the difference"]
  F --> C
  E --> G["Wait for next change or interval"]
  G --> B
    
Figure 5: The reconciliation loop that keeps the cluster honest.

The two leading tools

Two open-source tools dominate this space, and both are graduated projects of the Cloud Native Computing Foundation. Argo CD offers a friendly web interface showing every application, its sync status and its health, and models each deployed app as an Application object. Flux is a set of small controllers, configured through objects such as a Git source and a Kustomization, with a strong command-line and automation feel. Either one gives you drift detection, automatic sync, pruning of removed resources, and a record of every change.

Drift, healing and pruning

  • Drift means the live cluster differs from Git, usually because someone ran a manual command.
  • Self-healing means the controller reverts such manual changes back to what Git says.
  • Pruning means the controller deletes objects from the cluster when you remove them from Git.

Laying out the repository

A common layout has a folder per environment, each pointing at shared bases. Promoting a release then means a pull request that changes the image tag in the staging folder, followed by another that changes it in production. Each pull request is reviewed, tested and recorded. Larger organisations use an “app of apps” pattern, where one top-level application describes all the others, so a whole cluster can be recreated from one starting point.

The image tag question

Who updates the image tag in Git after CI builds a new image? Either the CI pipeline commits the change itself, or a helper tool watches the registry and commits for you. Both Argo CD and Flux have image automation add-ons for this. The key is that the change is always a Git commit, so it is visible and reversible.

!
Watch Out

Some fields are legitimately changed by other controllers, for example the replica count when a Horizontal Pod Autoscaler is used. If Git also sets that field, the two will fight forever. Leave such fields out of Git, or tell the GitOps tool to ignore them.

11How a Rolling Update Works Inside Kubernetes

Understanding the default deployment strategy explains most rollout surprises.

When the image in a Deployment changes, Kubernetes does not stop everything and restart. It performs a rolling update. Behind the scenes, the Deployment controller creates a new ReplicaSet for the new version and gradually moves pods from the old ReplicaSet to the new one.

flowchart TD
  A["Deployment updated with new image"] --> B["New ReplicaSet created"]
  B --> C["Start a few new pods, within maxSurge"]
  C --> D{"New pods Ready?"}
  D -->|"No, waiting"| D
  D -->|"Yes"| E["Stop some old pods, within maxUnavailable"]
  E --> F{"All pods on new version?"}
  F -->|"No"| C
  F -->|"Yes"| G["Old ReplicaSet kept at zero for rollback"]
    
Figure 6: The rolling update loop, driven by readiness.

The two dials

Two settings control the pace. maxSurge says how many extra pods may exist above the desired count during the update. maxUnavailable says how many pods may be missing. Both default to twenty-five percent. With ten replicas, that means up to three extra pods may start (rounded up) while up to two may be unavailable (rounded down). Setting maxUnavailable to zero guarantees full capacity throughout, at the price of needing spare room for the surge pods.

Readiness is the traffic light

A new pod only counts as ready, and only receives user traffic, once its readiness check passes. The rollout moves on only when new pods are ready. If the new version is broken and never becomes ready, the rollout simply stalls, and the old pods keep serving users. That is a wonderful safety feature, as long as you actually define a good readiness check.

Handy facts

  • A Deployment keeps a history of old ReplicaSets, ten by default, which is what makes quick rollback possible.
  • If a rollout makes no progress for ten minutes by default, the Deployment is marked as failed to progress. The controller does not roll back by itself, so your pipeline should notice and act.
  • An optional setting makes Kubernetes wait a minimum number of seconds after a pod is ready before counting it as available, which filters out pods that crash soon after starting.
Everyday Analogy

Changing the crew of a moving train is done one carriage at a time. A new driver boards and proves they know the route before the old driver steps off. At no point is the train driverless. If the new driver turns out to be unprepared, the old one stays in the cab.

i
Tip

Make your pipeline wait for the rollout to finish and report the result. A deployment step that merely sends a command and exits will happily show green while pods are crashing.

12Deployment Strategies: Rolling, Blue-Green, Canary and Recreate

Different releases deserve different levels of caution.

StrategyHow it worksBest forMain cost
RecreateStop all old pods, then start new onesApps that cannot run two versions at onceDowntime during the switch
RollingReplace pods graduallyMost stateless servicesTwo versions run together briefly
Blue-greenRun a full new copy, then switch all traffic at onceInstant switch and instant rollbackDouble the capacity during release
CanarySend a small share of traffic to the new version firstRisky changes needing real-world proofNeeds traffic control and good metrics

Blue-green, in short

You keep two identical environments, called blue and green. Users are on blue. You deploy the new version to green, test it quietly, and then flip the Service or the ingress to point at green. If anything goes wrong, you flip back in seconds. The old environment stays around until you are confident.

Canary, in short

The name comes from canaries once used in coal mines as an early warning. You send a tiny share of users, say five percent, to the new version. A system watches error rates and response times. If they stay healthy, the share grows to twenty, fifty and finally one hundred percent. If they worsen, the system pulls traffic back automatically.

flowchart LR
  U["Users"] --> R["Traffic router"]
  R -->|"95 percent"| S["Stable version"]
  R -->|"5 percent"| C["Canary version"]
  C --> M["Metrics analysis"]
  M -->|"healthy"| P["Increase canary share"]
  M -->|"unhealthy"| B["Roll back to stable"]
    
Figure 7: A canary release guarded by automatic analysis.

Tools that help

Kubernetes alone offers rolling and recreate. For canary and blue-green, teams add a controller. Argo Rollouts provides a Rollout object that replaces the Deployment and supports both strategies with automated analysis. Flagger automates canary releases on top of existing Deployments. Traffic shifting itself is done by a service mesh, an ingress controller or the Gateway API, which can send a chosen percentage of requests to each version.

Everyday Analogy

A restaurant changing its menu could replace every dish on the same night (recreate), swap items table by table (rolling), open a second dining room with the new menu and move guests over (blue-green), or offer the new dish to a few tables first and see whether they like it (canary).

i
Good to Know

Canary releases need enough traffic to be meaningful. A service receiving ten requests an hour cannot prove anything in a short canary. For tiny services, a simple rolling update with good tests is usually enough.

13Health Checks and Safe Rollouts

Kubernetes can only protect users if your application tells it the truth about its health.

Three kinds of probes let a container report its state. Each answers a different question, and mixing them up is one of the most common causes of bad releases.

Probe

Readiness

“Can I take traffic right now?” A failing readiness probe removes the pod from the Service, but does not restart it. This is what rollouts depend on.

Probe

Liveness

“Am I stuck beyond repair?” A failing liveness probe makes Kubernetes restart the container. Use it carefully, as a wrong setting causes endless restarts.

Probe

Startup

“Have I finished booting?” It holds back the other probes for slow-starting apps, so they are not killed before they are ready.

Hook

PreStop

A small action run just before a container stops, such as waiting a few seconds so that traffic drains away first.

A good readiness check

The best readiness check confirms that the application can really do its job: its own startup is complete and its must-have dependencies, such as a database connection, are reachable. A check that always says yes is worse than none, because it lets broken pods receive traffic. On the other hand, a check that depends on every optional service can make the whole fleet go unready when one minor system hiccups, so keep it focused.

Shutting down gracefully

When Kubernetes stops a pod, it sends a polite stop signal, waits for a grace period of thirty seconds by default, and then forcibly ends the container. During this time the pod is also being removed from the Service, but these two things happen in parallel, so a few requests may still arrive after the signal. A well-behaved application finishes its current requests, stops accepting new ones, and exits. A short pause in a preStop hook helps traffic move away first.

Protecting capacity

  • Run at least two replicas of anything important, so a single pod restart is never an outage.
  • Set a PodDisruptionBudget so that maintenance and node drains cannot take down too many pods together.
  • Set resource requests, so pods land on nodes that really have room.
  • Spread replicas across nodes and zones, so one failure does not remove them all.
Everyday Analogy

A waiter is “ready” when they are in uniform, know the menu and have a free hand, not merely when they have arrived at the restaurant. And a waiter finishing a shift should deliver the plates already in their hands before leaving, not drop them at the door.

!
Watch Out

A liveness check that depends on a database is dangerous. When the database slows down, every pod fails the check, all restart together, and a small problem becomes a full outage. Keep liveness checks about the process itself.

14Environments and Promotion

Software should earn its way to production through a series of safer places.

Most teams have at least three environments. Development is a playground where things break often. Staging is a rehearsal space that looks as much like production as budget allows. Production is where real users live. A change moves forward only after it proves itself in the previous stage. This movement is called promotion.

One cluster or many?

Namespaces in one cluster

  • Cheaper, with fewer clusters to run.
  • Quick to create and delete.
  • Fine for development and preview builds.

Separate clusters

  • Strong isolation between production and the rest.
  • Upgrades can be tested on non-production first.
  • Higher cost and more to maintain.

A common compromise is one cluster for all non-production environments, split by namespace, and a separate cluster for production, sometimes one per region.

Promotion rules

1

Build once

The same image travels through every environment. Only configuration changes between them.

2

Deploy to development automatically

Every merged change lands in development so that problems appear immediately.

3

Test in staging

Heavier tests run here: integration, end-to-end and performance checks against realistic data.

4

Approve for production

Either automatically after checks pass, or after a human reviews a pull request or clicks an approval button.

5

Verify after release

Smoke tests and dashboards confirm the release is healthy, with a clear plan to roll back if not.

Preview environments

A powerful trick is to create a short-lived environment for every pull request, usually a namespace with its own copy of the application and a unique web address. Reviewers can click and try the change before it is merged. When the pull request closes, the environment is deleted automatically. This catches problems that code review alone cannot, though it needs care to keep costs under control.

Separating deploy from release

Feature flags let you ship code to production switched off, then turn the feature on for chosen users later. This separates the technical act of deploying from the business decision of releasing. If a feature misbehaves, you switch it off in seconds without redeploying anything.

Everyday Analogy

A new play goes through rehearsals, a dress rehearsal, then opening night. The script is the same each time; only the audience changes. A feature flag is the curtain: the stage is built and the actors are in place, but the curtain opens only when the director decides.

15The Tool Landscape

There are many tools. They fall into a few families, and you will usually combine one from each.

FamilyExamplesTypical role
Hosted CIGitHub Actions, GitLab CI, CircleCIRun builds and tests from the Git host, with little to maintain
Self-managed CIJenkinsVery flexible, huge plugin world, you run and patch it
Kubernetes-native pipelinesTekton, Argo WorkflowsPipelines defined as objects and run as pods inside the cluster
GitOps CDArgo CD, FluxKeep clusters matching Git
Multi-cloud CD platformsSpinnakerAdvanced release strategies across clouds and clusters
Progressive deliveryArgo Rollouts, FlaggerCanary and blue-green with automated analysis
PackagingHelm, KustomizeDescribe and reuse manifests

A short family history

Jenkins grew out of an earlier project called Hudson and became the default CI server of the 2010s, thanks to its enormous plugin ecosystem. Hosted services then made CI almost effortless for small teams. Tekton emerged from the Knative project as a Kubernetes-native way to define pipelines, and is now part of the Continuous Delivery Foundation. Netflix open-sourced Spinnaker in 2015 to manage its own multi-cloud releases, and Google contributed heavily. Argo began at Applatix, which Intuit later acquired, and Flux was created at Weaveworks. Both Argo and Flux are now graduated Cloud Native Computing Foundation projects.

How to choose

  • Start where your code lives. If your repositories are on GitHub or GitLab, their built-in CI is the shortest path.
  • Prefer fewer moving parts. Each tool is something you must upgrade, secure and understand during an outage.
  • Separate CI from CD. Using one tool for building and another for deploying lets you replace either one without rebuilding everything.
  • Check the community. Active projects with good documentation and many users are far easier to live with.
Everyday Analogy

Choosing pipeline tools is like choosing kitchen equipment. A beginner needs a good oven and a sharp knife. A restaurant chain needs industrial machines and trained staff. Buying the largest kitchen before you cook for crowds only leaves you cleaning more equipment.

16Running CI Inside the Cluster

Kubernetes is not only where software runs. It is also a fine place to run the builders.

Instead of keeping a fleet of build servers that sit idle most of the day, many teams run each pipeline job as a short-lived pod. A job starts, does its work in a clean container, and disappears. The cluster provides the capacity, and its autoscaler adds machines when many jobs arrive and removes them when the queue is empty.

How the popular tools do it

  • GitHub Actions can use runners managed by the Actions Runner Controller, which creates runner pods on demand and scales them with the job queue.
  • GitLab CI has a Kubernetes executor that starts a pod for every job.
  • Jenkins has a Kubernetes plugin that launches agents as pods from templates.
  • Tekton and Argo Workflows are built for this model from the start.

The image-building puzzle

Building container images inside a container is tricky, because a normal image build needs a container engine and extra privileges. Two unsafe shortcuts are common and should be avoided. Mounting the host’s container engine socket into a job gives that job control over the entire node. Running a privileged “docker in docker” container gives it nearly the same power. A compromised job could then escape to the machine.

Safer options build images without a privileged daemon. Rootless BuildKit, Buildah and similar tools can create images inside ordinary containers. Kaniko was widely used for this purpose, but check its current maintenance status before choosing it for a new project, as its stewardship has changed. Whichever you pick, run builds on dedicated, isolated nodes when possible.

Make it fast and fair

  • Resource requests and limits on runner pods stop one heavy job from starving others.
  • A shared cache for layers and downloaded libraries cuts build time dramatically.
  • Dedicated node groups with taints keep noisy build pods away from production workloads.
  • Autoscaling lets the build fleet grow at lunchtime and shrink at night. The Cluster Autoscaler, or a similar tool, handles the nodes while a controller handles the runner pods.
  • Timeouts make sure a stuck job does not hold expensive capacity for hours.
Everyday Analogy

Fixed build servers are like permanent staff on salary even when there is no work. Pods that appear for each job are like casual workers called in for a busy shift and sent home afterwards. You pay for the busy hours, not for the empty ones.

!
Watch Out

Build jobs run code written by many people, including code from pull requests. Treat the build environment as potentially hostile. Do not give it production credentials, and do not let untrusted pull requests run jobs that can reach secrets.

17Configuration and Secrets

The same image runs everywhere. What changes is its settings, and some settings are secret.

Separate config from code

An application should read its settings, such as database addresses and feature switches, from the environment instead of having them baked into the image. In Kubernetes, ordinary settings live in a ConfigMap and sensitive ones in a Secret. Both are handed to pods as environment variables or as files. This is what lets one image serve development, staging and production unchanged.

A Secret is not very secret

A surprising fact for newcomers is that a Kubernetes Secret is only encoded, not encrypted, by default. Anyone who can read it can decode it instantly. Encryption at rest can be switched on in the cluster, and access can be limited with permissions, but the real danger comes when secrets are put into Git in plain form. Once a password is in Git history, it is effectively public to everyone with repository access, forever.

Safe ways to deliver secrets

Option

External Secrets Operator

Keeps the real secret in a cloud vault. The cluster object only says where to fetch it, and the operator creates the Secret on demand.

Option

Sealed Secrets

You encrypt a secret with a public key and commit the encrypted version to Git. Only the controller in the cluster can decrypt it.

Option

SOPS

Encrypts the values inside files while leaving names readable, so reviewers can still see what changed.

Option

Vault

A dedicated secrets service that can issue short-lived credentials on request, and records who asked.

Pipeline credentials

The pipeline itself needs permissions to push images, and sometimes to reach a cluster. The old way is to create a long-lived key and paste it into the CI system as a secret. If that key leaks, an attacker has lasting access. The modern way uses OpenID Connect federation. The CI system proves its identity to the cloud with a short-lived signed token, and the cloud hands back temporary credentials valid for minutes. No permanent key exists to steal. GitHub Actions, GitLab CI and others support this approach.

Everyday Analogy

A long-lived key is a house key copied and given to a contractor, who may keep it forever. A short-lived credential is a hotel key card that opens one door for one night and then stops working. If you lose the card, little harm is done.

i
Tip

Add a secret scanner to your pipeline. It reads every commit and blocks the ones containing passwords, tokens or private keys before they reach shared history.

18Security and the Software Supply Chain

Attackers increasingly aim at the pipeline itself, because it has the keys to production.

A supply chain attack does not break into your application directly. It poisons something your application trusts: a library, a base image, a build tool or the pipeline. Because modern software is assembled from hundreds of outside pieces, defending the chain is as important as defending the final product. The pipeline is the natural place to put the checks.

flowchart LR
  A["Code review and branch protection"] --> B["Secret and code scanning"]
  B --> C["Dependency and image scanning"]
  C --> D["Build in clean isolated runner"]
  D --> E["Generate bill of materials"]
  E --> F["Sign the image"]
  F --> G["Admission control verifies signature"]
  G --> H["Pod runs under restricted settings"]
    
Figure 8: Security gates from first commit to running pod.

The gates, one by one

  • Branch protection and review. No one pushes straight to the main branch. At least one other person approves each change.
  • Scanning. Tools such as Trivy and Grype look for known vulnerabilities in libraries and operating system packages. Static analysis looks for risky patterns in your own code.
  • Bill of materials. A list of everything inside the image, in formats such as SPDX or CycloneDX. When a new vulnerability is announced, you can search the lists instead of guessing.
  • Signing. Tools in the Sigstore family, such as Cosign, attach a signature to the image proving which pipeline built it.
  • Admission control. Policy engines such as Kyverno and OPA Gatekeeper, or built-in validating policies, sit at the cluster door and refuse anything that breaks the rules: unsigned images, images from unknown registries, containers running as root.
  • Pod security standards. Kubernetes defines privileged, baseline and restricted profiles. Aim for restricted wherever possible.

Permissions for the deployer

A push-based pipeline should use a service account limited to the namespaces and object types it truly needs. Cluster-wide administrator rights for a pipeline are an invitation to disaster. In the pull model, the in-cluster controller needs broad rights, so protect the Git repository holding its instructions with strict reviews, because whoever can change that repository can change the cluster.

An industry framework called SLSA, pronounced “salsa”, describes levels of supply chain maturity, from basic build records to tamper-resistant, verifiable builds. It gives teams a roadmap instead of an all-or-nothing goal.

Everyday Analogy

Think of a food factory. Ingredients are inspected on arrival (scanning), the recipe is on a list (bill of materials), boxes are sealed with a tamper-proof sticker (signature), and the shop door checks the sticker before accepting stock (admission control). One missing step is a gap where bad goods could slip in.

!
Watch Out

Scanners produce long lists. If every finding blocks the pipeline, people will find ways around the scanner. Block only on serious, fixable issues, and track the rest for later cleanup.

19Testing Throughout the Pipeline

Different tests answer different questions, and each belongs at a different point.

Test typeQuestion it answersWhere it runsSpeed
UnitDoes this small piece of logic work?CI, every commitSeconds
Manifest validationAre my Kubernetes files valid and policy-compliant?CI, before deploySeconds
IntegrationDo the parts work together, including databases?CI or a temporary environmentMinutes
ContractDo services still honour what other services expect?CIMinutes
End-to-endDoes a real user journey work?StagingMinutes to tens of minutes
PerformanceDoes it stay fast under load?Staging, scheduledTens of minutes
SmokeIs the new release alive and answering?After each deploySeconds

The shape of a healthy test suite

Aim for many fast unit tests, fewer integration tests and a small number of end-to-end tests. This is often drawn as a pyramid. Teams that invert it, relying mostly on slow browser tests, wait ages for feedback and suffer from flaky results.

Tests that are special to Kubernetes

  • Schema validation. Tools such as kubeconform check each manifest against the official Kubernetes schemas.
  • Policy tests. Tools like Conftest or the policy engine’s own command-line check your files against company rules before merge.
  • Dry runs. Asking the real API server to validate a change without applying it catches problems the schema alone cannot.
  • Chart checks. Linting Helm charts and rendering them for every environment shows exactly what will be applied.
  • Temporary clusters. Lightweight local clusters, started inside the CI job, let you test the whole deployment end to end for the cost of a minute or two.

Post-deploy verification

Tests before release prove that the software could work. Checks after release prove that it does. A short smoke test hitting the live health endpoints and one or two key user flows is the cheapest insurance you can buy. Combined with dashboards watching error rates and delays, it tells you in minutes whether to keep going or roll back.

Everyday Analogy

Before a bus service opens a new route, engineers check each part of the bus (unit), drive it round the depot (integration), do a full trial run with staff (end-to-end), and on opening day a supervisor rides the first trip to confirm everything works with real passengers (smoke test).

20Databases, Migrations and Stateful Changes

Code can be swapped in seconds. Data cannot. This is where many pipelines get into trouble.

When a new version needs a changed database layout, such as a new column, the database must change too. During a rolling update, old and new pods run side by side, talking to the same database. So the database must work with both versions at the same moment. A change that suits only the new code will break the old pods still serving users.

Expand, migrate, contract

The safe pattern splits one risky change into several safe ones.

1

Expand

Add the new column or table, keeping all old ones. Old code ignores it, so nothing breaks.

2

Deploy code that writes both

The new version writes to old and new places and can read from either. Old pods still work.

3

Backfill

Copy existing data into the new structure, in small careful batches.

4

Switch reads

Release code that reads only from the new place, once every row is ready.

5

Contract

Remove the old column in a later release, when no running version needs it.

Where do migrations run?

  • A Kubernetes Job that runs once before the new pods roll out. It is explicit and easy to observe.
  • Hooks in Helm or Argo CD, such as a pre-upgrade or pre-sync step, which run a migration job at the right moment in the release.
  • Init containers that run inside each new pod before the main container. Simple, but if many pods start together they may all try to migrate at once, so migrations must be safe to repeat and protected by locks.

Think about rollback early

Rolling back code is easy. Rolling back data is often impossible, because new data may already have been written. That is why backwards-compatible changes matter so much: if the old code can still work with the new database layout, then rollback of code remains a safe option. Take a backup or snapshot before risky migrations, and rehearse restoring it.

Everyday Analogy

Changing a database while the app is running is like rebuilding a bridge while traffic still crosses it. You build the new lane next to the old one, move cars across slowly, and only demolish the old lane when nobody is using it.

!
Watch Out

Dropping or renaming a column in the same release that stops using it is the classic outage. During the rollout, old pods still ask for that column and fail. Always separate the removal into a later release.

21Rollbacks and Failure Recovery

Every release plan needs a way out. Decide it before you need it.

Even excellent pipelines ship bad releases sometimes. What separates good teams from struggling ones is how quickly they notice and recover. The goal is a rollback so simple and well practised that people do it without fear.

flowchart TD
  A["Release finishes"] --> B{"Are health signals normal?"}
  B -->|"Yes"| C["Keep new version"]
  B -->|"No"| D{"Is the fix tiny and obvious?"}
  D -->|"No"| E["Roll back to last good version"]
  D -->|"Yes"| F["Roll forward with a quick fix"]
  E --> G["Confirm recovery on dashboards"]
  F --> G
  G --> H["Write a short review and improve the pipeline"]
    
Figure 9: Deciding between rolling back and rolling forward.

Ways to roll back

Method

Deployment Undo

Kubernetes can switch a Deployment back to its previous ReplicaSet, using the history it keeps. Fast, but in a GitOps setup it will be reversed by the controller unless Git is changed too.

Method

Helm Rollback

Returns a release to an earlier revision, including all the objects that belonged to it.

Method

Git Revert

In GitOps, revert the commit that changed the image tag. The controller applies the old state, and history records exactly what happened.

Method

Automatic Rollback

Progressive delivery tools watch metrics during a canary and pull traffic back if error rates climb, without waiting for a human.

Roll back or roll forward?

Rolling back is usually safest and fastest when a recent change caused the problem and the old version is known to be good. Rolling forward, meaning shipping a quick fix, makes sense when the fix is tiny and obvious, or when rollback is blocked, for example by an incompatible data change. The rule of thumb is to restore service first and investigate afterwards.

Make recovery routine

  • Keep the last few good versions available. Retention rules must never delete the image you might roll back to.
  • Rehearse. Run rollback drills in staging so the steps are familiar.
  • Automate detection. Alerts tied to releases tell you quickly that a deploy coincided with trouble.
  • Hold blameless reviews. After incidents, ask which gate could have caught it, and add that gate.
Everyday Analogy

A theatre keeps the old set stored backstage during the first week of a new production. If the new set collapses, the crew swaps back within minutes while the audience waits. Throwing away the old set on opening night would be bold, and very silly.

22Monitoring, Logging and Metrics

You cannot improve a pipeline you cannot measure, and you cannot trust a release you cannot observe.

Watch the release, not just the servers

After each deployment, the questions are simple. Are error rates normal? Are response times normal? Are pods restarting? Is traffic reaching the new version? To answer them quickly, mark every release on your dashboards with a vertical line or annotation. When a graph bends, you can see at a glance whether it bent right after a deploy. Many teams also tag logs and metrics with the version number, so they can compare old and new side by side.

Four numbers that describe delivery health

A research programme known as DORA, short for DevOps Research and Assessment, studied thousands of teams and found four measurements that predict how well a software organisation performs. They are now widely used.

Frequency
how often you deploy to production
Lead time
how long from commit to running in production
Failure rate
share of deployments that cause trouble

A fourth number, the time taken to recover from a failed release, completes the set. Notice the balance: two numbers measure speed, and two measure stability. Teams that do well tend to be good at both, because small, frequent, automated releases are safer than rare, huge ones.

What to measure in the pipeline itself

SignalWhy it matters
Pipeline durationSlow pipelines slow every developer and encourage big, risky batches
Queue time for runnersLong waits mean too few runners or poor autoscaling
Failure rate by stageShows where problems appear and which tests are flaky
Rollout duration and resultSpots stuck or slow deployments
Rollback countA rising number points to weak testing or poor release practice
Image size and pull timeLarge images slow rollouts and scaling

Notifications that people read

Send build and deploy results to the places where the team already works, such as chat channels, but keep the noise low. A message for every successful step trains people to mute the channel. A clear message when something fails, or when a production release starts and ends, is worth its weight in gold. Include a link to the exact run and the commit author, so the right person can act at once.

Gitops-specific signals

Tools like Argo CD and Flux expose metrics and events for sync status, drift and health. Alert on applications stuck out of sync or degraded for longer than a few minutes. A controller that silently stops syncing is as dangerous as a failed pipeline, because nobody notices that new releases are no longer arriving.

Everyday Analogy

Delivering a parcel is not finished when the van leaves the depot. Good courier companies track the parcel until it is signed for. A release is the same: it is finished only when the dashboards confirm that users are being served well by the new version.

i
Tip

Start measuring the four delivery numbers even if they look embarrassing. The first goal is an honest baseline. The second is picking one number to improve at a time.

23Advantages, Disadvantages and Trade-offs

Automated delivery to Kubernetes is powerful, and it is not free.

Advantages

  • Faster, more frequent and calmer releases.
  • Fewer human mistakes, since steps are written as code.
  • Quick feedback on broken changes.
  • Easy rollback and a full audit trail.
  • Identical environments reduce surprises.
  • Teams can ship independently without waiting for a release manager.

Disadvantages

  • Real upfront effort to design and build.
  • More tools to learn, secure and maintain.
  • A broken pipeline blocks everyone at once.
  • Tests need continuing care, or they decay.
  • Powerful credentials make the pipeline a target.
  • Cultural change is often harder than the technology.

The big trade-offs

ChoiceOne sideOther side
Speed or safetyDeploy every merge automaticallyRequire manual approval for production
Simplicity or controlOne hosted tool, few settingsSelf-managed tools you can bend to your needs
Push or pullSimple to startStronger security and drift correction
Monorepo or many reposEasy cross-cutting changesClear ownership and smaller blast radius
Shared or separate clustersLower costStronger isolation

There is no universally correct row. A start-up with five engineers and one cluster should usually choose the simple side of each. A bank with strict audit rules will land on the controlled side of several. The art is to revisit the choices as the organisation grows, rather than copying what a giant company does.

i
Good to Know

Continuous deployment to production is not mandatory. Many excellent teams use continuous delivery with a human approval step. What matters is that every change is always ready to release and the release itself is boring.

24Design Patterns and Anti-Patterns

Habits that make delivery smooth, and habits that quietly cause pain.

Patterns that work

Pattern

Build Once, Promote Many

One image, tested once, moves through every environment with only configuration changing.

Pattern

Pipeline as Code

Pipeline definitions live in version control beside the application, reviewed like any other change.

Pattern

Trunk-Based Development

Developers merge small changes to the main branch often, avoiding long-lived branches and painful merges.

Pattern

GitOps Promotion by Pull Request

Moving a release to the next environment is a reviewed commit, giving approval and audit in one step.

Pattern

Progressive Delivery

Release to a small share first, measure, then widen, with automatic retreat on bad signals.

Pattern

Ephemeral Environments

Temporary full environments for each pull request, destroyed on merge, keep testing realistic and cheap.

Anti-patterns to avoid

ANTI-PATTERN 01Avoid
The habit

Rebuilding the image separately for each environment.

Why it hurts

The thing you tested in staging is not the thing you shipped. Tiny differences in dependencies or build time can introduce bugs that no test saw.

Better approach

Build once, store the image, and promote that exact image. Change only configuration.

ANTI-PATTERN 02Avoid
The habit

Using the latest tag, or any moving tag, in production manifests.

Why it hurts

You cannot tell what is running, rollbacks have no clear target, and pods restarted at different times can run different code.

Better approach

Deploy by commit-based tags or digests, and refuse mutable tags with policy.

ANTI-PATTERN 03Avoid
The habit

Making manual changes to the live cluster to “fix things quickly”.

Why it hurts

Git no longer matches reality. The next deploy either overwrites the fix and brings the outage back, or a GitOps controller silently reverts it.

Better approach

Make fixes through Git. Keep a documented emergency path that still records the change afterwards.

ANTI-PATTERN 04Avoid
The habit

Giving the pipeline cluster-admin rights and storing long-lived keys in the CI system.

Why it hurts

One leaked token hands an attacker the entire cluster, and the pipeline becomes the weakest link in your security.

Better approach

Use narrow permissions, short-lived federated credentials, and the pull model where possible.

ANTI-PATTERN 05Avoid
The habit

Treating a green deployment step as proof that the release works.

Why it hurts

A command that merely submitted the change may report success while pods crash. Users suffer while the dashboard of the pipeline stays green.

Better approach

Wait for the rollout to complete, run smoke tests, and watch error and latency signals before declaring success.

ANTI-PATTERN 06Avoid
The habit

A giant pipeline that nobody dares touch, with copied scripts in every project.

Why it hurts

Fixes must be repeated in dozens of places, and tiny differences between projects cause baffling failures.

Better approach

Share reusable pipeline templates, version them, and keep each pipeline short and readable.

25Best Practices and Common Mistakes

A short checklist, followed by a troubleshooting guide for the failures you will definitely meet.

Best practices

  • Keep the main branch green. Fix or revert broken changes immediately.
  • Keep pipelines fast. Aim for feedback on a change within about ten minutes.
  • Make everything repeatable. Pin versions of tools, base images and libraries.
  • Use immutable, traceable tags. Every running pod should map to a commit.
  • Define good probes and resource requests for every workload.
  • Protect production with required reviews, narrow permissions and policy checks.
  • Practise rollbacks regularly, so they are routine.
  • Document the pipeline so a new teammate can follow the path from commit to cluster in an hour.

Common mistakes

  • Tolerating flaky tests until nobody trusts the pipeline.
  • Keeping secrets in repositories or in plain environment settings of the CI tool.
  • Forgetting resource limits on build pods, so builds crowd out real workloads.
  • Allowing different people to deploy the same service by different routes.
  • Skipping non-production environments to “save money”, then paying more during outages.
  • Never cleaning up old images, preview environments and finished jobs.

Troubleshooting common deployment failures

SymptomUsual causesFirst thing to check
ImagePullBackOffWrong image name or tag, missing pull credentials, registry down, image deleted by retention rulesThe events on the pod, which show the exact pull error
CrashLoopBackOffApplication crashes at startup, missing configuration or secret, bad commandThe logs of the previous container run
Pods stay PendingNot enough room on nodes, impossible placement rules, unbound storageThe scheduling message in the pod events
Rollout stuckNew pods never become ready, tight resource limits, failing readiness probeThe rollout status and the readiness probe of new pods
Application out of syncAnother controller changes fields, manual edits, failed webhookThe diff shown by the GitOps tool
Pipeline green but app brokenDeploy step did not wait for result, no smoke testAdd rollout wait and post-deploy checks
i
Tip

When a rollout fails, look at three things in order: the events, the logs and the status conditions of the Deployment. Nine times out of ten the cluster has already told you exactly what is wrong.

!
Watch Out

Image retention rules and rollbacks can collide. If cleanup deletes an old image, the previous revision of a Deployment can no longer start. Always keep recent production images.

26Real-World and Industry Examples

How well-known organisations shaped the tools and ideas we use today.

Netflix and Spinnaker

Netflix built Spinnaker to release software safely across many cloud environments, and open-sourced it in 2015 with help from Google. It popularised ideas such as automated canary analysis and pipelines that treat deployment strategies as first-class features.

Intuit and Argo

The Argo family of projects, including Argo CD, Argo Workflows and Argo Rollouts, grew from work at Applatix and then at Intuit. Argo CD became one of the most widely adopted GitOps tools and is a graduated Cloud Native Computing Foundation project.

Weaveworks and Flux

Weaveworks created Flux and popularised the name GitOps. Its approach of making Git the single source of truth shaped how many teams now think about operating clusters.

Google and its delivery products

Google’s long experience running software at huge scale led to the research behind DORA’s metrics and to managed delivery services on its cloud. Its internal lessons about small, frequent, automated releases influenced the wider industry.

Etsy and frequent deployment

Etsy became well known in the 2010s for deploying to production many times a day, and for describing publicly how it made that safe through automation, monitoring and a blame-free culture. It showed that speed and stability can improve together.

Typical scenario: a small team

A team of eight runs one cluster with three namespaces. They use hosted CI to build images, store them in their cloud registry, and a GitOps controller to roll out changes. Production releases happen after a pull request is approved. Total tooling is small enough that everybody understands every part.

Typical scenario: a large platform

A company with hundreds of services gives teams a shared pipeline template. Each team simply points it at their repository. Policy rules, signing and scanning are built in, so every service gets the same safety net without anyone redoing the work.

27Frequently Asked Questions

Q1What is the difference between CI and CD?
CI is about automatically building and testing every change as soon as it is shared. CD is about automatically preparing, and often releasing, tested changes to environments such as staging and production. CI proves the change is sound, and CD carries it to users.
Q2Do I need GitOps to deploy to Kubernetes?
No. A pipeline that applies manifests directly works fine, especially for small teams. GitOps adds drift correction, a built-in audit trail and the removal of cluster credentials from CI. Many teams adopt it once their number of clusters or services grows.
Q3Should CI and CD be the same tool?
They can be, but separating them is often wiser. CI tools are excellent at running jobs, while CD tools are excellent at keeping clusters matching a desired state. Using one of each lets you replace either without disturbing the other.
Q4Helm or Kustomize?
Helm shines for packaging and for installing third-party software, and keeps release history. Kustomize shines for lightly adjusting plain manifests per environment. Plenty of teams use both. Choose whichever stops you copying files by hand with the least complexity.
Q5How do I deploy without downtime?
Run several replicas, define a truthful readiness probe, use a rolling update with maxUnavailable set low, shut down gracefully, and protect capacity with a PodDisruptionBudget. For very sensitive releases, add a canary or blue-green strategy.
Q6Why is the latest tag discouraged?
Because it moves. It makes it impossible to know what code is running, breaks reliable rollbacks, and can cause different pods of one Deployment to run different versions after restarts. Commit-based tags or digests avoid all of this.
Q7Is a Kubernetes Secret safe to store in Git?
Not in its plain form, since it is only encoded and anyone can decode it. Use encryption tools such as Sealed Secrets or SOPS, or keep real values in an external vault and let the cluster fetch them.
Q8How do I handle database changes safely?
Make changes backwards compatible. Add new structures first, deploy code that can use both old and new, move the data, switch over, and remove the old structure in a later release. Run migrations as a controlled job, not as an afterthought.
Q9What should I do when a release goes wrong?
Restore service first. Usually that means rolling back to the last known good version, through a Git revert in GitOps or a rollback command otherwise. Investigate calmly afterwards and add a check to the pipeline that would have caught the problem.
Q10Can untrusted pull requests run my pipeline safely?
Only with care. Jobs triggered by outsiders should run without access to secrets and without any route to production. Many CI systems offer settings that withhold secrets from forked pull requests, and these should be used.
Q11How many environments do I need?
At minimum a place to test that is not production. Most teams use development, staging and production. The right number is the smallest one that gives real confidence before users are affected.
Q12How do I know if my pipeline is good?
Look at the delivery numbers. If you deploy often, changes reach production quickly, few releases cause trouble, and recovery is fast, the pipeline is doing its job. Developer happiness is also a fair guide: people should trust it and not fear it.

28Summary and Key Takeaways

If you remember only a handful of things, remember these.

Key Takeaways

  • A pipeline is an agreement written as code. It moves every change from commit to cluster the same way, every time.
  • Build once, promote the same image. Use immutable, traceable tags or digests, and never rebuild per environment.
  • Describe, do not command. Kubernetes delivery means changing a declared desired state, which tools like Helm, Kustomize and GitOps controllers manage.
  • Pull is safer, push is simpler. Keeping cluster credentials inside the cluster is a strong security win as teams grow.
  • Readiness and rollout settings protect users. Good probes, graceful shutdown and sensible surge limits make rolling updates safe.
  • Secure the chain. Scan, sign, restrict permissions, use short-lived credentials, and let admission policies enforce the rules.
  • Plan the way back. Backwards-compatible data changes, kept images and practised rollbacks turn bad releases into small events.