GKE に Elastic Stack を設定する

このチュートリアルでは、Elastic Cloud on Kubernetes(ECK)オペレーターを使用して GKE で Elastic Stack を実行する方法について説明します。

Elastic Stack は、リアルタイムのデータのロギング、モニタリング、分析に使用される一般的なオープンソース ソリューションです。GKE で Elastic Stack を使用すると、GKE Autopilot と強力な Elastic Stack 機能により、優れたスケーラビリティと信頼性を利用できます。

このチュートリアルは、Kubernetes 管理者またはサイト信頼性エンジニアを対象としています。

環境を準備する

このチュートリアルでは、Cloud Shell を使用して Google Cloudでホストされているリソースを管理します。Cloud Shell には、kubectlHelmgcloud CLI など、このチュートリアルに必要なソフトウェアがプリインストールされています。

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

  1. Google Cloud コンソールCloud Shell 有効化アイコンCloud Shell をアクティブにする)をクリックして、 Google Cloud コンソールから Cloud Shell セッションを起動します。これにより、 Google Cloud コンソールの下部ペインでセッションが起動します。

  2. Helm チャート リポジトリを追加して更新します。

    helm repo add elastic https://helm.elastic.co
    helm repo update
    
  3. GitHub リポジトリのクローンを作成します。

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git
    
  4. 作業ディレクトリを変更します。

    cd kubernetes-engine-samples/observability/elastic-stack-tutorial
    

GKE クラスタを作成する

コントロール プレーンの指標の収集を有効にして GKE クラスタを作成します。

gcloud container clusters create-auto elk-stack \
    --location="us-central1" \
    --monitoring="SYSTEM,WORKLOAD,API_SERVER,SCHEDULER,CONTROLLER_MANAGER"

ECK オペレーターをデプロイする

Elastic Cloud on Kubernetes(ECK)は、Kubernetes クラスタに Elastic Stack をデプロイして管理するためのプラットフォームです。

ECK は、Elastic Stack クラスタのデプロイと管理を自動化し、Kubernetes での Elastic Stack の設定とメンテナンスのプロセスを簡素化します。提供される Kubernetes カスタム リソースのセットを使用すると、Elasticsearch、Kibana、Application Performance Management Server、その他の Elastic Stack コンポーネントを Kubernetes で作成し、構成できます。これにより、デベロッパーと DevOps チームは、Elastic Stack クラスタを大規模に構成して管理できます。

ECK は、複数の Elasticsearch ノード、自動アプリケーション フェイルオーバー、シームレス アップグレード、SSL 暗号化をサポートしています。ECK には、Elasticsearch のパフォーマンスをモニタリングしてトラブルシューティングできる機能も含まれています。

  1. ECK Helm チャートをインストールします。

    helm upgrade --install "elastic-operator" "elastic/eck-operator" \
        --version="2.8.0" \
        --create-namespace \
        --namespace="elastic-system" \
        --set="resources.limits.cpu=250m" \
        --set="resources.limits.memory=512Mi" \
        --set="resources.limits.ephemeral-storage=1Gi" \
        --set="resources.requests.cpu=250m" \
        --set="resources.requests.memory=512Mi" \
        --set="resources.requests.ephemeral-storage=1Gi"
    
  2. オペレーターの準備ができるまで待ちます。

    watch kubectl get pods -n elastic-system
    

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

    NAME                 READY   STATUS    RESTARTS   AGE
    elastic-operator-0   1/1     Running   0          31s
    

    オペレーター STATUSRunning の場合は、Ctrl+C を押してコマンドラインに戻ります。

ECK を使用して Elastic Stack を構成する

Elastic Stack をフリートモードで動作する Elasticsearch、Kibana、Elastic Agent とともに使用すると、Kibana を使用してデータの管理と可視化を行う強力でスケーラブルなフルマネージド ソリューションを設定できます。

Kibana は、Elasticsearch でデータを検索、分析、可視化できるオープンソースのデータ分析および可視化ツールです。

Elastic Agent は、ログや指標などのさまざまなソースからデータを収集し、自動的に Elasticsearch に送信する軽量のデータシッパーです。

Elastic Fleet は、Elastic エージェントが中央のフリート サーバーに報告し、構成と管理を処理する運用モードです。フリート サーバーにより、Elastic エージェントのデプロイ、構成、スケーリングが簡素化され、大規模で複雑なデプロイの管理が容易になります。

Elasticsearch 自動スケーリングは、オペレーターが定義したポリシーに基づいて追加のリソースが必要になったときに報告を行うセルフ モニタリング機能です。たとえば、利用可能なディスク容量に基づいて特定のティアをスケーリングするようにポリシーで指定できます。Elasticsearch では、ディスク容量をモニタリングし、不足が予測された場合にスケーリングを提案できます。必要なリソースを追加するかどうかはオペレーターの判断によります。Elasticsearch 自動スケーリングの詳細については、Elasticsearch ドキュメントの自動スケーリングをご覧ください。

