亚马逊AWS官方博客

云上韧性系统实践之使用 Litmus 进行 EKS 容器平台的故障注入实验

混沌工程是在分布式系统上进行实验的学科,目的是建立对系统抵御生产环境中失控条件的能力以及信心,通过故障演练沉淀通用的故障模式,以可控成本在合适的环境中重放,以持续性的演练和回归方式运营来暴露问题,不断推动系统、工具、流程、人员能力的完善。本次文就是通过混沌工程的方法论,帮助客户发现系统中的潜在风险,提高系统韧性。

实验对象,客户在亚马逊云科技中国区部署的 Elastic Kubernetes Service(EKS)容器平台及基础设施平台。

混沌工程实施概述

完整的混沌工程实验是一个持续性迭代的闭环体系,从初步的实验需求和实验对象出发,通过实验可行性评估,确定实验范围,设计合适的观测指标、实验场景和环境,选择合适的实验工具和平台框架;建立实验计划,和实验对象的干系人充分沟通,进而联合执行实验过程,并搜集预先设计好的实验指标;待实验完成后,清理和恢复实验环境,对实验结果进行分析,追踪根源并解决问题,并将以上实验场景自动化,并入流水线,定期执行;之后,便可开始增加新的实验范围,持续迭代和有序改进。

韧性(Resilience):适应不断变化的环境,准备、承受并迅速从中断中恢复的能力。随着 K8s 的普及,K8s 开发人员和 SRE 越来越关注基于 K8s 部署的应用的韧性,混沌工程可以帮助我们实现 K8s 应用的韧性。上图展示了 K8s 应用实现韧性的依赖栈,是我们在对 K8s 平台进行混沌工程实验时的要考虑的环节。

篇幅原因,混沌工程完整过程的描述,不在本文说明,本文重点介绍针对容器环境进行混沌实验的工具 Litmus,混沌工程的说明请参考:在亚马逊云平台进行混沌工程的系列文章

Litmus 是一种开源混沌工程框架,主要用于在 Kubernetes 环境中进行混沌测试。Litmus 项目由 MayaData 公司推出,支持用户运行测试套件、捕获日志、生成报告并执行混沌测试。由于亚马逊云科技的 Fault Injection Simulator(FIS) 没有在中国区发布,因此针对中国区的客户需要使用第三方的软件(Litmus 或 Chaostoolkit)来实施混沌工程。在海外 region,开源混沌工具也可以成为 FIS 功能的补充。

Litmus 介绍及架构说明

Litmus 的组件可以划分为 Portal(Control Plane)和 Agent(Execution Plane)两部分:

Portal 是一组 Litmus 组件,作为跨云管理混沌实验的控制平面(WebUI),用于协调和观察 Agent 上的混沌实验工作流。

Agent 也是一组 Litmus 组件,包括运行在 K8s 集群上的混沌实验工作流。

使用 Portal,用户可以在 Agent 上创建和调度新的混沌实验工作流,并从 Portal 上观察结果。用户还可以将更多的集群连接到 Portal,并将 Portal 作为跨云混沌工程管理的单个门户。

Portal/Control Plane 组件

Litmus WebUI

Litmus WebUI 提供了 Web 用户界面,用户可以在这里轻松构建和观察混沌实验工作流。Litmus WebUI 也充当了跨云混沌实验控制平面。

Litmus Server

Litmus Server 作为中间件,用于处理来自用户界面的 API 请求,并将配置和处理结果详情信息存储到数据库中。它还充当各个请求之间的通信接口,并将工作流程调度到 Agent

Litmus DB

Litmus DB 作为混沌实验工作流及其测试结果详情的存储系统,目前采用 Litmus 框架内嵌的 MongoDB。

混沌工作流 (Chaos Scenario)

混沌工作流是由一组混沌实验组成,可在 Litmus 控制台对远程 K8s 集群上调度混沌工作流。

Agent/Execution Plane组件

Chaos Operator

使用 Operator SDK 框架构建,管理着混沌实验的生命周期,Chaos Operator 监视 ChaosEngine 并执行 CR 中提到的混沌实验。Chaos Operator 是命名空间范围的,默认情况下运行在 litmus 命名空间中。实验完成后,Chaos Operator 会调用 chaos-exporter 将混沌实验的指标导出到 Prometheus 数据库中。

Chaos CRD (CustomResourceDefinition

Litmus 安装过程中会生成以下几个 CRD,包括 Chaos CRD:ChaosEngine,ChaosExperiment 和 ChaosResult。使用上述 CRD 构建、运行和管理混沌实验。ChaosEngine CRD 将目标应用程序与 ChaosExperiment 自定义资源绑定在一起。运行时,结果将存储在 ChaosResult 自定义资源中。

Chaos Experiment

Chaos Experiment(混沌实验)是 LitmusChaos 体系结构中的基本单元,用户可以从 Chaos Hub 上选择现场的混沌实验或者自己创建新的混沌实验来构建所需的混沌实验工作流。简单来说就是定义一个该测试支持哪些操作、能传入哪些参数、可对哪些类型的对象进行测试等 CRD 资源清单,通常分为三种类别:通用的测试(比如内存,磁盘,CPU 等操作),应用的测试(比如针对 Nginx 来进行测试),平台测试(针对于某个云平台的测试:Amazon,Azure,GCP)。

Chaos Hub

保存了现有的 Chaos Experiment,并以 YAML 规范托管在公共实验库 Chaos Hub 上(https://hub.litmuschaos.io)。

Chaos Engine

ChaosEngine 将 Chaos Experiment 实现的功能具体实施到命名空间中的应用中。该 CR 由 Chaos Operator 监控。

Chaos Scheduler

混沌调度器支持对混沌实验进行精细化调度。

Chaos Probes

Chaos Probes 是可插拔的指标探针,可以在任意混沌实验的 ChaosEngine 中定义,实验 Pod 会根据其定义的模式来执行相应的检测,并将其是否成功作为决定实验结果的必要条件。

Chaos Results

ChaosResult 保存了混沌实验的结果,它会在实验运行时创建或更新,包含了各种信息,包括 Chaos Engine 的配置、实验状态等。chaos-exporter 将会读取结果并导出到 Prometheus 数据库中。

Chaos Exporter 

可以选择将指标导出到 Prometheus 数据库。Chaos Exporter 实现了 Prometheus metrics endpoint。包括:

  • Chaos Metrics Exporter

这是 Prometheus 指标导出器。诸如数量、实验类型及其结果之类的混沌实验指标都将导出到 Prometheus 中。然后就可以把这些指标和目标应用的指标组合在一起绘制,以显示混沌对应用服务或性能的影响。

  • Chaos Events Exporter

Litmus 会为每次发生的混沌注入动作生成一个混沌事件。这些混沌事件存储在 etcd 中,然后导出到事件接收器,以便对受混沌注入影响的服务进行关联或调试。

Subscriber

Subscriber 用来和 Litmus Server 交互,获取混沌实验工作流的详细结果,并发送回 Agent 端。

Litmus 对 Amazon EKS 的支持说明

Amazon EKS 可在 Amazon Elastic Compute Cloud(Amazon EC2)和 Amazon Fargate 上运行 Kubernetes 应用程序。对应的 Litmus 可以支持上述两种部署方式的故障注入,但对 Fargate 上运行的 EKS,需要通过部署 agent 的方式进行,且不支持 node 级别的故障注入(关闭或重启),但可以实现 K8s 层面的故障注入如 node drain 以及 pod 级别的故障注入。

安装说明

本文的 EKS(1.24) 环境部署在 EC2 上。安装版本 Litmus 2.14.0 版本。

先决条件

跳板机安装:

aws cli V2(https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html

eksctl(https://docs.aws.amazon.com/eks/latest/userguide/eksctl.html

kubectl(https://docs.aws.amazon.com/eks/latest/userguide/install-kubectl.html

EKS 集群的安装

生成 EKS 模板

eksctl create cluster --name=chaos-playground --region=cn-north-1 --dry-run > chaos-playground.yaml

修改 chaos-playground.yaml 其中的实例类型,修改为 t3.large

instanceSelector: {}
instanceType: t3.large

创建 EKS 集群

eksctl create cluster -f chaos-playground.yaml
aws eks update-kubeconfig --name chaos-playground --region cn-north-1
kubectl config current-context

需要为 service accounts 创建 Amazon EBS CSI 驱动程序的 IAM role

参考:https://docs.amazonaws.cn/en_us/eks/latest/userguide/csi-iam-role.html

注意中国区 endpiont 的不同,请进行相关的替换。

region-code.amazonaws.com.cn

安装 Amazon EBS CSI 驱动程序

Litmus 控制平面会通过 StatefulSet 创建 MongoDB 来存储元数据,需要安装Amazon EBS CSI 驱动。

1、为服务账户创建 Amazon EBS CSI 驱动程序 IAM 角色

https://docs.aws.amazon.com/zh_cn/eks/latest/userguide/csi-iam-role.html

第二个集群 annotate 一下即可。

kubectl annotate serviceaccount ebs-csi-controller-sa \

-n kube-system eks.amazonaws.com.cn/role-arn=$ROLE_ARN

2、Amazon EBS CSI 驱动程序作为 Amazon EKS 附加组件管理,可通过控制台安装。

https://docs.aws.amazon.com/zh_cn/eks/latest/userguide/managing-ebs-csi.html

检查

kubectl -n kube-system describe sa ebs-csi-controller-sa

其他组件也可一并安装 CoreDNS,Amazon VPC CNI,kube-proxy,详见:https://docs.amazonaws.cn/en_us/eks/latest/userguide/eks-networking-add-ons.html

安装 Metric server

wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
	
查看镜像地址
grep -rn image components.yaml

设置镜像地址为国内
sed -i "s/382721505900.dkr.ecr.cn-north-1.amazonaws.com.cn/metrics-server:latest#g" components.yaml

grep -rn image components.yaml

安装

kubectl apply -f components.yaml

验证

kubectl get pod -n kube-system | grep metrics

安装 Autoscaler

参考 gcr-eks-quickstart/Demo04-使用 ClusterAutoScaler 进行自动伸缩

——————–

为集群开启 IRSA

eksctl utils associate-iam-oidc-provider \
    --cluster chaos-playground \
    --approve

验证

aws eks describe-cluster --name chaos-playground --region cn-north-1 --query "cluster.identity.oidc.issuer" --output text
cat <<EoF > k8s-asg-policy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "autoscaling:DescribeAutoScalingGroups",
                "autoscaling:DescribeAutoScalingInstances",
                "autoscaling:DescribeLaunchConfigurations",
                "autoscaling:DescribeTags",
                "autoscaling:SetDesiredCapacity",
                "autoscaling:TerminateInstanceInAutoScalingGroup",
                "ec2:DescribeLaunchTemplateVersions"
            ],
            "Resource": "*",
            "Effect": "Allow"
        }
    ]
}
EoF

aws iam create-policy   \
  --policy-name k8s-asg-policy \
  --policy-document file://k8s-asg-policy.json
  
  
eksctl create iamserviceaccount \
    --name cluster-autoscaler \
    --namespace kube-system \
    --cluster chaos-playground \
    --attach-policy-arn "arn:aws-cn:iam::382721505900:policy/k8s-asg-policy" \
    --approve \
    --override-existing-serviceaccounts

kubectl -n kube-system describe sa cluster-autoscaler
  
Name:                cluster-autoscaler
Namespace:           kube-system
Labels:              app.kubernetes.io/managed-by=eksctl
Annotations:         eks.amazonaws.com/role-arn: arn:aws-cn:iam::382721505900:role/eksctl-chaos-playground-addon-iamserviceacco-Role1-MVDXC8CF06AT
Image pull secrets:  <none>
Mountable secrets:   cluster-autoscaler-token-qj2tm
Tokens:              cluster-autoscaler-token-qj2tm
Events:              <none>

Litmus 平台的安装

在生产环境部署混沌工程工具的时候,要考虑工具部署环境和生产环境隔离的问题,有两种做法,可以根据实际情况进行选择。

1、将 Litmus 环境和生产环境部署在一个 EKS 集群中,将 Litmus 环境固定在某一两个 node 上,从而实现隔离;

2、为 Litmus 控制平面部署专有的 EKS 集群,在需要混沌注入的执行平面集群中,安装 Litmus Delegate(即 Litmus 的执行环境),从 Litmus 的控制平面中进行故障注入的调度。

当前是基于 Litmus 2.14.0 版本进行安装和使用,目前最新的是 3.0-beta,不同版本的使用上会有一些区别,还请以官方说明为准。

Control Plane 的安装

创建命名空间:

kubectl create ns litmus

安装控制平面:

kubectl apply -f https://litmuschaos.github.io/litmus/2.14.0/litmus-2.14.0.yaml

查看 pod 状态:

kubectl get pod -n litmus

注意:Litmus 需要 MongoDB,如果 EBS CSI driver 没正确安装,则 pod ‘mongo-0’ 会处于 pending 状态。

映射公网访问端口:

kubectl patch svc litmusportal-frontend-service -p '{"spec": {"type": "LoadBalancer"}}' -n litmus

获得 litmusportal-frontend-service 的地址及端口:

kubectl get -n litmus svc litmusportal-frontend-service -o wide

根据上一步得到的地址,访问 Litums 控制台,默认用户名密码:admin/litmus, 需注意开放 EKS 集群安全组的对应端口。

http://a36719e1483244c6ea7ff1e990fc4da1-402034326.cn-north-1.elb.amazonaws.com.cn:9091

ChaosHUB 提供各种编排好的场景,如默认地址不能访问,可以手工修改如下 Chaos-chats 的地址:

https://gitee.com/radiumgu/chaos-charts

Delegate(或称 Agent)安装

1、Delegate 简介

Litmus 包含两种类型的 Delegate:

  • Self Delegate
  • External Delegate

默认情况下,作为 Litmus 安装的一部分,控制平面所在的集群被自动注册为 Self Cluster,可以自动的在 Self Cluster 中执行混沌实验,并且查看执行结果。

用户可以将多个外部 Kubernetes Delegate 连接到控制平面。连接后,用户可以从控制平面,统一管理和观测内部集群和外部集群的混沌实验。EKS on fargate 就需要用这种方式实现。

2、安装 litmusctl

下载地址及安装说明: https://docs.litmuschaos.io/docs/litmusctl/installation/

3、配置 Litmus 代理与控制平面的连接:

litmusctl config set-account(交互),或:

litmusctl config set-account —endpoint “http://aae739d0386844409a477496ebab3d6f-1240559370.cn-northwest-1.elb.amazonaws.com.cn:9091" —password "litmus" —username "admin" --non-interactive

Delegate 运行一段时间后,如果与控制平面端口链接,运行上述命令重新连接即可。

4、安装 Litmus Delegate

litmusctl connect chaos-delegate —name="new-chaos-delegate" —project-id="901adc98-2fc1-44df-8f72-b6395629d22c" —non-interactive

project-id 可在 litmus 控制台查看,或使用如下命令查看:

litmusctl get projects

安装完成后,在 ChaosCenter 的 Chaos Delegates 界面会看到除 Self-Agent 外的第二个 Delegate。

此时在执行平面集群执行kubectl get pods -n litmus,检查 litmus 相关的 pods。

需要注意:

安装 Litmus External Delegate,需要将 Litmus 控制平面所在集群的安全组进行配置(开放 3xxxx 的随机端口),端口获取方法如下图,确保两集群可以互相访问。

和控制平面通讯的 pod 是“subscriber”,可查看 subscriber pod 的日志,找到相应的端口,加入控制平面集群的安全组。

kubectl logs po/subscriber-5cbcb4df94-khvt4 -n litmus

混沌演练

进行混沌演练,建议分两阶段,首先在企业环境内完成单元的故障演练,之后编排出符合实际环境的混沌工作流,Litmus 集成了 Argo Workflows 实现故障场景的编排。

目前 Litmus 的 ChaosHub 中,预制了 58 个常用的场景,可基本覆盖亚马逊云平台环境下容器、主机平台中的混沌测试场景。分为 Pod 级别、Node 级别、EC2 级别,不同级别内分为状态、资源、网络三类,详见附录一。

测试过程简述

在 Chaos Scenarios 中 Schedule a new Chaos Scenario

选择目标集群:

开始创建混沌场景,选择使用 Chaos Hubs 创建:

给场景命名:

选择添加:

选择 pod-cpu-hog  pod-memory-hog:

点击 edit Sequence,可编辑各种故障注入的顺序。还可编辑故障注入的对象和时长等参数。

选择立刻执行,即可在 Chaos Scenarios 看到已经生成的任务状态。点击可查看详情。同时,可以观察 pod 的 cpu 和内存状态。

需要注意:

对于 EKS 1.24 及以上的版本,由于其默认的容器已经被替换为了 Containerd,所以在创建 pod-cpu-hog / pod-memory-hog 等 Scenario 的时候,容器仍然是配置的 Docker,需要按照下图修改为 Containerd 的相关配置。

node restart

需要 ssh key,参考下文中 Prerequisites:https://litmuschaos.github.io/litmus/experiments/categories/nodes/node-restart/

针对亚马逊云平台基础设施的故障注入

ec2-terminate

先决条件:需要配置操作权限

  • 配置方法 1,写入 ak/sk:

生成 eks-secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: cloud-secret
type: Opaque
stringData:
  cloud_config.yml: |-
    # Add the cloud AWS credentials respectively
    [default]
    aws_access_key_id = XXXXXXXXXXXXXXXXXXX
    aws_secret_access_key = XXXXXXXXXXXXXXX

k apply -f eks-secret.yaml

  • 配置方法 2,给 Kubernetes Service Account 赋予对应的 IAM Role,配置步骤参考:

配置 Kubernetes 服务账户以代入 IAM 角色

使用IAM Role for Service Account(IRSA)

注:部署后,请用 kubectl describe sa $sa-name -n kube-system 检查,出现过结果为“eks.amazonaws.com”,没有 cn 的情况,应为:
Annotations:         eks.amazonaws.com.cn/role-arn: arn:aws-cn:iam::382..

如出现可用 kubectl edit sa  chao-ec2-sa -n kube-system,编辑创建被测的 nginx 应用,参考如下链接中,部署一个Nginx测试EKS集群基本功能

探针(Probe)的使用

在进行混沌实验的过程中,需要定义一个稳态指标,来评估系统的健康状态并且在实施混沌过程当中进行监控和处理。另外,我们也需要验证系统的故障恢复机制,即通过通过健康检查等机制来验证系统是否具有这样的能力,这些操作都可以通过探针来实现。

探针可在 Litmus 的 Chaos Scenarios 中根据需要插入。

Litmus 目前支持四种类型的探针,这些探针可以单独使用或组合使用以实现所需的检查:

  1. httpProbe:查询 URI 的状态;
  2. cmdProbe:执行 shell 命令来实现健康检查功能;
  3. k8sProbe:对本机和自定义 Kubernetes 资源执行 CRUD 操作;
  4. promProbe:执行 promql 查询并匹配 prometheus 指标。

探针可以在实验执行前、实验执行后、实验执行中根据需要插入。并可设置 probeTimeout、retry、interval 等参数。

查看实验结果

实验结果可以在控制台中查看,也可通过 kubectl 查看。

kubectl get chaosresults -n litmus

NAME AGE
ec2-terminate-by-id-ugp4vfl8-ec2-terminate-by-id 6h53m
node-cpu-hog-4oi9r6kq-node-cpu-hog 7h22m
node-cpu-hog-e53227cx-node-cpu-hog 7h4m
node-cpu-hog-med9n8zz-node-cpu-hog 7h14m
pod-delete-fyeh9nlk-pod-delete 8h

kubectl describe chaosresults node-cpu-hog-med9n8zz-node-cpu-hog -n litmus

查看混沌实验事件

kubectl get events -n litmus --sort-by='{.lastTimestamp}'

基于 GitOps 的事件驱动

Litmus 中的 GitOps 功能能够为混沌实验配置单一的事实来源,对 git 或控制台中的实验所做的任何更改都将同步。这允许直接从 git 创建和执行混沌场景,从而在   CI/CD Pipeline 中实现混沌工程的自动化。

除了同步功能外,Litmus 中的 GitOps 还提供了一种基于事件驱动混沌注入的方法,其中目标资源可以配置为在资源部署发生任何变化时自动触发混沌场景。目前混沌注入支持的事件有资源镜像变更、配置变更、副本变更等。事件驱动的混沌注入允许 Litmus 与自动部署应用程序的 GitOps 流程集成。

以下简单介绍基于事件驱动混沌注入的流程:

GitOps 配置:

在 GitHub/GitLab 中创建一个 Repo,以便 Litmus 将所有的 Scenario 及时同步上去。

打开 Litmus 控制台,进入 Setting→GitOps,将上述创建好的 GitHub Repo 地址填入,并填入 GitHub 的 Access Token,Token 创建的流程请参考这里,点击 Connect 后,等待“Successfully updated GitOps!”消息弹出,即配置成功。

此时查看 GitHub Repo,可以看到 Litmus 中的 Scenario 的元信息已经上传,并且后续在创建和修改 Scenario 后,都会被即时上传到此 Repo。找到需要被自动化执行的 Scenario,打开其 yaml 文件,记录 workflow_id。

进入执行平面集群,执行下述 l 两个指令,即监控哪些 EKS 集群的修改,以自动触发混沌实验场景的执行。例如 target-application 替换为被监控的 deployment,${workflow_id}替换为上述被记录的 workflow_id。

kubectl annotate deploy/target-application litmuschaos.io/workflow=${workflow_id}
kubectl annotate deploy/target-application litmuschaos.io/gitops=true

修改执行平面集群上述 deployment 的配置,比如 replica 数量增减,即可触发指定混沌实验场景的执行。

局限性

1、Litmus 更新较快,截止发稿时已经发布了 3.0 beta 版,本文基于 2.14.0 版本编写,3.0 版本的部分使用方式可能会有变化;

2、Litmus在版本发布过程中,部分官方文档更新有误,本文未能全部验证,需要在使用时注意;

3、本文更多的介绍了 Litmus 工具的安装和故障注入的实验,并未在实际的业务环境中运行,没有进行稳态的定义、验证和回滚,在真实的混沌工程实验中,需完成上述步骤。

参考文档

litmus#getting-started

Litmus Docs

Litmus 和 Amazon Web Service 的权限集成

GCR EKS QuickStart 2022

安装过程中需要的镜像库在中国区的复制

Litums 源:

https://github.com/litmuschaos

中国区镜像:

https://gitee.com/radiumgu/litmus

https://gitee.com/radiumgu/litmusctl

https://gitee.com/radiumgu/chaos-charts

Docker-Hub 加速镜像:

gcr.io 加速镜像:

quay.io 加速镜像:

附录 Litmus 详细使用说明

Pod Chaos

Node Chaos

Cloud Infrastructure

本篇作者

谷雷

亚马逊云科技资深解决方案架构师,专注于迁移上云、云上业务连续性的实现等技术方向。

陈超

亚马逊云科技资深解决方案架构师,主要负责迁移相关的技术支持工作,同时致力于亚马逊云服务在国内的应用及推广。加入亚马逊云科技之前,曾在阿里巴巴工作 8 年,历任研发工程师、云计算解决方案架构师等,熟悉传统企业 IT、互联网架构,在企业应用架构方面有多年实践经验。