Configurar rutinas de inicio de la VM

Si usas Google Distributed Cloud versión 1.13.0 o posterior, puedes especificar rutinas de inicio para personalizar la inicialización de tu VM al iniciarse. Puedes configurar tu máquina virtual para crear claves SSH, añadir usuarios y contraseñas, instalar paquetes, escribir archivos, configurar ajustes de red y más.

Estas tareas de inicio se configuran con la API cloud-init o con la API de secuencias de comandos de inicio (no con ambas). Estas directivas de inicio se especifican en el archivo de manifiesto YAML VirtualMachine y se ejecutan automáticamente cada vez que se inicia la VM.

Requisitos previos

Para configurar una máquina virtual con directivas de inicio, debes cumplir los siguientes requisitos previos:

En las siguientes secciones se describe cómo especificar rutinas de inicio en el manifiesto de la VM con la API cloud-init o con secuencias de comandos de inicio.

Usar la API de cloud-init para inicializar VMs

Cloud-init se usa habitualmente para inicializar instancias de nube y personalizar máquinas virtuales durante el inicio. La inicialización de una máquina virtual suele implicar tareas como la instalación de paquetes, la configuración de repositorios, la creación de claves SSH, la escritura de datos en archivos y la configuración de otros aspectos de la máquina virtual. Puedes incorporar la configuración de cloud-init en formato YAML al recurso personalizado VirtualMachine con el campo spec.cloudInit. Cuando se inicia la instancia de VM, cloud-init lee los datos proporcionados e inicializa la VM en consecuencia.

Ten en cuenta los siguientes detalles de nuestra implementación de cloud-init:

.

Para ayudarte a empezar, hemos proporcionado algunos ejemplos de configuración para tareas comunes de inicialización de VMs.

Datos de usuario de cloud-init

VM Runtime en GDC admite datos de usuario de cloud-init en sintaxis cloud-config, por lo que debes empezar los datos de usuario con #cloud-config. Puedes dar formato a los datos de usuario como texto sin formato, una cadena codificada en base64 o un secreto de Kubernetes.

Para obtener más información sobre la sintaxis de los datos de usuario y la referencia de módulos, consulta la documentación de cloud-init.

Datos de usuario de cloud-init como texto sin cifrar

El siguiente ejemplo de archivo de manifiesto muestra cómo especificar datos de usuario como texto sin cifrar. En este caso, cloud-init ejecuta un comando cuando se inicia la VM:

apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      userData: |
        #cloud-config
        runcmd:
          - echo hello

Datos de usuario de cloud-init como cadena codificada en base64

En el siguiente ejemplo se muestra cómo especificar datos de usuario en formato codificado en base64. En este ejemplo, los datos de usuario constan del mismo comando echo hello que en el ejemplo de texto sin formato:

apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      userDataBase64: I2Nsb3VkLWNvbmZpZwpydW5jbWQ6CiAgLSBlY2hvIGhlbGxvCg==

Datos de usuario de cloud-init como secreto de Kubernetes

En el siguiente ejemplo se muestra un manifiesto YAML para un VirtualMachine y un Secret. La sección spec.cloudInit.noCloud.secretRef de la configuración VirtualMachine indica que los datos de usuario de cloud-init están en un secreto de Kubernetes llamado my-sec. La configuración Secret correspondiente especifica los datos de usuario como un par clave-valor. En este caso, el valor codificado en base64 son los datos de usuario de cloud-init en sintaxis de cloud-config.

En el secreto al que se hace referencia, usa la clave de datos userData (que se muestra) o userdata para especificar los datos de usuario de cloud-init.

En este ejemplo, los datos de usuario constan del mismo comando echo hello que en el ejemplo de texto sin formato:

apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      secretRef:
        name: my-sec
---
apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: my-sec
data:
  userData: I2Nsb3VkLWNvbmZpZwpydW5jbWQ6CiAgLSBlY2hvIGhlbGxvCg==

Si no se encuentra el secreto al que se hace referencia o si la clave de datos userData o userdata no existe en el secreto, ten en cuenta el siguiente comportamiento de inicio de la VM:

  • Cuando se crea una VM, esta se pone en estado ErrorConfiguration con un motivo y un mensaje detallados.

  • En otros casos, la VM sigue usando los datos de usuario antiguos de cloud-init hasta que se configure correctamente. Por lo tanto, los cambios en el estado del agente invitado no se aplican hasta que la VM se configura correctamente.

Para obtener información sobre la VM, incluidos los datos de usuario de cloud-init que se han utilizado, usa el siguiente comando:

kubectl get vm VM_NAME -o yaml --kubeconfig KUBECONFIG_PATH

Haz los cambios siguientes:

  • VM_NAME: el nombre de tu VM.

  • KUBECONFIG_PATH: la ruta al archivo kubeconfig del clúster que contiene tu VM.

Para obtener el evento de advertencia de Kubernetes relacionado, usa kubectl get event o kubectl describe gvm.

Datos de red de cloud-init

Al igual que con los datos de usuario, puedes dar formato a los datos de red como texto sin formato, una cadena codificada en base64 o un secreto de Kubernetes. A diferencia de los datos de usuario, los datos de red no usan la sintaxis de cloud-config.

Cuando se usa texto sin formato o una cadena codificada en base64, el tamaño máximo permitido es de 2048 bytes. Si el tamaño de los datos de usuario es igual o superior a 2048 bytes, especifícalo como un secreto de Kubernetes.

Para obtener más información sobre la sintaxis de los datos de red y otros detalles relacionados, consulta la sección Versión 2 de la configuración de red de la documentación de cloud-init.

Datos de red de cloud-init como texto sin cifrar

En el siguiente ejemplo de manifiesto se muestra cómo especificar datos de red como texto sin cifrar. En este caso, cloud-init habilita DHCP para todos los dispositivos Ethernet cuyos nombres empiecen por "e" (e*):

apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      userData: |
        #cloud-config
        runcmd:
          - echo hello
      networkData: |
        version: 2
        ethernets:
          alleths:
            match:
              name: e*
            dhcp4: true

Datos de red de cloud-init como una cadena codificada en base64

En el ejemplo siguiente se muestra cómo especificar datos de red en formato codificado en Base64. En este ejemplo, los datos de la red constan de la misma configuración DHCP especificada en el ejemplo de texto sin formato:

apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      networkDataBase64: dmVyc2lvbjogMgpldGhlcm5ldHM6CiAgYWxsZXRoczoKICAgIG1hdGNoOgogICAgICBuYW1lOiBlKgogICAgZGhjcDQ6IHRydWUK

Datos de red de cloud-init como secreto de Kubernetes

En el siguiente ejemplo se muestra un manifiesto YAML para un VirtualMachine y un Secret. La sección spec.cloudInit.noCloud.networkDataSecretRef de la configuración VirtualMachine indica que los datos de red de cloud-init están en un secreto de Kubernetes llamado my-sec. La configuración Secret correspondiente especifica los datos de la red como un par clave-valor. En este caso, el valor codificado en Base64 son los datos de red de cloud-init.

En el secreto al que se hace referencia, usa la clave de datos networkData (que se muestra) o networkdata para especificar los datos de red de cloud-init.

En este ejemplo, los datos de la red constan de la misma configuración DHCP especificada en el ejemplo de texto sin formato:

apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      networkDataSecretRef:
        name: my-sec
---
apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: my-sec
data:
  networkData: dmVyc2lvbjogMgpldGhlcm5ldHM6CiAgYWxsZXRoczoKICAgIG1hdGNoOgogICAgICBuYW1lOiBlKgogICAgZGhjcDQ6IHRydWUK

Ejemplos de cloud-init

En las siguientes secciones se incluyen ejemplos de texto sin formato de algunos casos prácticos habituales de inicialización de VMs con cloud-init:

Configurar claves SSH autorizadas

En el siguiente ejemplo de datos de usuario se asigna la clave SSH autorizada ssh-rsa AAAAB3NzaK8L93bWxnyp al usuario predeterminado.

apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      userData: |
        #cloud-config
        ssh_authorized_keys:
          - ssh-rsa AAAAB3NzaK8L93bWxnyp

Añadir a un nuevo usuario

En el siguiente ejemplo de datos de usuario se crea el usuario test y se le da acceso completo de superusuario.test En este ejemplo, se asigna al usuario una contraseña que no caduca: pwd.

apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      userData: |
        #cloud-config
        users:
        - default
        - name: test
          sudo: ALL=(ALL) NOPASSWD:ALL
        chpasswd:
          list: |
            test:pwd
          expire: False

Ejecutar comandos en el primer inicio

En el siguiente ejemplo de datos de usuario se ejecutan los comandos echo y ls. Puedes usar comandos para instalar paquetes y más cuando se inicie tu VM.

apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      userData: |
        #cloud-config
        runcmd:
          - [ echo, hello ]
          - [ ls, -l, / ]

Escribir archivos

En el siguiente ejemplo de datos de usuario se escribe una secuencia de comandos bash en el archivo test del directorio /var/lib/google de tu VM. Las directivas de cloud-init definen los permisos de lectura, escritura y ejecución (0744) del propietario del archivo.

apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      userData: |
        #cloud-config
        write_files:
        - path: /var/lib/google/test
          permissions: 0744
          content: |
            #!/bin/bash
            echo hello

Solucionar problemas de cloud-init

Si tienes problemas con la inicialización de tu máquina virtual y usas cloud-init, consulta los siguientes registros de cloud-init en tu máquina virtual:

  • /var/log/cloud-init.log: De forma predeterminada, cloud-init escribe todos los eventos con un nivel DEBUG o superior en este registro.

  • /var/log/cloud-init-output.log: De forma predeterminada, cloud-init dirige tanto stdout como stderr de todas las fases de cloud-init a este registro.

Usar secuencias de comandos de inicio para inicializar VMs

Las secuencias de comandos de inicio realizan tareas durante el proceso de inicio de una instancia de máquina virtual (VM). Puedes especificar una o varias secuencias de comandos en la sección spec.startupScripts del archivo VirtualMachine. Las secuencias de comandos de inicio se pueden usar para inicializar tu VM. La inicialización de una máquina virtual suele implicar tareas como la instalación de paquetes, la configuración de repositorios, la creación de claves SSH, la escritura de datos en archivos y la configuración de otros aspectos de la máquina virtual.

Ten en cuenta los siguientes detalles sobre las secuencias de comandos de inicio:

  • Puedes especificar secuencias de comandos de inicio en el manifiesto YAML VirtualMachine al crear o actualizar una VM. Para obtener instrucciones sobre cómo crear una máquina virtual aplicando un manifiesto, consulta el tutorial sobre cómo crear y gestionar una máquina virtual Linux en el tiempo de ejecución de máquinas virtuales en GDC.

  • Las secuencias de comandos especificadas se ejecutan cada vez que se inicia la VM.

  • Incluye #!/bin/... en la parte superior de la secuencia de comandos para indicar el intérprete de la secuencia de comandos. Por ejemplo, incluye #!/bin/bash para ejecutar la secuencia de comandos con el shell de Bash.

  • No puedes especificar directivas de la API cloud-init (spec.cloudInit) y secuencias de comandos de inicio (spec.startupScripts) en el mismo manifiesto VirtualMachine.

Formatos de secuencias de comandos

Puede especificar secuencias de comandos de inicio en los siguientes formatos de datos:

  • Borrar texto
  • Cadena codificada en Base64
  • Secreto de Kubernetes

Ten en cuenta las siguientes reglas para trabajar con diferentes formatos de guion:

  • Cuando se usa texto sin formato o una cadena codificada en base64, el tamaño máximo permitido para el contenido de los scripts es de 2048 bytes. Si el tamaño del contenido de tu secuencia de comandos es igual o superior a 2048 bytes, especifica las secuencias de comandos como un secreto de Kubernetes.

  • Cuando utilices un secreto de Kubernetes, usa la clave de datos script en el secreto al que se hace referencia para especificar el contenido de la secuencia de comandos.

  • Si no se encuentra un secreto al que se hace referencia o la clave de datos script no existe en el secreto al que se hace referencia, la VM sigue ejecutando la secuencia de comandos. Sin embargo, la VM no escribe ni actualiza el contenido de la secuencia de comandos. En este caso, puedes encontrar el evento de advertencia de Kubernetes con kubectl get event o kubectl describe gvm.

El siguiente manifiesto VirtualMachine YAML de ejemplo contiene tres secuencias de comandos, una en cada uno de los formatos admitidos. En este caso, cada secuencia de comandos ejecuta el comando echo hello que se muestra en myscript1, el ejemplo de texto sin cifrar.

apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  startupScripts:
  - name: myscript1
    script: |
      #!/bin/bash
      echo hello
  - name: myscript2
    scriptBase64: IyEvYmluL2Jhc2gKICAgICAgZWNobyBoZWxsbwo=
  - name: myscript3
    scriptSecretRef:
      name: my-sec
---
apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: my-sec
data:
  script: IyEvYmluL2Jhc2gKICAgICAgZWNobyBoZWxsbwo=

Solución de problemas de secuencias de comandos

Para comprobar los resultados o los registros de la secuencia de comandos, ejecuta el siguiente comando:

journalctl -u cloud-final

Las entradas de registro de la secuencia de comandos de inicio empiezan con el siguiente texto:

started to run the command /var/lib/google/startup-scripts/SCRIPT_NAME ...

La entrada de registro incluye SCRIPT_NAME, el nombre de la secuencia de comandos de inicio.