A Kubernetes secret is an object in the Kubernetes ecosystem that contains sensitive information (think keys, passwords, and tokens). Instead of including this data directly in a pod or a deployment, storing data you want to keep secure in a secret allows you to reduce your attack surface - and reduce the chance this critical information is altered during the software development life cycle.
apiVersion: v1
kind: Secret
metadata:
name: file-credential
data:
.secret-file: dmFsdWUtMg0KDQo=
Kubernetes Security Best Practices [Cheat Sheet]
This 6 page cheat sheet goes beyond the basics and covers security best practices for Kubernetes pods, components, and network security.
Download PDFOnce you create a secret, you need to refer to that secret in your pod. The config file below gives your pod access to the Kubernetes secret we created in the manifest above:
apiVersion: v1
kind: Pod
metadata:
name: secret-files-pod
spec:
volumes:
- name: secret-volume
secret:
secretName: file-secret
containers:
- name: dotfile-test-container
image: registry.k8s.io/busybox
command:
- ls
- "-l"
- "/etc/secret-volume"
volumeMounts:
- name: secret-volume
readOnly: true
mountPath: "/etc/secret-volume"
In this example, your secrets file will be present in the /etc/secret-volume location
in the file system for your application to access. (In the volume mount definition, you specify where the file path will be.)
Use cases for Kubernetes secrets
Let’s take a look at specific scenarios where it’s best practice to leverage Kubernetes secrets:
Providing environment variables to containers: Some environment variables can be used to control the behavior of your application, so it’s a good idea to use secrets to provide those values. These container environment variables can also contain sensitive information like credentials, which are used to call third-party apps (for example, payment gateways).
Providing credentials such as SSH keys and passwords to containers: Secrets can deliver SSH credentials, passwords, TLS certificates, and more to containers. SSH keys and TLS certificates are important security tokens that can be used in applications and via secrets delivered to them.
Allowing container images to be pulled from the registry: Secrets are also used when allowing the image-pull step in nodes. You can configure image pull secrets by providing Docker registry credentials in secrets, which will be used by Kubelet to pull the container images stored in the registry.
Storing extra information like Helm details: Just like Helm uses secrets, other applications can use secrets to carry out their functions.
Types of Kubernetes secrets
Based on specified secret values, secrets are divided into these types:
Opaque
Opaque secrets are generic secrets that anyone can create and use. These are basic key-value pairs and are the default secret type, so if you don’t explicitly mention the type, an Opaque secret will be created (with opaque type defined). Using this secret type is often recommended for storing arbitrary key-value pairs when no specialized secret format is required.
ServiceAccount token secrets
These are the tokens that are used to identify the service accounts, which can be used to provide specified Kubernetes APIs with access to pods. This API uses the kubernetes.io/service-account-token type.
SSH-auth
This type of secret is used to save data that’s used for SSH authentication purposes. SSH authentication secrets use the kubernetes.io/ssh-auth (defined and public secret) type.
TLS
Use these to store TLS certificates and the associated keys; kubernetes.io/tls is the type to define to leverage this form of secret.
Basic-auth
For basic authentication secrets, define the type as kubernetes.io/basic-auth.
Docker-cgf and Dockerconfigjson
Configurations related to Docker and registry secrets are generally stored in these two types of secrets. To use docker-cfg and dockerconfigjson, define the type as kubernetes.io/dockercfg or kubernetes.io/dockerconfigjson.
Token
This secrets type refers to the bootstrap token secrets that are used to add new nodes to a Kubernetes cluster. To use this token in the node bootstrap process, define bootstrap.kubernetes.io/token.
New data alert: Kubernetes clusters are being targeted within minutes of deployment.
The Wiz Kubernetes Security Report 2025 reveals that attackers start probing new clusters in as little as 18 minutes. Learn how to strengthen your defenses before threats strike.
Download PDFHow to create a secret in Kubernetes
Below are the steps to create and apply a Kubernetes secret:
1. Encode the secret value in Base64
Before adding a Secret to Kubernetes, the sensitive data must be encoded in Base64. Run the following command to encode your secret value:
echo -n "value-2" | base64
This outputs an encoded string, which you will use in the Secret manifest. Kubernetes requires Secrets in Base64 format to ensure proper storage and retrieval. Keep in mind that Base64 is not encryption, so the data remains readable if decoded. Use additional security measures like encryption at rest for better protection.
2. Create a secret YAML manifest
Now, define the Secret in a YAML file using the encoded value. Create a new file called secret.yaml and add the following content:
apiVersion: v1
kind: Secret
metadata:
name: file-credential
data:
.secret-file: dmFsdWUtMg0KDQo=
The .secret-file key represents the name of the secret file inside the pod, and the corresponding value is the Base64-encoded secret.
Kubernetes allows secret names beginning with dot characters, which means these files will be treated as hidden files when mounted inside a container. Keep in mind that in Unix-like systems, files beginning with dot are hidden by default—so if you run a standard ls -l, they may not appear; use ls -la to display all files, including hidden ones.
Alternatively, you can use stringData to store unencoded values, and Kubernetes will automatically encode them:
apiVersion: v1
kind: Secret
metadata:
name: file-credential
stringData:
.secret-file: value-2
3. Apply the secret to the cluster
Use kubectl apply to create the Secret in the Kubernetes cluster:
kubectl apply -f secret.yaml
To confirm that the Secret was created successfully, list all Secrets:
kubectl get secrets
To view the specific Secret in YAML format:
kubectl get secret file-credential -o yaml
To verify the stored value (decoding it from Base64):
kubectl get secret file-credential -o jsonpath="{.data.\.secret-file}" | base64 --decode
4. Mount the secret in a pod
To allow a pod to use the Secret, you need to define a volume that references it. Create a new file called pod.yaml and add the following configuration:
apiVersion: v1
kind: Pod
metadata:
name: secret-files-pod
spec:
volumes:
- name: secret-volume
secret:
secretName: file-credential
containers:
- name: dotfile-test-container
image: registry.k8s.io/busybox
command: [ "ls", "-l", "/etc/secret-volume" ]
volumeMounts:
- name: secret-volume
readOnly: true
mountPath: "/etc/secret-volume"
This mounts the Secret as a read-only file inside the container in a pod at /etc/secret-volume.
Kubernetes automatically creates a file for each key inside the mounted directory.
The secret value will be stored inside /etc/secret-volume/.secret-file.
This approach is also applicable for secrets with static pods, where the secret is pre-mounted into the pod's filesystem.
5. Deploy the pod and confirm the secret is accessible
Apply the pod configuration to deploy the pod:
kubectl apply -f pod.yaml
Check if the pod is running:
kubectl get pods
Instead of relying on logs, exec into the pod and verify the Secret is present:
kubectl exec secret-files-pod -- ls -l /etc/secret-volume
kubectl exec secret-files-pod -- cat /etc/secret-volume/.secret-file
If everything is set up correctly, the first command will list the secret file, and the second command will print its decoded contents.
How pods consume Kubernetes secrets
Kubernetes provides multiple ways for pods to securely access secrets, depending on the application's requirements. Secrets can be injected as environment variables, mounted as volumes, used for pulling container images, or leveraged for API authentication. Let's explore each method below with examples.
1. Using secrets as environment variables
Kubernetes allows secrets to be injected into a container’s environment variables, enabling applications to securely access sensitive data without hardcoding credentials. This method is useful for passing API keys, database passwords, or authentication tokens.
Below is a YAML example where a pod references a secret (db-secret) as an environment variable:
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
DB_PASSWORD: c3VwZXJzZWNyZXQ= # Base64-encoded "supersecret"
---
apiVersion: v1
kind: Pod
metadata:
name: env-secret-pod
spec:
containers:
- name: app-container
image: nginx
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: DB_PASSWORD
The DB_PASSWORD environment variable pulls its value from the db-secret secret.
This keeps sensitive data out of the container’s image and deployment files.
2. Mounting secrets as volumes
Another approach is mounting secrets as files inside a container, allowing applications to read them at runtime. This is ideal for SSH keys, TLS certificates, or complex configurations that don’t fit neatly into environment variables.
Here’s an example of a pod mounting a secret (tls-secret) as a volume:
apiVersion: v1
kind: Secret
metadata:
name: tls-secret
type: kubernetes.io/tls
data:
tls.crt: BASE64_ENCODED_CERT
tls.key: BASE64_ENCODED_KEY
---
apiVersion: v1
kind: Pod
metadata:
name: tls-secret-pod
spec:
volumes:
- name: tls-volume
secret:
secretName: tls-secret
containers:
- name: web-server
image: nginx
volumeMounts:
- name: tls-volume
mountPath: "/etc/tls"
readOnly: true
The secret is mounted inside the container at /etc/tls.
Applications can securely read the secret from this path at runtime.
3. Using secrets for pulling container images
When pulling images from private container registries, Kubernetes requires authentication credentials, which can be stored as a Docker registry secret. This secret allows nodes to securely fetch images without exposing credentials.
To use a container image pull secret (docker-registry-secret), reference it in a pod spec like this:
apiVersion: v1
kind: Pod
metadata:
name: private-registry-pod
spec:
containers:
- name: private-app
image: my-private-registry.com/private-image:latest
imagePullSecrets:
- name: docker-registry-secret
The imagePullSecrets field specifies the secret containing registry credentials.
Kubernetes will use this secret when pulling the container image.
4. Service account secrets for API authentication
Kubernetes automatically mounts service account tokens as secrets inside pods, allowing them to authenticate with the Kubernetes API securely. These tokens are used for inter-service communication and permission management.
By default, Kubernetes mounts the service account token in each pod at /var/run/secrets/kubernetes.io/serviceaccount/token. An application inside the pod can use this token to authenticate API requests, as shown in this example:
apiVersion: v1
kind: Pod
metadata:
name: service-account-pod
spec:
serviceAccountName: default
containers:
- name: api-client
image: busybox
command: [ "cat", "/var/run/secrets/kubernetes.io/serviceaccount/token" ]
The service account token allows the pod to interact with the Kubernetes API.
This is essential for applications that need to query cluster resources or perform automated tasks.
Managing Kubernetes secrets: Key actions and best practices
Kubernetes offers different ways to securely handle secrets, from creation and access control to monitoring and rotation. Proper secret management helps reduce the risk of unauthorized access and credential leaks. Below are key actions and best practices to ensure secrets are handled securely.
1. Create secrets
Kubernetes secrets can be created using three main methods: YAML manifests, kubectl commands, and the Kubernetes API.
YAML manifests allow you to define secrets declaratively, while kubectl create secret generic provides a quick command-line approach. For advanced use cases, the Kubernetes API enables dynamic secret creation within applications.
2. List secrets
To track secret usage in a Kubernetes namespace using kubectl, you can list all secrets to monitor their presence and ensure proper management. This helps identify outdated or unnecessary secrets that should be rotated or removed. Regularly reviewing secrets also improves security by reducing the risk of exposure.
3. Inspect secrets
Retrieving metadata and key names for a secret helps verify its contents and track usage. Using kubectl describe secret <secret-name> displays details such as creation timestamp, labels, annotations, and the keys stored within the secret. This allows administrators to confirm the presence of expected data without exposing the actual secret values.
4. Decode secret values
Kubernetes secrets are stored in Base64-encoded format rather than plaintext, requiring decoding for human-readable access.
To retrieve and decode a secret’s value, you must first extract it using kubectl get secret <secret-name> -o yaml and then apply a Base64 decoding command. This ensures that secret values remain obscured by default but can be accessed by authorized users when necessary.
5. Update secrets
To modify an existing secret, you can use kubectl edit secret <secret-name> to make inline changes or kubectl replace -f <file>.yaml to update it with a new configuration.
Alternatively, you can delete the existing secret and recreate it to ensure a clean update. Since changes to secrets aren’t automatically reflected in running pods, restarting affected workloads may be necessary.
6. Rotate secrets
Regularly rotating secrets helps mitigate the risk of credential leaks and unauthorized access by ensuring that compromised or outdated secrets are no longer valid.
Automating secret rotation reduces human error and enforces security best practices, especially for highly sensitive data such as API keys and database credentials. Kubernetes does not automatically propagate secret updates to running pods, so workloads may need to be restarted to apply new values.
7. Mount secrets in pods
Kubernetes secrets can be made available to containers by mounting them as volumes or injecting them as environment variables.
Mounting secrets as volumes allows applications to read them as files at runtime, while using environment variables enables direct access within the container’s execution environment. Choosing the right method depends on the application’s security requirements and how it consumes sensitive data.
8. Restrict access to secrets
Kubernetes Role-Based Access Control (RBAC) policies restrict which users and workloads can view or modify secrets, ensuring that only authorized entities have access.
By defining roles and role bindings, administrators can configure least privilege access to secrets, preventing unauthorized users from listing or retrieving secrets. This privileged access to secrets reduces the risk of accidental exposure or malicious access to secret data.
9. Monitor secret usage
Monitoring which workloads reference a secret helps identify unused or orphaned secrets that should be rotated or deleted.
Regular audits prevent unnecessary secret retention, reducing the risk of outdated credentials being exploited. By tracking secret usage, security teams can ensure that secrets are only accessible by the applications that actually need them.
10. Audit secret access
Enabling Kubernetes audit logs helps detect unauthorized access to secrets by capturing API requests related to secret creation, modification, and retrieval.
These logs provide visibility into who accessed or attempted to access a secret, helping security teams identify potential threats. Regularly reviewing audit logs strengthens security by allowing organizations to respond to suspicious activity in real time.
11. Delete secrets
Removing unused secrets reduces the attack surface by eliminating credentials that are no longer needed but could be exploited if left in the system. Stale secrets increase security risks, as they may contain outdated but still valid credentials. Regularly auditing and deleting unnecessary secrets ensures a cleaner and more secure Kubernetes environment.
12. Back up and restore secrets
Keeping encrypted backups of secrets is crucial for disaster recovery and compliance, ensuring that sensitive data can be restored in case of accidental deletion or system failures.
Secure backups should be stored in trusted, access-controlled locations, such as cloud key management services or encrypted storage solutions. Proper backup and recovery strategies help maintain operational resilience while meeting regulatory requirements for data protection.
Are Kubernetes secrets safe?
It’s important to remember that the way Kubernetes secrets are stored in etcd is not very secure because they aren’t encrypted. Instead, they’re stored as Base64-encoded objects. This means that if anyone gets their hands on the data, they can quickly decode the Base64 string and use all the secrets—all they need is access to see the Kubernetes secrets objects. (You can get around using Base64 by leveraging the stringData field.)
Configuring Kubernetes secrets to make them more secure
Below are a few steps you can take to keep Kubernetes secrets secure:
Implement RBAC rules: Kubernetes has rich support for policy-based and role-based access control. You can very easily control who can access which components in Kubernetes, meaning you can restrict the usage of secrets APIs and remove access to secrets from all users. Making sure that no one can access secrets via the Kubectl command-line tool is the first step.
Allow only containers to access specific secrets: Just like controlling RBAC for users, you can restrict secrets access to a particular set of applications. This way, your secrets will be accessible only to applications that are authorized to use them.
Enable encryption at rest: Encryption at rest is a feature that can be enabled on the API server using the flag --encryption-provider-config. In this flag, you’ll refer to a file that specifies the providers for which the encryption at rest will be enabled. The content of the YAML file will be something like this
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- events
providers:
- identity: {} # do not encrypt Events even though *.* is specified below
- resources:
- '*.apps'
providers:
- aescbc:
keys:
- name: first_key
secret: c2VlkansaklnsxlanslxHsa1hUndklMgaXQ/Cg==
- resources:
- '*.*'
providers:
- aescbc:
keys:
- name: second_key
secret: c2VjcmV12ds2JJklY3vyZSwgSSB0aGluaw==
If you look at this file, you’ll notice an array of resources we’re applying conditions to. The events resource has no encryption at rest because the provider identity is an empty array. Next, we’ve specified that resources under the app's API will be encrypted at rest. The last array shows that everything in Kubernetes will be encrypted.
Tools for robust secrets management
By following the configuration tips above, you can make sure that no unauthorized users or entities can access your secrets. However, actually delivering secrets to Kubernetes also presents security risks, which require role-based access control and other checks to mitigate. These features aren’t native to Kubernetes, but luckily, there are many effective tools to choose from. Let’s look at the third-party solutions first.
Third-party solutions
Vault: Vault is an industry standard and is used widely. By using the sidecar container, it provides functionalities like RBAC, auditing, secrets rotation, and a dynamic secrets engine. You can use Vault and deliver secrets to your containers without worrying about security.
Secrets Manager from AWS: AWS Secrets Manager is a much more affordable solution, but it lacks many of Vault’s features, like dynamic secrets generation and an RBAC UI. That said, you can implement RBAC using AWS native IAM policies.
Key Vault in Azure: Key Vault is similar to AWS Secrets Manager and secures secrets, TLS certificates, SSH keys, and more. One big benefit? You can create vaults in Azure’s international data centers to keep your secrets safer and make them more efficient.
Open-source solutions
Helm secrets: Helm is widely used to manage deployments in Kubernetes, and Helm secrets is an easy solution to integrate. Though it’s not as secure as a Vault, with proper privileges, Helm is a worthy open-source solution.
Open-source Vault: Vault has an open-source distribution in addition to the paid version we’ve already discussed. You can deploy the open-source version of Vault in your Kubernetes clusters or on a native VM and utilize it to push secrets to your containers. This version of Vault provides almost all of the features of the upgraded version except for backup and restore.
Conclusion
Secure everything you build and run in the cloud
Kubernetes secrets have some security gaps, but these can be handled by following the principle of least privilege and implementing encryption at rest. Auditing is also a key means of limiting your attack surface, and all the tools mentioned above have one or more ways to produce audit logs.
On the other hand, it can be tricky to keep track of all of the essential data from these disparate logs. Enter Wiz. With our all-in-one platform, you get complete visibility across containers, Kubernetes, and cloud environments in minutes without agents, and you can leverage the power of the Wiz Security Graph to analyze and prioritize risk with complete context.
Ready to secure everything you build and run in the cloud? Schedule a demo today
Empower your developers to be more productive, from code to production
Learn why the fastest growing companies choose Wiz to secure containers, Kubernetes, and cloud environments from build-time to real-time.