×

在 OpenShift Container Platform 4.17 版本中,您可以使用您提供的基础设施在 Microsoft Azure Stack Hub 上安装集群。

提供了一些Azure 资源管理器 (ARM) 模板来帮助完成这些步骤或帮助您创建自己的模板。

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

先决条件

配置您的 Azure Stack Hub 项目

在安装 OpenShift Container Platform 之前,您必须配置一个 Azure 项目来托管它。

所有通过公共端点可用的 Azure Stack Hub 资源都受到资源名称限制,您不能创建使用某些术语的资源。有关 Azure Stack Hub 限制的术语列表,请参阅 Azure 文档中的解决保留的资源名称错误

Azure Stack Hub 帐户限制

OpenShift Container Platform 集群使用许多 Microsoft Azure Stack Hub 组件,并且默认的Azure Stack Hub 中的配额类型会影响您安装 OpenShift Container Platform 集群的能力。

下表总结了其限制可能会影响您安装和运行 OpenShift Container Platform 集群的 Azure Stack Hub 组件。

组件 默认情况下所需的组件数量 描述

vCPU

56

默认集群需要 56 个 vCPU,因此您必须增加帐户限制。

默认情况下,每个集群会创建以下实例:

  • 一台引导程序机器,安装后将被删除

  • 三台控制平面机器

  • 三台计算机器

由于引导程序、控制平面和工作机器使用 Standard_DS4_v2 虚拟机(使用 8 个 vCPU),因此默认集群需要 56 个 vCPU。引导节点虚拟机仅在安装期间使用。

要部署更多工作节点、启用自动缩放、部署大型工作负载或使用不同的实例类型,您必须进一步增加帐户的 vCPU 限制,以确保您的集群可以部署您所需的机器。

VNet

1

每个默认集群需要一个虚拟网络 (VNet),其中包含两个子网。

网络接口

7

每个默认集群需要七个网络接口。如果您创建更多机器或已部署的工作负载创建负载均衡器,则您的集群将使用更多网络接口。

网络安全组

2

每个集群都会为 VNet 中的每个子网创建网络安全组。默认集群为控制平面和计算节点子网创建网络安全组。

控制平面

允许从任何位置通过端口 6443 访问控制平面机器

节点

允许通过端口 80 和 443 从互联网访问工作节点

网络负载均衡器

3

每个集群都会创建以下负载均衡器

默认

公共 IP 地址,用于跨工作机器对端口 80 和 443 的请求进行负载均衡

内部

专用 IP 地址,用于跨控制平面机器对端口 6443 和 22623 的请求进行负载均衡

外部

公共 IP 地址,用于跨控制平面机器对端口 6443 的请求进行负载均衡

如果您的应用程序创建更多 Kubernetes LoadBalancer 服务对象,则您的集群将使用更多负载均衡器。

公共 IP 地址

2

公共负载均衡器使用公共 IP 地址。引导程序机器也使用公共 IP 地址,以便您可以通过 SSH 登录到机器以对安装期间的问题进行故障排除。引导节点的 IP 地址仅在安装期间使用。

专用 IP 地址

7

内部负载均衡器、三台控制平面机器中的每一台以及三台工作机器中的每一台都使用专用 IP 地址。

其他资源

在 Azure Stack Hub 中配置 DNS 区域

要在 Azure Stack Hub 上成功安装 OpenShift Container Platform,您必须在 Azure Stack Hub DNS 区域中创建 DNS 记录。DNS 区域必须是该域的权威区域。要将注册商的 DNS 区域委派给 Azure Stack Hub,请参阅 Microsoft 有关Azure Stack Hub 数据中心 DNS 集成的文档。

您可以通过访问此创建 DNS 区域的示例来查看 Azure 的 DNS 解决方案。

证书签名请求管理

因为当您使用您自己提供的基础设施时,您的集群对自动机器管理的访问权限有限,因此您必须提供一种机制来批准安装后的集群证书签名请求 (CSR)。kube-controller-manager 仅批准 kubelet 客户端 CSR。machine-approver 无法保证使用 kubelet 凭据请求的服务证书的有效性,因为它无法确认正确的机器发出了请求。您必须确定并实现一种验证 kubelet 服务证书请求的有效性并批准它们的方法。

所需的 Azure Stack Hub 角色

您的 Microsoft Azure Stack Hub 帐户必须具有您使用的订阅的以下角色:

  • 所有者

要在 Azure 门户上设置角色,请参阅 Microsoft 文档中的使用基于角色的访问控制管理对 Azure Stack Hub 中资源的访问

创建服务主体

由于 OpenShift Container Platform 及其安装程序使用 Azure 资源管理器创建 Microsoft Azure 资源,因此必须创建一个服务主体来代表它。

先决条件
  • 安装或更新 Azure CLI

  • 您的 Azure 帐户具有您使用的订阅所需的权限。

步骤
  1. 注册您的环境

    $ az cloud register -n AzureStackCloud --endpoint-resource-manager <endpoint> (1)
    1 指定 Azure 资源管理器端点:`https://management.<region>.<fqdn>/`。

    详情请参见 Microsoft 文档

  2. 设置活动环境

    $ az cloud set -n AzureStackCloud
  3. 更新您的环境配置以使用 Azure Stack Hub 的特定 API 版本

    $ az cloud update --profile 2019-03-01-hybrid
  4. 登录 Azure CLI

    $ az login

    如果您处于多租户环境中,还必须提供租户 ID。

  5. 如果您的 Azure 帐户使用订阅,请确保您使用的是正确的订阅

    1. 查看可用帐户列表并记录您要用于集群的订阅的tenantId

      $ az account list --refresh
      示例输出
      [
        {
          "cloudName": AzureStackCloud",
          "id": "9bab1460-96d5-40b3-a78e-17b15e978a80",
          "isDefault": true,
          "name": "Subscription Name",
          "state": "Enabled",
          "tenantId": "6057c7e9-b3ae-489d-a54e-de3f6bf6a8ee",
          "user": {
            "name": "[email protected]",
            "type": "user"
          }
        }
      ]
    2. 查看您的活动帐户详细信息并确认tenantId值与您要使用的订阅匹配

      $ az account show
      示例输出
      {
        "environmentName": AzureStackCloud",
        "id": "9bab1460-96d5-40b3-a78e-17b15e978a80",
        "isDefault": true,
        "name": "Subscription Name",
        "state": "Enabled",
        "tenantId": "6057c7e9-b3ae-489d-a54e-de3f6bf6a8ee", (1)
        "user": {
          "name": "[email protected]",
          "type": "user"
        }
      }
      1 确保tenantId参数的值是正确的订阅 ID。
    3. 如果您没有使用正确的订阅,请更改活动订阅

      $ az account set -s <subscription_id> (1)
      1 指定订阅 ID。
    4. 验证订阅 ID 更新

      $ az account show
      示例输出
      {
        "environmentName": AzureStackCloud",
        "id": "33212d16-bdf6-45cb-b038-f6565b61edda",
        "isDefault": true,
        "name": "Subscription Name",
        "state": "Enabled",
        "tenantId": "8049c7e9-c3de-762d-a54e-dc3f6be6a7ee",
        "user": {
          "name": "[email protected]",
          "type": "user"
        }
      }
  6. 记录输出中的tenantIdid参数值。在 OpenShift Container Platform 安装过程中需要这些值。

  7. 为您的帐户创建服务主体

    $ az ad sp create-for-rbac --role Contributor --name <service_principal> \ (1)
      --scopes /subscriptions/<subscription_id> (2)
      --years <years> (3)
    
    1 指定服务主体名称。
    2 指定订阅 ID。
    3 指定年数。默认情况下,服务主体一年后过期。使用--years选项可以延长服务主体的有效期。
    示例输出
    Creating 'Contributor' role assignment under scope '/subscriptions/<subscription_id>'
    The output includes credentials that you must protect. Be sure that you do not
    include these credentials in your code or check the credentials into your source
    control. For more information, see https://aka.ms/azadsp-cli
    {
      "appId": "ac461d78-bf4b-4387-ad16-7e32e328aec6",
      "displayName": <service_principal>",
      "password": "00000000-0000-0000-0000-000000000000",
      "tenantId": "8049c7e9-c3de-762d-a54e-dc3f6be6a7ee"
    }
  8. 记录上一步输出中的appIdpassword参数值。在 OpenShift Container Platform 安装过程中需要这些值。

为 Azure Stack Hub 创建安装文件

要在使用用户预配基础设施的 Microsoft Azure Stack Hub 上安装 OpenShift Container Platform,必须生成安装程序部署集群所需的 文件,并对其进行修改,以便集群仅创建其将使用的机器。您需要手动创建install-config.yaml文件,然后生成和自定义 Kubernetes 清单和 Ignition 配置文件。您还可以选择在安装准备阶段先设置单独的var分区。

手动创建安装配置文件

安装集群需要手动创建安装配置文件。

先决条件
  • 您在本地机器上拥有一个 SSH 公钥,需要提供给安装程序。该密钥将用于 SSH 身份验证到您的集群节点,用于调试和灾难恢复。

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

步骤
  1. 创建一个安装目录来存储所需的安装资源

    $ mkdir <installation_directory>

    您必须创建一个目录。某些安装资源(如引导 X.509 证书)的有效期很短,因此您不能重复使用安装目录。如果您想重复使用来自另一个集群安装的单个文件,您可以将它们复制到您的目录中。但是,安装资源的文件名可能会在不同版本之间发生变化。从早期 OpenShift Container Platform 版本复制安装文件时,请务必小心。

  2. 自定义提供的示例install-config.yaml文件模板,并将其保存到<installation_directory>中。

    此配置文件必须命名为install-config.yaml

    针对 Azure Stack Hub 进行以下修改

    1. compute池的replicas参数设置为0

      compute:
      - hyperthreading: Enabled
        name: worker
        platform: {}
        replicas: 0 (1)
      1 设置为0

      计算机会稍后手动预配。

    2. 更新install-config.yaml文件的platform.azure部分以配置您的 Azure Stack Hub 配置

      platform:
        azure:
          armEndpoint: <azurestack_arm_endpoint> (1)
          baseDomainResourceGroupName: <resource_group> (2)
          cloudName: AzureStackCloud (3)
          region: <azurestack_region> (4)
      1 指定 Azure Stack Hub 环境的 Azure 资源管理器端点,例如https://management.local.azurestack.external
      2 指定包含您的基本域的 DNS 区域的资源组的名称。
      3 指定 Azure Stack Hub 环境,用于使用适当的 Azure API 端点配置 Azure SDK。
      4 指定您的 Azure Stack Hub 区域的名称。
  3. 备份install-config.yaml文件,以便您可以使用它来安装多个集群。

    install-config.yaml文件将在安装过程的下一步使用。您现在必须对其进行备份。

Azure Stack Hub 的示例自定义 install-config.yaml 文件

您可以自定义install-config.yaml文件以指定有关 OpenShift Container Platform 集群平台的更多详细信息,或修改所需参数的值。

此示例 YAML 文件仅供参考。将其用作资源,将参数值输入您手动创建的安装配置文件中。

apiVersion: v1
baseDomain: example.com
controlPlane: (1)
  name: master
  platform:
    azure:
      osDisk:
        diskSizeGB: 1024 (2)
        diskType: premium_LRS
  replicas: 3
compute: (1)
- name: worker
  platform:
    azure:
      osDisk:
        diskSizeGB: 512 (2)
        diskType: premium_LRS
  replicas: 0
metadata:
  name: test-cluster (3)
networking:
  clusterNetwork:
  - cidr: 10.128.0.0/14
    hostPrefix: 23
  machineNetwork:
  - cidr: 10.0.0.0/16
  networkType: OVNKubernetes (4)
  serviceNetwork:
  - 172.30.0.0/16
platform:
  azure:
    armEndpoint: azurestack_arm_endpoint (5)
    baseDomainResourceGroupName: resource_group (6)
    region: azure_stack_local_region (7)
    resourceGroupName: existing_resource_group (8)
    outboundType: Loadbalancer
    cloudName: AzureStackCloud (9)
pullSecret: '{"auths": ...}' (10)
fips: false (11)
additionalTrustBundle: | (12)
    -----BEGIN CERTIFICATE-----
    <MY_TRUSTED_CA_CERT>
    -----END CERTIFICATE-----
sshKey: ssh-ed25519 AAAA... (13)
1 controlPlane部分是一个单一映射,但compute部分是一系列映射。为了满足不同数据结构的要求,compute部分的第一行必须以连字符-开头,而controlPlane部分的第一行则不能。只使用一个控制平面池。
2 您可以指定要使用的磁盘大小(以 GB 为单位)。控制平面节点的最低建议值为 1024 GB。
3 指定集群的名称。
4 要安装的集群网络插件。默认值OVNKubernetes是唯一受支持的值。
5 指定您的 Azure Stack Hub 运营商提供的 Azure 资源管理器端点。
6 指定包含您的基本域的 DNS 区域的资源组的名称。
7 指定您的 Azure Stack Hub 本地区域的名称。
8 指定要将集群安装到的已存在资源组的名称。如果未定义,则会为集群创建一个新的资源组。
9 指定 Azure Stack Hub 环境作为您的目标平台。
10 指定验证您的集群所需的拉取密钥。
11 是否启用或禁用 FIPS 模式。默认情况下,FIPS 模式未启用。如果启用了 FIPS 模式,则 OpenShift Container Platform 运行的 Red Hat Enterprise Linux CoreOS (RHCOS) 机器将绕过默认的 Kubernetes 加密套件,并改用 RHCOS 提供的加密模块。

要为您的集群启用 FIPS 模式,必须从配置为在 FIPS 模式下运行的 Red Hat Enterprise Linux (RHEL) 计算机运行安装程序。有关在 RHEL 上配置 FIPS 模式的更多信息,请参见 在 FIPS 模式下安装系统

在 FIPS 模式下启动 Red Hat Enterprise Linux (RHEL) 或 Red Hat Enterprise Linux CoreOS (RHCOS) 时,OpenShift Container Platform 核心组件仅在 x86_64、ppc64le 和 s390x 架构上使用已提交给 NIST 用于 FIPS 140-2/140-3 验证的 RHEL 加密库。

12 如果您的 Azure Stack Hub 环境使用内部证书颁发机构 (CA),请添加必要的 .pem 格式的证书捆绑包。
13 您可以选择提供用于访问集群中机器的sshKey值。

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

安装期间配置集群范围的代理

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

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

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

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

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

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

    apiVersion: v1
    baseDomain: my.domain.com
    proxy:
      httpProxy: http://<username>:<pswd>@<ip>:<port> (1)
      httpsProxy: https://<username>:<pswd>@<ip>:<port> (2)
      noProxy: example.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。使用*绕过所有目标的代理。
    4 如果提供,安装程序将生成一个名为user-ca-bundle的 config map,位于openshift-config命名空间中,其中包含一个或多个用于代理 HTTPS 连接所需的附加 CA 证书。集群网络运营商然后创建一个trusted-ca-bundle config map,将这些内容与 Red Hat Enterprise Linux CoreOS (RHCOS) 信任捆绑包合并,并且此 config map 在Proxy对象的trustedCA字段中引用。除非代理的身份证书由 RHCOS 信任捆绑包中的机构签名,否则需要additionalTrustBundle字段。
    5 可选:确定Proxy对象的配置以在trustedCA字段中引用user-ca-bundle config map 的策略。允许的值为ProxyonlyAlways。使用Proxyonly仅在配置http/https代理时引用user-ca-bundle config map。使用Always始终引用user-ca-bundle config map。默认值为Proxyonly

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

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

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

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

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

导出 ARM 模板的公共变量

您必须导出与提供的 Azure 资源管理器 (ARM) 模板一起使用的公共变量集,这些模板用于协助在 Microsoft Azure Stack Hub 上完成用户提供的基础设施安装。

特定 ARM 模板也可能需要其他导出的变量,这些变量在其相关的过程中有详细说明。

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

步骤
  1. 导出install-config.yaml中找到的公共变量,供提供的 ARM 模板使用。

    $ export CLUSTER_NAME=<cluster_name>(1)
    $ export AZURE_REGION=<azure_region>(2)
    $ export SSH_KEY=<ssh_key>(3)
    $ export BASE_DOMAIN=<base_domain>(4)
    $ export BASE_DOMAIN_RESOURCE_GROUP=<base_domain_resource_group>(5)
    1 install-config.yaml文件中.metadata.name属性的值。
    2 将集群部署到的区域。这是install-config.yaml文件中.platform.azure.region属性的值。
    3 作为字符串的 SSH RSA 公钥文件。由于 SSH 密钥包含空格,因此必须将其括在引号中。这是install-config.yaml文件中.sshKey属性的值。
    4 将集群部署到的基本域名。基本域名对应于您为集群创建的 DNS 区域。这是install-config.yaml文件中.baseDomain属性的值。
    5 DNS 区域所在的资源组。这是install-config.yaml文件中.platform.azure.baseDomainResourceGroupName属性的值。

    例如:

    $ export CLUSTER_NAME=test-cluster
    $ export AZURE_REGION=centralus
    $ export SSH_KEY="ssh-rsa xxx/xxx/xxx= [email protected]"
    $ export BASE_DOMAIN=example.com
    $ export BASE_DOMAIN_RESOURCE_GROUP=ocp-cluster
  2. 导出 kubeadmin 凭据

    $ export KUBECONFIG=<installation_directory>/auth/kubeconfig (1)
    1 对于<installation_directory>,请指定您存储安装文件的目录的路径。

创建 Kubernetes 清单和 Ignition 配置文件

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    3. 保存并退出文件。

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

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

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

  7. 可选:如果您的 Azure Stack Hub 环境使用内部证书颁发机构 (CA),则必须更新<安装目录>/manifests/cluster-proxy-01-config.yaml文件中的.spec.trustedCA.name字段以使用user-ca-bundle

    ...
    spec:
      trustedCA:
        name: user-ca-bundle
    ...

    稍后,您必须更新您的 bootstrap ignition 以包含 CA。

  8. 在用户自备基础设施上配置 Azure 时,必须导出清单文件中定义的一些常用变量,以便稍后在 Azure 资源管理器 (ARM) 模板中使用。

    1. 使用以下命令导出基础设施 ID:

      $ export INFRA_ID=<infra_id> (1)
      1 OpenShift Container Platform 集群已分配一个标识符 (INFRA_ID),其格式为<集群名称>-<随机字符串>。这将用作使用提供的 ARM 模板创建的大多数资源的基本名称。这是manifests/cluster-infrastructure-02-config.yml文件中.status.infrastructureName属性的值。
    2. 使用以下命令导出资源组:

      $ export RESOURCE_GROUP=<resource_group> (1)
      1 在此 Azure 部署中创建的所有资源都作为资源组的一部分存在。资源组名称也基于INFRA_ID,格式为<集群名称>-<随机字符串>-rg。这是manifests/cluster-infrastructure-02-config.yml文件中.status.platformStatus.azure.resourceGroupName属性的值。
  9. 手动创建您的云凭据。

    1. 从包含安装程序的目录中,获取您的openshift-install二进制文件构建以使用的 OpenShift Container Platform 发行版映像的详细信息。

      $ openshift-install version
      示例输出
      release image quay.io/openshift-release-dev/ocp-release:4.y.z-x86_64
    2. 通过运行以下命令,使用安装文件中的发行版映像设置$RELEASE_IMAGE变量:

      $ RELEASE_IMAGE=$(./openshift-install version | awk '/release image/ {print $3}')
    3. 通过运行以下命令,从 OpenShift Container Platform 发行版映像中提取CredentialsRequest自定义资源 (CR) 列表:

      $ oc adm release extract \
        --from=$RELEASE_IMAGE \
        --credentials-requests \
        --included \(1)
        --install-config=<path_to_directory_with_installation_configuration>/install-config.yaml \(2)
        --to=<path_to_directory_for_credentials_requests> (3)
      1 --included参数仅包含您的特定集群配置所需的清单。
      2 指定install-config.yaml文件的位置。
      3 指定要存储CredentialsRequest对象的目录的路径。如果指定的目录不存在,则此命令会创建它。

      此命令为每个CredentialsRequest对象创建一个 YAML 文件。

      CredentialsRequest对象示例
      apiVersion: cloudcredential.openshift.io/v1
      kind: CredentialsRequest
      metadata:
        labels:
          controller-tools.k8s.io: "1.0"
        name: openshift-image-registry-azure
        namespace: openshift-cloud-credential-operator
      spec:
        secretRef:
          name: installer-cloud-credentials
          namespace: openshift-image-registry
        providerSpec:
          apiVersion: cloudcredential.openshift.io/v1
          kind: AzureProviderSpec
          roleBindings:
          - role: Contributor
    4. 在您之前生成的openshift-install清单目录中为密钥创建 YAML 文件。必须使用每个CredentialsRequest对象中spec.secretRef中定义的命名空间和密钥名称存储密钥。密钥数据的格式因每个云提供商而异。

      secrets.yaml文件示例
      apiVersion: v1
      kind: Secret
      metadata:
          name: ${secret_name}
          namespace: ${secret_namespace}
      stringData:
        azure_subscription_id: ${subscription_id}
        azure_client_id: ${app_id}
        azure_client_secret: ${client_secret}
        azure_tenant_id: ${tenant_id}
        azure_resource_prefix: ${cluster_name}
        azure_resourcegroup: ${resource_group}
        azure_region: ${azure_region}
    5. 在清单目录中创建一个cco-configmap.yaml文件,其中 Cloud Credential Operator (CCO) 已禁用。

      ConfigMap对象示例
      apiVersion: v1
      kind: ConfigMap
      metadata:
      name: cloud-credential-operator-config
      namespace: openshift-cloud-credential-operator
        annotations:
          release.openshift.io/create-only: "true"
      data:
        disabled: "true"
  10. 要创建 Ignition 配置文件,请从包含安装程序的目录中运行以下命令:

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

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

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

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

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

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

  • /var/lib/containers:保存与容器相关的內容,随着向系统添加更多映像和容器,它可能会增大。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

创建 Azure 资源组

您必须创建一个 Microsoft Azure 资源组。这在您在 Azure Stack Hub 上安装 OpenShift Container Platform 集群期间使用。

步骤
  • 在受支持的 Azure 区域中创建资源组。

    $ az group create --name ${RESOURCE_GROUP} --location ${AZURE_REGION}

上传 RHCOS 集群镜像和引导 Ignition 配置文件

Azure 客户端不支持基于本地现有文件的部署。您必须将 RHCOS 虚拟硬盘 (VHD) 集群镜像和引导 Ignition 配置文件复制并存储在存储容器中,以便在部署期间可以访问它们。

先决条件
  • 为您的集群生成 Ignition 配置文件。

步骤
  1. 创建一个 Azure 存储帐户来存储 VHD 集群镜像。

    $ az storage account create -g ${RESOURCE_GROUP} --location ${AZURE_REGION} --name ${CLUSTER_NAME}sa --kind Storage --sku Standard_LRS

    Azure 存储帐户名称的长度必须在 3 到 24 个字符之间,并且只能使用数字和小写字母。如果您的CLUSTER_NAME变量不符合这些限制,则必须手动定义 Azure 存储帐户名称。有关 Azure 存储帐户名称限制的更多信息,请参阅 Azure 文档中的解决存储帐户名称错误

  2. 将存储帐户密钥导出为环境变量。

    $ export ACCOUNT_KEY=`az storage account keys list -g ${RESOURCE_GROUP} --account-name ${CLUSTER_NAME}sa --query "[0].value" -o tsv`
  3. 将 RHCOS VHD 的 URL 导出为环境变量。

    $ export COMPRESSED_VHD_URL=$(openshift-install coreos print-stream-json | jq -r '.architectures.x86_64.artifacts.azurestack.formats."vhd.gz".disk.location')

    RHCOS 镜像可能不会随着每次 OpenShift Container Platform 版本的发布而更改。您必须指定一个版本号小于或等于您安装的 OpenShift Container Platform 版本的镜像。如果可用,请使用与您的 OpenShift Container Platform 版本匹配的镜像版本。

  4. 为 VHD 创建存储容器。

    $ az storage container create --name vhd --account-name ${CLUSTER_NAME}sa --account-key ${ACCOUNT_KEY}
  5. 在本地下载压缩的 RHCOS VHD 文件。

    $ curl -O -L ${COMPRESSED_VHD_URL}
  6. 解压缩 VHD 文件。

    解压缩后的 VHD 文件大约为 16 GB,因此请确保您的主机系统有 16 GB 的可用空间。上传后,您可以删除 VHD 文件。

  7. 将本地 VHD 复制到 Blob。

    $ az storage blob upload --account-name ${CLUSTER_NAME}sa --account-key ${ACCOUNT_KEY} -c vhd -n "rhcos.vhd" -f rhcos-<rhcos_version>-azurestack.x86_64.vhd
  8. 创建一个 Blob 存储容器并上传生成的bootstrap.ign文件。

    $ az storage container create --name files --account-name ${CLUSTER_NAME}sa --account-key ${ACCOUNT_KEY}
    $ az storage blob upload --account-name ${CLUSTER_NAME}sa --account-key ${ACCOUNT_KEY} -c "files" -f "<installation_directory>/bootstrap.ign" -n "bootstrap.ign"

创建 DNS 区域的示例

使用用户预配的基础架构的集群需要 DNS 记录。您应该选择适合您场景的 DNS 策略。

在此示例中,使用Azure Stack Hub 的数据中心 DNS 集成,因此您将创建一个 DNS 区域。

DNS 区域不需要与集群部署位于同一资源组中,并且可能已存在于您组织中以用于所需的基域。如果是这种情况,您可以跳过创建 DNS 区域;请确保您之前生成的安装配置反映了这种情况。

步骤
  • BASE_DOMAIN_RESOURCE_GROUP环境变量中导出的资源组中创建新的 DNS 区域。

    $ az network dns zone create -g ${BASE_DOMAIN_RESOURCE_GROUP} -n ${CLUSTER_NAME}.${BASE_DOMAIN}

    如果您使用的是已存在的 DNS 区域,则可以跳过此步骤。

您可以通过访问该部分来了解更多关于在 Azure Stack Hub 中配置 DNS 区域的信息。

在 Azure Stack Hub 中创建 VNet

您必须在 Microsoft Azure Stack Hub 中创建一个虚拟网络 (VNet) 供您的 OpenShift Container Platform 集群使用。您可以自定义 VNet 以满足您的要求。创建 VNet 的一种方法是修改提供的 Azure 资源管理器 (ARM) 模板。

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

步骤
  1. 从本主题的“VNet 的 ARM 模板”部分复制模板,并将其另存为安装目录中集群的01_vnet.json。此模板描述了集群所需的 VNet。

  2. 使用az CLI 创建部署。

    $ az deployment group create -g ${RESOURCE_GROUP} \
      --template-file "<installation_directory>/01_vnet.json" \
      --parameters baseName="${INFRA_ID}"(1)
    1 要在资源名称中使用的基本名称;这通常是集群的基础架构 ID。

VNet 的 ARM 模板

您可以使用以下 Azure 资源管理器 (ARM) 模板来部署 OpenShift Container Platform 集群所需的 VNet。

01_vnet.json ARM 模板
{
  "$schema" : "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion" : "1.0.0.0",
  "parameters" : {
    "baseName" : {
      "type" : "string",
      "minLength" : 1,
      "metadata" : {
        "description" : "Base name to be used in resource names (usually the cluster's Infra ID)"
      }
    }
  },
  "variables" : {
    "location" : "[resourceGroup().location]",
    "virtualNetworkName" : "[concat(parameters('baseName'), '-vnet')]",
    "addressPrefix" : "10.0.0.0/16",
    "masterSubnetName" : "[concat(parameters('baseName'), '-master-subnet')]",
    "masterSubnetPrefix" : "10.0.0.0/24",
    "nodeSubnetName" : "[concat(parameters('baseName'), '-worker-subnet')]",
    "nodeSubnetPrefix" : "10.0.1.0/24",
    "clusterNsgName" : "[concat(parameters('baseName'), '-nsg')]"
  },
  "resources" : [
    {
      "apiVersion" : "2017-10-01",
      "type" : "Microsoft.Network/virtualNetworks",
      "name" : "[variables('virtualNetworkName')]",
      "location" : "[variables('location')]",
      "dependsOn" : [
        "[concat('Microsoft.Network/networkSecurityGroups/', variables('clusterNsgName'))]"
      ],
      "properties" : {
        "addressSpace" : {
          "addressPrefixes" : [
            "[variables('addressPrefix')]"
          ]
        },
        "subnets" : [
          {
            "name" : "[variables('masterSubnetName')]",
            "properties" : {
              "addressPrefix" : "[variables('masterSubnetPrefix')]",
              "serviceEndpoints": [],
              "networkSecurityGroup" : {
                "id" : "[resourceId('Microsoft.Network/networkSecurityGroups', variables('clusterNsgName'))]"
              }
            }
          },
          {
            "name" : "[variables('nodeSubnetName')]",
            "properties" : {
              "addressPrefix" : "[variables('nodeSubnetPrefix')]",
              "serviceEndpoints": [],
              "networkSecurityGroup" : {
                "id" : "[resourceId('Microsoft.Network/networkSecurityGroups', variables('clusterNsgName'))]"
              }
            }
          }
        ]
      }
    },
    {
      "type" : "Microsoft.Network/networkSecurityGroups",
      "name" : "[variables('clusterNsgName')]",
      "apiVersion" : "2017-10-01",
      "location" : "[variables('location')]",
      "properties" : {
        "securityRules" : [
          {
            "name" : "apiserver_in",
            "properties" : {
              "protocol" : "Tcp",
              "sourcePortRange" : "*",
              "destinationPortRange" : "6443",
              "sourceAddressPrefix" : "*",
              "destinationAddressPrefix" : "*",
              "access" : "Allow",
              "priority" : 101,
              "direction" : "Inbound"
            }
          },
          {
            "name" : "ign_in",
            "properties" : {
              "protocol" : "*",
              "sourcePortRange" : "*",
              "destinationPortRange" : "22623",
              "sourceAddressPrefix" : "*",
              "destinationAddressPrefix" : "*",
              "access" : "Allow",
              "priority" : 102,
              "direction" : "Inbound"
            }
          }
        ]
      }
    }
  ]
}

为 Azure Stack Hub 基础架构部署 RHCOS 集群镜像

您必须为您的 OpenShift Container Platform 节点使用有效的 Red Hat Enterprise Linux CoreOS (RHCOS) Microsoft Azure Stack Hub 镜像。

先决条件
  • 将 RHCOS 虚拟硬盘 (VHD) 集群镜像存储在 Azure 存储容器中。

  • 将引导 Ignition 配置文件存储在 Azure 存储容器中。

步骤
  1. 从本主题的“镜像存储的 ARM 模板”部分复制模板,并将其另存为安装目录中集群的02_storage.json。此模板描述了集群所需的镜像存储。

  2. 将 RHCOS VHD Blob URL 导出为变量。

    $ export VHD_BLOB_URL=`az storage blob url --account-name ${CLUSTER_NAME}sa --account-key ${ACCOUNT_KEY} -c vhd -n "rhcos.vhd" -o tsv`
  3. 部署集群镜像。

    $ az deployment group create -g ${RESOURCE_GROUP} \
      --template-file "<installation_directory>/02_storage.json" \
      --parameters vhdBlobURL="${VHD_BLOB_URL}" \ (1)
      --parameters baseName="${INFRA_ID}" \ (2)
      --parameters storageAccount="${CLUSTER_NAME}sa" \ (3)
      --parameters architecture="<architecture>" (4)
    
    1 用于创建主节点和工作节点的 RHCOS VHD 的 Blob URL。
    2 要在资源名称中使用的基本名称;这通常是集群的基础架构 ID。
    3 您的 Azure 存储帐户的名称。
    4 指定系统架构。有效值为x64(默认值)或Arm64

镜像存储的 ARM 模板

您可以使用以下 Azure 资源管理器 (ARM) 模板来部署 OpenShift Container Platform 集群所需的已存储的 Red Hat Enterprise Linux CoreOS (RHCOS) 镜像。

02_storage.json ARM 模板
{
  "$schema" : "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion" : "1.0.0.0",
  "parameters" : {
    "baseName" : {
      "type" : "string",
      "minLength" : 1,
      "metadata" : {
        "description" : "Base name to be used in resource names (usually the cluster's Infra ID)"
      }
    },
    "vhdBlobURL" : {
      "type" : "string",
      "metadata" : {
        "description" : "URL pointing to the blob where the VHD to be used to create master and worker machines is located"
      }
    }
  },
  "variables" : {
    "location" : "[resourceGroup().location]",
    "imageName" : "[parameters('baseName')]"
  },
  "resources" : [
    {
      "apiVersion" : "2017-12-01",
      "type": "Microsoft.Compute/images",
      "name": "[variables('imageName')]",
      "location" : "[variables('location')]",
      "properties": {
        "storageProfile": {
          "osDisk": {
            "osType": "Linux",
            "osState": "Generalized",
            "blobUri": "[parameters('vhdBlobURL')]",
            "storageAccountType": "Standard_LRS"
          }
        }
      }
    }
  ]
}

用户预配的基础架构的网络要求

所有 Red Hat Enterprise Linux CoreOS (RHCOS) 机器都需要在启动期间的initramfs中配置网络才能获取其 Ignition 配置文件。

网络连接要求

您必须配置机器之间的网络连接,以允许 OpenShift Container Platform 集群组件进行通信。每台机器必须能够解析集群中所有其他机器的主机名。

本节提供了所需端口的详细信息。

在连接的 OpenShift Container Platform 环境中,所有节点都需要访问互联网才能拉取平台容器的镜像并向 Red Hat 提供遥测数据。

表 1. 所有机器之间通信使用的端口
协议 端口 描述

ICMP

N/A

网络连通性测试

TCP

1936

指标

9000-9999

主机级服务,包括端口 `9100`-`9101` 上的节点导出器和端口 `9099` 上的集群版本操作器。

10250-10259

Kubernetes 保留的默认端口

UDP

4789

VXLAN

6081

Geneve

9000-9999

主机级服务,包括端口 `9100`-`9101` 上的节点导出器。

500

IPsec IKE 数据包

4500

IPsec NAT-T 数据包

123

UDP 端口 `123` 上的网络时间协议 (NTP)

如果配置了外部 NTP 时间服务器,则必须打开 UDP 端口 `123`。

TCP/UDP

30000-32767

Kubernetes 节点端口

ESP

N/A

IPsec 封装安全载荷 (ESP)

表 2. 所有机器到控制平面通信使用的端口
协议 端口 描述

TCP

6443

Kubernetes API

表 3. 控制平面机器到控制平面机器通信使用的端口
协议 端口 描述

TCP

2379-2380

etcd 服务器和对等端口

在 Azure Stack Hub 中创建网络和负载均衡组件

您必须在 Microsoft Azure Stack Hub 中配置网络和负载均衡,才能使用您的 OpenShift Container Platform 集群。创建这些组件的一种方法是修改提供的 Azure 资源管理器 (ARM) 模板。

负载均衡需要以下 DNS 记录

  • DNS 区域中 API 公共负载均衡器的 `api` DNS 记录。

  • DNS 区域中 API 内部负载均衡器的 `api-int` DNS 记录。

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

先决条件
  • 在 Azure Stack Hub 中创建和配置 VNet 和关联的子网。

步骤
  1. 从本主题的“网络和负载均衡器的 ARM 模板”部分复制模板,并将其另存为集群安装目录中的 `03_infra.json`。此模板描述了集群所需的网络和负载均衡对象。

  2. 使用az CLI 创建部署。

    $ az deployment group create -g ${RESOURCE_GROUP} \
      --template-file "<installation_directory>/03_infra.json" \
      --parameters baseName="${INFRA_ID}"(1)
    1 要在资源名称中使用的基本名称;这通常是集群的基础架构 ID。
  3. 创建 `api` DNS 记录和 `api-int` DNS 记录。创建 API DNS 记录时,`${BASE_DOMAIN_RESOURCE_GROUP}` 变量必须指向 DNS 区域所在的资源组。

    1. 导出以下变量

      $ export PUBLIC_IP=`az network public-ip list -g ${RESOURCE_GROUP} --query "[?name=='${INFRA_ID}-master-pip'] | [0].ipAddress" -o tsv`
    2. 导出以下变量

      $ export PRIVATE_IP=`az network lb frontend-ip show -g "$RESOURCE_GROUP" --lb-name "${INFRA_ID}-internal" -n internal-lb-ip --query "privateIpAddress" -o tsv`
    3. 在新 DNS 区域中创建 `api` DNS 记录

      $ az network dns record-set a add-record -g ${BASE_DOMAIN_RESOURCE_GROUP} -z ${CLUSTER_NAME}.${BASE_DOMAIN} -n api -a ${PUBLIC_IP} --ttl 60

      如果将集群添加到现有 DNS 区域,则可以改为在其中创建 `api` DNS 记录

      $ az network dns record-set a add-record -g ${BASE_DOMAIN_RESOURCE_GROUP} -z ${BASE_DOMAIN} -n api.${CLUSTER_NAME} -a ${PUBLIC_IP} --ttl 60
    4. 在新 DNS 区域中创建 `api-int` DNS 记录

      $ az network dns record-set a add-record -g ${BASE_DOMAIN_RESOURCE_GROUP} -z "${CLUSTER_NAME}.${BASE_DOMAIN}" -n api-int -a ${PRIVATE_IP} --ttl 60

      如果将集群添加到现有 DNS 区域,则可以改为在其中创建 `api-int` DNS 记录

      $ az network dns record-set a add-record -g ${BASE_DOMAIN_RESOURCE_GROUP} -z ${BASE_DOMAIN} -n api-int.${CLUSTER_NAME} -a ${PRIVATE_IP} --ttl 60

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

您可以使用以下 Azure 资源管理器 (ARM) 模板部署 OpenShift Container Platform 集群所需的网络对象和负载均衡器

`03_infra.json` ARM 模板
{
  "$schema" : "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion" : "1.0.0.0",
  "parameters" : {
    "baseName" : {
      "type" : "string",
      "minLength" : 1,
      "metadata" : {
        "description" : "Base name to be used in resource names (usually the cluster's Infra ID)"
      }
    }
  },
  "variables" : {
    "location" : "[resourceGroup().location]",
    "virtualNetworkName" : "[concat(parameters('baseName'), '-vnet')]",
    "virtualNetworkID" : "[resourceId('Microsoft.Network/virtualNetworks', variables('virtualNetworkName'))]",
    "masterSubnetName" : "[concat(parameters('baseName'), '-master-subnet')]",
    "masterSubnetRef" : "[concat(variables('virtualNetworkID'), '/subnets/', variables('masterSubnetName'))]",
    "masterPublicIpAddressName" : "[concat(parameters('baseName'), '-master-pip')]",
    "masterPublicIpAddressID" : "[resourceId('Microsoft.Network/publicIPAddresses', variables('masterPublicIpAddressName'))]",
    "masterLoadBalancerName" : "[concat(parameters('baseName'))]",
    "masterLoadBalancerID" : "[resourceId('Microsoft.Network/loadBalancers', variables('masterLoadBalancerName'))]",
    "masterAvailabilitySetName" : "[concat(parameters('baseName'), '-cluster')]",
    "internalLoadBalancerName" : "[concat(parameters('baseName'), '-internal')]",
    "internalLoadBalancerID" : "[resourceId('Microsoft.Network/loadBalancers', variables('internalLoadBalancerName'))]",
    "skuName": "Basic"
  },
  "resources" : [
    {
      "apiVersion": "2017-03-30",
      "type" : "Microsoft.Compute/availabilitySets",
      "name" : "[variables('masterAvailabilitySetName')]",
      "location" : "[variables('location')]",
      "properties": {
        "platformFaultDomainCount": "2",
        "platformUpdateDomainCount": "5"
      },
      "sku": {
        "name": "Aligned"
      }
    },
    {
      "apiVersion" : "2017-10-01",
      "type" : "Microsoft.Network/publicIPAddresses",
      "name" : "[variables('masterPublicIpAddressName')]",
      "location" : "[variables('location')]",
      "sku": {
        "name": "[variables('skuName')]"
      },
      "properties" : {
        "publicIPAllocationMethod" : "Static",
        "dnsSettings" : {
          "domainNameLabel" : "[variables('masterPublicIpAddressName')]"
        }
      }
    },
    {
      "apiVersion" : "2017-10-01",
      "type" : "Microsoft.Network/loadBalancers",
      "name" : "[variables('masterLoadBalancerName')]",
      "location" : "[variables('location')]",
      "sku": {
        "name": "[variables('skuName')]"
      },
      "dependsOn" : [
        "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIpAddressName'))]"
      ],
      "properties" : {
        "frontendIPConfigurations" : [
          {
            "name" : "public-lb-ip",
            "properties" : {
              "publicIPAddress" : {
                "id" : "[variables('masterPublicIpAddressID')]"
              }
            }
          }
        ],
        "backendAddressPools" : [
          {
            "name" : "[variables('masterLoadBalancerName')]"
          }
        ],
        "loadBalancingRules" : [
          {
            "name" : "api-public",
            "properties" : {
              "frontendIPConfiguration" : {
                "id" :"[concat(variables('masterLoadBalancerID'), '/frontendIPConfigurations/public-lb-ip')]"
              },
              "backendAddressPool" : {
                "id" : "[concat(variables('masterLoadBalancerID'), '/backendAddressPools/', variables('masterLoadBalancerName'))]"
              },
              "protocol" : "Tcp",
              "loadDistribution" : "Default",
              "idleTimeoutInMinutes" : 30,
              "frontendPort" : 6443,
              "backendPort" : 6443,
              "probe" : {
                "id" : "[concat(variables('masterLoadBalancerID'), '/probes/api-public-probe')]"
              }
            }
          }
        ],
        "probes" : [
          {
            "name" : "api-public-probe",
            "properties" : {
              "protocol" : "Tcp",
              "port" : 6443,
              "intervalInSeconds" : 10,
              "numberOfProbes" : 3
            }
          }
        ]
      }
    },
    {
      "apiVersion" : "2017-10-01",
      "type" : "Microsoft.Network/loadBalancers",
      "name" : "[variables('internalLoadBalancerName')]",
      "location" : "[variables('location')]",
      "sku": {
        "name": "[variables('skuName')]"
      },
      "properties" : {
        "frontendIPConfigurations" : [
          {
            "name" : "internal-lb-ip",
            "properties" : {
              "privateIPAllocationMethod" : "Dynamic",
              "subnet" : {
                "id" : "[variables('masterSubnetRef')]"
              },
              "privateIPAddressVersion" : "IPv4"
            }
          }
        ],
        "backendAddressPools" : [
          {
            "name" : "[variables('internalLoadBalancerName')]"
          }
        ],
        "loadBalancingRules" : [
          {
            "name" : "api-internal",
            "properties" : {
              "frontendIPConfiguration" : {
                "id" : "[concat(variables('internalLoadBalancerID'), '/frontendIPConfigurations/internal-lb-ip')]"
              },
              "frontendPort" : 6443,
              "backendPort" : 6443,
              "enableFloatingIP" : false,
              "idleTimeoutInMinutes" : 30,
              "protocol" : "Tcp",
              "enableTcpReset" : false,
              "loadDistribution" : "Default",
              "backendAddressPool" : {
                "id" : "[concat(variables('internalLoadBalancerID'), '/backendAddressPools/', variables('internalLoadBalancerName'))]"
              },
              "probe" : {
                "id" : "[concat(variables('internalLoadBalancerID'), '/probes/api-internal-probe')]"
              }
            }
          },
          {
            "name" : "sint",
            "properties" : {
              "frontendIPConfiguration" : {
                "id" : "[concat(variables('internalLoadBalancerID'), '/frontendIPConfigurations/internal-lb-ip')]"
              },
              "frontendPort" : 22623,
              "backendPort" : 22623,
              "enableFloatingIP" : false,
              "idleTimeoutInMinutes" : 30,
              "protocol" : "Tcp",
              "enableTcpReset" : false,
              "loadDistribution" : "Default",
              "backendAddressPool" : {
                "id" : "[concat(variables('internalLoadBalancerID'), '/backendAddressPools/', variables('internalLoadBalancerName'))]"
              },
              "probe" : {
                "id" : "[concat(variables('internalLoadBalancerID'), '/probes/sint-probe')]"
              }
            }
          }
        ],
        "probes" : [
          {
            "name" : "api-internal-probe",
            "properties" : {
              "protocol" : "Tcp",
              "port" : 6443,
              "intervalInSeconds" : 10,
              "numberOfProbes" : 3
            }
          },
          {
            "name" : "sint-probe",
            "properties" : {
              "protocol" : "Tcp",
              "port" : 22623,
              "intervalInSeconds" : 10,
              "numberOfProbes" : 3
            }
          }
        ]
      }
    }
  ]
}

在 Azure Stack Hub 中创建引导机器

您必须在 Microsoft Azure Stack Hub 中创建引导机器,以便在 OpenShift Container Platform 集群初始化期间使用。创建此机器的一种方法是修改提供的 Azure 资源管理器 (ARM) 模板。

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

先决条件
  • 在 Azure Stack Hub 中创建和配置网络和负载均衡器。

步骤
  1. 从本主题的“引导机器的 ARM 模板”部分复制模板,并将其另存为集群安装目录中的 `04_bootstrap.json`。此模板描述了集群所需的引导机器。

  2. 导出引导 URL 变量

    $ bootstrap_url_expiry=`date -u -d "10 hours" '+%Y-%m-%dT%H:%MZ'`
    $ export BOOTSTRAP_URL=`az storage blob generate-sas -c 'files' -n 'bootstrap.ign' --https-only --full-uri --permissions r --expiry $bootstrap_url_expiry --account-name ${CLUSTER_NAME}sa --account-key ${ACCOUNT_KEY} -o tsv`
  3. 导出引导 ignition 变量

    1. 如果您的环境使用公共证书颁发机构 (CA),请运行此命令

      $ export BOOTSTRAP_IGNITION=`jq -rcnM --arg v "3.2.0" --arg url ${BOOTSTRAP_URL} '{ignition:{version:$v,config:{replace:{source:$url}}}}' | base64 | tr -d '\n'`
    2. 如果您的环境使用内部 CA,则必须将您的 PEM 编码包添加到引导 ignition 存根中,以便您的引导虚拟机可以从存储帐户中提取引导 ignition。运行以下命令,这些命令假设您的 CA 位于名为 `CA.pem` 的文件中

      $ export CA="data:text/plain;charset=utf-8;base64,$(cat CA.pem |base64 |tr -d '\n')"
      $ export BOOTSTRAP_IGNITION=`jq -rcnM --arg v "3.2.0" --arg url "$BOOTSTRAP_URL" --arg cert "$CA" '{ignition:{version:$v,security:{tls:{certificateAuthorities:[{source:$cert}]}},config:{replace:{source:$url}}}}' | base64 | tr -d '\n'`
  4. 使用az CLI 创建部署。

    $ az deployment group create --verbose -g ${RESOURCE_GROUP} \
      --template-file "<installation_directory>/04_bootstrap.json" \
      --parameters bootstrapIgnition="${BOOTSTRAP_IGNITION}" \ (1)
      --parameters baseName="${INFRA_ID}" \ (2)
      --parameters diagnosticsStorageAccountName="${CLUSTER_NAME}sa" (3)
    1 引导集群的引导 Ignition 内容。
    2 要在资源名称中使用的基本名称;这通常是集群的基础架构 ID。
    3 集群存储帐户的名称。

引导机器的 ARM 模板

您可以使用以下 Azure 资源管理器 (ARM) 模板部署 OpenShift Container Platform 集群所需的引导机器

`04_bootstrap.json` ARM 模板
{
  "$schema" : "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion" : "1.0.0.0",
  "parameters" : {
    "baseName" : {
      "type" : "string",
      "minLength" : 1,
      "metadata" : {
        "description" : "Base name to be used in resource names (usually the cluster's Infra ID)"
      }
    },
    "bootstrapIgnition" : {
      "type" : "string",
      "minLength" : 1,
      "metadata" : {
        "description" : "Bootstrap ignition content for the bootstrap cluster"
      }
    },
    "sshKeyData" : {
      "type" : "securestring",
      "metadata" : {
        "description" : "SSH RSA public key file as a string."
      }
    },
    "diagnosticsStorageAccountName": {
      "type": "string"
    },
    "bootstrapVMSize" : {
      "type" : "string",
      "defaultValue" : "Standard_DS4_v2",
      "metadata" : {
        "description" : "The size of the Bootstrap Virtual Machine"
      }
    }
  },
  "variables" : {
    "location" : "[resourceGroup().location]",
    "virtualNetworkName" : "[concat(parameters('baseName'), '-vnet')]",
    "virtualNetworkID" : "[resourceId('Microsoft.Network/virtualNetworks', variables('virtualNetworkName'))]",
    "masterSubnetName" : "[concat(parameters('baseName'), '-master-subnet')]",
    "masterSubnetRef" : "[concat(variables('virtualNetworkID'), '/subnets/', variables('masterSubnetName'))]",
    "masterLoadBalancerName" : "[concat(parameters('baseName'))]",
    "masterAvailabilitySetName" : "[concat(parameters('baseName'), '-cluster')]",
    "internalLoadBalancerName" : "[concat(parameters('baseName'), '-internal')]",
    "sshKeyPath" : "/home/core/.ssh/authorized_keys",
    "vmName" : "[concat(parameters('baseName'), '-bootstrap')]",
    "nicName" : "[concat(variables('vmName'), '-nic')]",
    "imageName" : "[parameters('baseName')]",
    "clusterNsgName" : "[concat(parameters('baseName'), '-nsg')]",
    "sshPublicIpAddressName" : "[concat(variables('vmName'), '-ssh-pip')]"
  },
  "resources" : [
    {
      "apiVersion" : "2017-10-01",
      "type" : "Microsoft.Network/publicIPAddresses",
      "name" : "[variables('sshPublicIpAddressName')]",
      "location" : "[variables('location')]",
      "sku": {
        "name": "Basic"
      },
      "properties" : {
        "publicIPAllocationMethod" : "Static",
        "dnsSettings" : {
          "domainNameLabel" : "[variables('sshPublicIpAddressName')]"
        }
      }
    },
    {
      "apiVersion" : "2017-10-01",
      "type" : "Microsoft.Network/networkInterfaces",
      "name" : "[variables('nicName')]",
      "location" : "[variables('location')]",
      "dependsOn" : [
        "[resourceId('Microsoft.Network/publicIPAddresses', variables('sshPublicIpAddressName'))]"
      ],
      "properties" : {
        "securityRules": [
          {
            "properties": {
              "description": "ssh-in-nic",
              "protocol": "Tcp",
              "sourcePortRange": "*",
              "destinationPortRange": "22"
            }}],
        "ipConfigurations" : [
          {
            "name" : "pipConfig",
            "properties" : {
              "privateIPAllocationMethod" : "Dynamic",
              "publicIPAddress": {
                "id": "[resourceId('Microsoft.Network/publicIPAddresses', variables('sshPublicIpAddressName'))]"
              },
              "subnet" : {
                "id" : "[variables('masterSubnetRef')]"
              },
              "loadBalancerBackendAddressPools" : [
                {
                  "id" : "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/loadBalancers/', variables('masterLoadBalancerName'), '/backendAddressPools/', variables('masterLoadBalancerName'))]"
                },
                {
                  "id" : "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/loadBalancers/', variables('internalLoadBalancerName'), '/backendAddressPools/', variables('internalLoadBalancerName'))]"
                }
              ]
            }
          }
        ]
      }
    },
    {
      "name": "[parameters('diagnosticsStorageAccountName')]",
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2017-10-01",
      "location": "[variables('location')]",
      "properties": {},
      "kind": "Storage",
      "sku": {
        "name": "Standard_LRS"
      }
    },
    {
      "apiVersion" : "2017-12-01",
      "type" : "Microsoft.Compute/virtualMachines",
      "name" : "[variables('vmName')]",
      "location" : "[variables('location')]",
      "dependsOn" : [
        "[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]",
        "[concat('Microsoft.Storage/storageAccounts/', parameters('diagnosticsStorageAccountName'))]"
      ],
      "properties" : {
        "availabilitySet": {
          "id": "[resourceId('Microsoft.Compute/availabilitySets',variables('masterAvailabilitySetName'))]"
        },
        "hardwareProfile" : {
          "vmSize" : "[parameters('bootstrapVMSize')]"
        },
        "osProfile" : {
          "computerName" : "[variables('vmName')]",
          "adminUsername" : "core",
          "customData" : "[parameters('bootstrapIgnition')]",
          "linuxConfiguration" : {
            "disablePasswordAuthentication" : true,
            "ssh" : {
              "publicKeys" : [
                {
                  "path" : "[variables('sshKeyPath')]",
                  "keyData" : "[parameters('sshKeyData')]"
                }
              ]
            }
          }
        },
        "storageProfile" : {
          "imageReference": {
            "id": "[resourceId('Microsoft.Compute/images', variables('imageName'))]"
          },
          "osDisk" : {
            "name": "[concat(variables('vmName'),'_OSDisk')]",
            "osType" : "Linux",
            "createOption" : "FromImage",
            "managedDisk": {
              "storageAccountType": "Standard_LRS"
            },
            "diskSizeGB" : 100
          }
        },
        "networkProfile" : {
          "networkInterfaces" : [
            {
              "id" : "[resourceId('Microsoft.Network/networkInterfaces', variables('nicName'))]"
            }
          ]
        },
        "diagnosticsProfile": {
          "bootDiagnostics": {
            "enabled": true,
            "storageUri": "[reference(resourceId('Microsoft.Storage/storageAccounts', parameters('diagnosticsStorageAccountName'))).primaryEndpoints.blob]"
          }
        }
      }
    },
    {
      "apiVersion" : "2017-10-01",
      "type": "Microsoft.Network/networkSecurityGroups/securityRules",
      "name" : "[concat(variables('clusterNsgName'), '/bootstrap_ssh_in')]",
      "location" : "[variables('location')]",
      "dependsOn" : [
        "[resourceId('Microsoft.Compute/virtualMachines', variables('vmName'))]"
      ],
      "properties": {
        "protocol" : "Tcp",
        "sourcePortRange" : "*",
        "destinationPortRange" : "22",
        "sourceAddressPrefix" : "*",
        "destinationAddressPrefix" : "*",
        "access" : "Allow",
        "priority" : 100,
        "direction" : "Inbound"
      }
    }
  ]
}

在 Azure Stack Hub 中创建控制平面机器

您必须在 Microsoft Azure Stack Hub 中创建控制平面机器才能供您的集群使用。创建这些机器的一种方法是修改提供的 Azure 资源管理器 (ARM) 模板。

如果您不使用提供的 ARM 模板来创建控制平面机器,则必须查看所提供的信息并手动创建基础设施。如果您的集群无法正确初始化,请考虑联系 Red Hat 支持并提供您的安装日志。

先决条件
  • 创建引导机器。

步骤
  1. 复制本主题的“控制平面机器的 ARM 模板”部分中的模板,并将其另存为集群安装目录中的 `05_masters.json`。此模板描述了集群所需的控制平面机器。

  2. 导出控制平面机器部署所需的以下变量

    $ export MASTER_IGNITION=`cat <installation_directory>/master.ign | base64 | tr -d '\n'`
  3. 使用az CLI 创建部署。

    $ az deployment group create -g ${RESOURCE_GROUP} \
      --template-file "<installation_directory>/05_masters.json" \
      --parameters masterIgnition="${MASTER_IGNITION}" \ (1)
      --parameters baseName="${INFRA_ID}" \ (2)
      --parameters diagnosticsStorageAccountName="${CLUSTER_NAME}sa" (3)
    1 控制平面节点(也称为主节点)的 Ignition 内容。
    2 要在资源名称中使用的基本名称;这通常是集群的基础架构 ID。
    3 集群存储帐户的名称。

控制平面机器的 ARM 模板

您可以使用以下 Azure 资源管理器 (ARM) 模板部署 OpenShift Container Platform 集群所需的控制平面机器

`05_masters.json` ARM 模板
{
  "$schema" : "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion" : "1.0.0.0",
  "parameters" : {
    "baseName" : {
      "type" : "string",
      "minLength" : 1,
      "metadata" : {
        "description" : "Base name to be used in resource names (usually the cluster's Infra ID)"
      }
    },
    "masterIgnition" : {
      "type" : "string",
      "metadata" : {
        "description" : "Ignition content for the master nodes"
      }
    },
    "sshKeyData" : {
      "type" : "securestring",
      "metadata" : {
        "description" : "SSH RSA public key file as a string"
      }
    },
    "diagnosticsStorageAccountName": {
      "type": "string"
    },
    "masterVMSize" : {
      "type" : "string",
      "defaultValue" : "Standard_DS4_v2",
      "metadata" : {
        "description" : "The size of the Master Virtual Machines"
      }
    },
    "diskSizeGB" : {
      "type" : "int",
      "defaultValue" : 1023,
      "metadata" : {
        "description" : "Size of the Master VM OS disk, in GB"
      }
    }
  },
  "variables" : {
    "location" : "[resourceGroup().location]",
    "virtualNetworkName" : "[concat(parameters('baseName'), '-vnet')]",
    "virtualNetworkID" : "[resourceId('Microsoft.Network/virtualNetworks', variables('virtualNetworkName'))]",
    "masterSubnetName" : "[concat(parameters('baseName'), '-master-subnet')]",
    "masterSubnetRef" : "[concat(variables('virtualNetworkID'), '/subnets/', variables('masterSubnetName'))]",
    "masterLoadBalancerName" : "[concat(parameters('baseName'))]",
    "masterAvailabilitySetName" : "[concat(parameters('baseName'), '-cluster')]",
    "internalLoadBalancerName" : "[concat(parameters('baseName'), '-internal')]",
    "sshKeyPath" : "/home/core/.ssh/authorized_keys",
    "clusterNsgName" : "[concat(parameters('baseName'), '-nsg')]",
    "imageName" : "[parameters('baseName')]",
    "numberOfMasters" : 3,
    "vms" : {
      "copy" : [
        {
          "name" : "vmNames",
          "count" :  "[variables('numberOfMasters')]",
          "input" : {
            "name" : "[concat(parameters('baseName'), string('-master-'), string(copyIndex('vmNames')))]"
          }
        }
      ]
    }
  },
  "resources" : [
    {
      "name": "[parameters('diagnosticsStorageAccountName')]",
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2017-10-01",
      "location": "[variables('location')]",
      "properties": {},
      "kind": "Storage",
      "sku": {
        "name": "Standard_LRS"
      }
    },
    {
      "apiVersion" : "2017-10-01",
      "type" : "Microsoft.Network/networkInterfaces",
      "location": "[variables('location')]",
      "copy" : {
        "name" : "nicCopy",
        "count" : "[variables('numberOfMasters')]"
      },
      "name" : "[concat(variables('vms').vmNames[copyIndex()].name, '-nic')]",
      "properties" : {
        "ipConfigurations" : [
          {
            "name" : "pipConfig",
            "properties" : {
              "privateIPAllocationMethod" : "Dynamic",
              "subnet" : {
                "id" : "[variables('masterSubnetRef')]"
              },
              "loadBalancerBackendAddressPools" : [
                {
                  "id" : "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/loadBalancers/', variables('masterLoadBalancerName'), '/backendAddressPools/', variables('masterLoadBalancerName'))]"
                },
                {
                  "id" : "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/loadBalancers/', variables('internalLoadBalancerName'), '/backendAddressPools/', variables('internalLoadBalancerName'))]"
                }
              ]
            }
          }
        ]
      }
    },
    {
      "apiVersion" : "2017-12-01",
      "type" : "Microsoft.Compute/virtualMachines",
      "location" : "[variables('location')]",
      "copy" : {
        "name" : "vmCopy",
        "count" : "[variables('numberOfMasters')]"
      },
      "name" : "[variables('vms').vmNames[copyIndex()].name]",
      "dependsOn" : [
        "[concat('Microsoft.Network/networkInterfaces/', concat(variables('vms').vmNames[copyIndex()].name, '-nic'))]",
        "[concat('Microsoft.Storage/storageAccounts/', parameters('diagnosticsStorageAccountName'))]"
      ],
      "properties" : {
        "availabilitySet": {
          "id": "[resourceId('Microsoft.Compute/availabilitySets',variables('masterAvailabilitySetName'))]"
        },
        "hardwareProfile" : {
          "vmSize" : "[parameters('masterVMSize')]"
        },
        "osProfile" : {
          "computerName" : "[variables('vms').vmNames[copyIndex()].name]",
          "adminUsername" : "core",
          "customData" : "[parameters('masterIgnition')]",
          "linuxConfiguration" : {
            "disablePasswordAuthentication" : true,
            "ssh" : {
              "publicKeys" : [
                {
                  "path" : "[variables('sshKeyPath')]",
                  "keyData" : "[parameters('sshKeyData')]"
                }
              ]
            }
          }
        },
        "storageProfile" : {
          "imageReference": {
            "id": "[resourceId('Microsoft.Compute/images', variables('imageName'))]"
          },
          "osDisk" : {
            "name": "[concat(variables('vms').vmNames[copyIndex()].name, '_OSDisk')]",
            "osType" : "Linux",
            "createOption" : "FromImage",
            "writeAcceleratorEnabled": false,
            "managedDisk": {
              "storageAccountType": "Standard_LRS"
            },
            "diskSizeGB" : "[parameters('diskSizeGB')]"
          }
        },
        "networkProfile" : {
          "networkInterfaces" : [
            {
              "id" : "[resourceId('Microsoft.Network/networkInterfaces', concat(variables('vms').vmNames[copyIndex()].name, '-nic'))]",
              "properties": {
                "primary": false
              }
            }
          ]
        },
        "diagnosticsProfile": {
          "bootDiagnostics": {
            "enabled": true,
            "storageUri": "[reference(resourceId('Microsoft.Storage/storageAccounts', parameters('diagnosticsStorageAccountName'))).primaryEndpoints.blob]"
          }
        }
      }
    }
  ]
}

等待引导完成并在 Azure Stack Hub 中删除引导资源

在 Microsoft Azure Stack Hub 中创建所有必需的基础设施后,请等待引导过程在您使用生成的 Ignition 配置文件配置的机器上完成。安装程序。

先决条件
  • 创建控制平面机器。

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

    $ ./openshift-install wait-for bootstrap-complete --dir <installation_directory> \ (1)
        --log-level info (2)
    
    1 对于<installation_directory>,请指定您存储安装文件的目录的路径。
    2 要查看不同的安装详细信息,请指定 `warn`、`debug` 或 `error` 代替 `info`。

    如果命令退出时没有 `FATAL` 警告,则您的生产控制平面已初始化。

  2. 删除引导资源

    $ az network nsg rule delete -g ${RESOURCE_GROUP} --nsg-name ${INFRA_ID}-nsg --name bootstrap_ssh_in
    $ az vm stop -g ${RESOURCE_GROUP} --name ${INFRA_ID}-bootstrap
    $ az vm deallocate -g ${RESOURCE_GROUP} --name ${INFRA_ID}-bootstrap
    $ az vm delete -g ${RESOURCE_GROUP} --name ${INFRA_ID}-bootstrap --yes
    $ az disk delete -g ${RESOURCE_GROUP} --name ${INFRA_ID}-bootstrap_OSDisk --no-wait --yes
    $ az network nic delete -g ${RESOURCE_GROUP} --name ${INFRA_ID}-bootstrap-nic --no-wait
    $ az storage blob delete --account-key ${ACCOUNT_KEY} --account-name ${CLUSTER_NAME}sa --container-name files --name bootstrap.ign
    $ az network public-ip delete -g ${RESOURCE_GROUP} --name ${INFRA_ID}-bootstrap-ssh-pip

如果您不删除引导服务器,则由于 API 流量被路由到引导服务器,安装可能无法成功。

在 Azure Stack Hub 中创建其他工作机器

您可以通过单独启动实例或通过集群外的自动化流程(例如自动缩放组)在 Microsoft Azure Stack Hub 中创建供集群使用的工作机器。您还可以利用 OpenShift Container Platform 中内置的集群缩放机制和机器 API。

在此示例中,您使用 Azure 资源管理器 (ARM) 模板手动启动一个实例。可以通过在文件中包含其他类型为 `06_workers.json` 的资源来启动其他实例。

如果您不使用提供的 ARM 模板来创建控制平面机器,则必须查看所提供的信息并手动创建基础设施。如果您的集群无法正确初始化,请考虑联系 Red Hat 支持并提供您的安装日志。

步骤
  1. 从本主题的“工作机器的 ARM 模板”部分复制模板,并将其另存为集群安装目录中的 `06_workers.json`。此模板描述了集群所需的工作机器。

  2. 导出工作机器部署所需的以下变量

    $ export WORKER_IGNITION=`cat <installation_directory>/worker.ign | base64 | tr -d '\n'`
  3. 使用az CLI 创建部署。

    $ az deployment group create -g ${RESOURCE_GROUP} \
      --template-file "<installation_directory>/06_workers.json" \
      --parameters workerIgnition="${WORKER_IGNITION}" \ (1)
      --parameters baseName="${INFRA_ID}" (2)
      --parameters diagnosticsStorageAccountName="${CLUSTER_NAME}sa" (3)
    1 工作节点的 Ignition 内容。
    2 要在资源名称中使用的基本名称;这通常是集群的基础架构 ID。
    3 集群存储帐户的名称。

用于工作机的 ARM 模板

您可以使用以下 Azure 资源管理器 (ARM) 模板部署 OpenShift Container Platform 集群所需的工作机。

06_workers.json ARM 模板
{
  "$schema" : "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion" : "1.0.0.0",
  "parameters" : {
    "baseName" : {
      "type" : "string",
      "minLength" : 1,
      "metadata" : {
        "description" : "Base name to be used in resource names (usually the cluster's Infra ID)"
      }
    },
    "workerIgnition" : {
      "type" : "string",
      "metadata" : {
        "description" : "Ignition content for the worker nodes"
      }
    },
    "numberOfNodes" : {
      "type" : "int",
      "defaultValue" : 3,
      "minValue" : 2,
      "maxValue" : 30,
      "metadata" : {
        "description" : "Number of OpenShift compute nodes to deploy"
      }
    },
    "sshKeyData" : {
      "type" : "securestring",
      "metadata" : {
        "description" : "SSH RSA public key file as a string"
      }
    },
    "diagnosticsStorageAccountName": {
      "type": "string"
    },
    "nodeVMSize" : {
      "type" : "string",
      "defaultValue" : "Standard_DS4_v2",
      "metadata" : {
        "description" : "The size of the each Node Virtual Machine"
      }
    }
  },
  "variables" : {
    "location" : "[resourceGroup().location]",
    "virtualNetworkName" : "[concat(parameters('baseName'), '-vnet')]",
    "virtualNetworkID" : "[resourceId('Microsoft.Network/virtualNetworks', variables('virtualNetworkName'))]",
    "nodeSubnetName" : "[concat(parameters('baseName'), '-worker-subnet')]",
    "nodeSubnetRef" : "[concat(variables('virtualNetworkID'), '/subnets/', variables('nodeSubnetName'))]",
    "infraLoadBalancerName" : "[parameters('baseName')]",
    "sshKeyPath" : "/home/core/.ssh/authorized_keys",
    "imageName" : "[parameters('baseName')]",
    "masterAvailabilitySetName" : "[concat(parameters('baseName'), '-cluster')]",
    "numberOfNodes" : "[parameters('numberOfNodes')]",
    "vms" : {
      "copy" : [
        {
        "name" : "vmNames",
        "count" :  "[parameters('numberOfNodes')]",
        "input" : {
            "name" : "[concat(parameters('baseName'), string('-worker-'), string(copyIndex('vmNames')))]"
        }
      }
    ]
  }
  },
  "resources" : [
    {
      "name": "[parameters('diagnosticsStorageAccountName')]",
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2017-10-01",
      "location": "[variables('location')]",
      "properties": {},
      "kind": "Storage",
      "sku": {
        "name": "Standard_LRS"
      }
    },
    {
      "apiVersion" : "2017-10-01",
      "type" : "Microsoft.Network/networkInterfaces",
      "location": "[variables('location')]",
      "copy" : {
        "name" : "nicCopy",
        "count" : "[variables('numberOfNodes')]"
      },
      "name" : "[concat(variables('vms').vmNames[copyIndex()].name, '-nic')]",
      "properties" : {
        "ipConfigurations" : [
          {
            "name" : "pipConfig",
            "properties" : {
              "privateIPAllocationMethod" : "Dynamic",
              "subnet" : {
                "id" : "[variables('nodeSubnetRef')]"
              }
            }
          }
        ]
      }
    },
    {
      "apiVersion" : "2017-12-01",
      "type" : "Microsoft.Compute/virtualMachines",
      "location" : "[variables('location')]",
      "copy" : {
        "name" : "vmCopy",
        "count" : "[variables('numberOfNodes')]"
      },
      "name" : "[variables('vms').vmNames[copyIndex()].name]",
      "dependsOn" : [
        "[concat('Microsoft.Network/networkInterfaces/', concat(variables('vms').vmNames[copyIndex()].name, '-nic'))]",
        "[concat('Microsoft.Storage/storageAccounts/', parameters('diagnosticsStorageAccountName'))]"
      ],
      "properties" : {
        "availabilitySet": {
          "id": "[resourceId('Microsoft.Compute/availabilitySets',variables('masterAvailabilitySetName'))]"
        },
        "hardwareProfile" : {
          "vmSize" : "[parameters('nodeVMSize')]"
        },
        "osProfile" : {
          "computerName" : "[variables('vms').vmNames[copyIndex()].name]",
          "adminUsername" : "core",
          "customData" : "[parameters('workerIgnition')]",
          "linuxConfiguration" : {
            "disablePasswordAuthentication" : true,
            "ssh" : {
              "publicKeys" : [
                {
                  "path" : "[variables('sshKeyPath')]",
                  "keyData" : "[parameters('sshKeyData')]"
                }
              ]
            }
          }
        },
        "storageProfile" : {
          "imageReference": {
            "id": "[resourceId('Microsoft.Compute/images', variables('imageName'))]"
          },
          "osDisk" : {
            "name": "[concat(variables('vms').vmNames[copyIndex()].name,'_OSDisk')]",
            "osType" : "Linux",
            "createOption" : "FromImage",
            "managedDisk": {
              "storageAccountType": "Standard_LRS"
            },
            "diskSizeGB": 128
          }
        },
        "networkProfile" : {
          "networkInterfaces" : [
            {
              "id" : "[resourceId('Microsoft.Network/networkInterfaces', concat(variables('vms').vmNames[copyIndex()].name, '-nic'))]",
              "properties": {
                "primary": true
              }
            }
          ]
        },
        "diagnosticsProfile": {
          "bootDiagnostics": {
            "enabled": true,
            "storageUri": "[reference(resourceId('Microsoft.Storage/storageAccounts', parameters('diagnosticsStorageAccountName'))).primaryEndpoints.blob]"
          }
        }
      }
    }
  ]
}

使用 CLI 登录集群

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

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

  • 您已安装oc CLI。

步骤
  1. 导出kubeadmin凭据

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

    $ oc whoami
    示例输出
    system:admin

批准机器的证书签名请求

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

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

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

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

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

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

  2. 查看待处理的 CSR,并确保您看到为添加到集群的每台机器的客户端请求显示“待处理”或“已批准”状态。

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

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

  3. 如果 CSR 未批准,在您添加的所有机器的待处理 CSR 都处于“待处理”状态后,请批准集群机器的 CSR。

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

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

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

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

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

      在批准一些 CSR 之前,某些运算符可能无法使用。

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

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

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

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

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

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

    批准服务器 CSR 后,机器可能需要几分钟才能转换为“就绪”状态。

其他信息

添加 Ingress DNS 记录

如果您在创建 Kubernetes 清单和生成 Ignition 配置时删除了 DNS 区域配置,则必须手动创建指向 Ingress 负载均衡器的 DNS 记录。您可以创建通配符*.apps.{baseDomain}.或特定记录。您可以根据您的需求使用 A、CNAME 和其他记录。

先决条件
  • 您已使用您预配的基础结构在 Microsoft Azure Stack Hub 上部署了 OpenShift Container Platform 集群。

  • 安装 OpenShift CLI (oc)。

  • 安装或更新 Azure CLI

步骤
  1. 确认 Ingress 路由器已创建负载均衡器并填充了EXTERNAL-IP字段

    $ oc -n openshift-ingress get service router-default
    示例输出
    NAME             TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)                      AGE
    router-default   LoadBalancer   172.30.20.10   35.130.120.110   80:32288/TCP,443:31215/TCP   20
  2. 将 Ingress 路由器 IP 导出为变量

    $ export PUBLIC_IP_ROUTER=`oc -n openshift-ingress get service router-default --no-headers | awk '{print $4}'`
  3. 向 DNS 区域添加*.apps记录。

    1. 如果您要将此集群添加到新的 DNS 区域,请运行

      $ az network dns record-set a add-record -g ${BASE_DOMAIN_RESOURCE_GROUP} -z ${CLUSTER_NAME}.${BASE_DOMAIN} -n *.apps -a ${PUBLIC_IP_ROUTER} --ttl 300
    2. 如果您要将此集群添加到已存在的 DNS 区域,请运行

      $ az network dns record-set a add-record -g ${BASE_DOMAIN_RESOURCE_GROUP} -z ${BASE_DOMAIN} -n *.apps.${CLUSTER_NAME} -a ${PUBLIC_IP_ROUTER} --ttl 300

如果您更愿意添加显式域名而不是使用通配符,您可以为集群的每个当前路由创建条目

$ oc get --all-namespaces -o jsonpath='{range .items[*]}{range .status.ingress[*]}{.host}{"\n"}{end}{end}' routes
示例输出
oauth-openshift.apps.cluster.basedomain.com
console-openshift-console.apps.cluster.basedomain.com
downloads-openshift-console.apps.cluster.basedomain.com
alertmanager-main-openshift-monitoring.apps.cluster.basedomain.com
prometheus-k8s-openshift-monitoring.apps.cluster.basedomain.com

完成用户预配基础结构上的 Azure Stack Hub 安装

在 Microsoft Azure Stack Hub 用户预配基础结构上启动 OpenShift Container Platform 安装后,您可以监视集群事件,直到集群准备就绪。

先决条件
  • 为用户预配的 Azure Stack Hub 基础结构上的 OpenShift Container Platform 集群部署引导程序机器。

  • 安装oc CLI 并登录。

步骤
  • 完成集群安装

    $ ./openshift-install --dir <installation_directory> wait-for install-complete (1)
    示例输出
    INFO Waiting up to 30m0s for the cluster to initialize...
    1 对于<installation_directory>,请指定您存储安装文件的目录的路径。
    • 安装程序生成的 Ignition 配置文件包含 24 小时后过期的证书,然后在该时间续订。如果集群在续订证书之前关闭,并且集群在 24 小时后重新启动,则集群会自动恢复过期的证书。例外情况是,您必须手动批准待处理的node-bootstrapper证书签名请求 (CSR) 以恢复 kubelet 证书。有关详细信息,请参阅有关“从过期的控制平面证书中恢复”的文档。

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