Microsoft Azureで実行するOCNEクラスタの作成

Microsoft Azureで実行するOracle Cloud Native Environment自己管理クラスタの構成

Cluster APIプロジェクトには、クラスタ管理用にKubernetesスタイルのAPIの標準的なセットが用意されています。Verrazzanoが現在、公式にサポートしているのは、OCIでのOCNEおよびOKEクラスタのプロビジョニングにおけるCluster APIの使用のみです。

ただし、Cluster APIプロジェクトの機能を試験的に使用して、Microsoft AzureにOCNEクラスタを直接デプロイすることも可能です。

Cluster APIまたはAzureでのCluster APIの詳細は、次を参照してください:

Azureリソースの準備

Cluster APIクラスタをデプロイする前に、Azureでいくつかのリソースを設定する必要があります。

  1. Azureコマンドライン・インタフェース(CLI)ツールをインストールします。手順は、Microsoft Azureのドキュメントの「How to install the Azure CLI」を参照してください。
  2. Azureリソース・グループを作成します。Azure CLIで、次のコマンドを実行します:
    $ az group create --name <ResourceGroupName> --location <location>
    
    詳細な手順は、Microsoft Azureのドキュメントの「Manage Azure Resource Groups by using Azure CLI」を参照してください。
  3. サービス・プリンシパルを作成します。リソースの作成に必要な権限があることを確認します。これは、最小限のコントリビュータ・ロールを意味します。次の例では、サービス・プリンシパルを作成し、それをコントリビュータ・ロールに割り当てて、スコープを定義しています。
    $ az ad sp create-for-rbac  --name myServicePrincipalName \
                                --role Contributor \
                                --scopes /subscriptions/mySubscriptionID/resourceGroups/myResourceGroupName
    
    詳細な手順は、Microsoft Azureのドキュメントの「Create an Azure service principal with Azure CLI」を参照してください。

管理クラスタの設定

Cluster APIでは、リソースをデプロイする開始点として初期クラスタが必要です。

  1. kindをインストールします。kindのドキュメントのインストールの手順に従います。

  2. kindを使用してKubernetesクラスタを作成します。『The Cluster API Book』の「Quick Start: Install and/or configure a Kubernetes cluster」の手順に従います。

  3. clusterctl CLIツールをインストールします。clusterctlは、Cluster APIの管理クラスタのライフサイクル操作を管理します。『The Cluster API Book』の「Quick Start: Install clusterctl」の手順に従います。

  4. 「CLI設定」の手順で、Verrazzano CLIツールをインストールします。

  5. devまたはprodインストール・プロファイルを使用して、クラスタにVerrazzanoをインストールします。「CLIを使用したインストール」の手順に従います。certManagerおよびclusterAPIコンポーネントは必須であるため、有効なままにしておく必要があります。

  6. クラスタで、Azureアカウントおよび作成したサービス・プリンシパルから、次のAzureリソースIDの環境変数を設定します:

    • サブスクリプションID
    • テナントID
    • クライアントID
    • クライアント・シークレット

    たとえば:

    # Azure resource  IDs
    $ export AZURE_SUBSCRIPTION_ID="<SubscriptionId>"
    $ export AZURE_TENANT_ID="<Tenant>"
    $ export AZURE_CLIENT_ID="<AppId>"
    $ export AZURE_CLIENT_SECRET="<Password>"
    
    # Base64 encode the Azure Resource IDs
    $ export AZURE_SUBSCRIPTION_ID_B64="$(echo -n "$AZURE_SUBSCRIPTION_ID" | base64 | tr -d '\n')"
    $ export AZURE_TENANT_ID_B64="$(echo -n "$AZURE_TENANT_ID" | base64 | tr -d '\n')"
    $ export AZURE_CLIENT_ID_B64="$(echo -n "$AZURE_CLIENT_ID" | base64 | tr -d '\n')"
    $ export AZURE_CLIENT_SECRET_B64="$(echo -n "$AZURE_CLIENT_SECRET" | base64 | tr -d '\n')"
    
    # Settings needed for AzureClusterIdentity used by the AzureCluster
    $ export AZURE_CLUSTER_IDENTITY_SECRET_NAME="<cluster-identity-secret>"
    $ export CLUSTER_IDENTITY_NAME="<cluster-identity>"
    $ export AZURE_CLUSTER_IDENTITY_SECRET_NAMESPACE="default"
    

  7. Azureで作成されたサービス・プリンシパルIDのパスワードを含むシークレットを作成します。このシークレットは、AzureClusterで使用されるAzureClusterIdentityによって参照されます。

    $ kubectl create secret generic "${AZURE_CLUSTER_IDENTITY_SECRET_NAME}" --from-literal=clientSecret="${AZURE_CLIENT_SECRET}" --namespace "${AZURE_CLUSTER_IDENTITY_SECRET_NAMESPACE}"
    

  8. Cluster API Azureインフラストラクチャ・プロバイダをインストールします。

    $ clusterctl init -n verrazzano-capi -i azure
    

    管理クラスタが正常に初期化されると、clusterctlによって報告されます。

