Install
This section describes how to deploy Protegrity Synthetic Data on Amazon EKS as part of Protegrity AI Team Edition.
It uses OpenTofu to provision cloud infrastructure, such as S3, IAM, and Karpenter. It also generates the syntheticdata-values.yaml file that Helm uses to deploy Kubernetes workloads.
Install order: prerequisites → OpenTofu infrastructure → Helm deployment.
OCI registry authentication
OpenTofu OCI modules and Helm charts may require authentication. If the registry requires authentication, log in before tofu init and Helm install:
echo "<password>" | helm registry login <Container_Registry_Path> --username "<username>" --password-stdin
Note:
- Set
registry_auth_enabled = truefor Protegrity container registry. Set it tofalseonly for a public or pre-authenticated registry.- If deploying from the Protegrity Container Registry, use
registry.protegrity.com:9443. Specify the local registry endpoint if a local registry is used.- Verify that you are logged in to the registry before proceeding.
Deployment Steps
Step 1 - Provision cloud resources with OpenTofu
The synthetic-data OpenTofu module provisions all cloud prerequisites and writes a
syntheticdata-values.yaml file with cloud-specific Helm overrides.
AWS (EKS)
The module creates:
- S3 bucket (name provided using
bucket_namevariable - must be globally unique) - IAM role + Pod Identity association →
synthetic-dataServiceAccount EC2NodeClassandNodePool(Bottlerocket FIPS, isolated nodes)syntheticdata-values.yaml- Helm overrides file
Azure (AKS)
The module creates:
- Storage Account + blob container for model storage
- Managed Identity + Workload Identity federated credential →
synthetic-dataServiceAccount syntheticdata-values.yaml- Helm overrides file
You do not have a root module
Create a new directory with a single main.tf:
Note: If deploying from the Protegrity Container Registry, use
registry.protegrity.com:9443. Specify the local registry endpoint if a local registry is used.
terraform {
required_version = "~> 1.10"
required_providers {
aws = { source = "registry.opentofu.org/hashicorp/aws", version = "~> 5.0" }
kubernetes = { source = "registry.opentofu.org/hashicorp/kubernetes", version = "~> 2.35" }
}
}
variable "cluster_name" {
type = string
}
variable "bucket_name" {
type = string
}
variable "chart_version" {
type = string
default = ""
}
data "aws_eks_cluster" "this" {
name = var.cluster_name
}
data "aws_eks_cluster_auth" "this" {
name = var.cluster_name
}
provider "kubernetes" {
host = data.aws_eks_cluster.this.endpoint
cluster_ca_certificate = base64decode(data.aws_eks_cluster.this.certificate_authority[0].data)
token = data.aws_eks_cluster_auth.this.token
}
module "synthetic_data" {
source = "oci://<Container_Registry_Path>/synthetic-data/synthetic-data-server/opentofu/synthetic-data?tag=aws-2.1.1"
cluster_name = var.cluster_name
oci_host = "<Container_Registry_Path>"
bucket_name = var.bucket_name
chart_version = var.chart_version
registry_auth_enabled = true
}
output "helm_install" {
value = module.synthetic_data.helm_install
}
output "helm_values" {
value = module.synthetic_data.helm_values
}
Run:
tofu init
tofu apply \
-var="cluster_name=<your-cluster-name>" \
-var="bucket_name=<globally-unique-s3-bucket>" \
-var="chart_version=2.1.1"
This creates the S3 storage, IAM/Pod Identity resources, isolated nodes when enabled, and syntheticdata-values.yaml.
Display both generated outputs:
tofu output
Create a new directory with a single main.tf:
Note: If deploying from the Protegrity Container Registry, use
registry.protegrity.com:9443. Specify the local registry endpoint if a local registry is used.
terraform {
required_version = "~> 1.10"
required_providers {
azurerm = {
source = "registry.opentofu.org/hashicorp/azurerm"
version = "~> 5.7"
}
kubernetes = {
source = "registry.opentofu.org/hashicorp/kubernetes"
version = "~> 2.35"
}
}
}
variable "cluster_name" {
type = string
}
variable "resource_group_name" {
type = string
}
variable "storage_account_name" {
type = string
}
variable "chart_version" {
type = string
default = ""
}
variable "environment" {
type = string
default = "production"
}
provider "azurerm" {
features {}
resource_provider_registrations = "none"
}
data "azurerm_kubernetes_cluster" "this" {
name = var.cluster_name
resource_group_name = var.resource_group_name
}
provider "kubernetes" {
host = data.azurerm_kubernetes_cluster.this.kube_config[0].host
client_certificate = base64decode(data.azurerm_kubernetes_cluster.this.kube_config[0].client_certificate)
client_key = base64decode(data.azurerm_kubernetes_cluster.this.kube_config[0].client_key)
cluster_ca_certificate = base64decode(data.azurerm_kubernetes_cluster.this.kube_config[0].cluster_ca_certificate)
}
module "synthetic_data" {
source = "oci://<Container_Registry_Path>/synthetic-data/synthetic-data-server/opentofu/synthetic-data?tag=azure-2.1.1"
cluster_name = var.cluster_name
oci_host = "<Container_Registry_Path>"
resource_group_name = var.resource_group_name
storage_account_name = var.storage_account_name
chart_version = var.chart_version
registry_auth_enabled = true
}
output "helm_install" {
value = module.synthetic_data.helm_install
}
output "helm_values" {
value = module.synthetic_data.helm_values
}
Run:
tofu init
tofu apply \
-var="cluster_name=<your-cluster-name>" \
-var="resource_group_name=<your-resource-group>" \
-var="storage_account_name=<globally-unique-storage-account>" \
-var="chart_version=2.1.1"
This creates the Azure Storage Account, Managed/Workload Identity resources, and syntheticdata-values.yaml.
Display both generated outputs:
tofu output
Module variables
| Variable | Required | Default | Description |
|---|---|---|---|
cluster_name | yes | - | EKS cluster name |
bucket_name | yes | - | S3 bucket name for model storage (must be globally unique across all AWS accounts) |
oci_host | no | <Container_Registry_Path> | OCI registry hostname Note: If deploying from the Protegrity Container Registry, use registry.protegrity.com:9443. Specify the local registry endpoint if a local registry is used. |
environment | no | production | Environment tag and S3 bucket prefix (staging or production) |
namespace | no | synthetic-data | Kubernetes namespace |
registry_type | no | artifactory | Protegrity container registry or Local registry |
chart_version | no | "" | Helm chart version. When set, tofu output -raw helm_install prints a ready-to-run command. |
karpenter.enabled | no | true | Create Karpenter NodePool + EC2NodeClass |
karpenter.node_class.ami_family | no | Bottlerocket | AMI family. Bottlerocket selects FIPS AMI automatically. |
karpenter.node_pool.instance_types | no | ["c5.large", ...] | EC2 instance types for Karpenter NodePool |
arch | no | amd64 | CPU architecture: amd64 |
fips | no | true | Use FIPS-validated Bottlerocket AMI. Set false to use the standard (non-FIPS) AMI. |
ami_id | no | "" | Explicit AMI ID override (highest priority). When set, bypasses both ami_family and fips selection. |
AMI selection priority:
| Priority | Condition | AMI Selected |
|---|---|---|
| 1 | ami_id is set | Exact AMI by ID (e.g. ami-0123456789abcdef0) |
| 2 | fips = true (default) | Latest bottlerocket-aws-k8s-<K8S_VER>-fips-<ARCH>-* |
| 3 | fips = false | Latest bottlerocket-aws-k8s-<K8S_VER>-<ARCH>-* |
Note: If you use
ami_id, theami_familyvalue must match the image that the AMI ID points to. The default value ofami_familyisBottlerocket.
Examples:
# Use a specific AMI (bypasses all auto-selection)
module "synthetic-data" {
source = "oci://..."
# ...
ami_id = "ami-0123456789abcdef0"
}
# Disable FIPS (use standard Bottlerocket AMI)
module "synthetic-data" {
source = "oci://..."
# ...
fips = false
}
| Variable | Required | Default | Description |
|---|---|---|---|
cluster_name | yes | - | AKS cluster name |
resource_group_name | yes | - | Azure resource group for the Managed Identity and Storage Account |
storage_account_name | yes | - | Azure Storage Account name (must be globally unique, 3-24 lowercase alphanumeric chars) |
environment | no | production | Environment tag and storage account name prefix |
namespace | no | synthetic-data | Kubernetes namespace |
oci_host | no | <Container_Registry_Path> | OCI registry hostname Note: If deploying from the Protegrity Container Registry, use registry.protegrity.com:9443. Specify the local registry endpoint if a local registry is used. |
registry_type | no | artifactory | Protegrity container registry or Local registry |
chart_version | no | "" | Helm chart version. When set, tofu output -raw helm_install prints a ready-to-run command. |
Note:
- Running
tofu planis optional. It lets you review the planned changes before they are applied.tofu output -raw helm_installprints a ready-to-run Helm command with the correct version and namespace.bucket_nameis a new S3 bucket name and it is created as part of this deployment.
Step 2 - Deploy with Helm
The OpenTofu module writes a syntheticdata-values.yaml file in your working directory.
Pass it to Helm with --values. Passwords are required on first install only - they are preserved automatically on subsequent upgrades.
Tip:
tofu output -raw helm_installprints a ready-to-run Helm command with the correct version and namespace pre-filled.
Note: If deploying from the Protegrity Container Registry, use
registry.protegrity.com:9443. Specify the local registry endpoint if a local registry is used. Ensureharbor-secretexists in thedefaultnamespace.
export MLOPS_PASSWORD=<your-mlops-password>
export JOBSTATE_PASSWORD=<your-jobstate-password>
helm upgrade --install synthetic-data \
oci://<Container_Registry_Path>/synthetic-data/synthetic-data-server/helm/synthetic-data \
--version 2.1.1 \
--namespace synthetic-data --create-namespace \
--values syntheticdata-values.yaml \
--set-string database.auth.mlopsPassword=$MLOPS_PASSWORD \
--set-string database.auth.jobstatePassword=$JOBSTATE_PASSWORD
On upgrade (passwords already stored in the cluster secret - omit --set):
helm upgrade synthetic-data \
oci://<Container_Registry_Path>/synthetic-data/synthetic-data-server/helm/synthetic-data \
--version <new-version> \
--namespace synthetic-data \
--values syntheticdata-values.yaml
To rotate a password during upgrade:
helm upgrade synthetic-data ... \
--set-string database.auth.mlopsPassword=$NEW_MLOPS_PASSWORD
For more information about the Python SDK, refer to Python SDK Reference.
Validate installation
Note: Before proceeding, ensure your
kubectlcontext is set to the target cluster tokubectl config current-context.
kubectl get pods -n synthetic-data # All pods should be Running
kubectl get statefulset -n synthetic-data # PostgreSQL, 1/1 ready
kubectl get deployment -n synthetic-data # App Deployment should have desired replicas ready
kubectl get hpa -n synthetic-data # Horizontal Pod Autoscaler status
kubectl get nodes -l synthetic-data.protegrity.com/deployment=true # AWS: Karpenter nodes (if enabled) should be Ready
kubectl get pods -n synthetic-data # All pods should be Running
kubectl get statefulset -n synthetic-data # PostgreSQL, 1/1 ready
kubectl get deployment -n synthetic-data # App Deployment should have desired replicas ready
kubectl get hpa -n synthetic-data # Horizontal Pod Autoscaler status
kubectl get nodes -l karpenter.sh/nodepool=synthetic-data-cpu # Azure: Karpenter nodes (if enabled) should be Ready
Standalone Helm Install (No OpenTofu)
Use this when cloud infrastructure already exists or is managed separately.
Step 1 - Verify prerequisites
# StorageClass
kubectl get storageclass ebs-sc # AWS
# Pod Identity Agent (AWS)
kubectl get daemonset -n kube-system eks-pod-identity-agent
# Karpenter NodePool (if using node isolation)
kubectl get nodepool synthetic-data-cpu
kubectl get ec2nodeclass synthetic-data-cpu
# StorageClass
kubectl get storageclass managed-csi-premium # Azure
kubectl get nodepool synthetic-data-cpu
kubectl get aksnodeclass synthetic-data-cpu
Step 2 - Create a values override file
AWS example (my-values.yaml):
cloudProvider: aws
serviceAccount:
name: synthetic-data
annotations:
eks.amazonaws.com/role-arn: "arn:aws:iam::<ACCOUNT_ID>:role/<ROLE_NAME>"
app:
config:
mlopsStorageDsn: "s3://<your-globally-unique-bucket-name>/synthetic-data/"
extraEnv:
- name: AWS_DEFAULT_REGION
value: us-east-1
- name: AWS_ENDPOINT_URL_S3
value: https://s3.us-east-1.amazonaws.com
database:
persistence:
storageClass: ebs-sc
size: 20Gi
karpenter:
enabled: true # set false if NOT using Karpenter isolation
Azure example (my-values.yaml):
cloudProvider: azure
serviceAccount:
name: synthetic-data
annotations:
azure.workload.identity/client-id: "<MANAGED_IDENTITY_CLIENT_ID>"
app:
podLabels:
azure.workload.identity/use: "true"
config:
mlopsStorageDsn: "azure://<storage_account>/<container>/synthetic-data/"
database:
persistence:
storageClass: managed-csi-premium
size: 20Gi
karpenter:
enabled: false
Step 3 - Install
Note: If deploying from the Protegrity Container Registry, use
registry.protegrity.com:9443. Specify the local registry endpoint if a local registry is used. Ensureharbor-secretexists in thedefaultnamespace.
export MLOPS_PASSWORD=<your-mlops-password>
export JOBSTATE_PASSWORD=<your-jobstate-password>
helm upgrade --install synthetic-data \
oci://<Container_Registry_Path>/synthetic-data/synthetic-data-server/helm/synthetic-data \
--version 2.1.1 \
--namespace synthetic-data --create-namespace \
--values my-values.yaml \
--set-string database.auth.mlopsPassword=$MLOPS_PASSWORD \
--set-string database.auth.jobstatePassword=$JOBSTATE_PASSWORD
Next Steps
For more information about the Python SDK, refer to Python SDK Reference.
If you encounter any error during or after installation, refer to Troubleshooting.
Feedback
Was this page helpful?