Note:

Utilice Packer para crear imágenes personalizadas de Oracle Cloud Infrastructure

Introducción

Este tutorial trata sobre cómo tomar una imagen base de OCI o cualquier imagen informática que ya tenga en OCI y modificarla según las necesidades del cliente.

Por ejemplo, puede que necesite cambiar el modo de inicio de imagen de nativo a paravirtualización o cambiar la asociación de tarjeta de interfaz de red virtual (VNIC). Por ejemplo, los nodos de trabajador de OKE los necesitan. Del mismo modo, puede instalar paquetes adicionales del sistema operativo o modificar los parámetros del núcleo de instancia mediante el aprovisionador de Packer (como en Terraform).

Supongamos que necesita una imagen en la que desea tener instalada la base de datos PostgreSQL y algunos parámetros ulimit para tener otros valores. Para ello, inicie un recurso informático desde una imagen y, a continuación, cambie lo que necesite, instale los programas, la aplicación y los paquetes que necesite y, a continuación, guarde la instancia como una nueva imagen personalizada.

Ahora imagine que necesita crear varias imágenes personalizadas, para varias arquitecturas y con el tiempo necesita agregar o cambiar los programas o paquetes agregados a su imagen personalizada. Para ello, podemos utilizar Packer de HashiCorp.

Empaquetador

Packer es la herramienta de código abierto de HashiCorp que se utiliza para crear imágenes de máquinas a partir de la configuración de origen. Es ligero, se ejecuta en todos los sistemas operativos principales, de alto rendimiento. No sustituye la gestión de configuración, como Chef o Puppet. De hecho, cuando crea imágenes, Packer puede utilizar herramientas como Chef o Puppet para instalar software en la imagen. Algunas de las funciones son:

Ventajas de Utilizar Packer

Autenticación de empaquetador

Puede autenticar Packer mediante las siguientes opciones.

Nota: Obtenga más información sobre la autenticación de paquetes, pero la forma preferible es utilizar el archivo .oci/config o el principal de instancia.

Funcionamiento de Packer

En las tareas, Packer toma una imagen especificada en el parámetro base_image_ocid y despliega una instancia informática con los atributos especificados por usted en los parámetros de configuración necesarios (es decir, disponibilidad*dominio, unidad, etc.).

Después de eso, Packer intentará utilizar ssh en la instancia para ejecutar cualquier provisionador (_provisioner "shell"*) especificado en el bloque build de la imagen base después de iniciarlo. Para esta tarea, debe tener en cuenta dónde desea desplegar la instancia (los atributos subnet_ocid), por lo que Packer puede utilizar ssh en la instancia desde la máquina que ejecuta Packer. Al final de las instantáneas del empaquetador, crea una imagen personalizada reutilizable.

Aprovisionadores de empaquetado

Los aprovisionadores son componentes importantes de Packer que instalan y configuran software dentro de un equipo en ejecución antes de que ese equipo se convierta en una imagen estática. Realizan el trabajo principal de hacer que la imagen contenga software útil.

Entre los aprovisionadores de ejemplo se incluyen:

Objetivos

Requisitos

Tarea 1: Creación del archivo de configuración del empaquetador

