Securing containerized applications and microservices architectures

By Jonathan D. Steele | August 29, 2025

Threat model and security principles

  • Shift-left: detect and prevent issues during build and CI/CD.
  • Least privilege: for images, containers, Kubernetes RBAC, and network policies.
  • Defense in depth: multiple controls at build, deploy, runtime, and network layers.
  • Immutable artifacts: build once, sign, and promote artifacts to environments.
  • Observability and fast response: logging, auditing, and runtime detection.

Build-time and supply chain security

Fix many issues before runtime by securing source, dependencies, and images.

1) Harden Dockerfiles and images

Examples and best practices:

  • Use minimal base images (e.g., distroless, Alpine) to reduce attack surface.
  • Specify explicit versions for base images and packages.
  • Run processes as non-root user inside container.
  • Remove build-time tools from final image (multi-stage builds).
  • Pin images by digest when deploying (immutable reference).

Example Dockerfile (multi-stage, non-root)

FROM golang:1.20-alpine AS builder

WORKDIR /app

COPY go.mod go.sum ./

RUN go mod download

COPY . .

RUN CGOENABLED=0 GOOS=linux GOARCH=amd64 go build -o app ./cmd/service

FROM gcr.io/distroless/static-debian11

COPY --from=builder /app/app /app/app

USER 10001

ENTRYPOINT ["/app/app"]

2) Scan dependencies and images in CI

Integrate static analysis and vulnerability scanning into CI pipelines. Example tools: Trivy, Clair, Grype for image vulnerability scanning; Snyk/Dependabot for code dependencies; Checkov/terrafirma for IaC.


Example: scan built image with Trivy in CI

trivy image --severity HIGH,CRITICAL --exit-code 1 --no-progress myrepo/myapp:sha256-...

3) Sign and verify artifacts

Prevent deployment of tampered images by signing images and enforcing verification before deploy. Tools: cosign (sigstore), Notary/v2.


Sign an OCI image with cosign

cosign sign --key cosign.key ghcr.io/org/myapp@sha256:...

Verify before deployment

cosign verify ghcr.io/org/myapp@sha256:...

4) CI/CD pipeline safeguards

Your pipeline should include stages: build, static tests, dependency checks, image scan, image sign, push, and deploy gates. Enforce approval policies and image provenance checks in deployment stages.


Example pipeline stages

  1. Checkout & lint -> 2. Unit tests -> 3. Dependency scan -> 4. Build image ->
  2. Image scan (fail on high/critical) -> 6. Sign image -> 7. Push -> 8. Deploy with gate

Runtime security in Kubernetes and other orchestrators

Runtime protections detect and mitigate compromised containers, and reduce impact of breaches.

1) Pod security hardening

  • Use Pod Security Admission (PSA) or OPA Gatekeeper policies to enforce Pod constraints: disallow privileged containers, restrict hostPath, require read-only root filesystem and non-root user.
  • Set resource limits and requests to prevent DoS via resource exhaustion.
  • Drop Linux capabilities; only add what's necessary.

Example Pod Security (psp-like) settings in PodSpec

securityContext:

runAsNonRoot: true

runAsUser: 10001

readOnlyRootFilesystem: true

allowPrivilegeEscalation: false

containers:

  • name: app

securityContext:

capabilities:

drop: ["ALL"]

resources:

requests:

Legal Protection Matters: Cybersecurity incidents often have significant legal implications. Our sister firm Steele Family Law helps Illinois families navigate complex legal situations with the same commitment to protection and discretion we bring to cybersecurity.

cpu: "100m"

memory: "128Mi"

limits:

cpu: "500m"

memory: "512Mi"

2) Network segmentation and policies


Example Kubernetes NetworkPolicy: allow traffic only from namespace "frontend"

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

name: allow-from-frontend

namespace: backend

spec:

podSelector:

matchLabels:

app: backend

ingress:

  • from:
  • namespaceSelector:

matchLabels:

name: frontend

ports:

  • protocol: TCP

port: 8080

3) Service mesh / mTLS for service-to-service auth

4) Runtime detection and process protections

  • Deploy runtime security agents (Falco, Sysdig, Aqua) to detect suspicious behavior: shell in container, privileged syscalls, unexpected outbound connections.
  • Use kernel hardening and container runtime configurations: seccomp profiles, AppArmor, SELinux.

5) Control plane and API server protection

Lock down the orchestrator API: restrict access to Kubernetes API server, use MFA for admin access, and apply least-privilege RBAC. Enable audit logging and regularly review audit events for suspicious activity.


Example RBAC: read-only role for monitoring

apiVersion: rbac.authorization.k8s.io/v1

kind: Role

