In OpenShift Container Platform version 4.7, you can install a cluster on Amazon Web Services (AWS) using infrastructure that you provide and an internal mirror of the installation release content.

While you can install an OpenShift Container Platform cluster by using mirrored installation release content, your cluster still requires Internet access to use the AWS APIs.

One way to create this infrastructure is to use the provided CloudFormation templates. You can modify the templates to customize your infrastructure or use the information that they contain to create AWS objects according to your company’s policies.

The steps for performing a user-provisioned infrastructure installation are provided as an example only. Installing a cluster with infrastructure you provide requires knowledge of the cloud provider and the installation process of OpenShift Container Platform. Several CloudFormation templates are provided to assist in completing these steps or to help model your own. You are also free to create the required resources through other methods; the templates are just an example.

Prerequisites

About installations in restricted networks

In OpenShift Container Platform 4.7, you can perform an installation that does not require an active connection to the Internet to obtain software components. Restricted network installations can be completed using installer-provisioned infrastructure or user-provisioned infrastructure, depending on the cloud platform to which you are installing the cluster.

If you choose to perform a restricted network installation on a cloud platform, you still require access to its cloud APIs. Some cloud functions, like Amazon Web Service’s IAM service, require Internet access, so you might still require Internet access. Depending on your network, you might require less Internet access for an installation on bare metal hardware or on VMware vSphere.

To complete a restricted network installation, you must create a registry that mirrors the contents of the OpenShift Container Platform registry and contains the installation media. You can create this registry on a mirror host, which can access both the Internet and your closed network, or by using other methods that meet your restrictions.

Because of the complexity of the configuration for user-provisioned installations, consider completing a standard user-provisioned infrastructure installation before you attempt a restricted network installation using user-provisioned infrastructure. Completing this test installation might make it easier to isolate and troubleshoot any issues that might arise during your installation in a restricted network.

Additional limits

Clusters in restricted networks have the following additional limitations and restrictions:

  • The ClusterVersion status includes an Unable to retrieve available updates error.

  • By default, you cannot use the contents of the Developer Catalog because you cannot access the required image stream tags.

Internet access for OpenShift Container Platform

In OpenShift Container Platform 4.7, you require access to the Internet to obtain the images that are necessary to install your cluster.

You must have Internet access to:

  • Access the Red Hat OpenShift Cluster Manager page to download the installation program and perform subscription management. If the cluster has Internet access and you do not disable Telemetry, that service automatically entitles your cluster.

  • Access Quay.io to obtain the packages that are required to install your cluster.

  • Obtain the packages that are required to perform cluster updates.

If your cluster cannot have direct Internet access, you can perform a restricted network installation on some types of infrastructure that you provision. During that process, you download the content that is required and use it to populate a mirror registry with the packages that you need to install a cluster and generate the installation program. With some installation types, the environment that you install your cluster in will not require Internet access. Before you update the cluster, you update the content of the mirror registry.

Required AWS infrastructure components

To install OpenShift Container Platform on user-provisioned infrastructure in Amazon Web Services (AWS), you must manually create both the machines and their supporting infrastructure.

For more information about the integration testing for different platforms, see the OpenShift Container Platform 4.x Tested Integrations page.

By using the provided CloudFormation templates, you can create stacks of AWS resources that represent the following components:

  • An AWS Virtual Private Cloud (VPC)

  • Networking and load balancing components

  • Security groups and roles

  • An OpenShift Container Platform bootstrap node

  • OpenShift Container Platform control plane nodes

  • An OpenShift Container Platform compute node

Alternatively, you can manually create the components or you can reuse existing infrastructure that meets the cluster requirements. Review the CloudFormation templates for more details about how the components interrelate.

Certificate signing requests management

Because your cluster has limited access to automatic machine management when you use infrastructure that you provision, you must provide a mechanism for approving cluster certificate signing requests (CSRs) after installation. The kube-controller-manager only approves the kubelet client CSRs. The machine-approver cannot guarantee the validity of a serving certificate that is requested by using kubelet credentials because it cannot confirm that the correct machine issued the request. You must determine and implement a method of verifying the validity of the kubelet serving certificate requests and approving them.

Other infrastructure components

  • A VPC

  • DNS entries

  • Load balancers (classic or network) and listeners

  • A public and a private Route 53 zone

  • Security groups

  • IAM roles

  • S3 buckets

If you are working in a disconnected environment or use a proxy, you cannot reach the public IP addresses for EC2 and ELB endpoints. To reach these endpoints, you must create a VPC endpoint and attach it to the subnet that the clusters are using. Create the following endpoints:

  • ec2.<region>.amazonaws.com

  • elasticloadbalancing.<region>.amazonaws.com

  • s3.<region>.amazonaws.com

Required VPC components

You must provide a suitable VPC and subnets that allow communication to your machines.

Component AWS type Description

VPC

  • AWS::EC2::VPC

  • AWS::EC2::VPCEndpoint

You must provide a public VPC for the cluster to use. The VPC uses an endpoint that references the route tables for each subnet to improve communication with the registry that is hosted in S3.

Public subnets

  • AWS::EC2::Subnet

  • AWS::EC2::SubnetNetworkAclAssociation

Your VPC must have public subnets for between 1 and 3 availability zones and associate them with appropriate Ingress rules.

Internet gateway

  • AWS::EC2::InternetGateway

  • AWS::EC2::VPCGatewayAttachment

  • AWS::EC2::RouteTable

  • AWS::EC2::Route

  • AWS::EC2::SubnetRouteTableAssociation

  • AWS::EC2::NatGateway

  • AWS::EC2::EIP

You must have a public Internet gateway, with public routes, attached to the VPC. In the provided templates, each public subnet has a NAT gateway with an EIP address. These NAT gateways allow cluster resources, like private subnet instances, to reach the Internet and are not required for some restricted network or proxy scenarios.

Network access control

  • AWS::EC2::NetworkAcl

  • AWS::EC2::NetworkAclEntry

You must allow the VPC to access the following ports:

Port

Reason

80

Inbound HTTP traffic

443

Inbound HTTPS traffic

22

Inbound SSH traffic

1024 - 65535

Inbound ephemeral traffic

0 - 65535

Outbound ephemeral traffic

Private subnets

  • AWS::EC2::Subnet

  • AWS::EC2::RouteTable

  • AWS::EC2::SubnetRouteTableAssociation

Your VPC can have private subnets. The provided CloudFormation templates can create private subnets for between 1 and 3 availability zones. If you use private subnets, you must provide appropriate routes and tables for them.

Required DNS and load balancing components

Your DNS and load balancer configuration needs to use a public hosted zone and can use a private hosted zone similar to the one that the installation program uses if it provisions the cluster’s infrastructure. You must create a DNS entry that resolves to your load balancer. An entry for api.<cluster_name>.<domain> must point to the external load balancer, and an entry for api-int.<cluster_name>.<domain> must point to the internal load balancer.

The cluster also requires load balancers and listeners for port 6443, which are required for the Kubernetes API and its extensions, and port 22623, which are required for the Ignition config files for new machines. The targets will be the control plane nodes (also known as the master nodes). Port 6443 must be accessible to both clients external to the cluster and nodes within the cluster. Port 22623 must be accessible to nodes within the cluster.

Component AWS type Description

DNS

AWS::Route53::HostedZone

The hosted zone for your internal DNS.

etcd record sets

AWS::Route53::RecordSet

The registration records for etcd for your control plane machines.

Public load balancer

AWS::ElasticLoadBalancingV2::LoadBalancer

The load balancer for your public subnets.

External API server record

AWS::Route53::RecordSetGroup

Alias records for the external API server.

External listener

AWS::ElasticLoadBalancingV2::Listener

A listener on port 6443 for the external load balancer.

External target group

AWS::ElasticLoadBalancingV2::TargetGroup

The target group for the external load balancer.

Private load balancer

AWS::ElasticLoadBalancingV2::LoadBalancer

The load balancer for your private subnets.

Internal API server record

AWS::Route53::RecordSetGroup

Alias records for the internal API server.

Internal listener

AWS::ElasticLoadBalancingV2::Listener

A listener on port 22623 for the internal load balancer.

Internal target group

AWS::ElasticLoadBalancingV2::TargetGroup

The target group for the internal load balancer.

Internal listener

AWS::ElasticLoadBalancingV2::Listener

A listener on port 6443 for the internal load balancer.

Internal target group

AWS::ElasticLoadBalancingV2::TargetGroup

The target group for the internal load balancer.

Security groups

The control plane and worker machines require access to the following ports:

Group Type IP Protocol Port range

MasterSecurityGroup

AWS::EC2::SecurityGroup

icmp

0

tcp

22

tcp

6443

tcp

22623

WorkerSecurityGroup

AWS::EC2::SecurityGroup

icmp

0

tcp

22

BootstrapSecurityGroup

AWS::EC2::SecurityGroup

tcp

22

tcp

19531

Control plane Ingress

The control plane machines require the following Ingress groups. Each Ingress group is a AWS::EC2::SecurityGroupIngress resource.

Ingress group Description IP protocol Port range

MasterIngressEtcd

etcd

tcp

2379- 2380

MasterIngressVxlan

Vxlan packets

udp

4789

MasterIngressWorkerVxlan

Vxlan packets

udp

4789

MasterIngressInternal

Internal cluster communication and Kubernetes proxy metrics

tcp

9000 - 9999

MasterIngressWorkerInternal

Internal cluster communication

tcp

9000 - 9999

MasterIngressKube

Kubernetes kubelet, scheduler and controller manager

tcp

10250 - 10259

MasterIngressWorkerKube

Kubernetes kubelet, scheduler and controller manager

tcp

10250 - 10259

MasterIngressIngressServices

Kubernetes Ingress services

tcp

30000 - 32767

MasterIngressWorkerIngressServices

Kubernetes Ingress services

tcp

30000 - 32767

Worker Ingress

The worker machines require the following Ingress groups. Each Ingress group is a AWS::EC2::SecurityGroupIngress resource.

Ingress group Description IP protocol Port range

WorkerIngressVxlan

Vxlan packets

udp

4789

WorkerIngressWorkerVxlan

Vxlan packets

udp

4789

WorkerIngressInternal

Internal cluster communication

tcp

9000 - 9999

WorkerIngressWorkerInternal

Internal cluster communication

tcp

9000 - 9999

WorkerIngressKube

Kubernetes kubelet, scheduler, and controller manager

tcp

10250

WorkerIngressWorkerKube

Kubernetes kubelet, scheduler, and controller manager

tcp

10250

WorkerIngressIngressServices

Kubernetes Ingress services

tcp

30000 - 32767

WorkerIngressWorkerIngressServices

Kubernetes Ingress services

tcp

30000 - 32767

Roles and instance profiles

You must grant the machines permissions in AWS. The provided CloudFormation templates grant the machines Allow permissions for the following AWS::IAM::Role objects and provide a AWS::IAM::InstanceProfile for each set of roles. If you do not use the templates, you can grant the machines the following broad permissions or the following individual permissions.

Role Effect Action Resource

Master

Allow

ec2:*

*

Allow

elasticloadbalancing:*

*

Allow

iam:PassRole

*

Allow

s3:GetObject

*

Worker

Allow

ec2:Describe*

*

Bootstrap

Allow

ec2:Describe*

*

Allow

ec2:AttachVolume

*

Allow

ec2:DetachVolume

*

Cluster machines

You need AWS::EC2::Instance objects for the following machines:

  • A bootstrap machine. This machine is required during installation, but you can remove it after your cluster deploys.

  • Three control plane machines. The control plane machines are not governed by a machine set.

  • Compute machines. You must create at least two compute machines, which are also known as worker machines, during installation. These machines are not governed by a machine set.

Supported AWS machine types

The following Amazon Web Services (AWS) instance types are supported with OpenShift Container Platform.

Instance types for machines
Instance type Bootstrap Control plane Compute

i3.large

x

m4.large

x

m4.xlarge

x

x

m4.2xlarge

x

x

m4.4xlarge

x

x

m4.10xlarge

x

x

m4.16xlarge

x

x

m5.large

x

m5.xlarge

x

x

m5.2xlarge

x

x

m5.4xlarge

x

x

m5.8xlarge

x

x

m5.12xlarge

x

x

m5.16xlarge

x

x

m5a.large

x

m5a.xlarge

x

x

m5a.2xlarge

x

x

m5a.4xlarge

x

x

m5a.8xlarge

x

x

m5a.10xlarge

x

x

m5a.16xlarge

x

x

c4.large

x

c4.xlarge

x

c4.2xlarge

x

x

c4.4xlarge

x

x

c4.8xlarge

x

x

c5.large

x

c5.xlarge

x

c5.2xlarge

x

x

c5.4xlarge

x

x

c5.9xlarge

x

x

c5.12xlarge

x

x

c5.18xlarge

x

x

c5.24xlarge

x

x

c5a.large

x

c5a.xlarge

x

c5a.2xlarge

x

x

c5a.4xlarge

x

x

c5a.8xlarge

x

x

c5a.12xlarge

x

x

c5a.16xlarge

x

x

c5a.24xlarge

x

x

r4.large

x

r4.xlarge

x

x

r4.2xlarge

x

x

r4.4xlarge

x

x

r4.8xlarge

x

x

r4.16xlarge

x

x

r5.large

x

r5.xlarge

x

x

r5.2xlarge

x

x

r5.4xlarge

x

x

r5.8xlarge

x

x

r5.12xlarge

x

x

r5.16xlarge

x

x

r5.24xlarge

x

x

r5a.large

x

r5a.xlarge

x

x

r5a.2xlarge

x

x

r5a.4xlarge

x

x

r5a.8xlarge

x

x

r5a.12xlarge

x

x

r5a.16xlarge

x

x

r5a.24xlarge

x

x

t3.large

x

t3.xlarge

x

t3.2xlarge

x

t3a.large

x

t3a.xlarge

x

t3a.2xlarge

x

Required AWS permissions for the IAM user

When you attach the AdministratorAccess policy to the IAM user that you create in Amazon Web Services (AWS), you grant that user all of the required permissions. To deploy all components of an OpenShift Container Platform cluster, the IAM user requires the following permissions:

Required EC2 permissions for installation
  • ec2:AuthorizeSecurityGroupEgress

  • ec2:AuthorizeSecurityGroupIngress

  • ec2:CopyImage

  • ec2:CreateNetworkInterface

  • ec2:AttachNetworkInterface

  • ec2:CreateSecurityGroup

  • ec2:CreateTags

  • ec2:CreateVolume

  • ec2:DeleteSecurityGroup

  • ec2:DeleteSnapshot

  • ec2:DeleteTags

  • ec2:DeregisterImage

  • ec2:DescribeAccountAttributes

  • ec2:DescribeAddresses

  • ec2:DescribeAvailabilityZones

  • ec2:DescribeDhcpOptions

  • ec2:DescribeImages

  • ec2:DescribeInstanceAttribute

  • ec2:DescribeInstanceCreditSpecifications

  • ec2:DescribeInstances

  • ec2:DescribeInstanceTypes

  • ec2:DescribeInternetGateways

  • ec2:DescribeKeyPairs

  • ec2:DescribeNatGateways

  • ec2:DescribeNetworkAcls

  • ec2:DescribeNetworkInterfaces

  • ec2:DescribePrefixLists

  • ec2:DescribeRegions

  • ec2:DescribeRouteTables

  • ec2:DescribeSecurityGroups

  • ec2:DescribeSubnets

  • ec2:DescribeTags

  • ec2:DescribeVolumes

  • ec2:DescribeVpcAttribute

  • ec2:DescribeVpcClassicLink

  • ec2:DescribeVpcClassicLinkDnsSupport

  • ec2:DescribeVpcEndpoints

  • ec2:DescribeVpcs

  • ec2:GetEbsDefaultKmsKeyId

  • ec2:ModifyInstanceAttribute

  • ec2:ModifyNetworkInterfaceAttribute

  • ec2:RevokeSecurityGroupEgress

  • ec2:RevokeSecurityGroupIngress

  • ec2:RunInstances

  • ec2:TerminateInstances

