GKE に Elasticsearch ベクトル データベースをデプロイする


このチュートリアルでは、Google Kubernetes Engine(GKE)に Elasticsearch ベクトル データベース クラスタをデプロイする方法について説明します。

ベクトル データベースは、高次元ベクトルの大規模なコレクションを管理および検索するために特別に設計されたデータストアです。これらのベクトルは、テキスト、画像、音声、動画などのデータのほか、数値でエンコードできるデータを表します。完全一致に依存するリレーショナル データベースとは異なり、ベクトル データベースは大規模なデータセット内の類似アイテムの検索やパターンの識別に特化しています。

Elasticsearch は、検索機能と分析機能を組み合わせたベクトル データベースです。クラスタを管理するためのオープンな REST API が用意されており、構造化クエリ、全文クエリ、複雑なクエリをサポートしています。Elasticsearch では、予測入力の候補を使用して、フレーズ検索、類似検索、接頭辞検索を行うことができます。

このチュートリアルは、GKE に Elasticsearch データベース クラスタをデプロイすることに関心があるクラウド プラットフォーム管理者とアーキテクトML エンジニア、MLOps(DevOps)の専門家を対象としています。

利点

Elasticsearch には次のようなメリットがあります。

  • さまざまなプログラミング言語に対応している幅広いライブラリと、他のサービスと統合できるオープン API。
  • 水平スケーリングと、シャーディング / レプリケーション サポートにより、スケーリングと高可用性を簡素化。
  • 最適なリソース使用率を実現するマルチノード クラスタのバランス調整。
  • コンテナと Kubernetes のサポートにより、最新のクラウドネイティブ環境にシームレスに統合。

目標

このチュートリアルでは、以下の方法について学習します。

  • Elasticsearch 向けに GKE インフラストラクチャを計画して、デプロイする。
  • GKE クラスタに Elasticsearch をデプロイして構成する。
  • StatefulHA オペレーターをデプロイして、Elasticsearch の高可用性を確保する。
  • デモ データセットをアップロードして検索クエリを実行する。
  • 指標を収集してダッシュボードで可視化する。

デプロイ アーキテクチャ

このチュートリアルでは、複数のアベイラビリティ ゾーンに複数の Kubernetes ノードを分散させ、Elasticsearch 用に高可用性のリージョン GKE クラスタをデプロイします。この設定により、フォールト トレランス、スケーラビリティ、地理的冗長性を確保できます。稼働時間と可用性の SLA を提供しながら、ローリング アップデートとメンテナンスが可能になります。詳細については、リージョン クラスタをご覧ください。

ノードがアクセス不能になっても、そのノード上の Pod はすぐには再スケジュールされません。StatefulSet を使用する Pod では、アプリケーション Pod が削除されて新しいノードに再スケジュールされるまでに 8 分以上かかることがあります。

この問題に対処するために、StatefulHA オペレーターは次の処理を行います。

  • .forceDeleteStrategy: AfterNodeUnreachable 設定を使用して、再スケジュールの遅延の解決、フェイルオーバー設定の処理、復旧時間の短縮を行います。
  • StatefulSet アプリケーションが RePD を使用していることを確認します。
  • Elasticsearch と同じ Namespace にデプロイされるカスタム HighAvailabilityApplication リソースにより GKE を拡張します。これにより、StatefulHA オペレーターはフェイルオーバー イベントをモニタリングし、対応できます。

次の図は、GKE クラスタ内の複数のノードとゾーンで実行されている Elasticsearch クラスタを示しています。

Elasticsearch のデプロイ アーキテクチャ

費用

このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。 新しい Google Cloud ユーザーは無料トライアルをご利用いただける場合があります。

このドキュメントに記載されているタスクの完了後、作成したリソースを削除すると、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。

Elasticsearch は、Server Side Public License(SSPL)に基づいて無料で利用できます。

始める前に

