×

在OpenShift Container Platform 4.17版本中,您可以使用您提供的基础设施和安装发行版内容的内部镜像在Amazon Web Services (AWS)上安装集群。

虽然您可以使用镜像的安装发行版内容安装OpenShift Container Platform集群,但您的集群仍然需要互联网访问才能使用AWS API。

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

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

先决条件

关于受限网络中的安装

在 OpenShift Container Platform 4.17 中,您可以执行无需主动连接到互联网即可获取软件组件的安装。受限网络安装可以使用安装程序预配的基础设施或用户预配的基础设施完成,具体取决于您要安装集群的云平台。

如果您选择在云平台上执行受限网络安装,您仍然需要访问其云 API。某些云功能(例如 Amazon Web Service 的 Route 53 DNS 和 IAM 服务)需要互联网访问。根据您的网络,在裸机硬件、Nutanix 或 VMware vSphere 上安装可能需要较少的互联网访问。

要完成受限网络安装,您必须创建一个镜像 OpenShift 镜像注册表内容并包含安装介质的注册表。您可以在可以访问互联网和封闭网络的镜像主机上创建此注册表,或者使用符合您限制的其他方法。

由于用户预配安装的配置复杂,建议您在尝试使用用户预配的基础设施进行受限网络安装之前,先完成标准的用户预配基础设施安装。完成此测试安装可能会更容易隔离和排除在受限网络中安装期间可能出现的任何问题。

其他限制

受限网络中的集群具有以下其他限制。

  • ClusterVersion状态包含无法检索可用更新错误。

  • 默认情况下,您无法使用开发者目录的内容,因为您无法访问所需的镜像流标签。

为 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 并保持数据完整。使用此方法,您无需再次拉取所有容器,也不需要在更新系统时复制大量的日志文件。

由于/var必须在 Red Hat Enterprise Linux CoreOS (RHCOS) 的全新安装之前到位,因此以下过程通过创建一个在 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(兆字节)。根文件系统会自动调整大小以填充所有可用空间,直至指定的偏移量。如果未指定值,或者指定的值小于建议的最小值,则生成的根文件系统将太小,并且将来重新安装 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 安装程序和集群的拉取密钥。对于受限网络安装,这些文件位于您的镜像主机上。

  • 您已检查您是否正在将集群部署到具有 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 和秘密访问密钥存储在安装主机当前用户主目录下的 ~/.aws/credentials 文件中。如果文件中不存在导出配置文件的凭据,安装程序会提示您输入凭据。您提供给安装程序的任何凭据都将存储在此文件中。

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

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

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

      7. 粘贴 来自 Red Hat OpenShift Cluster Manager 的 pull secret

  2. 编辑 install-config.yaml 文件,以提供受限网络安装所需的附加信息。

    1. 更新 pullSecret 值,使其包含注册表的身份验证信息。

      pullSecret: '{"auths":{"<local_registry>": {"auth": "<credentials>","email": "[email protected]"}}}'

      对于 <local_registry>,指定镜像注册表用于提供内容的注册表域名,以及可选的端口,例如 registry.example.comregistry.example.com:5000。对于 <credentials>,指定镜像注册表的 Base64 编码用户名和密码。

    2. 添加 additionalTrustBundle 参数和值。该值必须是您用于镜像注册表的证书文件的内容。证书文件可以是现有的受信任证书颁发机构,也可以是您为镜像注册表生成的自签名证书。

      additionalTrustBundle: |
        -----BEGIN CERTIFICATE-----
        ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
        -----END CERTIFICATE-----
    3. 添加镜像内容资源。

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

      使用命令输出中的 imageContentSources 部分来镜像存储库或您从带入受限网络的媒体中镜像内容时使用的值。

    4. 可选:将发布策略设置为 Internal

      publish: Internal

      通过设置此选项,您可以创建一个内部 Ingress Controller 和一个私有负载均衡器。

  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) 信任捆绑包合并,此 config map 在 Proxy 对象的 trustedCA 字段中引用。除非代理的身份证书由 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 对于 <安装目录>,请指定包含您创建的 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. 检查 <安装目录>/manifests/cluster-scheduler-02-config.yml Kubernetes 清单文件中 mastersSchedulable 参数是否设置为 false。此设置可防止将 Pod 调度到控制平面机器上。

    1. 打开 <安装目录>/manifests/cluster-scheduler-02-config.yml 文件。

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

    3. 保存并退出文件。

  6. 可选:如果您不希望 Ingress Operator 代表您创建 DNS 记录,请从 <安装目录>/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 对于 <安装目录>,请指定相同的安装目录。

    在安装目录中为引导程序、控制平面和计算节点创建 Ignition 配置文件。kubeadmin-passwordkubeconfig 文件创建在 ./<安装目录>/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 对于 <安装目录>,请指定您存储安装文件的目录的路径。
    示例输出
    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 <名称> 是 CloudFormation 堆栈的名称,例如 cluster-vpc。如果您删除集群,则需要此堆栈的名称。
    2 <模板> 是您保存的 CloudFormation 模板 YAML 文件的相对路径和名称。
    3 <参数> 是 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 <模板> 是您保存的 CloudFormation 模板 YAML 文件的相对路径和名称。
    3 <参数> 是 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 指定您为以x.x.x.x/16-24形式定义的 VPC 使用的 CIDR 块参数。
    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 <模板> 是您保存的 CloudFormation 模板 YAML 文件的相对路径和名称。
    3 <参数> 是 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 程序中,使用官方的stream-metadata-go库,网址为https://github.com/coreos/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 提供适用于您可以为 OpenShift Container Platform 节点手动指定的各种 AWS 区域和实例架构的 Red Hat Enterprise Linux CoreOS (RHCOS) AMI。

