Artículo
· 30 mayo, 2025 Lectura de 8 min

VIP en Azure

Si estás ejecutando IRIS en una configuración en mirror para alta disponibilidad (HA) en Azure, la cuestión de proporcionar una Mirror VIP (Virtual IP) es relevante. La Virtual IP ofrece una forma para que los sistemas interactuen con IRIS utilizando una dirección IP. Incluso cuando ocurre un failover, los otros sistemas pueden reconectarse a la misma dirección IP y continuar trabajando.

El problema principal, cuando se despliega en Azure, es que una IRIS VIP tiene el requerimiento de que IRIS sea esencialmente un admin de red, según se indica en la documentación.

Para tener HA, los miembros en mirror de IRIS deben ser desplegados en diferentes zonas de disponibilidad (availability zones o AZ) en una subred (lo que es posible en Azure ya que las subredes pueden abarcar varias zonas). Una de las soluciones puede ser utilizar balanceadores de carga pero, por supuesto, suponen un coste extra, y también necesitarás administrarlos.

En este artículo, quiero proporcionar un modo de configurar una Mirror VIP sin la utilización de balanceadores de carga que se sugiere en la mayoría de las propouestas de arquitectruas de referencia para Azure.

Arquitectura

Architecture

Tenemos una subred activa entre 2 zonas de disponibilidad (simplifico aquí - por supuesto, probablemente tendrás subredes públicas, arbitro en otra AZ, y así sucesivamente, pero esto es un ejemplo de lo mínimo imprescindible para demostrar esta propuesta). El CIDR de la subred es 10.0.0.0/24, lo que significa que las IPs que asigna van de la 10.0.0.1 a 10.0.0.255. Como Azure reserva las primeras 4 direcciones y la última dirección, podemos usar de la 10.0.0.4 a la 10.0.0.254.

Implementaremos ambos, una VIP pública y una privada al mismo tiempo. Si quieres, puedes implementar sólo la VIP privada.

Idea

Las máquinas virtuales en Azure tienen Interfaces de Red. Estos Interfaces de Red tienen Configuraciones IP. La configuración IP es una combinación de IPs Publica y Privada, y se enruta automáticamente a la máquina virtual asociada con la Interfaz de Red. Así que no hay necesidad de actualizar las rutas. Lo que haremos es, durante un evento de failover, borrar la configuración VIP IP del antiguo primario y crearla para un nuevo primario. Todas las operaciones para hacer eso llevan sólo unos 5-20 segundos por VIP Privada, y de 5 segundos a 1 minuto para una combinación de VIP IP Pública/Privada.

Implementando la VIP

  1. Asignar IP Externa para usas como una VIP pública. Salta este paso si sólo quieres una VIP Privada. Si asignas la VIP, debe residir en el mismo grupo de recursos y en la misma región y estar en todas las zonas con primario y backup. Necesitarás un nombre de IP Externa.
  2. Decide el valor de la VIP Privada. Yo utilizaré la última disponible: 10.0.0.254.
  3. En cada VM (Virtual Machine), asigna la dirección de IP de la VIP Privada al interfaz de red eth0:1.
cat << EOFVIP >> /etc/sysconfig/network-scripts/ifcfg-eth0:1
          DEVICE=eth0:1
          ONPARENT=on
          IPADDR=10.0.0.254
          PREFIX=32
          EOFVIP
sudo chmod -x /etc/sysconfig/network-scripts/ifcfg-eth0:1
sudo ifconfig eth0:1 up

Si sólo quieres probar, ejecuta: (pero no sobrevivirá a un reinicio de sistema)

sudo ifconfig eth0:1 10.0.0.254

Dependiendo del SO puede que necesites ejecutar:

ifconfig eth0:1
systemctl restart network
  1. Para cada VM, habilita Identidad asignada al Sistema o Usuario.
  2. Para cada identidad, asigna los permisos para modificar los Interfaces de Red. Para hacer eso crea un rol a medida, el permiso mínimo a establecer en ese caso sería:
{
  "roleName": "custom_nic_write",
  "description": "IRIS Role to assign VIP",
  "assignableScopes": [
    "/subscriptions/{subscriptionid}/resourceGroups/{resourcegroupid}/providers/Microsoft.Network/networkInterfaces/{nicid_primary}",
    "/subscriptions/{subscriptionid}/resourceGroups/{resourcegroupid}/providers/Microsoft.Network/networkInterfaces/{nicid_backup}"
  ],
  "permissions": [
    {
      "actions": [
        "Microsoft.Network/networkInterfaces/write",
        "Microsoft.Network/networkInterfaces/read"
      ],
      "notActions": [],
      "dataActions": [],
      "notDataActions": []
    }
  ]
}

Para entornos de no-producción podría utilizar un rol de sistema de tipo Network Contributor en el grupo de recursos, pero no está recomendado porque el Network Contributor es un rol muy amplio.

  1. Cada interfaz de red en Azure puede tener un conjunto de configuracion de IP. Cuando un miembro actual del mirror se convierte en primario, usaremos un callback de ZMIRROR para borrar una configuración de IP VIP del interfaz de red del otro miembre del miror y crear una configuración de VIP IP que le apunte a él mismo:

