I am provisioning a cluster on Azure where I can SSH into each machine using their public IPs. The Terraform file:
provider "azurerm" {
version = "~>2.0"
features {}
}
resource "azurerm_resource_group" "main" {
name = "${var.name}-resources"
location = "eastus2"
}
resource "azurerm_virtual_network" "main" {
name = "${var.name}-network"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
}
resource "azurerm_subnet" "internal" {
name = "internal"
resource_group_name = azurerm_resource_group.main.name
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = ["10.0.2.0/24"]
}
resource "azurerm_network_security_group" "nsg" {
name = "${var.name}NetworkSecurityGroup"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
security_rule {
name = "SSH"
priority = 1001
direction = "Inbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "*"
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
resource "azurerm_public_ip" "publicip" {
name = "${var.name}PublicIP-${count.index}"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
allocation_method = "Dynamic"
count = 1 + var.workers
}
resource "azurerm_network_interface" "main" {
name = "${var.name}-nic-${count.index}"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
count = 1 + var.workers
ip_configuration {
name = "${var.name}NICConfig${count.index}"
subnet_id = azurerm_subnet.internal.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.publicip[count.index].id
}
}
resource "azurerm_network_interface_security_group_association" "main" {
count = 1 + var.workers
network_interface_id = azurerm_network_interface.main[count.index].id
network_security_group_id = azurerm_network_security_group.nsg.id
}
resource "azurerm_linux_virtual_machine" "main" {
name = "${var.name}-${count.index}"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
size = "Standard_D8s_v3"
count = 1 + var.workers
admin_username = "adminuser"
network_interface_ids = [azurerm_network_interface.main[count.index].id]
admin_ssh_key {
username = "adminuser"
public_key = file("~/.ssh/id_rsa.pub")
}
source_image_reference {
publisher = "OpenLogic"
offer = "CentOS"
sku = "7.7"
version = "7.7.2020042900"
}
os_disk {
storage_account_type = "Standard_LRS"
caching = "ReadWrite"
}
}
output "ips" {
value = ["${azurerm_linux_virtual_machine.main.*.public_ip_address}"]
}
However, once I am on the machine, I can see that the virtual machine doesn't have a public IP when running ifconfig
:
Last login: Mon Jul 20 10:14:45 2020 from 78.141.104.252
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.0.2.5 netmask 255.255.255.0 broadcast 10.0.2.255
inet6 fe80::20d:3aff:fe0e:8428 prefixlen 64 scopeid 0x20<link>
ether 00:0d:3a:0e:84:28 txqueuelen 1000 (Ethernet)
RX packets 146462 bytes 156556974 (149.3 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 62320 bytes 12974670 (12.3 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 84 bytes 4400 (4.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 84 bytes 4400 (4.2 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
This is a problem when using kubeadm
on these instances as I need the public IP to be an existing network interface. Is there something I can set in the Terraform file to make this happen? I don't understand why the public IP isn't there if I can SSH into the machine using this public IP.
As answered by Taguada, Azure machines are unaware of their public IPs. To make them aware of it, Azure provides a tutorial.
In my case, on CentOS 7.7, I ran this Ansible script on all of my hosts:
---
- name: Set public IP
gather_facts: No
hosts: all
become: true
tasks:
- name: Set public IP in instance
blockinfile:
path: /etc/sysconfig/network-scripts/ifcfg-eth0:0
block: |
DEVICE=eth0:0
BOOTPROTO=static
ONBOOT=yes
IPADDR={{ ansible_ssh_host }}
NETMASK=255.255.255.0
create: true
- name: restart network
shell: /etc/init.d/network restart
And the machines were then aware of their public IPs.