Create a TLS Secret from Certificate Files
Create a TLS Secret named clever-cactus in the clever-cactus namespace for an existing Deployment named clever-cactus.
Live lab access
This task description is public. Live practice requires full access unless this is the selected free weekly task. AI Lab Coach is available in single-task labs, including the free weekly task. See this week's free task.
Create an account to continue →
On a phone? Read the task and create your account here, then sign in on a desktop or laptop for the terminal lab. Nothing starts until you choose Start.
The task
Context
You must complete securing access to a web server using SSL files stored in a TLS Secret.
Task
Create a TLS Secret named clever-cactus in the clever-cactus namespace for an existing Deployment named clever-cactus.
Use the following SSL files:
- Certificate:
/home/candidate/clever-cactus/web.k8s.local.crt - Key:
/home/candidate/clever-cactus/web.k8s.local.key
The Deployment is already configured to use the Secret as a volume.
Original Prepium guide · Written for Kubernetes v1.35 and checked against the official documentation on 6 October 2026. Use a disposable practice cluster. The openssl commands assume OpenSSL 3.x on your workstation.
Package a certificate and key as a kubernetes.io/tls Secret, and check it before anything uses it
A kubernetes.io/tls Secret is an ordinary Secret with a fixed contract: it must contain the keys tls.crt (the PEM certificate) and tls.key (the PEM private key). Ingress controllers and many applications look for exactly those names. Because the contract is about key names rather than file names, the usual exam mistakes are a mismatched key pair, a certificate for the wrong host, and a Secret in the wrong namespace or with the wrong name for the workload that mounts it.
portal.crt ─┐ ┌─→ Pod volume: /etc/tls/tls.crt, /etc/tls/tls.key
├─ kubectl create secret tls ─→ Secret ┤
portal.key ─┘ (type kubernetes.io/tls, └─→ Ingress spec.tls[].secretName
keys tls.crt + tls.key)
1. Make a throwaway certificate and inspect it
openssl req -x509 -newkey rsa:2048 -noenc -days 30 \
-keyout portal.key -out portal.crt \
-subj "/CN=portal.prepium.test" \
-addext "subjectAltName=DNS:portal.prepium.test"
openssl x509 -in portal.crt -noout -subject -issuer -dates -ext subjectAltName
-x509 makes openssl req output a self-signed certificate instead of a signing request, and -noenc leaves the private key unencrypted (on OpenSSL 1.1 the older spelling is -nodes). The second command is the habit to keep: read subject, issuer, validity window and the DNS names before you package anything. Clients compare the hostname they connect to with the names in the certificate, so a certificate that is valid but issued for another host still fails.
2. Prove the key belongs to the certificate
diff <(openssl x509 -in portal.crt -noout -pubkey) <(openssl pkey -in portal.key -pubout) \
&& echo "key matches certificate"
Both commands print a public key in PEM form, one extracted from the certificate and one derived from the private key. Identical output means they are a pair. kubectl create secret tls also requires the certificate to match the key, but checking first tells you which file is wrong when you have several candidates on disk.
3. Create the Secret
kubectl create namespace prepium-tutorial
kubectl -n prepium-tutorial create secret tls portal-tls \
--cert=portal.crt --key=portal.key
kubectl -n prepium-tutorial describe secret portal-tls
describe shows the type kubernetes.io/tls and the two data keys tls.crt and tls.key, with sizes but not contents. Your file names do not survive: whatever the files were called, the keys inside the Secret are always those two. If you write the YAML by hand instead, the API server insists that both keys are present for this type, but it does not validate the certificate itself.
4. Consume it, then verify from the cluster side
Mounted as a volume, each key becomes a file, so a container sees tls.crt and tls.key under its mountPath. An Ingress refers to it with spec.tls[].secretName, and the hosts listed there should match the host in the rules and the names in the certificate. Either way the workload needs the Secret's exact name, in the workload's namespace, so read the consuming manifest before you choose a name.
kubectl -n prepium-tutorial get secret portal-tls \
-o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -subject -enddate
The backslash escapes the dot inside the key name so jsonpath does not treat it as a path separator. If the output shows the subject and expiry you expect, what the cluster stores is what you meant to upload.
Common mistakes
- Swapping
--certand--key. kubectl refuses to build the Secret, since the certificate must be PEM and must match the key. - Creating a generic Secret from the same files. The keys are named after your files and the type is
Opaque, so consumers expectingtls.crtfind nothing. - Creating the Secret in
defaultwhile the workload lives elsewhere. The volume stays unresolved and the Pod does not start. - Replacing a certificate by deleting and recreating the Secret under a new name. Keep the name; mounted files are updated in place, eventually.
| Example check | Evidence |
|---|---|
| Right type and keys | type: kubernetes.io/tls with tls.crt and tls.key |
| Right certificate stored | Decoded tls.crt shows the expected subject, SAN and expiry |
| Pair is consistent | Public keys from certificate and key are identical |
| Consumer is satisfied | The mounting Pod is Running and sees both files |
Cleanup: kubectl delete namespace prepium-tutorial and delete the two local files. References: TLS Secrets, kubectl create secret tls, Ingress TLS, openssl-x509. Next, try TLS on an Ingress or generic Secrets.
What this tests
Restrict RBAC and service accounts, tighten API server flags, and keep the cluster patched. On the CKS exam, Cluster Hardening tasks are graded purely on what you build in the cluster - not multiple choice - so the only way to get faster is to do them on a real cluster against a clock.
Practice it for real
The public description lets you study the task before signing up. Full access includes this live lab; the selected Task of the Week is free with an account. You solve the task in a real terminal, hit validate, and a programmatic checker scores exactly what you got right and wrong (with partial credit). You can open the solution while practising, then retry and use the failed checks to improve your score.