Проблемы с сетью Azure Service Fabric IPv6 - PullRequest
0 голосов
/ 29 мая 2018

У нас возникают проблемы при развертывании нашего кластера Service Fabric в Azure, и он обрабатывает трафик как IPv4, так и IPv6.

Мы разрабатываем приложение с мобильными клиентами на iOS и Android, которое взаимодействует с нашим кластером Service Fabric.,Связь состоит как из HTTP-трафика, так и из TCP-сокета.Нам нужно поддерживать IPv6, чтобы Apple приняла приложение в своем App Store.

Мы используем шаблон ARM для развертывания в Azure, так как кажется, что портал не поддерживает настройку балансировщика нагрузки с конфигурацией IPv6 для виртуальной машины.Наборы весов (ref: url ).На связанной странице также указаны другие ограничения поддержки IPv6, например, частные адреса IPv6 не могут быть развернуты в наборах весов VM.Однако в соответствии с этой страницей в предварительном просмотре доступна возможность назначить частный IPv6 для наборов масштабов виртуальной машины (хотя это было последнее обновление 14.07.2017).

Для этого вопроса я пыталсячтобы сделать это как можно более общим, и основывать шаблон ARM на шаблоне, найденном в этого руководства .Шаблон называется "template_original.json" и может быть загружен с здесь .Это базовый шаблон для кластера сервисной фабрики без простоты безопасности.

Я буду связывать весь модифицированный шаблон ARM в нижней части этого поста, но сначала выделю основные модифицированные части.

Публичные адреса IPv4 и IPv6, связанные с балансировщиком нагрузки.Они связаны с их соответствующими внутренними пулами:

"frontendIPConfigurations": [
    {
        "name": "LoadBalancerIPv4Config",
        "properties": {
            "publicIPAddress": {
                "id": "[resourceId('Microsoft.Network/publicIPAddresses',concat(parameters('lbIPv4Name'),'-','0'))]"
            }
        }
    },
    {
        "name": "LoadBalancerIPv6Config",
        "properties": {
            "publicIPAddress": {
                "id": "[resourceId('Microsoft.Network/publicIPAddresses',concat(parameters('lbIPv6Name'),'-','0'))]"
            }
        }
    }
],
"backendAddressPools": [
    {
        "name": "LoadBalancerIPv4BEAddressPool",
        "properties": {}
    },
    {
        "name": "LoadBalancerIPv6BEAddressPool",
        "properties": {}
    }
],

Правила распределения нагрузки для портов внешнего интерфейса на соответствующих общедоступных IP-адресах, как IPv4, так и IPv6.Всего это четыре правила, по два на интерфейсный порт.Я добавил порт 80 для HTTP здесь и порт 5607 для подключения через сокет. Обратите внимание , что я изменил внутренний порт для IPv6-порта 80 на 8081 и IPv6-порт 8507 на 8517.