このチュートリアルでは、Cloud Shell を使用してコマンドを実行します。Google Cloud Shell は、Google Cloud でホストされているリソースを管理するためのシェル環境です。これには、Google Cloud CLIkubectlHelmTerraform コマンドライン ツールがプリインストールされています。Cloud Shell を使用しない場合は、Google Cloud CLI をインストールする必要があります。

  1. Install the Google Cloud CLI.
  2. To initialize the gcloud CLI, run the following command:

    gcloud init
  3. Google Cloud プロジェクトを作成または選択します

    • Google Cloud プロジェクトを作成します。

      gcloud projects create PROJECT_ID

      PROJECT_ID は、作成する Google Cloud プロジェクトの名前に置き換えます。

    • 作成した Google Cloud プロジェクトを選択します。

      gcloud config set project PROJECT_ID

      PROJECT_ID は、実際の Google Cloud プロジェクト名に置き換えます。

  4. Google Cloud プロジェクトで課金が有効になっていることを確認します

  5. Cloud Resource Manager, Compute Engine, GKE, IAM Service Account Credentials, and Backup for GKE API を有効にします。

    gcloud services enable cloudresourcemanager.googleapis.comcompute.googleapis.comcontainer.googleapis.comiamcredentials.googleapis.comgkebackup.googleapis.com
  6. Grant roles to your user account. Run the following command once for each of the following IAM roles: role/storage.objectViewer, roles/container.admin, roles/iam.serviceAccountAdmin, roles/compute.admin, roles/gkebackup.admin, roles/monitoring.viewer

    gcloud projects add-iam-policy-binding PROJECT_ID --member="USER_IDENTIFIER" --role=ROLE
    • Replace PROJECT_ID with your project ID.
    • Replace USER_IDENTIFIER with the identifier for your user account. For example, user:[email protected].

    • Replace ROLE with each individual role.

環境を設定する

Cloud Shell を使用して環境を設定するには、次の操作を行います。

  1. プロジェクト、リージョン、Kubernetes クラスタ リソースの接頭辞に環境変数を設定します。

    export PROJECT_ID=PROJECT_ID
    export KUBERNETES_CLUSTER_PREFIX=elasticsearch
    export REGION=us-central1
    
    • PROJECT_ID は、実際の Google Cloud プロジェクト ID に置き換えます。

    このチュートリアルでは、us-central1 リージョンを使用して Deployment リソースを作成します。

  2. Helm のバージョンを確認します。

    helm version
    

    3.13 より古い場合は、バージョンを更新します。

    curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
    
  3. GitHub からサンプルコード リポジトリのクローンを作成します。

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    
  4. elasticsearch ディレクトリに移動して、Deployment リソースの作成を開始します。

    cd kubernetes-engine-samples/databases/elasticsearch
    

クラスタ インフラストラクチャを作成する

このセクションでは、Terraform スクリプトを実行して、限定公開の高可用性リージョン GKE クラスタを作成し、Elasticsearch データベースをデプロイします。

Elasticsearch のデプロイには、Standard クラスタまたは Autopilot クラスタを使用できます。それぞれに利点があり、料金モデルも異なります。

Autopilot

次の図は、プロジェクトにデプロイされた Autopilot GKE クラスタを示しています。

GKE Autopilot クラスタ

クラスタ インフラストラクチャをデプロイするには、Cloud Shell で次のコマンドを実行します。

export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token)
terraform -chdir=terraform/gke-autopilot init
terraform -chdir=terraform/gke-autopilot apply \
-var project_id=${PROJECT_ID} \
-var region=${REGION} \
-var cluster_prefix=${KUBERNETES_CLUSTER_PREFIX}

GKE は、実行時に次の変数を置き換えます。

  • GOOGLE_OAUTH_ACCESS_TOKEN は、gcloud auth print-access-token コマンドを使用して、さまざまな Google Cloud APIs とのやり取りを認証するアクセス トークンを取得します。
  • PROJECT_IDREGIONKUBERNETES_CLUSTER_PREFIX は、環境を設定するセクションで定義した環境変数で、作成する Autopilot クラスタの新しい関連変数に割り当てられます。

プロンプトが表示されたら、「yes」と入力します。

出力は次のようになります。

...
Apply complete! Resources: 9 added, 0 changed, 0 destroyed.

Outputs:

kubectl_connection_command = "gcloud container clusters get-credentials elasticsearch-cluster --region us-central1"

Terraform が次のリソースを作成します。

  • Kubernetes ノード用のカスタム VPC ネットワークとプライベート サブネット
  • ネットワーク アドレス変換(NAT)を介してインターネットにアクセスするための Cloud Router。
  • us-central1 リージョンの限定公開 GKE クラスタ。
  • クラスタのロギングとモニタリングの権限を持つ ServiceAccount
  • クラスタのモニタリングおよびアラート用の Google Cloud Managed Service for Prometheus の構成。

Standard

