运维相关中间件

Kubernetes基于HPA 实现 CPU、内存指标自动扩缩容

2020-05-13  本文已影响0人  TryCatch菌

搭建的基础

基于此篇博文的进一步实践

kubernetes 简单操作deployment,service,pod,标签

参考博文
Horizontal Pod Autoscaler Walkthrough

Kubernetes:HPA 详解-基于 CPU、内存和自定义指标自动扩缩容

k8s Pod的自动水平伸缩(HPA)


当系统资源过高的时候,我们可以使用kubectl scale 命令可以来实现 Pod 的扩缩容功能,但是这个过程是手动操作的。在实际项目中,我们需要做到是的是一个自动化感知并自动扩容的操作。Kubernetes 也为提供了这样的一个资源对象:Horizontal Pod Autoscaling(Pod 水平自动伸缩),简称HPA。
HPA 通过监控分析一些控制器控制的所有 Pod 的负载变化情况来自动动态调整pod的数量。
要使用 HPA,就需要在集群中安装 Metrics Server 服务,要安装 Metrics Server 就需要开启 Aggregator,因为 Metrics Server 就是通过该代理进行扩展的。这里我的集群环境是通过 Kubeadm 搭建的,默认已经开启了。

检查是否安装Mertics Sercer

kubectl api-versions

如果没有,就需要安装


image.png

安装Metrics Server

master节点执行
k8s通过集群内的资源监控系统(metrics-server),来获取集群中资源的使用状态。
根据CPU、内存、以及用户自定义的资源指标数据的使用量或连接数为参考依据,来制定一个临界点,一旦超出这个点,HPA就会自动创建出pod副本。

获取metrics server 配置文件
for i in auth-delegator.yaml auth-reader.yaml metrics-apiservice.yaml metrics-server-deployment.yaml metrics-server-service.yaml resource-reader.yaml ;do wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/metrics-server/$i;done

一共6个配置文件


image.png
metrics-server所需要的docker镜像

从metrics-server-deployment.yaml配置文件可以看出,需要使用两个镜像

image.png

如果可以科学上网在每台k8s服务器执行如下两个命令

docker pull k8s.gcr.io/metrics-server-amd64:v0.3.6
docker pull k8s.gcr.io/addon-resizer:1.8.7

如果无法克服网络情况,可以使用国内的镜像仓库拉取镜像然后使用docker load命令加载进去,如果tag标签不一样,需要改为一样

docker load --input xxx.tar

保证docker里面与这两个镜像


image.png
修改文件:metrics-server-deployment.yaml

不同的版本修改的不一样, 我这里使用的是metrics-server-amd64:v0.3.6

vim metrics-server-deployment.yaml

修改如下

image.png

修改后的yaml

kind: ConfigMap
metadata:
  name: metrics-server-config
  namespace: kube-system
  labels:
    kubernetes.io/cluster-service: "true"
    addonmanager.kubernetes.io/mode: EnsureExists
data:
  NannyConfiguration: |-
    apiVersion: nannyconfig/v1alpha1
    kind: NannyConfiguration
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: metrics-server-v0.3.6
  namespace: kube-system
  labels:
    k8s-app: metrics-server
    kubernetes.io/cluster-service: "true"
    addonmanager.kubernetes.io/mode: Reconcile
    version: v0.3.6
spec:
  selector:
    matchLabels:
      k8s-app: metrics-server
      version: v0.3.6
  template:
    metadata:
      name: metrics-server
      labels:
        k8s-app: metrics-server
        version: v0.3.6
      annotations:
        seccomp.security.alpha.kubernetes.io/pod: 'docker/default'
    spec:
      priorityClassName: system-cluster-critical
      serviceAccountName: metrics-server
      nodeSelector:
        kubernetes.io/os: linux
      containers:
      - name: metrics-server
        image: k8s.gcr.io/metrics-server-amd64:v0.3.6
        command:
        - /metrics-server
        - --metric-resolution=30s
        - --kubelet-insecure-tls # 不能做TLS加密认证,使用不安全的通信,这里有的博文要加,有的没加也没问题,这里加上
        # These are needed for GKE, which doesn't support secure communication yet.
        # Remove these lines for non-GKE clusters, and when GKE supports token-based auth.
        
        #- --kubelet-port=10255   # 需要注释
        #- --deprecated-kubelet-completely-insecure=true # 需要注释
        - --kubelet-preferred-address-types=InternalIP,Hostname,InternalDNS,ExternalDNS,ExternalIP
        ports:
        - containerPort: 443
          name: https
          protocol: TCP
      - name: metrics-server-nanny
        image: k8s.gcr.io/addon-resizer:1.8.7
        resources:
          limits:
            cpu: 100m
            memory: 300Mi
          requests:
            cpu: 5m
            memory: 50Mi
        env:
          - name: MY_POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: MY_POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
        volumeMounts:
        - name: metrics-server-config-volume
          mountPath: /etc/config
        command:
          # 下面这些{{xxxxx}}需要替换,不替换,启动metrics-server-nanny容器时会报错
          - /pod_nanny
          - --config-dir=/etc/config
          # 设置metrics-server基本运行可用CPU豪核数量,测试设置100m,也可以注释掉
          #- --cpu={{ base_metrics_server_cpu }}
          - --extra-cpu=0.5m
          # #分配给metrics-server基本运行的内存大小, 测试设置 80Mi,根据自己服务器性能设置
          #- --memory={{ base_metrics_server_memory }}
          - --memory=80Mi
          # #每个节点上的metrics-server额外分配内存大小,测试8Mi,根据自己服务器性能设置
          #- --extra-memory={{ metrics_server_memory_per_node }}Mi
          - --extra-memory=8Mi
          - --threshold=5
          - --deployment=metrics-server-v0.3.6
          - --container=metrics-server
          - --poll-period=300000
          - --estimator=exponential
          # Specifies the smallest cluster (defined in number of nodes)
          # resources will be scaled to.
          # 设置启动几组Metrics-server,选项说明提示默认是16组. 可以注释掉了
          #- --minClusterSize={{ metrics_server_min_cluster_size }}
      volumes:
        - name: metrics-server-config-volume
          configMap:
            name: metrics-server-config


