演習 - Kubernetes を使用してインフラストラクチャの回復性を実装する

完了

前のユニットでは、.NET ネイティブの回復性拡張機能を使用するエラー処理コードを追加することにより、回復性を実装しました。 ただし、この変更は、変更したサービスにのみ適用されます。 多くのサービスを備える大規模なアプリを更新することは簡単ではありません。

このユニットでは、"コード ベース" の回復性を使う代わりに、アプリ全体を対象とする "インフラストラクチャ ベース" の回復性と呼ばれるアプローチを使います。 このチュートリアルの内容は次のとおりです。

  • Kubernetes には回復性を一切導入せずにアプリを再デプロイします。
  • Linkerd を Kubernetes クラスターにデプロイします。
  • 回復性のために Linkerd を使用するようにアプリを構成する。
  • Linkerd を使用してアプリの動作を確認する。

アプリを再デプロイする

Linkerd を適用する前に、コードベースの回復性が追加される前の状態にアプリを戻します。 元に戻すには、以下の手順に従います。

  1. 下部のパネルで、[ターミナル] タブを選択し、以下の git コマンドを実行して変更を元に戻します。

    cd Store
    git checkout Program.cs
    git checkout Store.csproj
    cd ..
    dotnet publish /p:PublishProfile=DefaultContainer
    

Kubernetes をインストールする

codespace に Kubernetes と k3d をインストールします。 k3d は、ローカル コンピューター上の仮想マシン (VM) 内で単一ノード Kubernetes クラスターを実行するツールです。 これは Kubernetes デプロイをローカルでテストするのに便利で、codespace 内で適切に動作します。

以下のコマンドを実行して、Kubernetes と MiniKube をインストールします。

curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/kubernetes-apt-keyring.gpg

echo 'deb [signed-by=/etc/apt/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

sudo apt-get update
sudo apt-get install -y kubectl

curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash
k3d cluster create devcluster --config k3d.yml

Docker Hub に eShop サービスをデプロイする

ビルドしたサービスのローカル イメージは、Kubernetes にデプロイ可能なコンテナー レジストリでホストする必要があります。 このユニットでは、コンテナー レジストリとして Docker Hub を使用します。

以下のコマンドを実行して、イメージを Docker Hub にプッシュします。

sudo docker login

sudo docker tag products [your username]/productservice
sudo docker tag store [your username]/storeimage

sudo docker push [your username]/productservice
sudo docker push [your username]/storeimage

docker-compose ファイルを Kubernetes マニフェストに変換する

現時点では、Docker でアプリを実行する方法を定義します。 Kubernetes は、アプリがどのように実行されるかの定義に別の形式を使用します。 Kompose というツールを使用して、docker-compose ファイルを Kubernetes マニフェストに変換できます。

  1. Docker Hub にプッシュしたイメージを使用するには、これらのファイルを編集する必要があります。

  2. codespace で、ファイル backend-deploy.yml を開きます。

  3. 変更するのは次の行です。

      containers:
        - image: [YOUR DOCKER USER NAME]/productservice:latest
    

    プレースホルダーの [YOUR DOCKER USER NAME] を、自分の実際の Docker ユーザー名に置き換えます。

  4. frontend-deploy.yml ファイルに対してこれらの手順を繰り返します。

  5. 変更するのは次の行です。

      containers:
      - name: storefrontend
        image: [YOUR DOCKER USER NAME]/storeimage:latest  
    

    プレースホルダーの [YOUR DOCKER USER NAME] を、自分の実際の Docker ユーザー名に置き換えます。

  6. 次のように eShop アプリを Kubernetes にデプロイします。

    kubectl apply -f backend-deploy.yml,frontend-deploy.yml  
    

    次のメッセージのような出力が表示されるはずです。

    deployment.apps/productsbackend created
    service/productsbackend created
    deployment.apps/storefrontend created
    service/storefrontend created
    
  7. 次のようにすべてのサービスが実行されていることを確認します。

    kubectl get pods
    

    次のメッセージのような出力が表示されるはずです。

    NAME                        READY   STATUS    RESTARTS   AGE
    backend-66f5657758-5gnkw    1/1     Running   0          20s
    frontend-5c9d8dbf5f-tp456   1/1     Running   0          20s
    
  8. [ポート] タブに切り替えて、Kubernetes で実行されている eShop を表示するために、[フロントエンド (32000)] ポートの横にある地球アイコンを選択します。

linkerd をインストールする

開発コンテナーには Linkerd CLI をインストールする必要があります。 次のコマンドを実行して、Linkerd の前提条件が満たされていることを確認します。

curl -sL run.linkerd.io/install | sh
export PATH=$PATH:/home/vscode/.linkerd2/bin
linkerd check --pre

次のような出力が表示されます。

kubernetes-api
--------------
√ can initialize the client
√ can query the Kubernetes API

kubernetes-version
------------------
√ is running the minimum Kubernetes API version
√ is running the minimum kubectl version

pre-kubernetes-setup
--------------------
√ control plane namespace does not already exist
√ can create non-namespaced resources
√ can create ServiceAccounts
√ can create Services
√ can create Deployments
√ can create CronJobs
√ can create ConfigMaps
√ can create Secrets
√ can read Secrets
√ can read extension-apiserver-authentication configmap
√ no clock skew detected

pre-kubernetes-capability
-------------------------
√ has NET_ADMIN capability
√ has NET_RAW capability

linkerd-version
---------------
√ can determine the latest version
√ cli is up-to-date

Status check results are √

Linkerd を Kubernetes にデプロイする

まず、次のコマンドを実行して、カスタム リソース定義 (CRD) をインストールします。

linkerd install --crds | kubectl apply -f -

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

linkerd install --set proxyInit.runAsRoot=true | kubectl apply -f -

上記のコマンドでは次のことが行われます。

  • linkerd install によって、必要なコントロール プレーン リソースを含む Kubernetes マニフェストが生成されます。
  • 生成されたマニフェストは kubectl apply にパイプされ、これがそれらのコントロール プレーン リソースを Kubernetes クラスターにインストールします。

出力の最初の行は、コントロール プレーンが独自の linkerd 名前空間にインストールされたことを示しています。 残りの出力は、作成されるオブジェクトを表しています。

namespace/linkerd created
clusterrole.rbac.authorization.k8s.io/linkerd-linkerd-identity created
clusterrolebinding.rbac.authorization.k8s.io/linkerd-linkerd-identity created
serviceaccount/linkerd-identity created
clusterrole.rbac.authorization.k8s.io/linkerd-linkerd-controller created

Linkerd のデプロイを確認する

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

linkerd check

上記のコマンドでは、Linkerd CLI およびコントロール プレーンの構成が分析されます。 Linkerd が正しく構成されている場合、次の出力が表示されます。

kubernetes-api
--------------
√ can initialize the client
√ can query the Kubernetes API

kubernetes-version
------------------
√ is running the minimum Kubernetes API version
√ is running the minimum kubectl version

linkerd-existence
-----------------
√ 'linkerd-config' config map exists
√ heartbeat ServiceAccount exist
√ control plane replica sets are ready
√ no unschedulable pods
√ controller pod is running
√ can initialize the client
√ can query the control plane API

linkerd-config
--------------
√ control plane Namespace exists
√ control plane ClusterRoles exist
√ control plane ClusterRoleBindings exist
√ control plane ServiceAccounts exist
√ control plane CustomResourceDefinitions exist
√ control plane MutatingWebhookConfigurations exist
√ control plane ValidatingWebhookConfigurations exist
√ control plane PodSecurityPolicies exist

linkerd-identity
----------------
√ certificate config is valid
√ trust anchors are using supported crypto algorithm
√ trust anchors are within their validity period
√ trust anchors are valid for at least 60 days
√ issuer cert is using supported crypto algorithm
√ issuer cert is within its validity period
√ issuer cert is valid for at least 60 days
√ issuer cert is issued by the trust anchor

linkerd-api
-----------
√ control plane pods are ready
√ control plane self-check
√ [kubernetes] control plane can talk to Kubernetes
√ [prometheus] control plane can talk to Prometheus
√ tap api service is running

linkerd-version
---------------
√ can determine the latest version
√ CLI is up to date

control-plane-version
---------------------
√ control plane is up to date
√ control plane and CLI versions match

linkerd-addons
--------------
√ 'linkerd-config-addons' config map exists

linkerd-grafana
---------------
√ grafana add-on service account exists
√ grafana add-on config map exists
√ grafana pod is running

Status check results are √

ヒント

インストールされた Linkerd コンポーネントの一覧を確認するには、kubectl -n linkerd get deploy コマンドを実行します。

Linkerd を使用するようにアプリを構成する

Linkerd はデプロイされますが、構成されていません。 アプリの動作は変更されません。

Linkerd では、サービスの内部を認識しないため、失敗した要求を再試行することが適切かどうかを判断できません。 たとえば、支払いに失敗した HTTP POST を再試行することは不適切です。 このため、"サービス プロファイル" が必要です。 "サービス プロファイル" は、サービスのルートを定義するカスタムの Kubernetes リソースです。 また、再試行やタイムアウトなどのルートごとの機能も有効になります。 Linkerd では、サービス プロファイル マニフェストで構成されたルートのみが再試行されます。