次の図は、3 つの異なるゾーンにデプロイされた限定公開のリージョン GKE Standard クラスタを示しています。

GKE Standard クラスタ

クラスタ インフラストラクチャをデプロイするには、Cloud Shell で次のコマンドを実行します。

export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token)
terraform -chdir=terraform/gke-standard init
terraform -chdir=terraform/gke-standard apply \
-var project_id=${PROJECT_ID} \
-var region=${REGION} \
-var cluster_prefix=${KUBERNETES_CLUSTER_PREFIX}

GKE は、実行時に次の変数を置き換えます。

  • GOOGLE_OAUTH_ACCESS_TOKEN は、gcloud auth print-access-token コマンドを使用して、さまざまな Google Cloud APIs とのやり取りを認証するアクセス トークンを取得します。
  • PROJECT_IDREGIONKUBERNETES_CLUSTER_PREFIX は、環境を設定するセクションで定義した環境変数で、作成する Standard クラスタの新しい関連変数に割り当てられます。

プロンプトが表示されたら、「yes」と入力します。これらのコマンドが完了し、クラスタが「準備完了」ステータスになるまでに数分かかることがあります。

出力は次のようになります。

...
Apply complete! Resources: 10 added, 0 changed, 0 destroyed.

Outputs:

kubectl_connection_command = "gcloud container clusters get-credentials elasticsearch-cluster --region us-central1"

Terraform が次のリソースを作成します。

  • Kubernetes ノード用のカスタム VPC ネットワークとプライベート サブネット
  • ネットワーク アドレス変換(NAT)を介してインターネットにアクセスするための Cloud Router。
  • 自動スケーリングを有効にした us-central1 リージョンの限定公開 GKE クラスタ(ゾーンあたり 1~2 ノード)。
  • クラスタのロギングとモニタリングの権限を持つ ServiceAccount
  • クラスタのモニタリングおよびアラート用の Google Cloud Managed Service for Prometheus の構成。

クラスタに接続する

認証情報を取得し、新しい GKE クラスタと通信できるように kubectl を構成します。

gcloud container clusters get-credentials \
    ${KUBERNETES_CLUSTER_PREFIX}-cluster --region ${REGION}

Elasticsearch データベースと StatefulHA オペレーターをデプロイする

このセクションでは、ECK Operator Helm チャートを使用して、Elasticsearch データベース(クラスタモード)と StatefulHA オペレーターを GKE クラスタにデプロイします。

Deployment により、次の構成の GKE クラスタが作成されます。

  • Elasticsearch ノードの 3 つのレプリカ。
  • DaemonSet。Elasticsearch のパフォーマンスを最適化するために仮想メモリ設定を変更します。
  • NodeAffinity と PodAntiAffinity の構成。Kubernetes ノード間で適切な分散を行い、ノードプールの使用が最適化され、複数のゾーンで可用性が最大化されます。
  • フェイルオーバー プロセスを管理し、高可用性を確保する Stateful HA オペレーター。
  • 認証のために、データベースは認証情報、パスワード、証明書を含む Kubernetes Secret を作成します。

Helm チャートを使用して Elasticsearch データベースをデプロイする手順は次のとおりです。

  1. StatefulHA アドオンを有効にします。

    Autopilot

    GKE は、クラスタの作成時に StatefulHA アドオンを自動的に有効にします。

    Standard

    次のコマンドを実行します。

    gcloud container clusters update ${KUBERNETES_CLUSTER_PREFIX}-cluster \
        --project=${PROJECT_ID} \
        --region=${REGION} \
        --update-addons=StatefulHA=ENABLED
    

    このコマンドが完了し、クラスタが準備完了ステータスになるまでに 15 分かかることがあります。

  2. Elastic Cloud on Kubernetes(ECK)カスタム リソース定義(CRD)を作成します。

    kubectl apply -f https://download.elastic.co/downloads/eck/2.11.1/crds.yaml
    
  3. ECK オペレーターをデプロイします。

    kubectl apply -f https://download.elastic.co/downloads/eck/2.11.1/operator.yaml
    
  4. データベースに Namespace elastic を作成します。

    kubectl create ns elastic
    
  5. Elasticsearch のフェイルオーバー ルールを定義する HighAvailabilityApplication(HAA)リソースをインストールします。

    kubectl apply -n elastic -f manifests/01-regional-pd/ha-app.yaml
    

    ha-app.yaml マニフェストには、HighAvailabilityApplication リソースが記述されています。

    kind: HighAvailabilityApplication
    apiVersion: ha.gke.io/v1
    metadata:
      name: elasticsearch-ha-es-main
      namespace: elastic
    spec:
      resourceSelection:
        resourceKind: StatefulSet
      policy:
        storageSettings:
          requireRegionalStorage: false
        failoverSettings:
          forceDeleteStrategy: AfterNodeUnreachable
          afterNodeUnreachable:
            afterNodeUnreachableSeconds: 20 # 60 seconds total
  6. マニフェストを適用して、リージョン SSD 永続ディスク StorageClass を作成します。

    kubectl apply -n elastic -f manifests/01-regional-pd/regional-pd.yaml
    

    regional-pd.yaml マニフェストには、永続 SSD ディスク StorageClass が記述されています。

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    allowVolumeExpansion: true
    metadata:
      name: ha-regional
    parameters:
      replication-type: regional-pd
      type: pd-ssd
      availability-class: regional-hard-failover
    provisioner: pd.csi.storage.gke.io
    reclaimPolicy: Retain
    volumeBindingMode: WaitForFirstConsumer
  7. DaemonSet リソースをデプロイして、各ノードで仮想メモリを設定します。

    kubectl apply -n elastic -f manifests/02-elasticsearch/mmap-count.yaml
    

    mmap-count.yaml マニフェストには、DaemonSet が記述されています。

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: max-map-count-setter
      labels:
        k8s-app: max-map-count-setter
    spec:
      selector:
        matchLabels:
          name: max-map-count-setter
      template:
        metadata:
          labels:
            name: max-map-count-setter
        spec:
          initContainers:
            - name: max-map-count-setter
              image: docker.io/bash:5.2.21
              resources:
                limits:
                  cpu: 100m
                  memory: 32Mi
              securityContext:
                privileged: true
                runAsUser: 0
              command: ['/usr/local/bin/bash', '-e', '-c', 'echo 262144 > /proc/sys/vm/max_map_count']
          containers:
            - name: sleep
              image: docker.io/bash:5.2.21
              command: ['sleep', 'infinity']
  8. マニフェストを適用して Elasticsearch クラスタをデプロイします。

    kubectl apply -n elastic -f manifests/02-elasticsearch/elasticsearch.yaml
    

    elasticsearch.yaml マニフェストには Deployment が記述されています。

    apiVersion: elasticsearch.k8s.elastic.co/v1
    kind: Elasticsearch
    metadata:
      name: elasticsearch-ha
    spec:
      version: 8.11.4
      nodeSets:
      - name: main
        count: 3
        volumeClaimTemplates:
        - metadata:
            name: elasticsearch-data 
          spec:
            accessModes:
            - ReadWriteOnce
            resources:
              requests:
                storage: 10Gi
            storageClassName: ha-regional
        config:
        podTemplate:
          metadata:
            labels:
              app.stateful/component: elasticsearch
          spec:
            initContainers:
            - name: max-map-count-check
              command: ['sh', '-c', "while true; do mmc=$(cat /proc/sys/vm/max_map_count); if [ ${mmc} -eq 262144 ]; then exit 0; fi; sleep 1; done"]
            containers:
            - name: metrics
              image: quay.io/prometheuscommunity/elasticsearch-exporter:v1.7.0
              command:
                - /bin/elasticsearch_exporter
                - --es.ssl-skip-verify
                - --es.uri=https://$(ES_USER):$(ES_PASSWORD)@localhost:9200
              securityContext:
                runAsNonRoot: true
                runAsGroup: 10000
                runAsUser: 10000
              resources:
                requests:
                  memory: "128Mi"
                  cpu: "25m"
                limits:
                  memory: "128Mi"
                  cpu: "100m"
              ports:
              - containerPort: 9114
              env:
              - name: ES_USER
                value: "elastic"
              - name: ES_PASSWORD
                valueFrom:
                  secretKeyRef:
                    name: elasticsearch-ha-es-elastic-user
                    key: elastic
            - name: elasticsearch
              resources:
                limits:
                  memory: 4Gi
                  cpu: 1
            affinity:
              nodeAffinity:
                preferredDuringSchedulingIgnoredDuringExecution:
                  - weight: 1
                    preference:
                      matchExpressions:
                      - key: app.stateful/component
                        operator: In
                        values:
                        - elasticsearch
              podAntiAffinity:
                preferredDuringSchedulingIgnoredDuringExecution:
                - weight: 1
                  podAffinityTerm:
                    labelSelector:
                      matchLabels:
                        app.stateful/component: elasticsearch
                    topologyKey: topology.kubernetes.io/zone

    Elasticsearch クラスタが完全に起動するまで数分待ちます。

  9. デプロイのステータスを確認します。

    kubectl get elasticsearch -n elastic --watch
    

    elasticsearch データベースが正常にデプロイされると、次のように出力されます。

    NAME               HEALTH   NODES   VERSION   PHASE   AGE
    elasticsearch-ha   green    3       8.11.4    Ready   2m30s
    

    HEALTH が「green」と表示されるまで待ちます。必要に応じて、Ctrl+C キーを押してコマンドを終了します。

  10. フェイルオーバー ルールが適用されているかどうかを確認するには、リソースの説明を取得して Status: Message: Application is protected を確認します。

    kubectl describe highavailabilityapplication elasticsearch-ha-es-main -n elastic
    

    出力は次のようになります。

    Status:
      Conditions:
        Last Transition Time:  2024-02-01T13:27:50Z
        Message:               Application is protected
        Observed Generation:   1
        Reason:                ApplicationProtected
        Status:                True
        Type:                  Protected
    Events:                    <none>
    
  11. GKE がワークロードを開始したら、GKE が Elasticsearch ワークロードを作成していることを確認します。

    kubectl get pod,svc,statefulset,pdb,secret,daemonset -n elastic
    

    出力は次のようになります。

    NAME                             READY   STATUS    RESTARTS   AGE
    pod/elasticsearch-ha-es-main-0   2/2     Running   0          7m16s
    pod/elasticsearch-ha-es-main-1   2/2     Running   0          7m16s
    pod/elasticsearch-ha-es-main-2   2/2     Running   0          7m16s
    pod/max-map-count-setter-28wt9   1/1     Running   0          7m27s
    pod/max-map-count-setter-cflsw   1/1     Running   0          7m27s
    pod/max-map-count-setter-gzq9k   1/1     Running   0          7m27s
    
    NAME                                        TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
    service/elasticsearch-ha-es-http            ClusterIP   10.52.8.28   <none>        9200/TCP   7m18s
    service/elasticsearch-ha-es-internal-http   ClusterIP   10.52.3.48   <none>        9200/TCP   7m18s
    service/elasticsearch-ha-es-main            ClusterIP   None         <none>        9200/TCP   7m16s
    service/elasticsearch-ha-es-transport       ClusterIP   None         <none>        9300/TCP   7m18s
    
    NAME                                        READY   AGE
    statefulset.apps/elasticsearch-ha-es-main   3/3     7m16s
    
    NAME                                                     MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
    poddisruptionbudget.policy/elasticsearch-ha-es-default   2               N/A               1                     7m16s
    
    NAME                                                 TYPE     DATA   AGE
    secret/elasticsearch-ha-es-elastic-user              Opaque   1      7m18s
    secret/elasticsearch-ha-es-file-settings             Opaque   1      7m16s
    secret/elasticsearch-ha-es-http-ca-internal          Opaque   2      7m17s
    secret/elasticsearch-ha-es-http-certs-internal       Opaque   3      7m17s
    secret/elasticsearch-ha-es-http-certs-public         Opaque   2      7m17s
    secret/elasticsearch-ha-es-internal-users            Opaque   4      7m18s
    secret/elasticsearch-ha-es-main-es-config            Opaque   1      7m16s
    secret/elasticsearch-ha-es-main-es-transport-certs   Opaque   7      7m16s
    secret/elasticsearch-ha-es-remote-ca                 Opaque   1      7m16s
    secret/elasticsearch-ha-es-transport-ca-internal     Opaque   2      7m16s
    secret/elasticsearch-ha-es-transport-certs-public    Opaque   1      7m16s
    secret/elasticsearch-ha-es-xpack-file-realm          Opaque   4      7m18s
    
    NAME                                  DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
    daemonset.apps/max-map-count-setter   6         6         6       6            6           <none>          13m
    