Required permissions for creating network resources during installation
  • ec2:AllocateAddress

  • ec2:AssociateAddress

  • ec2:AssociateDhcpOptions

  • ec2:AssociateRouteTable

  • ec2:AttachInternetGateway

  • ec2:CreateDhcpOptions

  • ec2:CreateInternetGateway

  • ec2:CreateNatGateway

  • ec2:CreateRoute

  • ec2:CreateRouteTable

  • ec2:CreateSubnet

  • ec2:CreateVpc

  • ec2:CreateVpcEndpoint

  • ec2:ModifySubnetAttribute

  • ec2:ModifyVpcAttribute

If you use an existing VPC, your account does not require these permissions for creating network resources.

Required Elastic Load Balancing permissions for installation
  • elasticloadbalancing:AddTags

  • elasticloadbalancing:ApplySecurityGroupsToLoadBalancer

  • elasticloadbalancing:AttachLoadBalancerToSubnets

  • elasticloadbalancing:ConfigureHealthCheck

  • elasticloadbalancing:CreateListener

  • elasticloadbalancing:CreateLoadBalancer

  • elasticloadbalancing:CreateLoadBalancerListeners

  • elasticloadbalancing:CreateTargetGroup

  • elasticloadbalancing:DeleteLoadBalancer

  • elasticloadbalancing:DeregisterInstancesFromLoadBalancer

  • elasticloadbalancing:DeregisterTargets

  • elasticloadbalancing:DescribeInstanceHealth

  • elasticloadbalancing:DescribeListeners

  • elasticloadbalancing:DescribeLoadBalancerAttributes

  • elasticloadbalancing:DescribeLoadBalancers

  • elasticloadbalancing:DescribeTags

  • elasticloadbalancing:DescribeTargetGroupAttributes

  • elasticloadbalancing:DescribeTargetHealth

  • elasticloadbalancing:ModifyLoadBalancerAttributes

  • elasticloadbalancing:ModifyTargetGroup

  • elasticloadbalancing:ModifyTargetGroupAttributes

  • elasticloadbalancing:RegisterInstancesWithLoadBalancer

  • elasticloadbalancing:RegisterTargets

  • elasticloadbalancing:SetLoadBalancerPoliciesOfListener

Required IAM permissions for installation
  • iam:AddRoleToInstanceProfile

  • iam:CreateInstanceProfile

  • iam:CreateRole

  • iam:DeleteInstanceProfile

  • iam:DeleteRole

  • iam:DeleteRolePolicy

  • iam:GetInstanceProfile

  • iam:GetRole

  • iam:GetRolePolicy

  • iam:GetUser

  • iam:ListInstanceProfilesForRole

  • iam:ListRoles

  • iam:ListUsers

  • iam:PassRole

  • iam:PutRolePolicy

  • iam:RemoveRoleFromInstanceProfile

  • iam:SimulatePrincipalPolicy

  • iam:TagRole

If you have not created an elastic load balancer (ELB) in your AWS account, the IAM user also requires the iam:CreateServiceLinkedRole permission.

Required Route 53 permissions for installation
  • route53:ChangeResourceRecordSets

  • route53:ChangeTagsForResource

  • route53:CreateHostedZone

  • route53:DeleteHostedZone

  • route53:GetChange

  • route53:GetHostedZone

  • route53:ListHostedZones

  • route53:ListHostedZonesByName

  • route53:ListResourceRecordSets

  • route53:ListTagsForResource

  • route53:UpdateHostedZoneComment

Required S3 permissions for installation
  • s3:CreateBucket

  • s3:DeleteBucket

  • s3:GetAccelerateConfiguration

  • s3:GetBucketAcl

  • s3:GetBucketCors

  • s3:GetBucketLocation

  • s3:GetBucketLogging

  • s3:GetBucketObjectLockConfiguration

  • s3:GetBucketReplication

  • s3:GetBucketRequestPayment

  • s3:GetBucketTagging

  • s3:GetBucketVersioning

  • s3:GetBucketWebsite

  • s3:GetEncryptionConfiguration

  • s3:GetLifecycleConfiguration

  • s3:GetReplicationConfiguration

  • s3:ListBucket

  • s3:PutBucketAcl

  • s3:PutBucketTagging

  • s3:PutEncryptionConfiguration

S3 permissions that cluster Operators require
  • s3:DeleteObject

  • s3:GetObject

  • s3:GetObjectAcl

  • s3:GetObjectTagging

  • s3:GetObjectVersion

  • s3:PutObject

  • s3:PutObjectAcl

  • s3:PutObjectTagging

Required permissions to delete base cluster resources
  • autoscaling:DescribeAutoScalingGroups

  • ec2:DeleteNetworkInterface

  • ec2:DeleteVolume

  • elasticloadbalancing:DeleteTargetGroup

  • elasticloadbalancing:DescribeTargetGroups

  • iam:DeleteAccessKey

  • iam:DeleteUser

  • iam:ListAttachedRolePolicies

  • iam:ListInstanceProfiles

  • iam:ListRolePolicies

  • iam:ListUserPolicies

  • s3:DeleteObject

  • s3:ListBucketVersions

  • tag:GetResources

Required permissions to delete network resources
  • ec2:DeleteDhcpOptions

  • ec2:DeleteInternetGateway

  • ec2:DeleteNatGateway

  • ec2:DeleteRoute

  • ec2:DeleteRouteTable

  • ec2:DeleteSubnet

  • ec2:DeleteVpc

  • ec2:DeleteVpcEndpoints

  • ec2:DetachInternetGateway

  • ec2:DisassociateRouteTable

  • ec2:ReleaseAddress

  • ec2:ReplaceRouteTableAssociation

If you use an existing VPC, your account does not require these permissions to delete network resources. Instead, your account only requires the tag:UntagResources permission to delete network resources.

Required permissions to delete a cluster with shared instance roles
  • iam:UntagRole

Additional IAM and S3 permissions that are required to create manifests
  • iam:DeleteAccessKey

  • iam:DeleteUser

  • iam:DeleteUserPolicy

  • iam:GetUserPolicy

  • iam:ListAccessKeys

  • iam:PutUserPolicy

  • iam:TagUser

  • iam:GetUserPolicy

  • iam:ListAccessKeys

  • s3:PutBucketPublicAccessBlock

  • s3:GetBucketPublicAccessBlock

  • s3:PutLifecycleConfiguration

  • s3:HeadBucket

  • s3:ListBucketMultipartUploads

  • s3:AbortMultipartUpload

If you are managing your cloud provider credentials with mint mode, the IAM user also requires the iam:CreateAccessKey and iam:CreateUser permissions.

Optional permissions for instance and quota checks for installation
  • ec2:DescribeInstanceTypeOfferings

  • servicequotas:ListAWSDefaultServiceQuotas

Generating an SSH private key and adding it to the agent

If you want to perform installation debugging or disaster recovery on your cluster, you must provide an SSH key to both your ssh-agent and the installation program. You can use this key to access the bootstrap machine in a public cluster to troubleshoot installation issues.

In a production environment, you require disaster recovery and debugging.

You can use this key to SSH into the master nodes as the user core. When you deploy the cluster, the key is added to the core user’s ~/.ssh/authorized_keys list.

