Configurar direcciones IP externas estáticas


Puedes asignar direcciones IP externas estáticas a tus instancias de máquina virtual y Bare Metal. También puedes cambiar, enumerar y liberar direcciones IP estáticas de tus instancias. Para reservar una dirección IP externa estática, consulta el artículo Reservar una dirección IP externa estática.

Las direcciones IP externas pueden ser estáticas o efímeras. Si una instancia requiere una dirección IP externa fija que no cambie, haz lo siguiente:

  1. Obtén una dirección IP externa estática. Puedes reservar nuevas direcciones IP externas o promover direcciones IP externas efímeras.
  2. Asigna la dirección IP reservada a una instancia ya creada o asígnala al crear una instancia.

Si necesitas una dirección IP estática en tu red interna de Compute Engine, consulta Reservar una dirección IP interna estática.

Para obtener información sobre cómo reservar una dirección IP externa estática o crear una dirección IP externa global, consulta Reservar una dirección IP externa estática.

Antes de empezar

  • Consulta información sobre las direcciones IP.
  • Consulta las cuotas y los límites de las direcciones IP externas estáticas.
  • Consulta los precios de las direcciones IP externas.
  • Si aún no lo has hecho, configura la autenticación. La autenticación verifica tu identidad para acceder a Google Cloud servicios y APIs. Para ejecutar código o ejemplos desde un entorno de desarrollo local, puedes autenticarte en Compute Engine seleccionando una de las siguientes opciones:

    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. Instala Google Cloud CLI. Después de la instalación, inicializa la CLI de Google Cloud ejecutando el siguiente comando:

      gcloud init

      Si utilizas un proveedor de identidades (IdP) externo, primero debes iniciar sesión en la CLI de gcloud con tu identidad federada.

    2. Set a default region and zone.

    Terraform

    Para usar las muestras de Terraform de esta página en un entorno de desarrollo local, instala e inicializa la CLI de gcloud y, a continuación, configura las credenciales predeterminadas de la aplicación con tus credenciales de usuario.

      Instala Google Cloud CLI.

      Si utilizas un proveedor de identidades (IdP) externo, primero debes iniciar sesión en la CLI de gcloud con tu identidad 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 obtener más información, consulta Set up authentication for a local development environment.

    REST

    Para usar las muestras de la API REST de esta página en un entorno de desarrollo local, debes usar las credenciales que proporciones a la CLI de gcloud.

      Instala Google Cloud CLI.

      Si utilizas un proveedor de identidades (IdP) externo, primero debes iniciar sesión en la CLI de gcloud con tu identidad federada.

    Para obtener más información, consulta el artículo Autenticarse para usar REST de la documentación sobre autenticación de Google Cloud .

Roles obligatorios

Para obtener los permisos que necesitas para configurar y gestionar direcciones IP estáticas, pide a tu administrador que te conceda los siguientes roles de gestión de identidades y accesos en tu proyecto:

Para obtener más información sobre cómo conceder roles, consulta el artículo Gestionar el acceso a proyectos, carpetas y organizaciones.

Estos roles predefinidos contienen los permisos necesarios para configurar y gestionar direcciones IP estáticas. Para ver los permisos exactos que se necesitan, despliega la sección Permisos necesarios:

Permisos obligatorios

Para configurar y gestionar direcciones IP estáticas, se necesitan los siguientes permisos:

  • compute.instances.update en la instancia
  • compute.instances.updateNetworkInterface en la instancia
  • compute.instances.addAccessConfig en la instancia
  • compute.instances.deleteAccessConfig en la instancia
  • compute.networks.list en la red
  • compute.subnetworks.use en la subred
  • compute.subnetworks.list en la subred
  • Para crear instancias, sigue estos pasos:
    • compute.instances.create en el proyecto
    • Para usar una imagen personalizada para crear la VM, haz clic en compute.images.useReadOnly en la imagen.
    • Para usar una captura para crear la VM, compute.snapshots.useReadOnly en la captura
    • Para usar una plantilla de instancia para crear la VM, haz clic en compute.instanceTemplates.useReadOnly en la plantilla de instancia.
    • Para asignar una red antigua a la VM, haz lo siguiente: compute.networks.use en el proyecto
    • Para especificar una dirección IP estática para la máquina virtual, compute.addresses.use en el proyecto
    • Para asignar una dirección IP externa a la VM cuando se usa una red antigua, haz lo siguiente: compute.networks.useExternalIp en el proyecto
    • Para especificar una subred para la VM, compute.subnetworks.use en el proyecto o en la subred elegida.
    • Para asignar una dirección IP externa a la VM cuando se usa una red de VPC, compute.subnetworks.useExternalIp en el proyecto o en la subred elegida.
    • Para definir los metadatos de la instancia de VM de la VM: compute.instances.setMetadata en el proyecto,
    • Para definir etiquetas en la máquina virtual, compute.instances.setTags en la máquina virtual
    • Para definir etiquetas de la VM, compute.instances.setLabels en la VM
    • Para definir una cuenta de servicio que use la VM, haz lo siguiente en la VM: compute.instances.setServiceAccount
    • Para crear un disco para la VM compute.disks.create del proyecto, sigue estos pasos:
    • Para adjuntar un disco en modo de solo lectura o de lectura y escritura, haz lo siguiente: compute.disks.use en el disco
    • Para adjuntar un disco en modo de solo lectura, compute.disks.useReadOnly en el disco.

También puedes obtener estos permisos con roles personalizados u otros roles predefinidos.

Limitaciones

  • Solo un recurso a la vez puede usar una dirección IP externa estática.

  • No hay forma de comprobar si una dirección IP es estática o efímera después de que se haya asignado a un recurso. Puedes comparar la dirección IP con la lista de direcciones IP externas estáticas reservadas para ese proyecto. Usa el subcomando gcloud compute addresses list para ver una lista de direcciones IP externas estáticas disponibles para el proyecto.

  • Cada VM puede tener varias interfaces de red, y cada interfaz puede tener asignadas las siguientes direcciones IP según su tipo de pila:

    • Interfaces solo IPv4:
      • Una dirección IPv4 interna (obligatoria)
      • Una dirección IPv4 externa (opcional)
    • Interfaces de doble pila (IPv4 e IPv6):
      • Una dirección IPv4 interna (obligatoria)
      • Una dirección IPv4 externa (opcional)
      • Un intervalo de direcciones IPv6, ya sea interno o externo, pero no ambos (obligatorio)/96
    • Interfaces solo IPv6:
      • Un intervalo de direcciones IPv6, ya sea interno o externo, pero no ambos (obligatorio)/96
  • No puedes desasignar ni cambiar la dirección IPv6 externa de una VM con una interfaz de red solo IPv6. Sin embargo, puedes convertir una dirección IP externa efímera de un recurso en una dirección IP externa estática para que la dirección siga reservada incluso después de que se elimine el recurso.

  • No puedes cambiar el nombre de una dirección IP estática.

Nota: Las interfaces de red pueden recibir tráfico de varias reglas de reenvío, que pueden servir otras direcciones IP externas. Cualquier número de direcciones IP externas puede hacer referencia a una interfaz de red a través de estas reglas de reenvío, pero a cada interfaz de red solo se le puede asignar una dirección IPv4 externa y un intervalo de direcciones IPv6 externas /96.

Para obtener más información sobre el balanceo de carga y las reglas de reenvío, consulta la documentación sobre el balanceo de carga.

Ver las direcciones IP externas estáticas disponibles

Para ver una lista de las direcciones IP externas estáticas que has reservado para tu proyecto, sigue estos pasos.

Consola

  1. En la Google Cloud consola, ve a la página Direcciones IP.

    Ir a direcciones IP

  2. Haz clic en Direcciones IP externas.

gcloud

Usa el comando gcloud compute addresses list:

  • Para obtener una lista de todas las direcciones IP, usa el siguiente comando:

    gcloud compute addresses list
  • Para ver una lista con todas las direcciones IP globales, usa el siguiente comando:

    gcloud compute addresses list --global
  • Para obtener una lista con todas las direcciones IP regionales de una región determinada, usa el siguiente comando:

    gcloud compute addresses list \
        --regions=REGION
    

    Sustituye REGION por la región de la que quieras obtener la lista de direcciones. Puede enumerar las direcciones de varias regiones especificando los nombres de las regiones separados por comas:

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