metadata:

namespace: monitoring

name: pod-reader

rules:

  • apiGroups: [""]

resources: ["pods", "pods/log"]

verbs: ["get", "list", "watch"]

Secrets, keys, and configuration

Secrets must never be baked into images or stored unencrypted. Use a dedicated secret store and short-lived credentials.

  • Use external secret stores: HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, Google Secret Manager.
  • In Kubernetes, use the Secrets Store CSI driver to mount secrets from external stores without persisting them in etcd.
  • Enable encryption at rest for Kubernetes secrets (Envelope encryption using KMS).
  • Prefer short-lived service tokens and dynamically provisioned credentials (e.g., Vault AppRole with leases, Kubernetes service account tokens with projected token expiration).

Example: mount secret with CSI Secrets Store (conceptual)

apiVersion: v1

kind: Pod

spec:

containers:

  • name: app

image: myrepo/myapp:sha256:...

volumeMounts:

  • name: secrets-store

mountPath: "/secrets"

volumes:

  • name: secrets-store

csi:

driver: secrets-store.csi.k8s.io

readOnly: true

volumeAttributes:

secretProviderClass: "vault-provider"

Identity, authentication, and authorization

  • Use short-lived service identities: Kubernetes service account tokens with projected tokens or workload identity (e.g., GKE Workload Identity).
  • Centralize identity and SSO for developers and operators; enable MFA for privileged operations.
  • Enforce RBAC and use policy engines (OPA/Gatekeeper) to enforce organizational policies in the cluster.

OPA/Gatekeeper sample constraint snippet (conceptual)

apiVersion: templates.gatekeeper.sh/v1beta1

kind: ConstraintTemplate

metadata:

name: k8sdenyprivileged

spec:

crd:

spec:

names:

kind: K8sDenyPrivileged

targets:

  • target: admission.k8s.gatekeeper.sh

rego: |

package k8sdenyprivileged

denymsg {

input.review.object.spec.containers[].securityContext.privileged == true

msg = "Privileged containers are not allowed"

}

Logging, auditing, and incident response

Observability is critical for detection and fast response.

  • Export Kubernetes audit logs to a centralized location and monitor for privilege escalations or abnormal API calls.
  • Collect and aggregate container logs and metrics (Prometheus, Grafana, ELK/EFK) and create alerts for anomalous patterns.
  • Use EDR and runtime anomaly detection to detect suspicious behavior inside containers.
  • Have a playbook: isolate workloads (network policy or node quarantine), revoke compromised credentials, roll back to signed images, and investigate using audit data.

Practical checks and quick wins

Actionable checklist you can apply quickly:

  1. Enable image scanning in CI and block builds with high/critical findings.
  2. Sign images after build and verify signatures before deploy.
  3. Run containers as non-root and set read-only root filesystems.
  4. Enforce NetworkPolicies to limit cross-service communication.
  5. Use a secrets manager with short-lived credentials and avoid storing secrets in plaintext in git or images.
  6. Restrict Kubernetes API access with least-privilege RBAC and enable audit logging.
  7. Install runtime detection (e.g., Falco) to alert on suspicious container behavior.

Example workflows — from build to runtime

Two short workflow examples that tie recommendations together.

CI/CD pipeline flow

Build -> Static tests -> Dependency scan -> Build image -> Trivy scan -> Sign image (cosign) -> Push to registry -> Deploy via GitOps (ArgoCD/Flux) which verifies signature and image digest -> Post-deploy runtime policy checks (OPA) and runtime monitoring (Falco).

Compromise containment scenario

If a container is suspected compromised: (1) Use NetworkPolicy or service mesh to isolate the pod/namespace, (2) scale the pod down or cordon the node, (3) revoke any active credentials/keys used by that workload, (4) promote a signed clean image (rollback), (5) analyze audit logs and runtime alerts to determine root cause.

Common pitfalls to avoid

  • Relying solely on images being "small" — even small images can contain vulnerable libraries.
  • Leaving default service accounts with broad permissions in namespaces.
  • Baking secrets into images or storing them in repo or plain Kubernetes Secrets without encryption.
  • Assuming network isolation exists by default — you must explicitly define NetworkPolicies.
  • Not enforcing signature verification or image provenance at deploy time.

Conclusion

---

Related Articles

Your Security is Non-Negotiable

At SteeleFortress, we've protected hundreds of organizations from cyber threats.

Schedule Your Free Security Assessment →

Stop hoping you won't get breached.

Get the 15-point Security Audit Checklist that attackers don't want you to have. Plus weekly intel briefs - no fluff, no vendor pitches.

No spam. Unsubscribe anytime. We don't sell your data - we protect it.