Operator Installation¶
The CloudTaser operator is the core component that enables secret injection into Kubernetes workloads. It runs as a Deployment with a mutating admission webhook that intercepts pod creation, injects the wrapper binary via an init container, and rewrites container entrypoints so secrets are fetched from an EU-hosted vault directly into process memory.
Prerequisites¶
Before installing the operator, ensure the following requirements are met.
Required
All three prerequisites are mandatory. The operator will not function without a compatible Kubernetes cluster, Helm, and a reachable vault instance.
| Requirement | Minimum | Recommended |
|---|---|---|
| Kubernetes | 1.28+ | 1.30+ |
| Helm | 3.x | Latest 3.x |
| Vault | OpenBao 2.x or HashiCorp Vault 1.15+ | OpenBao (no license concerns) |
Kubernetes Cluster¶
The operator is tested on GKE Standard, EKS (managed node groups), and AKS (regular node pools). Serverless environments such as GKE Autopilot and AWS Fargate are not supported because the eBPF agent requires host-level access.
EU-Hosted Vault¶
CloudTaser requires an OpenBao or HashiCorp Vault instance hosted in the EU. This is the foundation of the data sovereignty guarantee -- secrets transit only between the EU vault and process memory on the Kubernetes node. They never pass through etcd, Kubernetes Secrets, or any US-controlled storage layer.
Recommended EU regions
- GCP:
europe-west1(Belgium),europe-west3(Frankfurt),europe-west4(Netherlands) - AWS:
eu-central-1(Frankfurt),eu-west-1(Ireland),eu-west-3(Paris) - Azure:
westeurope(Netherlands),germanywestcentral(Frankfurt) - Self-hosted: Any EU data center
The vault instance must have:
- KV v2 secrets engine enabled
- Kubernetes auth backend enabled
- TLS configured (the wrapper validates the server certificate)
- Network reachability from the Kubernetes cluster
Installation¶
Install the operator and all CloudTaser components using the unified Helm chart from the OCI registry:
helm install cloudtaser oci://ghcr.io/skipopsltd/cloudtaser-helm/cloudtaser \
--namespace cloudtaser-system \
--create-namespace \
--set operator.vaultAddress=https://vault.eu.example.com
OCI registry authentication
The CloudTaser Helm chart is hosted on GitHub Container Registry. If your cluster requires authentication to pull from ghcr.io, create an image pull secret and reference it in your values:
Key Helm Values¶
The following values control operator behavior. For the full values reference, see Helm Values.
operator:
# Vault endpoint (required)
vaultAddress: "https://vault.eu.example.com"
# Container image
image:
repository: ghcr.io/skipopsltd/cloudtaser-operator
tag: "v0.4.18-amd64"
pullPolicy: IfNotPresent
# Replicas (use 3+ for production HA)
replicaCount: 1
ha: false
leaderElect: false
# Resource requests and limits
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
# Webhook configuration
webhook:
port: 9443
failurePolicy: Fail # (1)!
timeoutSeconds: 10
# Provide your own TLS cert (optional)
# certSecret: my-webhook-certs
# Wrapper image injected into workload pods
wrapper:
image:
repository: ghcr.io/skipopsltd/cloudtaser-wrapper
tag: "v0.0.14-amd64"
Failmeans pods will not be created if the webhook is unavailable. UseIgnoreonly in non-production environments where you prefer availability over enforcement.
Verify Installation¶
After the Helm install completes, verify the operator is running:
Check Pods¶
Expected output:
NAME READY STATUS RESTARTS AGE
cloudtaser-operator-6f8b9c7d4-x2k9m 1/1 Running 0 45s
cloudtaser-ebpf-node1 1/1 Running 0 45s
Check Webhook Configuration¶
Expected output:
Verify the webhook is configured with the correct CA bundle:
The caBundle field should be populated and the rules section should target pod creation.
Check Operator Logs¶
Look for a log line confirming the webhook server has started and vault connectivity is established.
Run Validation (Optional)¶
If you have the CloudTaser CLI installed, run a full validation:
Create a CloudTaserConfig CR¶
Instead of specifying vault configuration on every workload via annotations, you can define a shared CloudTaserConfig custom resource. Workloads reference the config by name, reducing annotation duplication and centralizing management.
apiVersion: api.cloudtaser.io/v1alpha1
kind: CloudTaserConfig
metadata:
name: default
namespace: cloudtaser-system
spec:
vaultAddress: "https://vault.eu.example.com"
vaultRole: "cloudtaser"
secretPaths:
- "secret/data/shared/config"
envMap:
db_password: PGPASSWORD
api_key: API_KEY
rotation:
strategy: restart # restart | sighup | none
interval: 1h
Apply the config:
Workloads can reference this config with a single annotation instead of specifying all vault parameters individually:
Annotate Your First Workload¶
Add CloudTaser annotations to a Deployment to enable secret injection:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
annotations:
cloudtaser.io/inject: "true"
cloudtaser.io/config: "default"
spec:
containers:
- name: myapp
image: myapp:latest
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
annotations:
cloudtaser.io/inject: "true"
cloudtaser.io/vault-address: "https://vault.eu.example.com"
cloudtaser.io/vault-role: "cloudtaser"
cloudtaser.io/secret-paths: "secret/data/myapp/config"
cloudtaser.io/env-map: "db_password=PGPASSWORD,api_key=API_KEY"
spec:
containers:
- name: myapp
image: myapp:latest
Apply and verify:
When the pod starts, the operator:
- Injects an init container that copies the wrapper binary to a memory-backed emptyDir (
/cloudtaser/) - Rewrites the container entrypoint to
/cloudtaser/wrapper - The wrapper authenticates to vault using Kubernetes auth, fetches secrets, and fork+execs the original application with secrets as environment variables
Secrets in memory only
Secrets exist only in process memory. They never touch etcd, Kubernetes Secrets, or disk. The eBPF agent blocks attempts to read /proc/pid/environ, /proc/pid/mem, and ptrace calls on protected processes.
Troubleshooting¶
| Symptom | Cause | Fix |
|---|---|---|
Pod stuck in Init |
Wrapper init container cannot pull image | Check imagePullSecrets and registry access |
Pod CrashLoopBackOff |
Wrapper cannot reach vault | Verify vault endpoint is reachable from the cluster |
| Webhook not firing | MutatingWebhookConfiguration missing or misconfigured | Check kubectl get mutatingwebhookconfigurations |
403 permission denied from vault |
Kubernetes auth role misconfigured | Run cloudtaser connect or verify the vault role manually |
For more details, see Troubleshooting.
Next Steps¶
- Install the eBPF daemonset for runtime enforcement
- Configure the S3 encryption proxy for client-side encryption
- Production deployment guide for HA, RBAC hardening, and monitoring