一、kubemark介绍

背景介绍

kubemark 是 K8s 官方给出的性能测试工具,能够不受任何资源限制,模拟出一个大规模 K8s 集群。其主要架构如图所示:需要一个外部 K8s 集群(external cluster) 以及一个机器节点运行 kubemark master,即另外一个 K8s 集群,但是只有一个 master 节点。我们需要在 external cluster 中部署运行 hollow pod,这些 pod 会主动向 kubemark 集群注册,并成为 kubemark 集群中的 hollow node(虚拟节点)。然后我们就可以在 kubemark 集群中进行 e2e 测试。虽然与真实集群的稍微有点误差,不过可以代表真实集群的数据

二、kubemark构建

  • 编译kubemark可执行文件
下载与环境一直的k8s源码包文件,安装go环境
#########查看目前环境为1.18.6版本
[root@node1 kubemark]# kubectl get node 
NAME    STATUS   ROLES    AGE   VERSION
node1   Ready    master   18h   v1.18.6
node2   Ready    master   18h   v1.18.6
node3   Ready    master   18h   v1.18.6
########下载源码包以及安装go环境
[root@node1 kubemark]# ll | grep kubernetes
drwxr-xr-x 21 root root      4096 Mar 31 14:13 kubernetes-1.18.6
-rw-r--r--  1 root root 454873856 Apr 12 16:29 kubernetes-1.18.6.tar.gz
    
########go版本
[root@node1 kubemark]# go version
go version go1.16.14 linux/amd64
[root@node1 kubemark]# 

#######编译kubemark
cd /root/test/kubemark/kubernetes-1.18.6

make kubemark GOGCFLAGS="-N -l"

编译好的文件在_output/bin/目录下:
[root@node1 kubernetes-1.18.6]# cd _output/bin/
[root@node1 bin]# ll
total 282868
-rwxr-xr-x 1 root root   6217728 Mar 31 14:13 conversion-gen
-rwxr-xr-x 1 root root   5971968 Apr 12 17:08 deepcopy-gen
-rwxr-xr-x 1 root root   5955584 Mar 31 14:13 defaulter-gen
-rwxr-xr-x 1 root root 113429456 Apr  6 10:59 e2e.test
-rwxr-xr-x 1 root root   3554775 Apr 12 17:08 go2make
-rwxr-xr-x 1 root root   1966080 Mar 31 14:14 go-bindata
-rwxr-xr-x 1 root root  41275392 Mar 31 15:45 kubectl
-rwxr-xr-x 1 root root 101385080 Apr 12 17:08 kubemark
-rwxr-xr-x 1 root root   9895936 Mar 31 14:13 openapi-gen

########编译好的工具下载解压即用
链接:https://pan.baidu.com/s/1iWTaZRz4nUZJ6W7mzC5mjA 
提取码:db37 
--来自百度网盘超级会员V6的分享
########################
  • 构建kubemark镜像
将生成的 kubemark 二进制文件从 _output/bin 复制到 cluster/images/kubemark 目录下。

[root@node1 kubernetes-1.18.6]# cp _output/bin/kubemark cluster/images/kubemark/
[root@node1 kubemark]# ll
total 99028
-rw-r--r-- 1 root root       791 Jul 16  2020 BUILD
-rw-r--r-- 1 root root       877 Apr 12 17:35 Dockerfile
-rwxr-xr-x 1 root root 101385080 Apr 12 17:08 kubemark
-rw-r--r-- 1 root root      1268 Jul 16  2020 Makefile
-rw-r--r-- 1 root root       147 Jul 16  2020 OWNERS
####需要替换Dockerfile中使用的镜像,默认镜像不可用。
FROM centos:7
COPY kubemark /kubemark
#######运行命令进行编译。或者使用下面云盘链接中编译好的镜像。
IMAGE_TAG=v1.14.8 make build   ###不指定tag默认为latest。

####修改tag上传至registry,方便其他节点使用。
链接:https://pan.baidu.com/s/1WI0V88sU4TTRtHfA9EmZjw 
提取码:3zdw 
--来自百度网盘超级会员V6的分享

