Vicedomini Softworks

DevOps

OpenShift Best Practices: Choices That Hold in Production

23 October 2026

Engineer reviewing an OpenShift production configuration

The most reliable OpenShift practices fall into five areas: explicit resource requests, health probes, restrictive security context constraints, declarative GitOps delivery and a clear operating model for the platform. Each has a conventional answer and at least one credible alternative. This article sets out the options side by side, states where the trade-offs lie and indicates which choice suits which kind of organisation.

Vicedomini Softworks
Build OpenShift Systems for Production
Vicedomini Softworks builds cloud-native software and infrastructure, with engineering expertise in Red Hat OpenShift, Kubernetes, security, and observability.
Ask for a consultation

TL;DR

  • Define resource requests for every production workload, and treat CPU limits as a deliberate decision rather than a default.
  • Configure both liveness and readiness probes, and keep application workloads out of the reserved openshift-* and kube-* projects.
  • Keep the restricted-v2 security context constraint as the baseline and create custom SCCs instead of editing the defaults.
  • Manage manifests declaratively through GitOps, with Helm or Kustomize rather than duplicated raw YAML.
  • Decide early who owns platform decisions: an in-house team, a managed service, or a technical advisory arrangement.

Table of Contents

Why “best practice” is a contested term

OpenShift extends Kubernetes with an opinionated security model, an integrated build and deployment toolchain and an operator-driven lifecycle. That opinionation removes many decisions, but not all of them. The Red Hat engineer behind the OpenShift GitOps guidance states openly that the phrase “best practices” implies a single correct way of working, and prefers to speak of recommended practices. The distinction is useful: most of what follows is a choice between options with different costs, not a rule to be applied mechanically.

The sections below therefore follow a consistent pattern. Each describes the baseline that nearly every production cluster should meet, then the decision points where reasonable teams diverge.

Resource requests and limits

The baseline: requests everywhere

Production workloads need explicit resource requests and limits in their pod specifications. Without requests, the scheduler cannot guarantee resources and pods may starve; without limits, a single pod can consume a disproportionate share of a node and trigger evictions or node-level failures. The same guidance suggests starting with modest values, for example 100m of CPU and 128Mi of memory, and refining them from observed behaviour in Prometheus and Grafana rather than from estimates.

Illustration contrasting CPU and memory limit behavior

A pod’s memory limit is enforced by the kernel through cgroups, as the capacity management guidance describes, which means a container exceeding it is terminated rather than slowed. This asymmetry between CPU and memory is the root of the most frequent disagreement in this area.

The decision: CPU limits or not

Setting CPU limits can trigger kernel-level throttling, which frequently appears as latency spikes even when the host has spare capacity. Teams that apply a uniform limit to every workload often misdiagnose the resulting slowness as an application defect. The table summarises the three common positions.

Approach Strength Weakness Suited to
Requests and limits for CPU and memory Predictable ceilings, simple capacity arithmetic Throttling can degrade latency-sensitive services Multi-tenant clusters with unknown workloads
CPU requests only, memory requests and limits Avoids throttling while still protecting nodes from memory exhaustion Noisy neighbours on CPU are possible under contention Latency-sensitive services owned by a mature team
Namespace quotas and default LimitRanges only Centralised governance, little per-team effort Defaults are rarely right for any specific service Early-stage platforms that need a safety net

Our reading is that the second approach is the most defensible for services whose latency matters, provided that requests are measured and quotas bound each project. The first remains sensible where the platform team cannot vouch for the workloads it hosts.

Sizing the platform’s own components

Resource discipline applies to platform tooling as well. The GitOps installation documentation includes sizing requirements, and production-scale Argo CD installations often require the argocd-redis pod to be given considerably more memory than its default, with 8Gi cited as an example of a manual increase. A GitOps controller evicted under load is an operational incident of the platform’s own making.

Health probes and resilience

