Skip to main content
Red Hat OpenShift admits pods through Security Context Constraints (SCCs), which restrict the user and group IDs a pod may request. The Tyk Helm charts ship hardened defaults that pin specific IDs, and those IDs fall outside the range OpenShift allocates to a project. This page explains how to opt out of the pinned IDs so the SCC can assign its own.

Compatible Versions

How Security Context Constraints Affect Tyk

When you create a project, OpenShift allocates it a block of UIDs and GIDs, typically starting above 1000000000. The restricted-v2 SCC applies one rule to both runAsUser and fsGroup:
  • If the pod leaves the field unset, the SCC assigns a value from the project’s allocated range.
  • If the pod sets the field explicitly, the SCC validates it against that range and rejects the pod if it falls outside.
The Tyk charts set both fields explicitly, so a default installation is rejected. Installing tyk-oss with default values on OpenShift as an unprivileged user produces two independent violations:
Only an explicit runAsUser and an explicit fsGroup cause this. The other hardening the charts apply is compliant with restricted-v2 and should be left in place.
SCCs are evaluated when a pod is admitted, not when a Deployment or StatefulSet is created. Rendering manifests with helm template does not prove that a workload will be admitted. Always verify against real pods.

Prerequisites

  • An OpenShift 4.21 cluster, including Red Hat OpenShift Service on AWS (ROSA).
  • The oc CLI and Helm 3+.
  • An Enterprise Edition License for tyk-stack, tyk-control-plane and tyk-data-plane.
  • A deploying account with the admin role on the target project. The edit role is not sufficient, because the charts create Roles and RoleBindings for the bootstrap job.
To see the UID and GID range allocated to your project:
If you deploy through Argo CD or Flux CD, also configure the bootstrap jobs for GitOps. See Deploy Tyk Helm Charts with GitOps.

Disabling The Chart Security Contexts

Every securityContext block in the charts accepts an enabled flag. Setting enabled: false omits the entire block from the rendered manifest, which leaves the fields unset and lets the SCC assign them. The enabled key itself is never rendered.

The Tyk Gateway Init Container Falls Through

The Tyk Gateway runs an init container, setupDirectories, that prepares its working directory. The chart resolves its runAsUser from the first value it finds: the init container’s own securityContext, then gateway.containerSecurityContext, then gateway.securityContext. If none sets a UID, the init container runs as 65532, which matches the Tyk Gateway image. Setting enabled: false on the init container’s own block does not remove the security context outright. The template falls back to gateway.containerSecurityContext. To omit the init container’s security context entirely, set enabled: false on both blocks. The values profiles below do this for you.
Use these opt-out flags only on clusters that assign IDs, such as OpenShift. On vanilla Kubernetes nothing assigns a UID, and kubelet rejects the busybox init container with CreateContainerConfigError: container has runAsNonRoot and image will run as root.

Values Profiles By Chart

Each tab below is a complete, ready-to-paste OpenShift profile. Merge it into your values.yaml alongside your normal configuration, then install as usual.

Tyk Pump is enabled by default in this chart. Tyk Developer Portal and Tyk Operator are not.

Redis And PostgreSQL

Redis and PostgreSQL are not dependencies of the Tyk charts. You install them as separate releases, and they have their own security contexts that OpenShift rejects independently of anything you configure in Tyk’s values. The Bitnami charts, which Tyk’s installation guides use, pin uid and gid 1001 on primary and replica pods. Disabling the Tyk security contexts does nothing for them. Apply the opt-out to those releases as well:
Consult the chart documentation for whichever Redis and PostgreSQL distributions you use, and confirm the exact key names, since they differ between chart vendors and versions.

Redis Must Be Able To Write Its Data Directory

Admission is only half the problem. A Redis pod that starts successfully can still be unusable if it cannot write to /data. Container images bake in a data directory owned by the image’s own user, for example redis:redis with mode 0755. On OpenShift the container runs as an arbitrary assigned UID that does not own that directory, so background saves fail. Because Redis defaults to stop-writes-on-bgsave-error yes, it then refuses every write command, including PING:
The failure is also delayed. Redis only attempts its first background save once its save interval elapses, so the deployment can look healthy for an hour before writes start failing. Mount a volume at the data directory so the SCC-assigned fsGroup applies to it. Any emptyDir or PersistentVolumeClaim works, because OpenShift sets group ownership and the setgid bit on mounted volumes:

Verifying Admission

Install the chart, then confirm the pods were admitted and see which SCC accepted them:
Every pod should report restricted-v2. Confirm the SCC assigned IDs from the project range rather than the chart defaults:
You should see a runAsUser and fsGroup in the 1000000000 range, and no fsGroup: 2000 or runAsUser: 65532. Finally, check the Tyk Gateway is healthy. Forward the service port and call the endpoint from your own machine:
A healthy Tyk Gateway returns "status":"pass" with a "pass" for each configured dependency:
If a pod is not created at all, the SCC rejected it. The error is on the ReplicaSet or Job, not the pod, because no pod object exists:

Running Helm Tests

The Helm test pods in tyk-stack, tyk-data-plane and tyk-oss pin runAsUser: 1000 on both their pod-level and container-level blocks, because the default test image declares no USER. Without the opt-out, helm test is rejected on OpenShift even when every application pod is running. The tests section in the profiles above covers this. tyk-control-plane ships no test pod.
One of the test pods is not cleaned up after a run, because it carries no helm.sh/hook-delete-policy. A second helm test against the same release then fails, because the pod name already exists. Delete the leftover pod before re-running:

Upgrade Notes

From chart v5.4.0 the container-level runAsUser is removed from the component defaults while runAsNonRoot: true is retained. When no runAsUser is set, kubelet falls back to the USER directive baked into the image and verifies it is non-root. This is safe on the default image tags, which all declare a numeric non-root USER. It is not safe if you pin older tags. On upgrade, every pod using an affected image fails admission:
Three cases break:
  • The image declares no USER at all.
  • The image declares USER 0. Tyk Gateway v5.9.1 is an example.
  • The image declares a symbolic USER, such as distroless nonroot. Kubelet cannot verify a non-numeric user against runAsNonRoot and reports non-numeric user (nonroot), cannot verify user is non-root.
Before upgrading, check any tag you have pinned:
Anything other than a numeric, non-zero value needs either a tag bump or an explicit runAsUser in your own values, which continues to be honored.
Tyk Dashboard tags earlier than v5.5.0 report USER='' and will fail this check. If you pin such a tag, set an explicit runAsUser for Tyk Dashboard or move to v5.5.0 or later.

Upgrading With Helm Hooks Disabled

With bootstrap.disableHelmHooks: true, a plain helm upgrade fails on the immutable bootstrap Job. See Upgrade And Re-Run Safety.

Changed Keys

  • pump.extraContainers was previously nested inside the Tyk Pump securityContext condition, so sidecars silently disappeared when that block was falsy. The two are now independent.