You must use a local key, not one that you configured with platform-specific approaches such as AWS key pairs.

Procedure
  1. If you do not have an SSH key that is configured for password-less authentication on your computer, create one. For example, on a computer that uses a Linux operating system, run the following command:

    $ ssh-keygen -t ed25519 -N '' \
        -f <path>/<file_name> (1)
    1 Specify the path and file name, such as ~/.ssh/id_rsa, of the new SSH key. If you have an existing key pair, ensure your public key is in the your ~/.ssh directory.

    Running this command generates an SSH key that does not require a password in the location that you specified.

    If you plan to install an OpenShift Container Platform cluster that uses FIPS Validated / Modules in Process cryptographic libraries on the x86_64 architecture, do not create a key that uses the ed25519 algorithm. Instead, create a key that uses the rsa or ecdsa algorithm.

  2. Start the ssh-agent process as a background task:

    $ eval "$(ssh-agent -s)"
    Example output
    Agent pid 31874

    If your cluster is in FIPS mode, only use FIPS-compliant algorithms to generate the SSH key. The key must be either RSA or ECDSA.

  3. Add your SSH private key to the ssh-agent:

    $ ssh-add <path>/<file_name> (1)
    Example output
    Identity added: /home/<you>/<path>/<file_name> (<computer_name>)
    1 Specify the path and file name for your SSH private key, such as ~/.ssh/id_rsa
Next steps
  • When you install OpenShift Container Platform, provide the SSH public key to the installation program. If you install a cluster on infrastructure that you provision, you must provide this key to your cluster’s machines.

Creating the installation files for AWS

To install OpenShift Container Platform on Amazon Web Services (AWS) using user-provisioned infrastructure, you must generate the files that the installation program needs to deploy your cluster and modify them so that the cluster creates only the machines that it will use. You generate and customize the install-config.yaml file, Kubernetes manifests, and Ignition config files. You also have the option to first set up a separate var partition during the preparation phases of installation.

Optional: Creating a separate /var partition

It is recommended that disk partitioning for OpenShift Container Platform be left to the installer. However, there are cases where you might want to create separate partitions in a part of the filesystem that you expect to grow.

OpenShift Container Platform supports the addition of a single partition to attach storage to either the /var partition or a subdirectory of /var. For example:

  • /var/lib/containers: Holds container-related content that can grow as more images and containers are added to a system.

  • /var/lib/etcd: Holds data that you might want to keep separate for purposes such as performance optimization of etcd storage.

  • /var: Holds data that you might want to keep separate for purposes such as auditing.

Storing the contents of a /var directory separately makes it easier to grow storage for those areas as needed and reinstall OpenShift Container Platform at a later date and keep that data intact. With this method, you will not have to pull all your containers again, nor will you have to copy massive log files when you update systems.

Because /var must be in place before a fresh installation of Red Hat Enterprise Linux CoreOS (RHCOS), the following procedure sets up the separate /var partition by creating a machine config that is inserted during the openshift-install preparation phases of an OpenShift Container Platform installation.

If you follow the steps to create a separate /var partition in this procedure, it is not necessary to create the Kubernetes manifest and Ignition config files again as described later in this section.

Prerequisites
  • If container storage is on the root partition, ensure that this root partition is mounted with the pquota option by including rootflags=pquota in the GRUB command line.

  • If the container storage is on a partition that is mounted by /etc/fstab, ensure that the following mount option is included in the /etc/fstab file:

    /dev/sdb1      /var           xfs defaults,pquota 0 0
  • If the container storage is on a partition that is mounted by systemd, ensure that the MachineConfig object includes the following mount option as in this example:

    spec:
      config:
        ignition:
          version: 3.2.0
        storage:
          disks:
            - device: /dev/sdb
              partitions:
                - label: var
                  sizeMiB: 240000
                  startMiB: 0
          filesystems:
            - device: /dev/disk/by-partlabel/var
              format: xfs
              path: /var
        systemd:
          units:
            - contents: |
                [Unit]
                Before=local-fs.target
                [Mount]
                Where=/var
                What=/dev/disk/by-partlabel/var
                Options=defaults,pquota
                [Install]
                WantedBy=local-fs.target
              enabled: true
              name: var.mount
Procedure
  1. Create a directory to hold the OpenShift Container Platform installation files:

    $ mkdir $HOME/clusterconfig
  2. Run openshift-install to create a set of files in the manifest and openshift subdirectories. Answer the system questions as you are prompted:

    $ openshift-install create manifests --dir $HOME/clusterconfig
    Example output
    ? SSH Public Key ...
    INFO Credentials loaded from the "myprofile" profile in file "/home/myuser/.aws/credentials"
    INFO Consuming Install Config from target directory
    INFO Manifests created in: $HOME/clusterconfig/manifests and $HOME/clusterconfig/openshift
  3. Optional: Confirm that the installation program created manifests in the clusterconfig/openshift directory:

    $ ls $HOME/clusterconfig/openshift/
    Example output
    99_kubeadmin-password-secret.yaml
    99_openshift-cluster-api_master-machines-0.yaml
    99_openshift-cluster-api_master-machines-1.yaml
    99_openshift-cluster-api_master-machines-2.yaml
    ...
  4. Create a MachineConfig object and add it to a file in the openshift directory. For example, name the file 98-var-partition.yaml, change the disk device name to the name of the storage device on the worker systems, and set the storage size as appropriate. This attaches storage to a separate /var directory.

    apiVersion: machineconfiguration.openshift.io/v1
    kind: MachineConfig
    metadata:
      labels:
        machineconfiguration.openshift.io/role: worker
      name: 98-var-partition
    spec:
      config:
        ignition:
          version: 3.2.0
        storage:
          disks:
          - device: /dev/<device_name> (1)
            partitions:
            - sizeMiB: <partition_size>
              startMiB: <partition_start_offset> (2)
              label: var
          filesystems:
            - path: /var
              device: /dev/disk/by-partlabel/var
              format: xfs
        systemd:
          units:
            - name: var.mount
              enabled: true
              contents: |
                [Unit]
                Before=local-fs.target
                [Mount]
                Where=/var
                What=/dev/disk/by-partlabel/var
                [Install]
                WantedBy=local-fs.target
    1 The storage device name of the disk that you want to partition.
    2 When adding a data partition to the boot disk, a minimum value of 25000 MiB (Mebibytes) is recommended. The root file system is automatically resized to fill all available space up to the specified offset. If no value is specified, or if the specified value is smaller than the recommended minimum, the resulting root file system will be too small, and future reinstalls of RHCOS might overwrite the beginning of the data partition.
  5. Run openshift-install again to create Ignition configs from a set of files in the manifest and openshift subdirectories:

    $ openshift-install create ignition-configs --dir $HOME/clusterconfig
    $ ls $HOME/clusterconfig/
    auth  bootstrap.ign  master.ign  metadata.json  worker.ign

Now you can use the Ignition config files as input to the installation procedures to install Red Hat Enterprise Linux CoreOS (RHCOS) systems.

Creating the installation configuration file

Generate and customize the installation configuration file that the installation program needs to deploy your cluster.

Prerequisites
  • You obtained the OpenShift Container Platform installation program for user-provisioned infrastructure and the pull secret for your cluster. For a restricted network installation, these files are on your mirror host.

  • You checked that you are deploying your cluster to a region with an accompanying Red Hat Enterprise Linux CoreOS (RHCOS) AMI published by Red Hat. If you are deploying to a region that requires a custom AMI, such as an AWS GovCloud region, you must create the install-config.yaml file manually.

