Kubernetes 社区提供了 SLI (服务等级指标) 和 SLO (服务等级目标) 系统性能测试、分析文档 Kubernetes scalability and performance SLIs/SLOs。模拟出一个 K8s cluster(Kubemark cluster),不受资源限制。cluster 中 master 是真实的机器,所有的 nodes 是 Hollow nodes。Hollow nodes 不会调用Docker,测试一套 K8s API 调用的完整流程,不会真正创建 pod。
社区开发了 perf-test/clusterloader2,可配置性好,并且统计了相应的性能指标
kubemark 不调用 CRI 接口之外,其它行为和 kubelet 基本一致
/bin/sh -c /kubemark --morph=kubelet --name=hollow-node-9dfp9 {{hollow_kubelet_params}} --kubeconfig=/kubeconfig/kubelet.kubeconfig --logtostderr -v 4
使用了 command.Cobra 第三方命令行包,直接上重点 run 函数
--morph 是该hollow 模拟哪个组建,可选的有 kubelet 和 kube-proxy
func run(config *hollowNodeConfig) {
// To help debugging, immediately log version
klog.Infof("Version: %+v", version.Get())
if !knownMorphs.Has(config.Morph) {
klog.Fatalf("Unknown morph: %v. Allowed values: %v", config.Morph, knownMorphs.List())
}
GetHollowKubeletConfig 设置 root dir 为 /tmp/hollow-kubelet,pod 工作目录为 /tmp/hollow-kubelet/static-pods,
直接调用 kubelet 的 NewKubeletFlags 初始化 kubelet 的参数
fakeDockerClientConfig := &dockershim.ClientConfig{
DockerEndpoint: libdocker.FakeDockerEndpoint,
EnableSleep: true,
WithTraceDisabled: true,
}
直接调用 kubelet 的 RunKubelet 函数,所以和 kubelet 行为一模一样,只不过调用到 fake docker endpoint
// Starts this HollowKubelet and blocks.
func (hk *HollowKubelet) Run() {
if err := kubeletapp.RunKubelet(&options.KubeletServer{
KubeletFlags: *hk.KubeletFlags,
KubeletConfiguration: *hk.KubeletConfiguration,
}, hk.KubeletDeps, false); err != nil {
klog.Fatalf("Failed to run HollowKubelet: %v. Exiting.", err)
}
select {}
}
iptables 以及 sysctl 使用了 fake
if config.Morph == "proxy" {
client, err := clientset.NewForConfig(clientConfig)
if err != nil {
klog.Fatalf("Failed to create API Server client: %v", err)
}
iptInterface := fakeiptables.NewFake()
sysctl := fakesysctl.NewFake()
execer := &fakeexec.FakeExec{
LookPathFunc: func(_ string) (string, error) { return "", errors.New("fake execer") },
}
在 kubernetes 目录下执行,make WHAT='test/e2e/e2e.test' && make ginkgo
kubectl create secret generic kubeconfig --from-file=kubelet.kubeconfig=/root/.kube/config
注意
C.1.设置真实节点 Taint,主要是避免测试调度到真正的 node 节点上
kubectl taint nodes ${node} role=real:NoSchedule
C.2 为真实node 设置label,使 hollow 调度到其上运行
kubectl label nodes ${node} role=real
apiVersion: apps/v1
kind: Deployment
metadata:
name: hollow-node
labels:
name: hollow-node
spec:
replicas: 5
selector:
matchLabels:
name: hollow-node
template:
metadata:
labels:
name: hollow-node
spec:
nodeSelector:
role: real
hostAliases:
- ip: "192.168.73.64"
hostnames:
- "master.node.local"
initContainers:
- name: init-inotify-limit
image: zhangzhonglin/kubemark:v1.10.5
command: ["sysctl", "-w", "fs.inotify.max_user_instances=10"]
securityContext:
privileged: true
volumes:
- name: kubeconfig-volume
secret:
secretName: kubeconfig
- name: logs-volume
hostPath:
path: /var/log
- name: no-serviceaccount-access-to-real-master
emptyDir: {}
containers:
- name: hollow-kubelet
image: zhangzhonglin/kubemark:v1.10.5
imagePullPolicy: Always
ports:
- containerPort: 4194
- containerPort: 10250
- containerPort: 10255
env:
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
command:
- /bin/sh
- -c
- /kubemark --morph=kubelet --name=$(NODE_NAME) {{hollow_kubelet_params}} --kubeconfig=/kubeconfig/kubelet.kubeconfig --logtostderr -v 4
volumeMounts:
- name: kubeconfig-volume
mountPath: /kubeconfig
readOnly: true
- name: logs-volume
mountPath: /var/log
securityContext:
privileged: true
tolerations:
- key: "role"
operator: "Equal"
value: "real"
effect: "NoSchedule"
可以看到注册出 hollow 节点