Skip to content

Akeyless unveiled the world’s first Unified Secrets and Machine Identity Platform to address the #1 cause of breaches. Discover Why & How.

Secure Kubernetes Secrets with Akeyless

Kubernetes Secrets

Managing secrets in Kubernetes can be a bit of a headache, but it’s super important for keeping your applications secure. In this post, we’re going to break down what Kubernetes Secrets are, why they’re crucial, and how you can secure them using Akeyless. There’s a common misconception about Kubernetes Secrets that we’ll address, so stay tuned for some surprising insights. By the end, you’ll know exactly how to manage your Kubernetes secrets safely, and I’ll even throw in a hands-on demo with Akeyless. Let’s dive in!

A Demo Video

What are Kubernetes Secrets?

Kubernetes Secrets are objects that hold sensitive data such as passwords, certificates, and SSH keys. Unlike ConfigMaps, which are meant to store nonsensitive data, Secrets provide a way to protect sensitive information within your Kubernetes cluster. A Kubernetes Secret is also known as a secret object that can be created, accessed, edited, and constrained in many ways.

Kubernetes Secrets can store and manage:

  • API keys
  • Database credentials
  • TLS certificates
  • Docker registry credentials

Why are Kubernetes Secrets Important?

Secrets are key to your application security and integrity. By using Secrets you avoid hardcoding sensitive information into your application code which can be exposed in version control systems or logs. Kubernetes Secrets allow you to:

  • Decouple sensitive data from your application code
  • Control access to sensitive data with Kubernetes RBAC
  • Enable secure communication between different parts of your application

Kubernetes Secret Types

There are a few types of Kubernetes secrets that we’ll discuss below. You can also reference the official Kubernetes documentation here.

Opaque

Opaque secrets in Kubernetes are a standard Secret type, storing arbitrary user-defined data as key-value pairs.

apiVersion: v1
kind: Secret
metadata:
  name: opaque-secret
type: Opaque
data:
  username: YWRtaW4=  # base64 encoded value of 'admin'
  password: czNjcjN0  # base64 encoded value of 's3cr3t'

Basic Authentication Secret

The kubernetes.io/basic-auth type is designed for storing credentials required for basic authentication. When using this Secret type, the data field of the Secret must contain the following keys:

  • username: The username for authentication.
  • password: The password or token for authentication.

Both values for these keys are base64 encoded strings. Alternatively, you can provide the plain text content using the stringData field in the Secret manifest.

Here’s an example manifest for a basic authentication Secret:

apiVersion: v1
kind: Secret
metadata:
  name: secret-basic-auth
type: kubernetes.io/basic-auth
stringData:
  username: admin # required field for kubernetes.io/basic-auth
  password: t0p-Secret # required field for kubernetes.io/basic-auth

Note: The basic authentication Secret type is provided for convenience. You can also use the Opaque type mentioned above for credentials used for basic authentication as it can store arbitrary data. However, using the defined and well-known Secret type (kubernetes.io/basic-auth) helps others understand the purpose of your Secret and sets a convention for expected key names. The Kubernetes API verifies that the required keys are set for a Secret of this type.

Bootstrap Token Secrets

A bootstrap token secret, is used for cluster bootstrapping and allows new nodes to join the cluster securely.

apiVersion: v1
kind: Secret
metadata:
  name: bootstrap-token
