Module 7 takes the agent you built in Module 6 and turns it into a production cloud service. You'll containerize the stack, orchestrate it on Kubernetes, automate delivery, and operate it with observability, security, and cost controls. The goal: a reliable Digital FTE that runs 24/7 for real users.
Prerequisites: Modules 4-6. You need a working agent service to deploy.
Your Task API needs an API key to call an external service. You hardcode it in your Docker image. Then you realize everyone who pulls your image can extract that key. You move it to an environment variable. Better, but now your deployment YAML has the key in plain text. Anyone with cluster access can read your manifests.
This isn't a hypothetical concern. In production systems, credential leaks cause real damage. API keys get revoked, databases get accessed by unauthorized parties, and teams spend days rotating compromised secrets across dozens of services.
Dapr's secrets building block solves this by providing a unified API to access secrets from multiple stores---Kubernetes secrets, HashiCorp Vault, Azure Key Vault, AWS Secrets Manager---without your application knowing which store is being used. This lesson shows you how to retrieve secrets securely in your Python code and reference them in component configurations.
Before Dapr can retrieve secrets, they must exist in Kubernetes. The kubectl create secret command creates secrets from literal values or files.
Output:
Output:
Notice the values are base64-encoded (not encrypted). Kubernetes secrets provide access control, not encryption at rest by default.
For later use with component YAML:
Output:
Dapr needs a secrets store component to know where to retrieve secrets from. The Kubernetes secrets store is built-in---no extra installation required.
This component:
Output:
Output:
The Secrets API endpoint is /v1.0/secrets/{store}/{key}. With the Python SDK, you use DaprClient.get_secret().
Output:
For FastAPI applications, use the async pattern:
Output:
Kubernetes secrets can contain multiple key-value pairs. The get_secret() response includes all keys:
Output:
To retrieve all secrets from a store:
Output:
Hard-coding credentials in component YAML defeats the purpose of secrets. Dapr supports secretKeyRef to pull values from a secrets store.
Instead of:
Use:
The auth.secretStore field tells Dapr which secrets store to use for resolving secretKeyRef values. Without this, Dapr doesn't know where to look up the secret.
Secrets are for sensitive data that rarely changes. Configuration is for dynamic settings that may change at runtime---feature flags, rate limits, threshold values.
Let's integrate secrets into the Task API from earlier chapters.
Your Task API needs:
Output (on startup):
You built a dapr-deployment skill in earlier lessons. Test and improve it based on what you learned.
Ask yourself:
If you found gaps:
Prompt 1: Retrieve Secrets in Your Application
What you're learning: The startup-load pattern ensures secrets are available throughout your application's lifetime without repeated API calls. The lifespan context manager is the modern FastAPI pattern for initialization.
Prompt 2: Reference Secrets in Component YAML
What you're learning: The secretKeyRef pattern keeps sensitive data out of your YAML files. The auth.secretStore field is required for Dapr to know which secrets store resolves the references.
Prompt 3: Secrets vs Configuration Decision
What you're learning: Secrets are for sensitive data with access control requirements. Configuration is for dynamic settings that may need runtime updates or subscriptions. Mixing them up creates security risks or unnecessary complexity.
Safety Note: Never log full secret values. The pattern api_key[:4] + "..." shown in this lesson reveals only enough to confirm the right secret was loaded. In production, consider not logging secret prefixes at all.