三、启动kubemark集群

  • 配置基础环境
在执行节点执行以下命令创建ns、cm、secret
kubectl create ns kubemark

kubectl create configmap node-configmap -n kubemark --from-literal=content.type="test-cluster"

kubectl create secret generic kubeconfig --type=Opaque --namespace=kubemark --from-file=kubelet.kubeconfig=/root/.kube/config --from-file=kubeproxy.kubeconfig=/root/.kube/config
  • 修改maxPods值
修改配置文件vim /var/lib/kubelet/config.yaml
maxPods: 1000000
然后重启kubelet
systemctl restart kubelet
  • 启动hollow node节点
1、设置物理node标签
kubectl label node node1 name=hollow-node
kubectl label node node2 name=hollow-node
kubectl label node node3 name=hollow-node
###########或者设置为不可调度
kubectl taint node node1 key=value:NoSchedule
kubectl taint node node2 key=value:NoSchedule
kubectl taint node node3 key=value:NoSchedule        

2、执行hollow-node.yaml文件创建虚拟节点
kubectl apply -f hollow-node.yaml

###yaml文件内容如下:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hollow-node
  namespace: kubemark
  labels:
    name: hollow-node
spec:
  replicas: 1000       ###启动的虚拟节点的数量
  selector:
    matchLabels:
      name: hollow-node
  template:
    metadata:
      labels:
        name: hollow-node
    spec:
      nodeSelector:
        name: hollow-node
      initContainers:
      - name: init-inotify-limit
        image: busybox
        imagePullPolicy: IfNotPresent
        command: ['sysctl', '-w', 'fs.inotify.max_user_instances=524288']
        securityContext:
          privileged: true
      volumes:
      - name: kubeconfig-volume
        secret:
          secretName: kubeconfig
      containers:
      - name: hollow-kubelet
        image: 172.18.30.4:5000/kubemark:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 4194
        - containerPort: 10250
        - containerPort: 10255
        env:
        - name: CONTENT_TYPE
          valueFrom:
            configMapKeyRef:
              name: node-configmap
              key: content.type
        - name: NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        command:
        - /bin/sh
        - -c
        - /kubemark --morph=kubelet --name=$(NODE_NAME) --kubeconfig=/kubeconfig/kubelet.kubeconfig $(CONTENT_TYPE) --alsologtostderr --v=2
        volumeMounts:
        - name: kubeconfig-volume
          mountPath: /kubeconfig
          readOnly: true
        securityContext:
          privileged: true
      - name: hollow-proxy
        image: 172.18.30.4:5000/kubemark:latest
        imagePullPolicy: IfNotPresent
        env:
        - name: CONTENT_TYPE
          valueFrom:
            configMapKeyRef:
              name: node-configmap
              key: content.type
        - name: NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        command:
        - /bin/sh
        - -c
        - /kubemark --morph=proxy --name=$(NODE_NAME) --use-real-proxier=false --kubeconfig=/kubeconfig/kubeproxy.kubeconfig $(CONTENT_TYPE) --alsologtostderr --v=2
        volumeMounts:
        - name: kubeconfig-volume
          mountPath: /kubeconfig
          readOnly: true
      tolerations:
        - key: key
          value: value
          effect: NoSchedule
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:  # 硬策略
            nodeSelectorTerms:
            - matchExpressions:
              - key: name
                operator: In
                values:
                - hollow-node  

#################################
#################################
#################################
如果集群是通过域名访问的,需要在hollow-node.yaml文件中添加如下配置:
spec:
      hostAliases:
      - ip: "10.233.0.1"   ###如果是高可用,则填写集群的vip地址
        hostnames:
        - "vip.sanyi.com"   ###集群域名
      nodeSelector:
        name: hollow-node    