API

  • Para enumerar las direcciones IPv4 o IPv6 regionales, llama al método addresses.list:

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

    Haz los cambios siguientes:

    • PROJECT_ID: el ID de proyecto de esta solicitud
    • REGION: el nombre de la región de esta solicitud
  • Para obtener una lista de todas las direcciones de todas las regiones, llama al método addresses.aggregatedList:

    GET https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/aggregated/addresses
    
  • Para enumerar las direcciones IPv4 o IPv6 globales, llama al método globalAddresses.list:

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

    Haz los cambios siguientes:

    PROJECT_ID: el ID de proyecto de esta solicitud

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

Configurar direcciones IP externas estáticas

En las siguientes secciones se describe cómo configurar direcciones IP externas estáticas para sus instancias.

Crear una instancia que use una dirección IP externa estática

Una vez que hayas reservado una dirección IP externa estática, puedes asignarla a una instancia.

Consola

  1. En la Google Cloud consola, ve a la página Crear una instancia.

    Ir a Crear una instancia

  2. Para asignar una dirección IP externa estática a la instancia, haz lo siguiente:

    1. En el menú de navegación, haga clic en Redes.

    2. En la sección Interfaces de red, especifica las interfaces de red que quieras usar en la instancia con las siguientes opciones:

      • Para añadir una interfaz de red, haz clic en Añadir interfaz de red. A continuación, en la lista Red, selecciona una red.

      • Para eliminar una interfaz de red, haz clic en Eliminar.

    3. Selecciona una de las opciones siguientes:

      • Para asignar una dirección IPv4 externa estática, sigue estos pasos:

        1. Despliega una interfaz de red.
        2. Selecciona la dirección IP de la lista Dirección IPv4 externa.
      • Para asignar una dirección IPv6 externa estática, sigue estos pasos:

        1. Expande una interfaz de red que contenga una subred con un intervalo de direcciones IPv6 externas.
        2. Seleccione esa subred en la lista Subred.
        3. En Tipo de pila de IP, selecciona IPv4 e IPv6 (pila dual) o IPv6 (pila única).
        4. Selecciona la dirección IPv6 externa recién reservada en la lista Dirección IPv6 externa. También puedes seleccionar Reservar dirección IPv6 externa estática y reservar una nueva dirección IPv6 externa estática.
        5. En Nivel de servicio de red, seleccione Premium.
    4. Para terminar de modificar la interfaz de red, haz clic en Hecho.

  3. Continúa con el proceso de creación de la instancia.

gcloud

Puedes crear una instancia y asignarle una dirección IP externa regional estática que ya hayas reservado.

  • Para asignar una dirección IPv4 externa estática, sigue estos pasos:

    gcloud compute instances create INSTANCE_NAME \
        --zone=ZONE \
        --address=IPV4_ADDRESS
    
  • Para asignar una dirección IPv6 externa estática, sigue estos pasos:

    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
    

    Haz los cambios siguientes:

    • INSTANCE_NAME: el nombre de la instancia de computación.
    • ZONE: la zona en la que se creará la instancia
    • IPV4_ADDRESS: la dirección IPv4 que se asignará a la instancia. Usa la dirección IP externa estática reservada, no el nombre de la dirección.
    • SUBNET: una subred que contiene direcciones IPv6 externas
    • STACK_TYPE: el tipo de pila de la instancia, ya sea IPV4_IPV6 (pila dual) o IPV6_ONLY
    • IPV6_ADDRESS: la dirección IPv6 que se asignará a la instancia. Usa la dirección IP externa estática reservada, no el nombre de la dirección.

Terraform

