> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Lab Solution Secrets Optional

> Guide demonstrating how to create and use Kubernetes Secrets, inject them into pods with envFrom secretRef, and verify application access to database credentials.

This lab walks through Kubernetes Secrets: how to list existing Secrets, inspect a ServiceAccount token Secret, create a generic Secret for database credentials, and consume that Secret from a pod using `envFrom: secretRef`. The lab uses `kubectl` commands and pod manifest examples.

## 1) How many Secrets exist in the `default` namespace?

Run:

```bash theme={null}
kubectl get secrets
```

Example output:

```text theme={null}
NAME                   TYPE                                  DATA   AGE
default-token-cr4sr    kubernetes.io/service-account-token   3      7m50s
```

Answer: 1

To inspect the secret in more detail:

```bash theme={null}
kubectl describe secret default-token-cr4sr
```

Example output (truncated):

```text theme={null}
Name:         default-token-cr4sr
Namespace:    default
Type:         kubernetes.io/service-account-token

Data
====
ca.crt:     570 bytes
namespace:  7 bytes
token:      <base64-encoded-token>
```

The `default-token-cr4sr` Secret contains three data keys: `ca.crt`, `namespace`, and `token`.

## 2) What is the type of the default token Secret?

From the `kubectl describe` output above, the Type is:

```text theme={null}
kubernetes.io/service-account-token
```

## 3) Which of the following is not a Secret data defined in the default token?

The data keys present are `ca.crt`, `namespace`, and `token`. Any other key would not be present in this Secret.

***

## Application deployment state

The sample application in this lab comprises a `webapp` pod and a `mysql` pod with their respective services. Confirm the current resources:

```bash theme={null}
kubectl get deploy
kubectl get pods
kubectl get svc
kubectl get secret
```

An example consolidated output:

```text theme={null}
# No deployments
No resources found in default namespace.

# Pods
NAME               READY   STATUS    RESTARTS   AGE
webapp-pod         1/1     Running   0          26s
mysql              1/1     Running   0          26s

# Services
NAME               TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)           AGE
kubernetes         ClusterIP   10.43.0.1      <none>        443/TCP           10m
webapp-service     NodePort    10.43.73.93    <none>        8080:30080/TCP    40s
sql01              ClusterIP   10.43.128.20   <none>        3306/TCP          40s

# Secrets
NAME                       TYPE                                DATA   AGE
default-token-cr4sr        kubernetes.io/service-account-token 3      10m
```

The `webapp` is failing because its database connection parameters are missing (environment variables are not set). Example runtime error from the `webapp`:

```text theme={null}
FAILED

Failed connecting to the MySQL database.

Environment Variables: DB_Host=Not Set; DB_Database=Not Set; DB_User=Not Set; DB_Password=Not Set; 2003: Can't connect to MySQL server on 'localhost:3306' (111 Connection refused)

From webapp-pod!
```

Root cause: the Secret containing database credentials has not yet been created.

## 4) Create a Secret for the database credentials

Create a generic Secret named `db-secret` using `kubectl create secret generic` with literal key/value pairs. `kubectl create secret generic` supports `--from-literal`, `--from-file`, and `--from-env-file`. This lab uses `--from-literal`.

Create the Secret:

```bash theme={null}
kubectl create secret generic db-secret \
  --from-literal=DB_Host=sql01 \
  --from-literal=DB_User=root \
  --from-literal=DB_Password=password123
```

Verify it was created:

```bash theme={null}
kubectl get secret db-secret
kubectl describe secret db-secret
```

Example output:

```text theme={null}
# get secret
NAME         TYPE     DATA   AGE
db-secret    Opaque   3      6s

# describe secret (truncated)
Name:         db-secret
Namespace:    default
Type:         Opaque

Data
====
DB_Password:  11 bytes
DB_User:      4 bytes
DB_Host:      5 bytes
```

The `db-secret` contains the three keys required by the `webapp`.

<Callout icon="warning" color="#FF6B6B">
  By default, Kubernetes stores Secrets in etcd unencrypted. Do not rely on Secrets alone for highly sensitive data. Consider enabling encryption at rest for etcd and using RBAC to limit access to Secrets.
</Callout>

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/gJFNfF5mIbzp1GWe/images/Certified-Kubernetes-Administrator-CKA/Application-Lifecycle-Management/Lab-Solution-Secrets-Optional/kubernetes-secrets-documentation-caution-unencrypted.jpg?fit=max&auto=format&n=gJFNfF5mIbzp1GWe&q=85&s=63707da5ff6c14c8804d328c9d2bc79e" alt="A screenshot of a documentation page titled &#x22;Secrets&#x22; (Kubernetes), describing what a Secret is and how it's used. The page includes a highlighted &#x22;Caution&#x22; box warning that Secrets are stored unencrypted by default and lists recommended safety steps." width="1920" height="1080" data-path="images/Certified-Kubernetes-Administrator-CKA/Application-Lifecycle-Management/Lab-Solution-Secrets-Optional/kubernetes-secrets-documentation-caution-unencrypted.jpg" />
</Frame>

