Configure endereços IP externos estáticos


Pode atribuir endereços IP externos estáticos à sua máquina virtual (VM) e instâncias bare metal. Também pode alterar, listar e libertar endereços IP estáticos para as suas instâncias. Para reservar um endereço IP externo estático, consulte o artigo Reserve um endereço IP externo estático.

Os endereços IP externos podem ser estáticos ou efémeros. Se uma instância precisar de um endereço IP externo fixo que não se altere, faça o seguinte:

  1. Obtenha um endereço IP externo estático. Pode reservar novos endereços IP externos ou promover endereços IP externos efémeros existentes.
  2. Atribua o endereço IP reservado a uma instância existente ou atribua-o quando criar uma nova instância.

Se precisar de um endereço IP estático na sua rede interna do Compute Engine, consulte o artigo Reserve um endereço IP interno estático.

Para obter informações sobre como reservar um endereço IP externo estático ou criar um endereço IP externo global, consulte o artigo Reserve um endereço IP externo estático.

Antes de começar

  • Leia acerca dos endereços IP.
  • Leia acerca das quotas e dos limites para endereços IP externos estáticos.
  • Leia acerca dos preços dos endereços IP externos.
  • Se ainda não o tiver feito, configure a autenticação. A autenticação valida a sua identidade para aceder a Google Cloud serviços e APIs. Para executar código ou exemplos a partir de um ambiente de desenvolvimento local, pode autenticar-se no Compute Engine selecionando uma das seguintes opções:

    Select the tab for how you plan to use the samples on this page:

    Console

    When you use the Google Cloud console to access Google Cloud services and APIs, you don't need to set up authentication.

    gcloud

    1. Instale a CLI Google Cloud. Após a instalação, inicialize a CLI gcloud executando o seguinte comando:

      gcloud init

      Se estiver a usar um fornecedor de identidade (IdP) externo, primeiro tem de iniciar sessão na CLI gcloud com a sua identidade federada.

    2. Set a default region and zone.

    Terraform

    Para usar os exemplos do Terraform nesta página num ambiente de desenvolvimento local, instale e inicialize a CLI gcloud e, em seguida, configure as credenciais predefinidas da aplicação com as suas credenciais de utilizador.

      Instale a CLI Google Cloud.

      Se estiver a usar um fornecedor de identidade (IdP) externo, primeiro tem de iniciar sessão na CLI gcloud com a sua identidade federada.

      If you're using a local shell, then create local authentication credentials for your user account:

      gcloud auth application-default login

      You don't need to do this if you're using Cloud Shell.

      If an authentication error is returned, and you are using an external identity provider (IdP), confirm that you have signed in to the gcloud CLI with your federated identity.

    Para mais informações, consulte Set up authentication for a local development environment.

    REST

    Para usar os exemplos da API REST nesta página num ambiente de desenvolvimento local, usa as credenciais que fornece à CLI gcloud.

      Instale a CLI Google Cloud.

      Se estiver a usar um fornecedor de identidade (IdP) externo, primeiro tem de iniciar sessão na CLI gcloud com a sua identidade federada.

    Para mais informações, consulte o artigo Autenticar para usar REST na Google Cloud documentação de autenticação.

Funções necessárias

Para receber as autorizações de que precisa para configurar e gerir endereços IP estáticos, peça ao seu administrador para lhe conceder as seguintes funções da IAM no seu projeto:

Para mais informações sobre a atribuição de funções, consulte o artigo Faça a gestão do acesso a projetos, pastas e organizações.

Estas funções predefinidas contêm as autorizações necessárias para configurar e gerir endereços IP estáticos. Para ver as autorizações exatas que são necessárias, expanda a secção Autorizações necessárias:

Autorizações necessárias

São necessárias as seguintes autorizações para configurar e gerir endereços IP estáticos:

  • compute.instances.update na instância
  • compute.instances.updateNetworkInterface na instância
  • compute.instances.addAccessConfig na instância
  • compute.instances.deleteAccessConfig na instância
  • compute.networks.list na rede
  • compute.subnetworks.use na sub-rede
  • compute.subnetworks.list na sub-rede
  • Para criar instâncias:
    • compute.instances.create no projeto
    • Para usar uma imagem personalizada para criar a VM: compute.images.useReadOnly na imagem
    • Para usar um instantâneo para criar a VM: compute.snapshots.useReadOnly no instantâneo
    • Para usar um modelo de instância para criar a VM: compute.instanceTemplates.useReadOnly no modelo de instância
    • Para atribuir uma rede antiga à VM: compute.networks.use no projeto
    • Para especificar um endereço IP estático para a VM: compute.addresses.use no projeto
    • Para atribuir um endereço IP externo à VM quando usar uma rede antiga: compute.networks.useExternalIp no projeto
    • Para especificar uma sub-rede para a VM: compute.subnetworks.use no projeto ou na sub-rede escolhida
    • Para atribuir um endereço IP externo à VM quando usar uma rede VPC: compute.subnetworks.useExternalIp no projeto ou na sub-rede escolhida
    • Para definir os metadados da instância de VM para a VM: compute.instances.setMetadata no projeto
    • Para definir etiquetas para a VM: compute.instances.setTags na VM
    • Para definir etiquetas para a VM: compute.instances.setLabels na VM
    • Para definir uma conta de serviço para a VM usar: compute.instances.setServiceAccount na VM
    • Para criar um novo disco para a VM: compute.disks.create no projeto
    • Para anexar um disco existente no modo de leitura ou leitura/escrita: compute.disks.use no disco
    • Para anexar um disco existente no modo de leitura: compute.disks.useReadOnly no disco

Também pode conseguir estas autorizações com funções personalizadas ou outras funções predefinidas.

Limitações

  • Apenas um recurso de cada vez pode usar um endereço IP externo estático.

  • Não existe forma de verificar se um endereço IP é estático ou efémero depois de ter sido atribuído a um recurso. Pode comparar o endereço IP com a lista de endereços IP externos estáticos reservados para esse projeto. Use o subcomando gcloud compute addresses list para ver uma lista de endereços IP externos estáticos disponíveis para o projeto.

  • Cada VM pode ter várias interfaces de rede e cada interface pode ter os seguintes endereços IP atribuídos de acordo com o respetivo tipo de pilha:

    • Interfaces apenas IPv4:
      • Um endereço IPv4 interno (obrigatório)
      • Um endereço IPv4 externo (opcional)
    • Interfaces de pilha dupla (IPv4 e IPv6):
      • Um endereço IPv4 interno (obrigatório)
      • Um endereço IPv4 externo (opcional)
      • Um intervalo de endereços IPv6, interno ou externo, mas não ambos (obrigatório)/96
    • Interfaces apenas IPv6:
      • Um intervalo de endereços IPv6, interno ou externo, mas não ambos (obrigatório)/96
  • Não pode anular a atribuição nem alterar o endereço IPv6 externo de uma VM com uma interface de rede apenas IPv6. No entanto, pode promover um endereço IP externo efémero de um recurso para um endereço IP externo estático, para que o endereço permaneça reservado mesmo após a eliminação do recurso.

  • Não pode alterar o nome de um endereço IP estático.

Nota: as interfaces de rede podem receber tráfego de várias regras de encaminhamento, que podem publicar outros endereços IP externos. Qualquer número de endereços IP externos pode fazer referência a uma interface de rede através destas regras de encaminhamento, mas só pode ser atribuído um endereço IPv4 externo e um intervalo de endereços IPv6 externos a cada interface de rede./96

Para mais informações sobre o balanceamento de carga e as regras de encaminhamento, leia a documentação sobre o balanceamento de carga.

Veja os endereços IP externos estáticos disponíveis

Para listar os endereços IP externos estáticos que reservou para o seu projeto, siga estes passos.

Consola

  1. Na Google Cloud consola, aceda à página Endereços IP.

    Aceda a Endereços IP

  2. Clique em Endereços IP externos.

gcloud

Use o comando gcloud compute addresses list:

  • Para apresentar uma lista de todos os endereços IP, use o seguinte comando:

    gcloud compute addresses list
  • Para apresentar uma lista de todos os endereços IP globais, use o seguinte comando:

    gcloud compute addresses list --global
  • Para apresentar uma lista de todos os endereços IP regionais numa determinada região, use o seguinte comando:

    gcloud compute addresses list \
        --regions=REGION
    

    Substitua REGION pela região para a qual quer apresentar uma lista de moradas. Pode listar endereços de várias regiões especificando nomes de regiões separados por vírgulas:

    gcloud compute addresses list \
        --regions=REGION1,REGION2,..REGION_n_
    

API

  • Para listar endereços IPv4 ou IPv6 regionais, chame o método addresses.list:

    GET https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/regions/REGION/addresses
    

    Substitua o seguinte:

    • PROJECT_ID: o ID do projeto para este pedido
    • REGION: o nome da região para este pedido
  • Para apresentar uma lista de todas as moradas em todas as regiões, chame o método addresses.aggregatedList:

    GET https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/aggregated/addresses
    
  • Para listar endereços IPv4 ou IPv6 globais, chame o método globalAddresses.list:

    GET https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/addresses
    

    Substitua o seguinte:

    PROJECT_ID: o ID do projeto para este pedido

