What are Kubernetes Secrets?
Kubernetes Secrets are API objects designed to store sensitive information separately from application code and container images. They are commonly used for passwords, API keys, OAuth tokens, SSH keys, TLS certificates, and Docker registry credentials. Applications can access Secrets either as environment variables or as files mounted into a Pod, allowing sensitive values to be injected at runtime instead of being hardcoded into images or configuration files.
Secrets are namespaced resources that can be managed with the Kubernetes API, kubectl, or declarative manifests. They integrate with Kubernetes features such as RBAC, ServiceAccounts, and volume mounts, making it easier to control which workloads can access specific credentials. Although Secrets provide a standardized way to manage confidential data, they are not a complete security solution. By default, Secret values are only Base64-encoded and stored unencrypted in etcd unless encryption at rest is enabled, so additional security controls are required for production environments.
Main takeaways from this article:
- Kubernetes Secrets provide a secure way to store and manage sensitive data such as passwords, SSH keys, and TLS certificates without embedding them directly into code or container images.
- There are multiple built-in types of Kubernetes Secrets, each tailored for specific use cases like authentication, Docker registry credentials, or cluster bootstrapping.
- While Kubernetes Secrets improve security and efficiency, they come with limitations by default, they are stored unencrypted in etcd, so enabling encryption, using RBAC, and following best practices are critical.
- For stronger security and flexibility, consider alternatives such as HashiCorp Vault, AWS Secrets Manager, or the Kubernetes Secrets Store CSI Driver.
Types of Kubernetes Secrets
Kubernetes provides several built-in types of Secrets to cater to common use cases. Each type has specific validations and constraints to ensure proper handling of the sensitive data.
1. Opaque Secrets
Opaque is the default Secret type if you don't specify a type. It is versatile and can store any kind of sensitive data. It is used to store arbitrary user-defined data.
apiVersion: v1
kind: Secret
metadata:
name: my-opaque-secret
type: Opaque
data:
username: YWRtaW4= # base64 encoded
password: MWYyZDFlMmU2N2Rm
Create using kubectl:
kubectl create secret generic my-opaque-secret \
--from-literal=username=admin \
--from-literal=password=1f2d1e2e67df
2. ServiceAccount Token Secrets
This type is used to provide long-lived ServiceAccount credentials to Pods. However, the recommended approach in Kubernetes v1.22 and later is to use the TokenRequest API for short-lived tokens. It is used to store a token credential that identifies a ServiceAccount.
apiVersion: v1
kind: Secret
metadata:
name: my-sa-token-secret
annotations:
kubernetes.io/service-account.name: "my-service-account"
type: kubernetes.io/service-account-token
data:
extra: YmFyCg== # base64 encoded
Auto-generated Legacy ServiceAccount Token Cleanup
Before v1.24, Kubernetes auto-generated Secret-based tokens for ServiceAccounts. These tokens were identified by a reference in the ServiceAccount's secrets field. From v1.29 onwards, unused auto-generated tokens are marked as invalid after one year and eventually purged.
apiVersion: v1
kind: Secret
metadata:
name: build-robot-token
namespace: default
labels:
kubernetes.io/legacy-token-last-used: 2024-09-13
kubernetes.io/legacy-token-invalid-since: 2025-09-14
annotations:
kubernetes.io/service-account.name: build-robot
type: kubernetes.io/service-account-token
Create using kubectl:
kubectl create secret generic my-sa-token-secret \
--type=kubernetes.io/service-account-token \
--from-literal=extra=bar
3. Docker Config Secrets
There are two types of Docker config Secrets:
- kubernetes.io/dockercfg: It stores a serialized `~/.dockercfg` file.
- kubernetes.io/dockerconfigjson: It stores a serialized `~/.docker/config.json` file.
It is used to store credentials for accessing a container image registry.
apiVersion: v1
kind: Secret
metadata:
name: my-docker-config-secret
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: eyJhdXRocyI6eyJodHRwczovL2V4YW1wbGUvdjEvIjp7ImF1dGgiOiJvcGVuc2VzYW1lIn19fQo= # base64 encoded JSON
Create using kubectl:
This is particularly useful when you don't have a pre-existing Docker configuration file.
kubectl create secret docker-registry my-docker-config-secret \
--docker-server=my-registry.example.com \
--docker-username=my-username \
--docker-password=my-password \
--docker-email=my-email@example.com
This command creates a Secret of type kubernetes.io/dockerconfigjson and stores the Docker registry credentials.
4. Basic Authentication Secrets
This type is specifically for storing a username and password for basic authentication. It is used to store credentials for basic authentication.
apiVersion: v1
kind: Secret
metadata:
name: my-basic-auth-secret
type: kubernetes.io/basic-auth
stringData:
username: admin
password: t0p-Secretstore
Create using kubectl:
kubectl create secret generic my-basic-auth-secret \
--type=kubernetes.io/basic-auth \
--from-literal=username=admin \
--from-literal=password=t0p-Secretstore
5. SSH Authentication Secrets
This type is used to store SSH private keys for authentication purposes.
apiVersion: v1
kind: Secret
metadata:
name: my-ssh-auth-secret
type: kubernetes.io/ssh-auth
data:
ssh-privatekey: UG91cmluZzYlRW1vdGljb24lU2N1YmE= # base64 encoded private key
Create using kubectl:
kubectl create secret generic my-ssh-auth-secret \
--type=kubernetes.io/ssh-auth \
--from-file=ssh-privatekey=path/to/private/key
6. TLS Secrets
This type is commonly used to configure encryption in transit for an Ingress. It is used to store a certificate and its associated key for TLS.
apiVersion: v1
kind: Secret
metadata:
name: tls-secret
type: kubernetes.io/tls
data:
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNVakNDQWJzQ0FnMytNQTBHQ1NxR1NJYjNEUUVCQlFVQU1JR2JNUXN3Q1FZRFZRUUdFd0pLVURFT01Bd0cKQTFVRUNCTUZWRzlyZVc4eEVEQU9CZ05WQkFjVEIwTm9kVzh0YTNVeEVUQVBCZ05WQkFvVENFWnlZVzVyTkVSRQpNUmd3RmdZRFZRUUxFdzlYWldKRFpYSjBJRk4xY0hCdmNuUXhHREFXQmdOVkJBTVREMFp5WVc1ck5FUkVJRmRsCllpQkRRVEVqTUNFR0NTcUdTSWIzRFFFSkFSWVVjM1Z3Y0c5eWRFQm1jbUZ1YXpSa1pDNWpiMjB3SGhjTk1UTXcKTVRFeE1EUTFNVE01V2hjTk1UZ3dNVEV3TURRMU1UTTVXakJMTVFzd0NRWURWUVFHREFKS1VERVB...
tls.key: RXhhbXBsZSBkYXRhIGZvciB0aGUgVExTIGNydCBmaWVsZA== # base64 encoded private key
Create using kubectl:
kubectl create secret tls tls-secret \
--cert=path/to/cert/file \
--key=path/to/key/file
7. Bootstrap Token Secrets
This type is used for tokens that sign well-known ConfigMaps during the bootstrap process. It is used to store tokens used during the node bootstrap process.
apiVersion: v1
kind: Secret
metadata:
name: bootstrap-token-6emitej
namespace: kube-system
type: bootstrap.kubernetes.io/token
data:
auth-extra-groups: c3lzdGVtOmJvb3RzdHJhcHBlcnM6a3ViZWFkbTpkZWZhdWx0LW5vZGUtdG9rZW4=
expiration: MjAyMC0wOS0xM1QwNDozOToxMFo=
token-id: NWVtaXRq
token-secret: a3E0Z2lodnN6emduMXAwcg==
usage-bootstrap-authentication: dHJ1ZQ==
usage-bootstrap-signing: dHJ1ZQ==
Create using kubectl:
kubectl create secret generic bootstrap-token-6emitej \
--type=bootstrap.kubernetes.io/token \
--from-literal=auth-extra-groups=system:bootstrappers:kubeadm:default-node-token \
--from-literal=expiration=2020-09-13T04:39:10Z \
--from-literal=token-id=5emitej \
--from-literal=token-secret=kq4gihvszzgn1p0r \
--from-literal=usage-bootstrap-authentication=true \
--from-literal=usage-bootstrap-signing=true
How Kubernetes Stores Secrets: Base64 and Encryption
A common misconception is that Kubernetes Secrets are encrypted because their values appear unreadable in YAML manifests. In reality, the data field stores values using Base64 encoding, which is an encoding format, not encryption. Anyone with permission to read the Secret can decode the values easily:
echo "YWRtaW4=" | base64 --decode
# Output:
# admin
Base64 exists so binary and text data can be represented safely in YAML and JSON. It does not provide confidentiality. If an attacker can retrieve a Secret object through the Kubernetes API or directly from etcd, the data can be decoded immediately.
By default, Kubernetes stores Secrets in etcd in plaintext unless encryption at rest is explicitly enabled. To protect Secrets, configure the API server with an EncryptionConfiguration that encrypts Secret resources before they are written to etcd. Kubernetes supports multiple providers, including aescbc, aesgcm, secretbox, and external KMS providers that integrate with cloud key management services.
Encryption at rest protects against unauthorized access to the etcd datastore, but it is only one layer of defense. Users or workloads with permission to read Secrets through the Kubernetes API still receive the decrypted values. For that reason, encryption should be combined with RBAC, least-privilege access, audit logging, and short-lived credentials to reduce the overall risk of secret exposure.
How to Create and Manage Secrets in Kubernetes
As we've already shown, one can use kubectl to create various types of Secrets. While this method is convenient for development and testing, it is not recommended for production environments due to security concerns. Instead, consider using manifest files, kustomize tool that provides better security and version control.
1. Using Secrets in Pods
Kubernetes Secrets can be used in Pods either as environment variables or as volume mounts.

2. As Environment Variables: To use a Secret in an environment variable, add an environment variable for each Secret key in the env[].valueFrom.secretKeyRef field.
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mycontainer
image: myimage
env:
- name: USERNAME
valueFrom:
secretKeyRef:
name: my-secret
key: username
- name: PASSWORD
valueFrom:
secretKeyRef:
name: my-secret
key: password
3. As Volume Mounts: K8s Secrets can be mounted as data volumes in a Pod. Kubernetes ensures that the specified object reference points to an object of type Secret.
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mycontainer
image: myimage
volumeMounts:
- name: secret-volume
mountPath: "/etc/secret-volume"
readOnly: true
volumes:
- name: secret-volume
secret:
secretName: my-secret
There are other ways to use K8s secrets in a Pod. These are:
4. Optional Secrets: You can mark a Secret as optional. If an optional Secret doesn't exist, Kubernetes ignores it.
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mycontainer
image: nginx
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
secret:
secretName: mysecret
optional: true
5. Container Image Pull Secrets: To fetch container images from a private repository, you can configure image pull Secrets.
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mycontainer
image: myprivateimage
imagePullSecrets:
- name: my-docker-config-secret
6. Immutable Secrets: Kubernetes allows you to mark Secrets as immutable, preventing any changes to the data. This improves cluster performance and protects against accidental updates.
apiVersion: v1
kind: Secret
metadata:
name: my-secret
data:
username: YWRtaW4=
password: cGFzc3dvcmQ=
immutable: true

