Azure Service Fabric IPv6 网络问题
Azure Service Fabric IPv6 networking issues
我们在将 Service Fabric 群集部署到 Azure 并让它同时处理 IPv4 时遇到问题
和 IPv6 流量。
我们正在开发一个在 iOS 和 Android 上有移动客户端的应用程序,它与
我们的 Service Fabric 集群。通信包括 HTTP 流量和 TCP 套接字通信。
我们需要支持 IPv6 才能让 Apple 在他们的 App Store 中接受该应用程序。
我们正在使用 ARM 模板部署到 Azure,因为该门户似乎不支持配置
具有虚拟机规模集 IPv6 配置的负载均衡器(参考:url)。 linked 页面还说明了其他限制
IPv6 支持,例如私有 IPv6 地址无法部署到 VM 规模集。然而根据
到 this 页面,可以在预览中使用将私有 IPv6 分配给 VM 规模集的可能性
(尽管这是最后更新于 07/14/2017)。
对于这个问题,我尽量保持笼统,并将 ARM 模板基于找到的模板
在 this tutorial。该模板名为 "template_original.json",可从以下网址下载
here。这是服务结构集群的基本模板,为简单起见没有安全性。
我将link在此 post 的底部编辑整个修改后的 ARM 模板,但会突出显示
首先是主要修改部分。
Public 与负载平衡器关联的 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": {}
}
],
各自 public IP 地址(IPv4 和 IPv6)上的前端端口的负载平衡规则。
这总共有四个规则,每个前端端口两个。我在这里为 HTTP 添加了端口 80,为 Socket 连接添加了端口 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"
}
}
还为每个负载均衡规则添加了一个探测,但为清楚起见此处省略。
根据上述预览解决方案的建议,VM 规模集的 apiVerison 设置为“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
load balancer error message
我不确定为什么无法通过 IPv6 传输流量。可能是我有什么事
在模板中遗漏了,还是我的其他错误?如果需要任何其他信息
不要犹豫,问。
这是整个 ARM 模板。由于篇幅和 post 长度的限制我没有嵌入它,但这里有一个 Pastebin link to the full ARM Template (Updated)。
更新
有关调试 IPv6 连接的一些信息。我尝试稍微更改 ARM 模板以将端口 80 上的 IPv6 流量转发到后端端口 8081。所以 IPv4 是 80=>80 和 IPv6 80=>8081。 ARM 模板已更新(请参阅上一节中的 link)。
在端口 80 上,我 运行 Kestrel 作为无状态 Web 服务器。我在 ServiceManifest.xml 中有以下条目:
<Endpoint Protocol="http" Name="ServiceEndpoint1" Type="Input" Port="80" />
<Endpoint Protocol="http" Name="ServiceEndpoint3" Type="Input" Port="8081" />
我有点不确定在 Kestrel 中具体要监听哪些地址。使用 FabricRuntime.GetNodeContext().IPAddressOrFQDN 总是 returns IPv4 地址。这就是我们目前的启动方式。为了调试这个,我目前掌握了所有 IPv6 地址,并且我们使用该地址对端口 8081 进行了硬编码破解。 Fort 端口 80 使用 IPAddress.IPv6Any,但是这始终默认为 FabricRuntime.GetNodeContext().IPAddressOrFQDN.
返回的 IPv4 地址
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 Explorer 中显示的其中一个节点的端点:Endpoint addresses
关于套接字侦听器,我也进行了更改,以便将 IPv6 转发到后端端口 8517 而不是 8507。与 Kestrel Web 服务器类似,套接字侦听器将在具有适当端口的相应地址上打开两个侦听实例。
希望这些信息对您有所帮助。
原来我犯了一个非常愚蠢的错误,完全是我的错,我忘了实际验证我的 ISP 是否完全支持 IPv6。事实证明他们没有!
从具有完整 IPv6 支持的提供商那里进行的测试可以正常工作,我能够完全连接到 Service Fabric 群集中的节点。
Here 是适用于需要支持 IPv4 和 IPv6 的 Service Fabric 集群的完整示例的任何人的工作 ARM 模板:
Not allowed to post pastebin links without a accompanied code snippet...
更新:
由于长度限制,无法将模板完整粘贴到此线程中,但是在 Service Fabric 的 GitHub 问题页面上,我交叉发布了这个。 ARM 模板作为评论发布在该线程中,希望它的可用时间比 pastebin link 长。查看here.
我们在将 Service Fabric 群集部署到 Azure 并让它同时处理 IPv4 时遇到问题 和 IPv6 流量。
我们正在开发一个在 iOS 和 Android 上有移动客户端的应用程序,它与 我们的 Service Fabric 集群。通信包括 HTTP 流量和 TCP 套接字通信。 我们需要支持 IPv6 才能让 Apple 在他们的 App Store 中接受该应用程序。
我们正在使用 ARM 模板部署到 Azure,因为该门户似乎不支持配置 具有虚拟机规模集 IPv6 配置的负载均衡器(参考:url)。 linked 页面还说明了其他限制 IPv6 支持,例如私有 IPv6 地址无法部署到 VM 规模集。然而根据 到 this 页面,可以在预览中使用将私有 IPv6 分配给 VM 规模集的可能性 (尽管这是最后更新于 07/14/2017)。
对于这个问题,我尽量保持笼统,并将 ARM 模板基于找到的模板 在 this tutorial。该模板名为 "template_original.json",可从以下网址下载 here。这是服务结构集群的基本模板,为简单起见没有安全性。
我将link在此 post 的底部编辑整个修改后的 ARM 模板,但会突出显示 首先是主要修改部分。
Public 与负载平衡器关联的 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": {}
}
],
各自 public IP 地址(IPv4 和 IPv6)上的前端端口的负载平衡规则。 这总共有四个规则,每个前端端口两个。我在这里为 HTTP 添加了端口 80,为 Socket 连接添加了端口 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"
}
}
还为每个负载均衡规则添加了一个探测,但为清楚起见此处省略。
根据上述预览解决方案的建议,VM 规模集的 apiVerison 设置为“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
load balancer error message
我不确定为什么无法通过 IPv6 传输流量。可能是我有什么事 在模板中遗漏了,还是我的其他错误?如果需要任何其他信息 不要犹豫,问。
这是整个 ARM 模板。由于篇幅和 post 长度的限制我没有嵌入它,但这里有一个 Pastebin link to the full ARM Template (Updated)。
更新
有关调试 IPv6 连接的一些信息。我尝试稍微更改 ARM 模板以将端口 80 上的 IPv6 流量转发到后端端口 8081。所以 IPv4 是 80=>80 和 IPv6 80=>8081。 ARM 模板已更新(请参阅上一节中的 link)。
在端口 80 上,我 运行 Kestrel 作为无状态 Web 服务器。我在 ServiceManifest.xml 中有以下条目:
<Endpoint Protocol="http" Name="ServiceEndpoint1" Type="Input" Port="80" />
<Endpoint Protocol="http" Name="ServiceEndpoint3" Type="Input" Port="8081" />
我有点不确定在 Kestrel 中具体要监听哪些地址。使用 FabricRuntime.GetNodeContext().IPAddressOrFQDN 总是 returns IPv4 地址。这就是我们目前的启动方式。为了调试这个,我目前掌握了所有 IPv6 地址,并且我们使用该地址对端口 8081 进行了硬编码破解。 Fort 端口 80 使用 IPAddress.IPv6Any,但是这始终默认为 FabricRuntime.GetNodeContext().IPAddressOrFQDN.
返回的 IPv4 地址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 Explorer 中显示的其中一个节点的端点:Endpoint addresses
关于套接字侦听器,我也进行了更改,以便将 IPv6 转发到后端端口 8517 而不是 8507。与 Kestrel Web 服务器类似,套接字侦听器将在具有适当端口的相应地址上打开两个侦听实例。
希望这些信息对您有所帮助。
原来我犯了一个非常愚蠢的错误,完全是我的错,我忘了实际验证我的 ISP 是否完全支持 IPv6。事实证明他们没有!
从具有完整 IPv6 支持的提供商那里进行的测试可以正常工作,我能够完全连接到 Service Fabric 群集中的节点。
Here 是适用于需要支持 IPv4 和 IPv6 的 Service Fabric 集群的完整示例的任何人的工作 ARM 模板:
Not allowed to post pastebin links without a accompanied code snippet...
更新:
由于长度限制,无法将模板完整粘贴到此线程中,但是在 Service Fabric 的 GitHub 问题页面上,我交叉发布了这个。 ARM 模板作为评论发布在该线程中,希望它的可用时间比 pastebin link 长。查看here.