Go

import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	"google.golang.org/api/iterator"

	"cloud.google.com/go/compute/apiv1/computepb"
)

// listRegionalExternal retrieves list external IP addresses in Google Cloud Platform region.
func listRegionalExternal(w io.Writer, projectID, region string) ([]*computepb.Address, error) {
	// projectID := "your_project_id"
	// region := "europe-west3"

	ctx := context.Background()
	// Create the service client.
	addressesClient, err := compute.NewAddressesRESTClient(ctx)
	if err != nil {
		return nil, err
	}
	defer addressesClient.Close()

	// Build the request.
	req := &computepb.ListAddressesRequest{
		Project: projectID,
		Region:  region,
	}

	// List the addresses.
	it := addressesClient.List(ctx, req)

	// Iterate over the results.
	var addresses []*computepb.Address
	for {
		address, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return nil, err
		}
		addresses = append(addresses, address)
	}

	// Print the addresses.
	fmt.Fprint(w, "Fetched addresses: \n")
	for _, address := range addresses {
		fmt.Fprintf(w, "%s\n", *address.Name)
	}

	return addresses, nil
}

// listGlobalExternal retrieves list external global IP addresses in Google Cloud Platform.
func listGlobalExternal(w io.Writer, projectID string) ([]*computepb.Address, error) {
	// projectID := "your_project_id"

	ctx := context.Background()
	// Create the service client.
	addressesClient, err := compute.NewGlobalAddressesRESTClient(ctx)
	if err != nil {
		return nil, err
	}
	defer addressesClient.Close()

	// Build the request.
	req := &computepb.ListGlobalAddressesRequest{
		Project: projectID,
	}

	// List the addresses.
	it := addressesClient.List(ctx, req)

	// Iterate over the results.
	var addresses []*computepb.Address
	for {
		address, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return nil, err
		}
		addresses = append(addresses, address)
	}

	// Print the addresses.
	fmt.Fprint(w, "Fetched addresses: \n")
	for _, address := range addresses {
		fmt.Fprintf(w, "%s\n", *address.Name)
	}

	return addresses, nil
}

Java


import com.google.cloud.compute.v1.Address;
import com.google.cloud.compute.v1.AddressesClient;
import com.google.cloud.compute.v1.GlobalAddressesClient;
import com.google.cloud.compute.v1.ListAddressesRequest;
import com.google.cloud.compute.v1.ListGlobalAddressesRequest;
import com.google.common.collect.Lists;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;

public class ListStaticExternalIp {

  public static void main(String[] args)
          throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // Project ID or project number of the Google Cloud project you want to use.
    String projectId = "your-project-id";
    // Region where the VM and IP is located.
    String region = "your-region-id";

    listStaticExternalIp(projectId, region);
  }

  // Lists all static external IP addresses, either regional or global.
  public static List<Address> listStaticExternalIp(String projectId, String region)
          throws IOException {
    // Use regional client if a region is specified
    if (region != null) {
      // Initialize client that will be used to send requests. This client only needs to be created
      // once, and can be reused for multiple requests.
      try (AddressesClient client = AddressesClient.create()) {
        ListAddressesRequest request = ListAddressesRequest.newBuilder()
                .setProject(projectId)
                .setRegion(region)
                .build();

        return Lists.newArrayList(client.list(request).iterateAll());
      }
    } else {
      // Initialize client that will be used to send requests. This client only needs to be created
      // once, and can be reused for multiple requests.
      try (GlobalAddressesClient client = GlobalAddressesClient.create()) {
        ListGlobalAddressesRequest request = ListGlobalAddressesRequest.newBuilder()
                .setProject(projectId)
                .build();

        return Lists.newArrayList(client.list(request).iterateAll());
      }
    }
  }
}

Python

from typing import List, Optional

from google.cloud.compute_v1.services.addresses.client import AddressesClient
from google.cloud.compute_v1.services.global_addresses import GlobalAddressesClient
from google.cloud.compute_v1.types import Address


def list_static_ip_addresses(
    project_id: str, region: Optional[str] = None
) -> List[Address]:
    """
    Lists all static external IP addresses, either regional or global.

    Args:
    project_id (str): project ID.
    region (Optional[str]): The region of the IP addresses if regional. None if global.

    Returns:
    List[Address]: A list of Address objects containing details about the requested IPs.
    """
    if region:
        # Use regional client if a region is specified
        client = AddressesClient()
        addresses_iterator = client.list(project=project_id, region=region)
    else:
        # Use global client if no region is specified
        client = GlobalAddressesClient()
        addresses_iterator = client.list(project=project_id)

    return list(addresses_iterator)  # Convert the iterator to a list to return

Configure endereços IP externos estáticos

As secções seguintes descrevem como configurar endereços IP externos estáticos para as suas instâncias.

Crie uma instância que use um endereço IP externo estático

Depois de reservar um endereço IP externo estático, pode atribuí-lo a uma instância.

Consola

  1. Na Google Cloud consola, aceda à página Criar uma instância.

    Aceda a Criar uma instância

  2. Para atribuir um endereço IP externo estático à instância, faça o seguinte:

    1. No menu de navegação, clique em Rede.

    2. Na secção Interfaces de rede, especifique as interfaces de rede que quer para a instância através das seguintes opções:

      • Para adicionar uma interface de rede, clique em Adicionar uma interface de rede. Em seguida, na lista Rede, selecione uma rede.

      • Para eliminar uma interface de rede, clique em Eliminar.

    3. Selecione uma das seguintes opções:

      • Para atribuir um endereço IPv4 externo estático, faça o seguinte:

        1. Expanda uma interface de rede.
        2. Selecione o endereço IP na lista Endereço IPv4 externo.
      • Para atribuir um endereço IPv6 externo estático, faça o seguinte:

        1. Expanda uma interface de rede que contenha uma sub-rede com um intervalo de endereços IPv6 externos.
        2. Selecione essa sub-rede na lista Sub-rede.
        3. Para Tipo de pilha de IP, selecione IPv4 e IPv6 (pilha dupla) ou IPv6 (pilha única).
        4. Selecione o endereço IPv6 externo reservado recentemente na lista Endereço IPv6 externo. Em alternativa, selecione Reservar endereço IPv6 externo estático e reserve um novo endereço IPv6 externo estático.
        5. Para o Nível de serviço de rede, selecione Premium.
    4. Para terminar a modificação da interface de rede, clique em Concluído.

  3. Continue com o processo de criação da instância.

gcloud

Pode criar uma instância e atribuir-lhe um endereço IP externo regional estático que já reservou.

  • Para atribuir um endereço IPv4 externo estático, faça o seguinte:

    gcloud compute instances create INSTANCE_NAME \
        --zone=ZONE \
        --address=IPV4_ADDRESS
    
  • Para atribuir um endereço IPv6 externo estático, faça o seguinte:

    gcloud compute instances create INSTANCE_NAME \
        --zone=ZONE \
        --subnet=SUBNET \
        --stack-type=STACK_TYPE \
        --external-ipv6-address=IPV6_ADDRESS \
        --external-ipv6-prefix-length=96 \
        --ipv6-network-tier=PREMIUM
    

    Substitua o seguinte:

    • INSTANCE_NAME: o nome da instância do Compute.
    • ZONE: a zona na qual criar a instância
    • IPV4_ADDRESS: o endereço IPv4 a atribuir à instância. Use o endereço IP externo estático reservado, não o nome do endereço.
    • SUBNET: uma sub-rede que contém endereços IPv6 externos
    • STACK_TYPE: o tipo de pilha para a instância, IPV4_IPV6 (dupla pilha) ou IPV6_ONLY
    • IPV6_ADDRESS: o endereço IPv6 a atribuir à instância. Use o endereço IP externo estático reservado, não o nome do endereço.

Terraform

Pode usar o recurso google_compute_instance para atribuir um endereço IP externo.

resource "google_compute_instance" "default" {
  name         = "dns-proxy-nfs"
  machine_type = "n1-standard-1"
  zone         = "us-central1-a"

  boot_disk {
    initialize_params {
      image = "ubuntu-1404-trusty-v20160627"
    }
  }

  network_interface {
    network = "default"
    access_config {
      nat_ip = google_compute_address.default.address
    }
  }
}

