← Back to Articles
Kubernetes DevOps Security Cloud Native Secrets Management

Kubernetes Secrets: Complete Guide to Secure Credential Management

Master Kubernetes Secrets with practical examples, security best practices, and advanced techniques for managing sensitive data in your clusters, honestly.

2026-09-07
12 min read
Written by Engineering Team

Introduction to Kubernetes Secrets

Kubernetes Secrets are objects designed to store sensitive information like passwords, OAuth tokens, SSH keys, and other confidential data, honestly. Unlike ConfigMaps, Secrets provide an additional layer of protection for your sensitive application data, basically.

Secrets are stored in etcd in base64-encoded format, which provides obfuscation but not encryption by default, you know? For production environments, you should definitely enable encryption at rest, trust me.

Understanding how to properly implement and manage Secrets is crucial for maintaining security in your Kubernetes clusters. This guide covers everything from basic usage to advanced security patterns, basically.

Types of Kubernetes Secrets

Kubernetes supports several built-in secret types, each designed for specific use cases, honestly.

  • ●

    Opaque: Generic secret type for arbitrary user-defined data

  • ●

    kubernetes.io/service-account-token: Service account tokens

  • ●

    kubernetes.io/dockerconfigjson: Docker registry credentials

  • ●

    kubernetes.io/basic-auth: Basic authentication credentials

  • ●

    kubernetes.io/ssh-auth: SSH authentication keys

  • ●

    kubernetes.io/tls: TLS certificates and keys, basically

opaque-secret.yaml
yaml
              apiVersion: v1
kind: Secret
metadata:
  name: app-secret
  namespace: production
type: Opaque
data:
  username: YWRtaW4=
  password: cGFzc3dvcmQxMjM=
stringData:
  config.json: |
    {
      "api_key": "secret-key-12345",
      "endpoint": "https://api.example.com"
    }

            

Creating Secrets: Best Practices

There are multiple ways to create Secrets in Kubernetes, honestly. Each method has its advantages depending on your workflow and security requirements, basically.

💡 Security First

Never commit plaintext secrets to version control, seriously. Use tools like Sealed Secrets, External Secrets Operator, or cloud-native secret managers for production workloads, you know?

create-secret-cli.sh
bash
              # Create secret from literal values
kubectl create secret generic db-credentials \
  --from-literal=username='admin' \
  --from-literal=password='S3cr3tP@ss!' \
  --namespace=production

# Create secret from files
kubectl create secret generic tls-secret \
  --from-file=tls.crt=./certs/tls.crt \
  --from-file=tls.key=./certs/tls.key \
  --namespace=production

# Create secret from env file
kubectl create secret generic app-config \
  --from-env-file=.env.production \
  --namespace=production

            

Using kubectl create is convenient for quick deployments, but for GitOps workflows, declarative YAML files are preferred, basically. Always ensure your secret files are excluded from version control using .gitignore, trust me.

Using Secrets in Pods

Secrets can be consumed in pods in three primary ways: as environment variables, as files in a volume, or through the kubelet for pulling images, you know?

pod-with-secrets.yaml
yaml
              apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  namespace: production
spec:
  containers:
    - name: myapp
      image: myapp:latest
      env:
        # Direct environment variable from secret
        - name: DATABASE_USERNAME
          valueFrom:
            secretKeyRef:
              name: db-credentials
              key: username
        # All keys from secret as env vars
        - nameFrom:
            secretRef:
              name: app-config
      volumeMounts:
        # Mount secret as files
        - name: secret-volume
          mountPath: /etc/secrets
          readOnly: true
  volumes:
    - name: secret-volume
      secret:
        secretName: db-credentials
        defaultMode: 0400  # Read-only for owner

            

When mounting secrets as volumes, Kubernetes automatically updates the files when the secret changes, honestly. However, the application must be configured to reload the configuration, basically.

Secret Security Best Practices

Securing secrets in Kubernetes requires a multi-layered approach, seriously. Here are critical security measures every team should implement, you know?

