//Module included in the following assemblies:
// hosted_control_planes/hcp-deploy/hcp-deploy-azure.adoc

:_mod-docs-content-type: PROCEDURE
[id="hcp-azure-private-hosted_{context}"]
= Creating a private {azure-short} hosted cluster

[role="_abstract"]
Create a private hosted cluster to ensure that the communication between compute nodes and the hosted control plane occurs over {azure-short} Private Link.

.Prerequisites

* You configured a subnet, as described in "Preparing a subnet for a private hosted cluster on {azure-short}".

* You installed the HyperShift Operator on an {product-title} management cluster on {azure-short}, 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

. Create the private hosted cluster by entering the following command:
+
[source,terminal]
----
$ 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-short} 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

. Check the Private Link resources by entering the following command:
+
[source,terminal]
----
$ oc get azureprivatelinkservices -n clusters-${CLUSTER_NAME}
----

. Check the status and connections by entering the following command:
+
[source,terminal]
----
$ oc get azureprivatelinkservices -n clusters-${CLUSTER_NAME} -o yaml
----
+
.Setup progress conditions
[cols="2",options="header"]
|===
|Condition |Description

|`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.

|===

. Check the overall cluster status by entering the following command:
+
[source,terminal]
----
$ oc get hostedcluster ${CLUSTER_NAME} -n clusters
----

. Wait for the status by entering the following command:
+
[source,terminal]
----
$ oc wait --for=condition=Available hostedcluster/${CLUSTER_NAME} -n clusters --timeout=30m
----
