Назначьте статический исходящий IP-адрес экземпляру контейнера Azure
Мне нужно создать настройку, в которой я могу читать и писать во внешнюю базу данных sql из сценария python, находящегося в экземпляре контейнера Azure. Я хочу сделать эту работу, мне нужно назначить статический ip для контейнера.
Поскольку я не могу связать экземпляр контейнера с выделенным IP-адресом, мне пришлось выполнить настройку, использующую следующие ресурсы: виртуальную сеть, шлюз и общедоступный IP-адрес.
Я частично позаимствовал настройку с https://godatadriven.com/blog/azure-container-instance-example/, где настройка выглядит следующим образом:
Я создал конвейер сборки и выпуска dev-ops. Я использую шаблон ARM для создания релиза (ресурсы шаблона ниже):
"resources": [
{
"type": "Microsoft.Network/virtualNetworks",
"name": "[parameters('vnetName')]",
"apiVersion": "2019-07-01",
"location": "[parameters('location')]",
"properties": {
"addressSpace": {
"addressPrefixes": [
"[parameters('vnetAddressPrefix')]"
]
},
"subnets": [
{
"name": "[parameters('subnet2Name')]",
"properties": {
"addressPrefix": "[parameters('subnet2AddressPrefix')]",
"privateEndpointNetworkPolicies": "Enabled",
"privateLinkServiceNetworkPolicies": "Enabled"
}
},
{
"name": "[parameters('subnetName')]",
"properties": {
"addressPrefix": "[parameters('subnetAddressPrefix')]",
"delegations": [
{
"name": "DelegationService",
"properties": {
"serviceName": "Microsoft.ContainerInstance/containerGroups"
}
}
],
"privateEndpointNetworkPolicies": "Enabled",
"privateLinkServiceNetworkPolicies": "Enabled"
}
}
]
}
},
{
"apiVersion": "2018-07-01",
"type": "Microsoft.Network/publicIPAddresses",
"name": "[variables('publicIPAddressName')]",
"location": "[parameters('location')]",
"sku": {
"name": "Standard",
"tier": "Regional"
},
"properties": {
"publicIPAddressVersion": "IPv4",
"publicIPAllocationMethod": "Static",
"idleTimeoutInMinutes": 4,
"dnsSettings": {
"domainNameLabel": "[parameters('dnsName')]"
}
}
},
{
"apiVersion": "2019-08-01",
"name": "[variables('applicationGatewayName')]",
"type": "Microsoft.Network/applicationGateways",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Network/virtualNetworks/', parameters('vnetName'))]",
"[resourceId('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
"[resourceId('Microsoft.ContainerInstance/containerGroups/', parameters('containerInstanceName'))]"
],
"properties": {
"sku": {
"name": "[parameters('skuName')]",
"tier": "Standard_v2",
"capacity": "[variables('capacity')]"
},
"gatewayIPConfigurations": [
{
"name": "appGatewayIpConfig",
"properties": {
"subnet": {
"id": "[variables('subnetRef')]"
}
}
}
],
"frontendIPConfigurations": [
{
"name": "appGatewayFrontendIP",
"properties": {
"privateIPAllocationMethod": "Dynamic",
"PublicIPAddress": {
"id": "[variables('publicIPRef')]"
}
}
}
],
"frontendPorts": [
{
"name": "appGatewayFrontendPort",
"properties": {
"Port": 80
}
}
],
"backendAddressPools": [
{
"name": "appGatewayBackendPool",
"properties": {
"backendAddresses": [
{
"IpAddress": "[parameters('backendIP')]"
}
]
}
}
],
"backendHttpSettingsCollection": [
{
"name": "appGatewayBackendHttpSettings",
"properties": {
"Port": 80,
"Protocol": "Http",
"CookieBasedAffinity": "Disabled"
}
}
],
"httpListeners": [
{
"name": "appGatewayHttpListener",
"properties": {
"FrontendIPConfiguration": {
"Id": "[resourceId('Microsoft.Network/applicationGateways/frontendIPConfigurations', variables('applicationGatewayName'), 'appGatewayFrontendIP')]"
},
"FrontendPort": {
"Id": "[resourceId('Microsoft.Network/applicationGateways/frontendPorts', variables('applicationGatewayName'), 'appGatewayFrontendPort')]"
},
"Protocol": "Http",
"SslCertificate": null
}
}
],
"requestRoutingRules": [
{
"Name": "rule1",
"properties": {
"RuleType": "Basic",
"httpListener": {
"id": "[resourceId('Microsoft.Network/applicationGateways/httpListeners', variables('applicationGatewayName'), 'appGatewayHttpListener')]"
},
"backendAddressPool": {
"id": "[resourceId('Microsoft.Network/applicationGateways/backendAddressPools', variables('applicationGatewayName'), 'appGatewayBackendPool')]"
},
"backendHttpSettings": {
"id": "[resourceId('Microsoft.Network/applicationGateways/backendHttpSettingsCollection', variables('applicationGatewayName'), 'appGatewayBackendHttpSettings')]"
}
}
}
]
}
},
{
"name": "[parameters('networkProfileName')]",
"type": "Microsoft.Network/networkProfiles",
"apiVersion": "2018-07-01",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Network/virtualNetworks', parameters('vnetName'))]"
],
"properties": {
"containerNetworkInterfaceConfigurations": [
{
"name": "[variables('interfaceConfigName')]",
"properties": {
"ipConfigurations": [
{
"name": "[variables('interfaceIpConfig')]",
"properties": {
"subnet": {
"id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('vnetName'), parameters('subnetName'))]"
}
}
}
]
}
}
]
}
},
{
"name": "[parameters('containerInstanceName')]",
"type": "Microsoft.ContainerInstance/containerGroups",
"apiVersion": "2018-10-01",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Network/networkProfiles', parameters('networkProfileName'))]"
],
"properties": {
"containers": [
{
"name": "[parameters('containerName')]",
"properties": {
"image": "[parameters('registryImageUri')]",
"ports": [{
"port": "[variables('port')]"
}],
"resources": {
"requests": {
"cpu": "[variables('cpuCores')]",
"memoryInGb": "[variables('memoryInGb')]"
}
}
}
}
],
"imageRegistryCredentials": [
{
"server": "[parameters('registryLoginServer')]",
"username": "[parameters('registryUserName')]",
"password": "[parameters('registryPassword')]"
}
],
"diagnostics": {
"logAnalytics": {
"workspaceId": "[parameters('LogAnalyticsID')]",
"workspaceKey": "[parameters('LogAnalyticsKEY')]"
}
},
"networkProfile": {
"Id": "[resourceId('Microsoft.Network/networkProfiles', parameters('networkProfileName'))]"
},
"osType": "Linux",
"ipAddress": {
"ports": [{
"protocol": "tcp",
"port": 80
}],
"type": "private",
"ip": "[parameters('backendIP')]"
},
"restartPolicy": "[parameters('restartPolicy')]"
}
}
]
Релиз работает, но когда я запускаю, я пытаюсь запустить экземпляр контейнера, каждый раз он использует другой ip.
Что я делаю не так?
2 ответа
Поскольку вы используете SQL, предоставленный Azure, я бы рекомендовал использовать частную виртуальную сеть, которую предоставляет Azure.
вам следует взглянуть на настройку вашего ACI с частной подсетью https://docs.microsoft.com/en-us/azure/container-instances/container-instances-vnet
а также настройте правило vnet для вашего SQL-сервера
https://docs.microsoft.com/en-us/azure/sql-database/sql-database-vnet-service-endpoint-rule-overview
Virtual network rules are one firewall security feature that controls whether the database server for your single databases and elastic pool in Azure SQL Database or for your databases in Azure Synapse Analytics accepts communications that are sent from particular subnets in virtual networks.
Важно также включить конечную точку службы SQL для SQL в подсети ACI.
Это избавит вас от необходимости управлять белым списком исходящих IP-адресов в вашем брандмауэре SQL.
Судя по тому, что вы сделали, я думаю, вы неправильно понимаете сеть экземпляра контейнера Azure. Тип Public или Private для ACI доступен только для входящего трафика, но не для исходящего. Даже когда вы используете частный тип, экземпляр также может получить доступ к Интернету без каких-либо других ресурсов, но в этом типе вы не можете получить к нему доступ из Интернета.
К сожалению, когда вы используете общедоступный тип, общедоступный IP-адрес для входящего и исходящего может даже не совпадать. А для экземпляра контейнера Azure мы не можем контролировать IP-адрес, который мы можем использовать. Поэтому, если вы хотите использовать статический общедоступный IP-адрес для доступа к базе данных SQL, экземпляр контейнера Azure не подходит, я бы рекомендовал виртуальную машину, она более управляема и уместна.