Este contenido no está disponible en el idioma seleccionado.

Chapter 4. Deploying hosted control planes


4.1. Deploying hosted control planes on AWS

To reduce infrastructure costs and improve cluster management efficiency, you can deploy hosted control planes on AWS. This configuration decouples the control plane from the data plane so that you can manage multiple clusters from a central management service.

A hosted cluster is an OpenShift Container Platform cluster with its API endpoint and control plane that are hosted on the management cluster. The hosted cluster includes the control plane and its corresponding data plane. To configure hosted control planes on premises, you must install multicluster engine for Kubernetes Operator in a management cluster. By deploying the HyperShift Operator on an existing managed cluster by using the hypershift-addon managed cluster add-on, you can enable that cluster as a management cluster and start to create the hosted cluster. The hypershift-addon managed cluster add-on is enabled by default for the local-cluster managed cluster.

You can use the multicluster engine Operator console or the hosted control plane command-line interface (CLI), hcp, to create a hosted cluster. The hosted cluster is automatically imported as a managed cluster. However, you can disable this automatic import feature into multicluster engine Operator.

4.1.1. Preparing to deploy hosted control planes on AWS

Preparing to deploy hosted control planes on Amazon Web Services (AWS) involves meeting several prerequisites and creating resources, including an S3 bucket, an OIDC secret, a routable public zone, IAM role and STS credentials.

4.1.1.1. Prerequisites to deploy hosted control planes on AWS

To ensure successful deployment of hosted control planes on Amazon Web Services (AWS), your environment must meet the following requirements.

  • You installed the multicluster engine for Kubernetes Operator 2.5 and later on an OpenShift Container Platform cluster. The multicluster engine Operator is automatically installed when you install Red Hat Advanced Cluster Management (RHACM). The multicluster engine Operator can also be installed without RHACM as an Operator from the OpenShift Container Platform software catalog.
  • You have at least one managed OpenShift Container Platform cluster for the multicluster engine Operator. The local-cluster is automatically imported in the multicluster engine Operator version 2.5 and later. You can check the status of your hub cluster by running the following command:

    $ oc get managedclusters local-cluster
  • You installed the aws command-line interface (CLI).
  • You installed the hosted control plane CLI, hcp.
Important
  • Run the management cluster and compute nodes on the same platform.
  • For each hosted cluster, provide a cluster-wide unique name. A hosted cluster name cannot be the same as any existing managed cluster in order for multicluster engine Operator to manage it.
  • Do not use clusters as a hosted cluster name.
  • Do not create a hosted cluster in the namespace of a multicluster engine Operator managed cluster.

Before you can create and manage a hosted cluster on Amazon Web Services (AWS), you must create the S3 bucket and S3 OIDC secret. These resources provide a place for the cluster to store information about itself and a way for the cluster to prove its identity to AWS.

Procedure

  1. Create an S3 bucket that has public access to host OIDC discovery documents for your clusters.

    1. Enter the following command:

      $ aws s3api create-bucket --bucket <bucket_name> \
        --create-bucket-configuration LocationConstraint=<region> \
        --region <region> 
      1

      where:

      <bucket_name>
      Specifies the name of the S3 bucket you are creating.
      <region>
      Specifies that you want to create the bucket in a region other than the us-east-1 region. Include this line and replace <region> with the region you want to use. To create a bucket in the us-east-1 region, omit this line.
    2. Enter the following command:

      $ aws s3api delete-public-access-block --bucket <bucket_name>

      Replace <bucket_name> with the name of the S3 bucket you are creating.

    3. Enter the following command:

      $ echo '{
          "Version": "2012-10-17",
          "Statement": [
              {
                  "Effect": "Allow",
                  "Principal": "*",
                  "Action": "s3:GetObject",
                  "Resource": "arn:aws:s3:::<bucket_name>/*"
              }
          ]
      }' | envsubst > policy.json

      Replace <bucket_name> with the name of the S3 bucket you are creating.

    4. Enter the following command:

      $ aws s3api put-bucket-policy --bucket <bucket_name> \
        --policy file://policy.json

      Replace <bucket_name> with the name of the S3 bucket you are creating.

      Note

      If you are using a Mac computer, you must export the bucket name in order for the policy to work.

  2. Create an OIDC S3 secret named hypershift-operator-oidc-provider-s3-credentials for the HyperShift Operator.
  3. Save the secret in the local-cluster namespace.
  4. See the following table to verify that the secret contains the following fields:

    Expand
    Table 4.1. Required fields for the AWS secret
    Field nameDescription

    bucket

    Contains an S3 bucket with public access to host OIDC discovery documents for your hosted clusters.

    credentials

    A reference to a file that contains the credentials of the default profile that can access the bucket. By default, HyperShift only uses the default profile to operate the bucket.

    region

    Specifies the region of the S3 bucket.

  5. To create an AWS secret, run the following command:

    $ oc create secret generic <secret_name> \
      --from-file=credentials=<path>/.aws/credentials \
      --from-literal=bucket=<s3_bucket> \
      --from-literal=region=<region> \
      -n local-cluster
    Note

    Disaster recovery backup for the secret is not automatically enabled. To add the label that enables the hypershift-operator-oidc-provider-s3-credentials secret to be backed up for disaster recovery, run the following command:

    $ oc label secret hypershift-operator-oidc-provider-s3-credentials \
      -n local-cluster cluster.open-cluster-management.io/backup=true

4.1.1.3. Creating a routable public zone for hosted clusters

In order to access applications in your hosted clusters, you must configure the routable public zone.

If the public zone exists, skip this step. Otherwise, the public zone affects the existing functions.

Procedure

  • To create a routable public zone for DNS records, enter the following command:

    $ aws route53 create-hosted-zone \
      --name <basedomain> \
      --caller-reference $(whoami)-$(date --rfc-3339=date)

    Replace <basedomain> with your base domain, for example, www.example.com.

4.1.1.4. Creating an AWS IAM role and STS credentials

Before you create a hosted cluster on Amazon Web Services (AWS), you must create an AWS IAM role and STS credentials.

Procedure

  1. Get the Amazon Resource Name (ARN) of your user by running the following command:

    $ aws sts get-caller-identity --query "Arn" --output text

    Example output

    arn:aws:iam::1234567890:user/<aws_username>

    Use this output as the value for the <arn> value in the next step.

  2. Create a JSON file that contains the trust relationship configuration for your role. See the following example:

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Principal": {
                    "AWS": "<arn>"
                },
                "Action": "sts:AssumeRole"
            }
        ]
    }

    Replace <arn> with the ARN of your user that you noted in the previous step.

  3. Create the Identity and Access Management (IAM) role by running the following command:

    $ aws iam create-role \
      --role-name <name> \
      --assume-role-policy-document file://<file_name>.json \
      --query "Role.Arn"

    where:

    <name>
    Specifies the role name, for example, hcp-cli-role.
    <file_name>
    Specifies the name of the JSON file you created in the previous step.

    Example output

    arn:aws:iam::820196288204:role/myrole

  4. Create a JSON file named policy.json that contains the following permission policies for your role:

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "EC2",
                "Effect": "Allow",
                "Action": [
                    "ec2:CreateDhcpOptions",
                    "ec2:DeleteSubnet",
                    "ec2:ReplaceRouteTableAssociation",
                    "ec2:DescribeAddresses",
                    "ec2:DescribeInstances",
                    "ec2:DeleteVpcEndpoints",
                    "ec2:CreateNatGateway",
                    "ec2:CreateVpc",
                    "ec2:DescribeDhcpOptions",
                    "ec2:AttachInternetGateway",
                    "ec2:DeleteVpcEndpointServiceConfigurations",
                    "ec2:DeleteRouteTable",
                    "ec2:AssociateRouteTable",
                    "ec2:DescribeInternetGateways",
                    "ec2:DescribeAvailabilityZones",
                    "ec2:CreateRoute",
                    "ec2:CreateInternetGateway",
                    "ec2:RevokeSecurityGroupEgress",
                    "ec2:ModifyVpcAttribute",
                    "ec2:DeleteInternetGateway",
                    "ec2:DescribeVpcEndpointConnections",
                    "ec2:RejectVpcEndpointConnections",
                    "ec2:DescribeRouteTables",
                    "ec2:ReleaseAddress",
                    "ec2:AssociateDhcpOptions",
                    "ec2:TerminateInstances",
                    "ec2:CreateTags",
                    "ec2:DeleteRoute",
                    "ec2:CreateRouteTable",
                    "ec2:DetachInternetGateway",
                    "ec2:DescribeVpcEndpointServiceConfigurations",
                    "ec2:DescribeNatGateways",
                    "ec2:DisassociateRouteTable",
                    "ec2:AllocateAddress",
                    "ec2:DescribeSecurityGroups",
                    "ec2:RevokeSecurityGroupIngress",
                    "ec2:CreateVpcEndpoint",
                    "ec2:DescribeVpcs",
                    "ec2:DeleteSecurityGroup",
                    "ec2:DeleteDhcpOptions",
                    "ec2:DeleteNatGateway",
                    "ec2:DescribeVpcEndpoints",
                    "ec2:DeleteVpc",
                    "ec2:CreateSubnet",
                    "ec2:DescribeSubnets"
                ],
                "Resource": "*"
            },
            {
                "Sid": "ELB",
                "Effect": "Allow",
                "Action": [
                    "elasticloadbalancing:DeleteLoadBalancer",
                    "elasticloadbalancing:DescribeLoadBalancers",
                    "elasticloadbalancing:DescribeTargetGroups",
                    "elasticloadbalancing:DeleteTargetGroup"
                ],
                "Resource": "*"
            },
            {
                "Sid": "IAMPassRole",
                "Effect": "Allow",
                "Action": "iam:PassRole",
                "Resource": "arn:*:iam::*:role/*-worker-role",
                "Condition": {
                    "ForAnyValue:StringEqualsIfExists": {
                        "iam:PassedToService": "ec2.amazonaws.com"
                    }
                }
            },
            {
                "Sid": "IAM",
                "Effect": "Allow",
                "Action": [
                    "iam:CreateInstanceProfile",
                    "iam:DeleteInstanceProfile",
                    "iam:GetRole",
                    "iam:UpdateAssumeRolePolicy",
                    "iam:GetInstanceProfile",
                    "iam:TagRole",
                    "iam:RemoveRoleFromInstanceProfile",
                    "iam:CreateRole",
                    "iam:DeleteRole",
                    "iam:PutRolePolicy",
                    "iam:AddRoleToInstanceProfile",
                    "iam:CreateOpenIDConnectProvider",
                    "iam:ListOpenIDConnectProviders",
                    "iam:DeleteRolePolicy",
                    "iam:UpdateRole",
                    "iam:DeleteOpenIDConnectProvider",
                    "iam:GetRolePolicy"
                ],
                "Resource": "*"
            },
            {
                "Sid": "Route53",
                "Effect": "Allow",
                "Action": [
                    "route53:ListHostedZonesByVPC",
                    "route53:CreateHostedZone",
                    "route53:ListHostedZones",
                    "route53:ChangeResourceRecordSets",
                    "route53:ListResourceRecordSets",
                    "route53:DeleteHostedZone",
                    "route53:AssociateVPCWithHostedZone",
                    "route53:ListHostedZonesByName"
                ],
                "Resource": "*"
            },
            {
                "Sid": "S3",
                "Effect": "Allow",
                "Action": [
                    "s3:ListAllMyBuckets",
                    "s3:ListBucket",
                    "s3:DeleteObject",
                    "s3:DeleteBucket"
                ],
                "Resource": "*"
            }
        ]
    }
  5. Attach the policy.json file that contains the permissions policies for your role by running the following command:

    $ aws iam put-role-policy \
      --role-name <role_name> \
      --policy-name <policy_name> \
      --policy-document file://policy.json

    where:

    <role_name>
    Specifies the name of your role.
    <policy_name>
    Specifies your policy name.
  6. Retrieve STS credentials in a JSON file named sts-creds.json by running the following command:

    $ aws sts get-session-token --output json > sts-creds.json

    Example sts-creds.json file

    {
        "Credentials": {
            "AccessKeyId": "<access_key_id",
            "SecretAccessKey": "<secret_access_key>”,
            "SessionToken": "<session_token>",
            "Expiration": "<time_stamp>"
        }
    }

4.1.2. Enabling external DNS for hosted control planes on AWS

To automate the management of DNS records, you can enable external DNS. By configuring this feature, you provide a way for the cluster to update your AWS Route 53 public hosted zones automatically when you create or delete services and ingresses.

The control plane and the data plane are separate in hosted control planes. You can configure DNS in two independent areas:

  • Ingress for workloads within the hosted cluster, such as the following domain: *.apps.service-consumer-domain.com.
  • Ingress for service endpoints within the management cluster, such as API or OAuth endpoints through the service provider domain: *.service-provider-domain.com.

The input for hostedCluster.spec.dns manages the ingress for workloads within the hosted cluster. The input for hostedCluster.spec.services.servicePublishingStrategy.route.hostname manages the ingress for service endpoints within the management cluster.

External DNS creates name records for hosted cluster services that specify a publishing type of LoadBalancer or Route and provide a hostname for that publishing type. For hosted clusters with Private or PublicAndPrivate endpoint access types, only the APIServer and OAuth services support hostnames. For Private hosted clusters, the DNS record resolves to a private IP address of a Virtual Private Cloud (VPC) endpoint in your VPC.

A hosted control plane exposes the following services:

  • APIServer
  • OIDC

You can expose these services by using the servicePublishingStrategy field in the HostedCluster specification. By default, for the LoadBalancer and Route types of servicePublishingStrategy, you can publish the service in one of the following ways:

  • By using the hostname of the load balancer that is in the status of the Service with the LoadBalancer type.
  • By using the status.host field of the Route resource.

However, when you deploy hosted control planes in a managed service context, those methods can expose the ingress subdomain of the underlying management cluster and limit options for the management cluster lifecycle and disaster recovery.

When a DNS indirection is layered on the LoadBalancer and Route publishing types, a managed service operator can publish all public hosted cluster services by using a service-level domain. This architecture allows remapping on the DNS name to a new LoadBalancer or Route and does not expose the ingress domain of the management cluster. Hosted control planes uses external DNS to achieve that indirection layer.

You can deploy external-dns alongside the HyperShift Operator in the hypershift namespace of the management cluster. External DNS watches for Services or Routes that have the external-dns.alpha.kubernetes.io/hostname annotation. That annotation is used to create a DNS record that points to the Service, such as an A record, or the Route, such as a CNAME record.

You can use external DNS on cloud environments only. For the other environments, you need to manually configure DNS and services.

For more information about external DNS, see external DNS.

4.1.2.1. Setting up external DNS for hosted control planes

To automate the management of DNS records, you can set up external DNS for hosted control planes on AWS. You need this configuration to ensure that when you create or modify services, the corresponding DNS records in your AWS Route 53 public hosted zones update automatically.

You can provision hosted control planes with external DNS or service-level DNS.

Prerequisites

  • You created an external public domain.
  • You have access to the AWS Route53 Management console.
  • You enabled AWS PrivateLink for hosted control planes.

Procedure

  1. Create an Amazon Web Services (AWS) credential secret for the HyperShift Operator and name it hypershift-operator-external-dns-credentials in the local-cluster namespace.
  2. Verify that the secret has the required fields. For your reference, the required fields are detailed in the following table.

    Expand
    Table 4.3. Required fields for the AWS secret
    Field nameDescriptionOptional or required

    provider

    The DNS provider that manages the service-level DNS zone.

    Required

    domain-filter

    The service-level domain.

    Required

    credentials

    The credential file that supports all external DNS types.

    Optional when you use AWS keys

    aws-access-key-id

    The credential access key id.

    Optional when you use the AWS DNS service

    aws-secret-access-key

    The credential access key secret.

    Optional when you use the AWS DNS service

  3. Create an AWS secret by running the following command:

    $ oc create secret generic <secret_name> \
      --from-literal=provider=aws \
      --from-literal=domain-filter=<domain_name> \
      --from-file=credentials=<path_to_aws_credentials_file> -n local-cluster
    Note

    Disaster recovery backup for the secret is not automatically enabled. To back up the secret for disaster recovery, add the hypershift-operator-external-dns-credentials by entering the following command:

    $ oc label secret hypershift-operator-external-dns-credentials \
      -n local-cluster \
      cluster.open-cluster-management.io/backup=""

4.1.2.2. Creating the public DNS hosted zone

You can create the public DNS hosted zone to use as the external DNS domain filter. The External DNS Operator uses the public DNS hosted zone to create your public hosted cluster.

Procedure

  1. In the AWS Route 53 management console, click Create hosted zone.
  2. On the Hosted zone configuration page, type a domain name, verify that Public hosted zone is selected as the type, and click Create hosted zone.
  3. After the zone is created, on the Records tab, note the values in the Value/Route traffic to column.
  4. In the main domain, create an NS record to redirect the DNS requests to the delegated zone. In the Value field, enter the values that you noted in the previous step.
  5. Click Create records.
  6. Verify that the DNS hosted zone is working by creating a test entry in the new subzone and testing it with a dig command, such as in the following example:

    $ dig +short test.user-dest-public.aws.kerberos.com

    Example output

    192.168.1.1

  7. To create a hosted cluster that sets the hostname for the LoadBalancer and Route services, enter the following command:

    $ hcp create cluster aws --name=<hosted_cluster_name> \
      --endpoint-access=PublicAndPrivate \
      --external-dns-domain=<public_hosted_zone> ...

    Replace <public_hosted_zone> with the public hosted zone that you created.

    Example services block for the hosted cluster

      platform:
        aws:
          endpointAccess: PublicAndPrivate
    ...
      services:
      - service: APIServer
        servicePublishingStrategy:
          route:
            hostname: api-example.service-provider-domain.com
          type: Route
      - service: OAuthServer
        servicePublishingStrategy:
          route:
            hostname: oauth-example.service-provider-domain.com
          type: Route
      - service: Konnectivity
        servicePublishingStrategy:
          type: Route
      - service: Ignition
        servicePublishingStrategy:
          type: Route

    The Control Plane Operator creates the Services and Routes resources and annotates them with the external-dns.alpha.kubernetes.io/hostname annotation. For Services and Routes, the Control Plane Operator uses a value of the hostname parameter in the servicePublishingStrategy field for the service endpoints. To create the DNS records, you can use a mechanism, such as the external-dns deployment.

    You can configure service-level DNS indirection for public services only. You cannot set hostname for private services because they use the hypershift.local private zone.

    The following table shows when it is valid to set hostname for a service and endpoint combinations:

    Expand
    Table 4.4. Service and endpoint combinations to set hostname
    ServicePublicPublicAndPrivatePrivate

    APIServer

    Y

    Y

    N

    OAuthServer

    Y

    Y

    N

    Konnectivity

    Y

    N

    N

    Ignition

    Y

    N

    N

4.1.2.3. Creating a hosted cluster by using the external DNS on AWS

When you create a hosted cluster on AWS, using external DNS provides advantages over standard installation methods. With external DNS, you can automatically synchronize your cluster’s service endpoints with AWS Route 53.

Without external DNS, you must manually manage DNS records for every new service or ingress, which increases the risk of configuration errors and downtime.

Prerequisites

  • You configured the following artifacts in your management cluster:

    • The public DNS hosted zone
    • The External DNS Operator
    • The HyperShift Operator

Procedure

  1. On the hcp command-line interface (CLI), enter the following command to access your management cluster:

    $ export KUBECONFIG=<path_to_management_cluster_kubeconfig>
  2. Verify that the External DNS Operator is running by entering the following command:

    $ oc get pod -n hypershift -lapp=external-dns

    Example output

    NAME                            READY   STATUS    RESTARTS   AGE
    external-dns-7c89788c69-rn8gp   1/1     Running   0          40s

  3. To create a hosted cluster by using external DNS, enter the following command:

    $ hcp create cluster aws \
        --role-arn <arn_role> \
        --instance-type <instance_type> \
        --region <region> \
        --auto-repair \
        --generate-ssh \
        --name <hosted_cluster_name> \
        --namespace clusters \
        --base-domain <service_consumer_domain> \
        --node-pool-replicas <node_replica_count> \
        --pull-secret <path_to_your_pull_secret> \
        --release-image quay.io/openshift-release-dev/ocp-release:<ocp_release_image> \
        --external-dns-domain=<service_provider_domain> \
        --endpoint-access=<endpoint_access_configuration> \
        --sts-creds <path_to_sts_credential_file>

    where:

    <arn_role>
    Specifies the Amazon Resource Name (ARN), for example, arn:aws:iam::820196288204:role/myrole.
    <instance_types>
    Specifies the instance type, for example, m6i.xlarge.
    <region>
    Specifies the AWS region, for example, us-east-1.
    <hosted_cluster_name>
    Specifies your hosted cluster name, for example, my-external-aws.
    <service_consumer_domain>
    Specifies the public hosted zone that the service consumer owns, for example, service-consumer-domain.com.
    <node_replica_count>
    Specifies the node replica count, for example, 2.
    <path_to_your_pull_secret>
    Specifies the path to your pull secret file.
    <ocp_release_image>
    Specifies the supported OpenShift Container Platform version that you want to use, for example, 4.22.0-multi.
    <service_provider_domain>
    Specifies the public hosted zone that the service provider owns, for example, service-provider-domain.com.
    <endpoint_access_configuraton>
    Specifies the endpoint access configuration for the external DNS. Set as PublicAndPrivate. You can use external DNS with Public or PublicAndPrivate configurations only.
    <path_to_sts_credential_file>
    Specifies the path to your AWS STS credentials file, for example, /home/user/sts-creds/sts-creds.json.

4.1.2.4. Defining a custom DNS name

As a cluster administrator, you can create a hosted cluster with an external API DNS name that differs from the internal endpoint that gets used for node bootstraps and control plane communication.

You might want to define a different DNS name for the following reasons:

  • To replace the user-facing TLS certificate with one from a public CA without breaking the control plane functions that bind to the internal root CA
  • To support split-horizon DNS and NAT scenarios
  • To ensure a similar experience to standalone control planes, where you can use functions, such as the Show Login Command function, with the correct kubeconfig and DNS configuration

You can define a DNS name either during your initial setup or during postinstallation operations, by entering a domain name in the kubeAPIServerDNSName parameter of a HostedCluster object.

Prerequisites

  • You have a valid TLS certificate that covers the DNS name that you set in the kubeAPIServerDNSName parameter.
  • You have a resolvable DNS name URI that can reach and point to the correct address.

Procedure

  • In the specification for the HostedCluster object, add the kubeAPIServerDNSName parameter and the address for the domain and specify which certificate to use, as shown in the following example:

    #...
    spec:
      configuration:
        apiServer:
          servingCerts:
            namedCertificates:
            - names:
              - xxx.example.com
              - yyy.example.com
              servingCertificate:
                name: <my_serving_certificate>
      kubeAPIServerDNSName: <custom_address>

    The value for the kubeAPIServerDNSName parameter must be a valid and addressable domain.

    After you define the kubeAPIServerDNSName parameter and specify the certificate, the Control Plane Operator controllers create a kubeconfig file named custom-admin-kubeconfig, where the file gets stored in the HostedControlPlane namespace. The generation of certificates happen from the root CA, and the HostedControlPlane namespace manages their expiration and renewal.

    The Control Plane Operator reports a new kubeconfig file named CustomKubeconfig in the HostedControlPlane namespace. That file uses the defined new server in the kubeAPIServerDNSName parameter.

    A reference for the custom kubeconfig file exists in the status parameter as CustomKubeconfig of the HostedCluster object. The CustomKubeConfig parameter is optional, and you can add the parameter only if the kubeAPIServerDNSName parameter is not empty. After you set the CustomKubeConfig parameter, the parameter triggers the generation of a secret named <hosted_cluster_name>-custom-admin-kubeconfig in the HostedCluster namespace. You can use the secret to access the HostedCluster API server. If you remove the CustomKubeConfig parameter during postinstallation operations, deletion of all related secrets and status references occur.

    Note

    Defining a custom DNS name does not directly impact the data plane, so no expected rollouts occur. The HostedControlPlane namespace receives the changes from the HyperShift Operator and deletes the corresponding parameters.

    If you remove the kubeAPIServerDNSName parameter from the specification for the HostedCluster object, all newly generated secrets and the CustomKubeconfig reference are removed from the cluster and from the status parameter.

4.1.3. Creating a hosted cluster on AWS

On AWS, you can create a hosted cluster by using the command-line interface, hcp, or by providing AWS STS credentials. You can also create a hosted cluster in multiple zones on AWS.

A hosted cluster is an OpenShift Container Platform cluster with its API endpoint and control plane hosted on a management cluster. The hosted cluster includes the control plane and its corresponding data plane.

The hosted cluster is automatically imported as a managed cluster. If you want to disable this automatic import feature, see "Disabling the automatic import of hosted clusters into multicluster engine Operator".

By default for hosted control planes on AWS, you use an AMD64 hosted cluster. However, you can enable hosted control planes to run on an ARM64 hosted cluster. For more information, see "Running hosted clusters on an ARM64 architecture".

For compatible combinations of node pools and hosted clusters, see the following table:

Expand
Table 4.5. Compatible architectures for node pools and hosted clusters
Hosted clusterNode pools

AMD64

AMD64 or ARM64

ARM64

ARM64 or AMD64

4.1.3.1. Creating a hosted cluster on AWS by using the CLI

To create a hosted cluster on Amazon Web Services (AWS), you can use the hosted control plane command-line interface (hcp).

Prerequisites

  • You have set up the hosted control plane CLI, hcp.
  • You have enabled the local-cluster managed cluster as the management cluster.
  • You created an AWS Identity and Access Management (IAM) role and AWS Security Token Service (STS) credentials.

Procedure

  1. To create a hosted cluster on AWS, run the following command:

    $ hcp create cluster aws \
        --name <hosted_cluster_name> \
        --infra-id <infra_id> \
        --base-domain <basedomain> \
        --sts-creds <path_to_sts_credential_file> \
        --pull-secret <path_to_pull_secret> \
        --region <region> \
        --generate-ssh \
        --node-pool-replicas <node_pool_replica_count> \
        --namespace <hosted_cluster_namespace> \
        --role-arn <role_name> \
        --render-into <file_name>.yaml

    where:

    <hosted_cluster_name>
    Specifies the name of your hosted cluster.
    <infra_id>
    Specifies your infrastructure name. You must provide the same value for <hosted_cluster_name> and <infra_id>. Otherwise the cluster might not appear correctly in the multicluster engine for Kubernetes Operator console.
    <basedomain>
    Specifies your base domain, for example, example.com.
    <path_to_sts_credential_file>
    Specifies the path to your AWS STS credentials file, for example, /home/user/sts-creds/sts-creds.json.
    <path_to_pull_secret>
    Specifies the path to your pull secret, for example, /user/name/pullsecret.
    <region>
    Specifies the AWS region name, for example, us-east-1.
    <node_pool_replica_count>
    Specifies the node pool replica count, for example, 3.
    <hosted_cluster_namespace>
    Specifies that you want to create the HostedCluster and NodePool custom resource in a specific namespace. Otherwise, by default, all HostedCluster and NodePool custom resources are created in the clusters namespace.
    <role_name>
    Specifies the Amazon Resource Name (ARN), for example, arn:aws:iam::820196288204:role/myrole.
    <file_name>
    Specifies whether the EC2 instance runs on shared or single tenant hardware. The --render-into flag renders Kubernetes resources into the YAML file that you specify in this field. Continue to the next step to edit the YAML file.
  2. If you included the --render-into flag in the previous command, edit the specified YAML file. Edit the NodePool specification in the YAML file to indicate whether the EC2 instance should run on shared or single-tenant hardware, similar to the following example:

    Example YAML file

    apiVersion: hypershift.openshift.io/v1beta1
    kind: NodePool
    metadata:
      name: <nodepool_name>
    spec:
      platform:
        aws:
          placement:
            tenancy: "default"

    where:

    <nodepool_name>
    Specifies the name of the NodePool resource.
    spec.platform.aws.placement.tenancy
    Specifies a valid value for tenancy: "default", "dedicated", or "host". Use "default" when node pool instances run on shared hardware. Use "dedicated" when each node pool instance runs on single-tenant hardware. Use "host" when node pool instances run on your pre-allocated dedicated hosts.
  3. If you use external load balancers, configure the ingress endpoint by editing the HostedCluster resource as shown in the following example. If you do not configure the endpoint, the default behavior is to randomize the node port that the service exposes the ingress on. To configure how the ingress controller publishes the default ingress route, set the endpointPublishingStrategy parameter and its underlying functions:

    #...
    spec:
      operatorConfiguration:
        ingressOperator:
          endpointPublishingStrategy:
            type: LoadBalancerService
            loadBalancer:
              scope: Internal
    #...

    The spec.operatorConfiguration.ingressOperator.endPointPublishingStrategy.type parameter specifies the endpoint for the load balancer. For AWS, use the LoadBalancerService type.

Verification

  1. Verify the status of your hosted cluster to check that the value of AVAILABLE is True. Run the following command:

    $ oc get hostedclusters -n <hosted_cluster_namespace>
  2. Get a list of your node pools by running the following command:

    $ oc get nodepools --namespace <hosted_cluster_namespace>

4.1.3.2. Creating a hosted cluster by providing AWS STS credentials

To enhance the security of your hosted control plane deployment, you can create a hosted cluster on AWS by using the AWS Security Token Service (STS).

When you create a hosted cluster by using the hcp create cluster aws command, you must provide an Amazon Web Services (AWS) account credentials that have permissions to create infrastructure resources for your hosted cluster.

Infrastructure resources include the following examples:

  • Virtual Private Cloud (VPC)
  • Subnets
  • Network address translation (NAT) gateways

You can provide the AWS credentials by using the either of the following ways:

  • The AWS Security Token Service (STS) credentials
  • The AWS cloud provider secret from multicluster engine Operator

Procedure

  • To create a hosted cluster on AWS by providing AWS STS credentials, enter the following command:

    $ hcp create cluster aws \
      --name <hosted_cluster_name> \
      --node-pool-replicas <node_pool_replica_count> \
      --base-domain <base_domain> \
      --pull-secret <path_to_pull_secret> \
      --sts-creds <path_to_sts_credential_file> \
      --region <region> \
      --role-arn <arn_role>

    where:

    <hosted_cluster_name>
    Specifies the name of your hosted cluster, for example, my-hosted-cluster-01.
    <node_pool_replica_count>
    Specifies the node pool replica count, for example, 2.
    <base_domain>
    Specifies your base domain, for example, example.com.
    <path_to_pull_secret>
    Specifies the path to your pull secret, for example, /user/name/pullsecret.
    <path_to_sts_credentials>
    Specifies the path to your AWS STS credentials file, for example, /home/user/sts-creds/sts-creds.json.
    <region>
    Specifies the AWS region name, for example, us-east-1.
    <arn_role>
    Specifies the Amazon Resource Name (ARN), for example, arn:aws:iam::820196288204:role/myrole.

4.1.3.3. Creating a hosted cluster in multiple zones on AWS

To improve availability and fault tolerance, you can create a hosted cluster across multiple AWS availability zones. Distributing your node pools and compute nodes across several zones protects your workloads against potential outages in a single geographical region.

You can create a hosted cluster in multiple zones on Amazon Web Services (AWS) by using the hcp command-line interface (CLI).

Prerequisites

  • You created an AWS Identity and Access Management (IAM) role and AWS Security Token Service (STS) credentials.

Procedure

  • Create a hosted cluster in multiple zones on AWS by running the following command:

    $ hcp create cluster aws \
      --name <hosted_cluster_name> \
      --node-pool-replicas=<node_pool_replica_count> \
      --base-domain <base_domain> \
      --pull-secret <path_to_pull_secret> \
      --role-arn <arn_role> \
      --region <region> \
      --zones <zones> \
      --sts-creds <path_to_sts_credential_file>

    where:

    <hosted_cluster_name>
    Specifies the name of your hosted cluster, such as my-hosted-cluster-01.
    <node_pool_replica_count>
    Specifies the node pool replica count, for example, 2.
    <base_domain>
    Specifies your base domain, for example, example.com.
    <path_to_pull_secret>
    Specifies the path to your pull secret, for example, /user/name/pullsecret.
    <arn_role>
    Specifies the Amazon Resource Name (ARN), for example, arn:aws:iam::820196288204:role/myrole.
    <region>
    Specifies the AWS region name, for example, us-east-1.
    <zones>
    Specifies availability zones within your AWS region, for example, us-east-1a, and us-east-1b. For each specified zone, the following infrastructure is created: public subnet, private subnet, NAT gateway, and private route table. A public route table is shared across public subnets. One NodePool resource is created for each zone. The node pool name is suffixed by the zone name. The private subnet for the zone is set in the spec.platform.aws.subnet.id parameter.
    <path_to_sts_credential_file>
    Specifies the path to your AWS STS credentials file, for example, /home/user/sts-creds/sts-creds.json.