Elasticsearch クラスタを構成する

Elasticsearch は、大量のデータを迅速かつ効率的に保存および検索するように設計された、分散型の RESTful 検索および分析エンジンを提供します。

Kubernetes に Elastic Stack をデプロイする場合は、Elasticsearch に必要な VM 設定(特に vm.max_map_count setting)を管理する必要があります。vm.max_map_count は、プロセスがファイルに割り当てることができるメモリ領域の数を指定します。Elasticsearch を最適に実行するには、この値を少なくとも 262144 に設定する必要があります。詳細については、ECK ドキュメントの仮想メモリをご覧ください。

  1. 次のマニフェストを確認します。

    # Copyright 2023 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #      https://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    apiVersion: scheduling.k8s.io/v1
    kind: PriorityClass
    metadata:
      name: user-daemonset-priority
    value: 999999999
    preemptionPolicy: PreemptLowerPriority
    globalDefault: false
    description: "User DaemonSet priority"
    ---
    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: max-map-count-setter
      namespace: elastic-system
      labels:
        k8s-app: max-map-count-setter
    spec:
      selector:
        matchLabels:
          name: max-map-count-setter
      template:
        metadata:
          labels:
            name: max-map-count-setter
        spec:
          priorityClassName: user-daemonset-priority
          nodeSelector:
            cloud.google.com/compute-class: "Balanced"
          initContainers:
            - name: max-map-count-setter
              image: docker.io/bash:5.2.15
              resources:
                requests:
                  cpu: 10m
                  memory: 10Mi
                  ephemeral-storage: 10Mi
                limits:
                  cpu: 50m
                  memory: 32Mi
                  ephemeral-storage: 10Mi
              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.15
              command: ["sleep", "infinity"]
              resources:
                requests:
                  cpu: 10m
                  memory: 10Mi
                  ephemeral-storage: 10Mi
                limits:
                  cpu: 10m
                  memory: 10Mi
                  ephemeral-storage: 10Mi
    

    このマニフェストでは、ホストでカーネル設定を直接構成する DaemonSet を記述しています。DaemonSet は、Pod のコピーがクラスタ内の各ノードで実行されるようにする Kubernetes コントローラです。

    上記のマニフェストは、Autopilot で実行するための許可リストに登録されています。このマニフェスト(コンテナ イメージを含む)は変更しないでください。

  2. このマニフェストをクラスタに適用します。

    kubectl apply -f max-map-count-setter-ds.yaml
    
  3. 次のマニフェストを確認します。

    apiVersion: elasticsearch.k8s.elastic.co/v1
    kind: Elasticsearch
    metadata:
      name: elasticsearch
      namespace: elastic-system
    spec:
      version: "8.9.0"
      volumeClaimDeletePolicy: DeleteOnScaledownOnly
      podDisruptionBudget:
        spec:
          minAvailable: 2
          selector:
            matchLabels:
              elasticsearch.k8s.elastic.co/cluster-name: elasticsearch
      nodeSets:
        - name: default
          config:
            node.roles: ["master", "data", "ingest", "ml", "remote_cluster_client"]
          podTemplate:
            metadata:
              labels:
                app.kubernetes.io/name: elasticsearch
                app.kubernetes.io/version: "8.9.0"
                app.kubernetes.io/component: "elasticsearch"
                app.kubernetes.io/part-of: "elk"
            spec:
              nodeSelector:
                cloud.google.com/compute-class: "Balanced"
              initContainers:
                - name: max-map-count-check
                  command:
                    - sh
                    - -c
                    - while true; do mmc=$(cat /proc/sys/vm/max_map_count); if test ${mmc} -eq 262144; then exit 0; fi; sleep 1; done
                  resources:
                    requests:
                      cpu: 10m
                      memory: 16Mi
                      ephemeral-storage: 16Mi
                    limits:
                      cpu: 10m
                      memory: 16Mi
                      ephemeral-storage: 16Mi
              containers:
                - name: elasticsearch
                  resources:
                    requests:
                      cpu: 990m
                      memory: 4080Mi
                      ephemeral-storage: 1008Mi
                    limits:
                      cpu: 1000m
                      memory: 4080Mi
                      ephemeral-storage: 1008Mi
                  env:
                    - name: ES_JAVA_OPTS
                      value: "-Xms2g -Xmx2g"
          count: 3
          volumeClaimTemplates:
            - metadata:
                name: elasticsearch-data # Do not change this name unless you set up a volume mount for the data path.
              spec:
                accessModes:
                  - ReadWriteOnce
                resources:
                  requests:
                    storage: 2Gi
                storageClassName: standard-rwo

    このマニフェストでは、次のフィールドを使用して Elasticsearch クラスタを定義しています。

    • initContainers: 仮想メモリホストのカーネル設定が変更されるまで待機します。
    • podDisruptionBudget: Pod のデフラグ プロセス中にクラスタを破棄しないことを指定します。
    • config.node.roles: Elasticsearch ノードロールの構成。ノードロールの詳細については、Elasticsearch ドキュメントでノードをご覧ください。
  4. このマニフェストをクラスタに適用します。

    kubectl apply -f elasticsearch.yaml
    
  5. Elasticsearch クラスタの準備が整うまで待ちます。

    watch kubectl --namespace elastic-system get elasticsearches.elasticsearch.k8s.elastic.co
    

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

    NAME            HEALTH   NODES   VERSION   PHASE   AGE
    elasticsearch   green    3       8.8.0     Ready   5m3s
    

    Elasticsearch クラスタ HEALTHgreen で、PHASEReady の場合は、Ctrl+C を押してコマンドラインに戻ります。

