×

在OpenShift Container Platform 4.17版本中,您可以安装使用您提供的基础架构的Amazon Web Services (AWS)集群。

创建此基础架构的一种方法是使用提供的CloudFormation模板。您可以修改模板以自定义您的基础架构,或使用其中包含的信息根据您公司的策略创建AWS对象。

执行用户预配基础架构安装的步骤仅作为示例提供。安装您提供的基础架构的集群需要了解云提供商和OpenShift Container Platform的安装过程。提供了一些CloudFormation模板来帮助完成这些步骤或帮助建模您自己的模板。您也可以自由地通过其他方法创建所需的资源;模板只是一个示例。

先决条件

为AWS创建安装文件

要在Amazon Web Services (AWS)上使用用户预配的基础设施安装OpenShift Container Platform,您必须生成安装程序部署集群所需的以及修改这些文件,以便集群仅创建其将使用的机器。您将生成和自定义install-config.yaml文件、Kubernetes清单和Ignition配置文件。您还可以选择在安装的准备阶段首先设置一个单独的var分区。

可选:创建单独的/var分区

建议将OpenShift Container Platform的磁盘分区留给安装程序。但是,在某些情况下,您可能希望在一个您预期会增长的文件系统部分创建单独的分区。

OpenShift Container Platform支持添加单个分区以将存储附加到/var分区或/var的子目录。例如:

  • /var/lib/containers:保存与容器相关的、随着向系统添加更多镜像和容器而可能增长的内容。

  • /var/lib/etcd:保存您可能出于性能优化etcd存储等目的而希望单独保存的数据。

  • /var:保存您可能出于审核等目的而希望单独保存的数据。

/var目录的内容单独存储可以更容易地根据需要增加这些区域的存储空间,并在以后重新安装OpenShift Container Platform并保持数据完整。使用此方法,您不必再次提取所有容器,也不必在更新系统时复制大量日志文件。

因为在Red Hat Enterprise Linux CoreOS (RHCOS)全新安装之前必须存在/var,所以以下过程通过在OpenShift Container Platform安装的openshift-install准备阶段插入的机器配置清单来设置单独的/var分区。

如果您按照此过程中的步骤创建单独的/var分区,则无需如本节后面所述再次创建Kubernetes清单和Ignition配置文件。

步骤
  1. 创建一个目录来保存OpenShift Container Platform安装文件

    $ mkdir $HOME/clusterconfig
  2. 运行openshift-install以在manifestopenshift子目录中创建一组文件。根据提示回答系统问题

    $ openshift-install create manifests --dir $HOME/clusterconfig
    示例输出
    ? SSH Public Key ...
    INFO Credentials loaded from the "myprofile" profile in file "/home/myuser/.aws/credentials"
    INFO Consuming Install Config from target directory
    INFO Manifests created in: $HOME/clusterconfig/manifests and $HOME/clusterconfig/openshift
  3. 可选:确认安装程序已在clusterconfig/openshift目录中创建清单

    $ ls $HOME/clusterconfig/openshift/
    示例输出
    99_kubeadmin-password-secret.yaml
    99_openshift-cluster-api_master-machines-0.yaml
    99_openshift-cluster-api_master-machines-1.yaml
    99_openshift-cluster-api_master-machines-2.yaml
    ...
  4. 创建一个Butane配置,用于配置附加分区。例如,将文件命名为$HOME/clusterconfig/98-var-partition.bu,将磁盘设备名称更改为worker系统上存储设备的名称,并根据需要设置存储大小。此示例将/var目录放在单独的分区上

    variant: openshift
    version: 4.17.0
    metadata:
      labels:
        machineconfiguration.openshift.io/role: worker
      name: 98-var-partition
    storage:
      disks:
      - device: /dev/disk/by-id/<device_name> (1)
        partitions:
        - label: var
          start_mib: <partition_start_offset> (2)
          size_mib: <partition_size> (3)
          number: 5
      filesystems:
        - device: /dev/disk/by-partlabel/var
          path: /var
          format: xfs
          mount_options: [defaults, prjquota] (4)
          with_mount_unit: true
    1 您要分区的磁盘的存储设备名称。
    2 向启动磁盘添加数据分区时,建议最小值为25000 MiB(Mebibytes)。根文件系统将自动调整大小以填充所有可用空间,直至指定的偏移量。如果没有指定值,或者指定的值小于建议的最小值,则生成的根文件系统将太小,并且以后重新安装RHCOS可能会覆盖数据分区的开头。
    3 数据分区的大小(以兆字节为单位)。
    4 必须为用于容器存储的文件系统启用prjquota挂载选项。

    创建单独的/var分区时,如果不同的实例类型没有相同的设备名称,则不能为工作节点使用不同的实例类型。

  5. 根据Butane配置创建一个清单,并将其保存到clusterconfig/openshift目录。例如,运行以下命令

    $ butane $HOME/clusterconfig/98-var-partition.bu -o $HOME/clusterconfig/openshift/98-var-partition.yaml
  6. 再次运行openshift-install以根据manifestopenshift子目录中的一组文件创建Ignition配置。

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

现在,您可以使用Ignition配置文件作为安装过程的输入来安装Red Hat Enterprise Linux CoreOS (RHCOS)系统。

创建安装配置文件

生成和自定义安装程序部署集群所需的安装配置文件。

先决条件
  • 您已获得用于用户预配基础设施的OpenShift Container Platform安装程序和集群的pull secret。

  • 您已检查您是否正在将集群部署到具有Red Hat发布的Red Hat Enterprise Linux CoreOS (RHCOS) AMI的AWS区域。如果您正在部署到需要自定义AMI的AWS区域(例如AWS GovCloud区域),则必须手动创建install-config.yaml文件。

步骤
  1. 创建install-config.yaml文件。

    1. 更改到包含安装程序的目录,并运行以下命令

      $ ./openshift-install create install-config --dir <installation_directory> (1)
      1 对于<installation_directory>,指定存储安装程序创建文件的目录名称。

      指定一个空目录。一些安装资源(如引导X.509证书)具有较短的到期时间间隔,因此您不能重用安装目录。如果您想重用来自另一个集群安装的单个文件,您可以将它们复制到您的目录中。但是,安装资源的文件名在不同版本之间可能会发生变化。从早期OpenShift Container Platform版本复制安装文件时,请注意谨慎。

    2. 在提示符下,提供云的配置详细信息

      1. 可选:选择一个SSH密钥来访问您的集群机器。

        对于要在其上执行安装调试或灾难恢复的生产OpenShift Container Platform集群,请指定您的ssh-agent进程使用的SSH密钥。

      2. 选择**aws**作为目标平台。

      3. 如果您计算机上没有存储 AWS 配置文件,请输入您配置为运行安装程序的用户AWS访问密钥 ID 和秘密访问密钥。

        AWS 访问密钥 ID 和秘密访问密钥存储在安装主机当前用户的 home 目录下的~/.aws/credentials中。如果导出的配置文件的凭据不在文件中,安装程序会提示您输入凭据。您提供给安装程序的任何凭据都将存储在该文件中。

      4. 选择要将集群部署到的 AWS 区域。

      5. 为您的集群配置的 Route 53 服务选择基础域名。

      6. 输入集群的描述性名称。

      7. 粘贴来自 Red Hat OpenShift 集群管理器的拉取密钥

  2. 如果您正在安装三节点集群,请通过将install-config.yaml文件中的compute.replicas参数设置为0来修改该文件。这确保了集群的控制平面是可调度的。有关更多信息,请参见“在 AWS 上安装三节点集群”。

  3. 可选:备份install-config.yaml文件。

    install-config.yaml文件在安装过程中会被使用。如果您想重复使用该文件,您现在必须对其进行备份。

其他资源

在安装过程中配置集群范围的代理

生产环境可能会拒绝直接访问互联网,而是提供 HTTP 或 HTTPS 代理。您可以通过在install-config.yaml文件中配置代理设置来配置新的 OpenShift Container Platform 集群以使用代理。

先决条件
  • 您拥有一个现有的install-config.yaml文件。

  • 您已查看集群需要访问的站点,并确定其中哪些站点需要绕过代理。默认情况下,所有集群出站流量都会被代理,包括对托管云提供商 API 的调用。如有必要,您已将站点添加到Proxy对象的spec.noProxy字段以绕过代理。

    Proxy对象的status.noProxy字段填充了安装配置中networking.machineNetwork[].cidrnetworking.clusterNetwork[].cidrnetworking.serviceNetwork[]字段的值。

    对于在 Amazon Web Services (AWS)、Google Cloud Platform (GCP)、Microsoft Azure 和 Red Hat OpenStack Platform (RHOSP) 上的安装,Proxy对象的status.noProxy字段还会填充实例元数据端点 (169.254.169.254)。

步骤
  1. 编辑您的install-config.yaml文件并添加代理设置。例如:

    apiVersion: v1
    baseDomain: my.domain.com
    proxy:
      httpProxy: http://<username>:<pswd>@<ip>:<port> (1)
      httpsProxy: https://<username>:<pswd>@<ip>:<port> (2)
      noProxy: ec2.<aws_region>.amazonaws.com,elasticloadbalancing.<aws_region>.amazonaws.com,s3.<aws_region>.amazonaws.com (3)
    additionalTrustBundle: | (4)
        -----BEGIN CERTIFICATE-----
        <MY_TRUSTED_CA_CERT>
        -----END CERTIFICATE-----
    additionalTrustBundlePolicy: <policy_to_add_additionalTrustBundle> (5)
    1 用于在集群外部创建 HTTP 连接的代理 URL。URL 方案必须为http
    2 用于在集群外部创建 HTTPS 连接的代理 URL。
    3 要从代理中排除的目标域名、IP 地址或其他网络 CIDR 的逗号分隔列表。在域名前加.以仅匹配子域名。例如,.y.com匹配x.y.com,但不匹配y.com。使用*绕过所有目标的代理。如果您已将 Amazon EC2Elastic Load BalancingS3 VPC 端点添加到您的 VPC,则必须将这些端点添加到noProxy字段。
    4 如果提供,安装程序会生成一个名为user-ca-bundle的 config map(位于openshift-config命名空间中),其中包含一个或多个代理 HTTPS 连接所需的附加 CA 证书。然后,集群网络操作员创建一个trusted-ca-bundle config map,将这些内容与 Red Hat Enterprise Linux CoreOS (RHCOS) 信任捆绑包合并,并引用Proxy对象的trustedCA字段中的此 config map。除非代理的身份证书由 RHCOS 信任捆绑包中的权威机构签署,否则需要additionalTrustBundle字段。
    5 可选:确定Proxy对象的配置以引用trustedCA字段中user-ca-bundle config map 的策略。允许的值为ProxyonlyAlways。使用Proxyonly仅在配置http/https代理时引用user-ca-bundle config map。使用Always始终引用user-ca-bundle config map。默认值为Proxyonly

    安装程序不支持代理readinessEndpoints字段。

    如果安装程序超时,请重新启动,然后使用安装程序的wait-for命令完成部署。例如:

    $ ./openshift-install wait-for install-complete --log-level debug
  2. 保存文件并在安装 OpenShift Container Platform 时引用它。

安装程序创建一个名为cluster的集群范围代理,该代理使用提供的install-config.yaml文件中的代理设置。如果未提供代理设置,仍然会创建cluster Proxy对象,但它将具有 nil spec

仅支持名为clusterProxy对象,并且不能创建其他代理。

创建 Kubernetes 清单和 Ignition 配置文件

因为您必须修改一些集群定义文件并手动启动集群机器,所以您必须生成集群配置机器所需的 Kubernetes 清单和 Ignition 配置文件。

安装配置文件会转换为 Kubernetes 清单。清单会包装到 Ignition 配置文件中,这些文件稍后将用于配置集群机器。

  • OpenShift Container Platform 安装程序生成的 Ignition 配置文件包含在 24 小时后过期的证书,然后会在那时续订。如果集群在续订证书之前关闭,并且在 24 小时后重新启动,集群会自动恢复过期的证书。例外情况是,您必须手动批准挂起的node-bootstrapper证书签名请求 (CSR) 以恢复 kubelet 证书。有关更多信息,请参阅有关“从过期的控制平面证书中恢复”的文档。

  • 建议您在生成 Ignition 配置文件后 12 小时内使用它们,因为 24 小时证书会在集群安装后 16 到 22 小时之间轮换。通过在 12 小时内使用 Ignition 配置文件,如果证书更新在安装过程中运行,您可以避免安装失败。

先决条件
  • 您已获得 OpenShift Container Platform 安装程序。

  • 您已创建install-config.yaml安装配置文件。

步骤
  1. 更改到包含 OpenShift Container Platform 安装程序的目录,并为集群生成 Kubernetes 清单

    $ ./openshift-install create manifests --dir <installation_directory> (1)
    1 对于<installation_directory>,请指定包含您创建的install-config.yaml文件的安装目录。
  2. 删除定义控制平面机器的 Kubernetes 清单文件。

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

    删除这些文件可以防止集群自动生成控制平面机器。

  3. 删除定义控制平面机器集的 Kubernetes 清单文件。

    $ rm -f <installation_directory>/openshift/99_openshift-machine-api_master-control-plane-machine-set.yaml
  4. 删除定义工作机器的 Kubernetes 清单文件。

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

    如果您在用户预配的基础架构上安装集群时禁用了MachineAPI功能,则必须删除定义工作机器的 Kubernetes 清单文件。否则,您的集群安装将失败。

    因为您自己创建和管理工作机器,所以不需要初始化这些机器。

    如果您正在安装一个三节点集群,请跳过以下步骤以允许控制平面节点可调度。

    当您将控制平面节点从默认的不可调度配置为可调度时,需要额外的订阅。这是因为控制平面节点随后会变成计算节点。

  5. 检查<installation_directory>/manifests/cluster-scheduler-02-config.yml Kubernetes 清单文件中mastersSchedulable参数是否设置为false。此设置可防止将 Pod 调度到控制平面机器上。

    1. 打开<installation_directory>/manifests/cluster-scheduler-02-config.yml文件。

    2. 找到mastersSchedulable参数并确保其设置为false

    3. 保存并退出文件。

  6. 可选:如果您不希望Ingress Operator代表您创建 DNS 记录,请从<installation_directory>/manifests/cluster-dns-02-config.yml DNS 配置文件中删除privateZonepublicZone部分。

    apiVersion: config.openshift.io/v1
    kind: DNS
    metadata:
      creationTimestamp: null
      name: cluster
    spec:
      baseDomain: example.openshift.com
      privateZone: (1)
        id: mycluster-100419-private-zone
      publicZone: (1)
        id: example.openshift.com
    status: {}
    1 完全删除此部分。

    如果您这样做,则必须在后面的步骤中手动添加 Ingress DNS 记录。

  7. 要创建 Ignition 配置文件,请从包含安装程序的目录运行以下命令。

    $ ./openshift-install create ignition-configs --dir <installation_directory> (1)
    1 对于<installation_directory>,请指定相同的安装目录。

    在安装目录中为引导程序、控制平面和计算节点创建 Ignition 配置文件。kubeadmin-passwordkubeconfig文件创建在./<installation_directory>/auth目录中。

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

提取基础设施名称

Ignition 配置文件包含一个唯一的集群标识符,您可以使用它来唯一标识您在 Amazon Web Services (AWS) 中的集群。基础设施名称还用于在 OpenShift Container Platform 安装期间查找相应的 AWS 资源。提供的 CloudFormation 模板包含对该基础设施名称的引用,因此您必须提取它。

先决条件
  • 您已获得 OpenShift Container Platform 安装程序和集群的拉取密钥。

  • 您已为您的集群生成 Ignition 配置文件。

  • 您已安装jq包。

步骤
  • 要从 Ignition 配置文件元数据中提取和查看基础设施名称,请运行以下命令。

    $ jq -r .infraID <installation_directory>/metadata.json (1)
    1 对于<installation_directory>,请指定您存储安装文件的目录的路径。
    示例输出
    openshift-vw9j6 (1)
    
    1 此命令的输出是您的集群名称和一个随机字符串。

在 AWS 中创建 VPC

您必须在 Amazon Web Services (AWS) 中创建一个虚拟私有云 (VPC),供您的 OpenShift Container Platform 集群使用。您可以自定义 VPC 以满足您的需求,包括 VPN 和路由表。