Elasticsearch クラスタ用に、次の GKE リソースが作成されます。

  • 3 つの Pod レプリカを制御する Elasticsearch StatefulSet
  • 仮想メモリ設定を構成する DaemonSet。
  • Elasticsearch に接続するサービス。
  • スーパーユーザー認証情報とサービス関連の証明書を含む Secret。
  • Elasticsearch アプリケーションをアクティブにモニタリングする、ステートフル HA オペレーター Pod と HighlyAvailableApplication リソース。

デモ データセットをアップロードして Jupyter Notebook で検索クエリを実行する

このセクションでは、ベクトルを Elasticsearch ドキュメントにアップロードし、公式の Elasticsearch Python クライアントを使用してセマンティック検索クエリを実行します。Elasticsearch のドキュメントは、それぞれ対応する値とペアになっているフィールドで構成されます。Elasticsearch を効果的に活用するには、データをドキュメントに構造化し、検索用のインデックスに登録することをおすすめします。

この例では、さまざまなジャンルの書籍のリストを含む CSV ファイルのデータセットを使用します。Elasticsearch は検索エンジンとして機能し、作成した Pod は Elasticsearch データベースをクエリするクライアントとして機能します。

  1. books-dataset ConfigMap と notebook ConfigMap を作成し、Jupyter Pod を実行して Elasticsearch クラスタとやり取りします。

    kubectl create -n elastic configmap books-dataset --from-file=manifests/03-notebook/dataset.csv
    kubectl create -n elastic configmap notebook --from-file=manifests/03-notebook/vector-database.ipynb
    kubectl apply -n elastic -f manifests/03-notebook/jupyter.yaml
    
    • 先ほど作成した elasticsearch-ha-es-elastic-user という名前の Secret が、PW という環境変数としてクライアント Pod にマウントされます。
    • books-dataset ConfigMap には、Elasticsearch インデックスの書籍データを含む csv ファイルが含まれています。
    • notebook ConfigMap には、books-dataset から Elasticsearch インデックスを作成する Jupyter Notebook が含まれています。

    jupyter.yaml マニフェストには、notebook Deployment とその Service が記述されています。

    ---
    apiVersion: v1
    kind: Service
    metadata:
      labels: &labels
        app: jupyter-notebook
      name: notebook
    spec:
      ports:
      - port: 8888
      selector: *labels
      type: LoadBalancer
      # type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: notebook
      labels: &labels
        app: jupyter-notebook
    spec:
      selector:
        matchLabels: *labels
      template:
        metadata: 
          labels: *labels
        spec:
          containers:
          - name: jupyter
            image: tensorflow/tensorflow:2.15.0-jupyter
            resources:
              requests:
                memory: "4500Mi"
                cpu: "1"
              limits:
                memory: "4500Mi"
                cpu: "1"
            ports:
            - containerPort: 8888
            env:
            - name: PW
              valueFrom:
                secretKeyRef:
                  name: elasticsearch-ha-es-elastic-user
                  key: elastic
            volumeMounts:
            - name: books-dataset
              mountPath: /usr/local/dataset
            - name: notebook
              mountPath: /tf
            - name: elastic-cert
              mountPath: /usr/local/cert
          volumes:
          - name: books-dataset
            configMap:
              name: books-dataset
          - name: notebook
            configMap:
              name: notebook
          - name: elastic-cert
            secret:
              secretName: elasticsearch-ha-es-http-certs-public
  2. GKE が Jupyter Pod を起動するまで待ちます。

    kubectl wait pods -l app=jupyter-notebook --for condition=Ready --timeout=300s -n elastic
    
  3. Jupyter に接続するためのアクセス トークンを含む URL を取得します。

    export EXTERNAL_IP=$(kubectl -n elastic get svc notebook --output jsonpath='{.status.loadBalancer.ingress[0].ip}')
    kubectl logs deploy/notebook -n elastic| grep '^ .*http://127'|sed "s|127.0.0.1|${EXTERNAL_IP}|"
    
  4. この URL を開き、vector-database.ipynb ファイルをクリックします。

  5. [Run] > [Run all cells] をクリックします。Jupyter がコードを実行し、テキスト drama about people and unhappy love の検索クエリを実行します。

    このクエリは、Elasticsearch の books インデックスに対してセマンティック検索を行い、クエリに関連する一致スコアが最も高い検索結果を最大 2 件取得します。

    出力は次のようになります。

    Title: Romeo and Juliet, Author: William Shakespeare, Paul Werstine (Editor),
    Barbara A. Mowat (Editor), Paavo Emil Cajander (Translator), score: 1.8473973
    In Romeo and Juliet, Shakespeare creates a violent world, in which two young people
    fall in love. It is not simply that their families disapprove; the Montagues and
    the Capulets are engaged in a blood feud.In this death-filled setting, the movement
    from love at first sight to the lovers' final union in death seems almost inevitable.
    And yet, this play set in an extraordinary world has become the quintessential
    story of young love. In part because of its exquisite language, it is easy to
    respond as if it were about all young lovers.
    ---------
    Title: A Midsummer Night's Dream, Author: William Shakespeare, Paul Werstine
    (Editor), Barbara A. Mowat (Editor), Catherine Belsey (Contributor), score: 1.8415744
    Shakespeare's intertwined love polygons begin to get complicated from the
    start--Demetrius and Lysander both want Hermia but she only has eyes for Lysander.
    Bad news is, Hermia's father wants Demetrius for a son-in-law. On the outside
    is Helena, whose unreturned love burns hot for Demetrius. Hermia and Lysander
    plan to flee from the city under cover of darkness but are pursued by an enraged
    Demetrius (who is himself pursued by an enraptured Helena). In the forest, unbeknownst
    to the mortals, Oberon and Titania (King and Queen of the faeries) are having a
    spat over a servant boy. The plot twists up when Oberon's head mischief-maker,
    Puck, runs loose with a flower which causes people to fall in love with the first
    thing they see upon waking. Throw in a group of labourers preparing a play for
    the Duke's wedding (one of whom is given a donkey's head and Titania for a lover
    by Puck) and the complications become fantastically funny.
    ---------
    