Kibana を構成する

  1. 次のマニフェストを確認します。

    apiVersion: kibana.k8s.elastic.co/v1
    kind: Kibana
    metadata:
      name: kibana
      namespace: elastic-system
    spec:
      version: "8.9.0"
      count: 1
      elasticsearchRef:
        name: elasticsearch
        namespace: elastic-system
      http:
        tls:
          selfSignedCertificate:
            disabled: true
      config:
        server.publicBaseUrl: https://elk.BASE_DOMAIN
        xpack.reporting.kibanaServer.port: 5601
        xpack.reporting.kibanaServer.protocol: http
        xpack.reporting.kibanaServer.hostname: kibana-kb-http.elastic-system.svc
        xpack.fleet.agents.elasticsearch.hosts: ["https://elasticsearch-es-http.elastic-system.svc:9200"]
        xpack.fleet.agents.fleet_server.hosts: ["https://fleet-server-agent-http.elastic-system.svc:8220"]
        xpack.fleet.packages:
        - name: system
          version: latest
        - name: elastic_agent
          version: latest
        - name: fleet_server
          version: latest
        - name: kubernetes
          version: latest
        xpack.fleet.agentPolicies:
        - name: Fleet Server on ECK policy
          id: eck-fleet-server
          namespace: default
          monitoring_enabled:
          - logs
          - metrics
          unenroll_timeout: 900
          package_policies:
          - name: fleet_server-1
            id: fleet_server-1
            package:
              name: fleet_server
        - name: Elastic Agent on ECK policy
          id: eck-agent
          namespace: default
          monitoring_enabled:
          - logs
          - metrics
          unenroll_timeout: 900
          package_policies:
          - package:
              name: system
            name: system-1
          - package:
              name: kubernetes
            name: kubernetes-1
      podTemplate:
        metadata:
          labels:
            app.kubernetes.io/name: kibana
            app.kubernetes.io/version: "8.9.0"
            app.kubernetes.io/component: "ui"
            app.kubernetes.io/part-of: "elk"
        spec:
          containers:
          - name: kibana
            resources:
              requests:
                memory: 1Gi
                cpu: 500m
                ephemeral-storage: 1Gi
              limits:
                memory: 1Gi
                cpu: 500m
                ephemeral-storage: 1Gi

    このマニフェストでは、フリート サーバーとエージェントのエージェント ポリシーを構成する Kibana カスタム リソースを記述しています。

  2. このマニフェストをクラスタに適用します。

    kubectl apply -f kibana.yaml
    
  3. Pod の準備が整うまで待ちます。

    watch kubectl --namespace elastic-system get kibanas.kibana.k8s.elastic.co
    

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

    NAME     HEALTH   NODES   VERSION   AGE
    kibana   green    1       8.8.0     6m47s
    

    Pod の HEALTHgreen になったら、Ctrl+C を押してコマンドラインに戻ります。

Kibana にアクセスするようにロードバランサを構成する

