Skaffold’s built-in secrets management is less about generating secrets and more about seamlessly injecting existing secrets into your development containers, making your local development loop feel exactly like your production environment.
Let’s see it in action. Imagine you have a Kubernetes Secret object named my-db-credentials in your development namespace, containing keys username and password. You want your local Go application, running in a dev container managed by Skaffold, to access these.
Here’s a snippet from a skaffold.yaml:
apiVersion: skaffold/v2
kind: Config
build:
artifacts:
my-app:
docker:
dockerfile: Dockerfile
deploy:
kubectl:
manifests:
- k8s/deployment.yaml
profiles:
- name: dev
activation:
- kubeContext: docker-desktop
manifests:
- k8s/development-deployment.yaml
deploy:
kubectl:
flags:
apply: ["--namespace=development"]
dev:
containers:
- name: my-app
ports:
- containerPort: 8080
sync:
manual: {}
# This is the magic:
secrets:
- secretName: my-db-credentials
paths:
- key: username
path: app/config/db_user.txt
- key: password
path: app/config/db_pass.txt
When you run skaffold dev --profile dev, Skaffold will:
-
Detect the
devprofile: It sees you’re targeting thedocker-desktopcontext and activates this profile. -
Apply development manifests: It uses
k8s/development-deployment.yamland applies it to thedevelopmentnamespace. This deployment must include a reference to themy-db-credentialssecret, either as a volume mount or environment variables. For example, yourdevelopment-deployment.yamlmight look like this:apiVersion: apps/v1 kind: Deployment metadata: name: my-app-deployment namespace: development spec: replicas: 1 selector: matchLabels: app: my-app template: metadata: labels: app: my-app spec: containers: - name: my-app image: my-app:latest # Skaffold will manage this image ports: - containerPort: 8080 volumeMounts: - name: credentials-volume mountPath: /etc/secrets # Or any path your app expects volumes: - name: credentials-volume secret: secretName: my-db-credentials -
Enter Dev Mode: For your
my-appcontainer, Skaffold recognizes thesecretsconfiguration. -
Inject Secrets: Skaffold doesn’t create the secret itself. It assumes the secret
my-db-credentialsalready exists in thedevelopmentnamespace. When Skaffold starts your dev container, it ensures that the secret data defined inmy-db-credentialsis available within the container at the specifiedpaths. In our example, theusernamefrom the secret will be written to/app/config/db_user.txtinside the container, and thepasswordto/app/config/db_pass.txt.
The core problem this solves is consistency between your local development environment and your deployed environments. Developers often struggle with local setups that don’t mirror production, leading to "it works on my machine" issues. By allowing Skaffold to manage the injection of pre-existing secrets (which you’d typically manage via CI/CD or GitOps in production), you reduce this drift. Your application code can read secrets from standard locations (files or environment variables) without needing special logic for local development.
The secrets block in skaffold.yaml is a declarative way to tell Skaffold: "When you run this container in dev mode, make sure these specific keys from this specific Kubernetes Secret are available at these specific file paths inside the container." Skaffold then orchestrates the mounting or copying of this data. It’s crucial to understand that Skaffold doesn’t create the Kubernetes Secret resource itself; it relies on that resource existing in the cluster. Your k8s/development-deployment.yaml (or similar) is responsible for telling Kubernetes how to expose that secret to the pod (e.g., via volume mounts as shown above). Skaffold then uses this information to ensure the data lands correctly in the dev container.
A common misconception is that Skaffold will create the Secret object in Kubernetes. It will not. It is designed to work with secrets that are already provisioned in your cluster. If the Secret object my-db-credentials doesn’t exist in the development namespace, or if it’s missing the username or password keys, your container will likely start but won’t have the expected credentials, leading to application errors.
The path directive in the secrets configuration is not just for mounting; Skaffold will actually write the secret data to these files within the dev container’s filesystem if they aren’t already mounted by Kubernetes. This is particularly useful if your Kubernetes deployment manifest doesn’t explicitly configure a volume mount for the secret, but your application expects the secret data to be in a file. Skaffold can bridge that gap for you during development.
The next step you’ll encounter is managing how these secrets are created in your cluster for different environments, which often involves tools like Helm, Kustomize, or dedicated secrets management solutions like HashiCorp Vault or AWS Secrets Manager, integrated into your CI/CD pipeline.