Prerequisites
Jump box
PPC is deployed and managed from a dedicated EC2 instance, referred to as the jump box.
A newly provisioned EC2 instance must be used as the jump box for PPC deployment.
The jump box must be provisioned in the same AWS region where the PPC cluster is deployed. This ensures proper connectivity and access to regional resources.
Supported operating systems: RHEL 10, Debian 12, or Debian 13.
Note: Ensure to retain the original jump box used for installation. A snapshot of the jump box must be maintained to prevent data loss.
AWS Account Details
A valid AWS account where Amazon EKS is to be deployed.
The AWS account ID and AWS region must be identified in advance, as all resources are provisioned in the selected region.
Virtual Private Cloud (VPC)
- An existing VPC must be available in the target AWS region.
- The VPC should be configured to support Amazon EKS workloads.
Subnet Requirements
- At least two private subnets must be available.
- Subnets must be distributed across two or more Availability Zones (AZs).
Zone Requirements
The cluster requires a minimum of two availability zones for high availability. It is required to have two zones available while deploying a PPC.
| Zones | Supported | Notes |
|---|---|---|
| 1 | No | Installation fails. |
| 2 | Yes | Minimum requirement for High Availability. |
Zones are derived from the private subnets which are provided. Each subnet maps to exactly one availability zone. During the installation, the bootstrap script validates that the selected subnets are in different Availability Zones.
Note: Zones cannot be changed after cluster creation.
Network requirements for shared VPC
Before installing, confirm with the network team that the selected subnet AZ IDs are enabled on the Transit Gateway attachment and that the egress firewall allows the subnet CIDRs. At least two selected AZs must have working egress. For more information, refer to EKS system node group stuck in CREATING.
Service Quotas
Verify that the AWS account has sufficient service quotas to support the deployment. At a minimum, ensure adequate limits for the following:
- EC2 instances based on node group size and instance types.
- VPC and networking limits, including subnets, route tables, and security groups.
- Elastic IP addresses and Load balancers.
If required, request quota increases through the AWS Service Quotas console before proceeding.
Service Control Policies (SCPs)
The AWS account must not have SCPs that restrict required permissions. In particular, SCPs must not block the following actions:
- eks:*
- ec2:*
- iam:PassRole
Restrictive SCPs may prevent successful cluster creation and resource provisioning.
Required IAM roles and permissions
This section describes the IAM roles and permissions required to deploy and manage PPC on Amazon EKS. Review and set up these roles before starting the installation.
IAM Roles
Contact the IT team to create the necessary IAM roles with the following permissions to create and manage AWS EKS resources. The IAM role names in the table link to AWS documentation about each role, and the policy names link to the AWS managed policy reference pages.
| IAM Role | Required Policies |
|---|---|
| Amazon EKS cluster IAM Role Manages the Kubernetes cluster. | - AmazonEKSBlockStoragePolicy - AmazonEKSClusterPolicy - AmazonEKSComputePolicy - AmazonEKSLoadBalancingPolicy - AmazonEKSNetworkingPolicy - AmazonEKSVPCResourceController - AmazonEKSServicePolicy - AmazonEBSCSIDriverPolicy |
| Amazon EKS node IAM Role Communicates with the node. | - AmazonEBSCSIDriverPolicy - AmazonEC2ContainerRegistryReadOnly - AmazonEKS_CNI_Policy - AmazonEKSWorkerNodePolicy - AmazonSSMManagedInstanceCore |
These policies are managed by AWS. For more information about AWS managed policies, refer to AWS managed policies for Amazon Elastic Kubernetes Service in the AWS documentation.
AWS IAM Permissions
The AWS IAM user or role to install PPC must have permissions to create and manage Amazon EKS clusters and the required supporting AWS resources.
EC2 Permissions
| Category | Required Permissions |
|---|---|
| Networking & VPC | ec2:DescribeVpcs ec2:DescribeSubnets ec2:DescribeVpcAttribute ec2:DescribeTags ec2:DescribeNetworkInterfaces |
| Security Groups | ec2:DescribeSecurityGroups ec2:DescribeSecurityGroupRules ec2:CreateSecurityGroup ec2:DeleteSecurityGroup ec2:AuthorizeSecurityGroupIngress ec2:AuthorizeSecurityGroupEgress ec2:RevokeSecurityGroupIngress ec2:RevokeSecurityGroupEgress |
| Launch Templates | ec2:DescribeLaunchTemplates ec2:DescribeLaunchTemplateVersions ec2:CreateLaunchTemplate ec2:DeleteLaunchTemplate |
| Instances | ec2:RunInstances |
| Tagging | ec2:CreateTags ec2:DeleteTags |
EKS Permissions
| Category | Required Permissions |
|---|---|
| Cluster Management | eks:CreateCluster eks:DescribeCluster |
| Node Groups | eks:CreateNodegroup eks:DescribeNodegroup |
| Add-ons | eks:CreateAddon eks:DescribeAddon eks:DescribeAddonVersions eks:DeleteAddon eks:ListAddons |
| Pod Identity Associations | eks:CreatePodIdentityAssociation eks:DescribePodIdentityAssociation eks:DeletePodIdentityAssociation eks:ListPodIdentityAssociations |
| Tagging | eks:TagResource |
IAM Permissions
| Category | Required Permissions |
|---|---|
| Roles & Policies | iam:CreateRole iam:DeleteRole iam:TagRole iam:GetRole iam:ListRoles iam:AttachRolePolicy iam:DetachRolePolicy iam:ListRolePolicies iam:ListAttachedRolePolicies |
| Policies | iam:CreatePolicy iam:DeletePolicy iam:TagPolicy iam:GetPolicy iam:GetPolicyVersion iam:ListPolicyVersions |
| Instance Profiles | iam:CreateInstanceProfile iam:DeleteInstanceProfile iam:TagInstanceProfile iam:GetInstanceProfile iam:AddRoleToInstanceProfile iam:RemoveRoleFromInstanceProfile iam:ListInstanceProfilesForRole |
| Service-linked Role | iam:CreateServiceLinkedRole |
AWS S3 Permissions
| Required Permissions |
|---|
| s3:ListBucket |
| s3:PutEncryptionConfiguration |
| s3:GetEncryptionConfiguration |
| s3:PutBucketVersioning |
| s3:GetObjectTagging |
| s3:ListBucketVersions |
| s3:DeleteObjectVersion |
KMS Permissions
| Required Permissions |
|---|
| kms:CreateKey |
| kms:PutKeyPolicy |
| kms:GetKeyPolicy |
Applying the IAM Roles and Permissions using JSON
The roles and permissions are updated using the JSONs.
From the AWS Console, navigate to IAM > Policies > Create policy > JSON, and create the following JSONs.
Note: Before using the provided JSON, replace the
AWS_ACCOUNT_IDandREGIONvalues with those of the account and region where the resources are being deployed.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ReadOnlyAccess",
"Effect": "Allow",
"Action": [
"eks:DescribeClusterVersions",
"ec2:DescribeInstances",
"ec2:DescribeVolumes",
"s3:ListAllMyBuckets",
"iam:ListUsers",
"ec2:RunInstances",
"ec2:DescribeInstances",
"ec2:DescribeVolumes",
"ec2:CreateKeyPair",
"ec2:DescribeImages"
],
"Resource": "*"
},
{
"Sid": "ScopedS3AndKMS",
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:PutEncryptionConfiguration",
"s3:GetEncryptionConfiguration",
"kms:CreateKey",
"kms:PutKeyPolicy",
"kms:GetKeyPolicy"
],
"Resource": [
"arn:aws:s3:::*",
"arn:aws:kms:*:<AWS_ACCOUNT_ID>:key/*"
]
},
{
"Sid": "SelfServiceIAM",
"Effect": "Allow",
"Action": [
"iam:ListSSHPublicKeys",
"iam:ListServiceSpecificCredentials",
"iam:GetLoginProfile",
"iam:ListAccessKeys",
"iam:CreateAccessKey"
],
"Resource": "arn:aws:iam::<AWS_ACCOUNT_ID>:user/${aws:username}"
},
{
"Sid": "EC2KeyPairPermission",
"Effect": "Allow",
"Action": [
"ec2:CreateKeyPair",
"ec2:DescribeKeyPairs"
],
"Resource": [
"*"
]
}
]
}
- Creating EC2 Service Policy.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyEC2Instances",
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": "arn:aws:ec2:*:*:instance/*",
"Condition": {
"StringLike": {
"ec2:InstanceType": [
"p*",
"g*",
"inf*",
"trn*",
"x*",
"u-*",
"z*",
"mac*"
]
}
}
},
{
"Sid": "ReadOnlyDescribeListEC2RegionRestricted",
"Effect": "Allow",
"Action": [
"ec2:DescribeVpcs",
"ec2:DescribeSubnets",
"ec2:DescribeVpcAttribute",
"ec2:DescribeTags",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSecurityGroupRules",
"ec2:DescribeLaunchTemplates",
"ec2:DescribeLaunchTemplateVersions",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeAccountAttributes"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:RequestedRegion": [
"<REGION>"
]
}
}
},
{
"Sid": "EC2LifecycleAndSecurity",
"Effect": "Allow",
"Action": [
"ec2:CreateSecurityGroup",
"ec2:DeleteSecurityGroup",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:AuthorizeSecurityGroupEgress",
"ec2:RevokeSecurityGroupIngress",
"ec2:RevokeSecurityGroupEgress",
"ec2:CreateLaunchTemplate",
"ec2:DeleteLaunchTemplate",
"ec2:CreateTags",
"ec2:DeleteTags"
],
"Resource": [
"arn:aws:ec2:*:*:security-group/*",
"arn:aws:ec2:*:*:launch-template/*",
"arn:aws:ec2:*:*:instance/*",
"arn:aws:ec2:*:*:network-interface/*",
"arn:aws:ec2:*:*:subnet/*",
"arn:aws:ec2:*:*:vpc/*",
"arn:aws:ec2:*:*:image/*",
"arn:aws:ec2:*:*:volume/*",
"arn:aws:ec2:*:*:snapshot/*"
]
}
]
}
- Creating EKS Service Policy.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ReadOnlyDescribeListEKSVersionsRegionRestricted",
"Effect": "Allow",
"Action": [
"eks:DescribeAddonVersions"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:RequestedRegion": [
"<REGION>"
]
}
}
},
{
"Sid": "ReadOnlyDescribeListEKS",
"Effect": "Allow",
"Action": [
"eks:DescribeCluster",
"eks:DescribeAddon",
"eks:DescribePodIdentityAssociation",
"eks:DescribeNodegroup",
"eks:ListAddons",
"eks:ListPodIdentityAssociations"
],
"Resource": [
"arn:aws:eks:*:<AWS_ACCOUNT_ID>:cluster/*",
"arn:aws:eks:*:<AWS_ACCOUNT_ID>:nodegroup/*",
"arn:aws:eks:*:<AWS_ACCOUNT_ID>:addon/*",
"arn:aws:eks:*:<AWS_ACCOUNT_ID>:podidentityassociation/*"
]
},
{
"Sid": "EKSLifecycleAndTag",
"Effect": "Allow",
"Action": [
"eks:CreateCluster",
"eks:UpdateClusterVersion",
"eks:UpdateClusterConfig",
"eks:CreateNodegroup",
"eks:UpdateNodegroupConfig",
"eks:UpdateNodegroupVersion",
"eks:DeleteNodegroup",
"eks:CreateAddon",
"eks:UpdateAddon",
"eks:DeleteAddon",
"eks:CreatePodIdentityAssociation",
"eks:DeletePodIdentityAssociation",
"eks:TagResource",
"eks:ListClusters"
],
"Resource": [
"arn:aws:eks:*:<AWS_ACCOUNT_ID>:cluster/*",
"arn:aws:eks:*:<AWS_ACCOUNT_ID>:nodegroup/*",
"arn:aws:eks:*:<AWS_ACCOUNT_ID>:addon/*",
"arn:aws:eks:*:<AWS_ACCOUNT_ID>:podidentityassociation/*"
]
},
{
"Sid": "AllowEKSNodegroupSLR",
"Effect": "Allow",
"Action": [
"iam:GetRole",
"iam:CreateServiceLinkedRole"
],
"Resource": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/aws-service-role/eks-nodegroup.amazonaws.com/AWSServiceRoleForAmazonEKSNodegroup"
},
{
"Sid": "EKSDeleteClusterV6",
"Effect": "Allow",
"Action": "eks:DeleteCluster",
"Resource": "arn:aws:eks:*:<AWS_ACCOUNT_ID>:cluster/*"
}
]
}
- Creating IAM Service Policy.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyAdminPolicyAttachment",
"Effect": "Deny",
"Action": [
"iam:AttachRolePolicy",
"iam:PutRolePolicy"
],
"Resource": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/eks-*",
"Condition": {
"ArnLike": {
"iam:PolicyARN": [
"arn:aws:iam::aws:policy/AdministratorAccess",
"arn:aws:iam::aws:policy/PowerUserAccess",
"arn:aws:iam::aws:policy/*FullAccess"
]
}
}
},
{
"Sid": "DenyInlinePolicyEscalation",
"Effect": "Deny",
"Action": [
"iam:PutRolePolicy",
"iam:PutUserPolicy",
"iam:PutGroupPolicy"
],
"Resource": "*"
},
{
"Sid": "ReadOnlyDescribeListIAMScoped",
"Effect": "Allow",
"Action": [
"iam:GetRole",
"iam:ListRolePolicies",
"iam:ListAttachedRolePolicies",
"iam:ListInstanceProfilesForRole",
"iam:GetInstanceProfile",
"iam:GetPolicy",
"iam:GetPolicyVersion",
"iam:ListPolicyVersions",
"iam:ListAccessKeys"
],
"Resource": [
"arn:aws:iam::<AWS_ACCOUNT_ID>:role/eks-*",
"arn:aws:iam::<AWS_ACCOUNT_ID>:instance-profile/eks-*",
"arn:aws:iam::<AWS_ACCOUNT_ID>:policy/eks-*"
]
},
{
"Sid": "ReadOnlyDescribeListUnavoidableStar",
"Effect": "Allow",
"Action": "iam:ListRoles",
"Resource": "*"
},
{
"Sid": "IAMLifecycleRolesPoliciesInstanceProfiles",
"Effect": "Allow",
"Action": [
"iam:CreateRole",
"iam:TagRole",
"iam:CreatePolicy",
"iam:DeletePolicy",
"iam:DeletePolicyVersion",
"iam:TagPolicy",
"iam:AttachRolePolicy",
"iam:DetachRolePolicy",
"iam:CreateInstanceProfile",
"iam:TagInstanceProfile",
"iam:AddRoleToInstanceProfile",
"iam:RemoveRoleFromInstanceProfile",
"iam:DeleteInstanceProfile"
],
"Resource": [
"arn:aws:iam::<AWS_ACCOUNT_ID>:role/eks-*",
"arn:aws:iam::<AWS_ACCOUNT_ID>:policy/eks-*",
"arn:aws:iam::<AWS_ACCOUNT_ID>:instance-profile/eks-*"
]
},
{
"Sid": "EKSDeleteRoles",
"Effect": "Allow",
"Action": "iam:DeleteRole",
"Resource": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/eks*"
},
{
"Sid": "PassRoleOnlyToEKS",
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/eks-*",
"Condition": {
"StringEquals": {
"iam:PassedToService": [
"eks.amazonaws.com",
"ec2.amazonaws.com",
"eks-pods.amazonaws.com",
"pods.eks.amazonaws.com"
]
}
}
},
{
"Sid": "PassRoleForEKSPodIdentityRoles",
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": [
"arn:aws:iam::<AWS_ACCOUNT_ID>:role/eks-*-karpenter-role",
"arn:aws:iam::<AWS_ACCOUNT_ID>:role/eks-*-backup-recovery-utility-role"
]
}
]
}
- Creating KMS Service Policy.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "KMSCreateAndList",
"Effect": "Allow",
"Action": [
"kms:CreateKey",
"kms:ListAliases"
],
"Resource": "*"
},
{
"Sid": "KMSKeyManagementScoped",
"Effect": "Allow",
"Action": [
"kms:PutKeyPolicy",
"kms:GetKeyPolicy",
"kms:DescribeKey",
"kms:GenerateDataKey",
"kms:Decrypt",
"kms:TagResource",
"kms:UntagResource",
"kms:EnableKeyRotation",
"kms:GetKeyRotationStatus",
"kms:ListResourceTags",
"kms:ScheduleKeyDeletion",
"kms:CreateAlias",
"kms:DeleteAlias"
],
"Resource": [
"arn:aws:kms:*:<AWS_ACCOUNT_ID>:key/*",
"arn:aws:kms:*:<AWS_ACCOUNT_ID>:alias/*"
]
}
]
}
- Creating AWS S3 Service Policy.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "S3EncryptionConfigAndStateScoped",
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetEncryptionConfiguration",
"s3:PutEncryptionConfiguration",
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:CreateBucket",
"s3:GetBucketTagging",
"s3:GetBucketPolicy",
"s3:GetBucketAcl",
"s3:GetBucketCORS",
"s3:PutBucketTagging",
"s3:GetBucketWebsite",
"s3:GetBucketVersioning",
"s3:GetAccelerateConfiguration",
"s3:GetBucketRequestPayment",
"s3:GetBucketLogging",
"s3:GetLifecycleConfiguration",
"s3:GetReplicationConfiguration",
"s3:GetBucketObjectLockConfiguration",
"s3:DeleteBucket",
"s3:PutBucketVersioning",
"s3:ListBucketVersions",
"s3:DeleteObjectVersion",
"s3:GetObjectTagging"
],
"Resource": "arn:aws:s3:::*",
"Condition": {
"StringEquals": {
"aws:RequestedRegion": [
"<REGION>"
],
"aws:PrincipalAccount": "<AWS_ACCOUNT_ID>"
}
}
}
]
}
Creating AWS KMS Key and AWS S3 Bucket
Amazon S3 Bucket: An Amazon S3 bucket is required to store critical data such as backups, configuration artifacts, and restore metadata used during installation and recovery workflows. Using a dedicated AWS S3 bucket helps ensure data durability, isolation, and controlled access during cluster operations.
AWS KMS Key: An AWS KMS customer‑managed key is required to encrypt data stored in the AWS S3 bucket. This ensures that sensitive data is protected at rest and allows customers to manage encryption policies, key rotation, and access control in accordance with their security requirements.
Note: The KMS key must allow access to the IAM roles used by the EKS cluster and related services.
The following section explains how to create AWS KMS Key and AWS S3 Bucket. This can be done from the AWS Web UI or using the script.
- Create a KMS key for backup bucket.
The KMS key created is referenced during installation and restore using its KMS ARN, and is validated by the installer.
Before you begin, ensure to have:
Access to the AWS account where the KMS key is created.
The KMS key can be in the same AWS account as the AWS S3 bucket, or in a different, cross‑account AWS account.
The user running the installer must have the permission
kms:DescribeKeyto describe the KMS key. If this permission is unavailable, then installation and restore fails.
The steps to create a KMS key are available at https://docs.aws.amazon.com/. Follow the KMS key creation steps, but ensure to select the following configurations.
On the Key configuration page:
Select Key type as Symmetric.
Select Key usage as Encrypt and decrypt.These settings are required for encrypting and decrypting AWS S3 objects used by backup and restore operations.
On the Key Administrative Permissions page, select the users or roles that can manage the key. The key administrators do not automatically get permission to encrypt or decrypt data unless these permissions are explicitly granted.
On the Define key usage permissions page, grant permissions to the principals that will use the key.
The user or role running the installation and restore must have the permission
kms:DescribeKeyto describe the key. This permission is mandatory because the installer validates the KMS key before proceeding. Without this, the installation or restore procedure fails, especially in cross‑account KMS scenarios.On the Edit key policy - optional page, click Edit.
The KMS key policy controls the access to the encryption key and must be applied before creating the AWS S3 bucket.
If you are using AWS SSO IAM Identity Center, ensure that the IAM role ARN specified in the KMS key policy includes the full SSO path prefix:
aws-reserved/sso.amazonaws.com/.
For example:arn:aws:iam::<ACCOUNT_ID>:role/aws-reserved/sso.amazonaws.com/<SSO_ROLE_NAME>
Omitting this path results in KMS key policy creation failures with anInvalidArnException.
The following example shows a key policy that:
Allows the PPC bootstrap user to use the KMS key for cluster creation and backup operations.
Allows the IAM role to encrypt and decrypt EKS backups.
cat > kms-key-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Id": "key-resource-policy-0",
"Statement": [
{
"Sid": "Allow KMS administrative actions only, no key usage permissions.",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<<ADMIN_AWS_ACCOUNT>>:root"
},
"Action": [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "Allow user running bootstrap.sh script of the PPC to use the KMS key.",
"Effect": "Allow",
"Principal": {
"AWS": "<<SSO_OR_IAM_USER_ACCOUNT_ARN>>"
},
"Action": [
"kms:DescribeKey",
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncryptFrom",
"kms:ReEncryptTo",
"kms:GenerateDataKey",
"kms:GenerateDataKeyWithoutPlaintext"
],
"Resource": "*"
},
{
"Sid": "Allow backup recovery utility and EKS Node roles KMS key usage permissions, Replace <<<<CLUSTER_NAME>>>> with the name of your EKS cluster.",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<<DEPLOYMENT_AWS_ACCOUNT>>:root"
},
"Action": [
"kms:Decrypt",
"kms:Encrypt",
"kms:ReEncryptFrom",
"kms:ReEncryptTo",
"kms:GenerateDataKey",
"kms:GenerateDataKeyWithoutPlaintext",
"kms:GenerateDataKeyPair",
"kms:GenerateDataKeyPairWithoutPlaintext",
"kms:DescribeKey"
],
"Resource": "*",
"Condition": {
"ArnLike": {
"aws:PrincipalArn": [
"arn:aws:iam::<<DEPLOYMENT_AWS_ACCOUNT>>:role/eks-<<CLUSTER_NAME>>-backup-recovery-utility-role",
"arn:aws:iam::<<DEPLOYMENT_AWS_ACCOUNT>>:role/eks-<<CLUSTER_NAME>>-node-role"
]
}
}
}
]
}
EOF
Update the values of the following based on the environment:
DEPLOYMENT_AWS_ACCOUNT- AWS account ID.CLUSTER_NAME- EKS cluster name.SSO_OR_IAM_USER_ACCOUNT_ARN- ARN of the IAM role used to run the bootstrap script. The ARN format depends on your authentication method:IAM role – Use the ARN returned by
aws sts get-caller-identity.AWS SSO (IAM Identity Center) – Convert the session ARN returned by
aws sts get-caller-identityto a full IAM role ARN before using it in the KMS key policy.If you are using AWS SSO (IAM Identity Center), the ARN returned by
aws sts get-caller-identityis a session ARN and cannot be used directly in an AWS KMS key policy. AWS KMS requires the full IAM role ARN, including theaws-reserved/sso.amazonaws.com/path. Without this, KMS key policy creation fails withInvalidArnException.
Retrieving the IAM role ARN for KMS key policy
To identify the role used to run the bootstrap script, run the following command:
aws sts get-caller-identity --query Arn --output text
IAM role: Use the returned ARN directly.
arn:aws:iam::<DEPLOYMENT_AWS_ACCOUNT>:role/your-role-nameAWS SSO (IAM Identity Center): The command returns a session ARN, which must be converted.
Do not use the session ARN:
arn:aws:sts::<<DEPLOYMENT_AWS_ACCOUNT>>:assumed-role/AWSReservedSSO_PermissionSetName_abc123/john.doe@company.comUse this converted IAM role ARN in KMS policy:
arn:aws:iam::<<DEPLOYMENT_AWS_ACCOUNT>>:role/aws-reserved/sso.amazonaws.com/AWSReservedSSO_PermissionSetName_abc123To convert:
- Replace
arn:aws:sts::witharn:aws:iam::. - Replace
assumed-role/withrole/aws-reserved/sso.amazonaws.com/. - Remove the session suffix (everything after the last /).
- Replace
Important: Before initiating restore operation, review and update the KMS key policy to reflect the restore
CLUSTER_NAME. Even if the policy was already configured for the source cluster, it must be updated for the new restore cluster. If the policy continues to reference the source cluster name, the IAM role created during restore cannot decrypt the backup data, causing the restore to fail.
After the KMS key is created, note the KMS key ARN. This KMS key ARN is required while creating the AWS S3 backup bucket.
- Create an AWS S3 Bucket encrypted with SSE‑KMS
The AWS S3 bucket encrypted with SSE‑KMS is used as a backup bucket during installation and restore.
Before you begin, ensure to have:
Access to the AWS account where the AWS S3 bucket will be created.
Permission to create AWS S3 bucket.
The user running the installer must have permission to describe the KMS key. Without this permission, installation and restore fails.
The steps to create an AWS S3 bucket are available at https://docs.aws.amazon.com/. Follow the AWS S3 bucket creation steps, but ensure to set the following configurations as mentioned below.
In the Default Encryption section:
Select Encryption type as Server-side encryption with AWS Key Management Service keys (SSE-KMS).
Select the AWS KMS key ARN. If the KMS key is in a different AWS account than the AWS S3 bucket, then the key will not appear in the AWS console dropdown. In this case, enter the KMS key ARN manually.
Enable Bucket Key.
Automatic AWS KMS Key and S3 Bucket Provisioning
When deploying PPC using the bootstrap script, the AWS S3 bucket and KMS key can be provisioned automatically during the installation process, without any separate pre-installation steps.
During the bootstrap script execution, at step 5, you are prompted to choose how to provide the AWS S3 bucket for cluster backups:
Do you want to use an existing AWS S3 bucket, or provision a new one (with KMS key)?
1) Use existing
2) Provision new via Tofu (backup-infra)
Select Option 2 - Provision new via Tofu to have the bootstrap script automatically:
- Create a new AWS KMS key.
- Create a new AWS S3 bucket encrypted with SSE-KMS.
- Associate the AWS S3 bucket with the KMS key.
At step 6, when prompted, provide a globally unique bucket name using the following naming rules:
- Lowercase letters, digits, and hyphens only.
- Between 3 and 63 characters.
- Must not already exist.
Note: The AWS S3 bucket and KMS key are created in the same AWS account using this option. For cross-account KMS configurations, follow the steps in the Using AWS Web UI tab.
Use a dedicated AWS S3 bucket per cluster for backup and restore operations to ensure data and encryption isolation. Sharing a bucket across clusters increases the risk of cross-cluster data access or decryption due to IAM misconfiguration.
Blocking Public Access to the AWS S3 Bucket
The PPC bootstrap script does not configure AWS S3 Block Public Access at the per-bucket level. This is by design because many AWS Organizations enforce AWS S3 Block Public Access through Service Control Policies (SCPs) at the account or organization level. This causes per-bucket s3:PutBucketPublicAccessBlock calls to fail with AccessDenied. AWS enabled S3 Block Public Access by default for all new accounts created after April 2023. However, verify the settings manually before proceeding.
Warning: The AWS S3 backup bucket stores highly sensitive data. Ensure that AWS S3 Block Public Access is enforced at the AWS account or organization level to prevent accidental public exposure.
Verify that AWS S3 Block Public Access is enabled at the account level before deploying PPC:
Navigate to the Amazon AWS S3 console.
Click Account and organization settings from the left navigation.
Ensure all four settings are enabled and set to On:
- Block public access to buckets and objects granted through new access control lists (ACLs)
- Block public access to buckets and objects granted through any access control lists (ACLs)
- Block public access to buckets and objects granted through new public bucket or access point policies
- Block public and cross-account access to buckets and objects through any public bucket or access point policies
If it is set to Off, then click Edit, select the check boxes, and click Save changes.
Verify that the Block Public Access settings for this account are enabled using the following command:
aws s3control get-public-access-block --account-id $(aws sts get-caller-identity --query Account --output text)All four fields
BlockPublicAcls,IgnorePublicAcls,BlockPublicPolicy,RestrictPublicBucketsshould be set totrue.
Note: To block the permissions at the bucket level, navigate to Buckets > General purpose buckets > select the bucket > Permissions > Block public access (bucket settings).
Installing or upgrading PPC in a region that does not support secure Bottlerocket AMIs
The service endpoints and the secure Bottlerocket AMI are available in a limited set of AWS regions. Regions such as eu-west-2 (London) do not offer secure endpoints for the AWS services that PPC depends on, and the secure Bottlerocket AMI is not published in every region.
To determine whether your target region supports secure Bottlerocket AMIs, use the following references:
Secure endpoints and services by region. Refer to AWS Regional Services List in the AWS official documentation for the current list of regions with secure endpoints and the services in scope.
Secure Bottlerocket AMI availability. Verify that the SSM parameter
/aws/service/bottlerocket/aws-k8s-<eks-version>-fips/<arch>/latest/image_idresolves in the target region:aws ssm get-parameter \ --region <region> \ --name "/aws/service/bottlerocket/aws-k8s-<eks-version>-fips/<arch>/latest/image_id"If the command returns
ParameterNotFound, the secure Bottlerocket AMI is not published in that region.
If secure Bottlerocket AMIs are not supported in the target region, use the standard deployment or upgrade path:
- To install PPC in a region that does not support secure Bottlerocket AMIs, refer to Configuring for a Standard Deployment in the respective section of Deploying PPC.
- To upgrade PPC in a region that does not support secure Bottlerocket AMIs, refer to Using Standard Bottlerocket AMI Deployment in the automated upgrade procedure.
Readiness check
The readiness check script validates the AWS credentials and confirms that the IAM permissions required to install PPC are available. If any required permission is missing, the script reports it and exits.
Navigate to the bootstrap-scripts directory and run the following script:
./readiness-aws.sh
After the readiness check is completed successfully, ensure to run the following checks for the selected region and architecture.
Supported Resources
While installing a cluster, the nodes are provisioned in two ways, that is, a managed node group and Karpenter. Therefore, both must be validated for the selected architecture.
Node pools overview
| Node pool | Provisioned by | Purpose |
|---|---|---|
| System pool | Managed node group | Critical add-ons only (Karpenter, CoreDNS) |
| Application pool | Karpenter | Application workloads |
System pool — default instance type
| Architecture | Default instance type |
|---|---|
| amd64 | t3.medium (2 vCPU / 4 GiB) |
| arm64 | t4g.medium (2 vCPU / 4 GiB) |
Application pool (Karpenter) — default instance type
| Architecture | Default family | Default instance type |
|---|---|---|
| amd64 | t3 | t3.2xlarge (8 vCPU / 32 GiB) |
| arm64 | t4g | t4g.2xlarge (8 vCPU / 32 GiB) |
Application pool (Karpenter) — Supported instance families
| Architecture | Supported instance families |
|---|---|
| amd64 | m5, m6i, c5, r5, t3, t3a |
| arm64 | t4g |
Availability Zones
Each instance type must be validated individually and must be available in at least 2 availability zones.
To verify the number of available availability zones on each instance type, run the following command:
REGION="<enter-your-region>" # e.g. us-east-1
INSTANCE_TYPE="<enter-instance-type>" # e.g. t3.2xlarge
aws ec2 describe-instance-type-offerings \
--region "$REGION" \
--location-type availability-zone \
--filters "Name=instance-type,Values=${INSTANCE_TYPE}" \
--query "InstanceTypeOfferings[].Location" --output table
For successfully validating the availability zones, the following output must be verified.Pass = the output lists 2 or more Availability Zones.
Validating IAM and SCP
The access to launch nodes in the required IAM and SCP is available.
To verify the required IAM and SCP access, run the following command:
REGION="<enter-your-region>" # e.g. us-east-1
ARCH="<enter-architecture>" # x86_64 for amd64, arm64 for arm64
INSTANCE_TYPE="<enter-instance-type>" # e.g. t3.2xlarge
SUBNET_ID="<enter-subnet-id>" # a private subnet in the target AZ
# Resolve a valid AMI id (public SSM parameter)
AMI_ID=$(aws ssm get-parameter --region "$REGION" \
--name "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-${ARCH}" \
--query 'Parameter.Value' --output text)
# Resolve a security group from the subnet's VPC
VPC_ID=$(aws ec2 describe-subnets --region "$REGION" \
--subnet-ids "$SUBNET_ID" --query 'Subnets[0].VpcId' --output text)
SG_ID=$(aws ec2 describe-security-groups --region "$REGION" \
--filters "Name=vpc-id,Values=$VPC_ID" \
--query 'SecurityGroups[0].GroupId' --output text)
# Dry-run launch (nothing is created)
aws ec2 run-instances --dry-run \
--region "$REGION" \
--instance-type "$INSTANCE_TYPE" \
--image-id "$AMI_ID" \
--subnet-id "$SUBNET_ID" \
--security-group-ids "$SG_ID"
After successful validation, a DryRunOperation: Request would have succeeded, but DryRun flag is set. message appears.
If the script fails with the UnauthorizedOperation message, then it might be blocked by IAM or an SCP.Fix the IAM or SCP, and then run the script for each subnet or AZ and instance type.
EC2 On-Demand vCPU service quota
The instance is within the EC2 On-Demand vCPU service quota for the required node count.
To verify the EC2 On-Demand vCPU service quota, run the following command:
REGION="<enter-your-region>" # e.g. us-east-1
# Quota L-1216C47A = Running On-Demand Standard (A,C,D,H,I,M,R,T,Z) instances
aws service-quotas get-service-quota \
--service-code ec2 --quota-code L-1216C47A \
--region "$REGION" --query 'Quota.Value' --output text
Note: PPC requires 28–32 vCPUs with the default node sizing. Ensure this capacity is available in addition to current account usage. Additionally, verify the available headroom in the AWS Service Quotas console and request a quota increase if required.
Feedback
Was this page helpful?