Nota:

Creare un cluster OKE (Container Engine for Kubernetes) con il provider OCI per Pulumi

Introduzione

Oracle Cloud Infrastructure (OCI) Container Engine for Kubernetes (OKE) è un servizio completamente gestito, scalabile e ad alta disponibilità che puoi utilizzare per distribuire le tue applicazioni gestite in container nel cloud. È possibile specificare le risorse di computazione necessarie alle applicazioni e OKE ne esegue il provisioning in OCI in una tenancy esistente. OKE utilizza Kubernetes per automatizzare la distribuzione, la scalabilità e la gestione di applicazioni in container in tutti i cluster di host.

Pulumi è una piattaforma di codice moderna che ti consente di usare linguaggi e strumenti di programmazione noti per creare, distribuire e gestire l'infrastruttura cloud. Il provider OCI (Oracle Cloud Infrastructure) per Pulumi può essere utilizzato per eseguire il provisioning di qualsiasi risorsa disponibile in OCI. Il provider OCI deve essere configurato con le credenziali per distribuire e aggiornare le risorse in OCI.

Questa esercitazione fornisce una panoramica su come gestire l'infrastruttura come codice mediante il provider OCI per Pulumi. Verrà descritto come eseguire il provisioning di un cluster OKE utilizzando Python come linguaggio di sviluppo.

Obiettivo

Prerequisiti

Task 1: Creare uno stack Pulumi

Ogni programma Pulumi è implementato in uno stack. Uno stack è un'istanza isolata e configurabile in modo indipendente di un programma Pulumi. Gli stack vengono in genere utilizzati per indicare varie fasi di sviluppo (ad esempio sviluppo, staging e produzione) o diramazioni delle funzioni (ad esempio feature-x-dev).

Creare una directory home

Creare una directory home per lo stack in cui memorizzare un file di stato e il codice sorgente dello stack.

$> mkdir pulumi-oke-py && cd pulumi-oke-py   (on Linux or MacOS )

Creare un repository di stato

Pulumi memorizza lo stato del tuo Stack in Pulumi Service o in un file di stato locale per tenere traccia delle modifiche della tua infrastruttura. In questa esercitazione verrà memorizzata in un file di stato locale.

Opzione 1. Creare una directory del file di stato locale

Questa opzione creerà una directory locale in cui memorizzare gli stati. Per questa esercitazione verrà configurata l'opzione 1.

$> mkdir oci-stack-statefile (on Linux or MacOS )
$> pulumi login file://oci-stack-statefile

Opzione 2. Memorizza lo stato nel servizio gratuito Pulumi

Pulumi offre un servizio per memorizzare lo stato Stack. Esistono più livelli da liberi a organizzativi.

$> pulumi login

Nota: per questa esercitazione verrà salvato in locale solo il file di stato come descritto nell'opzione 1. L'opzione 2 è solo per informazioni aggiuntive.

Crea un nuovo stack Python

  1. Verificare quale servizio e utente si stanno utilizzando eseguendo il comando whoami.

    $> pulumi whoami -v
    
    User: <user>
    Organizations:
    Backend URL: file://oci-stack-statefile
    
  2. Quando si crea uno stack, Pulumi deve capire quale tipo di modello utilizzare per il tuo progetto.

    Nota:

    • Come programmiamo in Python, è necessario selezionare un modello Python passando il nome del modello "python" dopo le parole chiave "pulumi new".
    • La CLI Pulumi ti chiederà un nome per il tuo progetto (l'impostazione predefinita è il nome della cartella padre) e un ambiente specifico (l'impostazione predefinita è dev) che ti aiuterà a classificare e classificare gli stack.
    $>pulumi new python --force
    
    This command will walk you through creating a new Pulumi project.
    
    Enter a value or leave blank to accept the (default), and press <ENTER>.
    Press ^C at any time to quit.
    
    project name: (pulumi-oke-py)
    project description: (A minimal Python Pulumi program)
    Created project 'pulumi-oke-py'
    
    stack name: (dev)
    Created stack 'dev'
    Enter your passphrase to protect config/secrets:
    Re-enter your passphrase to confirm:
    
    Failed to resolve python version command: fork/exec $PATH/pulumi-oke-py/venv/bin/python: no such file or directory
    
    Installing dependencies...
    
    Creating virtual environment...
    Finished creating virtual environment
    Updating pip, setuptools, and wheel in virtual environment...
    Collecting pip
    Using cached https://files.pythonhosted.org/packages/96/2f/caec18213f6a67852f6997fb0673ae08d2e93d1b81573edb93ba4ef06970/pip-22.1.2-py3-none-any.whl
    Collecting setuptools
    Using cached https://files.pythonhosted.org/packages/e9/1c/ec080fde54ab30a738c92f794eab7f5d2f354f2b619ee95b2efe353e0766/setuptools-62.3.2-py3-none-any.whl
    Collecting wheel
    Using cached https://files.pythonhosted.org/packages/27/d6/003e593296a85fd6ed616ed962795b2f87709c3eee2bca4f6d0fe55c6d00/wheel-0.37.1-py2.py3-none-any.whl
    Installing collected packages: pip, setuptools, wheel
    .....
    Collecting grpcio~=1.33
    Using cached grpcio-1.46.3-cp37-cp37m-macosx_10_10_x86_64.whl (4.3 MB)
    Installing collected packages: six, semver, pyyaml, protobuf, dill, grpcio, pulumi
    Successfully installed dill-0.3.5.1 grpcio-1.46.3 protobuf-3.20.1 pulumi-3.33.2 pyyaml-5.4.1 semver-2.13.0 six-1.16.0
    Finished installing dependencies
    
    Your new project is ready to go! ✨
    
    To perform an initial deployment, run 'pulumi up'
    
    

    Nota: quando si memorizza un file di stato localmente nello stesso percorso dello stack, l'opzione -force è necessaria poiché la directory non è vuota (contiene la cartella pulumi-statefile).

  3. Verrà ora eseguita la distribuzione iniziale. Conservare la passphrase immessa nella fase precedente a portata di mano.

       $> pulumi up
       Enter your passphrase to unlock config/secrets
          (set PULUMI_CONFIG_PASSPHRASE or PULUMI_CONFIG_PASSPHRASE_FILE to remember):
       Previewing update (dev):
          Type                 Name             Plan
       +   pulumi:pulumi:Stack  pulumi-oke-py-dev  create
    
       Resources:
          + 1 to create
    
       Do you want to perform this update? yes
       Updating (dev):
          Type                 Name             Status
       +   pulumi:pulumi:Stack  pulumi-oke-py-dev  created
    
       Resources:
          + 1 created
    
       Duration: 1s
    
  4. Confermare la creazione dell'ambiente con i comandi seguenti.

    Nota: dopo aver creato e memorizzato correttamente il modello in locale, Pulumi creerà anche un ambiente (venv) virtuale Python con pacchetti di siti utilizzati dal programma Python. Gli ambienti virtuali non sono inclusi in questa esercitazione.

    -rw-r--r--. 1 <user> oci 45 May 23 20:07 __main__.py
    -rw-r--r--. 1 <user> oci 117 May 23 20:07 Pulumi.yaml
    -rw-r--r--. 1 <user> oci 21 May 23 20:07 requirements.txt
    -rw-r--r--. 1 <user> oci 21 May 23 20:07 Pulumi.dev.yaml
    drwxr-xr-x. 5 <user> oci 100 May 23 20:08 venv
    drwxr-xr-x. 5 <user> oci 100 May 23 20:06 oci-stack-statefile
    
    • __main__py : Il punto di accesso per la tua applicazione Python e questo è quello che Pulumi analizzerà.

    • Pulumi.yaml: descrittore stack.

    • Pulumi.dev.yaml: configurazione dell'ambiente stack.

    • requirements.txt: file standard definito per elencare i pacchetti richiesti da Pip python.

    • venv: ambiente virtuale Python.

Task 2: configurare l'ambiente virtuale Python

Pulumi ha registrato il provider OCI ed è disponibile tramite pip. pip è un gestore dei pacchetti Python per installare le librerie esistenti. È necessario installarlo, ma solo nell'ambiente virtuale.

  1. Attivare l'ambiente virtuale Python utilizzando il comando seguente.

    $>  source venv/bin/activate
    
  2. Installare il package pulumi_oci utilizzando pip.

    (venv) j2joi@cloudshell:pulumi-oke-py (us-ashburn-1)$  pip install pulumi_oci
    
  3. Configurare il provider OCI per Pulumi.

    Nota: Pulumi memorizza i dettagli di configurazione all'interno del proprio servizio di configurazione. Per eseguire l'autenticazione contro la tenancy, è necessario configurare il provider OCI per Pulumi. Raccogliere il profilo utente, la chiave API, l'OCID utente, l'OCID tenancy, l'area e memorizzarlo come segreto all'interno della configurazione ambiente pulumi. Si noti che passerà come segreto, quindi verrà cifrato utilizzando la passphrase fornita durante la creazione dell'ambiente.

    $> pulumi config set oci:tenancyOcid "ocid1.tenancy.oc1..<unique_ID>" --secret  
    $> pulumi config set oci:userOcid "ocid1.user.oc1..<unique_ID>" --secret
    $> pulumi config set oci:fingerprint "<key_fingerprint>" --secret
    $> pulumi config set oci:region "<target region in OCI>"
    $> cat "~/.oci/oci_api_key.pem" | pulumi config set oci:privateKey --secret
    $> pulumi config set compartment_ocid "ocid1.compartment.oc1..aaaaaaaaqiuXXXXXXXXXX"
    

    Suggerimento:

    • Esportare PULUMI_CONFIG_PASSPHRASE con il valore della passphrase. Risparmia tempo invece di fornirlo ogni volta che viene aggiunto un segreto.
    • I valori di configurazione OCI possono essere letti direttamente dalle variabili di ambiente nel formato TF_VAR_${var_name}.
  4. Verificare che i segreti siano memorizzati nell'area di memorizzazione della configurazione.

    $> (venv) j2joi@cloudshell:pulumi-oke-py (us-ashburn-1)$  pulumi config
    
    KEY VALUE
    oci:fingerprint [secret]
    oci:privateKey [secret]
    oci:region us-ashburn-1
    oci:tenancyOcid [secret]
    oci:userOcid [secret]
    

    Nota: Pulumi utilizza due tipi di var principali, input [T] e output[T] di tipo T. Input[T] è un wrapper dei valori raw dei tipi di dati Python di base (stringa, booleano, Ditt, Sequenza) e Output contiene il valore futuro dopo la creazione di una risorsa.

    Tenere presente che se si sta tentando di manipolare il valore di un Output passandolo a qualsiasi libreria standard Python, ovvero cercando di suddividere un nome di output di risorsa [String], ad esempio name.split(), poiché finirà con un errore poiché la variabile di nome di tipo Output non supporta la divisione.

  5. Creare il primo cluster OKE. Prima di iniziare la codifica, il seguente snippet di codice richiede la creazione di una rete cloud virtuale esistente. Le subnet per OKE devono avere 3 subnet necessarie per l'endpoint Kubernetes, i nodi di lavoro e il servizio di bilanciamento del carico. Per ulteriori informazioni sui requisiti della subnet per OKE, come criteri, instradamento, consultare la documentazione OCI.

    Esaminare la definizione della variabile Python del cluster OCI:

    Type: pulumi_oci.containerengine.Cluster
    
    Arguments:
    
       - compartment_id : This is the Oracle Cloud Identifier OCID linked to the target compartment.
       - kubernetes_version : Update with the Kubernetes main stream versions that are supported in OCI.
       - name: This is the Kubernetes cluster displayed name.
       - options: Network CIDRs for different services and a list of subnets used for loadbalancer services, wrapped in a ClusterOptionsKubernetesNetworkConfigArgs object.
       - endpoint_config - Define if the cluster Kubernetes endpoint will have a public IP address and which subnet it will be attached to.
       - vcn_id - Virtual cloud network the Kubernetes cluster will be attached to.
    
  6. Una volta che la VCN OCI è pronta e disponi dei dettagli della VCN, delle subnet e dell'OCID del compartimento, procedere alla modifica del file __main__.yaml con lo snippet di codice seguente. Aggiorna i valori con gli OCID corrispondenti.

     "A Python Pulumi program"
     import pulumi
     import pulumi_oci as oci
    
     config = pulumi.Config()
    
     target_compartment_ocid = "ocid1.compartment.oc1.iad.XXXXXXX"
    
     subnets_lb_ocid= ["ocid1.subnet.oc1.iad.aaaaaaaan6fXXXXXXXXX"]
    
     subnet_workernodes_ocid = "ocid1.subnet.oc1.iad.aaaaaaaakYYYYYYY"
    
     subnet_endpoint_ocid = "ocid1.subnet.oc1.iad.aaaaaaaaxmfZZZZZZZZZ"
    
     vcn_ocid="ocid1.vcn.oc1.iad.amaaaaaadoggtjaasym4AAAAAAAAAA"
    
     kubernetes_version="v1.23.4"
    
     oke_cluster_opts_args = oci.containerengine.ClusterOptionsArgs(
     kubernetes_network_config=oci.containerengine.ClusterOptionsKubernetesNetworkConfigArgs(
     pods_cidr="10.244.0.0/16",
     services_cidr="10.96.0.0/16"),
     service_lb_subnet_ids = subnets_lb_ocid
     )
    
     oke_cluster = oci.containerengine.Cluster("oke_cluster",
     compartment_id = target_compartment_ocid,
     kubernetes_version = kubernetes_version,
     name = "firstPulumiPy_OKE",
     options = oke_cluster_opts_args,
     endpoint_config = oci.containerengine.ClusterEndpointConfigArgs(
     is_public_ip_enabled = True,
     subnet_id = subnet_endpoint_ocid),
     vcn_id = vcn_ocid,
     )
     pulumi.export("oke_cluster_ocid", oke_cluster)
    

    Suggerimento: è possibile richiedere agli ocid delle risorse dall'area di memorizzazione della configurazione Pulumi di riutilizzare il codice per altri ambienti invece di assegnare i valori ocid direttamente nel codice Python.

    Nota: l'indentazione è essenziale per Python. Assicurarsi che il codice rispetti la rientranza Python.

  7. Rivedi le modifiche dell'infrastruttura: Pulumi ha la possibilità di visualizzare in anteprima le risorse che lo stack attuale creerà/modificherà. Eseguire l'opzione "Anteprimapulumi" per convalidare lo stack python corrente.

    (venv) j2joi@cloudshell:pulumi-oke-py (us-ashburn-1)$ pulumi preview
    Previewing update (dev)
    
         Type                            Name               Plan       Info
     +   pulumi:pulumi:Stack             pulumi-oke-py-dev  create     1 message
     +   └─ oci:ContainerEngine:Cluster  oke_cluster        create     
    
  8. Applicare le modifiche all'infrastruttura. Se non viene visualizzato alcun messaggio di errore, è possibile creare un cluster OKE. Eseguire "pulumi up" per attivare lo stack per applicare le modifiche.

    (venv) j2joi@cloudshell:pulumi-oke-py (us-ashburn-1)$ pulumi up
    Updating (dev)
    
         Type                            Name               Status      Info
     +   pulumi:pulumi:Stack             pulumi-oke-py-dev  created     12 messages
     +   └─ oci:ContainerEngine:Cluster  oke_cluster        created
    
  9. Aggiungere una risorsa pool di nodi OKE: Pulumi Stack ha creato il primo cluster OKE "oke_cluster". Ora, consente di aggiungere nodi di lavoro assegnati a una variabile pool di nodi nello stesso file main.py. Le modifiche verranno aggiunte in modo incrementale al set di risorse in OCI perché Pulumi tiene traccia delle risorse create e confronterà qualsiasi differenza tra la risorsa all'interno del provider cloud e lo stato memorizzato nel backend selezionato per verificare se sono necessari aggiornamenti per le risorse esistenti o nuove.

    Worker node Compute Instance details
    number_worker_nodes= 3
    default_node_memory_size=16
    default_node_num_ocpus =1
    
    # Get the Availability Domain names for this region
    ad_list=oci.identity.get_availability_domains(target_compartment_ocid)
    ad=ad_list.availability_domains
    
    # Get the list of supported images based on the compartment and filter it by most recent image
    list_of_supported_image =oci.core.get_images(compartment_id=target_compartment_ocid,
                                          operating_system="Oracle Linux",
                                          operating_system_version= "7.9",
                                          shape= "VM.Standard.E3.Flex",
                                          sort_by="TIMECREATED",
                                          sort_order="DESC"
                                          )
    #Obtain the first image ocid from  list_of_supported_image var
    os_image_ocid= list_of_supported_image.images[0].id
    
    # Pin for this example all worker nodes to a first Availability Domain
    place_nodes_subnet=[oci.containerengine.NodePoolNodeConfigDetailsPlacementConfigArgs(
                    availability_domain=ad[0].name,
                    subnet_id= subnet_workernodes_ocid
                ),]
    
    #Declare all Pool properties
    node_pool_args = oci.containerengine.NodePoolArgs(cluster_id=oke_cluster.id,
                                                          compartment_id= target_compartment_ocid,
                                                          kubernetes_version=kubernetes_version,
                                                          node_shape= "VM.Standard.E3.Flex",
                                                          name="E3Flex",
                                                          node_config_details=oci.containerengine.NodePoolNodeConfigDetailsArgs(
                                                              placement_configs= place_nodes_subnet ,
                                                              size= number_worker_nodes
                                                          ),
                                                          node_shape_config=oci.containerengine.NodePoolNodeShapeConfigArgs(
                                                              memory_in_gbs= default_node_memory_size,
                                                              ocpus= default_node_num_ocpus,
                                                          ),
                                                          node_source_details=oci.containerengine.NodePoolNodeSourceDetailsArgs(
                                                              image_id= os_image_ocid,
                                                              source_type="IMAGE",
                                                              boot_volume_size_in_gbs=60,
                                                          ),
                                                          )
    #Assign node pool properties as args to node_pool
    node_pool = oci.containerengine.NodePool("nodepool", args=node_pool_args)
    
    pulumi.export("oke_cluster_ocid", oke_cluster)
    pulumi.export("oke_node_pool", node_pool)
    
  10. Aggiornare nuovamente l'infrastruttura eseguendo il comando "pulumi up".

    $> pulumi up
    

Ulteriori infomazioni

Pulumi Marketplace ha già alcuni altri provider esistenti che puoi utilizzare, come Kubernetes, Helm e così via. Un vantaggio di creare risorse in Oracle Cloud, ad esempio Kubernetes, è la compatibilità con la maggior parte degli standard Kubernetes e l'integrazione è semplice. L'esempio riportato di seguito mostra come creare un provider Kubernetes personalizzato utilizzando il provider di Pulumi e distribuire le applicazioni nel codice Python.

import pulumi_kubernetes

kubeconfig = oci.containerengine.get_cluster_kube_config_output(cluster_id=oke_cluster.id).apply(
   lambda kube_config: kube_config.content)

k8sProvider = pulumi_kubernetes.Provider("okeK8s",
                                        kubeconfig=kubeconfig
                                        )


pulumi.export("kubeconfig", kubeconfig)

Task 3: Rimuovi risorse

Hai completato il primo stack Python con il provider OCI per Pulumi. Per eliminare tutte le risorse, eseguire il comando pulumi destroy.

$> pulumi destroy

pulumi destroy
Previewing destroy (dev):
     Type                            Name             Plan
 -   pulumi:pulumi:Stack             local-state-dev  delete
 -   └─ oci:ContainerEngine:Cluster  oke_cluster      delete

Conferme

Altre risorse di apprendimento

Esplora altri laboratori su docs.oracle.com/learn o accedi ad altri contenuti per la formazione gratuita sul canale YouTube di Oracle Learning. Inoltre, visitare education.oracle.com/learning-explorer per diventare Oracle Learning Explorer.

Per la documentazione sul prodotto, visitare Oracle Help Center.