4.1.4. Accessing a hosted cluster on AWS

After you create a hosted cluster on AWS, you can access it by using your kubeconfig file, access secrets, and kubeadmin credentials.

The hosted cluster namespace contains hosted cluster resources and the access secrets. The hosted control plane runs in the hosted control plane namespace.

The secret name formats are shown in the following table:

Expand
Table 4.6. Access secrets
SecretFormatExample

kubeconfig secret

<hosted_cluster_namespace>-<name>-admin-kubeconfig

clusters-hypershift-demo-admin-kubeconfig

kubeadmin password secret

<hosted_cluster_namespace>-<name>-kubeadmin-password

clusters-hypershift-demo-kubeadmin-password

Note

The kubeadmin password secret is Base64-encoded and the kubeconfig secret contains a Base64-encoded kubeconfig configuration. You must decode the Base64-encoded kubeconfig configuration and save it into a <hosted_cluster_name>.kubeconfig file.

Procedure

  1. Generate the kubeconfig file by entering the following command:

    $ hcp create kubeconfig --namespace <hosted_cluster_namespace> \
      --name <hosted_cluster_name> > <hosted_cluster_name>.kubeconfig
  2. Use your <hosted_cluster_name>.kubeconfig file that contains the decoded kubeconfig configuration to access the hosted cluster. Enter the following command:

    $ oc --kubeconfig <hosted_cluster_name>.kubeconfig get nodes

    You must decode the kubeadmin password secret to log in to the API server or the console of the hosted cluster.

4.1.5. Running hosted clusters on an ARM64 architecture

By default for hosted control planes on Amazon Web Services (AWS), you use an AMD64 hosted cluster. However, you can enable hosted control planes to run on an ARM64 hosted cluster.

For compatible combinations of node pools and hosted clusters, see the following table:

Expand
Table 4.7. Compatible architectures for node pools and hosted clusters
Hosted clusterNode pools

AMD64

AMD64 or ARM64

ARM64

ARM64 or AMD64

You can run a hosted cluster on an ARM64 OpenShift Container Platform cluster for Amazon Web Services (AWS) by overriding the default release image with a multi-architecture release image.

If you do not use a multi-architecture release image, the compute nodes in the node pool are not created and reconciliation of the node pool stops until you either use a multi-architecture release image in the hosted cluster or update the NodePool custom resource based on the release image.

Prerequisites

  • You must have an OpenShift Container Platform cluster with a 64-bit ARM infrastructure that is installed on AWS. For more information, see "Create an OpenShift Container Platform Cluster: AWS (ARM)".
  • You must create an AWS Identity and Access Management (IAM) role and AWS Security Token Service (STS) credentials. For more information, see "Creating an AWS IAM role and STS credentials".

Procedure

  • Create a hosted cluster on an ARM64 OpenShift Container Platform cluster by entering the following command:

    $ hcp create cluster aws \
      --name <hosted_cluster_name> \
      --node-pool-replicas <node_pool_replica_count> \
      --base-domain <base_domain> \
      --pull-secret <path_to_pull_secret> \
      --sts-creds <path_to_sts_credential_file> \
      --region <region> \
      --release-image quay.io/openshift-release-dev/ocp-release:<ocp_release_image> \
      --role-arn <role_name>

    where:

    <hosted_cluster_name>
    Specifies the name of your hosted cluster, for example, my-hosted-cluster-01.
    <node_pool_replica_count>
    Specifies the node pool replica count, for example, 3.
    <base_domain>
    Specifies your base domain, for example, example.com.
    <path_to_pull_secret>
    Specifies the path to your pull secret, for example, /user/name/pullsecret.
    <path_to_sts_credential_file>
    Specifies the path to your AWS STS credentials file, for example, /home/user/sts-creds/sts-creds.json.
    <region>
    Specifies the AWS region name, for example, us-east-1.
    <ocp_release_image>
    Specifies the supported OpenShift Container Platform version that you want to use, for example, 4.22.0-multi. If you are using a disconnected environment, replace <ocp_release_image> with the digest image. To extract the OpenShift Container Platform release image digest, see "Extracting the OpenShift Container Platform release image digest".
    <role_name>
    Specifies the Amazon Resource Name (ARN), for example, arn:aws:iam::820196288204:role/myrole.

You can schedule application workloads that are the NodePool objects on 64-bit ARM and AMD from the same hosted control plane. To set the required processor architecture for the NodePool object, you define the arch field in the NodePool specification.

The valid values for the arch field are as follows:

  • arm64
  • amd64

Prerequisites

  • You must have a multi-architecture image for the HostedCluster custom resource to use. You can access multi-architecture nightly images. For more information, see "Multi-architecture nightly images".

Procedure

  • Add an ARM or AMD NodePool object to the hosted cluster on AWS by running the following command:

    $ hcp create nodepool aws \
      --cluster-name <hosted_cluster_name> \
      --name <node_pool_name> \
      --node-count <node_pool_replica_count> \
      --arch <architecture>

    where:

    <hosted_cluster_name>
    Specifies the name of your hosted cluster, for example, my-hosted-cluster-01.
    <node_pool_name>
    Specifies the node pool name.
    <node_pool_replica_count>
    Specifies the node pool replica count, for example, 3.
    <architecture>
    Specifies the architecture type, such as arm64 or amd64. If you do not specify a value for the --arch flag, the amd64 value is used by default.

4.1.6. Creating a private hosted cluster on AWS

After you enable the local-cluster as the management cluster, you can deploy a hosted cluster or a private hosted cluster on Amazon Web Services (AWS).

By default, hosted clusters are publicly accessible through public DNS and the default router for the management cluster.

For private clusters on AWS, all communication with the hosted cluster occurs over AWS PrivateLink.

Prerequisites

  • You enabled AWS PrivateLink. For more information, see "Enabling AWS PrivateLink".
  • You created an AWS Identity and Access Management (IAM) role and AWS Security Token Service (STS) credentials. For more information, see "Creating an AWS IAM role and STS credentials" and "Identity and Access Management (IAM) permissions".
  • You configured a bastion instance on AWS. For more information, see "Tutorial: Configuring private network access using a Linux Bastion Host".

Procedure

  • Create a private hosted cluster on AWS by entering the following command:

    $ hcp create cluster aws \
      --name <hosted_cluster_name> \
      --node-pool-replicas=<node_pool_replica_count> \
      --base-domain <basedomain> \
      --pull-secret <path_to_pull_secret> \
      --sts-creds <path_to_sts_credential_file> \
      --region <region> \
      --endpoint-access Private \
      --role-arn <role_name>

    where:

    <hosted_cluster_name>
    Specifies the name of your hosted cluster, such as, example.
    <node_pool_replica_count>
    Specifies the node pool replica count, for example, 3.
    <basedomain>
    Specifies your base domain, for example, example.com.
    <path_to_pull_secret>
    Specifies the path to your pull secret, for example, /user/name/pullsecret.
    <path_to_sts_credential_file>
    Specifies the path to your AWS STS credentials file, for example, /home/user/sts-creds/sts-creds.json.
    <region>
    Specifies the AWS region name, for example, us-east-1.
    Private
    Specifies that the cluster is private.
    <role_name>
    Specifies the Amazon Resource Name (ARN), for example, arn:aws:iam::820196288204:role/myrole. For more information about ARN roles, see "Identity and Access Management (IAM) permissions".

    The following API endpoints for the hosted cluster are accessible through a private DNS zone:

  • api.<hosted_cluster_name>.hypershift.local
  • *.apps.<hosted_cluster_name>.hypershift.local

4.1.6.1. Accessing a private hosted cluster on AWS

After you create a private hosted cluster, you can access it by using the command-line interface (CLI).

Procedure

  1. Find the private IPs of nodes by entering the following command:

    $ aws ec2 describe-instances \
      --filter="Name=tag:kubernetes.io/cluster/<infra_id>,Values=owned" \
      | jq '.Reservations[] | .Instances[] | select(.PublicDnsName=="") \
      | .PrivateIpAddress'
  2. Create a kubeconfig file for the hosted cluster that you can copy to a node by entering the following command:

    $ hcp create kubeconfig > <hosted_cluster_kubeconfig>
  3. To SSH into one of the nodes through the bastion, enter the following command:

    $ ssh -o ProxyCommand="ssh ec2-user@<bastion_ip> \
      -W %h:%p" core@<node_ip>
  4. From the SSH shell, copy the kubeconfig file contents to a file on the node by entering the following command:

    $ mv <path_to_kubeconfig_file> <new_file_name>
  5. Export the kubeconfig file by entering the following command:

    $ export KUBECONFIG=<path_to_kubeconfig_file>
  6. Observe the hosted cluster status by entering the following command:

    $ oc get clusteroperators clusterversion

4.2. Deploying hosted control planes on Azure

With hosted control planes on Microsoft Azure, you can reduce the cost associated with dedicated control-plane node VMs for each cluster. You can provision compute nodes as Azure Virtual Machine Scale sets for dynamic scaling, and ensure credential isolation with per-cluster Azure service principals.

Important

Hosted control planes on Azure is a Technology Preview feature only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs) and might not be functionally complete. Red Hat does not recommend using them in production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.

For more information about the support scope of Red Hat Technology Preview features, see Technology Preview Features Support Scope.

4.2.1. Overview of hosted control planes on Azure

You can deploy and manage hosted clusters on an OpenShift management cluster that runs in Microsoft Azure. With a self-managed deployment model, you manage your own OpenShift cluster.

4.2.1.1. Architecture of hosted control planes on Azure

At a high level, the architecture of hosted control planes on Azure consists of three layers:

Management cluster
An Azure OpenShift cluster that hosts the HyperShift Operator and the control planes for your hosted clusters.
Control plane
Kubernetes control-plane components that run as pods on the management cluster.
Data plane
Compute nodes that run as Azure virtual machines (VMs) in your Azure subscription.

The architecture uses Azure Workload Identity for secure, credential-free authentication between OpenShift Container Platform components and Azure services. As a result, you do not need to manage long-lived service principal credentials, and you get better security through federated identity credentials.

4.2.1.2. Deployment workflow for hosted control planes on Azure

Deploying self-managed hosted control planes on Azure involves a three-phase process in the following order:

Phase 1: Set up Azure Workload Identity

This phase establishes secure authentication infrastructure so that OpenShift Container Platform components can access Azure services. During this phase, the security infrastructure that your hosted clusters require is created:

  • Managed identities for each OpenShift Container Platform component, including the image registry, ingress, CSI drivers, cloud provider, network operator, and so on
  • OIDC issuer in Azure Blob Storage for service account token validation
  • Federated credentials that establish trust relationships between Azure Entra ID and OpenShift Container Platform service accounts
Phase 2: Set up the management cluster

In this phase, you prepare your OpenShift Container Platform management cluster on Azure to host and manage hosted clusters. During this phase, you install the following components:

  • Azure DNS zones, for private and public-private topologies
  • External DNS, for private and public-private topologies
  • HyperShift Operator
Phase 3: Create hosted clusters

In this phase, you create and configure hosted clusters. This phase involves the following steps:

  1. Setting up infrastructure
  2. Creating a hosted cluster
  3. Integrating workload identity
  4. Configuring private endpoint access (optional)

4.2.1.3. Azure infrastructure and credentials

Before you get started with hosted control planes on Microsoft Azure, get familiar with the required Azure resources and the necessary permissions.

4.2.1.3.1. Summary of requirements

You need the following resources, tools, access, and permissions to set up hosted control planes on Azure:

Azure resources
  • An OpenShift Container Platform management cluster on Azure.
  • An Azure subscription with contributor and user-access administrator permissions.
  • (Optional) A parent DNS zone in Azure for delegating cluster DNS records. This DNS zone is required only if you plan to use external DNS.
Tools and access
  • Azure command-line interface (CLI), az, configured with your subscription
  • OpenShift CLI (oc)
  • hosted control planes CLI, hcp
  • jq command-line JSON processor
  • Cloud Credential Operator utility (ccoctl)
  • A valid OpenShift Container Platform pull secret
Permissions
  • Subscription-level contributor and user access administrator roles
  • Microsoft Graph API permissions for creating service principals
4.2.1.3.2. DNS management options

You can set up hosted control planes on Azure with or without external DNS. If you plan to use a private or a public-private topology, external DNS is required. See the following table for more information:

Expand
Table 4.8. DNS approaches for hosted control planes on Azure
 With external DNSWithout external DNS

Best for

Production, multi-cluster

Development, testing

API server DNS

Custom (api-cluster.example.com)

Azure Load Balancer (abc123.region.cloudapp.azure.com)

Setup complexity

Low, requires DNS zones and service principals

None

Management

Fully automatic

Manual or Azure-provided

4.2.1.3.3. Resource group strategy

Cluster-specific resource groups are created and deleted with each hosted cluster. These resources include managed resource groups for cluster infrastructure. If you use custom networking, these resources also include Virtual Network (VNet) resource groups and Network Security Group (NSG) resource groups.

4.2.1.3.4. Security considerations for hosted control planes on Azure

Hosted control planes on Azure employs the following security best practices:

  • Workload identity federation, which eliminates long-lived credentials by using OIDC-based authentication.
  • Least-privilege access, where each component has its own managed identity with minimal required permissions.
  • Network isolation, where you can use custom VNets and NSGs to implement network segmentation and security policies.
  • Federated credentials, where trust relationships are scoped to specific service accounts, preventing unauthorized access.
  • Private connectivity, available as an option through Azure Private Link, which provides private API server access to ensure that control-plane traffic never traverses the public internet. Private connectivity is available for private and public-private topologies only.

4.2.2. Setting up Azure resources

Before you can create management and hosted clusters for your deployment of hosted control planes on Azure, you need to set up an OIDC issuer, Workload Identities, and your Azure infrastructure.

4.2.2.1. Setting up an OIDC issuer

To prepare to deploy hosted control planes on Azure, you need to set up an OIDC issuer for hosted clusters.

Prerequisites

  • The Azure command-line interface (CLI) is installed and configured.
  • The jq command-line JSON processor is installed.
  • The Cloud Credential Operator utility (ccoctl) is installed. For more information, see "How to obtain the ccoctl tool for OpenShift 4".
  • The appropriate Azure permissions are set.

Procedure

  1. Set your environment variables as shown in the following example:

    PERSISTENT_RG_NAME="os4-common"
    LOCATION="eastus"
    AZURE_CREDS="/path/to/azure-creds.json"
    SUBSCRIPTION_ID="my-subscription-id"
  2. Create a persistent resource group by entering the following command:

    $ az group create --name $PERSISTENT_RG_NAME --location $LOCATION
  3. Configure an OIDC issuer URL by using the Cloud Credential Operator tool to complete the following steps:

    1. Set the OIDC issuer variables as shown in the following example:

      OIDC_STORAGE_ACCOUNT_NAME="yourstorageaccount"
      TENANT_ID="your-tenant-id"
    2. Create an RSA key pair and save the private and public key by entering the following command:

      $ ccoctl azure create-key-pair
    3. Set variables for the token issuer key paths as shown in the following example:

      SA_TOKEN_ISSUER_PRIVATE_KEY_PATH="/path/to/serviceaccount-signer.private"
      SA_TOKEN_ISSUER_PUBLIC_KEY_PATH="/path/to/serviceaccount-signer.public"
    4. Create an OIDC issuer by entering the following command:

      $ ccoctl azure create-oidc-issuer \
          --oidc-resource-group-name ${PERSISTENT_RG_NAME} \
          --tenant-id ${TENANT_ID} \
          --region ${LOCATION} \
          --name ${OIDC_STORAGE_ACCOUNT_NAME} \
          --subscription-id ${SUBSCRIPTION_ID} \
          --public-key-file ${SA_TOKEN_ISSUER_PUBLIC_KEY_PATH}
    5. Set the OIDC issuer URL as shown in the following example:

      OIDC_ISSUER_URL="https://${OIDC_STORAGE_ACCOUNT_NAME}.blob.core.windows.net/${OIDC_STORAGE_ACCOUNT_NAME}"

Verification

  • Try to access the OIDC issuer by entering the following command:

    $ curl -s "${OIDC_ISSUER_URL}/.well-known/openid-configuration" | jq .

4.2.2.2. Creating Azure Workload Identities

To ensure control over Identity and Access Management (IAM) resources in your Azure deployment, create Workload Identities separately from your infrastructure.

Workload Identities authenticate hosted cluster components to Azure services by using OIDC federation. You must create identities separately and then consume them during infrastructure or cluster creation.

Prerequisites

  • You have an Azure credentials file in the following format:

    Example file

    {
      "subscriptionId": "your-subscription-id",
      "tenantId": "your-tenant-id",
      "clientId": "your-client-id",
      "clientSecret": "your-client-secret"
    }

  • You have a resource group to create the managed identities in.
  • You have an OIDC issuer URL for Workload Identity federation. For more information, see "Setting up an OIDC issuer".

Procedure

  1. Set environment variables as shown in the following example:

    CLUSTER_NAME="my-self-managed-cluster"
    INFRA_ID="${CLUSTER_NAME}-$(openssl rand -hex 4)"
  2. On the hosted control planes command-line interface, hcp, enter the following command:

    $ hcp create iam azure \
        --name <my_cluster_name> \
        --infra-id <infra_id> \
        --azure-creds <azure_credentials_file> \
        --resource-group-name <resource_group> \
        --oidc-issuer-url <oidc_issuer_url> \
        --output-file <workload_identities_file> \
        --location <my_region> \
        --cloud <my_cloud_environment>

    where:

    <my_cluster_name>
    Specifies the name of the cluster you intend to create.
    <infra_id>
    Specifies the unique identifier for naming Azure resources. Typically, this identifier is the cluster name with a suffix.
    <azure_credentials_file>
    Specifies the Azure credentials file with permission to create managed identities and federated credentials.
    <resource_group>
    Specifies the name of the resource group where you intend to create identities.
    <oidc_issuer_url>
    Specifies the URL of the OIDC identity provider for Workload Identity federation.
    <workload_identities_file>

    Specifies the output file path, such as my-cluster-name-iam-output.json.

    You can also add these optional flags to the hcp create iam azure command:

    <my_region>
    Specifies the Azure region for the managed identities. The default value is eastus.
    <my_cloud_environment>
    Specifies the Azure cloud environment. The default value is AzurePublicCloud.

Verification

  • Review the output file, which looks like the following example:

    Example output

    {
      "disk": {
        "tenantID": "...",
        "clientID": "...",
        "resourceID": "/subscriptions/.../providers/Microsoft.ManagedIdentity/userAssignedIdentities/my-cluster-abc123-disk"
      },
      "file": {
        "tenantID": "...",
        "clientID": "...",
        "resourceID": "..."
      },
      "imageRegistry": { ... },
      "ingress": { ... },
      "cloudProvider": { ... },
      "nodePoolManagement": { ... },
      "network": { ... },
      "controlPlaneOperator": { ... }
    }

    The output includes 8 user-assigned identities, one per cluster component, along with federated credentials for each identity:

    • Disk CSI driver
    • File CSI driver
    • Image registry
    • Ingress Operator
    • Cloud provider
    • Node pool management
    • Network Operator
    • Control Plane Operator

4.2.2.3. Creating Azure infrastructure

Create an Azure infrastructure separately so that when you create a hosted cluster on Azure, you can use pre-existing infrastructure.

Prerequisites

  • You have an Azure credentials file with the following format:

    {
      "subscriptionId": "<my_subscription_id>",
      "tenantId": "<my_tenant_id>",
      "clientId": "<my_client_id>",
      "clientSecret": "<my_client_secret>"
    }
  • You have an existing public DNS zone in your Azure subscription for your base domain.
  • You created Workload Identities. For more information, see "Creating Azure Workload Identities".

Procedure

  • To create the infrastructure with a new virtual network, subnet, and network security group, enter the following command:

    $ hcp create infra azure \
      --name <my_cluster_name> \
      --infra-id <infra_id> \
      --azure-creds <azure_credentials_file> \
      --base-domain <base_domain> \
      --location <location> \
      --workload-identities-file <workload_identities_file> \
      --assign-identity-roles \
      --dns-zone-rg-name <dns_zone_rg> \
      --output-file <output_infra_file>

    where:

    • --name specifies the name of the hosted cluster you intend to create.
    • --infra-id specifies a unique name that identifies your infrastructure. This value is used to name and tag Azure resources. Typically, it is the name of your cluster with a suffix appended to it.
    • --azure-creds specifies an Azure credentials file that has permission to create infrastructure resources, such as virtual networks, subnets, and load balancers.
    • --base-domain specifies the base domain for the ingress of your hosted cluster. The base domain must correspond to an existing public DNS zone in your Azure subscription.
    • --location specifies the Azure region where you want to create the infrastructure, such as eastus or westus2.
    • --workload-identities-file specifies the path to the JSON file that contains the Workload Identity configuration.
    • --assign-identity-roles specifies that automatic RBAC role assignment is enabled for Workload Identities.
    • --dns-zone-rg-name specifies the name of the resource group that contains your public DNS zone.
    • --output-file specifies the file where the details of the infrastructure are stored in YAML format.
  • To create the infrastructure with an existing virtual network, subnet, and network security group, enter the following command:

    $ hcp create infra azure \
      --name <my_cluster_name> \
      --infra-id <infra_id> \
      --azure-creds <azure_credentials_file> \
      --base-domain <base_domain> \
      --location <location> \
      --workload-identities-file <workload_identities_file> \
      --vnet-id /subscriptions/<subscription_id>/resourceGroups/<resource_group>/providers/Microsoft.Network/virtualNetworks/<vnet_name> \
      --subnet-id /subscriptions/<subscription_id>/resourceGroups/<resource_group>/providers/Microsoft.Network/virtualNetworks/<vnet_name>/subnets/<subnet_name> \
      --network-security-group-id /subscriptions/<subscription_id>/resourceGroups/<resource_group>/providers/Microsoft.Network/networkSecurityGroups/<network_security_group_name> \
      --assign-identity-roles \
      --dns-zone-rg-name <dns_zone_rg> \
      --output-file <output_infra_file>

    where:

    • --name specifies the name of the hosted cluster you intend to create.
    • --infra-id specifies a unique name that identifies your infrastructure. This value is used to name and tag Azure resources. Typically, it is the name of your cluster with a suffix appended to it.
    • --azure-creds specifies an Azure credentials file that has permission to create infrastructure resources, such as virtual networks, subnets, and load balancers.
    • --base-domain specifies the base domain for the ingress of your hosted cluster. The base domain must correspond to an existing public DNS zone in your Azure subscription.
    • --location specifies the Azure region where you want to create the infrastructure, such as eastus or westus2.
    • --workload-identities-file specifies the path to the JSON file that contains the Workload Identity configuration.
    • --vnet-id specifies your existing virtual network ID, which includes your subscription ID and your virtual network name.
    • --subnet-id specifies the ARM resource ID of your subnet, which includes your subscription ID, virtual network name, and subnet name.
    • --network-security-group-id specifies your existing network security group ID, which includes your subscription ID and your network security group name.
    • --assign-identity-roles specifies that automatic RBAC role assignment is enabled for Workload Identities.
    • --dns-zone-rg-name specifies the name of the resource group that contains your public DNS zone.
    • --output-file specifies the file where the details of the infrastructure are stored in YAML format.

To configure the management cluster for hosted control planes on Azure, you need to ensure that external DNS and the HyperShift Operator are set up on the cluster.

The configuration steps include configuring the DNS zone, delegating the DNS records for your cluster, and creating a dedicated service principal for external DNS.

Prerequisites

  • You installed the multicluster engine Operator 2.5 or later on an OpenShift Container Platform cluster. You can install multicluster engine Operator as an Operator from the OpenShift Container Platform software catalog. Or, if you already use Red Hat Advanced Cluster Management, the Operator is automatically installed. The HyperShift Operator is enabled by default in the operator package for multicluster engine Operator.
  • The Azure command-line interface (CLI) is installed and configured.
  • The OpenShift CLI (oc) is installed.
  • You have an OpenShift Container Platform management cluster on Azure.
  • If you are using external DNS, the jq command-line JSON processor is installed.

Procedure

  1. Set the DNS configuration variables as shown in the following example:

    PARENT_DNS_RG="<my_parent_dns_resource_group>"
    PARENT_DNS_ZONE="<my_parent.dns.zone.com>"
    DNS_RECORD_NAME="<my_subdomain>"
    RESOURCE_GROUP_NAME="<my_resource_group>"
    DNS_ZONE_NAME="<my_subdomain.my_parent.dns.zone.com>"
    LOCATION="<my_region>"
  2. Create the Azure group by entering the following command:

    $ az group create \
      --name $RESOURCE_GROUP_NAME \
      --location $LOCATION
  3. Create the Azure DNS zone by entering the following command:

    $ az network dns zone create \
      --resource-group $RESOURCE_GROUP_NAME \
      --name $DNS_ZONE_NAME
  4. If an existing name server record exists, delete it by entering the following command:

    $ az network dns record-set ns delete \
      --resource-group $PARENT_DNS_RG \
      --zone-name $PARENT_DNS_ZONE \
      --name $DNS_RECORD_NAME -y
  5. Get the name servers from your DNS zone by entering the following command:

    name_servers=$(az network dns zone show \
      --resource-group $RESOURCE_GROUP_NAME \
      --name $DNS_ZONE_NAME \
      --query nameServers \
      --output tsv)
  6. Create an array of name servers as shown in the following example:

    ns_array=()
    while IFS= read -r ns; do
        ns_array+=("$ns")
    done <<< "$name_servers"
  7. Add name server records to the parent zone as shown in the following example:

    for ns in "${ns_array[@]}"; do
        az network dns record-set ns add-record \
            --resource-group $PARENT_DNS_RG \
            --zone-name $PARENT_DNS_ZONE \
            --record-set-name $DNS_RECORD_NAME \
            --nsdname "$ns"
    done
  8. Set the external DNS configuration variables as shown in the following example:

    EXTERNAL_DNS_NEW_SP_NAME="<external_dns_service_principal>"
    SERVICE_PRINCIPAL_FILEPATH="<path_to_azure_mgmt_json_file>"
    RESOURCE_GROUP_NAME="<my_resource_group>"
  9. Create the service principal for external DNS by entering the following command:

    DNS_SP=$(az ad sp create-for-rbac --name ${EXTERNAL_DNS_NEW_SP_NAME})
    EXTERNAL_DNS_SP_APP_ID=$(echo "$DNS_SP" | jq -r '.appId')
    EXTERNAL_DNS_SP_PASSWORD=$(echo "$DNS_SP" | jq -r '.password')
  10. Get the DNS zone ID by entering the following command:

    DNS_ID=$(az network dns zone show \
      --name ${DNS_ZONE_NAME} \
      --resource-group ${RESOURCE_GROUP_NAME} \
      --query "id" \
      --output tsv)
  11. Assign the Reader role to the service principal by entering the following command:

    $ az role assignment create \
      --role "Reader" \
      --assignee "${EXTERNAL_DNS_SP_APP_ID}" \
      --scope "${DNS_ID}"
  12. Assign the Contributor role to the service principal by entering the following command:

    $ az role assignment create \
      --role "Contributor" \
      --assignee "${EXTERNAL_DNS_SP_APP_ID}" \
      --scope "${DNS_ID}"
  13. Create the content for the Azure credentials file as shown in the following example:

    {
      "tenantId": "$(az account show --query tenantId -o tsv)",
      "subscriptionId": "$(az account show --query id -o tsv)",
      "resourceGroup": "$RESOURCE_GROUP_NAME",
      "aadClientId": "$EXTERNAL_DNS_SP_APP_ID",
      "aadClientSecret": "$EXTERNAL_DNS_SP_PASSWORD"
    }
  14. Create the credentials file by entering the following command:

    $ oc apply -f <service_principal_filepath>.json
  15. If an existing Kubernetes secret for the Azure credentials exists, delete it by entering the following command:

    $ oc delete secret/azure-config-file --namespace "default" || true
  16. Create the Kubernetes secret for the Azure credentials by entering the following command:

    $ oc create secret generic azure-config-file \
      --namespace "default" \
      --from-file ${SERVICE_PRINCIPAL_FILEPATH}
  17. Configure the HyperShift Operator to use external DNS by creating the following ConfigMap object:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: hypershift-operator-install-flags
      namespace: local-cluster
    data:
      installFlagsToAdd: "--external-dns-provider=azure --external-dns-credentials <secret> --external-dns-domain-filter <dns_zone>"
      installFlagsToRemove: ""

    The data.installFlagsToAdd parameter specifies the flags to pass to the Operator so it detects the DNS.

  18. Apply the config map by entering the following command:

    $ oc apply -f hypershift-operator-install-flags.yaml

Verification

  • Verify that both the HyperShift Operator and the external DNS are running by entering the following command:

    $ oc get pods -n hypershift

    Example output

    NAME                           READY   STATUS    RESTARTS   AGE
    external-dns-xxxxx-xxxxx       1/1     Running   0          1m
    operator-xxxxx-xxxxx           1/1     Running   0          1m

4.2.4. Creating a hosted cluster on Azure

Hosted clusters are where your applications run. Each hosted cluster has its own control plane that runs on the management cluster and a set of compute node virtual machines (VMs) in Azure.

The hosted cluster uses Workload Identities to securely access Azure services without storing credentials.

Prerequisites

  • You installed the Azure command-line interface (CLI).
  • You installed the hosted control planes CLI, hcp.
  • You installed the OpenShift CLI (oc).
  • You installed the jq command-line JSON processor.
  • You have a management cluster where the HyperShift Operator is installed and external DNS is configured.
  • You set up Azure resources, including Workload Identities, an OIDC issuer, and infrastructure.
  • You have the appropriate Azure permissions.

    • At the subscription level, you must have the Contributor role and the User Access Administrator role.
    • For Microsoft Graph API, you must have the Application.ReadWrite.OwnedBy permission.

Procedure

  • Create the HostedCluster custom resource by entering the following command:

    $ hcp create cluster azure \
      --name "$CLUSTER_NAME" \
      --infra-id "$INFRA_ID" \
      --azure-creds $AZURE_CREDS \
      --location ${LOCATION} \
      --node-pool-replicas 2 \
      --base-domain $BASE_DOMAIN \
      --pull-secret $PULL_SECRET \
      --generate-ssh \
      --release-image ${RELEASE_IMAGE} \
      --sa-token-issuer-private-key-path "${SA_TOKEN_ISSUER_PRIVATE_KEY_PATH}" \
      --oidc-issuer-url "${OIDC_ISSUER_URL}" \
      --dns-zone-rg-name ${PERSISTENT_RG_NAME} \
      --assign-service-principal-roles \
      --infra-json <output_infra_file> \
      --diagnostics-storage-account-type Managed \
      --external-dns-domain "${DNS_ZONE_NAME}"

Verification

  1. Check the cluster status by entering the following command:

    $ oc get hostedcluster $CLUSTER_NAME -n clusters
  2. Wait for the cluster to be complete by entering the following command:

    $ oc wait \
      --for=jsonpath='{.status.version.history[0].state}'=Completed \
      hostedcluster/$CLUSTER_NAME \
      -n clusters --timeout=20m
  3. Create the kubeconfig file for the cluster by entering the following command:

    $ hcp create kubeconfig \
      --name $CLUSTER_NAME > $CLUSTER_NAME-kubeconfig
  4. Get the kubeconfig file by entering the following command:

    $ export KUBECONFIG=$CLUSTER_NAME-kubeconfig
  5. Access the cluster nodes by entering the following command:

    $ oc get nodes
  6. Access the cluster by entering the following command:

    $ oc get clusterversion

4.2.5. Private hosted clusters on Azure

By default, hosted clusters are accessible through public DNS and the default router of the management cluster. If you want communication between your compute nodes and the hosted control plane to be private, you can create hosted clusters that use Azure Private Link for communication.

