K8s 模拟大规模集群性能测试 -- kubemark

3,958 阅读3分钟

在 K8s 的使用中,我们会遇到这样一个场景,现有集群只有几个节点,但是我想模拟测试大规模集群时,集群的压力性能会表现如何呢?这里就需要用到 kubemark 了。

原理

kubemark 是 K8s 官方给出的性能测试工具,能够不受任何资源限制,模拟出一个大规模 K8s 集群。其主要架构如图所示:

需要一个外部 K8s 集群(external cluster) 以及一个机器节点运行 kubemark master,即另外一个 K8s 集群,但是只有一个 master 节点。我们需要在 external cluster 中部署运行 hollow pod,这些 pod 会主动向 kubemark 集群注册,并成为 kubemark 集群中的 hollow node(虚拟节点)。然后我们就可以在 kubemark 集群中进行 e2e 测试。虽然与真实集群的稍微有点误差,不过可以代表真实集群的数据。

准备

我使用的版本是 v1.14.6

构建 kubemark 镜像

首先需要下载下来 K8s 的源代码,并切换到对应分支上。然后执行

make quick-release

编译出的二进制存储在 _output 目录下。

注意,在编译过程中,需要 pull 一些镜像,可能需要翻墙,建议提前 pull 下来。主要用到的镜像有:

  • k8s.gcr.io/kube-cross:v1.12.5-1
  • k8s.gcr.io/debian-base-amd64:v1.0.0
  • k8s.gcr.io/debian-iptables-amd64:v11.0.2

然后进入到 $KUBE_SRC/cluster/images/kubemark 目录下,将编译得到的 kubemark 二进制复制到该目录下,并执行以下命令打镜像。

docker build -t kubemark:latest .

kubemark master 搭建

在 K8s 源码中,test/kubemark/ 目录下包含了在本地启动 kubemark master 的脚本,但是我在测试过程中,遇见了茫茫多的问题(应该是小弟才疏学浅,搞不定),因此采用另一种方案,通过 kubeadm 或者 kubespary 部署一个单节点的 K8s 集群作为 kubemark master 节点。

这里有个坑,就是需要将节点名称改为 xx-master,这样在后面跑 e2e 测试时,才会把该节点识别为master节点。具体源码如下,其他版本是否有这个问题,我暂时未去查找。

// 在 e2e 源码中,调用了pkg/util/system/system_utils.go 下面的方法判断是否为master节点
func IsMasterNode(nodeName string) bool {
	// We are trying to capture "master(-...)?$" regexp.
	// However, using regexp.MatchString() results even in more than 35%
	// of all space allocations in ControllerManager spent in this function.
	// That's why we are trying to be a bit smarter.
	if strings.HasSuffix(nodeName, "master") {
		return true
	}
	if len(nodeName) >= 10 {
		return strings.HasSuffix(nodeName[:len(nodeName)-3], "master-")
	}
	return false
}

此处需要注意的是,kubemark 集群部署时,不需要特定的网络插件,即 flannel 或 calico 之类的组件都不需要安装部署。若部署成功后,通过kubectl get node查看节点的状态是NotReady,则需要将 /etc/kubernetes/kubelet.env文件中的 KUBELET_NETWORK_PLUGIN=" --network-plugin=cni ..."注释掉,然后 systemctl restart kubelet 即可。

在部署完成后,kubectl get po -A查看pod状态,可能会存在一些 "0/1" 状态的pod,则需要做以下操作

  1. 删除 daemonSet 资源(包括 kube-proxy),
  2. 删除 deployment:autoscaler;
  3. 删除 namespace:ingress-nginx

如果还有其他的非 Running 状态pod,则需要做额外处理,直至所有pod 都处于Running状态。

最后需要将 kubemark master 节点设置为 unschedule

external cluster

在外部集群中,需要加载以下镜像,用于kubemark 测试

  • busybox
  • k8s.gcr.io/heapster:v1.3.0
  • kubemark(第一步中构建好的镜像)
  • k8s.gcr.io/node-porblem-detector:v0.4.1

需要准备以下文件:

  • kernel-monitor.json
  • hollow-node_template.yaml
  • addon/heapster_template.json
  • kubemark.kubeconfig (kubemark master的config) 前三个文件见连接 git.dev.tencent.com/packyzbq/ku…

使用以下命令,创建 hollow-node 的pod

kubectl create ns kubemark

kubectl create cm node-configmap -n kubemark --from-litera=content.type="" --from-file=kernel.monitor="kernel-monitor.json"

kubectl create secret generic kubeconfig --type=Opaque --namespace=kubemark \
--from-file=kubelet.kubeconfig=kubemark.kubeconfig \
--from-file=kubeproxy.kubeconfig=kubemark.kubeconfig \
--from-file=npd.kubeconfig=kubemark.kubeconfig \
--from-file=heapster.kubeconfig=kubemark.kubeconfig \
--from-file=cluster_autoscaler.kubeconfig=kubemark.kubeconfig \
--from-file=dns.kubeconfig=kubemark.kubeconfig

kubectl apply -f addon/ -n kubemark

kubectl apply -f hollow-node_template.yaml -n kubemark

当 external cluster 中,所有 hollow node 的pod 处于 Running 状态后,在 kubemark master 节点执行 kubectl get node,则会出现对应的 hollow node。

执行 e2e 测试

e2e 测试需要获取 etcd 的 metrics 数据,但是在源码中通过 curl http://localhost:2379/metrics 获取的,而我们部署的 kubemark 集群中 etcd 的访问需要证书认证,因此还需要修改源码。

//  test/e2e/framework/metrics_util.go
func getEtcdMetrics() ([]*model.Sample, error) {
    ...
    if TestContext.Provider == "gke" || TestContext.Provider == "eks" {
                Logf("Not grabbing etcd metrics through master SSH: unsupported for %s", TestContext.Provider)
                return nil, nil
        }
    cmd := "curl -L https://localhost:2379/metrics --key {your etcd key} --cert {your etcd cert}"
    sshResult, err := SSH(cmd, GetMasterHost()+":22", TestContext.Provider)
}

修改完后,编译 e2e.test

make WHAT="test/e2e/e2e.test"

然后执行以下命令进行 e2e 测试。

$KUBEROOT/_output/bin/e2e.test  --kube-master=xxx --host=http://127.0.0.1:8080 --ginkgo.focus=":Performance]" --provider=local --kubeconfig=/var/run/kubernetes/admin.kubeconfig --num-nodes=1 --v=3 --ginkgo.failFast --e2e-output-dir=xxxx --report-dir=xxx

其中 num-nodes 参数需要依据 hollow node 的个数改变。 在external cluster 中,可以按照1:20的比例去模拟节点数量(即使用1个物理节点去模拟20个 hollow node),进行大规模的集群测试。 如果喜欢,请关注我的公众号,或者查看我的博客 packyzbq.coding.me. 我会不定时的发送我自己的学习记录,大家互相学习交流哈~

weixin