{
    "name": "AppPortLBRule1Ipv4",
    "properties": {
        "backendAddressPool": {
            "id": "[variables('lbIPv4PoolID0')]"
        },
        "backendPort": "[parameters('loadBalancedAppPort1')]",
        "enableFloatingIP": "false",
        "frontendIPConfiguration": {
            "id": "[variables('lbIPv4Config0')]"
        },
        "frontendPort": "[parameters('loadBalancedAppPort1')]",
        "idleTimeoutInMinutes": "5",
        "probe": {
            "id": "[concat(variables('lbID0'),'/probes/AppPortProbe1')]"
        },
        "protocol": "tcp"
    }
},
{
    "name": "AppPortLBRule1Ipv6",
    "properties": {
        "backendAddressPool": {
            "id": "[variables('lbIPv6PoolID0')]"
        },
        /*"backendPort": "[parameters('loadBalancedAppPort1')]",*/
        "backendPort": 8081,
        "enableFloatingIP": "false",
        "frontendIPConfiguration": {
            "id": "[variables('lbIPv6Config0')]"
        },
        "frontendPort": "[parameters('loadBalancedAppPort1')]",
        /*"idleTimeoutInMinutes": "5",*/
        "probe": {
            "id": "[concat(variables('lbID0'),'/probes/AppPortProbe1')]"
        },
        "protocol": "tcp"
    }
},
{
    "name": "AppPortLBRule2Ipv4",
    "properties": {
        "backendAddressPool": {
            "id": "[variables('lbIPv4PoolID0')]"
        },
        "backendPort": "[parameters('loadBalancedAppPort2')]",
        "enableFloatingIP": "false",
        "frontendIPConfiguration": {
            "id": "[variables('lbIPv4Config0')]"
        },
        "frontendPort": "[parameters('loadBalancedAppPort2')]",
        "idleTimeoutInMinutes": "5",
        "probe": {
            "id": "[concat(variables('lbID0'),'/probes/AppPortProbe2')]"
        },
        "protocol": "tcp"
    }
},
{
    "name": "AppPortLBRule2Ipv6",
    "properties": {
        "backendAddressPool": {
            "id": "[variables('lbIPv6PoolID0')]"
        },
        "backendPort": 8517,
        "enableFloatingIP": "false",
        "frontendIPConfiguration": {
            "id": "[variables('lbIPv6Config0')]"
        },
        "frontendPort": "[parameters('loadBalancedAppPort2')]",
        /*"idleTimeoutInMinutes": "5",*/
        "probe": {
            "id": "[concat(variables('lbID0'),'/probes/AppPortProbe2')]"
        },
        "protocol": "tcp"
    }
}

Также добавлен один зонд на правило балансировки нагрузки, но здесь он опущендля ясности.

Для набора масштабов apiVerison for VM установлено значение "2017-03-30" в соответствии с рекомендацией вышеупомянутого решения для предварительного просмотра.Конфигурации сетевого интерфейса также настраиваются в соответствии с рекомендациями.

"networkInterfaceConfigurations": [
    {
        "name": "[concat(parameters('nicName'), '-0')]",
        "properties": {
            "ipConfigurations": [
                {
                    "name": "[concat(parameters('nicName'),'-IPv4Config-',0)]",
                    "properties": {
                        "privateIPAddressVersion": "IPv4",
                        "loadBalancerBackendAddressPools": [
                            {
                                "id": "[variables('lbIPv4PoolID0')]"
                            }
                        ],
                        "loadBalancerInboundNatPools": [
                            {
                                "id": "[variables('lbNatPoolID0')]"
                            }
                        ],
                        "subnet": {
                            "id": "[variables('subnet0Ref')]"
                        }
                    }
                },
                {
                    "name": "[concat(parameters('nicName'),'-IPv6Config-',0)]",
                    "properties": {
                        "privateIPAddressVersion": "IPv6",
                        "loadBalancerBackendAddressPools": [
                            {
                                "id": "[variables('lbIPv6PoolID0')]"
                            }
                        ]
                    }
                }
            ],
        "primary": true
        }
    }
]

С помощью этого шаблона я могу успешно развернуть его в Azure.Связь с использованием IPv4 с кластером работает, как и ожидалось, однако я вообще не могу пропустить трафик IPv6.Это одинаково для обоих портов 80 (HTTP) и 5607. (сокет).

При просмотре списка внутренних пулов для балансировщика нагрузки на портале Azure отображается следующее информационное сообщение, которое мне не удалосьнайти любую информацию о.Я не уверен, что это как-то влияет?

Backend pool 'loadbalanceripv6beaddresspool' was removed from Virtual machine scale set 'Node1'. Upgrade all the instances of 'Node1' for this change to apply Node1

сообщение об ошибке балансировщика нагрузки

Я не уверен, почему не могу получить трафик через IPv6.Возможно, что-то пропущено в шаблоне, или какая-то другая ошибка с моей стороны?Если требуется какая-либо дополнительная информация, не стесняйтесь спрашивать.

Вот весь шаблон ARM.Из-за ограничений по длине и длине поста я не встраивал их, но вот ссылка Pastebin на полный шаблон ARM (Обновлено) .

Обновление