您可以使用提供的 CloudFormation 模板和自定义参数文件来创建代表 VPC 的 AWS 资源堆栈。

如果您不使用提供的 CloudFormation 模板创建您的 AWS 基础设施,则必须查看提供的信息并手动创建基础设施。如果您的集群无法正确初始化,您可能需要联系 Red Hat 支持并提供您的安装日志。

先决条件
  • 您已配置 AWS 账户。

  • 您已通过运行aws configure将您的 AWS 密钥和区域添加到您的本地 AWS 配置文件中。

  • 您已为您的集群生成 Ignition 配置文件。

步骤
  1. 创建一个 JSON 文件,其中包含模板所需的参数值。

    [
      {
        "ParameterKey": "VpcCidr", (1)
        "ParameterValue": "10.0.0.0/16" (2)
      },
      {
        "ParameterKey": "AvailabilityZoneCount", (3)
        "ParameterValue": "1" (4)
      },
      {
        "ParameterKey": "SubnetBits", (5)
        "ParameterValue": "12" (6)
      }
    ]
    1 VPC 的 CIDR 块。
    2 请使用x.x.x.x/16-24格式指定 CIDR 块。
    3 要在其中部署 VPC 的可用区数量。
    4 指定13之间的整数。
    5 每个可用区中每个子网的大小。
    6 指定513之间的整数,其中5/2713/19
  2. 从本主题的“VPC 的 CloudFormation 模板”部分复制模板,并将其另存为计算机上的 YAML 文件。此模板描述了集群所需的 VPC。

  3. 启动 CloudFormation 模板以创建代表 VPC 的 AWS 资源堆栈。

    您必须在一行中输入命令。

    $ aws cloudformation create-stack --stack-name <name> (1)
         --template-body file://<template>.yaml (2)
         --parameters file://<parameters>.json (3)
    1 <name>是 CloudFormation 堆栈的名称,例如cluster-vpc。如果您删除集群,则需要此堆栈的名称。
    2 <template>是您保存的 CloudFormation 模板 YAML 文件的相对路径和名称。
    3 <parameters>是 CloudFormation 参数 JSON 文件的相对路径和名称。
    示例输出
    arn:aws:cloudformation:us-east-1:269333783861:stack/cluster-vpc/dbedae40-2fd3-11eb-820e-12a48460849f
  4. 确认模板组件存在。

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

    StackStatus显示CREATE_COMPLETE后,输出将显示以下参数的值。您必须将这些参数值提供给您运行以创建集群的其他 CloudFormation 模板。

    VpcId

    您的 VPC 的 ID。

    PublicSubnetIds

    新公共子网的 ID。

    PrivateSubnetIds

    新的专用子网的 ID。

VPC 的 CloudFormation 模板

您可以使用以下 CloudFormation 模板部署 OpenShift Container Platform 集群所需的 VPC。

VPC的CloudFormation模板
AWSTemplateFormatVersion: 2010-09-09
Description: Template for Best Practice VPC with 1-3 AZs

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

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

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

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

Outputs:
  VpcId:
    Description: ID of the new VPC.
    Value: !Ref VPC
  PublicSubnetIds:
    Description: Subnet IDs of the public subnets.
    Value:
      !Join [
        ",",
        [!Ref PublicSubnet, !If [DoAz2, !Ref PublicSubnet2, !Ref "AWS::NoValue"], !If [DoAz3, !Ref PublicSubnet3, !Ref "AWS::NoValue"]]
      ]
  PrivateSubnetIds:
    Description: Subnet IDs of the private subnets.
    Value:
      !Join [
        ",",
        [!Ref PrivateSubnet, !If [DoAz2, !Ref PrivateSubnet2, !Ref "AWS::NoValue"], !If [DoAz3, !Ref PrivateSubnet3, !Ref "AWS::NoValue"]]
      ]
  PublicRouteTableId:
    Description: Public Route table ID
    Value: !Ref PublicRouteTable
  PrivateRouteTableIds:
    Description: Private Route table IDs
    Value:
      !Join [
        ",",
        [
          !Join ["=", [
            !Select [0, "Fn::GetAZs": !Ref "AWS::Region"],
            !Ref PrivateRouteTable
          ]],
          !If [DoAz2,
               !Join ["=", [!Select [1, "Fn::GetAZs": !Ref "AWS::Region"], !Ref PrivateRouteTable2]],
               !Ref "AWS::NoValue"
          ],
          !If [DoAz3,
               !Join ["=", [!Select [2, "Fn::GetAZs": !Ref "AWS::Region"], !Ref PrivateRouteTable3]],
               !Ref "AWS::NoValue"
          ]
        ]
      ]
其他资源

在 AWS 中创建网络和负载均衡组件

您必须在 Amazon Web Services (AWS) 中配置网络和经典或网络负载均衡,以便您的 OpenShift Container Platform 集群可以使用。

您可以使用提供的 CloudFormation 模板和自定义参数文件来创建 AWS 资源堆栈。该堆栈代表您的 OpenShift Container Platform 集群所需的网络和负载均衡组件。该模板还创建托管区域和子网标签。

您可以在单个虚拟私有云 (VPC) 中多次运行该模板。

如果您不使用提供的 CloudFormation 模板创建您的 AWS 基础设施,则必须查看提供的信息并手动创建基础设施。如果您的集群无法正确初始化,您可能需要联系 Red Hat 支持并提供您的安装日志。

先决条件
  • 您已配置 AWS 账户。

  • 您已通过运行aws configure将您的 AWS 密钥和区域添加到您的本地 AWS 配置文件中。

  • 您已为您的集群生成 Ignition 配置文件。

  • 您已在 AWS 中创建和配置了 VPC 和关联的子网。

步骤
  1. 获取您为集群的install-config.yaml文件中指定的 Route 53 基础域的托管区域 ID。您可以通过运行以下命令来获取有关托管区域的详细信息。

    $ aws route53 list-hosted-zones-by-name --dns-name <route53_domain> (1)
    1 对于<route53_domain>,请指定在生成集群的install-config.yaml文件时使用的 Route 53 基础域。
    示例输出
    mycluster.example.com.	False	100
    HOSTEDZONES	65F8F38E-2268-B835-E15C-AB55336FCBFA	/hostedzone/Z21IXYZABCZ2A4	mycluster.example.com.	10

    在示例输出中,托管区域 ID 为Z21IXYZABCZ2A4

  2. 创建一个 JSON 文件,其中包含模板所需的参数值。

    [
      {
        "ParameterKey": "ClusterName", (1)
        "ParameterValue": "mycluster" (2)
      },
      {
        "ParameterKey": "InfrastructureName", (3)
        "ParameterValue": "mycluster-<random_string>" (4)
      },
      {
        "ParameterKey": "HostedZoneId", (5)
        "ParameterValue": "<random_string>" (6)
      },
      {
        "ParameterKey": "HostedZoneName", (7)
        "ParameterValue": "example.com" (8)
      },
      {
        "ParameterKey": "PublicSubnets", (9)
        "ParameterValue": "subnet-<random_string>" (10)
      },
      {
        "ParameterKey": "PrivateSubnets", (11)
        "ParameterValue": "subnet-<random_string>" (12)
      },
      {
        "ParameterKey": "VpcId", (13)
        "ParameterValue": "vpc-<random_string>" (14)
      }
    ]
    1 一个简短的、具有代表性的集群名称,用于主机名等。
    2 指定您在生成集群的install-config.yaml文件时使用的集群名称。
    3 集群的 Ignition 配置文件中编码的集群基础设施名称。
    4 指定您从 Ignition 配置文件元数据中提取的基础设施名称,其格式为<cluster-name>-<random-string>
    5 用于注册目标的 Route 53 公共区域 ID。
    6 指定 Route 53 公共区域 ID,其格式类似于Z21IXYZABCZ2A4。您可以从 AWS 控制台获取此值。
    7 用于注册目标的 Route 53 区域。
    8 指定您在生成集群的install-config.yaml文件时使用的 Route 53 基础域名。不要包含 AWS 控制台中显示的尾随句点(.)。
    9 您为 VPC 创建的公共子网。
    10 指定 VPC 的 CloudFormation 模板输出中的PublicSubnetIds值。
    11 您为 VPC 创建的私有子网。
    12 指定 VPC 的 CloudFormation 模板输出中的PrivateSubnetIds值。
    13 您为集群创建的 VPC。
    14 指定 VPC 的 CloudFormation 模板输出中的VpcId值。
  3. 复制本主题“网络和负载均衡器 CloudFormation 模板”部分中的模板,并将其另存为 YAML 文件到您的计算机上。此模板描述了集群所需的网络和负载均衡对象。

    如果您将集群部署到 AWS 政府或秘密区域,则必须更新 CloudFormation 模板中的InternalApiServerRecord以使用CNAME记录。AWS 政府区域不支持类型为ALIAS的记录。

  4. 启动 CloudFormation 模板以创建提供网络和负载均衡组件的 AWS 资源堆栈。

    您必须在一行中输入命令。

    $ aws cloudformation create-stack --stack-name <name> (1)
         --template-body file://<template>.yaml (2)
         --parameters file://<parameters>.json (3)
         --capabilities CAPABILITY_NAMED_IAM (4)
    
    1 <name>是 CloudFormation 堆栈的名称,例如cluster-dns。如果您删除集群,则需要此堆栈的名称。
    2 <template>是您保存的 CloudFormation 模板 YAML 文件的相对路径和名称。
    3 <parameters>是 CloudFormation 参数 JSON 文件的相对路径和名称。
    4 您必须显式声明CAPABILITY_NAMED_IAM功能,因为提供的模板会创建一些AWS::IAM::Role资源。
    示例输出
    arn:aws:cloudformation:us-east-1:269333783861:stack/cluster-dns/cd3e5de0-2fd4-11eb-5cf0-12be5c33a183
  5. 确认模板组件存在。

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

    StackStatus显示CREATE_COMPLETE后,输出将显示以下参数的值。您必须将这些参数值提供给您运行以创建集群的其他 CloudFormation 模板。

    PrivateHostedZoneId

    私有 DNS 的托管区域 ID。

    ExternalApiLoadBalancerName

    外部 API 负载均衡器的完整名称。

    InternalApiLoadBalancerName

    内部 API 负载均衡器的完整名称。

    ApiServerDnsName

    API 服务器的完整主机名。

    RegisterNlbIpTargetsLambda

    有用的 Lambda ARN,有助于注册/注销这些负载均衡器的 IP 目标。

    ExternalApiTargetGroupArn

    外部 API 目标组的 ARN。

    InternalApiTargetGroupArn

    内部 API 目标组的 ARN。

    InternalServiceTargetGroupArn

    内部服务目标组的 ARN。

网络和负载均衡器的 CloudFormation 模板

您可以使用以下 CloudFormation 模板来部署 OpenShift Container Platform 集群所需的网络对象和负载均衡器。

网络和负载均衡器的CloudFormation模板
AWSTemplateFormatVersion: 2010-09-09
Description: Template for OpenShift Cluster Network Elements (Route53 & LBs)

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

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

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

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

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

  ExternalApiServerRecord:
    Type: AWS::Route53::RecordSetGroup
    Properties:
      Comment: Alias record for the API server
      HostedZoneId: !Ref HostedZoneId
      RecordSets:
      - Name:
          !Join [
            ".",
            ["api", !Ref ClusterName, !Join ["", [!Ref HostedZoneName, "."]]],
          ]
        Type: A
        AliasTarget:
          HostedZoneId: !GetAtt ExtApiElb.CanonicalHostedZoneID
          DNSName: !GetAtt ExtApiElb.DNSName

  InternalApiServerRecord:
    Type: AWS::Route53::RecordSetGroup
    Properties:
      Comment: Alias record for the API server
      HostedZoneId: !Ref IntDns
      RecordSets:
      - Name:
          !Join [
            ".",
            ["api", !Ref ClusterName, !Join ["", [!Ref HostedZoneName, "."]]],
          ]
        Type: A
        AliasTarget:
          HostedZoneId: !GetAtt IntApiElb.CanonicalHostedZoneID
          DNSName: !GetAtt IntApiElb.DNSName
      - Name:
          !Join [
            ".",
            ["api-int", !Ref ClusterName, !Join ["", [!Ref HostedZoneName, "."]]],
          ]
        Type: A
        AliasTarget:
          HostedZoneId: !GetAtt IntApiElb.CanonicalHostedZoneID
          DNSName: !GetAtt IntApiElb.DNSName

  ExternalApiListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
      - Type: forward
        TargetGroupArn:
          Ref: ExternalApiTargetGroup
      LoadBalancerArn:
        Ref: ExtApiElb
      Port: 6443
      Protocol: TCP

  ExternalApiTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckIntervalSeconds: 10
      HealthCheckPath: "/readyz"
      HealthCheckPort: 6443
      HealthCheckProtocol: HTTPS
      HealthyThresholdCount: 2
      UnhealthyThresholdCount: 2
      Port: 6443
      Protocol: TCP
      TargetType: ip
      VpcId:
        Ref: VpcId
      TargetGroupAttributes:
      - Key: deregistration_delay.timeout_seconds
        Value: 60

  InternalApiListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
      - Type: forward
        TargetGroupArn:
          Ref: InternalApiTargetGroup
      LoadBalancerArn:
        Ref: IntApiElb
      Port: 6443
      Protocol: TCP

  InternalApiTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckIntervalSeconds: 10
      HealthCheckPath: "/readyz"
      HealthCheckPort: 6443
      HealthCheckProtocol: HTTPS
      HealthyThresholdCount: 2
      UnhealthyThresholdCount: 2
      Port: 6443
      Protocol: TCP
      TargetType: ip
      VpcId:
        Ref: VpcId
      TargetGroupAttributes:
      - Key: deregistration_delay.timeout_seconds
        Value: 60

  InternalServiceInternalListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
      - Type: forward
        TargetGroupArn:
          Ref: InternalServiceTargetGroup
      LoadBalancerArn:
        Ref: IntApiElb
      Port: 22623
      Protocol: TCP

  InternalServiceTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckIntervalSeconds: 10
      HealthCheckPath: "/healthz"
      HealthCheckPort: 22623
      HealthCheckProtocol: HTTPS
      HealthyThresholdCount: 2
      UnhealthyThresholdCount: 2
      Port: 22623
      Protocol: TCP
      TargetType: ip
      VpcId:
        Ref: VpcId
      TargetGroupAttributes:
      - Key: deregistration_delay.timeout_seconds
        Value: 60

  RegisterTargetLambdaIamRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Join ["-", [!Ref InfrastructureName, "nlb", "lambda", "role"]]
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
        - Effect: "Allow"
          Principal:
            Service:
            - "lambda.amazonaws.com"
          Action:
          - "sts:AssumeRole"
      Path: "/"
      Policies:
      - PolicyName: !Join ["-", [!Ref InfrastructureName, "master", "policy"]]
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
          - Effect: "Allow"
            Action:
              [
                "elasticloadbalancing:RegisterTargets",
                "elasticloadbalancing:DeregisterTargets",
              ]
            Resource: !Ref InternalApiTargetGroup
          - Effect: "Allow"
            Action:
              [
                "elasticloadbalancing:RegisterTargets",
                "elasticloadbalancing:DeregisterTargets",
              ]
            Resource: !Ref InternalServiceTargetGroup
          - Effect: "Allow"
            Action:
              [
                "elasticloadbalancing:RegisterTargets",
                "elasticloadbalancing:DeregisterTargets",
              ]
            Resource: !Ref ExternalApiTargetGroup

  RegisterNlbIpTargets:
    Type: "AWS::Lambda::Function"
    Properties:
      Handler: "index.handler"
      Role:
        Fn::GetAtt:
        - "RegisterTargetLambdaIamRole"
        - "Arn"
      Code:
        ZipFile: |
          import json
          import boto3
          import cfnresponse
          def handler(event, context):
            elb = boto3.client('elbv2')
            if event['RequestType'] == 'Delete':
              elb.deregister_targets(TargetGroupArn=event['ResourceProperties']['TargetArn'],Targets=[{'Id': event['ResourceProperties']['TargetIp']}])
            elif event['RequestType'] == 'Create':
              elb.register_targets(TargetGroupArn=event['ResourceProperties']['TargetArn'],Targets=[{'Id': event['ResourceProperties']['TargetIp']}])
            responseData = {}
            cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, event['ResourceProperties']['TargetArn']+event['ResourceProperties']['TargetIp'])
      Runtime: "python3.11"
      Timeout: 120

  RegisterSubnetTagsLambdaIamRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Join ["-", [!Ref InfrastructureName, "subnet-tags-lambda-role"]]
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
        - Effect: "Allow"
          Principal:
            Service:
            - "lambda.amazonaws.com"
          Action:
          - "sts:AssumeRole"
      Path: "/"
      Policies:
      - PolicyName: !Join ["-", [!Ref InfrastructureName, "subnet-tagging-policy"]]
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
          - Effect: "Allow"
            Action:
              [
                "ec2:DeleteTags",
                "ec2:CreateTags"
              ]
            Resource: "arn:aws:ec2:*:*:subnet/*"
          - Effect: "Allow"
            Action:
              [
                "ec2:DescribeSubnets",
                "ec2:DescribeTags"
              ]
            Resource: "*"

  RegisterSubnetTags:
    Type: "AWS::Lambda::Function"
    Properties:
      Handler: "index.handler"
      Role:
        Fn::GetAtt:
        - "RegisterSubnetTagsLambdaIamRole"
        - "Arn"
      Code:
        ZipFile: |
          import json
          import boto3
          import cfnresponse
          def handler(event, context):
            ec2_client = boto3.client('ec2')
            if event['RequestType'] == 'Delete':
              for subnet_id in event['ResourceProperties']['Subnets']:
                ec2_client.delete_tags(Resources=[subnet_id], Tags=[{'Key': 'kubernetes.io/cluster/' + event['ResourceProperties']['InfrastructureName']}]);
            elif event['RequestType'] == 'Create':
              for subnet_id in event['ResourceProperties']['Subnets']:
                ec2_client.create_tags(Resources=[subnet_id], Tags=[{'Key': 'kubernetes.io/cluster/' + event['ResourceProperties']['InfrastructureName'], 'Value': 'shared'}]);
            responseData = {}
            cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, event['ResourceProperties']['InfrastructureName']+event['ResourceProperties']['Subnets'][0])
      Runtime: "python3.11"
      Timeout: 120

  RegisterPublicSubnetTags:
    Type: Custom::SubnetRegister
    Properties:
      ServiceToken: !GetAtt RegisterSubnetTags.Arn
      InfrastructureName: !Ref InfrastructureName
      Subnets: !Ref PublicSubnets

  RegisterPrivateSubnetTags:
    Type: Custom::SubnetRegister
    Properties:
      ServiceToken: !GetAtt RegisterSubnetTags.Arn
      InfrastructureName: !Ref InfrastructureName
      Subnets: !Ref PrivateSubnets

