Configurar endereços IP externos estáticos


Você pode atribuir endereços IP externos estáticos à sua máquina virtual (VM) e às instâncias bare metal. Você também pode alterar, listar e liberar endereços IP estáticos para suas instâncias. Para reservar um endereço IP externo estático, consulte Reservar um endereço IP externo estático .

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

  1. Obtenha um endereço IP externo estático. Você pode reservar novos endereços IP externos ou promover endereços IP externos temporários existentes.
  2. Atribua o endereço IP reservado a uma instância existente ou atribua-o ao criar uma nova instância.

Se você precisar de um endereço IP estático na rede interna do Compute Engine, consulte Reservar 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 Reservar um endereço IP externo estático .

Antes de começar

Funções obrigatórias

Para obter as permissões necessárias para configurar e gerenciar endereços IP estáticos, peça ao administrador para conceder a você as seguintes funções do IAM em seu projeto:

Para obter mais informações sobre a concessão de funções, consulte Gerenciar acesso a projetos, pastas e organizações .

Essas funções predefinidas contêm as permissões necessárias para configurar e gerenciar endereços IP estáticos. Para ver as permissões exatas necessárias, expanda a seção Permissões necessárias :

Permissões necessárias

As seguintes permissões são necessárias para configurar e gerenciar 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 legada à 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 ao usar uma rede legada: 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 ao usar uma rede VPC: compute.subnetworks.useExternalIp no projeto ou na sub-rede escolhida
    • Para definir metadados de instância de VM para a VM: compute.instances.setMetadata no projeto
    • Para definir tags para a VM: compute.instances.setTags na VM
    • Para definir rótulos 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 somente leitura ou leitura-gravação: compute.disks.use no disco
    • Para anexar um disco existente no modo somente leitura: compute.disks.useReadOnly no disco

Você também poderá obter essas permissões com funções personalizadas ou outras funções predefinidas .

Limitações

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

  • Não há como verificar se um endereço IP é estático ou efêmero depois de ter sido atribuído a um recurso. Você 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 múltiplas interfaces de rede, e cada interface pode ter os seguintes endereços IP atribuídos de acordo com seu tipo de pilha :

    • Interfaces somente 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 /96 , interno ou externo, mas não ambos (obrigatório)
    • Interfaces somente IPv6 ( Visualização ):
      • Um intervalo de endereços IPv6 /96 , interno ou externo, mas não ambos (obrigatório)
  • Não é possível cancelar a atribuição ou alterar o endereço IPv6 externo de uma VM com uma interface de rede somente IPv6. No entanto, você 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 depois que o recurso for excluído.

  • Você não pode alterar o nome de um endereço IP estático.

Observação: as interfaces de rede podem receber tráfego de diversas regras de encaminhamento , que podem servir outros endereços IP externos. Qualquer número de endereços IP externos pode fazer referência a uma interface de rede por meio dessas regras de encaminhamento, mas cada interface de rede pode receber apenas um endereço IPv4 externo e um intervalo de endereços IPv6 /96 externo.

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

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

Para listar endereços IP externos estáticos que você reservou para o seu projeto, siga estas etapas.

Console

  1. No console do Google Cloud, acesse a página de endereços IP .

    Vá para endereços IP

  2. Clique em Endereços IP externos .

gcloud

Use o comando gcloud compute addresses list :

  • Para listar todos os endereços IP, use o seguinte comando:

    gcloud compute addresses list
  • Para listar todos os endereços IP globais, use o seguinte comando:

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

    gcloud compute addresses list \
        --regions=REGION
    

    Substitua REGION pela região para a qual você deseja listar os endereços. Você pode listar endereços de diversas regiões especificando nomes de regiões separados por vírgula:

    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 esta solicitação
    • REGION : o nome da região para esta solicitação
  • Para listar todos os endereços 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 esta solicitação

Ir

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());
      }
    }
  }
}

Pitão

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

Configurar endereços IP externos estáticos

As seções a seguir descrevem como configurar endereços IP externos estáticos para 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 , você poderá atribuí-lo a uma instância.

Console

  1. No console do Google Cloud, acesse a página Criar uma instância .

    Vá para 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 seção Interfaces de rede , especifique as interfaces de rede desejadas para a instância usando as 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 excluir uma interface de rede, clique em Excluir .

    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 de endereços IPv4 externos .
      • 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 externo.
        2. Selecione essa sub-rede na lista Sub-rede .
        3. Para o tipo de pilha IP , selecione IPv4 e IPv6 (pilha dupla) ou IPv6 (pilha única) .
        4. Selecione o endereço IPv6 externo recentemente reservado na lista de endereços IPv6 externos . Como alternativa, selecione Reservar endereço IPv6 externo estático e reserve um novo endereço IPv6 externo estático.
        5. Para Nível de serviço de rede , selecione Premium .
    4. Para finalizar a modificação da interface de rede, clique em Concluído .

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

