If I had to boil this article down to one line, it would be this: scan in CI, block at admission, and feed runtime alerts back into the pipeline.
That’s the pattern behind the case studies here. I can see teams using image scanning before push, manifest and Terraform checks in CI, Kyverno or Gatekeeper at deploy time, and runtime tools such as Falco or Trivy Operator after release. The payoff is plain: fewer bypasses, lower drift, and faster detection when something slips through.
Here’s the article in simple terms:
- Build stage: scan container images, base images, Kubernetes YAML, Helm output, and Terraform
- Deploy stage: use admission control to block bad changes, unsigned images,
latesttags, privileged pods, and missing limits - Runtime stage: watch live clusters for drift, new CVEs, and policy breaks, then send that data back into CI
- Team rollout: start in audit mode, then warn, then enforce
- Cost and speed: keep scans parallel, cut noise with rules like
--ignore-unfixed, and shrink images where you can
A few numbers stand out:
- 90%+ fewer OS CVEs is possible when teams move to distroless or small base images
- One hardened manifest moved from -37 to +8 on Kubesec scoring
- One UK South AKS setup cut compute spend by 50% after moving to ARM64 nodes and matching build agents
::: @figure
{Kubernetes CI/CD Security: 3-Stage Pipeline Framework}
:::
Kubernetes security scanning with Trivy CLI and Trivy Operator

Need help optimizing your cloud costs?
Get expert advice on how to reduce your cloud expenses without sacrificing performance.
Quick Comparison
| Stage | What to check | Common tools | Main goal |
|---|---|---|---|
| CI / build | Images, manifests, Helm, Terraform | Trivy, Grype, Kubesec, KubeLinter, Checkov | Stop bad artefacts before push or merge |
| Admission / deploy | Image signatures, tags, pod settings, limits | Kyverno, Gatekeeper, Conftest | Stop pipeline bypasses and bad cluster changes |
| Runtime | New CVEs, drift, live policy breaks | Falco, Trivy Operator, Kyverno events | Spot issues after release and push fixes back to Git |
What I like about these examples is that they don’t treat security as one gate at the end. They spread checks across the whole path from commit to cluster, which is where most teams get better results without slowing delivery too much.
That’s the lens I’d use to read the rest of the article: not “which single tool wins?”, but how each control covers a different gap.
Case studies: image and configuration scanning in CI
Scanning container images before registry push or deployment
A common setup is simple: scan images in CI after the build and before the registry push.
Teams that rely on hard CI gates often set up scanners like Trivy or Grype with exit-code 1 for CRITICAL and HIGH findings. That means the pipeline fails on the spot when those issues show up. It also helps to scan the base image separately from the application layers, so teams can tell the difference between upstream issues and problems pulled in by app dependencies.
A good example comes from Cloud DevOps Engineer Jenom Shehu, who built a production-grade pipeline for a Python Flask API on AWS EKS in April 2026 [5]. The pipeline followed a strict Build locally → Scan → Push flow, with six security gates running in parallel before the push. It blocked HIGH findings and avoided long-lived AWS credentials.
Use --ignore-unfixed if you want the pipeline to fail only when a fix is available. That keeps attention on issues teams can act on now. Another smart move is switching to distroless or minimal base images. In many cases, that cuts OS-level CVE counts by 90%+ compared with standard base images [7][1].
The trade-off comes down to scope and effort.
| Approach | Integration Effort | K8s Policy Support | Scan Speed | Reporting Depth | Fit for UK Multi-region |
|---|---|---|---|---|---|
| Trivy (CI-native) | Low | High (via Config) | Fast | High (SARIF/JSON) | Excellent (local execution) |
| Grype (SBOM-first) | Medium | Medium | Fast | High (VEX support) | Good (portable SBOMs) |
| Registry-native scanning | Very Low | Low | Slow (post-push) | Moderate | Poor (delayed feedback) |
Scanning Kubernetes manifests, Helm charts and Terraform for misconfigurations