REST

  • Para atribuir um endereço IPv4 externo estático a uma nova instância de computação, faça o seguinte:

    No seu pedido para criar uma nova instância, indique explicitamente a propriedade networkInterfaces[].accessConfigs[].natIP e o endereço IPv4 externo que quer usar, por exemplo:

    {
      "name": "INSTANCE_NAME",
      "machineType": "zones/ZONE/machineTypes/MACHINE_TYPE",
      "networkInterfaces": [{
          "accessConfigs": [{
            "type": "ONE_TO_ONE_NAT",
            "name": "External NAT",
            "natIP": "IPV4_ADDRESS"
          }],
          "network": "global/networks/default"
      }],
      "disks": [{
          "autoDelete": "true",
            "boot": "true",
            "type": "PERSISTENT",
            "initializeParams": {
                "sourceImage": "SOURCE_IMAGE"
             }
      }]
    }
    

    Substitua o seguinte:

    • INSTANCE_NAME: o nome da instância de computação
    • ZONE: a zona na qual criar a instância
    • MACHINE_TYPE: Opcional: um URL completo ou parcial do recurso de tipo de máquina a usar quando criar a instância, no formato: zones/ZONE/machineTypes/MACHINE_TYPE
    • IPV4_ADDRESS: o endereço IPv4 a atribuir à instância. Use o endereço IP externo estático reservado, não o nome do endereço.
    • SOURCE_IMAGE: uma versão específica de uma imagem pública, como projects/debian-cloud/global/images/debian-10-buster-v20200309 ou uma família de imagens, como projects/debian-cloud/global/images/family/debian-10
  • Para atribuir um endereço IPv6 externo estático a uma nova instância, faça o seguinte:

    No seu pedido para criar uma nova instância, forneça explicitamente a propriedade networkInterfaces[].ipv6AccessConfigs[].externalIpv6 e o endereço IPv6 externo que quer usar, por exemplo:

    {
      "name": "INSTANCE_NAME",
      "machineType": "zones/ZONE/machineTypes/MACHINE_TYPE",
      "networkInterfaces": [{
              "ipv6AccessConfigs": [{
             "externalIpv6": "IPV6_ADDRESS",
             "externalIpv6PrefixLength": 96,
             "name": "external-ipv6-access-config",
             "networkTier": "PREMIUM",
             "type": "DIRECT_IPV6"
              }],
          "stackType": "STACK_TYPE",
          "subnetwork":"SUBNETWORK"
      }],
      "disks": [{
          "autoDelete": "true",
          "boot": "true",
          "mode": "READ_WRITE",
          "type": "PERSISTENT",
          "initializeParams": {
              "sourceImage": "SOURCE_IMAGE"
          },
      }],
    }
    

    Substitua o seguinte:

    • INSTANCE_NAME: o nome da instância de computação
    • ZONE: a zona na qual criar a instância
    • MACHINE_TYPE: Opcional: um URL completo ou parcial do recurso de tipo de máquina a usar quando criar a instância, no formato: zones/ZONE/machineTypes/MACHINE_TYPE
    • IPV6_ADDRESS: o endereço IPv6 a atribuir à instância. Use o endereço IP externo estático reservado, não o nome do endereço.
    • STACK_TYPE: o tipo de pilha para a instância, IPV4_IPV6 (dupla pilha) ou IPV6_ONLY
    • SUBNET: uma sub-rede que contém endereços IPv6 externos
    • SOURCE_IMAGE: uma versão específica de uma imagem pública, como "projects/debian-cloud/global/images/debian-10-buster-v20200309" ou uma família de imagens, como "projects/debian-cloud/global/images/family/debian-10"

Go


// assignStaticExternalToNewVM creates a new VM instance and assigns a static external IP address to it.
// NOTE: ip address is expected to exist and be located in the same region as new VM
func assignStaticExternalToNewVM(w io.Writer, projectID, zone, instanceName, ipAddress string) error {
	// projectID := "your_project_id"
	// zone := "europe-central2-b"
	// instanceName := "your_instance_name"
	// ipAddress := 301.222.11.123

	ctx := context.Background()
	instancesClient, err := compute.NewInstancesRESTClient(ctx)
	if err != nil {
		return fmt.Errorf("NewInstancesRESTClient: %w", err)
	}
	defer instancesClient.Close()

	imagesClient, err := compute.NewImagesRESTClient(ctx)
	if err != nil {
		return fmt.Errorf("NewImagesRESTClient: %w", err)
	}
	defer imagesClient.Close()

	// List of public operating system (OS) images: https://cloud.google.com/compute/docs/images/os-details.
	newestDebianReq := &computepb.GetFromFamilyImageRequest{
		Project: "debian-cloud",
		Family:  "debian-12",
	}
	newestDebian, err := imagesClient.GetFromFamily(ctx, newestDebianReq)
	if err != nil {
		return fmt.Errorf("unable to get image from family: %w", err)
	}

	req := &computepb.InsertInstanceRequest{
		Project: projectID,
		Zone:    zone,
		InstanceResource: &computepb.Instance{
			Name: proto.String(instanceName),
			Disks: []*computepb.AttachedDisk{
				{
					InitializeParams: &computepb.AttachedDiskInitializeParams{
						DiskSizeGb:  proto.Int64(10),
						SourceImage: newestDebian.SelfLink,
						DiskType:    proto.String(fmt.Sprintf("zones/%s/diskTypes/pd-standard", zone)),
					},
					AutoDelete: proto.Bool(true),
					Boot:       proto.Bool(true),
					Type:       proto.String(computepb.AttachedDisk_PERSISTENT.String()),
				},
			},
			MachineType: proto.String(fmt.Sprintf("zones/%s/machineTypes/n1-standard-1", zone)),
			NetworkInterfaces: []*computepb.NetworkInterface{
				{
					AccessConfigs: []*computepb.AccessConfig{
						{
							Type:        proto.String(computepb.AccessConfig_ONE_TO_ONE_NAT.String()),
							Name:        proto.String("External NAT"),
							NetworkTier: proto.String(computepb.AccessConfig_PREMIUM.String()),
							NatIP:       proto.String(ipAddress),
						},
					},
				},
			},
		},
	}

	op, err := instancesClient.Insert(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to create instance: %w", err)
	}

	if err = op.Wait(ctx); err != nil {
		return fmt.Errorf("unable to wait for the operation: %w", err)
	}

	fmt.Fprintf(w, "Static address %s assigned to new VM", ipAddress)

	return nil
}

Java


import com.google.cloud.compute.v1.AccessConfig;
import com.google.cloud.compute.v1.AccessConfig.Type;
import com.google.cloud.compute.v1.Address.NetworkTier;
import com.google.cloud.compute.v1.AttachedDisk;
import com.google.cloud.compute.v1.AttachedDiskInitializeParams;
import com.google.cloud.compute.v1.GetInstanceRequest;
import com.google.cloud.compute.v1.ImagesClient;
import com.google.cloud.compute.v1.InsertInstanceRequest;
import com.google.cloud.compute.v1.Instance;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.NetworkInterface;
import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class AssignStaticExternalNewVmAddress {

  public static void main(String[] args)
          throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // Project ID or project number of the Google Cloud project you want to use.
    String projectId = "your-project-id";
    // Instance ID of the Google Cloud project you want to use.
    String instanceId = "your-instance-id";
    // Name of the zone to create the instance in. For example: "us-west3-b"
    String zone = "your-zone-id";
    // machine type of the VM being created. This value uses the
    // following format: "zones/{zone}/machineTypes/{type_name}".
    // For example: "zones/europe-west3-c/machineTypes/f1-micro"
    String machineType = String.format("zones/%s/machineTypes/{your-machineType-id}", zone);
    // boolean flag indicating if the instance should have an external IPv4 address assigned.
    boolean externalAccess = true;
    // external IPv4 address to be assigned to this instance. If you specify
    // an external IP address, it must live in the same region as the zone of the instance.
    // This setting requires `external_access` to be set to True to work.
    String externalIpv4 = "your-externalIpv4-id";

    assignStaticExternalNewVmAddress(projectId, instanceId, zone,
            externalAccess, machineType, externalIpv4);
  }

  // Create a new VM instance with assigned static external IP address.
  public static Instance assignStaticExternalNewVmAddress(String projectId, String instanceName,
                                                          String zone, boolean externalAccess,
                                                          String machineType, String externalIpv4)
          throws IOException, ExecutionException, InterruptedException, TimeoutException {
    String sourceImage;
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (ImagesClient imagesClient = ImagesClient.create()) {
      sourceImage = imagesClient.getFromFamily("debian-cloud", "debian-11").getSelfLink();
    }
    AttachedDisk attachedDisk = buildAttachedDisk(sourceImage, zone);

    return createInstance(projectId, instanceName, zone,
            attachedDisk, machineType, externalAccess, externalIpv4);
  }

  private static AttachedDisk buildAttachedDisk(String sourceImage, String zone) {
    AttachedDiskInitializeParams initializeParams = AttachedDiskInitializeParams.newBuilder()
            .setSourceImage(sourceImage)
            .setDiskSizeGb(10)
            .setDiskType(String.format("zones/%s/diskTypes/pd-standard", zone))
            .build();

    return AttachedDisk.newBuilder()
            .setInitializeParams(initializeParams)
            // Remember to set auto_delete to True if you want the disk to be deleted
            // when you delete your VM instance.
            .setAutoDelete(true)
            .setBoot(true)
            .build();
  }

  // Send an instance creation request to the Compute Engine API and wait for it to complete.
  private static Instance createInstance(String projectId, String instanceName,
                                         String zone, AttachedDisk disks,
                                         String machineType, boolean externalAccess,
                                         String externalIpv4)
          throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (InstancesClient client = InstancesClient.create()) {
      Instance instanceResource =
              buildInstanceResource(instanceName, disks, machineType, externalAccess, externalIpv4);

      InsertInstanceRequest build = InsertInstanceRequest.newBuilder()
              .setProject(projectId)
              .setRequestId(UUID.randomUUID().toString())
              .setZone(zone)
              .setInstanceResource(instanceResource)
              .build();
      client.insertCallable().futureCall(build).get(60, TimeUnit.SECONDS);

      GetInstanceRequest getInstanceRequest = GetInstanceRequest.newBuilder()
              .setInstance(instanceName)
              .setProject(projectId)
              .setZone(zone)
              .build();

      return client.get(getInstanceRequest);
    }
  }

  private static Instance buildInstanceResource(String instanceName, AttachedDisk disk,
                                                String machineType, boolean externalAccess,
                                                String externalIpv4) {
    NetworkInterface networkInterface =
            networkInterface(externalAccess, externalIpv4);

    return Instance.newBuilder()
            .setName(instanceName)
            .addDisks(disk)
            .setMachineType(machineType)
            .addNetworkInterfaces(networkInterface)
            .build();
  }

  private static NetworkInterface networkInterface(boolean externalAccess, String externalIpv4) {
    NetworkInterface.Builder build = NetworkInterface.newBuilder()
            .setNetwork("global/networks/default");
    if (externalAccess) {
      AccessConfig.Builder accessConfig = AccessConfig.newBuilder()
              .setType(Type.ONE_TO_ONE_NAT.name())
              .setName("External NAT")
              .setNetworkTier(NetworkTier.PREMIUM.name());
      if (externalIpv4 != null) {
        accessConfig.setNatIP(externalIpv4);
      }
      build.addAccessConfigs(accessConfig.build());
    }

    return build.build();
  }
}