gcloud

Você pode criar uma instância e atribuir um endereço IP externo regional estático que você 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 de computação.
    • ZONE : a zona na qual criar a instância
    • IPV4_ADDRESS : o endereço IPv4 a ser atribuído à 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 da instância, IPV4_IPV6 (pilha dupla) ou IPV6_ONLY
    • IPV6_ADDRESS : o endereço IPv6 a ser atribuído à instância. Use o endereço IP externo estático reservado, não o nome do endereço.

Terraforma

Você 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
    }
  }
}

DESCANSAR

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

    Em sua solicitação para criar uma nova instância , forneça explicitamente a networkInterfaces[].accessConfigs[].natIP e o endereço IPv4 externo que você deseja 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: uma URL completa ou parcial do recurso de tipo de máquina a ser usado ao criar a instância, no formato: zones/ ZONE /machineTypes/ MACHINE_TYPE
    • IPV4_ADDRESS : o endereço IPv4 a ser atribuído à 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:

    Em sua solicitação para criar uma nova instância , forneça explicitamente a propriedade networkInterfaces[].ipv6AccessConfigs[].externalIpv6 e o ​​endereço IPv6 externo que você deseja 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: uma URL completa ou parcial do recurso de tipo de máquina a ser usado ao criar a instância, no formato: zones/ ZONE /machineTypes/ MACHINE_TYPE
    • IPV6_ADDRESS : o endereço IPv6 a ser atribuído à instância. Use o endereço IP externo estático reservado, não o nome do endereço.
    • STACK_TYPE : o tipo de pilha da instância, IPV4_IPV6 (pilha dupla) 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"

Ir


// 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();
  }
}

Pitão

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

Alterar ou atribuir um endereço IP externo a uma instância existente

Você pode alterar ou atribuir um endereço IP externo, temporário ou estático, a uma instância existente somente IPv4 ou de pilha dupla. Este procedimento não é compatível com instâncias somente IPv6.

Uma instância de computação pode ter diversas 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, você deverá primeiro remover esse endereço . Em seguida, você poderá atribuir um novo endereço IP externo à instância existente.

Console

  1. No console do Google Cloud, acesse a página de instâncias de VM .

    Acesse as instâncias de VM

  2. Clique no nome da instância à qual você deseja atribuir um IP externo. A página de detalhes da instância é exibida.

  3. Na página de detalhes da instância , conclua as etapas a seguir:

    1. Clique em Editar .
    2. Expanda Interfaces de rede .
    3. Selecione o endereço IP externo necessário para atribuir à instância. Se a instância for somente IPv4 e você quiser atribuir um endereço IPv6, primeiro deverá alterar o tipo de pilha para pilha dupla.
      1. Para Endereço IPv4 externo , selecione Temporário ou um endereço IPv4 externo estático.
      2. Para Endereço IPv6 externo , selecione Temporário ou um endereço IPv6 externo estático.
    4. Clique em Concluído .
  4. Clique em Salvar .

gcloud

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

    Se quiser atribuir um endereço IP externo estático, você deverá reservar um endereço e certificar-se de que o endereço não esteja em uso por outro recurso. Se necessário, siga as instruções para reservar um novo endereço IP externo estático ou para cancelar a atribuição de um endereço IP externo estático .

    Se você pretende usar um endereço IP externo temporário, ignore esta etapa e o Compute Engine atribuirá aleatoriamente um endereço IP externo temporário.

  2. Remova qualquer atribuição de endereço IP existente, conforme descrito em Cancelar atribuição de 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. Você deve 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 para chamar esta configuração de acesso. Certifique-se de incluir o nome completo entre aspas.
      • IP_ADDRESS : o endereço IP a ser adicionado.

      Se você quiser que o Compute Engine atribua um endereço IP externo temporário 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 a ela 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 da instância, que deve ser IPV4_IPV6 . Você não pode alterar o tipo de pilha para IPV6_ONLY.
      • IPV6_ADDRESS : o endereço IPv6 a ser atribuído à instância. Especifique o primeiro endereço IPv6 no intervalo /96 .
      • ZONE : a zona da instância.

DESCANSAR

Você 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 em Cancelar atribuição de um endereço IP externo estático .

  2. Exclua a configuração de acesso existente fazendo uma solicitação POST para o 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 fazendo uma solicitação POST ao método instances.addAccessConfig .

Ir

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);
    }
  }
}

Pitão

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

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