Using Kubernetes Secrets in Pods (with examples)
Use Case 1: Pod with SSH Keys
To securely manage SSH keys within a Kubernetes cluster, you can create a Secret that contains your SSH private and public keys. This is useful for applications that require SSH access to other systems.
kubectl create secret generic ssh-key-secret --from-file=ssh-privatekey=/path/to/.ssh/id_rsa --from-file=ssh-publickey=/path/to/.ssh/id_rsa.pub
You can reference the SSH key Secret in a Pod and consume it as a volume:
apiVersion: v1
kind: Pod
metadata:
name: secret-test-pod
labels:
name: secret-test
spec:
volumes:
- name: secret-volume
secret:
secretName: ssh-key-secret
containers:
- name: ssh-test-container
image: mySshImage
volumeMounts:
- name: secret-volume
readOnly: true
mountPath: "/etc/secret-volume"
When the container runs, the SSH keys will be available at: /etc/secret-volume/ssh-publickey, /etc/secret-volume/ssh-privatekey The container can then use these keys to establish SSH connections securely.
Use Case 2: Pods with Production and Test Credentials
In environments where different credentials are required for production and test environments, you can create separate K8s Secrets for each:
kubectl create secret generic prod-db-mysecret --from-literal=username=produser --from-literal=password=Y4nys7f11
kubectl create secret generic test-db-mysecret --from-literal=username=testuser --from-literal=password=iluvtests
You can create Pods that consume these K8s Secrets, ensuring that each environment has the appropriate credentials:
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: Pod
metadata:
name: prod-db-client-pod
labels:
name: prod-db-client
spec:
volumes:
- name: secret-volume
secret:
secretName: prod-db-mysecret
containers:
- name: db-client-container
image: myClientImage
volumeMounts:
- name: secret-volume
readOnly: true
mountPath: "/etc/secret-volume"
- apiVersion: v1
kind: Pod
metadata:
name: test-db-client-pod
labels:
name: test-db-client
spec:
volumes:
- name: secret-volume
secret:
secretName: test-db-mysecret
containers:
- name: db-client-container
image: myClientImage
volumeMounts:
- name: secret-volume
readOnly: true
mountPath: "/etc/secret-volume"
Both containers will have the following files present on their filesystems: /etc/secret-volume/username/, etc/secret-volume/password. This approach allows you to maintain a common Pod configuration template, differing only in the Secret used.
Use Case 3: Dotfiles in Secret Volume
To make a piece of data "hidden" (i.e., in a file whose name begins with a dot character), you can define a key that begins with a dot:
apiVersion: v1
kind: Secret
metadata:
name: dotfile-mysecret
data:
.secret-file: dmFsdWUtMg0KDQo=
Mount the Secret into a volume in a Pod:
apiVersion: v1
kind: Pod
metadata:
name: secret-dotfiles-pod
spec:
volumes:
- name: secret-volume
secret:
secretName: dotfile-mysecret
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"
The secret-volume will contain a single file called .secret-file, and the container will have this file present at /etc/secret-volume/.secret-file.
Note: Files beginning with dot characters are hidden from the output of ls -l; use ls -la to see them when listing directory contents.
Kubernetes Secrets Best Practices
Configure Encryption at Rest
Enable encryption at rest so Secret data is encrypted before it is written to etcd. Kubernetes supports local encryption providers such as aescbc, aesgcm, and secretbox, as well as KMS providers that delegate encryption operations to an external key management service. A KMS-based setup is often preferred in production because it separates encryption keys from the cluster and supports centralized key rotation.
After enabling encryption, rewrite existing Secrets so they are stored using the new configuration. Otherwise, only newly created or updated Secrets will use the new encryption provider. Protect encryption keys, restrict access to the API server configuration, rotate keys regularly, and verify that old keys remain available until all existing data has been re-encrypted.
Implement Least-Privilege Access
Use Kubernetes RBAC to limit which users, service accounts, and workloads can read, create, update, or delete Secrets. Avoid broad permissions such as access to all Secrets in a namespace unless the workload truly requires it. Permissions to list or watch Secrets should be treated carefully because they can expose multiple credentials at once.
Grant access only to the specific Secret resources required by each application, and separate workloads across namespaces when appropriate. Review roles and role bindings regularly to remove unused permissions. Also avoid granting workloads permission to create Pods if they should not indirectly gain access to Secrets mounted by other service accounts.
Use Short-Lived Secrets
Prefer credentials that expire automatically instead of static passwords, API keys, or tokens. Short-lived Secrets reduce the time an exposed credential remains useful and make credential rotation easier to enforce. They are especially useful for ServiceAccount tokens, cloud credentials, database access, and internal service authentication.
Use the TokenRequest API for ServiceAccount tokens and configure external systems to issue temporary credentials with limited lifetimes. Automate renewal so applications can receive updated credentials before the old ones expire. Applications should also handle credential refresh without requiring a restart or manual deployment.
Implement Audit Rules
Enable Kubernetes audit logging to record access to Secret resources. Audit events can show which identity requested a Secret, when the request occurred, which namespace was involved, and whether the request succeeded. This information is useful for detecting misuse, investigating incidents, and proving that access controls are working as intended.
Create audit rules that capture Secret reads, updates, and deletions without recording sensitive values in log data. Send audit logs to a protected central system where they cannot be modified by cluster users. Monitor for unusual patterns, such as repeated failed requests, large numbers of Secret reads, or access from unexpected service accounts.
Improve etcd Management Policies
Protect etcd because it stores the cluster state, including Secret objects, RBAC policies, and workload configuration. Restrict network access so only trusted control plane components can connect to it. Require TLS for both client and peer communication, and limit direct administrative access to a small number of authorized operators.
Encrypt etcd backups and store them in a secure location with strict access controls. Backups should be protected as carefully as the live datastore because they may contain historical Secret values. Test restoration procedures regularly, keep etcd patched, rotate certificates before they expire, and monitor the datastore for unauthorized access attempts.
Configure Access to External Secrets
Use an external secrets manager when you need centralized storage, automatic rotation, dynamic credentials, detailed auditing, or stronger separation between applications and secret data. Common options include HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, and Google Secret Manager. These systems can reduce the need to store long-lived credentials directly in Kubernetes.
Integrate external stores through tools such as the Secrets Store CSI Driver or External Secrets Operator. Authenticate workloads with workload identities, managed identities, or short-lived tokens instead of static access keys. Limit each workload to the exact secret paths it requires, and decide whether secrets should be mounted directly into Pods or synchronized into Kubernetes Secret objects.
Shortcomings and Alternatives to Kubernetes Secrets
While Kubernetes Secrets are a common way to handle confidential data, they come with certain limitations. For example, Kubernetes Secrets are mounted to Pods unencrypted and are stored unencrypted in etcd, which can pose security risks. To overcome these limitations, several alternative methods can provide enhanced security and flexibility. Let's explore:
ServiceAccounts and Tokens
When your cloud-native component needs to authenticate to another application within the same Kubernetes cluster, using a ServiceAccount and its associated tokens can be an effective approach. ServiceAccounts are Kubernetes objects that provide an identity for processes running in a Pod. By assigning a ServiceAccount to a Pod, you can use Kubernetes' built-in authentication mechanisms to securely identify and authorize your client.
Third-Party Tools for Managing Sensitive Data
There are several third-party tools designed to manage sensitive data securely. These tools can run either within or outside your Kubernetes cluster and provide a secure way to handle secrets. For example, you can use a service that Pods access over HTTPS, which reveals a secret only if the client correctly authenticates using a ServiceAccount token.
Popular tools include:
HashiCorp Vault: A tool for securely accessing secrets. It provides a unified interface to any secret while providing tight access control and recording a detailed audit log.
AWS Secrets Manager: A service to manage secrets used by your applications, services, and IT resources.
Custom Signers for X.509 Certificates
For authentication purposes, you can implement a custom signer for X.509 certificates. By using CertificateSigningRequests (CSRs), you can have your custom signer issue certificates to Pods that need them. This method uses the robust security properties of X.509 certificates and can be useful for mutual TLS (mTLS) authentication between services.
Device Plugins for Node-Local Encryption Hardware
In scenarios where you need to leverage hardware-based security features, you can use device plugins to expose node-local encryption hardware to specific Pods. For example, you can schedule trusted Pods onto nodes equipped with a Trusted Platform Module (TPM), which is configured out-of-band.
Combining Multiple Methods
In many cases, the best approach is to combine multiple methods to achieve a layered security model. For example, you can deploy an operator that fetches short-lived session tokens from an external service and then creates Kubernetes Secrets based on those tokens. The operator ensures that the tokens are valid and refreshed as needed, while the Pods use the K8s Secrets without needing to know the underlying mechanisms.
Always remember that security is a continuous process. Regularly review and update your security practices to adapt to new threats and vulnerabilities. By doing so, you can ensure that your Kubernetes cluster remains secure and resilient against potential attacks.
Kubernetes secrets aren't the most secure but they are most efficient performance-wise. And if your cluster performance is important - try PerfectScale by DoiT to monitor and optimize Kubernetes performance, cost and reliability.
Get optimized your cluster today. Book a demo now with PerfectScale by DoiT.
Kubernetes Secrets FAQs
What are Kubernetes Secrets?
Kubernetes Secrets are objects used to store and manage sensitive information—like credentials, tokens, or keys—securely in a Kubernetes cluster, keeping them separate from application code and images.
Are Kubernetes Secrets encrypted?
By default, Kubernetes Secrets are stored unencrypted in etcd, which can be a security risk. To protect them, you should enable encryption at rest in Kubernetes and use TLS for communication with etcd.
How do I create a Kubernetes Secret?
You can create a Secret using kubectl or YAML manifests. For example:
kubectl create secret generic my-secret \
--from-literal=username=admin \
--from-literal=password=pass123
What are the alternatives to Kubernetes Secrets?
Alternatives include third-party secret management tools like HashiCorp Vault, AWS Secrets Manager, or the Kubernetes Secrets Store CSI Driver, which provide stronger security, better rotation policies, and centralized management outside the cluster.




.png)



