Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Este artigo descreve como criar um cluster Azure Red Hat OpenShift com planos de controlo alojados (HCP) usando o CLI do Azure ou um ficheiro Bicep.
O ficheiro Bicep define todos os recursos Azure necessários para o cluster, incluindo a infraestrutura de rede, identidades geridas, atribuições de funções, configuração do cluster e pool de nós.
Os comandos CLI criam todos os recursos Azure necessários para o cluster, incluindo a infraestrutura de rede, identidades geridas, atribuições de papéis, configuração do cluster e pool de nós.
Pré-requisitos
Prepare seu ambiente
Antes de criar o cluster, verifique se o seu ambiente Azure cumpre os seguintes requisitos.
CLI do Azure (Interface de Linha de Comando da Azure)
Verifique se você está usando a CLI do Azure versão 2.67.0 ou superior.
Usa az --version para verificar a versão instalada.
Para instalar ou atualizar, consulte Install CLI do Azure.
Extensão do CLI ARO HCP
Instale a extensão.
az extension add --name aroVerifique se a extensão está instalada:
az aro hcp -h
Quota de recursos
O Azure Red Hat OpenShift com planos de controlo alojados requer pelo menos 20 núcleos para criar e executar um cluster. A quota de recursos predefinida de uma nova subscrição do Azure não cumpre este requisito. Para solicitar um aumento do seu limite de recursos, consulte a quota Padrão: Aumentar os limites por série de VMs. Verifica se tens quota suficiente para a família de VMs que escolheres entre os tamanhos de VM dos nós de trabalho suportados.
Para verificar a quota atual da família de máquinas virtuais predefinida:
LOCATION=eastus
az vm list-usage -l $LOCATION \
--query "[?contains(name.value, 'standardDSv5Family')]" -o table
Permissões
Precisa de permissões de Colaborador e de Administrador de Acesso de Utilizador, ou permissões de Proprietário, no grupo de recursos ou na subscrição onde cria o cluster. Estas permissões são necessárias para criar o grupo de recursos, a rede virtual, as identidades geridas e as atribuições de funções.
Para mais informações, consulte Verificar as suas permissões.
Registrar provedores de recursos
Registe os seguintes fornecedores de recursos na sua subscrição do Azure:
Microsoft.RedHatOpenShiftMicrosoft.ComputeMicrosoft.StorageMicrosoft.Authorization
Para verificar se um fornecedor de recursos está registado:
az provider list --query "[?namespace=='Microsoft.RedHatOpenShift'].registrationState" \
--output table
Se encontrar algum prestador de recursos que não esteja registado, inscreva-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 mais informações sobre como registar fornecedores de recursos, consulte Registar os fornecedores de recursos.
Definir variáveis de ambiente
Defina as seguintes variáveis de ambiente para definir os nomes dos recursos que cria. Substitui os valores provisórios pelos teus 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 mais informações sobre os requisitos de versão do cluster e do conjunto de nós, consulte as combinações de versões suportadas.
Note
Para uma lista das regiões suportadas, veja Escolher a região do cluster.
Criar um grupo de recursos
Crie um grupo de recursos para armazenar o recurso do cluster, a rede virtual e as identidades geridas.
az group create \
--name "${CUSTOMER_RG_NAME}" \
--subscription "${SUBSCRIPTION_ID}" \
--location "${LOCATION}"
Criar o arquivo Bicep
Crie um arquivo nomeado azuredeploy.bicep com o seguinte conteúdo.
Este modelo Bicep define todos os recursos necessários para implementar um cluster do Azure Red Hat OpenShift com planos de controlo alojados, incluindo o grupo de segurança de rede, a rede virtual, as identidades geridas, as atribuições de funções, o Key Vault, a chave de encriptação do KMS, o cluster e o conjunto de nós.
O modelo implementa um cluster com rede OVN-Kubernetes com intervalos CIDR predefinidos, encriptação etcd gerida pelo cliente, conectividade de saída do balanceador de carga e um único pool de nós com dois Standard_D8s_v6 nós trabalhadores.
Para personalizar a configuração do cluster ou do pool de nós, consulte a referência do ficheiro Bicep.
Note
Se adicionar regras personalizadas ao grupo de segurança de rede (NSG), certifique-se de que o NSG permite o tráfego descrito em Tráfego obrigatório do grupo de segurança de rede.
@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
}
}
Desdobrar o arquivo Bicep
Implemente o modelo 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 como Public para um servidor de API acessível através da Internet, ou como Private para um servidor de API acessível apenas através de uma ligação de rede privada.
Defina ingressType como Public para rotas da aplicação acessíveis a partir da Internet, ou como Private para rotas da aplicação acessíveis apenas através de uma ligação de rede privada.
Defina privateKeyVault como true para restringir o acesso ao Key Vault a um ponto final privado, ou como false para permitir o acesso público. Se definires privateKeyVault como true, o modelo Bicep desativa o acesso público ao Key Vault, implementa os recursos do ponto final privado e define a visibilidade do cofre como Private no cluster.
Defina cryptoRestrictions como FIPS para restringir o cluster a módulos criptográficos validados pelo FIPS, ou None (por defeito) para instalar sem restrições FIPS. Esta configuração é imutável após a criação do cluster.
Note
O plano de controlo está sempre alojado num cluster habilitado por FIPS, independentemente desta configuração. O cryptoRestrictions parâmetro controla se os pools de nós trabalhadores utilizam módulos criptográficos validados por FIPS.
A implementação normalmente demora entre 15 a 20 minutos a ser concluída.
Verificar a implantação
Após o término da implementação, verifique se o cluster e o pool de nós foram criados com sucesso.
Verifique se o cluster foi criado com sucesso.
az aro hcp cluster show \ --name "${CLUSTER_NAME}" \ --resource-group "${CUSTOMER_RG_NAME}" \ --query "properties.provisioningState" \ --output tsvQuando o cluster está pronto, a saída é
Succeeded.Verifique se o pool de nós foi criado com sucesso.
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 está pronto, a saída é
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 da VNet com delegação.
Crie o grupo de segurança de rede (NSG).
Note
Se adicionar regras personalizadas ao NSG, certifique-se de que permite o tráfego descrito em Tráfego de grupo de segurança de rede obrigatório.
az network nsg create \ --name "${CUSTOMER_NSG}" \ --resource-group "${CUSTOMER_RG_NAME}" \ --location "${LOCATION}"Crie a rede virtual com a sub-rede de trabalhadores.
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 do 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 geridas
Crie as identidades geridas atribuídas pelo utilizador para os operadores do cluster e a identidade gerida do serviço. Para uma descrição de cada identidade e do seu propósito, veja Identidades geridas obrigatórias e atribuições de funções.
# 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 os IDs de recursos e IDs principais para as identidades geridas.
# 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ções
Atribuir os papéis Azure necessários a cada identidade gerida. Para uma descrição detalhada de cada identidade e das suas atribuições obrigatórias de funções, veja Identidades geridas e atribuições de funções obrigatórias.
Defina os GUIDs de definição de funções.
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 controlo.
# 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 gerida por 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 encriptação etcd gerida pelo cliente
O Azure Red Hat OpenShift com planos de controlo alojados encripta os dados etcd usando chaves geridas pelo cliente.
Criar a identidade gerida do KMS
Defina variáveis de ambiente para o Key Vault e a chave KMS.
KEYVAULT_NAME="<key-vault-name>" KMS_KEY_NAME="etcd-kms-key"Crie a identidade gerida por KMS.
az identity create --name "${CLUSTER_NAME}-cp-kms" --resource-group "${CUSTOMER_RG_NAME}"Obtenha o ID do recurso e o ID principal para a identidade gerida 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ção do KMS
Atribuir à identidade gerida do serviço o papel de Leitor na identidade gerida do KMS.
az role assignment create --assignee-object-id "${SERVICE_MI_PID}" --assignee-principal-type ServicePrincipal --role "${READER_ROLE}" --scope "${KMS_MI_ID}"
Criar o Key Vault e a chave KMS
Crie um Azure Key Vault com autorização RBAC e uma chave de encriptação RSA de 2048 bits para encriptação etcd gerida pelo cliente.
Cria o Key Vault.
az keyvault create \ --name "${KEYVAULT_NAME}" \ --resource-group "${CUSTOMER_RG_NAME}" \ --location "${LOCATION}" \ --enable-rbac-authorization trueAtribui-te o papel de utilizador do Key Vault Crypto Officer. Esta função concede-lhe permissões para criar a chave de encriptação 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 encriptação KMS.
az keyvault key create \ --vault-name "${KEYVAULT_NAME}" \ --name "${KMS_KEY_NAME}" \ --kty RSA \ --size 2048Compra a versão 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 Utilizador de Criptografia do Key Vault à identidade gerida pelo 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 do Key Vault a um endpoint privado
Se quiser restringir o acesso ao Key Vault a um endpoint privado, crie os seguintes recursos. Se não precisares de um Key Vault privado, salta para Criar o cluster.
Importante
Os passos desta secção configuram o acesso privado apenas no Azure Key Vault. Ao criar o cluster do Azure Red Hat OpenShift com planos de controlo alojados, define também --vault-visibility Private. Ambas as definições têm de corresponder.
Desative o acesso à rede pública no Key Vault.
az keyvault update \ --name "${KEYVAULT_NAME}" \ --resource-group "${CUSTOMER_RG_NAME}" \ --public-network-access DisabledCrie um endpoint 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 ligue-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 endpoint 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 cluster Azure Red Hat OpenShift com planos de controlo alojados usando a infraestrutura de rede, identidades geridas e atribuições de funções que configurou nos passos anteriores.
Note
Para informações sobre todos os parâmetros personalizáveis do cluster, consulte a ajuda de comandos (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 restringiste o Key Vault a um endpoint privado, define --vault-visibility em Private vez dePublic, para que a configuração do teu cluster corresponda à configuração da rede do Azure Key Vault.
Defina --api-visibility como Public para um servidor de API acessível através da Internet, ou como Private para um servidor de API acessível apenas através de uma ligação de rede privada.
Defina --ingress-visibility como Public para rotas da aplicação acessíveis a partir da Internet, ou como Private para rotas da aplicação acessíveis apenas através de uma ligação de rede privada.
A implementação normalmente demora entre 15 a 20 minutos a ser concluída.
Verifique se o cluster foi criado com sucesso.
az aro hcp cluster show \
--name "${CLUSTER_NAME}" \
--resource-group "${CUSTOMER_RG_NAME}" \
--query "properties.provisioningState" \
--output tsv
Quando o cluster está pronto, a saída é Succeeded.
Criar o pool de nós
Crie um pool de nós para adicionar capacidade de computação worker ao seu cluster.
O comando seguinte 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 Planeie a 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 sucesso.
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 está pronto, a saída é Succeeded.
Referência do ficheiro Bicep
O ficheiro Bicep de exemplo implementa um cluster com valores de configuração predefinidos. Esta secção descreve cada recurso e propriedade no ficheiro Bicep que pode personalizar antes de implementar.
Recursos de rede
O ficheiro 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 VNet, e a delegação de sub-rede para a sub-rede de integração VNet. Para dimensionamento das sub-redes, colocação e requisitos NSG, consulte Planear a sua rede de clusters.
Identidades geridas e atribuições de funções
O ficheiro Bicep define uma identidade gerida atribuída pelo utilizador para cada Operador de cluster OpenShift, e atribuições de funções que concedem a cada identidade as permissões de que necessita. Para uma descrição detalhada de cada identidade e das suas atribuições obrigatórias de funções, veja Identidades geridas e atribuições de funções obrigatórias.
Recursos de encriptação Etcd
O ficheiro Bicep inclui os seguintes recursos para encriptação etcd gerida pelo cliente:
-
Identidade gerida KMS - Uma identidade gerida atribuída pelo utilizador para aceder à chave KMS. Esta identidade exige:
- Uma atribuição de papel de utilizador do Key Vault Crypto com âmbito para o Azure Key Vault
- Uma atribuição de papel de Leitor que concede ao serviço acesso à leitura da identidade gerida do serviço em vez da identidade gerida do KMS
- Azure Key Vault - Um Azure Key Vault com autorização RBAC ativada
- Chave de encriptação KMS - Uma chave RSA 2048 criada no Key Vault
Se definir o privateKeyVault parâmetro para true, o ficheiro Bicep também implementa os seguintes recursos para restringir o acesso ao Key Vault a um endpoint privado:
- Um endpoint privado para o Key Vault
- Uma zona DNS privada (
privatelink.vaultcore.azure.net) - Um grupo privado de zona DNS que associa o endpoint privado à zona DNS
- Um link de rede virtual que liga a zona DNS privada à rede virtual do cluster
Propriedades dos recursos do cluster
O recurso do cluster (Microsoft.RedHatOpenShift/hcpOpenShiftClusters) define a configuração do seu cluster.
Para mais informações sobre cada opção de configuração, consulte Escolher as definições do seu cluster permanente.
| Property | Obrigatório | Description |
|---|---|---|
version.id |
Sim | A versão menor do OpenShift para instalar. Por exemplo, 4.20. Para listar as versões disponíveis, consulte Listar versões OpenShift disponíveis. |
version.channelGroup |
Sim | O canal de atualização do OpenShift. A única opção suportada é stable. |
dns.baseDomainPrefix |
No | Um prefixo personalizado para o domínio base do cluster. Comprimento máximo de 15 caracteres. Deve começar com uma letra minúscula, podendo conter apenas letras minúsculas, números e hífens (-). |
network.networkType |
No | O plugin de interface de rede de contentores (CNI). Os valores válidos são OVNKubernetes (por defeito) 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 para serviços. Padrão: 172.30.0.0/16. |
network.machineCidr |
No | Intervalo de endereços IP dos 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 os respetivos pods. Padrão: 23. |
api.visibility |
No | A visibilidade do servidor API. Os valores válidos são Public (por defeito) ou Private. Essa configuração é imutável. |
api.authorizedCidrs |
No | Uma lista de blocos CIDR autorizados (apenas IPv4) autorizados para aceder ao servidor API. Máximo de 500 inscrições. |
ingress.type |
No | O tipo de entrada padrão do cluster. Os valores válidos são Public (por defeito) ou Private. Essa configuração é imutável. |
cryptoRestrictions |
No | Restrições criptográficas para bibliotecas do kernel e do espaço de utilizador. Os valores válidos são None (por defeito) ou FIPS. Quando definido para FIPS, todas as operações criptográficas utilizam módulos validados por FIPS e todos os pools de nós herdam a configuração FIPS. Esta configuração é imutável após a criação do cluster. |
etcd.dataEncryption.keyManagementMode |
Sim | O modo de gestão de chaves de encriptação. O único valor suportado é CustomerManaged. |
etcd.dataEncryption.customerManaged.encryptionType |
Sim | O tipo de encriptação. O único valor suportado é KMS. |
etcd.dataEncryption.customerManaged.kms.vaultName |
Sim | O nome do Azure Key Vault. |
etcd.dataEncryption.customerManaged.kms.visibility |
Sim | Como o seu cluster Azure Red Hat OpenShift com planos de controlo alojados acede ao Key Vault. Os valores válidos são Public ou Private. Se definires isto para Private, também tens de 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 encriptação. |
etcd.dataEncryption.customerManaged.kms.activeKey.version |
Sim | A versão da chave de encriptação. |
clusterImageRegistry.state |
No | O estado do registo interno de imagens. Os valores válidos são Enabled (por defeito) ou Disabled. |
platform.managedResourceGroup |
No | O nome do grupo de recursos gerenciados. Comprimento máximo de 90 caracteres. |
platform.subnetId |
Sim | O ID do recurso Azure da sub-rede de trabalho. |
platform.vnetIntegrationSubnetId |
Sim | O ID de recurso Azure da sub-rede de integração VNet. |
platform.outboundType |
No | O modelo de conectividade de saída. O único valor suportado é loadBalancer. |
platform.networkSecurityGroupId |
Sim | O ID de recurso Azure do grupo de segurança de rede. |
platform.operatorsAuthentication |
Sim | As atribuições de identidade gerida dos operadores do cluster. |
autoscaling.maxNodesTotal |
No | O número máximo de nós que o autoescalador de cluster pode criar. Padrão: 0 (sem limite). |
autoscaling.maxPodGracePeriodSeconds |
No | Número máximo de segundos para o encerramento ordeiro do pod antes da redução. |
autoscaling.maxNodeProvisionTimeSeconds |
No | Número máximo de segundos para o provisionamento de nós. Padrão: 900. |
autoscaling.podPriorityThreshold |
No | O limiar de prioridade abaixo do qual os pods são tratados como melhor esforço pelo autoescalador. Padrão: -10. |
imageDigestMirrors |
No | Entradas espelhadas do digest de imagens que redirecionam imagens de um registo de origem para registos espelhados. Máximo de 240 inscrições. |
nodeDrainTimeoutMinutes |
No | O período de carência padrão para drenagem de nós para todos os pools de nós, em minutos. Alcance: 0 até 10080. Padrão: 0 (sem limite de tempo). |
identity.type |
Sim | O tipo de identidade. Deve ser UserAssigned. |
identity.userAssignedIdentities |
Sim | Um mapa dos IDs de recursos de identidade gerida atribuídos pelo utilizador. |
Propriedades dos recursos 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 partilham a mesma configuração.
| Property | Obrigatório | Description |
|---|---|---|
version.id |
Sim | A versão do patch OpenShift para este pool de nós. Por exemplo, 4.20.8. A versão do node pool deve ser uma versão patch dentro da versão menor do cluster. Para listar as versões disponíveis, consulte Listar versões OpenShift disponíveis. |
version.channelGroup |
Sim | O canal de atualização do OpenShift. A única opção suportada é 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 Listar tamanhos de VM disponíveis. |
platform.subnetId |
Sim | O ID de recurso Azure da subrede. Se não especificares esta propriedade, o conjunto de nós utiliza a sub-rede dos nós de trabalho do cluster. |
platform.osDisk.diskSizeGiB |
No | O tamanho do disco do sistema operativo 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 de recurso Azure de um DiskEncryptionSet para encriptar discos do sistema operativo. |
platform.osDisk.diskType |
No | O tipo de disco do sistema operativo. 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 | Permite encriptação ao nível do host para VMs. Padrão: false. |
replicas |
Conditional | O número de nós. É obrigatório se autoScaling não estiver configurado. |
autoScaling.min |
Conditional | O número mínimo de nós. É obrigatório se replicas não estiver configurado. |
autoScaling.max |
Conditional | O número máximo de nós. É obrigatório se replicas não estiver configurado. |
autoRepair |
No | Permite verificações do estado dos nós. Padrão: true. |
labels |
No | Etiquetas do Kubernetes aplicadas aos nós, sob a forma de um array de pares chave-valor. |
taints |
No | Contaminações de Kubernetes aplicadas a nós. Cada mancha tem um key, value, e effect (NoSchedule, PreferNoSchedule, ou NoExecute). |
nodeDrainTimeoutMinutes |
No | O período de carência para o esvaziamento dos nós deste conjunto de nós, em minutos. Sobrepõe-se ao padrão do cluster. Alcance: 0 até 10080. |
Lista disponível de versões OpenShift
O cluster version.id usa uma versão secundária (por exemplo, 4.20), enquanto o conjunto de nós version.id usa uma versão de correção (por exemplo, 4.20.8).
Para listar as versões OpenShift disponíveis na sua região, execute o seguinte comando:
az aro hcp get-versions --location "${LOCATION}" --output table
Lista de tamanhos de VM disponíveis
A disponibilidade dos tamanhos das VMs depende da região Azure do seu cluster. Para listar os tamanhos das VMs disponíveis na sua região, execute o seguinte comando:
az vm list-sizes --location "${LOCATION}" --output table
Para consultar a lista de tamanhos de máquinas virtuais suportados para os nós de trabalho do Azure Red Hat OpenShift com planos de controlo alojados, consulte Tamanhos de máquinas virtuais suportados. Utilize a lista regional para confirmar que um tamanho suportado está disponível na localização do seu cluster.