Observação:

Crie um cluster do Container Engine for Kubernetes (OKE) com o provedor do OCI para Pulumi

Introdução

O Oracle Cloud Infrastructure (OCI) Container Engine for Kubernetes (OKE) é um serviço totalmente gerenciado, escalável e altamente disponível que você pode usar para implantar seus aplicativos de contêineres na nuvem. Você especifica os recursos de computação que seus aplicativos exigem, e o OKE os provisiona no OCI em uma tenancy existente. O OKE usa o Kubernetes para automatizar a implantação, o dimensionamento e o gerenciamento de aplicativos em contêineres entre clusters de hosts.

Pulumi é uma plataforma moderna de infraestrutura como código que permite usar linguagens de programação e ferramentas familiares para criar, implantar e gerenciar a infraestrutura de nuvem. O provedor do Oracle Cloud Infrastructure (OCI) para Pulumi pode ser usado para provisionar qualquer um dos recursos disponíveis na OCI. O provedor do OCI deve ser configurado com credenciais para implantar e atualizar recursos no OCI.

Este tutorial fornece uma visão geral sobre como gerenciar a infraestrutura como código usando o provedor OCI para Pulumi. Você aprenderá a provisionar um cluster do OKE usando Python como linguagem de desenvolvimento.

Objetivo

Pré-requisitos

Tarefa 1: Criar uma Pilha Pulumi

Todo programa Pulumi é implantado em uma pilha. Uma pilha é uma instância isolada e configurável de forma independente de um programa Pulumi. As pilhas são comumente usadas para indicar diferentes fases de desenvolvimento (como desenvolvimento, preparação e produção) ou ramificações de recursos (como recurso-x-dev).

Criar um diretório home

Crie um diretório home para sua pilha onde armazenaremos um arquivo de estado e seu código-fonte da Pilha.

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

Criar um Repositório de Estado

Pulumi armazena o estado de sua Pilha no Serviço Pulumi ou em um arquivo de estado local para rastrear mudanças em sua infraestrutura. Neste tutorial, o armazenaremos em um arquivo de estado local.

Opção 1. Criar um diretório de arquivos de estado local

Esta opção criará um diretório local para armazenar estados. Para este tutorial, a Opção 1 será configurada.

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

Opção 2. Estado da loja no serviço gratuito Pulumi

Pulumi oferece um serviço para armazenar o estado de Pilha. Há várias camadas de livre para organizacional.

$> pulumi login

Observação: Para este tutorial, só vamos salvar o arquivo de estado localmente, conforme descrito na Opção 1. A opção 2 destina-se apenas a informações adicionais.

Criar um novo Python Stack

  1. Confirme qual serviço e usuário você está usando executando o comando whoami.

    $> pulumi whoami -v
    
    User: <user>
    Organizations:
    Backend URL: file://oci-stack-statefile
    
  2. Ao criar uma Pilha, Pulumi precisa entender que tipo de modelo usar para o seu projeto.

    Observação:

    • Como vamos codificar em Python, você deve selecionar um modelo Python especificando o nome do modelo "python" após as palavras-chave "pulumi new".
    • A Pulumi CLI solicitará um nome de seu projeto (padrão para o nome da pasta pai) e um ambiente específico (padrão para dev) para ajudá-lo a categorizar e classificar seus Pilhas.
    $>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'
    
    

    Observação: Ao armazenar um arquivo de estado localmente no mesmo caminho da sua Pilha, a opção -force é obrigatória, pois o diretório não está vazio (ele contém a pasta pulumi-statefile).

  3. Agora você executará a implantação inicial. Mantenha a frase-senha informada na etapa anterior útil.

       $> 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. Confirme se o ambiente foi criado usando os comandos a seguir.

    Observação: logo após o modelo ser criado e armazenado localmente, o Pulumi também criará um ambiente (venv) virtual Python com pacotes de sites usados pelo seu programa Python. Os ambientes virtuais não estão no escopo deste tutorial.

    -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 : O ponto de entrada para o seu aplicativo Python e é isso que Pulumi irá procurar.

    • Pulumi.yaml : Descritor do grupo.

    • Pulumi.dev.yaml : Configuração do ambiente de pilha.

    • requirements.txt: Arquivo padrão definido para listar os pacotes necessários de pip python.

    • venv : Ambiente virtual Python.

Tarefa 2: Configurar o ambiente virtual Python