Kibana にアクセスするには、Kubernetes Ingress オブジェクト、Google マネージド証明書、グローバル IP アドレス、DNS ゾーンを作成します。

  1. グローバル外部 IP アドレスを作成します。

    gcloud compute addresses create "elastic-stack" --global
    
  2. Cloud DNS でマネージド ゾーンとレコードセットを作成します。

    gcloud dns managed-zones create "elk" \
        --description="DNS Zone for Airflow" \
        --dns-name="elk.BASE_DOMAIN" \
        --visibility="public"
    
    gcloud dns record-sets create "elk.BASE_DOMAIN" \
        --rrdatas="$(gcloud compute addresses describe "elastic-stack" --global --format="value(address)")" \
        --ttl="300" \
        --type="A" \
        --zone="elk"
    
  3. ネームサーバーのリストを含む NS レコードセットを作成して、DNS ゾーンをベースドメインのサブドメインとして委任します。ネームサーバーのリストを取得するには、次のコマンドを使用します。

    gcloud dns record-sets describe elk.BASE_DOMAIN \
        --type="NS" \
        --zone="elk" \
        --format="value(DATA)"
    
  4. 次のマニフェストを確認します。

    # Copyright 2023 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #      https://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    apiVersion: networking.gke.io/v1beta1
    kind: FrontendConfig
    metadata:
      name: elastic-stack
      namespace: elastic-system
    spec:
      redirectToHttps:
        enabled: true
        responseCodeName: MOVED_PERMANENTLY_DEFAULT
    ---
    apiVersion: networking.gke.io/v1
    kind: ManagedCertificate
    metadata:
      name: elastic-stack
      namespace: elastic-system
    spec:
      domains:
        - elk.BASE_DOMAIN
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: kibana
      namespace: elastic-system
      annotations:
        networking.gke.io/managed-certificates: elastic-stack
        networking.gke.io/v1beta1.FrontendConfig: elastic-stack
        kubernetes.io/ingress.global-static-ip-name: elastic-stack
        kubernetes.io/ingress.class: gce
    spec:
      defaultBackend:
        service:
          name: kibana-kb-http
          port:
            number: 5601
    

    このマニフェストでは、TLS 接続を確立するための SSL 証明書をプロビジョニングする ManagedCertificate を記述しています。

  5. マニフェストをクラスタに適用します。

    kubectl apply -f ingress.yaml
    

Elastic エージェントを構成する

  1. 次のマニフェストを確認します。

    apiVersion: agent.k8s.elastic.co/v1alpha1
    kind: Agent
    metadata:
      name: fleet-server
      namespace: elastic-system
    spec:
      version: 8.9.0
      kibanaRef:
        name: kibana
        namespace: elastic-system
      elasticsearchRefs:
        - name: elasticsearch
          namespace: elastic-system
      mode: fleet
      fleetServerEnabled: true
      policyID: eck-fleet-server
      deployment:
        replicas: 1
        podTemplate:
          metadata:
            labels:
              app.kubernetes.io/name: fleet-server
              app.kubernetes.io/version: "8.9.0"
              app.kubernetes.io/component: "agent"
              app.kubernetes.io/part-of: "elk"
          spec:
            containers:
              - name: agent
                resources:
                  requests:
                    memory: 512Mi
                    cpu: 250m
                    ephemeral-storage: 10Gi
                  limits:
                    memory: 512Mi
                    cpu: 250m
                    ephemeral-storage: 10Gi
            volumes:
              - name: "agent-data"
                ephemeral:
                  volumeClaimTemplate:
                    spec:
                      accessModes: ["ReadWriteOnce"]
                      storageClassName: "standard-rwo"
                      resources:
                        requests:
                          storage: 10Gi
            serviceAccountName: fleet-server
            automountServiceAccountToken: true
            securityContext:
              runAsUser: 0

    このマニフェストでは、ECK を使用してフリート サーバーを構成する Elastic Agent を記述しています。

  2. このマニフェストをクラスタに適用します。

    kubectl apply -f fleet-server-and-agents.yaml
    
  3. Pod の準備が整うまで待ちます。

    watch kubectl --namespace elastic-system get agents.agent.k8s.elastic.co
    

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

    NAME            HEALTH   AVAILABLE   EXPECTED   VERSION   AGE
    elastic-agent   green    5           5          8.8.0     14m
    fleet-server    green    1           1          8.8.0     16m
    

    Pod の HEALTHgreen になったら、Ctrl+C を押してコマンドラインに戻ります。

ロギングとモニタリングを構成する

Elastic Stack は、kube-state-metrics エクスポーターを使用してクラスタレベルの指標を収集できます。

  1. Kube 状態指標をインストールします。

    helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
    helm repo update
    helm install kube-state-metrics prometheus-community/kube-state-metrics --namespace elastic-system
    
  2. デフォルトの Kibana elastic ユーザー認証情報を取得します。

    kubectl get secret elasticsearch-es-elastic-user -o yaml -n elastic-system -o jsonpath='{.data.elastic}' | base64 -d
    
  3. ブラウザで https://elk.BASE_DOMAIN を開き、認証情報を使用して Kibana にログインします。

  4. メニューから [Analytics]、[Dashboards] の順に選択します。

  5. 検索テキスト フィールドに「Kubernetes overview」と入力し、[Overview dashboard] を選択して基本指標を表示します。

    GKE では、Kibana がクラスタ指標の取得に使用するコントロール プレーン エンドポイントの一部に対するアクセスを制限しているため、一部のダッシュボード パネルにデータやエラー メッセージが表示されない場合があります。