Procedure
  1. Create the install-config.yaml file.

    1. Change to the directory that contains the installation program and run the following command:

      $ ./openshift-install create install-config --dir=<installation_directory> (1)
      1 For <installation_directory>, specify the directory name to store the files that the installation program creates.

      Specify an empty directory. Some installation assets, like bootstrap X.509 certificates have short expiration intervals, so you must not reuse an installation directory. If you want to reuse individual files from another cluster installation, you can copy them into your directory. However, the file names for the installation assets might change between releases. Use caution when copying installation files from an earlier OpenShift Container Platform version.

    2. At the prompts, provide the configuration details for your cloud:

      1. Optional: Select an SSH key to use to access your cluster machines.

        For production OpenShift Container Platform clusters on which you want to perform installation debugging or disaster recovery, specify an SSH key that your ssh-agent process uses.

      2. Select aws as the platform to target.

      3. If you do not have an AWS profile stored on your computer, enter the AWS access key ID and secret access key for the user that you configured to run the installation program.

        The AWS access key ID and secret access key are stored in ~/.aws/credentials in the home directory of the current user on the installation host. You are prompted for the credentials by the installation program if the credentials for the exported profile are not present in the file. Any credentials that you provide to the installation program are stored in the file.

      4. Select the AWS region to deploy the cluster to.

      5. Select the base domain for the Route 53 service that you configured for your cluster.

      6. Enter a descriptive name for your cluster.

      7. Paste the pull secret that you obtained from the Pull Secret page on the Red Hat OpenShift Cluster Manager site.

  2. Edit the install-config.yaml file to provide the additional information that is required for an installation in a restricted network.

    1. Update the pullSecret value to contain the authentication information for your registry:

      pullSecret: '{"auths":{"<local_registry>": {"auth": "<credentials>","email": "you@example.com"}}}'

      For <local_registry>, specify the registry domain name, and optionally the port, that your mirror registry uses to serve content. For example registry.example.com or registry.example.com:5000. For <credentials>, specify the base64-encoded user name and password for your mirror registry.

    2. Add the additionalTrustBundle parameter and value. The value must be the contents of the certificate file that you used for your mirror registry, which can be an existing, trusted certificate authority or the self-signed certificate that you generated for the mirror registry.

      additionalTrustBundle: |
        -----BEGIN CERTIFICATE-----
        ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
        -----END CERTIFICATE-----
    3. Add the image content resources:

      imageContentSources:
      - mirrors:
        - <local_registry>/<local_repository_name>/release
        source: quay.io/openshift-release-dev/ocp-release
      - mirrors:
        - <local_registry>/<local_repository_name>/release
        source: quay.io/openshift-release-dev/ocp-v4.0-art-dev

      Use the imageContentSources section from the output of the command to mirror the repository or the values that you used when you mirrored the content from the media that you brought into your restricted network.

    4. Optional: Set the publishing strategy to Internal:

      publish: Internal

      By setting this option, you create an internal Ingress Controller and a private load balancer.

  3. Optional: Back up the install-config.yaml file.

    The install-config.yaml file is consumed during the installation process. If you want to reuse the file, you must back it up now.

Additional resources

Configuring the cluster-wide proxy during installation

Production environments can deny direct access to the Internet and instead have an HTTP or HTTPS proxy available. You can configure a new OpenShift Container Platform cluster to use a proxy by configuring the proxy settings in the install-config.yaml file.

Prerequisites
  • You have an existing install-config.yaml file.

  • You reviewed the sites that your cluster requires access to and determined whether any of them need to bypass the proxy. By default, all cluster egress traffic is proxied, including calls to hosting cloud provider APIs. You added sites to the Proxy object’s spec.noProxy field to bypass the proxy if necessary.

    The Proxy object status.noProxy field is populated with the values of the networking.machineNetwork[].cidr, networking.clusterNetwork[].cidr, and networking.serviceNetwork[] fields from your installation configuration.

    For installations on Amazon Web Services (AWS), Google Cloud Platform (GCP), Microsoft Azure, and Red Hat OpenStack Platform (RHOSP), the Proxy object status.noProxy field is also populated with the instance metadata endpoint (169.254.169.254).

  • If your cluster is on AWS, you added the ec2.<region>.amazonaws.com, elasticloadbalancing.<region>.amazonaws.com, and s3.<region>.amazonaws.com endpoints to your VPC endpoint. These endpoints are required to complete requests from the nodes to the AWS EC2 API. Because the proxy works on the container level, not the node level, you must route these requests to the AWS EC2 API through the AWS private network. Adding the public IP address of the EC2 API to your allowlist in your proxy server is not sufficient.

Procedure
  1. Edit your install-config.yaml file and add the proxy settings. For example:

    apiVersion: v1
    baseDomain: my.domain.com
    proxy:
      httpProxy: http://<username>:<pswd>@<ip>:<port> (1)
      httpsProxy: https://<username>:<pswd>@<ip>:<port> (2)
      noProxy: example.com (3)
    additionalTrustBundle: | (4)
        -----BEGIN CERTIFICATE-----
        <MY_TRUSTED_CA_CERT>
        -----END CERTIFICATE-----
    ...
    1 A proxy URL to use for creating HTTP connections outside the cluster. The URL scheme must be http. If you use an MITM transparent proxy network that does not require additional proxy configuration but requires additional CAs, you must not specify an httpProxy value.
    2 A proxy URL to use for creating HTTPS connections outside the cluster. If you use an MITM transparent proxy network that does not require additional proxy configuration but requires additional CAs, you must not specify an httpsProxy value.
    3 A comma-separated list of destination domain names, domains, IP addresses, or other network CIDRs to exclude proxying. Preface a domain with . to match subdomains only. For example, .y.com matches x.y.com, but not y.com. Use * to bypass proxy for all destinations.
    4 If provided, the installation program generates a config map that is named user-ca-bundle in the openshift-config namespace that contains one or more additional CA certificates that are required for proxying HTTPS connections. The Cluster Network Operator then creates a trusted-ca-bundle config map that merges these contents with the Red Hat Enterprise Linux CoreOS (RHCOS) trust bundle, and this config map is referenced in the Proxy object’s trustedCA field. The additionalTrustBundle field is required unless the proxy’s identity certificate is signed by an authority from the RHCOS trust bundle. If you use an MITM transparent proxy network that does not require additional proxy configuration but requires additional CAs, you must provide the MITM CA certificate.

    The installation program does not support the proxy readinessEndpoints field.

  2. Save the file and reference it when installing OpenShift Container Platform.

The installation program creates a cluster-wide proxy that is named cluster that uses the proxy settings in the provided install-config.yaml file. If no proxy settings are provided, a cluster Proxy object is still created, but it will have a nil spec.

Only the Proxy object named cluster is supported, and no additional proxies can be created.

Creating the Kubernetes manifest and Ignition config files

Because you must modify some cluster definition files and manually start the cluster machines, you must generate the Kubernetes manifest and Ignition config files that the cluster needs to make its machines.

The installation configuration file transforms into the Kubernetes manifests. The manifests wrap into the Ignition configuration files, which are later used to create the cluster.

The Ignition config files that the installation program generates contain certificates that expire after 24 hours, which are then renewed at that time. If the cluster is shut down before renewing the certificates and the cluster is later restarted after the 24 hours have elapsed, the cluster automatically recovers the expired certificates. The exception is that you must manually approve the pending node-bootstrapper certificate signing requests (CSRs) to recover kubelet certificates. See the documentation for Recovering from expired control plane certificates for more information.

Prerequisites
  • You obtained the OpenShift Container Platform installation program. For a restricted network installation, these files are on your mirror host.

  • You created the install-config.yaml installation configuration file.

Procedure
  1. Change to the directory that contains the installation program and generate the Kubernetes manifests for the cluster:

    $ ./openshift-install create manifests --dir=<installation_directory> (1)
    Example output
    INFO Credentials loaded from the "myprofile" profile in file "/home/myuser/.aws/credentials"
    INFO Consuming Install Config from target directory
    INFO Manifests created in: install_dir/manifests and install_dir/openshift
    1 For <installation_directory>, specify the installation directory that contains the install-config.yaml file you created.
  2. Remove the Kubernetes manifest files that define the control plane machines:

    $ rm -f <installation_directory>/openshift/99_openshift-cluster-api_master-machines-*.yaml

    By removing these files, you prevent the cluster from automatically generating control plane machines.

  3. Remove the Kubernetes manifest files that define the worker machines:

    $ rm -f <installation_directory>/openshift/99_openshift-cluster-api_worker-machineset-*.yaml

    Because you create and manage the worker machines yourself, you do not need to initialize these machines.

  4. Check that the mastersSchedulable parameter in the <installation_directory>/manifests/cluster-scheduler-02-config.yml Kubernetes manifest file is set to false. This setting prevents pods from being scheduled on the control plane machines:

    1. Open the <installation_directory>/manifests/cluster-scheduler-02-config.yml file.

    2. Locate the mastersSchedulable parameter and ensure that it is set to false.

    3. Save and exit the file.

  5. Optional: If you do not want the Ingress Operator to create DNS records on your behalf, remove the privateZone and publicZone sections from the <installation_directory>/manifests/cluster-dns-02-config.yml DNS configuration file:

    apiVersion: config.openshift.io/v1
    kind: DNS
    metadata:
      creationTimestamp: null
      name: cluster
    spec:
      baseDomain: example.openshift.com
      privateZone: (1)
        id: mycluster-100419-private-zone
      publicZone: (1)
        id: example.openshift.com
    status: {}
    1 Remove this section completely.

    If you do so, you must add ingress DNS records manually in a later step.

  6. To create the Ignition configuration files, run the following command from the directory that contains the installation program:

    $ ./openshift-install create ignition-configs --dir=<installation_directory> (1)
    1 For <installation_directory>, specify the same installation directory.

    The following files are generated in the directory:

    .
    ├── auth
    │   ├── kubeadmin-password
    │   └── kubeconfig
    ├── bootstrap.ign
    ├── master.ign
    ├── metadata.json
    └── worker.ign

Extracting the infrastructure name

The Ignition config files contain a unique cluster identifier that you can use to uniquely identify your cluster in Amazon Web Services (AWS). The infrastructure name is also used to locate the appropriate AWS resources during an OpenShift Container Platform installation. The provided CloudFormation templates contain references to this infrastructure name, so you must extract it.

Prerequisites
  • You obtained the OpenShift Container Platform installation program and the pull secret for your cluster.

  • You generated the Ignition config files for your cluster.

  • You installed the jq package.

Procedure
  • To extract and view the infrastructure name from the Ignition config file metadata, run the following command:

    $ jq -r .infraID <installation_directory>/metadata.json (1)
    1 For <installation_directory>, specify the path to the directory that you stored the installation files in.
    Example output
    openshift-vw9j6 (1)
    
    1 The output of this command is your cluster name and a random string.

Creating a VPC in AWS

You must create a Virtual Private Cloud (VPC) in Amazon Web Services (AWS) for your OpenShift Container Platform cluster to use. You can customize the VPC to meet your requirements, including VPN and route tables.

You can use the provided CloudFormation template and a custom parameter file to create a stack of AWS resources that represent the VPC.

If you do not use the provided CloudFormation template to create your AWS infrastructure, you must review the provided information and manually create the infrastructure. If your cluster does not initialize correctly, you might have to contact Red Hat support with your installation logs.

Prerequisites
  • You configured an AWS account.

  • You added your AWS keys and region to your local AWS profile by running aws configure.

  • You generated the Ignition config files for your cluster.

Procedure
  1. Create a JSON file that contains the parameter values that the template requires:

    [
      {
        "ParameterKey": "VpcCidr", (1)
        "ParameterValue": "10.0.0.0/16" (2)
      },
      {
        "ParameterKey": "AvailabilityZoneCount", (3)
        "ParameterValue": "1" (4)
      },
      {
        "ParameterKey": "SubnetBits", (5)
        "ParameterValue": "12" (6)
      }
    ]
    1 The CIDR block for the VPC.
    2 Specify a CIDR block in the format x.x.x.x/16-24.
    3 The number of availability zones to deploy the VPC in.
    4 Specify an integer between 1 and 3.
    5 The size of each subnet in each availability zone.
    6 Specify an integer between 5 and 13, where 5 is /27 and 13 is /19.
  2. Copy the template from the CloudFormation template for the VPC section of this topic and save it as a YAML file on your computer. This template describes the VPC that your cluster requires.

  3. Launch the CloudFormation template to create a stack of AWS resources that represent the VPC:

    You must enter the command on a single line.

    $ aws cloudformation create-stack --stack-name <name> (1)
         --template-body file://<template>.yaml (2)
         --parameters file://<parameters>.json (3)
    1 <name> is the name for the CloudFormation stack, such as cluster-vpc. You need the name of this stack if you remove the cluster.
    2 <template> is the relative path to and name of the CloudFormation template YAML file that you saved.
    3 <parameters> is the relative path to and name of the CloudFormation parameters JSON file.
    Example output
    arn:aws:cloudformation:us-east-1:269333783861:stack/cluster-vpc/dbedae40-2fd3-11eb-820e-12a48460849f
  4. Confirm that the template components exist:

    $ aws cloudformation describe-stacks --stack-name <name>

    After the StackStatus displays CREATE_COMPLETE, the output displays values for the following parameters. You must provide these parameter values to the other CloudFormation templates that you run to create your cluster:

    VpcId

    The ID of your VPC.

    PublicSubnetIds

    The IDs of the new public subnets.

    PrivateSubnetIds

    The IDs of the new private subnets.

CloudFormation template for the VPC

You can use the following CloudFormation template to deploy the VPC that you need for your OpenShift Container Platform cluster.

CloudFormation template for the VPC
AWSTemplateFormatVersion: 2010-09-09
Description: Template for Best Practice VPC with 1-3 AZs

Parameters:
  VpcCidr:
    AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-4]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-24.
    Default: 10.0.0.0/16
    Description: CIDR block for VPC.
    Type: String
  AvailabilityZoneCount:
    ConstraintDescription: "The number of availability zones. (Min: 1, Max: 3)"
    MinValue: 1
    MaxValue: 3
    Default: 1
    Description: "How many AZs to create VPC subnets for. (Min: 1, Max: 3)"
    Type: Number
  SubnetBits:
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/19-27.
    MinValue: 5
    MaxValue: 13
    Default: 12
    Description: "Size of each subnet to create within the availability zones. (Min: 5 = /27, Max: 13 = /19)"
    Type: Number

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
    - Label:
        default: "Network Configuration"
      Parameters:
      - VpcCidr
      - SubnetBits
    - Label:
        default: "Availability Zones"
      Parameters:
      - AvailabilityZoneCount
    ParameterLabels:
      AvailabilityZoneCount:
        default: "Availability Zone Count"
      VpcCidr:
        default: "VPC CIDR"
      SubnetBits:
        default: "Bits Per Subnet"

Conditions:
  DoAz3: !Equals [3, !Ref AvailabilityZoneCount]
  DoAz2: !Or [!Equals [2, !Ref AvailabilityZoneCount], Condition: DoAz3]

