演習 - Kubernetes を使用してインフラストラクチャの回復性を実装する
前のユニットでは、.NET ネイティブの回復性拡張機能を使用するエラー処理コードを追加することにより、回復性を実装しました。 ただし、この変更は、変更したサービスにのみ適用されます。 多くのサービスを備える大規模なアプリを更新することは簡単ではありません。
このユニットでは、"コード ベース" の回復性を使う代わりに、アプリ全体を対象とする "インフラストラクチャ ベース" の回復性と呼ばれるアプローチを使います。 このチュートリアルの内容は次のとおりです。
- Kubernetes には回復性を一切導入せずにアプリを再デプロイします。
- Linkerd を Kubernetes クラスターにデプロイします。
- 回復性のために Linkerd を使用するようにアプリを構成する。
- Linkerd を使用してアプリの動作を確認する。
アプリを再デプロイする
Linkerd を適用する前に、コードベースの回復性が追加される前の状態にアプリを戻します。 元に戻すには、以下の手順に従います。
下部のパネルで、[ターミナル] タブを選択し、以下の 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 マニフェストに変換できます。
Docker Hub にプッシュしたイメージを使用するには、これらのファイルを編集する必要があります。
codespace で、ファイル backend-deploy.yml を開きます。
変更するのは次の行です。
containers: - image: [YOUR DOCKER USER NAME]/productservice:latest
プレースホルダーの [YOUR DOCKER USER NAME] を、自分の実際の Docker ユーザー名に置き換えます。
frontend-deploy.yml ファイルに対してこれらの手順を繰り返します。
変更するのは次の行です。
containers: - name: storefrontend image: [YOUR DOCKER USER NAME]/storeimage:latest
プレースホルダーの [YOUR DOCKER USER NAME] を、自分の実際の Docker ユーザー名に置き換えます。
次のように 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
次のようにすべてのサービスが実行されていることを確認します。
kubectl get pods
次のメッセージのような出力が表示されるはずです。
NAME READY STATUS RESTARTS AGE backend-66f5657758-5gnkw 1/1 Running 0 20s frontend-5c9d8dbf5f-tp456 1/1 Running 0 20s
[ポート] タブに切り替えて、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 プロキシ コンテナーを使うようにサービスを構成する必要があります。
linkerd.io/inject: enabled
注釈を、テンプレート メタデータの下の backend-deploy.yml ファイルに追加します。template: metadata: annotations: linkerd.io/inject: enabled labels:
frontend-deploy.yml ファイルの同じ場所に
linkerd.io/inject: enabled
注釈を追加します。次のように 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 のダッシュボードでアプリの状態を表示します。
ターミナルで次のコマンドを実行して、拡張機能をインストールします。
linkerd viz install | kubectl apply -f -
次のコマンドを使用してダッシュボードを表示します。
linkerd viz dashboard
[ポート] タブに移動し、linkerd viz ダッシュボードが実行されているプロセスで転送された新しいポートを表示します。 [ブラウザーで開く] を選んでダッシュボードを開きます。
Linkerd ダッシュボードで、[名前空間] を選択します。
[HTTP メトリック] で、[既定値] を選択します。
Linkerd の回復性をテストする
再デプロイされたコンテナーが正常な状態になったら、次の手順に従って、Linkerd を使用してアプリの動作をテストします。
次のコマンドを使用して、実行中のポッドの状態を確認します。
kubectl get pods --all-namespaces
次のようにすべての製品サービス ポッドを停止します。
kubectl scale deployment productsbackend --replicas=0
eShop Web アプリに移動し、製品の表示を試みます。 エラー メッセージ "製品の読み込みに問題があります。後でもう一度やり直してください" が表示されるまでに遅延が発生します。
次のように製品サービス ポッドを再起動します。
kubectl scale deployment productsbackend --replicas=1
これで、アプリに製品が表示されるはずです。
Linkerd は、コードベースの回復性で確認したものとは異なる回復性のアプローチに従います。 Linkerd では、短い間隔で何度も操作の再試行が透過的に実行されます。 この動作をサポートするために、アプリを変更する必要はありませんでした。
追加情報
Linkerd の構成の詳細については、次のリソースを参照してください。