## 5) Configure the webapp pod to read environment variables from the Secret

Kubernetes can inject all keys from a Secret into a container as environment variables using `envFrom` with `secretRef`. Below is a minimal Pod manifest that demonstrates exposing all keys in `db-secret` as environment variables inside the container:

```yaml theme={null}
apiVersion: v1
kind: Pod
metadata:
  name: secret-test-pod
spec:
  containers:
  - name: test-container
    image: k8s.gcr.io/busybox
    command: [ "/bin/sh", "-c", "env; sleep 3600" ]
    envFrom:
    - secretRef:
        name: db-secret
  restartPolicy: Never
```

You would add the same `envFrom` snippet into the `webapp` container spec so it receives `DB_Host`, `DB_User`, and `DB_Password` from the `db-secret`.

<Callout icon="lightbulb" color="#1CB2FE">
  Using `envFrom: secretRef` maps each key in the Secret to an environment variable in the container. If you only need specific keys, prefer `env` with `valueFrom.secretKeyRef` to avoid exposing unnecessary values.
</Callout>

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/gJFNfF5mIbzp1GWe/images/Certified-Kubernetes-Administrator-CKA/Application-Lifecycle-Management/Lab-Solution-Secrets-Optional/kubernetes-secrets-uses-alternatives-docs.jpg?fit=max&auto=format&n=gJFNfF5mIbzp1GWe&q=85&s=c520194064e1c14abeebf341ac4c2285" alt="A screenshot of a documentation webpage (Kubernetes) showing the headings &#x22;Uses for Secrets&#x22; and &#x22;Alternatives to Secrets&#x22; with explanatory bullet points and navigation menus on the left and right." width="1920" height="1080" data-path="images/Certified-Kubernetes-Administrator-CKA/Application-Lifecycle-Management/Lab-Solution-Secrets-Optional/kubernetes-secrets-uses-alternatives-docs.jpg" />
</Frame>

To update a running `webapp-pod` you can edit the Pod manifest or update the Deployment/ReplicaSet (if the app were managed). For unmanaged Pods you must recreate the Pod so the new spec takes effect.

Example flow used in this lab:

1. Edit the Pod YAML locally (or create a new Pod manifest that includes `envFrom`).
2. Apply/replace the Pod. One way to force recreation is:

```bash theme={null}
# After saving to /tmp/webapp-pod.yaml
kubectl replace --force -f /tmp/webapp-pod.yaml
```

Example output when the Pod is replaced:

```text theme={null}
pod "webapp-pod" deleted
pod/webapp-pod replaced
```

Verify the pod now references the Secret:

```bash theme={null}
kubectl describe pod webapp-pod
```

Relevant excerpt from `kubectl describe pod webapp-pod`:

```text theme={null}
Containers:
  webapp:
    Environment Variables from:
      db-secret  Secret  Optional: false
    Environment:    <none>
```

This confirms the container is sourcing environment variables from `db-secret`.

## 6) Verify application can now connect

After the Pod restarts and reads its environment variables from the Secret, check the web application logs or status. The webapp should be able to connect to MySQL:

Example success output from the application:

```text theme={null}
Successfully connected to the MySQL database.

Environment Variables: DB_Host=sql01; DB_Database=Not Set; DB_User=root; DB_Password=password123;

From webapp-pod!
```

Security reminder: avoid printing secrets to logs or exposing them in plaintext. This sample prints values only to demonstrate the flow.

***

This completes the lab: you created a Secret and consumed it in a Pod using `envFrom: secretRef`.

## Quick reference and further reading

| Topic | Command / Link |
| - | - |
| Create generic Secret | `kubectl create secret generic db-secret --from-literal=KEY=value` |
| Inject Secret as env vars | `envFrom:` + `secretRef` in pod spec |
| K8s Secrets docs | [https://kubernetes.io/docs/concepts/configuration/secret/](https://kubernetes.io/docs/concepts/configuration/secret/) |
| Etcd encryption and Secrets | [https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/) |

Further resources:

* [Kubernetes Secrets - official documentation](https://kubernetes.io/docs/concepts/configuration/secret/)
* [RBAC Authorization](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/cka-certification-course-certified-kubernetes-administrator/module/2ddcf79b-abb0-4aeb-ad0c-3d54c7b4fc64/lesson/09e9ebdc-31ca-4fce-ad34-18faf698728d" />
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.