Once image scanning is in place, the next weak spot is often the workload definition itself. Misconfigurations in manifests and IaC can still slip through, which is why this stage matters.
In a DevSecOps project from March 2026, Muhammad Hammad used Kubesec, KubeLinter and Trivy through GitHub Actions to enforce hardening standards across Kubernetes manifests [8]. Controls such as a non-root user, a read-only root filesystem and dropped capabilities pushed the hardened manifest to a +8 Kubesec score, while the insecure version scored -37 [8].
For Helm-based deployments, scan the rendered output, not the raw templates: helm template | kubesec scan -. That rendered YAML is what the cluster actually gets. Values passed in at deploy time can change the final manifest, so scanning templates alone can miss the point. Tools like Kubeconform add another check by spotting deprecated API versions and structural errors that standard linters may miss [9]. The same idea applies to Terraform. Full IaC scanners such as Checkov or Trivy Config can catch misconfigurations before deployment. In practice, these CI checks set the baseline for policy checks at deploy time.
| Feature | Manifest-only scanning (e.g. Kubesec, KubeLinter) | Full IaC scanning (e.g. Checkov, Trivy Config) |
|---|---|---|
| Coverage | Kubernetes resources only | K8s, Terraform, Dockerfile, Helm |
| False positives | Low (focused, specific rules) | Moderate (requires tuning) |
| Adoption effort | Low (single binary) | Medium (broader policy set needed) |
| Auditability | High (numeric scoring, maps to cluster) | High (SARIF exports, compliance mapping) |
For teams that are just getting started, manifest-only scanning is usually the easier entry point. Full IaC scanning tends to pay off more once the baseline is clean, especially when the goal is steady policy checks across many environments.
Case studies: policy enforcement at deploy time and runtime
Admission control with policy as code
CI scanning catches a lot. But anyone with kubectl access can skip the pipeline and push straight to a cluster.
That is exactly what happened to M. Taha Akça's platform team in April 2026, when an engineer skipped a 9-minute CI pipeline to push an unsigned hotfix directly to production [10]. So deploy-time policy becomes the backstop for anything a developer can work around.
Their fix was to use Kyverno with verifyImages and mutateDigest: true. That setup required a keyless Cosign signature for every internal image. Developers could still use tags in Git, while the cluster enforced immutable digests at runtime [10].
Strict without adoption strategy equals security theater. If teams cannot reliably produce signed images, enforcement blocks their work and creates pressure to find exceptions.- M. Taha Akça, Senior DevOps & Platform Engineer [10]
Admission control is the last gate. In the strongest setups, the same checks run in CI with Conftest or the Kyverno CLI, then run again inside the cluster. That way, teams see failures early instead of getting blocked only at deploy time.
A staged rollout helps avoid grinding teams to a halt before policy is part of day-to-day work. Dynatrace replaced manual checks with staged Kyverno policies rolled out in three phases: Audit Mode, Warn Mode and Enforce Mode [11]. In the Audit phase, violations were logged but nothing was blocked. Dynatrace Workflows then created Jira tickets for each violation, which gave teams time to fix the issue or ask for a documented exception before Enforce Mode went live. Dynatrace reached CIS Kubernetes Benchmarks compliance without slowing delivery [11].
| Policy | Enforced in CI | Enforced at Admission | Security effect |
|---|---|---|---|
No latest tags |
Yes (Conftest/Trivy) | Yes (Kyverno/Gatekeeper) | Prevents unpredictable rollouts |
| Non-root user | Yes (kubesec/Checkov) | Yes (Kyverno/PSA) | Cuts escape risk |
| Resource limits | Yes (Polaris) | Yes (Kyverno) | Blocks node exhaustion |
| Image signatures | No (verification only) | Yes (Kyverno/Cosign) | Blocks unsigned images |
| Privileged mode | Yes (Trivy) | Yes (Kyverno/Gatekeeper) | Prevents privileged pods |
Mutable tag enforcement also needs to line up with GitOps, or you'll get false drift. If you use tag-to-digest mutation in Kyverno, configure ArgoCD's ignoreDifferences for the image field. Without that, ArgoCD sees the digest change as drift and tries to revert it [10].
Using runtime monitoring to improve CI/CD rules
Runtime monitoring catches issues that only show up after deployment. Those same events can also feed tickets and policy updates, which means runtime data isn't just for alerting. It can tighten the next pipeline run too.
By feeding Kyverno violations into observability and Jira, Dynatrace pushed fixes back to Git instead of patching clusters by hand [11].
Securing Kubernetes is continuous, not one-off [\[11\]](https://medium.com/dynatrace-engineering/enforcing-kubernetes-security-policies-at-dynatrace-cad6c53a6947).
Teams that added runtime visibility saw three clear gains:
| Metric | Before (CI scanning only) | After (CI + Admission + Runtime) |
|---|---|---|
| Mean Time to Detect (MTTD) | Days or weeks (until manual audit) | Real-time, via Falco or Kyverno events |
| Mean Time to Remediate (MTTR) | High - manual patching required | Low - automated Jira/CI feedback loop |
| Incident type | Privileged containers running in production | Blocked at kubectl apply or PR stage |
| Configuration drift | High - manual kubectl edit permitted |
Low - admission controller rejects drift |
The Trivy Operator continuously rescans deployed images for new CVEs [1]. If a new vulnerability is published against a base image that is already running in the cluster, the operator flags it and can trigger a pipeline update to patch the image.
The pattern here is simple: every control should feed the next run of the pipeline.
Shared lessons for building a secure Kubernetes delivery model
What successful implementations had in common
Across the case studies, the same idea kept showing up: scan early, enforce at admission, and send runtime findings back into CI. The teams that did this well didn’t rely on one checkpoint. They built several gates across the delivery flow, so one miss couldn’t quietly slip a vulnerability into production. Jenom Shehu’s EKS pipeline, for example, ran six parallel scans before a Docker build could even begin [5]. Osahon Seth’s AKS setup did something similar, with five automated stages spread across the full delivery path [4].
GitOps acted as the deployment gate. In a pull-based model, the cluster only took changes that had already cleared automated checks. That removed direct kubectl apply from the normal deployment route, which cut down a common source of drift and bypasses.
The gap between YAML authoring and runtime admission is where security debt accumulates.- Systems Hardening [9]
Credential hygiene came up again and again too. Teams that switched to OIDC-based authentication for CI runners got rid of static keys and used short-lived tokens tied to a repository instead. That strips out a whole class of risk [5][12].
Balancing stronger controls with deployment speed and cloud spend
This setup only holds if the pipeline stays quick enough that teams won’t try to dodge it. A simple fix is to run scans in parallel before the Docker build. That way, the total wait time is set by the slowest scan, not by adding every scan together [4][5]. Slower checks, like full history scans, can run in a nightly workflow instead of blocking each pull request [5].
Noise matters as much as speed. If the pipeline throws alerts that nobody can act on, people stop taking it seriously. Using Trivy with --ignore-unfixed avoids failed pipelines for vulnerabilities that don’t yet have a patch. Pair that with a fixed remediation SLA for Critical and High findings, and teams have a clear way to sort what needs attention first without treating every alert like a fire alarm [1][2].
These choices also shape cloud spend. In June 2026, Osahon Seth’s AKS project in the UK South region cut compute costs by 50% after moving to ARM64 Standard_D2ps_v6 nodes for both the cluster and the self-hosted Azure DevOps agents [4]. Smaller images help on that front as well, because they cut patch volume and reduce cloud spend.
Conclusion: key lessons from Kubernetes CI/CD security case studies
Across these case studies, one theme kept showing up: scan early, enforce at admission, and send runtime findings back into CI. Early scanning in CI removes much of the preventable risk at low cost. Catching a misconfigured manifest at pull request stage is far cheaper than finding it after a breach.[3]
Admission control covers the deploy-time gap. Runtime monitoring covers what CI can't see. CI checks only matter if the cluster applies the same rules in practice. That means admission control needs to verify signed images at the cluster gate, so only artefacts that have cleared security checks can be scheduled.
Runtime findings also need to shape CI policy. If a violation appears in production, it should show up in the next pipeline run, not sit in an alert queue. Continuous in-cluster scanning spots vulnerabilities that surface after release.[6]
The teams that do this well don't treat security and delivery speed as opposing forces. They use fast, layered gates that protect both security and release flow, while also helping keep cloud spend under control.
Hokstad Consulting helps teams align Kubernetes security with cloud cost discipline.
FAQs
Where should we start with Kubernetes CI/CD security?
Start by shifting security left. Build automated checks into your CI/CD pipeline so security acts as a guardrail, not something you bolt on at the end.
Begin with automated gates for:
- manifest risk scoring and policy linting
- container image scanning for vulnerabilities
- policy-as-code to enforce standards such as labels, approved registries and security contexts
Why do we need admission control if CI scans already run?
CI scans are advisory. Admission control is mandatory because the Kubernetes cluster enforces it itself.
If you depend on CI alone, there are a few obvious gaps. Someone could change runners, steal registry credentials, or push images straight to the registry and skip the checks.
Admission controllers such as OPA Gatekeeper or Kyverno act as the final gate for every workload request. That helps make sure only signed, scanned, and compliant images make it into production.
How can we tighten security without slowing delivery?
Shift security left by adding automated gates to your CI/CD pipeline. That way, developers get fast feedback right where they already work, and insecure code gets blocked before it reaches deployment.
Here’s the core idea: run checks early and often.
- Automate scans for secrets, risky code patterns, and misconfigurations
- Validate IaC and Kubernetes manifests early in the process
- Scan container images at build time
- Use admission control as a last safety layer
This setup helps teams catch problems when they’re easier to fix, not after they’ve already moved downstream.