es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Creación dinámica/condicional de recursos de Terraform

Estoy usando Terraform con el proveedor libvirt y generando 4 invitados (índice: 0,1,2,3) usando este fragmento:

[...]
resource "libvirt_domain" "worker" {
    count   = var.worker["count"]
    name    = "${var.cluster_id}-worker-${count.index}"
    memory  = var.worker.memory
    vcpu    = var.worker.vcpu

    coreos_ignition = libvirt_ignition.worker[count.index].id

    disk {
        volume_id = libvirt_volume.worker[count.index].id
    }
    console {
        type        = "pty"
        target_port = 0
    }
    cpu = {
        mode = var.cpu_mode
    }
    network_interface {
        network_id  = var.network_id
        hostname    = "worker-${count.index}.${var.cluster_id}.${var.cluster_domain}"
        mac         = var.worker_macs[count.index]
    }

    dynamic "xml" {
        for_each = var.worker
        content {
            xslt = file("add_gpu_w${count.index}.xsl")
        }
    }
}
[...]

Ahora quiero agregar una declaración condicional, que los primeros dos trabajadores obtienen asignadas GPUs.

Entonces en código Python pseudo algo así como:

if ${count.index} == 0:
    # Agregar GPU 0 a trabajador ${count.index} (--> trabajador 0)
elif ${count.index} == 1:
    # Agregar GPU 1 a trabajador ${count.index} (--> trabajador 1)
else:
    # No asignar una GPU a un trabajador

Desde la documentación del proveedor libvirt, vi que tengo que usar XML y XSLT, lo cual ya verifiqué con un script más simple y eso funciona.

Ahora lo intenté en esta configuración más compleja con declaraciones condicionales, así como bloques dinámicos, pero no puedo hacer que funcione. Actualmente se ve así:

resource "libvirt_domain" "worker" {
    count   = var.worker["count"]
    name    = "${var.cluster_id}-worker-${count.index}"
    memory  = var.worker.memory
    vcpu    = var.worker.vcpu

    coreos_ignition = libvirt_ignition.worker[count.index].id

    disk {
        volume_id = libvirt_volume.worker[count.index].id
    }
    console {
        type        = "pty"
        target_port = 0
    }
    cpu = {
        mode = var.cpu_mode
    }
    network_interface {
        network_id  = var.network_id
        hostname    = "worker-${count.index}.${var.cluster_id}.${var.cluster_domain}"
        mac         = var.worker_macs[count.index]
    }

    dynamic "xml" {
        for_each = var.worker
        content {
            xslt = file("add_gpu_w${count.index}.xsl")
        }
    }
}

Siento que los bloques dinámicos podrían ser el enfoque incorrecto porque está iterando a través de todos los trabajadores, pero tampoco lo conseguí con el enfoque de la declaración condicional.

Cualquier ayuda es apreciada, ¡gracias!

Tags:  ,

Answer

  1. Avatar for davy.ai

    Para agregar una declaración condicional para asignar GPUs a los primeros dos trabajadores, se puede utilizar el enfoque de bloque dinámico con expresiones condicionales en el bucle for_each. Aquí hay un ejemplo de fragmento de código:

    recurso "libvirt_domain" "worker" {
      cuenta = var.trabajador["cuenta"]
      nombre = "${var.cluster_id}-worker-${count.index}"
      memoria = var.trabajador.memoria
      vcpu = var.trabajador.vcpu
    
      coreos_ignition = libvirt_ignition.worker[count.index].id
    
      disco {
        identificador_de_volumen = libvirt_volume.worker[count.index].id
      }
      consola {
        tipo = "pty"
        puerto_destino = 0
      }
      cpu = {
        modo = var.cpu_mode
      }
      interface_de_red {
        identificador_de_red = var.identificador_de_red
        nombre_de_equipo = "worker-${count.index}.${var.cluster_id}.${var.cluster_domain}"
        mac = var.worker_macs[count.index]
      }
    
      dinámico "xml" {
        for_each = range(var.trabajador["cuenta"])
        contenido {
          xslt = file("${var.directorio_de_plantillas_xml}/add_gpu_worker.xml")
    
          argumentos = {
            indice_gpu = (key < 2 ? key : -1)
            # establecer índice_gpu en -1 si el trabajador no recibe una GPU
            # por ejemplo. si el índice del trabajador es mayor o igual a 2
          }
        }
      }
    }
    

    En este fragmento de código, utilizamos la función de rango para generar una lista cuya longitud es var.trabajador["cuenta"]. Utilizamos esta lista como entrada para el argumento for_each del bloque dinámico.

    Dentro del bloque dinámico, utilizamos el objeto each para acceder a la variable de bucle (key) y el valor de bucle (value), que en este caso no se utiliza.

    Utilizamos each.key como índice de trabajador para determinar si el trabajador debe recibir una asignación de GPU. El bloque argumentos se utiliza para pasar la variable indice_gpu a la plantilla XSLT (add_gpu_worker.xml).

    Dentro de la plantilla XSLT, se puede usar lógica condicional para generar el documento XML que agrega o no agrega un dispositivo GPU al trabajador. Aquí hay una plantilla XSLT de ejemplo:

    <!-- add_gpu_worker.xml -->
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    
      <xsl:param name="indice_gpu"></xsl:param>
    
      <xsl:template match="domain">
        <xsl:copy>
          <xsl:apply-templates select="@*"></xsl:apply-templates>
          <xsl:apply-templates select="*"></xsl:apply-templates>
          <xsl:if test="$indice_gpu >= 0">
            <devices>
              <hostdev mode="subsystem" type="pci" managed="yes">
                <source>
                  <address domain="0x0000" bus="0x00" slot="0x${format('%02X', 4 + $indice_gpu * 2)}" function="0x0"></address>
    
                <driver name="nvidia"></driver>
              </hostdev>
            </devices>
          </xsl:if>
        </xsl:copy>
      </xsl:template>
    
    </xsl:stylesheet>
    

    Esta plantilla agrega un nodo de dispositivo GPU al XML de dominio solo si el parámetro indice_gpu es mayor o igual a 0. La función format se utiliza para formatear la dirección PCI del dispositivo GPU.

    Asegúrese de actualizar la variable var.directorio_de_plantillas_xml a la ruta del directorio que contiene el archivo de plantilla XSLT (add_gpu_worker.xml).

Comments are closed.