练习 - 使用 Kubernetes 实现基础结构复原能力
在上一单元中,你通过使用 .NET 本机复原扩展添加故障处理代码实现了复原。 然而,此更改仅适用于你已更改的服务。 更新包含多种服务的大型应用并非易事。
本单元没有使用基于代码的复原,而是使用了一种称为基于基础结构的复原的方法,此方法涵盖了整个应用。 你将:
- 将没有任何复原能力的应用重新部署到 Kubernetes。
- 在 Kubernetes 群集中部署 Linkerd。
- 配置应用以使用 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 部署,并在代码空间中运行良好。
运行以下命令以安装 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 清单。
需要编辑这些文件才能使用推送到 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。 要为这两种服务实现 Linkerd,你需要:
- 修改 eShop 部署,以便 Linkerd 在 Pod 中创建其代理容器。
- 要在优惠券服务的路由上配置重试操作,请将服务配置文件对象添加到群集。
修改 eShop 部署
必须将服务配置为使用 Linkerd 代理容器。
将
linkerd.io/inject: enabled
注释添加到 backend-deploy.yml 文件的模板元数据下。template: metadata: annotations: linkerd.io/inject: enabled labels:
将
linkerd.io/inject: enabled
注释添加到同一位置的 frontend-deploy.yml 文件。更新 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 的仪表板中查看应用的状态。
在终端中运行以下命令以安装扩展:
linkerd viz install | kubectl apply -f -
使用以下命令查看仪表板:
linkerd viz dashboard
转到“端口”选项卡,可看到一个新端口,该端口已通过正在运行的“linkerd viz 仪表板”进程进行转发。 选择“在浏览器中打开”以打开仪表板。
在 Linkerd 仪表板中,选择“命名空间”。
在“HTTP 指标”下,选择“默认值”。
测试 Linkerd 复原
重新部署的容器正常运行后,请按照以下步骤使用 Linkerd 测试应用的行为:
使用以下命令检查正在运行的 Pod 的状态:
kubectl get pods --all-namespaces
停止所有产品和服务 Pod:
kubectl scale deployment productsbackend --replicas=0
转到 eShop Web 应用并尝试查看产品。 发生延迟,直到最后出现错误消息“加载产品时出现问题。请稍后重试。”,
重启产品服务 Pod:
kubectl scale deployment productsbackend --replicas=1
应用现在应显示产品。
Linkerd 采用的复原方法与基于代码的复原所采用的方法不同。 Linkerd 连续多次以透明方式重试该操作。 支持此行为无需更改应用。
其他信息
有关 Linkerd 配置的详细信息,请参阅以下资源: