前言:

Kubernetes HPA是指k8s水平扩缩容,一般指的是一个部署好的应用指定了请求cpu内存限制,超过这个限制量会自动进行扩容pod。接下来我们亲自试验hpa吧。

准备工作:

在试验之前,我们需要给k8s集群安装指标服务(metrics server)。

如果是Mac环境大家可以直接用brew 安装 helm

brew install helm

再用helm 安装 metrics server。不过需要中途编辑部署文件。加上部分command内容。编辑好后跟vi编辑器一样的。:wq可退出编辑。它会自动帮你重新部署的。

 

command:
           - /metrics-server
           - --kubelet-insecure-tls
           - --kubelet-preferred-address-types=InternalIP,Hostname,ExternalIP
           - --metric-resolution=30shelm install stable/metrics-server --version 2.11.0 --set registry.cn-shanghai.aliyuncs.com/google_containers/metrics-server-amd64 --generate-name -n kube-system
kubectl edit deployments.apps $(kubectl get deployments -n kube-system|grep metrics-server|awk '{print $1}') -n kube-system
https://github.com/kubernetes-sigs/metrics-server 考虑到部署yaml镜像来源于google。我这边为大家提前准备好了。
默认镜像地址:k8s.gcr.io/metrics-server/metrics-server:v0.3.7
  阿里镜像地址:registry.cn-shanghai.aliyuncs.com/k8sgcrio_containers/metrics-server:v0.3.7
  部署文件地址:https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.3.7/components.yaml
  下载不了的话我贴在下面👇。需要注意的是,里面有个command记得加哦。复制我的准没错!我用的版本1.18以上版本,其他版本可能还是有bug的。如果你们安装不上,可以尝试部署在master节点上,你们要把污点去掉。然后再把每台master节点做个标记。后面可以用nodeSelector进行部署匹配。只有需要部署在master的应用才推荐这样使用,部署好记得再还原污点。执行如下命令:
kubectl taint nodes --all node-role.kubernetes.io/master-
kubectl label nodes master00 node-role=master
kubectl label nodes master01 node-role=master
kubectl label nodes master02 node-role=master
还原污点命令:
kubectl taint nodes master00 node-role.kubernetes.io/master=:NoSchedule
kubectl taint nodes master01 node-role.kubernetes.io/master=:NoSchedule
kubectl taint nodes master02 node-role.kubernetes.io/master=:NoSchedule

 

 components.yaml

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: system:aggregated-metrics-reader
  labels:
    rbac.authorization.k8s.io/aggregate-to-view: "true"
    rbac.authorization.k8s.io/aggregate-to-edit: "true"
    rbac.authorization.k8s.io/aggregate-to-admin: "true"
rules:
- apiGroups: ["metrics.k8s.io"]
  resources: ["pods", "nodes"]
  verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: metrics-server:system:auth-delegator
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:auth-delegator
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: metrics-server-auth-reader
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: apiregistration.k8s.io/v1beta1
kind: APIService
metadata:
  name: v1beta1.metrics.k8s.io
spec:
  service:
    name: metrics-server
    namespace: kube-system
  group: metrics.k8s.io
  version: v1beta1
  insecureSkipTLSVerify: true
  groupPriorityMinimum: 100
  versionPriority: 100
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: metrics-server
  namespace: kube-system
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: metrics-server
  namespace: kube-system
  labels:
    k8s-app: metrics-server
spec:
  selector:
    matchLabels:
      k8s-app: metrics-server
  template:
    metadata:
      name: metrics-server
      labels:
        k8s-app: metrics-server
    spec:
      serviceAccountName: metrics-server
      volumes:
      # mount in tmp so we can safely use from-scratch images and/or read-only containers
      - name: tmp-dir
        emptyDir: {}
      containers:
      - name: metrics-server
        image: registry.cn-shanghai.aliyuncs.com/k8sgcrio_containers/metrics-server:v0.3.7
        imagePullPolicy: IfNotPresent
        command:
          - /metrics-server
          - --kubelet-insecure-tls
          - --kubelet-preferred-address-types=InternalIP,Hostname,ExternalIP
          - --metric-resolution=30s
        args:
          - --cert-dir=/tmp
          - --secure-port=4443
        ports:
        - name: main-port
          containerPort: 4443
          protocol: TCP
        securityContext:
          readOnlyRootFilesystem: true
          runAsNonRoot: true
          runAsUser: 1000
        volumeMounts:
        - name: tmp-dir
          mountPath: /tmp
