K8S集群运维-HPA自动扩缩容与资源限制

1. Pod的资源限制 K8S当中,对于Deployment控制器可以通过sepc.template.spec.containers.resource配置去对单个容器所使用的资源进行限制。需要注意的是,这里配置的是容器的资源,而不是Pod的资源,因为一个Pod当中可能存在有多个容器。最终配置的格式应

1. Pod的资源限制

K8S当中,对于Deployment控制器可以通过sepc.template.spec.containers.resource配置去对单个容器所使用的资源进行限制。需要注意的是,这里配置的是容器的资源,而不是Pod的资源,因为一个Pod当中可能存在有多个容器。最终配置的格式应该参考如下:

spec:
  template:
    spec:
      containers:
          image: ...
          imagePullPolicy: IfNotPresent
          resources:
            requests:
              cpu: 100m
              memory: 90Mi
            limits:
              cpu: 100m
              memory: 90Mi

可以通过requests去配置初始申请的CPU和内存资源的量,通过limits去配置容器允许的最多使用的CPU和内存资源的量。

  • 对于CPU,在K8S当中,将一核CPU拆分成为1000m,如果是100m,那么就代表0.1个CPU核心,500m就代表0.5个CPU核心。
  • 对于内存,可以使用Mi和Gi单位,例如90Mi、5Gi。

2. HPA自动扩缩容配置

我们现在部署了一个Ingress服务,我们想要实现Ingress-Controller可以根据机器的负载(比如CPU和内存)进行自动扩容机器,避免Ingress-Controller机器扛不住流量。

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.12.0-beta.0
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  minReadySeconds: 0
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app.kubernetes.io/component: controller
      app.kubernetes.io/instance: ingress-nginx
      app.kubernetes.io/name: ingress-nginx
  strategy:
    rollingUpdate:
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      labels:
        app.kubernetes.io/component: controller
        app.kubernetes.io/instance: ingress-nginx
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
        app.kubernetes.io/version: 1.12.0-beta.0
    spec:
      containers:
        - args:
            - /nginx-ingress-controller
            - --publish-service=$(POD_NAMESPACE)/ingress-nginx-controller
            - --election-id=ingress-nginx-leader
            - --controller-class=k8s.io/ingress-nginx
            - --ingress-class=nginx
            - --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
            - --validating-webhook=:8443
            - --validating-webhook-certificate=/usr/local/certificates/cert
            - --validating-webhook-key=/usr/local/certificates/key
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: LD_PRELOAD
              value: /usr/local/lib/libmimalloc.so
          image: wanna1314y.top:1443/library/nginx-ingress-controller:latest
          imagePullPolicy: IfNotPresent
          lifecycle:
            preStop:
              exec:
                command:
                  - /wait-shutdown
          livenessProbe:
            failureThreshold: 5
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            initialDelaySeconds: 10
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 1
          name: controller
          ports:
            - containerPort: 80
              name: http
              protocol: TCP
            - containerPort: 443
              name: https
              protocol: TCP
            - containerPort: 8443
              name: webhook
              protocol: TCP
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            initialDelaySeconds: 10
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 1
          resources:
            requests:
              cpu: 100m
              memory: 90Mi
          securityContext:
            allowPrivilegeEscalation: false
            capabilities:
              add:
                - NET_BIND_SERVICE
              drop:
                - ALL
            readOnlyRootFilesystem: false
            runAsGroup: 82
            runAsNonRoot: true
            runAsUser: 101
            seccompProfile:
              type: RuntimeDefault
          volumeMounts:
            - mountPath: /usr/local/certificates/
              name: webhook-cert
              readOnly: true
      dnsPolicy: ClusterFirst
      nodeSelector:
        kubernetes.io/os: linux
      serviceAccountName: ingress-nginx
      terminationGracePeriodSeconds: 300
      volumes:
        - name: webhook-cert
          secret:
            secretName: ingress-nginx-admission

对于上述我们通过Deployment去部署的Ingress-Controller机器,我们通过如下的配置指定申请CPU的核心数是0.1个核心,内存为90M。我们想要实现,Pod的CPU使用量超过50%时,就自动将Ingress-Controller进行扩容,避免扛不住流量导致挂掉。

          resources:
            requests:
              cpu: 100m
              memory: 90Mi

我们可以基于K8S的HPA(HorizontalPodAutoscaler)去实现,我们定义如下的K8S的HPA资源,让ingress-nginx-controller这个Deployment可以根据CPU的使用情况进行自动扩缩容。

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: ingress-controller-hpa
  namespace: ingress-nginx
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: ingress-nginx-controller
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50

我们限制最小副本数为2,最大副本数为10,扩容阈值是CPU使用情况超过50%,意味着当机器CPU超过50%时,HPA会自动帮我们进行扩容,当机器CPU使用低于50%时,K8S会帮我们进行缩容,最小只能缩容到2个副本。

K8S的HPA采用的扩缩容策略是,快扩慢缩的机制:

  • 快扩:当CPU高于50%时,HPA立刻进行扩容。原因在于,CPU高于50%,意味着流量升高,必须很快把机器扩起来,才能注意应对新增的用户流量。
  • 慢缩:当CPU使用率低于50%,HPA不立刻进行缩容,而是会等待一会儿才尝试进行缩容。原因在于,如果立刻根据CPU缩容,那么如果后面又来一个高峰期的流量,剩余的Pod可能是不足以应对流量的,可以暂时将之前扩容起来的Pod留着,等到高峰期已经过去时,再将机器缩容下去。

需要注意的是,在使用HPA之前,必须需要先安装K8S的metrics-server组件,用来支持去采集Node和Pod的CPU和内存使用情况,HPA会根据metrics-server提供的指标,进行HPA的扩容和缩容。

3. 资源限制ResourceQuota

在K8S当中,可以通过ResourceQuota去对单个Namespace的资源进行限制,借助ResourceQuota可以对Namespace下的POD数,CPU核数,内存空间,ConfigMap数量,Secret数量等进行限制。

资源清单参考如下的配置:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: ingress-quota
  namespace: ingress-nginx
spec:
  hard:
    pods: 10                     # 限制最多 10 个 Pod
    requests.cpu: "2"            # 总 CPU 请求最多 2 核
    requests.memory: "4Gi"       # 总内存请求最多 4 GiB
    limits.cpu: "4"              # 总 CPU 限制最多 4 核
    limits.memory: "8Gi"         # 总内存限制最多 8 GiB
    persistentvolumeclaims: 5    # 限制最多 5 个 PVC
    requests.storage: "50Gi"     # 总存储请求最多 50 GiB
    configmaps: 10               # 限制最多 10 个 ConfigMap
    secrets: 10                  # 限制最多 10 个 Secret
    services: 5                  # 限制最多 5 个 Service
    services.nodeports: 2        # 限制最多 2 个 NodePort 类型的 Service
    services.loadbalancers: 1    # 限制最多 1 个 LoadBalancer 类型的 Service
Comment