type: [bootstrap.kubernetes.io/token](http://bootstrap.kubernetes.io/token)
data:
  token-id: dGVzdC10b2tlbg== # base64 encoded value of ‘test-token’
  token-secret: c2VjcmV0 # base64 encoded value of ‘secret’

TLS

TLS Secrets store a certificate and its associated key, used for HTTPS communication.

apiVersion: v1
kind: Secret
metadata:
  name: tls-secret
type: kubernetes.io/tls
data:
  tls.crt: LS0tLS1...LS0tLS0K  # base64 encoded certificate
  tls.key: LS0tLS1...LS0tLS0K  # base64 encoded key

SSH Authentication

SSH Authentication Secrets store SSH keys for authentication.

apiVersion: v1
kind: Secret
metadata:
  name: ssh-auth-secret
type: kubernetes.io/ssh-auth
data:
  ssh-privatekey: LS0tLS1...LS0tLS0K  # base64 encoded SSH private key

ImagePullSecrets

ImagePullSecrets, also known as Docker config secrets, store Docker registry credentials to pull images from private registries.

apiVersion: v1
kind: Secret
metadata:
  name: image-pull-secret
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: ewogICJhdXRocyI6IHJ...  # base64 encoded Docker config JSON

ServiceAccount Token Secrets

A Secret of type kubernetes.io/service-account-token in Kubernetes contains a token that identifies a ServiceAccount, previously used to provide Pods with long-lasting ServiceAccount credentials.

But now, in Kubernetes v1.22 and later, it’s better to use short-lived, automatically rotating tokens. You can get these short-lived tokens in a couple of ways:

  1. Using the TokenRequest API:
    • You can call the TokenRequest API or use a tool like kubectl to get a token. For example, use the command kubectl create token.
  2. Requesting a Token in a Projected Volume:
    • You can set up your Pod so that Kubernetes creates the token and mounts it in the Pod. The token will automatically expire when the Pod is deleted.

Note: Only create a ServiceAccount token Secret if you can’t use the TokenRequest API and are okay with the security risks of having a long-lasting token.

Here’s an example of a ServiceAccount token Secret:

apiVersion: v1
kind: Secret
metadata:
  name: secret-sa-sample
  annotations:
    kubernetes.io/service-account.name: "sa-name"
type: kubernetes.io/service-account-token
data:
  extra: YmFyCg==

Creating and Managing Kubernetes Secrets

Let’s now see how to practically create Kubernetes secrets.

Creating Secrets with kubectl

To create and access secrets with kubectl you can use the following command:

kubectl create secret generic my-secret --from-literal=username=admin --from-literal=password='s3cr3t'

You can verify the Secret was created with:

kubectl get secret my-secret

Using a manifest file and generators like Kustomize

You can also create Secrets with a YAML file:

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

Apply the Secret with kubectl:

kubectl apply -f my-secret.yaml

With Kustomize you can generate Secrets dynamically with a kustomization.yaml file:

secretGenerator:
- name: my-secret
  literals:
  - username=admin
  - password=s3cr3t

Apply the Kustomize configuration with:

kubectl apply -k .

Kubernetes Secrets in Action

Pull Docker images from private Docker registries

To pull images from a private Docker registry, create a Docker registry Secret:

kubectl create secret docker-registry my-registry-secret \
  --docker-server=myregistrydomain.com \
  --docker-username=myusername \
  --docker-password=mypassword \
  [email protected]

Reference the ImagePullSecret in your Pod spec:

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mycontainer
    image: myregistrydomain.com/myimage
  imagePullSecrets:
  - name: my-registry-secret

Using Secret data as container environment variables and in volume mounted files

Example of using Secrets as environment variables in a Pod:

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

Example of using Secrets as volume-mounted files:

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mycontainer
    image: myimage
    volumeMounts:
    - name: secret-volume
      mountPath: "/etc/secret-volume"
  volumes:
  - name: secret-volume
    secret:
      secretName: my-secret

Kubernetes Secrets limitations

The Misconception of “Secrets”: Base64 Encoding Explained

Kubernetes secrets are encoded with Base64, which is often misunderstood as encryption. But it’s just a reversible encoding, leaving your secrets vulnerable. Anyone with access to the encoded data can decode it. For example:

echo 'YWRtaW4=' | base64 --decode # Outputs 'admin'

Risks of using Kubernetes Native Secrets

Kubernetes Secrets are stored in plaintext in etcd, so if etcd is not properly secured, it’s a major security risk. Without proper encryption and access control, sensitive data can be exposed to unauthorized users. In the demo, I show you how easy it is to get the secret from the database directly. In my case, I’m not using etcd, I’m using SQLite with a k3s distribution, but the same applies.

Akeyless for Kubernetes Secrets

How Akeyless works with Kubernetes

Akeyless is a centralized secret management solution that integrates with Kubernetes. It provides secure encryption, fine-grained access control, and audit logging to protect your secrets.

Benefits of using Akeyless for secrets management

  • Centralized management: Manage all your secrets from one place.
  • Enhanced security: Encrypt secrets with strong algorithms and manage access with RBAC. This addresses a major drawback of using Kubernetes Secret, which are not encrypted at rest by default
  • Audit logging: Track all access and usage of secrets for compliance and security auditing.
  • Seamless integration: Integrate with Kubernetes and other cloud-native tools without changing your application code.

Akeyless with Kubernetes environments

1. Akeyless Secrets Injector

The Akeyless Secrets Injector injects secrets into your applications at runtime. No more storing secrets in your application code or config files. You can learn more from the Akeyless documentation here.

Below is a helpful diagram showing how it works.

Akeyless Secrets Injector Diagram
Step-by-Step Explanation:
  1. Deploy Akeyless K8s Plugin Secret Injector:
    • The first step is to deploy the Akeyless Plugin Secret Injector within the Kubernetes cluster. This injector is responsible for managing the injection of secrets into the pods.
  2. My App Deployment with Annotations:
    • When deploying your application (My App), you add specific annotations to the Pod specification. These annotations signal the need to inject secrets. The deployment also includes an init container, which is an auxiliary container that runs before the main application container starts. You could optionally also have a side-car container that will continue to run alongside the application.
  3. JWT Token and Annotations Sent to Gateway:
    • The annotations and a JWT token are sent to the Akeyless Gateway. This gateway authenticates the request and retrieves the required secret values from the Akeyless SaaS platform.
  4. Akeyless SaaS Authenticates and Sends Secret Value:
    • The Akeyless SaaS platform verifies the authentication and sends the secret value back to the Akeyless Gateway. The Gateway then passes this information back to the Kubernetes cluster.
  5. Init Container Injects Secret and Terminates:
    • The init container in the Pod uses the retrieved secret value and places it inside the specified location. After completing this task, the init container terminates, ensuring the secret is in place before the main application container starts running. Optionally, you could use a side-car container that will continue to run and fetch secrets on behalf of the application.

I will show you how to configure this in the demo section below.

2. External Secrets Operator

The External Secrets Operator (ESO) allows you to sync secrets from Akeyless to Kubernetes Secrets. You can find more information in the Akeyless documentation or watch a tutorial here. You will need to deploy the ESO in your cluster and create an ExternalSecret resource. Check this useful diagram below from Akeyless’ docs.

External Secrets Operator with Akeyless
Step-by-Step Explanation:
  1. Install External Secrets Operator on Cluster:
    • The first step is to deploy the ESO in your Kubernetes cluster. This operator will synchronize secrets from external secret management services like Akeyless into Kubernetes.
  2. Create a Secret Store on Cluster and K8s Secret to Authenticate:
    • After installing the ESO, create a Secret Store in the Kubernetes cluster. This store holds the configuration needed to connect and authenticate with Akeyless. Additionally, create a Kubernetes Secret that contains the authentication credentials required to access Akeyless.
  3. ESO Authenticates and Requests Secrets from Akeyless:
    • The ESO authenticates with Akeyless using the credentials provided. It then requests the necessary secrets from Akeyless. These secrets are stored in Kubernetes’ etcd and kept in sync, ensuring the most current secrets are available to your applications.

Here is an example of an ExternalSecret

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: akeyless-external-secret-example
spec:
  refreshInterval: 1h

  secretStoreRef:
    kind: SecretStore
    name: akeyless-secret-store # Must match SecretStore on the cluster

  target:
    name: akeyless-secret-to-create # Name for the secret to be created on the cluster
    creationPolicy: Owner

  data:
    - secretKey: secretKey # Key given to the secret to be created on the cluster
      remoteRef:
        key: /path/to/your/secret # Full path of the secret on Akeyless
Breakdown
  • spec: Defines the desired state and behavior of the ExternalSecret.
    • refreshInterval: Specifies how often to refresh the secret from Akeyless (every hour in this case).
    • secretStoreRef: References the SecretStore that contains the configuration for accessing Akeyless.
      • kind: The type of SecretStore (SecretStore).
      • name: The name of the SecretStore on the cluster (akeyless-secret-store).
    • target: Specifies the details of the secret to be created on the Kubernetes cluster.
      • name: The name of the Kubernetes secret to be created (akeyless-secret-to-create).
      • creationPolicy: Defines the ownership policy for the secret (Owner).
    • data: Maps the keys from Akeyless to the keys in the Kubernetes secret.
      • secretKey: The key for the secret to be created on the cluster (secretKey).
      • remoteRef:
        • key: The full path of the secret on Akeyless (/path/to/your/secret). This specifies where to find the secret in Akeyless.

3. K8s Secrets Store CSI Driver

The K8s Secrets Store CSI Driver allows you to mount Akeyless secret objects directly into your pods as files. You can find more details in the docs. Install the CSI driver in your cluster and create a SecretProviderClass resource.

This YAML configuration defines a SecretProviderClass resource that configures how secrets from Akeyless are provided to Kubernetes pods using the Secrets Store CSI driver.

apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: akeyless-test
spec:
  provider: akeyless
  parameters:
    akeylessGatewayURL: "https://<Your GW URL>:8081"
    akeylessAccessID: "Access Id"
    akeylessAccessType: "k8s"
    akeylessK8sAuthConfigName: "k8s-conf"
    objects:  |
      - secretPath: "/path/to/secret/foo"
        fileName: "foo"
      - secretPath: "/path/to/secret/bar"
        fileName: "bar"

Breakdown

  • spec: Defines the desired state and behavior of the SecretProviderClass.
    • provider: Specifies the external secrets provider to use (akeyless).
    • parameters: Contains the configuration parameters for the Akeyless provider.
      • akeylessGatewayURL: The URL of the Akeyless gateway (https://<Your GW URL>:8081).
      • akeylessAccessID: The access ID used to authenticate with Akeyless (Access Id).
      • akeylessAccessType: The type of access method used (k8s for Kubernetes authentication).
      • akeylessK8sAuthConfigName: The name of the Kubernetes authentication configuration (k8s-conf).
      • objects: Lists the secrets to be fetched from Akeyless and the corresponding filenames to be created in the pod.
        • secretPath: The path to the secret in Akeyless (/path/to/secret/foo).
        • fileName: The name of the file where the secret will be mounted (foo).
        • secretPath: Another path to a different secret in Akeyless (/path/to/secret/bar).
        • fileName: The name of the file for this secret (bar).

Then, reference this SecretProviderClass in your Pod specification:

apiVersion: v1
kind: Pod
metadata:
  name: test-csi
spec:
  containers:
  - image: alpine
    name: alpine
    command:
      - "sh"
      - "-c"
      - "echo going to sleep... && sleep 10000"
    volumeMounts:
    - name: secrets-store-inline
      mountPath: "/akeyless-secrets"
      readOnly: true
  volumes:
    - name: secrets-store-inline
      csi:
        driver: secrets-store.csi.k8s.io
        readOnly: true
        volumeAttributes:
          secretProviderClass: "akeyless-test"

Breakdown

  • spec: Defines the desired state and behavior of the Pod.
    • containers: Specifies the containers that will run in the Pod.
      • image: The container image to use (alpine).
      • name: The name of the container (alpine).
      • command: The command to run in the container.
      • volumeMounts: Specifies the volumes to mount in the container.
        • name: The name of the volume (secrets-store-inline).
        • mountPath: The path in the container where the volume will be mounted (/akeyless-secrets).
        • readOnly: Indicates the volume is read-only (true).
    • volumes: Defines the volumes available to be mounted in the Pod.
      • name: The name of the volume (secrets-store-inline).
      • csi: Specifies the CSI driver to use for the volume.
        • driver: The CSI driver to use (secrets-store.csi.k8s.io).
        • readOnly: Indicates the volume is read-only (true).
        • volumeAttributes: Attributes for the CSI driver.
          • secretProviderClass: The name of the SecretProviderClass to use (akeyless-test).

Demo: Akeyless with Kubernetes Secrets

In this demo, we will integrate Akeyless with Kubernetes to securely manage secrets using the Akeyless agent injector, the most commonly used method. As mentioned above, you could also use the K8s Secrets Store CSI Driver. I’m not a big fan of the External Secrets Operator because you store your Akeyless secret as a Kubernetes secret, which is just a base64 encoded key-value pair. However, sometimes, you’re forced to use it depending on the use case.

Prerequisites

Step 1: Install Akeyless Secrets Injector

First, install the Akeyless Secrets Injector in your Kubernetes cluster. The injector will automatically inject secrets into your Kubernetes pods at runtime.

helm repo add akeyless https://akeylesslabs.github.io/helm-charts
helm repo update
helm upgrade --install aks akeyless/akeyless-secrets-injection --namespace akeyless -f values.yaml

Notice the values.yaml file contains the following environment variables:

env:
  AKEYLESS_URL: "https://vault.akeyless.io"
  AKEYLESS_ACCESS_ID: "p-ukwx42wczc5skm" 
  AKEYLESS_ACCESS_TYPE: "k8s"
  AKEYLESS_API_GW_URL: "https://b46b-24-150-170-114.ngrok-free.app"
  AKEYLESS_K8S_AUTH_CONF_NAME: "my-k8s-auth-method"
  • AKEYLESS_ACCESS_ID is the Access ID of the Auth Method with access to the secret.
  • AKEYLESS_ACCESS_TYPE is k8s since we’re using the Kubernetes authentication method.
  • AKEYLESS_K8S_AUTH_CONF_NAME is set to our Gateway Kubernetes Auth name. Relevant only for Access type of k8s.
  • AKEYLESS_API_GW_URL is set with the URL of my Akeyless Gateway on port 8080. Since my gateway is running on my local machine, I’m using ngrok with ngrok http 8080 to forward an external url of https://b46b-24-150-170-114.ngrok-free.app to http://localhost:8080. This allows communication between my apps running in K8s and the gateway.

Modes of Retrieval of Secrets in Akeyless

There are two modes to retrieve secrets with Akeyless in K8s. Environment variables and file injection. The drawback with environment variables mode is requiring a pod restart if the secret changes. The secret is written to a file in the pod with file injection. You can use a sidecar to continuously retrieve updates to secrets in Akeyless. This is helpful for rotated and dynamic secrets.

Step 2: Retrieve Secrets into Environment Variables

Let’s now retrieve a secret from Akeyless into an environment variable. Run the following command:

kubectl apply -f app_env.yaml

Notice the content of this file:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-environment-variable
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello-secrets
  template:
    metadata:
      labels:
        app: hello-secrets
      annotations:
        akeyless/enabled: "true"
    spec:
      containers:
      - name: alpine
        image: alpine
        command:
          - "sh"
          - "-c"
          - "echo $MY_SECRET && echo ...going to sleep... && sleep 10000"
        env:
        - name: MY_SECRET
          value: akeyless:/K8s/my_k8s_secret

Notice the following annotation:

  • akeyless/enabled: “true”: An annotation that enables the K8s Injector plugin.

Now check the logs of the pod:

Output:

Defaulted container "alpine" out of: alpine, akeyless-init (init)
myPassword
...going to sleep...

It successfully retrieved the password in Akeyless: myPassword

Step 3: Retrieve Secrets into a File

Let’s now retrieve a secret from Akeyless into a file. Run the following command:

kubectl apply -f app_file.yaml

Here are the contents of the app_file.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-file
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello-secrets-2
  template:
    metadata:
      labels:
        app: hello-secrets-2
      annotations:
        akeyless/enabled: "true"
        akeyless/inject_file: "/K8s/my_k8s_secret"
    spec:
      containers:
      - name: alpine
        image: alpine
        command:
          - "sh"
          - "-c"
          - "cat /akeyless/secrets/K8s/my_k8s_secret && echo ...going to sleep... && sleep 2000"

Notice the following annotations:

  • akeyless/enabled: “true” -> An annotation that enables the K8s Injector plugin
  • akeyless/inject_file: “/K8s/my_k8s_secret” -> An annotation specifying the path to get the secret from in Akeyless. The default location of the Akeyless secrets folder inside your pod file system is /akeyless/secrets/. To explicitly set a different location you can override this by adding |location=<path> after your secret name within the annotation as we will see in the next example.

Check the logs of this pod:

Output:

Defaulted container "alpine" out of: alpine, akeyless-init (init)
myPassword

We got the same output as before. However, let’s exec into the container and look at the file where the secret was written into. Run this command:

kubectl exec -it pod/test-file-b9b6d4699-gprjf -c alpine -- sh
cat /akeyless/secrets/K8s/my_k8s_secret 

The content of the file will have the same password we saw earlier: myPassword.

This is great if our application is intended to retrieve the secret once from Akeyless, so an akeyless-init container retrieving the secret then exiting is appropriate. However, there are times where we need to continuously retrieve secrets from Akeyless. In this case, a sidecar container is needed. Let’s see how to do that in the next example.

Step 4: Retrieve Secrets into a File Continously with a Sidecar

Let’s now retrieve a secret from Akeyless into a file continously with a sidecar. Run the following command:

kubectl apply -f app_file_sidecar.yaml

and here are the contents of the app_file_sidecar.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-file-sidecar
spec:
  replicas: 1
  selector:
    matchLabels:
      app: file-secrets
  template:
    metadata:
      labels:
        app: file-secrets
      annotations:
        akeyless/enabled: "true"
        akeyless/inject_file: "/K8s/my_k8s_secret|location=/secrets/secretsVersion.json" 
        akeyless/side_car_enabled: "true"
        akeyless/side_car_refresh_interval: "5s"
        akeyless/side_car_versions_to_retrieve: "2"
    spec:
      containers:
      - name: alpine
        image: alpine
        command:
          - "sh"
          - "-c"
          - "while true; do [ ! -f /secrets/timestamp ] || [ /secrets/secretsVersion.json -nt /secrets/timestamp ] && touch /secrets/timestamp && cat /secrets/secretsVersion.json && echo ''; sleep 15; done"

Notice the following annotations:

  • akeyless/enabled: “true” -> An annotation that enables the K8s Injector plugin
  • akeyless/inject_file: “/K8s/my_k8s_secret|location=/secrets/secretsVersion.json” -> An annotation specifying the path to get the secret from in Akeyless. Here we’re specifying where to write the secret in the pod’s file system at /secrets/secretsVersion.json.
  • akeyless/side_car_enabled: “true” -> This is what enables the sidecar container.
  • akeyless/side_car_refresh_interval: “5s” -> This specifies the interval at which the sidecar will check for new versions of the secret.
  • akeyless/side_car_versions_to_retrieve: “2” -> This specifies the number of versions of the secret to retrieve.

If you run kubectl get po, you will see that we have now two containers running for our pod:

NAME                                         READY   STATUS    RESTARTS      AGE
test-file-sidecar-759667cccc-6h8xv           2/2     Running   0             43m

Now check the logs of the akeyless-sidecar container:

kubectl logs -f po/test-file-sidecar-759667cccc-6h8xv -c akeyless-sidecar

Output:

2024/06/22 14:58:02 [INFO] Secret /K8s/my_k8s_secret was successfully written to: /secrets/secretsVersion.json

and check the logs of the alpine container:

kubectl logs -f po/test-file-sidecar-759667cccc-6h8xv -c alpine

Output:

{
  "version": 1,
  "secret_value": "myPassword",
  "creation_date": 1719068280
}

Now update the secret in the Akeyless UI:

and notice the logs will automatically change to reflect the new secret:

[
 {
  "version": 2,
  "secret_value": "myPassword2",
  "creation_date": 1719071019
 },
 {
  "version": 1,
  "secret_value": "myPassword",
  "creation_date": 1719068280
 }
]

Finally, we can exec into the alpine container to see the file where all the secrets live:

kubectl exec -it pod/test-file-sidecar-759667cccc-6h8xv -c alpine -- sh
cat /secrets/secretsVersion.json 

Output:

[
 {
  "version": 2,
  "secret_value": "myPassword2",
  "creation_date": 1719071019
 },
 {
  "version": 1,
  "secret_value": "myPassword",
  "creation_date": 1719068280
 }
]

As we just saw, we can now actively retrieve new versions of the secret and write them to the file system. Application developers need to build logic into their applications to read the file and use the secret with retry mechanisms in case of failures due to an expired secret. This is the direction organizations should take to reduce long-lived credentials in their environments.

Conclusion

Key Takeaways

  • Kubernetes Secrets are required for sensitive data.
  • Native Kubernetes Secrets are base64 encoded and not encrypted at rest by default.
  • Akeyless improves secret management with additional security and integrations and encrypts secrets at rest.
  • The Akeyless Secrets Injector injects secrets into your Kubernetes pods seamlessly either in the form of environment variables or in files.

Why You Need Akeyless for Secret Management in Kubernetes

With Akeyless, you can centralize secret management, enhance security through strong encryption and RBAC, ensure compliance with detailed audit logs, and seamlessly integrate with Kubernetes without changing your application code. By using Akeyless, you can manage secrets more effectively and securely, making it an indispensable tool for any Kubernetes-based application.

Explore Akeyless’s solutions for secure key management and start fortifying your data protection strategies today. Visit the product pages for more information and to schedule a demo.

Ready to get started?

Discover how Akeyless simplifies secrets management, reduces sprawl, minimizes risk, and saves time.

Book a Demo