Kubernetes security best practices start by limiting what identities can do, protecting credentials, restricting what workloads may do on a node, and exposing only the network paths the application actually needs.
For small teams, the goal is not to reproduce every enterprise security control. It is to establish a baseline that prevents a routine application compromise from turning into cluster-wide control. RBAC should follow least privilege, workloads should use purpose-specific ServiceAccounts, Secrets should have a deliberate storage and delivery model, and Pods should run under a security policy appropriate to their risk.
This guide owns the security baseline inside the Kubernetes Cluster Management for Small Teams operating model. It does not duplicate the traffic-isolation work in Kubernetes Network Policies for Small Teams or the tenant-architecture decisions in Kubernetes Multi-Tenancy for MSPs.
At Raff, the security review starts with one question: if this identity, Pod, or credential is compromised, what is the largest action it can perform next? The baseline should make that answer as narrow and explainable as the workload allows.
Kubernetes security starts with four control layers
A production Kubernetes security baseline is easier to operate when controls are separated by what they protect.
| Layer | Main Kubernetes controls | Security question |
|---|---|---|
| Identity and API access | Users, ServiceAccounts, RBAC, kubeconfig | What can this identity do through the Kubernetes API? |
| Credentials and secrets | Secrets, external secret systems, token policy | Which sensitive values can this workload retrieve? |
| Workload execution | Pod Security Standards, securityContext, admission | What may this Pod do on the node? |
| Network and exposure | VPC, Services, ingress, NetworkPolicy | Which traffic paths can reach or leave the workload? |
These layers are related but not interchangeable.
RBAC can prevent a ServiceAccount from deleting Deployments, but it does not stop the application process from running as root inside its container. Pod Security can restrict privilege escalation, but it does not decide whether an engineer may read a Secret. A private VPC reduces public exposure, but it does not make every Pod inside the cluster equally trusted.
The operating model is therefore layered:
Human / workload identity ↓ Kubernetes RBAC ↓ Secret and credential access ↓ Pod execution restrictions ↓ Network exposure and segmentation ↓ Application authorization
Pod Security Standards define what a workload may do on a node; RBAC defines what an identity may do through the Kubernetes API.
For network segmentation after a workload is admitted, use the dedicated Kubernetes NetworkPolicy guide. This page keeps the security baseline centered on identities, credentials, and workload execution.
RBAC should make least privilege the default
Kubernetes Role-Based Access Control authorizes actions against API resources. The most important production rule is to grant only the permissions an identity actually needs.
The official Kubernetes RBAC good practices recommend namespace-level permissions where possible, avoiding wildcard permissions, and minimizing powerful credentials.
The four core RBAC objects have different scopes:
| Object | Scope | Main use |
|---|---|---|
Role | One namespace | Define permissions inside that namespace |
ClusterRole | Cluster-wide definition | Cluster-scoped resources or reusable permission sets |
RoleBinding | One namespace | Grant a Role or ClusterRole only inside that namespace |
ClusterRoleBinding | Cluster-wide | Grant a ClusterRole across the cluster |
This means a ClusterRole is not automatically a cluster-wide grant. A RoleBinding can bind a ClusterRole within one namespace. The larger escalation happens when a ClusterRole is attached through a ClusterRoleBinding.
A ClusterRoleBinding is a cluster-wide permission decision, not a convenience shortcut.
Small teams should review several permission patterns carefully:
cluster-adminfor routine users, CI/CD, or application workloads;- wildcard verbs such as
*when onlygetorlistis required; - wildcard resource access that automatically expands to future API resources;
- Secret
get,list, orwatchpermissions; - permissions to create or modify Pods and workload controllers;
- access to RBAC resources that lets an identity grant new permissions;
- cluster-scoped permissions when the workload operates in one namespace.
One subtle risk is workload creation. Kubernetes documents that permission to create a Pod or a controller such as a Deployment in a namespace can create indirect access to Secrets and other resources available to workloads in that namespace. Security review should therefore consider what an identity can cause a Pod to mount or impersonate, not only which objects it can read directly.
A practical review starts by asking what the identity must do in normal operation, then grants only the verbs, resources, and namespaces required for that job. If an emergency needs broader access, treat that as an explicit administrative path rather than the everyday default.
ServiceAccounts should have one job and minimal credentials
Kubernetes ServiceAccounts are non-human identities used by Pods, controllers, CI/CD systems, and automation.
Every namespace receives a default ServiceAccount. With RBAC enabled, that default identity receives only the baseline discovery permissions unless more access is granted. However, a Pod that does not specify another ServiceAccount is assigned the namespace's default ServiceAccount, and Kubernetes normally projects credentials for the assigned identity into the Pod.
The security baseline is therefore not simply “the default ServiceAccount has no roles.” It is to make workload identity intentional.
Use a dedicated ServiceAccount when a workload needs Kubernetes API permissions. Grant that account only the required RBAC rights and assign it only to the workloads that need them.
When an application does not need to call the Kubernetes API, consider disabling automatic service-account token mounting with automountServiceAccountToken: false. Current Kubernetes versions use short-lived, automatically rotating projected tokens through the TokenRequest API for normal Pod ServiceAccount credentials, which is safer than the older long-lived static token pattern. The Service Accounts documentation recommends short-lived TokenRequest or projected tokens over manually created long-lived ServiceAccount token Secrets.
A small-team identity model can be simple:
web application → no Kubernetes API access deployment controller → narrowly scoped deployment permissions backup controller → only the resources required for backup/restore human administrator → separate named administrative identity
Avoid using one powerful ServiceAccount for several unrelated workloads merely because it already works. Shared credentials make it harder to understand blast radius and harder to rotate or revoke one application's access without affecting another.
At Raff, we treat a ServiceAccount as part of the workload architecture, not as deployment boilerplate. If a Pod receives an API credential, there should be a named reason for it.
Secrets need stronger controls than base64 encoding
Kubernetes Secrets provide a native way to hold confidential values such as passwords, tokens, keys, or certificates, but the object type does not make every secret-handling decision safe automatically.
The most important distinction is that base64 is formatting, not encryption.
The upstream Kubernetes Secrets documentation states that Secret objects are stored unencrypted in etcd by default unless encryption at rest is configured. Managed Kubernetes services can change that implementation detail, so teams should verify the provider's documented behavior rather than assuming upstream defaults or assuming encryption exists without evidence.
For Raff specifically, the current public Kubernetes product page does not document the encryption-at-rest implementation for Kubernetes Secret objects. This guide therefore does not claim one. Teams with a specific encryption or key-management requirement should verify that control before treating it as part of their compliance boundary.
Secret security still has several workload-level controls regardless of provider implementation:
- do not commit plaintext Secret values to Git or application repositories;
- restrict RBAC access to
get,list, andwatchSecrets; - separate namespaces when workloads should not share mounted-secret trust;
- expose each workload only to the credentials it actually needs;
- rotate credentials when a team member, service, or integration no longer needs them;
- avoid logging Secret values or passing them through diagnostics;
- use short-lived credentials where the external system supports them;
- define who can create workloads that mount or reference Secrets.
The Kubernetes Secrets good practices also recommend encryption at rest and restrictive Secret API permissions for cluster administrators.
Raff currently lists Sealed Secrets as an optional one-click Kubernetes application. That can be part of a team's Git-oriented Secret workflow, but its availability should not be interpreted as automatic Secret encryption for every workload or as a replacement for RBAC and credential rotation.
The practical question is not “Are we using Kubernetes Secrets?” It is “Who can retrieve this value, how does the workload receive it, how is it rotated, and what happens if it leaks?”
Pod Security Standards create a workload execution baseline
RBAC protects the Kubernetes API. Pod security controls what an admitted workload can do once it runs on a node.
Kubernetes defines three Pod Security Standards:
| Profile | Intent | Typical use |
|---|---|---|
Privileged | Unrestricted | Trusted system/infrastructure workloads that genuinely require host-level capabilities |
Baseline | Prevent known privilege escalations while preserving broad compatibility | General workloads that cannot yet meet Restricted |
Restricted | Enforce current Pod hardening best practices | Security-sensitive and lower-trust application workloads where compatibility allows |
The Restricted profile builds on Baseline and includes controls such as disallowing privilege escalation, requiring non-root execution, requiring an allowed seccomp profile, and dropping Linux capabilities except tightly defined exceptions.
This does not mean every namespace should be switched directly to Restricted without testing. Infrastructure components, storage systems, networking add-ons, or other trusted system workloads can require privileges that ordinary applications should never receive.
Kubernetes' built-in Pod Security Admission supports three modes:
enforcerejects Pods that violate the selected policy;auditrecords violations in audit annotations without rejecting the Pod;warnshows a user-facing warning while allowing the Pod.
These modes make gradual adoption possible. A team can identify which workloads fail a target policy before turning that policy into a production admission gate.
Workload securityContext settings then provide the concrete execution controls beneath that policy. Common production settings to evaluate include:
runAsNonRoot;allowPrivilegeEscalation: false;- dropping unnecessary Linux capabilities;
- using
RuntimeDefaultor another approved seccomp profile; - avoiding privileged containers and host namespace access unless the workload requires them.
The correct policy follows the workload. A normal public API should not receive host-level privileges because one monitoring or storage component requires them.
The security decision framework should follow workload risk
A small team does not need one identical policy for every Pod. It needs explicit security tiers whose exceptions can be explained.
| Workload type | RBAC starting point | Credential approach | Pod security starting point | Additional review |
|---|---|---|---|---|
| Public stateless web/API | No Kubernetes API rights unless required | Only application credentials it needs | Restricted where compatible | Public exposure + NetworkPolicy |
| Private worker | No API rights by default | Queue/database credentials only | Restricted where compatible | Egress dependencies |
| CI/CD controller | Narrow deploy permissions in target namespaces | Short-lived automation identity where possible | Baseline/Restricted according to controller requirements | RBAC escalation paths |
| Database/operator controller | Exact CRD/resource permissions needed | Dedicated ServiceAccount and data credentials | Test against Restricted; document exceptions | Storage, backup, cluster-scoped access |
| Observability/security agent | Only required read/watch permissions | Dedicated ServiceAccount | May need specific exceptions | Node access and data sensitivity |
| Trusted infrastructure add-on | Explicitly reviewed elevated rights | Dedicated credentials | Baseline or Privileged only when justified | Node blast radius and isolation |
Use four questions when approving an exception:
- Why does this workload need the permission or privilege? Name the feature that fails without it.
- Can the permission be namespaced? Avoid cluster-wide grants when the workload operates in one namespace.
- Can the credential be removed or shortened? A workload that never calls the API should not carry an API token by habit.
- What is the blast radius if the workload is compromised? Consider API access, mounted Secrets, node privileges, and network reachability together.
Network isolation remains a separate layer. If the answer includes “this Pod should only talk to the database and DNS,” implement that through the NetworkPolicy model, not through RBAC.
For MSPs deciding whether a tenant should share a control plane at all, use Kubernetes Multi-Tenancy for MSPs. That page owns the shared-cluster-versus-dedicated boundary.