Некоторая информация об отладке подключения IPv6.Я попытался слегка изменить шаблон ARM для пересылки трафика IPv6 через порт 80 на внутренний порт 8081 вместо этого.Таким образом, IPv4 равен 80 => 80, а IPv6 80 => 8081.Шаблон ARM был обновлен (см. Ссылку в предыдущем разделе).

На порту 80 я использую Kestrel в качестве веб-сервера без сохранения состояния.У меня есть следующие записи в ServiceManifest.xml:

<Endpoint Protocol="http" Name="ServiceEndpoint1" Type="Input" Port="80" />      
<Endpoint Protocol="http" Name="ServiceEndpoint3" Type="Input" Port="8081" />

Я был немного не уверен, какие именно адреса слушать в Кестреле.Использование FabricRuntime.GetNodeContext (). IPAddressOrFQDN всегда возвращает адрес IPv4.Это то, как мы начинаем.Для отладки этого я в настоящее время получаю все адреса IPv6, и хакодированный хак для порта 8081 мы используем этот адрес.Порт форта 80 использует IPAddress.IPv6Any, однако по умолчанию это всегда IPv4-адрес, возвращаемый FabricRuntime.GetNodeContext (). IPAddressOrFQDN.

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
    var endpoints = Context.CodePackageActivationContext.GetEndpoints()
        .Where(endpoint => endpoint.Protocol == EndpointProtocol.Http ||
                           endpoint.Protocol == EndpointProtocol.Https);

    var strHostName = Dns.GetHostName();
    var ipHostEntry = Dns.GetHostEntry(strHostName);
    var ipv6Addresses = new List<IPAddress>();

    ipv6Addresses.AddRange(ipHostEntry.AddressList.Where(
        ipAddress => ipAddress.AddressFamily == AddressFamily.InterNetworkV6));

    var listeners = new List<ServiceInstanceListener>();

    foreach (var endpoint in endpoints)
    {
        var instanceListener = new ServiceInstanceListener(serviceContext =>
            new KestrelCommunicationListener(
                serviceContext,
                (url, listener) => new WebHostBuilder().
                    UseKestrel(options =>
                    {
                        if (endpoint.Port == 8081 && ipv6Addresses.Count > 0)
                        {
                            // change idx to test different IPv6 addresses found
                            options.Listen(ipv6Addresses[0], endpoint.Port);
                        }
                        else
                        {
                            // always defaults to ipv4 address
                            options.Listen(IPAddress.IPv6Any, endpoint.Port);
                        }
                    }).
                    ConfigureServices(
                        services => services
                            .AddSingleton<StatelessServiceContext>(serviceContext))
                    .UseContentRoot(Directory.GetCurrentDirectory())
                    .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                    .UseStartup<Startup>()
                    .UseUrls(url)
                    .Build()), endpoint.Name);
        listeners.Add(instanceListener);
    }

    return listeners;
}

Здесь показаны конечные точки в обозревателе Service Fabric для одного из узлов: Адреса конечных точек

Что касается прослушивателя сокетов, я также изменил так, чтобы IPv6 переадресовывался на внутренний порт 8517 вместо 8507. Аналогично веб-серверу Kestrel прослушиватель сокетов откроет два прослушивающих экземпляра.по соответствующим адресам с соответствующим портом.

Надеюсь, эта информация поможет.

1 Ответ

0 голосов
/ 31 мая 2018

Оказывается, я сделал очень глупую ошибку, которая полностью моя вина, я забыл проверить, что мой провайдер полностью поддерживает IPv6.Оказывается, это не так!

Тестирование от поставщика с полной поддержкой IPv6 работает должным образом, и я могу получить полное подключение к узлам в кластере Service Fabric.

Здесь - это рабочий шаблон ARM для всех, кому нужен полностью рабочий пример кластера Service Fabric с поддержкой IPv4 и IPv6:

Not allowed to post pastebin links without a accompanied code snippet...

Обновление:

Из-за ограничений по длине шаблон не может быть вставлен в этот поток полностью, однако на странице GitHub Issues для Service Fabric я добавил это.Шаблон ARM публикуется как комментарий в этой теме, он будет доступен дольше, чем ссылка для вставки.Посмотреть здесь .

...