Skip to content

Getting Started with cloudtaser on GKE

This guide walks you through deploying cloudtaser on a GKE cluster and protecting your first workload. By the end, your application secrets will be fetched directly from an EU-hosted OpenBao into process memory, bypassing Kubernetes Secrets and etcd entirely.

Compliance note

After deploying cloudtaser, secrets are no longer stored in Kubernetes Secrets or etcd. They travel directly from your EU-hosted OpenBao into process memory at runtime. This eliminates the cloud provider's ability to access secret data, providing a technical supplementary measure for Schrems II compliance.

Time to value

A first workload can be protected in under 30 minutes. The process involves deploying the operator via Helm, connecting to your EU OpenBao, and adding annotations to a single deployment. No application code changes are required.


Prerequisites

Before you begin

Ensure you have the following tools installed and configured:

  • A GKE Standard cluster (1.28+) with kubectl access
  • gcloud CLI authenticated with your project
  • helm v3.x installed
  • cloudtaser-cli installed (CLI Reference)
  • An EU-hosted OpenBao (also compatible with HashiCorp Vault) instance (or deploy one in Step 1)

Step 1: Deploy the Secret Store in an EU Region

cloudtaser requires an EU-hosted secret store - today, OpenBao or HashiCorp Vault (other backends are on the roadmap; see the backend architecture overview). This is fundamental to the sovereignty guarantee: secrets never leave EU jurisdiction.

Jurisdiction matters

The secret-store instance must run in an EU region. Deploying outside the EU undermines the entire sovereignty model. Choose a region such as europe-west1 (Belgium), europe-west3 (Frankfurt), or europe-west4 (Netherlands).

The recipe below uses OpenBao; if you already run HashiCorp Vault in the EU you can point cloudtaser at it directly - the two are API-compatible.

Deploy OpenBao on a VM or Kubernetes cluster in an EU region:

# Deploy OpenBao on a GCE VM in Belgium
gcloud compute instances create openbao-eu \
  --zone=europe-west1-b \
  --machine-type=e2-medium \
  --image-family=ubuntu-2204-lts \
  --image-project=ubuntu-os-cloud

After installation, initialize and unseal OpenBao:

# Initialize
openbao operator init -key-shares=5 -key-threshold=3

# Unseal (repeat with 3 different keys)
openbao operator unseal <key1>
openbao operator unseal <key2>
openbao operator unseal <key3>

# Enable KV v2 secrets engine
openbao secrets enable -path=secret kv-v2

# Store a test secret
openbao kv put secret/myapp/config \
  db_password="s3cret" \
  api_key="ak-12345"

Tip

Ensure the OpenBao instance is reachable from your GKE cluster via firewall rules, VPN, or a public endpoint with TLS.


Step 2: Install cloudtaser via Helm

Add the cloudtaser Helm chart and install the operator and eBPF agent:

# Add the cloudtaser Helm repository
helm repo add cloudtaser https://charts.cloudtaser.io
helm repo update

# Install cloudtaser
helm install cloudtaser cloudtaser/cloudtaser \
  --namespace cloudtaser-system \
  --create-namespace \
  --set operator.secretstore.address=https://vault.eu.example.com

Verify the installation:

kubectl get pods -n cloudtaser-system

Expected output:

NAME                                  READY   STATUS    RESTARTS   AGE
cloudtaser-operator-abc123-xyz        1/1     Running   0          30s
cloudtaser-ebpf-node1                 1/1     Running   0          30s

Step 3: Configure the Secret Store Connection

Use the cloudtaser CLI to connect your cluster to the secret store (OpenBao or HashiCorp Vault). By default, this uses beacon relay mode -- both the secret store and the cluster connect outbound to a stateless beacon relay on TCP 443. No direct network path between the secret store and cluster is needed.

Beacon mode (recommended):

# 1. Get the cluster fingerprint
cloudtaser-cli target fingerprint

# 2. Register the cluster on the secret-store side (creates namespace cloudtaser/<fingerprint[:8]>)
cloudtaser-cli source register \
  --fingerprint <cluster-fingerprint> \
  --secretstore-address https://vault.eu.example.com \
  --secretstore-token hvs.YOUR_ADMIN_TOKEN

This command performs the following:

  1. Generates mTLS certificates (CA, bridge cert, broker cert) -- all in memory
  2. Stores the certificates and configuration in the secret store
  3. Computes the info hash used to match bridge and broker through the beacon
  4. Creates a dedicated OpenBao namespace for the cluster at cloudtaser/<fingerprint[:8]> (the current secret-store backend is OpenBao/HashiCorp Vault; future backends will map the same namespace concept onto their native isolation primitives)
  5. Registers the cluster fingerprint in the secret store

Direct connect (legacy):

cloudtaser-cli target connect \
  --secretstore-address https://vault.eu.example.com \
  --secretstore-token hvs.YOUR_ADMIN_TOKEN \
  --namespaces default,production \
  --secret-paths "secret/data/*"

Connectivity modes

Beacon relay is the default. For other options, see Beacon Relay, Reverse-Connect, or pass --mode direct for legacy direct secret-store access.

Legacy --vault-* flag names

The CLI still accepts --vault-address / --vault-token / --vault-role (and every other --vault-* flag) as aliases. They are hidden from --help output; new guides should use --secretstore-* exclusively. Phase 3 of the rename removes the aliases.

Preview before applying

Use --dry-run to see what changes will be made before applying them:

cloudtaser-cli target connect \
  --secretstore-address https://vault.eu.example.com \
  --secretstore-token hvs.YOUR_ADMIN_TOKEN \
  --dry-run

Step 4: Discover Existing Secrets

Scan your cluster for workloads that reference Kubernetes Secrets:

cloudtaser-cli target discover \
  --secretstore-address https://vault.eu.example.com \
  --secretstore-role cloudtaser

This scans all Deployments, StatefulSets, and DaemonSets for secretKeyRef, secretRef, and third-party secret-store injector annotations (e.g. Vault Agent Injector). It outputs SecretMapping CRD YAML to stdout.

cloudtaser-cli target discover \
  --secretstore-address https://vault.eu.example.com \
  --secretstore-role cloudtaser | kubectl apply -f -
cloudtaser-cli target discover \
  -n production \
  --secretstore-address https://vault.eu.example.com \
  --secretstore-role cloudtaser
cloudtaser-cli target discover \
  --secretstore-address https://vault.eu.example.com \
  --secretstore-role cloudtaser > mappings.yaml

Step 5: Annotate a Deployment for Injection

Add cloudtaser annotations to your 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/secretstore-address: "https://vault.eu.example.com"
        cloudtaser.io/secretstore-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 the deployment:

kubectl apply -f myapp-deployment.yaml

When the pod starts, the cloudtaser operator:

  1. Injects an init container that copies the wrapper binary to a memory-backed emptyDir (/cloudtaser/)
  2. Rewrites the container entrypoint to /cloudtaser/wrapper
  3. The wrapper authenticates to the secret store, fetches secrets, and fork+execs your application with secrets as environment variables (PGPASSWORD, API_KEY)

Secrets exist only in process memory

They never touch etcd, Kubernetes Secrets, or disk.

Annotation Reference

Annotation Required Description
cloudtaser.io/inject Yes Set to "true" to enable injection
cloudtaser.io/secretstore-address No (beacon) / Yes (direct) Secret store endpoint URL. Not needed in beacon mode -- the operator broker routes requests automatically. Legacy alias: cloudtaser.io/vault-address.
cloudtaser.io/secretstore-role Yes Kubernetes auth role name registered in the secret store. Legacy alias: cloudtaser.io/vault-role.
cloudtaser.io/secret-paths Yes Comma-separated KV v2 paths in the secret store
cloudtaser.io/env-map Yes Secret-store field to env var mappings (e.g., password=PGPASSWORD)
cloudtaser.io/rotation No Rotation strategy: restart, sighup, or none (default: restart)
cloudtaser.io/config No Reference a CloudTaserConfig CR instead of per-pod annotations

Full configuration reference

For the complete list of annotations, CRDs, and Helm values, see Configuration.


Step 6: Verify Protection

Check the status of cloudtaser components and protected workloads:

cloudtaser-cli target status
cloudtaser-cli target status -n default

This reports operator health, webhook status, eBPF enforcement coverage, and per-workload protection status.

Run Validation

Run validation to verify the full stack is working correctly:

cloudtaser-cli target validate \
  --secretstore-address https://vault.eu.example.com
cloudtaser-cli target validate \
  --secretstore-address https://vault.eu.example.com \
  --secretstore-token hvs.YOUR_TOKEN

Validation checks include:

  • Kubernetes cluster connectivity
  • cloudtaser operator deployment
  • Mutating webhook configuration
  • Secret-store health and seal status (OpenBao/HashiCorp Vault)
  • Kubernetes auth method registered in the secret store
  • Protected and unprotected workload counts
  • eBPF daemonset status

Step 7: Run an Audit

Generate a data sovereignty compliance audit report:

cloudtaser-cli target audit \
  --secretstore-address https://vault.eu.example.com

The audit scans all workloads and reports:

  • Protected workloads -- cloudtaser-injected
  • Unprotected workloads -- still using K8s Secrets directly
  • Orphaned secrets in etcd
  • eBPF runtime enforcement coverage
cloudtaser-cli target audit \
  --secretstore-address https://vault.eu.example.com \
  -o json > audit-report.json
cloudtaser-cli target audit \
  --secretstore-address https://vault.eu.example.com \
  -n production

Next Steps