Configurar direcciones IP externas estáticas


Puede asignar direcciones IP externas estáticas a su máquina virtual (VM) e instancias bare metal. También puede cambiar, enumerar y liberar direcciones IP estáticas para sus instancias. Para reservar una dirección IP externa estática, consulte 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 cambia, haga lo siguiente:

  1. Obtenga una dirección IP externa estática. Puede reservar nuevas direcciones IP externas o promocionar direcciones IP externas efímeras existentes.
  2. Asigne la dirección IP reservada a una instancia existente o asígnela al crear una nueva instancia.

Si necesita una dirección IP estática en su red interna de Compute Engine, consulte 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, consulte Reservar una dirección IP externa estática .

Antes de comenzar

Roles requeridos

Para obtener los permisos que necesita para configurar y administrar direcciones IP estáticas, solicite a su administrador que le otorgue las siguientes funciones de IAM en su proyecto:

Para obtener más información sobre cómo otorgar roles, consulte Administrar el acceso a proyectos, carpetas y organizaciones .

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

Permisos requeridos

Se requieren los siguientes permisos para configurar y administrar direcciones IP estáticas:

  • 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:
    • compute.instances.create en el proyecto.
    • Para usar una imagen personalizada para crear la VM: compute.images.useReadOnly en la imagen
    • Para usar una instantánea para crear la VM: compute.snapshots.useReadOnly en la instantánea
    • Para usar una plantilla de instancia para crear la VM: compute.instanceTemplates.useReadOnly en la plantilla de instancia
    • Para asignar una red heredada a la VM: compute.networks.use en el proyecto
    • Para especificar una dirección IP estática para la VM: compute.addresses.use en el proyecto
    • Para asignar una dirección IP externa a la VM cuando se usa una red heredada: 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 VPC: compute.subnetworks.useExternalIp en el proyecto o en la subred elegida
    • Para configurar metadatos de instancia de VM para la VM: compute.instances.setMetadata en el proyecto
    • Para configurar etiquetas para la VM: compute.instances.setTags en la VM
    • Para configurar etiquetas para la VM: compute.instances.setLabels en la VM
    • Para configurar una cuenta de servicio para que la use la VM: compute.instances.setServiceAccount en la VM
    • Para crear un nuevo disco para la VM: compute.disks.create en el proyecto
    • Para conectar un disco existente en modo de solo lectura o lectura-escritura: compute.disks.use en el disco
    • Para conectar un disco existente en modo de solo lectura: compute.disks.useReadOnly en el disco

Es posible que también pueda obtener estos permisos con roles personalizados u otros roles predefinidos .

Limitaciones

  • Sólo un recurso a la vez puede utilizar 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 haber sido asignada a un recurso. Puede 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 múltiples interfaces de red y cada interfaz puede tener las siguientes direcciones IP asignadas 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 rango de direcciones IPv6 /96 , ya sea interno o externo, pero no ambos (obligatorio)
    • Interfaces solo IPv6 ( vista previa ):
      • Un rango de direcciones IPv6 /96 , ya sea interno o externo, pero no ambos (obligatorio)
  • No puede desasignar ni cambiar la dirección IPv6 externa de una máquina virtual con una interfaz de red solo IPv6. Sin embargo, puede promover una dirección IP externa efímera de un recurso a una dirección IP externa estática para que la dirección permanezca reservada incluso después de que se elimine el recurso.

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

Nota: Las interfaces de red pueden recibir tráfico de múltiples reglas de reenvío , que podrían servir a otras direcciones IP externas. Cualquier cantidad 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 rango de direcciones IPv6 externo /96 .

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

Ver direcciones IP externas estáticas disponibles

Para enumerar las direcciones IP externas estáticas que ha reservado para su proyecto, siga estos pasos.

Consola

  1. En la consola de Google Cloud, vaya a la página de direcciones IP .

    Ir a direcciones IP

  2. Haga clic en Direcciones IP externas .