Puede usar el recurso google_compute_instance para asignar una dirección IP externa.

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 asignar una dirección IPv4 externa estática a una instancia de computación nueva, sigue estos pasos:

    En tu solicitud para crear una instancia, proporciona explícitamente la propiedad networkInterfaces[].accessConfigs[].natIP y la dirección IPv4 externa que quieras usar. Por ejemplo:

    {
      "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"
             }
      }]
    }
    

    Haz los cambios siguientes:

    • INSTANCE_NAME: el nombre de la instancia de computación
    • ZONE: la zona en la que se creará la instancia
    • MACHINE_TYPE: opcional: URL completa o parcial del recurso de tipo de máquina que se usará al crear la instancia, con el siguiente formato: zones/ZONE/machineTypes/MACHINE_TYPE
    • IPV4_ADDRESS: la dirección IPv4 que se asignará a la instancia. Usa la dirección IP externa estática reservada, no el nombre de la dirección.
    • SOURCE_IMAGE: una versión específica de una imagen pública, como projects/debian-cloud/global/images/debian-10-buster-v20200309, o una familia de imágenes, como projects/debian-cloud/global/images/family/debian-10.
  • Para asignar una dirección IPv6 externa estática a una instancia nueva, haz lo siguiente:

    En tu solicitud para crear una instancia, proporciona explícitamente la propiedad networkInterfaces[].ipv6AccessConfigs[].externalIpv6 y la dirección IPv6 externa que quieras usar. Por ejemplo:

    {
      "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"
          },
      }],
    }
    

    Haz los cambios siguientes:

    • INSTANCE_NAME: el nombre de la instancia de computación
    • ZONE: la zona en la que se creará la instancia
    • MACHINE_TYPE: opcional. URL completa o parcial del recurso de tipo de máquina que se usará al crear la instancia, con el siguiente formato: zones/ZONE/machineTypes/MACHINE_TYPE
    • IPV6_ADDRESS: la dirección IPv6 que se asignará a la instancia. Usa la dirección IP externa estática reservada, no el nombre de la dirección.
    • STACK_TYPE: el tipo de pila de la instancia, que puede ser IPV4_IPV6 (pila dual) o IPV6_ONLY
    • SUBNET: una subred que contiene direcciones IPv6 externas
    • SOURCE_IMAGE: una versión específica de una imagen pública, como "projects/debian-cloud/global/images/debian-10-buster-v20200309", o una familia de imágenes, 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

Cambiar o asignar una dirección IP externa a una instancia ya creada

Puedes cambiar o asignar una dirección IP externa, ya sea efímera o estática, a una instancia de solo IPv4 o de pila dual que ya exista. Este procedimiento no se admite en instancias que solo usen IPv6.

Una instancia de proceso puede tener varias interfaces. Una interfaz de pila única puede tener una dirección IP externa. Una interfaz de doble pila puede tener una dirección IPv4 externa y una dirección IPv6 externa. Si la instancia ya tiene una dirección IP externa, primero debes quitarla. Después, puedes asignar una nueva dirección IP externa a la instancia.

Consola

  1. En la consola de Google Cloud , ve a la página Instancias de VM.

    Ir a instancias de VM

  2. Haga clic en el nombre de la instancia a la que quiera asignar una IP externa. Se muestra la página Detalles de la instancia.

  3. En la página Detalles de la instancia, sigue estos pasos:

    1. Haz clic en Editar.
    2. Despliega Interfaces de red.
    3. Selecciona la dirección IP externa que quieras asignar a la instancia. Si la instancia es solo IPv4 y quieres asignarle una dirección IPv6, primero debes cambiar el tipo de pila a doble pila.
      1. En Dirección IPv4 externa, selecciona Efímera o una dirección IPv4 externa estática.
      2. En Dirección IPv6 externa, selecciona Efímera (automática), Efímera (personalizada) o una dirección IPv6 externa estática.
    4. Haz clic en Listo.
  4. Haz clic en Guardar.

