1. 为什么“能用”和“好用”之间,隔着一套完整的测试
刚接触原生Kubernetes的时候,很多人跟我一样,以为把集群用二进制或者Kubeadm装起来、kubectl get nodes看到Ready状态,就算大功告成了。说实话,这个想法特别危险。Kubernetes是一个由二十多个独立组件协同工作的分布式系统,控制面有etcd、kube-apiserver、kube-controller-manager、kube-scheduler,数据面有kubelet、kube-proxy、容器运行时,任何一环存在配置隐患或者性能瓶颈,在节点少、负载低的时候都看不出来,等到正式业务跑上来才暴露,那时候排查成本就非常高了。
所以“基本测试使用”这件事,本质上是做一次集群的“验收”和“体检”。它跟跑几个Pod看看能不能起来是两个维度的事情。基本测试至少应该覆盖:资源生命周期管理能不能正常工作、网络能不能连通且策略是否生效、存储能不能挂载、配置能不被正确下发、调度器能否按约束分配Pod、节点出现故障时能不能自愈、控制面组件有没有隐性问题。每一个看起来都是Kubernetes的“标准能力”,但“标准能力”和“实际可用”之间隔着很多真实环境的坑,比如网络插件的CNI配置和Pod网段有没有冲突、kube-proxy的转发模式跟节点内核版本是否匹配、ingress-controller的部署方式是不是符合你的网络架构。
这一篇我写的,是我个人在部署完一套原生Kubernetes集群之后,做基础功能测试的完整思路和实际操作。用到的环境是标准的单主多节点架构,容器运行时用的containerd,网络插件选了Calico,Ingress用的Nginx Ingress Controller。这套组合属于目前社区里最主流、资料最多、坑也相对少的搭配。适合刚完成集群部署、准备让开发团队接入的运维同学,也适合Kubernetes新手想自己验证一套集群到底行不行。
我尽量把每一步操作背后的思路也说清楚,而不是只丢一堆命令让你照着敲。因为你一旦理解了“为什么这么做”,以后在生产环境里遇到同类问题,自己就能判断大概率的故障点在哪个环节。而且每一类测试我都会附上我认为有价值的排查技巧和验收标准,方便你直接参考。
2. 测试前的环境准备和工具选型
2.1 先确认集群本身是健康的
动手测功能之前,先做一次整体体检。这一步很多人跳过,直接开始创建资源,结果后面发现是集群本身的系统组件有问题,导致测试结果根本不具备参考价值。我会按下面这套顺序来看:
首先当然是节点状态。kubectl get nodes -o wide看每个节点的STATUS、角色、内部IP、Kubelet版本。正常情况所有节点都应该是Ready,如果有的节点显示NotReady,先不要往后面走,去解决节点问题。常见原因是kubelet没有正常启动、容器运行时配置出错、或者网络插件没有部署成功导致节点心跳上报失败。
然后是控制面组件状态。kubectl get componentstatuses虽然在实际使用中被诟病不够准确,但可以快速扫一眼。更可靠的方式是直接看kube-system命名空间下的Pod状态:
kubectl get pods -n kube-system -o wide正常情况下,etcd、kube-apiserver、kube-controller-manager、kube-scheduler相关的Pod都应该是Running状态,核心容器已经Ready。如果你看到某些Pod处于CrashLoopBackOff,别急着测试功能,先排查。比如etcd容器一直重启,大部分原因是证书配置不对或者etcd数据目录权限问题。
除了集群组件本身,我还会检查一遍网络插件状态。Calico部署完成之后,它会有一些名为calico-kube-controllers和calico-node的Pod在kube-system下运行。kubectl get pods -n kube-system | grep calico应该能看到Running状态。然后再看看kubectl get daemonset -n kube-system,calico-node是在每个节点上都应该有一个副本的DaemonSet。
提示:测试前明确记录集群当前的版本信息和配置基线,比如Kubernetes版本、containerd版本、Calico版本、内核版本、Pod网段、Service网段。这些信息在后续出问题排查的时候非常关键,而且我建议保存到文档里,跟测试报告放一起。
2.2 准备一套顺手的测试工具
基础测试不需要装很复杂的东西,但有些工具是必须提前准备的。我自己平时工作目录里常备这些:
- kubectl:这是必须的,控制集群的唯一命令行入口。建议本机版本和集群版本不要差太多。
- yq或jq:解析YAML和JSON输出的利器。排查Pod状态的时候,
kubectl get pod xxx -o json | jq .能很快定位问题。 - curl:测试Service和Ingress访问的必备工具。
- dig或nslookup:验证CoreDNS解析是否正常。
- openssl:偶尔需要检查证书相关的问题。
- stress或sysbench(可选):如果要做节点资源紧张的模拟测试,这两个工具能帮你制造CPU和内存压力。
- ipvsadm或iptables(按需):排查kube-proxy转发链路的辅助工具。
另外建议准备一个Git仓库管理你的测试YAML文件。这样每次做集群测试,拉下来的就是一套标准化的流程,不用每次临时写,而且可以记录下每次测试用的配置版本。
2.3 理解你测试的对象是什么
这里说的“原生Kubernetes”,指的是没有用Rancher、OpenShift这类发行版封装,直接由Kubeadm或二进制部署的社区版集群。它的特点是组件齐全、API标准、没有额外的抽象层。所以测试时踩到的坑,基本都能在社区找到对应Issue,排查路径相对清晰。
好处是你能完整看到Kubernetes各组件是怎么协同工作的,出了问题定位链条短;坏处是很多东西要自己配置和维护,不像发行版那样有预设的管理面。这意味着“基本测试使用”在你的运维体系里要承担更重的责任,因为你没有上层平台帮你兜底,一切以原生API为准。
理解了这一点,测试的时候就该把精力放在验证Kubernetes本身核心机制的可用性上,而不是急着去装各种花哨的附加组件。先把地基打牢,再在上面盖房子。
3. 核心功能测试的设计思路:一条链路走到底
3.1 为什么建议按业务链路来测
我见过不少人做集群测试,是今天创建一个Deployment,明天创建一个Service,后天创建一个PVC,每个都是独立操作,测完就删。这种测法不能说完全没用,但效率很低。原因在于,它没有模拟出真实的业务使用场景,也就无法暴露“组件之间交互”时才会出现的问题。
真实业务跑在Kubernetes上,一个最简单的应用链路是这样的:通过Ingress域名访问,Ingress把流量转发给Service,Service通过Label选择器把流量转发给后端的Pod,Pod里的容器读取ConfigMap和Secret作为配置,业务数据写入PVC持久化存储。这条链路里任何一个环节断裂,业务就不可用。
所以我的建议是:设计一套完整的测试应用,让它同时依赖Deployment、Service、Ingress、ConfigMap、Secret、PVC这些核心资源,然后从外到内、从创建到销毁整体走一遍。一旦某个环节出错,就能立刻定位到是配置问题、网络问题、存储问题还是调度问题。这种测试方式跟生产环境的使用方式高度一致,测试结果更有参考价值。
3.2 测试用例设计遵循的原则
设计测试用例的时候,我会遵循几个原则:
第一是覆盖核心资源类型。不要只测Deployment,应该把常见的工作负载类型都测一遍,包括StatefulSet、DaemonSet、Job和CronJob。因为它们的调度逻辑、生命周期管理方式、使用场景完全不同,任何一个有隐藏问题都会在特定场景下暴露。
第二是覆盖关键机制。包括滚动更新、优雅停机、自动重启、重新调度、配置热更新、水平伸缩、Ingress路由规则。这些机制是Kubernetes相对于传统虚拟机的核心价值,如果只是验证部署,不验证生命周期机制,那测试是不完整的。
第三是覆盖故障场景。挑一个工作节点,模拟节点宕机或者网络分区,看Kubelet失联之后Pod会不会被驱逐到其他节点。这个测试做一次,你就能确认集群的自愈能力到底是真的还是配置上摆样子。
第四是保留测试产物。每一次测试的YAML、输出日志、执行时间点、最终结果,都要记录清楚。这是以后对比集群性能和定位问题的基础数据,非常重要。
3.3 测试过程中的风险控制
测试不是搞破坏,别把集群弄坏了影响后续工作。我开始做测试之前,会创建一个单独的命名空间,比如叫platform-test,所有测试资源都放里面。这样测完直接kubectl delete ns platform-test,全部清理干净,不会污染其他内容。
另外,模拟故障场景的测试要控制范围。比如我模拟节点不可用,只在非核心业务节点上进行,并且在操作前确保这个节点上的Pod副本数大于等于2,避免测试过程中业务真的被中断。而且节点故障测试要提前跟团队打招呼,别一声不吭把节点关机了,遇到线上用户在访问,那就要出事故了。
4. 基础测试的实操过程:手把手完整跑一遍
4.1 命名空间和测试应用部署
先创建命名空间。所有测试资源都放在这个空间里,逻辑隔离,后面清理也方便。
kubectl create ns platform-test然后准备一个测试用的Deployment。这里我刻意选择了nginx作为测试镜像,因为nginx的镜像小、启动快、自带默认监听80端口,方便后面测试Service转发。关键地方在于YAML里的各种配置要尽量跟生产环境保持一致,否则测试结果没有参考性。
创建一个命名为test-nginx的YAML文件:
apiVersion: apps/v1 kind: Deployment metadata: name: test-nginx namespace: platform-test labels: app: test-nginx spec: replicas: 3 selector: matchLabels: app: test-nginx template: metadata: labels: app: test-nginx spec: containers: - name: nginx image: nginx:1.27-alpine ports: - containerPort: 80 name: http resources: requests: cpu: 100m memory: 128Mi limits: cpu: 500m memory: 256Mi readinessProbe: httpGet: path: / port: 80 initialDelaySeconds: 3 periodSeconds: 10 livenessProbe: httpGet: path: / port: 80 initialDelaySeconds: 5 periodSeconds: 15 env: - name: NGINX_ENV valueFrom: configMapKeyRef: name: test-config key: env.type部署之后检查Pod状态:
kubectl apply -f test-nginx.yaml kubectl get pods -n platform-test -o wide正常的Pod应该是Running且READY为1/1。如果有Pending,用kubectl describe pod看一下事件,大概率是资源不足、镜像拉取失败或者节点调度约束不满足。如果一直处于ContainerCreating,则重点排查镜像仓库连通性和容器运行时状态。
4.2 验证滚动更新和回滚
滚动更新是Kubernetes保障服务不中断的核心机制。我们把镜像版本从1.27-alpine升级到1.28-alpine,指定更新策略为RollingUpdate,观察Pod按批次替换的过程。
kubectl set image deployment/test-nginx nginx=nginx:1.28-alpine -n platform-test kubectl rollout status deployment/test-nginx -n platform-test运行过程中会看到状态为Progressing,旧的Pod逐个终止、新的Pod逐个创建。更新完成后检查所有Pod是否都处于Running状态。这里有一个容易踩的坑:如果新版本镜像有兼容性问题导致Pod启动失败,RollingUpdate会卡住。此时可以用回滚命令恢复:
kubectl rollout undo deployment/test-nginx -n platform-test注意:不要在生产环境随意修改镜像tag。测试过程中,如果反复切换版本,建议给镜像打上明确的版本标识,避免混淆。另外,滚动更新策略里的maxSurge和maxUnavailable参数值得关注,默认是25%和25%,你可以根据业务可容忍的抖动程度去调整,但不要在测试阶段乱调,先用默认值验证机制本身是否正常。
4.3 配置与密钥管理验证
Production环境的应用离不开配置管理。ConfigMap和Secret是Kubernetes里最常用的两种配置资源。我创建一个ConfigMap和Secret,挂载到测试应用的Pod里,验证配置是否正确下发。
创建ConfigMap:
kubectl create configmap test-config -n platform-test \ --from-literal=env.type=staging \ --from-literal=log.level=info创建Secret:
kubectl create secret generic test-secret -n platform-test \ --from-literal=db.password='S3curePass!'但在上面那个Deployment的YAML里已经通过env的方式引用了ConfigMap。为了更直观地验证,我把Secret也挂进去。修改Deployment,在容器里增加:
env: - name: DB_PASSWORD valueFrom: secretKeyRef: name: test-secret key: db.password然后进入容器验证:
kubectl exec -it test-nginx-xxx -n platform-test -- /bin/sh env | grep -E "NGINX_ENV|DB_PASSWORD" echo $NGINX_ENV echo $DB_PASSWORD如果输出正常,说明环境变量注入没问题。关于配置热更新,这里有一个细节必须说明:通过环境变量方式注入的配置,修改ConfigMap之后不会自动同步到Pod环境变量中,必须滚动重启Pod才能生效。而通过volume挂载方式注入的configmap数据,在部分文件更新场景下能自动同步到容器内,但也不是实时刷新,存在kubelet同步周期。测试时如果你依赖配置热更新,建议优先试验volume方式,并且结合应用自身对配置文件变更的监听能力来设计。
4.4 创建Service并验证负载均衡和DNS解析
有了Pod,创建Service让流量能访问进来。我用ClusterIP类型,先验证集群内部的Service访问链路。
kubectl expose deployment test-nginx -n platform-test \ --port=80 --target-port=80 --type=ClusterIP查看Service内容:
kubectl get svc -n platform-test kubectl describe svc test-nginx -n platform-test然后从集群内任意节点或任意Pod里访问这个Service:
kubectl run curl-test -n platform-test --rm -it \ --image=curlimages/curl --restart=Never -- \ curl -s http://test-nginx如果访问返回nginx默认页面,说明Service的Label Selector正确关联到了后端Pod,kube-proxy的转发链路也正常。
再验证CoreDNS域名解析:
kubectl run dns-test -n platform-test --rm -it \ --image=busybox:1.36 --restart=Never -- \ nslookup test-nginx.platform-test.svc.cluster.local能解析出ClusterIP就说明CoreDNS配置正常。如果解析失败,检查CoreDNS Pod状态、kube-dns Service、以及Pod的resolv.conf配置。
4.5 测试Ingress路由
ClusterIP只能在集群内部访问,要测试外部访问,需要Ingress。先部署Nginx Ingress Controller。
我这里假设你已经通过Helm或YAML方式安装了Nginx Ingress Controller。验证一下:
kubectl get pods -n ingress-nginx kubectl get svc -n ingress-nginx确认ingress-nginx-controller的Service类型是LoadBalancer或者NodePort。如果是裸金属环境没有LoadBalancer,通常会使用NodePort或者MetalLB方式暴露。不管哪种方式,只要外部能访问到Ingress Controller的入口,后面的Ingress规则才能生效。
创建一个Ingress:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: test-nginx-ingress namespace: platform-test annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: ingressClassName: nginx rules: - host: test.local http: paths: - path: / pathType: Prefix backend: service: name: test-nginx port: number: 80应用后测试访问:
kubectl apply -f test-ingress.yaml curl -H "Host: test.local" http://<INGRESS_IP>/返回nginx默认页说明Ingress Controller把请求转发给了Service,Service再转发给Pod。如果返回404或者502,重点排查Ingress Controller日志和Service Endpoints。
提示:测试用的域名建议不要用真实域名,就用test.local这类不会引起冲突的假域名。Ingress规则匹配Host的时候区分大小写,而且注意ingressClassName字段的配置要跟实际部署的Ingress Controller对应,匹配错误的话Ingress不会生效。
4.6 验证存储挂载
存储是Kubernetes生产环境里最容易踩坑的环节之一。测试环境我先验证emptyDir,验证Pod生命周期内的临时数据写入。然后重点验证PV和PVC的动态供给。
如果你的集群没有默认StorageClass,先部署一个。以常见的NFS StorageClass为例,或者你可以用本地存储测试。假设集群有StorageClass名为standard,创建一个PVC然后挂载到Deployment中。
创建PVC:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: test-pvc namespace: platform-test spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: standard在Deployment的Pod模板里增加volume挂载:
volumeMounts: - name: test-data mountPath: /usr/share/nginx/html volumes: - name: test-data persistentVolumeClaim: claimName: test-pvc应用后检查PVC状态:
kubectl get pvc -n platform-test kubectl get pvPVC的STATUS应该是Bound,如果一直Pending,说明StorageClass的动态供给有问题,或者存储后端没有准备好。这时用describe命令看事件,一般能看到原因。比如云平台快照没绑定、NFS服务不可达等等。Pod启动后在容器里写一个文件到挂载目录,再重建Pod,文件还在,说明持久化生效了。
这里有一个我个人的实操心得:如果你测试存储想快速看到效果,就写一个标记文件再删掉Pod重新调度,确认文件还在;但这要求PVC的accessModes与Pod调度策略匹配,如果Pod被调度到其他节点而存储后端不支持跨节点挂载,就会出问题。每个存储类型的行为不一样,别把NFS的行为套用到local卷上,也别把local卷的行为套用到云盘上。
4.7 调度与自愈能力测试
接下来是重头戏:验证调度器的分配逻辑和集群的故障自愈。
先说分配逻辑。Kubernetes调度器会按照节点资源剩余量、节点亲和性、Pod亲和性、污点和容忍度等规则决定Pod的最终位置。测试时我给测试Deployment添加nodeSelector:
spec: template: spec: nodeSelector: kubernetes.io/hostname: node-01应用后确认Pod都调度到了指定节点:
kubectl get pods -n platform-test -o wide | grep test-nginx然后验证反亲和性,让多个副本尽量分散到不同节点,避免单点故障导致所有实例同时挂掉:
spec: template: spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - test-nginx topologyKey: kubernetes.io/hostname接下来做节点故障模拟。选择运行着test-nginx副本的一个节点,用kubectl drain做节点维护操作:
kubectl drain node-02 --delete-emptydir-data --ignore-daemonsets --forcedrain会把节点上的普通Pod驱逐到其他节点,类似一次正常的节点维护流程。执行后观察Pod在别的节点上重新创建:
kubectl get pods -n platform-test -o wide -w如果只想模拟节点突然宕机,可以直接在节点上执行systemctl stop kubelet,或者直接关机。此时由于节点心跳超时,控制器会在一段时间后把Pod标记为Unknown,然后在其他可用节点重建副本。这个时间受到pod-eviction-timeout参数影响,默认5分钟。你可以观察这个超时过程是否符合预期。
注意:节点关机测试属于破坏性操作,务必在测试环境进行,不要在正式环境直接拔电源。另外drain节点后,记得用
kubectl uncordon node-02恢复节点可调度状态,否则后续测试会变得很奇怪,因为Pod不会主动调度回该节点。
4.8 验证水平伸缩
HPA(HorizontalPodAutoscaler)是验证集群弹性能力的关键功能。先在测试Deployment里加上资源限制(前面已经加了),然后创建HPA:
kubectl autoscale deployment test-nginx -n platform-test \ --cpu-percent=50 --min=1 --max=5或者用YAML方式创建:
apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: test-nginx-hpa namespace: platform-test spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: test-nginx minReplicas: 1 maxReplicas: 5 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 50HPA默认需要metrics-server采集指标,确认metrics-server已经部署并且正常:
kubectl top nodes kubectl top pods -n platform-test如果kubectl top没有输出,说明metrics-server没装好,HPA就无法工作。验证时我会给Pod加压,比如进去跑一个触发CPU消耗的命令,观察HPA是否自动扩容副本数量:
kubectl exec -it test-nginx-xxx -n platform-test -- /bin/sh # 在容器内执行 yes > /dev/null &隔一两分钟查看:
kubectl get hpa -n platform-test kubectl get pods -n platform-test如果Pod数量从1变成了多个,说明HPA弹性伸缩机制正常。然后取消压力,等待冷却时间后,观察副本数量自动缩回。
提示:HPA的扩容和缩容都有冷却机制,不会立刻上下弹跳,这是为了保护系统稳定性。测试时要耐心等待一段时间。另外缩容时Pod数量会有下限保护,不会缩到minReplicas以下。
5. 常见问题排查实录:踩过的坑和解决办法
5.1 Pod一直Pending排查思路
Pending表示调度器还没找到合适的节点。最常见的三个原因:节点资源不足、节点亲和性/污点约束不满足、PVC无法挂载。
我碰到过一个案例,某个节点使用率特别高,所有Worker节点CPU都快满了,新创建的Pod找不到可调度节点,一直Pending。用以下命令确认:
kubectl describe pod test-nginx-xxx -n platform-test | tail -n 20看到Events里有FailedScheduling相关事件,内容会明确提示Insufficient cpu或者Insufficient memory。这时要么扩容节点,要么调低Pod的requests值。
另一个容易忽略的原因是节点上有自定义污点。比如我之前在某环境下,为了把监控类组件固定到专用节点,给节点打了污点,结果新建的业务Pod没配置对应容忍度,就一直Pending。排查命令:
kubectl describe node node-01 | grep Taints5.2 CrashLoopBackOff与ImagePullBackOff的区别
两者都表现为Pod无法进入Running状态,但原因差别很大。
ImagePullBackOff表示镜像拉取失败,常见原因有:镜像tag不存在、镜像仓库需要认证、节点无法访问镜像仓库。排查:
kubectl describe pod test-nginx-xxx -n platform-testEvents里会有类似Failed to pull image "nginx:xxx": rpc error的报错。如果私有仓库认证问题,考虑配置imagePullSecrets,或者在所有节点上提前完成docker login并配置好containerd的registry配置。
CrashLoopBackOff表示容器启动了但马上退出。原因通常出在应用本身,比如启动命令不对、配置文件错误、端口被占用。排查手段是看日志:
kubectl logs test-nginx-xxx -n platform-test --tail=50 kubectl logs test-nginx-xxx -n platform-test --previous第二个命令看的是容器退出前的日志,非常有用,因为新容器重启后,之前的日志可能被刷新。
5.3 Service无法访问,但Pod是Running
这种情况很经典:Pod本身是健康的,但通过Service访问时不通。排查链条如下:
先看Service有没有关联到Endpoints:
kubectl get endpoints test-nginx -n platform-test如果Endpoints列表为空,说明Service的Label选择器没有匹配到任何Pod。检查一下Pod的labels和Service的selector是否一致,YAML里少写一个标签都是坑。
如果Endpoints正常,但访问仍然不通,就要看kube-proxy的转发模式。如果是iptables模式,检查节点上的iptables规则:
iptables -t nat -L -n | grep test-nginx在节点规模较大的集群里,iptables规则数量会非常多,规则加载性能出问题的情况时有发生。如果是IPVS模式,用ipvsadm确认虚拟服务的后端列表:
ipvsadm -L -n | grep test-nginx再往下可以看kube-proxy日志,但多数情况下以上两步已经能定位问题。
5.4 DNS解析失败
CoreDNS解析失败,通常表现为Pod内部通过服务名访问不到别的服务。排查顺序:
第一,确认CoreDNS Pod本身是Running且Ready:
kubectl get pods -n kube-system -l k8s-app=kube-dns第二,确认kube-dns Service存在且ClusterIP正确。第三,进入有问题的Pod查看resolv.conf:
kubectl exec -it test-nginx-xxx -n platform-test -- cat /etc/resolv.conf正常应该包含nameserver指向kube-dns的ClusterIP,并且search域包含namespace.svc.cluster.local。如果resolv.conf不对,检查Pod的dnsPolicy配置。用了默认ClusterFirst的话,Kubelet会注入正确的配置。
还有一种情况是节点上的iptables规则拦住了DNS请求,特别是在某些自定义了防火墙策略的节点上容易发生。可以单独起一个临时Pod用nslookup来复现问题:
kubectl run dns-debug -n platform-test --rm -it \ --image=busybox:1.36 --restart=Never -- \ nslookup kubernetes.default.svc.cluster.local5.5 PVC一直Pending
PVC Pending的排查点集中在StorageClass和存储后端:
kubectl describe pvc test-pvc -n platform-test kubectl get storageclass如果是动态供给,确认storageClassName匹配。如果是本地存储,确认PV的nodeAffinity和PVC的accessModes匹配。云盘类型的存储还要确认可用区和节点是否一致,某些云平台挂载卷有可用区限制。
我之前遇到一个典型的案例:PVC的accessModes是ReadWriteMany,但存储后端只支持ReadWriteOnce,创建PV时兼容性匹配不上,PVC就一直Pending。解决方式是调整PVC的accessModes或更换存储类型。
6. 测试完成后的收尾和验收标准
6.1 清理测试资源
测试做完了,别把一堆测试资源留在集群里占地方。清理方法很粗暴:
kubectl delete ns platform-test同时清理Ingress Controller等测试期间安装但生产不需要的组件,尤其是那些通过Helm安装的,按对应chart删除。
但是有一个点要注意:如果你在测试中创建了StorageClass,而且StorageClass对应的是真实存储后端(比如NFS),删除StorageClass并不会删除底层存储数据。PV如果被删了但底层数据没被回收,下次再创建同名PVC,可能会看到容量被占用或者数据残留。所以测试前明确哪些存储资源可以销毁,别在真实存储上随便造数据。
6.2 输出一份测试验收报告
基础测试不是跑完就算,建议按下面这个表格整理一份测试报告。这个报告既是当前集群可用的证明,也是后续扩容、升级、故障排查的基线文档。
表格中的“测试项”就是这次覆盖的模块:集群健康检查、工作负载部署、滚动更新、配置注入、Service与DNS、Ingress访问、持久化存储、调度策略、节点故障自愈、HPA弹性伸缩。“测试结果”记录Pass/Pass with issues/Fail。“问题描述”记录失败项的现象和根因。“备注”记录涉及的关键配置和参数。
提示:以后每次做版本升级或者配置变更,都再做一轮相同流量的冒烟测试,用这份报告对比结果差异。这是我在实操中踩过很多坑之后养成的习惯。升级前一切正常,升级后某块功能挂了,如果没有之前的Baseline对比,排查的范围会大很多。
6.3 测试中发现的问题要闭环
测试的意义不仅是验证“能跑”,更重要的是发现隐患并修复。测试过程中如果发现某个组件存在配置不合理的地方,不要想着“先这样吧”,记录到问题清单,安排时间修复,再回归验证。比如测试时发现kube-proxy使用iptables模式在大量Service条件下性能下降明显,就要评估是否切换到IPVS模式,而不是等线上出问题才处理。
我个人在实际操作中的体会是:基础测试最容易出的问题不是技术本身,而是“懒得测”和“不知道怎么测才全面”。你花两三个小时把上面这条链路完整走一遍,换来的是对集群健康状况的明确认识。这套流程我已经在多个环境里原样跑过,踩过的坑都写在这篇里面了,按顺序做基本不会有大问题。如果你在测试过程中碰到其他奇怪的现象,欢迎带着现象和日志来聊,很多问题在交流中反而更容易定位。