クラスタの Prometheus 指標を表示する

GKE クラスタは Google Cloud Managed Service for Prometheus で構成されており、Prometheus 形式での指標の収集が可能です。このサービスは、モニタリングとアラート用のフルマネージド ソリューションを提供し、クラスタとそのアプリケーションからの指標の収集、保存、分析を可能にします。

次の図は、Prometheus がクラスタの指標を収集する方法を示しています。

Prometheus 指標の収集

この図の GKE 限定公開クラスタには、次のコンポーネントが含まれています。

  • パス / とポート 9114 で指標を公開する Elasticsearch Pod。これらの指標は、elasticsearch_exporter を含む metrics というサイドカー コンテナによって提供されます。
  • Elasticsearch Pod から取得した指標を処理する Prometheus ベースのコレクタ
  • Cloud Monitoring に指標を送信する PodMonitoring リソース

クラスタ構成では、Prometheus 形式の指標エクスポータを含むサイドカー コンテナを定義します。

apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
  name: elasticsearch-ha
spec:
  ...
  nodeSets:
  - name: main
    ...
    podTemplate:
      spec:
        containers:
        ...
        - name: metrics
          image: quay.io/prometheuscommunity/elasticsearch-exporter:v1.7.0
          command:
          - /bin/elasticsearch_exporter
          - --es.ssl-skip-verify
          - --es.uri=https://$(ES_USER):$(ES_PASSWORD)@localhost:9200
          ...
          env:
          - name: ES_USER
            value: "elastic"
          - name: ES_PASSWORD
            valueFrom:
            secretKeyRef:
              name: elasticsearch-ha-es-elastic-user
              key: elastic

指標をエクスポートして表示する手順は次のとおりです。

  1. labelSelector で指標を収集する PodMonitoring リソースを作成します。

    kubectl apply -n elastic -f manifests/04-prometheus-metrics/pod-monitoring.yaml
    

    pod-monitoring.yaml マニフェストには、PodMonitoring リソースが記述されています。

    apiVersion: monitoring.googleapis.com/v1
    kind: PodMonitoring
    metadata:
      name: elasticsearch
    spec:
      selector:
        matchLabels:
          app.stateful/component: elasticsearch
          elasticsearch.k8s.elastic.co/cluster-name: elasticsearch-ha
      endpoints:
      - port: 9114
        interval: 30s
        path: /metrics

    数分後、組み込みダッシュボード(Elasticsearch Prometheus Overview)が表示されます。

  2. データに関連するグラフをさらに表示するには、dashboard.json で定義された構成を使用して、カスタムの Cloud Monitoring ダッシュボードをインポートします。

    gcloud --project "${PROJECT_ID}" monitoring dashboards create --config-from-file monitoring/dashboard.json
    
  3. コマンドが正常に実行されたら、Cloud Monitoring のダッシュボードに移動します。

    ダッシュボードの概要に移動

  4. ダッシュボードのリストで、ElasticSearch Overview ダッシュボードを開きます。指標の収集と表示には 1~2 分かかる場合があります。

    ダッシュボードには、次の主要な指標のカウントが表示されます。

    • インデックス
    • ドキュメントとシャード
    • 保留中のオペレーション
    • 実行中のノードとその健全性ステータス