Outputs:
  PrivateHostedZoneId:
    Description: Hosted zone ID for the private DNS, which is required for private records.
    Value: !Ref IntDns
  ExternalApiLoadBalancerName:
    Description: Full name of the external API load balancer.
    Value: !GetAtt ExtApiElb.LoadBalancerFullName
  InternalApiLoadBalancerName:
    Description: Full name of the internal API load balancer.
    Value: !GetAtt IntApiElb.LoadBalancerFullName
  ApiServerDnsName:
    Description: Full hostname of the API server, which is required for the Ignition config files.
    Value: !Join [".", ["api-int", !Ref ClusterName, !Ref HostedZoneName]]
  RegisterNlbIpTargetsLambda:
    Description: Lambda ARN useful to help register or deregister IP targets for these load balancers.
    Value: !GetAtt RegisterNlbIpTargets.Arn
  ExternalApiTargetGroupArn:
    Description: ARN of the external API target group.
    Value: !Ref ExternalApiTargetGroup
  InternalApiTargetGroupArn:
    Description: ARN of the internal API target group.
    Value: !Ref InternalApiTargetGroup
  InternalServiceTargetGroupArn:
    Description: ARN of the internal service target group.
    Value: !Ref InternalServiceTargetGroup

如果您将集群部署到 AWS 政府或秘密区域,则必须更新InternalApiServerRecord以使用CNAME记录。AWS 政府区域不支持类型为ALIAS的记录。例如

Type: CNAME
TTL: 10
ResourceRecords:
- !GetAtt IntApiElb.DNSName
其他资源

在 AWS 中创建安全组和角色

您必须在 Amazon Web Services (AWS) 中为您的 OpenShift Container Platform 集群创建安全组和角色才能使用。

您可以使用提供的 CloudFormation 模板和自定义参数文件来创建 AWS 资源堆栈。该堆栈代表 OpenShift Container Platform 集群所需的安全性组和角色。

如果您不使用提供的 CloudFormation 模板创建您的 AWS 基础设施,则必须查看提供的信息并手动创建基础设施。如果您的集群无法正确初始化,您可能需要联系 Red Hat 支持并提供您的安装日志。

先决条件
  • 您已配置 AWS 账户。

  • 您已通过运行aws configure将您的 AWS 密钥和区域添加到您的本地 AWS 配置文件中。

  • 您已为您的集群生成 Ignition 配置文件。

  • 您已在 AWS 中创建和配置了 VPC 和关联的子网。

步骤
  1. 创建一个 JSON 文件,其中包含模板所需的参数值。

    [
      {
        "ParameterKey": "InfrastructureName", (1)
        "ParameterValue": "mycluster-<random_string>" (2)
      },
      {
        "ParameterKey": "VpcCidr", (3)
        "ParameterValue": "10.0.0.0/16" (4)
      },
      {
        "ParameterKey": "PrivateSubnets", (5)
        "ParameterValue": "subnet-<random_string>" (6)
      },
      {
        "ParameterKey": "VpcId", (7)
        "ParameterValue": "vpc-<random_string>" (8)
      }
    ]
    1 集群的 Ignition 配置文件中编码的集群基础设施名称。
    2 指定您从 Ignition 配置文件元数据中提取的基础设施名称,其格式为<cluster-name>-<random-string>
    3 VPC 的 CIDR 块。
    4 指定您为 VPC 使用的 CIDR 块参数,格式为x.x.x.x/16-24
    5 您为 VPC 创建的私有子网。
    6 指定 VPC 的 CloudFormation 模板输出中的PrivateSubnetIds值。
    7 您为集群创建的 VPC。
    8 指定 VPC 的 CloudFormation 模板输出中的VpcId值。
  2. 复制本主题“安全对象 CloudFormation 模板”部分中的模板,并将其另存为 YAML 文件到您的计算机上。此模板描述了集群所需的安全性组和角色。

  3. 启动 CloudFormation 模板以创建代表安全组和角色的 AWS 资源堆栈。

    您必须在一行中输入命令。

    $ aws cloudformation create-stack --stack-name <name> (1)
         --template-body file://<template>.yaml (2)
         --parameters file://<parameters>.json (3)
         --capabilities CAPABILITY_NAMED_IAM (4)
    
    1 <name>是 CloudFormation 堆栈的名称,例如cluster-sec。如果您删除集群,则需要此堆栈的名称。
    2 <template>是您保存的 CloudFormation 模板 YAML 文件的相对路径和名称。
    3 <parameters>是 CloudFormation 参数 JSON 文件的相对路径和名称。
    4 您必须显式声明CAPABILITY_NAMED_IAM功能,因为提供的模板会创建一些AWS::IAM::RoleAWS::IAM::InstanceProfile资源。
    示例输出
    arn:aws:cloudformation:us-east-1:269333783861:stack/cluster-sec/03bd4210-2ed7-11eb-6d7a-13fc0b61e9db
  4. 确认模板组件存在。

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

    StackStatus显示CREATE_COMPLETE后,输出将显示以下参数的值。您必须将这些参数值提供给您运行以创建集群的其他 CloudFormation 模板。

    MasterSecurityGroupId

    主安全组 ID

    WorkerSecurityGroupId

    工作节点安全组 ID

    MasterInstanceProfile

    主 IAM 实例配置文件

    WorkerInstanceProfile

    工作节点 IAM 实例配置文件

安全对象的 CloudFormation 模板

您可以使用以下 CloudFormation 模板来部署 OpenShift Container Platform 集群所需的安全性对象。

安全对象的CloudFormation模板
AWSTemplateFormatVersion: 2010-09-09
Description: Template for OpenShift Cluster Security Elements (Security Groups & IAM)

Parameters:
  InfrastructureName:
    AllowedPattern: ^([a-zA-Z][a-zA-Z0-9\-]{0,26})$
    MaxLength: 27
    MinLength: 1
    ConstraintDescription: Infrastructure name must be alphanumeric, start with a letter, and have a maximum of 27 characters.
    Description: A short, unique cluster ID used to tag cloud resources and identify items owned or used by the cluster.
    Type: String
  VpcCidr:
    AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-4]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-24.
    Default: 10.0.0.0/16
    Description: CIDR block for VPC.
    Type: String
  VpcId:
    Description: The VPC-scoped resources will belong to this VPC.
    Type: AWS::EC2::VPC::Id
  PrivateSubnets:
    Description: The internal subnets.
    Type: List<AWS::EC2::Subnet::Id>

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
    - Label:
        default: "Cluster Information"
      Parameters:
      - InfrastructureName
    - Label:
        default: "Network Configuration"
      Parameters:
      - VpcId
      - VpcCidr
      - PrivateSubnets
    ParameterLabels:
      InfrastructureName:
        default: "Infrastructure Name"
      VpcId:
        default: "VPC ID"
      VpcCidr:
        default: "VPC CIDR"
      PrivateSubnets:
        default: "Private Subnets"

Resources:
  MasterSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Cluster Master Security Group
      SecurityGroupIngress:
      - IpProtocol: icmp
        FromPort: 0
        ToPort: 0
        CidrIp: !Ref VpcCidr
      - IpProtocol: tcp
        FromPort: 22
        ToPort: 22
        CidrIp: !Ref VpcCidr
      - IpProtocol: tcp
        ToPort: 6443
        FromPort: 6443
        CidrIp: !Ref VpcCidr
      - IpProtocol: tcp
        FromPort: 22623
        ToPort: 22623
        CidrIp: !Ref VpcCidr
      VpcId: !Ref VpcId

  WorkerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Cluster Worker Security Group
      SecurityGroupIngress:
      - IpProtocol: icmp
        FromPort: 0
        ToPort: 0
        CidrIp: !Ref VpcCidr
      - IpProtocol: tcp
        FromPort: 22
        ToPort: 22
        CidrIp: !Ref VpcCidr
      VpcId: !Ref VpcId

  MasterIngressEtcd:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt MasterSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
      Description: etcd
      FromPort: 2379
      ToPort: 2380
      IpProtocol: tcp

  MasterIngressVxlan:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt MasterSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
      Description: Vxlan packets
      FromPort: 4789
      ToPort: 4789
      IpProtocol: udp

  MasterIngressWorkerVxlan:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt MasterSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
      Description: Vxlan packets
      FromPort: 4789
      ToPort: 4789
      IpProtocol: udp

  MasterIngressGeneve:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt MasterSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
      Description: Geneve packets
      FromPort: 6081
      ToPort: 6081
      IpProtocol: udp

  MasterIngressWorkerGeneve:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt MasterSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
      Description: Geneve packets
      FromPort: 6081
      ToPort: 6081
      IpProtocol: udp

  MasterIngressIpsecIke:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt MasterSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
      Description: IPsec IKE packets
      FromPort: 500
      ToPort: 500
      IpProtocol: udp

  MasterIngressIpsecNat:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt MasterSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
      Description: IPsec NAT-T packets
      FromPort: 4500
      ToPort: 4500
      IpProtocol: udp

  MasterIngressIpsecEsp:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt MasterSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
      Description: IPsec ESP packets
      IpProtocol: 50

  MasterIngressWorkerIpsecIke:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt MasterSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
      Description: IPsec IKE packets
      FromPort: 500
      ToPort: 500
      IpProtocol: udp

  MasterIngressWorkerIpsecNat:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt MasterSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
      Description: IPsec NAT-T packets
      FromPort: 4500
      ToPort: 4500
      IpProtocol: udp

  MasterIngressWorkerIpsecEsp:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt MasterSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
      Description: IPsec ESP packets
      IpProtocol: 50

  MasterIngressInternal:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt MasterSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
      Description: Internal cluster communication
      FromPort: 9000
      ToPort: 9999
      IpProtocol: tcp

  MasterIngressWorkerInternal:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt MasterSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
      Description: Internal cluster communication
      FromPort: 9000
      ToPort: 9999
      IpProtocol: tcp

  MasterIngressInternalUDP:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt MasterSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
      Description: Internal cluster communication
      FromPort: 9000
      ToPort: 9999
      IpProtocol: udp

  MasterIngressWorkerInternalUDP:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt MasterSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
      Description: Internal cluster communication
      FromPort: 9000
      ToPort: 9999
      IpProtocol: udp

  MasterIngressKube:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt MasterSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
      Description: Kubernetes kubelet, scheduler and controller manager
      FromPort: 10250
      ToPort: 10259
      IpProtocol: tcp

  MasterIngressWorkerKube:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt MasterSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
      Description: Kubernetes kubelet, scheduler and controller manager
      FromPort: 10250
      ToPort: 10259
      IpProtocol: tcp

  MasterIngressIngressServices:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt MasterSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
      Description: Kubernetes ingress services
      FromPort: 30000
      ToPort: 32767
      IpProtocol: tcp

  MasterIngressWorkerIngressServices:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt MasterSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
      Description: Kubernetes ingress services
      FromPort: 30000
      ToPort: 32767
      IpProtocol: tcp

  MasterIngressIngressServicesUDP:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt MasterSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
      Description: Kubernetes ingress services
      FromPort: 30000
      ToPort: 32767
      IpProtocol: udp

  MasterIngressWorkerIngressServicesUDP:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt MasterSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
      Description: Kubernetes ingress services
      FromPort: 30000
      ToPort: 32767
      IpProtocol: udp

  WorkerIngressVxlan:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt WorkerSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
      Description: Vxlan packets
      FromPort: 4789
      ToPort: 4789
      IpProtocol: udp

  WorkerIngressMasterVxlan:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt WorkerSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
      Description: Vxlan packets
      FromPort: 4789
      ToPort: 4789
      IpProtocol: udp

  WorkerIngressGeneve:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt WorkerSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
      Description: Geneve packets
      FromPort: 6081
      ToPort: 6081
      IpProtocol: udp

  WorkerIngressMasterGeneve:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt WorkerSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
      Description: Geneve packets
      FromPort: 6081
      ToPort: 6081
      IpProtocol: udp

  WorkerIngressIpsecIke:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt WorkerSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
      Description: IPsec IKE packets
      FromPort: 500
      ToPort: 500
      IpProtocol: udp

  WorkerIngressIpsecNat:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt WorkerSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
      Description: IPsec NAT-T packets
      FromPort: 4500
      ToPort: 4500
      IpProtocol: udp

  WorkerIngressIpsecEsp:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt WorkerSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
      Description: IPsec ESP packets
      IpProtocol: 50

  WorkerIngressMasterIpsecIke:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt WorkerSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
      Description: IPsec IKE packets
      FromPort: 500
      ToPort: 500
      IpProtocol: udp

  WorkerIngressMasterIpsecNat:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt WorkerSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
      Description: IPsec NAT-T packets
      FromPort: 4500
      ToPort: 4500
      IpProtocol: udp

  WorkerIngressMasterIpsecEsp:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt WorkerSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
      Description: IPsec ESP packets
      IpProtocol: 50

  WorkerIngressInternal:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt WorkerSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
      Description: Internal cluster communication
      FromPort: 9000
      ToPort: 9999
      IpProtocol: tcp

  WorkerIngressMasterInternal:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt WorkerSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
      Description: Internal cluster communication
      FromPort: 9000
      ToPort: 9999
      IpProtocol: tcp

  WorkerIngressInternalUDP:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt WorkerSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
      Description: Internal cluster communication
      FromPort: 9000
      ToPort: 9999
      IpProtocol: udp

  WorkerIngressMasterInternalUDP:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt WorkerSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
      Description: Internal cluster communication
      FromPort: 9000
      ToPort: 9999
      IpProtocol: udp

  WorkerIngressKube:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt WorkerSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
      Description: Kubernetes secure kubelet port
      FromPort: 10250
      ToPort: 10250
      IpProtocol: tcp

  WorkerIngressWorkerKube:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt WorkerSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
      Description: Internal Kubernetes communication
      FromPort: 10250
      ToPort: 10250
      IpProtocol: tcp

  WorkerIngressIngressServices:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt WorkerSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
      Description: Kubernetes ingress services
      FromPort: 30000
      ToPort: 32767
      IpProtocol: tcp

  WorkerIngressMasterIngressServices:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt WorkerSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
      Description: Kubernetes ingress services
      FromPort: 30000
      ToPort: 32767
      IpProtocol: tcp

  WorkerIngressIngressServicesUDP:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt WorkerSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt WorkerSecurityGroup.GroupId
      Description: Kubernetes ingress services
      FromPort: 30000
      ToPort: 32767
      IpProtocol: udp

  WorkerIngressMasterIngressServicesUDP:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt WorkerSecurityGroup.GroupId
      SourceSecurityGroupId: !GetAtt MasterSecurityGroup.GroupId
      Description: Kubernetes ingress services
      FromPort: 30000
      ToPort: 32767
      IpProtocol: udp

  MasterIamRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
        - Effect: "Allow"
          Principal:
            Service:
            - "ec2.amazonaws.com"
          Action:
          - "sts:AssumeRole"
      Policies:
      - PolicyName: !Join ["-", [!Ref InfrastructureName, "master", "policy"]]
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
          - Effect: "Allow"
            Action:
            - "ec2:AttachVolume"
            - "ec2:AuthorizeSecurityGroupIngress"
            - "ec2:CreateSecurityGroup"
            - "ec2:CreateTags"
            - "ec2:CreateVolume"
            - "ec2:DeleteSecurityGroup"
            - "ec2:DeleteVolume"
            - "ec2:Describe*"
            - "ec2:DetachVolume"
            - "ec2:ModifyInstanceAttribute"
            - "ec2:ModifyVolume"
            - "ec2:RevokeSecurityGroupIngress"
            - "elasticloadbalancing:AddTags"
            - "elasticloadbalancing:AttachLoadBalancerToSubnets"
            - "elasticloadbalancing:ApplySecurityGroupsToLoadBalancer"
            - "elasticloadbalancing:CreateListener"
            - "elasticloadbalancing:CreateLoadBalancer"
            - "elasticloadbalancing:CreateLoadBalancerPolicy"
            - "elasticloadbalancing:CreateLoadBalancerListeners"
            - "elasticloadbalancing:CreateTargetGroup"
            - "elasticloadbalancing:ConfigureHealthCheck"
            - "elasticloadbalancing:DeleteListener"
            - "elasticloadbalancing:DeleteLoadBalancer"
            - "elasticloadbalancing:DeleteLoadBalancerListeners"
            - "elasticloadbalancing:DeleteTargetGroup"
            - "elasticloadbalancing:DeregisterInstancesFromLoadBalancer"
            - "elasticloadbalancing:DeregisterTargets"
            - "elasticloadbalancing:Describe*"
            - "elasticloadbalancing:DetachLoadBalancerFromSubnets"
            - "elasticloadbalancing:ModifyListener"
            - "elasticloadbalancing:ModifyLoadBalancerAttributes"
            - "elasticloadbalancing:ModifyTargetGroup"
            - "elasticloadbalancing:ModifyTargetGroupAttributes"
            - "elasticloadbalancing:RegisterInstancesWithLoadBalancer"
            - "elasticloadbalancing:RegisterTargets"
            - "elasticloadbalancing:SetLoadBalancerPoliciesForBackendServer"
            - "elasticloadbalancing:SetLoadBalancerPoliciesOfListener"
            - "kms:DescribeKey"
            Resource: "*"

  MasterInstanceProfile:
    Type: "AWS::IAM::InstanceProfile"
    Properties:
      Roles:
      - Ref: "MasterIamRole"

  WorkerIamRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
        - Effect: "Allow"
          Principal:
            Service:
            - "ec2.amazonaws.com"
          Action:
          - "sts:AssumeRole"
      Policies:
      - PolicyName: !Join ["-", [!Ref InfrastructureName, "worker", "policy"]]
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
          - Effect: "Allow"
            Action:
            - "ec2:DescribeInstances"
            - "ec2:DescribeRegions"
            Resource: "*"

  WorkerInstanceProfile:
    Type: "AWS::IAM::InstanceProfile"
    Properties:
      Roles:
      - Ref: "WorkerIamRole"