gcloud

  1. Opcional: Reserva una dirección IP externa estática.

    Si quieres asignar una dirección IP externa estática, debes reservar una dirección y asegurarte de que no la esté usando otro recurso. Si es necesario, sigue las instrucciones para reservar una dirección IP externa estática nueva o para desasignar una dirección IP externa estática.

    Si tienes intención de usar una dirección IP externa efímera, puedes omitir este paso y Compute Engine asignará aleatoriamente una dirección IP externa efímera.

  2. Quita cualquier asignación de dirección IP, tal como se describe en el artículo Anular la asignación de una dirección IP externa estática.

  3. Asigna la nueva dirección IP externa.

    • Para asignar una dirección IPv4, usa el subcomando instances add-access-config:

      Nota: No sustituyas IP_ADDRESS por el nombre de la dirección IP estática. Debes usar la dirección IP real.
      gcloud compute instances add-access-config INSTANCE_NAME \
        --access-config-name="ACCESS_CONFIG_NAME" --address=IP_ADDRESS
      

      Haz los cambios siguientes:

      • INSTANCE_NAME: el nombre de la instancia.
      • ACCESS_CONFIG_NAME: el nombre que se le asignará a esta configuración de acceso. Asegúrate de incluir el nombre completo entre comillas.
      • IP_ADDRESS: la dirección IP que se va a añadir.

      Si quieres que Compute Engine asigne una dirección IP externa efímera en lugar de usar una estática, omite la propiedad --address IP_ADDRESS:

      gcloud compute instances add-access-config INSTANCE_NAME \
        --access-config-name="ACCESS_CONFIG_NAME"
      
    • Para cambiar una instancia a doble pila y asignarle una dirección IPv6, usa el 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
      

      Haz los cambios siguientes:

      • INSTANCE_NAME: el nombre de la instancia.
      • NIC: el nombre de la interfaz de red.
      • STACK_TYPE: el tipo de pila de la instancia, que debe ser IPV4_IPV6. No puedes cambiar el tipo de pila a IPV6_ONLY.
      • IPV6_ADDRESS: la dirección IPv6 que se asignará a la instancia. Especifica la primera dirección IPv6 del intervalo /96.
      • ZONE: la zona de la instancia.

REST

Puedes cambiar la dirección IPv4 o IPv6 externa de una instancia añadiendo una nueva configuración de acceso a esa instancia.

  1. Quita cualquier asignación de dirección IP, tal como se describe en el artículo Anular la asignación de una dirección IP externa estática.

  2. Elimina la configuración de acceso actual haciendo una solicitud POST al método instances.deleteAccessConfig.

    POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME/deleteAccessConfig
    
  3. Añade una nueva configuración de acceso a la interfaz de red de la instancia enviando una solicitud POST al 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

Restringir las direcciones IP externas a instancias específicas

En el caso de algunas cargas de trabajo, es posible que tengas requisitos esenciales, como restricciones de seguridad y de red. Por ejemplo, puede restringir las direcciones IP externas para que solo puedan usarlas determinadas instancias de proceso. Esta opción puede ayudar a evitar la filtración externa de datos o a mantener el aislamiento de la red. Con una política de organización, puedes restringir las direcciones IP externas a instancias específicas con restricciones para controlar el uso de direcciones IP externas de tus instancias en una organización o un proyecto.

La restricción para controlar las direcciones IP externas de las instancias es la siguiente:

constraints/compute.vmExternalIpAccess

Para usar la restricción, especifica una política con un allowedList de instancias que puedan tener direcciones IP externas. Si no especifica ninguna política, se permitirán todas las direcciones IP externas en todas las instancias. Cuando la política está en vigor, solo se puede asignar una dirección IP externa (efímera o estática) a las instancias que se incluyan en la lista allowedValues. Las demás instancias de Compute Engine de la organización o del proyecto que no se definan explícitamente en la política no podrán usar direcciones IP externas.

Las instancias se identifican en las listas de permitidas y denegadas mediante el URI de la instancia:

projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME

Especificaciones para restringir direcciones IP externas

  • Puede aplicar esta restricción de lista solo a instancias.
  • No puedes aplicar la restricción de forma retroactiva. Todas las instancias que tengan direcciones IP externas antes de habilitar la política conservarán sus direcciones IP externas.
  • Esta restricción acepta un allowedList o un deniedList, pero no ambos, en la misma política.
  • Tú o un administrador con los permisos necesarios podéis gestionar y mantener el ciclo de vida y la integridad de la instancia. La restricción solo verifica el URI de la instancia y no impide que las instancias de la lista de permitidas se modifiquen, eliminen o vuelvan a crear.

Permisos necesarios para restringir direcciones IP externas

Para definir una restricción a nivel de proyecto o de organización, debes tener asignado el rol orgpolicy.policyAdmin en la organización.

Definir la restricción de la política a nivel de organización