Packer admite formato HCL o JSON. En la siguiente tarea, es un formato HCL.

  1. Asigne al archivo el nombre que desee, pero al final incluya .pkr.hcl.

    packer {
        required_plugins {
          oracle = {
            source = "github.com/hashicorp/oracle"
            version = ">= 1.0.3"
          }
        }
    }
    
    source "oracle-oci" "example" {
      availability_domain = "GqIF:EU-FRANKFURT-1-AD-2"
      #you may use an OCID or use a base_image_filter
      #base_image_ocid     = "ocid1.image.oc1.eu-frankfurt-1......"
      base_image_filter  {
        #display_name = "Oracle-Linux-7.9-2023.05.24-0"
        display_name_search =  "^Oracle-Linux-7.9*"
      }
      compartment_ocid    = "ocid1.compartment.oc1......"
      image_name          = "ExampleImage"
      shape               = "VM.Standard1.1"
      ssh_username        = "opc"
      #This is public subnet as I run packer from outside OCI VCN
      subnet_ocid         = "ocid1.subnet.oc1.eu-frankfurt-1....."
      #this attribute will be changed
      nic_attachment_type  = "VFIO"
      #this attribute will be changed
      image_launch_mode = "NATIVE"
      #you may skip the image creation if you are running tests
      #when you want to test set this as true
      skip_create_image = false
    }
    
    build {
      sources = ["source.oracle-oci.example"]
    }
    
  2. subnet_ocid es la subred en la que se aprovisiona la instancia hasta que se crea la imagen personalizada. Se trata de una subred a la que se debe poder acceder desde el host que ejecuta Packer. Normalmente no desearía crear instancias de desarrollo con una IP pública, ya que no hay ninguna razón para que se expongan a Internet y, al hacerlo, solo se crean problemas de seguridad. Una forma de evitar el uso de IP pública es ejecutar Packer desde OCI o utilizar el servicio OCI Bastion. También puede utilizar FastConnect u otra VPN para acceder a la subred de OCI desde entornos locales sin necesidad de recorrer Internet.

Tarea 2: Inicializar empaquetador

  1. Ejecute la inicialización del empaquetador.

    <path to packer bin> init <packer conf file>
    

    Por ejemplo:

    <path to packer bin> init oke.pkr.hcl
    

Tarea 3: Crear la imagen

  1. En este punto, tiene una imagen personalizada que tendrá image_launch_mode = "NATIVE" y nic_attachment_type = "VFIO". Hay otros atributos que puede cambiar. Todos se describen en el documento oficial.

  2. Puede ejecutar comandos personalizados o scripts (se adjuntan ejemplos).

    <path to packer bin> build oke.pkr.hcl
    
    oracle-oci.example: output will be in this color.
    
    ==> oracle-oci.example: Creating temporary ssh key for instance...
    ==> oracle-oci.example: Creating instance...
    ==> oracle-oci.example: Created instance (ocid1.instance.........).
    ==> oracle-oci.example: Waiting for instance to enter 'RUNNING' state...
    ==> oracle-oci.example: Instance 'RUNNING'.
    ==> oracle-oci.example: Instance has IP: 130.61.X.X
    ==> oracle-oci.example: Using SSH communicator to connect: 130.61.X.X
    ==> oracle-oci.example: Waiting for SSH to become available...
    ==> oracle-oci.example: Connected to SSH!
    ==> oracle-oci.example: Creating image from instance...
    ==> oracle-oci.example: Updating image schema...
    ==> oracle-oci.example: Created image (ocid1.image........).
    ==> oracle-oci.example: Terminating instance (ocid1.instance.....)...
    ==> oracle-oci.example: Terminated instance.
    Build 'oracle-oci.example' finished after 4 minutes 37 seconds.
    
    ==> Wait completed after 4 minutes 37 seconds
    
    ==> Builds finished. The artifacts of successful builds are:
    --> oracle-oci.example: An image was created: 'ExampleImage' (OCID: ocid1.image..........'
    

    Ejemplo con el provisionador:

    • En este ejemplo, se utiliza provisioner (shell y archivo).

    • Se crearían 2 imágenes (especificadas en el origen).

      variable "VAREXAMPLE" {
        type = string
        default = "val Example"
      }
      
      variable "deploy_in_comp" {
        type = string
        default = "ocid1.compartment.oc1......."
      }
      
      variable "OCI_PROFILE" {
        type = string
        default = "DEFAULT"
      }
      
      locals {
        pkr_root    = "${path.cwd}"           #the directory from where Packer was started
        pkr_scripts = "${path.root}/scripts"  #the directory of the input HCL file or the input folder
        root        = path.root
      }
      
      source "oracle-oci" "img1" {
        access_cfg_file_account = var.OCI_PROFILE
        availability_domain = "GqIF:US-ASHBURN-AD-3"
        base_image_ocid     = "ocid1.image.oc1.iad....."
        compartment_ocid    = "ocid1.compartment.oc1......"
        image_name          = "img1"
        shape               = "VM.Standard.E4.Flex"
        #usage of shape config
        shape_config {
        ocpus               = "1"
        }
        ssh_username        = "opc"
        subnet_ocid         = "ocid1.subnet.oc1.iad....."
      }
      
      source "oracle-oci" "img2" {
        access_cfg_file_account = var.OCI_PROFILE
        availability_domain = "GqIF:US-ASHBURN-AD-3"
        base_image_ocid     = "ocid1.image.oc1.iad....."
        compartment_ocid    = "ocid1.compartment.oc1........."
        image_name          = "img2"
        shape               = "VM.Standard.E4.Flex"
        shape_config {
        ocpus               = "2"
        }
        ssh_username        = "opc"
        subnet_ocid         = "ocid1.subnet.oc1.iad........"
        image_compartment_ocid = var.deploy_in_comp
      }
      
      build {
        # here we secific both source above, img1 and img2
        sources = [
          "source.oracle-oci.img1",
          "source.oracle-oci.img2"
        ]
        provisioner "shell" {
          # this will run on all sources
          inline = [
            "echo to run on all sources ${var.VAREXAMPLE}"
          ]
        }
        provisioner "shell" {
          # This provisioner only runs for img1 source.
          only = ["oracle-oci.img1"]
          inline = [
            "echo To run in img1",
          ]
        }
        provisioner "shell" {
          # This provisioner  runs on all but img1 source.
          # Mnd that there is no "source" string but only the name of the source
          except = ["oracle-oci.img1"]
          inline = [
            "echo To run in all except img1",
          ]
        }
        provisioner "file" {
          only = ["oracle-oci.img2"]
          source = "${local.pkr_scripts}/test.txt"
          destination = "/tmp/test.txt"
        }
        # This will run local on the machine you run packer
        provisioner "shell-local" {
          inline = ["echo ${local.pkr_root} and ${local.pkr_scripts}"]
        }
        # This will run local on the machine you run packer
        provisioner "shell-local" {
          inline = ["echo VAR from file :${var.VAREXAMPLE}"]
        }
      }
      
      
    • Utiliza variables (como en Terraform).

      image_compartment_ocid = var.deploy_in_comp
      
    • el método Auth es con el archivo .oci/config (valor por defecto), pero utiliza un atributo para especificar el perfil wich en el archivo que se va a utilizar.

      access_cfg_file_account = var.OCI_PROFILE
      
    • En este caso, utilizamos provisioner "shell" y provisioner "file" y provisioner "shell-local".

    • shell Packer provisioner aprovisiona máquinas creadas por Packer mediante scripts de shell. El aprovisionamiento de shell es la forma más sencilla de instalar y configurar software en una máquina.

    • Puede ejecutar el comando shell en el equipo (utilice inline) o ejecutar una secuencia de comandos electrónica (utilice script).

    • También utilizamos el aprovisionamiento file. El provisionador de empaquetado de archivos carga archivos en máquinas creadas por Packer.

    • Puede ver más ejemplos en el archivo hcl que puede descargar prov-example.pkr.hcl.

    Ejemplo con archivos de variables y aprovisionadores de Ansible:

    • Utilizamos:

      • archivos de variables.
      • un método Auth diferente: utilizando variables.
    • En lugar de utilizar shell para instalar paquetes, estamos utilizando la opción de ejecutar cuadernos de estrategias almacenados en una carpeta independiente.

    • Este método es para una situación más compleja que Ansible puede manejar mejor.

    • Hay dos aprovisionadores responsables:

      • ansible-local: Necesita unsible instalado en el host que Packer creará (puede utilizar el shell de provisionador para instalar Ansible).
      • ansible: se ejecutará ansible desde el host que ejecuta Packer, por lo que no es necesario que esté presente en la instancia que cree.
    • hay varios archivos de configuración implicados, por lo que debe especificar el nombre del directorio al crear.

      packer build <directory name>
      
    • En este ejemplo, el archivo ansible-example.pkr.hcl. A continuación se muestra el ansible-example.pkr.hcl.

      # mind there is a variables.pkr.hcl file where
      # other vars are set
      # so when build use: packer build <directory name>
      # so all the files within dir will be loaded
      
      
      source "oracle-oci" "img1" {
      #auth vars
      region        = var.REGION
      tenancy_ocid  = var.TENANCY_OCID
      user_ocid     = var.USER_OCID
      key_file      = var.KEY_FILE
      fingerprint   = var.FINGERPRINT
      #
      availability_domain = var.AD
      base_image_ocid     = var.BASE_IMG_OCID
      compartment_ocid    = var.COMP_IMG_OCID
      image_name          = var.IMG_NAME
      shape               = var.SHAPE
      shape_config {
      ocpus               = var.SHAPE_OCPUS
      }
      ssh_username        = "opc"
      subnet_ocid         = var.SUBNET_OCID
      # for testing and debug. remove it after
      skip_create_image   = true
      }
      
      source "oracle-oci" "img2" {
      #auth vars
      region        = var.REGION
      tenancy_ocid  = var.TENANCY_OCID
      user_ocid     = var.USER_OCID
      key_file      = var.KEY_FILE
      fingerprint   = var.FINGERPRINT
      #
      availability_domain = var.AD
      base_image_ocid     = var.BASE_IMG_OCID
      compartment_ocid    = var.COMP_IMG_OCID
      image_name          = var.IMG_NAME1
      shape               = var.SHAPE
      shape_config {
      ocpus               = var.SHAPE_OCPUS
      }
      ssh_username        = "opc"
      subnet_ocid         = var.SUBNET_OCID
      # for testing and debug. remove it after
      skip_create_image   = true
      }
      
      build {
      sources = [
        "source.oracle-oci.img1",
        "source.oracle-oci.img2"
      ]
      
      #need ansible installed on VM that packer will build
      #so you need to install ansible beforehand
      
      provisioner "shell" {
        # this will run on all sources
        inline = [
          "sudo yum install ansible -y"
        ]
      }
      
      # this provisioner ansible-local needs ansible installed
      # on the host that packer will builds
      
      provisioner "ansible-local" {
        playbook_file   = "${path.root}/ansible/pb1.yaml"
      }
      
      # This provisioner ansible
      # will run ansible playbook from host that runs packer
      # so you don't need to inmstall ansible on VM that packer wil create
      
      #provisioner "ansible" {
      #  playbook_file   = "${path.root}/ansible/pb-remote.yaml"
      #  user = "opc"
      #  # in case you need to debug ansible tasks
      #  extra_arguments = [ "-vvvv" ]
      #}
      }
      
      
    • Aquí está vars.pkr.hcl. En este archivo los declaramos e inicializamos.

      variable "AD" {
      type = string
      default = "GqIF:US-ASHBURN-AD-3"
      }
      
      variable "BASE_IMG_OCID" {
      type = string
      default = "ocid1.image.oc1.iad......"
      }
      
      variable "COMP_IMG_OCID" {
      type = string
      default = "ocid1.compartment.oc1......."
      }
      
      variable "IMG_NAME" {
      type = string
      default = "img1"
      }
      
      variable "IMG_NAME1" {
      type = string
      default = "img2"
      }
      
      variable "SHAPE" {
      type = string
      default = "VM.Standard.E3.Flex"
      }
      
      variable "SHAPE_OCPUS" {
      type = string
      default = "1"
      }
      
      variable "SUBNET_OCID" {
      type = string
      default = "ocid1.subnet.oc1.iad......"
      }
      
    • Este es el archivo auth-vars.pkr.hcl. Utilizamos este archivo para configurar la autenticación.

      variable "REGION" {
        type = string
        default = "us-ashburn-1"
      }
      
      variable "TENANCY_OCID" {
        type = string
        default = "ocid1.tenancy.oc1......."
      }
      
      variable "USER_OCID" {
        type = string
        default = "ocid1.user.oc1......"
      }
      
      variable "KEY_FILE" {
        type = string
        default = ".....oci_api_key.pem"
      }
      
      variable "FINGERPRINT" {
        type = string
        default = "...."
      }
      

Acuses de recibo

Autor: Francisc Vass (Arquitecto principal de Cloud)

Más recursos de aprendizaje

Explore otros laboratorios en docs.oracle.com/learn o acceda a más contenido de aprendizaje gratuito en el canal YouTube de Oracle Learning. Además, visite education.oracle.com/learning-explorer para convertirse en un explorador de Oracle Learning.

Para obtener documentación sobre los productos, visite Oracle Help Center.