Aquí tienes los comandos de Azure CLI para ambos nodos, asumiendo el grupo de recursos rg, la configuración de IP vip, y mi IP Externa my_vip_ip:

az login --identity
az network nic ip-config delete --resource-group rg --name vip --nic-name mirrorb280_z2
az network nic ip-config create --resource-group rg --name vip --nic-name mirrora290_z1 --private-ip-address 10.0.0.254 --public-ip-address my_vip_ip

y:

az login --identity
az network nic ip-config delete --resource-group rg --name vip --nic-name mirrora290_z1
az network nic ip-config create --resource-group rg --name vip --nic-name mirrorb280_z2 --private-ip-address 10.0.0.254 --public-ip-address my_vip_ip

Y el mismo código en una rutina ZMIRROR:

ROUTINE ZMIRROR

NotifyBecomePrimary() PUBLIC {
    #include %occMessages
    set rg = "rg"
    set config = "vip"
    set privateVIP = "10.0.0.254"
    set publicVIP = "my_vip_ip"

    set nic = "mirrora290_z1"
    set otherNIC = "mirrorb280_z2"
    if ##class(SYS.Mirror).DefaultSystemName() [ "MIRRORB" {
        // we are on mirrorb node, swap
        set $lb(nic, otherNIC)=$lb(otherNIC, nic)
    }

    set rc1 = $zf(-100, "/SHELL", "export", "AZURE_CONFIG_DIR=/tmp", "&&", "az", "login", "--identity")
    set rc2 = $zf(-100, "/SHELL", "export", "AZURE_CONFIG_DIR=/tmp", "&&", "az", "network", "nic", "ip-config", "delete", "--resource-group", rg, "--name", config, "--nic-name", otherNIC)
    set rc3 = $zf(-100, "/SHELL", "export", "AZURE_CONFIG_DIR=/tmp", "&&", "az", "network", "nic", "ip-config", "create", "--resource-group", rg, "--name", config, "--nic-name",      nic,  "--private-ip-address", privateVIP, "--public-ip-address", publicVIP)
    quit 1
}

La rutina es la misma para ambos miembros del mirror, nosotros simplemente intercambiamos los nombre de NIC basandonos en el nombre del miembre de mirror actual. Puede que no tengas que hacer export AZURE_CONFIG_DIR=/tmp, pero a veces az intenta escribir credenciales en el directorio home de root, lo que podría fallar. En lugar de /tmp, es mejor utilizar el subdirectorio home del usuario IRIS (o puede que ni siquiera necesites ese nombre de variable, dependiendo de tu configuración).

Y, si quieres utilizar Python Embebido, aquí tienes el código de Azure Python SDK:

from azure.identity import DefaultAzureCredential
from azure.mgmt.network import NetworkManagementClient
from azure.mgmt.network.models import NetworkInterface, NetworkInterfaceIPConfiguration, PublicIPAddress

sub_id = "AZURE_SUBSCRIPTION_ID"
client = NetworkManagementClient(credential=DefaultAzureCredential(), subscription_id=sub_id)

resource_group_name = "rg"
nic_name = "mirrora290_z1"
other_nic_name = "mirrorb280_z2"
public_ip_address_name = "my_vip_ip"
private_ip_address = "10.0.0.254"
vip_configuration_name = "vip"


# remove old VIP configuration
nic: NetworkInterface = client.network_interfaces.get(resource_group_name, other_nic_name)
ip_configurations_old_length = len(nic.ip_configurations)
nic.ip_configurations[:] = [ip_configuration for ip_configuration in nic.ip_configurations if
                            ip_configuration.name != vip_configuration_name]

if ip_configurations_old_length != len(nic.ip_configurations):
    poller = client.network_interfaces.begin_create_or_update(
        resource_group_name,
        other_nic_name,
        nic
    )
    nic_info = poller.result()

# add new VIP configuration
nic: NetworkInterface = client.network_interfaces.get(resource_group_name, nic_name)
ip: PublicIPAddress = client.public_ip_addresses.get(resource_group_name, public_ip_address_name)
vip = NetworkInterfaceIPConfiguration(name=vip_configuration_name,
                                      private_ip_address=private_ip_address,
                                      private_ip_allocation_method="Static",
                                      public_ip_address=ip,
                                      subnet=nic.ip_configurations[0].subnet)
nic.ip_configurations.append(vip)

poller = client.network_interfaces.begin_create_or_update(
    resource_group_name,
    nic_name,
    nic
)
nic_info = poller.result()

Arranque inicial

NotifyBecomePrimary se llama también automáticamente cuando el sistema arranca (tras la reconexión del mirror), pero si quieres que tus entornos sin mirror adquieran una VIP del mismo modo, utiliza ZSTART routine:

SYSTEM() PUBLIC {
  if '$SYSTEM.Mirror.IsMember() {
    do NotifyBecomePrimary^ZMIRROR()
  }
  quit 1
}

Conclusión

¡Y ya estaría! Cambiamos la configuración de la IP para apuntar al mirror Primario cuando ocurre un evento NotifyBecomePrimary.

Comentarios (0)1
Inicie sesión o regístrese para continuar