Hinweis:
- Dieses Tutorial erfordert Zugriff auf Oracle Cloud. Informationen zum Anmelden für einen kostenlosen Account finden Sie unter Erste Schritte mit Oracle Cloud Infrastructure Free Tier.
- Es verwendet Beispielwerte für Oracle Cloud Infrastructure-Zugangsdaten, -Mandanten und -Compartments. Wenn Sie Ihre Übung abgeschlossen haben, ersetzen Sie diese Werte durch die Werte, die für Ihre Cloud-Umgebung spezifisch sind.
Mit Packer benutzerdefinierte Oracle Cloud Infrastructure-Images erstellen
Einführung
In diesem Tutorial geht es darum, ein OCI-Basisimage oder ein beliebiges Compute-Image zu erstellen, das Sie bereits in OCI haben, und es entsprechend den Kundenanforderungen zu ändern.
Beispiel: Sie müssen den Imagestartmodus von "Nativ" in "Paravirtualisierung" ändern oder den Virtual Network Interface Card-(VNIC-)Anhang ändern. Für OKE-Worker-Knoten sind diese beispielsweise erforderlich. Ebenso können Sie zusätzliche BS-Packages installieren oder die Kernel-Parameter der Instanz mit dem Packer provisioner ändern (wie in Terraform).
Angenommen, Sie benötigen ein Image, auf dem die PostgreSQL-Datenbank installiert werden soll, und einige ulimit-Parameter müssen andere Werte aufweisen. All diese oben genannten Aufgaben können Sie ausführen, indem Sie eine Compute-Instanz von einem Image starten und dann die erforderlichen Elemente ändern. Installieren Sie die Programme, die Anwendung und die erforderlichen Packages, und speichern Sie die Instanz als neues benutzerdefiniertes Image.
Stellen Sie sich vor, Sie müssen jetzt mehrere benutzerdefinierte Images für mehrere Architekturen erstellen und im Laufe der Zeit die Programme oder Pakete hinzufügen/ändern, die Ihrem benutzerdefinierten Image hinzugefügt wurden. Dazu können Sie Packer aus HashiCorp verwenden.
Packer
Packer ist das Open-Source-Tool von HashiCorp, mit dem Maschinenimages aus der Quellkonfiguration erstellt werden. Es ist leicht, läuft auf jedem großen Betriebssystem, hochleistungsfähig. Konfigurationsmanagement wie Chef oder Puppet wird nicht ersetzt. Wenn Sie Bilder erstellen, kann Packer Tools wie Chef oder Puppet verwenden, um Software auf dem Bild zu installieren. Einige der Features sind:
-
Automatisieren Sie die Erstellung eines beliebigen Maschinentyps. Passen Sie Bilder an die Anwendungs- und Organisationsanforderungen an.
-
Erstellen Sie identische Maschinenimages für mehrere Plattformen aus einer Quellkonfiguration.
-
Erstellen Sie Maschinenimages für mehrere Plattformen parallel.
Vorteile der Verwendung von Packer
- Automatisieren Sie den gesamten Prozess.
- Erstellen Sie mehrere benutzerdefinierte Images gleichzeitig.
- Erstellen Sie Images für verschiedene Architekturen.
- Kann parallel ausgeführt werden.
- Kann in der OCI DevOps-Build-Pipeline verwendet werden.
- Es verwendet HCL-Sprache.
- Kann mit Provisioning (d.h. Shell oder Ansible) benutzerdefinierte Skripte/Befehle auf dem Compute ausführen.
Packer-Authentifizierung
Sie können Packer mit den folgenden Optionen authentifizieren.
-
Standardmäßig wird das Profil DEFAULT aus der Datei
.oci/config
verwendet. -
Mit Instanz-Principal: Fügen Sie das Argument use_instance_principals in die Packer-Konfigurationsdatei ein (Beispiel unten).
-
API-Signaturschlüssel.
-
Sicherheitstoken.
Hinweis: Weitere Informationen zur Packer-Authentifizierung. Sie sollten jedoch entweder die Datei
.oci/config
oder den Instanz-Principal verwenden.
Funktionsweise von Packer
In den Aufgaben nimmt Packer ein Image an, das im Parameter base_image_ocid angegeben ist, und stellt eine Compute-Instanz mit den von Ihnen angegebenen Attributen in den erforderlichen Konfigurationsparametern bereit (z.B. Verfügbarkeit*Domain, Ausprägung usw.).
Nach diesem Packer wird versucht, einen SSH-Vorgang in die Instanz auszuführen, um einen beliebigen Provisioning-Block (_provisioner "shell"*) auszuführen, den Sie nach dem Starten im Block build im Basisimage angegeben haben. Für diese Aufgabe müssen Sie überlegen, wo Sie die Instanz bereitstellen (die Attribute subnet_ocid), sodass Packer über den Rechner, auf dem Packer ausgeführt wird, in der Instanz ein SSH ausführen kann. Bei den End-Packer-Snapshots wird ein wiederverwendbares benutzerdefiniertes Image erstellt.
Packer-Provisioner
Providern sind wichtige Komponenten von Packer, die Software innerhalb eines laufenden Rechners installieren und konfigurieren, bevor dieser Rechner in ein statisches Image umgewandelt wird. Sie führen die Hauptarbeit bei der Erstellung des Images mit nützlicher Software aus.
Beispiele für Provisioning-Operatoren:
- Shell: Die einfachste Möglichkeit, Software auf einem Rechner zu installieren und zu konfigurieren.
- Datei: So laden Sie Dateien auf Rechner hoch, die von Packer erstellt wurden.
- Ansible: Ansible-Playbooks ausführen.
Ziele
-
Erstellen Sie ein benutzerdefiniertes Image aus einem vorhandenen Image, und ändern Sie die Attribute
nic_attachment_type
undimage_launch_mode
. -
Erstellen Sie ein benutzerdefiniertes Image aus einem vorhandenen Image, und führen Sie ein Ansible-Playbook auf dem neu erstellten Image aus.
Voraussetzungen
-
OCI-Mandant und OCI-Account mit ausreichenden Berechtigungen zum Verwalten von Instanzfamilie, Verwenden von Netzwerk und Images.
Allow group PackerGroup to manage instance-family in compartment ${COMPARTMENT_NAME} Allow group PackerGroup to manage instance-images in compartment ${COMPARTMENT_NAME} Allow group PackerGroup to use virtual-network-family in compartment ${COMPARTMENT_NAME} Allow group PackerGroup to use compute-image-capability-schema in tenancy
-
Installieren Sie Packer Packer.
-
Packer benötigt einige Konfigurationsparameter. Informationen hierzu finden Sie unter Erforderliche Konfigurationsparameter.
-
Packer verwendet ssh, um eine Verbindung zu bereitgestelltem Compute herzustellen, um die in der Packer-Konfigurationsdatei beschriebenen Änderungen vorzunehmen. Machen Sie die Instanz auf Port 22 erreichbar (geben Sie in der Regel eine Subnetz-OCID an, auf die von dem Host zugegriffen werden kann, auf dem Packer ausgeführt wird - das atribute subnet_ocid).
Aufgabe 1: Paketkonfigurationsdatei erstellen
Packer unterstützt das HCL- oder JSON-Format. In der folgenden Aufgabe ist es ein HCL-Format.
-
Benennen Sie die Datei so, wie Sie möchten. Geben Sie am Ende jedoch .pkr.hcl ein.
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"] }
-
subnet_ocid ist das Subnetz, in dem die Instanz bereitgestellt wird, bis das benutzerdefinierte Image erstellt wird. Dies ist ein Subnetz, das von dem Host erreichbar sein muss, auf dem Packer ausgeführt wird. Normalerweise sollten Sie keine Entwicklungsinstanzen mit einer öffentlichen IP erstellen, da es keinen Grund dafür gibt, dass diese dem Internet ausgesetzt sind, und dies nur Sicherheitsbedenken verursacht. Eine Möglichkeit, öffentliche IP-Adressen zu vermeiden, besteht darin, Packer aus OCI auszuführen oder den OCI Bastion-Service zu verwenden. Sie können auch FastConnect oder ein anderes VPN verwenden, um das OCI-Subnetz von On Premise aus zu erreichen, ohne das Internet durchlaufen zu müssen.
Aufgabe 2: Packer initialisieren
-
Packer-Initialisierung ausführen.
<path to packer bin> init <packer conf file>
Beispiel:
<path to packer bin> init oke.pkr.hcl
Aufgabe 3: Bild erstellen
-
Zu diesem Zeitpunkt verfügen Sie über ein benutzerdefiniertes Image mit
image_launch_mode = "NATIVE"
undnic_attachment_type = "VFIO"
. Sie können andere Attribute ändern. Alle sind in der offiziellen Dokumentation beschrieben. -
Sie können benutzerdefinierte Befehle oder Skripte ausführen (es sind Beispiele angehängt).
<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..........'
Beispiel mit Provisioning:
-
In diesem Beispiel wird provisioner (Shell und Datei) verwendet.
-
Er würde 2 Bilder erstellen (in der Quelle angegeben).
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}"] } }
-
Es verwendet Variablen (wie in Terraform).
image_compartment_ocid = var.deploy_in_comp
-
Die Authentifizierungsmethode ist mit der .oci/config-Datei (Standard), verwendet jedoch ein Attribut, um das gewünschte Profil innerhalb der zu verwendenden Datei anzugeben.
access_cfg_file_account = var.OCI_PROFILE
-
In diesem Beispiel verwenden wir provisioner "shell" und provisioner "file" sowie provisioner "shell-local".
-
Der Shell Packer-Provisioner stellt Rechner bereit, die von Packer mit Shellskripten erstellt wurden. Das Shell-Provisioning ist die einfachste Möglichkeit, Software auf einem Rechner zu installieren und zu konfigurieren.
-
Sie können entweder den Shell-Befehl auf dem Rechner ausführen (verwenden Sie inline) oder das E-Skript ausführen (verwenden Sie script).
-
Außerdem wurde der file-Provisioner verwendet. Der File Packer-Provisioner lädt Dateien auf Rechner hoch, die von Packer erstellt wurden.
-
Weitere Beispiele finden Sie in der hcl-Datei, die Sie prov-example.pkr.hcl herunterladen können.
Beispiel für die Verwendung von Variablendateien und Ansible-Providern:
-
Wir verwenden:
- Variablendateien.
- eine andere Authentifizierungsmethode - Variablen werden verwendet.
-
Anstatt Shell zum Installieren von Packages zu verwenden, verwenden wir ansible zum Ausführen von Playbooks, die in einem separaten Ordner gespeichert sind.
-
Diese Methode ist für komplexere Situationen gedacht, die von Ansible besser gehandhabt werden können.
-
Es gibt zwei unglaubliche Bereitsteller:
- ansible-local: Kann auf dem Host installiert werden, den Packer erstellt (Sie können Ansible mit der Provisioning-Shell installieren).
- Ansible: Es wird vom Host ausgeführt, der Packer ausführt, damit keine Instanz vorhanden sein muss, die Sie erstellen.
-
Es sind mehrere Konfigurationsdateien beteiligt, sodass Sie den Verzeichnisnamen beim Erstellen angeben müssen.
packer build <directory name>
-
Hier die Beispieldatei ansible-example.pkr.hcl. Im Folgenden finden Sie die 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" ] #} }
-
Hier ist die vars.pkr.hcl. In dieser Datei deklarieren und initialisieren wir sie.
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......" }
-
Hier ist die Authentifizierung (auth-vars.pkr.hcl), diese Datei wird zum Setup der Authentifizierung verwendet.
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 = "...." }
-
Verwandte Links
Danksagungen
Autor - Francisc Vass (Principal Cloud Architect)
Weitere Lernressourcen
Sehen Sie sich andere Übungen zu docs.oracle.com/learn an, oder greifen Sie auf weitere kostenlose Lerninhalte im Oracle Learning YouTube-Kanal zu. Besuchen Sie außerdem die Website education.oracle.com/learning-explorer, um Oracle Learning Explorer zu werden.
Produktdokumentation finden Sie im Oracle Help Center.
Use Packer to create Oracle Cloud Infrastructure custom images
F87727-01
October 2023
Copyright © 2023, Oracle and/or its affiliates.