Resources:
  VPC:
    Type: "AWS::EC2::VPC"
    Properties:
      EnableDnsSupport: "true"
      EnableDnsHostnames: "true"
      CidrBlock: !Ref VpcCidr
  PublicSubnet:
    Type: "AWS::EC2::Subnet"
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Select [0, !Cidr [!Ref VpcCidr, 6, !Ref SubnetBits]]
      AvailabilityZone: !Select
      - 0
      - Fn::GetAZs: !Ref "AWS::Region"
  PublicSubnet2:
    Type: "AWS::EC2::Subnet"
    Condition: DoAz2
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Select [1, !Cidr [!Ref VpcCidr, 6, !Ref SubnetBits]]
      AvailabilityZone: !Select
      - 1
      - Fn::GetAZs: !Ref "AWS::Region"
  PublicSubnet3:
    Type: "AWS::EC2::Subnet"
    Condition: DoAz3
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Select [2, !Cidr [!Ref VpcCidr, 6, !Ref SubnetBits]]
      AvailabilityZone: !Select
      - 2
      - Fn::GetAZs: !Ref "AWS::Region"
  InternetGateway:
    Type: "AWS::EC2::InternetGateway"
  GatewayToInternet:
    Type: "AWS::EC2::VPCGatewayAttachment"
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway
  PublicRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VPC
  PublicRoute:
    Type: "AWS::EC2::Route"
    DependsOn: GatewayToInternet
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway
  PublicSubnetRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref PublicRouteTable
  PublicSubnetRouteTableAssociation2:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Condition: DoAz2
    Properties:
      SubnetId: !Ref PublicSubnet2
      RouteTableId: !Ref PublicRouteTable
  PublicSubnetRouteTableAssociation3:
    Condition: DoAz3
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      SubnetId: !Ref PublicSubnet3
      RouteTableId: !Ref PublicRouteTable
  PrivateSubnet:
    Type: "AWS::EC2::Subnet"
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Select [3, !Cidr [!Ref VpcCidr, 6, !Ref SubnetBits]]
      AvailabilityZone: !Select
      - 0
      - Fn::GetAZs: !Ref "AWS::Region"
  PrivateRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VPC
  PrivateSubnetRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      SubnetId: !Ref PrivateSubnet
      RouteTableId: !Ref PrivateRouteTable
  NAT:
    DependsOn:
    - GatewayToInternet
    Type: "AWS::EC2::NatGateway"
    Properties:
      AllocationId:
        "Fn::GetAtt":
        - EIP
        - AllocationId
      SubnetId: !Ref PublicSubnet
  EIP:
    Type: "AWS::EC2::EIP"
    Properties:
      Domain: vpc
  Route:
    Type: "AWS::EC2::Route"
    Properties:
      RouteTableId:
        Ref: PrivateRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId:
        Ref: NAT
  PrivateSubnet2:
    Type: "AWS::EC2::Subnet"
    Condition: DoAz2
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Select [4, !Cidr [!Ref VpcCidr, 6, !Ref SubnetBits]]
      AvailabilityZone: !Select
      - 1
      - Fn::GetAZs: !Ref "AWS::Region"
  PrivateRouteTable2:
    Type: "AWS::EC2::RouteTable"
    Condition: DoAz2
    Properties:
      VpcId: !Ref VPC
  PrivateSubnetRouteTableAssociation2:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Condition: DoAz2
    Properties:
      SubnetId: !Ref PrivateSubnet2
      RouteTableId: !Ref PrivateRouteTable2
  NAT2:
    DependsOn:
    - GatewayToInternet
    Type: "AWS::EC2::NatGateway"
    Condition: DoAz2
    Properties:
      AllocationId:
        "Fn::GetAtt":
        - EIP2
        - AllocationId
      SubnetId: !Ref PublicSubnet2
  EIP2:
    Type: "AWS::EC2::EIP"
    Condition: DoAz2
    Properties:
      Domain: vpc
  Route2:
    Type: "AWS::EC2::Route"
    Condition: DoAz2
    Properties:
      RouteTableId:
        Ref: PrivateRouteTable2
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId:
        Ref: NAT2
  PrivateSubnet3:
    Type: "AWS::EC2::Subnet"
    Condition: DoAz3
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Select [5, !Cidr [!Ref VpcCidr, 6, !Ref SubnetBits]]
      AvailabilityZone: !Select
      - 2
      - Fn::GetAZs: !Ref "AWS::Region"
  PrivateRouteTable3:
    Type: "AWS::EC2::RouteTable"
    Condition: DoAz3
    Properties:
      VpcId: !Ref VPC
  PrivateSubnetRouteTableAssociation3:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Condition: DoAz3
    Properties:
      SubnetId: !Ref PrivateSubnet3
      RouteTableId: !Ref PrivateRouteTable3
  NAT3:
    DependsOn:
    - GatewayToInternet
    Type: "AWS::EC2::NatGateway"
    Condition: DoAz3
    Properties:
      AllocationId:
        "Fn::GetAtt":
        - EIP3
        - AllocationId
      SubnetId: !Ref PublicSubnet3
  EIP3:
    Type: "AWS::EC2::EIP"
    Condition: DoAz3
    Properties:
      Domain: vpc
  Route3:
    Type: "AWS::EC2::Route"
    Condition: DoAz3
    Properties:
      RouteTableId:
        Ref: PrivateRouteTable3
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId:
        Ref: NAT3
  S3Endpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      PolicyDocument:
        Version: 2012-10-17
        Statement:
        - Effect: Allow
          Principal: '*'
          Action:
          - '*'
          Resource:
          - '*'
      RouteTableIds:
      - !Ref PublicRouteTable
      - !Ref PrivateRouteTable
      - !If [DoAz2, !Ref PrivateRouteTable2, !Ref "AWS::NoValue"]
      - !If [DoAz3, !Ref PrivateRouteTable3, !Ref "AWS::NoValue"]
      ServiceName: !Join
      - ''
      - - com.amazonaws.
        - !Ref 'AWS::Region'
        - .s3
      VpcId: !Ref VPC

Outputs:
  VpcId:
    Description: ID of the new VPC.
    Value: !Ref VPC
  PublicSubnetIds:
    Description: Subnet IDs of the public subnets.
    Value:
      !Join [
        ",",
        [!Ref PublicSubnet, !If [DoAz2, !Ref PublicSubnet2, !Ref "AWS::NoValue"], !If [DoAz3, !Ref PublicSubnet3, !Ref "AWS::NoValue"]]
      ]
  PrivateSubnetIds:
    Description: Subnet IDs of the private subnets.
    Value:
      !Join [
        ",",
        [!Ref PrivateSubnet, !If [DoAz2, !Ref PrivateSubnet2, !Ref "AWS::NoValue"], !If [DoAz3, !Ref PrivateSubnet3, !Ref "AWS::NoValue"]]
      ]

Creating networking and load balancing components in AWS

You must configure networking and classic or network load balancing in Amazon Web Services (AWS) that your OpenShift Container Platform cluster can use.

You can use the provided CloudFormation template and a custom parameter file to create a stack of AWS resources. The stack represents the networking and load balancing components that your OpenShift Container Platform cluster requires. The template also creates a hosted zone and subnet tags.

You can run the template multiple times within a single Virtual Private Cloud (VPC).

If you do not use the provided CloudFormation template to create your AWS infrastructure, you must review the provided information and manually create the infrastructure. If your cluster does not initialize correctly, you might have to contact Red Hat support with your installation logs.

Prerequisites
  • You configured an AWS account.

  • You added your AWS keys and region to your local AWS profile by running aws configure.

  • You generated the Ignition config files for your cluster.

  • You created and configured a VPC and associated subnets in AWS.