Outputs:
  MasterSecurityGroupId:
    Description: Master Security Group ID
    Value: !GetAtt MasterSecurityGroup.GroupId

  WorkerSecurityGroupId:
    Description: Worker Security Group ID
    Value: !GetAtt WorkerSecurityGroup.GroupId

  MasterInstanceProfile:
    Description: Master IAM Instance Profile
    Value: !Ref MasterInstanceProfile

  WorkerInstanceProfile:
    Description: Worker IAM Instance Profile
    Value: !Ref WorkerInstanceProfile
其他资源

使用流元数据访问 RHCOS AMI

在 OpenShift Container Platform 中,流元数据以 JSON 格式提供关于 RHCOS 的标准化元数据,并将元数据注入集群。流元数据是一种稳定的格式,支持多种架构,旨在实现自文档化以维护自动化。

您可以使用openshift-installcoreos print-stream-json子命令来访问流元数据格式中引导映像的信息。此命令提供了一种以可编写脚本的、机器可读的格式打印流元数据的方法。

对于用户预配的安装,openshift-install二进制文件包含对经过测试可与 OpenShift Container Platform(例如 AWS AMI)一起使用的 RHCOS 引导映像版本的引用。

步骤

要解析流元数据,请使用以下方法之一:

  • 在 Go 程序中,使用位于https://github.com/coreos/stream-metadata-go的官方stream-metadata-go库。您也可以在库中查看示例代码。

  • 在其他编程语言(如 Python 或 Ruby)中,使用您首选编程语言的 JSON 库。

  • 从处理 JSON 数据的命令行实用程序(如jq

    • 打印 AWS 区域(如us-west-1)的当前x86_64aarch64 AMI

      对于 x86_64
      $ openshift-install coreos print-stream-json | jq -r '.architectures.x86_64.images.aws.regions["us-west-1"].image'
      示例输出
      ami-0d3e625f84626bbda
      对于 aarch64
      $ openshift-install coreos print-stream-json | jq -r '.architectures.aarch64.images.aws.regions["us-west-1"].image'
      示例输出
      ami-0af1d3b7fa5be2131

      此命令的输出是您指定的架构和us-west-1区域的 AWS AMI ID。AMI 必须属于与集群相同的区域。

AWS 基础设施的 RHCOS AMI

Red Hat 提供 Red Hat Enterprise Linux CoreOS (RHCOS) AMI,这些 AMI 对您可以为 OpenShift Container Platform 节点手动指定的各种 AWS 区域和实例架构有效。

通过导入您自己的 AMI,您还可以安装到没有发布 RHCOS AMI 的区域。

表 1. x86_64 RHCOS AMI
AWS 区域 AWS AMI

af-south-1

ami-019b3e090bb062842

ap-east-1

ami-0cb76d97f77cda0a1

ap-northeast-1

ami-0d7d4b329e5403cfb

ap-northeast-2

ami-02d3789d532feb517

ap-northeast-3

ami-08b82c4899109b707

ap-south-1

ami-0c184f8b5ad8af69d

ap-south-2

ami-0b0525037b9a20e9a

ap-southeast-1

ami-0dbee0006375139a7

ap-southeast-2

ami-043072b1af91be72f

ap-southeast-3

ami-09d8bbf16b228139e

ap-southeast-4

ami-01c6b29e9c57b434b

ca-central-1

ami-06fda1fa0b65b864b

ca-west-1

ami-0141eea486b5e2c43

eu-central-1

ami-0f407de515454fdd0

eu-central-2

ami-062cfad83bc7b71b8

eu-north-1

ami-0af77aba6aebb5086

eu-south-1

ami-04d9da83bc9f854fc

eu-south-2

ami-035d487abf54f0af7

eu-west-1

ami-043dd3b788dbaeb1c

eu-west-2

ami-0c7d0f90a4401b723

eu-west-3

ami-039baa878e1def55f

il-central-1

ami-07d305bf03b2148de

me-central-1

ami-0fc457e8897ccb41a

me-south-1

ami-0af99a751cf682b90

sa-east-1

ami-04a7300f64ee01d68

us-east-1

ami-01b53f2824bf6d426

us-east-2

ami-0565349610e27bd41

us-gov-east-1

ami-0020504fa043fe41d

us-gov-west-1

ami-036798bce4722d3c2

us-west-1

ami-0147c634ad692da52

us-west-2

ami-0c65d71e89d43aa90

表 2. aarch64 RHCOS AMI
AWS 区域 AWS AMI

af-south-1

ami-0e585ef53405bebf5

ap-east-1

ami-05f32f1715bb51bda

ap-northeast-1

ami-05ecb62bab0c50e52

ap-northeast-2

ami-0a3ffb2c07c9e4a8d

ap-northeast-3

ami-0ae6746ea17d1042c

ap-south-1

ami-00deb5b08c86060b8

ap-south-2

ami-047a47d5049781e03

ap-southeast-1

ami-09cb598f0d36fde4c

ap-southeast-2

ami-01fe8a7538500f24c

ap-southeast-3

ami-051b3f67dd787d5e9

ap-southeast-4

ami-04d2e14a9eef40143

ca-central-1

ami-0f66973ff12d09356

ca-west-1

ami-0c9f3e2f0470d6d0b

eu-central-1

ami-0a79af8849b425a8a

eu-central-2

ami-0f9f66951c9709471

eu-north-1

ami-0670362aa7eb9032d

eu-south-1

ami-031b24b970eae750b

eu-south-2

ami-0734d2ed55c00a46c

eu-west-1

ami-0a9af75c2649471c0

eu-west-2

ami-0b84155a3672ac44e

eu-west-3

ami-02b51442c612818d4

il-central-1

ami-0d2c47a297d483ce4

me-central-1

ami-0ef3005246bd83b07

me-south-1

ami-0321ca1ee89015eda

sa-east-1

ami-0e63f1103dc71d8ae

us-east-1

ami-0404da96615c73bec

us-east-2

ami-04c3bd7be936f728f

us-gov-east-1

ami-0d30bc0b99b153247

us-gov-west-1

ami-0ee006f84d6aa5045

us-west-1

ami-061bfd61d5cfd7aa6

us-west-2

ami-05ffb8f6f18b8e3f8

没有发布 RHCOS AMI 的 AWS 区域

您可以将 OpenShift Container Platform 集群部署到 Amazon Web Services (AWS) 区域,这些区域不原生支持 Red Hat Enterprise Linux CoreOS (RHCOS) Amazon 机器镜像 (AMI) 或 AWS 软件开发工具包 (SDK)。如果 AWS 区域没有发布的 AMI,您可以在安装集群之前上传自定义 AMI。

如果您部署到 AWS SDK 不支持的区域,并且没有指定自定义 AMI,安装程序会自动将us-east-1 AMI 复制到用户帐户。然后,安装程序使用默认或用户指定的密钥管理服务 (KMS) 密钥创建具有加密 EBS 卷的控制平面机器。这允许 AMI 遵循与已发布的 RHCOS AMI 相同的过程工作流程。

在集群创建过程中,终端无法选择没有原生支持 RHCOS AMI 的区域,因为它没有发布。但是,您可以通过在install-config.yaml文件中配置自定义 AMI 来安装到此区域。

在 AWS 中上传自定义 RHCOS AMI

如果您要部署到自定义 Amazon Web Services (AWS) 区域,则必须上传属于该区域的自定义 Red Hat Enterprise Linux CoreOS (RHCOS) Amazon 机器镜像 (AMI)。

先决条件
  • 您已配置 AWS 账户。

  • 您已使用所需的 IAM 服务角色 创建了一个 Amazon S3 存储桶。

  • 您已将 RHCOS VMDK 文件上传到 Amazon S3。RHCOS VMDK 文件必须是最高版本,该版本小于或等于您正在安装的 OpenShift Container Platform 版本。

  • 您已下载 AWS CLI 并将其安装到您的计算机上。请参阅 使用捆绑安装程序安装 AWS CLI

步骤
  1. 将您的 AWS 配置文件导出为环境变量

    $ export AWS_PROFILE=<aws_profile> (1)
  2. 将要与您的自定义 AMI 关联的区域导出为环境变量

    $ export AWS_DEFAULT_REGION=<aws_region> (1)
  3. 将您上传到 Amazon S3 的 RHCOS 版本导出为环境变量

    $ export RHCOS_VERSION=<version> (1)
    1 RHCOS VMDK 版本,例如4.17.0
  4. 将 Amazon S3 存储桶名称导出为环境变量

    $ export VMIMPORT_BUCKET_NAME=<s3_bucket_name>
  5. 创建containers.json文件并定义您的 RHCOS VMDK 文件

    $ cat <<EOF > containers.json
    {
       "Description": "rhcos-${RHCOS_VERSION}-x86_64-aws.x86_64",
       "Format": "vmdk",
       "UserBucket": {
          "S3Bucket": "${VMIMPORT_BUCKET_NAME}",
          "S3Key": "rhcos-${RHCOS_VERSION}-x86_64-aws.x86_64.vmdk"
       }
    }
    EOF
  6. 将 RHCOS 磁盘导入为 Amazon EBS 快照

    $ aws ec2 import-snapshot --region ${AWS_DEFAULT_REGION} \
         --description "<description>" \ (1)
         --disk-container "file://<file_path>/containers.json" (2)
    
    1 正在导入的 RHCOS 磁盘的描述,例如rhcos-${RHCOS_VERSION}-x86_64-aws.x86_64
    2 描述 RHCOS 磁盘的 JSON 文件的文件路径。JSON 文件应包含您的 Amazon S3 存储桶名称和密钥。
  7. 检查镜像导入状态

    $ watch -n 5 aws ec2 describe-import-snapshot-tasks --region ${AWS_DEFAULT_REGION}
    示例输出
    {
        "ImportSnapshotTasks": [
            {
                "Description": "rhcos-4.7.0-x86_64-aws.x86_64",
                "ImportTaskId": "import-snap-fh6i8uil",
                "SnapshotTaskDetail": {
                    "Description": "rhcos-4.7.0-x86_64-aws.x86_64",
                    "DiskImageSize": 819056640.0,
                    "Format": "VMDK",
                    "SnapshotId": "snap-06331325870076318",
                    "Status": "completed",
                    "UserBucket": {
                        "S3Bucket": "external-images",
                        "S3Key": "rhcos-4.7.0-x86_64-aws.x86_64.vmdk"
                    }
                }
            }
        ]
    }

    复制SnapshotId以注册镜像。

  8. 从 RHCOS 快照创建自定义 RHCOS AMI

    $ aws ec2 register-image \
       --region ${AWS_DEFAULT_REGION} \
       --architecture x86_64 \ (1)
       --description "rhcos-${RHCOS_VERSION}-x86_64-aws.x86_64" \ (2)
       --ena-support \
       --name "rhcos-${RHCOS_VERSION}-x86_64-aws.x86_64" \ (3)
       --virtualization-type hvm \
       --root-device-name '/dev/xvda' \
       --block-device-mappings 'DeviceName=/dev/xvda,Ebs={DeleteOnTermination=true,SnapshotId=<snapshot_ID>}' (4)
    
    1 RHCOS VMDK 架构类型,例如x86_64aarch64s390xppc64le
    2 导入快照的描述
    3 RHCOS AMI 的名称。
    4 导入快照的SnapshotID

要了解有关这些 API 的更多信息,请参阅 AWS 文档,了解 导入快照创建基于 EBS 的 AMI

在 AWS 中创建引导节点

您必须在 Amazon Web Services (AWS) 中创建引导节点,以便在 OpenShift Container Platform 集群初始化期间使用。您可以通过以下方式执行此操作:

  • 提供一个位置,用于将bootstrap.ign Ignition 配置文件提供给您的集群。此文件位于您的安装目录中。提供的 CloudFormation 模板假定您的集群的 Ignition 配置文件是从 S3 存储桶提供的。如果您选择从其他位置提供文件,则必须修改模板。

  • 使用提供的 CloudFormation 模板和自定义参数文件创建 AWS 资源堆栈。堆栈代表 OpenShift Container Platform 安装所需的引导节点。

如果您不使用提供的 CloudFormation 模板来创建引导节点,则必须查看提供的信息并手动创建基础架构。如果您的集群未正确初始化,您可能必须联系 Red Hat 支持人员提供您的安装日志。

先决条件
  • 您已配置 AWS 账户。

  • 您已通过运行aws configure将您的 AWS 密钥和区域添加到您的本地 AWS 配置文件中。

  • 您已为您的集群生成 Ignition 配置文件。

  • 您已在 AWS 中创建和配置了 VPC 和关联的子网。

  • 您已在 AWS 中创建并配置了 DNS、负载均衡器和侦听器。

  • 您已在 AWS 中创建了集群所需的安全性组和角色。

步骤
  1. 运行以下命令创建存储桶

    $ aws s3 mb s3://<cluster-name>-infra (1)
    1 <cluster-name>-infra是存储桶名称。创建install-config.yaml文件时,请将<cluster-name>替换为您为集群指定的名称。

    如果您要执行以下操作,则必须使用 S3 存储桶的预签名 URL,而不是s3://模式:

    • 部署到具有与 AWS SDK 不同的端点的区域。

    • 部署代理。

    • 提供您自己的自定义端点。

  2. 运行以下命令将bootstrap.ign Ignition 配置文件上传到存储桶

    $ aws s3 cp <installation_directory>/bootstrap.ign s3://<cluster-name>-infra/bootstrap.ign (1)
    1 对于<installation_directory>,请指定您存储安装文件的目录的路径。
  3. 运行以下命令验证已上传的文件

    $ aws s3 ls s3://<cluster-name>-infra/
    示例输出
    2019-04-03 16:15:16     314878 bootstrap.ign

    引导程序 Ignition 配置文件包含密钥,例如 X.509 密钥。以下步骤提供了 S3 存储桶的基本安全性。为了提供额外的安全性,您可以启用 S3 存储桶策略,只允许某些用户(例如 OpenShift IAM 用户)访问存储桶中包含的对象。您可以完全避免使用 S3,并从引导机器可以访问的任何地址提供您的引导程序 Ignition 配置文件。

  4. 创建一个 JSON 文件,其中包含模板所需的参数值。

    [
      {
        "ParameterKey": "InfrastructureName", (1)
        "ParameterValue": "mycluster-<random_string>" (2)
      },
      {
        "ParameterKey": "RhcosAmi", (3)
        "ParameterValue": "ami-<random_string>" (4)
      },
      {
        "ParameterKey": "AllowedBootstrapSshCidr", (5)
        "ParameterValue": "0.0.0.0/0" (6)
      },
      {
        "ParameterKey": "PublicSubnet", (7)
        "ParameterValue": "subnet-<random_string>" (8)
      },
      {
        "ParameterKey": "MasterSecurityGroupId", (9)
        "ParameterValue": "sg-<random_string>" (10)
      },
      {
        "ParameterKey": "VpcId", (11)
        "ParameterValue": "vpc-<random_string>" (12)
      },
      {
        "ParameterKey": "BootstrapIgnitionLocation", (13)
        "ParameterValue": "s3://<bucket_name>/bootstrap.ign" (14)
      },
      {
        "ParameterKey": "AutoRegisterELB", (15)
        "ParameterValue": "yes" (16)
      },
      {
        "ParameterKey": "RegisterNlbIpTargetsLambdaArn", (17)
        "ParameterValue": "arn:aws:lambda:<aws_region>:<account_number>:function:<dns_stack_name>-RegisterNlbIpTargets-<random_string>" (18)
      },
      {
        "ParameterKey": "ExternalApiTargetGroupArn", (19)
        "ParameterValue": "arn:aws:elasticloadbalancing:<aws_region>:<account_number>:targetgroup/<dns_stack_name>-Exter-<random_string>" (20)
      },
      {
        "ParameterKey": "InternalApiTargetGroupArn", (21)
        "ParameterValue": "arn:aws:elasticloadbalancing:<aws_region>:<account_number>:targetgroup/<dns_stack_name>-Inter-<random_string>" (22)
      },
      {
        "ParameterKey": "InternalServiceTargetGroupArn", (23)
        "ParameterValue": "arn:aws:elasticloadbalancing:<aws_region>:<account_number>:targetgroup/<dns_stack_name>-Inter-<random_string>" (24)
      }
    ]
    
    1 集群的 Ignition 配置文件中编码的集群基础设施名称。
    2 指定您从 Ignition 配置文件元数据中提取的基础设施名称,其格式为<cluster-name>-<random-string>
    3 根据您选择的架构,用于引导节点的当前 Red Hat Enterprise Linux CoreOS (RHCOS) AMI。
    4 指定有效的 AWS::EC2::Image::Id 值。
    5 允许 SSH 访问引导节点的 CIDR 块。
    6 请使用x.x.x.x/16-24格式指定 CIDR 块。
    7 与您的 VPC 关联的公共子网,用于将引导节点启动到其中。
    8 指定 VPC 的 CloudFormation 模板输出中的PublicSubnetIds值。
    9 主安全组 ID(用于注册临时规则)
    10 从 CloudFormation 模板的安全组和角色输出中指定 MasterSecurityGroupId 值。
    11 创建的 VPC 资源将属于。
    12 指定 VPC 的 CloudFormation 模板输出中的VpcId值。
    13 获取引导程序 Ignition 配置文件的地址。
    14 s3://<bucket_name>/bootstrap.ign 的形式指定 S3 存储桶和文件名。
    15 是否注册网络负载均衡器 (NLB)。
    16 指定 yesno。如果指定 yes,则必须提供 Lambda Amazon 资源名称 (ARN) 值。
    17 NLB IP 目标注册 lambda 组的 ARN。
    18 从 DNS 和负载均衡的 CloudFormation 模板输出中指定 RegisterNlbIpTargetsLambda 值。如果将集群部署到 AWS GovCloud 区域,请使用 arn:aws-us-gov
    19 外部 API 负载均衡器目标组的 ARN。
    20 从 DNS 和负载均衡的 CloudFormation 模板输出中指定 ExternalApiTargetGroupArn 值。如果将集群部署到 AWS GovCloud 区域,请使用 arn:aws-us-gov
    21 内部 API 负载均衡器目标组的 ARN。
    22 从 DNS 和负载均衡的 CloudFormation 模板输出中指定 InternalApiTargetGroupArn 值。如果将集群部署到 AWS GovCloud 区域,请使用 arn:aws-us-gov
    23 内部服务负载均衡器目标组的 ARN。
    24 从 DNS 和负载均衡的 CloudFormation 模板输出中指定 InternalServiceTargetGroupArn 值。如果将集群部署到 AWS GovCloud 区域,请使用 arn:aws-us-gov
  5. 从本主题的“引导机器的 CloudFormation 模板”部分复制模板,并将其另存为计算机上的 YAML 文件。此模板描述了集群所需的引导机器。

  6. 可选:如果您使用代理部署集群,则必须更新模板中的 ignition 以添加 ignition.config.proxy 字段。此外,如果您已将 Amazon EC2、弹性负载均衡和 S3 VPC 端点添加到您的 VPC,则必须将这些端点添加到 noProxy 字段。

  7. 启动 CloudFormation 模板以创建表示引导节点的 AWS 资源堆栈。

    您必须在一行中输入命令。

    $ aws cloudformation create-stack --stack-name <name> (1)
         --template-body file://<template>.yaml (2)
         --parameters file://<parameters>.json (3)
         --capabilities CAPABILITY_NAMED_IAM (4)
    
    1 <name> 是 CloudFormation 堆栈的名称,例如 cluster-bootstrap。如果您删除集群,则需要此堆栈的名称。
    2 <template>是您保存的 CloudFormation 模板 YAML 文件的相对路径和名称。
    3 <parameters>是 CloudFormation 参数 JSON 文件的相对路径和名称。
    4 您必须显式声明CAPABILITY_NAMED_IAM功能,因为提供的模板会创建一些AWS::IAM::RoleAWS::IAM::InstanceProfile资源。
    示例输出
    arn:aws:cloudformation:us-east-1:269333783861:stack/cluster-bootstrap/12944486-2add-11eb-9dee-12dace8e3a83
  8. 确认模板组件存在。

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

    StackStatus显示CREATE_COMPLETE后,输出将显示以下参数的值。您必须将这些参数值提供给您运行以创建集群的其他 CloudFormation 模板。

    BootstrapInstanceId

    引导实例 ID。

    BootstrapPublicIp

    引导节点的公共 IP 地址。

    BootstrapPrivateIp

    引导节点的私有 IP 地址。

引导机器的 CloudFormation 模板

您可以使用以下 CloudFormation 模板部署 OpenShift Container Platform 集群所需的引导机器。

引导机的CloudFormation模板
AWSTemplateFormatVersion: 2010-09-09
Description: Template for OpenShift Cluster Bootstrap (EC2 Instance, Security Groups and IAM)

Parameters:
  InfrastructureName:
    AllowedPattern: ^([a-zA-Z][a-zA-Z0-9\-]{0,26})$
    MaxLength: 27
    MinLength: 1
    ConstraintDescription: Infrastructure name must be alphanumeric, start with a letter, and have a maximum of 27 characters.
    Description: A short, unique cluster ID used to tag cloud resources and identify items owned or used by the cluster.
    Type: String
  RhcosAmi:
    Description: Current Red Hat Enterprise Linux CoreOS AMI to use for bootstrap.
    Type: AWS::EC2::Image::Id
  AllowedBootstrapSshCidr:
    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]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/0-32.
    Default: 0.0.0.0/0
    Description: CIDR block to allow SSH access to the bootstrap node.
    Type: String
  PublicSubnet:
    Description: The public subnet to launch the bootstrap node into.
    Type: AWS::EC2::Subnet::Id
  MasterSecurityGroupId:
    Description: The master security group ID for registering temporary rules.
    Type: AWS::EC2::SecurityGroup::Id
  VpcId:
    Description: The VPC-scoped resources will belong to this VPC.
    Type: AWS::EC2::VPC::Id
  BootstrapIgnitionLocation:
    Default: s3://my-s3-bucket/bootstrap.ign
    Description: Ignition config file location.
    Type: String
  AutoRegisterELB:
    Default: "yes"
    AllowedValues:
    - "yes"
    - "no"
    Description: Do you want to invoke NLB registration, which requires a Lambda ARN parameter?
    Type: String
  RegisterNlbIpTargetsLambdaArn:
    Description: ARN for NLB IP target registration lambda.
    Type: String
  ExternalApiTargetGroupArn:
    Description: ARN for external API load balancer target group.
    Type: String
  InternalApiTargetGroupArn:
    Description: ARN for internal API load balancer target group.
    Type: String
  InternalServiceTargetGroupArn:
    Description: ARN for internal service load balancer target group.
    Type: String
  BootstrapInstanceType:
    Description: Instance type for the bootstrap EC2 instance
    Default: "i3.large"
    Type: String

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
    - Label:
        default: "Cluster Information"
      Parameters:
      - InfrastructureName
    - Label:
        default: "Host Information"
      Parameters:
      - RhcosAmi
      - BootstrapIgnitionLocation
      - MasterSecurityGroupId
    - Label:
        default: "Network Configuration"
      Parameters:
      - VpcId
      - AllowedBootstrapSshCidr
      - PublicSubnet
    - Label:
        default: "Load Balancer Automation"
      Parameters:
      - AutoRegisterELB
      - RegisterNlbIpTargetsLambdaArn
      - ExternalApiTargetGroupArn
      - InternalApiTargetGroupArn
      - InternalServiceTargetGroupArn
    ParameterLabels:
      InfrastructureName:
        default: "Infrastructure Name"
      VpcId:
        default: "VPC ID"
      AllowedBootstrapSshCidr:
        default: "Allowed SSH Source"
      PublicSubnet:
        default: "Public Subnet"
      RhcosAmi:
        default: "Red Hat Enterprise Linux CoreOS AMI ID"
      BootstrapIgnitionLocation:
        default: "Bootstrap Ignition Source"
      MasterSecurityGroupId:
        default: "Master Security Group ID"
      AutoRegisterELB:
        default: "Use Provided ELB Automation"

