Remarque :

Créer un cluster Container Engine for Kubernetes (OKE) avec un fournisseur OCI pour Pulumi

Introduction

Oracle Cloud Infrastructure (OCI) Container Engine for Kubernetes (OKE) est un service entièrement géré, évolutif et hautement disponible que vous pouvez utiliser pour déployer vos applications en conteneur vers le cloud. Vous indiquez les ressources de calcul requises par vos applications et OKE les provisionne sur OCI dans une location existante. OKE utilise Kubernetes pour automatiser le déploiement, la mise à l'échelle et la gestion d'applications en conteneur sur les clusters d'hôtes.

Pulumi est une plate-forme moderne d'infrastructure en tant que code qui vous permet d'utiliser des langages de programmation et des outils familiers pour créer, déployer et gérer une infrastructure cloud. Le fournisseur Oracle Cloud Infrastructure (OCI) pour Pulumi peut être utilisé pour provisionner toutes les ressources disponibles dans OCI. Le fournisseur OCI doit être configuré avec des informations d'identification pour déployer et mettre à jour des ressources dans OCI.

Ce tutoriel présente la gestion de l'infrastructure en tant que code à l'aide du fournisseur OCI pour Pulumi. Vous apprendrez à provisionner un cluster OKE en utilisant Python comme langage de développement.

Objectif

Prérequis

Tâche 1 : Créer une pile Pulumi

Chaque programme Pulumi est déployé sur une pile. Une pile est une instance isolée et configurable indépendamment d'un programme Pulumi. Les piles sont généralement utilisées pour désigner différentes phases de développement (développement, préparation et production, par exemple) ou branches d'objets (fonctionnalités x-dev, par exemple).

Créer un répertoire de base

Créez un répertoire de base pour votre pile dans lequel nous stockons un fichier d'état et votre code source de pile.

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

Créer un référentiel d'états

Pulumi stocke l'état de votre pile dans Pulumi Service ou dans un fichier d'état local pour suivre les modifications de votre infrastructure. Dans ce tutoriel, nous allons le stocker dans un fichier d'état local.

Option 1. créer un répertoire de fichier d'état local

Cette option crée un répertoire local pour stocker les états. Pour ce tutoriel, l'option 1 sera configurée.

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

Option 2. État du magasin dans le service gratuit de Pulumi

Pulumi propose un service pour stocker l'état de la pile. Il existe plusieurs couches, de libre à organisation.

$> pulumi login

Remarque : Pour ce tutoriel, nous enregistrerons uniquement le fichier d'état localement comme décrit dans l'option 1. L'option 2 ne concerne que des informations supplémentaires.

Créer une pile Python

  1. Confirmez le service et l'utilisateur que vous utilisez en exécutant la commande whoami.

    $> pulumi whoami -v
    
    User: <user>
    Organizations:
    Backend URL: file://oci-stack-statefile
    
  2. Lors de la création d'une pile, Pulumi doit comprendre le type de modèle à utiliser pour votre projet.

    Remarque :

    • Comme nous allons coder en Python, vous devez sélectionner un modèle Python en transmettant le nom du modèle "python" après les mots-clés "pulumi new".
    • La CLI Pulumi vous invite à saisir le nom de votre projet (par défaut, le nom du dossier parent) et un environnement spécifique (par défaut, dev) pour vous aider à classer et classer vos piles.
    $>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'
    
    

    Remarque : lorsque vous stockez un fichier d'état localement dans le même chemin que votre pile, l'option -force est requise car le répertoire n'est pas vide (il contient le dossier pulumi-statefile).

  3. Vous allez à présent exécuter le déploiement initial. Gardez la phrase de passe que vous avez entrée à l'étape précédente à portée de main.

       $> 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. Vérifiez que l'environnement est créé à l'aide des commandes suivantes.

    Remarque : juste après que le modèle soit correctement créé et stocké localement, Pulumi crée également un environnement (venv) virtuel Python avec des packages de site utilisés par votre programme Python. Les environnements virtuels ne sont pas inclus dans la portée de ce tutoriel.

    -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 : point d'entrée de votre application Python et c'est ce que Pulumi recherchera.

    • Pulumi.yaml : descripteur de pile.

    • Pulumi.dev.yaml : configuration d'environnement de pile.

    • requirements.txt : fichier standard défini pour répertorier les packages requis par pip python.

    • venv : environnement virtuel Python.

Tâche 2 : configuration de l'environnement virtuel Python

Pulumi a enregistré le fournisseur OCI et il est disponible via pip. pip est un gestionnaire de packages Python pour installer les bibliothèques existantes. Installez-le, mais uniquement dans l'environnement virtuel.

  1. Activez votre environnement virtuel Python à l'aide de la commande suivante.

    $>  source venv/bin/activate
    
  2. Installez le package pulumi_oci à l'aide de pip.

    (venv) j2joi@cloudshell:pulumi-oke-py (us-ashburn-1)$  pip install pulumi_oci
    
  3. Configurez le fournisseur OCI pour Pulumi.

    Remarque : Pulumi stocke les détails de configuration dans son propre service de configuration. Vous devez configurer le fournisseur OCI pour Pulumi afin qu'il s'authentifie auprès de votre location. Collectez le profil utilisateur, la clé d'API, l'OCID utilisateur, l'OCID de location, la région et stockez-le en tant que clés secrètes dans la configuration de l'environnement pulumi. Notez que vous les transmettez en tant que clés secrètes, de sorte qu'elles seront cryptées à l'aide de la phrase de passe que vous avez fournie lors de la création de l'environnement.

    $> 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"
    

    Conseil :

    • Exportez PULUMI_CONFIG_PASSPHRASE avec votre valeur de phrase de passe. Cela permet de gagner du temps au lieu de le fournir à chaque ajout d'une clé secrète.
    • Les valeurs de configuration OCI peuvent être lues directement à partir des variables d'environnement sous la forme TF_VAR_${var_name}.
  4. Vérifiez que vos clés secrètes sont stockées dans la banque de configuration.

    $> (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]
    

    Remarque : Pulumi utilise deux types var principaux, l'entrée [T] et la sortie [T] de type T. Input[T] est un wrapper de valeurs brutes de types de données Python de base (chaîne, booléen, Dict, séquence) et Output contient la valeur future une fois qu'une ressource est créée.

    Gardez cela à l'esprit si vous tentez de manipuler la valeur d'une sortie en la transmettant à une bibliothèque standard Python, c'est-à-dire en tentant de fractionner un nom de sortie de ressource [String], comme name.split(), car elle se terminera par une erreur car la variable de nom de type Sortie ne prend pas en charge le fractionnement.

  5. Créez le premier cluster OKE. Avant de commencer à coder, le fragment de code suivant nécessite la création d'un réseau cloud virtuel existant. Les sous-réseaux pour OKE doivent comporter 3 sous-réseaux requis pour l'adresse Kubernetes, les noeuds de processus actif et le service d'équilibreur de charge. Pour plus d'informations sur les exigences du sous-réseau pour OKE, telles que la stratégie et le routage, reportez-vous à la documentation OCI.

    Examinons la définition de variable Python du 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. Une fois le VCN OCI prêt et les détails de l'OCID de compartiment, de sous-réseaux et de VCN disponibles, modifiez le fichier __main__.yaml à l'aide du fragment de code suivant. Mettez à jour les valeurs avec les OCID correspondants.

     "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)
    

    Conseil : vous pouvez demander des ocids de ressource à partir du magasin de configuration Pulumi afin de réutiliser votre code pour d'autres environnements au lieu d'affecter des valeurs ocid directement dans votre code Python.

    Remarque : l'indentation est essentielle pour Python. Assurez-vous que votre code suit l'indentation Python.

  7. Vérifier les modifications de l'infrastructure : Pulumi a la possibilité de prévisualiser les ressources que la pile actuelle va créer/modifier. Exécutez l'option "prévisualisation pulumi" pour valider votre pile python actuelle.

    (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. Appliquez les modifications à votre infrastructure : si aucun message d'erreur n'est affiché, vous pouvez créer un cluster OKE. Exécutez "pulumi up" pour déclencher l'application des modifications à la pile.

    (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. Ajoutez une ressource de pool de noeuds OKE : Pulumi Stack a créé le premier cluster OKE "oke_cluster". Maintenant, nous allons ajouter des noeuds de processus actif affectés à une variable de pool de noeuds dans le même fichier main.py. Les modifications seront ajoutées de manière incrémentielle à l'ensemble de ressources dans OCI car Pulumi suit les ressources créées et compare toutes les différences entre la ressource dans le fournisseur cloud et l'état stocké dans le back-end sélectionné pour vérifier si des mises à jour sont requises pour les ressources existantes ou nouvelles.

    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. Mettez à jour à nouveau votre infrastructure en exécutant la commande "pulumi up".

    $> pulumi up
    

Informations supplémentaires

Pulumi Marketplace dispose déjà d'autres fournisseurs existants que vous pouvez utiliser, comme Kubernetes, Helm, etc. L'un des avantages de la création de ressources dans Oracle Cloud, comme Kubernetes, est sa compatibilité avec la plupart des normes Kubernetes et son intégration est simple. L'exemple suivant montre comment créer votre propre fournisseur Kubernetes à l'aide du fournisseur de Pulumi et déployer des applications dans votre code 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)

Tâche 3 : Supprimer des ressources

Vous avez terminé votre première pile Python avec le fournisseur OCI de Pulumi. Pour supprimer toutes les ressources, exécutez la commande 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

Accusés de réception

Ressources de formation supplémentaires

Explorez d'autres ateliers sur docs.oracle.com/learn ou accédez à davantage de contenu de formation gratuit sur le canal Oracle Learning YouTube. En outre, accédez à education.oracle.com/learning-explorer pour devenir explorateur Oracle Learning.

Pour consulter la documentation du produit, consultez Oracle Help Center.