#如果有啥问题,可以尝试安装master节点
      #nodeSelector:
        #node-role: master
---
apiVersion: v1
kind: Service
metadata:
  name: metrics-server
  namespace: kube-system
  labels:
    kubernetes.io/name: "Metrics-server"
    kubernetes.io/cluster-service: "true"
spec:
  selector:
    k8s-app: metrics-server
  ports:
  - port: 443
    protocol: TCP
    targetPort: main-port
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: system:metrics-server
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - nodes
  - nodes/stats
  - namespaces
  - configmaps
  verbs:
  - get
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: system:metrics-server
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:metrics-server
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system

开始部署:

[root@client ~]# kubectl apply -f components.yaml
[root@client ~]# kubectl get pods -n kube-system|grep metrics
metrics-server-5987bb5dff-kwzl9                      1/1     Running   0          38m

试验:

hpa.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: php-apache
spec:
  selector:
    matchLabels:
      run: php-apache
  replicas: 1
  template:
    metadata:
      labels:
        run: php-apache
    spec:
      containers:
      - name: php-apache
        image: registry.cn-shanghai.aliyuncs.com/k8sgcrio_containers/hpa-example
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: 500m
          requests:
            cpu: 200m
---
apiVersion: v1
kind: Service
metadata:
  name: php-apache
  labels:
    run: php-apache
spec:
  ports:
  - port: 80
  selector:
    run: php-apache

 部署hpa示例

[root@client ~]# kubectl apply -f hpa.yaml 
deployment.apps/php-apache created
service/php-apache created
[root@client ~]# kubectl get pods
NAME                         READY   STATUS    RESTARTS   AGE
php-apache-b6968c487-ldmml   1/1     Running   0          55s
[root@client ~]# kubectl top pods
NAME                         CPU(cores)   MEMORY(bytes)   
php-apache-b6968c487-ldmml   1m           7Mi

 创建水平Pod自动缩放器,参数cpu-percent指的是cpu的百分比。超过%50即扩容1个pod。min是最小pod数,max最大pod数。

创建好,一般要个30s左右才能获取到相关指标。你们可以看到TARGETS栏,会有<unknow>。给它点时间!

[root@client ~]# kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10
horizontalpodautoscaler.autoscaling/php-apache autoscaled
[root@client ~]# kubectl get hpa
NAME         REFERENCE               TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   <unknown>/50%   1         10        0          8s
[root@client ~]# kubectl get hpa
NAME         REFERENCE               TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   <unknown>/50%   1         10        0          13s
[root@client ~]# kubectl get hpa
NAME         REFERENCE               TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   <unknown>/50%   1         10        0          15s
[root@client ~]# kubectl get hpa
NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   0%/50%    1         10        1          19s
[root@client ~]# kubectl get hpa
NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   0%/50%    1         10        1          22s
[root@client ~]#

再开一个窗口。我们需要对部署的应用进行请求负载。

[root@client ~]# kubectl run -it --rm load-generator --image=busybox /bin/sh
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
If you don't see a command prompt, try pressing enter.
/ # while true; do wget -q -O- http://php-apache; done
OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!

现在继续查看hpa信息

[root@client ~]# kubectl get hpa
NAME         REFERENCE               TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   251%/50%   1         10        4          6m26s
[root@client ~]# kubectl get pods
NAME                             READY   STATUS    RESTARTS   AGE
load-generator-dbf8dc997-lhjwh   1/1     Running   0          2m48s
php-apache-b6968c487-6kq6g       1/1     Running   0          101s
php-apache-b6968c487-cpbs4       1/1     Running   0          116s
php-apache-b6968c487-kszmp       1/1     Running   0          101s
php-apache-b6968c487-ldmml       1/1     Running   0          12m
[root@client ~]#

大家可以看到Replicas开始增加了,也就是pod数量。TARGES百分比也在增加。这说明负载测试成功了!

接下来暂停负载程序,按住ctrl+c即可。等个五分钟吧!!!然后hpa就自动缩回去。

[root@client ~]# kubectl get hpa
NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   0%/50%    1         10        1          14m
[root@client ~]#