管理対象クラスタの作成

Cluster APIでは、クラスタ・テンプレートを使用して、事前に定義したCluster APIオブジェクトのセットをデプロイし、管理対象クラスタを作成します。

  1. 次の環境変数を設定して、クラスタ・テンプレートで使用できるようにします。ご使用の環境が反映されるように値を更新します。

    # Base64 encoded SSH key for node access
    $ export AZURE_SSH_PUBLIC_KEY_B64="<sshKey>"
      
    # Select VM types.
    $ export AZURE_CONTROL_PLANE_MACHINE_TYPE="Standard_D2s_v3"
    $ export AZURE_NODE_MACHINE_TYPE="Standard_D2s_v3"
     
    # [Optional] Select resource group. The default value is ${CLUSTER_NAME}.
    $ export AZURE_RESOURCE_GROUP="<resourceGroupName>
     
    # Name of the Azure datacenter location. Change this value to your desired location.
    $ export AZURE_LOCATION="<location>"
     
    # Cluster name info
    $ export CLUSTER_NAME="capi-quickstart"
    $ export KUBERNETES_VERSION="<k8sVersion>"
    $ export NAMESPACE="default"
    $ export CONTROL_PLANE_MACHINE_COUNT="1"
    $ export WORKER_MACHINE_COUNT="1"
    

  2. クラスタ・テンプレートをコピーし、ローカルにazure-capi.yamlとして保存します。

    クラスタ・テンプレートはここをクリック
    apiVersion: cluster.x-k8s.io/v1beta1
    kind: Cluster
    metadata:
      name: ${CLUSTER_NAME}
      namespace: default
    spec:
      clusterNetwork:
        pods:
          cidrBlocks:
            - 192.168.0.0/16
      controlPlaneRef:
        apiVersion: controlplane.cluster.x-k8s.io/v1beta1
        kind: OCNEControlPlane
        name: ${CLUSTER_NAME}-control-plane
      infrastructureRef:
        apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
        kind: AzureCluster
        name: ${CLUSTER_NAME}
    ---
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: AzureCluster
    metadata:
      name: ${CLUSTER_NAME}
      namespace: default
    spec:
      identityRef:
        apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
        kind: AzureClusterIdentity
        name: ${CLUSTER_IDENTITY_NAME}
      location: ${AZURE_LOCATION}
      networkSpec:
        subnets:
          - name: control-plane-subnet
            role: control-plane
          - name: node-subnet
            role: node
        vnet:
          name: ${AZURE_VNET_NAME:=${CLUSTER_NAME}-vnet}
      resourceGroup: ${AZURE_RESOURCE_GROUP:=${CLUSTER_NAME}}
      subscriptionID: ${AZURE_SUBSCRIPTION_ID}
    ---
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: AzureMachineTemplate
    metadata:
      name: ${CLUSTER_NAME}-control-plane
      namespace: default
    spec:
      template:
        spec:
          image:
            marketplace:
              publisher: "Oracle"
              offer: "Oracle-Linux"
              sku: "ol88-lvm-gen2"
              version: "8.8.3"
          dataDisks:
            - diskSizeGB: 256
              lun: 0
              nameSuffix: etcddisk
          osDisk:
            diskSizeGB: 128
            osType: Linux
          sshPublicKey: ${AZURE_SSH_PUBLIC_KEY_B64:=""}
          vmSize: ${AZURE_CONTROL_PLANE_MACHINE_TYPE}
    ---
    apiVersion: cluster.x-k8s.io/v1beta1
    kind: MachineDeployment
    metadata:
      name: ${CLUSTER_NAME}-md-0
      namespace: default
    spec:
      clusterName: ${CLUSTER_NAME}
      replicas: ${WORKER_MACHINE_COUNT}
      selector:
        matchLabels: null
      template:
        spec:
          bootstrap:
            configRef:
              apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
              kind: OCNEConfigTemplate
              name: ${CLUSTER_NAME}-md-0
          clusterName: ${CLUSTER_NAME}
          infrastructureRef:
            apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
            kind: AzureMachineTemplate
            name: ${CLUSTER_NAME}-md-0
          version: ${KUBERNETES_VERSION}
    ---
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: AzureMachineTemplate
    metadata:
      name: ${CLUSTER_NAME}-md-0
      namespace: default
    spec:
      template:
        spec:
          image:
            marketplace:
              publisher: "Oracle"
              offer: "Oracle-Linux"
              sku: "ol88-lvm-gen2"
              version: "8.8.3"
          osDisk:
            diskSizeGB: 128
            osType: Linux
          sshPublicKey: ${AZURE_SSH_PUBLIC_KEY_B64:=""}
          vmSize: ${AZURE_NODE_MACHINE_TYPE}
    ---
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: AzureClusterIdentity
    metadata:
      labels:
        clusterctl.cluster.x-k8s.io/move-hierarchy: "true"
      name: ${CLUSTER_IDENTITY_NAME}
      namespace: default
    spec:
      allowedNamespaces: {}
      clientID: ${AZURE_CLIENT_ID}
      clientSecret:
        name: ${AZURE_CLUSTER_IDENTITY_SECRET_NAME}
        namespace: ${AZURE_CLUSTER_IDENTITY_SECRET_NAMESPACE}
      tenantID: ${AZURE_TENANT_ID}
      type: ServicePrincipal
    ---
    apiVersion: controlplane.cluster.x-k8s.io/v1alpha1
    kind: OCNEControlPlane
    metadata:
      name: ${CLUSTER_NAME}-control-plane
      namespace: default
    spec:
      moduleOperator:
        enabled: true
      verrazzanoPlatformOperator:
        enabled: true
      controlPlaneConfig:
        clusterConfiguration:
          apiServer:
            extraArgs:
              cloud-provider: external
            certSANs:
              - localhost
              - 127.0.0.1
          dns:
            imageRepository: ${OCNE_IMAGE_REPOSITORY=container-registry.oracle.com}/${OCNE_IMAGE_PATH=olcne}
            imageTag: ${DNS_TAG=v1.9.3}
          etcd:
            local:
              imageRepository: ${OCNE_IMAGE_REPOSITORY=container-registry.oracle.com}/${OCNE_IMAGE_PATH=olcne}
              imageTag: ${ETCD_TAG=3.5.6}
          controllerManager:
            extraArgs:
              cloud-provider: external
          networking: {}
          scheduler: {}
          imageRepository: ${OCNE_IMAGE_REPOSITORY=container-registry.oracle.com}/${OCNE_IMAGE_PATH=olcne}
        files:
          - contentFrom:
              secret:
                key: control-plane-azure.json
                name: ${CLUSTER_NAME}-control-plane-azure-json
            owner: root:root
            path: /etc/kubernetes/azure.json
            permissions: "0644"
        initConfiguration:
          nodeRegistration:
            criSocket: /var/run/crio/crio.sock
            kubeletExtraArgs:
              cloud-provider: external
            name: '{{ local_hostname }}'
        joinConfiguration:
          discovery: {}
          nodeRegistration:
            criSocket: /var/run/crio/crio.sock
            kubeletExtraArgs:
              cloud-provider: external
            name: '{{ local_hostname }}'
        preOCNECommands:
          - hostnamectl set-hostname "{{ ds.meta_data.hostname }}"
          - echo "::1         ipv6-localhost ipv6-loopback localhost6 localhost6.localdomain6"
            >/etc/hosts
          - echo "127.0.0.1   {{ ds.meta_data.hostname }} {{ local_hostname }} localhost
            localhost.localdomain localhost4 localhost4.localdomain4" >>/etc/hosts
        users:
          - name: opc
            sudo: ALL=(ALL) NOPASSWD:ALL
      machineTemplate:
        infrastructureRef:
          apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
          kind: AzureMachineTemplate
          name: ${CLUSTER_NAME}-control-plane
          namespace: default
      replicas: ${CONTROL_PLANE_MACHINE_COUNT}
      version: ${KUBERNETES_VERSION}
    ---
    apiVersion: bootstrap.cluster.x-k8s.io/v1alpha1
    kind: OCNEConfigTemplate
    metadata:
      name: ${CLUSTER_NAME}-md-0
      namespace: default
    spec:
      template:
        spec:
          clusterConfiguration:
            imageRepository: ${OCNE_IMAGE_REPOSITORY=container-registry.oracle.com}/${OCNE_IMAGE_PATH=olcne}
          joinConfiguration:
            nodeRegistration:
              kubeletExtraArgs:
                cloud-provider: external
              name: '{{ local_hostname }}'
          preOCNECommands:
            - hostnamectl set-hostname "{{ ds.meta_data.hostname }}"
            - echo "::1         ipv6-localhost ipv6-loopback localhost6 localhost6.localdomain6"
              >/etc/hosts
            - echo "127.0.0.1   {{ ds.meta_data.hostname }} {{ local_hostname }} localhost
              localhost.localdomain localhost4 localhost4.localdomain4" >>/etc/hosts
          users:
            - name: opc
              sudo: ALL=(ALL) NOPASSWD:ALL
    
  3. 次のコマンドを実行してテンプレートを生成し、適用します:

    $ clusterctl generate yaml --from azure-capi.yaml | kubectl apply -f -
    

クラスタおよびそのリソースのステータスを表示するには、次を実行します:

$ clusterctl describe cluster $CLUSTER_NAME

kubeconfigファイルを取得するには、次を実行します:

$ clusterctl get kubeconfig ${CLUSTER_NAME} > ${CLUSTER_NAME}.kubeconfig

クラスタ構成の終了

クラスタ・リソースを作成したら、追加のステップを実行して、クラスタの構成を終了する必要があります。

  1. クラウド・コントローラ・マネージャ(CCM)をインストールします。ロード・バランサなどのクラウド・リソースをデプロイする場合は、CCMが必要です。
    $ helm install --kubeconfig=./${CLUSTER_NAME}.kubeconfig --repo https://raw.githubusercontent.com/kubernetes-sigs/cloud-provider-azure/master/helm/repo cloud-provider-azure --generate-name --set infra.clusterName=clusterName --set cloudControllerManager.clusterCIDR="192.168.0.0/16" --set cloudControllerManager.caCertDir=/etc/pki/ca-trust
    
  2. コンテナ・ネットワーク・インタフェース(CNI)をインストールします。次の例では、Calico CNIを使用します。
    $ helm repo add projectcalico https://docs.tigera.io/calico/charts --kubeconfig=./${CLUSTER_NAME}.kubeconfig && \
    $ helm install calico projectcalico/tigera-operator --kubeconfig=./${CLUSTER_NAME}.kubeconfig -f https://raw.githubusercontent.com/kubernetes-sigs/cluster-api-provider-azure/main/templates/addons/calico/values.yaml --namespace tigera-operator --create-namespace
    

管理クラスタと最初の管理対象クラスタが稼働し、アプリケーションをデプロイする準備が整います。必要に応じて、さらに管理対象クラスタを追加できます。

詳細は、Cluster APIおよびCluster API Azureのドキュメントを参照してください:

デプロイメントのトラブルシューティング

Azureリソースのデプロイメントが失敗した場合は、次のログ・ファイルを確認して問題を診断できます:

Azureクラスタ・コントローラ・プロバイダのログ:

$ kubectl logs -n verrazzano-capi -l cluster.x-k8s.io/provider=infrastructure-azure
OCNEコントロール・プレーン・プロバイダのログ:
$ kubectl logs -n verrazzano-capi -l cluster.x-k8s.io/provider=control-plane-ocne

ノート: ポッドがCrashLoopBackOff状態になった場合は、デプロイメントを再起動するか、通常どおり実行される状態になるのを待機します。これは既知の問題で、クラスタのデプロイメントに影響はありません。

クラスタの削除

  1. 管理対象クラスタを削除します。
    $ kubectl delete cluster $CLUSTER_NAME
    
  2. 管理クラスタを削除します。
    $ kind delete cluster
    

手動でのクリーンアップが必要な保留中のリソースが残ってしまう可能性があるため、kubectl delete -f capi-quickstart.yamlを使用して、クラスタ・テンプレート全体を一度に削除しないでください。