Conditions:
  DoRegistration: !Equals ["yes", !Ref AutoRegisterELB]

Resources:
  BootstrapIamRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
        - Effect: "Allow"
          Principal:
            Service:
            - "ec2.amazonaws.com"
          Action:
          - "sts:AssumeRole"
      Path: "/"
      Policies:
      - PolicyName: !Join ["-", [!Ref InfrastructureName, "bootstrap", "policy"]]
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
          - Effect: "Allow"
            Action: "ec2:Describe*"
            Resource: "*"
          - Effect: "Allow"
            Action: "ec2:AttachVolume"
            Resource: "*"
          - Effect: "Allow"
            Action: "ec2:DetachVolume"
            Resource: "*"
          - Effect: "Allow"
            Action: "s3:GetObject"
            Resource: "*"

  BootstrapInstanceProfile:
    Type: "AWS::IAM::InstanceProfile"
    Properties:
      Path: "/"
      Roles:
      - Ref: "BootstrapIamRole"

  BootstrapSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Cluster Bootstrap Security Group
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 22
        ToPort: 22
        CidrIp: !Ref AllowedBootstrapSshCidr
      - IpProtocol: tcp
        ToPort: 19531
        FromPort: 19531
        CidrIp: 0.0.0.0/0
      VpcId: !Ref VpcId

  BootstrapInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref RhcosAmi
      IamInstanceProfile: !Ref BootstrapInstanceProfile
      InstanceType: !Ref BootstrapInstanceType
      NetworkInterfaces:
      - AssociatePublicIpAddress: "true"
        DeviceIndex: "0"
        GroupSet:
        - !Ref "BootstrapSecurityGroup"
        - !Ref "MasterSecurityGroupId"
        SubnetId: !Ref "PublicSubnet"
      UserData:
        Fn::Base64: !Sub
        - '{"ignition":{"config":{"replace":{"source":"${S3Loc}"}},"version":"3.1.0"}}'
        - {
          S3Loc: !Ref BootstrapIgnitionLocation
        }

  RegisterBootstrapApiTarget:
    Condition: DoRegistration
    Type: Custom::NLBRegister
    Properties:
      ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
      TargetArn: !Ref ExternalApiTargetGroupArn
      TargetIp: !GetAtt BootstrapInstance.PrivateIp

  RegisterBootstrapInternalApiTarget:
    Condition: DoRegistration
    Type: Custom::NLBRegister
    Properties:
      ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
      TargetArn: !Ref InternalApiTargetGroupArn
      TargetIp: !GetAtt BootstrapInstance.PrivateIp

  RegisterBootstrapInternalServiceTarget:
    Condition: DoRegistration
    Type: Custom::NLBRegister
    Properties:
      ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
      TargetArn: !Ref InternalServiceTargetGroupArn
      TargetIp: !GetAtt BootstrapInstance.PrivateIp

Outputs:
  BootstrapInstanceId:
    Description: Bootstrap Instance ID.
    Value: !Ref BootstrapInstance

  BootstrapPublicIp:
    Description: The bootstrap node public IP address.
    Value: !GetAtt BootstrapInstance.PublicIp

  BootstrapPrivateIp:
    Description: The bootstrap node private IP address.
    Value: !GetAtt BootstrapInstance.PrivateIp
其他资源

在 AWS 中创建控制平面机器

您必须在 Amazon Web Services (AWS) 中创建集群将使用的控制平面机器。

您可以使用提供的 CloudFormation 模板和自定义参数文件来创建表示控制平面节点的 AWS 资源堆栈。

CloudFormation 模板创建表示三个控制平面节点的堆栈。

如果您不使用提供的 CloudFormation 模板来创建控制平面节点,则必须查看提供的信息并手动创建基础设施。如果您的集群未正确初始化,您可能需要联系 Red Hat 支持并提供您的安装日志。

先决条件
  • 您已配置 AWS 账户。

  • 您已通过运行aws configure将您的 AWS 密钥和区域添加到您的本地 AWS 配置文件中。

  • 您已为您的集群生成 Ignition 配置文件。

  • 您已在 AWS 中创建和配置了 VPC 和关联的子网。

  • 您已在 AWS 中创建并配置了 DNS、负载均衡器和侦听器。

  • 您已在 AWS 中创建了集群所需的安全性组和角色。

  • 您已创建引导机器。

步骤
  1. 创建一个 JSON 文件,其中包含模板所需的参数值。

    [
      {
        "ParameterKey": "InfrastructureName", (1)
        "ParameterValue": "mycluster-<random_string>" (2)
      },
      {
        "ParameterKey": "RhcosAmi", (3)
        "ParameterValue": "ami-<random_string>" (4)
      },
      {
        "ParameterKey": "AutoRegisterDNS", (5)
        "ParameterValue": "yes" (6)
      },
      {
        "ParameterKey": "PrivateHostedZoneId", (7)
        "ParameterValue": "<random_string>" (8)
      },
      {
        "ParameterKey": "PrivateHostedZoneName", (9)
        "ParameterValue": "mycluster.example.com" (10)
      },
      {
        "ParameterKey": "Master0Subnet", (11)
        "ParameterValue": "subnet-<random_string>" (12)
      },
      {
        "ParameterKey": "Master1Subnet", (11)
        "ParameterValue": "subnet-<random_string>" (12)
      },
      {
        "ParameterKey": "Master2Subnet", (11)
        "ParameterValue": "subnet-<random_string>" (12)
      },
      {
        "ParameterKey": "MasterSecurityGroupId", (13)
        "ParameterValue": "sg-<random_string>" (14)
      },
      {
        "ParameterKey": "IgnitionLocation", (15)
        "ParameterValue": "https://api-int.<cluster_name>.<domain_name>:22623/config/master" (16)
      },
      {
        "ParameterKey": "CertificateAuthorities", (17)
        "ParameterValue": "data:text/plain;charset=utf-8;base64,ABC...xYz==" (18)
      },
      {
        "ParameterKey": "MasterInstanceProfileName", (19)
        "ParameterValue": "<roles_stack>-MasterInstanceProfile-<random_string>" (20)
      },
      {
        "ParameterKey": "MasterInstanceType", (21)
        "ParameterValue": "" (22)
      },
      {
        "ParameterKey": "AutoRegisterELB", (23)
        "ParameterValue": "yes" (24)
      },
      {
        "ParameterKey": "RegisterNlbIpTargetsLambdaArn", (25)
        "ParameterValue": "arn:aws:lambda:<aws_region>:<account_number>:function:<dns_stack_name>-RegisterNlbIpTargets-<random_string>" (26)
      },
      {
        "ParameterKey": "ExternalApiTargetGroupArn", (27)
        "ParameterValue": "arn:aws:elasticloadbalancing:<aws_region>:<account_number>:targetgroup/<dns_stack_name>-Exter-<random_string>" (28)
      },
      {
        "ParameterKey": "InternalApiTargetGroupArn", (29)
        "ParameterValue": "arn:aws:elasticloadbalancing:<aws_region>:<account_number>:targetgroup/<dns_stack_name>-Inter-<random_string>" (30)
      },
      {
        "ParameterKey": "InternalServiceTargetGroupArn", (31)
        "ParameterValue": "arn:aws:elasticloadbalancing:<aws_region>:<account_number>:targetgroup/<dns_stack_name>-Inter-<random_string>" (32)
      }
    ]
    1 集群的 Ignition 配置文件中编码的集群基础设施名称。
    2 指定您从 Ignition 配置文件元数据中提取的基础设施名称,其格式为<cluster-name>-<random-string>
    3 根据您选择的架构,用于控制平面机器的当前 Red Hat Enterprise Linux CoreOS (RHCOS) AMI。
    4 指定 AWS::EC2::Image::Id 值。
    5 是否执行 DNS etcd 注册。
    6 指定 yesno。如果指定 yes,则必须提供托管区域信息。
    7 用于注册 etcd 目标的 Route 53 私有区域 ID。
    8 从 DNS 和负载均衡的 CloudFormation 模板输出中指定 PrivateHostedZoneId 值。
    9 用于注册目标的 Route 53 区域。
    10 指定 <cluster_name>.<domain_name>,其中 <domain_name> 是您在为集群生成 install-config.yaml 文件时使用的 Route 53 基础域名。请勿包含在 AWS 控制台中显示的尾随句点 (.)。
    11 一个子网(最好是私有子网),用于在其上启动控制平面机器。
    12 从 DNS 和负载均衡的 CloudFormation 模板输出的 PrivateSubnets 值中指定一个子网。
    13 要与控制平面节点关联的主安全组 ID。
    14 从 CloudFormation 模板的安全组和角色输出中指定 MasterSecurityGroupId 值。
    15 获取控制平面 Ignition 配置文件的地址。
    16 指定生成的 Ignition 配置文件位置,https://api-int.<cluster_name>.<domain_name>:22623/config/master
    17 要使用的 base64 编码证书颁发机构字符串。
    18 指定安装目录中 master.ign 文件中的值。此值是格式为 data:text/plain;charset=utf-8;base64,ABC…​xYz== 的长字符串。
    19 要与控制平面节点关联的 IAM 配置文件。
    20 从安全组和角色的 CloudFormation 模板输出中指定 MasterInstanceProfile 参数值。
    21 根据您选择的架构,要用于控制平面机器的 AWS 实例类型。
    22 实例类型值对应于控制平面机器的最低资源要求。例如,m6i.xlarge 是 AMD64 的类型,m6g.xlarge 是 ARM64 的类型。
    23 是否注册网络负载均衡器 (NLB)。
    24 指定 yesno。如果指定 yes,则必须提供 Lambda Amazon 资源名称 (ARN) 值。
    25 NLB IP 目标注册 lambda 组的 ARN。
    26 从 DNS 和负载均衡的 CloudFormation 模板输出中指定 RegisterNlbIpTargetsLambda 值。如果将集群部署到 AWS GovCloud 区域,请使用 arn:aws-us-gov
    27 外部 API 负载均衡器目标组的 ARN。
    28 从 DNS 和负载均衡的 CloudFormation 模板输出中指定 ExternalApiTargetGroupArn 值。如果将集群部署到 AWS GovCloud 区域,请使用 arn:aws-us-gov
    29 内部 API 负载均衡器目标组的 ARN。
    30 从 DNS 和负载均衡的 CloudFormation 模板输出中指定 InternalApiTargetGroupArn 值。如果将集群部署到 AWS GovCloud 区域,请使用 arn:aws-us-gov
    31 内部服务负载均衡器目标组的 ARN。
    32 从 DNS 和负载均衡的 CloudFormation 模板输出中指定 InternalServiceTargetGroupArn 值。如果将集群部署到 AWS GovCloud 区域,请使用 arn:aws-us-gov
  2. 从本主题的“控制平面机器的 CloudFormation 模板”部分复制模板,并将其另存为计算机上的 YAML 文件。此模板描述了集群所需的控制平面机器。

  3. 如果您将 m5 实例类型指定为 MasterInstanceType 的值,请将该实例类型添加到 CloudFormation 模板中的 MasterInstanceType.AllowedValues 参数中。

  4. 启动 CloudFormation 模板以创建表示控制平面节点的 AWS 资源堆栈。

    您必须在一行中输入命令。

    $ aws cloudformation create-stack --stack-name <name> (1)
         --template-body file://<template>.yaml (2)
         --parameters file://<parameters>.json (3)
    1 <name> 是 CloudFormation 堆栈的名称,例如 cluster-control-plane。如果您删除集群,则需要此堆栈的名称。
    2 <template>是您保存的 CloudFormation 模板 YAML 文件的相对路径和名称。
    3 <parameters>是 CloudFormation 参数 JSON 文件的相对路径和名称。
    示例输出
    arn:aws:cloudformation:us-east-1:269333783861:stack/cluster-control-plane/21c7e2b0-2ee2-11eb-c6f6-0aa34627df4b

    CloudFormation 模板创建表示三个控制平面节点的堆栈。

  5. 确认模板组件存在。

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

控制平面机器的 CloudFormation 模板

您可以使用以下 CloudFormation 模板部署 OpenShift Container Platform 集群所需的控制平面机器。

控制平面机器的CloudFormation模板
AWSTemplateFormatVersion: 2010-09-09
Description: Template for OpenShift Cluster Node Launch (EC2 master instances)

Parameters:
  InfrastructureName:
    AllowedPattern: ^([a-zA-Z][a-zA-Z0-9\-]{0,26})$
    MaxLength: 27
    MinLength: 1
    ConstraintDescription: Infrastructure name must be alphanumeric, start with a letter, and have a maximum of 27 characters.
    Description: A short, unique cluster ID used to tag nodes for the kubelet cloud provider.
    Type: String
  RhcosAmi:
    Description: Current Red Hat Enterprise Linux CoreOS AMI to use for bootstrap.
    Type: AWS::EC2::Image::Id
  AutoRegisterDNS:
    Default: ""
    Description: unused
    Type: String
  PrivateHostedZoneId:
    Default: ""
    Description: unused
    Type: String
  PrivateHostedZoneName:
    Default: ""
    Description: unused
    Type: String
  Master0Subnet:
    Description: The subnets, recommend private, to launch the master nodes into.
    Type: AWS::EC2::Subnet::Id
  Master1Subnet:
    Description: The subnets, recommend private, to launch the master nodes into.
    Type: AWS::EC2::Subnet::Id
  Master2Subnet:
    Description: The subnets, recommend private, to launch the master nodes into.
    Type: AWS::EC2::Subnet::Id
  MasterSecurityGroupId:
    Description: The master security group ID to associate with master nodes.
    Type: AWS::EC2::SecurityGroup::Id
  IgnitionLocation:
    Default: https://api-int.$CLUSTER_NAME.$DOMAIN:22623/config/master
    Description: Ignition config file location.
    Type: String
  CertificateAuthorities:
    Default: data:text/plain;charset=utf-8;base64,ABC...xYz==
    Description: Base64 encoded certificate authority string to use.
    Type: String
  MasterInstanceProfileName:
    Description: IAM profile to associate with master nodes.
    Type: String
  MasterInstanceType:
    Default: m5.xlarge
    Type: String

  AutoRegisterELB:
    Default: "yes"
    AllowedValues:
    - "yes"
    - "no"
    Description: Do you want to invoke NLB registration, which requires a Lambda ARN parameter?
    Type: String
  RegisterNlbIpTargetsLambdaArn:
    Description: ARN for NLB IP target registration lambda. Supply the value from the cluster infrastructure or select "no" for AutoRegisterELB.
    Type: String
  ExternalApiTargetGroupArn:
    Description: ARN for external API load balancer target group. Supply the value from the cluster infrastructure or select "no" for AutoRegisterELB.
    Type: String
  InternalApiTargetGroupArn:
    Description: ARN for internal API load balancer target group. Supply the value from the cluster infrastructure or select "no" for AutoRegisterELB.
    Type: String
  InternalServiceTargetGroupArn:
    Description: ARN for internal service load balancer target group. Supply the value from the cluster infrastructure or select "no" for AutoRegisterELB.
    Type: String

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
    - Label:
        default: "Cluster Information"
      Parameters:
      - InfrastructureName
    - Label:
        default: "Host Information"
      Parameters:
      - MasterInstanceType
      - RhcosAmi
      - IgnitionLocation
      - CertificateAuthorities
      - MasterSecurityGroupId
      - MasterInstanceProfileName
    - Label:
        default: "Network Configuration"
      Parameters:
      - VpcId
      - AllowedBootstrapSshCidr
      - Master0Subnet
      - Master1Subnet
      - Master2Subnet
    - Label:
        default: "Load Balancer Automation"
      Parameters:
      - AutoRegisterELB
      - RegisterNlbIpTargetsLambdaArn
      - ExternalApiTargetGroupArn
      - InternalApiTargetGroupArn
      - InternalServiceTargetGroupArn
    ParameterLabels:
      InfrastructureName:
        default: "Infrastructure Name"
      VpcId:
        default: "VPC ID"
      Master0Subnet:
        default: "Master-0 Subnet"
      Master1Subnet:
        default: "Master-1 Subnet"
      Master2Subnet:
        default: "Master-2 Subnet"
      MasterInstanceType:
        default: "Master Instance Type"
      MasterInstanceProfileName:
        default: "Master Instance Profile Name"
      RhcosAmi:
        default: "Red Hat Enterprise Linux CoreOS AMI ID"
      BootstrapIgnitionLocation:
        default: "Master Ignition Source"
      CertificateAuthorities:
        default: "Ignition CA String"
      MasterSecurityGroupId:
        default: "Master Security Group ID"
      AutoRegisterELB:
        default: "Use Provided ELB Automation"

Conditions:
  DoRegistration: !Equals ["yes", !Ref AutoRegisterELB]

Resources:
  Master0:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref RhcosAmi
      BlockDeviceMappings:
      - DeviceName: /dev/xvda
        Ebs:
          VolumeSize: "120"
          VolumeType: "gp2"
      IamInstanceProfile: !Ref MasterInstanceProfileName
      InstanceType: !Ref MasterInstanceType
      NetworkInterfaces:
      - AssociatePublicIpAddress: "false"
        DeviceIndex: "0"
        GroupSet:
        - !Ref "MasterSecurityGroupId"
        SubnetId: !Ref "Master0Subnet"
      UserData:
        Fn::Base64: !Sub
        - '{"ignition":{"config":{"merge":[{"source":"${SOURCE}"}]},"security":{"tls":{"certificateAuthorities":[{"source":"${CA_BUNDLE}"}]}},"version":"3.1.0"}}'
        - {
          SOURCE: !Ref IgnitionLocation,
          CA_BUNDLE: !Ref CertificateAuthorities,
        }
      Tags:
      - Key: !Join ["", ["kubernetes.io/cluster/", !Ref InfrastructureName]]
        Value: "shared"

  RegisterMaster0:
    Condition: DoRegistration
    Type: Custom::NLBRegister
    Properties:
      ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
      TargetArn: !Ref ExternalApiTargetGroupArn
      TargetIp: !GetAtt Master0.PrivateIp

  RegisterMaster0InternalApiTarget:
    Condition: DoRegistration
    Type: Custom::NLBRegister
    Properties:
      ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
      TargetArn: !Ref InternalApiTargetGroupArn
      TargetIp: !GetAtt Master0.PrivateIp

  RegisterMaster0InternalServiceTarget:
    Condition: DoRegistration
    Type: Custom::NLBRegister
    Properties:
      ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
      TargetArn: !Ref InternalServiceTargetGroupArn
      TargetIp: !GetAtt Master0.PrivateIp

  Master1:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref RhcosAmi
      BlockDeviceMappings:
      - DeviceName: /dev/xvda
        Ebs:
          VolumeSize: "120"
          VolumeType: "gp2"
      IamInstanceProfile: !Ref MasterInstanceProfileName
      InstanceType: !Ref MasterInstanceType
      NetworkInterfaces:
      - AssociatePublicIpAddress: "false"
        DeviceIndex: "0"
        GroupSet:
        - !Ref "MasterSecurityGroupId"
        SubnetId: !Ref "Master1Subnet"
      UserData:
        Fn::Base64: !Sub
        - '{"ignition":{"config":{"merge":[{"source":"${SOURCE}"}]},"security":{"tls":{"certificateAuthorities":[{"source":"${CA_BUNDLE}"}]}},"version":"3.1.0"}}'
        - {
          SOURCE: !Ref IgnitionLocation,
          CA_BUNDLE: !Ref CertificateAuthorities,
        }
      Tags:
      - Key: !Join ["", ["kubernetes.io/cluster/", !Ref InfrastructureName]]
        Value: "shared"

  RegisterMaster1:
    Condition: DoRegistration
    Type: Custom::NLBRegister
    Properties:
      ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
      TargetArn: !Ref ExternalApiTargetGroupArn
      TargetIp: !GetAtt Master1.PrivateIp

  RegisterMaster1InternalApiTarget:
    Condition: DoRegistration
    Type: Custom::NLBRegister
    Properties:
      ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
      TargetArn: !Ref InternalApiTargetGroupArn
      TargetIp: !GetAtt Master1.PrivateIp

  RegisterMaster1InternalServiceTarget:
    Condition: DoRegistration
    Type: Custom::NLBRegister
    Properties:
      ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
      TargetArn: !Ref InternalServiceTargetGroupArn
      TargetIp: !GetAtt Master1.PrivateIp

  Master2:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref RhcosAmi
      BlockDeviceMappings:
      - DeviceName: /dev/xvda
        Ebs:
          VolumeSize: "120"
          VolumeType: "gp2"
      IamInstanceProfile: !Ref MasterInstanceProfileName
      InstanceType: !Ref MasterInstanceType
      NetworkInterfaces:
      - AssociatePublicIpAddress: "false"
        DeviceIndex: "0"
        GroupSet:
        - !Ref "MasterSecurityGroupId"
        SubnetId: !Ref "Master2Subnet"
      UserData:
        Fn::Base64: !Sub
        - '{"ignition":{"config":{"merge":[{"source":"${SOURCE}"}]},"security":{"tls":{"certificateAuthorities":[{"source":"${CA_BUNDLE}"}]}},"version":"3.1.0"}}'
        - {
          SOURCE: !Ref IgnitionLocation,
          CA_BUNDLE: !Ref CertificateAuthorities,
        }
      Tags:
      - Key: !Join ["", ["kubernetes.io/cluster/", !Ref InfrastructureName]]
        Value: "shared"

  RegisterMaster2:
    Condition: DoRegistration
    Type: Custom::NLBRegister
    Properties:
      ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
      TargetArn: !Ref ExternalApiTargetGroupArn
      TargetIp: !GetAtt Master2.PrivateIp

  RegisterMaster2InternalApiTarget:
    Condition: DoRegistration
    Type: Custom::NLBRegister
    Properties:
      ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
      TargetArn: !Ref InternalApiTargetGroupArn
      TargetIp: !GetAtt Master2.PrivateIp

  RegisterMaster2InternalServiceTarget:
    Condition: DoRegistration
    Type: Custom::NLBRegister
    Properties:
      ServiceToken: !Ref RegisterNlbIpTargetsLambdaArn
      TargetArn: !Ref InternalServiceTargetGroupArn
      TargetIp: !GetAtt Master2.PrivateIp

