CloudTaserConfig CRD¶
The CloudTaserConfig custom resource provides a reusable, namespace-scoped configuration object for CloudTaser sidecar injection. Instead of specifying vault addresses, secret paths, and environment mappings as individual pod annotations, you define them once in a CR and reference it from your workloads.
API Details¶
| Field | Value |
|---|---|
| API Group | api.cloudtaser.io |
| API Version | v1alpha1 |
| Kind | CloudTaserConfig |
| Short Name | ctc |
| Scope | Namespaced |
# List all CloudTaserConfig resources
kubectl get ctc -A
# Describe a specific config
kubectl describe ctc my-app-config -n production
Spec Fields¶
vaultAddress¶
| Type | string |
| Required | Yes |
The URL of the EU-hosted OpenBao or Vault instance, including scheme and port.
vaultRole¶
| Type | string |
| Required | Yes |
The Vault Kubernetes auth role name. This role must be configured in Vault to accept service account tokens from the target namespace and service accounts.
vaultAuthPath¶
| Type | string |
| Required | No |
| Default | "auth/kubernetes" |
The mount path of the Kubernetes auth method in Vault. Override this when using a non-default auth mount.
secretPaths¶
| Type | []string |
| Required | Yes |
A list of Vault KV secret paths to fetch at pod startup. Each path is read in order, and all key-value pairs from each path are made available to the wrapped application process.
spec:
secretPaths:
- "secret/data/myapp/database"
- "secret/data/myapp/api-keys"
- "secret/data/shared/tls-certs"
envMap¶
| Type | map[string]map[string]string |
| Required | No |
Maps Vault secret fields to specific environment variable names. The outer key is the Vault path (must match an entry in secretPaths), and the inner map provides field: ENV_VAR mappings.
spec:
envMap:
"secret/data/myapp/database":
username: DB_USER
password: DB_PASS
host: DB_HOST
"secret/data/myapp/api-keys":
stripe_key: STRIPE_SECRET_KEY
sendgrid_key: SENDGRID_API_KEY
Unmapped fields
Fields not listed in envMap are still injected into the process environment using their original Vault field names. The map provides renaming, not filtering.
wrapperImage¶
| Type | string |
| Required | No |
| Default | Uses the image configured in the operator |
Overrides the wrapper container image. Useful when pinning specific wrapper versions per workload or using a private registry mirror.
wrapperResources¶
| Type | corev1.ResourceRequirements |
| Required | No |
| Default | requests: {cpu: 10m, memory: 32Mi}, limits: {cpu: 100m, memory: 64Mi} |
Resource requests and limits for the injected wrapper init container and sidecar.
namespaceSelector¶
| Type | metav1.LabelSelector |
| Required | No |
When set, restricts which namespaces this config can be referenced from. Pods in namespaces that do not match the selector will not be injected even if they reference this config.
Status Fields¶
The status subresource is managed by the operator and is read-only.
ready¶
| Type | bool |
Indicates whether the config has been validated and is ready for use. The operator validates vault connectivity and auth configuration.
message¶
| Type | string |
A human-readable message describing the current state, especially useful when ready is false.
injectedPods¶
| Type | int |
The number of pods currently running with this config applied.
lastValidated¶
| Type | metav1.Time |
Timestamp of the last successful validation of the vault connection and auth configuration.
conditions¶
| Type | []metav1.Condition |
Standard Kubernetes conditions providing detailed status information.
| Condition Type | Description |
|---|---|
VaultReachable |
The operator can reach the configured vault address. |
AuthConfigured |
The Kubernetes auth role is valid and accepts tokens from the target namespace. |
SecretsAccessible |
The configured secret paths are readable with the given role. |
Ready |
All validation checks have passed. |
Full Example¶
apiVersion: api.cloudtaser.io/v1alpha1
kind: CloudTaserConfig
metadata:
name: payment-service
namespace: production
labels:
app.kubernetes.io/name: payment-service
app.kubernetes.io/part-of: payments
spec:
vaultAddress: "https://vault.eu-west-1.example.com:8200"
vaultRole: "payment-service"
vaultAuthPath: "auth/kubernetes"
secretPaths:
- "secret/data/payments/database"
- "secret/data/payments/stripe"
- "secret/data/payments/internal-api"
envMap:
"secret/data/payments/database":
username: PGUSER
password: PGPASSWORD
host: PGHOST
port: PGPORT
dbname: PGDATABASE
"secret/data/payments/stripe":
secret_key: STRIPE_SECRET_KEY
webhook_secret: STRIPE_WEBHOOK_SECRET
"secret/data/payments/internal-api":
token: INTERNAL_API_TOKEN
wrapperImage: "europe-docker.pkg.dev/skipops/cloudtaser/wrapper:v0.2.0"
wrapperResources:
requests:
cpu: "10m"
memory: "32Mi"
limits:
cpu: "100m"
memory: "64Mi"
namespaceSelector:
matchLabels:
environment: production
Usage Pattern¶
Step 1: Create the CloudTaserConfig in your target namespace.
Step 2: Verify the config is ready.
Expected output:
Step 3: Reference the config from your Deployment annotations.
apiVersion: apps/v1
kind: Deployment
metadata:
name: payment-service
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: payment-service
template:
metadata:
labels:
app: payment-service
annotations:
cloudtaser.io/inject: "true"
cloudtaser.io/config: "payment-service"
cloudtaser.io/rotation: "sighup"
cloudtaser.io/ebpf: "true"
spec:
serviceAccountName: payment-service
containers:
- name: api
image: eu.gcr.io/myproject/payment-service:v2.1.0
ports:
- containerPort: 8080
Step 4: Confirm injection after pod creation.
kubectl get pods -n production -l app=payment-service -o jsonpath='{.items[0].metadata.annotations.cloudtaser\.io/status}'
Expected output: injected
Troubleshooting¶
Config not found
If the webhook cannot find the referenced CloudTaserConfig in the pod's namespace, the pod will be admitted without injection and cloudtaser.io/status will be set to "error". Check that the CR name matches exactly and exists in the same namespace as the pod.
Config not ready
If the CloudTaserConfig exists but its ready status is false, the webhook will still inject the sidecar, but the wrapper may fail to authenticate at runtime. Always verify kubectl get ctc shows READY: True before deploying workloads.
Check operator logs for detailed validation errors: