演習 - 複数コンテナー ソリューションを Kubernetes クラスターにデプロイする

完了

プロジェクトで提供されるリリース パイプラインは、ソリューションを Docker コンテナーとしてビルドし、Azure App Service にデプロイするように設計されています。 Kubernetes クラスターへの複数のコンテナーのデプロイをサポートするには、このパイプラインを変更する必要があります。

このユニットでは、次の方法を学習します。

  • main ブランチへのコミットトリガーするようにパイプラインを更新します。
  • パイプライン全体で共有される変数を定義します。
  • Docker イメージをビルドして発行します。
  • Kubernetes マニフェストを発行します。
  • Kubernetes とコンテナー レジストリ インスタンスの間で使用するイメージ プル シークレットを作成するタスクを追加します。
  • 更新されたイメージを Kubernetes クラスターにデプロイします。

トリガーをサポートするようにパイプラインを更新する

  1. Azure DevOps 組織にサインインしてから、プロジェクトに移動します。

  2. [パイプライン] を選択し、使用するパイプラインを選択します。

  3. [編集] を選んで azure-pipelines.yml を編集します。

    Andy: これは、前の単一コンテナー ソリューション用に設けたビルド ステージでした。 正常に実行されないことがわかったので、無効にしました。 main ブランチへのコミットでのトリガーを再び有効にすることで開始できます。

  4. ファイルの先頭にある既存の trigger 行を次のスニペットに置き換えます。 これにより、メイン ブランチに対してコミットが行われるたびにパイプライン実行がトリガーされます。

    trigger:
    - 'main'
    

パイプライン全体でアクセスできる変数を定義する

Andy: 2 つのパイプライン変数を追加する必要があります。 1 つはランキング リポジトリの名前 (leaderboard) を指定するためのものです。 もう 1 つは、デプロイの間に AKS と ACR のインスタンス間で共有するために使われる、イメージ プル シークレットの名前用です。

  1. 次の強調表示されたコードを variables セクションに追加します。

    variables:
      buildConfiguration: 'Release'
      leaderboardRepository: 'leaderboard'
      webRepository: 'web'
      tag: '$(Build.BuildId)'
      imagePullSecret: 'secret'
    

Docker イメージをビルドして Azure Container Registry に発行する

Andy: Web アプリを Docker コンテナーとしてビルドするためのタスクは既にあります。これを、コンテナー レジストリに発行します。 2 つ目のタスクを使用するだけで、ランキングに対して同じ操作を行うことができます。

  1. 次の強調表示されたスニペットを使用して、2 番目の Docker@2 タスクを追加して、ランキング コンテナーをビルドして発行します。 Web コンテナー タスクのすぐ後にこのタスクを追加します。

    - task: Docker@2
      displayName: 'Build and push the web image to container registry'
      inputs:
        command: buildAndPush
        buildContext: $(Build.Repository.LocalPath)
        repository: $(webRepository)
        dockerfile: '$(Build.SourcesDirectory)/Tailspin.SpaceGame.Web/Dockerfile'
        containerRegistry: 'Container Registry Connection'
        tags: |
          $(tag)
    
    - task: Docker@2
      displayName: 'Build and push the leaderboard image to container registry'
      inputs:
        command: buildAndPush
        buildContext: $(Build.Repository.LocalPath)
        repository: $(leaderboardRepository)
        dockerfile: '$(Build.SourcesDirectory)/Tailspin.SpaceGame.LeaderboardContainer/Dockerfile'
        containerRegistry: 'Container Registry Connection'
        tags: |
          $(tag)
    

ヒント

YAML ファイルでは空白文字が重要であるため、ここで追加するタスクで前のタスクと同じインデントが使われていることを確認します。

Kubernetes マニフェストを発行する

Andy: 次のステージに進むことができると思います。 何か足りないものがありますか。

Mara:あなたは、デプロイするときに Kubernetes で必要なデプロイとサービスが定義されているいくつかのマニフェスト ファイルがソース プロジェクトにあると言いました。 このステージを完了する前に、それらを発行する必要があります。

Andy: それが必要ですか。 それらはまだローカル ディスクに存在するのではありませんか。

Mara: ビルドと同じステージ内にデプロイ タスクを追加したとしたら、そうでしょう。 ただし、"デプロイ" タスクは独自のデプロイ ステージで実行されるため、新しい環境 (おそらく別のエージェント上でも) で実行されます。 このステージで生成されるもので、他のステージで必要なものは必ず発行する必要があります。

Andy: それは大事なポイントです。 簡単にできますか。 manifests フォルダーが新しいエージェントにコピーされるようにする必要があります。

Mara: それが PublishBuildArtifacts@1 タスクの役割です。 非常に一般的なので、そのための簡単な方法として publish があります。

  1. 次のコード スニペットに示すように、後のステージのために manifests フォルダーを格納する publish タスクを追加します。 このタスクのインデントが前のタスクのインデントと一致していることを確認します。

    - task: Docker@2
      displayName: 'Build and push the leaderboard image to container registry'
      inputs:
        command: buildAndPush
        buildContext: $(Build.Repository.LocalPath)
        repository: $(leaderboardRepository)
        dockerfile: '$(Build.SourcesDirectory)/Tailspin.SpaceGame.LeaderboardContainer/Dockerfile'
        containerRegistry: 'Container Registry Connection'
        tags: |
          $(tag)
    
    - publish: '$(Build.SourcesDirectory)/manifests'
      artifact: manifests
    

デプロイ ステージを置き換える

Mara: 既存のデプロイ ステージを、デプロイ ジョブを使用するものに置き換えます。 "デプロイ ジョブ" は特別な種類のジョブであり、前に作成した Azure DevOps 環境にデプロイを関連付けることができます。 これにより、デプロイ履歴を簡単に追跡できるようになり、ソリューションがより洗練されたものになるにつれて特に役立ちます。

  1. 既存のデプロイ ステージ (ビルド ステージの後にあるものすべて) を削除し、次のスニペットに置き換えます。 利用するデプロイ環境を示す強調表示された行をメモしておきます。

    - stage: 'Deploy'
      displayName: 'Deploy the containers'
      dependsOn: Build
      jobs:
      - deployment: Deploy
        displayName: Deploy
        pool:
          vmImage: 'ubuntu-20.04'
        environment: 'Dev'
        variables:
        - group: Release
        strategy:
          runOnce:
            deploy:
              steps:
    

    Mara: デプロイ ステージに追加する最初のステップでは、前に発行されたマニフェスト成果物を、DownloadBuildArtifacts@0 を使用してダウンロードします。

    Andy: 当ててみましょうか。そのタスクには download の短縮形があるのではないですか。

    Mara: そのとおりです。 current 指定子を使用して、パイプラインの現在の実行からの成果物が必要であることを示すことができます。

  2. 強調されている行を、デプロイ ステージの最初のステップとして追加します。

    - stage: 'Deploy'
      displayName: 'Deploy the containers'
      dependsOn: Build
      jobs:
      - deployment: Deploy
        displayName: Deploy
        pool:
          vmImage: 'ubuntu-20.04'
        environment: 'spike.default'
        variables:
        - group: Release
        strategy:
          runOnce:
            deploy:
              steps:
              - download: current
                artifact: manifests
    

    Andy: 次に、ACR と AKS インスタンスの間で共有されるイメージ プル シークレットを作成する必要があります。 使用できるタスクがあるかどうか、わかりますか。

    Mara: それについて調べたのですが、ラッキーです。 KubernetesManifest@0 タスクで、必要なシークレットを作成するアクションがサポートされています。

Kubernetes マニフェスト タスク

Kubernetes マニフェスト タスクは、Kubernetes に必要なすべてのメインストリーム デプロイ操作を管理するように設計されています。 シークレットの作成からイメージのデプロイまで、複数の action オプションがサポートされています。 この場合、createSecret アクションが次のパラメーターと共に使用されます。

  • action は、実行する機能を示します。 この場合、createSecret によって共有シークレットが作成されます。
  • connectionType では、使用するサービス接続の種類を指定します。 省略可能: azureResourceManager または kubernetesServiceConnection
  • secretName では、作成するシークレットの名前を指定します。
  • dockerRegistryEndpoint では、Azure Container Registry のサービス接続の名前を指定します。
  • azureSubscriptionConnection では、ARM のサービス接続の名前を指定します。
  • azureResourceGroup では、リソース グループの名前を指定します。
  • kubernetesCluster では、AKS クラスターの名前を指定します。
  • namespace では、このアクションを適用する Kubernetes 名前空間を指定します。
  1. 次のスニペットをパイプラインの末尾に追加します。 リソース グループ名とクラスター名の両方が、前に作成したものの名前と一致していることを確認します。 このタスクのインデントが、"ダウンロード" タスクのインデントと一致していることを確認します。

    - task: KubernetesManifest@1
      displayName: Create imagePullSecret
      inputs:
        action: createSecret
        connectionType: azureResourceManager
        secretName: $(imagePullSecret)
        dockerRegistryEndpoint: 'Container Registry Connection'
        azureSubscriptionConnection: 'Kubernetes Cluster Connection'
        azureResourceGroup: 'tailspin-space-game-rg'
        kubernetesCluster: 'tailspinspacegame-24591'
        namespace: 'default'
    

    Andy: 最後のステップでは、Kubernetes クラスターへのイメージのデプロイをトリガーします。 ドキュメントに基づくと、同じタスクを使用できるように見えますが、アクションやパラメーターは異なります。

    • action は、実行する機能を示します。 この場合は、AKS クラスターにデプロイするための deploy
    • connectionType では、使用するサービス接続の種類を指定します。 省略可能: azureResourceManager または kubernetesServiceConnection
    • azureSubscriptionConnection では、ARM のサービス接続の名前を指定します。
    • azureResourceGroup では、リソース グループの名前を指定します。
    • kubernetesCluster では、AKS クラスターの名前を指定します。
    • namespace では、このアクションを適用する Kubernetes 名前空間を指定します。
    • imagePullSecrets では、コンテナー レジストリからプルするために必要なシークレットの一覧を指定します。
    • containers では、デプロイするコンテナー イメージの一覧を指定します。
  2. 次のスニペットをパイプラインの末尾に追加します。 リソース グループ名とクラスター名の両方が、前に作成したものの名前と一致していることを確認します。 このタスクのインデントが前のタスクのものと一致していることを確認します。

    - task: KubernetesManifest@1
      displayName: Deploy to Kubernetes cluster
      inputs:
        action: deploy
        connectionType: azureResourceManager
        azureSubscriptionConnection: 'Kubernetes Cluster Connection'
        azureResourceGroup: 'tailspin-space-game-rg'
        kubernetesCluster: 'tailspinspacegame-24591'
        namespace: 'default'
        manifests: |
          $(Pipeline.Workspace)/manifests/deployment.yml
          $(Pipeline.Workspace)/manifests/service.yml
        imagePullSecrets: |
          $(imagePullSecret)
        containers: |
          $(RegistryName)/$(webRepository):$(tag)
          $(RegistryName)/$(leaderboardRepository):$(tag)
    

パイプラインを実行する

  1. ページの右上隅にある [保存] を選択します。 [保存] を選んで、コミット メッセージを確認します。

  2. [実行] を選び、ブランチ名を確認してから、[実行] を選んでパイプラインの実行をトリガーします。

  3. [パイプライン] を選んでから、自分のパイプラインを選んでパイプライン実行のログを表示します。

  4. パイプラインの実行が完了したら、左側のペインで [環境] を選び、開発環境を選んでデプロイ ジョブを表示します。

  5. 次に、デプロイされた Web アプリと API エンドポイントを確認します。 そのためには、Web と "ランキング" 両方のサービスの外部 IP アドレスを取得する必要があります。

  6. Azure portal に移動し、自分の AKS クラスターを選んでから、[サービスとイングレス] を選びます。

    Screenshot of how to find the external IPs for your web and leaderboard services.

  7. AKS でサイトを表示するには、Web サービスの [外部 IP] を選びます。

    Screenshot of the Space Game web site.

  8. 中断した Azure portal ウィンドウに戻り、ランキング サービスの [外部 IP] をコピーします。 この IP アドレスは、ランキング API がパブリックにホストされている場所です。

  9. 次のリンクのプレースホルダーを、コピーした外部 IP に置き換えます。 pageSize=10 クエリ パラメーターを追加して、ブラウザーで JSON 応答を簡単に表示できるようにすることもできます。 ブラウザーの新しいタブで、次のような URL を使用します。

    http://[IP]/api/Leaderboard?pageSize=10
    
  10. AKS クラスターでホストされているスコアボード API からの生の JSON 応答を見ることができます。 これで、他のアプリケーションから呼び出すことができる REST API ができました。

    Screenshot of a web browser showing the JSON response from the leaderboard service.

Andy: これはすばらしい結果になりました! Kubernetes の使用は、幅広いマイクロサービス戦略を導入するための優れた方法だと思います。