簡潔にするため、アグリゲーターとクーポン サービスにのみ Linkerd を実装します。 これら 2 つのサービスに Linkerd を実装するには、次のようにします。

  • Linkerd がポッド内にプロキシ コンテナーを作成するように、eShop デプロイを変更します。
  • クーポン サービスのルートでの再試行を構成するには、クラスターにサービス プロファイル オブジェクトを追加します。

eShop デプロイを変更する

Linkerd プロキシ コンテナーを使うようにサービスを構成する必要があります。

  1. linkerd.io/inject: enabled 注釈を、テンプレート メタデータの下の backend-deploy.yml ファイルに追加します。

      template:
        metadata:
          annotations:
            linkerd.io/inject: enabled
          labels: 
    
  2. frontend-deploy.yml ファイルの同じ場所に linkerd.io/inject: enabled 注釈を追加します。

  3. 次のように Kubernetes クラスター内のデプロイを更新します。

    kubectl apply -f backend-deploy.yml,frontend-deploy.yml
    

製品サービスに対して Linkerd サービス プロファイルを適用する

製品サービスのサービス プロファイル マニフェストは以下のとおりです。

apiVersion: linkerd.io/v1alpha2
kind: ServiceProfile
metadata:
  name: backend
  namespace: default
spec:
  routes:
  - condition:
      method: GET
      pathRegex: /api/Product
    name: GET /v1/products
    isRetryable: true
  retryBudget:
    retryRatio: 0.2
    minRetriesPerSecond: 10
    ttl: 120s

上記のマニフェストは、次のように構成されています。

  • パターン /api/Product に一致するべき等の HTTP GET ルートを再試行できます。
  • 再試行により、増える要求の負荷は 20% 以下であり、1 秒あたり 10 回の "無料" の再試行が追加されます。

次のコマンドを実行して、Kubernetes クラスターでサービス プロファイルを使用します。

kubectl apply -f - <<EOF
apiVersion: linkerd.io/v1alpha2
kind: ServiceProfile
metadata:
  name: backend
  namespace: default
spec:
  routes:
  - condition:
      method: GET
      pathRegex: /api/Product
    name: GET /v1/products 
    isRetryable: true
  retryBudget:
    retryRatio: 0.2
    minRetriesPerSecond: 10
    ttl: 120s  
EOF

次のような出力が表示されます。

serviceprofile.linkerd.io/backend created

サービス メッシュに監視をインストールする

Linkerd には、追加の機能を提供する拡張機能があります。 viz 拡張機能をインストールし、Linkerd のダッシュボードでアプリの状態を表示します。

  1. ターミナルで次のコマンドを実行して、拡張機能をインストールします。

    linkerd viz install | kubectl apply -f -
    
  2. 次のコマンドを使用してダッシュボードを表示します。

    linkerd viz dashboard
    

    [ポート] タブに移動し、linkerd viz ダッシュボードが実行されているプロセスで転送された新しいポートを表示します。 [ブラウザーで開く] を選んでダッシュボードを開きます。

  3. Linkerd ダッシュボードで、[名前空間] を選択します。

  4. [HTTP メトリック] で、[既定値] を選択します。

    Screenshot showing the Linkerd dashboard with both the frontend and backend.

Linkerd の回復性をテストする

再デプロイされたコンテナーが正常な状態になったら、次の手順に従って、Linkerd を使用してアプリの動作をテストします。

  1. 次のコマンドを使用して、実行中のポッドの状態を確認します。

    kubectl get pods --all-namespaces
    
  2. 次のようにすべての製品サービス ポッドを停止します。

    kubectl scale deployment productsbackend --replicas=0
    
  3. eShop Web アプリに移動し、製品の表示を試みます。 エラー メッセージ "製品の読み込みに問題があります。後でもう一度やり直してください" が表示されるまでに遅延が発生します。

  4. 次のように製品サービス ポッドを再起動します。

    kubectl scale deployment productsbackend --replicas=1
    
  5. これで、アプリに製品が表示されるはずです。

Linkerd は、コードベースの回復性で確認したものとは異なる回復性のアプローチに従います。 Linkerd では、短い間隔で何度も操作の再試行が透過的に実行されます。 この動作をサポートするために、アプリを変更する必要はありませんでした。

追加情報

Linkerd の構成の詳細については、次のリソースを参照してください。