This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Installation

Prepare and install Anonymization on a supported Kubernetes cluster.

The installation process includes preparing the cluster, provisioning the required infrastructure with OpenTofu, deploying the umbrella Helm chart, and verifying the gateway and its bundled dependencies.

1 - Prerequisites

List of Prerequisites for Anonymization.

Ensure that all PPC prerequisites for AWS and PPC prerequisites for Azure are met.

Required Tools

ToolVersionNotes
OpenTofu>= 1.10.0Used to provision cloud resources
Helm>= 3.12Used to deploy the chart
kubectlanyRequired for validation; must be configured for the target cluster

AWS additionally requires:

ToolNotes
AWS CLIMust be configured with credentials that have EKS, IAM, and S3 permissions, and a default region set.

If there are any Permission denied errors when executing cloud CLI commands, refer to Appendix for required permissions per cloud.

Azure additionally requires:

ToolNotes
Azure CLIMust be logged in (az login) with permissions to create Managed Identities and Storage Accounts.

If there are any Permission denied errors when executing cloud CLI commands, refer to Appendix for required permissions per cloud.

Required cluster prerequisites

PrerequisiteDetails
Kubernetes >= 1.27EKS
StorageClassebs-sc (AWS) - verify: kubectl get storageclass
AWS — eks-pod-identity-agent addonDaemonSet running on each node
AWS — Karpenter >= 1.0Installed in karpenter namespace (if using node isolation)

StorageClass note: If your cluster uses different StorageClass names, override using --set database.persistence.storageClass=<name> during Helm install.

PrerequisiteDetails
Kubernetes >= 1.27AKS
StorageClassmanaged-csi-premium (Azure) - verify: kubectl get storageclass

StorageClass note: If your cluster uses different StorageClass names, override using --set database.persistence.storageClass=<name> during Helm install.

Configuration reference

Key values.yaml parameters

KeyDefaultDescription
cloudProvider""aws
database.auth.mlopsPassword""Required on first install
database.auth.jobstatePassword""Required on first install
database.auth.hostAuthMethodtrustPOSTGRES_HOST_AUTH_METHOD for PostgreSQL init
database.persistence.storageClass""Set per cloud: ebs-sc
database.persistence.size20GiPVC size
database.persistence.retentionPolicy.whenDeletedRetainKeep PVC on uninstall
karpenter.enabledtrueInject node affinity/tolerations for Karpenter nodes
anonapp.affinity{}Injected by OpenTofu when karpenter.enabled=true
anonapp.tolerations[]Injected by OpenTofu when karpenter.enabled=true
database.affinity{}Injected by OpenTofu when karpenter.enabled=true
database.tolerations[]Injected by OpenTofu when karpenter.enabled=true
dask.affinity{}Injected by OpenTofu when karpenter.enabled=true
dask.tolerations[]Injected by OpenTofu when karpenter.enabled=true
serviceaccount.nameanon-service-accountMust match Pod Identity association
KeyDefaultDescription
cloudProvider""azure
database.auth.mlopsPassword""Required on first install
database.auth.jobstatePassword""Required on first install
database.auth.hostAuthMethodtrustPOSTGRES_HOST_AUTH_METHOD for PostgreSQL init
database.persistence.storageClass""Set per cloud: managed-csi-premium
database.persistence.size20GiPVC size
database.persistence.retentionPolicy.whenDeletedRetainKeep PVC on uninstall
karpenter.enabledtrueInject node affinity/tolerations for Karpenter nodes
anonapp.affinity{}Injected by OpenTofu when karpenter.enabled=true
anonapp.tolerations[]Injected by OpenTofu when karpenter.enabled=true
database.affinity{}Injected by OpenTofu when karpenter.enabled=true
database.tolerations[]Injected by OpenTofu when karpenter.enabled=true
dask.affinity{}Injected by OpenTofu when karpenter.enabled=true
dask.tolerations[]Injected by OpenTofu when karpenter.enabled=true
serviceaccount.nameanon-service-accountMust match Pod Identity association

Appendix: Required cloud permissions

Required AWS permissions

If you encounter an AccessDenied error during installation, request the following permissions for your IAM user or role.

IAM
PermissionPurpose
iam:CreatePolicy / iam:DeletePolicy / iam:GetPolicyCreate and manage the S3 access policy
iam:CreateRole / iam:DeleteRole / iam:GetRoleCreate and manage the Pod Identity IAM role
iam:AttachRolePolicy / iam:DetachRolePolicyAttach the S3 policy to the role
EKS
PermissionPurpose
eks:DescribeClusterRead cluster details
eks:DescribeAddonVerify eks-pod-identity-agent is installed
eks:CreatePodIdentityAssociation / eks:DeletePodIdentityAssociation / eks:DescribePodIdentityAssociationAssociate the IAM role with the ServiceAccount
S3
PermissionPurpose
s3:CreateBucket / s3:DeleteBucketCreate and manage the models bucket
s3:PutBucketPolicy / s3:GetBucketPolicyApply bucket policy
s3:PutObject / s3:GetObject / s3:DeleteObjectRead/write model files

Required Azure permissions

If you encounter an AuthorizationFailed error during installation, request the following permissions.

PermissionPurpose
Microsoft.ManagedIdentity/userAssignedIdentities/writeCreate the Managed Identity
Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/writeCreate the Federated Identity Credential for Workload Identity
Microsoft.Storage/storageAccounts/writeCreate the Storage Account
Microsoft.Storage/storageAccounts/blobServices/containers/writeCreate the blob container for models
Microsoft.Authorization/roleAssignments/writeAssign Storage Blob Data Contributor role

2 - Install

Steps to install Protegrity Anonymization.

This project deploys the Anonymization service on Amazon EKS as part of the AI Team Edition.

Install order: prerequisites → OpenTofu infrastructure configuration → Helm deployment.

OCI registry authentication

OpenTofu OCI modules and Helm charts may require authentication. If the registry requires a login, authenticate before running tofu init or helm upgrade --install:

echo "<password>" | helm registry login <Container_Registry_Path> --username "<username>" --password-stdin

Note:

  • Set registry_auth_enabled = true for Protegrity container registry. Set it to false only 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 anonymization OpenTofu module provisions all cloud prerequisites and writes an anonymization-values.yaml file with cloud-specific Helm overrides.

AWS (EKS)

The module creates:

  • S3 bucket (name provided via bucket_name variable — must be globally unique)
  • IAM role + Pod Identity association → anon-service-account ServiceAccount
  • EC2NodeClass and NodePool (Bottlerocket FIPS, isolated nodes)
  • anonymization-values.yaml — Helm overrides file
Azure (AKS)

The module creates:

  • Storage Account + blob container for model storage
  • Managed Identity + Workload Identity federated credential → anon-service-account ServiceAccount
  • anonymization-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.

mkdir anon-install && cd anon-install
cat > main.tf <<'EOF'
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 "anonymization" {
  source = "oci://<Container_Registry_Path>/anonymization/anonymization-server/opentofu/anonymization?tag=aws-2.1.0"

  cluster_name          = var.cluster_name
  oci_host              = "<Container_Registry_Path>"
  bucket_name           = var.bucket_name
  chart_version         = var.chart_version
  registry_auth_enabled = true  # required for registry.protegrity.com; set false only for public/pre-authenticated registries
}

output "helm_install" { value = module.anonymization.helm_install }
output "helm_values" { value = module.anonymization.helm_values }
EOF

tofu init
tofu apply \
  -var="cluster_name=<your-cluster-name>" \
  -var="bucket_name=<globally-unique-bucket>" \
  -var="chart_version=2.1.0"

This writes anonymization-values.yaml (S3, IAM/Pod Identity, Karpenter node isolation, affinity/tolerations already filled in).

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.

mkdir anon-install && cd anon-install
cat > main.tf <<'EOF'
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 "anonymization" {
  source = "oci://<Container_Registry_Path>/anonymization/anonymization-server/opentofu/anonymization?tag=azure-2.1.0"

  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  # required for registry.protegrity.com; set false only for public/pre-authenticated registries
}

output "helm_install" { value = module.anonymization.helm_install }
output "helm_values" { value = module.anonymization.helm_values }
EOF

tofu init
tofu apply \
  -var="cluster_name=<cluster>" \
  -var="resource_group_name=<rg>" \
  -var="storage_account_name=<globally-unique-name>" \
  -var="chart_version=2.1.0"

This writes anonymization-values.yaml (Storage Account, Managed/Workload Identity, affinity/tolerations already filled in).

Display both generated outputs:

tofu output
Module variables
VariableRequiredDefaultDescription
cluster_nameyes—EKS cluster name
bucket_nameyes—S3 bucket name for model storage (must be globally unique across all AWS accounts)
oci_hostno<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.
environmentnoproductionEnvironment tag and S3 bucket prefix (staging or production)
namespacenoanon-nsKubernetes namespace
registry_typenoartifactoryProtegrity container registry or Local registry
chart_versionno""Helm chart version. When set, tofu output -raw helm_install prints a ready-to-run command.
karpenter.enablednotrueCreate Karpenter NodePool + EC2NodeClass
karpenter.node_class.ami_familynoBottlerocketAMI family. Bottlerocket selects FIPS AMI automatically.
karpenter.node_class.ami_idno""Explicit AMI ID override. When set, overrides ami_family-based selection.
karpenter.node_pool.instance_typesno["c5.large", ...]EC2 instance types for Karpenter NodePool
archnoamd64CPU architecture: amd64
fipsnotrueUse FIPS-validated Bottlerocket AMI. Set false to use the standard (non-FIPS) AMI.
ami_idno""Explicit AMI ID override (highest priority). When set, bypasses both ami_family and fips selection.

