练习 - 实现基于基础结构的复原

已完成

在上一单元中,你通过使用 Polly 添加故障处理代码来实现复原。 但这项更改仅适用于你已更改的服务。 更新包含多种服务的大型应用并非易事。

此单元重点介绍如何替换基于代码的复原。 这里改为采用跨整个应用的基于基础结构的复原方法。 你将:

  • 重新部署没有任何复原能力的应用。
  • 在 AKS 群集中部署 Linkerd。
  • 配置应用以使用 Linkerd 进行复原。
  • 使用 Linkerd 探索应用行为。

备注

如果 Cloud Shell 会话由于不活动而断开连接,请重新连接并运行以下命令以返回到此目录并打开 Cloud Shell 编辑器:

cd ~/clouddrive/aspnet-learn/src/ && \
  code .

重新部署应用

在应用 Linkerd 之前,先将应用还原为添加基于代码的复原之前的状态。 若要还原,请使用以下命令重新部署未修改的 webshoppingagg 映像:

./deploy/k8s/deploy-application.sh --registry eshopdev --charts webshoppingagg

验证服务的可用性

  1. 执行以下命令:

    cat ~/clouddrive/aspnet-learn/deployment-urls.txt
    
  2. 选择命令行界面中的 General application status 链接,查看 WebStatus 运行状况检查仪表板。

  3. 如果所有服务都正常运行,请继续阅读下一部分。

验证失败行为

可按照与之前相同的步骤,验证应用是否像预期那样再次失败:

  1. 选择 .NET FOUNDATION PIN。

  2. 选择购物车图标。

  3. 选择 CHECKOUT。

  4. 输入折扣代码 FAIL 2 DISC-10 并选择 APPLY。

    此时将显示消息 CONFIG: 2 failure(s) configured for code "DISC-10"!!。

  5. 将折扣代码更改为 DISC-10 并选择 APPLY 两次。

  6. 验证在每次选择 APPLY 后是否立即收到 ERROR: 500 - Internal Server Error! 消息。

验证 AKS 群集

安装脚本已安装 Linkerd CLI。 运行以下命令,确认是否已满足 Linkerd 先决条件:

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 部署到 AKS 群集

运行以下命令:

linkerd install | kubectl apply -f -

在上述命令中:

  • linkerd install 生成一个 Kubernetes 清单,其中具有必要的控制平面资源。
  • 生成的清单通过管道传输到 kubectl apply,后者在 AKS 群集中安装这些控制平面资源。

输出的第一行显示控件平面安装在其自己的 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,你需要:

  • 修改聚合器和优惠券部署,以便 Linkerd 在 Pod 中创建其代理容器。
  • 配置相关 Nginx 入口的标头。
  • 将服务配置文件对象添加到群集,以便在优惠券服务的路由上配置重试操作。

修改 webshoppingaggcoupon 部署

必须将优惠券和聚合器服务配置为使用 Linkerd 代理容器。

  1. 将突出显示的注释添加到 coupon 图表的 deployment.yaml 文件中 (deploy/k8s/helm-simple/coupon/templates/deployment.yaml)。 保存所做更改。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: coupon
      labels:
        app: eshop
        service: coupon
    spec:
      replicas: 1
      selector:
        matchLabels:
          service: coupon
      template:
        metadata:
          labels:
            app: eshop
            service: coupon
          annotations:
            linkerd.io/inject: enabled
        spec:
          # remainder of file omitted for brevity
    

    linkerd.io/inject: enabled 注释指示 Linkerd 在创建 Pod 时添加 linkerd-proxy 容器。

    重要

    在 YAML 清单中保持正确的缩进非常重要。

  2. 同样地,将突出显示的注释添加到 webshoppingagg 图表的 deployment.yaml 文件中 (deploy/k8s/helm-simple/webshoppingagg/templates/deployment.yaml)。 保存所做更改。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: webshoppingagg
      labels:
        app: eshop
        service: webshoppingagg
    spec:
      replicas: 1
      selector:
        matchLabels:
          service: webshoppingagg
      template:
        metadata:
          labels:
            app: eshop
            service: webshoppingagg
          annotations:
            linkerd.io/inject: enabled        
        spec:
          # remainder of file omitted for brevity
    

应用优惠券服务的 Linkerd 服务配置文件

优惠券服务的服务配置文件清单在 deploy/k8s/linkerd/coupon-serviceprofile.yaml 文件中提供:

apiVersion: linkerd.io/v1alpha2
kind: ServiceProfile
metadata:
  creationTimestamp: null
  name: coupon-api.default.svc.cluster.local
  namespace: default
spec:
  routes:
  - condition:
      method: GET
      pathRegex: /coupon-api/api/v1/coupon/{code}
    name: GET /v1/coupon/code
    isRetryable: true
  retryBudget:
    retryRatio: 0.2
    minRetriesPerSecond: 10
    ttl: 10s

上述清单配置为:

  • 任何与 /coupon-api/api/v1/coupon/{code} 模式匹配的幂等 HTTP GET 路由都可以重试。
  • 重试增加的额外请求负载不得超过 20%;此外,每秒还有 10 次重试“不增加负载”。

运行以下命令,在 AKS 群集中使用服务配置文件:

kubectl apply -f ./deploy/k8s/linkerd/coupon-serviceprofile.yaml

随即显示以下输出:

serviceprofile.linkerd.io/coupon-api.default.svc.cluster.local created

配置 Nginx 的标头

Linkerd 需要 Nginx 提供请求标头中的其他信息,从而将请求传递给正确的服务。 因此,必须将注释添加到入口路由。

将突出显示的行添加到 deploy/k8s/helm-simple/apigateway/templates/ingress-gateway.yaml 文件中。 保存所做更改。

# beginning of file omitted for brevity
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-gw-cp
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /webshoppingagg/$2
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      proxy_set_header l5d-dst-override $service_name.$namespace.svc.cluster.local:$service_port;
      grpc_set_header l5d-dst-override $service_name.$namespace.svc.cluster.local:$service_port;    
  labels:
    app: eshop
spec:
  # remainder of file omitted for brevity

上述更改指示 Nginx 添加一个名为 l5d-dst-override 的 Linkerd 目标替代请求标头。 标头的值将动态设置为目标服务的 DNS 名称和端口。 proxy_set_headergrpc_set_header 指令分别用于 HTTP 和 gRPC 请求。

备注

eShopOnContainers 应用使用 gRPC 进行服务到服务通信。 更具体地说,这种同步通信从 HTTP 升级得来,在聚合器与服务之间发生。 另一方面,外部可访问的终结点是 RESTful 终结点。 gRPC 是基于 RPC 的协议,其特点是高性能和低带宽使用率。 这些特征使得 gRPC 成为内部服务通信的最佳候选项。

部署已更新的 Helm 图表

运行以下命令,重新部署已更新的图表:

./deploy/k8s/deploy-application.sh --registry eshopdev --charts apigateway,coupon,webshoppingagg

每个更新的 Pod 现在都有两个容器 (0/2)。 其中一个是服务容器,另一个是 linkerd-proxy

具有两个容器的已更新 Pod

再次测试应用

验证服务的可用性

  1. 执行以下命令:

    cat ~/clouddrive/aspnet-learn/deployment-urls.txt
    
  2. 选择命令行界面中的 General application status 链接,查看 WebStatus 运行状况检查仪表板。

  3. 如果所有服务都正常运行,请继续阅读下一部分。

测试 Linkerd 复原

重新部署的容器正常运行后,请按照以下步骤使用 Linkerd 测试应用的行为:

  1. 将一件商品放入购物袋,开始结帐过程。

  2. 选择 .NET FOUNDATION PIN。

  3. 选择购物车图标。

  4. 选择 CHECKOUT。

  5. 输入折扣代码 FAIL 5 DISC-10 并选择 APPLY。

  6. 将代码更改为 DISC-10 并选择 APPLY。

    会立即收到正确的响应。 此时将显示一条错误消息,指示此优惠券已兑换。

  7. 检查日志跟踪中是否有以下消息:

    使用 Linkerd 进行的日志跟踪

Linkerd 采用的复原方法与 Polly 所采用的方法不同。 Linkerd 连续多次以透明方式重试该操作。 用户未注意到任何故障。

其他信息

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