Python

from __future__ import annotations

import re
import sys
from typing import Any
import warnings

from google.api_core.extended_operation import ExtendedOperation
from google.cloud import compute_v1


def get_image_from_family(project: str, family: str) -> compute_v1.Image:
    """
    Retrieve the newest image that is part of a given family in a project.

    Args:
        project: project ID or project number of the Cloud project you want to get image from.
        family: name of the image family you want to get image from.

    Returns:
        An Image object.
    """
    image_client = compute_v1.ImagesClient()
    # List of public operating system (OS) images: https://cloud.google.com/compute/docs/images/os-details
    newest_image = image_client.get_from_family(project=project, family=family)
    return newest_image


def disk_from_image(
    disk_type: str,
    disk_size_gb: int,
    boot: bool,
    source_image: str,
    auto_delete: bool = True,
) -> compute_v1.AttachedDisk:
    """
    Create an AttachedDisk object to be used in VM instance creation. Uses an image as the
    source for the new disk.

    Args:
         disk_type: the type of disk you want to create. This value uses the following format:
            "zones/{zone}/diskTypes/(pd-standard|pd-ssd|pd-balanced|pd-extreme)".
            For example: "zones/us-west3-b/diskTypes/pd-ssd"
        disk_size_gb: size of the new disk in gigabytes
        boot: boolean flag indicating whether this disk should be used as a boot disk of an instance
        source_image: source image to use when creating this disk. You must have read access to this disk. This can be one
            of the publicly available images or an image from one of your projects.
            This value uses the following format: "projects/{project_name}/global/images/{image_name}"
        auto_delete: boolean flag indicating whether this disk should be deleted with the VM that uses it

    Returns:
        AttachedDisk object configured to be created using the specified image.
    """
    boot_disk = compute_v1.AttachedDisk()
    initialize_params = compute_v1.AttachedDiskInitializeParams()
    initialize_params.source_image = source_image
    initialize_params.disk_size_gb = disk_size_gb
    initialize_params.disk_type = disk_type
    boot_disk.initialize_params = initialize_params
    # Remember to set auto_delete to True if you want the disk to be deleted when you delete
    # your VM instance.
    boot_disk.auto_delete = auto_delete
    boot_disk.boot = boot
    return boot_disk


def wait_for_extended_operation(
    operation: ExtendedOperation, verbose_name: str = "operation", timeout: int = 300
) -> Any:
    """
    Waits for the extended (long-running) operation to complete.

    If the operation is successful, it will return its result.
    If the operation ends with an error, an exception will be raised.
    If there were any warnings during the execution of the operation
    they will be printed to sys.stderr.

    Args:
        operation: a long-running operation you want to wait on.
        verbose_name: (optional) a more verbose name of the operation,
            used only during error and warning reporting.
        timeout: how long (in seconds) to wait for operation to finish.
            If None, wait indefinitely.

    Returns:
        Whatever the operation.result() returns.

    Raises:
        This method will raise the exception received from `operation.exception()`
        or RuntimeError if there is no exception set, but there is an `error_code`
        set for the `operation`.

        In case of an operation taking longer than `timeout` seconds to complete,
        a `concurrent.futures.TimeoutError` will be raised.
    """
    result = operation.result(timeout=timeout)

    if operation.error_code:
        print(
            f"Error during {verbose_name}: [Code: {operation.error_code}]: {operation.error_message}",
            file=sys.stderr,
            flush=True,
        )
        print(f"Operation ID: {operation.name}", file=sys.stderr, flush=True)
        raise operation.exception() or RuntimeError(operation.error_message)

    if operation.warnings:
        print(f"Warnings during {verbose_name}:\n", file=sys.stderr, flush=True)
        for warning in operation.warnings:
            print(f" - {warning.code}: {warning.message}", file=sys.stderr, flush=True)

    return result


def create_instance(
    project_id: str,
    zone: str,
    instance_name: str,
    disks: list[compute_v1.AttachedDisk],
    machine_type: str = "n1-standard-1",
    network_link: str = "global/networks/default",
    subnetwork_link: str = None,
    internal_ip: str = None,
    external_access: bool = False,
    external_ipv4: str = None,
    accelerators: list[compute_v1.AcceleratorConfig] = None,
    preemptible: bool = False,
    spot: bool = False,
    instance_termination_action: str = "STOP",
    custom_hostname: str = None,
    delete_protection: bool = False,
) -> compute_v1.Instance:
    """
    Send an instance creation request to the Compute Engine API and wait for it to complete.

    Args:
        project_id: project ID or project number of the Cloud project you want to use.
        zone: name of the zone to create the instance in. For example: "us-west3-b"
        instance_name: name of the new virtual machine (VM) instance.
        disks: a list of compute_v1.AttachedDisk objects describing the disks
            you want to attach to your new instance.
        machine_type: machine type of the VM being created. This value uses the
            following format: "zones/{zone}/machineTypes/{type_name}".
            For example: "zones/europe-west3-c/machineTypes/f1-micro"
        network_link: name of the network you want the new instance to use.
            For example: "global/networks/default" represents the network
            named "default", which is created automatically for each project.
        subnetwork_link: name of the subnetwork you want the new instance to use.
            This value uses the following format:
            "regions/{region}/subnetworks/{subnetwork_name}"
        internal_ip: internal IP address you want to assign to the new instance.
            By default, a free address from the pool of available internal IP addresses of
            used subnet will be used.
        external_access: boolean flag indicating if the instance should have an external IPv4
            address assigned.
        external_ipv4: external IPv4 address to be assigned to this instance. If you specify
            an external IP address, it must live in the same region as the zone of the instance.
            This setting requires `external_access` to be set to True to work.
        accelerators: a list of AcceleratorConfig objects describing the accelerators that will
            be attached to the new instance.
        preemptible: boolean value indicating if the new instance should be preemptible
            or not. Preemptible VMs have been deprecated and you should now use Spot VMs.
        spot: boolean value indicating if the new instance should be a Spot VM or not.
        instance_termination_action: What action should be taken once a Spot VM is terminated.
            Possible values: "STOP", "DELETE"
        custom_hostname: Custom hostname of the new VM instance.
            Custom hostnames must conform to RFC 1035 requirements for valid hostnames.
        delete_protection: boolean value indicating if the new virtual machine should be
            protected against deletion or not.
    Returns:
        Instance object.
    """
    instance_client = compute_v1.InstancesClient()

    # Use the network interface provided in the network_link argument.
    network_interface = compute_v1.NetworkInterface()
    network_interface.network = network_link
    if subnetwork_link:
        network_interface.subnetwork = subnetwork_link

    if internal_ip:
        network_interface.network_i_p = internal_ip

    if external_access:
        access = compute_v1.AccessConfig()
        access.type_ = compute_v1.AccessConfig.Type.ONE_TO_ONE_NAT.name
        access.name = "External NAT"
        access.network_tier = access.NetworkTier.PREMIUM.name
        if external_ipv4:
            access.nat_i_p = external_ipv4
        network_interface.access_configs = [access]

    # Collect information into the Instance object.
    instance = compute_v1.Instance()
    instance.network_interfaces = [network_interface]
    instance.name = instance_name
    instance.disks = disks
    if re.match(r"^zones/[a-z\d\-]+/machineTypes/[a-z\d\-]+$", machine_type):
        instance.machine_type = machine_type
    else:
        instance.machine_type = f"zones/{zone}/machineTypes/{machine_type}"

    instance.scheduling = compute_v1.Scheduling()
    if accelerators:
        instance.guest_accelerators = accelerators
        instance.scheduling.on_host_maintenance = (
            compute_v1.Scheduling.OnHostMaintenance.TERMINATE.name
        )

    if preemptible:
        # Set the preemptible setting
        warnings.warn(
            "Preemptible VMs are being replaced by Spot VMs.", DeprecationWarning
        )
        instance.scheduling = compute_v1.Scheduling()
        instance.scheduling.preemptible = True

    if spot:
        # Set the Spot VM setting
        instance.scheduling.provisioning_model = (
            compute_v1.Scheduling.ProvisioningModel.SPOT.name
        )
        instance.scheduling.instance_termination_action = instance_termination_action

    if custom_hostname is not None:
        # Set the custom hostname for the instance
        instance.hostname = custom_hostname

    if delete_protection:
        # Set the delete protection bit
        instance.deletion_protection = True

    # Prepare the request to insert an instance.
    request = compute_v1.InsertInstanceRequest()
    request.zone = zone
    request.project = project_id
    request.instance_resource = instance

    # Wait for the create operation to complete.
    print(f"Creating the {instance_name} instance in {zone}...")

    operation = instance_client.insert(request=request)

    wait_for_extended_operation(operation, "instance creation")

    print(f"Instance {instance_name} created.")
    return instance_client.get(project=project_id, zone=zone, instance=instance_name)


def assign_static_external_ip_to_new_vm(
    project_id: str, zone: str, instance_name: str, ip_address: str
) -> compute_v1.Instance:
    """
    Create a new VM instance with assigned static external IP address.

    Args:
        project_id (str): project ID or project number of the Cloud project you want to use.
        zone (str): name of the zone to create the instance in. For example: "us-west3-b"
        instance_name (str): name of the new virtual machine (VM) instance.
        ip_address(str): external address to be assigned to this instance. It must live in the same
        region as the zone of the instance and be precreated before function called.

    Returns:
        Instance object.
    """
    newest_debian = get_image_from_family(project="debian-cloud", family="debian-12")
    disk_type = f"zones/{zone}/diskTypes/pd-standard"
    disks = [disk_from_image(disk_type, 10, True, newest_debian.self_link, True)]
    instance = create_instance(
        project_id,
        zone,
        instance_name,
        disks,
        external_ipv4=ip_address,
        external_access=True,
    )
    return instance

Altere ou atribua um endereço IP externo a uma instância existente

Pode alterar ou atribuir um endereço IP externo, quer seja efémero ou estático, a uma instância existente apenas IPv4 ou de pilha dupla. Este procedimento não é suportado para instâncias apenas IPv6.

Uma instância de computação pode ter várias interfaces. Uma interface de pilha única pode ter um endereço IP externo. Uma interface de pilha dupla pode ter um endereço IPv4 externo e um endereço IPv6 externo. Se a instância já tiver um endereço IP externo, tem de remover esse endereço primeiro. Em seguida, pode atribuir um novo endereço IP externo à instância existente.

Consola

  1. Na Google Cloud consola, aceda à página Instâncias de VM.

    Aceder às instâncias de VM

  2. Clique no nome da instância à qual quer atribuir um IP externo. É apresentada a página Detalhes da instância.

  3. Na página Detalhes da instância, conclua os seguintes passos:

    1. Clique em Edit.
    2. Expanda Interfaces de rede.
    3. Selecione o endereço IP externo necessário para atribuir à instância. Se a instância for apenas IPv4 e quiser atribuir um endereço IPv6, primeiro, tem de alterar o tipo de pilha para pilha dupla.
      1. Para Endereço IPv4 externo, selecione Efémero ou um endereço IPv4 externo estático.
      2. Para o endereço IPv6 externo, selecione Efémero (automático), Efémero (personalizado) ou um endereço IPv6 externo estático.
    4. Clique em Concluído.
  4. Clique em Guardar.

gcloud

  1. Opcional: reserve um endereço IP externo estático.

    Se quiser atribuir um endereço IP externo estático, tem de reservar um endereço e certificar-se de que o endereço não está a ser usado por outro recurso. Se necessário, siga as instruções para reservar um novo endereço IP externo estático ou para anular a atribuição de um endereço IP externo estático.

    Se pretender usar um endereço IP externo efémero, pode ignorar este passo e o Compute Engine atribui aleatoriamente um endereço IP externo efémero.

  2. Remova qualquer atribuição de endereço IP existente, conforme descrito no artigo Desatribua um endereço IP externo estático.

  3. Atribua o novo endereço IP externo.

    • Para atribuir um endereço IPv4, use o subcomando instances add-access-config:

      Nota: não substitua IP_ADDRESS pelo nome do endereço IP estático. Tem de usar o endereço IP real.
      gcloud compute instances add-access-config INSTANCE_NAME \
        --access-config-name="ACCESS_CONFIG_NAME" --address=IP_ADDRESS
      

      Substitua o seguinte:

      • INSTANCE_NAME: o nome da instância.
      • ACCESS_CONFIG_NAME: o nome a atribuir a esta configuração de acesso. Certifique-se de que inclui o nome completo entre aspas.
      • IP_ADDRESS: o endereço IP a adicionar.

      Se quiser que o Compute Engine atribua um endereço IP externo efémero em vez de usar um endereço IP externo estático, omita a propriedade --address IP_ADDRESS:

      gcloud compute instances add-access-config INSTANCE_NAME \
        --access-config-name="ACCESS_CONFIG_NAME"
      
    • Para alterar uma instância para pilha dupla e atribuir-lhe um endereço IPv6, use o subcomando instance network-interfaces update:

      gcloud compute instances network-interfaces update INSTANCE_NAME \
        --network-interface=NIC \
        --ipv6-network-tier=PREMIUM \
        --stack-type=STACK_TYPE \
        --external-ipv6-address=IPV6_ADDRESS \
        --external-ipv6-prefix-length=96 \
        --zone=ZONE
      

      Substitua o seguinte:

      • INSTANCE_NAME: o nome da instância.
      • NIC: o nome da interface de rede.
      • STACK_TYPE: o tipo de pilha para a instância, que tem de ser IPV4_IPV6. Não pode alterar o tipo de pilha para IPV6_ONLY.
      • IPV6_ADDRESS: o endereço IPv6 a atribuir à instância. Especifique o primeiro endereço IPv6 no intervalo /96.
      • ZONE: a zona da instância.

REST

Pode alterar o endereço IPv4 ou IPv6 externo de uma instância adicionando uma nova configuração de acesso para essa instância.

  1. Remova qualquer atribuição de endereço IP existente, conforme descrito no artigo Desatribua um endereço IP externo estático.

  2. Elimine a configuração de acesso existente fazendo um pedido POST ao método instances.deleteAccessConfig.

    POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME/deleteAccessConfig
    
  3. Adicione uma nova configuração de acesso à interface de rede da instância enviando um pedido POST ao método instances.addAccessConfig.

Go

import (
	"context"
	"fmt"
	"io"

	"google.golang.org/protobuf/proto"

	compute "cloud.google.com/go/compute/apiv1"
	"cloud.google.com/go/compute/apiv1/computepb"
)

// assignStaticAddressToExistingVM assigns a static external IP address to an existing VM instance.
// Note: VM and assigned IP must be in the same region.
func assignStaticAddressToExistingVM(w io.Writer, projectID, zone, instanceName, IPAddress, networkInterfaceName string) error {
	// projectID := "your_project_id"
	// zone := "europe-central2-b"
	// instanceName := "your_instance_name"
	// IPAddress := "34.111.222.333"
	// networkInterfaceName := "nic0"

	ctx := context.Background()
	instancesClient, err := compute.NewInstancesRESTClient(ctx)
	if err != nil {
		return fmt.Errorf("NewInstancesRESTClient: %w", err)
	}
	defer instancesClient.Close()

	reqGet := &computepb.GetInstanceRequest{
		Project:  projectID,
		Zone:     zone,
		Instance: instanceName,
	}

	instance, err := instancesClient.Get(ctx, reqGet)
	if err != nil {
		return fmt.Errorf("could not get instance: %w", err)
	}

	var networkInterface *computepb.NetworkInterface
	for _, ni := range instance.NetworkInterfaces {
		if *ni.Name == networkInterfaceName {
			networkInterface = ni
			break
		}
	}

	if networkInterface == nil {
		return fmt.Errorf("No network interface named '%s' found on instance %s", networkInterfaceName, instanceName)
	}

	var accessConfig *computepb.AccessConfig
	for _, ac := range networkInterface.AccessConfigs {
		if *ac.Type == computepb.AccessConfig_ONE_TO_ONE_NAT.String() {
			accessConfig = ac
			break
		}
	}

	if accessConfig != nil {
		// network interface is immutable - deletion stage is required in case of any assigned ip (static or ephemeral).
		reqDelete := &computepb.DeleteAccessConfigInstanceRequest{
			Project:          projectID,
			Zone:             zone,
			Instance:         instanceName,
			AccessConfig:     *accessConfig.Name,
			NetworkInterface: networkInterfaceName,
		}

		opDelete, err := instancesClient.DeleteAccessConfig(ctx, reqDelete)
		if err != nil {
			return fmt.Errorf("unable to delete access config: %w", err)
		}

		if err = opDelete.Wait(ctx); err != nil {
			return fmt.Errorf("unable to wait for the operation: %w", err)
		}
	}

	reqAdd := &computepb.AddAccessConfigInstanceRequest{
		Project:  projectID,
		Zone:     zone,
		Instance: instanceName,
		AccessConfigResource: &computepb.AccessConfig{
			NatIP: &IPAddress,
			Type:  proto.String(computepb.AccessConfig_ONE_TO_ONE_NAT.String()),
		},
		NetworkInterface: networkInterfaceName,
	}

	opAdd, err := instancesClient.AddAccessConfig(ctx, reqAdd)
	if err != nil {
		return fmt.Errorf("unable to add access config: %w", err)
	}

	if err = opAdd.Wait(ctx); err != nil {
		return fmt.Errorf("unable to wait for the operation: %w", err)
	}

	fmt.Fprintf(w, "Static address %s assigned to the instance %s\n", IPAddress, instanceName)

	return nil
}

Java


import com.google.cloud.compute.v1.AccessConfig;
import com.google.cloud.compute.v1.AccessConfig.Type;
import com.google.cloud.compute.v1.Instance;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.NetworkInterface;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class AssignStaticExistingVm {

  public static void main(String[] args)
          throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // Project ID or project number of the Google Cloud project you want to use.
    String projectId = "your-project-id";
    // Instance ID of the Google Cloud project you want to use.
    String instanceId = "your-instance-id";
    // Name of the zone to create the instance in. For example: "us-west3-b"
    String zone = "your-zone-id";
    // Name of the network interface to assign.
    String netInterfaceName = "your-netInterfaceName-id";

    assignStaticExistingVmAddress(projectId, instanceId, zone, netInterfaceName);
  }

  // Updates or creates an access configuration for a VM instance to assign a static external IP.
  // As network interface is immutable - deletion stage is required
  // in case of any assigned ip (static or ephemeral).
  // VM and ip address must be created before calling this function.
  // IMPORTANT: VM and assigned IP must be in the same region.
  public static Instance assignStaticExistingVmAddress(String projectId, String instanceId,
                                                       String zone, String netInterfaceName)
          throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (InstancesClient client = InstancesClient.create()) {
      Instance instance = client.get(projectId, zone, instanceId);

      NetworkInterface networkInterface = null;
      for (NetworkInterface netInterface : instance.getNetworkInterfacesList()) {
        if (netInterface.getName().equals(netInterfaceName)) {
          networkInterface = netInterface;
          break;
        }
      }

      if (networkInterface == null) {
        throw new IllegalArgumentException(
                String.format(
                        "No '{network_interface_name}' variable found on instance %s.",
                        instanceId)
        );
      }
      AccessConfig accessConfig = null;
      for (AccessConfig config : networkInterface.getAccessConfigsList()) {
        if (config.getType().equals(Type.ONE_TO_ONE_NAT.name())) {
          accessConfig = config;
          break;
        }
      }

      if (accessConfig != null) {
        // Delete the existing access configuration first
        client.deleteAccessConfigAsync(projectId, zone, instanceId,
                        accessConfig.getName(), netInterfaceName)
                .get(30, TimeUnit.SECONDS);
      }

      // Add a new access configuration with the new IP
      AccessConfig newAccessConfig = AccessConfig.newBuilder()
              // Leave this field undefined to use an IP from a shared ephemeral IP address pool
              // .setNatIP(ipAddress)
              .setType(Type.ONE_TO_ONE_NAT.name())
              .setName("external-nat")
              .build();

      client.addAccessConfigAsync(projectId, zone, instanceId, netInterfaceName, newAccessConfig)
              .get(30, TimeUnit.SECONDS);

      // return updated instance
      return client.get(projectId, zone, instanceId);
    }
  }
}

Python

import uuid

from google.cloud.compute_v1 import InstancesClient
from google.cloud.compute_v1.types import AccessConfig
from google.cloud.compute_v1.types import AddAccessConfigInstanceRequest
from google.cloud.compute_v1.types import DeleteAccessConfigInstanceRequest


def assign_static_ip_to_existing_vm(
    project_id: str,
    zone: str,
    instance_name: str,
    ip_address: str,
    network_interface_name: str = "nic0",
):
    """
    Updates or creates an access configuration for a VM instance to assign a static external IP.
    As network interface is immutable - deletion stage is required in case of any assigned ip (static or ephemeral).
    VM and ip address must be created before calling this function.
    IMPORTANT: VM and assigned IP must be in the same region.

    Args:
        project_id (str): Project ID.
        zone (str): Zone where the VM is located.
        instance_name (str): Name of the VM instance.
        ip_address (str): New static external IP address to assign to the VM.
        network_interface_name (str): Name of the network interface to assign.

    Returns:
        google.cloud.compute_v1.types.Instance: Updated instance object.
    """
    client = InstancesClient()
    instance = client.get(project=project_id, zone=zone, instance=instance_name)
    network_interface = next(
        (ni for ni in instance.network_interfaces if ni.name == network_interface_name),
        None,
    )

    if network_interface is None:
        raise ValueError(
            f"No network interface named '{network_interface_name}' found on instance {instance_name}."
        )

    access_config = next(
        (ac for ac in network_interface.access_configs if ac.type_ == "ONE_TO_ONE_NAT"),
        None,
    )

    if access_config:
        # Delete the existing access configuration first
        delete_request = DeleteAccessConfigInstanceRequest(
            project=project_id,
            zone=zone,
            instance=instance_name,
            access_config=access_config.name,
            network_interface=network_interface_name,
            request_id=str(uuid.uuid4()),
        )
        delete_operation = client.delete_access_config(delete_request)
        delete_operation.result()

    # Add a new access configuration with the new IP
    add_request = AddAccessConfigInstanceRequest(
        project=project_id,
        zone=zone,
        instance=instance_name,
        network_interface="nic0",
        access_config_resource=AccessConfig(
            nat_i_p=ip_address, type_="ONE_TO_ONE_NAT", name="external-nat"
        ),
        request_id=str(uuid.uuid4()),
    )
    add_operation = client.add_access_config(add_request)
    add_operation.result()

    updated_instance = client.get(project=project_id, zone=zone, instance=instance_name)
    return updated_instance

Restrinja endereços IP externos a instâncias específicas

Para determinadas cargas de trabalho, pode ter requisitos essenciais que incluem restrições de segurança e de rede. Por exemplo, pode querer restringir endereços IP externos para que apenas instâncias de computação específicas os possam usar. Esta opção pode ajudar a evitar a exfiltração de dados ou a manter o isolamento da rede. Através de uma política da organização, pode restringir endereços IP externos a instâncias específicas com restrições para controlar a utilização de endereços IP externos para as suas instâncias numa organização ou num projeto.

A restrição para controlar o endereço IP externo nas instâncias é:

constraints/compute.vmExternalIpAccess

Para usar a restrição, especifica uma política com um allowedList de instâncias que podem ter endereços IP externos. Se não especificar uma política, todos os endereços IP externos são permitidos para todas as instâncias. Quando a política está em vigor, apenas as instâncias listadas na lista allowedValues podem ser atribuídas a um endereço IP externo, quer seja efémero ou estático, e outras instâncias do Compute Engine na organização ou no projeto que não estão explicitamente definidas na política estão proibidas de usar endereços IP externos.

As instâncias são identificadas nas listas de permissões e negações através do URI da instância:

projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME

Especificações para restringir endereços IP externos

  • Só pode aplicar esta restrição de lista a instâncias.
  • Não pode aplicar a restrição retroativamente. Todas as instâncias que tenham endereços IP externos antes de ativar a política mantêm os respetivos endereços IP externos.
  • Esta restrição aceita um allowedList ou um deniedList, mas não ambos na mesma política.
  • É da sua responsabilidade ou da responsabilidade de um administrador com as autorizações necessárias gerir e manter o ciclo de vida e a integridade da instância. A restrição apenas valida o URI da instância e não impede que as instâncias na lista de autorizações sejam alteradas, eliminadas ou recriadas.

Autorizações necessárias para restringir endereços IP externos

Para definir uma restrição ao nível do projeto ou da organização, tem de lhe ter sido atribuída a função orgpolicy.policyAdmin na organização.

Defina a restrição de política ao nível da organização

Consola

  1. Aceda à página Políticas organizacionais.

    Aceda às políticas organizacionais

  2. Se necessário, selecione a organização necessária no menu pendente do projeto.
  3. Clique em Defina IPs externos permitidos para instâncias de VM.
  4. Clique em Editar para editar a política de IP externo. Se não conseguir aceder à ferramenta Editar, não tem as autorizações corretas.
  5. Selecione Personalizar para definir a política da organização para instâncias específicas.

    Opção de personalização na página de edição da política da organização.

  6. Selecione a Aplicação de políticas e o Tipo de política necessários.

  7. Para Valores da política, selecione Personalizado.

  8. Introduza um URI para uma instância. O URI tem de estar no seguinte formato:

    projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME
    
  9. Clique em Novo valor da política e introduza os URIs para instâncias, conforme necessário.

  10. Clique em Guardar para aplicar a restrição.