Procedure
  1. Obtain the hosted zone ID for the Route 53 base domain that you specified in the install-config.yaml file for your cluster. You can obtain details about your hosted zone by running the following command:

    $ aws route53 list-hosted-zones-by-name --dns-name <route53_domain> (1)
    1 For the <route53_domain>, specify the Route 53 base domain that you used when you generated the install-config.yaml file for the cluster.
    Example output
    mycluster.example.com.	False	100
    HOSTEDZONES	65F8F38E-2268-B835-E15C-AB55336FCBFA	/hostedzone/Z21IXYZABCZ2A4	mycluster.example.com.	10

    In the example output, the hosted zone ID is Z21IXYZABCZ2A4.

  2. Create a JSON file that contains the parameter values that the template requires:

    [
      {
        "ParameterKey": "ClusterName", (1)
        "ParameterValue": "mycluster" (2)
      },
      {
        "ParameterKey": "InfrastructureName", (3)
        "ParameterValue": "mycluster-<random_string>" (4)
      },
      {
        "ParameterKey": "HostedZoneId", (5)
        "ParameterValue": "<random_string>" (6)
      },
      {
        "ParameterKey": "HostedZoneName", (7)
        "ParameterValue": "example.com" (8)
      },
      {
        "ParameterKey": "PublicSubnets", (9)
        "ParameterValue": "subnet-<random_string>" (10)
      },
      {
        "ParameterKey": "PrivateSubnets", (11)
        "ParameterValue": "subnet-<random_string>" (12)
      },
      {
        "ParameterKey": "VpcId", (13)
        "ParameterValue": "vpc-<random_string>" (14)
      }
    ]
    1 A short, representative cluster name to use for hostnames, etc.
    2 Specify the cluster name that you used when you generated the install-config.yaml file for the cluster.
    3 The name for your cluster infrastructure that is encoded in your Ignition config files for the cluster.
    4 Specify the infrastructure name that you extracted from the Ignition config file metadata, which has the format <cluster-name>-<random-string>.
    5 The Route 53 public zone ID to register the targets with.
    6 Specify the Route 53 public zone ID, which as a format similar to Z21IXYZABCZ2A4. You can obtain this value from the AWS console.
    7 The Route 53 zone to register the targets with.
    8 Specify the Route 53 base domain that you used when you generated the install-config.yaml file for the cluster. Do not include the trailing period (.) that is displayed in the AWS console.
    9 The public subnets that you created for your VPC.
    10 Specify the PublicSubnetIds value from the output of the CloudFormation template for the VPC.
    11 The private subnets that you created for your VPC.
    12 Specify the PrivateSubnetIds value from the output of the CloudFormation template for the VPC.
    13 The VPC that you created for the cluster.
    14 Specify the VpcId value from the output of the CloudFormation template for the VPC.
  3. Copy the template from the CloudFormation template for the network and load balancers section of this topic and save it as a YAML file on your computer. This template describes the networking and load balancing objects that your cluster requires.

    If you are deploying your cluster to an AWS government or secret region, you must update the InternalApiServerRecord in the CloudFormation template to use CNAME records. Records of type ALIAS are not supported for AWS government regions.

  4. Launch the CloudFormation template to create a stack of AWS resources that provide the networking and load balancing components:

    You must enter the command on a single line.

    $ aws cloudformation create-stack --stack-name <name> (1)
         --template-body file://<template>.yaml (2)
         --parameters file://<parameters>.json (3)
         --capabilities CAPABILITY_NAMED_IAM (4)
    
    1 <name> is the name for the CloudFormation stack, such as cluster-dns. You need the name of this stack if you remove the cluster.
    2 <template> is the relative path to and name of the CloudFormation template YAML file that you saved.
    3 <parameters> is the relative path to and name of the CloudFormation parameters JSON file.
    4 You must explicitly declare the CAPABILITY_NAMED_IAM capability because the provided template creates some AWS::IAM::Role resources.
    Example output
    arn:aws:cloudformation:us-east-1:269333783861:stack/cluster-dns/cd3e5de0-2fd4-11eb-5cf0-12be5c33a183
  5. Confirm that the template components exist:

    $ aws cloudformation describe-stacks --stack-name <name>

    After the StackStatus displays CREATE_COMPLETE, the output displays values for the following parameters. You must provide these parameter values to the other CloudFormation templates that you run to create your cluster:

    PrivateHostedZoneId

    Hosted zone ID for the private DNS.

    ExternalApiLoadBalancerName

    Full name of the external API load balancer.

    InternalApiLoadBalancerName

    Full name of the internal API load balancer.

    ApiServerDnsName

    Full hostname of the API server.

    RegisterNlbIpTargetsLambda

    Lambda ARN useful to help register/deregister IP targets for these load balancers.

    ExternalApiTargetGroupArn

    ARN of external API target group.

    InternalApiTargetGroupArn

    ARN of internal API target group.

    InternalServiceTargetGroupArn

    ARN of internal service target group.

CloudFormation template for the network and load balancers

You can use the following CloudFormation template to deploy the networking objects and load balancers that you need for your OpenShift Container Platform cluster.

CloudFormation template for the network and load balancers
AWSTemplateFormatVersion: 2010-09-09
Description: Template for OpenShift Cluster Network Elements (Route53 & LBs)

Parameters:
  ClusterName:
    AllowedPattern: ^([a-zA-Z][a-zA-Z0-9\-]{0,26})$
    MaxLength: 27
    MinLength: 1
    ConstraintDescription: Cluster name must be alphanumeric, start with a letter, and have a maximum of 27 characters.
    Description: A short, representative cluster name to use for host names and other identifying names.
    Type: String
  InfrastructureName:
    AllowedPattern: ^([a-zA-Z][a-zA-Z0-9\-]{0,26})$
    MaxLength: 27
    MinLength: 1
    ConstraintDescription: Infrastructure name must be alphanumeric, start with a letter, and have a maximum of 27 characters.
    Description: A short, unique cluster ID used to tag cloud resources and identify items owned or used by the cluster.
    Type: String
  HostedZoneId:
    Description: The Route53 public zone ID to register the targets with, such as Z21IXYZABCZ2A4.
    Type: String
  HostedZoneName:
    Description: The Route53 zone to register the targets with, such as example.com. Omit the trailing period.
    Type: String
    Default: "example.com"
  PublicSubnets:
    Description: The internet-facing subnets.
    Type: List<AWS::EC2::Subnet::Id>
  PrivateSubnets:
    Description: The internal subnets.
    Type: List<AWS::EC2::Subnet::Id>
  VpcId:
    Description: The VPC-scoped resources will belong to this VPC.
    Type: AWS::EC2::VPC::Id

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
    - Label:
        default: "Cluster Information"
      Parameters:
      - ClusterName
      - InfrastructureName
    - Label:
        default: "Network Configuration"
      Parameters:
      - VpcId
      - PublicSubnets
      - PrivateSubnets
    - Label:
        default: "DNS"
      Parameters:
      - HostedZoneName
      - HostedZoneId
    ParameterLabels:
      ClusterName:
        default: "Cluster Name"
      InfrastructureName:
        default: "Infrastructure Name"
      VpcId:
        default: "VPC ID"
      PublicSubnets:
        default: "Public Subnets"
      PrivateSubnets:
        default: "Private Subnets"
      HostedZoneName:
        default: "Public Hosted Zone Name"
      HostedZoneId:
        default: "Public Hosted Zone ID"

Resources:
  ExtApiElb:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Name: !Join ["-", [!Ref InfrastructureName, "ext"]]
      IpAddressType: ipv4
      Subnets: !Ref PublicSubnets
      Type: network

  IntApiElb:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Name: !Join ["-", [!Ref InfrastructureName, "int"]]
      Scheme: internal
      IpAddressType: ipv4
      Subnets: !Ref PrivateSubnets
      Type: network

  IntDns:
    Type: "AWS::Route53::HostedZone"
    Properties:
      HostedZoneConfig:
        Comment: "Managed by CloudFormation"
      Name: !Join [".", [!Ref ClusterName, !Ref HostedZoneName]]
      HostedZoneTags:
      - Key: Name
        Value: !Join ["-", [!Ref InfrastructureName, "int"]]
      - Key: !Join ["", ["kubernetes.io/cluster/", !Ref InfrastructureName]]
        Value: "owned"
      VPCs:
      - VPCId: !Ref VpcId
        VPCRegion: !Ref "AWS::Region"

  ExternalApiServerRecord:
    Type: AWS::Route53::RecordSetGroup
    Properties:
      Comment: Alias record for the API server
      HostedZoneId: !Ref HostedZoneId
      RecordSets:
      - Name: