21 ‐ Kubernetes Secrets - CloudScope/DevOpsWithCloudScope GitHub Wiki

Kubernetes Secrets: Overview

In Kubernetes, Secrets are used to store and manage sensitive information, such as passwords, OAuth tokens, SSH keys, and API keys. Secrets are similar to ConfigMaps but with additional security features, such as the ability to encrypt data at rest. Unlike ConfigMaps, which are used for non-sensitive configuration, Secrets provide a more secure way to store and access sensitive data within Kubernetes clusters.


Key Features of Kubernetes Secrets

  1. Sensitive Data Storage:

    • Secrets allow you to store sensitive data like database credentials, application keys, private certificates, and other secrets that should not be exposed directly in code, configuration files, or container images.
  2. Base64 Encoding:

    • Kubernetes stores secret data in base64-encoded form. This encoding is not encryption, but simply an encoding format to make the data easier to store as text. The data is still considered sensitive, so Kubernetes provides features like encryption at rest to protect it.
  3. Encryption at Rest:

    • Kubernetes supports encryption at rest for secrets, which ensures that sensitive data is encrypted when stored in etcd, the key-value store used by Kubernetes. This encryption is enabled by configuring the EncryptionConfiguration on the Kubernetes API server.
  4. Access Control:

    • Kubernetes uses RBAC (Role-Based Access Control) to restrict who can access or modify Secrets. By applying appropriate permissions, you can ensure that only authorized users or Pods can access the secret data.
  5. Automatic Mounting:

    • Secrets can be mounted into Pods as environment variables or files, which allows the application running in the Pod to access them easily without storing them in the image or configuration files.

When to Use Kubernetes Secrets

  • Storing sensitive information: For credentials such as database passwords, API tokens, private keys, and certificates.
  • Environment-specific secrets: When managing different secrets for different environments (e.g., development, production).
  • Secure storage of sensitive configuration data: For example, SSH keys or cloud provider access keys.
  • Secure handling of application secrets: For services or applications that require a secure means of accessing credentials or tokens.

Creating a Secret

  1. Using kubectl (Literal Values): You can create a secret from literal key-value pairs directly using the kubectl command:

    kubectl create secret generic my-secret --from-literal=username=admin --from-literal=password=secretpassword
    
  2. Using a File: You can create a secret from a file, where the file's contents will be stored as the value of a key.

    kubectl create secret generic my-secret --from-file=ssh-privatekey=/path/to/ssh/key
    
  3. Using a Directory: You can create a secret from a directory where each file in the directory will be treated as a key, and its content will be the value.

    kubectl create secret generic my-secret --from-file=/path/to/config-dir/
    
  4. Using a YAML Definition: You can define a Secret in a YAML file, which is especially useful for more complex scenarios.

    Example:

    apiVersion: v1
    kind: Secret
    metadata:
      name: my-secret
    type: Opaque
    data:
      username: YWRtaW4=  # base64-encoded value of 'admin'
      password: c2VjcmV0cGFzc3dvcmQ=  # base64-encoded value of 'secretpassword'
    

    Apply the YAML to create the Secret:

    kubectl apply -f secret.yaml
    

    Note: In the YAML definition, sensitive data like username and password should be base64-encoded.


Consuming Secrets

You can consume Kubernetes Secrets in Pods in several ways:

  1. As Environment Variables: You can reference a Secret and expose its keys as environment variables inside your container.

    Example:

    apiVersion: v1
    kind: Pod
    metadata:
      name: example-pod
    spec:
      containers:
      - name: example-container
        image: myapp:latest
        envFrom:
        - secretRef:
            name: my-secret
    

    In this example, the keys in the my-secret Secret will be exposed as environment variables within the container.

  2. As Volume Mounts: You can mount a Secret as a volume, where each key in the Secret becomes a file and the file's content is the corresponding value.

    Example:

    apiVersion: v1
    kind: Pod
    metadata:
      name: example-pod
    spec:
      containers:
      - name: example-container
        image: myapp:latest
        volumeMounts:
        - name: secret-volume
          mountPath: /etc/secrets
      volumes:
      - name: secret-volume
        secret:
          secretName: my-secret
    

    In this example, the keys from my-secret will be mounted as files in the /etc/secrets directory inside the container. Each key will become a file, and the value will be the file's content.

  3. As Command-Line Arguments: Secrets can also be passed as command-line arguments to containers by referencing the Secret's data in the command line.

    Example:

    apiVersion: v1
    kind: Pod
    metadata:
      name: example-pod
    spec:
      containers:
      - name: example-container
        image: myapp:latest
        args:
        - "--username=$(USERNAME)"
        - "--password=$(PASSWORD)"
        env:
        - name: USERNAME
          valueFrom:
            secretKeyRef:
              name: my-secret
              key: username
        - name: PASSWORD
          valueFrom:
            secretKeyRef:
              name: my-secret
              key: password
    

Updating a Secret

Updating a Secret in Kubernetes is straightforward. You can edit the Secret by modifying its values, either using kubectl or by updating the YAML file.

  1. Using kubectl: You can update a Secret using the kubectl create secret command with the --dry-run and -o yaml flags to generate the updated Secret definition, and then apply it:

    kubectl create secret generic my-secret --from-literal=username=newuser --from-literal=password=newpassword --dry-run=client -o yaml | kubectl apply -f -
    
  2. Direct Editing: You can also directly edit a Secret using kubectl edit:

    kubectl edit secret my-secret
    

    This will open the Secret in your default text editor, where you can make changes and save.

Note: After updating a Secret, Pods that consume it will not automatically reload the updated values. You may need to restart the Pods to pick up the new Secret values.


image

Best Practices for Kubernetes Secrets

  1. Enable Encryption at Rest: Ensure that Secrets are encrypted at rest by configuring the EncryptionConfiguration on your Kubernetes API server. This ensures that even if someone gains access to etcd, they cannot easily view the secret data.

  2. Access Control: Use Role-Based Access Control (RBAC) to restrict access to Secrets. Only authorized users, service accounts, or Pods should have access to sensitive data.

  3. Avoid Exposing Secrets in Logs or UI: Be mindful of where you expose Secrets. Avoid printing them in logs, UI, or other locations where they might be accidentally leaked.

  4. Use Secrets for Sensitive Information Only: Use Secrets for truly sensitive information (e.g., passwords, tokens), and use ConfigMaps for non-sensitive data.

  5. Rotate Secrets Regularly: Regularly rotate Secrets to minimize the risk of them being compromised. Implement automation for rotating credentials and secrets.

  6. Limit the Size of Secrets: Kubernetes imposes limits on the size of objects stored in etcd. If you store large amounts of data in a Secret, it might impact Kubernetes performance or stability.