Practice Priority Implementation
Enable encryption at rest Critical Configure EncryptionConfiguration for etcd
Implement RBAC Critical Restrict secret access with role-based controls
Use external secret managers High Integrate with Vault, AWS Secrets Manager, or Azure Key Vault
Rotate secrets regularly High Automate secret rotation with operators
Audit secret access Medium Enable audit logging for secret operations
Use namespace isolation Medium Separate secrets by environment and team, basically
encryption-config.yaml
yaml
              apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: <base64-encoded-secret-key>
      - identity: {}

            

💡 RBAC Example

Create a Role that limits secret access to specific pods and namespaces, honestly. Never use cluster-admin for application workloads, basically.

External Secrets Management

For production environments, integrating with external secret management systems provides better security, audit trails, and secret rotation capabilities, you know?

The External Secrets Operator (ESO) is a Kubernetes operator that fetches secrets from external APIs like AWS Secrets Manager, Azure Key Vault, Google Cloud Secret Manager, and HashiCorp Vault, then creates Kubernetes secrets automatically, basically.

external-secret.yaml
yaml
              apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: database-credentials
  namespace: production
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secretsmanager
    kind: ClusterSecretStore
  target:
    name: db-credentials
    creationPolicy: Owner
  data:
    - secretKey: username
      remoteRef:
        key: production/database
        property: username
    - secretKey: password
      remoteRef:
        key: production/database
        property: password

            

Common Pitfalls and How to Avoid Them

  • ●

    Storing secrets in Git repositories (even encoded in base64), which is a huge no-no

  • ●

    Using the same secrets across multiple environments

  • ●

    Not rotating secrets regularly, honestly

  • ●

    Granting excessive RBAC permissions to service accounts

  • ●

    Forgetting to enable audit logging

  • ●

    Not monitoring secret access patterns, basically

"Security is not a feature, it's a requirement, honestly. Treat your secrets with the same importance as your production data, trust me."
— Kubernetes Security Best Practices

Monitoring and Auditing Secrets

Implementing proper monitoring and auditing is essential for detecting unauthorized access and maintaining compliance, basically.

audit-commands.sh
bash
              # List all secrets in namespace
kubectl get secrets -n production

# Describe specific secret (shows metadata only)
kubectl describe secret db-credentials -n production

# Decode secret value (requires access)
kubectl get secret db-credentials -n production -o jsonpath='{.data.username}' | base64 --decode

# Check who has access to secrets
kubectl auth can-i get secrets --as=system:serviceaccount:production:myapp

# View audit logs for secret access
kubectl logs -n kube-system kube-apiserver | grep secrets

            

Frequently Asked Questions

Are Kubernetes secrets encrypted by default?
No, honestly. Secrets are stored in base64-encoded format in etcd, which is not encryption. You must enable encryption at rest using EncryptionConfiguration to protect secrets at rest, basically.
How do I rotate secrets without downtime?
Create a new secret with updated credentials, update your deployment to use the new secret, verify the application works correctly, then delete the old secret, you know? For zero-downtime, use secret versioning and gradual rollouts, trust me.
Can I limit which pods can access a secret?
Yes, basically. Use RBAC (Role-Based Access Control) to restrict which service accounts can access specific secrets. Combine with namespace isolation for additional security, honestly.
What's the difference between ConfigMap and Secret?
ConfigMaps store non-confidential configuration data, while Secrets are designed for sensitive information, seriously. Secrets provide additional protections like restricted RBAC permissions and the ability to enable encryption at rest, basically.
Should I use Helm to manage secrets?
Helm can manage secrets, but avoid storing plaintext values in values.yaml, you know? Use Helm secrets plugin, external secret operators, or integrate with secret management tools like Vault, honestly.

Conclusion

Kubernetes Secrets are a fundamental component of secure application deployment, basically. While they provide basic obfuscation out of the box, production environments require additional layers of security including encryption at rest, RBAC, external secret managers, and comprehensive auditing, you know?

By following the best practices outlined in this guide, you can significantly improve your cluster's security posture and protect sensitive data from unauthorized access, honestly. Remember that security is an ongoing process—regularly review and update your secret management strategies as your infrastructure evolves, basically.

Ready to implement enterprise-grade secret management? Consider integrating External Secrets Operator with your cloud provider's secret manager for automated, secure, and auditable secret management, trust me.

We use cookies to improve your experience.