##############################
##############################
##############################        
c查看已经注册好的hollow node节点,如下:
[root@node1 ~]# kubectl get pod -n kubemark -o wide
NAME                          READY   STATUS    RESTARTS   AGE   IP              NODE    NOMINATED NODE   READINESS GATES
hollow-node-7cdbb7d69-6jqnv   2/2     Running   0          71s   172.25.135.58   node3   <none>           <none>
hollow-node-7cdbb7d69-prhx5   2/2     Running   0          71s   172.25.104.44   node2   <none>           <none>
hollow-node-7cdbb7d69-szn5m   2/2     Running   0          71s   172.25.104.43   node2   <none>           <none>
[root@node1 ~]# 
[root@node1 ~]# kubectl get node 
NAME                          STATUS   ROLES    AGE   VERSION
hollow-node-7cdbb7d69-6jqnv   Ready    <none>   66s   v1.18.6
hollow-node-7cdbb7d69-prhx5   Ready    <none>   66s   v1.18.6
hollow-node-7cdbb7d69-szn5m   Ready    <none>   66s   v1.18.6
node1                         Ready    master   19h   v1.18.6
node2                         Ready    master   19h   v1.18.6
node3                         Ready    master   19h   v1.18.6

每个hollow node节点也会启动相应的k8s组件,如下:
[root@node1 ~]# kubectl get pod -A -o wide | grep hollow
kube-system                    calico-node-724sq                                                 0/1     Init:0/3    0          94s     192.168.192.168   hollow-node-7cdbb7d69-6jqnv   <none>           <none>
kube-system                    calico-node-bzq7p                                                 0/1     Init:0/3    0          94s     192.168.192.168   hollow-node-7cdbb7d69-szn5m   <none>           <none>
kube-system                    calico-node-d7255                                                 0/1     Init:0/3    0          94s     192.168.192.168   hollow-node-7cdbb7d69-prhx5   <none>           <none>
kube-system                    kube-proxy-bqph2                                                  1/1     Running     0          94s     192.168.192.168   hollow-node-7cdbb7d69-6jqnv   <none>           <none>
kube-system                    kube-proxy-gtl5z                                                  1/1     Running     0          94s     192.168.192.168   hollow-node-7cdbb7d69-prhx5   <none>           <none>
kube-system                    kube-proxy-qvkcb                                                  1/1     Running     0          94s     192.168.192.168   hollow-node-7cdbb7d69-szn5m   <none>           <none>
kubemark                       hollow-node-7cdbb7d69-6jqnv                                       2/2     Running     0          103s    172.25.135.58     node3                         <none>           <none>
kubemark                       hollow-node-7cdbb7d69-prhx5                                       2/2     Running     0          103s    172.25.104.44     node2                         <none>           <none>
kubemark                       hollow-node-7cdbb7d69-szn5m                                       2/2     Running     0          103s    172.25.104.43     node2                         <none>           <none>
kubesphere-logging-system      fluent-bit-8lvg4                                                  1/1     Running     0          94s     192.168.192.168   hollow-node-7cdbb7d69-6jqnv   <none>           <none>
kubesphere-logging-system      fluent-bit-lvdw9                                                  1/1     Running     0          94s     192.168.192.168   hollow-node-7cdbb7d69-prhx5   <none>           <none>
kubesphere-logging-system      fluent-bit-scgtq                                                  1/1     Running     0          94s     192.168.192.168   hollow-node-7cdbb7d69-szn5m   <none>           <none>
kubesphere-monitoring-system   node-exporter-8b9ts                                               2/2     Running     0          94s     192.168.192.168   hollow-node-7cdbb7d69-6jqnv   <none>           <none>
kubesphere-monitoring-system   node-exporter-pmbst                                               2/2     Running     0          94s     192.168.192.168   hollow-node-7cdbb7d69-szn5m   <none>           <none>
kubesphere-monitoring-system   node-exporter-tzjrg                                               2/2     Running     0          94s     192.168.192.168   hollow-node-7cdbb7d69-prhx5   <none>           <none>
velero                         restic-7b8tm                                                      1/1     Running     0          84s     192.168.192.168   hollow-node-7cdbb7d69-szn5m   <none>           <none>
velero                         restic-8rfvc                                                      1/1     Running     0          84s     192.168.192.168   hollow-node-7cdbb7d69-6jqnv   <none>           <none>
velero                         restic-cm654                                                      1/1     Running     0          84s     192.168.192.168   hollow-node-7cdbb7d69-prhx5   <none>           <none>
[root@node1 ~]#
  • 在hollow节点启动pod测试
1、为hollow node节点添加标签,如下:
[root@node1 kubemark]# kubectl label node hollow-node-7cdbb7d69-6jqnv app=nginx
node/hollow-node-7cdbb7d69-6jqnv labeled
[root@node1 kubemark]# kubectl label node hollow-node-7cdbb7d69-prhx5 app=nginx
node/hollow-node-7cdbb7d69-prhx5 labeled
[root@node1 kubemark]# kubectl label node hollow-node-7cdbb7d69-szn5m app=nginx
node/hollow-node-7cdbb7d69-szn5m labeled

2、执行yaml脚本,在hollow节点启动pod,如下:
kubectl apply -f deploy-pod.yaml
###yaml问价内容如下:
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      nodeSelector:     ####匹配hollow node节点标签,如果物理node设置了NoSchedule则不需要添加
        app: nginx
      containers:
      - name: nginx-deploy
        image: nginx:latest      ###不会真的去下载镜像
        imagePullPolicy: IfNotPresent
            
3、查看启动好的pod节点信息,如下:
[root@node1 ~]# kubectl get pod -o wide 
NAME                            READY   STATUS    RESTARTS   AGE     IP                NODE                          NOMINATED NODE   READINESS GATES
deployment-5bd6b744d4-5fnwr     1/1     Running   0          9s      192.168.192.168   hollow-node-7cdbb7d69-szn5m   <none>           <none>
deployment-5bd6b744d4-cx6wv     1/1     Running   0          9s      192.168.192.168   hollow-node-7cdbb7d69-6jqnv   <none>           <none>
deployment-5bd6b744d4-fh29s     1/1     Running   0          9s      192.168.192.168   hollow-node-7cdbb7d69-prhx5   <none>           <none>

四、perf-test压测工具使用

  • clusterloader工具构建
下载perf-test源码包,与目前k8s环境版本一致,如下:
[root@node1 perf-test]# ll
total 46512
drwxr-xr-x 14 root root     4096 Apr 18 11:15 perf-tests-release-1.18
-rw-r--r--  1 root root 47622183 Apr 19 14:18 perf-tests-release-1.18.zip
    
    
####工具编译
[root@node1 perf-test]# cd perf-tests-release-1.18/clusterloader2/
[root@node1 clusterloader2]# go build -o clusterloader './cmd/'

###编译完成后查看已经存在clusterloader文件,如下:
[root@node1 clusterloader2]# ll
total 37964
drwxr-xr-x  2 root root       43 Apr 18 11:14 api
-rw-r--r--  1 root root     2631 Apr 18 11:14 clean-up-old-snapshots.sh
-rwxrwxrwx  1 root root 38557259 Apr 18 11:14 clusterloader  ########
drwxr-xr-x  2 root root       30 Apr 18 11:14 cmd
drwxr-xr-x  2 root root       97 Apr 18 11:15 docs
drwxr-xr-x  2 root root       40 Apr 18 11:15 drivers
-rw-r--r--  1 root root       49 Apr 18 11:14 go.mod
-rw-r--r--  1 root root     2080 Apr 25 15:41 junit.xml
-rw-r--r--  1 root root      126 Apr 18 11:14 OWNERS
-rw-r--r--  1 root root      315 Apr 18 11:14 perf.sh
drwxr-xr-x 16 root root      223 Apr 18 11:16 pkg
-rw-r--r--  1 root root     6444 Apr 18 11:14 README.md
drwxr-xr-x  2 root root     4096 Apr 18 11:15 reports
-rw-r--r--  1 root root     1485 Apr 18 11:14 run-e2e.sh
-rw-r--r--  1 root root      239 Apr 19 15:18 sh
drwxr-xr-x 11 root root      166 Apr 18 11:23 testing
-rw-r--r--  1 root root   271115 Apr 18 11:14 test.log
drwxr-xr-x 11 root root      215 Apr 18 11:26 vendor
 
#####编译好的工具,解压即用
链接:https://pan.baidu.com/s/1Ukv1g6SsNkgHCDZ0lxP-7Q 
提取码:xsm0 
--来自百度网盘超级会员V6的分享
  • 参数修改
clusterloader2的测试配置文件在testing目录下。可以参考修改配置
按修改后的测试配置文件,指定参数变量,执行clusterloader测试
[root@node1 clusterloader2]# cd testing/density/
You have mail in /var/spool/mail/root
[root@node1 density]# ll
total 32
drwxr-xr-x 2 root root   27 Apr 19 14:22 2000_nodes
drwxr-xr-x 2 root root   27 Apr 18 11:18 5000_nodes
drwxr-xr-x 2 root root   40 Apr 18 11:18 600_nodes
-rw-r--r-- 1 root root 9626 Apr 19 14:21 config.yaml  ####运行的文件
-rw-r--r-- 1 root root  968 Apr 19 14:25 deployment.yaml
-rw-r--r-- 1 root root 8583 Apr 18 11:16 high-density-config.yaml
drwxr-xr-x 5 root root   93 Apr 19 14:43 legacy
drwxr-xr-x 5 root root   78 Apr 18 11:23 scheduler
-rw-r--r-- 1 root root  543 Apr 18 11:16 scheduler-suite.yaml
###此文件中需要修改的参数如下:
1、Nodes,属于配置文件上下文参数,如果不指定,测试工具会抓取实际环境中的可用的节点数,进行设置
2、NODES_PER_NAMESPACE, 每个ns下的nodes数。这里需注意: NODES > NODES_PER_NAMESPACE
3、PODS_PER_NODE,每个节点下的pod数
4、MIN_LATENCY_PODS这个数值会跟 PODS_PER_NODE比较 选取最大的,作为LATENCY测试的参数。因为LATENCY测试一般使用较多pod 数,即$MIN_LATENCY_PODS
5、测试中会有测试使用的资源参数,这里需要对实际情况进行config.yaml调整。
•	LATENCY_POD_CPU
•	LATENCY_POD_MEMORY
•	其它自定义资源数量,可以在config.yaml文件中添加配置

此次运行pod数量如下:
•	NODES_PER_NAMESPACE 2
•	PODS_PER_NODE 40
•	MIN_LATENCY_PODS 40

####还需要修改次目录下的deployment.yaml文件,如下:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{.Name}}
  labels:
    group: {{.Group}}
spec:
  replicas: {{.Replicas}}
  selector:
    matchLabels:
      name: {{.Name}}
  template:
    metadata:
      labels:
        name: {{.Name}}
        group: {{.Group}}
    spec:
      nodeSelector:  ###添加此参数,让pod启动在hollow节点上。
        app: nginx
      containers:
      - image: 172.18.30.5:5000/pause:3.2
        imagePullPolicy: IfNotPresent
        name: {{.Name}}
        ports:
        resources:
          requests:
            cpu: {{.CpuRequest}}
            memory: {{.MemoryRequest}}
  • 工具运行
cd /root/perf-tests-release-1.18/clusterloader2
####运行如下命令,提换实际ip地址
[root@node1 clusterloader2]# ./clusterloader --kubeconfig=/root/.kube/config     --mastername=192.168.1.117   --masterip=192.168.1.117  --master-internal-ip=192.168.1.117   --testconfig=/root/go/perf-tests-release-1.18/clusterloader2/testing/density/config.yaml     --report-dir=/tmp     --alsologtostderr 2>&1 | tee /tmp/clusterload.log

###此工具会先启动三个名为exec-pod的pod,之后通过配置的depolyment启动pod。