修改配置文件resource-reader.yaml
vim resource-reader.yaml

添加如下参数


image.png

修改后的yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: system:metrics-server
  labels:
    kubernetes.io/cluster-service: "true"
    addonmanager.kubernetes.io/mode: Reconcile
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - nodes
  - namespaces
  - nodes/stats # nodes/stats和nodes是两个不同的资源. nodes/stats是获取节点监控数据的专用资源
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - "apps"
  resources:
  - deployments
  verbs:
  - get
  - list
  - update
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: system:metrics-server
  labels:
    kubernetes.io/cluster-service: "true"
    addonmanager.kubernetes.io/mode: Reconcile
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:metrics-server
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system

安装Metrics Server

2个配置文件修改完成后,在6个配置文件的目录下执行

kubectl apply -f .

第一次执行会显示create,后面修改后执行会显示如下

image.png
验证是否安装成功
kubectl get pod -n kube-system

成功,显示如下

image.png

测试获取node信息

kubectl top nodes
image.png

测试获取pod信息

kubectl top pod
image.png

如果显示如下错误,等待一会再次执行

error: metrics not available yet

如果还是不行,通过如果下两个命令查询出报错信息
kubectl logs 后面跟的是通过kubectl get pod -n kube-system 查询出的name

kubectl logs metrics-server-v0.3.6-6f9474fc7d-z4564 -c metrics-server -n kube-system

kubectl logs metrics-server-v0.3.6-6f9474fc7d-z4564  -c metrics-server-nanny -n kube-system

如果出现如下报错,重启pod所在节点重启kubelet

the server is currently unable to handle the request (get nodes.metrics.k8s.io)
image.png

创建pod

这里和之前的那个demo博客不同,我们需要设置pod节点的资源使用率

基础概念

在K8s的资源:
 CPU:
  我们知道2核2线程的CPU,可被系统识别为4个逻辑CPU,在K8s中对CPU的分配限制是对逻辑CPU做分片限制的。
  也就是说分配给容器一个CPU,实际是分配一个逻辑CPU。
  而且1个逻辑CPU还可被单独划分子单位,即 1个逻辑CPU,还可被划分为1000个millicore(毫核), 简单说就是1个逻辑CPU,继续逻辑分割为1000个豪核心。
  豪核:可简单理解为将CPU的时间片做逻辑分割,每一段时间片就是一个豪核心。
  所以:500m 就是500豪核心,即0.5个逻辑CPU.

内存:
  K,M,G,T,P,E #通常这些单位是以1000为换算标准的。
  Ki, Mi, Gi, Ti, Pi, Ei #这些通常是以1024为换算标准的。

k8s pod 配置之 resources 中 含义

limit对应资源量的上限, 既最多允许使用这个上限的资源量, 由于cpu是可压缩的, 进程是无法突破上限的, 而memory是不可压缩资源, 当进程试图请求超过limit限制时的memory, 此进程就会被kubernetes杀掉
对于cpu和内存而言, pod的request和limit是指该pod中所有容器的 Requests或Limits的总和。

例如: 某个节点cpu资源充足, 而内存为4G,其中3GB可以运行pod, 而某个pod的memory request为1GB, limit为2GB, 那么这个节点上最多可以运行3个这样的pod
待调度pod的request值总和超过该节点提供的空闲资源, 不会调度到该节点node上;

image.png

deployment.yaml

apiVersion: apps/v1 #apiVersion是当前配置格式的版本
kind: Deployment #kind是要创建的资源类型
metadata:  #metadata是该资源的元数据,name是必须的元数据项
  #指定deployment的名称
  name: demo-deployment
  labels:
    app: ecs-demo  #标签