Para determinadas cargas de trabalho, você pode ter requisitos essenciais que incluem restrições de segurança e de rede. Por exemplo, talvez você queira restringir endereços IP externos para que apenas instâncias de computação específicas possam usá-los. Esta opção pode ajudar a evitar a exfiltração de dados ou manter o isolamento da rede. Usando uma Política da Organização , você pode restringir endereços IP externos a instâncias específicas com restrições para controlar o uso de endereços IP externos para suas instâncias em uma organização ou projeto.

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

constraints/compute.vmExternalIpAccess

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

As instâncias são identificadas nas listas de permissão e negação usando o URI da instância:

projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME

Especificações para restringir endereços IP externos

  • Você pode aplicar essa restrição de lista somente a instâncias.
  • Você não pode aplicar a restrição retroativamente. Todas as instâncias que possuem endereços IP externos antes de você ativar a política mantêm seus endereços IP externos.
  • Esta restrição aceita uma allowedList ou uma deniedList , mas não ambas na mesma política.
  • Cabe a você ou a um administrador com as permissões necessárias gerenciar e manter o ciclo de vida e a integridade da instância. A restrição verifica apenas o URI da instância e não impede que as instâncias na lista de permissões sejam alteradas, excluídas ou recriadas.

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

Para definir uma restrição no nível do projeto ou da organização, você deve ter recebido a função orgpolicy.policyAdmin na organização.

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

Console

  1. Vá para a página Políticas Organizacionais .

    Vá para Políticas Organizacionais

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

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

  6. Selecione a aplicação da política e o tipo de política necessários.

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

  8. Insira um URI para uma instância. O URI deve estar no seguinte formato:

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

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

gcloud

Para definir uma restrição para acesso IP externo, primeiro você precisa do ID da sua organização. Você 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 retorna 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. Você precisa fornecer sua política como um arquivo JSON. Crie um arquivo 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 esta solicitação, como example-project . Observe que isso é diferente de configurar políticas da organização, que exigem o ID numérico da organização.
  • ZONE : a zona da instância
  • INSTANCE_NAME : o nome da instância

Alternativamente, você pode especificar uma lista deniedValues ​​para indicar instâncias que você deseja proibir explicitamente de terem um endereço IP externo. Qualquer instância que não estivesse na lista teria permissão implícita para ter um endereço IP externo. Você só pode especificar allowedValues ​​ou deniedValues , mas não ambos.

Em seguida, passe o arquivo com sua solicitação:

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 IP externo, você pode definir uma política com allValues ​​definido como DENY :

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

DESCANSAR

Use a API setOrgPolicy() para definir sua restrição. As instâncias na lista allowedValue especificada podem ter endereços IP externos. Como alternativa, você pode especificar uma lista deniedValues ​​para expressar instâncias que você deseja proibir explicitamente de terem um endereço IP externo. Qualquer instância que não estivesse na lista teria permissão implícita para ter um endereço IP externo. Você só pode especificar allowedValues ​​ou deniedValues , mas não ambos.

Por exemplo, a seguir está uma solicitação para aplicar a restrição compute.vmExternalIpAccess a uma organização onde instâncias de determinados projetos dentro da 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 da sua solicitação, forneça 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 IP externo, você pode definir uma política com allValues ​​definido como DENY :

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

Defina a política no nível do projeto

Definir uma política no nível do projeto substitui a política no 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 no nível do projeto tiver a mesma instância na lista deniedValues , a instância não poderá ter um endereço IP externo.

Console

Siga o mesmo processo documentado em Definir uma restrição de política no nível da organização, mas escolha 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. Você precisa fornecer sua política como um arquivo JSON. Crie um arquivo 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 esta solicitação, como example-project . Observe que isso é diferente de configurar políticas da organização, que exigem o ID numérico da organização.
  • ZONE : a zona da instância.
  • INSTANCE_NAME : o nome da instância.

Como alternativa, você pode especificar uma lista deniedValues ​​de instâncias que deseja proibir explicitamente de terem um endereço IP externo. Qualquer instância que não estivesse na lista teria permissão implícita para ter um endereço IP externo. Você só pode especificar allowedValues ​​ou deniedValues , mas não ambos.

Em seguida, passe o arquivo com sua solicitação:

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

DESCANSAR

Use a API setOrgPolicy para definir sua restrição. As instâncias na lista allowedValue especificada podem ter endereços IP externos. Como alternativa, você pode especificar uma lista deniedValues ​​para expressar instâncias que você deseja proibir explicitamente de terem um endereço IP externo. Qualquer instância que não esteja na lista pode implicitamente ter um endereço IP externo. Você pode especificar apenas allowedValues ​​ou deniedValues , mas não ambos.

Por exemplo, veja a seguir uma solicitação para definir a restrição compute.vmExternalIpAccess em um 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 desta solicitação.

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

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

