注意:

使用 OCI 提供 Pulumi 的提供者建置 Container Engine for Kubernetes (OKE) 叢集

簡介

Oracle Cloud Infrastructure (OCI) Container Engine for Kubernetes (OKE) 是一個完全受管理、可擴展且高可用性的服務,可用來將容器化應用系統部署到雲端。您可以指定應用程式所需的運算資源,OKE 在現有租用戶的 OCI 上佈建這些資源。OKE 使用 Kubernetes,在主機叢集間自動部署、調整及管理容器化應用系統。

Pulumi 是一個現代化的基礎架構,作為程式碼平台,可讓您使用熟悉的程式設計語言和工具來建立、部署及管理雲端基礎架構。Pulumi 的 Oracle Cloud Infrastructure (OCI) 提供者可以用來佈建 OCI 中任何可用的資源。OCI 提供者必須設定證明資料,才能在 OCI 中部署及更新資源。

本教學課程介紹使用 OCI 提供 Pulumi 提供者的基礎架構即程式碼方式。學員將學習如何使用 Python 作為開發語言來佈建 OKE 叢集。

目標

必要條件

作業 1:建立 Pulumi 堆疊

每個 Pulumi 程式都會部署到一個堆疊中。堆疊是獨立設定的 Pulumi 程式執行處理。堆疊通常用來表示不同的開發階段 (例如開發、暫存以及生產階段),或特徵分支 (例如 feature-x-dev)。

建立本位目錄

請為您的堆疊建立本位目錄,其中我們會儲存狀態檔案和堆疊原始碼。

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

建立狀態儲存區域

Pulumi 會將堆疊狀態儲存在 Pulumi 服務或本機狀態檔案,以追蹤您基礎架構上的變更。在本教學課程中,我們會將它儲存在本機狀態檔案中。

選項 1。建立本機狀態檔案目錄

此選項將會建立本機目錄以儲存狀態。在此教學課程中,將會設定選項 1。

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

選項 2。將狀態儲存在 Pulumi 免費服務中

Pulumi 提供儲存堆疊狀態的服務。有多層從免費到組織。

$> pulumi login

注意:對於此教學課程,我們只會根據選項 1 中所述在本機儲存狀態檔案。選項 2 僅適用於其他資訊。

建立新的 Python 堆疊

  1. 執行 whoami 命令,確認您要使用哪個服務和使用者。

    $> pulumi whoami -v
    
    User: <user>
    Organizations:
    Backend URL: file://oci-stack-statefile
    
  2. 建立堆疊時,Pulumi 必須瞭解專案要使用的樣板類型。

    注意

    • 當我們要在 Python 中編寫程式碼時,必須在關鍵字 "pulumi new" 之後傳送樣板 "python" 的名稱來選取 Python 樣板。
    • Pulumi CLI 會提示您輸入專案名稱 (預設為父項資料夾的名稱) 和特定環境 (預設為 dev),以協助您分類和分類堆疊。
    $>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'
    
    

    注意:將狀態檔案儲存在本機與堆疊相同的路徑中時,因為目錄不是空的 (包含跳脫狀態檔資料夾),需要 -force 選項。

  3. 您現在將執行初始部署。保留您在上一個步驟過程中所輸入的密碼詞組。

       $> 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. 使用下列命令確認環境建立。

    注意:在樣板正確建立並儲存在本機之後,Pulumi 也會建立 Python 虛擬 (venv) 環境,其中包含您 Python 程式所使用的網站套件。虛擬環境不在此教學課程中。

    -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 :Python 應用程式的進入點,這是 Pulumi 要掃描的項目。

    • Pulumi.yaml :堆疊描述子。

    • Pulumi.dev.yaml :堆疊環境組態。

    • requirements.txt:定義用來列出所需的 pip python 套裝軟體的標準檔案。

    • venv :Python 虛擬環境。

作業 2:設定 Python 虛擬環境

Pulumi 已經註冊 OCI 提供者,而且可透過 pip 取得。pip 是安裝現有程式庫的 Python 套裝程式管理程式。讓我們安裝,但只在虛擬環境中。

  1. 使用下列指令啟用 Python 虛擬環境。

    $>  source venv/bin/activate
    
  2. 使用 pip 安裝 pulumi_oci 套裝軟體。

    (venv) j2joi@cloudshell:pulumi-oke-py (us-ashburn-1)$  pip install pulumi_oci
    
  3. 設定 Pulumi 的 OCI 提供者。

    注意:Pulumi 會將組態詳細資訊儲存在自己的組態服務中。您必須設定 Pulumi 的 OCI 提供者以根據您的租用戶進行認證。收集使用者設定檔、API 金鑰、使用者 ocid、租用戶 ocid、區域,並將其儲存為提取環境組態中的加密密碼。請注意,您將會以加密方式傳送它們,因此將使用您在建立環境時所提供的密碼詞組加密。

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

    秘訣:

    • 以您的密碼詞組值匯出 PULUMI_CONFIG_PASSPHRASE。它會在每次新增密碼時省下時間,而不提供。
    • OCI 組態值可以直接從環境變數讀取,格式為 TF_VAR_${var_name}。
  4. 確認您的加密密碼儲存在組態存放區中。

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

    注意:Pulumi 使用兩種主要變數類型,輸入 [T] 與輸出 [T] 類型為 T。Input[T] 是基本 Python 資料類型 (字串、布林、Dict、序列) 原始值的包裝函式,在建立資源後輸出會保留未來的值。

    如果您嘗試將「輸出」值傳送至任何 Python 標準程式庫 (亦即,嘗試分割資源輸出 [String] 名稱,例如 name.split(),因為類型「輸出」的名稱變數不支援分割,所以請記住這。

  5. 建立第一個 OKE 叢集。您必須建立現有的虛擬雲端網路,才能開始編寫程式碼片段。OKE 的子網路必須是 Kubernetes 端點、工作節點及負載平衡器服務所需的 3 個子網路。如需 OKE 之子網路需求 (例如原則、路由) 的詳細資訊,請參閱 OCI 文件

    讓我們複習 OCI Cluster Python 變數定義:

    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. 您的 OCI VCN 準備好並且您有 VCN、子網路和區間 OCID 詳細資訊之後,請繼續使用下列程式碼片段編輯 __main__.yaml 檔案。以對應的 OCID 更新值。

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

    秘訣:您可以從 Pulumi 組態存放區要求資源 ocid,以重複使用您的程式碼給其他環境,而不直接在 Python 程式碼中指定 ocid 值。

    注意:Python 必須提供縮排。確定您的程式碼遵循 Python 縮排。

  7. 複查基礎架構變更:Pulumi 可以選擇預覽目前堆疊將要建立 / 修改的資源。執行「pulumi 預覽」選項以驗證您目前的 python 堆疊。

    (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. 對您的基礎架構套用變更:若未顯示錯誤訊息,您可以建立 OKE 叢集。執行 "pulumi up" 以觸發堆疊以套用變更。

    (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. 新增 OKE 節點集區資源:Pulumi 堆疊建立了您的第一個 OKE 叢集 "oke_cluster"。現在,允許在相同 main.py 檔案中新增指派給「節點集區」變數的工作節點。變更將會以增量方式新增至您 OCI 中的一組資源,因為 Pulumi 會追蹤建立的資源,並將雲端提供者內資源和所選後端中儲存之狀態之間的任何差異進行比較,以驗證是否需要更新現有資源或新資源。

    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. 執行 "pulumi up" 命令,重新更新您的基礎架構。

    $> pulumi up
    

其他資訊

Pulumi Marketplace 已經有一些您可以使用的其他現有提供者,例如 Kubernetes、Helm 等。在 Oracle Cloud 中建立資源 (例如 Kubernetes) 的優勢,是與多數 Kubernetes 標準相容,而且整合相當簡單。下列範例顯示如何使用 Pulumi 的提供者建立自己的 Kubernetes 提供者,並在您的 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)

作業 3:移除資源

您已完成 Pulumi 提供 OCI 提供者第一項 Python 堆疊。若要刪除所有資源,請執行脈 umi 毀棄命令。

$> pulumi destroy

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

致謝

其他學習資源

探索 docs.oracle.com/learn 上的其他實驗室,或前往 Oracle Learning YouTube 通道存取更多免費學習內容。此外,請造訪 education.oracle.com/learning-explorer 以成為 Oracle Learning Explorer。

如需產品文件,請瀏覽 Oracle Help Center