练习 - 使用 Kubernetes 实现基础结构复原能力

已完成

在上一单元中,你通过使用 .NET 本机复原扩展添加故障处理代码实现了复原。 然而,此更改仅适用于你已更改的服务。 更新包含多种服务的大型应用并非易事。

本单元没有使用基于代码的复原,而是使用了一种称为基于基础结构的复原的方法,此方法涵盖了整个应用。 你将:

  • 将没有任何复原能力的应用重新部署到 Kubernetes。
  • 在 Kubernetes 群集中部署 Linkerd。
  • 配置应用以使用 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 部署,并在代码空间中运行良好。

运行以下命令以安装 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

将 eShop 服务部署到 Docker Hub

生成的服务的本地映像需要托管在容器注册表中,才能部署到 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。 要为这两种服务实现 Linkerd,你需要:

  • 修改 eShop 部署,以便 Linkerd 在 Pod 中创建其代理容器。
  • 要在优惠券服务的路由上配置重试操作,请将服务配置文件对象添加到群集。

修改 eShop 部署

必须将服务配置为使用 Linkerd 代理容器。

  1. linkerd.io/inject: enabled 注释添加到 backend-deploy.yml 文件的模板元数据下

      template:
        metadata:
          annotations:
            linkerd.io/inject: enabled
          labels: 
    
  2. linkerd.io/inject: enabled 注释添加到同一位置的 frontend-deploy.yml 文件

  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%;此外,每秒还有 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. 使用以下命令检查正在运行的 Pod 的状态:

    kubectl get pods --all-namespaces
    
  2. 停止所有产品和服务 Pod:

    kubectl scale deployment productsbackend --replicas=0
    
  3. 转到 eShop Web 应用并尝试查看产品。 发生延迟,直到最后出现错误消息“加载产品时出现问题。请稍后重试。”

  4. 重启产品服务 Pod:

    kubectl scale deployment productsbackend --replicas=1
    
  5. 应用现在应显示产品。

Linkerd 采用的复原方法与基于代码的复原所采用的方法不同。 Linkerd 连续多次以透明方式重试该操作。 支持此行为无需更改应用。

其他信息

有关 Linkerd 配置的详细信息,请参阅以下资源: