在 K8s 的使用中,我们会遇到这样一个场景,现有集群只有几个节点,但是我想模拟测试大规模集群时,集群的压力性能会表现如何呢?这里就需要用到 kubemark 了。
原理
kubemark 是 K8s 官方给出的性能测试工具,能够不受任何资源限制,模拟出一个大规模 K8s 集群。其主要架构如图所示:
准备
我使用的版本是 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,则需要做以下操作
- 删除 daemonSet 资源(包括 kube-proxy),
- 删除 deployment:autoscaler;
- 删除 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. 我会不定时的发送我自己的学习记录,大家互相学习交流哈~