コンテナの概要


このチュートリアルでは、コンテナ化されたワークロードに馴染みがない方を対象に、ソースコードから GKE でのコンテナ実行までのシンプルなアプリケーションの設定手順を通して、コンテナとコンテナ オーケストレーションについて説明します。

このチュートリアルには、コンテナや Kubernetes の使用経験は必要ありません。このチュートリアルを開始する前に Kubernetes の主な用語をおおまかに確認しておくには、Kubernetes の学習を開始するをご覧ください。ご希望なら、Kubernetes を漫画で学習できる Kubernetes コミックもあります。詳細なリソースについては、チュートリアルの最後にある次のステップをご覧ください。

コンテナと Kubernetes をすでによくご存じの場合は、このチュートリアルをスキップして、GKE 自体の学習を開始できます。

目標

  1. シンプルなマルチサービス「Hello World」アプリケーションを確認する。
  2. ソースからアプリケーションを実行する。
  3. アプリケーションをコンテナ化する。
  4. Kubernetes クラスタを作成する。
  5. コンテナをクラスタにデプロイする。

始める前に

次の手順で Kubernetes Engine API を有効にします。
  1. Google Cloud コンソールで Kubernetes Engine ページにアクセスします。
  2. プロジェクトを作成または選択します。
  3. API と関連サービスが有効になるのを待ちます。 これには数分かかることがあります。
  4. Make sure that billing is enabled for your Google Cloud project.

Cloud Shell を準備する

このチュートリアルでは、Cloud Shell を使用して、Debian ベースの Linux オペレーティング システムを実行している g1-small Compute Engine 仮想マシン(VM)をプロビジョニングします。

Cloud Shell を使用すると、次のようなメリットがあります。

  • Python 3 開発環境(virtualenv を含む)が完全にセットアップされています。
  • このチュートリアルで使用するコマンドライン ツールの gclouddockergitkubectl がすでにインストールされています。
  • 次の組み込みのテキスト エディタを選択できます。

    • Cloud Shell エディタ。Cloud Shell ウィンドウの上部にある [エディタを開く] をクリックしてアクセスします。

    • Emacs、Vim、Nano。Cloud Shell のコマンドラインからアクセスします。

  • In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    サンプルコードをダウンロードする

    1. helloserver ソースコードをダウンロードします。

      git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-samples
      
    2. サンプルコードのディレクトリに移動します。

      cd anthos-service-mesh-samples/docs/helloserver
      

    マルチサービス アプリケーションを確認する

    サンプル アプリケーションは Python で記述されており、REST を使用して通信する次のコンポーネントがあります。

    • server: 1 つの GET エンドポイント(/)を持つ基本的なサーバー。ターミナル ウィンドウに「hello world」を出力します。
    • loadgen: server にトラフィックを送信するスクリプト。1 秒あたりのリクエスト数(RPS)を構成できます。

    サンプル アプリケーション

    ソースからアプリケーションを実行する

    サンプル アプリケーションに慣れるため、Cloud Shell で実行します。

    1. sample-apps/helloserver ディレクトリから server を実行します。

      python3 server/server.py
      

      起動時に、server には次のとおりに表示されます。

      INFO:root:Starting server...
      
    2. 別のターミナル ウィンドウを開き、server にリクエストを送信できるようにします。Cloud Shell でこれを行うには、 [新しいタブを開く] をクリックして別のセッションを開きます。

    3. 新しいターミナル ウィンドウで、server にリクエストを送信します。

      curl http://localhost:8080
      

      server の出力は次のとおりです。

      Hello World!
      
    4. 同じタブで、loadgen スクリプトを含むディレクトリに移動します。

      cd anthos-service-mesh-samples/docs/helloserver/loadgen
    5. 次の環境変数を作成します。

      export SERVER_ADDR=http://localhost:8080
      export REQUESTS_PER_SECOND=5
      
    6. virtualenv を開始します。

      virtualenv --python python3 env
      
    7. 仮想環境をアクティブにします。

      source env/bin/activate
      
    8. loadgen の要件をインストールします。

      pip3 install -r requirements.txt
      
    9. loadgen アプリケーションを実行して、server のトラフィックを生成します。

      python3 loadgen.py
      

      起動時に、loadgen の出力は次のようになります。

      Starting loadgen: 2024-10-11 09:49:51.798028
      5 request(s) complete to http://localhost:8080
      
    10. 次に、server を実行しているターミナル ウィンドウを開きます。次のようなメッセージが表示されます。

      127.0.0.1 - - [11/Oct/2024 09:51:28] "GET / HTTP/1.1" 200 -
      INFO:root:GET request,
      Path: /
      Headers:
      Host: localhost:8080
      User-Agent: python-requests/2.32.3
      Accept-Encoding: gzip, deflate
      Accept: */*
      Connection: keep-alive
      

      ネットワーキングの観点からは、アプリケーション全体が同じホスト上で実行されているため、localhost を使用して server にリクエストを送信できます。

    11. loadgenserver を停止するには、各ターミナル ウィンドウで Ctrl-c を入力します。

    12. loadgen ターミナル ウィンドウで、仮想環境を無効にします。

      deactivate
      

    アプリケーションをコンテナ化する

    GKE でアプリケーションを実行するには、サンプル アプリケーションの両方のコンポーネントをコンテナにパッケージ化する必要があります。コンテナは、アプリケーションをどの環境でも実行できるようにするために必要なすべての要素を含むパッケージです。このチュートリアルでは、アプリケーションのコンテナ化に Docker を使用します。

    Docker でアプリケーションをコンテナ化するには、Dockerfile が必要です。Dockerfile はテキスト ファイルで、アプリケーション ソースコードとその依存関係をコンテナ イメージにアセンブルするために必要なコマンドを定義します。イメージをビルドしたら、そのイメージを Artifact Registry などのコンテナ レジストリにアップロードします。

    このチュートリアルのソースコードには、serverloadgen の両方の Dockerfile があり、イメージのビルドに必要なすべてのコマンドが用意されています。以下は、server 用の Dockerfile です。

    FROM python:3.13-slim as base
    FROM base as builder
    RUN apt-get -qq update \
        && apt-get install -y --no-install-recommends \
            g++ \
        && rm -rf /var/lib/apt/lists/*
    
    # Enable unbuffered logging
    FROM base as final
    ENV PYTHONUNBUFFERED=1
    
    RUN apt-get -qq update \
        && apt-get install -y --no-install-recommends \
            wget
    
    WORKDIR /helloserver
    
    # Grab packages from builder
    COPY --from=builder /usr/local/lib/python3.* /usr/local/lib/
    
    # Add the application
    COPY . .
    
    EXPOSE 8080
    ENTRYPOINT [ "python", "server.py" ]
    

    このファイルでは次の内容を確認できます。

    • FROM python:3-slim as base 命令は、最新の Python 3 イメージをベースイメージとして使用するように Docker に指示します。
    • COPY . . 命令は、現在の作業ディレクトリ(この場合は server.py)からコンテナのファイル システムに、ソースファイルをコピーします。
    • ENTRYPOINT は、コンテナを実行するために使用するコマンドを定義します。この例の命令は、ソースコードからの server.py の実行で使用した命令と似ています。
    • EXPOSE 命令は、server がポート 8080 でリッスンすることを指定します。この命令はポートを公開しませんが、コンテナの実行時にポート 8080 を開く必要があることを示すドキュメントとして機能します。

    アプリケーションのコンテナ化を準備する

    アプリケーションをコンテナ化する前に、使用するツールとサービスの設定を行う必要があります。

    1. Google Cloud CLI のデフォルト Google Cloud  プロジェクトを設定します。

      gcloud config set project PROJECT_ID
    2. Google Cloud CLI のデフォルトのリージョンを設定します。

      gcloud config set compute/region us-central1
      

    リポジトリを作成する

    Artifact Registry に Docker コンテナ イメージの新しいリポジトリを作成するには、次の操作を行います。

    1. Google Cloud プロジェクトで Artifact Registry サービスが有効になっていることを確認します。

      gcloud services enable artifactregistry.googleapis.com
      
      
    2. Artifact Registry リポジトリを作成します。

      gcloud artifacts repositories create container-intro --repository-format=docker \
          --location=us-central1 \
          --description="My new Docker repository"
      
    3. Google Cloud CLI を使用して、Docker から Artifact Registry への認証を設定します。

      gcloud auth configure-docker us-central1-docker.pkg.dev
      

    server をコンテナ化する

    次に、アプリケーションをコンテナ化します。まず、「hello world」server をコンテナ化し、イメージを Artifact Registry に push します。

    1. サンプル server があるディレクトリに移動します。

      cd ~/anthos-service-mesh-samples/docs/helloserver/server/
    2. Dockerfile を使用してイメージをビルドします。

      docker build -t us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver:v0.0.1 .
      
      • PROJECT_ID は、 Google Cloud プロジェクトの ID に置き換えます。

      -t フラグは Docker タグを表します。これは、コンテナのデプロイ時に使用するイメージの名前です。

    3. イメージを Artifact Registry に push します。

      docker push us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver:v0.0.1
      

    loadgen をコンテナ化する

    次に、同じ方法で負荷生成ツールのサービスをコンテナ化します。

    1. サンプル loadgen があるディレクトリに移動します。

      cd ../loadgen
      
    2. イメージをビルドします。

      docker build -t us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen:v0.0.1 .
      
    3. イメージを Artifact Registry に push します。

      docker push us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen:v0.0.1
      

    イメージのリストを表示する

    リポジトリ内のイメージのリストを取得して、イメージが push されたことを確認します。

    gcloud container images list --repository us-central1-docker.pkg.dev/PROJECT_ID/container-intro
    

    出力には、push したイメージ名が次のように一覧表示されます。

    NAME
    us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver
    us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen
    

    GKE クラスタを作成する

    この時点で、docker run コマンドを使用して、Cloud Shell VM でコンテナを実行することもできます。ただし、本番環境で信頼性の高いワークロードを実行するには、より統一された方法でコンテナを管理する必要があります。たとえば、コンテナが失敗した場合に確実に再起動するようにする必要があります。また、トラフィックの増加に対応するためにスケールアップし、コンテナの追加インスタンスを起動する方法も必要です。

    GKE では、これらのニーズに対処できます。GKE は、VM をクラスタに接続することで機能するコンテナ オーケストレーション プラットフォームです。各 VM はノードと呼ばれます。GKE クラスタでは、Kubernetes オープンソース クラスタ管理システムが使用されます。クラスタの操作には、Kubernetes のメカニズムが使用されます。

    GKE でコンテナを実行するには、まずクラスタを作成して接続する必要があります。

    1. クラスタを作成します。

      gcloud container clusters create-auto container-intro
      

      gcloud コマンドは、前に設定したデフォルト Google Cloud  プロジェクトとリージョンにクラスタを作成します。

      クラスタを作成するコマンドが完了するまで数分かかります。クラスタの準備ができている場合、出力は次のようになります。

       NAME: container-intro
       LOCATION: us-central1
       MASTER_VERSION: 1.30.4-gke.1348000
       MASTER_IP: 34.44.14.166
       MACHINE_TYPE: e2-small
       NODE_VERSION: 1.30.4-gke.1348000
       NUM_NODES: 3
       STATUS: RUNNING
      
    2. kubectl コマンドライン ツールに認証情報を提供して、クラスタの管理に使用できるようにします。

      gcloud container clusters get-credentials container-intro
      

    Kubernetes マニフェストを調べる

    ソースコードからアプリケーションを実行したとき、命令型コマンド python3 server.py を使用しました。

    命令型とは、「これをしろ」のような動詞駆動という意味です。

    対照的に、Kubernetes は宣言型モデルで動作します。つまり、Kubernetes には、実際の処理を指示するのではなく、望ましい状態を提示します。たとえば、実際のシステム状態が望ましい状態になるように、Kubernetes は必要に応じて Pod を起動または停止します。

    望ましい状態は、マニフェストというファイルで指定します。マニフェストは YAML や JSON などの言語で記述され、1 つ以上の Kubernetes オブジェクトの仕様が含まれています。

    このサンプルには、serverloadgen のマニフェストがそれぞれ含まれています。各マニフェストは、Kubernetes Deployment オブジェクト(Kubernetes Pod として管理用にパッケージ化されたコンテナの実行を管理する)と Service(Pod の IP アドレスを提供する)の望ましい状態を指定します。Pod は、Kubernetes で作成して管理できる、デプロイ可能なコンピューティングの最小単位であり、1 つ以上のコンテナを保持しています。

    次の図は、GKE で実行されるアプリケーションを示しています。

    GKE で実行されているコンテナ化されたアプリケーション

    Pod、Deployment、Service の詳細については、Kubernetes の学習を開始する、またはこのページの下部にあるリソースをご覧ください。

    サーバー

    まず、「hello world」server のマニフェストを確認します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: helloserver
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: helloserver
      template:
        metadata:
          labels:
            app: helloserver
        spec:
          containers:
          - image: gcr.io/google-samples/istio/helloserver:v0.0.1
            imagePullPolicy: Always
            name: main
          restartPolicy: Always
          terminationGracePeriodSeconds: 5

    このマニフェストには次のフィールドが含まれています。

    • kind はオブジェクトの種類を示します。
    • metadata.name で Deployment の名前を指定します。
    • 最初の spec フィールドには、望ましい状態の説明が含まれています。
    • spec.replicas で目的の Pod の数を指定します。
    • spec.template セクションで Pod テンプレートを定義します。Pod の仕様には、Artifact Registry から pull するイメージの名前である image フィールドが含まれています。次のステップでは、このイメージを先ほど作成した新しいイメージに更新します。

    hellosvc Service は、次のように定義されます。

    apiVersion: v1
    kind: Service
    metadata:
      name: hellosvc
    spec:
      ports:
      - name: http
        port: 80
        targetPort: 8080
      selector:
        app: helloserver
      type: LoadBalancer
    • LoadBalancer: クライアントは、安定した IP アドレスを持ち、クラスタの外部からアクセス可能なネットワーク ロードバランサの IP アドレスにリクエストを送信します。
    • targetPort: DockerfileEXPOSE 8080 コマンドでは実際にはポートが公開されないことに注意してください。ポート 8080 を公開して、クラスタの外部にある server コンテナにアクセスできるようにします。この場合、hellosvc.default.cluster.local:80(略称: hellosvc)は helloserver Pod IP のポート 8080 にマッピングされます。
    • port: クラスタ内の他のサービスでリクエストを送信するときに使用するポート番号です。

    負荷生成ツール

    loadgen.yaml の Deployment オブジェクトは server.yaml に類似します。大きな違いとして、loadgen Deployment の Pod 仕様に env というフィールドがあります。このセクションでは、ソースからアプリケーションを実行したときに設定済みの loadgen で必要とされる環境変数を定義します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: loadgenerator
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: loadgenerator
      template:
        metadata:
          labels:
            app: loadgenerator
        spec:
          containers:
          - env:
            - name: SERVER_ADDR
              value: http://hellosvc:80/
            - name: REQUESTS_PER_SECOND
              value: '10'
            image: gcr.io/google-samples/istio/loadgen:v0.0.1
            imagePullPolicy: Always
            name: main
            resources:
              limits:
                cpu: 500m
                memory: 512Mi
              requests:
                cpu: 300m
                memory: 256Mi
          restartPolicy: Always
          terminationGracePeriodSeconds: 5

    loadgen は受信リクエストを受け付けないため、type フィールドは ClusterIP に設定されます。このタイプの Service は、クラスタ内のエンティティが使用できる安定した IP アドレスを提供しますが、その IP アドレスは外部クライアントには公開されません。

    apiVersion: v1
    kind: Service
    metadata:
      name: loadgensvc
    spec:
      ports:
      - name: http
        port: 80
        targetPort: 8080
      selector:
        app: loadgenerator
      type: ClusterIP

    コンテナを GKE にデプロイする

    コンテナをデプロイするには、kubectl を使用して、望ましい状態を指定するマニフェストを適用します。

    server をデプロイする

    1. サンプル server があるディレクトリに移動します。

      cd ~/anthos-service-mesh-samples/docs/helloserver/server/
    2. Cloud Shell エディタ(または任意のテキスト エディタ)で server.yaml を開きます。

    3. image フィールド内の名前を Docker イメージの名前に置き換えます。

      image: us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver:v0.0.1
      

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

      • Cloud Shell エディタを使用している場合、ファイルは自動的に保存されます。[ターミナルを開く] をクリックして、ターミナル ウィンドウに戻ります。
      • Cloud Shell でテキスト エディタを使用している場合は、server.yaml を保存して閉じます。
    4. マニフェストを Kubernetes にデプロイします。

      kubectl apply -f server.yaml
      

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

      deployment.apps/helloserver created
      service/hellosvc created
      

    loadgen をデプロイする

    1. loadgen があるディレクトリに移動します。

      cd ../loadgen
      
    2. 前と同様に、テキスト エディタで loadgen.yaml を開きます。

    3. 再度、image フィールド内の名前を Docker イメージの名前に置き換えます。

      image: us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen:v0.0.1
      

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

      • Cloud Shell エディタを使用している場合、ファイルは自動的に保存されます。[ターミナルを開く] をクリックして、ターミナル ウィンドウに戻ります。
      • Cloud Shell でテキスト エディタを使用している場合は、loadgen.yaml を保存して閉じます。
    4. マニフェストをクラスタにデプロイします。

      kubectl apply -f loadgen.yaml
      

      成功すると、コマンドは次のレスポンスを返します。

      deployment.apps/loadgenerator created
      service/loadgensvc created
      

    デプロイを確認する

    マニフェストをクラスタにデプロイしたら、コンテナが正常にデプロイされたことを確認します。

    1. クラスタ内の Pod のステータスを確認します。

      kubectl get pods
      

      このコマンドは、次のようなステータスを返します。

      NAME                             READY   STATUS    RESTARTS   AGE
      helloserver-69b9576d96-mwtcj     1/1     Running   0          58s
      loadgenerator-774dbc46fb-gpbrz   1/1     Running   0          57s
      
    2. loadgen Pod からアプリケーション ログを取得します。POD_ID は、出力済みの負荷生成ツールの Pod ID に置き換えます。

      kubectl logs POD_ID
      
    3. hellosvc の外部 IP アドレスを取得します。

      kubectl get service hellosvc
      

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

      NAME         TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE
      hellosvc     LoadBalancer   10.81.15.158   192.0.2.1       80:31127/TCP   33m
      
    4. hellosvc にリクエストを送信します。EXTERNAL_IPhellosvc の外部 IP アドレスに置き換えます。

      curl http://EXTERNAL_IP
      

      サーバーから「Hello World!」というメッセージが表示されます。

    クリーンアップ

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

    プロジェクト全体を削除しない場合は、次の操作を行います。

    • GKE クラスタを削除します。クラスタの削除では、クラスタを構成するすべてのリソース(Compute Engine インスタンス、ディスク、ネットワーク リソースなど)が削除されます。

       gcloud container clusters delete container-intro
      
    • Artifact Registry リポジトリを削除します。

       gcloud artifacts repositories delete container-intro --location=us-central1
      

    次のステップ