Availability depends on two distinct signals. A liveness probe restarts a pod whose process has hung. A readiness probe withholds traffic until the application has finished initialising, which prevents intermittent connection errors during startup and rolling updates. The Red Hat developer guidance recommends defining both, typically against a lightweight endpoint such as /healthz, and adding timeouts, retries and circuit breakers, ideally offloaded to a service mesh.

The Kubernetes project’s own catalogue of common pitfalls lists deployments without explicit health checks among the recurring mistakes. The practical caution concerns liveness probes in particular: a probe that depends on a downstream database will restart healthy pods whenever that database is slow, converting a partial outage into a complete one. Liveness should test the process itself; readiness may test its dependencies.

Probe design Behaviour under a slow dependency Recommendation
Liveness checks the dependency Pods restart in a cascade Avoid
Readiness checks the dependency Pods leave the service endpoints and recover without restarts Preferred
No probes Traffic reaches pods that are not ready Avoid in production

Security context constraints and project hygiene

Keep the restricted baseline

As of OpenShift 4.18, the restricted-v2 SCC is applied to newly created pods. It requires non-root execution and applies the runtime default seccomp profile, which limits the system calls a container may make. Applications that assume root, a common legacy of Docker-based images, must be rebuilt to run under an arbitrary user ID rather than granted broader permissions.

Custom SCCs instead of edited defaults

The documentation on managing security context constraints discourages modifying the default SCCs, because they are recreated during installation and when some Operators are installed. The alternative is to define a custom SCC for each unusual workload and bind it to a dedicated service account. This keeps exceptions visible, reviewable and narrow.

Never deploy into default projects

Projects beginning with openshift- and kube- host cluster components and are highly privileged. Placing customer workloads there bypasses the protections that SCCs and admission plugins provide, and exposes the whole cluster to the consequences of a compromised application. Dedicated projects per application or team are the standard remedy.

Admission control as the enforcement layer

Admission plugins intercept API requests before objects are persisted to etcd. The architecture documentation explains that mutating plugins run first and validating ones afterwards, and that validating webhooks operate on the final object state. Knowing this order is what allows an engineer to explain why a deployment was rejected, and which policy to adjust. The Kubernetes security guidance adds a complementary habit: pin image versions instead of using the :latest tag, and use admission policy to stop privileged or root containers reaching the cluster at all.

Admission request flow through mutation and validation

GitOps and configuration management

The central principle is declarative state held in Git. The GitOps recommendations referenced above advise separating application source repositories from manifest repositories, since the two evolve on different lifecycles, and using a YAML management tool rather than maintaining duplicate raw files per environment. The remaining question is which tool.

Criterion Kustomize Helm
Model Patches layered over plain YAML bases Templates with values files
Readability of output High, since bases remain valid YAML Lower when templates are heavily conditional
Best fit Environment variations of in-house applications Packaged third-party software and cases that need real templating
Principal risk Overlay sprawl across many clusters Template logic that is hard to review

The guidance itself is pragmatic: a team may nominate a preferred tool without becoming locked into it, and should use Helm where templating is genuinely required instead of contorting Kustomize. Versioning manifests, through tag tracking or commit pinning in Kustomize or versioned charts in a Helm or OCI repository, keeps rollbacks deterministic.

Scaling and capacity

Cluster growth carries its own operational rules. Red Hat’s scalability and performance documentation advises spreading nodes across all available zones and scaling up by no more than 25 to 50 machines at once, with additional machine sets per zone using alternative instance types to mitigate provider capacity constraints. Teams planning a large migration should therefore stage node growth rather than request the final capacity in one step, and verify the figures against the documentation for their own OpenShift version, as limits change between releases.

Choosing an operating model

Technical practice is only sustained if someone owns it. Three operating models recur, and none is universally superior.

Model Advantage Constraint
Fully in-house platform team Deep context, direct control Hiring and retaining OpenShift expertise is slow and costly; knowledge concentrates in few people
Managed OpenShift service Cluster lifecycle handled by the provider Application-level decisions (quotas, SCCs, GitOps structure, probes) remain the customer’s responsibility
In-house team with senior technical advisory Architectural decisions reviewed by an experienced engineer, without a full-time hire Requires the in-house team to execute recommendations