通过导入您自己的 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

在 AWS 中创建引导节点

在 OpenShift Container Platform 集群初始化期间使用时,必须在 Amazon Web Services (AWS) 中创建引导节点。方法如下:

  • 提供一个位置,用于将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 对于 <安装目录>,请指定您存储安装文件的目录的路径。
  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 资源所属的 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.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 <模板> 是您保存的 CloudFormation 模板 YAML 文件的相对路径和名称。
    3 <参数> 是 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 <模板> 是您保存的 CloudFormation 模板 YAML 文件的相对路径和名称。
    3 <参数> 是 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)中创建工作节点。

您可以使用提供的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 <模板> 是您保存的 CloudFormation 模板 YAML 文件的相对路径和名称。
    3 <参数> 是 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 对于 <安装目录>,请指定您存储安装文件的目录的路径。
    2 要查看不同的安装详细信息,请指定 warndebugerror 代替 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 控制平面已初始化。

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

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

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

批准您的机器的证书签名请求

将机器添加到集群时,会为添加的每台机器生成两个挂起的证书签名请求 (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,并确保您看到为添加到集群的每台机器的客户端请求显示 PendingApproved 状态

    $ 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,以便所有 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。

禁用默认的 OperatorHub 目录源

在 OpenShift Container Platform 安装期间,默认情况下,为 OperatorHub 配置了由 Red Hat 和社区项目提供的 Operator 目录内容。在受限制的网络环境中,您必须以集群管理员身份禁用默认目录。

步骤
  • 通过将 disableAllDefaultSources: true 添加到 OperatorHub 对象来禁用默认目录的源

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

或者,您可以使用 Web 控制台管理目录源。在**管理** → **集群设置** → **配置** → **OperatorHub** 页面中,单击**源**选项卡,您可以在其中创建、更新、删除、禁用和启用各个源。

镜像注册表存储配置

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

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

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

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

安装期间,您的云凭据足以创建 Amazon S3 存储桶,并且 Registry Operator 将自动配置存储。

如果 Registry Operator 无法创建 S3 存储桶并自动配置存储,您可以使用以下过程创建 S3 存储桶并配置存储。

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

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

    • REGISTRY_STORAGE_S3_ACCESSKEY

    • REGISTRY_STORAGE_S3_SECRETKEY

步骤

如果注册表操作员无法创建 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 存储桶的公共访问

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

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

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

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

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

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

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

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

删除引导资源

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

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

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

    • 使用 AWS CLI 删除堆栈

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

创建 Ingress DNS 记录

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

先决条件
  • 您在 Amazon Web Services (AWS) 上部署了一个 OpenShift Container Platform 集群,该集群使用您预配的基础架构。

  • 您已安装 OpenShift CLI (oc)。

  • 您已安装 jq 包。

  • 您已下载 AWS CLI 并将其安装在您的计算机上。请参阅使用捆绑安装程序安装 AWS CLI(Linux、macOS 或 Unix)

步骤
  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。

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

    $ ./openshift-install --dir <installation_directory> wait-for install-complete (1)
    1 对于 <安装目录>,请指定您存储安装文件的目录的路径。
    示例输出
    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 配置文件,如果证书更新在安装期间运行,您可以避免安装失败。

  2. 集群注册页面上注册您的集群。

使用 CLI 登录集群

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

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

  • 您已安装oc CLI。

步骤
  1. 导出kubeadmin凭据

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

    $ oc whoami
    示例输出
    system:admin

使用 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 文档中的堆栈操作

后续步骤