Private endpoint access uses Azure Private Link to expose the internal load balancer of the hosted control plane to the Azure Virtual Network (VNet) of the hosted cluster. Compute nodes resolve the API server hostname by using private DNS zones that point to the private endpoint IP address.

4.2.5.1. Preparing a subnet for a private hosted cluster on Azure

Azure Private Link requires a dedicated subnet for network address translator (NAT) IP address allocation. You can manually create the subnet, or it can be automatically created during cluster creation.

By manually creating the subnet, you have control over classless inter-domain routing (CIDR) allocation and naming. The following steps apply to manually creating the subnet. If you want the subnet to be automatically created, skip this procedure.

Note

Azure Private Link, the NAT subnet, and the internal load balancer of the management cluster must all be in the same Azure region. Private Link is automatically created in the location where the hosted cluster is created. Azure rejects the creation of Private Link if the NAT subnet is in a different region.

Prerequisites

  • You have an OpenShift Container Platform management cluster on Azure. For more information, see "Configuring an Azure management cluster for hosted control planes".
  • The Azure command-line interface (CLI) is installed and configured.
  • The OpenShift CLI (oc) is installed.
  • If you are using external DNS, the jq command-line JSON processor is installed.
  • You configured an OIDC issuer. For more information, see "Setting up an OIDC issuer".

Procedure

  1. Identify the Azure Virtual Network (VNet) of the management cluster.

    1. Obtain the infrastructure resource group of the management cluster as shown in the following example:

      $ MGMT_INFRA_RG=$(oc get infrastructure cluster -o jsonpath='{.status.platformStatus.azure.resourceGroupName}')
    2. Find the VNet in the infrastructure resource group as shown in the following example:

      $ MGMT_VNET_NAME=$(az network vnet list --resource-group "${MGMT_INFRA_RG}" --query "[0].name" -o tsv)
    3. Set the environment variable for the VNet by entering the following command:

      $ MGMT_VNET_RG="${MGMT_INFRA_RG}"
  2. Create the NAT subnet.

    1. Check the existing address space and subnets to ensure that you do not choose an overlapping classless inter-domain routing (CIDR) range. Enter the following command:

      $ az network vnet show \
        --resource-group "${MGMT_VNET_RG}" \
        --name "${MGMT_VNET_NAME}" \
        --query '{addressSpace: addressSpace.addressPrefixes, subnets: subnets[].{name: name, prefix: addressPrefix}}' \
        -o json
    2. Create the subnet as shown in the following example:

      $ az network vnet subnet create \
        --resource-group "${MGMT_VNET_RG}" \
        --vnet-name "${MGMT_VNET_NAME}" \
        --name "${NAT_SUBNET_NAME}" \
        --address-prefixes 10.1.64.0/24 \
        --disable-private-link-service-network-policies true
      • The NAT subnet must be in the VNet of the management cluster because Private Link is created alongside the internal load balancer of the management cluster.
      • The 10.1.64.0/24 address prefix is an example only. Replace it with a CIDR range that does not overlap with any other subnet in the VNet of the management cluster. If the VNet uses 10.0.0.0/16, the NAT subnet must fall within that range, or you must expand the address space of the VNet.
      • The --disable-private-link-service-network-policies flag is required and must be set to true. Otherwise, Azure rejects the creation of Private Link on the subnet.
  3. Obtain the NAT subnet resource ID for later use as shown in the following example:

    $ NAT_SUBNET_ID=$(az network vnet subnet show \
      --resource-group "${MGMT_VNET_RG}" \
      --vnet-name "${MGMT_VNET_NAME}" \
      --name "${NAT_SUBNET_NAME}" \
      --query id -o tsv)

To set up an environment that supports private clusters, you must install the HyperShift Operator with flags that configure Azure Private Link management.

Note

If you already installed the HyperShift Operator but you did not include the --private-platform Azure setting, you must run the hcp install command again with the private platform flags before you can create private clusters.

Prerequisites

  • You have an OpenShift Container Platform management cluster on Azure.
  • The Azure command-line interface (CLI) is installed and configured.
  • The OpenShift CLI (oc) is installed.
  • If you are using external DNS, the jq command-line JSON processor is installed.
  • You configured an OIDC issuer. For more information, see "Setting up an OIDC issuer".

Procedure

  1. Obtain credentials so that the Operator can manage Private Link resources.

    1. Obtain the credentials file for Private Link management as shown in the following example:

      $ AZURE_PRIVATE_CREDS="<path_to_azure_private_credentials_json>"
    2. Obtain the infrastructure resource group of the management cluster as shown in the following example:

      $ MGMT_INFRA_RG=$(oc get infrastructure cluster -o jsonpath='{.status.platformStatus.azure.resourceGroupName}')
  2. Set the external DNS configuration variables as shown in the following examples:

    $ SERVICE_PRINCIPAL_FILEPATH="<path_to_azure_mgmt_json_file>"
    $ DNS_ZONE_NAME="<my_subdomain_my_parent_dns_zone_com>"
  3. Install the HyperShift Operator with private platform support as shown in the following example:

    $ hcp install \
      --pull-secret ${PULL_SECRET} \
      --private-platform Azure \
      --azure-private-creds ${AZURE_PRIVATE_CREDS} \
      --azure-pls-resource-group ${MGMT_INFRA_RG} \
      --external-dns-provider=azure \
      --external-dns-credentials ${SERVICE_PRINCIPAL_FILEPATH} \
      --external-dns-domain-filter ${DNS_ZONE_NAME}
    • --private-platform Azure specifies that Azure Private Link management is to be enabled in the Operator.
    • --azure-private-creds specifies the path to the Azure credentials file that is used for Private Link operations.

      Note

      Besides using the --azure-private-creds flag, you can use one of the following authentication methods. Be sure to use only one authentication method.

      • --azure-private-secret specifies an existing Kubernetes secret that has Azure credentials. This flag has a companion flag, --azure-private-secret-key. Its default value is credentials, but you can customize it for secrets that have non-standard key names.
      • --azure-pls-managed-identity-client-id specifies the client ID of a managed identity for Private Link operations through Workload Identity federation. If you specify this flag, you must also include the --azure-pls-subscription-id flag, which specifies the Azure subscription ID for Private Link operations.
    • --azure-pls-resource-group specifies the resource group where the Private Link resources are to be created. This resource group is the same as the resource group of the infrastructure for the management cluster.
    • --external-dns-credentials specifies the path to a file that contains DNS credentials. If preferred, you can use the --external-dns-secret flag instead to specify a Kubernetes secret that has DNS credentials.

4.2.5.3. Configuring IAM resources for a private hosted cluster

Create Workload Identities so that your private clusters can manage private endpoints and private DNS zones.

Prerequisites

  • You have an OpenShift Container Platform management cluster on Azure that has the HyperShift Operator installed.
  • The Azure command-line interface (CLI) is installed and configured.
  • The OpenShift CLI (oc) is installed.
  • If you are using external DNS, the jq command-line JSON processor is installed.
  • You configured an OIDC issuer. For more information, see "Setting up an OIDC issuer".

Procedure

  1. Set your environment variables:

    1. Set your prefix by entering the following command:

      $ PREFIX="<my_prefix>"
    2. Set the cluster name by entering the following command:

      $ CLUSTER_NAME="${PREFIX}-hc"
    3. Set the resource group name by entering the following command:

      $ RESOURCE_GROUP_NAME="${CLUSTER_NAME}-${PREFIX}"
    4. Set the location by entering the following command:

      $ LOCATION="<my_region>"
    5. Set the variable for the path to the Azure credentials file by entering the following command:

      $ AZURE_CREDS="<path_to_azure_credentials_json>"
    6. Set the variable for the OIDC issuer URL by entering the following command:

      $ OIDC_ISSUER_URL="<my_oidc_url_com>"
    7. Set the path to the Workload Identities file by entering the following command:

      $ WORKLOAD_IDENTITIES_FILE="<path_to_workload_identities_file_json>"
  2. Create Workload Identities by entering the following command:

    $ hcp create iam azure \
      --name "${CLUSTER_NAME}" \
      --infra-id "${PREFIX}" \
      --azure-creds "${AZURE_CREDS}" \
      --location "${LOCATION}" \
      --resource-group-name "${RESOURCE_GROUP_NAME}" \
      --oidc-issuer-url "${OIDC_ISSUER_URL}" \
      --output-file "${WORKLOAD_IDENTITIES_FILE}"

    The command creates 8 Workload Identities. For Private and PublicAndPrivate clusters, the Control Plane Operator identity is used to create and manage private endpoints, private DNS zones, Azure Virtual Network (VNet) links, and DNS A records. The Control Plane Identity is assigned the Contributor role by default. To use a more restrictive role, use the --assign-custom-hcp-roles flag.

4.2.5.4. Creating infrastructure for a private hosted cluster

Set up infrastructure so that you can create private hosted clusters.

Prerequisites

  • You have an OpenShift Container Platform management cluster on Azure that has the HyperShift Operator installed.
  • The Azure command-line interface (CLI) is installed and configured.
  • The OpenShift CLI (oc) is installed.
  • If you are using external DNS, the yq command-line YAML processor is installed.
  • You configured an OIDC issuer. For more information, see "Setting up an OIDC issuer".

Procedure

  1. Set your environment variables:

    1. Set the variable for the DNS zone resource group by entering the following command:

      $ DNS_ZONE_RG_NAME="os4-common"
    2. Set the variable for the base domain of your DNS zone by entering the following command:

      $ PARENT_DNS_ZONE="<your_base_domain_com>"
    3. Set the variable that points to the infrastructure output file by entering the following command:

      $ INFRA_OUTPUT_FILE="${PREFIX}-infra-output.json"
  2. Create infrastructure by entering the following command:

    $ hcp create infra azure \
      --azure-creds "${AZURE_CREDS}" \
      --infra-id "${PREFIX}" \
      --name "${CLUSTER_NAME}" \
      --location "${LOCATION}" \
      --base-domain "${PARENT_DNS_ZONE}" \
      --dns-zone-rg-name "${DNS_ZONE_RG_NAME}" \
      --workload-identities-file "${WORKLOAD_IDENTITIES_FILE}" \
      --assign-identity-roles \
      --output-file "${INFRA_OUTPUT_FILE}"
  3. Read the infrastructure output to get the resource IDs that you created, as shown in the following example:

    1. Read the resource group name by entering the following command:

      $ MANAGED_RG_NAME=$(yq -r -p yaml '.resourceGroupName' "${INFRA_OUTPUT_FILE}")
    2. Read the VNet ID by entering the following command:

      $ VNET_ID=$(yq -r -p yaml '.vnetID' "${INFRA_OUTPUT_FILE}")
    3. Read the subnet ID by entering the following command:

      $ SUBNET_ID=$(yq -r -p yaml '.subnetID' "${INFRA_OUTPUT_FILE}")
    4. Read the network security group ID by entering the following command:

      $ NSG_ID=$(yq -r -p yaml '.securityGroupID' "${INFRA_OUTPUT_FILE}")

      Note the resource IDs because you need them to create the private hosted cluster.

4.2.5.5. Creating a private Azure hosted cluster

Create a private hosted cluster to ensure that the communication between compute nodes and the hosted control plane occurs over Azure Private Link.

Prerequisites

  • You configured a subnet, as described in "Preparing a subnet for a private hosted cluster on Azure".
  • You installed the HyperShift Operator on an OpenShift Container Platform management cluster on Azure, as described in "Installing the HyperShift Operator with private platform support".
  • You created Identity and Access Management (IAM) resources, as described in "Configuring IAM resources for a private hosted cluster".
  • You created infrastructure, as described in "Creating infrastructure for a private hosted cluster".
  • This procedure relies on environment variables that you created in the prerequisite procedures. Be sure to complete this procedure in the same terminal where you already defined the environment variables.

Procedure

  1. Create the private hosted cluster by entering the following command:

    $ hcp create cluster azure \
      --name "$CLUSTER_NAME" \
      --namespace "clusters" \
      --azure-creds ${AZURE_CREDS} \
      --location ${LOCATION} \
      --node-pool-replicas 2 \
      --base-domain ${PARENT_DNS_ZONE} \
      --pull-secret ${PULL_SECRET} \
      --generate-ssh \
      --release-image ${RELEASE_IMAGE} \
      --resource-group-name "${MANAGED_RG_NAME}" \
      --vnet-id "${VNET_ID}" \
      --subnet-id "${SUBNET_ID}" \
      --network-security-group-id "${NSG_ID}" \
      --sa-token-issuer-private-key-path "${SA_TOKEN_ISSUER_PRIVATE_KEY_PATH}" \
      --oidc-issuer-url "${OIDC_ISSUER_URL}" \
      --dns-zone-rg-name ${DNS_ZONE_RG_NAME} \
      --assign-service-principal-roles \
      --workload-identities-file ${WORKLOAD_IDENTITIES_FILE} \
      --external-dns-domain ${DNS_ZONE_NAME} \
      --endpoint-access Private \
      --endpoint-access-private-nat-subnet-id "${NAT_SUBNET_ID}"
    • When you choose a value for the --external-dns-domain flag, ensure that the value does not match {cluster-name}.{base-domain}. If you use {cluster-name}.{base-domain} for the value, the Control Plane Operator creates a private DNS zone that can shadow the *.apps domain, which causes the console and ingress to become unreachable.
    • --endpoint-access accepts 3 values:

      • Public, which is the default value. When you specify Public, the API server is accessible through public endpoint only.
      • PublicAndPrivate, where the API server is accessible through both public and private endpoints.
      • Private, where the API server is accessible only through Private Link.

        After you create a cluster, you cannot change it between Public endpoint and non-public (PublicAndPrivate or Private) endpoint access.

        If you need to allow Private endpoint connections from Azure subscriptions other than the hosted cluster’s subscription, use the following flag: --endpoint-access-private-additional-allowed-subscriptions "sub-id-1, sub-id-2".

Verification

  1. Check the Private Link resources by entering the following command:

    $ oc get azureprivatelinkservices -n clusters-${CLUSTER_NAME}
  2. Check the status and connections by entering the following command:

    $ oc get azureprivatelinkservices -n clusters-${CLUSTER_NAME} -o yaml
    Expand
    Table 4.9. Setup progress conditions
    ConditionDescription

    AzureInternalLoadBalancerAvailable

    The internal load balancer has a front-end IP address.

    AzurePLSCreated

    Private Link is created in the management cluster.

    AzurePrivateEndpointAvailable

    Private endpoint is created in the hosted cluster VNet.

    AzurePrivateDNSAvailable

    Private DNS zones and A records are created.

    AzurePrivateLinkServiceAvailable

    All components are ready and private connectivity is available.

  3. Check the overall cluster status by entering the following command:

    $ oc get hostedcluster ${CLUSTER_NAME} -n clusters
  4. Wait for the status by entering the following command:

    $ oc wait --for=condition=Available hostedcluster/${CLUSTER_NAME} -n clusters --timeout=30m

4.2.5.6. Accessing a private Azure hosted cluster

After you create a private hosted cluster, you need to take additional steps to access it.

Prerequisites

  • You completed the steps in "Creating a private Azure hosted cluster".

Procedure

  • To access a private hosted cluster by generating a kubeconfig file, enter the following command:

    $ hcp create kubeconfig \
      --name ${CLUSTER_NAME} \
      --port-forward > ${CLUSTER_NAME}-kubeconfig
  • If you have access to the management cluster, you can port forward to the API server to access the private hosted cluster.

    1. Port forward to the kube-apiserver service by entering the following command:

      $ kubectl port-forward svc/kube-apiserver \
        -n clusters-${CLUSTER_NAME} 6443:6443 &
    2. Access the hosted cluster by using the kubeconfig file:

      $ KUBECONFIG=${CLUSTER_NAME}-kubeconfig oc get nodes
  • If you have a virtual machine (VM) in an Azure Virtual Network (VNet) that is peered with the hosted cluster’s VNet, you can access the API server, but you must first link the private DNS zones to the peered VNet.

    Note

    The Control Plane Operator links private DNS zones only to the hosted cluster’s VNet. If you want to resolve the API server hostname from a peered VNet, you must manually link the private DNS zones to that VNet as shown in the following steps. Otherwise, DNS resolution fails from the peered VNet.

    1. Link the private DNS zone to your peered VNet as shown in the following example:

      $ PEERED_VNET_ID="/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Network/virtualNetworks/<vnet>"
    2. Enter the following command:

      $ az network private-dns link vnet create \
        --resource-group "${MANAGED_RG_NAME}" \
        --zone-name "${CLUSTER_NAME}.hypershift.local" \
        --name "peered-vnet-link" \
        --virtual-network "${PEERED_VNET_ID}" \
        --registration-enabled false
    3. If you also need base-domain resolution, enter the following command:

      $ az network private-dns link vnet create \
        --resource-group "${MANAGED_RG_NAME}" \
        --zone-name "${PARENT_DNS_ZONE}" \
        --name "peered-vnet-basedomain-link" \
        --virtual-network "${PEERED_VNET_ID}" \
        --registration-enabled false
    4. Access the cluster as shown in the following example:

      $ KUBECONFIG=${CLUSTER_NAME}-kubeconfig oc get nodes

4.2.5.7. Troubleshooting private hosted clusters on Azure

If your private hosted cluster gets stuck, check the AzurePrivateLinkService custom resource conditions.

Procedure

  1. Enter the following command to check the Private Link conditions:

    $ oc get azureprivatelinkservices \
      -n clusters-${CLUSTER_NAME} \
      -o jsonpath='{.items[0].status.conditions}' | jq .
  2. Review the output and compare it to the following condition table:

    Expand
    Table 4.10. Private cluster stuck conditions
    ConditionPossible cause

    AzureInternalLoadBalancerAvailable = False

    The private-router service has not received an internal load balancer IP address yet. Check the service status and Azure networking.

    AzurePLSCreated = False

    Private Link creation failed. Check the NAT subnet policies, credentials, and the HyperShift Operator logs.

    AzurePrivateEndpointAvailable = False

    Private endpoint creation failed or the connection was not approved. Check the Private Link auto-approval list and the Control Plane Operator logs.

    AzurePrivateDNSAvailable = False

    The DNS zone or record creation failed. In the Azure subscription that stores the infrastructure resources for the hosted cluster, check the Control Plane Operator identity permissions.

4.2.6. Example: Autoscaling a hosted cluster on Azure

To balance node pools on your Azure hosted cluster, you can configure autoscaling for the cluster.

When you scale up NodePool objects, the Cluster API Provider for Azure provisions individual Azure virtual machines.

To configure autoscaling for a hosted cluster on Azure, you edit the spec.autoscaling parameters in the HostedCluster resource. The following example shows a HostedCluster resource with 2 Azure node pools.

Note

This example shows only the autoscaling-related fields.

apiVersion: hypershift.openshift.io/v1beta1
kind: HostedCluster
metadata:
  name: my-cluster
  namespace: my-cluster-namespace
spec:
  autoscaling:
    scaling: ScaleUpAndScaleDown
    maxNodesTotal: 12
    expanders:
      - Random
    scaleDown:
      delayAfterAddSeconds: 300
      unneededDurationSeconds: 600
      utilizationThresholdPercent: 40
    balancingIgnoredLabels:
      - "custom.label/environment"
    maxFreeDifferenceRatioPercent: 70
---
apiVersion: hypershift.openshift.io/v1beta1
kind: NodePool
metadata:
  name: my-cluster-nodepool-1
  namespace: my-cluster-namespace
spec:
  clusterName: my-cluster
  autoScaling:
    min: 1
    max: 6
  platform:
    azure:
      vmSize: Standard_D4s_v3
      # ...
---
apiVersion: hypershift.openshift.io/v1beta1
kind: NodePool
metadata:
  name: my-cluster-nodepool-2
  namespace: my-cluster-namespace
spec:
  clusterName: my-cluster
  autoScaling:
    min: 1
    max: 6
  platform:
    azure:
      vmSize: Standard_D4s_v3
      # ...
  • spec.autoScaling.min must be greater than or equal to 1. Scaling from zero (autoScaling.min: 0) is not supported on Azure.

4.2.7. Deleting an Azure hosted cluster and its resources

If you no longer need a hosted cluster, you can remove it and its infrastructure. Any related Workload Identities and OIDC issuers that were created during setup can be reused for other clusters or deleted separately if you no longer need them.

4.2.7.1. Deleting a hosted cluster on Azure

If you are no longer using a hosted cluster on Azure, you can delete it.

Procedure

  • To delete a hosted cluster, enter the following command:

    $ hcp destroy cluster azure \
      --name $CLUSTER_NAME \
      --azure-creds $AZURE_CREDS \
      --dns-zone-rg-name $PERSISTENT_RG_NAME \
      --preserve-resource-group
    • --name specifies your hosted cluster name.
    • --azure-creds specifies an Azure credentials file that has permission to create infrastructure resources, such as virtual networks, subnets, and load balancers.
    • --dns-zone-rg-name specifies the name of the resource group that contains your DNS zone.
    • --preserve-resource-group specifies that the infrastructure will be preserved. If you do not want to preserve the infrastructure, do not include this flag.

4.2.7.2. Deleting Azure infrastructure

If you have Azure infrastructure without a hosted cluster, you can remove the infrastructure if you are not using it.

For example, this scenario can happen if you created the infrastructure standalone but never created a hosted cluster. Or, you might have manually deleted the hosted cluster or management cluster, but the infrastructure resources still exist.

You can delete the entire infrastructure, or delete cluster-specific resources but preserve the main resource group. Preserving the main resource group is helpful when you have other resources in the same resource group that you want to keep.

If you have a hosted cluster and want to delete infrastructure while you delete the hosted cluster, follow the steps in "Deleting a hosted cluster on Azure", but omit the --preserve-resource-group flag.

Procedure

  • To delete the infrastructure, enter one of the following commands:

    • To delete the infrastructure, including the resource group, enter the following command:

      $ hcp destroy infra azure \
        --name <my_cluster_name> \
        --infra-id <infra_id> \
        --azure-creds <azure_credentials_file>
      • --name specifies your hosted cluster name.
      • --infra-id specifies a unique name that identifies your infrastructure. This value is used to name and tag Azure resources. Typically, it is the name of your cluster with a suffix appended to it.
      • --azure-creds specifies an Azure credentials file that has permission to create infrastructure resources, such as virtual networks, subnets, and load balancers.
    • To preserve the resource group but delete only cluster-specific resources, enter the following command:

      $ hcp destroy infra azure \
        --name <my_cluster_name> \
        --infra-id <infra_id> \
        --azure-creds <azure_credentials_file> \
        --preserve-resource-group
      • --name specifies your hosted cluster name.
      • --infra-id specifies a unique name that identifies your infrastructure. This value is used to name and tag Azure resources. Typically, it is the name of your cluster with a suffix appended to it.
      • --azure-creds specifies an Azure credentials file that has permission to create infrastructure resources, such as virtual networks, subnets, and load balancers.
      • --preserve-resource-group specifies that you want to preserve the resource group.

4.2.7.3. Deleting Azure Workload Identities

As part of the process to delete a hosted cluster on Azure, you need to delete the Workload Identities.

To delete the Workload Identities, you enter a command on the hosted control planes command-line interface, hcp. The command uses the file that was generated when you created the Workload Identities to identify the identities to delete. Both the managed identities and their federated credentials are removed.

Prerequisites

  • If you created infrastructure by using the Workload Identities, delete the infrastructure before you delete the identities.

Procedure

  • Enter the following command:

    $ hcp destroy iam azure \
        --azure-creds <azure_credentials_file> \
        --workload-identities-file <workload_identities_file> \
        --resource-group-name <resource_group> \
        --name <my_cluster_name> \
        --infra-id <infra_id> \
        --dns-zone-rg-name <dns_zone_rg> \
        --cloud <my_cloud_environment>
    • <azure_credentials_file> specifies the Azure credentials file with permission to create managed identities and federated credentials.
    • <workload_identities_file> specifies the path to the Workload Identities JSON file, such as my-cluster-name-iam-output.json.
    • <resource_group> specifies the name of the resource group where you created identities.
    • <my_cluster_name> specifies the name of your hosted cluster.
    • <infra_id> specifies the unique identifier for naming Azure resources. Typically, this identifier is the cluster name with a suffix.
    • <dns_zone_rg> specifies the DNS zone resource group.
    • <my_cloud_environment> specifies the Azure cloud environment. Setting the --cloud flag is optional. The default value is AzurePublicCloud.

4.2.7.4. Deleting a private hosted cluster on Azure

If you are no longer using a private hosted cluster on Azure, you can delete it.

The deletion process automatically cleans up Private Link resources in the following order:

  1. The Control Plane Operator removes the private endpoint, private DNS zones, VNet links, and A records.
  2. The hcp destroy command removes role-based access control (RBAC) role assignments.
  3. The HyperShift Operator removes Private Link.

Procedure

  • To delete a private hosted cluster, enter the following command:

    $ hcp destroy cluster azure \
      --name ${CLUSTER_NAME} \
      --azure-creds ${AZURE_CREDS} \
      --resource-group-name ${MANAGED_RG_NAME} \
      --dns-zone-rg-name ${DNS_ZONE_RG_NAME}
    • --name specifies your hosted cluster name.
    • --azure-creds specifies an Azure credentials file that has permission to create infrastructure resources, such as virtual networks, subnets, and load balancers. This flag is required because the hcp destroy cluster azure command cleans up RBAC role assignments before it deletes infrastructure.
    • --resource-group-name specifies the name of the resource group where you created identities.
    • --dns-zone-rg-name specifies the name of the resource group that contains your DNS zone.

To maximize hardware performance and maintain control over your physical infrastructure, you can deploy hosted control planes on bare metal by using the Agent platform. This deployment method reduces virtualization overhead and offers low-latency networking for performance-intensive workloads.

You can deploy hosted control planes on bare-metal infrastructure with the Agent platform by configuring an OpenShift Container Platform cluster to function as a management cluster.

The management cluster is the OpenShift Container Platform cluster where the control planes are hosted. In some contexts, the management cluster is also known as the hosting cluster. The management cluster is not the same thing as the managed cluster. A managed cluster is a cluster that the hub cluster manages.

The hosted control planes feature is enabled by default.

The multicluster engine Operator supports only the default local-cluster, which is a hub cluster that is managed, and the hub cluster as the management cluster. If you have Red Hat Advanced Cluster Management installed, you can use the managed hub cluster, also known as the local-cluster, as the management cluster.

A hosted cluster is an OpenShift Container Platform cluster with its API endpoint and control plane that are hosted on the management cluster. The hosted cluster includes the control plane and its corresponding data plane. You can use the multicluster engine Operator console or the hosted control plane command-line interface (hcp) to create a hosted cluster.

The hosted cluster is automatically imported as a managed cluster. If you want to disable this automatic import feature, see "Disabling the automatic import of hosted clusters into multicluster engine Operator".

4.3.2. Preparing to deploy hosted control planes on bare metal

Before you deploy hosted control planes on bare metal, ensure that you understand the requirements for the deployment.

  • Run the management cluster and compute nodes on the same platform.
  • All bare-metal hosts require a manual start with a Discovery Image ISO that the central infrastructure management provides. You can start the hosts manually or through automation by using the Cluster Baremetal Operator. After each host starts, it runs an Agent process to discover the host details and complete the installation. An Agent custom resource represents each host.
  • When you configure storage for hosted control planes, consider the recommended etcd practices. To ensure that you meet the latency requirements, dedicate a fast storage device to all hosted control plane etcd instances that run on each control-plane node. You can use LVM storage to configure a local storage class for hosted etcd pods. For more information, see "Recommended etcd practices" and "Persistent storage using logical volume manager storage".

4.3.2.1. Bare metal firewall, port, and service requirements

You must meet the firewall, port, and service requirements so that ports can communicate between the management cluster, the control plane, and hosted clusters.

Note

Services run on their default ports. However, if you use the NodePort publishing strategy, services run on the port that is assigned by the NodePort service.

Use firewall rules, security groups, or other access controls to restrict access to only required sources. Avoid exposing ports publicly unless necessary. For production deployments, use a load balancer to simplify access through a single IP address.

If your hub cluster has a proxy configuration, ensure that it can reach the hosted cluster API endpoint by adding all hosted cluster API endpoints to the noProxy field on the Proxy object. For more information, see "Configuring the cluster-wide proxy".

A hosted control plane exposes the following services on bare metal:

  • APIServer

    • The APIServer service runs on port 6443 by default and requires ingress access for communication between the control plane components.
    • If you use MetalLB load balancing, allow ingress access to the IP range that is used for load balancer IP addresses.
  • OAuthServer

    • The OAuthServer service runs on port 443 by default when you use the route and ingress to expose the service.
    • If you use the NodePort publishing strategy, use a firewall rule for the OAuthServer service.
  • Konnectivity

    • The Konnectivity service runs on port 443 by default when you use the route and ingress to expose the service.
    • The Konnectivity agent establishes a reverse tunnel to allow the control plane to access the network for the hosted cluster. The agent uses egress to connect to the Konnectivity server. The server is exposed by using either a route on port 443 or a manually assigned NodePort.
    • If the cluster API server address is an internal IP address, allow access from the workload subnets to the IP address on port 6443.
    • If the address is an external IP address, allow egress on port 6443 to that external IP address from the nodes.
  • Ignition

    • The Ignition service runs on port 443 by default when you use the route and ingress to expose the service.
    • If you use the NodePort publishing strategy, use a firewall rule for the Ignition service.

You do not need the following services on bare metal:

  • OVNSbDb
  • OIDC

4.3.2.2. Bare metal infrastructure requirements

Although the Agent platform does not create any infrastructure, the Agent platform does have requirements for infrastructure.

  • Agents: An Agent represents a host that is booted with a discovery image and is ready to be provisioned as an OpenShift Container Platform node.
  • DNS: The API and ingress endpoints must be routable.

4.3.3. Configuring a management cluster for bare metal

Before you create a hosted cluster on bare metal with the Agent platform, you need a properly configured OpenShift Container Platform management cluster.

Prerequisites

  • The management cluster and compute nodes must be on the same platform.
  • You need the multicluster engine for Kubernetes Operator 2.2 and later installed on an OpenShift Container Platform cluster. You can install multicluster engine Operator as an Operator from the OpenShift Container Platform software catalog.

Procedure

  1. The multicluster engine Operator must have at least one managed OpenShift Container Platform cluster. The local-cluster is automatically imported in multicluster engine Operator 2.2 and later. For more information about the local-cluster, see "Advanced configuration" in the Red Hat Advanced Cluster Management documentation. You can check the status of your hub cluster by running the following command:

    $ oc get managedclusters local-cluster
  2. Add the topology.kubernetes.io/zone label to your bare-metal hosts on your management cluster. Ensure that each host has a unique value for topology.kubernetes.io/zone. Otherwise, all of the control plane pods are scheduled on a single node, causing a single point of failure.
  3. Use the Agent platform to provision hosted control planes on bare metal. The Agent platform uses the central infrastructure management service to add compute nodes to a hosted cluster. For more information, see "Enabling the central infrastructure management service".
  4. Install the hosted control plane command-line interface. For more information, see "Installing the hosted control planes command-line interface".

4.3.4. DNS configurations on bare metal

The API Server for the hosted cluster is exposed as a NodePort service. A DNS entry must exist for api.<hosted_cluster_name>.<base_domain> that points to destination where the API Server can be reached.

The DNS entry can be as simple as a record that points to one of the nodes in the management cluster that is running the hosted control plane. The entry can also point to a load balancer that is deployed to redirect incoming traffic to the ingress pods.

Example DNS configuration

api.example.krnl.es.    IN A 192.168.122.20
api.example.krnl.es.    IN A 192.168.122.21
api.example.krnl.es.    IN A 192.168.122.22
api-int.example.krnl.es.    IN A 192.168.122.20
api-int.example.krnl.es.    IN A 192.168.122.21
api-int.example.krnl.es.    IN A 192.168.122.22
`*`.apps.example.krnl.es. IN A 192.168.122.23

Note

In the previous example, *.apps.example.krnl.es. IN A 192.168.122.23 is either a node in the hosted cluster or a load balancer, if one has been configured.

If you are configuring DNS for a disconnected environment on an IPv6 network, the configuration looks like the following example.

Example DNS configuration for an IPv6 network

api.example.krnl.es.    IN A 2620:52:0:1306::5
api.example.krnl.es.    IN A 2620:52:0:1306::6
api.example.krnl.es.    IN A 2620:52:0:1306::7
api-int.example.krnl.es.    IN A 2620:52:0:1306::5
api-int.example.krnl.es.    IN A 2620:52:0:1306::6
api-int.example.krnl.es.    IN A 2620:52:0:1306::7
`*`.apps.example.krnl.es. IN A 2620:52:0:1306::10

If you are configuring DNS for a disconnected environment on a dual stack network, be sure to include DNS entries for both IPv4 and IPv6.

Example DNS configuration for a dual stack network

host-record=api-int.hub-dual.dns.base.domain.name,192.168.126.10
host-record=api.hub-dual.dns.base.domain.name,192.168.126.10
address=/apps.hub-dual.dns.base.domain.name/192.168.126.11
dhcp-host=aa:aa:aa:aa:10:01,ocp-control-plane-0,192.168.126.20
dhcp-host=aa:aa:aa:aa:10:02,ocp-control-plane-1,192.168.126.21
dhcp-host=aa:aa:aa:aa:10:03,ocp-control-plane-2,192.168.126.22
dhcp-host=aa:aa:aa:aa:10:06,ocp-installer,192.168.126.25
dhcp-host=aa:aa:aa:aa:10:07,ocp-bootstrap,192.168.126.26

host-record=api-int.hub-dual.dns.base.domain.name,2620:52:0:1306::2
host-record=api.hub-dual.dns.base.domain.name,2620:52:0:1306::2
address=/apps.hub-dual.dns.base.domain.name/2620:52:0:1306::3
dhcp-host=aa:aa:aa:aa:10:01,ocp-control-plane-0,[2620:52:0:1306::5]
dhcp-host=aa:aa:aa:aa:10:02,ocp-control-plane-1,[2620:52:0:1306::6]
dhcp-host=aa:aa:aa:aa:10:03,ocp-control-plane-2,[2620:52:0:1306::7]
dhcp-host=aa:aa:aa:aa:10:06,ocp-installer,[2620:52:0:1306::8]
dhcp-host=aa:aa:aa:aa:10:07,ocp-bootstrap,[2620:52:0:1306::9]

4.3.4.1. Defining a custom DNS name

As a cluster administrator, you can create a hosted cluster with an external API DNS name that differs from the internal endpoint that gets used for node bootstraps and control plane communication.

You might want to define a different DNS name for the following reasons:

  • To replace the user-facing TLS certificate with one from a public CA without breaking the control plane functions that bind to the internal root CA
  • To support split-horizon DNS and NAT scenarios
  • To ensure a similar experience to standalone control planes, where you can use functions, such as the Show Login Command function, with the correct kubeconfig and DNS configuration

You can define a DNS name either during your initial setup or during postinstallation operations, by entering a domain name in the kubeAPIServerDNSName parameter of a HostedCluster object.

Prerequisites

  • You have a valid TLS certificate that covers the DNS name that you set in the kubeAPIServerDNSName parameter.
  • You have a resolvable DNS name URI that can reach and point to the correct address.

Procedure

  • In the specification for the HostedCluster object, add the kubeAPIServerDNSName parameter and the address for the domain and specify which certificate to use, as shown in the following example:

    #...
    spec:
      configuration:
        apiServer:
          servingCerts:
            namedCertificates:
            - names:
              - xxx.example.com
              - yyy.example.com
              servingCertificate:
                name: <my_serving_certificate>
      kubeAPIServerDNSName: <custom_address>

    The value for the kubeAPIServerDNSName parameter must be a valid and addressable domain.

    After you define the kubeAPIServerDNSName parameter and specify the certificate, the Control Plane Operator controllers create a kubeconfig file named custom-admin-kubeconfig, where the file gets stored in the HostedControlPlane namespace. The generation of certificates happen from the root CA, and the HostedControlPlane namespace manages their expiration and renewal.

    The Control Plane Operator reports a new kubeconfig file named CustomKubeconfig in the HostedControlPlane namespace. That file uses the defined new server in the kubeAPIServerDNSName parameter.

    A reference for the custom kubeconfig file exists in the status parameter as CustomKubeconfig of the HostedCluster object. The CustomKubeConfig parameter is optional, and you can add the parameter only if the kubeAPIServerDNSName parameter is not empty. After you set the CustomKubeConfig parameter, the parameter triggers the generation of a secret named <hosted_cluster_name>-custom-admin-kubeconfig in the HostedCluster namespace. You can use the secret to access the HostedCluster API server. If you remove the CustomKubeConfig parameter during postinstallation operations, deletion of all related secrets and status references occur.

    Note

    Defining a custom DNS name does not directly impact the data plane, so no expected rollouts occur. The HostedControlPlane namespace receives the changes from the HyperShift Operator and deletes the corresponding parameters.

    If you remove the kubeAPIServerDNSName parameter from the specification for the HostedCluster object, all newly generated secrets and the CustomKubeconfig reference are removed from the cluster and from the status parameter.

4.3.5. Creating an InfraEnv resource

Before you can create a hosted cluster on bare metal, you need an InfraEnv resource.

On hosted control planes, the control-plane components run as pods on the management cluster while the data plane runs on dedicated nodes. You can use the Assisted Service to boot your hardware with a discovery ISO that adds your hardware to a hardware inventory.

Later, when you create a hosted cluster, the hardware from the inventory is used to provision the data-plane nodes. The object that is used to get the discovery ISO is an InfraEnv resource. You need to create a BareMetalHost object that configures the cluster to boot the bare-metal node from the discovery ISO.

4.3.5.1. Creating an InfraEnv resource and adding nodes

To ensure that your hardware is provisioned correctly before you create a hosted cluster on bare metal, create an InfraEnv resource. You can create the resource and add nodes by using the command-line interface (CLI).

Procedure

  1. Create a namespace to store your hardware inventory by entering the following command:

    $ oc --kubeconfig ~/<directory_example>/mgmt-kubeconfig create \
      namespace <namespace_example>

    where:

    <directory_example>
    Is the name of the directory where the kubeconfig file for the management cluster is saved.
    <namespace_example>

    Is the name of the namespace that you are creating; for example, hardware-inventory.

    Example output

    namespace/hardware-inventory created

  2. Copy the pull secret of the management cluster by entering the following command:

    $ oc --kubeconfig ~/<directory_example>/mgmt-kubeconfig \
      -n openshift-config get secret pull-secret -o yaml \
      | grep -vE "uid|resourceVersion|creationTimestamp|namespace" \
      | sed "s/openshift-config/<namespace_example>/g" \
      | oc --kubeconfig ~/<directory_example>/mgmt-kubeconfig \
      -n <namespace> apply -f -

    where:

    <directory_example>
    Is the name of the directory where the kubeconfig file for the management cluster is saved.
    <namespace_example>

    Is the name of the namespace that you are creating; for example, hardware-inventory.

    Example output

    secret/pull-secret created

  3. Create the InfraEnv resource by adding the following content to a YAML file:

    apiVersion: agent-install.openshift.io/v1beta1
    kind: InfraEnv
    metadata:
      name: hosted
      namespace: <namespace_example>
    spec:
      additionalNTPSources:
      - <ip_address>
      pullSecretRef:
        name: pull-secret
      sshAuthorizedKey: <ssh_public_key>
    # ...
  4. Apply the changes to the YAML file by entering the following command:

    $ oc apply -f <infraenv_config>.yaml

    Replace <infraenv_config> with the name of your file.

  5. Verify that the InfraEnv resource was created by entering the following command:

    $ oc --kubeconfig ~/<directory_example>/mgmt-kubeconfig \
      -n <namespace_example> get infraenv hosted
  6. Add bare-metal hosts by following one of two methods:

    • If you do not use the Metal3 Operator, obtain the discovery ISO from the InfraEnv resource and boot the hosts manually by completing the following steps:

      1. Download the live ISO by entering the following commands:

        $ oc get infraenv -A
        $ oc get infraenv <namespace_example> -o jsonpath='{.status.isoDownloadURL}' -n <namespace_example> <iso_url>
      2. Boot the ISO. The node communicates with the Assisted Service and registers as an agent in the same namespace as the InfraEnv resource.
      3. For each agent, set the installation disk ID and hostname, and approve it to indicate that the agent is ready for use.

        1. Enter the following command to get the agents for your hosted control plane namespace:

          $ oc -n <hosted_control_plane_namespace> get agents

          In this example, two agents are listed.

          Example output

          NAME                                   CLUSTER   APPROVED   ROLE          STAGE
          example-agent-1                        auto-assign
          example-agent-2                        auto-assign

        2. Enter the following command to set the installation disk ID and hostname for the first agent:

          $ oc -n <hosted_control_plane_namespace> \
            patch agent example-agent-1 \
            -p '{"spec":{"installation_disk_id":"/dev/sda","approved":true,"hostname":"worker-0.example.krnl.es"}}' \
            --type merge
        3. Enter the following command to set the installation disk ID and hostname for the second agent:

          $ oc -n <hosted_control_plane_namespace> \
            patch agent example-agent-2 -p \
            '{"spec":{"installation_disk_id":"/dev/sda","approved":true,"hostname":"worker-1.example.krnl.es"}}' \
            --type merge
    • If you use the Metal3 Operator, you can automate the bare-metal host registration by creating the following objects:

      1. Create a YAML file and add the following content to it:

        apiVersion: v1
        kind: Secret
        metadata:
          name: hosted-worker0-bmc-secret
          namespace: <namespace_example>
        data:
          password: <password>
          username: <username>
        type: Opaque
        ---
        apiVersion: v1
        kind: Secret
        metadata:
          name: hosted-worker1-bmc-secret
          namespace: <namespace_example>
        data:
          password: <password>
          username: <username>
        type: Opaque
        ---
        apiVersion: v1
        kind: Secret
        metadata:
          name: hosted-worker2-bmc-secret
          namespace: <namespace_example>
        data:
          password: <password>
          username: <username>
        type: Opaque
        ---
        apiVersion: metal3.io/v1alpha1
        kind: BareMetalHost
        metadata:
          name: hosted-worker0
          namespace: <namespace_example>
          labels:
            infraenvs.agent-install.openshift.io: hosted
          annotations:
            inspect.metal3.io: disabled
            bmac.agent-install.openshift.io/hostname: hosted-worker0
        spec:
          automatedCleaningMode: disabled
          bmc:
            disableCertificateVerification: True
            address: <bmc_address>
            credentialsName: hosted-worker0-bmc-secret
          bootMACAddress: aa:aa:aa:aa:02:01
          online: true
        ---
        apiVersion: metal3.io/v1alpha1
        kind: BareMetalHost
        metadata:
          name: hosted-worker1
          namespace: <namespace_example>
          labels:
            infraenvs.agent-install.openshift.io: hosted
          annotations:
            inspect.metal3.io: disabled
            bmac.agent-install.openshift.io/hostname: hosted-worker1
        spec:
          automatedCleaningMode: disabled
          bmc:
            disableCertificateVerification: True
            address: <bmc_address>
            credentialsName: hosted-worker1-bmc-secret
          bootMACAddress: aa:aa:aa:aa:02:02
          online: true
        ---
        apiVersion: metal3.io/v1alpha1
        kind: BareMetalHost
        metadata:
          name: hosted-worker2
          namespace: <namespace_example>
          labels:
            infraenvs.agent-install.openshift.io: hosted
          annotations:
            inspect.metal3.io: disabled
            bmac.agent-install.openshift.io/hostname: hosted-worker2
        spec:
          automatedCleaningMode: disabled
          bmc:
            disableCertificateVerification: True
            address: <bmc_address>
            credentialsName: hosted-worker2-bmc-secret
          bootMACAddress: aa:aa:aa:aa:02:03
          online: true
        ---
        apiVersion: rbac.authorization.k8s.io/v1
        kind: Role
        metadata:
          name: capi-provider-role
          namespace: <namespace_example>
        rules:
        - apiGroups:
          - agent-install.openshift.io
          resources:
          - agents
          verbs:
          - '*'

        where:

        <namespace_example>
        Is the your namespace.
        <password>
        Is the password for your secret.
        <username>
        Is the user name for your secret.
        <bmc_address>

        Is the BMC address for the BareMetalHost object.

        Note

        When you apply this YAML file, the following objects are created:

        • Secrets with credentials for the Baseboard Management Controller (BMCs)
        • The BareMetalHost objects
        • A role for the HyperShift Operator to be able to manage the agents

        Notice how the InfraEnv resource is referenced in the BareMetalHost objects by using the infraenvs.agent-install.openshift.io: hosted custom label. This ensures that the nodes are booted with the ISO generated.

      2. Apply the changes to the YAML file by entering the following command:

        $ oc apply -f <bare_metal_host_config>.yaml

        Replace <bare_metal_host_config> with the name of your file.

  7. Enter the following command, and then wait a few minutes for the BareMetalHost objects to move to the Provisioning state:

    $ oc --kubeconfig ~/<directory_example>/mgmt-kubeconfig -n <namespace_example> get bmh

    Example output

    NAME             STATE          CONSUMER   ONLINE   ERROR   AGE
    hosted-worker0   provisioning              true             106s
    hosted-worker1   provisioning              true             106s
    hosted-worker2   provisioning              true             106s

  8. Enter the following command to verify that nodes are booting and showing up as agents. This process can take a few minutes, and you might need to enter the command more than once.

    $ oc --kubeconfig ~/<directory_example>/mgmt-kubeconfig -n <namespace_example> get agent

    Example output

    NAME                                   CLUSTER   APPROVED   ROLE          STAGE
    aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaa0201             true       auto-assign
    aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaa0202             true       auto-assign
    aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaa0203             true       auto-assign

4.3.5.2. Creating an InfraEnv resource by using the console

If you prefer to use the OpenShift Container Platform web console, you can use it to create an InfraEnv resource for a hosted cluster on bare metal.

Procedure

  1. Open the OpenShift Container Platform web console and log in by entering your administrator credentials. For instructions to open the console, see "Accessing the web console".
  2. In the console header, ensure that All Clusters is selected.
  3. Click Infrastructure Host inventory Create infrastructure environment.
  4. After you create the InfraEnv resource, add bare-metal hosts from within the InfraEnv view by clicking Add hosts and selecting from the available options.

4.3.6. Creating a hosted cluster on bare metal

You can create a hosted cluster on bare metal with the Agent platform by using the command-line interface (CLI), the console, or by using a mirror registry.

4.3.6.1. Creating a hosted cluster by using the CLI

On bare-metal infrastructure, you can import a hosted cluster or create one by using the command-line interface (CLI).

After you enable the Assisted Installer as an add-on to multicluster engine Operator and you create a hosted cluster with the Agent platform, the HyperShift Operator installs the Agent Cluster API provider in the hosted control plane namespace. The Agent Cluster API provider connects a management cluster that hosts the control plane and a hosted cluster that consists of only the compute nodes.

Prerequisites

  • Each hosted cluster must have a cluster-wide unique name. A hosted cluster name cannot be the same as any existing managed cluster. Otherwise, the multicluster engine Operator cannot manage the hosted cluster.
  • Do not use the word clusters as a hosted cluster name.
  • You cannot create a hosted cluster in the namespace of a multicluster engine Operator managed cluster.
  • For best security and management practices, create a hosted cluster separate from other hosted clusters.
  • Verify that you have a default storage class configured for your cluster. Otherwise, you might see pending persistent volume claims (PVCs).
  • By default when you use the hcp create cluster agent command, the command creates a hosted cluster with configured node ports. The preferred publishing strategy for hosted clusters on bare metal exposes services through a load balancer. If you create a hosted cluster by using the web console or by using Red Hat Advanced Cluster Management, to set a publishing strategy for a service besides the Kubernetes API server, you must manually specify the servicePublishingStrategy information in the HostedCluster custom resource.
  • Ensure that you meet the requirements described in "Requirements for hosted control planes on bare metal", which includes requirements related to infrastructure, firewalls, ports, and services. For example, those requirements describe how to add the appropriate zone labels to the bare-metal hosts in your management cluster, as shown in the following example commands:

    $ oc label node [compute-node-1] topology.kubernetes.io/zone=zone1
    $ oc label node [compute-node-2] topology.kubernetes.io/zone=zone2
    $ oc label node [compute-node-3] topology.kubernetes.io/zone=zone3
  • Ensure that you have added bare-metal nodes to a hardware inventory.

Procedure

  1. Create a namespace by entering the following command:

    $ oc create ns <hosted_cluster_namespace>

    Replace <hosted_cluster_namespace> with an identifier for your hosted cluster namespace. The HyperShift Operator creates the namespace. During the hosted cluster creation process on bare-metal infrastructure, a generated Cluster API provider role requires that the namespace already exists.

  2. Create the configuration file for your hosted cluster by entering the following command:

    $ hcp create cluster agent \
      --name=<hosted_cluster_name> \
      --pull-secret=<path_to_pull_secret> \
      --agent-namespace=<hosted_control_plane_namespace> \
      --base-domain=<base_domain> \
      --api-server-address=api.<hosted_cluster_name>.<base_domain>
      --etcd-storage-class=<etcd_storage_class> \
      --ssh-key=<path_to_ssh_key> \
      --namespace=<hosted_cluster_namespace> \
      --control-plane-availability-policy=HighlyAvailable \
      --release-image=quay.io/openshift-release-dev/ocp-release:<ocp_release_image>-multi \
      --node-pool-replicas=<node_pool_replica_count> \
      --render \
      --render-sensitive \
      --ssh-key <home_directory>/<path_to_ssh_key>/<ssh_key> > hosted-cluster-config.yaml

    where:

    <hosted_cluster_name>
    Specifies the name of your hosted cluster, such as example.
    <path_to_pull_secret>
    Specifies the path to your pull secret, such as /user/name/pullsecret.
    <hosted_control_plane_namespace>
    Specifies your hosted control plane namespace, such as clusters-example. Ensure that agents are available in this namespace by using the oc get agent -n <hosted_control_plane_namespace> command.
    <base_domain>
    Specifies your base domain, such as krnl.es.
    --api-server-address
    Specifies the IP address that gets used for the Kubernetes API communication in the hosted cluster. If you do not set the --api-server-address flag, you must log in to connect to the management cluster.
    <etcd_storage_class>
    Specifies the etcd storage class name, such as lvm-storageclass.
    <path_to_ssh_key>
    Specifies the path to your SSH public key. The default file path is ~/.ssh/id_rsa.pub.
    <hosted_cluster_namespace>
    Specifies your hosted cluster namespace.
    control-plane-availability-policy
    Specifies the availability policy for the hosted control plane components. Supported options are SingleReplica and HighlyAvailable. The default value is HighlyAvailable.
    <ocp_release_image>
    Specifies the supported OpenShift Container Platform version that you want to use, such as 4.22.0-multi. If you are using a disconnected environment, replace <ocp_release_image> with the digest image. To extract the OpenShift Container Platform release image digest, see "Extracting the OpenShift Container Platform release image digest".
    <node_pool_replica_count>
    Specifies the node pool replica count, such as 3. You must specify the replica count as 0 or greater to create the same number of replicas. Otherwise, you do not create node pools.
    <home_directory>/<path_to_ssh_key>/<ssh_key>
    Specifies the path to the SSH key, such as user/.ssh/id_rsa.
  3. Configure the service publishing strategy. By default, hosted clusters use the NodePort service publishing strategy because node ports are always available without additional infrastructure. However, you can configure the service publishing strategy to use a load balancer.

    • If you are using the default NodePort strategy, configure the DNS to point to the hosted cluster compute nodes, not the management cluster nodes. For more information, see "DNS configurations on bare metal".
    • For production environments, use the LoadBalancer strategy because this strategy provides certificate handling and automatic DNS resolution. The following example demonstrates changing the service publishing LoadBalancer strategy in your hosted cluster configuration file:

      apiVersion: hypershift.openshift.io/v1beta1
      kind: HostedCluster
      metadata:
      # ...
      spec:
        services:
        - service: APIServer
          servicePublishingStrategy:
            type: LoadBalancer
        - service: Ignition
          servicePublishingStrategy:
            type: Route
        - service: Konnectivity
          servicePublishingStrategy:
            type: Route
        - service: OAuthServer
          servicePublishingStrategy:
            type: Route
        - service: OIDC
          servicePublishingStrategy:
            type: Route
        sshKey:
          name: <ssh_key>
      # ...

      Specify LoadBalancer as the API Server type. For all other services, specify Route as the type.

  4. If you use external load balancers, configure the ingress endpoint as shown in the following example. If you do not configure the endpoint, the default behavior is to randomize the node port that the service exposes the ingress on. To configure how the ingress controller publishes the default ingress route, set the endpointPublishingStrategy parameter and its underlying functions by editing the HostedCluster resource:

    apiVersion: hypershift.openshift.io/v1beta1
    kind: HostedCluster
    metadata:
    #...
    spec:
      operatorConfiguration:
        ingressOperator:
          endpointPublishingStrategy:
            hostNetwork:
              httpPort: 80
              httpsPort: 443
              protocol: TCP
              statsPort: 1936
            type: HostNetwork
    #...

    The spec.operatorConfiguration.ingressOperator.endPointPublishingStrategy.type parameter specifies the endpoint for the load balancer. For bare-metal installations, use the HostNetwork type.

  5. Apply the changes to the hosted cluster configuration file by entering the following command:

    $ oc apply -f hosted_cluster_config.yaml
  6. Check for the creation of the hosted cluster, node pools, and pods by entering the following commands:

    $ oc get hostedcluster \
      <hosted_cluster_namespace> -n \
      <hosted_cluster_namespace> -o \
      jsonpath='{.status.conditions[?(@.status=="False")]}' | jq .
    $ oc get nodepool \
      <hosted_cluster_namespace> -n \
      <hosted_cluster_namespace> -o \
      jsonpath='{.status.conditions[?(@.status=="False")]}' | jq .
    $ oc get pods -n <hosted_cluster_namespace>
  7. Confirm that the hosted cluster is ready. The status of Available: True indicates the readiness of the cluster and the node pool status shows AllMachinesReady: True. These statuses indicate the healthiness of all cluster Operators.
  8. Install MetalLB in the hosted cluster:

    1. Extract the kubeconfig file from the hosted cluster and set the environment variable for hosted cluster access by entering the following commands:

      $ oc get secret \
        <hosted_cluster_namespace>-admin-kubeconfig \
        -n <hosted_cluster_namespace> \
        -o jsonpath='{.data.kubeconfig}' \
        | base64 -d > \
        kubeconfig-<hosted_cluster_namespace>.yaml
      $ export KUBECONFIG="/path/to/kubeconfig-<hosted_cluster_namespace>.yaml"
    2. Install the MetalLB Operator by creating the install-metallb-operator.yaml file:

      apiVersion: v1
      kind: Namespace
      metadata:
        name: metallb-system
      ---
      apiVersion: operators.coreos.com/v1
      kind: OperatorGroup
      metadata:
        name: metallb-operator
        namespace: metallb-system
      ---
      apiVersion: operators.coreos.com/v1alpha1
      kind: Subscription
      metadata:
        name: metallb-operator
        namespace: metallb-system
      spec:
        channel: "stable"
        name: metallb-operator
        source: redhat-operators
        sourceNamespace: openshift-marketplace
        installPlanApproval: Automatic
      # ...
    3. Apply the file by entering the following command:

      $ oc apply -f install-metallb-operator.yaml
    4. Configure the MetalLB IP address pool by creating the deploy-metallb-ipaddresspool.yaml file:

      apiVersion: metallb.io/v1beta1
      kind: IPAddressPool
      metadata:
        name: metallb
        namespace: metallb-system
      spec:
        autoAssign: true
        addresses:
        - 10.11.176.71-10.11.176.75
      ---
      apiVersion: metallb.io/v1beta1
      kind: L2Advertisement
      metadata:
        name: l2advertisement
        namespace: metallb-system
      spec:
        ipAddressPools:
        - metallb
      # ...
    5. Apply the configuration by entering the following command:

      $ oc apply -f deploy-metallb-ipaddresspool.yaml
    6. Verify the installation of MetalLB by checking the Operator status, the IP address pool, and the L2Advertisement resource by entering the following commands:

      $ oc get pods -n metallb-system
      $ oc get ipaddresspool -n metallb-system
      $ oc get l2advertisement -n metallb-system
  9. Configure the load balancer for ingress:

    1. Create the ingress-loadbalancer.yaml file:

      apiVersion: v1
      kind: Service
      metadata:
        annotations:
          metallb.universe.tf/address-pool: metallb
        name: metallb-ingress
        namespace: openshift-ingress
      spec:
        ports:
          - name: http
            protocol: TCP
            port: 80
            targetPort: 80
          - name: https
            protocol: TCP
            port: 443
            targetPort: 443
        selector:
          ingresscontroller.operator.openshift.io/deployment-ingresscontroller: default
        type: LoadBalancer
      # ...
    2. Apply the configuration by entering the following command:

      $ oc apply -f ingress-loadbalancer.yaml
    3. Verify that the load balancer service works as expected by entering the following command:

      $ oc get svc metallb-ingress -n openshift-ingress

      Example output

      NAME              TYPE           CLUSTER-IP       EXTERNAL-IP    PORT(S)                      AGE
      metallb-ingress   LoadBalancer   172.31.127.129   10.11.176.71   80:30961/TCP,443:32090/TCP   16h

  10. Configure the DNS to work with the load balancer:

    1. Configure the DNS for the apps domain by pointing the *.apps.<hosted_cluster_namespace>.<base_domain> wildcard DNS record to the load balancer IP address.
    2. Verify the DNS resolution by entering the following command:

      $ nslookup console-openshift-console.apps.<hosted_cluster_namespace>.<base_domain> <load_balancer_ip_address>

      Example output

      Server:         10.11.176.1
      Address:        10.11.176.1#53
      
      Name:   console-openshift-console.apps.my-hosted-cluster.sample-base-domain.com
      Address: 10.11.176.71

Verification

  1. Check the cluster Operators by entering the following command:

    $ oc get clusteroperators

    Ensure that all Operators show AVAILABLE: True, PROGRESSING: False, and DEGRADED: False.

  2. Check the nodes by entering the following command:

    $ oc get nodes

    Ensure that each node has the READY status.

  3. Test access to the console by entering the following URL in a web browser:

    https://console-openshift-console.apps.<hosted_cluster_namespace>.<base_domain>

4.3.6.2. Creating a hosted cluster on bare metal by using the console

Instead of using the command-line interface to create a hosted cluster on bare metal, you can also use the OpenShift Container Platform web console.

Procedure

  1. Open the OpenShift Container Platform web console and log in by entering your administrator credentials. For instructions to open the console, see "Accessing the web console".
  2. In the console header, ensure that All Clusters is selected.
  3. Click Infrastructure Clusters.
  4. Click Create cluster Host inventory Hosted control plane.

    The Create cluster page is displayed.

  5. On the Create cluster page, follow the prompts to enter details about the cluster, node pools, networking, and automation.

    Note

    As you enter details about the cluster, you might find the following tips useful:

    • If you want to use predefined values to automatically populate fields in the console, you can create a host inventory credential. For more information, see "Creating a credential for an on-premises environment".
    • On the Cluster details page, the pull secret is your OpenShift Container Platform pull secret that you use to access OpenShift Container Platform resources. If you selected a host inventory credential, the pull secret is automatically populated.
    • On the Node pools page, the namespace contains the hosts for the node pool. If you created a host inventory by using the console, the console creates a dedicated namespace.
    • On the Networking page, you select an API server publishing strategy. The API server for the hosted cluster can be exposed either by using an existing load balancer or as a service of the NodePort type. A DNS entry must exist for the api.<hosted_cluster_name>.<base_domain> setting that points to the destination where the API server can be reached. This entry can be a record that points to one of the nodes in the management cluster or a record that points to a load balancer that redirects incoming traffic to the Ingress pods.
  6. Review your entries and click Create.

    The Hosted cluster view is displayed.

  7. Monitor the deployment of the hosted cluster in the Hosted cluster view.
  8. If you do not see information about the hosted cluster, ensure that All Clusters is selected, then click the cluster name.
  9. Wait until the control plane components are ready. This process can take a few minutes.
  10. To view the node pool status, scroll to the NodePool section. The process to install the nodes takes about 10 minutes. You can also click Nodes to confirm whether the nodes joined the hosted cluster.

You can use a mirror registry to create a hosted cluster on bare metal by specifying the --image-content-sources flag in the hcp create cluster command.

Procedure

  1. Create a YAML file to define Image Content Source Policies (ICSP). See the following example:

    - mirrors:
      - brew.registry.redhat.io
      source: registry.redhat.io
    - mirrors:
      - brew.registry.redhat.io
      source: registry.stage.redhat.io
    - mirrors:
      - brew.registry.redhat.io
      source: registry-proxy.engineering.redhat.com
  2. Save the file as icsp.yaml. This file contains your mirror registries.
  3. To create a hosted cluster by using your mirror registries, run the following command:

    $ hcp create cluster agent \
        --name=<hosted_cluster_name> \
        --pull-secret=<path_to_pull_secret> \
        --agent-namespace=<hosted_control_plane_namespace> \
        --base-domain=<base_domain> \
        --api-server-address=api.<hosted_cluster_name>.<base_domain> \
        --image-content-sources <icsp.yaml>  \
        --ssh-key  <path_to_ssh_key> \
        --namespace <hosted_cluster_namespace> \
        --release-image=quay.io/openshift-release-dev/ocp-release:<ocp_release_image>

    where:

    <hosted_cluster_name>
    Specifies the name of your hosted cluster, for example, my-hosted-cluster.
    <path_to_pull_secret>
    Specifies the path to your pull secret, for example, /user/name/pullsecret.
    <hosted_control_plane_namespace>
    Specifies your hosted control plane namespace, for example, clusters-example. Ensure that agents are available in this namespace by using the oc get agent -n <hosted-control-plane-namespace> command.
    <base_domain>
    Specifies your base domain, for example, krnl.es.
    <hosted_cluster_name>.<base_domain>
    Specifies the IP address that is used for the Kubernetes API communication in the hosted cluster. If you do not set the --api-server-address flag, you must log in to connect to the management cluster.
    <icsp.yaml>
    Specifies the icsp.yaml file that defines ICSP and your mirror registries.
    <path_to_ssh_key>
    Specifies the path to your SSH public key. The default file path is ~/.ssh/id_rsa.pub.
    <hosted_cluster_namespace>
    Specifies your hosted cluster namespace.
    <ocp_release_image>
    Specifies the supported OpenShift Container Platform version that you want to use, for example, 4.22.0-multi. If you are using a disconnected environment, replace <ocp_release_image> with the digest image. To extract the OpenShift Container Platform release image digest, see "Extracting the OpenShift Container Platform release image digest".

4.3.7. Verifying hosted cluster creation

After the deployment process is complete, you can verify that the hosted cluster was created successfully.

After you create the hosted cluster, wait a few minutes before you start the steps in the procedure.

Procedure

  1. Obtain the kubeconfig for your new hosted cluster by entering the extract command:

    $ oc extract -n <hosted-control-plane-namespace> secret/admin-kubeconfig \
      --to=- > kubeconfig-<hosted-cluster-name>
  2. Use the kubeconfig to view the cluster Operators of the hosted cluster. Enter the following command:

    $ oc get co --kubeconfig=kubeconfig-<hosted-cluster-name>

    Example output

    NAME                                       VERSION   AVAILABLE   PROGRESSING   DEGRADED   SINCE   MESSAGE
    console                                    4.10.26   True        False         False      2m38s
    dns                                        4.10.26   True        False         False      2m52s
    image-registry                             4.10.26   True        False         False      2m8s
    ingress                                    4.10.26   True        False         False      22m

  3. You can also view the running pods on your hosted cluster by entering the following command:

    $ oc get pods -A --kubeconfig=kubeconfig-<hosted-cluster-name>

    Example output

    NAMESPACE                                          NAME                                                      READY   STATUS             RESTARTS        AGE
    kube-system                                        konnectivity-agent-khlqv                                  0/1     Running            0               3m52s
    openshift-cluster-node-tuning-operator             tuned-dhw5p                                               1/1     Running            0               109s
    openshift-cluster-storage-operator                 cluster-storage-operator-5f784969f5-vwzgz                 1/1     Running            1 (113s ago)    20m
    openshift-cluster-storage-operator                 csi-snapshot-controller-6b7687b7d9-7nrfw                  1/1     Running            0               3m8s
    openshift-console                                  console-5cbf6c7969-6gk6z                                  1/1     Running            0               119s
    openshift-console                                  downloads-7bcd756565-6wj5j                                1/1     Running            0               4m3s
    openshift-dns-operator                             dns-operator-77d755cd8c-xjfbn                             2/2     Running            0               21m
    openshift-dns                                      dns-default-kfqnh                                         2/2     Running            0               113s

4.4. Deploying hosted control planes on OpenShift Virtualization

With hosted control planes and OpenShift Virtualization, you can create OpenShift Container Platform clusters with worker nodes that are hosted by KubeVirt virtual machines. Hosted control planes on OpenShift Virtualization provides several benefits:

  • Enhances resource usage by packing hosted control planes and hosted clusters in the same underlying bare-metal infrastructure
  • Separates hosted control planes and hosted clusters to provide strong isolation
  • Reduces cluster provision time by eliminating the bare-metal node bootstrapping process
  • Manages many releases under the same base OpenShift Container Platform cluster

The hosted control planes feature is enabled by default.

You can use the hosted control plane command-line interface, hcp, to create an OpenShift Container Platform hosted cluster. The hosted cluster is automatically imported as a managed cluster. If you want to disable this automatic import feature, see "Disabling the automatic import of hosted clusters into multicluster engine Operator".

As you prepare to deploy hosted control planes on OpenShift Virtualization, consider the following information:

  • Run the management cluster on bare metal.
  • Each hosted cluster must have a cluster-wide unique name.
  • Do not use clusters as a hosted cluster name.
  • A hosted cluster cannot be created in the namespace of a multicluster engine Operator managed cluster.
  • When you configure storage for hosted control planes, consider the recommended etcd practices. To ensure that you meet the latency requirements, dedicate a fast storage device to all hosted control plane etcd instances that run on each control-plane node. You can use LVM storage to configure a local storage class for hosted etcd pods. For more information, see "Recommended etcd practices" and "Persistent storage using Logical Volume Manager storage".

4.4.1.1. Prerequisites

You must meet the following prerequisites to create an OpenShift Container Platform cluster on OpenShift Virtualization:

  • You have administrator access to an OpenShift Container Platform cluster, version 4.14 or later, specified in the KUBECONFIG environment variable.
  • The OpenShift Container Platform management cluster must have wildcard DNS routes enabled, as shown in the following command:

    $ oc patch ingresscontroller -n openshift-ingress-operator default \
      --type=json \
      -p '[{ "op": "add", "path": "/spec/routeAdmission", "value": {wildcardPolicy: "WildcardsAllowed"}}]'
  • The OpenShift Container Platform management cluster has OpenShift Virtualization, version 4.14 or later, installed on it. For more information, see "Installing OpenShift Virtualization using the web console".
  • The OpenShift Container Platform management cluster is on-premise bare metal.
  • The OpenShift Container Platform management cluster must be configured with OVNKubernetes as the default pod network Container Network Interface (CNI). Live migration is supported for nodes only if the CNI is OVN-Kubernetes.
  • The OpenShift Container Platform management cluster has a default storage class. For more information, see "Postinstallation storage configuration". The following example shows how to set a default storage class:

    $ oc patch storageclass ocs-storagecluster-ceph-rbd \
      -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
  • You have a valid pull secret file for the quay.io/openshift-release-dev repository. For more information, see "Install OpenShift on any x86_64 platform with user-provisioned infrastructure".
  • You have installed the hosted control plane command-line interface.
  • You have configured a load balancer. For more information, see "Configuring MetalLB".
  • For optimal network performance, you are using a network maximum transmission unit (MTU) of 9000 or greater on the OpenShift Container Platform cluster that hosts the KubeVirt virtual machines. If you use a lower MTU setting, network latency and the throughput of the hosted pods are affected. Enable multiqueue on node pools only when the MTU is 9000 or greater.

    Important

    You cannot change the MTU value for your cluster as a postinstallation task.

  • The multicluster engine Operator has at least one managed OpenShift Container Platform cluster. The local-cluster is automatically imported. For more information about the local-cluster, see "Advanced configuration" in the multicluster engine Operator documentation. You can check the status of your hub cluster by running the following command:

    $ oc get managedclusters local-cluster
  • On the OpenShift Container Platform cluster that hosts the OpenShift Virtualization virtual machines, you are using a ReadWriteMany (RWX) storage class so that live migration can be enabled.

4.4.1.2. Firewall and port requirements

Ensure that you meet the firewall and port requirements so that ports can communicate between the management cluster, the control plane, and hosted clusters:

  • The kube-apiserver service runs on port 6443 by default and requires ingress access for communication between the control plane components.

    • If you use the NodePort publishing strategy, ensure that the node port that is assigned to the kube-apiserver service is exposed.
    • If you use MetalLB load balancing, allow ingress access to the IP range that is used for load balancer IP addresses.
  • If you use the NodePort publishing strategy, use a firewall rule for the ignition-server and Oauth-server settings.
  • The konnectivity agent, which establishes a reverse tunnel to allow bi-directional communication on the hosted cluster, requires egress access to the cluster API server address on port 6443. With that egress access, the agent can reach the kube-apiserver service.

    • If the cluster API server address is an internal IP address, allow access from the workload subnets to the IP address on port 6443.
    • If the address is an external IP address, allow egress on port 6443 to that external IP address from the nodes.
  • If you change the default port of 6443, adjust the rules to reflect that change.
  • Ensure that you open any ports that are required by the workloads that run in the clusters.
  • Use firewall rules, security groups, or other access controls to restrict access to only required sources. Avoid exposing ports publicly unless necessary.
  • For production deployments, use a load balancer to simplify access through a single IP address.

4.4.2. Live migration for compute nodes

While the management cluster for hosted cluster virtual machines (VMs) is undergoing updates or maintenance, the hosted cluster VMs can be automatically live migrated to prevent disrupting hosted cluster workloads. As a result, the management cluster can be updated without affecting the availability and operation of the KubeVirt platform hosted clusters.

Important

The live migration of KubeVirt VMs is enabled by default provided that the VMs use ReadWriteMany (RWX) storage for both the root volume and the storage classes that are mapped to the kubevirt-csi CSI provider.

You can verify that the VMs in a node pool are capable of live migration by checking the KubeVirtNodesLiveMigratable condition in the status section of a NodePool object.

In the following example, the VMs cannot be live migrated because RWX storage is not used.

Example configuration where VMs cannot be live migrated

    - lastTransitionTime: "2024-10-08T15:38:19Z"
      message: |
        3 of 3 machines are not live migratable
        Machine user-np-ngst4-gw2hz: DisksNotLiveMigratable: user-np-ngst4-gw2hz is not a live migratable machine: cannot migrate VMI: PVC user-np-ngst4-gw2hz-rhcos is not shared, live migration requires that all PVCs must be shared (using ReadWriteMany access mode)
        Machine user-np-ngst4-npq7x: DisksNotLiveMigratable: user-np-ngst4-npq7x is not a live migratable machine: cannot migrate VMI: PVC user-np-ngst4-npq7x-rhcos is not shared, live migration requires that all PVCs must be shared (using ReadWriteMany access mode)
        Machine user-np-ngst4-q5nkb: DisksNotLiveMigratable: user-np-ngst4-q5nkb is not a live migratable machine: cannot migrate VMI: PVC user-np-ngst4-q5nkb-rhcos is not shared, live migration requires that all PVCs must be shared (using ReadWriteMany access mode)
      observedGeneration: 1
      reason: DisksNotLiveMigratable
      status: "False"
      type: KubeVirtNodesLiveMigratable

In the next example, the VMs meet the requirements to be live migrated.

Example configuration where VMs can be live migrated

    - lastTransitionTime: "2024-10-08T15:38:19Z"
      message: "All is well"
      observedGeneration: 1
      reason: AsExpected
      status: "True"
      type: KubeVirtNodesLiveMigratable

While live migration can protect VMs from disruption in normal circumstances, events such as infrastructure node failure can result in a hard restart of any VMs that are hosted on the failed node. For live migration to be successful, the source node that a VM is hosted on must be working correctly.

When the VMs in a node pool cannot be live migrated, workload disruption might occur on the hosted cluster during maintenance on the management cluster. By default, the hosted control planes controllers try to drain the workloads that are hosted on KubeVirt VMs that cannot be live migrated before the VMs are stopped. Draining the hosted cluster nodes before stopping the VMs allows pod disruption budgets to protect workload availability within the hosted cluster.

4.4.3. Creating a hosted cluster with the KubeVirt platform

With OpenShift Container Platform 4.14 and later, you can create a cluster with KubeVirt, to include creating with an external infrastructure.

To create a hosted cluster on OpenShift Virtualization, you can use the hosted control plane command-line interface (CLI), hcp.

Important

Avoid storing all hosted cluster information in a shared namespace. If you create a hosted cluster in a shared namespace and then back up and restore the hosted cluster, you might unintentionally change other hosted clusters. Either store hosted cluster information in a separate namespace or set up your hosted cluster to back up and restore resources based on labels.

Procedure

  1. Create a hosted cluster with the KubeVirt platform by entering the following command:

    $ hcp create cluster kubevirt \
      --name <hosted_cluster_name> \
      --node-pool-replicas <node_pool_replica_count> \
      --pull-secret <path_to_pull_secret> \
      --memory <value_for_memory> \
      --cores <value_for_cpu> \
      --etcd-storage-class=<etcd_storage_class> \
      --arch <architecture_of_the_nodepool> \
      --release-image <ocp_release_image_for_the_cluster> \
      --image-content-sources <path_to_image_content_sources_file> \
      --additional-trust-bundle <path_to_ca_bundle_file>
    • --name defines the name of your hosted cluster, for example, my-hosted-cluster.
    • --node-pool-replicas defines the node pool replica count, for example, 3. You must specify the replica count as 0 or greater to create the same number of replicas. Otherwise, no node pools are created.
    • --pull-secret defines the path to your pull secret, for example, /user/name/pullsecret.
    • --memory defines a value for memory, for example, 6Gi.
    • --cores defines a value for CPU, for example, 2.
    • --etcd-storage-class defines the etcd storage class name, for example, lvm-storageclass.
    • --arch defines the architecture of the node pool, for example, s390x. The default is amd64.
    • --release-image defines the OpenShift Container Platform release image for the cluster, for example, quay.io/openshift-release-dev/ocp-release:4.20.14-multi. You can use the --release-image flag to set up the hosted cluster with a specific OpenShift Container Platform release.
    • --image-content-sources specifies the path to a file with image content sources.
    • --additional-trust-bundle specifies the path to a file with user CA bundle.

    A default node pool is created for the cluster with a specific number of virtual machine worker replicas according to the --node-pool-replicas flag.

  2. After a few moments, verify that the hosted control plane pods are running by entering the following command:

    $ oc -n clusters-<hosted-cluster-name> get pods

    Example output

    NAME                                                  READY   STATUS    RESTARTS   AGE
    capi-provider-5cc7b74f47-n5gkr                        1/1     Running   0          3m
    catalog-operator-5f799567b7-fd6jw                     2/2     Running   0          69s
    certified-operators-catalog-784b9899f9-mrp6p          1/1     Running   0          66s
    cluster-api-6bbc867966-l4dwl                          1/1     Running   0          66s
    .
    .
    .
    redhat-operators-catalog-9d5fd4d44-z8qqk              1/1     Running   0          66s

    A hosted cluster that has worker nodes that are backed by KubeVirt virtual machines typically takes 10-15 minutes to be fully provisioned.

Verification

  • To check the status of the hosted cluster, see the corresponding HostedCluster resource by entering the following command:

    $ oc get --namespace clusters hostedclusters

    See the following example output, which illustrates a fully provisioned HostedCluster object:

    NAMESPACE   NAME                VERSION     KUBECONFIG                 PROGRESS    AVAILABLE   PROGRESSING   MESSAGE
    clusters    my-hosted-cluster   <4.x.0>     example-admin-kubeconfig   Completed   True        False         The hosted control plane is available

    Replace <4.x.0> with the supported OpenShift Container Platform version that you want to use.

By default, the HyperShift Operator hosts both the control plane pods of the hosted cluster and the KubeVirt worker VMs within the same cluster. With the external infrastructure feature, you can place the worker node VMs on a separate cluster from the control plane pods.

  • The management cluster is the OpenShift Container Platform cluster that runs the HyperShift Operator and hosts the control plane pods for a hosted cluster.
  • The infrastructure cluster is the OpenShift Container Platform cluster that runs the KubeVirt worker VMs for a hosted cluster.
  • By default, the management cluster also acts as the infrastructure cluster that hosts VMs. However, for external infrastructure, the management and infrastructure clusters are different.
Important

Avoid storing all hosted cluster information in a shared namespace. If you create a hosted cluster in a shared namespace and then back up and restore the hosted cluster, you might unintentionally change other hosted clusters. Either store hosted cluster information in a separate namespace or set up your hosted cluster to back up and restore resources based on labels.

Prerequisites

  • You must have a namespace on the external infrastructure cluster for the KubeVirt nodes to be hosted in.
  • You must have a kubeconfig file for the external infrastructure cluster.

Procedure

  • In the hcp command-line interface, place the KubeVirt worker VMs on the infrastructure cluster, use the --infra-kubeconfig-file and --infra-namespace arguments, as shown in the following example:

    $ hcp create cluster kubevirt \
      --name <hosted-cluster-name> \
      --node-pool-replicas <worker-count> \
      --pull-secret <path-to-pull-secret> \
      --memory <value-for-memory> \
      --cores <value-for-cpu> \
      --infra-namespace=<hosted-cluster-namespace>-<hosted-cluster-name> \
      --infra-kubeconfig-file=<path-to-external-infra-kubeconfig>
    • --name defines the name of your hosted cluster, for example, my-hosted-cluster.
    • --node-pool-replicas defines the worker count, for example, 2.
    • --pull-secret defines the path to your pull secret, for example, /user/name/pullsecret.
    • --memory defines a value for memory, for example, 6Gi.
    • --cores defines a value for CPU, for example, 2.
    • --infra-namespace defines the infrastructure namespace, for example, clusters-example.
    • --infra-kubeconfig-file defines the path to your kubeconfig file for the infrastructure cluster, for example, /user/name/external-infra-kubeconfig.

    After you enter the command, the control plane pods are hosted on the management cluster that the HyperShift Operator runs on, and the KubeVirt VMs are hosted on a separate infrastructure cluster.

4.4.3.3. Creating a hosted cluster by using the console

If you prefer to work in the OpenShift Container Platform console instead of the CLI, you can create a hosted cluster on the KubeVirt platform by using the console.

Note

If you want to use predefined values to automatically populate fields in the console, you can create a OpenShift Virtualization credential. For more information, see "Creating a credential for an on-premises environment".

Procedure

  1. Open the OpenShift Container Platform web console and log in by entering your administrator credentials.
  2. In the console header, ensure that All Clusters is selected.
  3. Click Infrastructure > Clusters.
  4. Click Create cluster > Red Hat OpenShift Virtualization > Hosted.
  5. On the Create cluster page, follow the prompts to enter details about the cluster and node pools.

    On the Cluster details page, the pull secret is your OpenShift Container Platform pull secret that you use to access OpenShift Container Platform resources. If you selected a OpenShift Virtualization credential, the pull secret is automatically populated.

    Important

    Avoid storing all hosted cluster information in a shared namespace. If you create a hosted cluster in a shared namespace and then back up and restore the hosted cluster, you might unintentionally change other hosted clusters. Either store hosted cluster information in a separate namespace or set up your hosted cluster to back up and restore resources based on labels.

  6. On the Node pools page, expand the Networking options section and configure the networking options for your node pool:

    1. In the Additional networks field, enter a network name in the format of <namespace>/<name>; for example, my-namespace/network1. The namespace and the name must be valid DNS labels. Multiple networks are supported.
    2. By default, the Attach default pod network checkbox is selected. You can clear this checkbox only if additional networks exist.
  7. Review your entries and click Create.

    The Hosted cluster view is displayed.

Verification

  1. Monitor the deployment of the hosted cluster in the Hosted cluster view. If you do not see information about the hosted cluster, ensure that All Clusters is selected, and click the cluster name.
  2. Wait until the control plane components are ready. This process can take a few minutes.
  3. To view the node pool status, scroll to the NodePool section. The process to install the nodes takes about 10 minutes. You can also click Nodes to confirm whether the nodes joined the hosted cluster.

Every OpenShift Container Platform cluster includes a default application Ingress Controller, which must have an wildcard DNS record associated with it. By default, hosted clusters that are created by using OpenShift Virtualization automatically become a subdomain of the OpenShift Container Platform cluster that the virtual machines run on.

For example, your OpenShift Container Platform cluster might have the following default ingress DNS entry:

*.apps.mgmt-cluster.example.com

As a result, a hosted cluster that is named guest and that runs on that underlying OpenShift Container Platform cluster has the following default ingress:

*.apps.guest.apps.mgmt-cluster.example.com

Procedure

  • For the default ingress DNS to work properly, the cluster that hosts the virtual machines must allow wildcard DNS routes. You can configure this behavior by entering the following command:

    $ oc patch ingresscontroller -n openshift-ingress-operator default \
      --type=json \
      -p '[{ "op": "add", "path": "/spec/routeAdmission", "value": {wildcardPolicy: "WildcardsAllowed"}}]'
    Note

    When you use the default hosted cluster ingress, connectivity is limited to HTTPS traffic over port 443. Plain HTTP traffic over port 80 is rejected. This limitation applies to only the default ingress behavior.

4.4.4.1. Defining a custom DNS name

As a cluster administrator, you can create a hosted cluster with an external API DNS name that differs from the internal endpoint that gets used for node bootstraps and control plane communication.

You might want to define a different DNS name for the following reasons:

  • To replace the user-facing TLS certificate with one from a public CA without breaking the control plane functions that bind to the internal root CA
  • To support split-horizon DNS and NAT scenarios
  • To ensure a similar experience to standalone control planes, where you can use functions, such as the Show Login Command function, with the correct kubeconfig and DNS configuration

You can define a DNS name either during your initial setup or during postinstallation operations, by entering a domain name in the kubeAPIServerDNSName parameter of a HostedCluster object.

Prerequisites

  • You have a valid TLS certificate that covers the DNS name that you set in the kubeAPIServerDNSName parameter.
  • You have a resolvable DNS name URI that can reach and point to the correct address.

Procedure

  • In the specification for the HostedCluster object, add the kubeAPIServerDNSName parameter and the address for the domain and specify which certificate to use, as shown in the following example:

    #...
    spec:
      configuration:
        apiServer:
          servingCerts:
            namedCertificates:
            - names:
              - xxx.example.com
              - yyy.example.com
              servingCertificate:
                name: <my_serving_certificate>
      kubeAPIServerDNSName: <custom_address>

    The value for the kubeAPIServerDNSName parameter must be a valid and addressable domain.

    After you define the kubeAPIServerDNSName parameter and specify the certificate, the Control Plane Operator controllers create a kubeconfig file named custom-admin-kubeconfig, where the file gets stored in the HostedControlPlane namespace. The generation of certificates happen from the root CA, and the HostedControlPlane namespace manages their expiration and renewal.

    The Control Plane Operator reports a new kubeconfig file named CustomKubeconfig in the HostedControlPlane namespace. That file uses the defined new server in the kubeAPIServerDNSName parameter.

    A reference for the custom kubeconfig file exists in the status parameter as CustomKubeconfig of the HostedCluster object. The CustomKubeConfig parameter is optional, and you can add the parameter only if the kubeAPIServerDNSName parameter is not empty. After you set the CustomKubeConfig parameter, the parameter triggers the generation of a secret named <hosted_cluster_name>-custom-admin-kubeconfig in the HostedCluster namespace. You can use the secret to access the HostedCluster API server. If you remove the CustomKubeConfig parameter during postinstallation operations, deletion of all related secrets and status references occur.

    Note

    Defining a custom DNS name does not directly impact the data plane, so no expected rollouts occur. The HostedControlPlane namespace receives the changes from the HyperShift Operator and deletes the corresponding parameters.

    If you remove the kubeAPIServerDNSName parameter from the specification for the HostedCluster object, all newly generated secrets and the CustomKubeconfig reference are removed from the cluster and from the status parameter.

4.4.5. Customizing ingress and DNS behavior

If you do not want to use the default ingress and DNS behavior, you can configure a KubeVirt hosted cluster with a unique base domain at creation time. This option requires manual configuration steps during creation and involves three main steps: cluster creation, load balancer creation, and wildcard DNS configuration.

4.4.5.1. Deploying a hosted cluster that specifies the base domain

To create a hosted cluster that specifies a base domain, complete the following steps.

Procedure

  1. Enter the following command:

    $ hcp create cluster kubevirt \
      --name <hosted_cluster_name> \ 
    1
    
      --node-pool-replicas <worker_count> \ 
    2
    
      --pull-secret <path_to_pull_secret> \ 
    3
    
      --memory <value_for_memory> \ 
    4
    
      --cores <value_for_cpu> \ 
    5
    
      --base-domain <basedomain> \ 
    6
    
      --arch <architecture_of_the_nodepool> \ 
    7
    
      --release-image <ocp_release_image_for_the_cluster> \ 
    8
    
      --image-content-sources <path_to_image_content_sources_file> \ 
    9
    
      --additional-trust-bundle <path_to_ca_bundle_file> 
    10
    1
    Specify the name of your hosted cluster.
    1 2
    Specify the worker count, for example, 2.
    3
    Specify the path to your pull secret, for example, /user/name/pullsecret.
    4
    Specify a value for memory, for example, 6Gi.
    5
    Specify a value for CPU, for example, 2.
    6
    Specify the base domain, for example, hypershift.lab.
    7
    Specify the architecture of the node pool, for example, s390x. The default is amd64.
    8
    Specify the ocp release image for the cluster, for example, quay.io/openshift-release-dev/ocp-release:4.20.14-multi.
    9
    Specify the path to a file with image content sources.
    10
    Specify the path to a file with user CA bundle.

    As a result, the hosted cluster has an ingress wildcard that is configured for the cluster name and the base domain, for example, .apps.example.hypershift.lab. The hosted cluster remains in Partial status because after you create a hosted cluster with unique base domain, you must configure the required DNS records and load balancer.

Verification

  1. View the status of your hosted cluster by entering the following command:

    $ oc get --namespace clusters hostedclusters

    Example output

    NAME            VERSION   KUBECONFIG                       PROGRESS   AVAILABLE   PROGRESSING   MESSAGE
    example                   example-admin-kubeconfig         Partial    True        False         The hosted control plane is available

  2. Access the cluster by entering the following commands:

    $ hcp create kubeconfig --name <hosted_cluster_name> \
      > <hosted_cluster_name>-kubeconfig
    $ oc --kubeconfig <hosted_cluster_name>-kubeconfig get co

    Example output

    NAME                                       VERSION   AVAILABLE   PROGRESSING   DEGRADED   SINCE   MESSAGE
    console                                    <4.x.0>     False       False         False      30m     RouteHealthAvailable: failed to GET route (https://console-openshift-console.apps.example.hypershift.lab): Get "https://console-openshift-console.apps.example.hypershift.lab": dial tcp: lookup console-openshift-console.apps.example.hypershift.lab on 172.31.0.10:53: no such host
    ingress                                    <4.x.0>     True        False         True       28m     The "default" ingress controller reports Degraded=True: DegradedConditions: One or more other status conditions indicate a degraded state: CanaryChecksSucceeding=False (CanaryChecksRepetitiveFailures: Canary route checks for the default ingress controller are failing)

    Replace <4.x.0> with the supported OpenShift Container Platform version that you want to use.

Next steps

To fix the errors in the output, complete the steps in "Setting up the load balancer" and "Setting up a wildcard DNS".

Note

If your hosted cluster is on bare metal, you might need MetalLB to set up load balancer services. For more information, see "Configuring MetalLB".

4.4.5.2. Setting up the load balancer

Set up the load balancer service that routes ingress traffic to the KubeVirt VMs and assigns a wildcard DNS entry to the load balancer IP address.

Procedure

  1. A NodePort service that exposes the hosted cluster ingress already exists. You can export the node ports and create the load balancer service that targets those ports.

    1. Get the HTTP node port by entering the following command:

      $ oc --kubeconfig <hosted_cluster_name>-kubeconfig get services \
        -n openshift-ingress router-nodeport-default \
        -o jsonpath='{.spec.ports[?(@.name=="http")].nodePort}'

      Note the HTTP node port value to use in the next step.

    2. Get the HTTPS node port by entering the following command:

      $ oc --kubeconfig <hosted_cluster_name>-kubeconfig get services \
        -n openshift-ingress router-nodeport-default \
        -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}'

      Note the HTTPS node port value to use in the next step.

  2. Enter the following information in a YAML file:

    apiVersion: v1
    kind: Service
    metadata:
      labels:
        app: <hosted_cluster_name>
      name: <hosted_cluster_name>-apps
      namespace: clusters-<hosted_cluster_name>
    spec:
      ports:
      - name: https-443
        port: 443
        protocol: TCP
        targetPort: <https_node_port> 
    1
    
      - name: http-80
        port: 80
        protocol: TCP
        targetPort: <http_node_port> 
    2
    
      selector:
        kubevirt.io: virt-launcher
      type: LoadBalancer
    1
    Specify the HTTPS node port value that you noted in the previous step.
    2
    Specify the HTTP node port value that you noted in the previous step.
  3. Create the load balancer service by running the following command:

    $ oc create -f <file_name>.yaml

4.4.5.3. Setting up a wildcard DNS

Set up a wildcard DNS record or CNAME that references the external IP of the load balancer service.

Procedure

  1. Get the external IP address by entering the following command:

    $ oc -n clusters-<hosted_cluster_name> get service <hosted-cluster-name>-apps \
      -o jsonpath='{.status.loadBalancer.ingress[0].ip}'

    Example output

    192.168.20.30

  2. Configure a wildcard DNS entry that references the external IP address. View the following example DNS entry:

    *.apps.<hosted_cluster_name\>.<base_domain\>.

    The DNS entry must be able to route inside and outside of the cluster.

    DNS resolutions example

    dig +short test.apps.example.hypershift.lab
    
    192.168.20.30

Verification

  • Check that hosted cluster status has moved from Partial to Completed by entering the following command:

    $ oc get --namespace clusters hostedclusters

    Example output

    NAME            VERSION   KUBECONFIG                       PROGRESS    AVAILABLE   PROGRESSING   MESSAGE
    example         <4.x.0>     example-admin-kubeconfig         Completed   True        False         The hosted control plane is available

    Replace <4.x.0> with the supported OpenShift Container Platform version that you want to use.

4.4.6. Configuring MetalLB

You must install the MetalLB Operator before you configure MetalLB.

Procedure

Complete the following steps to configure MetalLB on your hosted cluster:

  1. Create a MetalLB resource by saving the following sample YAML content in the configure-metallb.yaml file:

    apiVersion: metallb.io/v1beta1
    kind: MetalLB
    metadata:
      name: metallb
      namespace: metallb-system
  2. Apply the YAML content by entering the following command:

    $ oc apply -f configure-metallb.yaml

    Example output

    metallb.metallb.io/metallb created

  3. Create a IPAddressPool resource by saving the following sample YAML content in the create-ip-address-pool.yaml file:

    apiVersion: metallb.io/v1beta1
    kind: IPAddressPool
    metadata:
      name: metallb
      namespace: metallb-system
    spec:
      addresses:
      - 192.168.216.32-192.168.216.122 
    1
    1
    Create an address pool with an available range of IP addresses within the node network. Replace the IP address range with an unused pool of available IP addresses in your network.
  4. Apply the YAML content by entering the following command:

    $ oc apply -f create-ip-address-pool.yaml

    Example output

    ipaddresspool.metallb.io/metallb created

  5. Create a L2Advertisement resource by saving the following sample YAML content in the l2advertisement.yaml file:

    apiVersion: metallb.io/v1beta1
    kind: L2Advertisement
    metadata:
      name: l2advertisement
      namespace: metallb-system
    spec:
      ipAddressPools:
       - metallb
  6. Apply the YAML content by entering the following command:

    $ oc apply -f l2advertisement.yaml

    Example output

    l2advertisement.metallb.io/metallb created

If you need to configure additional networks for node pools, request a guaranteed CPU access for Virtual Machines (VMs), or manage scheduling of KubeVirt VMs, see the following procedures.

4.4.7.1. Adding multiple networks to a node pool

By default, nodes generated by a node pool are attached to the pod network. You can attach additional networks to the nodes by using NetworkAttachmentDefinitions.

Important

You can connect compute nodes to multiple networks that have a Linux bridge or a user-defined network (UDN) that uses the localnet topology. Red Hat does not support connecting compute nodes to multiple UDNs that use a layer 2 or a layer 3 overlay topology.

Procedure

  • To add multiple networks to nodes, use the --additional-network argument by running the following command:

    $ hcp create cluster kubevirt \
      --name <hosted_cluster_name> \
      --node-pool-replicas <worker_node_count> \
      --pull-secret <path_to_pull_secret> \
      --memory <memory> \
      --cores <cpu> \
      --additional-network name:<namespace/name> \
      –-additional-network name:<namespace/name>

    where:

    hosted_cluster_name
    Specifies the name of your hosted cluster, for example, my-hosted-cluster.
    worker_node_count
    Specifies your compute node count, for example, 2.
    path_to_pull_secret
    Specifies the path to your pull secret, for example, /user/name/pullsecret.
    memory
    Specifies the memory value, for example, 8Gi.
    cpu
    Specifies the CPU value, for example, 2.
    namespace/name
    Specifies the value of the --additional-network argument to name:<namespace/name>. Replace <namespace/name> with a namespace and name of your NetworkAttachmentDefinitions.
4.4.7.1.1. Using an additional network as default

You can add your additional network as a default network for the nodes by disabling the default pod network.

Procedure

  • To add an additional network as default to your nodes, run the following command:

    $ hcp create cluster kubevirt \
      --name <hosted_cluster_name> \
    1
    
      --node-pool-replicas <worker_node_count> \
    2
    
      --pull-secret <path_to_pull_secret> \
    3
    
      --memory <memory> \
    4
    
      --cores <cpu> \
    5
    
      --attach-default-network false \
    6
    
      --additional-network name:<namespace>/<network_name> 
    7
    1
    Specify the name of your hosted cluster, for example, my-hosted-cluster.
    2
    Specify your worker node count, for example, 2.
    3
    Specify the path to your pull secret, for example, /user/name/pullsecret.
    4
    Specify the memory value, for example, 8Gi.
    5
    Specify the CPU value, for example, 2.
    6
    The --attach-default-network false argument disables the default pod network.
    7
    Specify the additional network that you want to add to your nodes, for example, name:my-namespace/my-network.

4.4.7.2. Requesting guaranteed CPU resources

By default, KubeVirt VMs might share their CPUs with other workloads on a node. This might impact performance of a VM. To avoid the performance impact, you can request a guaranteed CPU access for VMs.

Procedure

  • To request guaranteed CPU resources, set the --qos-class argument to Guaranteed by running the following command:

    $ hcp create cluster kubevirt \
      --name <hosted_cluster_name> \
    1
    
      --node-pool-replicas <worker_node_count> \
    2
    
      --pull-secret <path_to_pull_secret> \
    3
    
      --memory <memory> \
    4
    
      --cores <cpu> \
    5
    
      --qos-class Guaranteed 
    6
    1
    Specify the name of your hosted cluster, for example, my-hosted-cluster.
    2
    Specify your worker node count, for example, 2.
    3
    Specify the path to your pull secret, for example, /user/name/pullsecret.
    4
    Specify the memory value, for example, 8Gi.
    5
    Specify the CPU value, for example, 2.
    6
    The --qos-class Guaranteed argument guarantees that the specified number of CPU resources are assigned to VMs.

4.4.7.3. Scheduling KubeVirt VMs on a set of nodes

By default, KubeVirt VMs created by a node pool are scheduled to any available nodes. You can schedule KubeVirt VMs on a specific set of nodes that has enough capacity to run the VM.

Procedure

  • To schedule KubeVirt VMs within a node pool on a specific set of nodes, use the --vm-node-selector argument by running the following command:

    $ hcp create cluster kubevirt \
      --name <hosted_cluster_name> \
    1
    
      --node-pool-replicas <worker_node_count> \
    2
    
      --pull-secret <path_to_pull_secret> \
    3
    
      --memory <memory> \
    4
    
      --cores <cpu> \
    5
    
      --vm-node-selector <label_key>=<label_value>,<label_key>=<label_value> 
    6
    1
    Specify the name of your hosted cluster, for example, my-hosted-cluster.
    2
    Specify your worker node count, for example, 2.
    3
    Specify the path to your pull secret, for example, /user/name/pullsecret.
    4
    Specify the memory value, for example, 8Gi.
    5
    Specify the CPU value, for example, 2.
    6
    The --vm-node-selector flag defines a specific set of nodes that contains the key-value pairs. Replace <label_key> with the keys of your labels and replace <label_value> with the values of your labels.

4.4.8. Scaling a node pool

You can manually scale a node pool by using the oc scale command.

Procedure

  1. Run the following command:

    NODEPOOL_NAME=${CLUSTER_NAME}-work
    NODEPOOL_REPLICAS=5
    
    $ oc scale nodepool/$NODEPOOL_NAME --namespace clusters \
      --replicas=$NODEPOOL_REPLICAS
  2. After a few moments, enter the following command to see the status of the node pool:

    $ oc --kubeconfig $CLUSTER_NAME-kubeconfig get nodes

    Example output

    NAME                  STATUS   ROLES    AGE     VERSION
    example-9jvnf         Ready    worker   97s     v1.27.4+18eadca
    example-n6prw         Ready    worker   116m    v1.27.4+18eadca
    example-nc6g4         Ready    worker   117m    v1.27.4+18eadca
    example-thp29         Ready    worker   4m17s   v1.27.4+18eadca
    example-twxns         Ready    worker   88s     v1.27.4+18eadca

4.4.8.1. Adding node pools

You can create node pools for a hosted cluster by specifying a name, number of replicas, and any additional information, such as memory and CPU requirements.

Procedure

  1. If the management cluster has a cluster-wide proxy configured, you must configure proxy settings in the HostedCluster resource by completing the following steps:

    1. Edit the HostedCluster resource by entering the following command:

      $ oc edit hc <hosted_cluster_name> -n <hosted_cluster_namespace>
    2. In the HostedCluster resource, add the proxy configuration as shown in the following example:

      apiVersion: hypershift.openshift.io/v1beta1
      kind: HostedCluster
      metadata:
        annotations:
      # ...
          hypershift.openshift.io/HasBeenAvailable: "true"
          hypershift.openshift.io/management-platform: VSphere
      # ...
        name: <hosted_cluster_name>
        namespace: <hosted_cluster_namespace>
      # ...
      spec:
      # ...
        clusterID: fa45babd-40f3-4085-9b30-8bc3b7df1557
        configuration:
          proxy:
            httpProxy: http://web-proxy.example.com:3128
            httpsProxy: http://web-proxy.example.com:3128
            noProxy: .example.com,192.168.10.0/24

      In the spec.configuration.proxy fields, specify the details of the proxy configuration.

    3. Check the status on the management cluster by entering the following command:

      $ oc get nodepool -n <hosted_cluster_namespace>
    4. Check the status on the hosted cluster by entering the following command:

      $ oc --kubeconfig <hosted_cluster_name>-kubeconfig get nodes
  2. To create a node pool, enter the following information. In this example, the node pool has more CPUs assigned to the VMs:

    export NODEPOOL_NAME=${CLUSTER_NAME}-extra-cpu
    export WORKER_COUNT="2"
    export MEM="6Gi"
    export CPU="4"
    export DISK="16"
    
    $ hcp create nodepool kubevirt \
      --cluster-name $CLUSTER_NAME \
      --name $NODEPOOL_NAME \
      --node-count $WORKER_COUNT \
      --memory $MEM \
      --cores $CPU \
      --root-volume-size $DISK
  3. Check the status of the node pool by listing nodepool resources in the namespace:

    $ oc get nodepools --namespace <hosted_cluster_namespace>

    Example output

    NAME                      CLUSTER         DESIRED NODES   CURRENT NODES   AUTOSCALING   AUTOREPAIR   VERSION   UPDATINGVERSION   UPDATINGCONFIG   MESSAGE
    example                   example         5               5               False         False        <4.x.0>
    example-extra-cpu         example         2                               False         False                  True              True             Minimum availability requires 2 replicas, current 0 available

    Replace <4.x.0> with the supported OpenShift Container Platform version that you want to use.

Verification

  1. After some time, you can check the status of the node pool by entering the following command:

    $ oc --kubeconfig $CLUSTER_NAME-kubeconfig get nodes

    Example output

    NAME                      STATUS   ROLES    AGE     VERSION
    example-9jvnf             Ready    worker   97s     v1.27.4+18eadca
    example-n6prw             Ready    worker   116m    v1.27.4+18eadca
    example-nc6g4             Ready    worker   117m    v1.27.4+18eadca
    example-thp29             Ready    worker   4m17s   v1.27.4+18eadca
    example-twxns             Ready    worker   88s     v1.27.4+18eadca
    example-extra-cpu-zh9l5   Ready    worker   2m6s    v1.27.4+18eadca
    example-extra-cpu-zr8mj   Ready    worker   102s    v1.27.4+18eadca

  2. Verify that the node pool is in the status that you expect by entering this command:

    $ oc get nodepools --namespace <hosted_cluster_namespace>

    Example output

    NAME                      CLUSTER         DESIRED NODES   CURRENT NODES   AUTOSCALING   AUTOREPAIR   VERSION   UPDATINGVERSION   UPDATINGCONFIG   MESSAGE
    example                   example         5               5               False         False        <4.x.0>
    example-extra-cpu         example         2               2               False         False        <4.x.0>

    Replace <4.x.0> with the supported OpenShift Container Platform version that you want to use.

4.4.9. Verifying hosted cluster creation on OpenShift Virtualization

To verify that your hosted cluster was successfully created, complete the following steps.

Procedure

  1. Verify that the HostedCluster resource transitioned to the completed state by entering the following command:

    $ oc get --namespace clusters hostedclusters <hosted_cluster_name>

    Example output

    NAMESPACE   NAME      VERSION   KUBECONFIG                 PROGRESS    AVAILABLE   PROGRESSING   MESSAGE
    clusters    example   4.12.2    example-admin-kubeconfig   Completed   True        False         The hosted control plane is available

  2. Verify that all the cluster operators in the hosted cluster are online by entering the following commands:

    $ hcp create kubeconfig --name <hosted_cluster_name> \
      > <hosted_cluster_name>-kubeconfig
    $ oc get co --kubeconfig=<hosted_cluster_name>-kubeconfig

    Example output

    NAME                                       VERSION   AVAILABLE   PROGRESSING   DEGRADED   SINCE   MESSAGE
    console                                    4.12.2   True        False         False      2m38s
    csi-snapshot-controller                    4.12.2   True        False         False      4m3s
    dns                                        4.12.2   True        False         False      2m52s
    image-registry                             4.12.2   True        False         False      2m8s
    ingress                                    4.12.2   True        False         False      22m
    kube-apiserver                             4.12.2   True        False         False      23m
    kube-controller-manager                    4.12.2   True        False         False      23m
    kube-scheduler                             4.12.2   True        False         False      23m
    kube-storage-version-migrator              4.12.2   True        False         False      4m52s
    monitoring                                 4.12.2   True        False         False      69s
    network                                    4.12.2   True        False         False      4m3s
    node-tuning                                4.12.2   True        False         False      2m22s
    openshift-apiserver                        4.12.2   True        False         False      23m
    openshift-controller-manager               4.12.2   True        False         False      23m
    openshift-samples                          4.12.2   True        False         False      2m15s
    operator-lifecycle-manager                 4.12.2   True        False         False      22m
    operator-lifecycle-manager-catalog         4.12.2   True        False         False      23m
    operator-lifecycle-manager-packageserver   4.12.2   True        False         False      23m
    service-ca                                 4.12.2   True        False         False      4m41s
    storage                                    4.12.2   True        False         False      4m43s

4.5. Deploying hosted control planes on non-bare-metal agent machines

You can deploy hosted control planes by configuring a cluster to function as a hosting cluster. The hosting cluster is an OpenShift Container Platform cluster where the control planes are hosted. The hosting cluster is also known as the management cluster.

Important

Hosted control planes on non-bare-metal agent machines is a Technology Preview feature only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs) and might not be functionally complete. Red Hat does not recommend using them in production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.

For more information about the support scope of Red Hat Technology Preview features, see Technology Preview Features Support Scope.

Note

The management cluster is not the same thing as the managed cluster. A managed cluster is a cluster that the hub cluster manages.

The hosted control planes feature is enabled by default.

The multicluster engine Operator supports only the default local-cluster managed hub cluster. On Red Hat Advanced Cluster Management (RHACM) 2.10, you can use the local-cluster managed hub cluster as the hosting cluster.

A hosted cluster is an OpenShift Container Platform cluster with its API endpoint and control plane that are hosted on the hosting cluster. The hosted cluster includes the control plane and its corresponding data plane. You can use the multicluster engine Operator console or the hcp command-line interface (CLI) to create a hosted cluster.

The hosted cluster is automatically imported as a managed cluster. If you want to disable this automatic import feature, see "Disabling the automatic import of hosted clusters into multicluster engine Operator".

As you prepare to deploy hosted control planes on bare metal, consider the following information:

  • You can add agent machines as a worker node to a hosted cluster by using the Agent platform. Agent machine represents a host booted with a Discovery Image and ready to be provisioned as an OpenShift Container Platform node. The Agent platform is part of the central infrastructure management service. For more information, see Enabling the central infrastructure management service.
  • All hosts that are not bare metal require a manual boot with a Discovery Image ISO that the central infrastructure management provides.
  • When you scale up the node pool, a machine is created for every replica. For every machine, the Cluster API provider finds and installs an Agent that is approved, is passing validations, is not currently in use, and meets the requirements that are specified in the node pool specification. You can monitor the installation of an Agent by checking its status and conditions.
  • When you scale down a node pool, Agents are unbound from the corresponding cluster. Before you can reuse the Agents, you must restart them by using the Discovery image.
  • When you configure storage for hosted control planes, consider the recommended etcd practices. To ensure that you meet the latency requirements, dedicate a fast storage device to all hosted control planes etcd instances that run on each control-plane node. You can use LVM storage to configure a local storage class for hosted etcd pods. For more information, see "Recommended etcd practices" and "Persistent storage using logical volume manager storage" in the OpenShift Container Platform documentation.

Before you deploy hosted control planes on non-bare-metal agent machines, ensure you meet the following prerequisites:

  • You must have multicluster engine for Kubernetes Operator 2.5 or later installed on an OpenShift Container Platform cluster. You can install the multicluster engine Operator as an Operator from the OpenShift Container Platform software catalog.
  • You must have at least one managed OpenShift Container Platform cluster for the multicluster engine Operator. The local-cluster management cluster is automatically imported. For more information about the local-cluster, see Advanced configuration in the Red Hat Advanced Cluster Management documentation. You can check the status of your management cluster by running the following command:

    $ oc get managedclusters local-cluster
  • You have enabled central infrastructure management. For more information, see Enabling the central infrastructure management service in the Red Hat Advanced Cluster Management documentation.
  • You have installed the hcp command-line interface.
  • Your hosted cluster has a cluster-wide unique name.
  • You are running the management cluster and workers on the same infrastructure.

You must meet the firewall and port requirements so that ports can communicate between the management cluster, the control plane, and hosted clusters.

Note

Services run on their default ports. However, if you use the NodePort publishing strategy, services run on the port that is assigned by the NodePort service.

Use firewall rules, security groups, or other access controls to restrict access to only required sources. Avoid exposing ports publicly unless necessary. For production deployments, use a load balancer to simplify access through a single IP address.

A hosted control plane exposes the following services on non-bare-metal agent machines:

  • APIServer

    • The APIServer service runs on port 6443 by default and requires ingress access for communication between the control plane components.
    • If you use MetalLB load balancing, allow ingress access to the IP range that is used for load balancer IP addresses.
  • OAuthServer

    • The OAuthServer service runs on port 443 by default when you use the route and ingress to expose the service.
    • If you use the NodePort publishing strategy, use a firewall rule for the OAuthServer service.
  • Konnectivity

    • The Konnectivity service runs on port 443 by default when you use the route and ingress to expose the service.
    • The Konnectivity agent establishes a reverse tunnel to allow the control plane to access the network for the hosted cluster. The agent uses egress to connect to the Konnectivity server. The server is exposed by using either a route on port 443 or a manually assigned NodePort.
    • If the cluster API server address is an internal IP address, allow access from the workload subnets to the IP address on port 6443.
    • If the address is an external IP address, allow egress on port 6443 to that external IP address from the nodes.
  • Ignition

    • The Ignition service runs on port 443 by default when you use the route and ingress to expose the service.
    • If you use the NodePort publishing strategy, use a firewall rule for the Ignition service.

You do not need the following services on non-bare-metal agent machines:

  • OVNSbDb
  • OIDC

The Agent platform does not create any infrastructure, but it has the following infrastructure requirements:

  • Agents: An Agent represents a host that is booted with a discovery image and is ready to be provisioned as an OpenShift Container Platform node.
  • DNS: The API and ingress endpoints must be routable.

4.5.2. Configuring DNS on non-bare-metal agent machines

The API Server for the hosted cluster is exposed as a NodePort service. A DNS entry must exist for api.<hosted_cluster_name>.<basedomain> that points to destination where the API Server can be reached.

The DNS entry can be as simple as a record that points to one of the nodes in the managed cluster that is running the hosted control plane. The entry can also point to a load balancer that is deployed to redirect incoming traffic to the ingress pods.

  • If you are configuring DNS for a connected environment on an IPv4 network, see the following example DNS configuration:

    api.example.krnl.es.        IN A 192.168.122.20
    api.example.krnl.es.        IN A 192.168.122.21
    api.example.krnl.es.        IN A 192.168.122.22
    api-int.example.krnl.es.    IN A 192.168.122.20
    api-int.example.krnl.es.    IN A 192.168.122.21
    api-int.example.krnl.es.    IN A 192.168.122.22
    `*`.apps.example.krnl.es.   IN A 192.168.122.23
  • If you are configuring DNS for a disconnected environment on an IPv6 network, see the following example DNS configuration:

    api.example.krnl.es.        IN A 2620:52:0:1306::5
    api.example.krnl.es.        IN A 2620:52:0:1306::6
    api.example.krnl.es.        IN A 2620:52:0:1306::7
    api-int.example.krnl.es.    IN A 2620:52:0:1306::5
    api-int.example.krnl.es.    IN A 2620:52:0:1306::6
    api-int.example.krnl.es.    IN A 2620:52:0:1306::7
    `*`.apps.example.krnl.es.   IN A 2620:52:0:1306::10
  • If you are configuring DNS for a disconnected environment on a dual stack network, be sure to include DNS entries for both IPv4 and IPv6. See the following example DNS configuration:

    host-record=api-int.hub-dual.dns.base.domain.name,192.168.126.10
    host-record=api.hub-dual.dns.base.domain.name,192.168.126.10
    address=/apps.hub-dual.dns.base.domain.name/192.168.126.11
    dhcp-host=aa:aa:aa:aa:10:01,ocp-master-0,192.168.126.20
    dhcp-host=aa:aa:aa:aa:10:02,ocp-master-1,192.168.126.21
    dhcp-host=aa:aa:aa:aa:10:03,ocp-master-2,192.168.126.22
    dhcp-host=aa:aa:aa:aa:10:06,ocp-installer,192.168.126.25
    dhcp-host=aa:aa:aa:aa:10:07,ocp-bootstrap,192.168.126.26
    
    host-record=api-int.hub-dual.dns.base.domain.name,2620:52:0:1306::2
    host-record=api.hub-dual.dns.base.domain.name,2620:52:0:1306::2
    address=/apps.hub-dual.dns.base.domain.name/2620:52:0:1306::3
    dhcp-host=aa:aa:aa:aa:10:01,ocp-master-0,[2620:52:0:1306::5]
    dhcp-host=aa:aa:aa:aa:10:02,ocp-master-1,[2620:52:0:1306::6]
    dhcp-host=aa:aa:aa:aa:10:03,ocp-master-2,[2620:52:0:1306::7]
    dhcp-host=aa:aa:aa:aa:10:06,ocp-installer,[2620:52:0:1306::8]
    dhcp-host=aa:aa:aa:aa:10:07,ocp-bootstrap,[2620:52:0:1306::9]

4.5.2.1. Defining a custom DNS name

As a cluster administrator, you can create a hosted cluster with an external API DNS name that differs from the internal endpoint that gets used for node bootstraps and control plane communication.

You might want to define a different DNS name for the following reasons:

  • To replace the user-facing TLS certificate with one from a public CA without breaking the control plane functions that bind to the internal root CA
  • To support split-horizon DNS and NAT scenarios
  • To ensure a similar experience to standalone control planes, where you can use functions, such as the Show Login Command function, with the correct kubeconfig and DNS configuration

You can define a DNS name either during your initial setup or during postinstallation operations, by entering a domain name in the kubeAPIServerDNSName parameter of a HostedCluster object.

Prerequisites

  • You have a valid TLS certificate that covers the DNS name that you set in the kubeAPIServerDNSName parameter.
  • You have a resolvable DNS name URI that can reach and point to the correct address.

Procedure

  • In the specification for the HostedCluster object, add the kubeAPIServerDNSName parameter and the address for the domain and specify which certificate to use, as shown in the following example:

    #...
    spec:
      configuration:
        apiServer:
          servingCerts:
            namedCertificates:
            - names:
              - xxx.example.com
              - yyy.example.com
              servingCertificate:
                name: <my_serving_certificate>
      kubeAPIServerDNSName: <custom_address>

    The value for the kubeAPIServerDNSName parameter must be a valid and addressable domain.

    After you define the kubeAPIServerDNSName parameter and specify the certificate, the Control Plane Operator controllers create a kubeconfig file named custom-admin-kubeconfig, where the file gets stored in the HostedControlPlane namespace. The generation of certificates happen from the root CA, and the HostedControlPlane namespace manages their expiration and renewal.

    The Control Plane Operator reports a new kubeconfig file named CustomKubeconfig in the HostedControlPlane namespace. That file uses the defined new server in the kubeAPIServerDNSName parameter.

    A reference for the custom kubeconfig file exists in the status parameter as CustomKubeconfig of the HostedCluster object. The CustomKubeConfig parameter is optional, and you can add the parameter only if the kubeAPIServerDNSName parameter is not empty. After you set the CustomKubeConfig parameter, the parameter triggers the generation of a secret named <hosted_cluster_name>-custom-admin-kubeconfig in the HostedCluster namespace. You can use the secret to access the HostedCluster API server. If you remove the CustomKubeConfig parameter during postinstallation operations, deletion of all related secrets and status references occur.

    Note

    Defining a custom DNS name does not directly impact the data plane, so no expected rollouts occur. The HostedControlPlane namespace receives the changes from the HyperShift Operator and deletes the corresponding parameters.

    If you remove the kubeAPIServerDNSName parameter from the specification for the HostedCluster object, all newly generated secrets and the CustomKubeconfig reference are removed from the cluster and from the status parameter.

When you create a hosted cluster with the Agent platform, the HyperShift Operator installs the Agent Cluster API provider in the hosted control plane namespace. You can create a hosted cluster on bare metal or import one.

As you create a hosted cluster, review the following guidelines:

  • Each hosted cluster must have a cluster-wide unique name. A hosted cluster name cannot be the same as any existing managed cluster in order for multicluster engine Operator to manage it.
  • Do not use clusters as a hosted cluster name.
  • A hosted cluster cannot be created in the namespace of a multicluster engine Operator managed cluster.

Procedure

  1. Create the hosted control plane namespace by entering the following command:

    $ oc create ns <hosted_cluster_namespace>-<hosted_cluster_name> 
    1
    1
    Replace <hosted_cluster_namespace> with your hosted cluster namespace name, for example, clusters. Replace <hosted_cluster_name> with your hosted cluster name.
  2. Create a hosted cluster by entering the following command:

    $ hcp create cluster agent \
      --name=<hosted_cluster_name> \
    1
    
      --pull-secret=<path_to_pull_secret> \
    2
    
      --agent-namespace=<hosted_control_plane_namespace> \
    3
    
      --base-domain=<basedomain> \
    4
    
      --api-server-address=api.<hosted_cluster_name>.<basedomain> \
    5
    
      --etcd-storage-class=<etcd_storage_class> \
    6
    
      --ssh-key  <path_to_ssh_key> \
    7
    
      --namespace <hosted_cluster_namespace> \
    8
    
      --control-plane-availability-policy HighlyAvailable \
    9
    
      --release-image=quay.io/openshift-release-dev/ocp-release:<ocp_release> \
    10
    
      --node-pool-replicas <node_pool_replica_count> 
    11
    1
    Specify the name of your hosted cluster, for instance, example.
    2
    Specify the path to your pull secret, for example, /user/name/pullsecret.
    3
    Specify your hosted control plane namespace, for example, clusters-example. Ensure that agents are available in this namespace by using the oc get agent -n <hosted-control-plane-namespace> command.
    4
    Specify your base domain, for example, krnl.es.
    5
    The --api-server-address flag defines the IP address that is used for the Kubernetes API communication in the hosted cluster. If you do not set the --api-server-address flag, you must log in to connect to the management cluster.
    6
    Verify that you have a default storage class configured for your cluster. Otherwise, you might end up with pending PVCs. Specify the etcd storage class name, for example, lvm-storageclass.
    7
    Specify the path to your SSH public key. The default file path is ~/.ssh/id_rsa.pub.
    8
    Specify your hosted cluster namespace.
    9
    Specify the availability policy for the hosted control plane components. Supported options are SingleReplica and HighlyAvailable. The default value is HighlyAvailable.
    10
    Specify the supported OpenShift Container Platform version that you want to use, for example, 4.22.0-multi.
    11
    Specify the node pool replica count, for example, 3. You must specify the replica count as 0 or greater to create the same number of replicas. Otherwise, no node pools are created.

Verification

  • After a few moments, verify that your hosted control plane pods are up and running by entering the following command:

    $ oc -n <hosted_cluster_namespace>-<hosted_cluster_name> get pods

    Example output

    NAME                                             READY   STATUS    RESTARTS   AGE
    catalog-operator-6cd867cc7-phb2q                 2/2     Running   0          2m50s
    control-plane-operator-f6b4c8465-4k5dh           1/1     Running   0          4m32s

You can create a hosted cluster on non-bare-metal agent machines by using the OpenShift Container Platform web console.

Prerequisites

  • You have access to the cluster with cluster-admin privileges.
  • You have access to the OpenShift Container Platform web console.

Procedure

  1. Open the OpenShift Container Platform web console and log in by entering your administrator credentials.
  2. In the console header, select All Clusters.
  3. Click Infrastructure Clusters.
  4. Click Create cluster Host inventory Hosted control plane.

    The Create cluster page is displayed.

  5. On the Create cluster page, follow the prompts to enter details about the cluster, node pools, networking, and automation.

As you enter details about the cluster, you might find the following tips useful:

  • If you want to use predefined values to automatically populate fields in the console, you can create a host inventory credential. For more information, see Creating a credential for an on-premises environment.
  • On the Cluster details page, the pull secret is your OpenShift Container Platform pull secret that you use to access OpenShift Container Platform resources. If you selected a host inventory credential, the pull secret is automatically populated.
  • On the Node pools page, the namespace contains the hosts for the node pool. If you created a host inventory by using the console, the console creates a dedicated namespace.
  • On the Networking page, you select an API server publishing strategy. The API server for the hosted cluster can be exposed either by using an existing load balancer or as a service of the NodePort type. A DNS entry must exist for the api.<hosted_cluster_name>.<basedomain> setting that points to the destination where the API server can be reached. This entry can be a record that points to one of the nodes in the management cluster or a record that points to a load balancer that redirects incoming traffic to the Ingress pods.

    1. Review your entries and click Create.

    The Hosted cluster view is displayed.

    1. Monitor the deployment of the hosted cluster in the Hosted cluster view. If you do not see information about the hosted cluster, ensure that All Clusters is selected, and click the cluster name. Wait until the control plane components are ready. This process can take a few minutes.
    2. To view the node pool status, scroll to the NodePool section. The process to install the nodes takes about 10 minutes. You can also click Nodes to confirm whether the nodes joined the hosted cluster.

You can use a mirror registry to create a hosted cluster on non-bare-metal agent machines by specifying the --image-content-sources flag in the hcp create cluster command.

Procedure

  1. Create a YAML file to define Image Content Source Policies (ICSP). See the following example:

    - mirrors:
      - brew.registry.redhat.io
      source: registry.redhat.io
    - mirrors:
      - brew.registry.redhat.io
      source: registry.stage.redhat.io
    - mirrors:
      - brew.registry.redhat.io
      source: registry-proxy.engineering.redhat.com
  2. Save the file as icsp.yaml. This file contains your mirror registries.
  3. To create a hosted cluster by using your mirror registries, run the following command:

    $ hcp create cluster agent \
        --name=<hosted_cluster_name> \
    1
    
        --pull-secret=<path_to_pull_secret> \
    2
    
        --agent-namespace=<hosted_control_plane_namespace> \
    3
    
        --base-domain=<basedomain> \
    4
    
        --api-server-address=api.<hosted_cluster_name>.<basedomain> \
    5
    
        --image-content-sources icsp.yaml  \
    6
    
        --ssh-key  <path_to_ssh_key> \
    7
    
        --namespace <hosted_cluster_namespace> \
    8
    
        --release-image=quay.io/openshift-release-dev/ocp-release:<ocp_release_image> 
    9
    1
    Specify the name of your hosted cluster, for instance, example.
    2
    Specify the path to your pull secret, for example, /user/name/pullsecret.
    3
    Specify your hosted control plane namespace, for example, clusters-example. Ensure that agents are available in this namespace by using the oc get agent -n <hosted-control-plane-namespace> command.
    4
    Specify your base domain, for example, krnl.es.
    5
    The --api-server-address flag defines the IP address that is used for the Kubernetes API communication in the hosted cluster. If you do not set the --api-server-address flag, you must log in to connect to the management cluster.
    6
    Specify the icsp.yaml file that defines ICSP and your mirror registries.
    7
    Specify the path to your SSH public key. The default file path is ~/.ssh/id_rsa.pub.
    8
    Specify your hosted cluster namespace.
    9
    Specify the supported OpenShift Container Platform version that you want to use, for example, 4.22.0-multi. If you are using a disconnected environment, replace <ocp_release_image> with the digest image. To extract the OpenShift Container Platform release image digest, see Extracting the OpenShift Container Platform release image digest.

After the deployment process is complete, you can verify that the hosted cluster was created successfully. Follow these steps a few minutes after you create the hosted cluster.

Procedure

  1. Obtain the kubeconfig file for your new hosted cluster by entering the following command:

    $ oc extract -n <hosted_cluster_namespace> \
      secret/<hosted_cluster_name>-admin-kubeconfig --to=- \
      > kubeconfig-<hosted_cluster_name>
  2. Use the kubeconfig file to view the cluster Operators of the hosted cluster. Enter the following command:

    $ oc get co --kubeconfig=kubeconfig-<hosted_cluster_name>

    Example output

    NAME                                       VERSION   AVAILABLE   PROGRESSING   DEGRADED   SINCE   MESSAGE
    console                                    4.10.26   True        False         False      2m38s
    csi-snapshot-controller                    4.10.26   True        False         False      4m3s
    dns                                        4.10.26   True        False         False      2m52s

  3. View the running pods on your hosted cluster by entering the following command:

    $ oc get pods -A --kubeconfig=kubeconfig-<hosted_cluster_name>

    Example output

    NAMESPACE                                          NAME                                                      READY   STATUS             RESTARTS        AGE
    kube-system                                        konnectivity-agent-khlqv                                  0/1     Running            0               3m52s
    openshift-cluster-samples-operator                 cluster-samples-operator-6b5bcb9dff-kpnbc                 2/2     Running            0               20m
    openshift-monitoring                               alertmanager-main-0                                       6/6     Running            0               100s
    openshift-monitoring                               openshift-state-metrics-677b9fb74f-qqp6g                  3/3     Running            0               104s

4.6. Deploying hosted control planes on IBM Z

You can deploy hosted control planes by configuring a cluster to function as a management cluster. The management cluster is the OpenShift Container Platform cluster where the control planes are hosted. The management cluster is also known as the hosting cluster.

Note

The management cluster is not the managed cluster. A managed cluster is a cluster that the hub cluster manages. The management cluster can run on either the x86_64 architecture, supported beginning with OpenShift Container Platform 4.17 and multicluster engine for Kubernetes Operator 2.7, or the s390x architecture, supported beginning with OpenShift Container Platform 4.20 and multicluster engine for Kubernetes Operator 2.10.

You can convert a managed cluster to a management cluster by using the hypershift add-on to deploy the HyperShift Operator on that cluster. Then, you can start to create the hosted cluster.

The multicluster engine Operator supports only the default local-cluster, which is a hub cluster that is managed, and the hub cluster as the management cluster.

To provision hosted control planes on bare metal, you can use the Agent platform. The Agent platform uses the central infrastructure management service to add worker nodes to a hosted cluster. For more information, see "Enabling the central infrastructure management service".

Each IBM Z system host must be started with the PXE or ISO images that are provided by the central infrastructure management. After each host starts, it runs an Agent process to discover the details of the host and completes the installation. An Agent custom resource represents each host.

When you create a hosted cluster with the Agent platform, HyperShift Operator installs the Agent Cluster API provider in the hosted control plane namespace.

4.6.1. Prerequisites to configure hosted control planes on IBM Z

  • The multicluster engine for Kubernetes Operator version 2.7 or later must be installed on an OpenShift Container Platform cluster. You can install multicluster engine Operator as an Operator from the OpenShift Container Platform OperatorHub.
  • The multicluster engine Operator must have at least one managed OpenShift Container Platform cluster. The local-cluster is automatically imported in multicluster engine Operator 2.7 and later. For more information about the local-cluster, see Advanced configuration in the Red Hat Advanced Cluster Management documentation. You can check the status of your hub cluster by running the following command:

    $ oc get managedclusters local-cluster
  • You need a hosting cluster with at least three worker nodes to run the HyperShift Operator.
  • You need to enable the central infrastructure management service. For more information, see Enabling the central infrastructure management service.
  • You need to install the hosted control plane command-line interface. For more information, see Installing the hosted control plane command-line interface.
Note

The management cluster can run on either the x86_64 architecture, supported beginning with OpenShift Container Platform 4.17 and multicluster engine for Kubernetes Operator 2.7, or the s390x architecture, supported beginning with OpenShift Container Platform 4.20 and multicluster engine for Kubernetes Operator 2.10.

4.6.2. IBM Z infrastructure requirements

The Agent platform does not create any infrastructure, but requires the following resources for infrastructure:

  • Agents: An Agent represents a host that is booted with a discovery image, or PXE image and is ready to be provisioned as an OpenShift Container Platform node.
  • DNS: The API and Ingress endpoints must be routable.

The hosted control planes feature is enabled by default. If you disabled the feature and want to manually enable it, or if you need to disable the feature, see Enabling or disabling the hosted control planes feature.

4.6.3. DNS configuration for hosted control planes on IBM Z

The API server for the hosted cluster is exposed as a NodePort service. A DNS entry must exist for the api.<hosted_cluster_name>.<base_domain> that points to the destination where the API server is reachable.

The DNS entry can be as simple as a record that points to one of the nodes in the managed cluster that is running the hosted control plane.

The entry can also point to a load balancer deployed to redirect incoming traffic to the Ingress pods.

See the following example of a DNS configuration:

$ cat /var/named/<example.krnl.es.zone>

Example output

$ TTL 900
@ IN  SOA bastion.example.krnl.es.com. hostmaster.example.krnl.es.com. (
      2019062002
      1D 1H 1W 3H )
  IN NS bastion.example.krnl.es.com.
;
;
api                   IN A 1xx.2x.2xx.1xx 
1

api-int               IN A 1xx.2x.2xx.1xx
;
;
*.apps        IN A 1xx.2x.2xx.1xx
;
;EOF

1
The record refers to the IP address of the API load balancer that handles ingress and egress traffic for hosted control planes.

For IBM z/VM, add IP addresses that correspond to the IP address of the agent.

compute-0              IN A 1xx.2x.2xx.1yy
compute-1              IN A 1xx.2x.2xx.1yy

4.6.3.1. Defining a custom DNS name

As a cluster administrator, you can create a hosted cluster with an external API DNS name that differs from the internal endpoint that gets used for node bootstraps and control plane communication.

You might want to define a different DNS name for the following reasons:

  • To replace the user-facing TLS certificate with one from a public CA without breaking the control plane functions that bind to the internal root CA
  • To support split-horizon DNS and NAT scenarios
  • To ensure a similar experience to standalone control planes, where you can use functions, such as the Show Login Command function, with the correct kubeconfig and DNS configuration

You can define a DNS name either during your initial setup or during postinstallation operations, by entering a domain name in the kubeAPIServerDNSName parameter of a HostedCluster object.

Prerequisites

  • You have a valid TLS certificate that covers the DNS name that you set in the kubeAPIServerDNSName parameter.
  • You have a resolvable DNS name URI that can reach and point to the correct address.

Procedure

  • In the specification for the HostedCluster object, add the kubeAPIServerDNSName parameter and the address for the domain and specify which certificate to use, as shown in the following example:

    #...
    spec:
      configuration:
        apiServer:
          servingCerts:
            namedCertificates:
            - names:
              - xxx.example.com
              - yyy.example.com
              servingCertificate:
                name: <my_serving_certificate>
      kubeAPIServerDNSName: <custom_address>

    The value for the kubeAPIServerDNSName parameter must be a valid and addressable domain.

    After you define the kubeAPIServerDNSName parameter and specify the certificate, the Control Plane Operator controllers create a kubeconfig file named custom-admin-kubeconfig, where the file gets stored in the HostedControlPlane namespace. The generation of certificates happen from the root CA, and the HostedControlPlane namespace manages their expiration and renewal.

    The Control Plane Operator reports a new kubeconfig file named CustomKubeconfig in the HostedControlPlane namespace. That file uses the defined new server in the kubeAPIServerDNSName parameter.

    A reference for the custom kubeconfig file exists in the status parameter as CustomKubeconfig of the HostedCluster object. The CustomKubeConfig parameter is optional, and you can add the parameter only if the kubeAPIServerDNSName parameter is not empty. After you set the CustomKubeConfig parameter, the parameter triggers the generation of a secret named <hosted_cluster_name>-custom-admin-kubeconfig in the HostedCluster namespace. You can use the secret to access the HostedCluster API server. If you remove the CustomKubeConfig parameter during postinstallation operations, deletion of all related secrets and status references occur.

    Note

    Defining a custom DNS name does not directly impact the data plane, so no expected rollouts occur. The HostedControlPlane namespace receives the changes from the HyperShift Operator and deletes the corresponding parameters.

    If you remove the kubeAPIServerDNSName parameter from the specification for the HostedCluster object, all newly generated secrets and the CustomKubeconfig reference are removed from the cluster and from the status parameter.

4.6.4. Creating a hosted cluster on bare metal for IBM Z

You can create a hosted cluster or import one. When the Assisted Installer is enabled as an add-on to multicluster engine Operator and you create a hosted cluster with the Agent platform, the HyperShift Operator installs the Agent Cluster API provider in the hosted control plane namespace.

4.6.4.1. Creating a hosted cluster on bare metal for IBM Z

On bare-metal infrastructure, you can create or import a hosted cluster. After you enable the Assisted Installer as an add-on to multicluster engine Operator and you create a hosted cluster with the Agent platform, the HyperShift Operator installs the Agent Cluster API provider in the hosted control plane namespace. The Agent Cluster API provider connects a management cluster that hosts the control plane and a hosted cluster that consists of only the compute nodes.

Prerequisites

  • Each hosted cluster must have a cluster-wide unique name. A hosted cluster name cannot be the same as any existing managed cluster. Otherwise, the multicluster engine Operator cannot manage the hosted cluster.
  • Do not use the word clusters as a hosted cluster name.
  • You cannot create a hosted cluster in the namespace of a multicluster engine Operator managed cluster.
  • For best security and management practices, create a hosted cluster separate from other hosted clusters.
  • Verify that you have a default storage class configured for your cluster. Otherwise, you might see pending persistent volume claims (PVCs).

Procedure

  1. Create a namespace by entering the following command:

    $ oc create ns <hosted_cluster_namespace>

    Replace <hosted_cluster_namespace> with an identifier for your hosted cluster namespace. The HyperShift Operator creates the namespace. During the hosted cluster creation process on bare-metal infrastructure, a generated Cluster API provider role requires that the namespace already exists.

  2. Create the configuration file for your hosted cluster by entering the following command:

    $ hcp create cluster agent \
      --name=<hosted_cluster_name> \
      --pull-secret=<path_to_pull_secret> \
      --agent-namespace=<hosted_control_plane_namespace> \
      --base-domain=<base_domain> \
      --api-server-address=api.<hosted_cluster_name>.<base_domain> \
      --etcd-storage-class=<etcd_storage_class> \
      --ssh-key=<path_to_ssh_key> \
      --namespace=<hosted_cluster_namespace> \
      --control-plane-availability-policy=HighlyAvailable \
      --release-image=quay.io/openshift-release-dev/ocp-release:<ocp_release_image>-multi \
      --node-pool-replicas=<node_pool_replica_count> \
      --render \
      --render-sensitive \
      --ssh-key <home_directory>/<path_to_ssh_key>/<ssh_key> > hosted-cluster-config.yaml 
    1

    where:

    <hosted_cluster_name>
    Specifies the name of your hosted cluster, such as example.
    <path_to_pull_secret>
    Specifies the path to your pull secret, such as /user/name/pullsecret.
    <hosted_control_plane_namespace>
    Specifies your hosted control plane namespace, such as clusters-example. Ensure that agents are available in this namespace by using the oc get agent -n <hosted_control_plane_namespace> command.
    <base_domain>
    Specifies your base domain, such as krnl.es.
    api-server-address
    Specifies the IP address that gets used for the Kubernetes API communication in the hosted cluster. If you do not set the --api-server-address flag, you must log in to connect to the management cluster.
    <etcd_storage_class>
    Specifies the etcd storage class name, such as lvm-storageclass.
    <path_to_ssh_key>
    Specifies the path to your SSH public key. The default file path is ~/.ssh/id_rsa.pub.
    <hosted_cluster_namespace>
    Specifies your hosted cluster namespace.
    control-plane-availability-policy
    Specifies the availability policy for the hosted control plane components. Supported options are SingleReplica and HighlyAvailable. The default value is HighlyAvailable.
    <ocp_release_image>
    Specifies the supported OpenShift Container Platform version that you want to use, such as 4.19.0-multi. If you are using a disconnected environment, replace <ocp_release_image> with the digest image. To extract the OpenShift Container Platform release image digest, see "Extracting the OpenShift Container Platform release image digest".
    <node_pool_replica_count>
    Specifies the node pool replica count, such as 3. You must specify the replica count as 0 or greater to create the same number of replicas. Otherwise, you do not create node pools.
    <home_directory>/<path_to_ssh_key>/<ssh_key>
    Specifies the path to the SSH key, such as user/.ssh/id_rsa.
  3. Apply the changes to the hosted cluster configuration file by entering the following command:

    $ oc apply -f hosted_cluster_config.yaml
  4. Check for the creation of the hosted cluster, node pools, and pods by entering the following commands:

    $ oc get hostedcluster \
      <hosted_cluster_name> -n \
      <hosted_cluster_namespace> -o \
      jsonpath='{.status.conditions[?(@.status=="False")]}' | jq .
    $ oc get hostedcluster \
      <nodepool_name> -n \
      <hosted_cluster_namespace> -o \
      jsonpath='{.status.conditions[?(@.status=="False")]}' | jq .
    $ oc get pods -n <hosted_control_plane_namespace>
  5. Confirm that the hosted cluster is ready. The status of Available: True indicates the readiness of the control plane.

An InfraEnv is an environment where hosts that are booted with PXE images can join as agents. In this case, the agents are created in the same namespace as your hosted control plane.

Procedure

  1. Create a YAML file to contain the configuration. See the following example:

    apiVersion: agent-install.openshift.io/v1beta1
    kind: InfraEnv
    metadata:
      name: <hosted_cluster_name>
      namespace: <hosted_control_plane_namespace>
    spec:
      cpuArchitecture: s390x
      pullSecretRef:
        name: pull-secret
      sshAuthorizedKey: <ssh_public_key>
  2. Save the file as infraenv-config.yaml.
  3. Apply the configuration by entering the following command:

    $ oc apply -f infraenv-config.yaml
  4. To fetch the URL to download the PXE or ISO images, such as, initrd.img, kernel.img, or rootfs.img, which allows IBM Z machines to join as agents, enter the following command:

    $ oc -n <hosted_control_plane_namespace> get InfraEnv <hosted_cluster_name> -o json

4.6.6. Adding IBM Z agents to the InfraEnv resource

To attach compute nodes to a hosted control plane, create agents that help you to scale the node pool. Adding agents in an IBM Z environment requires additional steps, which are described in detail in this section.

Unless stated otherwise, these procedures apply to both z/VM and RHEL KVM installations on IBM Z and IBM LinuxONE.

4.6.6.1. Adding IBM Z KVM as agents

For IBM Z with KVM, run the following command to start your IBM Z environment with the downloaded PXE images from the InfraEnv resource. After the Agents are created, the host communicates with the Assisted Service and registers in the same namespace as the InfraEnv resource on the management cluster.

Procedure

  1. Run the following command:

    virt-install \
       --name "<vm_name>" \ 
    1
    
       --autostart \
       --ram=16384 \
       --cpu host \
       --vcpus=4 \
       --location "<path_to_kernel_initrd_image>,kernel=kernel.img,initrd=initrd.img" \ 
    2
    
       --disk <qcow_image_path> \ 
    3
    
       --network network:macvtap-net,mac=<mac_address> \ 
    4
    
       --graphics none \
       --noautoconsole \
       --wait=-1
       --extra-args "rd.neednet=1 nameserver=<nameserver>   coreos.live.rootfs_url=http://<http_server>/rootfs.img random.trust_cpu=on rd.luks.options=discard ignition.firstboot ignition.platform.id=metal console=tty1 console=ttyS1,115200n8 coreos.inst.persistent-kargs=console=tty1 console=ttyS1,115200n8" 
    5
    1
    Specify the name of the virtual machine.
    2
    Specify the location of the kernel_initrd_image file.
    3
    Specify the disk image path.
    4
    Specify the Mac address.
    5
    Specify the server name of the agents.
  2. For ISO boot, download ISO from the InfraEnv resource and boot the nodes by running the following command:

    virt-install \
      --name "<vm_name>" \ 
    1
    
      --autostart \
      --memory=16384 \
      --cpu host \
      --vcpus=4 \
      --network network:macvtap-net,mac=<mac_address> \ 
    2
    
      --cdrom "<path_to_image.iso>" \ 
    3
    
      --disk <qcow_image_path> \
      --graphics none \
      --noautoconsole \
      --os-variant <os_version> \ 
    4
    
      --wait=-1
    1
    Specify the name of the virtual machine.
    2
    Specify the Mac address.
    3
    Specify the location of the image.iso file.
    4
    Specify the operating system version that you are using.

4.6.6.2. Adding IBM Z LPAR as agents

You can add the Logical Partition (LPAR) on IBM Z or IBM LinuxONE as a compute node to a hosted control plane.

Procedure

  1. Create a boot parameter file for the agents:

    Example parameter file

    rd.neednet=1 cio_ignore=all,!condev \
    console=ttysclp0 \
    ignition.firstboot ignition.platform.id=metal
    coreos.live.rootfs_url=http://<http_server>/rhcos-<version>-live-rootfs.<architecture>.img \
    1
    
    coreos.inst.persistent-kargs=console=ttysclp0
    ip=<ip>::<gateway>:<netmask>::<interface>:none nameserver=<dns> \
    2
    
    rd.znet=qeth,<network_adaptor_range>,layer2=1
    rd.<disk_type>=<adapter> \
    3
    
    zfcp.allow_lun_scan=0
    ai.ip_cfg_override=1 \
    4
    
    random.trust_cpu=on rd.luks.options=discard

    1
    For the coreos.live.rootfs_url artifact, specify the matching rootfs artifact for the kernel and initramfs that you are starting. Only HTTP and HTTPS protocols are supported.
    2
    For the ip parameter, manually assign the IP address, as described in Installing a cluster with z/VM on IBM Z and IBM LinuxONE.
    3
    For installations on DASD-type disks, use rd.dasd to specify the DASD where Red Hat Enterprise Linux CoreOS (RHCOS) is to be installed. For installations on FCP-type disks, use rd.zfcp=<adapter>,<wwpn>,<lun> to specify the FCP disk where RHCOS is to be installed.
    4
    Specify this parameter when you use an Open Systems Adapter (OSA) or HiperSockets.
  2. Download the .ins and initrd.img.addrsize files from the InfraEnv resource.

    By default, the URL for the .ins and initrd.img.addrsize files is not available in the InfraEnv resource. You must edit the URL to fetch those artifacts.

    1. Update the kernel URL endpoint to include ins-file by running the followign command:

      $ curl -k -L -o generic.ins "< url for ins-file >"

      Example URL

      https://…/boot-artifacts/ins-file?arch=s390x&version=4.17.0

    2. Update the initrd URL endpoint to include s390x-initrd-addrsize:

      Example URL

      https://…./s390x-initrd-addrsize?api_key=<api-key>&arch=s390x&version=4.17.0

  3. Transfer the initrd, kernel, generic.ins, and initrd.img.addrsize parameter files to the file server. For more information about how to transfer the files with FTP and boot, see "Installing in an LPAR".
  4. Start the machine.
  5. Repeat the procedure for all other machines in the cluster.

4.6.6.3. Adding IBM z/VM as agents

If you want to use a static IP for z/VM guest, you must configure the NMStateConfig attribute for the z/VM agent so that the IP parameter persists in the second start.

Complete the following steps to start your IBM Z environment with the downloaded PXE images from the InfraEnv resource. After the Agents are created, the host communicates with the Assisted Service and registers in the same namespace as the InfraEnv resource on the management cluster.

Procedure

  1. Update the parameter file to add the rootfs_url, network_adaptor and disk_type values.

    Example parameter file

    rd.neednet=1 cio_ignore=all,!condev \
    console=ttysclp0  \
    ignition.firstboot ignition.platform.id=metal \
    coreos.live.rootfs_url=http://<http_server>/rhcos-<version>-live-rootfs.<architecture>.img \
    1
    
    coreos.inst.persistent-kargs=console=ttysclp0
    ip=<ip>::<gateway>:<netmask>::<interface>:none nameserver=<dns> \
    2
    
    rd.znet=qeth,<network_adaptor_range>,layer2=1
    rd.<disk_type>=<adapter> \
    3
    
    zfcp.allow_lun_scan=0
    ai.ip_cfg_override=1 \
    4

    1
    For the coreos.live.rootfs_url artifact, specify the matching rootfs artifact for the kernel and initramfs that you are starting. Only HTTP and HTTPS protocols are supported.
    2
    For the ip parameter, manually assign the IP address, as described in Installing a cluster with z/VM on IBM Z and IBM LinuxONE.
    3
    For installations on DASD-type disks, use rd.dasd to specify the DASD where Red Hat Enterprise Linux CoreOS (RHCOS) is to be installed. For installations on FCP-type disks, use rd.zfcp=<adapter>,<wwpn>,<lun> to specify the FCP disk where RHCOS is to be installed.
    Note

    For FCP multipath configurations, provide two disks instead of one.

    Example

    rd.zfcp=<adapter1>,<wwpn1>,<lun1> \
    rd.zfcp=<adapter2>,<wwpn2>,<lun2>

    4
    Specify this parameter when you use an Open Systems Adapter (OSA) or HiperSockets.
  2. Move initrd, kernel images, and the parameter file to the guest VM by running the following commands:

    vmur pun -r -u -N kernel.img $INSTALLERKERNELLOCATION/<image name>
    vmur pun -r -u -N generic.parm $PARMFILELOCATION/paramfilename
    vmur pun -r -u -N initrd.img $INSTALLERINITRAMFSLOCATION/<image name>
  3. Run the following command from the guest VM console:

    cp ipl c
  4. To list the agents and their properties, enter the following command:

    $ oc -n <hosted_control_plane_namespace> get agents

    Example output

    NAME    CLUSTER APPROVED    ROLE    STAGE
    50c23cda-cedc-9bbd-bcf1-9b3a5c75804d    auto-assign
    5e498cd3-542c-e54f-0c58-ed43e28b568a    auto-assign

  5. Run the following command to approve the agent.

    $ oc -n <hosted_control_plane_namespace> patch agent \
      50c23cda-cedc-9bbd-bcf1-9b3a5c75804d -p \
      '{"spec":{"installation_disk_id":"/dev/sda","approved":true,"hostname":"worker-zvm-0.hostedn.example.com"}}' \
    1
    
      --type merge
    1
    Optionally, you can set the agent ID <installation_disk_id> and <hostname> in the specification.
  6. Run the following command to verify that the agents are approved:

    $ oc -n <hosted_control_plane_namespace> get agents

    Example output

    NAME                                            CLUSTER     APPROVED   ROLE          STAGE
    50c23cda-cedc-9bbd-bcf1-9b3a5c75804d             true       auto-assign
    5e498cd3-542c-e54f-0c58-ed43e28b568a             true       auto-assign

4.6.7. Scaling the NodePool object for a hosted cluster on IBM Z

The NodePool object is created when you create a hosted cluster. By scaling the NodePool object, you can add more compute nodes to the hosted control plane.

When you scale up a node pool, a machine is created. The Cluster API provider finds an Agent that is approved, is passing validations, is not currently in use, and meets the requirements that are specified in the node pool specification. You can monitor the installation of an Agent by checking its status and conditions.

Procedure

  1. Run the following command to scale the NodePool object to two nodes:

    $ oc -n <clusters_namespace> scale nodepool <nodepool_name> --replicas 2

    The Cluster API agent provider randomly picks two agents that are then assigned to the hosted cluster. Those agents go through different states and finally join the hosted cluster as OpenShift Container Platform nodes. The agents pass through the transition phases in the following order:

    • binding
    • discovering
    • insufficient
    • installing
    • installing-in-progress
    • added-to-existing-cluster
  2. Run the following command to see the status of a specific scaled agent:

    $ oc -n <hosted_control_plane_namespace> get agent -o \
      jsonpath='{range .items[*]}BMH: {@.metadata.labels.agent-install\.openshift\.io/bmh} \
      Agent: {@.metadata.name} State: {@.status.debugInfo.state}{"\n"}{end}'

    Example output

    BMH: Agent: 50c23cda-cedc-9bbd-bcf1-9b3a5c75804d State: known-unbound
    BMH: Agent: 5e498cd3-542c-e54f-0c58-ed43e28b568a State: insufficient

  3. Run the following command to see the transition phases:

    $ oc -n <hosted_control_plane_namespace> get agent

    Example output

    NAME                                   CLUSTER           APPROVED       ROLE        STAGE
    50c23cda-cedc-9bbd-bcf1-9b3a5c75804d   hosted-forwarder   true          auto-assign
    5e498cd3-542c-e54f-0c58-ed43e28b568a                      true          auto-assign
    da503cf1-a347-44f2-875c-4960ddb04091   hosted-forwarder   true          auto-assign

  4. Run the following command to generate the kubeconfig file to access the hosted cluster:

    $ hcp create kubeconfig \
      --namespace <clusters_namespace> \
      --name <hosted_cluster_namespace> > <hosted_cluster_name>.kubeconfig
  5. After the agents reach the added-to-existing-cluster state, verify that you can see the OpenShift Container Platform nodes by entering the following command:

    $ oc --kubeconfig <hosted_cluster_name>.kubeconfig get nodes

    Example output

    NAME                             STATUS   ROLES    AGE      VERSION
    worker-zvm-0.hostedn.example.com Ready    worker   5m41s    v1.24.0+3882f8f
    worker-zvm-1.hostedn.example.com Ready    worker   6m3s     v1.24.0+3882f8f

    Cluster Operators start to reconcile by adding workloads to the nodes.

  6. Enter the following command to verify that two machines were created when you scaled up the NodePool object:

    $ oc -n <hosted_control_plane_namespace> get machine.cluster.x-k8s.io

    Example output

    NAME                                CLUSTER  NODENAME PROVIDERID     PHASE     AGE   VERSION
    hosted-forwarder-79558597ff-5tbqp   hosted-forwarder-crqq5   worker-zvm-0.hostedn.example.com   agent://50c23cda-cedc-9bbd-bcf1-9b3a5c75804d   Running   41h   4.15.0
    hosted-forwarder-79558597ff-lfjfk   hosted-forwarder-crqq5   worker-zvm-1.hostedn.example.com   agent://5e498cd3-542c-e54f-0c58-ed43e28b568a   Running   41h   4.15.0

  7. Run the following command to check the cluster version:

    $ oc --kubeconfig <hosted_cluster_name>.kubeconfig get clusterversion,co

    Example output

    NAME                                         VERSION       AVAILABLE   PROGRESSING   SINCE   STATUS
    clusterversion.config.openshift.io/version   4.15.0-ec.2   True        False         40h     Cluster version is 4.15.0-ec.2

  8. Run the following command to check the cluster operator status:

    $ oc --kubeconfig <hosted_cluster_name>.kubeconfig get clusteroperators

For each component of your cluster, the output shows the following cluster operator statuses: NAME, VERSION, AVAILABLE, PROGRESSING, DEGRADED, SINCE, and MESSAGE.

For an output example, see Initial Operator configuration.

4.7. Deploying hosted control planes on IBM Power

You can deploy hosted control planes by configuring a cluster to function as a hosting cluster. This configuration provides an efficient and scalable solution for managing many clusters. The hosting cluster is an OpenShift Container Platform cluster that hosts control planes. The hosting cluster is also known as the management cluster.

Note

The management cluster is not the managed cluster. A managed cluster is a cluster that the hub cluster manages.

The multicluster engine Operator supports only the default local-cluster, which is a managed hub cluster, and the hub cluster as the hosting cluster.

To provision hosted control planes on bare-metal infrastructure, you can use the Agent platform. The Agent platform uses the central infrastructure management service to add compute nodes to a hosted cluster. For more information, see "Enabling the central infrastructure management service".

You must start each IBM Power host with a Discovery image that the central infrastructure management provides. After each host starts, it runs an Agent process to discover the details of the host and completes the installation. An Agent custom resource represents each host.

When you create a hosted cluster with the Agent platform, HyperShift installs the Agent Cluster API provider in the hosted control plane namespace.

4.7.1. Prerequisites to configure hosted control planes on IBM Power

  • The multicluster engine for Kubernetes Operator version 2.7 and later installed on an OpenShift Container Platform cluster. The multicluster engine Operator is automatically installed when you install Red Hat Advanced Cluster Management (RHACM). You can also install the multicluster engine Operator without RHACM as an Operator from the OpenShift Container Platform software catalog.
  • The multicluster engine Operator must have at least one managed OpenShift Container Platform cluster. The local-cluster managed hub cluster is automatically imported in the multicluster engine Operator version 2.7 and later. For more information about local-cluster, see Advanced configuration in the RHACM documentation. You can check the status of your hub cluster by running the following command:

    $ oc get managedclusters local-cluster
  • You need a hosting cluster with at least 3 compute nodes to run the HyperShift Operator.
  • You need to enable the central infrastructure management service. For more information, see "Enabling the central infrastructure management service".
  • You need to install the hosted control planes command-line interface. For more information, see "Installing the hosted control plane command-line interface".

The hosted control planes feature is enabled by default. If you disabled the feature and want to manually enable the feature, see "Manually enabling the hosted control planes feature". If you need to disable the feature, see "Disabling the hosted control planes feature".

4.7.2. IBM Power infrastructure requirements

The Agent platform does not create any infrastructure, but requires the following resources for infrastructure:

  • Agents: An Agent represents a host that boots with a Discovery image and that you can provision as an OpenShift Container Platform node.
  • DNS: The API and Ingress endpoints must be routable.

4.7.3. DNS configuration for hosted control planes on IBM Power

Clients outside the network can access the API server for the hosted cluster. A DNS entry must exist for the api.<hosted_cluster_name>.<basedomain> entry that points to the destination where the API server is reachable.

The DNS entry can be as simple as a record that points to one of the nodes in the managed cluster that runs the hosted control plane.

The entry can also point to a deployed load balancer to redirect incoming traffic to the ingress pods.

See the following example of a DNS configuration:

$ cat /var/named/<example.krnl.es.zone>

Example output

$ TTL 900
@ IN  SOA bastion.example.krnl.es.com. hostmaster.example.krnl.es.com. (
      2019062002
      1D 1H 1W 3H )
  IN NS bastion.example.krnl.es.com.
;
;
api                   IN A 1xx.2x.2xx.1xx 
1

api-int               IN A 1xx.2x.2xx.1xx
;
;
*.apps.<hosted_cluster_name>.<basedomain>           IN A 1xx.2x.2xx.1xx
;
;EOF

1
The record refers to the IP address of the API load balancer that handles ingress and egress traffic for hosted control planes.

For IBM Power, add IP addresses that correspond to the IP address of the agent.

Example configuration

compute-0              IN A 1xx.2x.2xx.1yy
compute-1              IN A 1xx.2x.2xx.1yy

4.7.3.1. Defining a custom DNS name

As a cluster administrator, you can create a hosted cluster with an external API DNS name that differs from the internal endpoint that gets used for node bootstraps and control plane communication.

You might want to define a different DNS name for the following reasons:

  • To replace the user-facing TLS certificate with one from a public CA without breaking the control plane functions that bind to the internal root CA
  • To support split-horizon DNS and NAT scenarios
  • To ensure a similar experience to standalone control planes, where you can use functions, such as the Show Login Command function, with the correct kubeconfig and DNS configuration

You can define a DNS name either during your initial setup or during postinstallation operations, by entering a domain name in the kubeAPIServerDNSName parameter of a HostedCluster object.

Prerequisites

  • You have a valid TLS certificate that covers the DNS name that you set in the kubeAPIServerDNSName parameter.
  • You have a resolvable DNS name URI that can reach and point to the correct address.

Procedure

  • In the specification for the HostedCluster object, add the kubeAPIServerDNSName parameter and the address for the domain and specify which certificate to use, as shown in the following example:

    #...
    spec:
      configuration:
        apiServer:
          servingCerts:
            namedCertificates:
            - names:
              - xxx.example.com
              - yyy.example.com
              servingCertificate:
                name: <my_serving_certificate>
      kubeAPIServerDNSName: <custom_address>

    The value for the kubeAPIServerDNSName parameter must be a valid and addressable domain.

    After you define the kubeAPIServerDNSName parameter and specify the certificate, the Control Plane Operator controllers create a kubeconfig file named custom-admin-kubeconfig, where the file gets stored in the HostedControlPlane namespace. The generation of certificates happen from the root CA, and the HostedControlPlane namespace manages their expiration and renewal.

    The Control Plane Operator reports a new kubeconfig file named CustomKubeconfig in the HostedControlPlane namespace. That file uses the defined new server in the kubeAPIServerDNSName parameter.

    A reference for the custom kubeconfig file exists in the status parameter as CustomKubeconfig of the HostedCluster object. The CustomKubeConfig parameter is optional, and you can add the parameter only if the kubeAPIServerDNSName parameter is not empty. After you set the CustomKubeConfig parameter, the parameter triggers the generation of a secret named <hosted_cluster_name>-custom-admin-kubeconfig in the HostedCluster namespace. You can use the secret to access the HostedCluster API server. If you remove the CustomKubeConfig parameter during postinstallation operations, deletion of all related secrets and status references occur.

    Note

    Defining a custom DNS name does not directly impact the data plane, so no expected rollouts occur. The HostedControlPlane namespace receives the changes from the HyperShift Operator and deletes the corresponding parameters.

    If you remove the kubeAPIServerDNSName parameter from the specification for the HostedCluster object, all newly generated secrets and the CustomKubeconfig reference are removed from the cluster and from the status parameter.

4.7.4. Creating a hosted cluster by using the CLI

On bare-metal infrastructure, you can import a hosted cluster or create one by using the command-line interface (CLI).

After you enable the Assisted Installer as an add-on to multicluster engine Operator and you create a hosted cluster with the Agent platform, the HyperShift Operator installs the Agent Cluster API provider in the hosted control plane namespace. The Agent Cluster API provider connects a management cluster that hosts the control plane and a hosted cluster that consists of only the compute nodes.

Prerequisites

  • Each hosted cluster must have a cluster-wide unique name. A hosted cluster name cannot be the same as any existing managed cluster. Otherwise, the multicluster engine Operator cannot manage the hosted cluster.
  • Do not use the word clusters as a hosted cluster name.
  • You cannot create a hosted cluster in the namespace of a multicluster engine Operator managed cluster.
  • For best security and management practices, create a hosted cluster separate from other hosted clusters.
  • Verify that you have a default storage class configured for your cluster. Otherwise, you might see pending persistent volume claims (PVCs).
  • By default when you use the hcp create cluster agent command, the command creates a hosted cluster with configured node ports. The preferred publishing strategy for hosted clusters on bare metal exposes services through a load balancer. If you create a hosted cluster by using the web console or by using Red Hat Advanced Cluster Management, to set a publishing strategy for a service besides the Kubernetes API server, you must manually specify the servicePublishingStrategy information in the HostedCluster custom resource.
  • Ensure that you meet the requirements described in "Requirements for hosted control planes on bare metal", which includes requirements related to infrastructure, firewalls, ports, and services. For example, those requirements describe how to add the appropriate zone labels to the bare-metal hosts in your management cluster, as shown in the following example commands:

    $ oc label node [compute-node-1] topology.kubernetes.io/zone=zone1
    $ oc label node [compute-node-2] topology.kubernetes.io/zone=zone2
    $ oc label node [compute-node-3] topology.kubernetes.io/zone=zone3
  • Ensure that you have added bare-metal nodes to a hardware inventory.