Pulumi registrou o provedor OCI e está disponível por meio do pip. pip é um gerenciador de pacotes Python para instalar bibliotecas existentes. Vamos instalá-lo, mas apenas no ambiente virtual.

  1. Ative seu ambiente virtual Python usando o comando a seguir.

    $>  source venv/bin/activate
    
  2. Instale o pacote pulumi_oci usando o pip.

    (venv) j2joi@cloudshell:pulumi-oke-py (us-ashburn-1)$  pip install pulumi_oci
    
  3. Configure o Provedor do OCI para Pulumi.

    Observação: Pulumi armazena detalhes da configuração dentro do seu próprio serviço de configuração. Configure o provedor OCI para Pulumi a ser autenticado na sua tenancy. Colete o perfil do usuário, a chave da API, o ocid do usuário, o ocid da tenancy, região e armazene-o como segredos dentro da configuração de ambiente pulumi. Observe que você os passará como segredos, portanto, eles serão criptografados usando a frase-senha fornecida ao criar o 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"
    

    Dica:

    • Exporte PULUMI_CONFIG_PASSPHRASE com seu valor de frase-senha. Ele economizará tempo em vez de fornecê-lo toda vez que um segredo for adicionado.
    • Os valores de configuração do OCI podem ser lidos diretamente das variáveis de ambiente na forma de TF_VAR_${var_name}.
  4. Confirme se seus segredos estão armazenados no armazenamento de configuração.

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

    Observação: Pulumi usa dois tipos principais de var, entrada [T] e Saída[T] do tipo T. A Entrada[T] é um wrapper para valores brutos de tipos de dados Python básicos (String, booliano, Dito, Sequência) e a Saída mantém o valor futuro quando um recurso é criado.

    Tenha isso em mente se você estiver tentando manipular o valor de uma Saída, passando-o para qualquer biblioteca padrão Python, ou seja, tentando dividir um nome de Saída [String] do recurso, como name.split(), pois ele terminará com erro porque a variável de nome do tipo Saída não suporta divisão.

  5. Crie o primeiro cluster do OKE. Antes de começar a codificar, o trecho de código a seguir requer a criação de uma Rede Virtual na Nuvem existente. As sub-redes do OKE devem ter 3 sub-redes necessárias para Ponto Final do Kubernetes, nós de Trabalho e Serviço do Balanceador de Carga. Para obter mais informações sobre os requisitos de sub-rede para o OKE, como política, roteamento, consulte a documentação do OCI.

    Vamos revisar a definição de variável Python do Cluster do 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. Depois que sua VCN do OCI estiver pronta e você tiver os detalhes de VCN, Sub-redes e OCID do compartimento, prossiga para editar o arquivo __main__.yaml com o trecho de código a seguir. Atualize valores com OCIDs correspondentes.

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

    Dica: Você pode solicitar ocids de recurso do armazenamento de configuração Pulumi para reutilizar seu código para outros ambientes em vez de atribuir valores ocid diretamente em seu código Python.

    Observação: O recuo é essencial para o Python. Certifique-se de que seu código siga o recuo para Python.

  7. Revise as mudanças de infraestrutura: Pulumi tem a opção de visualizar quais recursos a pilha atual vai criar/modificar. Execute a opção "pulumi preview" para validar sua pilha de python atual.

    (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. Aplicar alterações à infraestrutura: Se nenhuma mensagem de erro for exibida, você poderá criar um cluster do OKE. Execute "pulumi up" para acionar a pilha para aplicar as alterações.

    (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. Adicione um recurso do Pool de Nós do OKE: Pulumi Stack criou seu primeiro cluster do OKE "oke_cluster". Agora, vamos adicionar nós de trabalho designados a uma variável Pool de Nós no mesmo arquivo main.py. As alterações serão adicionadas incrementalmente ao seu conjunto de recursos no OCI porque a Pulumi rastreia os recursos criados e comparará quaisquer diferenças entre o recurso dentro do provedor de nuvem e o estado armazenado no backend selecionado para validar se as atualizações são necessárias para os recursos novos ou existentes.

    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. Atualize sua infraestrutura novamente executando o comando "pulumi up".

    $> pulumi up
    

Informações Adicionais

O Pulumi Marketplace já tem alguns outros provedores existentes que você pode usar, como Kubernetes, Helm etc. Uma vantagem da criação de recursos no Oracle Cloud, como o Kubernetes, é que ele é compatível com a maioria dos padrões do Kubernetes e a integração é simples. O exemplo a seguir mostra como criar seu próprio provedor de Kubernetes usando o provedor Pulumi e implantar aplicativos em seu código 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)

Tarefa 3: Remover Recursos

Você concluiu sua primeira Pilha Python com o provedor OCI para Pulumi. Para excluir todos os recursos, execute o comando de destruição pulumi.

$> pulumi destroy

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

Avaliações

Mais Recursos de Aprendizagem

Explore outros laboratórios em docs.oracle.com/learn ou acesse mais conteúdo de aprendizado gratuito no canal YouTube do Oracle Learning. Além disso, visite education.oracle.com/learning-explorer para se tornar um Oracle Learning Explorer.

Para obter a documentação do produto, visite o Oracle Help Center.