Outputs:
  PrivateIPs:
    Description: The control-plane node private IP addresses.
    Value:
      !Join [
        ",",
        [!GetAtt Master0.PrivateIp, !GetAtt Master1.PrivateIp, !GetAtt Master2.PrivateIp]
      ]
其他资源

在 AWS 中创建工作节点

您可以为集群创建将在 Amazon Web Services (AWS) 中使用的 Worker 节点。

如果您正在安装三节点集群,请跳过此步骤。三节点集群由三个控制平面机器组成,这些机器也充当计算机器。

您可以使用提供的 CloudFormation 模板和自定义参数文件来创建代表工作节点的 AWS 资源堆栈。

CloudFormation 模板创建一个代表单个工作节点的堆栈。您必须为每个工作节点创建一个堆栈。

如果您不使用提供的 CloudFormation 模板创建工作节点,则必须查看提供的信息并手动创建基础架构。如果您的集群未正确初始化,您可能需要联系 Red Hat 支持并提供您的安装日志。

先决条件
  • 您已配置 AWS 账户。

  • 您已通过运行aws configure将您的 AWS 密钥和区域添加到您的本地 AWS 配置文件中。

  • 您已为您的集群生成 Ignition 配置文件。

  • 您已在 AWS 中创建和配置了 VPC 和关联的子网。

  • 您已在 AWS 中创建并配置了 DNS、负载均衡器和侦听器。

  • 您已在 AWS 中创建了集群所需的安全性组和角色。

  • 您已创建引导机器。

  • 您已创建控制平面机器。

步骤
  1. 创建一个 JSON 文件,其中包含 CloudFormation 模板所需的参数值。

    [
      {
        "ParameterKey": "InfrastructureName", (1)
        "ParameterValue": "mycluster-<random_string>" (2)
      },
      {
        "ParameterKey": "RhcosAmi", (3)
        "ParameterValue": "ami-<random_string>" (4)
      },
      {
        "ParameterKey": "Subnet", (5)
        "ParameterValue": "subnet-<random_string>" (6)
      },
      {
        "ParameterKey": "WorkerSecurityGroupId", (7)
        "ParameterValue": "sg-<random_string>" (8)
      },
      {
        "ParameterKey": "IgnitionLocation", (9)
        "ParameterValue": "https://api-int.<cluster_name>.<domain_name>:22623/config/worker" (10)
      },
      {
        "ParameterKey": "CertificateAuthorities", (11)
        "ParameterValue": "" (12)
      },
      {
        "ParameterKey": "WorkerInstanceProfileName", (13)
        "ParameterValue": "" (14)
      },
      {
        "ParameterKey": "WorkerInstanceType", (15)
        "ParameterValue": "" (16)
      }
    ]
    1 集群的 Ignition 配置文件中编码的集群基础设施名称。
    2 指定您从 Ignition 配置文件元数据中提取的基础设施名称,其格式为<cluster-name>-<random-string>
    3 根据您选择的架构,用于工作节点的当前 Red Hat Enterprise Linux CoreOS (RHCOS) AMI。
    4 指定 AWS::EC2::Image::Id 值。
    5 一个子网,最好是私有子网,用于启动工作节点。
    6 从 DNS 和负载均衡的 CloudFormation 模板输出的 PrivateSubnets 值中指定一个子网。
    7 与工作节点关联的工作安全组 ID。
    8 指定安全组和角色的 CloudFormation 模板输出中的 `WorkerSecurityGroupId` 值。
    9 获取引导 Ignition 配置文件的地址。
    10 指定生成的 Ignition 配置文件地址:`https://api-int.<cluster_name>.<domain_name>:22623/config/worker`。
    11 要使用的 Base64 编码的证书颁发机构字符串。
    12 指定安装目录中 `worker.ign` 文件中的值。此值是一个长字符串,格式为 `data:text/plain;charset=utf-8;base64,ABC…​xYz==`。
    13 要与工作节点关联的 IAM 角色。
    14 指定安全组和角色的 CloudFormation 模板输出中的 `WorkerInstanceProfile` 参数值。
    15 根据您选择的架构,用于计算机器的 AWS 实例类型。
    16 实例类型值对应于计算机器的最低资源要求。例如,`m6i.large` 是 AMD64 的一种类型,而 `m6g.large` 是 ARM64 的一种类型。
  2. 从本主题的“工作机器的 CloudFormation 模板”部分复制模板,并将其另存为计算机上的 YAML 文件。此模板描述了集群所需的网络对象和负载均衡器。

  3. 可选:如果您将 `m5` 实例类型指定为 `WorkerInstanceType` 的值,请将该实例类型添加到 CloudFormation 模板中的 `WorkerInstanceType.AllowedValues` 参数中。

  4. 可选:如果您使用 AWS Marketplace 镜像进行部署,请使用从您的订阅中获得的 AMI ID 更新 `Worker0.type.properties.ImageID` 参数。

  5. 使用 CloudFormation 模板创建一个代表工作节点的 AWS 资源堆栈。

    您必须在一行中输入命令。

    $ aws cloudformation create-stack --stack-name <name> (1)
         --template-body file://<template>.yaml \ (2)
         --parameters file://<parameters>.json (3)
    1 `<name>` 是 CloudFormation 堆栈的名称,例如 `cluster-worker-1`。如果您删除集群,则需要此堆栈的名称。
    2 <template>是您保存的 CloudFormation 模板 YAML 文件的相对路径和名称。
    3 <parameters>是 CloudFormation 参数 JSON 文件的相对路径和名称。
    示例输出
    arn:aws:cloudformation:us-east-1:269333783861:stack/cluster-worker-1/729ee301-1c2a-11eb-348f-sd9888c65b59

    CloudFormation 模板创建一个代表单个工作节点的堆栈。

  6. 确认模板组件存在。

    $ aws cloudformation describe-stacks --stack-name <name>
  7. 继续创建工作程序堆栈,直到您为集群创建足够的计算节点为止。您可以通过引用相同的模板和参数文件并指定不同的堆栈名称来创建其他工作程序堆栈。

    您必须至少创建两台工作机器,因此您必须至少创建两个使用此 CloudFormation 模板的堆栈。

工作机器的 CloudFormation 模板

您可以使用以下 CloudFormation 模板部署 OpenShift Container Platform 集群所需的工作机器。

工作机的CloudFormation模板
AWSTemplateFormatVersion: 2010-09-09
Description: Template for OpenShift Cluster Node Launch (EC2 worker instance)

Parameters:
  InfrastructureName:
    AllowedPattern: ^([a-zA-Z][a-zA-Z0-9\-]{0,26})$
    MaxLength: 27
    MinLength: 1
    ConstraintDescription: Infrastructure name must be alphanumeric, start with a letter, and have a maximum of 27 characters.
    Description: A short, unique cluster ID used to tag nodes for the kubelet cloud provider.
    Type: String
  RhcosAmi:
    Description: Current Red Hat Enterprise Linux CoreOS AMI to use for bootstrap.
    Type: AWS::EC2::Image::Id
  Subnet:
    Description: The subnets, recommend private, to launch the worker nodes into.
    Type: AWS::EC2::Subnet::Id
  WorkerSecurityGroupId:
    Description: The worker security group ID to associate with worker nodes.
    Type: AWS::EC2::SecurityGroup::Id
  IgnitionLocation:
    Default: https://api-int.$CLUSTER_NAME.$DOMAIN:22623/config/worker
    Description: Ignition config file location.
    Type: String
  CertificateAuthorities:
    Default: data:text/plain;charset=utf-8;base64,ABC...xYz==
    Description: Base64 encoded certificate authority string to use.
    Type: String
  WorkerInstanceProfileName:
    Description: IAM profile to associate with worker nodes.
    Type: String
  WorkerInstanceType:
    Default: m5.large
    Type: String

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
    - Label:
        default: "Cluster Information"
      Parameters:
      - InfrastructureName
    - Label:
        default: "Host Information"
      Parameters:
      - WorkerInstanceType
      - RhcosAmi
      - IgnitionLocation
      - CertificateAuthorities
      - WorkerSecurityGroupId
      - WorkerInstanceProfileName
    - Label:
        default: "Network Configuration"
      Parameters:
      - Subnet
    ParameterLabels:
      Subnet:
        default: "Subnet"
      InfrastructureName:
        default: "Infrastructure Name"
      WorkerInstanceType:
        default: "Worker Instance Type"
      WorkerInstanceProfileName:
        default: "Worker Instance Profile Name"
      RhcosAmi:
        default: "Red Hat Enterprise Linux CoreOS AMI ID"
      IgnitionLocation:
        default: "Worker Ignition Source"
      CertificateAuthorities:
        default: "Ignition CA String"
      WorkerSecurityGroupId:
        default: "Worker Security Group ID"

Resources:
  Worker0:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref RhcosAmi
      BlockDeviceMappings:
      - DeviceName: /dev/xvda
        Ebs:
          VolumeSize: "120"
          VolumeType: "gp2"
      IamInstanceProfile: !Ref WorkerInstanceProfileName
      InstanceType: !Ref WorkerInstanceType
      NetworkInterfaces:
      - AssociatePublicIpAddress: "false"
        DeviceIndex: "0"
        GroupSet:
        - !Ref "WorkerSecurityGroupId"
        SubnetId: !Ref "Subnet"
      UserData:
        Fn::Base64: !Sub
        - '{"ignition":{"config":{"merge":[{"source":"${SOURCE}"}]},"security":{"tls":{"certificateAuthorities":[{"source":"${CA_BUNDLE}"}]}},"version":"3.1.0"}}'
        - {
          SOURCE: !Ref IgnitionLocation,
          CA_BUNDLE: !Ref CertificateAuthorities,
        }
      Tags:
      - Key: !Join ["", ["kubernetes.io/cluster/", !Ref InfrastructureName]]
        Value: "shared"

Outputs:
  PrivateIP:
    Description: The compute node private IP address.
    Value: !GetAtt Worker0.PrivateIp
其他资源

使用用户预配的基础架构在 AWS 上初始化引导序列

在 Amazon Web Services (AWS) 中创建所有必需的基础架构后,您可以启动初始化 OpenShift Container Platform 控制平面的引导序列。

先决条件
  • 您已配置 AWS 账户。

  • 您已通过运行aws configure将您的 AWS 密钥和区域添加到您的本地 AWS 配置文件中。

  • 您已为您的集群生成 Ignition 配置文件。

  • 您已在 AWS 中创建和配置了 VPC 和关联的子网。

  • 您已在 AWS 中创建并配置了 DNS、负载均衡器和侦听器。

  • 您已在 AWS 中创建了集群所需的安全性组和角色。

  • 您已创建引导机器。

  • 您已创建控制平面机器。

  • 您已创建工作节点。

步骤
  1. 更改到包含安装程序的目录,并启动初始化 OpenShift Container Platform 控制平面的引导过程。

    $ ./openshift-install wait-for bootstrap-complete --dir <installation_directory> \ (1)
        --log-level=info (2)
    
    1 对于<installation_directory>,请指定您存储安装文件的目录的路径。
    2 要查看不同的安装详细信息,请指定 `warn`、`debug` 或 `error`,而不是 `info`。
    示例输出
    INFO Waiting up to 20m0s for the Kubernetes API at https://api.mycluster.example.com:6443...
    INFO API v1.30.3 up
    INFO Waiting up to 30m0s for bootstrapping to complete...
    INFO It is now safe to remove the bootstrap resources
    INFO Time elapsed: 1s

    如果命令在没有 `FATAL` 警告的情况下退出,则您的 OpenShift Container Platform 控制平面已初始化。

    控制平面初始化后,它会设置计算节点并在运算符的形式下安装其他服务。

其他资源
  • 有关监控 OpenShift Container Platform 安装进度期间的安装、引导和控制平面日志的详细信息,请参阅 监控安装进度

  • 有关解决与引导过程相关的问题的详细信息,请参阅 收集引导节点诊断数据

  • 您可以使用 AWS EC2 控制台 查看创建的正在运行的实例的详细信息。

使用 CLI 登录集群

您可以通过导出集群 `kubeconfig` 文件以默认系统用户身份登录到集群。`kubeconfig` 文件包含有关集群的信息,CLI 使用这些信息将客户端连接到正确的集群和 API 服务器。该文件特定于一个集群,并在 OpenShift Container Platform 安装期间创建。

先决条件
  • 您已部署 OpenShift Container Platform 集群。

  • 您已安装 `oc` CLI。

步骤
  1. 导出 `kubeadmin` 凭据。

    $ export KUBECONFIG=<installation_directory>/auth/kubeconfig (1)
    1 对于<installation_directory>,请指定您存储安装文件的目录的路径。
  2. 验证您可以使用导出的配置成功运行 `oc` 命令。

    $ oc whoami
    示例输出
    system:admin

批准机器的证书签名请求 (CSR)

将机器添加到集群时,会为添加的每台机器生成两个挂起的证书签名请求 (CSR)。您必须确认这些 CSR 已获批准,或者如有必要,自行批准它们。必须先批准客户端请求,然后才能批准服务器请求。

先决条件
  • 您已将机器添加到集群。