nube de gcloud

Usa el comando gcloud compute addresses list :

  • Para enumerar todas las direcciones IP, utilice el siguiente comando:

    gcloud compute addresses list
  • Para enumerar todas las direcciones IP globales, utilice el siguiente comando:

    gcloud compute addresses list --global
  • Para enumerar todas las direcciones IP regionales en una región determinada, utilice el siguiente comando:

    gcloud compute addresses list \
        --regions=REGION
    

    Reemplace REGION con la región para la que desea enumerar las direcciones. Puede enumerar direcciones de varias regiones especificando nombres de región separados por comas:

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

API

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

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

    Reemplace lo siguiente:

    • PROJECT_ID : el ID del proyecto para esta solicitud
    • REGION : el nombre de la región para esta solicitud
  • Para enumerar todas las direcciones en todas las regiones, llame al método addresses.aggregatedList :

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

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

    Reemplace lo siguiente:

    PROJECT_ID : el ID del proyecto para esta solicitud

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ón

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

Las siguientes secciones describen cómo configurar direcciones IP externas estáticas para sus instancias.

Cree una instancia que utilice una dirección IP externa estática

Después de haber reservado una dirección IP externa estática , puede asignarla a una instancia.

Consola

  1. En la consola de Google Cloud, vaya 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, haga lo siguiente:

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

    2. En la sección Interfaces de red , especifique las interfaces de red que desea para la instancia mediante las siguientes opciones:

      • Para agregar una interfaz de red, haga clic en Agregar una interfaz de red . Luego, en la lista Red , seleccione una red.

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

    3. Seleccione una de las siguientes opciones:

      • Para asignar una dirección IPv4 externa estática, haga lo siguiente:

        1. Expandir una interfaz de red.
        2. Seleccione la dirección IP de la lista de direcciones IPv4 externas .
      • Para asignar una dirección IPv6 externa estática, haga lo siguiente:

        1. Expanda una interfaz de red que contenga una subred con un rango de direcciones IPv6 externo.
        2. Seleccione esa subred de la lista Subred .
        3. Para el tipo de pila IP , seleccione IPv4 e IPv6 (pila doble) o IPv6 (pila única) .
        4. Seleccione la dirección IPv6 externa recién reservada de la lista de direcciones IPv6 externas . Alternativamente, seleccione Reservar dirección IPv6 externa estática y reserve una nueva dirección IPv6 externa estática.
        5. Para Nivel de servicio de red , seleccione Premium .
    4. Para terminar de modificar la interfaz de red, haga clic en Listo .

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

nube de gcloud

Puede crear una instancia y asignar una dirección IP externa regional estática que ya haya reservado.

  • Para asignar una dirección IPv4 externa estática, haga lo siguiente:

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

    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
    

    Reemplace lo siguiente:

    • INSTANCE_NAME : el nombre de la instancia informática.
    • ZONE : la zona para crear la instancia en
    • IPV4_ADDRESS : la dirección IPv4 que se asignará a la instancia. Utilice 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 para la instancia, ya sea IPV4_IPV6 (doble pila) o IPV6_ONLY
    • IPV6_ADDRESS : la dirección IPv6 que se asignará a la instancia. Utilice la dirección IP externa estática reservada, no el nombre de la dirección.

Terraformar

Puede utilizar 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
    }
  }
}

DESCANSAR

  • Para asignar una dirección IPv4 externa estática a una nueva instancia informática, haga lo siguiente:

    En su solicitud para crear una nueva instancia , proporcione explícitamente la propiedad networkInterfaces[].accessConfigs[].natIP y la dirección IPv4 externa que desea 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"
             }
      }]
    }
    

    Reemplace lo siguiente:

    • INSTANCE_NAME : el nombre de la instancia informática
    • ZONE : la zona para crear la instancia en
    • MACHINE_TYPE : Opcional: una URL completa o parcial del recurso de tipo de máquina que se utilizará al crear la instancia, en el formato: zones/ ZONE /machineTypes/ MACHINE_TYPE
    • IPV4_ADDRESS : la dirección IPv4 que se asignará a la instancia. Utilice 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 nueva instancia, haga lo siguiente:

    En su solicitud para crear una nueva instancia , proporcione explícitamente la propiedad networkInterfaces[].ipv6AccessConfigs[].externalIpv6 y la dirección IPv6 externa que desea 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"
          },
      }],
    }
    

    Reemplace lo siguiente:

    • INSTANCE_NAME : el nombre de la instancia informática
    • ZONE : la zona para crear la instancia en
    • MACHINE_TYPE : Opcional: una URL completa o parcial del recurso de tipo de máquina que se utilizará al crear la instancia, en el formato: zones/ ZONE /machineTypes/ MACHINE_TYPE
    • IPV6_ADDRESS : la dirección IPv6 que se asignará a la instancia. Utilice la dirección IP externa estática reservada, no el nombre de la dirección.
    • STACK_TYPE : el tipo de pila para la instancia, ya sea IPV4_IPV6 (doble pila) 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"

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ón

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 existente

Puede cambiar o asignar una dirección IP externa, ya sea efímera o estática, a una instancia existente de doble pila o solo IPv4. Este procedimiento no se admite para instancias solo de IPv6.

Una instancia informática 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 debe eliminar esa dirección . Luego puede asignar una nueva dirección IP externa a la instancia existente.

Consola

  1. En la consola de Google Cloud, vaya a la página de instancias de VM .

    Ir a instancias de VM

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

  3. Desde la página de detalles de la instancia , complete los siguientes pasos:

    1. Haga clic en Editar .
    2. Expanda Interfaces de red .
    3. Seleccione la dirección IP externa requerida para asignarla a la instancia. Si la instancia es solo IPv4 y desea asignar una dirección IPv6, primero debe cambiar el tipo de pila a doble pila.
      1. Para Dirección IPv4 externa , seleccione Dirección IPv4 externa efímera o estática.
      2. Para Dirección IPv6 externa , seleccione Dirección IPv6 externa efímera o estática.
    4. Haga clic en Listo .
  4. Haga clic en Guardar .

nube de gcloud

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

    Si desea asignar una dirección IP externa estática, debe reservar una dirección y asegurarse de que la dirección no esté siendo utilizada por otro recurso. Si es necesario, siga las instrucciones para reservar una nueva dirección IP externa estática o desasignar una dirección IP externa estática .

    Si tiene la intención de utilizar una dirección IP externa efímera, puede omitir este paso y Compute Engine asignará aleatoriamente una dirección IP externa efímera.

  2. Elimine cualquier asignación de dirección IP existente, como se describe en Desasignar una dirección IP externa estática .

  3. Asigne la nueva dirección IP externa.

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

      Nota: No reemplace IP_ADDRESS con el nombre de la dirección IP estática. Debe utilizar la dirección IP real.
      gcloud compute instances add-access-config INSTANCE_NAME \
        --access-config-name="ACCESS_CONFIG_NAME" --address=IP_ADDRESS
      

      Reemplace lo siguiente:

      • INSTANCE_NAME : el nombre de la instancia.
      • ACCESS_CONFIG_NAME : el nombre para llamar a esta configuración de acceso. Asegúrese de incluir el nombre completo entre comillas.
      • IP_ADDRESS : la dirección IP a agregar.

      Si deseas que Compute Engine asigne una dirección IP externa efímera en lugar de usar una dirección IP externa 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, utilice 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
      

      Reemplace lo siguiente:

      • 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 puede cambiar el tipo de pila a IPV6_ONLY.
      • IPV6_ADDRESS : la dirección IPv6 que se asignará a la instancia. Especifique la primera dirección IPv6 en el rango /96 .
      • ZONE : la zona de la instancia.

DESCANSAR

Puede cambiar la dirección IPv4 o IPv6 externa de una instancia agregando una nueva configuración de acceso para esa instancia.

  1. Elimine cualquier asignación de dirección IP existente, como se describe en Desasignar una dirección IP externa estática .

  2. Elimine la configuración de acceso existente realizando 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. Agregue una nueva configuración de acceso a la interfaz de red de la instancia realizando una solicitud POST al 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ón

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 direcciones IP externas a instancias específicas

Para determinadas cargas de trabajo, es posible que tenga requisitos esenciales que incluyan restricciones de seguridad y de red. Por ejemplo, es posible que desee restringir las direcciones IP externas para que solo instancias informáticas específicas puedan usarlas. Esta opción puede ayudar a evitar la filtración de datos o mantener el aislamiento de la red. Al utilizar una política de organización , puede restringir las direcciones IP externas a instancias específicas con restricciones para controlar el uso de direcciones IP externas para sus instancias dentro de una organización o un proyecto.

La restricción para controlar la dirección IP externa en las instancias es:

constraints/compute.vmExternalIpAccess

Para utilizar la restricción, especifica una política con una allowedList de instancias que pueden tener direcciones IP externas. Si no especifica una política, se permiten todas las direcciones IP externas para todas las instancias. Cuando la política está implementada, solo a las instancias que figuran en la lista de allowedValues se les puede asignar una dirección IP externa, ya sea efímera o estática, y otras instancias de Compute Engine en la organización o proyecto que no estén definidas explícitamente en la política tienen prohibido usar direcciones IP externas.

Las instancias se identifican en las listas de permitir y denegar 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 puede aplicar la restricción retroactivamente. Todas las instancias que tienen direcciones IP externas antes de habilitar la política conservan sus direcciones IP externas.
  • Esta restricción acepta una allowedList o una deniedList pero no ambas en la misma política.
  • Depende de usted o de un administrador con los permisos necesarios administrar 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 en la lista de permitidos se modifiquen, eliminen o vuelvan a crear.

Permisos necesarios para restringir direcciones IP externas

Para establecer una restricción a nivel de proyecto u organización, se le debe haber otorgado el rol orgpolicy.policyAdmin en la organización.

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

Consola

  1. Vaya a la página Políticas organizativas .

    Ir a Políticas Organizacionales

  2. Si es necesario, seleccione la organización requerida en el menú desplegable del proyecto.
  3. Haga clic en Definir IP externas permitidas para instancias de VM .
  4. Haga clic en Editar para editar la política de IP externa. Si no puede acceder a la herramienta Editar , no tiene los permisos correctos.
  5. Seleccione Personalizar para configurar la política de la organización para instancias específicas.

    Personalizar la opción en la página de edición de políticas de la organización.

  6. Seleccione la aplicación de políticas y el tipo de política requeridos.

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

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

    projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME
    
  9. Haga clic en Nuevo valor de política e ingrese los URI para las instancias según sea necesario.

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

nube de gcloud

Para establecer una restricción para el acceso IP externo, primero necesita el ID de su organización. Puede encontrar el ID de la organización ejecutando el comando organizations list y buscando el ID numérico en la respuesta:

gcloud organizations list

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

DISPLAY_NAME               ID
example-organization1      29252605212
example-organization2      1234567890

Usa el comando gcloud resource-manager org-policies set-policy para configurar la política. Debe proporcionar su política como un archivo JSON. Cree un archivo JSON en 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"
  ]
 }
}

Reemplace lo siguiente:

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

Alternativamente, puede especificar una lista de deniedValues para indicar las instancias a las que desea prohibir explícitamente que tengan una dirección IP externa. A cualquier instancia que no esté en la lista se le permitiría implícitamente tener una dirección IP externa. Solo puede especificar allowedValues o deniedValues , pero no ambos.

Luego, pasa el archivo con tu solicitud:

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

Reemplace ORGANIZATION_ID con el ID numérico de la organización.

Si no desea que ninguna instancia tenga acceso a IP externa, puede establecer una política con allValues ​​configurado en DENY :

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

DESCANSAR

Utilice la API setOrgPolicy() para definir su restricción. Las instancias en la lista de allowedValue que especifique pueden tener direcciones IP externas. Alternativamente, puede especificar una lista de deniedValues para expresar las instancias a las que desea prohibir explícitamente que tengan una dirección IP externa. A cualquier instancia que no esté en la lista se le permitiría implícitamente tener una dirección IP externa. Solo puede 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 donde las instancias de ciertos proyectos dentro de la organización pueden tener 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 su solicitud, proporcione la política para 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 desea que ninguna instancia tenga acceso a IP externa, puede establecer una política con allValues ​​configurado en DENY :

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

Establecer la política a nivel de proyecto

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

Consola

Siga el mismo proceso documentado en Establecer una restricción de política a nivel de organización, pero elija su proyecto en el selector de proyectos en lugar de la organización.

Selector de proyectos.

nube de gcloud

Usa el comando gcloud resource-manager org-policies set-policy para configurar la política. Debe proporcionar su política como un archivo JSON. Cree un archivo JSON en el siguiente formato:

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

Reemplace lo siguiente:

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

Alternativamente, puede especificar una lista de deniedValues de instancias a las que desea prohibir explícitamente que tengan una dirección IP externa. A cualquier instancia que no esté en la lista se le permitiría implícitamente tener una dirección IP externa. Solo puede especificar allowedValues o deniedValues , pero no ambos.

Luego, pasa el archivo con tu solicitud:

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

DESCANSAR

Utilice la API setOrgPolicy para definir su restricción. Las instancias en la lista de allowedValue que especifique pueden tener direcciones IP externas. Alternativamente, puede especificar una lista de deniedValues para expresar las instancias que desea prohibir explícitamente que tengan una dirección IP externa. Cualquier instancia que no esté en la lista tiene implícitamente permitido tener una dirección IP externa. Puede especificar solo allowedValues o deniedValues , pero no ambos.

Por ejemplo, la siguiente es una solicitud para establecer 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

Reemplace PROJECT_ID con el ID del proyecto para esta solicitud.

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

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

Mejores prácticas para restringir direcciones IP externas

  • Evite utilizar la lista de deniedValues con esta restricción. Si define valores en la lista deniedValues , significa que solo las instancias de la lista de deniedValues tienen restringido el uso de direcciones IP externas. Esto podría ser un problema de seguridad si desea controlar exactamente qué instancias pueden tener direcciones IP externas. Si desea eliminar determinadas instancias de la lista allowedValues , actualice la política existente para eliminar las instancias de la allowedList en lugar de colocarlas en la lista de deniedValues en una jerarquía inferior.

  • Si desea establecer una política en una gran parte de la jerarquía de recursos pero eximir ciertos proyectos, restaure la política predeterminada utilizando el método setOrgPolicy especificando el objeto restoreDefault para permitir que todas las instancias de los proyectos se asocien con direcciones IP externas. Las políticas actuales para proyectos no se ven afectadas por la configuración predeterminada.

  • Utilice la política de organización junto con los roles de IAM para controlar mejor su entorno. Esta política se aplica solo a instancias, pero si desea controlar y restringir mejor las direcciones IP externas en dispositivos de red, puede otorgar la función compute.networkAdmin a las partes correspondientes.

  • Todos los servicios y productos que se ejecutan en Compute Engine dentro de la organización o proyecto con la política habilitada están sujetos a esta política de la organización. Específicamente, esta política afecta a servicios como Google Kubernetes Engine, Dataflow, Dataproc y Cloud SQL. Si esto supone un problema, Google recomienda configurar otros servicios y productos en un proyecto diferente al que no se le haya aplicado la política de la organización y utilizar VPC compartida , si es necesario.

Administrar direcciones IP externas estáticas

Las siguientes secciones describen cómo administrar direcciones IP externas estáticas para sus 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 igual en la mayoría de los contextos. Sin embargo, con direcciones IP internas estáticas, puede usar la misma dirección IP para el mismo recurso incluso si elimina y vuelve a crear el recurso. En general, se libera una dirección IP efímera si detiene o elimina el recurso.

Para determinar si una dirección es estática o efímera, haga lo siguiente:

  1. En la consola de Google Cloud, vaya a la página de direcciones IP .

    Ir a direcciones IP

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

Desasignar una dirección IP externa estática

La desasignación de una dirección IP la elimina del recurso pero mantiene la dirección IP reservada. Una vez desasignada la dirección IP, puede reasignarla a otro recurso. Este procedimiento se admite para instancias de doble pila, pero no para instancias de solo IPv6.

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

Consola

  1. En la consola de Google Cloud, vaya a la página de direcciones IP .

    Ir a direcciones IP

  2. Haga clic en Direcciones IP externas .

  3. Seleccione la dirección IP estática que desea desasignar.

  4. Haga clic en Ver acciones y seleccione la opción Reasignar a otro recurso .

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

  6. Haga clic en Aceptar .

nube de gcloud

  1. Comprueba si hay una dirección IP estática en uso mediante el comando gcloud compute addresses list :

    gcloud compute addresses list
    

    El resultado es 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. Recupere el nombre de la instancia que utiliza la dirección IP:

    gcloud compute addresses describe ADDRESS_NAME \
      --region=REGION
    

    Reemplace lo siguiente:

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

    El resultado es 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
    

    El campo users muestra el nombre de la instancia que utiliza la dirección IP.

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

    • Para cancelar la asignación de una dirección IPv4, elimine el archivo de configuración de acceso de la instancia:

      1. Obtenga el nombre de la configuración de acceso que desea eliminar. Para obtener el nombre, usa el comando gcloud compute instances describe . Reemplace INSTANCE_NAME con el nombre de la instancia.

        gcloud compute instances describe INSTANCE_NAME
        

        La configuración de acceso aparece en 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 mediante el comando gcloud compute instances delete-access-config :

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

        Reemplace lo siguiente:

        • INSTANCE_NAME : el nombre de la instancia.
        • ACCESS_CONFIG_NAME : el nombre de la configuración de acceso a eliminar. Asegúrese de incluir el nombre completo entre comillas.
    • Para desasignar un rango de direcciones IPv6, use el comando instance network-interfaces update :

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

      Reemplace lo siguiente:

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

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

    Reemplace lo siguiente:

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

Ahora que su dirección IP externa estática está disponible, puede optar por asignarla a otra instancia .

DESCANSAR

Para desasignar una dirección IPv4 o IPv6 externa estática, realice los siguientes pasos:

  • Para direcciones IPv4, elimine la configuración de acceso adjunta a la instancia que usa la dirección.

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

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

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

      Reemplace lo siguiente:

      • PROJECT_ID : el ID del proyecto para esta solicitud
      • ZONE : la zona donde se encuentra la instancia
      • INSTANCE_NAME : el nombre de la instancia
  • Para direcciones IPv6, actualice el tipo de pila de la interfaz de red para la instancia donde está adjunta la dirección IPv6.

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

    2. En el cuerpo de la solicitud, actualice 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);
    }
  }
}

Pitón

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 necesita una dirección IPv4 o IPv6 externa estática, puede liberar la dirección IP eliminando el recurso de dirección IP. Eliminar una instancia no libera automáticamente una dirección IP externa estática. Debe liberar manualmente las direcciones IP externas estáticas cuando ya no las necesite.

Para liberar una dirección IP externa estática, consulte Liberar una dirección IP externa estática en la documentación de VPC.

¿Qué sigue?