Procedure

  1. Create a namespace by entering the following command:

    $ oc create ns <hosted_cluster_namespace>

    Replace <hosted_cluster_namespace> with an identifier for your hosted cluster namespace. The HyperShift Operator creates the namespace. During the hosted cluster creation process on bare-metal infrastructure, a generated Cluster API provider role requires that the namespace already exists.

  2. Create the configuration file for your hosted cluster by entering the following command:

    $ hcp create cluster agent \
      --name=<hosted_cluster_name> \
      --pull-secret=<path_to_pull_secret> \
      --agent-namespace=<hosted_control_plane_namespace> \
      --base-domain=<base_domain> \
      --api-server-address=api.<hosted_cluster_name>.<base_domain>
      --etcd-storage-class=<etcd_storage_class> \
      --ssh-key=<path_to_ssh_key> \
      --namespace=<hosted_cluster_namespace> \
      --control-plane-availability-policy=HighlyAvailable \
      --release-image=quay.io/openshift-release-dev/ocp-release:<ocp_release_image>-multi \
      --node-pool-replicas=<node_pool_replica_count> \
      --render \
      --render-sensitive \
      --ssh-key <home_directory>/<path_to_ssh_key>/<ssh_key> > hosted-cluster-config.yaml

    where:

    <hosted_cluster_name>
    Specifies the name of your hosted cluster, such as example.
    <path_to_pull_secret>
    Specifies the path to your pull secret, such as /user/name/pullsecret.
    <hosted_control_plane_namespace>
    Specifies your hosted control plane namespace, such as clusters-example. Ensure that agents are available in this namespace by using the oc get agent -n <hosted_control_plane_namespace> command.
    <base_domain>
    Specifies your base domain, such as krnl.es.
    --api-server-address
    Specifies the IP address that gets used for the Kubernetes API communication in the hosted cluster. If you do not set the --api-server-address flag, you must log in to connect to the management cluster.
    <etcd_storage_class>
    Specifies the etcd storage class name, such as lvm-storageclass.
    <path_to_ssh_key>
    Specifies the path to your SSH public key. The default file path is ~/.ssh/id_rsa.pub.
    <hosted_cluster_namespace>
    Specifies your hosted cluster namespace.
    control-plane-availability-policy
    Specifies the availability policy for the hosted control plane components. Supported options are SingleReplica and HighlyAvailable. The default value is HighlyAvailable.
    <ocp_release_image>
    Specifies the supported OpenShift Container Platform version that you want to use, such as 4.22.0-multi. If you are using a disconnected environment, replace <ocp_release_image> with the digest image. To extract the OpenShift Container Platform release image digest, see "Extracting the OpenShift Container Platform release image digest".
    <node_pool_replica_count>
    Specifies the node pool replica count, such as 3. You must specify the replica count as 0 or greater to create the same number of replicas. Otherwise, you do not create node pools.
    <home_directory>/<path_to_ssh_key>/<ssh_key>
    Specifies the path to the SSH key, such as user/.ssh/id_rsa.
  3. Configure the service publishing strategy. By default, hosted clusters use the NodePort service publishing strategy because node ports are always available without additional infrastructure. However, you can configure the service publishing strategy to use a load balancer.

    • If you are using the default NodePort strategy, configure the DNS to point to the hosted cluster compute nodes, not the management cluster nodes. For more information, see "DNS configurations on bare metal".
    • For production environments, use the LoadBalancer strategy because this strategy provides certificate handling and automatic DNS resolution. The following example demonstrates changing the service publishing LoadBalancer strategy in your hosted cluster configuration file:

      apiVersion: hypershift.openshift.io/v1beta1
      kind: HostedCluster
      metadata:
      # ...
      spec:
        services:
        - service: APIServer
          servicePublishingStrategy:
            type: LoadBalancer
        - service: Ignition
          servicePublishingStrategy:
            type: Route
        - service: Konnectivity
          servicePublishingStrategy:
            type: Route
        - service: OAuthServer
          servicePublishingStrategy:
            type: Route
        - service: OIDC
          servicePublishingStrategy:
            type: Route
        sshKey:
          name: <ssh_key>
      # ...

      Specify LoadBalancer as the API Server type. For all other services, specify Route as the type.

  4. If you use external load balancers, configure the ingress endpoint as shown in the following example. If you do not configure the endpoint, the default behavior is to randomize the node port that the service exposes the ingress on. To configure how the ingress controller publishes the default ingress route, set the endpointPublishingStrategy parameter and its underlying functions by editing the HostedCluster resource:

    apiVersion: hypershift.openshift.io/v1beta1
    kind: HostedCluster
    metadata:
    #...
    spec:
      operatorConfiguration:
        ingressOperator:
          endpointPublishingStrategy:
            hostNetwork:
              httpPort: 80
              httpsPort: 443
              protocol: TCP
              statsPort: 1936
            type: HostNetwork
    #...

    The spec.operatorConfiguration.ingressOperator.endPointPublishingStrategy.type parameter specifies the endpoint for the load balancer. For bare-metal installations, use the HostNetwork type.

  5. Apply the changes to the hosted cluster configuration file by entering the following command:

    $ oc apply -f hosted_cluster_config.yaml
  6. Check for the creation of the hosted cluster, node pools, and pods by entering the following commands:

    $ oc get hostedcluster \
      <hosted_cluster_namespace> -n \
      <hosted_cluster_namespace> -o \
      jsonpath='{.status.conditions[?(@.status=="False")]}' | jq .
    $ oc get nodepool \
      <hosted_cluster_namespace> -n \
      <hosted_cluster_namespace> -o \
      jsonpath='{.status.conditions[?(@.status=="False")]}' | jq .
    $ oc get pods -n <hosted_cluster_namespace>
  7. Confirm that the hosted cluster is ready. The status of Available: True indicates the readiness of the cluster and the node pool status shows AllMachinesReady: True. These statuses indicate the healthiness of all cluster Operators.
  8. Install MetalLB in the hosted cluster:

    1. Extract the kubeconfig file from the hosted cluster and set the environment variable for hosted cluster access by entering the following commands:

      $ oc get secret \
        <hosted_cluster_namespace>-admin-kubeconfig \
        -n <hosted_cluster_namespace> \
        -o jsonpath='{.data.kubeconfig}' \
        | base64 -d > \
        kubeconfig-<hosted_cluster_namespace>.yaml
      $ export KUBECONFIG="/path/to/kubeconfig-<hosted_cluster_namespace>.yaml"
    2. Install the MetalLB Operator by creating the install-metallb-operator.yaml file:

      apiVersion: v1
      kind: Namespace
      metadata:
        name: metallb-system
      ---
      apiVersion: operators.coreos.com/v1
      kind: OperatorGroup
      metadata:
        name: metallb-operator
        namespace: metallb-system
      ---
      apiVersion: operators.coreos.com/v1alpha1
      kind: Subscription
      metadata:
        name: metallb-operator
        namespace: metallb-system
      spec:
        channel: "stable"
        name: metallb-operator
        source: redhat-operators
        sourceNamespace: openshift-marketplace
        installPlanApproval: Automatic
      # ...
    3. Apply the file by entering the following command:

      $ oc apply -f install-metallb-operator.yaml
    4. Configure the MetalLB IP address pool by creating the deploy-metallb-ipaddresspool.yaml file:

      apiVersion: metallb.io/v1beta1
      kind: IPAddressPool
      metadata:
        name: metallb
        namespace: metallb-system
      spec:
        autoAssign: true
        addresses:
        - 10.11.176.71-10.11.176.75
      ---
      apiVersion: metallb.io/v1beta1
      kind: L2Advertisement
      metadata:
        name: l2advertisement
        namespace: metallb-system
      spec:
        ipAddressPools:
        - metallb
      # ...
    5. Apply the configuration by entering the following command:

      $ oc apply -f deploy-metallb-ipaddresspool.yaml
    6. Verify the installation of MetalLB by checking the Operator status, the IP address pool, and the L2Advertisement resource by entering the following commands:

      $ oc get pods -n metallb-system
      $ oc get ipaddresspool -n metallb-system
      $ oc get l2advertisement -n metallb-system
  9. Configure the load balancer for ingress:

    1. Create the ingress-loadbalancer.yaml file:

      apiVersion: v1
      kind: Service
      metadata:
        annotations:
          metallb.universe.tf/address-pool: metallb
        name: metallb-ingress
        namespace: openshift-ingress
      spec:
        ports:
          - name: http
            protocol: TCP
            port: 80
            targetPort: 80
          - name: https
            protocol: TCP
            port: 443
            targetPort: 443
        selector:
          ingresscontroller.operator.openshift.io/deployment-ingresscontroller: default
        type: LoadBalancer
      # ...
    2. Apply the configuration by entering the following command:

      $ oc apply -f ingress-loadbalancer.yaml
    3. Verify that the load balancer service works as expected by entering the following command:

      $ oc get svc metallb-ingress -n openshift-ingress

      Example output

      NAME              TYPE           CLUSTER-IP       EXTERNAL-IP    PORT(S)                      AGE
      metallb-ingress   LoadBalancer   172.31.127.129   10.11.176.71   80:30961/TCP,443:32090/TCP   16h

  10. Configure the DNS to work with the load balancer:

    1. Configure the DNS for the apps domain by pointing the *.apps.<hosted_cluster_namespace>.<base_domain> wildcard DNS record to the load balancer IP address.
    2. Verify the DNS resolution by entering the following command:

      $ nslookup console-openshift-console.apps.<hosted_cluster_namespace>.<base_domain> <load_balancer_ip_address>

      Example output

      Server:         10.11.176.1
      Address:        10.11.176.1#53
      
      Name:   console-openshift-console.apps.my-hosted-cluster.sample-base-domain.com
      Address: 10.11.176.71

Verification

  1. Check the cluster Operators by entering the following command:

    $ oc get clusteroperators

    Ensure that all Operators show AVAILABLE: True, PROGRESSING: False, and DEGRADED: False.

  2. Check the nodes by entering the following command:

    $ oc get nodes

    Ensure that each node has the READY status.

  3. Test access to the console by entering the following URL in a web browser:

    https://console-openshift-console.apps.<hosted_cluster_namespace>.<base_domain>

A node pool is a group of nodes within a cluster that share the same configuration. Heterogeneous node pools have different configurations, so that you can create pools and optimize them for various workloads.

You can create heterogeneous node pools on the agent platform. The platform enables clusters to run diverse machine types, such as x86_64 or ppc64le, within a single hosted cluster.

Creating a heterogeneous node pool requires completion of the following general steps:

  • Create an AgentServiceConfig custom resource (CR) that informs the Operator how much storage it needs for components such as the database and filesystem. The CR also defines which OpenShift Container Platform versions to support.
  • Create an agent cluster.
  • Create the heterogeneous node pool.
  • Configure DNS for hosted control planes
  • Create an InfraEnv custom resource (CR) for each architecture.
  • Add agents to the heterogeneous cluster.

4.7.5.1. Creating the AgentServiceConfig custom resource

To create heterogeneous node pools on an agent hosted cluster, you need to create the AgentServiceConfig CR with two heterogeneous architecture operating system (OS) images.

Procedure

  • Run the following command:

    $ envsubst <<"EOF" | oc apply -f -
    apiVersion: agent-install.openshift.io/v1beta1
    kind: AgentServiceConfig
    metadata:
     name: agent
    spec:
      databaseStorage:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: <db_volume_name> 
    1
    
      filesystemStorage:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: <fs_volume_name> 
    2
    
      osImages:
        - openshiftVersion: <ocp_version> 
    3
    
          version: <ocp_release_version_x86> 
    4
    
          url: <iso_url_x86> 
    5
    
          rootFSUrl: <root_fs_url_x8> 
    6
    
          cpuArchitecture: <arch_x86> 
    7
    
        - openshiftVersion: <ocp_version> 
    8
    
          version: <ocp_release_version_ppc64le> 
    9
    
          url: <iso_url_ppc64le> 
    10
    
          rootFSUrl: <root_fs_url_ppc64le> 
    11
    
          cpuArchitecture: <arch_ppc64le> 
    12
    
    EOF
    1
    Specify the multicluster engine for Kubernetes Operator agentserviceconfig config, database volume name.
    2
    Specify the multicluster engine Operator agentserviceconfig config, filesystem volume name.
    3
    Specify the current version of OpenShift Container Platform.
    4
    Specify the current OpenShift Container Platform release version for x86.
    5
    Specify the ISO URL for x86.
    6
    Specify the root filesystem URL for x86.
    7
    Specify the CPU architecture for x86.
    8
    Specify the current OpenShift Container Platform version.
    9
    Specify the OpenShift Container Platform release version for ppc64le.
    10
    Specify the ISO URL for ppc64le.
    11
    Specify the root filesystem URL for ppc64le.
    12
    Specify the CPU architecture for ppc64le.

4.7.5.2. Create an agent cluster

An agent-based approach manages and provisions an agent cluster. An agent cluster can use heterogeneous node pools, allowing the use of different types of compute nodes within the same cluster.

Prerequisites

  • You used a multi-architecture release image to enable support for heterogeneous node pools when creating a hosted cluster. Find the latest multi-architecture images on the Multi-arch release images page.

Procedure

  1. Create an environment variable for the cluster namespace by running the following command:

    $ export CLUSTERS_NAMESPACE=<hosted_cluster_namespace>
  2. Create an environment variable for the machine classless inter-domain routing (CIDR) notation by running the following command:

    $ export MACHINE_CIDR=192.168.122.0/24
  3. Create the hosted control namespace by running the following command:

    $ oc create ns <hosted_control_plane_namespace>
  4. Create the cluster by running the following command:

    $ hcp create cluster agent \
        --name=<hosted_cluster_name> \
    1
    
        --pull-secret=<pull_secret_file> \
    2
    
        --agent-namespace=<hosted_control_plane_namespace> \
    3
    
        --base-domain=<basedomain> \
    4
    
        --api-server-address=api.<hosted_cluster_name>.<basedomain> \
        --release-image=quay.io/openshift-release-dev/ocp-release:<ocp_release> 
    5
    1
    Specify the hosted cluster name.
    2
    Specify the pull secret file path.
    3
    Specify the namespace for the hosted control plane.
    4
    Specify the base domain for the hosted cluster.
    5
    Specify the current OpenShift Container Platform release version.

4.7.5.3. Creating heterogeneous node pools

You create heterogeneous node pools by using the NodePool custom resource (CR), so that you can optimize costs and performance by associating different workloads to specific hardware.

Procedure

  • To define a NodePool CR, create a YAML file similar to the following example:

    envsubst <<"EOF" | oc apply -f -
    apiVersion:apiVersion: hypershift.openshift.io/v1beta1
    kind: NodePool
    metadata:
      name: <hosted_cluster_name>
      namespace: <clusters_namespace>
    spec:
      arch: <arch_ppc64le>
      clusterName: <hosted_cluster_name>
      management:
        autoRepair: false
        upgradeType: InPlace
      nodeDrainTimeout: 0s
      nodeVolumeDetachTimeout: 0s
      platform:
        agent:
          agentLabelSelector:
            matchLabels:
              inventory.agent-install.openshift.io/cpu-architecture: <arch_ppc64le> 
    1
    
        type: Agent
      release:
        image: quay.io/openshift-release-dev/ocp-release:<ocp_release>
      replicas: 0
    EOF
    1
    The selector block selects the agents that match the specified label. To create a node pool of architecture ppc64le with zero replicas, specify ppc64le. This ensures that the selector block selects only agents from ppc64le architecture during a scaling operation.

4.7.5.4. DNS configuration for hosted control planes

A Domain Name Service (DNS) configuration for hosted control planes means that external clients can reach ingress controllers, so that the clients can route traffic to internal components. Configuring this setting ensures that traffic gets routed to either a ppc64le or an x86_64 compute node.

You can point an *.apps.<cluster_name> record to either of the compute nodes that hosts the ingress application. Or, if you can set up a load balancer on top of the compute nodes, point the record to this load balancer. When you are creating a heterogeneous node pool, make sure the compute nodes can reach each other or keep them in the same network.

4.7.5.5. Creating infrastructure environment resources

For heterogeneous node pools, you must create an infraEnv custom resource (CR) for each architecture. This configuration ensures that the correct architecture-specific operating system and boot artifacts get used during the node provisioning process. For example, for node pools with x86_64 and ppc64le architectures, create an InfraEnv CR for x86_64 and ppc64le.

Note

Before starting the procedure, ensure that you add the operating system images for both x86_64 and ppc64le architectures to the AgentServiceConfig resource. After this, you can use the InfraEnv resources to get the minimal ISO image.

Procedure

  1. Create the InfraEnv resource with x86_64 architecture for heterogeneous node pools by running the following command:

    $ envsubst <<"EOF" | oc apply -f -
    apiVersion: agent-install.openshift.io/v1beta1
    kind: InfraEnv
    metadata:
      name: <hosted_cluster_name>-<arch_x86> 
    1
     
    2
    
      namespace: <hosted_control_plane_namespace> 
    3
    
    spec:
      cpuArchitecture: <arch_x86>
      pullSecretRef:
        name: pull-secret
      sshAuthorizedKey: <ssh_pub_key> 
    4
    
    EOF
    1
    The hosted cluster name.
    2
    The x86_64 architecture.
    3
    The hosted control plane namespace.
    4
    The SSH public key.
  2. Create the InfraEnv resource with ppc64le architecture for heterogeneous node pools by running the following command:

    envsubst <<"EOF" | oc apply -f -
    apiVersion: agent-install.openshift.io/v1beta1
    kind: InfraEnv
    metadata:
      name: <hosted_cluster_name>-<arch_ppc64le> 
    1
     
    2
    
      namespace: <hosted_control_plane_namespace> 
    3
    
    spec:
      cpuArchitecture: <arch_ppc64le>
      pullSecretRef:
        name: pull-secret
      sshAuthorizedKey: <ssh_pub_key> 
    4
    
    EOF
    1
    The hosted cluster name.
    2
    The ppc64le architecture.
    3
    The hosted control plane namespace.
    4
    The SSH public key.
  3. Verify the successful creation of the InfraEnv resources by running the following commands:

    • Verify the successful creation of the x86_64 InfraEnv resource:

      $ oc describe InfraEnv <hosted_cluster_name>-<arch_x86>
    • Verify the successful creation of the ppc64le InfraEnv resource:

      $ oc describe InfraEnv <hosted_cluster_name>-<arch_ppc64le>
  4. Generate a live ISO that allows either a virtual machine or a bare-metal machine to join as agents by running the following commands:

    1. Generate a live ISO for x86_64:

      $ oc -n <hosted_control_plane_namespace> get InfraEnv <hosted_cluster_name>-<arch_x86> -ojsonpath="{.status.isoDownloadURL}"
    2. Generate a live ISO for ppc64le:

      $ oc -n <hosted_control_plane_namespace> get InfraEnv <hosted_cluster_name>-<arch_ppc64le> -ojsonpath="{.status.isoDownloadURL}"

4.7.5.6. Adding agents to the heterogeneous cluster

You add agents by manually configuring the machine to boot with a live ISO. You can download the live ISO and use it to boot a bare-metal node or a virtual machine. On boot, the node communicates with the assisted-service and registers as an agent in the same namespace as the InfraEnv resource. After the creation of each agent, you can optionally set its installation_disk_id and hostname parameters in the specifications. You can then approve the agent to indicate the agent as ready for use.

Procedure

  1. Obtain a list of agents by running the following command:

    $ oc -n <hosted_control_plane_namespace> get agents

    Example output

    NAME                                   CLUSTER   APPROVED   ROLE          STAGE
    86f7ac75-4fc4-4b36-8130-40fa12602218                        auto-assign
    e57a637f-745b-496e-971d-1abbf03341ba                        auto-assign

  2. Patch an agent by running the following command:

    $ oc -n <hosted_control_plane_namespace> patch agent 86f7ac75-4fc4-4b36-8130-40fa12602218 -p '{"spec":{"installation_disk_id":"/dev/sda","approved":true,"hostname":"worker-0.example.krnl.es"}}' --type merge
  3. Patch the second agent by running the following command:

    $ oc -n <hosted_control_plane_namespace> patch agent 23d0c614-2caa-43f5-b7d3-0b3564688baa -p '{"spec":{"installation_disk_id":"/dev/sda","approved":true,"hostname":"worker-1.example.krnl.es"}}' --type merge
  4. Check the agent approval status by running the following command:

    $ oc -n <hosted_control_plane_namespace> get agents

    Example output

    NAME                                   CLUSTER   APPROVED   ROLE          STAGE
    86f7ac75-4fc4-4b36-8130-40fa12602218             true       auto-assign
    e57a637f-745b-496e-971d-1abbf03341ba             true       auto-assign

4.7.5.7. Scaling the node pool

After you approve your agents, you can scale the node pools. The agentLabelSelector value that you configured in the node pool ensures that only matching agents get added to the cluster. This also helps scale down the node pool. To remove specific architecture nodes from the cluster, scale down the corresponding node pool.

Procedure

  • Scale the node pool by running the following command:

    $ oc -n <clusters_namespace> scale nodepool <nodepool_name> --replicas 2
    Note

    The Cluster API agent provider picks two agents randomly to assign to the hosted cluster. These agents pass through different states and then join the hosted cluster as OpenShift Container Platform nodes. The various agent states are binding, discovering, insufficient, installing, installing-in-progress, and added-to-existing-cluster.

Verification

  1. List the agents by running the following command:

    $ oc -n <hosted_control_plane_namespace> get agent

    Example output

    NAME                                   CLUSTER         APPROVED   ROLE          STAGE
    4dac1ab2-7dd5-4894-a220-6a3473b67ee6   hypercluster1   true       auto-assign
    d9198891-39f4-4930-a679-65fb142b108b                   true       auto-assign
    da503cf1-a347-44f2-875c-4960ddb04091   hypercluster1   true       auto-assign

  2. Check the status of a specific scaled agent by running the following command:

    $ oc -n <hosted_control_plane_namespace> get agent -o jsonpath='{range .items[*]}BMH: {@.metadata.labels.agent-install\.openshift\.io/bmh} Agent: {@.metadata.name} State: {@.status.debugInfo.state}{"\n"}{end}'

    Example output

    BMH: ocp-worker-2 Agent: 4dac1ab2-7dd5-4894-a220-6a3473b67ee6 State: binding
    BMH: ocp-worker-0 Agent: d9198891-39f4-4930-a679-65fb142b108b State: known-unbound
    BMH: ocp-worker-1 Agent: da503cf1-a347-44f2-875c-4960ddb04091 State: insufficient

  3. After the agents reach the added-to-existing-cluster state, verify that the OpenShift Container Platform nodes are ready by running the following command:

    $ oc --kubeconfig <hosted_cluster_name>.kubeconfig get nodes

    Example output

    NAME           STATUS   ROLES    AGE     VERSION
    ocp-worker-1   Ready    worker   5m41s   v1.24.0+3882f8f
    ocp-worker-2   Ready    worker   6m3s    v1.24.0+3882f8f

  4. Adding workloads to the nodes can reconcile some cluster operators. The following command displays the creation of two machines that happened after scaling up the node pool:

    $ oc -n <hosted_control_plane_namespace> get machines

    Example output

    NAME                            CLUSTER               NODENAME       PROVIDERID                                     PHASE     AGE   VERSION
    hypercluster1-c96b6f675-m5vch   hypercluster1-b2qhl   ocp-worker-1   agent://da503cf1-a347-44f2-875c-4960ddb04091   Running   15m   4.11.5
    hypercluster1-c96b6f675-tl42p   hypercluster1-b2qhl   ocp-worker-2   agent://4dac1ab2-7dd5-4894-a220-6a3473b67ee6   Running   15m   4.11.5

4.8. Deploying hosted control planes on OpenStack

Important

Deploying hosted control planes clusters on Red Hat OpenStack Platform (RHOSP) is a Technology Preview feature only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs) and might not be functionally complete. Red Hat does not recommend using them in production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.

For more information about the support scope of Red Hat Technology Preview features, see Technology Preview Features Support Scope.

You can deploy hosted control planes with hosted clusters that run on Red Hat OpenStack Platform (RHOSP) 17.1.

A hosted cluster is an OpenShift Container Platform cluster with its API endpoint and control plane that are hosted on a management cluster. With hosted control planes, control planes exist as pods on a management cluster without the need for dedicated virtual or physical machines for each control plane.

4.8.1. Prerequisites for OpenStack

Before you create a hosted cluster on Red Hat OpenStack Platform (RHOSP), ensure that you meet the following requirements:

  • You have administrative access to a management OpenShift Container Platform cluster version 4.17 or greater. This cluster can run on bare metal, RHOSP, or a supported public cloud.
  • The HyperShift Operator is installed on the management cluster as specified in "Preparing to deploy hosted control planes".
  • The management cluster is configured with OVN-Kubernetes as the default pod network CNI.
  • The OpenShift CLI (oc) and hosted control planes CLI, hcp are installed.
  • A load-balancer backend, for example, Octavia, is installed on the management OCP cluster. The load balancer is required for the kube-api service to be created for each hosted cluster.

    • When ingress is configured with an Octavia load balance, the RHOSP Octavia service is running in the cloud that hosts the guest cluster.
  • A valid pull secret file is present for the quay.io/openshift-release-dev repository.
  • The default external network for the management cluster is reachable from the guest cluster. The kube-apiserver load-balancer type service is created on this network.
  • If you use a pre-defined floating IP address for ingress, you created a DNS record that points to it for the following wildcard domain: *.apps.<cluster_name>.<base_domain>, where:

    • <cluster_name> is the name of the management cluster.
    • <base_domain> is the parent DNS domain under which your cluster’s applications live.

4.8.2. Preparing the management cluster for etcd local storage

In a Hosted Control Plane (HCP) deployment on Red Hat OpenStack Platform (RHOSP), you can improve etcd performance by using local ephemeral storage that is provisioned with the TopoLVM CSI driver instead of relying on the default Cinder-based Persistent Volume Claims (PVCs).

Prerequisites

  • You have access to a management cluster with HyperShift installed.
  • You can create and manage RHOSP flavors and machine sets.
  • You have the oc and openstack CLI tools installed and configured.
  • You are familiar with TopoLVM and Logical Volume Manager (LVM) storage concepts.
  • You installed the LVM Storage Operator on the management cluster. For more information, see "Installing LVM Storage by using the CLI" in the Storage section of the OpenShift Container Platform documentation.

Procedure

  1. Create a Nova flavor with an additional ephemeral disk by using the openstack CLI. For example:

    $ openstack flavor create \
      --id auto \
      --ram 8192 \
      --disk 0 \
      --ephemeral 100 \
      --vcpus 4 \
      --public \
      hcp-etcd-ephemeral
    Note

    Nova automatically attaches the ephemeral disk to the instance and formats it as vfat when a server is created with that flavor.

  2. Create a compute machine set that uses the new flavor. For more information, see "Creating a compute machine set on OpenStack" in the OpenShift Container Platform documentation.
  3. Scale the machine set to meet your requirements. If clusters are deployed for high availability, a minimum of 3 workers must be deployed so the pods can be distributed accordingly.
  4. Label the new worker nodes to identify them for etcd use. For example:

    $ oc label node <node_name> hypershift-capable=true

    This label is arbitrary; you can update it later.

  5. In a file called lvmcluster.yaml, create the following LVMCluster custom resource to the local storage configuration for etcd:

    apiVersion: lvm.topolvm.io/v1alpha1
    kind: LVMCluster
    metadata:
      name: etcd-hcp
      namespace: openshift-storage
    spec:
      storage:
        deviceClasses:
        - name: etcd-class
          default: true
          nodeSelector:
             nodeSelectorTerms:
             - matchExpressions:
               - key: hypershift-capable
                operator: In
                values:
                - "true"
          deviceSelector:
            forceWipeDevicesAndDestroyAllData: true
            paths:
            - /dev/vdb

    In this example resource:

    • The ephemeral disk location is /dev/vdb, which is the case in most situations. Verify that this location is true in your case, and note that symlinks are not supported.
    • The parameter forceWipeDevicesAndDestroyAllData is set to a True value because the default Nova ephemeral disk comes formatted in VFAT.
  6. Apply the LVMCluster resource by running the following command:

    oc apply -f lvmcluster.yaml
  7. Verify the LVMCluster resource by running the following command:

    $ oc get lvmcluster -A

    Example output

    NAMESPACE           NAME    STATUS
    openshift-storage   etcd-hcp   Ready

  8. Verify the StorageClass resource by running the following command:

    $ oc get storageclass

    Example output

    NAME                    PROVISIONER               RECLAIMPOLICY   VOLUMEBINDINGMODE     ALLOWVOLUMEEXPANSION   AGE
    lvms-etcd-class         topolvm.io                Delete          WaitForFirstConsumer  true                   23m
    standard-csi (default)  cinder.csi.openstack.org  Delete          WaitForFirstConsumer  true                   56m

You can now deploy a hosted cluster with a performant etcd configuration. The deployment process is described in "Creating a hosted cluster on OpenStack".

4.8.3. Creating a floating IP for ingress

If you want to make ingress available in a hosted cluster without manual intervention, you can create a floating IP address for it in advance.

Prerequisites

  • You have access to the Red Hat OpenStack Platform (RHOSP) cloud.
  • If you use a pre-defined floating IP address for ingress, you created a DNS record that points to it for the following wildcard domain: *.apps.<cluster_name>.<base_domain>, where:

    • <cluster_name> is the name of the management cluster.
    • <base_domain> is the parent DNS domain under which your cluster’s applications live.

Procedure

  • Create a floating IP address by running the following command:

    $ openstack floating ip create <external_network_id>

    where:

    <external_network_id>
    Specifies the ID of the external network.
Note

If you specify a floating IP address by using the --openstack-ingress-floating-ip flag without creating it in advance, the cloud-provider-openstack component attempts to create it automatically. This process only succeeds if the Neutron API policy permits creating a floating IP address with a specific IP address.

4.8.4. Uploading the RHCOS image to OpenStack

If you want to specify the RHCOS image to use when deploying node pools on hosted control planes and Red Hat OpenStack Platform (RHOSP) deployment, upload the image to the RHOSP cloud. If you do not upload the image, the OpenStack Resource Controller (ORC) downloads an image from the OpenShift Container Platform mirror and deletes the image after deletion of the hosted cluster.

Prerequisites

  • You downloaded the RHCOS image from the OpenShift Container Platform mirror.
  • You have access to your RHOSP cloud.

Procedure

  • Upload an RHCOS image to RHOSP by running the following command:

    $ openstack image create --disk-format qcow2 --file <image_file_name> rhcos

    where:

    <image_file_name>
    Specifies the file name of the RHCOS image.

4.8.5. Creating a hosted cluster on OpenStack

You can create a hosted cluster on Red Hat OpenStack Platform (RHOSP) by using the hcp CLI.

Prerequisites

  • You completed all prerequisite steps in "Preparing to deploy hosted control planes".
  • You reviewed "Prerequisites for OpenStack".
  • You completed all steps in "Preparing the management cluster for etcd local storage".
  • You have access to the management cluster.
  • You have access to the RHOSP cloud.

Procedure

  • Create a hosted cluster by running the hcp create command. For example, for a cluster that takes advantage of the performant etcd configuration detailed in "Preparing the management cluster for etcd local storage", enter:

    $ hcp create cluster openstack \
      --name my-hcp-cluster \
      --openstack-node-flavor m1.xlarge \
      --base-domain example.com \
      --pull-secret /path/to/pull-secret.json \
      --release-image quay.io/openshift-release-dev/ocp-release:4.22.0-x86_64 \
      --node-pool-replicas 3 \
      --etcd-storage-class lvms-etcd-class
Note

Many options are available at cluster creation. For RHOSP-specific options, see "Options for creating a Hosted Control Planes cluster on OpenStack". For general options, see the hcp documentation.

Verification

  1. Verify that the hosted cluster is ready by running the following command on it:

    $ oc -n clusters-<cluster_name> get pods

    where:

    <cluster_name>
    Specifies the name of the cluster.

    After several minutes, the output should show that the hosted control plane pods are running.

    Example output

    NAME                                                  READY   STATUS    RESTARTS   AGE
    capi-provider-5cc7b74f47-n5gkr                        1/1     Running   0          3m
    catalog-operator-5f799567b7-fd6jw                     2/2     Running   0          69s
    certified-operators-catalog-784b9899f9-mrp6p          1/1     Running   0          66s
    cluster-api-6bbc867966-l4dwl                          1/1     Running   0          66s
    ...
    ...
    ...
    redhat-operators-catalog-9d5fd4d44-z8qqk              1/1     Running   0

  2. To validate the etcd configuration of the cluster:

    1. Validate the etcd persistent volume claim (PVC) by running the following command:

      $ oc get pvc -A
    2. Inside the hosted control planes etcd pod, confirm the mount path and device by running the following command:

      $ df -h /var/lib
Note

The RHOSP resources that the cluster API provider creates are tagged with the label openshiftClusterID=<infraID>.

You can define additional tags for the resources as values in the HostedCluster.Spec.Platform.OpenStack.Tags field of a YAML manifest that you use to create the hosted cluster. After you scale up the node pool, the tags apply to resources.

You can supply several options to the hcp CLI while deploying a Hosted Control Planes Cluster on Red Hat OpenStack Platform (RHOSP).

Expand
OptionDescriptionRequired

--openstack-ca-cert-file

Path to the OpenStack CA certificate file. If not provided, this will be automatically extracted from the cloud entry in clouds.yaml.

No

--openstack-cloud

Name of the cloud entry in clouds.yaml. The default value is openstack.

No

--openstack-credentials-file

Path to the OpenStack credentials file. If not provided, hcp will search the following directories:

  • The current working directory
  • $HOME/.config/openstack
  • /etc/openstack

No

--openstack-dns-nameservers

List of DNS server addresses that are provided when creating the subnet.

No

--openstack-external-network-id

ID of the OpenStack external network.

No

--openstack-ingress-floating-ip

A floating IP for OpenShift ingress.

No

--openstack-node-additional-port

Additional ports to attach to nodes. Valid values are: network-id, vnic-type, disable-port-security, and address-pairs.

No

--openstack-node-availability-zone

Availability zone for the node pool.

No

--openstack-node-flavor

Flavor for the node pool.

Yes

--openstack-node-image-name

Image name for the node pool.

No

Red Hat logoGithubredditYoutubeTwitter

Aprender

Pruebe, compre y venda

Comunidades

Acerca de Red Hat

Ofrecemos soluciones reforzadas que facilitan a las empresas trabajar en plataformas y entornos, desde el centro de datos central hasta el perímetro de la red.

Hacer que el código abierto sea más inclusivo

Red Hat se compromete a reemplazar el lenguaje problemático en nuestro código, documentación y propiedades web. Para más detalles, consulte el Blog de Red Hat.

Acerca de la documentación de Red Hat

Legal Notice

Theme

© 2026 Red Hat
Volver arriba