gcloud

Para definir uma restrição para o acesso de IP externo, primeiro precisa do ID da sua organização. Pode encontrar o ID da organização executando o comando organizations list e procurando o ID numérico na resposta:

gcloud organizations list

A CLI gcloud devolve uma lista de organizações no seguinte formato:

DISPLAY_NAME               ID
example-organization1      29252605212
example-organization2      1234567890

Use o comando gcloud resource-manager org-policies set-policy para definir a política. Tem de fornecer a sua política como um ficheiro JSON. Crie um ficheiro JSON no seguinte formato:

{
"constraint": "constraints/compute.vmExternalIpAccess",
"listPolicy": {
  "allowedValues": [
     "projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME",
     "projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME",
     "projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME"
  ]
 }
}

Substitua o seguinte:

  • PROJECT_ID: o ID do projeto para este pedido, como example-project. Tenha em atenção que isto é diferente da configuração das políticas da organização, que requerem o ID numérico da organização.
  • ZONE: a zona da instância
  • INSTANCE_NAME: o nome da instância

Em alternativa, pode especificar uma lista deniedValues para indicar instâncias que quer explicitamente proibir de ter um endereço IP externo. Qualquer instância que não esteja na lista tem implicitamente permissão para ter um endereço IP externo. Só pode especificar allowedValues ou deniedValues, mas não ambos.

Em seguida, transmita o ficheiro com o seu pedido:

gcloud resource-manager org-policies set-policy MY_POLICY.JSON --organization=ORGANIZATION_ID

Substitua ORGANIZATION_ID pelo ID numérico da organização.

Se não quiser que nenhuma instância tenha acesso a IP externo, pode definir uma política com allValues definido como DENY:

{
  "constraint": "constraints/compute.vmExternalIpAccess",
  "listPolicy": {
    "allValues": "DENY"
  }
}

REST

Use a API setOrgPolicy() para definir a restrição. As instâncias na lista allowedValue que especificar podem ter endereços IP externos. Em alternativa, pode especificar uma lista de deniedValues para expressar instâncias que quer proibir explicitamente de ter um endereço IP externo. Qualquer instância que não esteja na lista tem implicitamente autorização para ter um endereço IP externo. Só pode especificar allowedValues ou deniedValues, mas não ambos.

Por exemplo, o seguinte é um pedido para aplicar a restrição compute.vmExternalIpAccess a uma organização onde as instâncias de determinados projetos na organização podem ter endereços IP externos:

POST https://cloudresourcemanager.googleapis.com/v1/organizations/ORGANIZATION_ID:setOrgPolicy

onde ORGANIZATION_ID é o ID numérico da organização.

Agora, no corpo do pedido, indique a política para esta restrição:

{
  "policy": {
    "constraint": "constraints/compute.vmExternalIpAccess",
    "listPolicy": {
      "allowedValues": [
        "projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME",
        "projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME",
        "projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME"
        ]
      }
    }
 }

Se não quiser que nenhuma instância tenha acesso a IP externo, pode definir uma política com allValues definido como DENY:

{
  "policy": {
    "constraint": "constraints/compute.vmExternalIpAccess",
    "listPolicy": {
      "allValues": "DENY"
      }
    }
 }

Defina a política ao nível do projeto

A definição de uma política ao nível do projeto substitui a política ao nível da organização. Por exemplo, se o nível da organização tiver example-vm-1 na lista allowedValues, mas a política ao nível do projeto tiver a mesma instância na lista deniedValues, a instância não pode ter um endereço IP externo.

Consola

Siga o mesmo processo documentado em Defina uma restrição de política ao nível da organização, mas escolha o seu projeto no seletor de projetos em vez da organização.

Seletor de projetos.

gcloud

Use o comando gcloud resource-manager org-policies set-policy para definir a política. Tem de fornecer a sua política como um ficheiro JSON. Crie um ficheiro JSON no seguinte formato:

{
 "constraint": "constraints/compute.vmExternalIpAccess",
 "listPolicy": {
  "allowedValues": [
   "projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME"
  ]
 }
}

Substitua o seguinte:

  • PROJECT_ID: o ID do projeto para este pedido, como example-project. Tenha em atenção que isto é diferente da configuração das políticas da organização, que requerem o ID numérico da organização.
  • ZONE: a zona da instância.
  • INSTANCE_NAME: o nome da instância.

Em alternativa, pode especificar uma deniedValueslista de instâncias que quer proibir explicitamente de ter um endereço IP externo. Qualquer instância que não esteja na lista tem implicitamente permissão para ter um endereço IP externo. Só pode especificar allowedValues ou deniedValues, mas não ambos.

Em seguida, transmita o ficheiro com o seu pedido:

gcloud resource-manager org-policies set-policy MY_POLICY.JSON --project=example-project

REST

Use a API setOrgPolicy para definir a restrição. As instâncias na lista allowedValue que especificar podem ter endereços IP externos. Em alternativa, pode especificar uma lista deniedValues para expressar instâncias que quer explicitamente proibir de ter um endereço IP externo. Qualquer instância que não esteja na lista tem implicitamente permissão para ter um endereço IP externo. Pode especificar apenas allowedValues ou deniedValues, mas não ambos.

Por exemplo, o seguinte é um pedido para definir a restrição compute.vmExternalIpAccess num projeto para permitir que instâncias específicas tenham endereços IP externos:

POST https://cloudresourcemanager.googleapis.com/v1/projects/PROJECT_ID:setOrgPolicy

Substitua PROJECT_ID pelo ID do projeto para este pedido.

O corpo do pedido contém a política para esta restrição:

{
  "policy": {
    "constraint": "constraints/compute.vmExternalIpAccess",
    "listPolicy": {
      "allowedValues": [
        "projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME"
      ]
    }
  }
}

Práticas recomendadas para restringir endereços IP externos

  • Evite usar a lista deniedValues com esta restrição. Se definir valores na lista deniedValues, significa que apenas as instâncias na lista deniedValues estão restritas de usar endereços IP externos. Isto pode ser um problema de segurança se quiser controlar exatamente que instâncias podem ter endereços IP externos. Se quiser remover determinadas instâncias da lista allowedValues, atualize a política existente para remover as instâncias da lista allowedList, em vez de colocar as instâncias na lista deniedValues numa hierarquia inferior.

  • Se quiser definir uma política numa grande parte da hierarquia de recursos, mas isentar determinados projetos, restaure a política predefinida através do método setOrgPolicy, especificando o objeto restoreDefault para permitir que todas as instâncias nos projetos sejam associadas a endereços IP externos. As políticas atuais para projetos não são afetadas pela predefinição.

  • Use a política da organização juntamente com as funções IAM para controlar melhor o seu ambiente. Esta política aplica-se apenas a instâncias, mas se quiser controlar e restringir melhor os endereços IP externos em dispositivos de rede, pode conceder a função compute.networkAdmin às partes adequadas.

  • Todos os serviços e produtos em execução no Compute Engine na organização ou no projeto com a política ativada estão sujeitos a esta política organizacional. Especificamente, os serviços como o Google Kubernetes Engine, o Dataflow, o Dataproc e o Cloud SQL são afetados por esta política. Se isto for um problema, a Google recomenda que configure outros serviços e produtos num projeto diferente que não tenha a política da organização aplicada e use a VPC partilhada, se necessário.

Faça a gestão de endereços IP externos estáticos

As secções seguintes descrevem como gerir endereços IP externos estáticos para as suas instâncias.

Determine se um endereço IP interno é efémero ou estático

Os endereços IP internos estáticos e efémeros comportam-se e aparecem da mesma forma na maioria dos contextos. No entanto, com endereços IP internos estáticos, pode usar o mesmo endereço IP para o mesmo recurso, mesmo que elimine e recrie o recurso. Em geral, um endereço IP efémero é libertado se parar ou eliminar o recurso.

Para determinar se um endereço é estático ou efémero, faça o seguinte:

  1. Na Google Cloud consola, aceda à página Endereços IP.

    Aceda a Endereços IP

  2. Encontre o endereço na lista e verifique a coluna Tipo para saber o tipo de endereço IP.

Anule a atribuição de um endereço IP externo estático

A anulação da atribuição de um endereço IP remove-o do recurso, mas mantém o endereço IP reservado. Depois de anular a atribuição do endereço IP, pode voltar a atribuí-lo a outro recurso. Este procedimento é suportado para instâncias de pilha dupla, mas não para instâncias apenas de IPv6.

Também pode anular a atribuição do endereço IPv4 ou IPv6 eliminando a instância.

Consola

  1. Na Google Cloud consola, aceda à página Endereços IP.

    Aceda a Endereços IP

  2. Clique em Endereços IP externos.

  3. Selecione o endereço IP estático cuja atribuição quer remover.

  4. Clique em Ver ações e selecione a opção Reatribuir a outro recurso.

  5. Na lista pendente Anexar a, selecione Nenhum.

  6. Clique em OK.

gcloud

  1. Verifique se está a ser usado um endereço IP estático através do comando gcloud compute addresses list:

    gcloud compute addresses list
    

    O resultado é semelhante ao seguinte:

    NAME                      REGION    ADDRESS                  STATUS
    example-address-ipv4      REGION    198.51.100.1             RESERVED
    example-address-new-ipv4  REGION    203.0.113.1              IN_USE
    example-address-ipv6      REGION    2001:db8:1:1:1:1:1:1     RESERVED
    example-address-new-ipv6  REGION    2001:db8:4:4:4:4:4:4     IN_USE
    
    • Se o endereço IP não estiver em utilização, o estado é RESERVED.
    • Se o endereço IP estiver em utilização, o estado é IN_USE.
  2. Recupere o nome da instância que está a usar o endereço IP:

    gcloud compute addresses describe ADDRESS_NAME \
      --region=REGION
    

    Substitua o seguinte:

    • ADDRESS_NAME: o nome do recurso de endereço IPv6.
    • REGION: a região do recurso de endereço IPv6.

    O resultado é semelhante ao seguinte:

    address: IP_ADDRESS
    addressType: EXTERNAL
    ...
    region: https://www.googleapis.com/compute/v1/projects/PROJECT/regions/REGION
    selfLink: https://www.googleapis.com/compute/v1/projects/PROJECT/regions/REGION/addresses/ADDRESS_NAME
    status: IN_USE
    subnetwork: https://www.googleapis.com/compute/v1/projects/PROJECT/regions/REGION/subnetworks/SUBNET
    users:
    - https://www.googleapis.com/compute/v1/projects/PROJECT/zones/ZONE/instances/INSTANCE_NAME
    

    O campo users apresenta o nome da instância que está a usar o endereço IP.

  3. Desassocie o endereço IP da instância.

    • Para anular a atribuição de um endereço IPv4, elimine o ficheiro de configuração de acesso da instância:

      1. Obtenha o nome da configuração de acesso a eliminar. Para obter o nome, use o comando gcloud compute instances describe. Substitua INSTANCE_NAME pelo nome da instância.

        gcloud compute instances describe INSTANCE_NAME
        

        A configuração de acesso é apresentada no seguinte formato:

        networkInterfaces:
          - accessConfigs:
            - kind: compute#accessConfig
              name: external-nat
              natIP: 203.0.113.1
              type: ONE_TO_ONE_NAT
        
      2. Elimine a configuração de acesso através do comando gcloud compute instances delete-access-config:

        gcloud compute instances delete-access-config INSTANCE_NAME \
          --access-config-name="ACCESS_CONFIG_NAME"
        

        Substitua o seguinte:

        • INSTANCE_NAME: o nome da instância.
        • ACCESS_CONFIG_NAME: o nome da configuração de acesso a eliminar. Certifique-se de que inclui o nome completo entre aspas.
    • Para anular a atribuição de um intervalo de endereços IPv6, use o comando instance network-interfaces update:

      gcloud compute instances network-interfaces update INSTANCE_NAME \
        --network-interface=nic0 \
        --stack-type=IPV4_ONLY \
        --zone=ZONE
      

      Substitua o seguinte:

      • INSTANCE_NAME: o nome da instância que está a usar o endereço IP.
      • ZONE: a zona da instância.
  4. Verifique se o seu endereço IP externo estático está agora disponível e marcado como RESERVED em vez de IN_USE.

    gcloud compute addresses list \
      --filter="ADDRESS_NAME AND region=REGION"
    

    Substitua o seguinte:

    • ADDRESS_NAME: o nome do recurso de endereço IP.
    • REGION: a região do recurso de endereço IP.

Agora que o seu endereço IP externo estático está disponível, pode optar por atribuí-lo a outra instância.

REST

Para anular a atribuição de um endereço IPv4 ou IPv6 externo estático, siga os seguintes passos:

  • Para endereços IPv4, elimine a configuração de acesso anexada à instância que está a usar o endereço.

    1. Para verificar os detalhes da configuração de acesso de uma instância, faça um pedido GET ao método instances.get.

      GET https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME
      
    2. Elimine a configuração de acesso existente fazendo um pedido ao instances.deleteAccessConfigmétodo.POST

      POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME/deleteAccessConfig
      

      Substitua o seguinte:

      • PROJECT_ID: o ID do projeto para este pedido
      • ZONE: a zona onde a instância está localizada
      • INSTANCE_NAME: o nome da instância
  • Para endereços IPv6, atualize o tipo de pilha da interface de rede para a instância onde o endereço IPv6 está associado.

    1. Faça um pedido PATCH ao método instances.updateNetworkInterface.

    2. No corpo do pedido, atualize o valor do campo stackType para IPV4_ONLY.

      Por exemplo:

      PATCH https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME/updateNetworkInterface
      
      {
        "networkInterfaces": [{
          ...
          "stackType" : "IPV4_ONLY"
          ...
          }]
      }
      

Java


import com.google.cloud.compute.v1.AccessConfig;
import com.google.cloud.compute.v1.AccessConfig.Type;
import com.google.cloud.compute.v1.Instance;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.NetworkInterface;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class UnassignStaticIpAddress {

  public static void main(String[] args)
          throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // Project ID or project number of the Google Cloud project you want to use.
    String projectId = "your-project-id";
    // Instance ID of the Google Cloud project you want to use.
    String instanceId = "your-instance-id";
    // Name of the zone to create the instance in. For example: "us-west3-b"
    String zone = "your-zone";
    // Name of the network interface to assign.
    String netInterfaceName = "your-netInterfaceName";

    unassignStaticIpAddress(projectId, instanceId, zone, netInterfaceName);
  }

  public static Instance unassignStaticIpAddress(String projectId, String instanceId,
                                                 String zone, String netInterfaceName)
          throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (InstancesClient client = InstancesClient.create()) {
      Instance instance = client.get(projectId, zone, instanceId);
      NetworkInterface networkInterface = null;
      for (NetworkInterface netIterface : instance.getNetworkInterfacesList()) {
        if (netIterface.getName().equals(netInterfaceName)) {
          networkInterface = netIterface;
          break;
        }
      }

      if (networkInterface == null) {
        throw new IllegalArgumentException(
                String.format(
                        "No '{network_interface_name}' variable found on instance %s.",
                        instanceId)
        );
      }

      AccessConfig accessConfig = null;
      for (AccessConfig config : networkInterface.getAccessConfigsList()) {
        if (config.getType().equals(Type.ONE_TO_ONE_NAT.name())) {
          accessConfig = config;
          break;
        }
      }

      if (accessConfig != null) {
        // Delete the existing access configuration first
        client.deleteAccessConfigAsync(projectId, zone, instanceId,
                        accessConfig.getName(), netInterfaceName).get(30, TimeUnit.SECONDS);
      }

      // return updated instance
      return client.get(projectId, zone, instanceId);
    }
  }
}

Python

import uuid

from google.cloud.compute_v1 import InstancesClient
from google.cloud.compute_v1.types import DeleteAccessConfigInstanceRequest


def unassign_static_ip_from_existing_vm(
    project_id: str,
    zone: str,
    instance_name: str,
    network_interface_name: str = "nic0",
):
    """
    Updates access configuration for a VM instance to unassign a static external IP.
    VM (and IP address in case of static IP assigned) must be created before calling this function.

    Args:
        project_id (str): Project ID.
        zone (str): Zone where the VM is located.
        instance_name (str): Name of the VM instance.
        network_interface_name (str): Name of the network interface to unassign.
    """
    client = InstancesClient()
    instance = client.get(project=project_id, zone=zone, instance=instance_name)
    network_interface = next(
        (ni for ni in instance.network_interfaces if ni.name == network_interface_name),
        None,
    )

    if network_interface is None:
        raise ValueError(
            f"No network interface named '{network_interface_name}' found on instance {instance_name}."
        )

    access_config = next(
        (ac for ac in network_interface.access_configs if ac.type_ == "ONE_TO_ONE_NAT"),
        None,
    )

    if access_config:
        # Delete the existing access configuration
        delete_request = DeleteAccessConfigInstanceRequest(
            project=project_id,
            zone=zone,
            instance=instance_name,
            access_config=access_config.name,
            network_interface=network_interface_name,
            request_id=str(uuid.uuid4()),
        )
        delete_operation = client.delete_access_config(delete_request)
        delete_operation.result()

    updated_instance = client.get(project=project_id, zone=zone, instance=instance_name)
    return updated_instance

Libertar um endereço IP externo estático

Se já não precisar de um endereço IPv4 ou IPv6 externo estático, pode libertar o endereço IP eliminando o recurso de endereço IP. A eliminação de uma instância não liberta automaticamente um endereço IP externo estático. Tem de libertar manualmente os endereços IP externos estáticos quando já não precisar deles.

Para libertar um endereço IP externo estático, consulte o artigo Libertar um endereço IP externo estático na documentação da VPC.

O que se segue?