Use kubectl create secret generic --from-file to create a Kubernetes Secret from a local file and mount it in a Pod through a Secret volume. This tutorial also shows you how to verify a change by reading the file again without displaying its value. The lab uses only harmless demonstration data that cannot grant access to a service.
What are Kubernetes Secrets, and when do you need them?
Kubernetes Secrets are API objects for confidential data such as passwords, tokens or keys, which you manage separately from application code and provide to a Pod, for example as a file or environment variable.
Use the Opaque Secret type for keys you define yourself. A ConfigMap, by contrast, is intended for non-confidential configuration, such as a database host or operating mode. A Secret separates sensitive values from the Pod manifest, but it does not replace a security strategy: Base64 is an encoding and provides no confidentiality.
Prerequisites and versions
The reference versions for this tutorial are fixed as of 2026-10-06:
| Component | Version or prerequisite |
|---|---|
| Kubernetes API server and kubectl | v1.35.9 for both |
| Pod and Secret API | v1 |
| Local shell | Bash 5.2 on Linux |
| Local file utilities | GNU Coreutils 9.4 |
| Container image | busybox:1.37.0-glibc on a Linux worker |
These versions describe the documented reference environment. Before adopting the procedure in production, check the Kubernetes release status and compatibility with your provider. The image tag does not replace pinning a digest or performing a security review. You do not need to downgrade Bash or Coreutils to older versions for this example.
You need a suitable kubeconfig and an accessible test cluster. Your user must be able to create, read and delete namespaces; create, read, list, patch and delete Secrets; and create, read, list and delete Pods. You also need access to pods/exec; waiting for the Pod may require watch. Cluster policies must allow the Pod described here.
Work outside a Git repository in a new local directory created for this lab. If you still need to set up the client, see the tutorial on kubectl and Kubernetes clusters.
Prepare the test environment
First, check which cluster your commands target and which client and server versions are in use:
$ kubectl config current-context
$ kubectl versionContinue only if the context belongs to your intended test cluster. Then create the namespace secrets-labor:
$ kubectl create namespace secrets-laborIf the namespace already exists, resolve the naming conflict before the next step. Do not use an existing namespace for the lab without checking it first. The same applies to the local working directory: if creating it fails, do not simply continue working in it.
Run the following commands individually in Bash. umask 077 restricts other users' access to newly created files and directories:
$ umask 077
$ mkdir secrets-labor-dateien
$ cd secrets-labor-dateien
$ printf '%s' 'demo-eins' > password.txtdemo-eins is a public practice value. Do not replace it with a real password in this procedure. printf '%s' does not add a trailing newline; kubectl would include any existing newline as part of the value. Stay in this working directory for subsequent file operations. In a new shell, you must change to this directory and set umask 077 again.
Create a Secret from a file
Create the Secret app-zugang in the lab namespace. With password=./password.txt, you explicitly set the key to password, regardless of the filename:
$ kubectl create secret generic app-zugang -n secrets-labor --from-file=password=./password.txt
$ kubectl get secret app-zugang -n secrets-laborThe default output of get secret shows information such as the name, type and number of data fields, but no Secret value. Check that the object has type Opaque and one data field. Do not use YAML or JSON output for this check: it contains the encoded data, which can be decoded again. The limited table view does not restrict your API read permissions.
Matching infrastructure at centron
From container to cluster: managed Kubernetes from centron with control plane and traffic included. Explore managed Kubernetes →
How do you use a Secret as a file in a Pod?
To use a Kubernetes Secret as a file in a Pod, reference its name under volumes.secret and mount that volume in the container; the Pod and Secret must be in the same namespace.
Save the following content as secret-leser.yaml in your working directory:
apiVersion: v1
kind: Pod
metadata:
name: secret-leser
namespace: secrets-labor
spec:
nodeSelector:
kubernetes.io/os: linux
automountServiceAccountToken: false
restartPolicy: Never
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: secret-leser
image: busybox:1.37.0-glibc
command: ["sleep", "3600"]
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
volumeMounts:
- name: app-zugang
mountPath: /etc/app-zugang
readOnly: true
volumes:
- name: app-zugang
secret:
secretName: app-zugang
defaultMode: 0440
items:
- key: password
path: passworditems specifically projects the key password into the file /etc/app-zugang/password. With this selection, additional Secret keys would not be mounted. The Pod manifest contains only the reference, not the value.
The container runs with user and group ID 1000. 0440 sets read permissions for the owner and group as the initial mode; fsGroup: 1000 accounts for the volume's group permissions for the container. Settings such as fsGroup can affect the final file permissions. The mount remains read-only. Automatic ServiceAccount token mounts are also disabled: the container does not need to call the Kubernetes API itself for this Secret volume.
Create the Pod and wait up to 120 seconds for its Ready condition:
$ kubectl apply -n secrets-labor -f secret-leser.yaml
$ kubectl wait -n secrets-labor --for=condition=Ready pod/secret-leser --timeout=120s
$ kubectl exec -n secrets-labor secret-leser -- test -s /etc/app-zugang/passwordtest -s checks whether the file exists and is larger than zero bytes. A successful call exits with status 0 and displays no content. It does not yet prove that an application processes the value. The container waits for one hour with sleep 3600; complete the following checks during that time.
What happens when you change a Kubernetes Secret?
When you change a Kubernetes Secret, Kubernetes updates a regularly mounted Secret volume after a delay; an application must read the file again, while running containers receive updated Secret environment variables only after a restart.
First, check the byte count of the initial practice value in the Pod:
$ kubectl exec -n secrets-labor secret-leser -- wc -c /etc/app-zugang/passwordFor demo-eins without a newline, the length is nine bytes. wc -c prints the byte count and file path, not the content. This length check is intended for demonstration data; do not unnecessarily log the sizes of real secrets.
Now write a deliberately longer practice value to the same local file and update the same Secret key:
$ printf '%s' 'demo-zwei-laenger' > password.txt
$ kubectl create secret generic app-zugang -n secrets-labor --from-file=password=./password.txt --dry-run=client -o yaml | kubectl apply -n secrets-labor -f -
$ kubectl exec -n secrets-labor secret-leser -- wc -c /etc/app-zugang/password--dry-run=client generates the manifest locally; the pipe passes it directly to apply. It carries the Base64-encoded data. Do not print or log the pipe's contents. Client-Side Apply also stores manifest data in the annotation kubectl.kubernetes.io/last-applied-configuration. The first apply to the object previously created with create may display a notice about the missing annotation; apply adds it. This is why the procedure is explicitly limited to dummy values. Production updates belong in your established Secret management process.
The second value has 17 bytes. If the check still shows nine bytes, repeat only the last wc call after waiting a little. The delay depends, among other things, on the kubelet synchronization interval and caching strategy. These factors do not establish a fixed waiting time for the update to take effect.
In this example, 17 bytes indicate the change to the other length. The check does not distinguish arbitrary values of the same length and does not prove that an application reloads automatically. Each wc call opens the file again; an application that caches credentials needs its own mechanism for reading them again.
| Integration method | Behavior when Secrets are updated |
|---|---|
| Secret volume as in the example | File is updated after a delay; the application must read it again. |
Mount with subPath |
Does not receive automatic Secret updates. |
Environment variable through secretKeyRef |
Running container keeps the old value; a new container is required. |
For the alternative of using an environment variable, the snippet under the container could look like this:
env:
- name: APP_PASSWORD
valueFrom:
secretKeyRef:
name: app-zugang
key: passwordThis snippet is not a standalone resource and is not applied in the file-based lab. The choice between a file and an environment variable depends on the application. Changing the Secret also does not rotate a password in a database or another target system.
Consider security limitations in production
Beyond choosing the appropriate integration method, production use requires clear rules for access and storage. The Kubernetes recommendations for Secrets emphasize encryption at rest and keeping permissions to a minimum.
- Check encryption of Secret data in etcd with your cluster operator. It is a cluster configuration and does not follow from either Base64 or a file mount.
- Restrict
get,listandwatchpermissions on Secrets. Evenlistcan return their contents. Also consider permissions to create Pods: anyone allowed to create a Pod with a Secret can read the value through that Pod, even without direct permission to read the Secret. - Give access only to containers that need the particular value. A separate namespace organizes access, but is not sufficient protection on its own.
- Keep real values and encoded Secret manifests out of Git, shell arguments, history and logs. The application must also protect the data it reads.
With Managed Kubernetes, clarify with the provider which safeguards cluster operations cover and which tasks remain with your team. These include Secret access, updates and applications reading changed values again. The service name does not imply a specific encryption configuration.
Troubleshoot problems
Start with the default output for the Pod and Secret:
$ kubectl get pod secret-leser -n secrets-labor
$ kubectl get secret app-zugang -n secrets-labor| Problem | What to check |
|---|---|
| Pod does not start because of the Secret mount | The Secret must exist in secrets-labor and contain the key password specified in items. Missing required Secrets or keys prevent startup. |
| Object is not found | Check the context, namespace and spelling against the names used here. |
Request is rejected with Forbidden |
Check permissions for the specific action; do not grant administrator privileges indiscriminately. |
| Image cannot be pulled | Check the image tag, registry connectivity and the test cluster's image pull requirements. |
| Byte count differs | The local file may contain an extra newline. The printf commands shown here do not write one. |
| Application uses the old value | Check for propagation delays, failure to read the file again, subPath or use as an environment variable. |
| Data change is rejected | A Secret marked with immutable: true does not allow changes to its data. |
For example, you can check one specific permission like this:
$ kubectl auth can-i create pods -n secrets-laborThis query checks only the specified action. It confirms neither all the necessary permissions nor whether the Pod manifest is allowed under cluster policies.
Clean up and plan your next steps
First, delete the lab Pod and Secret explicitly:
$ kubectl delete pod secret-leser -n secrets-labor
$ kubectl delete secret app-zugang -n secrets-labor
$ kubectl get pods,secrets -n secrets-laborThe last query shows only Pods and Secrets. Before deleting the namespace, also check that it contains no unrelated workloads or other resources you need. Deleting a namespace removes all resources within it. Delete secrets-labor only if you created it specifically for this lab as described:
$ kubectl delete namespace secrets-laborThen delete only the two files you created in the local working directory:
$ rm -- ./password.txt ./secret-leser.yamlYou can then remove the empty working directory manually. rm removes files but does not guarantee secure physical erasure of their contents.
To apply this procedure to your application, next determine how it reads changed credentials again, who may update Secrets and how changes are coordinated with the target system. These decisions turn the demonstrated file mount into a suitable procedure for your production environment.
Testen Sie Ihr Setup auf ccloud³
Registrieren Sie sich in der ccloud³ und erhalten Sie 200 € Startguthaben für Ihr Projekt – z. B. für eine PostgreSQL-VM mit automatischen Backups.