Consola

  1. Ve a la página Políticas de la organización.

    Ir a Políticas de organización

  2. Si es necesario, selecciona la organización que quieras en el menú desplegable de proyectos.
  3. Haz clic en Define allowed external IPs for VM instances (Definir IPs externas permitidas para instancias de VM).
  4. Haga clic en Editar para modificar la política de IP externa. Si no puedes acceder a la herramienta Editar, significa que no tienes los permisos adecuados.
  5. Selecciona Personalizar para definir la política de la organización en instancias concretas.

    Opción de personalización en la página de edición de la política de la organización.

  6. Seleccione la implementación de la política y el tipo de política que necesite.

  7. En Valores de la política, selecciona Personalizado.

  8. Introduce un URI para una instancia. El URI debe tener el siguiente formato:

    projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME
    
  9. Haz clic en Nuevo valor de política e introduce los URIs de las instancias según sea necesario.

  10. Haz clic en Guardar para aplicar la restricción.

gcloud

Para definir una restricción de acceso a IPs externas, primero necesitas el ID de tu organización. Para encontrar el ID de organización, ejecuta el organizations listcomando y busca el ID numérico en la respuesta:

gcloud organizations list

La CLI de gcloud devuelve una lista de organizaciones con el siguiente formato:

DISPLAY_NAME               ID
example-organization1      29252605212
example-organization2      1234567890

Usa el comando gcloud resource-manager org-policies set-policy para definir la política. Debes proporcionar tu política en un archivo JSON. Crea un archivo JSON con el siguiente 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"
  ]
 }
}

Haz los cambios siguientes:

  • PROJECT_ID: el ID del proyecto de esta solicitud, como example-project. Ten en cuenta que esto es diferente de la configuración de políticas de la organización, que requiere el ID numérico de la organización.
  • ZONE: la zona de la instancia
  • INSTANCE_NAME: el nombre de la instancia

También puede especificar una deniedValues lista para indicar las instancias que quiere prohibir explícitamente que tengan una dirección IP externa. Cualquier instancia que no esté en la lista podrá tener implícitamente una dirección IP externa. Solo puede especificar allowedValues o deniedValues, pero no ambos.

A continuación, envía el archivo con tu solicitud:

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

Sustituye ORGANIZATION_ID por el ID numérico de la organización.

Si no quieres que ninguna instancia tenga acceso a una IP externa, puedes definir una política con allValues en DENY:

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

REST

Usa la API setOrgPolicy() para definir la restricción. Las instancias de la lista allowedValue que especifiques podrán tener direcciones IP externas. También puedes especificar una deniedValues lista para indicar las instancias que quieres que no tengan una dirección IP externa. Cualquier instancia que no esté en la lista podrá tener una dirección IP externa. Solo puedes especificar allowedValues o deniedValues, pero no ambos.

Por ejemplo, la siguiente es una solicitud para aplicar la restricción compute.vmExternalIpAccess a una organización en la que se permite que las instancias de determinados proyectos tengan direcciones IP externas:

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

donde ORGANIZATION_ID es el ID numérico de la organización.

Ahora, en el cuerpo de la solicitud, proporciona la política de esta restricción:

{
  "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"
        ]
      }
    }
 }

Si no quieres que ninguna instancia tenga acceso a una IP externa, puedes definir una política con allValues en DENY:

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

Definir la política a nivel de proyecto

Si se define una política a nivel de proyecto, se anula la política a nivel de organización. Por ejemplo, si el nivel de organización tiene example-vm-1 en la lista allowedValues, pero la política a nivel de proyecto tiene la misma instancia en la lista deniedValues, la instancia no podrá tener una dirección IP externa.

Consola

Sigue el mismo proceso que se describe en Definir una restricción de política a nivel de organización, pero elige tu proyecto en el selector de proyectos en lugar de la organización.

Selector de proyectos.

gcloud

Usa el comando gcloud resource-manager org-policies set-policy para definir la política. Debes proporcionar tu política en un archivo JSON. Crea un archivo JSON con el siguiente formato:

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

Haz los cambios siguientes:

  • PROJECT_ID: el ID del proyecto de esta solicitud, como example-project. Ten en cuenta que esto es diferente de la configuración de políticas de la organización, que requiere el ID numérico de la organización.
  • ZONE: la zona de la instancia.
  • INSTANCE_NAME: el nombre de la instancia.

También puedes especificar una deniedValues lista de instancias a las que quieras prohibir explícitamente que tengan una dirección IP externa. Cualquier instancia que no esté en la lista podrá tener una dirección IP externa. Solo puede especificar allowedValues o deniedValues, pero no ambos.

A continuación, envía el archivo con tu solicitud:

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

REST

Usa la API setOrgPolicy para definir la restricción. Las instancias de la lista allowedValue que especifiques podrán tener direcciones IP externas. También puedes especificar una deniedValues lista para indicar las instancias que quieres prohibir explícitamente que tengan una dirección IP externa. Cualquier instancia que no esté en la lista podrá tener una dirección IP externa. Solo puede especificar allowedValues o deniedValues, pero no ambos.

Por ejemplo, a continuación se muestra una solicitud para definir la restricción compute.vmExternalIpAccess en un proyecto para permitir que instancias específicas tengan direcciones IP externas:

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

Sustituye PROJECT_ID por el ID del proyecto de esta solicitud.

El cuerpo de la solicitud contiene la política de esta restricción:

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

Prácticas recomendadas para restringir direcciones IP externas

  • Evita usar la lista deniedValues con esta restricción. Si define valores en la lista deniedValues, significa que solo las instancias de la lista deniedValues tienen restringido el uso de direcciones IP externas. Esto podría suponer un problema de seguridad si quieres controlar exactamente qué instancias pueden tener direcciones IP externas. Si quieres quitar determinadas instancias de la lista allowedValues, actualiza la política para quitar las instancias de allowedList en lugar de ponerlas en la lista deniedValues en una jerarquía inferior.

  • Si quieres definir una política en una gran parte de la jerarquía de recursos, pero quieres excluir determinados proyectos, restaura la política predeterminada con el método setOrgPolicy especificando el objeto restoreDefault para permitir que todas las instancias de los proyectos se asocien a direcciones IP externas. La configuración predeterminada no afecta a las políticas actuales de los proyectos.

  • Usa la política de organización junto con los roles de gestión de identidades y accesos para controlar mejor tu entorno. Esta política solo se aplica a las instancias, pero si quieres controlar y restringir mejor las direcciones IP externas en los dispositivos de red, puedes asignar el rol compute.networkAdmin a las partes correspondientes.

  • Todos los servicios y productos que se ejecuten en Compute Engine dentro de la organización o el proyecto en el que esté habilitada la política estarán sujetos a esta política de organización. En concreto, esta política afecta a servicios como Google Kubernetes Engine, Dataflow, Dataproc y Cloud SQL. Si esto supone un problema, Google recomienda que configure otros servicios y productos en un proyecto diferente al que no se le aplique la política de la organización y que utilice la VPC compartida, si es necesario.

Gestionar direcciones IP externas estáticas

En las siguientes secciones se describe cómo gestionar las direcciones IP externas estáticas de tus instancias.

Determinar si una dirección IP interna es efímera o estática

Las direcciones IP internas estáticas y efímeras se comportan y aparecen de la misma forma en la mayoría de los contextos. Sin embargo, con las direcciones IP internas estáticas, puedes usar la misma dirección IP para el mismo recurso aunque lo elimines y lo vuelvas a crear. Por lo general, una dirección IP efímera se libera si detienes o eliminas el recurso.

Para determinar si una dirección es estática o efímera, sigue estos pasos:

  1. En la Google Cloud consola, ve a la página Direcciones IP.

    Ir a direcciones IP

  2. Busca la dirección en la lista y consulta la columna Tipo para ver el tipo de dirección IP.

Anular la asignación de una dirección IP externa estática

Si anulas la asignación de una dirección IP, se eliminará del recurso, pero la dirección IP seguirá reservada. Una vez que se haya desasignado la dirección IP, podrá reasignarla a otro recurso. Este procedimiento se admite en instancias de pila dual, pero no en instancias solo IPv6.

También puedes desasignar la dirección IPv4 o IPv6 eliminando la instancia.

Consola

  1. En la Google Cloud consola, ve a la página Direcciones IP.

    Ir a direcciones IP

  2. Haz clic en Direcciones IP externas.

  3. Selecciona la dirección IP estática que quieras desasignar.

  4. Haz clic en Ver acciones y selecciona la opción Reasignar a otro recurso.

  5. En la lista desplegable Adjuntar a, selecciona Ninguno.

  6. Haz clic en Aceptar.

gcloud

  1. Para comprobar si una dirección IP estática se está utilizando, usa el comando gcloud compute addresses list:

    gcloud compute addresses list
    

    El resultado debería ser similar al siguiente:

    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
    
    • Si la dirección IP no está en uso, el estado es RESERVED.
    • Si la dirección IP está en uso, el estado es IN_USE.
  2. Recupera el nombre de la instancia que usa la dirección IP:

    gcloud compute addresses describe ADDRESS_NAME \
      --region=REGION
    

    Haz los cambios siguientes:

    • ADDRESS_NAME: nombre del recurso de dirección IPv6.
    • REGION: la región del recurso de dirección IPv6.

    El resultado debería ser similar al siguiente:

    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
    

    En el campo users se muestra el nombre de la instancia que usa la dirección IP.

  3. Desasigna la dirección IP de la instancia.

    • Para desasignar una dirección IPv4, elimina el archivo de configuración de acceso de la instancia:

      1. Obtén el nombre de la configuración de acceso que quieras eliminar. Para obtener el nombre, usa el comando gcloud compute instances describe. Sustituye INSTANCE_NAME por el nombre de la instancia.

        gcloud compute instances describe INSTANCE_NAME
        

        La configuración de acceso tiene el siguiente formato:

        networkInterfaces:
          - accessConfigs:
            - kind: compute#accessConfig
              name: external-nat
              natIP: 203.0.113.1
              type: ONE_TO_ONE_NAT
        
      2. Elimina la configuración de acceso con el comando gcloud compute instances delete-access-config:

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

        Haz los cambios siguientes:

        • INSTANCE_NAME: el nombre de la instancia.
        • ACCESS_CONFIG_NAME: el nombre de la configuración de acceso que se va a eliminar. No olvides incluir el nombre completo entre comillas.
    • Para desasignar un intervalo de direcciones IPv6, usa el comando instance network-interfaces update:

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

      Haz los cambios siguientes:

      • INSTANCE_NAME: el nombre de la instancia que usa la dirección IP.
      • ZONE: la zona de la instancia.
  4. Comprueba que tu dirección IP externa estática esté disponible y marcada como RESERVED en lugar de IN_USE.

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

    Haz los cambios siguientes:

    • ADDRESS_NAME: el nombre del recurso de dirección IP.
    • REGION: la región del recurso de dirección IP.

Ahora que tienes disponible tu dirección IP externa estática, puedes asignarla a otra instancia.

REST

Para desasignar una dirección IPv4 o IPv6 externa estática, sigue estos pasos:

  • En el caso de las direcciones IPv4, elimina la configuración de acceso asociada a la instancia que usa la dirección.

    1. Para consultar los detalles de configuración de acceso de una instancia, haz una solicitud GET al método instances.get.

      GET https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME
      
    2. Elimina la configuración de acceso actual haciendo una solicitud POST al método instances.deleteAccessConfig.

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

      Haz los cambios siguientes:

      • PROJECT_ID: el ID del proyecto de esta solicitud
      • ZONE: la zona en la que se encuentra la instancia
      • INSTANCE_NAME: el nombre de la instancia
  • En el caso de las direcciones IPv6, actualiza el tipo de pila de la interfaz de red de la instancia a la que está asociada la dirección IPv6.

    1. Realiza una solicitud PATCH al método instances.updateNetworkInterface.

    2. En el cuerpo de la solicitud, actualiza el valor del campo stackType a IPV4_ONLY.

      Por ejemplo:

      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

Liberar una dirección IP externa estática

Si ya no necesitas una dirección IPv4 o IPv6 externa estática, puedes liberar la dirección IP eliminando el recurso de dirección IP. Si eliminas una instancia, no se libera automáticamente una dirección IP externa estática. Debes liberar manualmente las direcciones IP externas estáticas cuando ya no las necesites.

Para liberar una dirección IP externa estática, consulta el artículo Liberar una dirección IP externa estática de la documentación de VPC.

Siguientes pasos