4.3. 使用 CloudFormation 模板在 AWS 中用户置备的基础架构上安装集群
在 OpenShift Container Platform 版本 4.16 中,您可以使用您提供的基础架构在 Amazon Web Services (AWS) 上安装集群。
创建此基础架构的一种方法是使用提供的 CloudFormation 模板。您可以修改模板来自定义基础架构,或使用其包含的信息来按照公司策略创建 AWS 对象。
进行用户置备的基础架构安装的步骤仅作为示例。使用您提供的基础架构安装集群需要了解云供应商和 OpenShift Container Platform 安装过程。提供的几个 CloudFormation 模板可帮助完成这些步骤,或者帮助您自行建模。您也可以自由选择通过其他方法创建所需的资源;模板仅作示例之用。
4.3.1. 先决条件
- 您可以参阅有关 OpenShift Container Platform 安装和更新 流程的详细信息。
- 您可以阅读选择集群安装方法并为用户准备它的文档。
已将 AWS 帐户配置为托管集群。
重要如果您的计算机上存储有 AWS 配置集,则不要在使用多因素验证设备的同时使用您生成的临时会话令牌。集群将继续使用您当前的 AWS 凭证为集群的整个生命周期创建 AWS 资源,因此您必须使用基于密钥的长期凭证。要生成适当的密钥,请参阅 AWS 文档中的管理 IAM 用户的访问密钥。您可在运行安装程序时提供密钥。
- 已准备好用户置备的基础架构。
- 您下载了 AWS CLI 并安装到您的计算机上。请参阅 AWS 文档中的使用捆绑安装程序(Linux、macOS 或 UNIX)安装 AWS CLI。
如果使用防火墙,将其配置为允许集群需要访问的站点。
注意如果要配置代理,请务必查看此站点列表。
-
如果环境中无法访问云身份和访问管理(IAM)API,或者不想将管理员级别的凭证 secret 存储在
kube-system
命名空间中,您可以 手动创建和维护 IAM 凭证。
4.3.2. 创建用于 AWS 的安装文件
要使用用户置备的基础架构在 Amazon Web Services (AWS) 上安装 OpenShift Container Platform,您必须生成并修改安装程序部署集群所需的文件,以便集群只创建要使用的机器。您要生成并自定义 install-config.yaml
文件、Kubernetes 清单和 Ignition 配置文件。您还可以选择在安装准备阶段首先设置独立 var
分区。
4.3.2.1. 可选:创建独立 /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 配置文件,如本节所述。
流程
创建存放 OpenShift Container Platform 安装文件的目录:
$ mkdir $HOME/clusterconfig
运行
openshift-install
,以在manifest
和openshift
子目录中创建一组文件。在系统提示时回答系统问题:$ 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
可选:确认安装程序在
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 ...
创建用于配置额外分区的 Butane 配置。例如,将文件命名为
$HOME/clusterconfig/98-var-partition.bu
,将磁盘设备名称改为worker
系统上存储设备的名称,并根据情况设置存储大小。这个示例将/var
目录放在一个单独的分区中:variant: openshift version: 4.16.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
注意当创建单独的
/var
分区时,如果不同的实例类型没有相同的设备名称,则无法为 worker 节点使用不同的实例类型。从 Butane 配置创建一个清单,并将它保存到
clusterconfig/openshift
目录中。例如,运行以下命令:$ butane $HOME/clusterconfig/98-var-partition.bu -o $HOME/clusterconfig/openshift/98-var-partition.yaml
再次运行
openshift-install
,从manifest
和openshift
子目录中的一组文件创建 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)系统。
4.3.2.2. 创建安装配置文件
生成并自定义安装程序部署集群所需的安装配置文件。
先决条件
- 已获取 OpenShift Container Platform 安装程序用于用户置备的基础架构和集群的 pull secret。
-
使用红帽发布的附带 Red Hat Enterprise Linux CoreOS (RHCOS) AMI 检查您是否将集群部署到 AWS 区域。如果要部署到需要自定义 AMI 的 AWS 区域,如 AWS GovCloud 区域,您必须手动创建
install-config.yaml
文件。
流程
创建
install-config.yaml
文件。进入包含安装程序的目录并运行以下命令:
$ ./openshift-install create install-config --dir <installation_directory> 1
- 1
- 对于
<installation_directory>
,请指定要存储安装程序创建的文件的目录名称。
重要指定一个空目录。有些安装资产,如 bootstrap X.509 证书的过期间隔较短,因此不得重复使用安装目录。如果要重复使用另一个集群安装中的单个文件,您可以将它们复制到您的目录中。但是,安装资产的文件名可能会在发行版本间有所变化。从以前的 OpenShift Container Platform 版本中复制安装文件时请小心。
在提示符处,提供云的配置详情:
可选: 选择用于访问集群机器的 SSH 密钥。
注意对于您要在其上执行安装调试或灾难恢复的生产环境 OpenShift Container Platform 集群,请指定
ssh-agent
进程使用的 SSH 密钥。- 选择 aws 作为目标平台。
如果计算机上没有保存 AWS 配置集,请为您配置用于运行安装程序的用户输入 AWS 访问密钥 ID 和 secret 访问密钥。
注意AWS 访问密钥 ID 和 secret 访问密钥存储在安装主机上当前用户主目录中的
~/.aws/credentials
中。如果文件中不存在导出的配置集凭证,安装程序会提示您输入凭证。您向安装程序提供的所有凭证都存储在文件中。- 选择要将集群部署到的 AWS Region。
- 选择您为集群配置的 Route 53 服务的基域。
- 为集群输入描述性名称。
- 粘贴 Red Hat OpenShift Cluster Manager 中的 pull secret。
-
如果要安装三节点集群,请通过将
compute.replicas
参数设置为0
来修改install-config.yaml
文件。这样可确保集群的 control plane 可以调度。如需更多信息,请参阅"在 AWS 上安装三节点集群"。 可选:备份
install-config.yaml
文件。重要install-config.yaml
文件会在安装过程中消耗掉。如果要重复使用此文件,必须现在备份。
其他资源
- 如需有关 AWS 配置集和凭证配置的更多信息,请参阅 AWS 文档中的配置和凭证文件设置。
4.3.2.3. 在安装过程中配置集群范围代理
生产环境可能会拒绝直接访问互联网,而是提供 HTTP 或 HTTPS 代理。您可以通过在 install-config.yaml
文件中配置代理设置,将新的 OpenShift Container Platform 集群配置为使用代理。
先决条件
-
您有一个现有的
install-config.yaml
文件。 您检查了集群需要访问的站点,并确定它们中的任何站点是否需要绕过代理。默认情况下,所有集群出口流量都经过代理,包括对托管云供应商 API 的调用。如果需要,您将在
Proxy 对象的
spec.noProxy
字段中添加站点来绕过代理。注意Proxy
对象status.noProxy
字段使用安装配置中的networking.machineNetwork[].cidr
、networking.clusterNetwork[].cidr
和networking.serviceNetwork[]
字段的值填充。对于在 Amazon Web Services(AWS)、Google Cloud Platform(GCP)、Microsoft Azure 和 Red Hat OpenStack Platform(RHOSP)上安装,
Proxy
对象status.noProxy
字段也会使用实例元数据端点填充(169.254.169.254
)。
流程
编辑
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
。使用*
绕过所有目的地的代理。如果您已将 AmazonEC2
、Elastic Load Balancing
和S3
VPC 端点添加到 VPC 中,您必须将这些端点添加到noProxy
字段。 - 4
- 如果提供,安装程序会在
openshift-config
命名空间中生成名为user-ca-bundle
的配置映射,其包含代理 HTTPS 连接所需的一个或多个额外 CA 证书。然后,Cluster Network Operator 会创建trusted-ca-bundle
配置映射,将这些内容与 Red Hat Enterprise Linux CoreOS(RHCOS)信任捆绑包合并,Proxy
对象的trustedCA
字段中也会引用此配置映射。additionalTrustBundle
字段是必需的,除非代理的身份证书由来自 RHCOS 信任捆绑包的颁发机构签名。 - 5
- 可选:决定
Proxy
对象的配置以引用trustedCA
字段中user-ca-bundle
配置映射的策略。允许的值是Proxyonly
和Always
。仅在配置了http/https
代理时,使用Proxyonly
引用user-ca-bundle
配置映射。使用Always
始终引用user-ca-bundle
配置映射。默认值为Proxyonly
。
注意安装程序不支持代理的
readinessEndpoints
字段。注意如果安装程序超时,重启并使用安装程序的
wait-for
命令完成部署。例如:$ ./openshift-install wait-for install-complete --log-level debug
- 保存该文件并在安装 OpenShift Container Platform 时引用。
安装程序会创建一个名为 cluster 的集群范围代理,该代理 使用
提供的 install-config.yaml
文件中的代理设置。如果没有提供代理设置,仍然会创建一个 cluster
Proxy
对象,但它会有一个空 spec
。
只支持名为 cluster
的 Proxy
对象,且无法创建额外的代理。
4.3.2.4. 创建 Kubernetes 清单和 Ignition 配置文件
由于您必须修改一些集群定义文件并手动启动集群机器,因此您必须生成 Kubernetes 清单和 Ignition 配置文件来配置机器。
安装配置文件转换为 Kubernetes 清单。清单嵌套到 Ignition 配置文件中,稍后用于配置集群机器。
-
OpenShift Container Platform 安装程序生成的 Ignition 配置文件包含 24 小时后过期的证书,然后在该时进行续订。如果在更新证书前关闭集群,且集群在 24 小时后重启,集群会自动恢复过期的证书。一个例外是,您必须手动批准待处理的
node-bootstrapper
证书签名请求(CSR)来恢复 kubelet 证书。如需更多信息,请参阅从过期的 control plane 证书 中恢复的文档。 - 建议您在 Ignition 配置文件生成后的 12 小时内使用它们,因为 24 小时的证书会在集群安装后的 16 小时到 22 小时间进行轮转。通过在 12 小时内使用 Ignition 配置文件,您可以避免在安装过程中因为执行了证书更新而导致安装失败的问题。
先决条件
- 已获得 OpenShift Container Platform 安装程序。
-
已创建
install-config.yaml
安装配置文件。
流程
进入包含 OpenShift Container Platform 安装程序的目录,并为集群生成 Kubernetes 清单:
$ ./openshift-install create manifests --dir <installation_directory> 1
- 1
- 对于
<installation_directory>
,请指定包含您创建的install-config.yaml
文件的安装目录。
删除定义 control plane 机器的 Kubernetes 清单文件:
$ rm -f <installation_directory>/openshift/99_openshift-cluster-api_master-machines-*.yaml
通过删除这些文件,您可以防止集群自动生成 control plane 机器。
删除定义 control plane 机器集的 Kubernetes 清单文件:
$ rm -f <installation_directory>/openshift/99_openshift-machine-api_master-control-plane-machine-set.yaml
删除定义 worker 机器的 Kubernetes 清单文件:
$ rm -f <installation_directory>/openshift/99_openshift-cluster-api_worker-machineset-*.yaml
重要如果在用户置备的基础架构上安装集群时禁用了
MachineAPI
功能,则必须删除定义 worker 机器的 Kubernetes 清单文件。否则,集群将无法安装。由于您要自行创建和管理 worker 机器,因此不需要初始化这些机器。
警告如果您要安装一个三节点集群,请跳过以下步骤,以便可以调度 control plane 节点。
重要当您将 control plane 节点从默认的不可调度配置为可以调度时,需要额外的订阅。这是因为 control plane 节点变为计算节点。
检查
<installation_directory>/manifests/cluster-scheduler-02-config.yml Kubernetes 清单文件中的
mastersSchedulable
参数是否已设置为false
。此设置可防止在 control plane 机器上调度 pod:-
打开
<installation_directory>/manifests/cluster-scheduler-02-config.yml
文件。 -
找到
mastersSchedulable
参数,并确保它被设置为false
。 - 保存并退出 文件。
-
打开
可选:如果您不希望 Ingress Operator 代表您创建 DNS 记录,请删除
<installation_directory>/manifests/cluster-dns-02-config.yml
DNS 配置文件中的privateZone
和 publicZone
部分: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: 2 id: example.openshift.com status: {}
如果这样做,您必须在后续步骤中手动添加入口 DNS 记录。
要创建 Ignition 配置文件,请从包含安装程序的目录运行以下命令:
$ ./openshift-install create ignition-configs --dir <installation_directory> 1
- 1
- 对于
<installation_directory>
,请指定相同的安装目录。
为安装目录中的 bootstrap、control plane 和计算节点创建 Ignition 配置文件。
kubeadmin-password
和kubeconfig
文件在./<installation_directory>/auth
目录中创建:. ├── auth │ ├── kubeadmin-password │ └── kubeconfig ├── bootstrap.ign ├── master.ign ├── metadata.json └── worker.ign
4.3.3. 提取基础架构名称
Ignition 配置文件包含一个唯一集群标识符,您可以使用它在 Amazon Web Services (AWS) 中唯一地标识您的集群。基础架构名称还用于在 OpenShift Container Platform 安装过程中定位适当的 AWS 资源。提供的 CloudFormation 模板包含对此基础架构名称的引用,因此您必须提取它。
先决条件
- 已获取 OpenShift Container Platform 安装程序和集群的 pull secret。
- 已为集群生成 Ignition 配置文件。
-
已安装
jq
软件包。
4.3.4. 在 AWS 中创建 VPC
您必须在 Amazon Web Services(AWS)中创建 Virtual Private Cloud(VPC),供您的 OpenShift Container Platform 集群使用。您可以自定义 VPC 来满足您的要求,包括 VPN 和路由表。
您可以使用提供的 CloudFormation 模板和自定义参数文件创建代表 VPC 的 AWS 资源堆栈。
如果不使用提供的 CloudFormation 模板来创建 AWS 基础架构,您必须检查提供的信息并手动创建基础架构。如果集群没有正确初始化,您可能需要联系红帽支持并提供您的安装日志。
先决条件
- 已配置了一个 AWS 帐户。
-
您可以通过运行
aws configure
,将 AWS 密钥和区域添加到本地 AWS 配置集中。 - 已为集群生成 Ignition 配置文件。
流程
创建一个 JSON 文件,其包含模板所需的参数值:
[ { "ParameterKey": "VpcCidr", 1 "ParameterValue": "10.0.0.0/16" 2 }, { "ParameterKey": "AvailabilityZoneCount", 3 "ParameterValue": "1" 4 }, { "ParameterKey": "SubnetBits", 5 "ParameterValue": "12" 6 } ]
- 复制本主题的 VPC 的 CloudFormation 模板部分中的模板,并将它以 YAML 文件形式保存到计算机上。此模板描述了集群所需的 VPC。
启动 CloudFormation 模板,以创建代表 VPC 的 AWS 资源堆栈:
重要您必须在一行内输入命令。
$ aws cloudformation create-stack --stack-name <name> 1 --template-body file://<template>.yaml 2 --parameters file://<parameters>.json 3
输出示例
arn:aws:cloudformation:us-east-1:269333783861:stack/cluster-vpc/dbedae40-2fd3-11eb-820e-12a48460849f
确认模板组件已存在:
$ aws cloudformation describe-stacks --stack-name <name>
在
StackStatus
显示CREATE_COMPLETE
后,输出会显示以下参数的值。您必须将这些参数值提供给您在创建集群时要运行的其他 CloudFormation 模板:VpcId
您的 VPC ID。
PublicSubnetIds
新公共子网的 ID。
PrivateSubnetIds
新专用子网的 ID。
4.3.4.1. VPC 的 CloudFormation 模板
您可以使用以下 CloudFormation 模板来部署 OpenShift Container Platform 集群所需的 VPC。
例 4.18. 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 CloudFormation 控制台来查看您创建的 CloudFormation 堆栈的详情。
4.3.5. 在 AWS 中创建网络和负载均衡组件
您必须在 OpenShift Container Platform 集群可以使用的 Amazon Web Services(AWS)中配置网络、经典或网络负载均衡。
您可以使用提供的 CloudFormation 模板和自定义参数文件来创建 AWS 资源堆栈。堆栈代表 OpenShift Container Platform 集群所需的网络和负载均衡组件。该模板还创建一个托管区和子网标签。
您可以在单一虚拟私有云(VPC)内多次运行该模板。
如果不使用提供的 CloudFormation 模板来创建 AWS 基础架构,您必须检查提供的信息并手动创建基础架构。如果集群没有正确初始化,您可能需要联系红帽支持并提供您的安装日志。
先决条件
- 已配置了一个 AWS 帐户。
-
您可以通过运行
aws configure
,将 AWS 密钥和区域添加到本地 AWS 配置集中。 - 已为集群生成 Ignition 配置文件。
- 您在 AWS 中创建并配置了 VPC 及相关子网。
流程
获取您在
install-config.yaml
文件中为集群指定的 Route 53 基域的托管区 ID。您可以运行以下命令来获取托管区的详细信息:$ aws route53 list-hosted-zones-by-name --dns-name <route53_domain> 1
- 1
- 对于
<route53_domain>
,请指定您为集群生成install-config.yaml
文件时所用的 Route53 基域。
输出示例
mycluster.example.com. False 100 HOSTEDZONES 65F8F38E-2268-B835-E15C-AB55336FCBFA /hostedzone/Z21IXYZABCZ2A4 mycluster.example.com. 10
在示例输出中,托管区 ID 为
Z21IXYZABCZ2A4
。创建一个 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
值。
复制本主题的网络和负载均衡器的 CloudFormation 模板部分中的模板,并将它以 YAML 文件形式保存到计算机上。此模板描述了集群所需的网络和负载均衡对象。
重要如果要将集群部署到 AWS 政府或 secret 区域,您必须更新 CloudFormation 模板中的
InternalApiServerRecord
,以使用CNAME
记录。AWS 政府区不支持ALIAS
类型的记录。启动 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
输出示例
arn:aws:cloudformation:us-east-1:269333783861:stack/cluster-dns/cd3e5de0-2fd4-11eb-5cf0-12be5c33a183
确认模板组件已存在:
$ aws cloudformation describe-stacks --stack-name <name>
在
StackStatus
显示CREATE_COMPLETE
后,输出会显示以下参数的值。您必须将这些参数值提供给您在创建集群时要运行的其他 CloudFormation 模板:PrivateHostedZoneId
专用 DNS 的托管区 ID。
ExternalApiLoadBalancerName
外部 API 负载均衡器的完整名称。
InternalApiLoadBalancerName
内部 API 负载均衡器的完整名称。
ApiServerDnsName
API 服务器的完整主机名。
RegisterNlbIpTargetsLambda
有助于为这些负载均衡器注册/撤销注册 IP 目标的 Lambda ARN。
ExternalApiTargetGroupArn
外部 API 目标组的 ARN。
InternalApiTargetGroupArn
内部 API 目标组的 ARN。
InternalServiceTargetGroupArn
内部服务目标组群的 ARN。
4.3.5.1. 网络和负载均衡器的 CloudFormation 模板
您可以使用以下 CloudFormation 模板来部署 OpenShift Container Platform 集群所需的网络对象和负载均衡器。
例 4.19. 网络和负载均衡器的 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 政府或 secret 区域,您必须更新 InternalApiServerRecord
以使用 CNAME
记录。AWS 政府区不支持 ALIAS
类型的记录。例如:
Type: CNAME TTL: 10 ResourceRecords: - !GetAtt IntApiElb.DNSName
其他资源
- 您可以通过导航 AWS CloudFormation 控制台来查看您创建的 CloudFormation 堆栈的详情。
- 您可以通过导航到 AWS Route 53 控制台来查看托管区的详情。
- 有关列出公共托管区的更多信息,请参阅 AWS 文档中的列出公共托管区。
4.3.6. 在 AWS 中创建安全组和角色
您必须在 Amazon Web Services (AWS) 中创建安全组和角色,供您的 OpenShift Container Platform 集群使用。
您可以使用提供的 CloudFormation 模板和自定义参数文件来创建 AWS 资源堆栈。堆栈代表 OpenShift Container Platform 集群所需的安全组和角色。
如果不使用提供的 CloudFormation 模板来创建 AWS 基础架构,您必须检查提供的信息并手动创建基础架构。如果集群没有正确初始化,您可能需要联系红帽支持并提供您的安装日志。
先决条件
- 已配置了一个 AWS 帐户。
-
您可以通过运行
aws configure
,将 AWS 密钥和区域添加到本地 AWS 配置集中。 - 已为集群生成 Ignition 配置文件。
- 您在 AWS 中创建并配置了 VPC 及相关子网。
流程
创建一个 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 } ]
- 复制本主题的安全对象的 CloudFormation 模板部分中的模板,并将它以 YAML 文件形式保存到计算机上。此模板描述了集群所需的安全组和角色。
启动 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
输出示例
arn:aws:cloudformation:us-east-1:269333783861:stack/cluster-sec/03bd4210-2ed7-11eb-6d7a-13fc0b61e9db
确认模板组件已存在:
$ aws cloudformation describe-stacks --stack-name <name>
在
StackStatus
显示CREATE_COMPLETE
后,输出会显示以下参数的值。您必须将这些参数值提供给您在创建集群时要运行的其他 CloudFormation 模板:MasterSecurityGroupId
Master 安全组 ID
WorkerSecurityGroupId
worker 安全组 ID
MasterInstanceProfile
Master IAM 实例配置集
WorkerInstanceProfile
worker IAM 实例配置集
4.3.6.1. 安全对象的 CloudFormation 模板
您可以使用以下 CloudFormation 模板来部署 OpenShift Container Platform 集群所需的安全对象。
例 4.20. 安全对象的 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
其他资源
- 您可以通过导航 AWS CloudFormation 控制台来查看您创建的 CloudFormation 堆栈的详情。
4.3.7. 使用流元数据访问 RHCOS AMI
在 OpenShift Container Platform 中,流元数据以 JSON 格式提供与 RHCOS 相关的标准化元数据,并将元数据注入集群中。流元数据是一种稳定的格式,支持多种架构,旨在自我记录以维护自动化。
您可以使用 openshift-install
的 coreos print-stream-json
子命令访问流元数据格式的引导镜像的信息。此命令提供了一种以可脚本、机器可读格式打印流元数据的方法。
对于用户置备的安装,openshift-install
二进制文件包含对经过测试用于 OpenShift Container Platform 的 RHCOS 引导镜像版本的引用,如 AWS AMI。
流程
要解析流元数据,请使用以下方法之一:
-
在 Go 程序中使用位于 https://github.com/coreos/stream-metadata-go 的正式
stream-metadata-go
库。您还可以查看库中的示例代码。 - 在 Python 或 Ruby 等其他编程语言中使用您首选编程语言的 JSON 库。
在处理 JSON 数据的命令行工具中,如
jq
:为 AWS 区域输出当前的
x86_64
或aarch64
AMI,如us-west-1
:对于 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 必须与集群属于同一区域。
4.3.8. AWS 基础架构的 RHCOS AMI
红帽提供了对可手动为 OpenShift Container Platform 节点指定的各种 AWS 区域和实例架构有效的 Red Hat Enterprise Linux CoreOS(RHCOS)AMI。
通过导入您自己的 AMI,您还可以安装到没有公布的 RHCOS AMI 的区域。
AWS 区 | AWS AMI |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AWS 区 | AWS AMI |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4.3.8.1. 没有公布的 RHCOS AMI 的 AWS 区域
您可以将 OpenShift Container Platform 集群部署到 Amazon Web Services(AWS)区域,而无需对 Red Hat Enterprise Linux CoreOS(RHCOS)Amazon Machine Image(AMI)或 AWS 软件开发 kit(SDK)的原生支持。如果 AWS 区域没有可用的已公布的 AMI,您可以在安装集群前上传自定义 AMI。
如果您要部署到 AWS SDK 不支持的区域,且您没有指定自定义 AMI,安装程序会自动将 us-east-1
AMI 复制到用户帐户。然后,安装程序使用默认或用户指定的密钥管理服务(KMS)密钥创建带有加密 EBS 卷的 control plane 机器。这允许 AMI 跟踪与公布的 RHCOS AMI 相同的进程工作流。
在集群创建过程中,无法从终端中选择没有原生支持 RHCOS AMI 的区域,因为它没有发布。但是,您可以通过在 install-config.yaml
文件中配置自定义 AMI 来安装到这个区域。
4.3.8.2. 在 AWS 中上传自定义 RHCOS AMI
如果要部署到自定义 Amazon Web Services(AWS)区域,您必须上传属于该区域的自定义 Red Hat Enterprise Linux CoreOS(RHCOS)Amazon Machine Image(AMI)。
先决条件
- 已配置了一个 AWS 帐户。
- 已使用所需的 IAM 服务角色创建 Amazon S3 存储桶。
- 将 RHCOS VMDK 文件上传到 Amazon S3。RHCOS VMDK 文件必须是小于或等于您要安装的 OpenShift Container Platform 版本的最高版本。
- 您下载了 AWS CLI 并安装到您的计算机上。请参阅使用捆绑安装程序安装 AWS CLI。
流程
将 AWS 配置集导出为环境变量:
$ export AWS_PROFILE=<aws_profile> 1
将与自定义 AMI 关联的区域导出为环境变量:
$ export AWS_DEFAULT_REGION=<aws_region> 1
将上传至 Amazon S3 的 RHCOS 版本导出为环境变量:
$ export RHCOS_VERSION=<version> 1
将 Amazon S3 存储桶名称导出为环境变量:
$ export VMIMPORT_BUCKET_NAME=<s3_bucket_name>
创建
containers.json
文件并定义 RHCOS VMDK 文件:$ cat <<EOF > containers.json { "Description": "rhcos-${RHCOS_VERSION}-x86_64-aws.x86_64", "Format": "vmdk", "UserBucket": { "S3Bucket": "${VMIMPORT_BUCKET_NAME}", "S3Key": "rhcos-${RHCOS_VERSION}-x86_64-aws.x86_64.vmdk" } } EOF
将 RHCOS 磁盘导入为 Amazon EBS 快照:
$ aws ec2 import-snapshot --region ${AWS_DEFAULT_REGION} \ --description "<description>" \ 1 --disk-container "file://<file_path>/containers.json" 2
检查镜像导入的状态:
$ watch -n 5 aws ec2 describe-import-snapshot-tasks --region ${AWS_DEFAULT_REGION}
输出示例
{ "ImportSnapshotTasks": [ { "Description": "rhcos-4.7.0-x86_64-aws.x86_64", "ImportTaskId": "import-snap-fh6i8uil", "SnapshotTaskDetail": { "Description": "rhcos-4.7.0-x86_64-aws.x86_64", "DiskImageSize": 819056640.0, "Format": "VMDK", "SnapshotId": "snap-06331325870076318", "Status": "completed", "UserBucket": { "S3Bucket": "external-images", "S3Key": "rhcos-4.7.0-x86_64-aws.x86_64.vmdk" } } } ] }
复制
SnapshotId
以注册镜像。从 RHCOS 快照创建自定义 RHCOS AMI:
$ aws ec2 register-image \ --region ${AWS_DEFAULT_REGION} \ --architecture x86_64 \ 1 --description "rhcos-${RHCOS_VERSION}-x86_64-aws.x86_64" \ 2 --ena-support \ --name "rhcos-${RHCOS_VERSION}-x86_64-aws.x86_64" \ 3 --virtualization-type hvm \ --root-device-name '/dev/xvda' \ --block-device-mappings 'DeviceName=/dev/xvda,Ebs={DeleteOnTermination=true,SnapshotId=<snapshot_ID>}' 4
如需了解更多有关这些 API 的信息,请参阅 AWS 文档 导入快照 和 创建由 EBS 支持的 AMI。
4.3.9. 在 AWS 中创建 bootstrap 节点
您必须在 Amazon Web Services (AWS) 中创建 bootstrap 节点,以便在 OpenShift Container Platform 集群初始化过程中使用。您可以按照以下方法:
-
为集群提供
bootstrap.ign
Ignition 配置文件的位置。此文件位于您的安装目录中。提供的 CloudFormation 模板假定集群的 Ignition 配置文件由 S3 存储桶提供。如果选择从其他位置提供文件,您必须修改模板。 - 使用提供的 CloudFormation 模板和自定义参数文件来创建 AWS 资源堆栈。堆栈代表 OpenShift Container Platform 安装所需的 bootstrap 节点。
如果不使用提供的 CloudFormation 模板来创建 bootstrap 节点,您必须检查提供的信息并手动创建基础架构。如果集群没有正确初始化,您可能需要联系红帽支持并提供您的安装日志。
先决条件
- 已配置了一个 AWS 帐户。
-
您可以通过运行
aws configure
,将 AWS 密钥和区域添加到本地 AWS 配置集中。 - 已为集群生成 Ignition 配置文件。
- 您在 AWS 中创建并配置了 VPC 及相关子网。
- 您在 AWS 中创建并配置了 DNS、负载均衡器和监听程序。
- 您在 AWS 中创建了集群所需的安全组和角色。
流程
运行以下命令来创建存储桶:
$ aws s3 mb s3://<cluster-name>-infra 1
- 1
<cluster-name>-infra
是存储桶名称。在创建install-config.yaml
文件时,将<cluster-name>
替换为为集群指定的名称。
如果需要,您必须为 S3 存储桶使用预签名 URL,而不是
s3://
模式:- 部署到具有与 AWS SDK 不同端点的区域。
- 部署代理。
- 提供您自己的自定义端点。
运行以下命令,将
bootstrap.ign
Ignition 配置文件上传到存储桶:$ aws s3 cp <installation_directory>/bootstrap.ign s3://<cluster-name>-infra/bootstrap.ign 1
- 1
- 对于
<installation_directory>
,请指定安装文件保存到的目录的路径。
运行以下命令验证文件是否已上传:
$ aws s3 ls s3://<cluster-name>-infra/
输出示例
2019-04-03 16:15:16 314878 bootstrap.ign
注意bootstrap Ignition 配置文件包含 secret,如 X.509 密钥。以下步骤为 S3 存储桶提供基本安全性。若要提供额外的安全性,您可以启用 S3 存储桶策略,仅允许某些用户(如 OpenShift IAM 用户)访问存储桶中包含的对象。您可以完全避开 S3,并从 bootstrap 可访问的任意地址提供 bootstrap Ignition 配置文件。
创建一个 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 用于 bootstrap 节点。
- 4
- 指定有效的
AWS::EC2::Image::Id
值。 - 5
- 允许通过 SSH 访问 bootstrap 节点的 CIDR 块。
- 6
- 以
x.x.x.x/16-24
格式指定 CIDR 块。 - 7
- 与 VPC 关联的公共子网,将 bootstrap 节点启动到其中。
- 8
- 指定 VPC 的 CloudFormation 模板输出的
PublicSubnetIds
值。 - 9
- master 安全组 ID(用于注册临时规则)
- 10
- 指定安全组和角色的 CloudFormation 模板输出的
MasterSecurityGroupId
值。 - 11
- 创建的资源将从属于的 VPC。
- 12
- 指定 VPC 的 CloudFormation 模板输出的
VpcId
值。 - 13
- 从中获取 bootstrap Ignition 配置文件的位置。
- 14
- 指定 S3 存储桶和文件名,格式为
s3://<bucket_name>/bootstrap.ign
。 - 15
- 是否要注册网络负载均衡器 (NLB) 。
- 16
- 指定
yes
或no
。如果指定yes
,您必须提供一个 Lambda Amazon Resource Name (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
。
- 复制本主题的 Bootstrap 机器的 CloudFormation 模板部分中的模板,并将它以 YAML 文件形式保存到计算机上。此模板描述了集群所需的 bootstrap 机器。
-
可选: 如果要使用代理部署集群,您必须更新模板中的 ignition 以添加
ignition.config.proxy
字段。另外,如果您已将 Amazon EC2、Elastic Load Balancing 和 S3 VPC 端点添加到 VPC 中,您必须将这些端点添加到noProxy
字段。 启动 CloudFormation 模板,以创建代表 bootstrap 节点的 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
输出示例
arn:aws:cloudformation:us-east-1:269333783861:stack/cluster-bootstrap/12944486-2add-11eb-9dee-12dace8e3a83
确认模板组件已存在:
$ aws cloudformation describe-stacks --stack-name <name>
在
StackStatus
显示CREATE_COMPLETE
后,输出会显示以下参数的值。您必须将这些参数值提供给您在创建集群时要运行的其他 CloudFormation 模板:BootstrapInstanceId
bootstrap 实例 ID。
BootstrapPublicIp
bootstrap 节点公共 IP 地址。
BootstrapPrivateIp
bootstrap 节点专用 IP 地址。
4.3.9.1. bootstrap 机器的 CloudFormation 模板
您可以使用以下 CloudFormation 模板来部署 OpenShift Container Platform 集群所需的 bootstrap 机器。
例 4.21. bootstrap 机器的 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 CloudFormation 控制台来查看您创建的 CloudFormation 堆栈的详情。
- 如需有关 AWS 区的 Red Hat Enterprise Linux CoreOS(RHCOS)AMI 的详细信息,请参阅 AWS 基础架构的 RHCOS AMI。
4.3.10. 在 AWS 中创建 control plane 机器
您必须在集群要使用的 Amazon Web Services(AWS)中创建 control plane 机器。
您可以使用提供的 CloudFormation 模板和自定义参数文件,创建代表 control plane 节点的 AWS 资源堆栈。
CloudFormation 模板会创建一个堆栈,它代表三个 control plane 节点。
如果不使用提供的 CloudFormation 模板来创建 control plane 节点,您必须检查提供的信息并手动创建基础架构。如果集群没有正确初始化,您可能需要联系红帽支持并提供您的安装日志。
先决条件
- 已配置了一个 AWS 帐户。
-
您可以通过运行
aws configure
,将 AWS 密钥和区域添加到本地 AWS 配置集中。 - 已为集群生成 Ignition 配置文件。
- 您在 AWS 中创建并配置了 VPC 及相关子网。
- 您在 AWS 中创建并配置了 DNS、负载均衡器和监听程序。
- 您在 AWS 中创建了集群所需的安全组和角色。
- 已创建 bootstrap 机器。
流程
创建一个 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", 13 "ParameterValue": "subnet-<random_string>" 14 }, { "ParameterKey": "Master2Subnet", 15 "ParameterValue": "subnet-<random_string>" 16 }, { "ParameterKey": "MasterSecurityGroupId", 17 "ParameterValue": "sg-<random_string>" 18 }, { "ParameterKey": "IgnitionLocation", 19 "ParameterValue": "https://api-int.<cluster_name>.<domain_name>:22623/config/master" 20 }, { "ParameterKey": "CertificateAuthorities", 21 "ParameterValue": "data:text/plain;charset=utf-8;base64,ABC...xYz==" 22 }, { "ParameterKey": "MasterInstanceProfileName", 23 "ParameterValue": "<roles_stack>-MasterInstanceProfile-<random_string>" 24 }, { "ParameterKey": "MasterInstanceType", 25 "ParameterValue": "" 26 }, { "ParameterKey": "AutoRegisterELB", 27 "ParameterValue": "yes" 28 }, { "ParameterKey": "RegisterNlbIpTargetsLambdaArn", 29 "ParameterValue": "arn:aws:lambda:<aws_region>:<account_number>:function:<dns_stack_name>-RegisterNlbIpTargets-<random_string>" 30 }, { "ParameterKey": "ExternalApiTargetGroupArn", 31 "ParameterValue": "arn:aws:elasticloadbalancing:<aws_region>:<account_number>:targetgroup/<dns_stack_name>-Exter-<random_string>" 32 }, { "ParameterKey": "InternalApiTargetGroupArn", 33 "ParameterValue": "arn:aws:elasticloadbalancing:<aws_region>:<account_number>:targetgroup/<dns_stack_name>-Inter-<random_string>" 34 }, { "ParameterKey": "InternalServiceTargetGroupArn", 35 "ParameterValue": "arn:aws:elasticloadbalancing:<aws_region>:<account_number>:targetgroup/<dns_stack_name>-Inter-<random_string>" 36 } ]
- 1
- 您的 Ignition 配置文件中为集群编码的集群基础架构名称。
- 2
- 指定从 Ignition 配置文件元数据中提取的基础架构名称,其格式为
<cluster-name>-<random-string>
。 - 3
- 根据您选择的架构,当前用于 control plane 机器的 Red Hat Enterprise Linux CoreOS (RHCOS) AMI。
- 4
- 指定
AWS::EC2::Image::Id
值。 - 5
- 是否要执行 DNS etcd 注册。
- 6
- 指定
yes
或no
。如果指定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 13 15
- 在其中启动 control plane 机器的子网,最好是专用子网。
- 12 14 16
- 从 DNS 和负载均衡的 CloudFormation 模板输出的
PrivateSubnets
值指定子网。 - 17
- 与 control plane 节点关联的 master 安全组 ID。
- 18
- 指定安全组和角色的 CloudFormation 模板输出的
MasterSecurityGroupId
值。 - 19
- 从中获取 control plane Ignition 配置文件的位置。
- 20
- 指定生成的 Ignition 配置文件的位置,
https://api-int.<cluster_name>.<domain_name>:22623/config/master
。 - 21
- 要使用的 base64 编码证书颁发机构字符串。
- 22
- 指定安装目录中
master.ign
文件中的值。这个值是一个长字符串,格式为data:text/plain;charset=utf-8;base64,ABC…xYz==
。 - 23
- 与 control plane 节点关联的 IAM 配置集。
- 24
- 指定安全组和角色的 CloudFormation 模板输出的
MasterInstanceProfile
参数值。 - 25
- 根据您选择的架构,用于 control plane 机器的 AWS 实例类型。
- 26
- 实例类型值与 control plane 机器的最低资源要求对应。例如,
m6i.xlarge
是 AMD64 的类型,m6g.xlarge
是 ARM64 的类型。 - 27
- 是否要注册网络负载均衡器 (NLB) 。
- 28
- 指定
yes
或no
。如果指定yes
,您必须提供一个 Lambda Amazon Resource Name (ARN) 值。 - 29
- NLB IP 目标注册 lambda 组的 ARN。
- 30
- 指定 DNS 和负载均衡的 CloudFormation 模板输出的
RegisterNlbIpTargetsLambda
值。如果将集群部署到 AWS GovCloud 区域,请使用arn:aws-us-gov
。 - 31
- 外部 API 负载均衡器目标组的 ARN。
- 32
- 指定 DNS 和负载均衡的 CloudFormation 模板输出的
ExternalApiTargetGroupArn
值。如果将集群部署到 AWS GovCloud 区域,请使用arn:aws-us-gov
。 - 33
- 内部 API 负载均衡器目标组群的 ARN。
- 34
- 指定 DNS 和负载均衡的 CloudFormation 模板输出的
InternalApiTargetGroupArn
值。如果将集群部署到 AWS GovCloud 区域,请使用arn:aws-us-gov
。 - 35
- 内部服务负载均衡器目标组群的 ARN。
- 36
- 指定 DNS 和负载均衡的 CloudFormation 模板输出的
InternalServiceTargetGroupArn
值。如果将集群部署到 AWS GovCloud 区域,请使用arn:aws-us-gov
。
- 复制control plane 机器的 CloudFormation 模板一节中的模板,并将它以 YAML 文件形式保存到计算机上。此模板描述了集群所需的 control plane 机器。
-
如果您将
m5
实例类型指定为MasterInstanceType
的值,请将该实例类型添加到 CloudFormation 模板中的MasterInstanceType.AllowedValues
参数。 启动 CloudFormation 模板,以创建代表 control plane 节点的 AWS 资源堆栈:
重要您必须在一行内输入命令。
$ aws cloudformation create-stack --stack-name <name> 1 --template-body file://<template>.yaml 2 --parameters file://<parameters>.json 3
输出示例
arn:aws:cloudformation:us-east-1:269333783861:stack/cluster-control-plane/21c7e2b0-2ee2-11eb-c6f6-0aa34627df4b
注意CloudFormation 模板会创建一个堆栈,它代表三个 control plane 节点。
确认模板组件已存在:
$ aws cloudformation describe-stacks --stack-name <name>
4.3.10.1. control plane 机器的 CloudFormation 模板
您可以使用以下 CloudFormation 模板来部署 OpenShift Container Platform 集群所需的 control plane 机器。
例 4.22. control plane 机器的 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 CloudFormation 控制台来查看您创建的 CloudFormation 堆栈的详情。
4.3.11. 在 AWS 中创建 worker 节点
您可以在 Amazon Web Services (AWS) 中创建 worker 节点,供集群使用。
如果您要安装三节点集群,请跳过这一步。三节点集群包含三个 control plane 机器,它们也可以充当计算机器。
您可以使用提供的 CloudFormation 模板和自定义参数文件创建代表 worker 节点的 AWS 资源堆栈。
CloudFormation 模板会创建一个堆栈,它代表一个 worker 节点。您必须为每个 worker 节点创建一个堆栈。
如果不使用提供的 CloudFormation 模板来创建 worker 节点,您必须检查提供的信息并手动创建基础架构。如果集群没有正确初始化,您可能需要联系红帽支持并提供您的安装日志。
先决条件
- 已配置了一个 AWS 帐户。
-
您可以通过运行
aws configure
,将 AWS 密钥和区域添加到本地 AWS 配置集中。 - 已为集群生成 Ignition 配置文件。
- 您在 AWS 中创建并配置了 VPC 及相关子网。
- 您在 AWS 中创建并配置了 DNS、负载均衡器和监听程序。
- 您在 AWS 中创建了集群所需的安全组和角色。
- 已创建 bootstrap 机器。
- 已创建 control plane 机器。
流程
创建一个 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 用于 worker 节点。
- 4
- 指定
AWS::EC2::Image::Id
值。 - 5
- 在其中启动 worker 节点的子网,最好是专用子网。
- 6
- 从 DNS 和负载均衡的 CloudFormation 模板输出的
PrivateSubnets
值指定子网。 - 7
- 与 worker 节点关联的 worker 安全组 ID。
- 8
- 指定安全组和角色的 CloudFormation 模板输出的
WorkerSecurityGroupId
值。 - 9
- 从中获取 bootstrap 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
- 与 worker 节点关联的 IAM 配置集。
- 14
- 指定安全组和角色的 CloudFormation 模板输出的
WorkerInstanceProfile
参数值。 - 15
- 根据您选择的架构,用于计算机器的 AWS 实例类型。
- 16
- 实例类型值对应于计算机器的最低资源要求。例如,
m6i.large
是 AMD64 的类型,m6g.large
是 ARM64 的类型。
- 复制 worker 机器的 CloudFormation 模板一节中的模板,并将它以 YAML 文件形式保存到计算机上。此模板描述了集群所需的网络对象和负载均衡器。
-
可选:如果将
m5
实例类型指定为WorkerInstanceType
的值,请将该实例类型添加到 CloudFormation 模板中的WorkerInstanceType.AllowedValues
参数。 -
可选:如果您使用 AWS Marketplace 镜像部署,请使用从订阅获取的 AMI ID 更新
Worker0.type.properties.ImageID
参数。 使用 CloudFormation 模板创建代表 worker 节点的 AWS 资源堆栈:
重要您必须在一行内输入命令。
$ aws cloudformation create-stack --stack-name <name> 1 --template-body file://<template>.yaml \ 2 --parameters file://<parameters>.json 3
输出示例
arn:aws:cloudformation:us-east-1:269333783861:stack/cluster-worker-1/729ee301-1c2a-11eb-348f-sd9888c65b59
注意CloudFormation 模板会创建一个堆栈,它代表一个 worker 节点。
确认模板组件已存在:
$ aws cloudformation describe-stacks --stack-name <name>
继续创建 worker 堆栈,直到为集群创建了充足的 worker 机器。您可以通过引用同一模板和参数文件并指定不同的堆栈名称来创建额外的 worker 堆栈。
重要您必须至少创建两台 worker 机器,因此您必须创建至少两个使用此 CloudFormation 模板的堆栈。
4.3.11.1. worker 机器的 CloudFormation 模板
您可以使用以下 CloudFormation 模板来部署 OpenShift Container Platform 集群所需的 worker 机器。
例 4.23. worker 机器的 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 CloudFormation 控制台来查看您创建的 CloudFormation 堆栈的详情。
4.3.12. 使用用户置备的基础架构在 AWS 上初始化 bootstrap 序列
在 Amazon Web Services(AWS)中创建所有所需的基础架构后,您可以启动初始化 OpenShift Container Platform control plane 的 bootstrap 序列。
先决条件
- 已配置了一个 AWS 帐户。
-
您可以通过运行
aws configure
,将 AWS 密钥和区域添加到本地 AWS 配置集中。 - 已为集群生成 Ignition 配置文件。
- 您在 AWS 中创建并配置了 VPC 及相关子网。
- 您在 AWS 中创建并配置了 DNS、负载均衡器和监听程序。
- 您在 AWS 中创建了集群所需的安全组和角色。
- 已创建 bootstrap 机器。
- 已创建 control plane 机器。
- 已创建 worker 节点。
流程
更改为包含安装程序的目录,并启动初始化 OpenShift Container Platform control plane 的 bootstrap 过程:
$ ./openshift-install wait-for bootstrap-complete --dir <installation_directory> \ 1 --log-level=info 2
输出示例
INFO Waiting up to 20m0s for the Kubernetes API at https://api.mycluster.example.com:6443... INFO API v1.29.4 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 control plane 已被初始化。注意在 control plane 初始化后,它会设置计算节点,并以 Operator 的形式安装其他服务。
其他资源
- 如需了解在 OpenShift Container Platform 安装过程中监控安装、bootstrap 和 control plane 日志的详细信息,请参阅监控安装进度。
- 如需有关对 bootstrap 过程进行故障排除的信息,请参阅收集 bootstrap 节点诊断数据。
- 您可以使用 AWS EC2 控制台查看正在运行的实例的详情。
4.3.13. 使用 CLI 登录集群
您可以通过导出集群 kubeconfig
文件,以默认系统用户身份登录集群。kubeconfig
文件包含有关集群的信息,供 CLI 用于将客户端连接到正确的集群和 API 服务器。该文件特定于集群,在 OpenShift Container Platform 安装过程中创建。
先决条件
- 已部署 OpenShift Container Platform 集群。
-
已安装
oc
CLI。
流程
导出
kubeadmin
凭证:$ export KUBECONFIG=<installation_directory>/auth/kubeconfig 1
- 1
- 对于
<installation_directory>
,请指定安装文件保存到的目录的路径。
验证您可以使用导出的配置成功运行
oc
命令:$ oc whoami
输出示例
system:admin
4.3.14. 批准机器的证书签名请求
当您将机器添加到集群时,会为您添加的每台机器生成两个待处理证书签名请求(CSR)。您必须确认这些 CSR 已获得批准,或根据需要自行批准。必须首先批准客户端请求,然后批准服务器请求。
先决条件
- 您已将机器添加到集群中。
流程
确认集群可以识别这些机器:
$ oc get nodes
输出示例
NAME STATUS ROLES AGE VERSION master-0 Ready master 63m v1.29.4 master-1 Ready master 63m v1.29.4 master-2 Ready master 64m v1.29.4
输出中列出了您创建的所有机器。
注意在有些 CSR 被批准前,前面的输出可能不包括计算节点(也称为 worker 节点)。
检查待处理的 CSR,并确保添加到集群中的每台机器都有
Pending
或Approved
状态的客户端请求:$ oc get csr
输出示例
NAME AGE REQUESTOR CONDITION csr-8b2br 15m system:serviceaccount:openshift-machine-config-operator:node-bootstrapper Pending csr-8vnps 15m system:serviceaccount:openshift-machine-config-operator:node-bootstrapper Pending ...
在本例中,两台机器加入集群。您可能会在列表中看到更多已批准的 CSR。
如果 CSR 没有获得批准,在您添加的机器的所有待处理 CSR 都处于
Pending 状态
后,请批准集群机器的 CSR:注意由于 CSR 会自动轮转,因此请在将机器添加到集群后一小时内批准您的 CSR。如果没有在一小时内批准它们,证书将会轮转,每个节点会存在多个证书。您必须批准所有这些证书。批准客户端 CSR 后,Kubelet 为服务证书创建一个二级 CSR,这需要手动批准。然后,如果 Kubelet 请求具有相同参数的新证书,则后续提供证书续订请求由
machine-approver
自动批准。注意对于在未启用机器 API 的平台上运行的集群,如裸机和其他用户置备的基础架构,您必须实施一种方法来自动批准 kubelet 提供证书请求(CSR)。如果没有批准请求,则
oc exec
、ocrsh
和oc logs
命令将无法成功,因为 API 服务器连接到 kubelet 时需要服务证书。与 Kubelet 端点联系的任何操作都需要此证书批准。该方法必须监视新的 CSR,确认 CSR 由 system:node
或system: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 可能无法使用。
现在,您的客户端请求已被批准,您必须查看添加到集群中的每台机器的服务器请求:
$ 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 ...
如果剩余的 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
批准所有客户端和服务器 CSR 后,机器将
处于 Ready 状态
。运行以下命令验证:$ oc get nodes
输出示例
NAME STATUS ROLES AGE VERSION master-0 Ready master 73m v1.29.4 master-1 Ready master 73m v1.29.4 master-2 Ready master 74m v1.29.4 worker-0 Ready worker 11m v1.29.4 worker-1 Ready worker 11m v1.29.4
注意批准服务器 CSR 后可能需要几分钟时间让机器过渡到
Ready 状态
。
其他信息
- 如需有关 CSR 的更多信息,请参阅 证书签名请求。
4.3.15. 初始 Operator 配置
在 control plane 初始化后,您必须立即配置一些 Operator,以便它们都可用。
先决条件
- 您的 control plane 已初始化。
流程
观察集群组件上线:
$ watch -n5 oc get clusteroperators
输出示例
NAME VERSION AVAILABLE PROGRESSING DEGRADED SINCE authentication 4.16.0 True False False 19m baremetal 4.16.0 True False False 37m cloud-credential 4.16.0 True False False 40m cluster-autoscaler 4.16.0 True False False 37m config-operator 4.16.0 True False False 38m console 4.16.0 True False False 26m csi-snapshot-controller 4.16.0 True False False 37m dns 4.16.0 True False False 37m etcd 4.16.0 True False False 36m image-registry 4.16.0 True False False 31m ingress 4.16.0 True False False 30m insights 4.16.0 True False False 31m kube-apiserver 4.16.0 True False False 26m kube-controller-manager 4.16.0 True False False 36m kube-scheduler 4.16.0 True False False 36m kube-storage-version-migrator 4.16.0 True False False 37m machine-api 4.16.0 True False False 29m machine-approver 4.16.0 True False False 37m machine-config 4.16.0 True False False 36m marketplace 4.16.0 True False False 37m monitoring 4.16.0 True False False 29m network 4.16.0 True False False 38m node-tuning 4.16.0 True False False 37m openshift-apiserver 4.16.0 True False False 32m openshift-controller-manager 4.16.0 True False False 30m openshift-samples 4.16.0 True False False 32m operator-lifecycle-manager 4.16.0 True False False 37m operator-lifecycle-manager-catalog 4.16.0 True False False 37m operator-lifecycle-manager-packageserver 4.16.0 True False False 32m service-ca 4.16.0 True False False 38m storage 4.16.0 True False False 37m
- 配置不可用的 Operator。
4.3.15.1. 镜像 registry 存储配置
Amazon Web Services 提供默认存储,这意味着 Image Registry Operator 在安装后可用。但是,如果 Registry Operator 无法创建 S3 存储桶并自动配置存储,您需要手工配置 registry 存储。
显示配置生产集群所需的持久性卷的说明。如果适用,显示有关将空目录配置为存储位置的说明,这仅适用于非生产集群。
另外还提供了在升级过程中使用 Recreate
rollout 策略来允许镜像 registry 使用块存储类型的说明。
您可以在 AWS 中为用户置备的基础架构配置 registry 存储,以将 OpenShift Container Platform 部署到隐藏的区域。请参阅为 AWS 用户置备的基础架构配置 registry。
4.3.15.1.1. 为使用用户置备的基础架构的 AWS 配置 registry 存储
在安装过程中,使用您的云凭据就可以创建一个 Amazon S3 存储桶,Registry Operator 将会自动配置存储。
如果 Registry Operator 无法创建 S3 存储桶或自动配置存储,您可以按照以下流程创建 S3 存储桶并配置存储。
先决条件
- 在带有用户置备的基础架构的 AWS 上有一个集群。
对于 Amazon S3 存储,secret 应该包含以下两个键:
-
REGISTRY_STORAGE_S3_ACCESSKEY
-
REGISTRY_STORAGE_S3_SECRETKEY
-
流程
如果 Registry Operator 无法创建 S3 存储桶并自动配置存储,请进行以下操作。
- 设置一个 Bucket Lifecycle Policy用来终止已有一天之久的未完成的分段上传操作。
在
configs.imageregistry.operator.openshift.io/cluster中
中输入存储配置:$ oc edit configs.imageregistry.operator.openshift.io/cluster
配置示例
storage: s3: bucket: <bucket-name> region: <region-name>
为了保护 AWS 中 registry 镜像的安全,阻止对 S3 存储桶的公共访问。
4.3.15.1.2. 在非生产集群中配置镜像 registry 存储
您必须为 Image Registry Operator 配置存储。对于非生产集群,您可以将镜像 registry 设置为空目录。如果您这样做,重启 registry 时会丢失所有镜像。
流程
将镜像 registry 存储设置为空目录:
$ oc patch configs.imageregistry.operator.openshift.io cluster --type merge --patch '{"spec":{"storage":{"emptyDir":{}}}}'
警告仅为非生产集群配置这个选项。
如果在 Image Registry Operator 初始化其组件前运行这个命令,
oc patch
命令会失败并显示以下错误:Error from server (NotFound): configs.imageregistry.operator.openshift.io "cluster" not found
等待几分钟,然后再次运行该命令。
4.3.16. 删除 bootstrap 资源:
完成集群的初始 Operator 配置后,从 Amazon Web Services (AWS) 中删除 bootstrap 资源。
先决条件
- 已为集群完成初始的 Operator 配置。
流程
删除 bootstrap 资源。如果您使用了 CloudFormation 模板,请删除其堆栈:
使用 AWS CLI 删除堆栈:
$ aws cloudformation delete-stack --stack-name <name> 1
- 1
<name>
是 bootstrap 堆栈的名称。
- 使用 AWS CloudFormation 控制台删除堆栈。
4.3.17. 创建 Ingress DNS 记录
如果您删除了 DNS 区配置,请手动创建指向 Ingress 负载均衡器的 DNS 记录。您可以创建一个 wildcard 记录或具体的记录。以下流程使用了 A 记录,但您可以使用其他所需记录类型,如 CNAME 或别名。
先决条件
- 已在 Amazon Web Services (AWS) 上安装了使用您置备的基础架构的 OpenShift Container Platform 集群。
-
已安装 OpenShift CLI(
oc
)。 -
安装了
jq
软件包。 - 您下载了 AWS CLI 并安装到您的计算机上。请参阅使用捆绑安装程序(Linux、macOS 或 Unix)安装 AWS CLI的文档。
流程
决定要创建的路由。
-
要创建一个 wildcard 记录,请使用
*.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>
-
要创建一个 wildcard 记录,请使用
获取 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
为负载均衡器定位托管区 ID:
$ aws elb describe-load-balancers | jq -r '.LoadBalancerDescriptions[] | select(.DNSName == "<external_ip>").CanonicalHostedZoneNameID' 1
- 1
- 对于
<external_ip>
,请指定您获取的 Ingress Operator 负载均衡器的外部 IP 地址值。
输出示例
Z3AADJGX6KTTL2
这个命令的输出是负载均衡器托管区 ID。
获取集群域的公共托管区 ID:
$ aws route53 list-hosted-zones-by-name \ --dns-name "<domain_name>" \ 1 --query 'HostedZones[? Config.PrivateZone != `true` && Name == `<domain_name>.`].Id' 2 --output text
输出示例
/hostedzone/Z3URY6TWQ91KVV
命令输出中会显示您的域的公共托管区 ID。在本例中是
Z3URY6TWQ91KVV
。在您的私有区中添加别名记录:
$ 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 > } > } > } > ] > }'
在您的公共区中添加记录:
$ 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 > } > } > } > ] > }'
4.3.18. 在用户置备的基础架构上完成 AWS 安装
在用户置备的基础架构 Amazon Web Service (AWS) 上启动 OpenShift Container Platform 安装后,监视进程并等待安装完成。
先决条件
- 您在用户置备的 AWS 基础架构上为 OpenShift Container Platform 集群删除了 bootstrap 节点。
-
已安装
oc
CLI。
流程
在包含安装程序的目录中完成集群安装:
$ ./openshift-install --dir <installation_directory> wait-for install-complete 1
- 1
- 对于
<installation_directory>
,请指定安装文件保存到的目录的路径。
输出示例
INFO Waiting up to 40m0s for the cluster at https://api.mycluster.example.com:6443 to initialize... INFO Waiting up to 10m0s for the openshift-console route to be created... INFO Install complete! INFO To access the cluster as the system:admin user when using 'oc', run 'export KUBECONFIG=/home/myuser/install_dir/auth/kubeconfig' INFO Access the OpenShift web-console here: https://console-openshift-console.apps.mycluster.example.com INFO Login to the console with user: "kubeadmin", and password: "password" INFO Time elapsed: 1s
重要-
安装程序生成的 Ignition 配置文件包含在 24 小时后过期的证书,然后在过期时进行续订。如果在更新证书前关闭集群,且集群在 24 小时后重启,集群会自动恢复过期的证书。一个例外是,您必须手动批准待处理的
node-bootstrapper
证书签名请求(CSR)来恢复 kubelet 证书。如需更多信息,请参阅从过期的 control plane 证书 中恢复的文档。 - 建议您在 Ignition 配置文件生成后的 12 小时内使用它们,因为 24 小时的证书会在集群安装后的 16 小时到 22 小时间进行轮转。通过在 12 小时内使用 Ignition 配置文件,您可以避免在安装过程中因为执行了证书更新而导致安装失败的问题。
4.3.19. 使用 Web 控制台登录到集群
kubeadmin
用户默认在 OpenShift Container Platform 安装后存在。您可以使用 OpenShift Container Platform Web 控制台以 kubeadmin
用户身份登录集群。
先决条件
- 有访问安装主机的访问权限。
- 您完成了集群安装,所有集群 Operator 都可用。
流程
从安装主机上的
kubeadmin
-password
文件中获取 kubeadmin 用户的密码:$ cat <installation_directory>/auth/kubeadmin-password
注意另外,您还可以从安装主机上的
<installation_directory>/.openshift_install.log
日志文件获取kubeadmin
密码。列出 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
-
在 Web 浏览器中导航到上一命令输出中包括的路由,以
kubeadmin
用户身份登录。
其他资源
- 如需有关 访问和了解 OpenShift Container Platform Web 控制台的更多详情,请参阅 访问 Web 控制台。
4.3.20. 其他资源
- 如需有关 AWS CloudFormation 堆栈的更多信息,请参阅 AWS 文档中的使用堆栈。