Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este artigo descreve como criar um Red Hat OpenShift no Azure com o cluster HCP (planos de controle hospedados) usando o CLI do Azure ou um arquivo Bicep.
O arquivo Bicep define todos os recursos de Azure necessários para o cluster, incluindo a infraestrutura de rede, identidades gerenciadas, atribuições de função, configuração de cluster e pool de nós.
Os comandos da CLI criam todos os recursos Azure necessários para o cluster, incluindo a infraestrutura de rede, identidades gerenciadas, atribuições de função, configuração de cluster e pool de nós.
Pré-requisitos
Prepare o seu ambiente
Antes de criar o cluster, verifique se seu ambiente de Azure atende aos requisitos a seguir.
CLI do Azure
Verifique se você está usando a CLI do Azure versão 2.67.0 ou superior.
Use az --version para verificar sua versão instalada.
Para instalar ou atualizar, consulte Instalar CLI do Azure.
Extensão de CLI do ARO HCP
Instale a extensão.
az extension add --name aroVerifique se a extensão foi instalada:
az aro hcp -h
Cota de recursos
Red Hat OpenShift no Azure com planos de controle hospedados requer pelo menos 20 núcleos para criar e executar um cluster. A cota de recursos padrão do Azure para uma nova assinatura do Azure não atende a esse requisito. Para solicitar um aumento no limite de recursos, consulte Cota padrão: aumentar os limites por série de VMs. Verifique se você tenha cota suficiente para a família de VM escolhida na lista de tamanhos de VM compatíveis para nós de trabalho.
Para verificar a cota atual para a família de máquinas virtuais padrão:
LOCATION=eastus
az vm list-usage -l $LOCATION \
--query "[?contains(name.value, 'standardDSv5Family')]" -o table
Permissões
Você precisa de permissões de Colaborador e Administrador de Acesso do Usuário, ou permissões de Proprietário, no grupo de recursos ou na assinatura na qual você cria o cluster. Essas permissões são necessárias para criar o grupo de recursos, a rede virtual, as identidades gerenciadas e as atribuições de função.
Para obter mais informações, consulte Verificar suas permissões.
Registrar os provedores de recursos
Registre os seguintes provedores de recursos em sua assinatura de Azure:
Microsoft.RedHatOpenShiftMicrosoft.ComputeMicrosoft.StorageMicrosoft.Authorization
Para verificar se um provedor de recursos está registrado:
az provider list --query "[?namespace=='Microsoft.RedHatOpenShift'].registrationState" \
--output table
Se você encontrar provedores de recursos que não estejam registrados, registre-os.
az provider register --namespace Microsoft.RedHatOpenShift --wait
az provider register --namespace Microsoft.Compute --wait
az provider register --namespace Microsoft.Storage --wait
az provider register --namespace Microsoft.Authorization --wait
Para obter mais informações sobre como registrar provedores de recursos, consulte Registrar os provedores de recursos.
Definir variáveis de ambiente
Defina as variáveis de ambiente a seguir para definir os nomes dos recursos criados. Substitua os valores de placeholder pelos seus próprios.
# Azure resource location and subscription
LOCATION="<region>"
SUBSCRIPTION_ID="$(az account show --query id --output tsv)"
CUSTOMER_RG_NAME="<resource-group-name>"
# Network resources
CUSTOMER_NSG="<nsg-name>"
CUSTOMER_VNET_NAME="<vnet-name>"
CUSTOMER_VNET_SUBNET1="<worker-subnet-name>"
CUSTOMER_VNET_INTEGRATION_SUBNET_NAME="<vnet-integration-subnet-name>"
# Cluster and node pool
CLUSTER_NAME="<cluster-name>"
MANAGED_RESOURCE_GROUP="${CLUSTER_NAME}-managed-rg"
NP_NAME="<node-pool-name>"
CLUSTER_VERSION="<major.minor>" # Example: 4.22
NP_VERSION="<major.minor.patch>" # Example: 4.22.1
Note
Para obter mais informações sobre os requisitos de versão do cluster e do pool de nós, consulte as combinações de versões compatíveis.
Note
Para obter uma lista das regiões com suporte, consulte Escolher a região do cluster.
Criar um grupo de recursos
Crie um grupo de recursos para manter o recurso de cluster, a rede virtual e as identidades gerenciadas.
az group create \
--name "${CUSTOMER_RG_NAME}" \
--subscription "${SUBSCRIPTION_ID}" \
--location "${LOCATION}"
Criar o arquivo Bicep
Crie um arquivo nomeado azuredeploy.bicep com o conteúdo a seguir.
Esse modelo Bicep define todos os recursos necessários para implantar um cluster do Red Hat OpenShift no Azure com planos de controle hospedados, incluindo o grupo de segurança de rede, a rede virtual, as identidades gerenciadas, as atribuições de funções, o Key Vault, a chave de criptografia KMS, o cluster e o pool de nós.
O modelo implanta um cluster com rede OVN-Kubernetes com intervalos CIDR padrão, criptografia etcd gerenciada pelo cliente, conectividade de saída do balanceador de carga e um único pool de nós com dois Standard_D8s_v6 nós de trabalho.
Para personalizar a configuração do cluster ou do pool de nós, consulte a referência do arquivo Bicep.
Note
Se você adicionar regras personalizadas ao NSG (grupo de segurança de rede), verifique se o NSG permite o tráfego descrito no tráfego de grupo de segurança de rede necessário.
@description('Network Security Group Name')
param customerNsgName string
@description('Virtual Network Name')
param customerVnetName string
@description('Subnet Name')
param customerVnetSubnetName string
@description('Virtual Network Integration Subnet Name')
param customerVirtualNetworkIntegrationSubnetName string
@description('Name of the cluster')
param clusterName string
@description('The cluster managed resource group name')
param managedResourceGroupName string
@description('The name of the node pool')
param nodePoolName string
@description('The OpenShift version for the cluster (X.Y format, e.g. 4.20)')
param clusterVersion string
@description('The OpenShift version for the node pool (X.Y.Z format, e.g. 4.20.8)')
param nodePoolVersion string
@description('Deploy ARO HCP with a private key vault')
param privateKeyVault bool
@description('API server visibility')
@allowed([
'Public'
'Private'
])
param apiVisibility string = 'Public'
@description('Default ingress type')
@allowed([
'Public'
'Private'
])
param ingressType string = 'Public'
@description('Cryptographic restrictions for kernel and userspace libraries (immutable after creation)')
@allowed(['None', 'FIPS'])
param cryptoRestrictions string = 'None'
var etcdEncryptionKeyName = 'etcd-data-kms-encryption-key'
var randomSuffix = toLower(uniqueString(clusterName))
var randomKeyVaultSuffix = toLower(uniqueString(resourceGroup().id))
var customerKeyVaultName string = 'cust-kv-${randomKeyVaultSuffix}'
var addressPrefix = '10.0.0.0/16'
var subnetPrefix = '10.0.0.0/24'
var virtualNetworkIntegrationSubnetPrefix = '10.0.1.0/24'
// Network Security Group
resource customerNsg 'Microsoft.Network/networkSecurityGroups@2023-05-01' = {
name: customerNsgName
location: resourceGroup().location
}
// Virtual network with worker subnet and VNet integration subnet
resource customerVnet 'Microsoft.Network/virtualNetworks@2023-05-01' = {
name: customerVnetName
location: resourceGroup().location
properties: {
addressSpace: {
addressPrefixes: [
addressPrefix
]
}
subnets: [
{
name: customerVnetSubnetName
properties: {
addressPrefix: subnetPrefix
networkSecurityGroup: {
id: customerNsg.id
}
}
}
{
name: customerVirtualNetworkIntegrationSubnetName
properties: {
addressPrefix: virtualNetworkIntegrationSubnetPrefix
networkSecurityGroup: {
id: customerNsg.id
}
delegations: [
{
name: 'aro-hcp-delegation'
properties: {
serviceName: 'Microsoft.RedHatOpenShift/hcpOpenShiftClusters'
}
}
]
}
}
]
}
}
resource subnet 'Microsoft.Network/virtualNetworks/subnets@2022-07-01' existing = {
name: customerVnetSubnetName
parent: customerVnet
}
resource vnetIntegrationSubnet 'Microsoft.Network/virtualNetworks/subnets@2022-07-01' existing = {
name: customerVirtualNetworkIntegrationSubnetName
parent: customerVnet
}
resource customerKeyVault 'Microsoft.KeyVault/vaults@2024-12-01-preview' = {
name: customerKeyVaultName
location: resourceGroup().location
properties: {
enableRbacAuthorization: true
tenantId: subscription().tenantId
publicNetworkAccess: privateKeyVault ? 'Disabled' : 'Enabled'
sku: {
family: 'A'
name: 'standard'
}
}
}
resource etcdEncryptionKey 'Microsoft.KeyVault/vaults/keys@2024-12-01-preview' = {
parent: customerKeyVault
name: 'etcd-data-kms-encryption-key'
properties: {
kty: 'RSA'
keySize: 2048
}
}
resource privateEndpointDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = if (privateKeyVault) {
name: 'privatelink.vaultcore.azure.net'
location: 'global'
properties: {}
dependsOn: [
privateEndpoint
]
}
resource privateEndpoint 'Microsoft.Network/privateEndpoints@2023-09-01' = if (privateKeyVault) {
name: 'kv-private-endpoint'
properties: {
privateLinkServiceConnections: [
{
name: 'kv-private-endpoint'
properties: {
privateLinkServiceId: customerKeyVault.id
groupIds: ['vault']
}
}
]
subnet: {
id: customerVnet.properties.subnets[0].id
}
}
location: resourceGroup().location
}
resource privateEndpointDnsGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2023-09-01' = if (privateKeyVault) {
name: 'kv-private-ep-dns-group'
parent: privateEndpoint
properties: {
privateDnsZoneConfigs: [
{
name: 'config1'
properties: {
privateDnsZoneId: privateEndpointDnsZone.id
}
}
]
}
dependsOn: [
privateDnsZoneVnetLink
]
}
resource privateDnsZoneVnetLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = if (privateKeyVault) {
name: uniqueString('kv-private-dns-zone-link')
parent: privateEndpointDnsZone
location: 'global'
properties: {
registrationEnabled: false
virtualNetwork: {
id: customerVnet.id
}
}
}
//
// Control plane identities
//
// Reader
var readerRoleId = subscriptionResourceId(
'Microsoft.Authorization/roleDefinitions',
'acdd72a7-3385-48ef-bd42-f606fba81ae7'
)
//
// Cluster API Azure managed identity
//
resource clusterApiAzureMi 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
name: '${clusterName}-cp-cluster-api-azure-${randomSuffix}'
location: resourceGroup().location
}
// Azure Red Hat OpenShift with hosted control planes Cluster API Provider
var hcpClusterApiProviderRoleId = subscriptionResourceId(
'Microsoft.Authorization/roleDefinitions',
'88366f10-ed47-4cc0-9fab-c8a06148393e'
)
resource hcpClusterApiProviderRoleVnetAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, clusterApiAzureMi.id, hcpClusterApiProviderRoleId, customerVnet.id)
scope: customerVnet
properties: {
principalId: clusterApiAzureMi.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: hcpClusterApiProviderRoleId
}
}
resource serviceManagedIdentityReaderOnClusterApiAzureMi 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, serviceManagedIdentity.id, readerRoleId, clusterApiAzureMi.id)
scope: clusterApiAzureMi
properties: {
principalId: serviceManagedIdentity.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: readerRoleId
}
}
//
// KMS managed identity
//
resource kmsMi 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
name: '${clusterName}-cp-kms-${randomSuffix}'
location: resourceGroup().location
}
// Key Vault Crypto User
var keyVaultCryptoUserRoleId = subscriptionResourceId(
'Microsoft.Authorization/roleDefinitions',
'12338af0-0e69-4776-bea7-57ae8d297424'
)
resource keyVaultCryptoUserToKeyVaultRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, kmsMi.id, keyVaultCryptoUserRoleId, customerKeyVault.id)
scope: customerKeyVault
properties: {
principalId: kmsMi.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: keyVaultCryptoUserRoleId
}
}
resource serviceManagedIdentityReaderOnKmsMi 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, serviceManagedIdentity.id, readerRoleId, kmsMi.id)
scope: kmsMi
properties: {
principalId: serviceManagedIdentity.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: readerRoleId
}
}
//
// Control plane operator managed identity
//
resource controlPlaneMi 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
name: '${clusterName}-cp-control-plane-${randomSuffix}'
location: resourceGroup().location
}
// Azure Red Hat OpenShift with hosted control planes Control Plane Operator
var hcpControlPlaneOperatorRoleId = subscriptionResourceId(
'Microsoft.Authorization/roleDefinitions',
'fc0c873f-45e9-4d0d-a7d1-585aab30c6ed'
)
resource hcpControlPlaneOperatorVnetRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, controlPlaneMi.id, hcpControlPlaneOperatorRoleId, customerVnet.id)
scope: customerVnet
properties: {
principalId: controlPlaneMi.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: hcpControlPlaneOperatorRoleId
}
}
resource hcpControlPlaneOperatorNsgRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, controlPlaneMi.id, hcpControlPlaneOperatorRoleId, customerNsg.id)
scope: customerNsg
properties: {
principalId: controlPlaneMi.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: hcpControlPlaneOperatorRoleId
}
}
resource serviceManagedIdentityReaderOnControlPlaneMi 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, serviceManagedIdentity.id, readerRoleId, controlPlaneMi.id)
scope: controlPlaneMi
properties: {
principalId: serviceManagedIdentity.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: readerRoleId
}
}
//
// Cloud controller manager managed identity
//
resource cloudControllerManagerMi 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
name: '${clusterName}-cp-cloud-controller-manager-${randomSuffix}'
location: resourceGroup().location
}
// Azure Red Hat OpenShift Cloud Controller Manager
var cloudControllerManagerRoleId = subscriptionResourceId(
'Microsoft.Authorization/roleDefinitions',
'a1f96423-95ce-4224-ab27-4e3dc72facd4'
)
resource cloudControllerManagerRoleNsgAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, cloudControllerManagerMi.id, cloudControllerManagerRoleId, customerNsg.id)
scope: customerNsg
properties: {
principalId: cloudControllerManagerMi.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: cloudControllerManagerRoleId
}
}
resource cloudControllerManagerRoleVnetAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, cloudControllerManagerMi.id, cloudControllerManagerRoleId, customerVnet.id)
scope: customerVnet
properties: {
principalId: cloudControllerManagerMi.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: cloudControllerManagerRoleId
}
}
resource serviceManagedIdentityReaderOnCloudControllerManagerMi 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, serviceManagedIdentity.id, readerRoleId, cloudControllerManagerMi.id)
scope: cloudControllerManagerMi
properties: {
principalId: serviceManagedIdentity.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: readerRoleId
}
}
//
// Ingress managed identity
//
resource ingressMi 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
name: '${clusterName}-cp-ingress-${randomSuffix}'
location: resourceGroup().location
}
// Azure Red Hat OpenShift Cluster Ingress Operator
var ingressOperatorRoleId = subscriptionResourceId(
'Microsoft.Authorization/roleDefinitions',
'0336e1d3-7a87-462b-b6db-342b63f7802c'
)
// Azure Red Hat OpenShift Image Registry Operator
var imageRegistryOperatorRoleId = subscriptionResourceId(
'Microsoft.Authorization/roleDefinitions',
'8b32b316-c2f5-4ddf-b05b-83dacd2d08b5'
)
resource ingressOperatorRoleVnetAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, ingressMi.id, ingressOperatorRoleId, customerVnet.id)
scope: customerVnet
properties: {
principalId: ingressMi.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: ingressOperatorRoleId
}
}
resource serviceManagedIdentityReaderOnIngressMi 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, serviceManagedIdentity.id, readerRoleId, ingressMi.id)
scope: ingressMi
properties: {
principalId: serviceManagedIdentity.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: readerRoleId
}
}
//
// Disk CSI driver managed identity
//
resource diskCsiDriverMi 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
name: '${clusterName}-cp-disk-csi-driver-${randomSuffix}'
location: resourceGroup().location
}
resource serviceManagedIdentityReaderOnDiskCsiDriverMi 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, serviceManagedIdentity.id, readerRoleId, diskCsiDriverMi.id)
scope: diskCsiDriverMi
properties: {
principalId: serviceManagedIdentity.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: readerRoleId
}
}
//
// File CSI driver managed identity
//
resource fileCsiDriverMi 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
name: '${clusterName}-cp-file-csi-driver-${randomSuffix}'
location: resourceGroup().location
}
// Azure Red Hat OpenShift File Storage Operator
var fileStorageOperatorRoleId = subscriptionResourceId(
'Microsoft.Authorization/roleDefinitions',
'0d7aedc0-15fd-4a67-a412-efad370c947e'
)
resource fileStorageOperatorRoleNsgAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, fileCsiDriverMi.id, fileStorageOperatorRoleId, customerNsg.id)
scope: customerNsg
properties: {
principalId: fileCsiDriverMi.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: fileStorageOperatorRoleId
}
}
resource fileStorageOperatorRoleVnetAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, fileCsiDriverMi.id, fileStorageOperatorRoleId, customerVnet.id)
scope: customerVnet
properties: {
principalId: fileCsiDriverMi.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: fileStorageOperatorRoleId
}
}
resource serviceManagedIdentityReaderOnFileCsiDriverMi 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, serviceManagedIdentity.id, readerRoleId, fileCsiDriverMi.id)
scope: fileCsiDriverMi
properties: {
principalId: serviceManagedIdentity.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: readerRoleId
}
}
//
// Image registry managed identity
//
resource imageRegistryMi 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
name: '${clusterName}-cp-image-registry-${randomSuffix}'
location: resourceGroup().location
}
resource serviceManagedIdentityReaderOnImageRegistryMi 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, serviceManagedIdentity.id, readerRoleId, imageRegistryMi.id)
scope: imageRegistryMi
properties: {
principalId: serviceManagedIdentity.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: readerRoleId
}
}
resource imageRegistryOperatorRoleVnetAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, imageRegistryMi.id, imageRegistryOperatorRoleId, customerVnet.id)
scope: customerVnet
properties: {
principalId: imageRegistryMi.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: imageRegistryOperatorRoleId
}
}
//
// Cloud network config managed identity
//
resource cloudNetworkConfigMi 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
name: '${clusterName}-cp-cloud-network-config-${randomSuffix}'
location: resourceGroup().location
}
// Azure Red Hat OpenShift Network Operator
var networkOperatorRoleId = subscriptionResourceId(
'Microsoft.Authorization/roleDefinitions',
'be7a6435-15ae-4171-8f30-4a343eff9e8f'
)
resource networkOperatorRoleVnetAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, cloudNetworkConfigMi.id, networkOperatorRoleId, customerVnet.id)
scope: customerVnet
properties: {
principalId: cloudNetworkConfigMi.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: networkOperatorRoleId
}
}
resource serviceManagedIdentityReaderOnCloudNetworkMi 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, serviceManagedIdentity.id, readerRoleId, cloudNetworkConfigMi.id)
scope: cloudNetworkConfigMi
properties: {
principalId: serviceManagedIdentity.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: readerRoleId
}
}
//
// Data plane identities
//
// Azure Red Hat OpenShift Federated Credential
var federatedCredentialsRoleId = subscriptionResourceId(
'Microsoft.Authorization/roleDefinitions',
'ef318e2a-8334-4a05-9e4a-295a196c6a6e'
)
resource dpDiskCsiDriverMi 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
name: '${clusterName}-dp-disk-csi-driver-${randomSuffix}'
location: resourceGroup().location
}
resource dpDiskCsiDriverMiFederatedCredentialsRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, dpDiskCsiDriverMi.id, federatedCredentialsRoleId)
scope: dpDiskCsiDriverMi
properties: {
principalId: serviceManagedIdentity.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: federatedCredentialsRoleId
}
}
resource dpFileCsiDriverMi 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
name: '${clusterName}-dp-file-csi-driver-${randomSuffix}'
location: resourceGroup().location
}
resource dpFileCsiDriverMiFederatedCredentialsRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, dpFileCsiDriverMi.id, federatedCredentialsRoleId)
scope: dpFileCsiDriverMi
properties: {
principalId: serviceManagedIdentity.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: federatedCredentialsRoleId
}
}
resource dpFileCsiDriverFileStorageOperatorRoleNsgAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, dpFileCsiDriverMi.id, fileStorageOperatorRoleId, customerNsg.id)
scope: customerNsg
properties: {
principalId: dpFileCsiDriverMi.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: fileStorageOperatorRoleId
}
}
resource dpFileCsiDriverFileStorageOperatorRoleVnetAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, dpFileCsiDriverMi.id, fileStorageOperatorRoleId, customerVnet.id)
scope: customerVnet
properties: {
principalId: dpFileCsiDriverMi.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: fileStorageOperatorRoleId
}
}
resource dpImageRegistryMi 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
name: '${clusterName}-dp-image-registry-${randomSuffix}'
location: resourceGroup().location
}
resource dpImageRegistryMiFederatedCredentialsRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, dpImageRegistryMi.id, federatedCredentialsRoleId)
scope: dpImageRegistryMi
properties: {
principalId: serviceManagedIdentity.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: federatedCredentialsRoleId
}
}
resource dpImageRegistryOperatorRoleVnetAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, dpImageRegistryMi.id, imageRegistryOperatorRoleId, customerVnet.id)
scope: customerVnet
properties: {
principalId: dpImageRegistryMi.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: imageRegistryOperatorRoleId
}
}
//
// Service managed identity
//
resource serviceManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
name: '${clusterName}-service-managed-identity-${randomSuffix}'
location: resourceGroup().location
}
// Azure Red Hat OpenShift with hosted control planes Service Managed Identity
var hcpServiceManagedIdentityRoleId = subscriptionResourceId(
'Microsoft.Authorization/roleDefinitions',
'c0ff367d-66d8-445e-917c-583feb0ef0d4'
)
resource serviceManagedIdentityRoleAssignmentVnet 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, serviceManagedIdentity.id, hcpServiceManagedIdentityRoleId, customerVnet.id)
scope: customerVnet
properties: {
principalId: serviceManagedIdentity.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: hcpServiceManagedIdentityRoleId
}
}
resource serviceManagedIdentityRoleAssignmentNSG 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, serviceManagedIdentity.id, hcpServiceManagedIdentityRoleId, customerNsg.id)
scope: customerNsg
properties: {
principalId: serviceManagedIdentity.properties.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: hcpServiceManagedIdentityRoleId
}
}
// Cluster resource
resource hcp 'Microsoft.RedHatOpenShift/hcpOpenShiftClusters@2026-09-01-preview' = {
name: clusterName
location: resourceGroup().location
properties: {
version: {
id: clusterVersion
channelGroup: 'stable'
}
dns: {}
network: {
networkType: 'OVNKubernetes'
podCidr: '10.128.0.0/14'
serviceCidr: '172.30.0.0/16'
machineCidr: '10.0.0.0/16'
hostPrefix: 23
}
etcd: {
dataEncryption: {
keyManagementMode: 'CustomerManaged'
customerManaged: {
encryptionType: 'KMS'
kms: {
activeKey: {
name: etcdEncryptionKeyName
version: last(split(etcdEncryptionKey.properties.keyUriWithVersion, '/'))
}
vaultName: customerKeyVaultName
visibility: privateKeyVault ? 'Private' : 'Public'
}
}
}
}
api: {
visibility: apiVisibility
}
ingress: {
type: ingressType
}
cryptoRestrictions: cryptoRestrictions
clusterImageRegistry: {
state: 'Enabled'
}
platform: {
managedResourceGroup: managedResourceGroupName
subnetId: subnet.id
vnetIntegrationSubnetId: vnetIntegrationSubnet.id
outboundType: 'LoadBalancer'
networkSecurityGroupId: customerNsg.id
operatorsAuthentication: {
userAssignedIdentities: {
controlPlaneOperators: {
'cluster-api-azure': clusterApiAzureMi.id
'control-plane': controlPlaneMi.id
'cloud-controller-manager': cloudControllerManagerMi.id
ingress: ingressMi.id
'disk-csi-driver': diskCsiDriverMi.id
'file-csi-driver': fileCsiDriverMi.id
'image-registry': imageRegistryMi.id
'cloud-network-config': cloudNetworkConfigMi.id
kms: kmsMi.id
}
dataPlaneOperators: {
'disk-csi-driver': dpDiskCsiDriverMi.id
'file-csi-driver': dpFileCsiDriverMi.id
'image-registry': dpImageRegistryMi.id
}
serviceManagedIdentity: serviceManagedIdentity.id
}
}
}
}
identity: {
type: 'UserAssigned'
userAssignedIdentities: {
'${serviceManagedIdentity.id}': {}
'${clusterApiAzureMi.id}': {}
'${controlPlaneMi.id}': {}
'${cloudControllerManagerMi.id}': {}
'${ingressMi.id}': {}
'${diskCsiDriverMi.id}': {}
'${fileCsiDriverMi.id}': {}
'${imageRegistryMi.id}': {}
'${cloudNetworkConfigMi.id}': {}
'${kmsMi.id}': {}
}
}
dependsOn: [
hcpClusterApiProviderRoleVnetAssignment
keyVaultCryptoUserToKeyVaultRoleAssignment
hcpControlPlaneOperatorVnetRoleAssignment
hcpControlPlaneOperatorNsgRoleAssignment
cloudControllerManagerRoleNsgAssignment
cloudControllerManagerRoleVnetAssignment
ingressOperatorRoleVnetAssignment
fileStorageOperatorRoleNsgAssignment
fileStorageOperatorRoleVnetAssignment
networkOperatorRoleVnetAssignment
dpDiskCsiDriverMiFederatedCredentialsRoleAssignment
dpFileCsiDriverMiFederatedCredentialsRoleAssignment
dpImageRegistryMiFederatedCredentialsRoleAssignment
serviceManagedIdentityRoleAssignmentVnet
serviceManagedIdentityRoleAssignmentNSG
dpFileCsiDriverFileStorageOperatorRoleNsgAssignment
dpFileCsiDriverFileStorageOperatorRoleVnetAssignment
imageRegistryOperatorRoleVnetAssignment
dpImageRegistryOperatorRoleVnetAssignment
serviceManagedIdentityReaderOnControlPlaneMi
serviceManagedIdentityReaderOnCloudControllerManagerMi
serviceManagedIdentityReaderOnIngressMi
serviceManagedIdentityReaderOnDiskCsiDriverMi
serviceManagedIdentityReaderOnFileCsiDriverMi
serviceManagedIdentityReaderOnImageRegistryMi
serviceManagedIdentityReaderOnCloudNetworkMi
serviceManagedIdentityReaderOnClusterApiAzureMi
serviceManagedIdentityReaderOnKmsMi
]
}
// Node pool resource
resource nodepool 'Microsoft.RedHatOpenShift/hcpOpenShiftClusters/nodePools@2026-09-01-preview' = {
parent: hcp
name: nodePoolName
location: resourceGroup().location
properties: {
version: {
id: nodePoolVersion
channelGroup: 'stable'
}
platform: {
subnetId: hcp.properties.platform.subnetId
vmSize: 'Standard_D8s_v6'
osDisk: {
sizeGiB: 64
diskStorageAccountType: 'StandardSSD_LRS'
}
}
replicas: 2
}
}
Implante o arquivo Bicep
Implante o modelo de Bicep para criar o cluster e todos os recursos necessários.
az deployment group create \
--name 'aro-hcp' \
--subscription "${SUBSCRIPTION_ID}" \
--resource-group "${CUSTOMER_RG_NAME}" \
--template-file azuredeploy.bicep \
--parameters \
customerNsgName="${CUSTOMER_NSG}" \
customerVnetName="${CUSTOMER_VNET_NAME}" \
customerVirtualNetworkIntegrationSubnetName="${CUSTOMER_VNET_INTEGRATION_SUBNET_NAME}" \
customerVnetSubnetName="${CUSTOMER_VNET_SUBNET1}" \
clusterName="${CLUSTER_NAME}" \
managedResourceGroupName="${MANAGED_RESOURCE_GROUP}" \
nodePoolName="${NP_NAME}" \
clusterVersion="${CLUSTER_VERSION}" \
nodePoolVersion="${NP_VERSION}" \
apiVisibility="<Public-or-Private>" \
ingressType="<Public-or-Private>" \
privateKeyVault=<true-or-false> \
cryptoRestrictions="<None-or-FIPS>"
Defina apiVisibility para um servidor de API acessível pela Internet ou Private para um servidor de API acessível somente por meio de uma conexão de rede Public privada.
Defina ingressType para Public rotas de aplicativo acessíveis à Internet ou Private para rotas de aplicativo acessíveis somente por meio de uma conexão de rede privada.
Defina privateKeyVault como true para restringir o acesso ao Key Vault a um endpoint privado, ou como false para permitir acesso público. Se você definir privateKeyVault como true, o modelo Bicep desabilita o acesso público ao Key Vault, implanta os recursos do ponto de extremidade privado e define a visibilidade do cofre como Private no cluster.
Defina cryptoRestrictions para FIPS restringir o cluster a módulos criptográficos validados por FIPS ou None (padrão) para implantar sem restrições FIPS. Essa configuração é imutável após a criação do cluster.
Note
O plano de controle sempre é hospedado em um cluster habilitado para FIPS, independentemente dessa configuração. O cryptoRestrictions parâmetro controla se os pools de nós de trabalho usam módulos criptográficos validados por FIPS.
A implantação normalmente leva de 15 a 20 minutos para ser concluída.
Verificar a implantação
Após a implantação ser concluída, verifique se o cluster e o pool de nós foram criados com êxito.
Verifique se o cluster foi criado com êxito.
az aro hcp cluster show \ --name "${CLUSTER_NAME}" \ --resource-group "${CUSTOMER_RG_NAME}" \ --query "properties.provisioningState" \ --output tsvQuando o cluster estiver pronto, a saída será
Succeeded.Verifique se o pool de nós foi criado com êxito.
az aro hcp cluster nodepool show \ --cluster-name "${CLUSTER_NAME}" \ --name "${NP_NAME}" \ --resource-group "${CUSTOMER_RG_NAME}" \ --query "properties.provisioningState" \ --output tsvQuando o pool de nós estiver pronto, a saída será
Succeeded.
Criar a infraestrutura de rede
Crie um grupo de segurança de rede, uma rede virtual com uma sub-rede de trabalho e uma sub-rede de integração de VNet com delegação.
Crie o NSG (grupo de segurança de rede).
Note
Se você adicionar regras personalizadas ao NSG, verifique se ele permite o tráfego descrito no tráfego do grupo de segurança de rede necessário.
az network nsg create \ --name "${CUSTOMER_NSG}" \ --resource-group "${CUSTOMER_RG_NAME}" \ --location "${LOCATION}"Crie a rede virtual com a sub-rede de trabalho.
az network vnet create \ --name "${CUSTOMER_VNET_NAME}" \ --resource-group "${CUSTOMER_RG_NAME}" \ --location "${LOCATION}" \ --address-prefixes 10.0.0.0/16 \ --subnet-name "${CUSTOMER_VNET_SUBNET1}" \ --subnet-prefixes 10.0.0.0/24 \ --nsg "${CUSTOMER_NSG}"Crie a sub-rede de integração da VNet com a delegação necessária.
az network vnet subnet create \ --name "${CUSTOMER_VNET_INTEGRATION_SUBNET_NAME}" \ --vnet-name "${CUSTOMER_VNET_NAME}" \ --resource-group "${CUSTOMER_RG_NAME}" \ --address-prefixes 10.0.1.0/24 \ --delegations Microsoft.RedHatOpenShift/hcpOpenShiftClustersObtenha os IDs dos recursos de rede.
NSG_ID=$(az network nsg show \ --name "${CUSTOMER_NSG}" \ --resource-group "${CUSTOMER_RG_NAME}" \ --query id --output tsv) SUBNET_ID=$(az network vnet subnet show \ --name "${CUSTOMER_VNET_SUBNET1}" \ --vnet-name "${CUSTOMER_VNET_NAME}" \ --resource-group "${CUSTOMER_RG_NAME}" \ --query id --output tsv) VNET_ID=$(az network vnet show \ --name "${CUSTOMER_VNET_NAME}" \ --resource-group "${CUSTOMER_RG_NAME}" \ --query id --output tsv) VNET_INTEGRATION_SUBNET_ID=$(az network vnet subnet show \ --name "${CUSTOMER_VNET_INTEGRATION_SUBNET_NAME}" \ --vnet-name "${CUSTOMER_VNET_NAME}" \ --resource-group "${CUSTOMER_RG_NAME}" \ --query id --output tsv)
Criar as identidades gerenciadas
Crie as identidades gerenciadas atribuídas pelo usuário para os operadores de cluster e a identidade gerenciada pelo serviço. Para obter uma descrição de cada identidade e sua finalidade, consulte identidades gerenciadas necessárias e atribuições de função.
# Control plane operator identities
az identity create --name "${CLUSTER_NAME}-cp-cluster-api-azure" --resource-group "${CUSTOMER_RG_NAME}"
az identity create --name "${CLUSTER_NAME}-cp-control-plane" --resource-group "${CUSTOMER_RG_NAME}"
az identity create --name "${CLUSTER_NAME}-cp-cloud-controller-manager" --resource-group "${CUSTOMER_RG_NAME}"
az identity create --name "${CLUSTER_NAME}-cp-ingress" --resource-group "${CUSTOMER_RG_NAME}"
az identity create --name "${CLUSTER_NAME}-cp-disk-csi-driver" --resource-group "${CUSTOMER_RG_NAME}"
az identity create --name "${CLUSTER_NAME}-cp-file-csi-driver" --resource-group "${CUSTOMER_RG_NAME}"
az identity create --name "${CLUSTER_NAME}-cp-image-registry" --resource-group "${CUSTOMER_RG_NAME}"
az identity create --name "${CLUSTER_NAME}-cp-cloud-network-config" --resource-group "${CUSTOMER_RG_NAME}"
# Data plane operator identities
az identity create --name "${CLUSTER_NAME}-dp-disk-csi-driver" --resource-group "${CUSTOMER_RG_NAME}"
az identity create --name "${CLUSTER_NAME}-dp-file-csi-driver" --resource-group "${CUSTOMER_RG_NAME}"
az identity create --name "${CLUSTER_NAME}-dp-image-registry" --resource-group "${CUSTOMER_RG_NAME}"
# Service managed identity
az identity create --name "${CLUSTER_NAME}-service-managed-identity" --resource-group "${CUSTOMER_RG_NAME}"
Obtenha as IDs de recurso e as IDs de entidade de segurança para as identidades gerenciadas.
# Control plane identity resource IDs and principal IDs
CLUSTER_API_AZURE_MI_ID=$(az identity show --name "${CLUSTER_NAME}-cp-cluster-api-azure" --resource-group "${CUSTOMER_RG_NAME}" --query id --output tsv)
CLUSTER_API_AZURE_MI_PID=$(az identity show --name "${CLUSTER_NAME}-cp-cluster-api-azure" --resource-group "${CUSTOMER_RG_NAME}" --query principalId --output tsv)
CONTROL_PLANE_MI_ID=$(az identity show --name "${CLUSTER_NAME}-cp-control-plane" --resource-group "${CUSTOMER_RG_NAME}" --query id --output tsv)
CONTROL_PLANE_MI_PID=$(az identity show --name "${CLUSTER_NAME}-cp-control-plane" --resource-group "${CUSTOMER_RG_NAME}" --query principalId --output tsv)
CLOUD_CONTROLLER_MANAGER_MI_ID=$(az identity show --name "${CLUSTER_NAME}-cp-cloud-controller-manager" --resource-group "${CUSTOMER_RG_NAME}" --query id --output tsv)
CLOUD_CONTROLLER_MANAGER_MI_PID=$(az identity show --name "${CLUSTER_NAME}-cp-cloud-controller-manager" --resource-group "${CUSTOMER_RG_NAME}" --query principalId --output tsv)
INGRESS_MI_ID=$(az identity show --name "${CLUSTER_NAME}-cp-ingress" --resource-group "${CUSTOMER_RG_NAME}" --query id --output tsv)
INGRESS_MI_PID=$(az identity show --name "${CLUSTER_NAME}-cp-ingress" --resource-group "${CUSTOMER_RG_NAME}" --query principalId --output tsv)
DISK_CSI_DRIVER_MI_ID=$(az identity show --name "${CLUSTER_NAME}-cp-disk-csi-driver" --resource-group "${CUSTOMER_RG_NAME}" --query id --output tsv)
FILE_CSI_DRIVER_MI_ID=$(az identity show --name "${CLUSTER_NAME}-cp-file-csi-driver" --resource-group "${CUSTOMER_RG_NAME}" --query id --output tsv)
FILE_CSI_DRIVER_MI_PID=$(az identity show --name "${CLUSTER_NAME}-cp-file-csi-driver" --resource-group "${CUSTOMER_RG_NAME}" --query principalId --output tsv)
IMAGE_REGISTRY_MI_ID=$(az identity show --name "${CLUSTER_NAME}-cp-image-registry" --resource-group "${CUSTOMER_RG_NAME}" --query id --output tsv)
IMAGE_REGISTRY_MI_PID=$(az identity show --name "${CLUSTER_NAME}-cp-image-registry" --resource-group "${CUSTOMER_RG_NAME}" --query principalId --output tsv)
CLOUD_NETWORK_CONFIG_MI_ID=$(az identity show --name "${CLUSTER_NAME}-cp-cloud-network-config" --resource-group "${CUSTOMER_RG_NAME}" --query id --output tsv)
CLOUD_NETWORK_CONFIG_MI_PID=$(az identity show --name "${CLUSTER_NAME}-cp-cloud-network-config" --resource-group "${CUSTOMER_RG_NAME}" --query principalId --output tsv)
# Data plane identity resource IDs and principal IDs
DP_DISK_CSI_DRIVER_MI_ID=$(az identity show --name "${CLUSTER_NAME}-dp-disk-csi-driver" --resource-group "${CUSTOMER_RG_NAME}" --query id --output tsv)
DP_FILE_CSI_DRIVER_MI_ID=$(az identity show --name "${CLUSTER_NAME}-dp-file-csi-driver" --resource-group "${CUSTOMER_RG_NAME}" --query id --output tsv)
DP_FILE_CSI_DRIVER_MI_PID=$(az identity show --name "${CLUSTER_NAME}-dp-file-csi-driver" --resource-group "${CUSTOMER_RG_NAME}" --query principalId --output tsv)
DP_IMAGE_REGISTRY_MI_ID=$(az identity show --name "${CLUSTER_NAME}-dp-image-registry" --resource-group "${CUSTOMER_RG_NAME}" --query id --output tsv)
DP_IMAGE_REGISTRY_MI_PID=$(az identity show --name "${CLUSTER_NAME}-dp-image-registry" --resource-group "${CUSTOMER_RG_NAME}" --query principalId --output tsv)
# Service managed identity resource ID and principal ID
SERVICE_MI_ID=$(az identity show --name "${CLUSTER_NAME}-service-managed-identity" --resource-group "${CUSTOMER_RG_NAME}" --query id --output tsv)
SERVICE_MI_PID=$(az identity show --name "${CLUSTER_NAME}-service-managed-identity" --resource-group "${CUSTOMER_RG_NAME}" --query principalId --output tsv)
Criar as atribuições de função
Atribua as funções de Azure necessárias a cada identidade gerenciada. Para obter uma descrição detalhada de cada identidade e suas atribuições de função necessárias, consulte as identidades gerenciadas necessárias e as atribuições de função.
Defina os GUIDs de definição de função.
READER_ROLE="acdd72a7-3385-48ef-bd42-f606fba81ae7" HCP_CLUSTER_API_PROVIDER_ROLE="88366f10-ed47-4cc0-9fab-c8a06148393e" HCP_CONTROL_PLANE_OPERATOR_ROLE="fc0c873f-45e9-4d0d-a7d1-585aab30c6ed" CLOUD_CONTROLLER_MANAGER_ROLE="a1f96423-95ce-4224-ab27-4e3dc72facd4" INGRESS_OPERATOR_ROLE="0336e1d3-7a87-462b-b6db-342b63f7802c" FILE_STORAGE_OPERATOR_ROLE="0d7aedc0-15fd-4a67-a412-efad370c947e" NETWORK_OPERATOR_ROLE="be7a6435-15ae-4171-8f30-4a343eff9e8f" FEDERATED_CREDENTIAL_ROLE="ef318e2a-8334-4a05-9e4a-295a196c6a6e" HCP_SERVICE_MI_ROLE="c0ff367d-66d8-445e-917c-583feb0ef0d4" IMAGE_REGISTRY_OPERATOR_ROLE="8b32b316-c2f5-4ddf-b05b-83dacd2d08b5"Atribuir funções de operador do plano de controle.
# Cluster API Azure → ARO HCP Cluster API Provider on the VNet az role assignment create --assignee-object-id "${CLUSTER_API_AZURE_MI_PID}" --assignee-principal-type ServicePrincipal --role "${HCP_CLUSTER_API_PROVIDER_ROLE}" --scope "${VNET_ID}" # Control Plane → ARO HCP Control Plane Operator on VNet and NSG az role assignment create --assignee-object-id "${CONTROL_PLANE_MI_PID}" --assignee-principal-type ServicePrincipal --role "${HCP_CONTROL_PLANE_OPERATOR_ROLE}" --scope "${VNET_ID}" az role assignment create --assignee-object-id "${CONTROL_PLANE_MI_PID}" --assignee-principal-type ServicePrincipal --role "${HCP_CONTROL_PLANE_OPERATOR_ROLE}" --scope "${NSG_ID}" # Cloud Controller Manager → ARO Cloud Controller Manager on VNet and NSG az role assignment create --assignee-object-id "${CLOUD_CONTROLLER_MANAGER_MI_PID}" --assignee-principal-type ServicePrincipal --role "${CLOUD_CONTROLLER_MANAGER_ROLE}" --scope "${NSG_ID}" az role assignment create --assignee-object-id "${CLOUD_CONTROLLER_MANAGER_MI_PID}" --assignee-principal-type ServicePrincipal --role "${CLOUD_CONTROLLER_MANAGER_ROLE}" --scope "${VNET_ID}" # Ingress → ARO Cluster Ingress Operator on VNet az role assignment create --assignee-object-id "${INGRESS_MI_PID}" --assignee-principal-type ServicePrincipal --role "${INGRESS_OPERATOR_ROLE}" --scope "${VNET_ID}" # File CSI Driver → ARO File Storage Operator on VNet and NSG az role assignment create --assignee-object-id "${FILE_CSI_DRIVER_MI_PID}" --assignee-principal-type ServicePrincipal --role "${FILE_STORAGE_OPERATOR_ROLE}" --scope "${NSG_ID}" az role assignment create --assignee-object-id "${FILE_CSI_DRIVER_MI_PID}" --assignee-principal-type ServicePrincipal --role "${FILE_STORAGE_OPERATOR_ROLE}" --scope "${VNET_ID}" # Cloud Network Config → ARO Network Operator on VNet az role assignment create --assignee-object-id "${CLOUD_NETWORK_CONFIG_MI_PID}" --assignee-principal-type ServicePrincipal --role "${NETWORK_OPERATOR_ROLE}" --scope "${VNET_ID}" # Image Registry → ARO Image Registry Operator on VNet az role assignment create --assignee-object-id "${IMAGE_REGISTRY_MI_PID}" --assignee-principal-type ServicePrincipal --role "${IMAGE_REGISTRY_OPERATOR_ROLE}" --scope "${VNET_ID}"Atribuir funções de identidade gerenciada do serviço.
# Service MI → ARO HCP Service Managed Identity on VNet and NSG az role assignment create --assignee-object-id "${SERVICE_MI_PID}" --assignee-principal-type ServicePrincipal --role "${HCP_SERVICE_MI_ROLE}" --scope "${VNET_ID}" az role assignment create --assignee-object-id "${SERVICE_MI_PID}" --assignee-principal-type ServicePrincipal --role "${HCP_SERVICE_MI_ROLE}" --scope "${NSG_ID}" # Service MI → Reader on each control plane identity az role assignment create --assignee-object-id "${SERVICE_MI_PID}" --assignee-principal-type ServicePrincipal --role "${READER_ROLE}" --scope "${CLUSTER_API_AZURE_MI_ID}" az role assignment create --assignee-object-id "${SERVICE_MI_PID}" --assignee-principal-type ServicePrincipal --role "${READER_ROLE}" --scope "${CONTROL_PLANE_MI_ID}" az role assignment create --assignee-object-id "${SERVICE_MI_PID}" --assignee-principal-type ServicePrincipal --role "${READER_ROLE}" --scope "${CLOUD_CONTROLLER_MANAGER_MI_ID}" az role assignment create --assignee-object-id "${SERVICE_MI_PID}" --assignee-principal-type ServicePrincipal --role "${READER_ROLE}" --scope "${INGRESS_MI_ID}" az role assignment create --assignee-object-id "${SERVICE_MI_PID}" --assignee-principal-type ServicePrincipal --role "${READER_ROLE}" --scope "${DISK_CSI_DRIVER_MI_ID}" az role assignment create --assignee-object-id "${SERVICE_MI_PID}" --assignee-principal-type ServicePrincipal --role "${READER_ROLE}" --scope "${FILE_CSI_DRIVER_MI_ID}" az role assignment create --assignee-object-id "${SERVICE_MI_PID}" --assignee-principal-type ServicePrincipal --role "${READER_ROLE}" --scope "${IMAGE_REGISTRY_MI_ID}" az role assignment create --assignee-object-id "${SERVICE_MI_PID}" --assignee-principal-type ServicePrincipal --role "${READER_ROLE}" --scope "${CLOUD_NETWORK_CONFIG_MI_ID}"Atribuir funções de operador de plano de dados.
# Service MI → ARO Federated Credential on each data plane identity az role assignment create --assignee-object-id "${SERVICE_MI_PID}" --assignee-principal-type ServicePrincipal --role "${FEDERATED_CREDENTIAL_ROLE}" --scope "${DP_DISK_CSI_DRIVER_MI_ID}" az role assignment create --assignee-object-id "${SERVICE_MI_PID}" --assignee-principal-type ServicePrincipal --role "${FEDERATED_CREDENTIAL_ROLE}" --scope "${DP_FILE_CSI_DRIVER_MI_ID}" az role assignment create --assignee-object-id "${SERVICE_MI_PID}" --assignee-principal-type ServicePrincipal --role "${FEDERATED_CREDENTIAL_ROLE}" --scope "${DP_IMAGE_REGISTRY_MI_ID}" # Data Plane File CSI Driver → ARO File Storage Operator on VNet and NSG az role assignment create --assignee-object-id "${DP_FILE_CSI_DRIVER_MI_PID}" --assignee-principal-type ServicePrincipal --role "${FILE_STORAGE_OPERATOR_ROLE}" --scope "${NSG_ID}" az role assignment create --assignee-object-id "${DP_FILE_CSI_DRIVER_MI_PID}" --assignee-principal-type ServicePrincipal --role "${FILE_STORAGE_OPERATOR_ROLE}" --scope "${VNET_ID}" # Data Plane Image Registry → ARO Image Registry Operator on VNet az role assignment create --assignee-object-id "${DP_IMAGE_REGISTRY_MI_PID}" --assignee-principal-type ServicePrincipal --role "${IMAGE_REGISTRY_OPERATOR_ROLE}" --scope "${VNET_ID}"
Configurar a criptografia gerenciada pelo cliente etcd
Red Hat OpenShift no Azure com planos de controle hospedados criptografa dados etcd usando chaves gerenciadas pelo cliente.
Criar a identidade gerenciada do KMS
Defina variáveis de ambiente para a chave Key Vault e KMS.
KEYVAULT_NAME="<key-vault-name>" KMS_KEY_NAME="etcd-kms-key"Crie a identidade gerenciada do KMS.
az identity create --name "${CLUSTER_NAME}-cp-kms" --resource-group "${CUSTOMER_RG_NAME}"Obtenha o ID do recurso e o ID do principal da identidade gerenciada do KMS.
KMS_MI_ID=$(az identity show --name "${CLUSTER_NAME}-cp-kms" --resource-group "${CUSTOMER_RG_NAME}" --query id --output tsv) KMS_MI_PID=$(az identity show --name "${CLUSTER_NAME}-cp-kms" --resource-group "${CUSTOMER_RG_NAME}" --query principalId --output tsv)
Criar as atribuições de funções do KMS
Atribua à identidade gerenciada do serviço a função Leitor na identidade gerenciada do KMS.
az role assignment create --assignee-object-id "${SERVICE_MI_PID}" --assignee-principal-type ServicePrincipal --role "${READER_ROLE}" --scope "${KMS_MI_ID}"
Criar a chave Key Vault e KMS
Crie um Azure Key Vault com autorização rbac e uma chave de criptografia RSA de 2048 bits para criptografia etcd gerenciada pelo cliente.
Crie o Key Vault.
az keyvault create \ --name "${KEYVAULT_NAME}" \ --resource-group "${CUSTOMER_RG_NAME}" \ --location "${LOCATION}" \ --enable-rbac-authorization trueAtribua a si mesmo a função de usuário do Key Vault Crypto Officer. Essa função concede a você as permissões para criar a chave de criptografia KMS.
az role assignment create \ --role "Key Vault Crypto Officer" \ --assignee "$(az account show --query user.name -o tsv)" \ --scope "$(az keyvault show --name "${KEYVAULT_NAME}" --resource-group "${CUSTOMER_RG_NAME}" --query id -o tsv)"Crie a chave de criptografia KMS.
az keyvault key create \ --vault-name "${KEYVAULT_NAME}" \ --name "${KMS_KEY_NAME}" \ --kty RSA \ --size 2048Obtenha a versão da chave.
KMS_KEY_VERSION=$(az keyvault key show \ --vault-name "${KEYVAULT_NAME}" \ --name "${KMS_KEY_NAME}" \ --query "key.kid" --output tsv | rev | cut -d'/' -f1 | rev)Atribua a função de Usuário de Criptografia do Key Vault à identidade gerenciada do KMS no Key Vault.
KEY_VAULT_CRYPTO_USER_ROLE="12338af0-0e69-4776-bea7-57ae8d297424" KEYVAULT_ID=$(az keyvault show --name "${KEYVAULT_NAME}" --query id --output tsv) az role assignment create \ --assignee-object-id "${KMS_MI_PID}" \ --assignee-principal-type ServicePrincipal \ --role "${KEY_VAULT_CRYPTO_USER_ROLE}" \ --scope "${KEYVAULT_ID}"
(Opcional) Restringir o acesso ao Key Vault a um ponto de extremidade privado
Se você quiser restringir o acesso ao Key Vault a um endpoint privado, crie os recursos a seguir. Se você não precisar de uma Key Vault privada, pule para Criar o cluster.
Importante
As etapas nesta seção configuram o acesso privado somente em Azure Key Vault. Ao criar seu cluster do Red Hat OpenShift no Azure com planos de controle hospedados, também defina --vault-visibility Private. Ambas as configurações devem corresponder.
Desabilite o acesso à rede pública no Key Vault.
az keyvault update \ --name "${KEYVAULT_NAME}" \ --resource-group "${CUSTOMER_RG_NAME}" \ --public-network-access DisabledCrie um ponto de extremidade privado para o Key Vault.
az network private-endpoint create \ --name "kv-private-endpoint" \ --resource-group "${CUSTOMER_RG_NAME}" \ --vnet-name "${CUSTOMER_VNET_NAME}" \ --subnet "${CUSTOMER_VNET_SUBNET1}" \ --private-connection-resource-id "${KEYVAULT_ID}" \ --group-ids vault \ --connection-name "kv-private-endpoint"Crie uma zona DNS privada e vincule-a à rede virtual.
az network private-dns zone create \ --name "privatelink.vaultcore.azure.net" \ --resource-group "${CUSTOMER_RG_NAME}" az network private-dns link vnet create \ --name "kv-private-dns-zone-link" \ --resource-group "${CUSTOMER_RG_NAME}" \ --zone-name "privatelink.vaultcore.azure.net" \ --virtual-network "${CUSTOMER_VNET_NAME}" \ --registration-enabled falseCrie um grupo de zonas DNS para o ponto de extremidade privado.
az network private-endpoint dns-zone-group create \ --name "kv-private-ep-dns-group" \ --resource-group "${CUSTOMER_RG_NAME}" \ --endpoint-name "kv-private-endpoint" \ --private-dns-zone "privatelink.vaultcore.azure.net" \ --zone-name "config1"
Criar o cluster
Crie o Red Hat OpenShift no Azure com o cluster de planos de controle hospedados usando a infraestrutura de rede, as identidades gerenciadas e as atribuições de função configuradas nas etapas anteriores.
Note
Para obter informações sobre todos os parâmetros de cluster personalizáveis, consulte a ajuda de comando (az aro hcp cluster create -h).
Crie o cluster com o seguinte comando:
az aro hcp cluster create \
--name "${CLUSTER_NAME}" \
--resource-group "${CUSTOMER_RG_NAME}" \
--location "${LOCATION}" \
--version "${CLUSTER_VERSION}" \
--channel-group stable \
--subnet-id "${SUBNET_ID}" \
--vnet-integration-subnet-id "${VNET_INTEGRATION_SUBNET_ID}" \
--nsg "${NSG_ID}" \
--managed-resource-group-name "${MANAGED_RESOURCE_GROUP}" \
--kms-vault-name "${KEYVAULT_NAME}" \
--vault-visibility <Public-or-Private> \
--kms-active-key "{name:${KMS_KEY_NAME},version:${KMS_KEY_VERSION}}" \
--api-visibility <Public-or-Private> \
--ingress-visibility <Public-or-Private> \
--assign-service-managed-identity "${SERVICE_MI_ID}" \
--assign-control-plane-operator-identity cluster-api-azure "${CLUSTER_API_AZURE_MI_ID}" \
--assign-control-plane-operator-identity control-plane "${CONTROL_PLANE_MI_ID}" \
--assign-control-plane-operator-identity cloud-controller-manager "${CLOUD_CONTROLLER_MANAGER_MI_ID}" \
--assign-control-plane-operator-identity ingress "${INGRESS_MI_ID}" \
--assign-control-plane-operator-identity disk-csi-driver "${DISK_CSI_DRIVER_MI_ID}" \
--assign-control-plane-operator-identity file-csi-driver "${FILE_CSI_DRIVER_MI_ID}" \
--assign-control-plane-operator-identity image-registry "${IMAGE_REGISTRY_MI_ID}" \
--assign-control-plane-operator-identity cloud-network-config "${CLOUD_NETWORK_CONFIG_MI_ID}" \
--assign-control-plane-operator-identity kms "${KMS_MI_ID}" \
--assign-data-plane-operator-identity disk-csi-driver "${DP_DISK_CSI_DRIVER_MI_ID}" \
--assign-data-plane-operator-identity file-csi-driver "${DP_FILE_CSI_DRIVER_MI_ID}" \
--assign-data-plane-operator-identity image-registry "${DP_IMAGE_REGISTRY_MI_ID}"
Se você restringiu o Key Vault a um ponto de extremidade privado, defina --vault-visibility como Private em vez de Public para que a configuração do cluster corresponda à configuração de rede do Azure Key Vault.
Defina --api-visibility para um servidor de API acessível pela Internet ou Private para um servidor de API acessível somente por meio de uma conexão de rede Public privada.
Defina --ingress-visibility para Public rotas de aplicativo acessíveis à Internet ou Private para rotas de aplicativo acessíveis somente por meio de uma conexão de rede privada.
A implantação normalmente leva de 15 a 20 minutos para ser concluída.
Verifique se o cluster foi criado com êxito.
az aro hcp cluster show \
--name "${CLUSTER_NAME}" \
--resource-group "${CUSTOMER_RG_NAME}" \
--query "properties.provisioningState" \
--output tsv
Quando o cluster estiver pronto, a saída será Succeeded.
Criar o pool de nós
Crie um pool de nós para adicionar capacidade de computação de trabalho ao cluster.
O comando a seguir cria um pool de nós com dois Standard_D8s_v6 nós de trabalho.
Importante
Antes de criar o pool de nós, verifique se as regras NSG permitem o tráfego necessário descrito em Planejar sua rede de cluster. Uma regra Deny correspondente pode impedir que o pool de nós conclua o provisionamento.
az aro hcp cluster nodepool create \
--cluster-name "${CLUSTER_NAME}" \
--name "${NP_NAME}" \
--resource-group "${CUSTOMER_RG_NAME}" \
--replicas 2 \
--vm-size Standard_D8s_v6 \
--version "${NP_VERSION}" \
--channel-group stable
Verifique se o pool de nós foi criado com êxito.
az aro hcp cluster nodepool show \
--cluster-name "${CLUSTER_NAME}" \
--name "${NP_NAME}" \
--resource-group "${CUSTOMER_RG_NAME}" \
--query "properties.provisioningState" \
--output tsv
Quando o pool de nós estiver pronto, a saída será Succeeded.
referência do arquivo Bicep
O arquivo Bicep de exemplo implanta um cluster com valores de configuração padrão. Esta seção descreve cada recurso e propriedade no arquivo Bicep que você pode personalizar antes da implantação.
Recursos de rede
O arquivo Bicep define um grupo de segurança de rede (NSG), uma rede virtual com uma sub-rede de trabalho e uma sub-rede de integração com a VNet, e a delegação da sub-rede de integração com a VNet. Para obter os requisitos de dimensionamento, posicionamento e NSG da sub-rede, consulte Planejar sua rede de cluster.
Identidades gerenciadas e atribuições de função
O arquivo Bicep define uma identidade gerenciada atribuída pelo usuário para cada Operador de cluster do OpenShift e atribuições de função que concedem a cada identidade as permissões necessárias. Para obter uma descrição detalhada de cada identidade e suas atribuições de função necessárias, consulte as identidades gerenciadas necessárias e as atribuições de função.
Recursos de criptografia do etcd
O arquivo Bicep inclui os seguintes recursos para criptografia etcd gerenciada pelo cliente:
-
Identidade gerenciada kms - uma identidade gerenciada atribuída pelo usuário para acessar a chave KMS. Essa identidade requer:
- Uma atribuição da função Key Vault Crypto User no escopo do Azure Key Vault
- Uma atribuição de função de Leitor que concede ao serviço acesso de leitura à identidade gerenciada pelo KMS
- Azure Key Vault – Um Azure Key Vault com autorização RBAC habilitada
- Chave de criptografia KMS – uma chave RSA 2048 criada no Key Vault
Se você definir o privateKeyVault parâmetro como true, o arquivo Bicep também implantará os seguintes recursos para restringir o acesso ao Key Vault a um ponto de extremidade privado:
- Um ponto de extremidade privado para o Key Vault
- Uma zona DNS privada (
privatelink.vaultcore.azure.net) - Um grupo de zonas DNS privadas que associa o ponto de extremidade privado à zona DNS
- Um link de rede virtual que conecta a zona DNS privada à rede virtual do cluster
Propriedades do recurso de cluster
O recurso de cluster (Microsoft.RedHatOpenShift/hcpOpenShiftClusters) define a configuração do cluster.
Para obter mais informações sobre cada opção de configuração, consulte Escolher as configurações permanentes do cluster.
| Propriedade | Obrigatório | Description |
|---|---|---|
version.id |
Sim | A versão menor do OpenShift a ser instalada. Por exemplo, 4.20. Para listar as versões disponíveis, consulte Lista de versões disponíveis do OpenShift. |
version.channelGroup |
Sim | O canal de atualização do OpenShift. A única opção com suporte é stable. |
dns.baseDomainPrefix |
No | Um prefixo personalizado para o nome de domínio base do cluster. Comprimento máximo de 15 caracteres. Deve começar com uma letra minúscula e pode conter apenas letras minúsculas, números e hifens (-). |
network.networkType |
No | O plug-in da Interface de Rede de Contêineres (CNI). Os valores válidos são OVNKubernetes (padrão) ou Other. |
network.podCidr |
No | O intervalo de endereços IP para pods. Padrão: 10.128.0.0/14. |
network.serviceCidr |
No | O intervalo de endereços IP dos serviços. Padrão: 172.30.0.0/16. |
network.machineCidr |
No | O intervalo de endereços IP para nós de computação. Padrão: 10.0.0.0/16. |
network.hostPrefix |
No | O comprimento do prefixo de sub-rede atribuído a cada nó para seus pods. Padrão: 23. |
api.visibility |
No | A visibilidade do servidor de API. Os valores válidos são Public (padrão) ou Private. Essa configuração é imutável. |
api.authorizedCidrs |
No | Uma lista de blocos CIDR autorizados (somente IPv4) permitidos para acessar o servidor de API. Máximo de 500 entradas. |
ingress.type |
No | O tipo de entrada padrão do cluster. Os valores válidos são Public (padrão) ou Private. Essa configuração é imutável. |
cryptoRestrictions |
No | Restrições criptográficas para bibliotecas de kernel e espaço de usuário. Os valores válidos são None (padrão) ou FIPS. Quando configurado como FIPS, todas as operações criptográficas usam módulos validados pelo FIPS, e todos os pools de nós herdam a configuração FIPS. Essa configuração é imutável após a criação do cluster. |
etcd.dataEncryption.keyManagementMode |
Sim | O modo de gerenciamento de chave de criptografia. O único valor com suporte é CustomerManaged. |
etcd.dataEncryption.customerManaged.encryptionType |
Sim | O tipo de criptografia. O único valor com suporte é KMS. |
etcd.dataEncryption.customerManaged.kms.vaultName |
Sim | O nome do Azure Key Vault. |
etcd.dataEncryption.customerManaged.kms.visibility |
Sim | Como o Red Hat OpenShift no Azure com o cluster de planos de controle hospedados atinge a Key Vault. Os valores válidos são Public ou Private. Se você definir isso como Private, também deverá desativar o acesso à rede pública no Key Vault e criar um endpoint privado na rede virtual do cluster. |
etcd.dataEncryption.customerManaged.kms.activeKey.name |
Sim | O nome da chave de criptografia. |
etcd.dataEncryption.customerManaged.kms.activeKey.version |
Sim | A versão da chave de criptografia. |
clusterImageRegistry.state |
No | O estado do registro de imagem interno. Os valores válidos são Enabled (padrão) ou Disabled. |
platform.managedResourceGroup |
No | O nome do grupo de recursos gerenciado. Comprimento máximo de 90 caracteres. |
platform.subnetId |
Sim | A ID de recurso do Azure da sub-rede de trabalho. |
platform.vnetIntegrationSubnetId |
Sim | O ID de recurso Azure da sub-rede de integração do VNet. |
platform.outboundType |
No | O modelo de conectividade de saída. O único valor com suporte é loadBalancer. |
platform.networkSecurityGroupId |
Sim | O ID do recurso do Azure do grupo de segurança de rede. |
platform.operatorsAuthentication |
Sim | As atribuições de identidade gerenciada para os operadores do cluster. |
autoscaling.maxNodesTotal |
No | O número máximo de nós que o dimensionador automático de cluster pode criar. Padrão: 0 (sem limite). |
autoscaling.maxPodGracePeriodSeconds |
No | Número máximo de segundos para o encerramento normal do pod antes da redução de escala. |
autoscaling.maxNodeProvisionTimeSeconds |
No | O tempo máximo em segundos para o provisionamento do nó. Padrão: 900. |
autoscaling.podPriorityThreshold |
No | O limite de prioridade abaixo do qual os pods são tratados como o melhor esforço pelo dimensionador automático. Padrão: -10. |
imageDigestMirrors |
No | Entradas espelhadas de resumo de imagem que redirecionam a imagem são extraídas de um registro de origem para registros espelho. Máximo de 240 entradas. |
nodeDrainTimeoutMinutes |
No | O período de tolerância padrão para a drenagem de nós de todos os pools de nós, em minutos. Intervalo: 0 para 10080. Padrão: 0 (sem limite de tempo). |
identity.type |
Sim | O tipo de identidade. Deve ser UserAssigned. |
identity.userAssignedIdentities |
Sim | Um mapa de IDs de recurso de identidade gerenciada atribuídas pelo usuário. |
Propriedades do recurso do pool de nós
O recurso do pool de nós (Microsoft.RedHatOpenShift/hcpOpenShiftClusters/nodePools) define um grupo de nós de trabalho que compartilham a mesma configuração.
| Propriedade | Obrigatório | Description |
|---|---|---|
version.id |
Sim | A versão do patch do OpenShift para este pool de nós. Por exemplo, 4.20.8. A versão do pool de nós deve ser uma versão de patch dentro da versão secundária do cluster. Para listar as versões disponíveis, consulte Lista de versões disponíveis do OpenShift. |
version.channelGroup |
Sim | O canal de atualização do OpenShift. A única opção com suporte é stable. |
platform.vmSize |
Sim | O tamanho da máquina virtual do Azure para os nós. Para listar os tamanhos de VM disponíveis, consulte Os tamanhos de VM disponíveis da lista. |
platform.subnetId |
Sim | O ID do recurso do Azure da sub-rede. Se você não especificar essa propriedade, o pool de nós usará a sub-rede de trabalho do cluster. |
platform.osDisk.diskSizeGiB |
No | O tamanho do disco do sistema operacional em GiB. Mínimo: 16. |
platform.osDisk.diskStorageAccountType |
No | O tipo de conta de armazenamento em disco. Os valores válidos são Premium_LRS, StandardSSD_LRS ou Standard_LRS. |
platform.osDisk.encryptionSetId |
No | O ID do recurso do Azure de um DiskEncryptionSet para criptografar discos do sistema operacional. |
platform.osDisk.diskType |
No | O tipo de disco do sistema operacional. Os valores válidos são Managed ou Ephemeral. |
platform.availabilityZone |
No | A zona de disponibilidade do Azure para o pool de nós. |
platform.enableEncryptionAtHost |
No | Habilita a criptografia no nível do host para VMs. Padrão: false. |
replicas |
Condicional | O número de nós. Obrigatório se autoScaling não estiver configurado. |
autoScaling.min |
Condicional | O número mínimo de nós. Obrigatório se replicas não estiver configurado. |
autoScaling.max |
Condicional | O número máximo de nós. Obrigatório se replicas não estiver configurado. |
autoRepair |
No | Habilita verificações de integridade para nós. Padrão: true. |
labels |
No | Rótulos do Kubernetes aplicados a nós, como uma matriz de pares chave-valor. |
taints |
No | Os taints do Kubernetes aplicados aos nós. Cada mancha tem um key, valuee effect (NoSchedule, PreferNoScheduleou NoExecute). |
nodeDrainTimeoutMinutes |
No | O período de tolerância para o esvaziamento do nó deste pool de nós, em minutos. Substitui o padrão do cluster. Intervalo: 0 para 10080. |
Listar versões disponíveis do OpenShift
O cluster version.id usa uma versão secundária (por exemplo, 4.20), enquanto o pool de nós version.id usa uma versão de patch (por exemplo, 4.20.8).
Para listar as versões disponíveis do OpenShift em sua região, execute o seguinte comando:
az aro hcp get-versions --location "${LOCATION}" --output table
Listar tamanhos de VM disponíveis
A disponibilidade de tamanhos de VM depende da região Azure do cluster. Para listar os tamanhos de VM disponíveis em sua região, execute o seguinte comando:
az vm list-sizes --location "${LOCATION}" --output table
Para obter a lista de tamanhos de VM de nó de trabalho compatíveis com o Red Hat OpenShift no Azure com planos de controle hospedados, consulte Tamanhos de máquina virtual compatíveis. Use a lista de regiões para confirmar se há um tamanho com suporte disponível na região em que seu cluster está localizado.