AMI selection priority:

PriorityConditionAMI Selected
1ami_id is setExact AMI by ID (e.g. ami-0123456789abcdef0)
2fips = true (default)Latest bottlerocket-aws-k8s-<K8S_VER>-fips-<ARCH>-*
3fips = falseLatest bottlerocket-aws-k8s-<K8S_VER>-<ARCH>-*

Note: If you use ami_id, the ami_family value must match the image that the AMI ID points to. The default value of ami_family is Bottlerocket.

Examples:

# Use a specific AMI (bypasses all auto-selection)
module "anonymization" {
  source = "oci://..."
  # ...
  ami_id = "ami-0123456789abcdef0"
}

# Disable FIPS (use standard Bottlerocket AMI)
module "anonymization" {
  source = "oci://..."
  # ...
  fips = false
}
VariableRequiredDefaultDescription
cluster_nameyes—AKS cluster name
resource_group_nameyes—Azure resource group for the Managed Identity and Storage Account
storage_account_nameyes—Azure Storage Account name (must be globally unique, 3-24 lowercase alphanumeric chars)
environmentnoproductionEnvironment tag and storage account name prefix
namespacenoanon-nsKubernetes namespace
oci_hostno<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_typenoartifactoryProtegrity container registry or Local registry
chart_versionno""Helm chart version. When set, tofu output -raw helm_install prints a ready-to-run command.
instance_typesno["Standard_D4as_v5", ...]VM instance types for NodePool

Note:

  • Running tofu plan is optional. It lets you review the planned changes before they are applied.
  • tofu output -raw helm_install prints a ready-to-run Helm command with the correct version and namespace.
  • bucket_name is a new S3 bucket name and it is created as part of this deployment.

Step2 - Deploy with Helm

The OpenTofu module writes an anonymization-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_install prints 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. Ensure harbor-secret exists in the default namespace.

export MLOPS_PASSWORD=<your-mlops-password>
export JOBSTATE_PASSWORD=<your-jobstate-password>

helm upgrade --install anonymization \
  oci://<Container_Registry_Path>/anonymization/anonymization-server/helm/anonymization \
  --version 2.1.0 \
  --namespace anon-ns --create-namespace \
  --values anonymization-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 anonymization \
  oci://<Container_Registry_Path>/anonymization/anonymization-server/helm/anonymization \
  --version <new-version> \
  --namespace anon-ns \
  --values anonymization-values.yaml

To rotate a password during upgrade:

helm upgrade anonymization ... \
  --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 kubectl context is set to the target cluster kubectl config current-context.

kubectl get pods -n anon-ns          # All pods should be Running
kubectl get statefulset -n anon-ns   # PostgreSQL, 1/1 ready
kubectl get deployment -n anon-ns    # app, dask-scheduler, dask-worker
kubectl get hpa -n anon-ns
kubectl get nodes -l anonymization.protegrity.com/deployment=true   # AWS: Karpenter nodes (if enabled) should be Ready.
kubectl get pods -n anon-ns          # All pods should be Running
kubectl get statefulset -n anon-ns   # PostgreSQL, 1/1 ready
kubectl get deployment -n anon-ns    # app, dask-scheduler, dask-worker
kubectl get hpa -n anon-ns

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 anonymization-cpu
kubectl get ec2nodeclass anonymization-cpu
# StorageClass
kubectl get storageclass managed-csi-premium  # Azure

kubectl get nodepool anonymization-cpu
kubectl get aksnodeclass anonymization-cpu
Step 2 - Create a values override file

AWS example (my-values.yaml):

cloudProvider: aws

serviceaccount:
  name: anon-service-account
  annotations:
    eks.amazonaws.com/role-arn: "arn:aws:iam::<ACCOUNT_ID>:role/<ROLE_NAME>"

storage:
  enabled: true
  bucketName: <your-globally-unique-bucket-name>
  region: us-east-1

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: anon-service-account
  annotations:
    azure.workload.identity/client-id: "<MANAGED_IDENTITY_CLIENT_ID>"

storage:
  enabled: true
  dsn: "abfss://models@<storage_account>.dfs.core.windows.net/"

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. Ensure harbor-secret exists in the default namespace.

export MLOPS_PASSWORD=<your-mlops-password>
export JOBSTATE_PASSWORD=<your-jobstate-password>

helm upgrade --install anonymization \
  oci://<Container_Registry_Path>/anonymization/anonymization-server/helm/anonymization \
  --version 2.1.0 \
  --namespace anon-ns --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.