The second row deserves emphasis. Outsourcing the control plane does not outsource the practices described above; the majority of them operate at the namespace and application level. The third model suits organisations that have developers but lack someone accountable for architecture.

Our perspective

Vicedomini Softworks is an Italian software engineering company, and OpenShift sits within the cloud-native stack we build on alongside Kubernetes, Quarkus, Spring Boot and Jakarta EE. Our experience is that platform failures rarely originate in exotic features. They originate in ordinary decisions taken without an owner: a limit copied from a template, a probe that checks the wrong thing, an SCC widened for a deadline and never narrowed again.

For that reason we work without an account-manager layer, so that the engineers who design and maintain a system are the ones who explain its trade-offs. We hold no vendor bias, and every consulting engagement ends in written recommendations, which allows a team to challenge, adopt or reject each decision on its merits. We also limit the number of simultaneous projects, because an architectural review conducted in a hurry reproduces the very defaults it is meant to question.

Our practical advice is to start with the least glamorous items: measured requests, honest probes, a restricted security baseline and a manifest repository that a new engineer can read in an afternoon. Sophistication in service meshes or multi-cluster topologies is worth pursuing only once those foundations hold.

— Pepe F.

Getting an experienced second opinion

Where an OpenShift estate has grown without a clear owner, a structured review is usually more productive than a rewrite. We offer an initial assessment from €3,500 as a one-off engagement, and ongoing technical leadership through CTO Advisory from €1,800 per month, Fractional CTO from €4,000 per month and CTO Partner from €7,500 per month. Code audits, architecture and technology stack reviews and system integration work are described on our services page, and examples of delivered work are collected among our case studies.

A pragmatic order of adoption

For an organisation starting from an unreviewed cluster, the sequence below reduces risk fastest, because each step makes the following one safer.

Stage Action Evidence that it is done
1 Move any workload out of openshift-* and kube-* projects No application pods remain in default projects
2 Remove ad hoc changes to default SCCs; create custom ones where needed Every exception is a named, reviewed SCC
3 Add requests, memory limits and a reasoned CPU policy Quotas exist per project; throttling metrics are monitored
4 Add liveness and readiness probes with distinct purposes Rolling updates complete without connection errors
5 Move manifests to Git with Helm or Kustomize, and pin image versions The cluster state can be rebuilt from the repository
6 Enforce policy through admission control Insecure configurations are rejected at the API

This order is deliberately security-first, since the first two stages cost little and remove the largest exposure.

FAQ

Is OpenShift harder to learn than Kubernetes?

OpenShift adds concepts such as projects, routes, SCCs and Operators on top of Kubernetes, but it also supplies defaults that Kubernetes leaves to the operator. Teams that understand Kubernetes fundamentals tend to adopt OpenShift’s additions quickly. Starting with OpenShift alone is possible, although administrators then often meet Kubernetes behaviour they were not expecting.

Should every container have a CPU limit?

Not necessarily. CPU limits can cause kernel throttling and visible latency even when the node has spare capacity, so latency-sensitive services are often run with CPU requests only. Memory limits, by contrast, should normally be set, since memory cannot be reclaimed by throttling.

Can the default security context constraints be edited?

The documentation discourages it, because defaults are recreated during installation and when certain Operators are installed. The recommended route is a custom SCC assigned to a specific service account, which keeps the exception explicit and auditable.

Helm or Kustomize for OpenShift GitOps?

Both are supported, and the guidance advises against exclusive loyalty to one. Kustomize suits environment overlays of plain manifests, while Helm suits packaged software and cases that need genuine templating.

Does a managed OpenShift service remove the need for these practices?

No. The provider operates the cluster, but resource sizing, probes, project layout, SCC choices and GitOps structure remain the responsibility of the teams deploying applications.

Sources

This article was produced with AI assistance and reviewed for accuracy. It is provided for general information only and is not professional advice.