spec:
  #期望创建1个实例(1个pod)
  replicas: 1
  selector: # .spec.selector 必须匹配 .spec.template.metadata.labels,否则它将被API拒绝。如果 .spec.selector 没有被指定, .spec.selector.matchLabels 默认是 .spec.template.metadata.labels
    #选择label:app=ecs-demo的pod来创建实例
    matchLabels:   #metadata定义Pod的元数据,至少要顶一个label,label的key和value可以任意指定
      app: ecs-demo
  template:
    metadata:
      labels:
        app: ecs-demo
    spec:
      containers:
      - name: ecs-demo
        image: wangzhh/login_demo:20200429   # docker imange地址  REPOSITORY:TAG
        ports:
        - containerPort: 8080 #暴露给service的地址
        resources:
          requests:
            cpu: 500m # podcpu占用最小资源,根据服务器性能设置
            memory: 512Mi # pod占用最小内存,根据服务器性能设置
          limits:
            cpu: 1000m # pod占用cpu大资源,根据服务器性能设置
            memory: 1024Mi # pod占用最大内存,根据服务器性能设置
        readinessProbe: #就绪探针
          httpGet:
            port: 8080
            path: /
          initialDelaySeconds: 50 # initialDelaySeconds这个参数 机器新能不好调大
          periodSeconds: 10
        livenessProbe:
          httpGet:
            path: /
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 50 # initialDelaySeconds这个参数 机器新能不好调大
          periodSeconds: 10

在master节点执行命令

kubectl create -f deployment.yaml

创建service

service.yaml

apiVersion: v1 #apiVersion是当前配置格式的版本
kind: Service #kind是要创建的资源类型
metadata: #metadata是该资源的元数据,name是必须的元数据项
  name: demo-service
spec:
  selector: # selector 指明挑选那些 label 为 run: xx 的 Pod 作为 Service 的后端。
    app: ecs-demo
  ports:  #将Service 的 8080 端口映射到 Pod 的 8080 端口,使用 TCP 协议
  - protocol: TCP
    port: 8080
    targetPort: 8080
    nodePort: 30036  # nodePort,它指定节点上开放的端口值 端口范围只能是 30000-32767,如果不指定这个端口,系统将选择一个随机端口
  sessionAffinity: ClientIP # service内部实现session保持
  sessionAffinityConfig:
    clientIP:
        timeoutSeconds: 10800 # timeoutSeconds指的是session保持的时间,这个时间默认是10800秒,也就是三个小时
  type: NodePort # 暴露service的三种方式 NodePort,LoadBalancer 和 Ingress 

在master节点执行命令

kubectl create -f service.yaml

创建HPA

这里我们通过yaml的方式发布hpa,当然也可以使用下面的命令,简单的发布

kubectl autoscale deployment xxxx --cpu-percent=50 --min=1 --max=10
可以使用的版本

通过命令可以查看到kubectl api-versions

autoscaling/v1         #只支持通过cpu为参考依据,来改变pod副本数
autoscaling/v2beta1    #支持通过cpu、内存、连接数以及用户自定义的资源指标数据为参考依据。
autoscaling/v2beta2    #与v2beta1差不多,小的变动
image.png
一些查询命令

此命令可以查询到系统使用的版本

kubectl explain hpa
image.png

此命令可以指定版本

kubectl explain hpa --api-version=autoscaling/v2beta1 
通过yaml配置HPA 实现 CPU、内存指标自动扩缩容

基于cpu和内存指标的HPA yaml脚本

apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
  name: demo-hpa-beta1
  namespace: default
spec:
  minReplicas: 1         ##至少1个副本
  maxReplicas: 5         ##最多5个副本
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: demo-deployment # 创建的deploment文件里面的name
  metrics:
  - type: Resource
    resource:
      name: cpu
      targetAverageUtilization: 50  ##注意此时是根据使用率,也可以根据使用量:targetAverageValue
  - type: Resource
    resource:
      name: memory
      targetAverageUtilization: 50  ##注意此时是根据使用率,也可以根据使用量:targetAverageValue

创建HPA

kubectl apply -f hpa.yaml 
image.png

查看是否创建成功

kubectl get hpa
image.png

此命令可查看详细信息,如果没成功可用作报错排查

kubectl describe hpa
image.png

这个时候我们get下pod可以看到只有一个pod

image.png

测试

使用压力测试命令调用tomcat,测试是否自动扩容
安装命令

yum install httpd-tools

测试

ab -c 100 -n 5000000 http://10.211.55.9:30036/

再次查看hpa,发现操过上限


image.png

获取pod查看,自动扩容到4个pod


image.png

查看pod资源使用情况,满足预期


image.png

停止压力测试,等待一段时间,发现只有一个pod存在

到此,k8s自动扩缩容完成

上一篇下一篇

猜你喜欢

热点阅读