Installing a cluster on AWS in a restricted network with user-provisioned infrastructure

    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 OKD. 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.

    • You reviewed details about the processes.

    • You read the documentation on selecting a cluster installation method and preparing it for users.

    • You and obtained the imageContentSources data for your version of OKD.

      Because the installation media is on the mirror host, you can use that computer to complete all installation steps.

    • You configured an AWS account to host the cluster.

      If you have an AWS profile stored on your computer, it must not use a temporary session token that you generated while using a multi-factor authentication device. The cluster continues to use your current AWS credentials to create AWS resources for the entire life of the cluster, so you must use key-based, long-lived credentials. To generate appropriate keys, see in the AWS documentation. You can supply the keys when you run the installation program.

    • You downloaded the AWS CLI and installed it on your computer. See Install the AWS CLI Using the Bundled Installer (Linux, macOS, or Unix) in the AWS documentation.

    • If you use a firewall and plan to use the Telemetry service, you that your cluster requires access to.

      Be sure to also review this site list if you are configuring a proxy.

    • If the cloud identity and access management (IAM) APIs are not accessible in your environment, or if you do not want to store an administrator-level credential secret in the kube-system namespace, you can manually create and maintain IAM credentials.

    About installations in restricted networks

    In OKD 4.13, 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 Route 53 DNS and IAM services, require internet access. Depending on your network, you might require less internet access for an installation on bare metal hardware, Nutanix, or on VMware vSphere.

    To complete a restricted network installation, you must create a registry that mirrors the contents of the OpenShift image 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.

    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.

    Requirements for a cluster with user-provisioned infrastructure

    For a cluster that contains user-provisioned infrastructure, you must deploy all of the required machines.

    This section describes the requirements for deploying OKD on user-provisioned infrastructure.

    Required machines for cluster installation

    The smallest OKD clusters require the following hosts:

    Table 1. Minimum required hosts
    HostsDescription

    One temporary bootstrap machine

    The cluster requires the bootstrap machine to deploy the OKD cluster on the three control plane machines. You can remove the bootstrap machine after you install the cluster.

    Three control plane machines

    The control plane machines run the Kubernetes and OKD services that form the control plane.

    At least two compute machines, which are also known as worker machines.

    The workloads requested by OKD users run on the compute machines.

    To maintain high availability of your cluster, use separate physical hosts for these cluster machines.

    The bootstrap and control plane machines must use Fedora CoreOS (FCOS) as the operating system. However, the compute machines can choose between Fedora CoreOS (FCOS), Fedora 8.6, Fedora 8.7, or Fedora 8.8.

    See .

    Minimum resource requirements for cluster installation

    Each cluster machine must meet the following minimum requirements:

    Table 2. Minimum resource requirements
    MachineOperating SystemvCPU [1]Virtual RAMStorageIOPS [2]

    Bootstrap

    FCOS

    4

    16 GB

    100 GB

    300

    Control plane

    FCOS

    4

    16 GB

    100 GB

    300

    Compute

    FCOS

    2

    8 GB

    100 GB

    300

    1. One vCPU is equivalent to one physical core when simultaneous multithreading (SMT), or hyperthreading, is not enabled. When enabled, use the following formula to calculate the corresponding ratio: (threads per core × cores) × sockets = vCPUs.

    2. OKD and Kubernetes are sensitive to disk performance, and faster storage is recommended, particularly for etcd on the control plane nodes which require a 10 ms p99 fsync duration. Note that on many cloud platforms, storage size and IOPS scale together, so you might need to over-allocate storage volume to obtain sufficient performance.

    3. As with all user-provisioned installations, if you choose to use Fedora compute machines in your cluster, you take responsibility for all operating system life cycle management and maintenance, including performing system updates, applying patches, and completing all other required tasks. Use of Fedora 7 compute machines is deprecated and has been removed in OKD 4.10 and later.

    If an instance type for your platform meets the minimum requirements for cluster machines, it is supported to use in OKD.

    Tested instance types for AWS

    The following Amazon Web Services (AWS) instance types have been tested with OKD.

    Use the machine types included in the following charts for your AWS instances. If you use an instance type that is not listed in the chart, ensure that the instance size you use matches the minimum resource requirements that are listed in “Minimum resource requirements for cluster installation”.

    Machine types based on x86_64 architecture

    • c4.*

    • c5.*

    • c5a.*

    • i3.*

    • m4.*

    • m5.*

    • m5a.*

    • m6i.*

    • r4.*

    • r5.*

    • r5a.*

    • r6i.*

    • t3.*

    • t3a.*

    Tested instance types for AWS ARM

    The following Amazon Web Services (AWS) ARM instance types have been tested with OKD.

    Use the machine types included in the following charts for your AWS ARM instances. If you use an instance type that is not listed in the chart, ensure that the instance size you use matches the minimum resource requirements that are listed in “Minimum resource requirements for cluster installation”.

    Machine types based on arm64 architecture

    • c6g.*

    • m6g.*

    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.

    Supported AWS machine types

    The following Amazon Web Services (AWS) instance types are supported with OKD.

    Machine types based on x86_64 architecture

    Instance typeBootstrapControl planeCompute

    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.12xlarge

    x

    x

    m5a.16xlarge

    x

    x

    m6i.large

    x

    m6i.xlarge

    x

    x

    m6i.2xlarge

    x

    x

    m6i.4xlarge

    x

    x

    m6i.8xlarge

    x

    x

    m6i.12xlarge

    x

    x

    m6i.16xlarge

    x

    x

    c4.2xlarge

    x

    x

    c4.4xlarge

    x

    x

    c4.8xlarge

    x

    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.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 infrastructure components

    To install OKD 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 OKD bootstrap node

    • OKD control plane nodes

    • An OKD 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.

    • 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, you are unable to reach the public IP addresses for EC2, ELB, and S3 endpoints. Depending on the level to which you want to restrict internet traffic during the installation, the following configuration options are available:

    Option 1: Create VPC endpoints

    Create a VPC endpoint and attach it to the subnets that the clusters are using. Name the endpoints as follows:

    • ec2.<aws_region>.amazonaws.com

    • elasticloadbalancing.<aws_region>.amazonaws.com

    • s3.<aws_region>.amazonaws.com

    With this option, network traffic remains private between your VPC and the required AWS services.

    Option 2: Create a proxy without VPC endpoints

    As part of the installation process, you can configure an HTTP or HTTPS proxy. With this option, internet traffic goes through the proxy to reach the required AWS services.

    Option 3: Create a proxy with VPC endpoints

    As part of the installation process, you can configure an HTTP or HTTPS proxy with VPC endpoints. Create a VPC endpoint and attach it to the subnets that the clusters are using. Name the endpoints as follows:

    • ec2.<aws_region>.amazonaws.com

    • elasticloadbalancing.<aws_region>.amazonaws.com

    • s3.<aws_region>.amazonaws.com

    When configuring the proxy in the install-config.yaml file, add these endpoints to the noProxy field. With this option, the proxy prevents the cluster from accessing the internet directly. However, network traffic remains private between your VPC and the required AWS services.

    Required VPC components

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

    ComponentAWS typeDescription

    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. 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.

    ComponentAWS typeDescription

    DNS

    AWS::Route53::HostedZone

    The hosted zone for your internal DNS.

    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:

    GroupTypeIP ProtocolPort 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 groupDescriptionIP protocolPort range

    MasterIngressEtcd

    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

    MasterIngressGeneve

    Geneve packets

    udp

    6081

    MasterIngressWorkerGeneve

    Geneve packets

    udp

    6081

    MasterIngressIpsecIke

    IPsec IKE packets

    udp

    500

    MasterIngressWorkerIpsecIke

    IPsec IKE packets

    udp

    500

    MasterIngressIpsecNat

    IPsec NAT-T packets

    udp

    4500

    MasterIngressWorkerIpsecNat

    IPsec NAT-T packets

    udp

    4500

    MasterIngressIpsecEsp

    IPsec ESP packets

    50

    All

    MasterIngressWorkerIpsecEsp

    IPsec ESP packets

    50

    All

    MasterIngressInternalUDP

    Internal cluster communication

    udp

    9000 - 9999

    MasterIngressWorkerInternalUDP

    Internal cluster communication

    udp

    9000 - 9999

    MasterIngressIngressServicesUDP

    Kubernetes Ingress services

    udp

    30000 - 32767

    MasterIngressWorkerIngressServicesUDP

    Kubernetes Ingress services

    udp

    30000 - 32767

    Worker Ingress

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

    Ingress groupDescriptionIP protocolPort 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

    WorkerIngressGeneve

    Geneve packets

    udp

    6081

    WorkerIngressMasterGeneve

    Geneve packets

    udp

    6081

    WorkerIngressIpsecIke

    IPsec IKE packets

    udp

    500

    WorkerIngressMasterIpsecIke

    IPsec IKE packets

    udp

    500

    WorkerIngressIpsecNat

    IPsec NAT-T packets

    udp

    4500

    WorkerIngressMasterIpsecNat

    IPsec NAT-T packets

    udp

    4500

    WorkerIngressIpsecEsp

    IPsec ESP packets

    50

    All

    WorkerIngressMasterIpsecEsp

    IPsec ESP packets

    50

    All

    WorkerIngressInternalUDP

    Internal cluster communication

    udp

    9000 - 9999

    WorkerIngressMasterInternalUDP

    Internal cluster communication

    udp

    9000 - 9999

    WorkerIngressIngressServicesUDP

    Kubernetes Ingress services

    udp

    30000 - 32767

    WorkerIngressMasterIngressServicesUDP

    Kubernetes Ingress services

    udp

    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.

    RoleEffectActionResource

    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 control plane 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 compute machine set.

    Required AWS permissions for the IAM user

    Your IAM user must have the permission tag:GetResources in the region us-east-1 to delete the base cluster resources. As part of the AWS API requirement, the OKD installation program performs various actions in this region.

    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 OKD 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 (ELB) for installation

    • elasticloadbalancing:AddTags

    • elasticloadbalancing:ApplySecurityGroupsToLoadBalancer

    • elasticloadbalancing:AttachLoadBalancerToSubnets

    • elasticloadbalancing:ConfigureHealthCheck

    • elasticloadbalancing:CreateLoadBalancer

    • elasticloadbalancing:CreateLoadBalancerListeners

    • elasticloadbalancing:DeleteLoadBalancer

    • elasticloadbalancing:DeregisterInstancesFromLoadBalancer

    • elasticloadbalancing:DescribeInstanceHealth

    • elasticloadbalancing:DescribeLoadBalancerAttributes

    • elasticloadbalancing:DescribeLoadBalancers

    • elasticloadbalancing:DescribeTags

    • elasticloadbalancing:ModifyLoadBalancerAttributes

    • elasticloadbalancing:RegisterInstancesWithLoadBalancer

    • elasticloadbalancing:SetLoadBalancerPoliciesOfListener

    Required Elastic Load Balancing permissions (ELBv2) for installation

    • elasticloadbalancing:AddTags

    • elasticloadbalancing:CreateListener

    • elasticloadbalancing:CreateLoadBalancer

    • elasticloadbalancing:CreateTargetGroup

    • elasticloadbalancing:DeleteLoadBalancer

    • elasticloadbalancing:DeregisterTargets

    • elasticloadbalancing:DescribeListeners

    • elasticloadbalancing:DescribeLoadBalancerAttributes

    • elasticloadbalancing:DescribeLoadBalancers

    • elasticloadbalancing:DescribeTargetGroupAttributes

    • elasticloadbalancing:DescribeTargetHealth

    • elasticloadbalancing:ModifyLoadBalancerAttributes

    • elasticloadbalancing:ModifyTargetGroup

    • elasticloadbalancing:ModifyTargetGroupAttributes

    • elasticloadbalancing:RegisterTargets

    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 a load balancer 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:GetBucketPolicy

    • 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:DeletePlacementGroup

    • 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

    • 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 a key pair for cluster node SSH access

    During an OKD installation, you can provide an SSH public key to the installation program. The key is passed to the Fedora CoreOS (FCOS) nodes through their Ignition config files and is used to authenticate SSH access to the nodes. The key is added to the ~/.ssh/authorized_keys list for the core user on each node, which enables password-less authentication.

    After the key is passed to the nodes, you can use the key pair to SSH in to the FCOS nodes as the user core. To access the nodes through SSH, the private key identity must be managed by SSH for your local user.

    If you want to SSH in to your cluster nodes to perform installation debugging or disaster recovery, you must provide the SSH public key during the installation process. The ./openshift-install gather command also requires the SSH public key to be in place on the cluster nodes.

    Do not skip this procedure in production environments, where disaster recovery and debugging is required.

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

    On clusters running Fedora CoreOS (FCOS), the SSH keys specified in the Ignition config files are written to the /home/core/.ssh/authorized_keys.d/core file. However, the Machine Config Operator manages SSH keys in the /home/core/.ssh/authorized_keys file and configures sshd to ignore the /home/core/.ssh/authorized_keys.d/core file. As a result, newly provisioned OKD nodes are not accessible using SSH until the Machine Config Operator reconciles the machine configs with the authorized_keys file. After you can access the nodes using SSH, you can delete the /home/core/.ssh/authorized_keys.d/core file.

    Procedure

    1. If you do not have an existing SSH key pair on your local machine to use for authentication onto your cluster nodes, create one. For example, on a computer that uses a Linux operating system, run the following command:

      1Specify the path and file name, such as ~/.ssh/id_ed25519, of the new SSH key. If you have an existing key pair, ensure your public key is in the your ~/.ssh directory.

      If you plan to install an OKD 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.

      1. $ cat <path>/<file_name>.pub

      For example, run the following to view the ~/.ssh/id_ed25519.pub public key:

      1. $ cat ~/.ssh/id_ed25519.pub
    2. Add the SSH private key identity to the SSH agent for your local user, if it has not already been added. SSH agent management of the key is required for password-less SSH authentication onto your cluster nodes, or if you want to use the ./openshift-install gather command.

      On some distributions, default SSH private key identities such as ~/.ssh/id_rsa and ~/.ssh/id_dsa are managed automatically.

      1. If the ssh-agent process is not already running for your local user, start it as a background task:

        1. $ eval "$(ssh-agent -s)"

        Example output

        1. 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:

      1. $ ssh-add <path>/<file_name> (1)
      1Specify the path and file name for your SSH private key, such as ~/.ssh/id_ed25519

      Example output

      1. Identity added: /home/<you>/<path>/<file_name> (<computer_name>)

    Next steps

    • When you install OKD, provide the SSH public key to the installation program. If you install a cluster on infrastructure that you provision, you must provide the key to the installation program.

    Creating the installation files for AWS

    To install OKD 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 OKD 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.

    OKD 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 OKD 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 Fedora CoreOS (FCOS), the following procedure sets up the separate /var partition by creating a machine config manifest that is inserted during the openshift-install preparation phases of an OKD 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.

    Procedure

    1. Create a directory to hold the OKD installation files:

      1. $ 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:

      1. $ openshift-install create manifests --dir $HOME/clusterconfig

      Example output

      1. ? SSH Public Key ...
      2. INFO Credentials loaded from the "myprofile" profile in file "/home/myuser/.aws/credentials"
      3. INFO Consuming Install Config from target directory
      4. 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:

      1. $ ls $HOME/clusterconfig/openshift/

      Example output

      1. 99_kubeadmin-password-secret.yaml
      2. 99_openshift-cluster-api_master-machines-0.yaml
      3. 99_openshift-cluster-api_master-machines-1.yaml
      4. 99_openshift-cluster-api_master-machines-2.yaml
      5. ...
    4. Create a Butane config that configures the additional partition. For example, name the file $HOME/clusterconfig/98-var-partition.bu, change the disk device name to the name of the storage device on the worker systems, and set the storage size as appropriate. This example places the /var directory on a separate partition:

      1. variant: openshift
      2. version: 4.13.0
      3. metadata:
      4. labels:
      5. machineconfiguration.openshift.io/role: worker
      6. name: 98-var-partition
      7. storage:
      8. disks:
      9. - device: /dev/<device_name> (1)
      10. partitions:
      11. - label: var
      12. start_mib: <partition_start_offset> (2)
      13. size_mib: <partition_size> (3)
      14. filesystems:
      15. - device: /dev/disk/by-partlabel/var
      16. path: /var
      17. format: xfs
      18. mount_options: [defaults, prjquota] (4)
      19. with_mount_unit: true
      1The storage device name of the disk that you want to partition.
      2When 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 FCOS might overwrite the beginning of the data partition.
      3The size of the data partition in mebibytes.
      4The prjquota mount option must be enabled for filesystems used for container storage.

      When creating a separate /var partition, you cannot use different instance types for worker nodes, if the different instance types do not have the same device name.

    5. Create a manifest from the Butane config and save it to the clusterconfig/openshift directory. For example, run the following command:

      1. $ butane $HOME/clusterconfig/98-var-partition.bu -o $HOME/clusterconfig/openshift/98-var-partition.yaml
    6. Run openshift-install again to create Ignition configs from a set of files in the manifest and openshift subdirectories:

      1. $ openshift-install create ignition-configs --dir $HOME/clusterconfig
      2. $ ls $HOME/clusterconfig/
      3. 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 Fedora CoreOS (FCOS) 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 OKD 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 Fedora CoreOS (FCOS) 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:

        1. $ ./openshift-install create install-config --dir <installation_directory> (1)
        1For <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 OKD 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 OKD 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.

        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 from the Red Hat OpenShift Cluster Manager. This field is optional.

    1. Edit the install-config.yaml file to give 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:

        1. 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. The certificate file can be an existing, trusted certificate authority or the self-signed certificate that you generated for the mirror registry.

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

        1. imageContentSources:
        2. - mirrors:
        3. - <local_registry>/<local_repository_name>/release
        4. source: quay.io/openshift-release-dev/ocp-release
        5. - mirrors:
        6. - <local_registry>/<local_repository_name>/release
        7. 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:

        1. publish: Internal

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

    2. 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

    • See in the AWS documentation for more information about AWS profile and credential configuration.

    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 OKD 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 OpenStack, the Proxy object status.noProxy field is also populated with the instance metadata endpoint (169.254.169.254).

    Procedure

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

      1. apiVersion: v1
      2. baseDomain: my.domain.com
      3. proxy:
      4. httpProxy: http://<username>:<pswd>@<ip>:<port> (1)
      5. httpsProxy: https://<username>:<pswd>@<ip>:<port> (2)
      6. noProxy: ec2.<aws_region>.amazonaws.com,elasticloadbalancing.<aws_region>.amazonaws.com,s3.<aws_region>.amazonaws.com (3)
      7. additionalTrustBundle: | (4)
      8. -----BEGIN CERTIFICATE-----
      9. <MY_TRUSTED_CA_CERT>
      10. -----END CERTIFICATE-----
      11. additionalTrustBundlePolicy: <policy_to_add_additionalTrustBundle> (5)
      1A proxy URL to use for creating HTTP connections outside the cluster. The URL scheme must be http.
      2A proxy URL to use for creating HTTPS connections outside the cluster.
      3A comma-separated list of destination domain names, IP addresses, or other network CIDRs to exclude from proxying. Preface a domain with . to match subdomains only. For example, .y.com matches x.y.com, but not y.com. Use * to bypass the proxy for all destinations. If you have added the Amazon EC2,Elastic Load Balancing, and S3 VPC endpoints to your VPC, you must add these endpoints to the noProxy field.
      4If 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 Fedora CoreOS (FCOS) trust bundle, and this config map is referenced in the trustedCA field of the Proxy object. The additionalTrustBundle field is required unless the proxy’s identity certificate is signed by an authority from the FCOS trust bundle.
      5Optional: The policy to determine the configuration of the Proxy object to reference the user-ca-bundle config map in the trustedCA field. The allowed values are Proxyonly and Always. Use Proxyonly to reference the user-ca-bundle config map only when http/https proxy is configured. Use Always to always reference the user-ca-bundle config map. The default value is Proxyonly.

      The installation program does not support the proxy readinessEndpoints field.

      If the installer times out, restart and then complete the deployment by using the wait-for command of the installer. For example:

      1. $ ./openshift-install wait-for install-complete log-level debug
    2. Save the file and reference it when installing OKD.

    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 configure the machines.

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

    • The Ignition config files that the OKD 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.

    • It is recommended that you use Ignition config files within 12 hours after they are generated because the 24-hour certificate rotates from 16 to 22 hours after the cluster is installed. By using the Ignition config files within 12 hours, you can avoid installation failure if the certificate update runs during installation.

    Prerequisites

    • You obtained the OKD 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 OKD installation program and generate the Kubernetes manifests for the cluster:

      1. $ ./openshift-install create manifests --dir <installation_directory> (1)
      1For <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:

      1. $ 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 control plane machine set:

      1. $ rm -f <installation_directory>/openshift/99_openshift-machine-api_master-control-plane-machine-set.yaml
    4. Remove the Kubernetes manifest files that define the worker machines:

      1. $ 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.

    5. 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.

    6. 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:

      1. apiVersion: config.openshift.io/v1
      2. kind: DNS
      3. metadata:
      4. creationTimestamp: null
      5. name: cluster
      6. spec:
      7. baseDomain: example.openshift.com
      8. privateZone: (1)
      9. id: mycluster-100419-private-zone
      10. publicZone: (1)
      11. id: example.openshift.com
      12. status: {}
      1Remove this section completely.

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

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

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

      Ignition config files are created for the bootstrap, control plane, and compute nodes in the installation directory. The kubeadmin-password and kubeconfig files are created in the ./<installation_directory>/auth directory:

      1. .
      2. ├── auth
      3. ├── kubeadmin-password
      4. └── kubeconfig
      5. ├── bootstrap.ign
      6. ├── master.ign
      7. ├── metadata.json
      8. └── 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 OKD installation. The provided CloudFormation templates contain references to this infrastructure name, so you must extract it.

    Prerequisites

    • You obtained the OKD 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:

      1. $ jq -r .infraID <installation_directory>/metadata.json (1)
      1For <installation_directory>, specify the path to the directory that you stored the installation files in.

      Example output

      1. openshift-vw9j6 (1)
      1The 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 OKD 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:

      1. [
      2. {
      3. "ParameterKey": "VpcCidr", (1)
      4. "ParameterValue": "10.0.0.0/16" (2)
      5. },
      6. {
      7. "ParameterKey": "AvailabilityZoneCount", (3)
      8. "ParameterValue": "1" (4)
      9. },
      10. {
      11. "ParameterKey": "SubnetBits", (5)
      12. "ParameterValue": "12" (6)
      13. }
      14. ]
      1The CIDR block for the VPC.
      2Specify a CIDR block in the format x.x.x.x/16-24.
      3The number of availability zones to deploy the VPC in.
      4Specify an integer between 1 and 3.
      5The size of each subnet in each availability zone.
      6Specify 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.

      1. $ aws cloudformation create-stack --stack-name <name> (1)
      2. --template-body file://<template>.yaml (2)
      3. --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

      1. arn:aws:cloudformation:us-east-1:269333783861:stack/cluster-vpc/dbedae40-2fd3-11eb-820e-12a48460849f
    4. Confirm that the template components exist:

      1. $ 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.

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

    CloudFormation template for the VPC

    1. AWSTemplateFormatVersion: 2010-09-09
    2. Description: Template for Best Practice VPC with 1-3 AZs
    3. Parameters:
    4. VpcCidr:
    5. 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]))$
    6. ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-24.
    7. Default: 10.0.0.0/16
    8. Description: CIDR block for VPC.
    9. Type: String
    10. AvailabilityZoneCount:
    11. ConstraintDescription: "The number of availability zones. (Min: 1, Max: 3)"
    12. MinValue: 1
    13. MaxValue: 3
    14. Default: 1
    15. Description: "How many AZs to create VPC subnets for. (Min: 1, Max: 3)"
    16. Type: Number
    17. SubnetBits:
    18. ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/19-27.
    19. MinValue: 5
    20. MaxValue: 13
    21. Default: 12
    22. Description: "Size of each subnet to create within the availability zones. (Min: 5 = /27, Max: 13 = /19)"
    23. Type: Number
    24. Metadata:
    25. AWS::CloudFormation::Interface:
    26. ParameterGroups:
    27. - Label:
    28. default: "Network Configuration"
    29. Parameters:
    30. - VpcCidr
    31. - SubnetBits
    32. - Label:
    33. default: "Availability Zones"
    34. Parameters:
    35. - AvailabilityZoneCount
    36. ParameterLabels:
    37. AvailabilityZoneCount:
    38. default: "Availability Zone Count"
    39. VpcCidr:
    40. default: "VPC CIDR"
    41. SubnetBits:
    42. default: "Bits Per Subnet"
    43. Conditions:
    44. DoAz3: !Equals [3, !Ref AvailabilityZoneCount]
    45. DoAz2: !Or [!Equals [2, !Ref AvailabilityZoneCount], Condition: DoAz3]
    46. Resources:
    47. VPC:
    48. Type: "AWS::EC2::VPC"
    49. Properties:
    50. EnableDnsSupport: "true"
    51. EnableDnsHostnames: "true"
    52. CidrBlock: !Ref VpcCidr
    53. PublicSubnet:
    54. Type: "AWS::EC2::Subnet"
    55. Properties:
    56. VpcId: !Ref VPC
    57. CidrBlock: !Select [0, !Cidr [!Ref VpcCidr, 6, !Ref SubnetBits]]
    58. AvailabilityZone: !Select
    59. - 0
    60. - Fn::GetAZs: !Ref "AWS::Region"
    61. PublicSubnet2:
    62. Type: "AWS::EC2::Subnet"
    63. Condition: DoAz2
    64. Properties:
    65. VpcId: !Ref VPC
    66. CidrBlock: !Select [1, !Cidr [!Ref VpcCidr, 6, !Ref SubnetBits]]
    67. AvailabilityZone: !Select
    68. - 1
    69. - Fn::GetAZs: !Ref "AWS::Region"
    70. PublicSubnet3:
    71. Type: "AWS::EC2::Subnet"
    72. Condition: DoAz3
    73. Properties:
    74. VpcId: !Ref VPC
    75. CidrBlock: !Select [2, !Cidr [!Ref VpcCidr, 6, !Ref SubnetBits]]
    76. AvailabilityZone: !Select
    77. - 2
    78. - Fn::GetAZs: !Ref "AWS::Region"
    79. InternetGateway:
    80. Type: "AWS::EC2::InternetGateway"
    81. GatewayToInternet:
    82. Type: "AWS::EC2::VPCGatewayAttachment"
    83. Properties:
    84. VpcId: !Ref VPC
    85. InternetGatewayId: !Ref InternetGateway
    86. PublicRouteTable:
    87. Type: "AWS::EC2::RouteTable"
    88. Properties:
    89. VpcId: !Ref VPC
    90. PublicRoute:
    91. Type: "AWS::EC2::Route"
    92. DependsOn: GatewayToInternet
    93. Properties:
    94. RouteTableId: !Ref PublicRouteTable
    95. DestinationCidrBlock: 0.0.0.0/0
    96. GatewayId: !Ref InternetGateway
    97. PublicSubnetRouteTableAssociation:
    98. Type: "AWS::EC2::SubnetRouteTableAssociation"
    99. Properties:
    100. SubnetId: !Ref PublicSubnet
    101. RouteTableId: !Ref PublicRouteTable
    102. PublicSubnetRouteTableAssociation2:
    103. Type: "AWS::EC2::SubnetRouteTableAssociation"
    104. Condition: DoAz2
    105. Properties:
    106. SubnetId: !Ref PublicSubnet2
    107. RouteTableId: !Ref PublicRouteTable
    108. PublicSubnetRouteTableAssociation3:
    109. Condition: DoAz3
    110. Type: "AWS::EC2::SubnetRouteTableAssociation"
    111. Properties:
    112. SubnetId: !Ref PublicSubnet3
    113. RouteTableId: !Ref PublicRouteTable
    114. PrivateSubnet:
    115. Type: "AWS::EC2::Subnet"
    116. Properties:
    117. VpcId: !Ref VPC
    118. CidrBlock: !Select [3, !Cidr [!Ref VpcCidr, 6, !Ref SubnetBits]]
    119. AvailabilityZone: !Select
    120. - 0
    121. - Fn::GetAZs: !Ref "AWS::Region"
    122. PrivateRouteTable:
    123. Type: "AWS::EC2::RouteTable"
    124. Properties:
    125. VpcId: !Ref VPC
    126. PrivateSubnetRouteTableAssociation:
    127. Type: "AWS::EC2::SubnetRouteTableAssociation"
    128. Properties:
    129. SubnetId: !Ref PrivateSubnet
    130. RouteTableId: !Ref PrivateRouteTable
    131. NAT:
    132. DependsOn:
    133. - GatewayToInternet
    134. Type: "AWS::EC2::NatGateway"
    135. Properties:
    136. AllocationId:
    137. "Fn::GetAtt":
    138. - EIP
    139. - AllocationId
    140. SubnetId: !Ref PublicSubnet
    141. EIP:
    142. Type: "AWS::EC2::EIP"
    143. Properties:
    144. Domain: vpc
    145. Route:
    146. Type: "AWS::EC2::Route"
    147. Properties:
    148. RouteTableId:
    149. Ref: PrivateRouteTable
    150. DestinationCidrBlock: 0.0.0.0/0
    151. NatGatewayId:
    152. Ref: NAT
    153. PrivateSubnet2:
    154. Type: "AWS::EC2::Subnet"
    155. Condition: DoAz2
    156. Properties:
    157. VpcId: !Ref VPC
    158. CidrBlock: !Select [4, !Cidr [!Ref VpcCidr, 6, !Ref SubnetBits]]
    159. AvailabilityZone: !Select
    160. - 1
    161. - Fn::GetAZs: !Ref "AWS::Region"
    162. PrivateRouteTable2:
    163. Type: "AWS::EC2::RouteTable"
    164. Condition: DoAz2
    165. Properties:
    166. VpcId: !Ref VPC
    167. PrivateSubnetRouteTableAssociation2:
    168. Type: "AWS::EC2::SubnetRouteTableAssociation"
    169. Condition: DoAz2
    170. Properties:
    171. SubnetId: !Ref PrivateSubnet2
    172. RouteTableId: !Ref PrivateRouteTable2
    173. NAT2:
    174. DependsOn:
    175. - GatewayToInternet
    176. Type: "AWS::EC2::NatGateway"
    177. Condition: DoAz2
    178. Properties:
    179. AllocationId:
    180. "Fn::GetAtt":
    181. - EIP2
    182. - AllocationId
    183. SubnetId: !Ref PublicSubnet2
    184. EIP2:
    185. Type: "AWS::EC2::EIP"
    186. Condition: DoAz2
    187. Properties:
    188. Domain: vpc
    189. Route2:
    190. Type: "AWS::EC2::Route"
    191. Condition: DoAz2
    192. Properties:
    193. RouteTableId:
    194. Ref: PrivateRouteTable2
    195. DestinationCidrBlock: 0.0.0.0/0
    196. NatGatewayId:
    197. Ref: NAT2
    198. PrivateSubnet3:
    199. Type: "AWS::EC2::Subnet"
    200. Condition: DoAz3
    201. Properties:
    202. VpcId: !Ref VPC
    203. CidrBlock: !Select [5, !Cidr [!Ref VpcCidr, 6, !Ref SubnetBits]]
    204. AvailabilityZone: !Select
    205. - 2
    206. - Fn::GetAZs: !Ref "AWS::Region"
    207. PrivateRouteTable3:
    208. Type: "AWS::EC2::RouteTable"
    209. Condition: DoAz3
    210. Properties:
    211. VpcId: !Ref VPC
    212. PrivateSubnetRouteTableAssociation3:
    213. Type: "AWS::EC2::SubnetRouteTableAssociation"
    214. Condition: DoAz3
    215. Properties:
    216. SubnetId: !Ref PrivateSubnet3
    217. RouteTableId: !Ref PrivateRouteTable3
    218. NAT3:
    219. DependsOn:
    220. - GatewayToInternet
    221. Type: "AWS::EC2::NatGateway"
    222. Condition: DoAz3
    223. Properties:
    224. AllocationId:
    225. "Fn::GetAtt":
    226. - EIP3
    227. - AllocationId
    228. SubnetId: !Ref PublicSubnet3
    229. EIP3:
    230. Type: "AWS::EC2::EIP"
    231. Condition: DoAz3
    232. Properties:
    233. Domain: vpc
    234. Route3:
    235. Type: "AWS::EC2::Route"
    236. Condition: DoAz3
    237. Properties:
    238. RouteTableId:
    239. Ref: PrivateRouteTable3
    240. DestinationCidrBlock: 0.0.0.0/0
    241. NatGatewayId:
    242. Ref: NAT3
    243. S3Endpoint:
    244. Type: AWS::EC2::VPCEndpoint
    245. Properties:
    246. PolicyDocument:
    247. Version: 2012-10-17
    248. Statement:
    249. - Effect: Allow
    250. Principal: '*'
    251. Action:
    252. - '*'
    253. Resource:
    254. - '*'
    255. RouteTableIds:
    256. - !Ref PublicRouteTable
    257. - !Ref PrivateRouteTable
    258. - !If [DoAz2, !Ref PrivateRouteTable2, !Ref "AWS::NoValue"]
    259. - !If [DoAz3, !Ref PrivateRouteTable3, !Ref "AWS::NoValue"]
    260. ServiceName: !Join
    261. - ''
    262. - - com.amazonaws.
    263. - !Ref 'AWS::Region'
    264. - .s3
    265. VpcId: !Ref VPC
    266. Outputs:
    267. VpcId:
    268. Description: ID of the new VPC.
    269. Value: !Ref VPC
    270. PublicSubnetIds:
    271. Description: Subnet IDs of the public subnets.
    272. Value:
    273. !Join [
    274. ",",
    275. [!Ref PublicSubnet, !If [DoAz2, !Ref PublicSubnet2, !Ref "AWS::NoValue"], !If [DoAz3, !Ref PublicSubnet3, !Ref "AWS::NoValue"]]
    276. ]
    277. PrivateSubnetIds:
    278. Description: Subnet IDs of the private subnets.
    279. Value:
    280. !Join [
    281. ",",
    282. [!Ref PrivateSubnet, !If [DoAz2, !Ref PrivateSubnet2, !Ref "AWS::NoValue"], !If [DoAz3, !Ref PrivateSubnet3, !Ref "AWS::NoValue"]]
    283. ]
    284. PublicRouteTableId:
    285. Description: Public Route table ID
    286. Value: !Ref PublicRouteTable

    You must configure networking and classic or network load balancing in Amazon Web Services (AWS) that your OKD 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 OKD 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:

      1For 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

      1. mycluster.example.com. False 100
      2. 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:

      1. [
      2. {
      3. "ParameterKey": "ClusterName", (1)
      4. "ParameterValue": "mycluster" (2)
      5. },
      6. {
      7. "ParameterKey": "InfrastructureName", (3)
      8. "ParameterValue": "mycluster-<random_string>" (4)
      9. {
      10. "ParameterKey": "HostedZoneId", (5)
      11. "ParameterValue": "<random_string>" (6)
      12. },
      13. {
      14. "ParameterKey": "HostedZoneName", (7)
      15. "ParameterValue": "example.com" (8)
      16. },
      17. {
      18. "ParameterKey": "PublicSubnets", (9)
      19. "ParameterValue": "subnet-<random_string>" (10)
      20. },
      21. {
      22. "ParameterKey": "PrivateSubnets", (11)
      23. "ParameterValue": "subnet-<random_string>" (12)
      24. },
      25. {
      26. "ParameterKey": "VpcId", (13)
      27. "ParameterValue": "vpc-<random_string>" (14)
      28. }
      29. ]
      1A short, representative cluster name to use for hostnames, etc.
      2Specify the cluster name that you used when you generated the install-config.yaml file for the cluster.
      3The name for your cluster infrastructure that is encoded in your Ignition config files for the cluster.
      4Specify the infrastructure name that you extracted from the Ignition config file metadata, which has the format <cluster-name>-<random-string>.
      5The Route 53 public zone ID to register the targets with.
      6Specify the Route 53 public zone ID, which as a format similar to Z21IXYZABCZ2A4. You can obtain this value from the AWS console.
      7The Route 53 zone to register the targets with.
      8Specify 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.
      9The public subnets that you created for your VPC.
      10Specify the PublicSubnetIds value from the output of the CloudFormation template for the VPC.
      11The private subnets that you created for your VPC.
      12Specify the PrivateSubnetIds value from the output of the CloudFormation template for the VPC.
      13The VPC that you created for the cluster.
      14Specify 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.

      1. $ aws cloudformation create-stack --stack-name <name> (1)
      2. --template-body file://<template>.yaml (2)
      3. --parameters file://<parameters>.json (3)
      4. --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.
      4You must explicitly declare the CAPABILITY_NAMED_IAM capability because the provided template creates some AWS::IAM::Role resources.

      Example output

      1. arn:aws:cloudformation:us-east-1:269333783861:stack/cluster-dns/cd3e5de0-2fd4-11eb-5cf0-12be5c33a183
    5. Confirm that the template components exist:

      1. $ 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 OKD cluster.

    CloudFormation template for the network and load balancers

    1. AWSTemplateFormatVersion: 2010-09-09
    2. Description: Template for OpenShift Cluster Network Elements (Route53 & LBs)
    3. Parameters:
    4. ClusterName:
    5. AllowedPattern: ^([a-zA-Z][a-zA-Z0-9\-]{0,26})$
    6. MaxLength: 27
    7. MinLength: 1
    8. ConstraintDescription: Cluster name must be alphanumeric, start with a letter, and have a maximum of 27 characters.
    9. Description: A short, representative cluster name to use for host names and other identifying names.
    10. Type: String
    11. InfrastructureName:
    12. AllowedPattern: ^([a-zA-Z][a-zA-Z0-9\-]{0,26})$
    13. MaxLength: 27
    14. MinLength: 1
    15. ConstraintDescription: Infrastructure name must be alphanumeric, start with a letter, and have a maximum of 27 characters.
    16. Description: A short, unique cluster ID used to tag cloud resources and identify items owned or used by the cluster.
    17. Type: String
    18. HostedZoneId:
    19. Description: The Route53 public zone ID to register the targets with, such as Z21IXYZABCZ2A4.
    20. Type: String
    21. HostedZoneName:
    22. Description: The Route53 zone to register the targets with, such as example.com. Omit the trailing period.
    23. Type: String
    24. Default: "example.com"
    25. PublicSubnets:
    26. Description: The internet-facing subnets.
    27. Type: List<AWS::EC2::Subnet::Id>
    28. PrivateSubnets:
    29. Description: The internal subnets.
    30. Type: List<AWS::EC2::Subnet::Id>
    31. VpcId:
    32. Description: The VPC-scoped resources will belong to this VPC.
    33. Type: AWS::EC2::VPC::Id
    34. Metadata:
    35. AWS::CloudFormation::Interface:
    36. ParameterGroups:
    37. - Label:
    38. default: "Cluster Information"
    39. Parameters:
    40. - ClusterName
    41. - InfrastructureName
    42. - Label:
    43. default: "Network Configuration"
    44. Parameters:
    45. - VpcId
    46. - PublicSubnets
    47. - PrivateSubnets
    48. - Label:
    49. default: "DNS"
    50. Parameters:
    51. - HostedZoneName
    52. - HostedZoneId
    53. ParameterLabels:
    54. ClusterName:
    55. default: "Cluster Name"
    56. InfrastructureName:
    57. default: "Infrastructure Name"
    58. VpcId:
    59. default: "VPC ID"
    60. PublicSubnets:
    61. default: "Public Subnets"
    62. PrivateSubnets:
    63. default: "Private Subnets"
    64. HostedZoneName:
    65. default: "Public Hosted Zone Name"
    66. HostedZoneId:
    67. default: "Public Hosted Zone ID"
    68. Resources:
    69. ExtApiElb:
    70. Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    71. Properties:
    72. Name: !Join ["-", [!Ref InfrastructureName, "ext"]]
    73. IpAddressType: ipv4
    74. Subnets: !Ref PublicSubnets
    75. Type: network
    76. IntApiElb:
    77. Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    78. Properties:
    79. Name: !Join ["-", [!Ref InfrastructureName, "int"]]
    80. Scheme: internal
    81. IpAddressType: ipv4
    82. Subnets: !Ref PrivateSubnets
    83. Type: network
    84. IntDns:
    85. Type: "AWS::Route53::HostedZone"
    86. Properties:
    87. HostedZoneConfig:
    88. Comment: "Managed by CloudFormation"
    89. Name: !Join [".", [!Ref ClusterName, !Ref HostedZoneName]]
    90. HostedZoneTags:
    91. - Key: Name
    92. Value: !Join ["-", [!Ref InfrastructureName, "int"]]
    93. - Key: !Join ["", ["kubernetes.io/cluster/", !Ref InfrastructureName]]
    94. Value: "owned"
    95. VPCs:
    96. - VPCId: !Ref VpcId
    97. VPCRegion: !Ref "AWS::Region"
    98. ExternalApiServerRecord:
    99. Type: AWS::Route53::RecordSetGroup
    100. Properties:
    101. Comment: Alias record for the API server
    102. HostedZoneId: !Ref HostedZoneId
    103. RecordSets:
    104. - Name:
    105. !Join [
    106. ".",
    107. ["api", !Ref ClusterName, !Join ["", [!Ref HostedZoneName, "."]]],
    108. ]
    109. Type: A
    110. AliasTarget:
    111. HostedZoneId: !GetAtt ExtApiElb.CanonicalHostedZoneID
    112. DNSName: !GetAtt ExtApiElb.DNSName
    113. InternalApiServerRecord:
    114. Type: AWS::Route53::RecordSetGroup
    115. Properties:
    116. Comment: Alias record for the API server
    117. HostedZoneId: !Ref IntDns
    118. RecordSets:
    119. - Name:
    120. !Join [
    121. ".",
    122. ["api", !Ref ClusterName, !Join ["", [!Ref HostedZoneName, "."]]],
    123. ]
    124. Type: A
    125. AliasTarget:
    126. HostedZoneId: !GetAtt IntApiElb.CanonicalHostedZoneID
    127. DNSName: !GetAtt IntApiElb.DNSName
    128. - Name:
    129. !Join [
    130. ".",
    131. ["api-int", !Ref ClusterName, !Join ["", [!Ref HostedZoneName, "."]]],
    132. ]
    133. Type: A
    134. AliasTarget:
    135. HostedZoneId: !GetAtt IntApiElb.CanonicalHostedZoneID
    136. DNSName: !GetAtt IntApiElb.DNSName
    137. ExternalApiListener:
    138. Type: AWS::ElasticLoadBalancingV2::Listener
    139. Properties:
    140. DefaultActions:
    141. - Type: forward
    142. Ref: ExternalApiTargetGroup
    143. LoadBalancerArn:
    144. Ref: ExtApiElb
    145. Port: 6443
    146. Protocol: TCP
    147. ExternalApiTargetGroup:
    148. Type: AWS::ElasticLoadBalancingV2::TargetGroup
    149. Properties:
    150. HealthCheckIntervalSeconds: 10
    151. HealthCheckPath: "/readyz"
    152. HealthCheckPort: 6443
    153. HealthCheckProtocol: HTTPS
    154. HealthyThresholdCount: 2
    155. UnhealthyThresholdCount: 2
    156. Port: 6443
    157. Protocol: TCP
    158. TargetType: ip
    159. VpcId:
    160. Ref: VpcId
    161. TargetGroupAttributes:
    162. - Key: deregistration_delay.timeout_seconds
    163. Value: 60
    164. InternalApiListener:
    165. Type: AWS::ElasticLoadBalancingV2::Listener
    166. Properties:
    167. DefaultActions:
    168. - Type: forward
    169. TargetGroupArn:
    170. Ref: InternalApiTargetGroup
    171. LoadBalancerArn:
    172. Ref: IntApiElb
    173. Port: 6443
    174. Protocol: TCP
    175. InternalApiTargetGroup:
    176. Type: AWS::ElasticLoadBalancingV2::TargetGroup
    177. Properties:
    178. HealthCheckIntervalSeconds: 10
    179. HealthCheckPath: "/readyz"
    180. HealthCheckPort: 6443
    181. HealthCheckProtocol: HTTPS
    182. HealthyThresholdCount: 2
    183. UnhealthyThresholdCount: 2
    184. Port: 6443
    185. Protocol: TCP
    186. TargetType: ip
    187. VpcId:
    188. Ref: VpcId
    189. TargetGroupAttributes:
    190. - Key: deregistration_delay.timeout_seconds
    191. Value: 60
    192. InternalServiceInternalListener:
    193. Type: AWS::ElasticLoadBalancingV2::Listener
    194. Properties:
    195. DefaultActions:
    196. - Type: forward
    197. TargetGroupArn:
    198. Ref: InternalServiceTargetGroup
    199. LoadBalancerArn:
    200. Ref: IntApiElb
    201. Port: 22623
    202. Protocol: TCP
    203. InternalServiceTargetGroup:
    204. Type: AWS::ElasticLoadBalancingV2::TargetGroup
    205. Properties:
    206. HealthCheckIntervalSeconds: 10
    207. HealthCheckPath: "/healthz"
    208. HealthCheckPort: 22623
    209. HealthCheckProtocol: HTTPS
    210. HealthyThresholdCount: 2
    211. UnhealthyThresholdCount: 2
    212. Port: 22623
    213. Protocol: TCP
    214. TargetType: ip
    215. VpcId:
    216. Ref: VpcId
    217. TargetGroupAttributes:
    218. - Key: deregistration_delay.timeout_seconds
    219. Value: 60
    220. RegisterTargetLambdaIamRole:
    221. Type: AWS::IAM::Role
    222. Properties:
    223. RoleName: !Join ["-", [!Ref InfrastructureName, "nlb", "lambda", "role"]]
    224. AssumeRolePolicyDocument:
    225. Version: "2012-10-17"
    226. Statement:
    227. - Effect: "Allow"
    228. Principal:
    229. Service:
    230. - "lambda.amazonaws.com"
    231. Action:
    232. - "sts:AssumeRole"
    233. Path: "/"
    234. Policies:
    235. - PolicyName: !Join ["-", [!Ref InfrastructureName, "master", "policy"]]
    236. PolicyDocument:
    237. Version: "2012-10-17"
    238. Statement:
    239. - Effect: "Allow"
    240. Action:
    241. [
    242. "elasticloadbalancing:RegisterTargets",
    243. "elasticloadbalancing:DeregisterTargets",
    244. ]
    245. Resource: !Ref InternalApiTargetGroup
    246. - Effect: "Allow"
    247. Action:
    248. [
    249. "elasticloadbalancing:RegisterTargets",
    250. "elasticloadbalancing:DeregisterTargets",
    251. ]
    252. Resource: !Ref InternalServiceTargetGroup
    253. - Effect: "Allow"
    254. Action:
    255. [
    256. "elasticloadbalancing:RegisterTargets",
    257. "elasticloadbalancing:DeregisterTargets",
    258. ]
    259. Resource: !Ref ExternalApiTargetGroup
    260. RegisterNlbIpTargets:
    261. Type: "AWS::Lambda::Function"
    262. Properties:
    263. Handler: "index.handler"
    264. Role:
    265. Fn::GetAtt:
    266. - "RegisterTargetLambdaIamRole"
    267. - "Arn"
    268. Code:
    269. ZipFile: |
    270. import json
    271. import boto3
    272. import cfnresponse
    273. def handler(event, context):
    274. elb = boto3.client('elbv2')
    275. if event['RequestType'] == 'Delete':
    276. elb.deregister_targets(TargetGroupArn=event['ResourceProperties']['TargetArn'],Targets=[{'Id': event['ResourceProperties']['TargetIp']}])
    277. elif event['RequestType'] == 'Create':
    278. elb.register_targets(TargetGroupArn=event['ResourceProperties']['TargetArn'],Targets=[{'Id': event['ResourceProperties']['TargetIp']}])
    279. responseData = {}
    280. cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, event['ResourceProperties']['TargetArn']+event['ResourceProperties']['TargetIp'])
    281. Runtime: "python3.8"
    282. Timeout: 120
    283. RegisterSubnetTagsLambdaIamRole:
    284. Type: AWS::IAM::Role
    285. Properties:
    286. RoleName: !Join ["-", [!Ref InfrastructureName, "subnet-tags-lambda-role"]]
    287. AssumeRolePolicyDocument:
    288. Version: "2012-10-17"
    289. Statement:
    290. - Effect: "Allow"
    291. Principal:
    292. Service:
    293. - "lambda.amazonaws.com"
    294. Action:
    295. - "sts:AssumeRole"
    296. Path: "/"
    297. Policies:
    298. - PolicyName: !Join ["-", [!Ref InfrastructureName, "subnet-tagging-policy"]]
    299. PolicyDocument:
    300. Version: "2012-10-17"
    301. Statement:
    302. - Effect: "Allow"
    303. Action:
    304. [
    305. "ec2:DeleteTags",
    306. "ec2:CreateTags"
    307. ]
    308. Resource: "arn:aws:ec2:*:*:subnet/*"
    309. - Effect: "Allow"
    310. Action:
    311. [
    312. "ec2:DescribeSubnets",
    313. "ec2:DescribeTags"
    314. ]
    315. Resource: "*"
    316. RegisterSubnetTags:
    317. Type: "AWS::Lambda::Function"
    318. Properties:
    319. Handler: "index.handler"
    320. Role:
    321. Fn::GetAtt:
    322. - "RegisterSubnetTagsLambdaIamRole"
    323. - "Arn"
    324. Code:
    325. ZipFile: |
    326. import json
    327. import boto3
    328. import cfnresponse
    329. def handler(event, context):
    330. ec2_client = boto3.client('ec2')
    331. if event['RequestType'] == 'Delete':
    332. for subnet_id in event['ResourceProperties']['Subnets']:
    333. ec2_client.delete_tags(Resources=[subnet_id], Tags=[{'Key': 'kubernetes.io/cluster/' + event['ResourceProperties']['InfrastructureName']}]);
    334. elif event['RequestType'] == 'Create':
    335. for subnet_id in event['ResourceProperties']['Subnets']:
    336. ec2_client.create_tags(Resources=[subnet_id], Tags=[{'Key': 'kubernetes.io/cluster/' + event['ResourceProperties']['InfrastructureName'], 'Value': 'shared'}]);
    337. responseData = {}
    338. cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, event['ResourceProperties']['InfrastructureName']+event['ResourceProperties']['Subnets'][0])
    339. Runtime: "python3.8"
    340. Timeout: 120
    341. RegisterPublicSubnetTags:
    342. Type: Custom::SubnetRegister
    343. Properties:
    344. ServiceToken: !GetAtt RegisterSubnetTags.Arn
    345. InfrastructureName: !Ref InfrastructureName
    346. Subnets: !Ref PublicSubnets
    347. RegisterPrivateSubnetTags:
    348. Type: Custom::SubnetRegister
    349. Properties:
    350. ServiceToken: !GetAtt RegisterSubnetTags.Arn
    351. InfrastructureName: !Ref InfrastructureName
    352. Subnets: !Ref PrivateSubnets
    353. Outputs:
    354. PrivateHostedZoneId:
    355. Description: Hosted zone ID for the private DNS, which is required for private records.
    356. Value: !Ref IntDns
    357. ExternalApiLoadBalancerName:
    358. Description: Full name of the external API load balancer.
    359. Value: !GetAtt ExtApiElb.LoadBalancerFullName
    360. InternalApiLoadBalancerName:
    361. Description: Full name of the internal API load balancer.
    362. Value: !GetAtt IntApiElb.LoadBalancerFullName
    363. ApiServerDnsName:
    364. Description: Full hostname of the API server, which is required for the Ignition config files.
    365. Value: !Join [".", ["api-int", !Ref ClusterName, !Ref HostedZoneName]]
    366. RegisterNlbIpTargetsLambda:
    367. Description: Lambda ARN useful to help register or deregister IP targets for these load balancers.
    368. Value: !GetAtt RegisterNlbIpTargets.Arn
    369. ExternalApiTargetGroupArn:
    370. Description: ARN of the external API target group.
    371. Value: !Ref ExternalApiTargetGroup
    372. InternalApiTargetGroupArn:
    373. Description: ARN of the internal API target group.
    374. Value: !Ref InternalApiTargetGroup
    375. InternalServiceTargetGroupArn:
    376. Description: ARN of the internal service target group.
    377. Value: !Ref InternalServiceTargetGroup

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

    1. Type: CNAME
    2. TTL: 10
    3. ResourceRecords:
    4. - !GetAtt IntApiElb.DNSName

    Additional resources

    Creating security group and roles in AWS

    You must create security groups and roles in Amazon Web Services (AWS) for your OKD cluster to use.

    You can use the provided CloudFormation template and a custom parameter file to create a stack of AWS resources. The stack represents the security groups and roles that your OKD cluster requires.

    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. Create a JSON file that contains the parameter values that the template requires:

      1. [
      2. {
      3. "ParameterKey": "InfrastructureName", (1)
      4. "ParameterValue": "mycluster-<random_string>" (2)
      5. },
      6. {
      7. "ParameterKey": "VpcCidr", (3)
      8. "ParameterValue": "10.0.0.0/16" (4)
      9. },
      10. {
      11. "ParameterKey": "PrivateSubnets", (5)
      12. "ParameterValue": "subnet-<random_string>" (6)
      13. },
      14. {
      15. "ParameterKey": "VpcId", (7)
      16. "ParameterValue": "vpc-<random_string>" (8)
      17. }
      18. ]
      1The name for your cluster infrastructure that is encoded in your Ignition config files for the cluster.
      2Specify the infrastructure name that you extracted from the Ignition config file metadata, which has the format <cluster-name>-<random-string>.
      3The CIDR block for the VPC.
      4Specify the CIDR block parameter that you used for the VPC that you defined in the form x.x.x.x/16-24.
      5The private subnets that you created for your VPC.
      6Specify the PrivateSubnetIds value from the output of the CloudFormation template for the VPC.
      7The VPC that you created for the cluster.
      8Specify the VpcId value from the output of the CloudFormation template for the VPC.
    2. Copy the template from the CloudFormation template for security objects section of this topic and save it as a YAML file on your computer. This template describes the security groups and roles that your cluster requires.

    3. Launch the CloudFormation template to create a stack of AWS resources that represent the security groups and roles:

      You must enter the command on a single line.

      1. $ aws cloudformation create-stack --stack-name <name> (1)
      2. --template-body file://<template>.yaml (2)
      3. --parameters file://<parameters>.json (3)
      4. --capabilities CAPABILITY_NAMED_IAM (4)
      1<name> is the name for the CloudFormation stack, such as cluster-sec. 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.
      4You must explicitly declare the CAPABILITY_NAMED_IAM capability because the provided template creates some AWS::IAM::Role and AWS::IAM::InstanceProfile resources.

      Example output

      1. arn:aws:cloudformation:us-east-1:269333783861:stack/cluster-sec/03bd4210-2ed7-11eb-6d7a-13fc0b61e9db
    4. Confirm that the template components exist:

      1. $ 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:

      MasterSecurityGroupId

      Master Security Group ID

      WorkerSecurityGroupId

      Worker Security Group ID

      MasterInstanceProfile

      Master IAM Instance Profile

      WorkerInstanceProfile

      Worker IAM Instance Profile

    CloudFormation template for security objects

    You can use the following CloudFormation template to deploy the security objects that you need for your OKD cluster.

    CloudFormation template for security objects

    1. AWSTemplateFormatVersion: 2010-09-09
    2. Description: Template for OpenShift Cluster Security Elements (Security Groups & IAM)
    3. Parameters:
    4. InfrastructureName:
    5. AllowedPattern: ^([a-zA-Z][a-zA-Z0-9\-]{0,26})$
    6. MaxLength: 27
    7. MinLength: 1
    8. ConstraintDescription: Infrastructure name must be alphanumeric, start with a letter, and have a maximum of 27 characters.
    9. Description: A short, unique cluster ID used to tag cloud resources and identify items owned or used by the cluster.
    10. Type: String
    11. VpcCidr:
    12. 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]))$
    13. ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-24.
    14. Default: 10.0.0.0/16
    15. Description: CIDR block for VPC.
    16. Type: String
    17. VpcId:
    18. Description: The VPC-scoped resources will belong to this VPC.
    19. Type: AWS::EC2::VPC::Id
    20. PrivateSubnets:
    21. Description: The internal subnets.
    22. Type: List<AWS::EC2::Subnet::Id>
    23. Metadata:
    24. AWS::CloudFormation::Interface:
    25. ParameterGroups:
    26. - Label:
    27. default: "Cluster Information"
    28. Parameters:
    29. - InfrastructureName
    30. - Label:
    31. default: "Network Configuration"
    32. Parameters:
    33. - VpcId
    34. - VpcCidr
    35. - PrivateSubnets
    36. ParameterLabels:
    37. InfrastructureName:
    38. default: "Infrastructure Name"
    39. VpcId:
    40. default: "VPC ID"
    41. VpcCidr:
    42. default: "VPC CIDR"
    43. PrivateSubnets:
    44. default: "Private Subnets"
    45. Resources:
    46. MasterSecurityGroup:
    47. Type: AWS::EC2::SecurityGroup
    48. Properties:
    49. GroupDescription: Cluster Master Security Group
    50. SecurityGroupIngress:
    51. - IpProtocol: icmp
    52. FromPort: 0
    53. ToPort: 0
    54. CidrIp: !Ref VpcCidr
    55. - IpProtocol: tcp
    56. FromPort: 22
    57. ToPort: 22
    58. CidrIp: !Ref VpcCidr
    59. - IpProtocol: tcp
    60. ToPort: 6443
    61. FromPort: 6443
    62. CidrIp: !Ref VpcCidr
    63. - IpProtocol: tcp
    64. FromPort: 22623
    65. ToPort: 22623
    66. CidrIp: !Ref VpcCidr
    67. VpcId: !Ref VpcId
    68. WorkerSecurityGroup:
    69. Type: AWS::EC2::SecurityGroup
    70. Properties:
    71. GroupDescription: Cluster Worker Security Group
    72. SecurityGroupIngress:
    73. - IpProtocol: icmp
    74. FromPort: 0
    75. ToPort: 0
    76. CidrIp: !Ref VpcCidr
    77. - IpProtocol: tcp
    78. FromPort: 22
    79. ToPort: 22
    80. CidrIp: !Ref VpcCidr
    81. VpcId: !Ref VpcId
    82. MasterIngressEtcd:
    83. Type: AWS::EC2::SecurityGroupIngress
    84. Properties:
    85. GroupId: !GetAtt MasterSecurityGroup.GroupId
    86. SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
    87. Description: etcd
    88. FromPort: 2379
    89. ToPort: 2380
    90. IpProtocol: tcp
    91. MasterIngressVxlan:
    92. Type: AWS::EC2::SecurityGroupIngress
    93. Properties:
    94. GroupId: !GetAtt MasterSecurityGroup.GroupId
    95. SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
    96. Description: Vxlan packets
    97. FromPort: 4789
    98. ToPort: 4789
    99. IpProtocol: udp
    100. MasterIngressWorkerVxlan:
    101. Type: AWS::EC2::SecurityGroupIngress
    102. Properties:
    103. GroupId: !GetAtt MasterSecurityGroup.GroupId
    104. SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
    105. Description: Vxlan packets
    106. FromPort: 4789
    107. ToPort: 4789
    108. IpProtocol: udp
    109. MasterIngressGeneve:
    110. Type: AWS::EC2::SecurityGroupIngress
    111. Properties:
    112. GroupId: !GetAtt MasterSecurityGroup.GroupId
    113. SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
    114. Description: Geneve packets
    115. FromPort: 6081
    116. ToPort: 6081
    117. IpProtocol: udp
    118. MasterIngressWorkerGeneve:
    119. Type: AWS::EC2::SecurityGroupIngress
    120. Properties:
    121. GroupId: !GetAtt MasterSecurityGroup.GroupId
    122. SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
    123. Description: Geneve packets
    124. FromPort: 6081
    125. ToPort: 6081
    126. IpProtocol: udp
    127. MasterIngressIpsecIke:
    128. Type: AWS::EC2::SecurityGroupIngress
    129. Properties:
    130. GroupId: !GetAtt MasterSecurityGroup.GroupId
    131. SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
    132. Description: IPsec IKE packets
    133. FromPort: 500
    134. ToPort: 500
    135. IpProtocol: udp
    136. MasterIngressIpsecNat:
    137. Type: AWS::EC2::SecurityGroupIngress
    138. Properties:
    139. GroupId: !GetAtt MasterSecurityGroup.GroupId
    140. SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
    141. Description: IPsec NAT-T packets
    142. FromPort: 4500
    143. ToPort: 4500
    144. IpProtocol: udp
    145. MasterIngressIpsecEsp:
    146. Type: AWS::EC2::SecurityGroupIngress
    147. Properties:
    148. GroupId: !GetAtt MasterSecurityGroup.GroupId
    149. SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
    150. Description: IPsec ESP packets
    151. IpProtocol: 50
    152. MasterIngressWorkerIpsecIke:
    153. Type: AWS::EC2::SecurityGroupIngress
    154. Properties:
    155. GroupId: !GetAtt MasterSecurityGroup.GroupId
    156. SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
    157. Description: IPsec IKE packets
    158. FromPort: 500
    159. ToPort: 500
    160. IpProtocol: udp
    161. MasterIngressWorkerIpsecNat:
    162. Type: AWS::EC2::SecurityGroupIngress
    163. Properties:
    164. GroupId: !GetAtt MasterSecurityGroup.GroupId
    165. SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
    166. Description: IPsec NAT-T packets
    167. FromPort: 4500
    168. ToPort: 4500
    169. IpProtocol: udp
    170. MasterIngressWorkerIpsecEsp:
    171. Type: AWS::EC2::SecurityGroupIngress
    172. Properties:
    173. GroupId: !GetAtt MasterSecurityGroup.GroupId
    174. SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
    175. Description: IPsec ESP packets
    176. IpProtocol: 50
    177. MasterIngressInternal:
    178. Type: AWS::EC2::SecurityGroupIngress
    179. Properties:
    180. GroupId: !GetAtt MasterSecurityGroup.GroupId
    181. SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
    182. Description: Internal cluster communication
    183. FromPort: 9000
    184. ToPort: 9999
    185. IpProtocol: tcp
    186. MasterIngressWorkerInternal:
    187. Type: AWS::EC2::SecurityGroupIngress
    188. Properties:
    189. GroupId: !GetAtt MasterSecurityGroup.GroupId
    190. SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
    191. Description: Internal cluster communication
    192. FromPort: 9000
    193. ToPort: 9999
    194. IpProtocol: tcp
    195. MasterIngressInternalUDP:
    196. Type: AWS::EC2::SecurityGroupIngress
    197. Properties:
    198. GroupId: !GetAtt MasterSecurityGroup.GroupId
    199. SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
    200. Description: Internal cluster communication
    201. FromPort: 9000
    202. ToPort: 9999
    203. IpProtocol: udp
    204. MasterIngressWorkerInternalUDP:
    205. Type: AWS::EC2::SecurityGroupIngress
    206. Properties:
    207. GroupId: !GetAtt MasterSecurityGroup.GroupId
    208. SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
    209. Description: Internal cluster communication
    210. FromPort: 9000
    211. ToPort: 9999
    212. IpProtocol: udp
    213. MasterIngressKube:
    214. Type: AWS::EC2::SecurityGroupIngress
    215. Properties:
    216. GroupId: !GetAtt MasterSecurityGroup.GroupId
    217. SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
    218. Description: Kubernetes kubelet, scheduler and controller manager
    219. FromPort: 10250
    220. ToPort: 10259
    221. IpProtocol: tcp
    222. MasterIngressWorkerKube:
    223. Type: AWS::EC2::SecurityGroupIngress
    224. Properties:
    225. GroupId: !GetAtt MasterSecurityGroup.GroupId
    226. SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
    227. Description: Kubernetes kubelet, scheduler and controller manager
    228. FromPort: 10250
    229. ToPort: 10259
    230. IpProtocol: tcp
    231. MasterIngressIngressServices:
    232. Type: AWS::EC2::SecurityGroupIngress
    233. Properties:
    234. GroupId: !GetAtt MasterSecurityGroup.GroupId
    235. SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
    236. Description: Kubernetes ingress services
    237. FromPort: 30000
    238. ToPort: 32767
    239. IpProtocol: tcp
    240. MasterIngressWorkerIngressServices:
    241. Type: AWS::EC2::SecurityGroupIngress
    242. Properties:
    243. GroupId: !GetAtt MasterSecurityGroup.GroupId
    244. SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
    245. Description: Kubernetes ingress services
    246. FromPort: 30000
    247. ToPort: 32767
    248. IpProtocol: tcp
    249. MasterIngressIngressServicesUDP:
    250. Type: AWS::EC2::SecurityGroupIngress
    251. Properties:
    252. GroupId: !GetAtt MasterSecurityGroup.GroupId
    253. SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
    254. Description: Kubernetes ingress services
    255. FromPort: 30000
    256. ToPort: 32767
    257. IpProtocol: udp
    258. MasterIngressWorkerIngressServicesUDP:
    259. Type: AWS::EC2::SecurityGroupIngress
    260. Properties:
    261. GroupId: !GetAtt MasterSecurityGroup.GroupId
    262. SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
    263. Description: Kubernetes ingress services
    264. FromPort: 30000
    265. ToPort: 32767
    266. IpProtocol: udp
    267. WorkerIngressVxlan:
    268. Type: AWS::EC2::SecurityGroupIngress
    269. Properties:
    270. GroupId: !GetAtt WorkerSecurityGroup.GroupId
    271. SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
    272. Description: Vxlan packets
    273. FromPort: 4789
    274. ToPort: 4789
    275. IpProtocol: udp
    276. WorkerIngressMasterVxlan:
    277. Type: AWS::EC2::SecurityGroupIngress
    278. Properties:
    279. GroupId: !GetAtt WorkerSecurityGroup.GroupId
    280. SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
    281. Description: Vxlan packets
    282. FromPort: 4789
    283. ToPort: 4789
    284. IpProtocol: udp
    285. WorkerIngressGeneve:
    286. Type: AWS::EC2::SecurityGroupIngress
    287. Properties:
    288. GroupId: !GetAtt WorkerSecurityGroup.GroupId
    289. SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
    290. Description: Geneve packets
    291. FromPort: 6081
    292. ToPort: 6081
    293. IpProtocol: udp
    294. WorkerIngressMasterGeneve:
    295. Type: AWS::EC2::SecurityGroupIngress
    296. Properties:
    297. GroupId: !GetAtt WorkerSecurityGroup.GroupId
    298. SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
    299. Description: Geneve packets
    300. FromPort: 6081
    301. ToPort: 6081
    302. IpProtocol: udp
    303. WorkerIngressIpsecIke:
    304. Type: AWS::EC2::SecurityGroupIngress
    305. Properties:
    306. GroupId: !GetAtt WorkerSecurityGroup.GroupId
    307. SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
    308. Description: IPsec IKE packets
    309. FromPort: 500
    310. ToPort: 500
    311. IpProtocol: udp
    312. WorkerIngressIpsecNat:
    313. Type: AWS::EC2::SecurityGroupIngress
    314. Properties:
    315. GroupId: !GetAtt WorkerSecurityGroup.GroupId
    316. SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
    317. Description: IPsec NAT-T packets
    318. FromPort: 4500
    319. ToPort: 4500
    320. IpProtocol: udp
    321. WorkerIngressIpsecEsp:
    322. Type: AWS::EC2::SecurityGroupIngress
    323. Properties:
    324. GroupId: !GetAtt WorkerSecurityGroup.GroupId
    325. SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
    326. Description: IPsec ESP packets
    327. IpProtocol: 50
    328. WorkerIngressMasterIpsecIke:
    329. Type: AWS::EC2::SecurityGroupIngress
    330. Properties:
    331. GroupId: !GetAtt WorkerSecurityGroup.GroupId
    332. SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
    333. Description: IPsec IKE packets
    334. FromPort: 500
    335. ToPort: 500
    336. IpProtocol: udp
    337. WorkerIngressMasterIpsecNat:
    338. Type: AWS::EC2::SecurityGroupIngress
    339. Properties:
    340. GroupId: !GetAtt WorkerSecurityGroup.GroupId
    341. SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
    342. Description: IPsec NAT-T packets
    343. FromPort: 4500
    344. ToPort: 4500
    345. IpProtocol: udp
    346. WorkerIngressMasterIpsecEsp:
    347. Type: AWS::EC2::SecurityGroupIngress
    348. Properties:
    349. GroupId: !GetAtt WorkerSecurityGroup.GroupId
    350. SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
    351. Description: IPsec ESP packets
    352. IpProtocol: 50
    353. WorkerIngressInternal:
    354. Type: AWS::EC2::SecurityGroupIngress
    355. Properties:
    356. GroupId: !GetAtt WorkerSecurityGroup.GroupId
    357. SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
    358. Description: Internal cluster communication
    359. FromPort: 9000
    360. ToPort: 9999
    361. IpProtocol: tcp
    362. WorkerIngressMasterInternal:
    363. Type: AWS::EC2::SecurityGroupIngress
    364. Properties:
    365. GroupId: !GetAtt WorkerSecurityGroup.GroupId
    366. SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
    367. Description: Internal cluster communication
    368. FromPort: 9000
    369. ToPort: 9999
    370. IpProtocol: tcp
    371. WorkerIngressInternalUDP:
    372. Type: AWS::EC2::SecurityGroupIngress
    373. Properties:
    374. GroupId: !GetAtt WorkerSecurityGroup.GroupId
    375. SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
    376. Description: Internal cluster communication
    377. FromPort: 9000
    378. ToPort: 9999
    379. IpProtocol: udp
    380. WorkerIngressMasterInternalUDP:
    381. Type: AWS::EC2::SecurityGroupIngress
    382. Properties:
    383. GroupId: !GetAtt WorkerSecurityGroup.GroupId
    384. SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
    385. Description: Internal cluster communication
    386. FromPort: 9000
    387. ToPort: 9999
    388. IpProtocol: udp
    389. WorkerIngressKube:
    390. Type: AWS::EC2::SecurityGroupIngress
    391. Properties:
    392. GroupId: !GetAtt WorkerSecurityGroup.GroupId
    393. SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
    394. Description: Kubernetes secure kubelet port
    395. FromPort: 10250
    396. ToPort: 10250
    397. IpProtocol: tcp
    398. WorkerIngressWorkerKube:
    399. Type: AWS::EC2::SecurityGroupIngress
    400. Properties:
    401. GroupId: !GetAtt WorkerSecurityGroup.GroupId
    402. SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
    403. Description: Internal Kubernetes communication
    404. FromPort: 10250
    405. ToPort: 10250
    406. IpProtocol: tcp
    407. WorkerIngressIngressServices:
    408. Type: AWS::EC2::SecurityGroupIngress
    409. Properties:
    410. GroupId: !GetAtt WorkerSecurityGroup.GroupId
    411. SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
    412. Description: Kubernetes ingress services
    413. FromPort: 30000
    414. ToPort: 32767
    415. IpProtocol: tcp
    416. WorkerIngressMasterIngressServices:
    417. Type: AWS::EC2::SecurityGroupIngress
    418. Properties:
    419. GroupId: !GetAtt WorkerSecurityGroup.GroupId
    420. SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
    421. Description: Kubernetes ingress services
    422. FromPort: 30000
    423. ToPort: 32767
    424. IpProtocol: tcp
    425. WorkerIngressIngressServicesUDP:
    426. Type: AWS::EC2::SecurityGroupIngress
    427. Properties:
    428. GroupId: !GetAtt WorkerSecurityGroup.GroupId
    429. SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
    430. Description: Kubernetes ingress services
    431. FromPort: 30000
    432. ToPort: 32767
    433. IpProtocol: udp
    434. WorkerIngressMasterIngressServicesUDP:
    435. Type: AWS::EC2::SecurityGroupIngress
    436. Properties:
    437. GroupId: !GetAtt WorkerSecurityGroup.GroupId
    438. SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
    439. Description: Kubernetes ingress services
    440. FromPort: 30000
    441. ToPort: 32767
    442. IpProtocol: udp
    443. MasterIamRole:
    444. Type: AWS::IAM::Role
    445. Properties:
    446. AssumeRolePolicyDocument:
    447. Version: "2012-10-17"
    448. Statement:
    449. - Effect: "Allow"
    450. Principal:
    451. Service:
    452. - "ec2.amazonaws.com"
    453. Action:
    454. - "sts:AssumeRole"
    455. Policies:
    456. - PolicyName: !Join ["-", [!Ref InfrastructureName, "master", "policy"]]
    457. PolicyDocument:
    458. Version: "2012-10-17"
    459. Statement:
    460. - Effect: "Allow"
    461. Action:
    462. - "ec2:AttachVolume"
    463. - "ec2:AuthorizeSecurityGroupIngress"
    464. - "ec2:CreateSecurityGroup"
    465. - "ec2:CreateTags"
    466. - "ec2:CreateVolume"
    467. - "ec2:DeleteSecurityGroup"
    468. - "ec2:DeleteVolume"
    469. - "ec2:Describe*"
    470. - "ec2:DetachVolume"
    471. - "ec2:ModifyInstanceAttribute"
    472. - "ec2:ModifyVolume"
    473. - "ec2:RevokeSecurityGroupIngress"
    474. - "elasticloadbalancing:AddTags"
    475. - "elasticloadbalancing:AttachLoadBalancerToSubnets"
    476. - "elasticloadbalancing:ApplySecurityGroupsToLoadBalancer"
    477. - "elasticloadbalancing:CreateListener"
    478. - "elasticloadbalancing:CreateLoadBalancer"
    479. - "elasticloadbalancing:CreateLoadBalancerPolicy"
    480. - "elasticloadbalancing:CreateLoadBalancerListeners"
    481. - "elasticloadbalancing:CreateTargetGroup"
    482. - "elasticloadbalancing:ConfigureHealthCheck"
    483. - "elasticloadbalancing:DeleteListener"
    484. - "elasticloadbalancing:DeleteLoadBalancer"
    485. - "elasticloadbalancing:DeleteLoadBalancerListeners"
    486. - "elasticloadbalancing:DeleteTargetGroup"
    487. - "elasticloadbalancing:DeregisterInstancesFromLoadBalancer"
    488. - "elasticloadbalancing:DeregisterTargets"
    489. - "elasticloadbalancing:Describe*"
    490. - "elasticloadbalancing:DetachLoadBalancerFromSubnets"
    491. - "elasticloadbalancing:ModifyListener"
    492. - "elasticloadbalancing:ModifyLoadBalancerAttributes"
    493. - "elasticloadbalancing:ModifyTargetGroup"
    494. - "elasticloadbalancing:ModifyTargetGroupAttributes"
    495. - "elasticloadbalancing:RegisterInstancesWithLoadBalancer"
    496. - "elasticloadbalancing:RegisterTargets"
    497. - "elasticloadbalancing:SetLoadBalancerPoliciesForBackendServer"
    498. - "elasticloadbalancing:SetLoadBalancerPoliciesOfListener"
    499. - "kms:DescribeKey"
    500. Resource: "*"
    501. MasterInstanceProfile:
    502. Type: "AWS::IAM::InstanceProfile"
    503. Properties:
    504. Roles:
    505. - Ref: "MasterIamRole"
    506. WorkerIamRole:
    507. Type: AWS::IAM::Role
    508. Properties:
    509. AssumeRolePolicyDocument:
    510. Version: "2012-10-17"
    511. Statement:
    512. - Effect: "Allow"
    513. Principal:
    514. Service:
    515. - "ec2.amazonaws.com"
    516. Action:
    517. - "sts:AssumeRole"
    518. Policies:
    519. - PolicyName: !Join ["-", [!Ref InfrastructureName, "worker", "policy"]]
    520. PolicyDocument:
    521. Version: "2012-10-17"
    522. Statement:
    523. - Effect: "Allow"
    524. Action:
    525. - "ec2:DescribeInstances"
    526. - "ec2:DescribeRegions"
    527. Resource: "*"
    528. WorkerInstanceProfile:
    529. Type: "AWS::IAM::InstanceProfile"
    530. Properties:
    531. Roles:
    532. - Ref: "WorkerIamRole"
    533. Outputs:
    534. MasterSecurityGroupId:
    535. Description: Master Security Group ID
    536. Value: !GetAtt MasterSecurityGroup.GroupId
    537. WorkerSecurityGroupId:
    538. Description: Worker Security Group ID
    539. Value: !GetAtt WorkerSecurityGroup.GroupId
    540. MasterInstanceProfile:
    541. Description: Master IAM Instance Profile
    542. Value: !Ref MasterInstanceProfile
    543. WorkerInstanceProfile:
    544. Description: Worker IAM Instance Profile
    545. Value: !Ref WorkerInstanceProfile

    Accessing FCOS AMIs with stream metadata

    In OKD, stream metadata provides standardized metadata about FCOS in the JSON format and injects the metadata into the cluster. Stream metadata is a stable format that supports multiple architectures and is intended to be self-documenting for maintaining automation.

    You can use the coreos print-stream-json sub-command of openshift-install to access information about the boot images in the stream metadata format. This command provides a method for printing stream metadata in a scriptable, machine-readable format.

    For user-provisioned installations, the openshift-install binary contains references to the version of FCOS boot images that are tested for use with OKD, such as the AWS AMI.

    Procedure

    To parse the stream metadata, use one of the following methods:

    • From a Go program, use the official library at https://github.com/coreos/stream-metadata-go. You can also view example code in the library.

    • From another programming language, such as Python or Ruby, use the JSON library of your preferred programming language.

    • From a command-line utility that handles JSON data, such as jq:

      • Print the current x86_64 AMI for an AWS region, such as us-west-1:

        For x86_64

        1. $ openshift-install coreos print-stream-json | jq -r '.architectures.x86_64.images.aws.regions["us-west-1"].image'

        Example output

        1. ami-0d3e625f84626bbda

        The output of this command is the AWS AMI ID for your designated architecture and the us-west-1 region. The AMI must belong to the same region as the cluster.

    FCOS AMIs for the AWS infrastructure

    Red Hat provides Fedora CoreOS (FCOS) AMIs that are valid for the various AWS regions and instance architectures that you can manually specify for your OKD nodes.

    By importing your own AMI, you can also install to regions that do not have a published FCOS AMI.

    Creating the bootstrap node in AWS

    You must create the bootstrap node in Amazon Web Services (AWS) to use during OKD cluster initialization. You do this by:

    • Providing a location to serve the bootstrap.ign Ignition config file to your cluster. This file is located in your installation directory. The provided CloudFormation Template assumes that the Ignition config files for your cluster are served from an S3 bucket. If you choose to serve the files from another location, you must modify the templates.

    • Using the provided CloudFormation template and a custom parameter file to create a stack of AWS resources. The stack represents the bootstrap node that your OKD installation requires.

    If you do not use the provided CloudFormation template to create your bootstrap node, 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.

    • You created and configured DNS, load balancers, and listeners in AWS.

    • You created the security groups and roles required for your cluster in AWS.

    Procedure

    1. Create the bucket by running the following command:

      1. $ aws s3 mb s3://<cluster-name>-infra (1)
      1<cluster-name>-infra is the bucket name. When creating the install-config.yaml file, replace <cluster-name> with the name specified for the cluster.

      You must use a presigned URL for your S3 bucket, instead of the s3:// schema, if you are:

      • Deploying to a region that has endpoints that differ from the AWS SDK.

      • Deploying a proxy.

      • Providing your own custom endpoints.

    2. Upload the bootstrap.ign Ignition config file to the bucket by running the following command:

      1. $ aws s3 cp <installation_directory>/bootstrap.ign s3://<cluster-name>-infra/bootstrap.ign (1)
      1For <installation_directory>, specify the path to the directory that you stored the installation files in.
    3. Verify that the file uploaded by running the following command:

      1. $ aws s3 ls s3://<cluster-name>-infra/

      Example output

      1. 2019-04-03 16:15:16 314878 bootstrap.ign

      The bootstrap Ignition config file does contain secrets, like X.509 keys. The following steps provide basic security for the S3 bucket. To provide additional security, you can enable an S3 bucket policy to allow only certain users, such as the OpenShift IAM user, to access objects that the bucket contains. You can avoid S3 entirely and serve your bootstrap Ignition config file from any address that the bootstrap machine can reach.

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

      1. [
      2. {
      3. "ParameterKey": "InfrastructureName", (1)
      4. "ParameterValue": "mycluster-<random_string>" (2)
      5. },
      6. {
      7. "ParameterKey": "RhcosAmi", (3)
      8. "ParameterValue": "ami-<random_string>" (4)
      9. },
      10. {
      11. "ParameterKey": "AllowedBootstrapSshCidr", (5)
      12. "ParameterValue": "0.0.0.0/0" (6)
      13. },
      14. {
      15. "ParameterKey": "PublicSubnet", (7)
      16. "ParameterValue": "subnet-<random_string>" (8)
      17. },
      18. {
      19. "ParameterKey": "MasterSecurityGroupId", (9)
      20. "ParameterValue": "sg-<random_string>" (10)
      21. },
      22. {
      23. "ParameterKey": "VpcId", (11)
      24. "ParameterValue": "vpc-<random_string>" (12)
      25. },
      26. {
      27. "ParameterKey": "BootstrapIgnitionLocation", (13)
      28. "ParameterValue": "s3://<bucket_name>/bootstrap.ign" (14)
      29. },
      30. {
      31. "ParameterKey": "AutoRegisterELB", (15)
      32. "ParameterValue": "yes" (16)
      33. },
      34. {
      35. "ParameterKey": "RegisterNlbIpTargetsLambdaArn", (17)
      36. "ParameterValue": "arn:aws:lambda:<aws_region>:<account_number>:function:<dns_stack_name>-RegisterNlbIpTargets-<random_string>" (18)
      37. },
      38. {
      39. "ParameterKey": "ExternalApiTargetGroupArn", (19)
      40. "ParameterValue": "arn:aws:elasticloadbalancing:<aws_region>:<account_number>:targetgroup/<dns_stack_name>-Exter-<random_string>" (20)
      41. },
      42. {
      43. "ParameterKey": "InternalApiTargetGroupArn", (21)
      44. "ParameterValue": "arn:aws:elasticloadbalancing:<aws_region>:<account_number>:targetgroup/<dns_stack_name>-Inter-<random_string>" (22)
      45. },
      46. {
      47. "ParameterKey": "InternalServiceTargetGroupArn", (23)
      48. "ParameterValue": "arn:aws:elasticloadbalancing:<aws_region>:<account_number>:targetgroup/<dns_stack_name>-Inter-<random_string>" (24)
      49. }
      50. ]
      1The name for your cluster infrastructure that is encoded in your Ignition config files for the cluster.
      2Specify the infrastructure name that you extracted from the Ignition config file metadata, which has the format <cluster-name>-<random-string>.
      3Current Fedora CoreOS (FCOS) AMI to use for the bootstrap node based on your selected architecture.
      4Specify a valid AWS::EC2::Image::Id value.
      5CIDR block to allow SSH access to the bootstrap node.
      6Specify a CIDR block in the format x.x.x.x/16-24.
      7The public subnet that is associated with your VPC to launch the bootstrap node into.
      8Specify the PublicSubnetIds value from the output of the CloudFormation template for the VPC.
      9The master security group ID (for registering temporary rules)
      10Specify the MasterSecurityGroupId value from the output of the CloudFormation template for the security group and roles.
      11The VPC created resources will belong to.
      12Specify the VpcId value from the output of the CloudFormation template for the VPC.
      13Location to fetch bootstrap Ignition config file from.
      14Specify the S3 bucket and file name in the form s3://<bucket_name>/bootstrap.ign.
      15Whether or not to register a network load balancer (NLB).
      16Specify yes or no. If you specify yes, you must provide a Lambda Amazon Resource Name (ARN) value.
      17The ARN for NLB IP target registration lambda group.
      18Specify the RegisterNlbIpTargetsLambda value from the output of the CloudFormation template for DNS and load balancing. Use arn:aws-us-gov if deploying the cluster to an AWS GovCloud region.
      19The ARN for external API load balancer target group.
      20Specify the ExternalApiTargetGroupArn value from the output of the CloudFormation template for DNS and load balancing. Use arn:aws-us-gov if deploying the cluster to an AWS GovCloud region.
      21The ARN for internal API load balancer target group.
      22Specify the InternalApiTargetGroupArn value from the output of the CloudFormation template for DNS and load balancing. Use arn:aws-us-gov if deploying the cluster to an AWS GovCloud region.
      23The ARN for internal service load balancer target group.
      24Specify the InternalServiceTargetGroupArn value from the output of the CloudFormation template for DNS and load balancing. Use arn:aws-us-gov if deploying the cluster to an AWS GovCloud region.
    5. Copy the template from the CloudFormation template for the bootstrap machine section of this topic and save it as a YAML file on your computer. This template describes the bootstrap machine that your cluster requires.

    6. Optional: If you are deploying the cluster with a proxy, you must update the ignition in the template to add the ignition.config.proxy fields. Additionally, If you have added the Amazon EC2, Elastic Load Balancing, and S3 VPC endpoints to your VPC, you must add these endpoints to the noProxy field.

    7. Launch the CloudFormation template to create a stack of AWS resources that represent the bootstrap node:

      1. $ aws cloudformation create-stack --stack-name <name> (1)
      2. --template-body file://<template>.yaml (2)
      3. --parameters file://<parameters>.json (3)
      4. --capabilities CAPABILITY_NAMED_IAM (4)
      1<name> is the name for the CloudFormation stack, such as cluster-bootstrap. 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.
      4You must explicitly declare the CAPABILITY_NAMED_IAM capability because the provided template creates some AWS::IAM::Role and AWS::IAM::InstanceProfile resources.

      Example output

      1. arn:aws:cloudformation:us-east-1:269333783861:stack/cluster-bootstrap/12944486-2add-11eb-9dee-12dace8e3a83
    8. Confirm that the template components exist:

      1. $ 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:

      BootstrapInstanceId

      The bootstrap Instance ID.

      BootstrapPublicIp

      The bootstrap node public IP address.

      BootstrapPrivateIp

      The bootstrap node private IP address.

    CloudFormation template for the bootstrap machine

    You can use the following CloudFormation template to deploy the bootstrap machine that you need for your OKD cluster.

    CloudFormation template for the bootstrap machine

    1. AWSTemplateFormatVersion: 2010-09-09
    2. Description: Template for OpenShift Cluster Bootstrap (EC2 Instance, Security Groups and IAM)
    3. Parameters:
    4. AllowedPattern: ^([a-zA-Z][a-zA-Z0-9\-]{0,26})$
    5. MaxLength: 27
    6. MinLength: 1
    7. ConstraintDescription: Infrastructure name must be alphanumeric, start with a letter, and have a maximum of 27 characters.
    8. Description: A short, unique cluster ID used to tag cloud resources and identify items owned or used by the cluster.
    9. Type: String
    10. RhcosAmi:
    11. Description: Current Red Hat Enterprise Linux CoreOS AMI to use for bootstrap.
    12. Type: AWS::EC2::Image::Id
    13. AllowedBootstrapSshCidr:
    14. 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])(\/([0-9]|1[0-9]|2[0-9]|3[0-2]))$
    15. ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/0-32.
    16. Default: 0.0.0.0/0
    17. Description: CIDR block to allow SSH access to the bootstrap node.
    18. Type: String
    19. PublicSubnet:
    20. Description: The public subnet to launch the bootstrap node into.
    21. Type: AWS::EC2::Subnet::Id
    22. MasterSecurityGroupId:
    23. Description: The master security group ID for registering temporary rules.
    24. Type: AWS::EC2::SecurityGroup::Id
    25. VpcId:
    26. Description: The VPC-scoped resources will belong to this VPC.
    27. Type: AWS::EC2::VPC::Id
    28. BootstrapIgnitionLocation:
    29. Default: s3://my-s3-bucket/bootstrap.ign
    30. Description: Ignition config file location.
    31. Type: String
    32. AutoRegisterELB:
    33. Default: "yes"
    34. AllowedValues:
    35. - "yes"
    36. - "no"
    37. Description: Do you want to invoke NLB registration, which requires a Lambda ARN parameter?
    38. Type: String
    39. RegisterNlbIpTargetsLambdaArn:
    40. Description: ARN for NLB IP target registration lambda.
    41. Type: String
    42. ExternalApiTargetGroupArn:
    43. Description: ARN for external API load balancer target group.
    44. Type: String
    45. InternalApiTargetGroupArn:
    46. Description: ARN for internal API load balancer target group.
    47. Type: String
    48. InternalServiceTargetGroupArn:
    49. Description: ARN for internal service load balancer target group.
    50. Type: String
    51. BootstrapInstanceType:
    52. Description: Instance type for the bootstrap EC2 instance
    53. Default: "i3.large"
    54. Type: String
    55. Metadata:
    56. AWS::CloudFormation::Interface:
    57. ParameterGroups:
    58. - Label:
    59. default: "Cluster Information"
    60. Parameters:
    61. - InfrastructureName
    62. - Label:
    63. default: "Host Information"
    64. Parameters:
    65. - RhcosAmi
    66. - BootstrapIgnitionLocation
    67. - MasterSecurityGroupId
    68. - Label:
    69. default: "Network Configuration"
    70. Parameters:
    71. - VpcId
    72. - AllowedBootstrapSshCidr
    73. - PublicSubnet
    74. - Label:
    75. default: "Load Balancer Automation"
    76. Parameters:
    77. - AutoRegisterELB
    78. - RegisterNlbIpTargetsLambdaArn
    79. - ExternalApiTargetGroupArn
    80. - InternalApiTargetGroupArn
    81. - InternalServiceTargetGroupArn
    82. ParameterLabels:
    83. InfrastructureName:
    84. default: "Infrastructure Name"
    85. VpcId:
    86. default: "VPC ID"
    87. AllowedBootstrapSshCidr:
    88. default: "Allowed SSH Source"
    89. PublicSubnet:
    90. default: "Public Subnet"
    91. RhcosAmi:
    92. default: "Red Hat Enterprise Linux CoreOS AMI ID"
    93. BootstrapIgnitionLocation:
    94. default: "Bootstrap Ignition Source"
    95. MasterSecurityGroupId:
    96. default: "Master Security Group ID"
    97. AutoRegisterELB:
    98. default: "Use Provided ELB Automation"
    99. Conditions:
    100. DoRegistration: !Equals ["yes", !Ref AutoRegisterELB]
    101. Resources:
    102. BootstrapIamRole:
    103. Type: AWS::IAM::Role
    104. Properties:
    105. AssumeRolePolicyDocument:
    106. Version: "2012-10-17"
    107. Statement:
    108. - Effect: "Allow"
    109. Principal:
    110. Service:
    111. - "ec2.amazonaws.com"
    112. Action:
    113. - "sts:AssumeRole"
    114. Path: "/"
    115. Policies:
    116. - PolicyName: !Join ["-", [!Ref InfrastructureName, "bootstrap", "policy"]]
    117. PolicyDocument:
    118. Version: "2012-10-17"
    119. Statement:
    120. - Effect: "Allow"
    121. Action: "ec2:Describe*"
    122. Resource: "*"
    123. - Effect: "Allow"
    124. Action: "ec2:AttachVolume"
    125. Resource: "*"
    126. - Effect: "Allow"
    127. Action: "ec2:DetachVolume"
    128. Resource: "*"
    129. - Effect: "Allow"
    130. Action: "s3:GetObject"
    131. Resource: "*"
    132. BootstrapInstanceProfile:
    133. Type: "AWS::IAM::InstanceProfile"
    134. Properties:
    135. Path: "/"
    136. Roles:
    137. - Ref: "BootstrapIamRole"
    138. BootstrapSecurityGroup:
    139. Type: AWS::EC2::SecurityGroup
    140. Properties:
    141. GroupDescription: Cluster Bootstrap Security Group
    142. SecurityGroupIngress:
    143. - IpProtocol: tcp
    144. FromPort: 22
    145. ToPort: 22
    146. CidrIp: !Ref AllowedBootstrapSshCidr
    147. - IpProtocol: tcp
    148. ToPort: 19531
    149. FromPort: 19531
    150. CidrIp: 0.0.0.0/0
    151. VpcId: !Ref VpcId
    152. BootstrapInstance:
    153. Type: AWS::EC2::Instance
    154. Properties:
    155. ImageId: !Ref RhcosAmi
    156. IamInstanceProfile: !Ref BootstrapInstanceProfile
    157. InstanceType: !Ref BootstrapInstanceType
    158. NetworkInterfaces:
    159. - AssociatePublicIpAddress: "true"
    160. DeviceIndex: "0"
    161. GroupSet:
    162. - !Ref "BootstrapSecurityGroup"
    163. - !Ref "MasterSecurityGroupId"
    164. SubnetId: !Ref "PublicSubnet"
    165. UserData:
    166. Fn::Base64: !Sub
    167. - '{"ignition":{"config":{"replace":{"source":"${S3Loc}"}},"version":"3.1.0"}}'
    168. - {
    169. S3Loc: !Ref BootstrapIgnitionLocation
    170. }
    171. RegisterBootstrapApiTarget:
    172. Condition: DoRegistration
    173. Type: Custom::NLBRegister
    174. Properties:
    175. ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
    176. TargetArn: !Ref ExternalApiTargetGroupArn
    177. TargetIp: !GetAtt BootstrapInstance.PrivateIp
    178. RegisterBootstrapInternalApiTarget:
    179. Condition: DoRegistration
    180. Type: Custom::NLBRegister
    181. Properties:
    182. ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
    183. TargetArn: !Ref InternalApiTargetGroupArn
    184. TargetIp: !GetAtt BootstrapInstance.PrivateIp
    185. RegisterBootstrapInternalServiceTarget:
    186. Condition: DoRegistration
    187. Type: Custom::NLBRegister
    188. Properties:
    189. ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
    190. TargetArn: !Ref InternalServiceTargetGroupArn
    191. TargetIp: !GetAtt BootstrapInstance.PrivateIp
    192. Outputs:
    193. BootstrapInstanceId:
    194. Description: Bootstrap Instance ID.
    195. Value: !Ref BootstrapInstance
    196. BootstrapPublicIp:
    197. Description: The bootstrap node public IP address.
    198. Value: !GetAtt BootstrapInstance.PublicIp
    199. BootstrapPrivateIp:
    200. Description: The bootstrap node private IP address.
    201. Value: !GetAtt BootstrapInstance.PrivateIp

    Additional resources

    Creating the control plane machines in AWS

    You must create the control plane machines in Amazon Web Services (AWS) that your cluster will use.

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

    The CloudFormation template creates a stack that represents three control plane nodes.

    If you do not use the provided CloudFormation template to create your control plane nodes, 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.

    • You created and configured DNS, load balancers, and listeners in AWS.

    • You created the security groups and roles required for your cluster in AWS.

    • You created the bootstrap machine.

    Procedure

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

      1. [
      2. {
      3. "ParameterKey": "InfrastructureName", (1)
      4. "ParameterValue": "mycluster-<random_string>" (2)
      5. },
      6. {
      7. "ParameterKey": "RhcosAmi", (3)
      8. "ParameterValue": "ami-<random_string>" (4)
      9. },
      10. {
      11. "ParameterKey": "AutoRegisterDNS", (5)
      12. "ParameterValue": "yes" (6)
      13. },
      14. {
      15. "ParameterKey": "PrivateHostedZoneId", (7)
      16. "ParameterValue": "<random_string>" (8)
      17. },
      18. {
      19. "ParameterKey": "PrivateHostedZoneName", (9)
      20. "ParameterValue": "mycluster.example.com" (10)
      21. },
      22. {
      23. "ParameterKey": "Master0Subnet", (11)
      24. "ParameterValue": "subnet-<random_string>" (12)
      25. },
      26. {
      27. "ParameterKey": "Master1Subnet", (11)
      28. "ParameterValue": "subnet-<random_string>" (12)
      29. },
      30. {
      31. "ParameterKey": "Master2Subnet", (11)
      32. "ParameterValue": "subnet-<random_string>" (12)
      33. },
      34. {
      35. "ParameterKey": "MasterSecurityGroupId", (13)
      36. "ParameterValue": "sg-<random_string>" (14)
      37. },
      38. {
      39. "ParameterKey": "IgnitionLocation", (15)
      40. "ParameterValue": "https://api-int.<cluster_name>.<domain_name>:22623/config/master" (16)
      41. },
      42. {
      43. "ParameterKey": "CertificateAuthorities", (17)
      44. "ParameterValue": "data:text/plain;charset=utf-8;base64,ABC...xYz==" (18)
      45. },
      46. {
      47. "ParameterKey": "MasterInstanceProfileName", (19)
      48. "ParameterValue": "<roles_stack>-MasterInstanceProfile-<random_string>" (20)
      49. },
      50. {
      51. "ParameterKey": "MasterInstanceType", (21)
      52. "ParameterValue": "" (22)
      53. },
      54. {
      55. "ParameterKey": "AutoRegisterELB", (23)
      56. "ParameterValue": "yes" (24)
      57. },
      58. {
      59. "ParameterKey": "RegisterNlbIpTargetsLambdaArn", (25)
      60. "ParameterValue": "arn:aws:lambda:<aws_region>:<account_number>:function:<dns_stack_name>-RegisterNlbIpTargets-<random_string>" (26)
      61. },
      62. {
      63. "ParameterKey": "ExternalApiTargetGroupArn", (27)
      64. "ParameterValue": "arn:aws:elasticloadbalancing:<aws_region>:<account_number>:targetgroup/<dns_stack_name>-Exter-<random_string>" (28)
      65. },
      66. {
      67. "ParameterKey": "InternalApiTargetGroupArn", (29)
      68. "ParameterValue": "arn:aws:elasticloadbalancing:<aws_region>:<account_number>:targetgroup/<dns_stack_name>-Inter-<random_string>" (30)
      69. },
      70. {
      71. "ParameterKey": "InternalServiceTargetGroupArn", (31)
      72. "ParameterValue": "arn:aws:elasticloadbalancing:<aws_region>:<account_number>:targetgroup/<dns_stack_name>-Inter-<random_string>" (32)
      73. }
      74. ]
      1The name for your cluster infrastructure that is encoded in your Ignition config files for the cluster.
      2Specify the infrastructure name that you extracted from the Ignition config file metadata, which has the format <cluster-name>-<random-string>.
      3Current Fedora CoreOS (FCOS) AMI to use for the control plane machines based on your selected architecture.
      4Specify an AWS::EC2::Image::Id value.
      5Whether or not to perform DNS etcd registration.
      6Specify yes or no. If you specify yes, you must provide hosted zone information.
      7The Route 53 private zone ID to register the etcd targets with.
      8Specify the PrivateHostedZoneId value from the output of the CloudFormation template for DNS and load balancing.
      9The Route 53 zone to register the targets with.
      10Specify <cluster_name>.<domain_name> where <domain_name> is the Route 53 base domain that you used when you generated install-config.yaml file for the cluster. Do not include the trailing period (.) that is displayed in the AWS console.
      11A subnet, preferably private, to launch the control plane machines on.
      12Specify a subnet from the PrivateSubnets value from the output of the CloudFormation template for DNS and load balancing.
      13The master security group ID to associate with control plane nodes.
      14Specify the MasterSecurityGroupId value from the output of the CloudFormation template for the security group and roles.
      15The location to fetch control plane Ignition config file from.
      16Specify the generated Ignition config file location, https://api-int.<cluster_name>.<domain_name>:22623/config/master.
      17The base64 encoded certificate authority string to use.
      18Specify the value from the master.ign file that is in the installation directory. This value is the long string with the format data:text/plain;charset=utf-8;base64,ABC…​xYz==.
      19The IAM profile to associate with control plane nodes.
      20Specify the MasterInstanceProfile parameter value from the output of the CloudFormation template for the security group and roles.
      21The type of AWS instance to use for the control plane machines based on your selected architecture.
      22The instance type value corresponds to the minimum resource requirements for control plane machines. For example m6i.xlarge is a type for x86_64
      23Whether or not to register a network load balancer (NLB).
      24Specify yes or no. If you specify yes, you must provide a Lambda Amazon Resource Name (ARN) value.
      25The ARN for NLB IP target registration lambda group.
      26Specify the RegisterNlbIpTargetsLambda value from the output of the CloudFormation template for DNS and load balancing. Use arn:aws-us-gov if deploying the cluster to an AWS GovCloud region.
      27The ARN for external API load balancer target group.
      28Specify the ExternalApiTargetGroupArn value from the output of the CloudFormation template for DNS and load balancing. Use arn:aws-us-gov if deploying the cluster to an AWS GovCloud region.
      29The ARN for internal API load balancer target group.
      30Specify the InternalApiTargetGroupArn value from the output of the CloudFormation template for DNS and load balancing. Use arn:aws-us-gov if deploying the cluster to an AWS GovCloud region.
      31The ARN for internal service load balancer target group.
      32Specify the InternalServiceTargetGroupArn value from the output of the CloudFormation template for DNS and load balancing. Use arn:aws-us-gov if deploying the cluster to an AWS GovCloud region.
    2. Copy the template from the CloudFormation template for control plane machines section of this topic and save it as a YAML file on your computer. This template describes the control plane machines that your cluster requires.

    3. If you specified an m5 instance type as the value for MasterInstanceType, add that instance type to the MasterInstanceType.AllowedValues parameter in the CloudFormation template.

    4. Launch the CloudFormation template to create a stack of AWS resources that represent the control plane nodes:

      You must enter the command on a single line.

      1. $ aws cloudformation create-stack --stack-name <name> (1)
      2. --template-body file://<template>.yaml (2)
      3. --parameters file://<parameters>.json (3)
      1<name> is the name for the CloudFormation stack, such as cluster-control-plane. 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

      1. arn:aws:cloudformation:us-east-1:269333783861:stack/cluster-control-plane/21c7e2b0-2ee2-11eb-c6f6-0aa34627df4b

      The CloudFormation template creates a stack that represents three control plane nodes.

    5. Confirm that the template components exist:

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

    CloudFormation template for control plane machines

    You can use the following CloudFormation template to deploy the control plane machines that you need for your OKD cluster.

    CloudFormation template for control plane machines

    1. AWSTemplateFormatVersion: 2010-09-09
    2. Description: Template for OpenShift Cluster Node Launch (EC2 master instances)
    3. Parameters:
    4. InfrastructureName:
    5. AllowedPattern: ^([a-zA-Z][a-zA-Z0-9\-]{0,26})$
    6. MaxLength: 27
    7. MinLength: 1
    8. ConstraintDescription: Infrastructure name must be alphanumeric, start with a letter, and have a maximum of 27 characters.
    9. Description: A short, unique cluster ID used to tag nodes for the kubelet cloud provider.
    10. Type: String
    11. RhcosAmi:
    12. Description: Current Red Hat Enterprise Linux CoreOS AMI to use for bootstrap.
    13. Type: AWS::EC2::Image::Id
    14. AutoRegisterDNS:
    15. Default: ""
    16. Description: unused
    17. Type: String
    18. PrivateHostedZoneId:
    19. Default: ""
    20. Description: unused
    21. Type: String
    22. PrivateHostedZoneName:
    23. Default: ""
    24. Description: unused
    25. Type: String
    26. Master0Subnet:
    27. Description: The subnets, recommend private, to launch the master nodes into.
    28. Type: AWS::EC2::Subnet::Id
    29. Master1Subnet:
    30. Description: The subnets, recommend private, to launch the master nodes into.
    31. Type: AWS::EC2::Subnet::Id
    32. Master2Subnet:
    33. Description: The subnets, recommend private, to launch the master nodes into.
    34. Type: AWS::EC2::Subnet::Id
    35. MasterSecurityGroupId:
    36. Description: The master security group ID to associate with master nodes.
    37. Type: AWS::EC2::SecurityGroup::Id
    38. IgnitionLocation:
    39. Default: https://api-int.$CLUSTER_NAME.$DOMAIN:22623/config/master
    40. Description: Ignition config file location.
    41. Type: String
    42. CertificateAuthorities:
    43. Default: data:text/plain;charset=utf-8;base64,ABC...xYz==
    44. Description: Base64 encoded certificate authority string to use.
    45. Type: String
    46. MasterInstanceProfileName:
    47. Description: IAM profile to associate with master nodes.
    48. Type: String
    49. MasterInstanceType:
    50. Default: m5.xlarge
    51. Type: String
    52. AutoRegisterELB:
    53. Default: "yes"
    54. AllowedValues:
    55. - "yes"
    56. - "no"
    57. Description: Do you want to invoke NLB registration, which requires a Lambda ARN parameter?
    58. Type: String
    59. RegisterNlbIpTargetsLambdaArn:
    60. Description: ARN for NLB IP target registration lambda. Supply the value from the cluster infrastructure or select "no" for AutoRegisterELB.
    61. Type: String
    62. ExternalApiTargetGroupArn:
    63. Description: ARN for external API load balancer target group. Supply the value from the cluster infrastructure or select "no" for AutoRegisterELB.
    64. Type: String
    65. InternalApiTargetGroupArn:
    66. Description: ARN for internal API load balancer target group. Supply the value from the cluster infrastructure or select "no" for AutoRegisterELB.
    67. Type: String
    68. InternalServiceTargetGroupArn:
    69. Description: ARN for internal service load balancer target group. Supply the value from the cluster infrastructure or select "no" for AutoRegisterELB.
    70. Type: String
    71. Metadata:
    72. AWS::CloudFormation::Interface:
    73. ParameterGroups:
    74. - Label:
    75. default: "Cluster Information"
    76. Parameters:
    77. - InfrastructureName
    78. - Label:
    79. default: "Host Information"
    80. Parameters:
    81. - MasterInstanceType
    82. - RhcosAmi
    83. - IgnitionLocation
    84. - CertificateAuthorities
    85. - MasterSecurityGroupId
    86. - MasterInstanceProfileName
    87. - Label:
    88. default: "Network Configuration"
    89. Parameters:
    90. - VpcId
    91. - AllowedBootstrapSshCidr
    92. - Master0Subnet
    93. - Master1Subnet
    94. - Master2Subnet
    95. - Label:
    96. default: "Load Balancer Automation"
    97. Parameters:
    98. - AutoRegisterELB
    99. - RegisterNlbIpTargetsLambdaArn
    100. - ExternalApiTargetGroupArn
    101. - InternalApiTargetGroupArn
    102. - InternalServiceTargetGroupArn
    103. ParameterLabels:
    104. InfrastructureName:
    105. default: "Infrastructure Name"
    106. VpcId:
    107. default: "VPC ID"
    108. Master0Subnet:
    109. default: "Master-0 Subnet"
    110. Master1Subnet:
    111. default: "Master-1 Subnet"
    112. Master2Subnet:
    113. default: "Master-2 Subnet"
    114. MasterInstanceType:
    115. default: "Master Instance Type"
    116. MasterInstanceProfileName:
    117. default: "Master Instance Profile Name"
    118. RhcosAmi:
    119. default: "Red Hat Enterprise Linux CoreOS AMI ID"
    120. BootstrapIgnitionLocation:
    121. default: "Master Ignition Source"
    122. CertificateAuthorities:
    123. default: "Ignition CA String"
    124. MasterSecurityGroupId:
    125. default: "Master Security Group ID"
    126. AutoRegisterELB:
    127. default: "Use Provided ELB Automation"
    128. Conditions:
    129. DoRegistration: !Equals ["yes", !Ref AutoRegisterELB]
    130. Resources:
    131. Master0:
    132. Type: AWS::EC2::Instance
    133. Properties:
    134. ImageId: !Ref RhcosAmi
    135. BlockDeviceMappings:
    136. - DeviceName: /dev/xvda
    137. Ebs:
    138. VolumeSize: "120"
    139. VolumeType: "gp2"
    140. IamInstanceProfile: !Ref MasterInstanceProfileName
    141. InstanceType: !Ref MasterInstanceType
    142. NetworkInterfaces:
    143. - AssociatePublicIpAddress: "false"
    144. DeviceIndex: "0"
    145. GroupSet:
    146. - !Ref "MasterSecurityGroupId"
    147. SubnetId: !Ref "Master0Subnet"
    148. UserData:
    149. Fn::Base64: !Sub
    150. - '{"ignition":{"config":{"merge":[{"source":"${SOURCE}"}]},"security":{"tls":{"certificateAuthorities":[{"source":"${CA_BUNDLE}"}]}},"version":"3.1.0"}}'
    151. - {
    152. SOURCE: !Ref IgnitionLocation,
    153. CA_BUNDLE: !Ref CertificateAuthorities,
    154. }
    155. Tags:
    156. - Key: !Join ["", ["kubernetes.io/cluster/", !Ref InfrastructureName]]
    157. Value: "shared"
    158. RegisterMaster0:
    159. Condition: DoRegistration
    160. Type: Custom::NLBRegister
    161. Properties:
    162. ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
    163. TargetArn: !Ref ExternalApiTargetGroupArn
    164. TargetIp: !GetAtt Master0.PrivateIp
    165. RegisterMaster0InternalApiTarget:
    166. Condition: DoRegistration
    167. Type: Custom::NLBRegister
    168. Properties:
    169. ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
    170. TargetArn: !Ref InternalApiTargetGroupArn
    171. TargetIp: !GetAtt Master0.PrivateIp
    172. RegisterMaster0InternalServiceTarget:
    173. Condition: DoRegistration
    174. Type: Custom::NLBRegister
    175. Properties:
    176. ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
    177. TargetArn: !Ref InternalServiceTargetGroupArn
    178. TargetIp: !GetAtt Master0.PrivateIp
    179. Master1:
    180. Type: AWS::EC2::Instance
    181. Properties:
    182. ImageId: !Ref RhcosAmi
    183. BlockDeviceMappings:
    184. - DeviceName: /dev/xvda
    185. Ebs:
    186. VolumeSize: "120"
    187. VolumeType: "gp2"
    188. IamInstanceProfile: !Ref MasterInstanceProfileName
    189. InstanceType: !Ref MasterInstanceType
    190. NetworkInterfaces:
    191. - AssociatePublicIpAddress: "false"
    192. DeviceIndex: "0"
    193. GroupSet:
    194. - !Ref "MasterSecurityGroupId"
    195. SubnetId: !Ref "Master1Subnet"
    196. UserData:
    197. Fn::Base64: !Sub
    198. - '{"ignition":{"config":{"merge":[{"source":"${SOURCE}"}]},"security":{"tls":{"certificateAuthorities":[{"source":"${CA_BUNDLE}"}]}},"version":"3.1.0"}}'
    199. - {
    200. SOURCE: !Ref IgnitionLocation,
    201. CA_BUNDLE: !Ref CertificateAuthorities,
    202. }
    203. Tags:
    204. - Key: !Join ["", ["kubernetes.io/cluster/", !Ref InfrastructureName]]
    205. Value: "shared"
    206. RegisterMaster1:
    207. Condition: DoRegistration
    208. Type: Custom::NLBRegister
    209. Properties:
    210. ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
    211. TargetArn: !Ref ExternalApiTargetGroupArn
    212. TargetIp: !GetAtt Master1.PrivateIp
    213. RegisterMaster1InternalApiTarget:
    214. Condition: DoRegistration
    215. Type: Custom::NLBRegister
    216. Properties:
    217. ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
    218. TargetArn: !Ref InternalApiTargetGroupArn
    219. TargetIp: !GetAtt Master1.PrivateIp
    220. RegisterMaster1InternalServiceTarget:
    221. Condition: DoRegistration
    222. Type: Custom::NLBRegister
    223. Properties:
    224. ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
    225. TargetArn: !Ref InternalServiceTargetGroupArn
    226. TargetIp: !GetAtt Master1.PrivateIp
    227. Master2:
    228. Type: AWS::EC2::Instance
    229. Properties:
    230. ImageId: !Ref RhcosAmi
    231. BlockDeviceMappings:
    232. - DeviceName: /dev/xvda
    233. Ebs:
    234. VolumeSize: "120"
    235. VolumeType: "gp2"
    236. IamInstanceProfile: !Ref MasterInstanceProfileName
    237. InstanceType: !Ref MasterInstanceType
    238. NetworkInterfaces:
    239. - AssociatePublicIpAddress: "false"
    240. DeviceIndex: "0"
    241. GroupSet:
    242. - !Ref "MasterSecurityGroupId"
    243. SubnetId: !Ref "Master2Subnet"
    244. UserData:
    245. Fn::Base64: !Sub
    246. - '{"ignition":{"config":{"merge":[{"source":"${SOURCE}"}]},"security":{"tls":{"certificateAuthorities":[{"source":"${CA_BUNDLE}"}]}},"version":"3.1.0"}}'
    247. - {
    248. SOURCE: !Ref IgnitionLocation,
    249. CA_BUNDLE: !Ref CertificateAuthorities,
    250. }
    251. Tags:
    252. - Key: !Join ["", ["kubernetes.io/cluster/", !Ref InfrastructureName]]
    253. Value: "shared"
    254. RegisterMaster2:
    255. Condition: DoRegistration
    256. Type: Custom::NLBRegister
    257. Properties:
    258. ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
    259. TargetArn: !Ref ExternalApiTargetGroupArn
    260. TargetIp: !GetAtt Master2.PrivateIp
    261. RegisterMaster2InternalApiTarget:
    262. Condition: DoRegistration
    263. Type: Custom::NLBRegister
    264. Properties:
    265. ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
    266. TargetArn: !Ref InternalApiTargetGroupArn
    267. TargetIp: !GetAtt Master2.PrivateIp
    268. RegisterMaster2InternalServiceTarget:
    269. Condition: DoRegistration
    270. Type: Custom::NLBRegister
    271. Properties:
    272. ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
    273. TargetArn: !Ref InternalServiceTargetGroupArn
    274. TargetIp: !GetAtt Master2.PrivateIp
    275. Outputs:
    276. PrivateIPs:
    277. Description: The control-plane node private IP addresses.
    278. Value:
    279. !Join [
    280. ",",
    281. [!GetAtt Master0.PrivateIp, !GetAtt Master1.PrivateIp, !GetAtt Master2.PrivateIp]
    282. ]

    Creating the worker nodes in AWS

    You can create worker nodes in Amazon Web Services (AWS) for your cluster to use.

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

    The CloudFormation template creates a stack that represents one worker node. You must create a stack for each worker node.

    If you do not use the provided CloudFormation template to create your worker nodes, 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.

    • You created and configured DNS, load balancers, and listeners in AWS.

    • You created the security groups and roles required for your cluster in AWS.

    • You created the bootstrap machine.

    • You created the control plane machines.

    Procedure

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

      1. [
      2. {
      3. "ParameterKey": "InfrastructureName", (1)
      4. "ParameterValue": "mycluster-<random_string>" (2)
      5. },
      6. {
      7. "ParameterKey": "RhcosAmi", (3)
      8. "ParameterValue": "ami-<random_string>" (4)
      9. },
      10. {
      11. "ParameterKey": "Subnet", (5)
      12. "ParameterValue": "subnet-<random_string>" (6)
      13. },
      14. {
      15. "ParameterKey": "WorkerSecurityGroupId", (7)
      16. "ParameterValue": "sg-<random_string>" (8)
      17. },
      18. {
      19. "ParameterKey": "IgnitionLocation", (9)
      20. "ParameterValue": "https://api-int.<cluster_name>.<domain_name>:22623/config/worker" (10)
      21. },
      22. {
      23. "ParameterKey": "CertificateAuthorities", (11)
      24. "ParameterValue": "" (12)
      25. },
      26. {
      27. "ParameterKey": "WorkerInstanceProfileName", (13)
      28. "ParameterValue": "" (14)
      29. },
      30. {
      31. "ParameterKey": "WorkerInstanceType", (15)
      32. "ParameterValue": "" (16)
      33. }
      34. ]
      1The name for your cluster infrastructure that is encoded in your Ignition config files for the cluster.
      2Specify the infrastructure name that you extracted from the Ignition config file metadata, which has the format <cluster-name>-<random-string>.
      3Current Fedora CoreOS (FCOS) AMI to use for the worker nodes based on your selected architecture.
      4Specify an AWS::EC2::Image::Id value.
      5A subnet, preferably private, to start the worker nodes on.
      6Specify a subnet from the PrivateSubnets value from the output of the CloudFormation template for DNS and load balancing.
      7The worker security group ID to associate with worker nodes.
      8Specify the WorkerSecurityGroupId value from the output of the CloudFormation template for the security group and roles.
      9The location to fetch the bootstrap Ignition config file from.
      10Specify the generated Ignition config location, .
      11Base64 encoded certificate authority string to use.
      12Specify the value from the worker.ign file that is in the installation directory. This value is the long string with the format data:text/plain;charset=utf-8;base64,ABC…​xYz==.
      13The IAM profile to associate with worker nodes.
      14Specify the WorkerInstanceProfile parameter value from the output of the CloudFormation template for the security group and roles.
      15The type of AWS instance to use for the compute machines based on your selected architecture.
      16The instance type value corresponds to the minimum resource requirements for compute machines. For example m6i.large is a type for x86_64
    2. Copy the template from the CloudFormation template for worker machines section of this topic and save it as a YAML file on your computer. This template describes the networking objects and load balancers that your cluster requires.

    3. Optional: If you specified an m5 instance type as the value for WorkerInstanceType, add that instance type to the WorkerInstanceType.AllowedValues parameter in the CloudFormation template.

    4. Optional: If you are deploying with an AWS Marketplace image, update the Worker0.type.properties.ImageID parameter with the AMI ID that you obtained from your subscription.

    5. Use the CloudFormation template to create a stack of AWS resources that represent a worker node:

      You must enter the command on a single line.

      1. $ aws cloudformation create-stack --stack-name <name> (1)
      2. --template-body file://<template>.yaml \ (2)
      3. --parameters file://<parameters>.json (3)
      1<name> is the name for the CloudFormation stack, such as cluster-worker-1. 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

      1. arn:aws:cloudformation:us-east-1:269333783861:stack/cluster-worker-1/729ee301-1c2a-11eb-348f-sd9888c65b59

      The CloudFormation template creates a stack that represents one worker node.

    6. Confirm that the template components exist:

      1. $ aws cloudformation describe-stacks --stack-name <name>
    7. Continue to create worker stacks until you have created enough worker machines for your cluster. You can create additional worker stacks by referencing the same template and parameter files and specifying a different stack name.

      You must create at least two worker machines, so you must create at least two stacks that use this CloudFormation template.

    CloudFormation template for worker machines

    You can use the following CloudFormation template to deploy the worker machines that you need for your OKD cluster.

    CloudFormation template for worker machines

    1. AWSTemplateFormatVersion: 2010-09-09
    2. Description: Template for OpenShift Cluster Node Launch (EC2 worker instance)
    3. Parameters:
    4. InfrastructureName:
    5. AllowedPattern: ^([a-zA-Z][a-zA-Z0-9\-]{0,26})$
    6. MaxLength: 27
    7. MinLength: 1
    8. ConstraintDescription: Infrastructure name must be alphanumeric, start with a letter, and have a maximum of 27 characters.
    9. Description: A short, unique cluster ID used to tag nodes for the kubelet cloud provider.
    10. Type: String
    11. RhcosAmi:
    12. Description: Current Red Hat Enterprise Linux CoreOS AMI to use for bootstrap.
    13. Type: AWS::EC2::Image::Id
    14. Subnet:
    15. Description: The subnets, recommend private, to launch the master nodes into.
    16. Type: AWS::EC2::Subnet::Id
    17. WorkerSecurityGroupId:
    18. Description: The master security group ID to associate with master nodes.
    19. Type: AWS::EC2::SecurityGroup::Id
    20. IgnitionLocation:
    21. Default: https://api-int.$CLUSTER_NAME.$DOMAIN:22623/config/worker
    22. Description: Ignition config file location.
    23. Type: String
    24. CertificateAuthorities:
    25. Default: data:text/plain;charset=utf-8;base64,ABC...xYz==
    26. Description: Base64 encoded certificate authority string to use.
    27. Type: String
    28. WorkerInstanceProfileName:
    29. Description: IAM profile to associate with master nodes.
    30. Type: String
    31. WorkerInstanceType:
    32. Default: m5.large
    33. Type: String
    34. Metadata:
    35. AWS::CloudFormation::Interface:
    36. ParameterGroups:
    37. - Label:
    38. default: "Cluster Information"
    39. Parameters:
    40. - InfrastructureName
    41. - Label:
    42. default: "Host Information"
    43. Parameters:
    44. - WorkerInstanceType
    45. - RhcosAmi
    46. - IgnitionLocation
    47. - CertificateAuthorities
    48. - WorkerSecurityGroupId
    49. - WorkerInstanceProfileName
    50. - Label:
    51. default: "Network Configuration"
    52. Parameters:
    53. - Subnet
    54. ParameterLabels:
    55. Subnet:
    56. default: "Subnet"
    57. InfrastructureName:
    58. default: "Infrastructure Name"
    59. WorkerInstanceType:
    60. default: "Worker Instance Type"
    61. WorkerInstanceProfileName:
    62. default: "Worker Instance Profile Name"
    63. RhcosAmi:
    64. default: "Red Hat Enterprise Linux CoreOS AMI ID"
    65. IgnitionLocation:
    66. default: "Worker Ignition Source"
    67. CertificateAuthorities:
    68. default: "Ignition CA String"
    69. WorkerSecurityGroupId:
    70. default: "Worker Security Group ID"
    71. Resources:
    72. Worker0:
    73. Type: AWS::EC2::Instance
    74. Properties:
    75. ImageId: !Ref RhcosAmi
    76. BlockDeviceMappings:
    77. - DeviceName: /dev/xvda
    78. Ebs:
    79. VolumeSize: "120"
    80. VolumeType: "gp2"
    81. IamInstanceProfile: !Ref WorkerInstanceProfileName
    82. InstanceType: !Ref WorkerInstanceType
    83. NetworkInterfaces:
    84. - AssociatePublicIpAddress: "false"
    85. DeviceIndex: "0"
    86. GroupSet:
    87. - !Ref "WorkerSecurityGroupId"
    88. SubnetId: !Ref "Subnet"
    89. UserData:
    90. Fn::Base64: !Sub
    91. - '{"ignition":{"config":{"merge":[{"source":"${SOURCE}"}]},"security":{"tls":{"certificateAuthorities":[{"source":"${CA_BUNDLE}"}]}},"version":"3.1.0"}}'
    92. - {
    93. SOURCE: !Ref IgnitionLocation,
    94. CA_BUNDLE: !Ref CertificateAuthorities,
    95. }
    96. Tags:
    97. - Key: !Join ["", ["kubernetes.io/cluster/", !Ref InfrastructureName]]
    98. Value: "shared"
    99. Outputs:
    100. PrivateIP:
    101. Description: The compute node private IP address.
    102. Value: !GetAtt Worker0.PrivateIp

    Initializing the bootstrap sequence on AWS with user-provisioned infrastructure

    After you create all of the required infrastructure in Amazon Web Services (AWS), you can start the bootstrap sequence that initializes the OKD control plane.

    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.

    • You created and configured DNS, load balancers, and listeners in AWS.

    • You created the security groups and roles required for your cluster in AWS.

    • You created the bootstrap machine.

    • You created the control plane machines.

    • You created the worker nodes.

    Procedure

    1. Change to the directory that contains the installation program and start the bootstrap process that initializes the OKD control plane:

      1. $ ./openshift-install wait-for bootstrap-complete --dir <installation_directory> \ (1)
      2. --log-level=info (2)
      1For <installation_directory>, specify the path to the directory that you stored the installation files in.
      2To view different installation details, specify warn, debug, or error instead of info.

      Example output

      1. INFO Waiting up to 20m0s for the Kubernetes API at https://api.mycluster.example.com:6443...
      2. INFO API v1.26.0 up
      3. INFO Waiting up to 30m0s for bootstrapping to complete...
      4. INFO It is now safe to remove the bootstrap resources
      5. INFO Time elapsed: 1s

      If the command exits without a FATAL warning, your OKD control plane has initialized.

      After the control plane initializes, it sets up the compute nodes and installs additional services in the form of Operators.

    Additional resources

    • See Monitoring installation progress for details about monitoring the installation, bootstrap, and control plane logs as an OKD installation progresses.

    • See for information about troubleshooting issues related to the bootstrap process.

    You can log in to your cluster as a default system user by exporting the cluster kubeconfig file. The kubeconfig file contains information about the cluster that is used by the CLI to connect a client to the correct cluster and API server. The file is specific to a cluster and is created during OKD installation.

    Prerequisites

    • You deployed an OKD cluster.

    • You installed the oc CLI.

    Procedure

    1. Export the kubeadmin credentials:

      1For <installation_directory>, specify the path to the directory that you stored the installation files in.
    2. Verify you can run oc commands successfully using the exported configuration:

      1. $ oc whoami

      Example output

      1. system:admin

    Approving the certificate signing requests for your machines

    When you add machines to a cluster, two pending certificate signing requests (CSRs) are generated for each machine that you added. You must confirm that these CSRs are approved or, if necessary, approve them yourself. The client requests must be approved first, followed by the server requests.

    Prerequisites

    • You added machines to your cluster.

    Procedure

    1. Confirm that the cluster recognizes the machines:

      1. $ oc get nodes

      Example output

      1. NAME STATUS ROLES AGE VERSION
      2. master-0 Ready master 63m v1.26.0
      3. master-1 Ready master 63m v1.26.0
      4. master-2 Ready master 64m v1.26.0

      The output lists all of the machines that you created.

      The preceding output might not include the compute nodes, also known as worker nodes, until some CSRs are approved.

    2. Review the pending CSRs and ensure that you see the client requests with the Pending or Approved status for each machine that you added to the cluster:

      1. $ oc get csr

      Example output

      1. NAME AGE REQUESTOR CONDITION
      2. csr-8b2br 15m system:serviceaccount:openshift-machine-config-operator:node-bootstrapper Pending
      3. csr-8vnps 15m system:serviceaccount:openshift-machine-config-operator:node-bootstrapper Pending
      4. ...

      In this example, two machines are joining the cluster. You might see more approved CSRs in the list.

    3. If the CSRs were not approved, after all of the pending CSRs for the machines you added are in Pending status, approve the CSRs for your cluster machines:

      Because the CSRs rotate automatically, approve your CSRs within an hour of adding the machines to the cluster. If you do not approve them within an hour, the certificates will rotate, and more than two certificates will be present for each node. You must approve all of these certificates. After the client CSR is approved, the Kubelet creates a secondary CSR for the serving certificate, which requires manual approval. Then, subsequent serving certificate renewal requests are automatically approved by the machine-approver if the Kubelet requests a new certificate with identical parameters.

      For clusters running on platforms that are not machine API enabled, such as bare metal and other user-provisioned infrastructure, you must implement a method of automatically approving the kubelet serving certificate requests (CSRs). If a request is not approved, then the oc exec, oc rsh, and oc logs commands cannot succeed, because a serving certificate is required when the API server connects to the kubelet. Any operation that contacts the Kubelet endpoint requires this certificate approval to be in place. The method must watch for new CSRs, confirm that the CSR was submitted by the node-bootstrapper service account in the system:node or system:admin groups, and confirm the identity of the node.

      • To approve them individually, run the following command for each valid CSR:

        1. $ oc adm certificate approve <csr_name> (1)
        1<csr_name> is the name of a CSR from the list of current CSRs.
      • To approve all pending CSRs, run the following command:

        1. $ oc get csr -o go-template='{{range .items}}{{if not .status}}{{.metadata.name}}{{"\n"}}{{end}}{{end}}' | xargs --no-run-if-empty oc adm certificate approve

        Some Operators might not become available until some CSRs are approved.

    4. Now that your client requests are approved, you must review the server requests for each machine that you added to the cluster:

      1. $ oc get csr

      Example output

      1. NAME AGE REQUESTOR CONDITION
      2. csr-bfd72 5m26s system:node:ip-10-0-50-126.us-east-2.compute.internal Pending
      3. csr-c57lv 5m26s system:node:ip-10-0-95-157.us-east-2.compute.internal Pending
      4. ...
    5. If the remaining CSRs are not approved, and are in the Pending status, approve the CSRs for your cluster machines:

      • To approve them individually, run the following command for each valid CSR:

        1. $ oc adm certificate approve <csr_name> (1)
        1<csr_name> is the name of a CSR from the list of current CSRs.
      • To approve all pending CSRs, run the following command:

        1. $ oc get csr -o go-template='{{range .items}}{{if not .status}}{{.metadata.name}}{{"\n"}}{{end}}{{end}}' | xargs oc adm certificate approve
    6. After all client and server CSRs have been approved, the machines have the Ready status. Verify this by running the following command:

      1. $ oc get nodes

      Example output

      1. NAME STATUS ROLES AGE VERSION
      2. master-0 Ready master 73m v1.26.0
      3. master-1 Ready master 73m v1.26.0
      4. master-2 Ready master 74m v1.26.0
      5. worker-0 Ready worker 11m v1.26.0
      6. worker-1 Ready worker 11m v1.26.0

      It can take a few minutes after approval of the server CSRs for the machines to transition to the Ready status.

    Additional information

    Initial Operator configuration

    After the control plane initializes, you must immediately configure some Operators so that they all become available.

    Prerequisites

    • Your control plane has initialized.

    Procedure

    1. Watch the cluster components come online:

      1. $ watch -n5 oc get clusteroperators

      Example output

      1. NAME VERSION AVAILABLE PROGRESSING DEGRADED SINCE
      2. authentication 4.13.0 True False False 19m
      3. baremetal 4.13.0 True False False 37m
      4. cloud-credential 4.13.0 True False False 40m
      5. cluster-autoscaler 4.13.0 True False False 37m
      6. config-operator 4.13.0 True False False 38m
      7. console 4.13.0 True False False 26m
      8. csi-snapshot-controller 4.13.0 True False False 37m
      9. dns 4.13.0 True False False 37m
      10. etcd 4.13.0 True False False 36m
      11. image-registry 4.13.0 True False False 31m
      12. ingress 4.13.0 True False False 30m
      13. insights 4.13.0 True False False 31m
      14. kube-apiserver 4.13.0 True False False 26m
      15. kube-controller-manager 4.13.0 True False False 36m
      16. kube-scheduler 4.13.0 True False False 36m
      17. kube-storage-version-migrator 4.13.0 True False False 37m
      18. machine-api 4.13.0 True False False 29m
      19. machine-approver 4.13.0 True False False 37m
      20. machine-config 4.13.0 True False False 36m
      21. marketplace 4.13.0 True False False 37m
      22. monitoring 4.13.0 True False False 29m
      23. network 4.13.0 True False False 38m
      24. node-tuning 4.13.0 True False False 37m
      25. openshift-apiserver 4.13.0 True False False 32m
      26. openshift-controller-manager 4.13.0 True False False 30m
      27. openshift-samples 4.13.0 True False False 32m
      28. operator-lifecycle-manager 4.13.0 True False False 37m
      29. operator-lifecycle-manager-catalog 4.13.0 True False False 37m
      30. operator-lifecycle-manager-packageserver 4.13.0 True False False 32m
      31. service-ca 4.13.0 True False False 38m
      32. storage 4.13.0 True False False 37m
    2. Configure the Operators that are not available.

    Disabling the default OperatorHub catalog sources

    Operator catalogs that source content provided by Red Hat and community projects are configured for OperatorHub by default during an OKD installation. In a restricted network environment, you must disable the default catalogs as a cluster administrator.

    Procedure

    • Disable the sources for the default catalogs by adding disableAllDefaultSources: true to the OperatorHub object:

      1. $ oc patch OperatorHub cluster --type json \
      2. -p '[{"op": "add", "path": "/spec/disableAllDefaultSources", "value": true}]'

    Alternatively, you can use the web console to manage catalog sources. From the AdministrationCluster SettingsConfigurationOperatorHub page, click the Sources tab, where you can create, delete, disable, and enable individual sources.

    Amazon Web Services provides default storage, which means the Image Registry Operator is available after installation. However, if the Registry Operator cannot create an S3 bucket and automatically configure storage, you must manually configure registry storage.

    Instructions are shown for configuring a persistent volume, which is required for production clusters. Where applicable, instructions are shown for configuring an empty directory as the storage location, which is available for only non-production clusters.

    Additional instructions are provided for allowing the image registry to use block storage types by using the Recreate rollout strategy during upgrades.

    Configuring registry storage for AWS with user-provisioned infrastructure

    During installation, your cloud credentials are sufficient to create an Amazon S3 bucket and the Registry Operator will automatically configure storage.

    If the Registry Operator cannot create an S3 bucket and automatically configure storage, you can create an S3 bucket and configure storage with the following procedure.

    Prerequisites

    • You have a cluster on AWS with user-provisioned infrastructure.

    • For Amazon S3 storage, the secret is expected to contain two keys:

      • REGISTRY_STORAGE_S3_ACCESSKEY

      • REGISTRY_STORAGE_S3_SECRETKEY

    Procedure

    Use the following procedure if the Registry Operator cannot create an S3 bucket and automatically configure storage.

    1. Set up a to abort incomplete multipart uploads that are one day old.

    2. Fill in the storage configuration in configs.imageregistry.operator.openshift.io/cluster:

      1. $ oc edit configs.imageregistry.operator.openshift.io/cluster

      Example configuration

      1. storage:
      2. s3:
      3. bucket: <bucket-name>
      4. region: <region-name>

    To secure your registry images in AWS, block public access to the S3 bucket.

    Configuring storage for the image registry in non-production clusters

    You must configure storage for the Image Registry Operator. For non-production clusters, you can set the image registry to an empty directory. If you do so, all images are lost if you restart the registry.

    Procedure

    • To set the image registry storage to an empty directory:

      1. $ oc patch configs.imageregistry.operator.openshift.io cluster --type merge --patch '{"spec":{"storage":{"emptyDir":{}}}}'

      Configure this option for only non-production clusters.

      If you run this command before the Image Registry Operator initializes its components, the oc patch command fails with the following error:

      1. Error from server (NotFound): configs.imageregistry.operator.openshift.io "cluster" not found

      Wait a few minutes and run the command again.

    Deleting the bootstrap resources

    After you complete the initial Operator configuration for the cluster, remove the bootstrap resources from Amazon Web Services (AWS).

    Prerequisites

    • You completed the initial Operator configuration for your cluster.

    Procedure

    1. Delete the bootstrap resources. If you used the CloudFormation template, :

      • Delete the stack by using the AWS CLI:

        1. $ aws cloudformation delete-stack --stack-name <name> (1)
        1<name> is the name of your bootstrap stack.
      • Delete the stack by using the AWS CloudFormation console.

    Creating the Ingress DNS Records

    If you removed the DNS Zone configuration, manually create DNS records that point to the Ingress load balancer. You can create either a wildcard record or specific records. While the following procedure uses A records, you can use other record types that you require, such as CNAME or alias.

    Prerequisites

    Procedure

    1. Determine the routes to create.

      • To create a wildcard record, use *.apps.<cluster_name>.<domain_name>, where <cluster_name> is your cluster name, and <domain_name> is the Route 53 base domain for your OKD cluster.

      • To create specific records, you must create a record for each route that your cluster uses, as shown in the output of the following command:

        1. $ oc get --all-namespaces -o jsonpath='{range .items[*]}{range .status.ingress[*]}{.host}{"\n"}{end}{end}' routes

        Example output

        1. oauth-openshift.apps.<cluster_name>.<domain_name>
        2. console-openshift-console.apps.<cluster_name>.<domain_name>
        3. downloads-openshift-console.apps.<cluster_name>.<domain_name>
        4. alertmanager-main-openshift-monitoring.apps.<cluster_name>.<domain_name>
        5. prometheus-k8s-openshift-monitoring.apps.<cluster_name>.<domain_name>
    2. Retrieve the Ingress Operator load balancer status and note the value of the external IP address that it uses, which is shown in the EXTERNAL-IP column:

      1. $ oc -n openshift-ingress get service router-default

      Example output

      1. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
      2. router-default LoadBalancer 172.30.62.215 ab3...28.us-east-2.elb.amazonaws.com 80:31499/TCP,443:30693/TCP 5m
    3. Locate the hosted zone ID for the load balancer:

      1. $ aws elb describe-load-balancers | jq -r '.LoadBalancerDescriptions[] | select(.DNSName == "<external_ip>").CanonicalHostedZoneNameID' (1)
      1For <external_ip>, specify the value of the external IP address of the Ingress Operator load balancer that you obtained.

      Example output

      1. Z3AADJGX6KTTL2

      The output of this command is the load balancer hosted zone ID.

    4. Obtain the public hosted zone ID for your cluster’s domain:

      1. $ aws route53 list-hosted-zones-by-name \
      2. --dns-name "<domain_name>" \ (1)
      3. --query 'HostedZones[? Config.PrivateZone != `true` && Name == `<domain_name>.`].Id' (1)
      4. --output text
      1For <domain_name>, specify the Route 53 base domain for your OKD cluster.

      Example output

      1. /hostedzone/Z3URY6TWQ91KVV

      The public hosted zone ID for your domain is shown in the command output. In this example, it is Z3URY6TWQ91KVV.

    5. Add the alias records to your private zone:

      1. $ aws route53 change-resource-record-sets --hosted-zone-id "<private_hosted_zone_id>" --change-batch '{ (1)
      2. > "Changes": [
      3. > {
      4. > "Action": "CREATE",
      5. > "ResourceRecordSet": {
      6. > "Name": "\\052.apps.<cluster_domain>", (2)
      7. > "Type": "A",
      8. > "AliasTarget":{
      9. > "HostedZoneId": "<hosted_zone_id>", (3)
      10. > "DNSName": "<external_ip>.", (4)
      11. > "EvaluateTargetHealth": false
      12. > }
      13. > }
      14. > }
      15. > ]
      16. > }'
      1For <private_hosted_zone_id>, specify the value from the output of the CloudFormation template for DNS and load balancing.
      2For <cluster_domain>, specify the domain or subdomain that you use with your OKD cluster.
      3For <hosted_zone_id>, specify the public hosted zone ID for the load balancer that you obtained.
      4For <external_ip>, specify the value of the external IP address of the Ingress Operator load balancer. Ensure that you include the trailing period (.) in this parameter value.
    6. Add the records to your public zone:

      1. $ aws route53 change-resource-record-sets --hosted-zone-id "<public_hosted_zone_id>"" --change-batch '{ (1)
      2. > "Changes": [
      3. > {
      4. > "Action": "CREATE",
      5. > "ResourceRecordSet": {
      6. > "Name": "\\052.apps.<cluster_domain>", (2)
      7. > "Type": "A",
      8. > "AliasTarget":{
      9. > "HostedZoneId": "<hosted_zone_id>", (3)
      10. > "DNSName": "<external_ip>.", (4)
      11. > "EvaluateTargetHealth": false
      12. > }
      13. > }
      14. > }
      15. > ]
      16. > }'
      1For <public_hosted_zone_id>, specify the public hosted zone for your domain.
      2For <cluster_domain>, specify the domain or subdomain that you use with your OKD cluster.
      3For <hosted_zone_id>, specify the public hosted zone ID for the load balancer that you obtained.
      4For <external_ip>, specify the value of the external IP address of the Ingress Operator load balancer. Ensure that you include the trailing period (.) in this parameter value.

    Completing an AWS installation on user-provisioned infrastructure

    After you start the OKD installation on Amazon Web Service (AWS) user-provisioned infrastructure, monitor the deployment to completion.

    Prerequisites

    • You removed the bootstrap node for an OKD cluster on user-provisioned AWS infrastructure.

    • You installed the oc CLI.

    Procedure

    1. From the directory that contains the installation program, complete the cluster installation:

      1. $ ./openshift-install --dir <installation_directory> wait-for install-complete (1)
      1For <installation_directory>, specify the path to the directory that you stored the installation files in.

      Example output

      1. INFO Waiting up to 40m0s for the cluster at https://api.mycluster.example.com:6443 to initialize...
      2. INFO Waiting up to 10m0s for the openshift-console route to be created...
      3. INFO Install complete!
      4. INFO To access the cluster as the system:admin user when using 'oc', run 'export KUBECONFIG=/home/myuser/install_dir/auth/kubeconfig'
      5. INFO Access the OpenShift web-console here: https://console-openshift-console.apps.mycluster.example.com
      6. INFO Login to the console with user: "kubeadmin", and password: "4vYBz-Fe5en-ymBEc-Wt6NL"
      7. INFO Time elapsed: 1s
      • 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.

      • It is recommended that you use Ignition config files within 12 hours after they are generated because the 24-hour certificate rotates from 16 to 22 hours after the cluster is installed. By using the Ignition config files within 12 hours, you can avoid installation failure if the certificate update runs during installation.

    2. Register your cluster on the Cluster registration page.

    Logging in to the cluster by using the web console

    The kubeadmin user exists by default after an OKD installation. You can log in to your cluster as the kubeadmin user by using the OKD web console.

    Prerequisites

    • You have access to the installation host.

    • You completed a cluster installation and all cluster Operators are available.

    Procedure

    1. Obtain the password for the kubeadmin user from the kubeadmin-password file on the installation host:

      1. $ cat <installation_directory>/auth/kubeadmin-password

      Alternatively, you can obtain the kubeadmin password from the <installation_directory>/.openshift_install.log log file on the installation host.

    2. List the OKD web console route:

      Example output

      1. console console-openshift-console.apps.<cluster_name>.<base_domain> console https reencrypt/Redirect None
    3. Navigate to the route detailed in the output of the preceding command in a web browser and log in as the kubeadmin user.

    Additional resources

    Additional resources

    • See for more information about the Telemetry service

    Additional resources

    • See in the AWS documentation for more information about AWS CloudFormation stacks.