步骤
  1. 确认集群识别这些机器。

    $ oc get nodes
    示例输出
    NAME      STATUS    ROLES   AGE  VERSION
    master-0  Ready     master  63m  v1.30.3
    master-1  Ready     master  63m  v1.30.3
    master-2  Ready     master  64m  v1.30.3

    输出列出了您创建的所有机器。

    在批准一些 CSR 之前,上述输出可能不包含计算节点(也称为工作节点)。

  2. 查看挂起的 CSR,并确保您看到为添加到集群的每台机器显示 `Pending` 或 `Approved` 状态的客户端请求。

    $ oc get csr
    示例输出
    NAME        AGE     REQUESTOR                                                                   CONDITION
    csr-8b2br   15m     system:serviceaccount:openshift-machine-config-operator:node-bootstrapper   Pending
    csr-8vnps   15m     system:serviceaccount:openshift-machine-config-operator:node-bootstrapper   Pending
    ...

    在此示例中,两台机器正在加入集群。您可能会在列表中看到更多已批准的 CSR。

  3. 如果 CSR 未获批准,则在您添加的所有机器的挂起 CSR 处于 `Pending` 状态后,批准集群机器的 CSR。

    由于 CSR 会自动轮换,因此在将机器添加到集群后一小时内批准您的 CSR。如果您在一小时内没有批准它们,证书将轮换,并且每个节点将存在两个以上的证书。您必须批准所有这些证书。批准客户端 CSR 后,Kubelet 将为服务证书创建辅助 CSR,这需要手动批准。然后,如果 Kubelet 请求具有相同参数的新证书,则 `machine-approver` 将自动批准后续的服务证书续订请求。

    对于在未启用机器 API 的平台(例如裸机和其他用户预配的基础设施)上运行的集群,必须实现一种自动批准 kubelet 服务证书请求 (CSR) 的方法。如果未批准请求,则oc execoc rshoc logs 命令将无法成功执行,因为 API 服务器连接到 kubelet 时需要服务证书。任何联系 Kubelet 端点的操作都需要此证书批准到位。此方法必须监视新的 CSR,确认 CSR 是由system:nodesystem:admin 组中的node-bootstrapper 服务帐户提交的,并确认节点的身份。

    • 要逐个批准它们,请对每个有效的 CSR 运行以下命令

      $ oc adm certificate approve <csr_name> (1)
      1 <csr_name> 是当前 CSR 列表中 CSR 的名称。
    • 要批准所有待处理的 CSR,请运行以下命令

      $ 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

      在批准某些 CSR 之前,某些 Operator 可能会不可用。

  4. 现在您的客户端请求已获批准,您必须检查为添加到集群中的每台机器的服务器请求

    $ oc get csr
    示例输出
    NAME        AGE     REQUESTOR                                                                   CONDITION
    csr-bfd72   5m26s   system:node:ip-10-0-50-126.us-east-2.compute.internal                       Pending
    csr-c57lv   5m26s   system:node:ip-10-0-95-157.us-east-2.compute.internal                       Pending
    ...
  5. 如果剩余的 CSR 未获批准且状态为Pending,请批准集群机器的 CSR

    • 要逐个批准它们,请对每个有效的 CSR 运行以下命令

      $ oc adm certificate approve <csr_name> (1)
      1 <csr_name> 是当前 CSR 列表中 CSR 的名称。
    • 要批准所有待处理的 CSR,请运行以下命令

      $ oc get csr -o go-template='{{range .items}}{{if not .status}}{{.metadata.name}}{{"\n"}}{{end}}{{end}}' | xargs oc adm certificate approve
  6. 批准所有客户端和服务器 CSR 后,机器将具有Ready 状态。通过运行以下命令验证此状态

    $ oc get nodes
    示例输出
    NAME      STATUS    ROLES   AGE  VERSION
    master-0  Ready     master  73m  v1.30.3
    master-1  Ready     master  73m  v1.30.3
    master-2  Ready     master  74m  v1.30.3
    worker-0  Ready     worker  11m  v1.30.3
    worker-1  Ready     worker  11m  v1.30.3

    批准服务器 CSR 后,机器可能需要几分钟才能过渡到Ready 状态。

更多信息

初始 Operator 配置

控制平面初始化后,必须立即配置一些 Operator,以便它们全部可用。

先决条件
  • 您的控制平面已初始化。

步骤
  1. 监视集群组件上线

    $ watch -n5 oc get clusteroperators
    示例输出
    NAME                                       VERSION   AVAILABLE   PROGRESSING   DEGRADED   SINCE
    authentication                             4.17.0    True        False         False      19m
    baremetal                                  4.17.0    True        False         False      37m
    cloud-credential                           4.17.0    True        False         False      40m
    cluster-autoscaler                         4.17.0    True        False         False      37m
    config-operator                            4.17.0    True        False         False      38m
    console                                    4.17.0    True        False         False      26m
    csi-snapshot-controller                    4.17.0    True        False         False      37m
    dns                                        4.17.0    True        False         False      37m
    etcd                                       4.17.0    True        False         False      36m
    image-registry                             4.17.0    True        False         False      31m
    ingress                                    4.17.0    True        False         False      30m
    insights                                   4.17.0    True        False         False      31m
    kube-apiserver                             4.17.0    True        False         False      26m
    kube-controller-manager                    4.17.0    True        False         False      36m
    kube-scheduler                             4.17.0    True        False         False      36m
    kube-storage-version-migrator              4.17.0    True        False         False      37m
    machine-api                                4.17.0    True        False         False      29m
    machine-approver                           4.17.0    True        False         False      37m
    machine-config                             4.17.0    True        False         False      36m
    marketplace                                4.17.0    True        False         False      37m
    monitoring                                 4.17.0    True        False         False      29m
    network                                    4.17.0    True        False         False      38m
    node-tuning                                4.17.0    True        False         False      37m
    openshift-apiserver                        4.17.0    True        False         False      32m
    openshift-controller-manager               4.17.0    True        False         False      30m
    openshift-samples                          4.17.0    True        False         False      32m
    operator-lifecycle-manager                 4.17.0    True        False         False      37m
    operator-lifecycle-manager-catalog         4.17.0    True        False         False      37m
    operator-lifecycle-manager-packageserver   4.17.0    True        False         False      32m
    service-ca                                 4.17.0    True        False         False      38m
    storage                                    4.17.0    True        False         False      37m
  2. 配置不可用的 Operator。

镜像注册表存储配置

Amazon Web Services 提供默认存储,这意味着镜像注册表 Operator 在安装后可用。但是,如果注册表 Operator 无法创建 S3 存储桶并自动配置存储,则必须手动配置注册表存储。

显示了配置持久卷的说明,这是生产集群所需的。在适用情况下,显示了将空目录配置为存储位置的说明,这仅适用于非生产集群。

提供了其他说明,用于通过在升级期间使用Recreate 展开策略来允许镜像注册表使用块存储类型。

您可以为 AWS 中的用户预配基础设施配置注册表存储,以将 OpenShift Container Platform 部署到隐藏区域。有关更多信息,请参见为 AWS 用户预配的基础设施配置注册表

为使用用户预配基础设施的 AWS 配置注册表存储

安装过程中,您的云凭据足以创建 Amazon S3 存储桶,注册表 Operator 将自动配置存储。

如果注册表 Operator 无法创建 S3 存储桶并自动配置存储,您可以创建 S3 存储桶并使用以下步骤配置存储。

先决条件
  • 您在 AWS 上拥有一个使用用户预配基础设施的集群。

  • 对于 Amazon S3 存储,预期密钥包含两个密钥

    • REGISTRY_STORAGE_S3_ACCESSKEY

    • REGISTRY_STORAGE_S3_SECRETKEY

步骤

如果注册表 Operator 无法创建 S3 存储桶并自动配置存储,请使用以下步骤。

  1. 设置一个存储桶生命周期策略以中止一天前的未完成分段上传。

  2. configs.imageregistry.operator.openshift.io/cluster中填写存储配置

    $ oc edit configs.imageregistry.operator.openshift.io/cluster
    配置示例
    storage:
      s3:
        bucket: <bucket-name>
        region: <region-name>

要保护 AWS 中的注册表镜像,请阻止对 S3 存储桶的公共访问

配置非生产集群中镜像注册表的存储

您必须为镜像注册表 Operator 配置存储。对于非生产集群,您可以将镜像注册表设置为空目录。如果这样做,则重新启动注册表后,所有镜像都将丢失。

步骤
  • 要将镜像注册表存储设置为空目录

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

    仅为非生产集群配置此选项。

    如果在镜像注册表 Operator 初始化其组件之前运行此命令,则oc patch 命令将失败并显示以下错误

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

    等待几分钟,然后再次运行该命令。

删除引导资源

完成集群的初始 Operator 配置后,请从 Amazon Web Services (AWS) 中删除引导资源。

先决条件
  • 您已完成集群的初始 Operator 配置。

步骤
  1. 删除引导资源。如果您使用了 CloudFormation 模板,请删除其堆栈

    • 使用 AWS CLI 删除堆栈

      $ aws cloudformation delete-stack --stack-name <name> (1)
      1 <name> 是您的引导堆栈的名称。
    • 使用AWS CloudFormation 控制台删除堆栈。

创建 Ingress DNS 记录

如果您删除了 DNS 区域配置,请手动创建指向 Ingress 负载均衡器的 DNS 记录。您可以创建通配符记录或特定记录。虽然以下步骤使用 A 记录,但您可以使用您需要的其他记录类型,例如 CNAME 或别名。

先决条件
步骤
  1. 确定要创建的路由。

    • 要创建通配符记录,请使用*.apps.<cluster_name>.<domain_name>,其中<cluster_name> 是您的集群名称,<domain_name> 是 OpenShift Container Platform 集群的 Route 53 基础域。

    • 要创建特定记录,您必须为集群使用的每个路由创建一个记录,如以下命令的输出所示

      $ oc get --all-namespaces -o jsonpath='{range .items[*]}{range .status.ingress[*]}{.host}{"\n"}{end}{end}' routes
      示例输出
      oauth-openshift.apps.<cluster_name>.<domain_name>
      console-openshift-console.apps.<cluster_name>.<domain_name>
      downloads-openshift-console.apps.<cluster_name>.<domain_name>
      alertmanager-main-openshift-monitoring.apps.<cluster_name>.<domain_name>
      prometheus-k8s-openshift-monitoring.apps.<cluster_name>.<domain_name>
  2. 检索 Ingress Operator 负载均衡器状态,并记下其使用的外部 IP 地址的值,该值显示在EXTERNAL-IP 列中

    $ oc -n openshift-ingress get service router-default
    示例输出
    NAME             TYPE           CLUSTER-IP      EXTERNAL-IP                            PORT(S)                      AGE
    router-default   LoadBalancer   172.30.62.215   ab3...28.us-east-2.elb.amazonaws.com   80:31499/TCP,443:30693/TCP   5m
  3. 找到负载均衡器的托管区域 ID

    $ aws elb describe-load-balancers | jq -r '.LoadBalancerDescriptions[] | select(.DNSName == "<external_ip>").CanonicalHostedZoneNameID' (1)
    1 对于<external_ip>,请指定您获得的 Ingress Operator 负载均衡器的外部 IP 地址的值。
    示例输出
    Z3AADJGX6KTTL2

    此命令的输出是负载均衡器托管区域 ID。

  4. 获取集群域的公共托管区域 ID

    $ aws route53 list-hosted-zones-by-name \
                --dns-name "<domain_name>" \ (1)
                --query 'HostedZones[? Config.PrivateZone != `true` && Name == `<domain_name>.`].Id' (1)
                --output text
    1 对于<domain_name>,请指定 OpenShift Container Platform 集群的 Route 53 基础域。
    示例输出
    /hostedzone/Z3URY6TWQ91KVV

    命令输出中显示了您域的公共托管区域 ID。在此示例中,它是Z3URY6TWQ91KVV

  5. 将别名记录添加到您的私有区域

    $ aws route53 change-resource-record-sets --hosted-zone-id "<private_hosted_zone_id>" --change-batch '{ (1)
    >   "Changes": [
    >     {
    >       "Action": "CREATE",
    >       "ResourceRecordSet": {
    >         "Name": "\\052.apps.<cluster_domain>", (2)
    >         "Type": "A",
    >         "AliasTarget":{
    >           "HostedZoneId": "<hosted_zone_id>", (3)
    >           "DNSName": "<external_ip>.", (4)
    >           "EvaluateTargetHealth": false
    >         }
    >       }
    >     }
    >   ]
    > }'
    1 对于<private_hosted_zone_id>,请指定 CloudFormation 模板中 DNS 和负载均衡的输出值。
    2 对于<cluster_domain>,请指定您与 OpenShift Container Platform 集群一起使用的域或子域。
    3 对于<hosted_zone_id>,请指定您获得的负载均衡器的公共托管区域 ID。
    4 对于<external_ip>,请指定 Ingress Operator 负载均衡器的外部 IP 地址的值。确保在此参数值中包含尾随句点 (.)。
  6. 将记录添加到您的公共区域

    $ aws route53 change-resource-record-sets --hosted-zone-id "<public_hosted_zone_id>"" --change-batch '{ (1)
    >   "Changes": [
    >     {
    >       "Action": "CREATE",
    >       "ResourceRecordSet": {
    >         "Name": "\\052.apps.<cluster_domain>", (2)
    >         "Type": "A",
    >         "AliasTarget":{
    >           "HostedZoneId": "<hosted_zone_id>", (3)
    >           "DNSName": "<external_ip>.", (4)
    >           "EvaluateTargetHealth": false
    >         }
    >       }
    >     }
    >   ]
    > }'
    1 对于<public_hosted_zone_id>,请指定您域的公共托管区域。
    2 对于<cluster_domain>,请指定您与 OpenShift Container Platform 集群一起使用的域或子域。
    3 对于<hosted_zone_id>,请指定您获得的负载均衡器的公共托管区域 ID。
    4 对于<external_ip>,请指定 Ingress Operator 负载均衡器的外部 IP 地址的值。确保在此参数值中包含尾随句点 (.)。

完成用户预配基础设施上的 AWS 安装

在Amazon Web Service (AWS) 用户自备基础设施上启动OpenShift Container Platform安装后,监控部署直至完成。

先决条件
  • 您已删除用户自备AWS基础设施上OpenShift Container Platform集群的引导节点。

  • 您已安装 `oc` CLI。

步骤
  • 从包含安装程序的目录中,完成集群安装。

    $ ./openshift-install --dir <installation_directory> wait-for install-complete (1)
    1 对于<installation_directory>,请指定您存储安装文件的目录的路径。
    示例输出
    INFO Waiting up to 40m0s for the cluster at https://api.mycluster.example.com:6443 to initialize...
    INFO Waiting up to 10m0s for the openshift-console route to be created...
    INFO Install complete!
    INFO To access the cluster as the system:admin user when using 'oc', run 'export KUBECONFIG=/home/myuser/install_dir/auth/kubeconfig'
    INFO Access the OpenShift web-console here: https://console-openshift-console.apps.mycluster.example.com
    INFO Login to the console with user: "kubeadmin", and password: "password"
    INFO Time elapsed: 1s
    • 安装程序生成的Ignition配置文件包含24小时后过期的证书,届时会自动续期。如果集群在证书续期前关闭,并在24小时后重新启动,集群会自动恢复已过期的证书。例外情况是,您必须手动批准待处理的node-bootstrapper证书签名请求 (CSR) 以恢复kubelet证书。有关更多信息,请参阅从过期的控制平面证书中恢复文档。

    • 建议您在生成 Ignition 配置文件后 12 小时内使用它们,因为 24 小时证书会在集群安装后 16 到 22 小时之间轮换。通过在 12 小时内使用 Ignition 配置文件,如果证书更新在安装过程中运行,您可以避免安装失败。

使用Web控制台登录集群

OpenShift Container Platform安装完成后,默认情况下存在kubeadmin用户。您可以使用OpenShift Container Platform Web控制台以kubeadmin用户身份登录到您的集群。

先决条件
  • 您可以访问安装主机。

  • 您已完成集群安装,并且所有集群操作符都可用。

步骤
  1. 从安装主机上的kubeadmin-password文件中获取kubeadmin用户的密码。

    $ cat <installation_directory>/auth/kubeadmin-password

    或者,您可以从安装主机上的<installation_directory>/.openshift_install.log日志文件中获取kubeadmin密码。

  2. 列出OpenShift Container Platform Web控制台路由。

    $ oc get routes -n openshift-console | grep 'console-openshift'

    或者,您可以从安装主机上的<installation_directory>/.openshift_install.log日志文件中获取OpenShift Container Platform路由。

    示例输出
    console     console-openshift-console.apps.<cluster_name>.<base_domain>            console     https   reencrypt/Redirect   None
  3. 在Web浏览器中导航到前面命令输出中详细说明的路由,并以kubeadmin用户身份登录。

其他资源
  • 有关访问和了解OpenShift Container Platform Web控制台的更多详细信息,请参阅访问Web控制台

其他资源

  • 有关AWS CloudFormation堆栈的更多信息,请参阅AWS文档中的使用堆栈

后续步骤