Melhores práticas para restringir endereços IP externos

  • Evite usar a lista deniedValues ​​com esta restrição. Se você definir valores na lista deniedValues , isso significa que apenas as instâncias na lista deniedValues ​​terão acesso restrito ao uso de endereços IP externos. Isso pode ser uma preocupação de segurança se você quiser controlar exatamente quais instâncias podem ter endereços IP externos. Se você quiser remover determinadas instâncias da lista allowedValues , atualize a política existente para remover as instâncias da allowedList em vez de colocar as instâncias na lista deniedValues ​​em uma hierarquia inferior.

  • Se você quiser definir uma política em uma grande parte da hierarquia de recursos, mas isentar determinados projetos, restaure a política padrão usando o 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 configuração padrão.

  • Use a política organizacional junto com as funções do IAM para controlar melhor seu ambiente. Esta política se aplica apenas a instâncias, mas se você quiser controlar melhor e restringir endereços IP externos em dispositivos de rede, poderá conceder a função compute.networkAdmin às partes apropriadas.

  • 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 da organização. Especificamente, serviços como Google Kubernetes Engine, Dataflow, Dataproc e Cloud SQL são afetados por esta política. Se isso for um problema, o Google recomenda que você configure outros serviços e produtos em um projeto diferente que não tenha a política da organização aplicada e use a VPC compartilhada , se necessário.

Gerenciar endereços IP externos estáticos

As seções a seguir descrevem como gerenciar endereços IP externos estáticos para suas instâncias.

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

Endereços IP internos estáticos e efêmeros se comportam e aparecem da mesma forma na maioria dos contextos. No entanto, com endereços IP internos estáticos, você pode usar o mesmo endereço IP para o mesmo recurso, mesmo se excluir e recriar o recurso. Em geral, um endereço IP temporário é liberado se você interromper ou excluir o recurso.

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

  1. No console do Google Cloud, acesse a página de endereços IP .

    Vá para endereços IP

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

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

Cancelar a atribuição de um endereço IP remove-o do recurso, mas mantém o endereço IP reservado. Após a atribuição do endereço IP, você poderá reatribuir o endereço IP a outro recurso. Este procedimento é compatível com instâncias de pilha dupla, mas não com instâncias somente IPv6.

Você também pode cancelar a atribuição do endereço IPv4 ou IPv6 excluindo a instância .

Console

  1. No console do Google Cloud, acesse a página de endereços IP .

    Vá para endereços IP

  2. Clique em Endereços IP externos .

  3. Selecione o endereço IP estático cuja atribuição você deseja cancelar.

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

  5. Na lista suspensa Anexar a , selecione Nenhum .

  6. Clique em OK .

gcloud

  1. Verifique se um endereço IP estático está em uso usando o comando gcloud compute addresses list :

    gcloud compute addresses list
    

    A saída é semelhante à 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 uso, o status será RESERVED .
    • Se o endereço IP estiver em uso, o status será IN_USE .
  2. Recupere o nome da instância que está usando 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.

    A saída é semelhante à 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 exibe o nome da instância que está usando o endereço IP.

  3. Cancele a atribuição do endereço IP da instância.

    • Para cancelar a atribuição de um endereço IPv4, exclua o arquivo de configuração de acesso da instância:

      1. Obtenha o nome da configuração de acesso a ser excluída. 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 aparece no seguinte formato:

        networkInterfaces:
          - accessConfigs:
            - kind: compute#accessConfig
              name: external-nat
              natIP: 203.0.113.1
              type: ONE_TO_ONE_NAT
        
      2. Exclua a configuração de acesso usando o 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 ser excluída. Certifique-se de incluir o nome completo entre aspas.
    • Para cancelar 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á usando o endereço IP.
      • ZONE : a zona da instância.
  4. Verifique se o seu endereço IP externo estático agora está 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 seu endereço IP externo estático está disponível, você pode optar por atribuí-lo a outra instância .

DESCANSAR

Para cancelar a atribuição de um endereço IPv4 ou IPv6 externo estático, execute as seguintes etapas:

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

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

      GET https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME
      
    2. Exclua a configuração de acesso existente fazendo uma solicitação POST para o método instances.deleteAccessConfig .

      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 esta solicitação
      • 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 da instância à qual o endereço IPv6 está anexado.

    1. Faça uma solicitação PATCH para o método instances.updateNetworkInterface .

    2. No corpo da solicitação, 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);
    }
  }
}

Pitão

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

Liberar um endereço IP externo estático

Se você não precisar mais de um endereço IPv4 ou IPv6 externo estático, poderá liberar o endereço IP excluindo o recurso de endereço IP. A exclusão de uma instância não libera automaticamente um endereço IP externo estático. Você deverá liberar manualmente endereços IP externos estáticos quando não precisar mais deles.

Para liberar um endereço IP externo estático, consulte Liberar um endereço IP externo estático na documentação da VPC.

O que vem a seguir