クラスタ構成をバックアップする

Backup for GKE 機能を使用すると、デプロイされたワークロードとそのデータを含む GKE クラスタ構成全体の定期的なバックアップ スケジュールを設定できます。

このチュートリアルでは、Secret と Volume を含むすべてのワークロードのバックアップを毎日午前 3 時に実行するように、GKE クラスタのバックアップ プランを構成します。ストレージ管理を効率的に行うため、3 日以上経過したバックアップは自動的に削除されます。

  1. クラスタで Backup for GKE 機能を有効にします。

    gcloud container clusters update ${KUBERNETES_CLUSTER_PREFIX}-cluster \
        --project=${PROJECT_ID} \
        --region=${REGION} \
        --update-addons=BackupRestore=ENABLED
    
  2. クラスタ内のすべての Namespace の日次スケジュールでバックアップ プランを作成します。

    gcloud beta container backup-restore backup-plans create ${KUBERNETES_CLUSTER_PREFIX}-cluster-backup \
        --project=${PROJECT_ID} \
        --location=${REGION} \
        --cluster="projects/${PROJECT_ID}/\locations/${REGION}/\clusters/${KUBERNETES_CLUSTER_PREFIX}-cluster" \
        --all-namespaces \
        --include-secrets \
        --include-volume-data \
        --cron-schedule="0 3 * * *" \
        --backup-retain-days=3
    

    このコマンドは、実行時に関連する環境変数を使用します。

    クラスタ名の形式は、プロジェクトとリージョンに対して相対的です。

    projects/PROJECT_ID/locations/REGION/clusters/CLUSTER_NAME
    

    プロンプトが表示されたら、「y.」と入力します。出力は次のようになります。

    Create request issued for: [elasticsearch-cluster-backup]
    Waiting for operation [projects/PROJECT_ID/locations/us-central1/operations/operation-1706528750815-610142ffdc9ac-71be4a05-f61c99fc] to complete...⠹
    

    このオペレーションが正常に完了するまで数分かかることがあります。実行が完了すると、出力は次のようになります。

    Created backup plan [elasticsearch-cluster-backup].
    
  3. 新しく作成したバックアップ プラン elasticsearch-cluster-backup が Backup for GKE コンソールに表示されます。

    Backup for GKE に移動

保存したバックアップ構成を復元する場合は、バックアップを復元するをご覧ください。

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

プロジェクトを削除する

課金が発生しないようにする最も簡単な方法は、このチュートリアル用に作成したプロジェクトを削除することです。

Delete a Google Cloud project:

gcloud projects delete PROJECT_ID

プロジェクトを削除すると、クリーンアップが完了します。プロジェクトを削除していない場合は、個々のリソースを削除します。

リソースを個別に削除する

  1. 環境変数を設定します。

    export PROJECT_ID=${PROJECT_ID}
    export KUBERNETES_CLUSTER_PREFIX=elasticsearch
    export REGION=us-central1
    
  2. terraform destroy コマンドを実行します。

    export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token)
    terraform  -chdir=terraform/FOLDER destroy \
    -var project_id=${PROJECT_ID} \
    -var region=${REGION} \
    -var cluster_prefix=${KUBERNETES_CLUSTER_PREFIX}
    

    作成した GKE クラスタのタイプに応じて、FOLDERgke-autopilot または gke-standard に置き換えます。

    プロンプトが表示されたら、「yes」と入力します。

  3. アタッチされていないすべてのディスクを検索します。

    export disk_list=$(gcloud compute disks list --filter="-users:* AND labels.name=${KUBERNETES_CLUSTER_PREFIX}-cluster" --format "value[separator=|](name,region)")
    
  4. ディスクを削除します。

    for i in $disk_list; do
     disk_name=$(echo $i| cut -d'|' -f1)
     disk_region=$(echo $i| cut -d'|' -f2|sed 's|.*/||')
     echo "Deleting $disk_name"
     gcloud compute disks delete $disk_name --region $disk_region --quiet
    done
    
  5. GitHub リポジトリを削除します。

    rm -r ~/kubernetes-engine-samples/
    

次のステップ