Pod定时伸缩

最近更新时间:2020-08-17 17:29:08

CronHPA是Kubernetes中Pod水平扩展功能的一种,Kubernetes中的HPA是基于监控度量来定义并驱动Pod水平扩展缩容的,而CronHPA是根据crontab的方式,定期性的对Pod水平进行扩展缩容操作。
CronHPA支持任意规模类型资源的扩展缩容操作,其中包括Deployment和StatefulSet等。

使用场景

通过运维经验积累掌握负载规律后,可以使用CronHPA实现定期自动扩展缩容操作,以应对可预期的业务需求。

使用说明

前提条件

您已使用金山云容器引擎服务创建一个正常运行的Kubernetes集群,关于如何创建集群,请参见创建集群

CronHPA插件安装

  • 进入容器集群内任意节点,创建cron-hpa.yaml
$ kubectl apply -f cron-hpa.yaml
  • cron-hpa.yaml如下:
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  creationTimestamp: null
  labels:
    controller-tools.k8s.io: "1.0"
  name: cronhorizontalpodautoscalers.autoscaling.kce.ksyun.com
spec:
  group: autoscaling.kce.ksyun.com
  names:
    kind: CronHorizontalPodAutoscaler
    plural: cronhorizontalpodautoscalers
    shortNames:
      - cronhpa
  scope: Namespaced
  validation:
    openAPIV3Schema:
      properties:
        apiVersion:
          description: 'APIVersion defines the versioned schema of this representation
            of an object. Servers should convert recognized schemas to the latest
            internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources'
          type: string
        kind:
          description: 'Kind is a string value representing the REST resource this
            object represents. Servers may infer this from the endpoint the client
            submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds'
          type: string
        metadata:
          type: object
        spec:
          properties:
            jobs:
              items:
                properties:
                  name:
                    type: string
                  schedule:
                    type: string
                  targetSize:
                    format: int32
                    type: integer
                required:
                - name
                - schedule
                - targetSize
                type: object
              type: array
            scaleTargetRef:
              description: 'INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
                Important: Run "make" to regenerate code after modifying this file'
              properties:
                apiVersion:
                  type: string
                kind:
                  type: string
                name:
                  type: string
              required:
              - apiVersion
              - kind
              - name
              type: object
          required:
          - scaleTargetRef
          - jobs
          type: object
        status:
          properties:
            conditions:
              description: 'INSERT ADDITIONAL STATUS FIELD - define observed state
                of cluster Important: Run "make" to regenerate code after modifying
                this file'
              items:
                properties:
                  jobId:
                    type: string
                  lastProbeTime:
                    format: date-time
                    type: string
                  message:
                    description: Human readable message indicating details about last
                      transition.
                    type: string
                  name:
                    description: Type of job condition, Complete or Failed.
                    type: string
                  schedule:
                    type: string
                  state:
                    type: string
                required:
                - name
                - jobId
                - schedule
                - state
                - lastProbeTime
                - message
                type: object
              type: array
          required:
          - conditions
          type: object
  version: v1beta1
status:
  acceptedNames:
    kind: ""
    plural: ""
  conditions: []
  storedVersions: []
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: kubernetes-cronhpa-controller-role
rules:
- apiGroups: [""]
  resources: ["*"]
  verbs:
  - get
  - list
  - watch
  - update
- apiGroups:
  - extensions
  resources: ["*"]
  verbs:
  - get
  - list
  - watch
  - update
- apiGroups:
  - apps
  resources: ["*"]
  verbs:
  - get
  - list
  - watch
  - update
- apiGroups: [""]
  resources: ["events"]
  verbs:
  - get
  - list
  - watch
  - create
  - update
  - patch
- apiGroups: [""]
  resources: ["configmaps"]
  verbs:
    - get
    - create
    - update
- apiGroups:
  - autoscaling.kce.ksyun.com
  resources:
  - cronhorizontalpodautoscalers
  verbs:
  - get
  - list
  - watch
  - create
  - update
  - patch
- apiGroups:
  - autoscaling
  resources:
  - horizontalpodautoscalers
  verbs:
  - get
  - list
  - watch
  - create
  - update
  - patch
  - delete
- apiGroups:
  - admissionregistration.k8s.io
  resources:
  - mutatingwebhookconfigurations
  - validatingwebhookconfigurations
  verbs:
  - get
  - list
  - watch
  - create
  - update
  - patch
  - delete
- apiGroups:
  - apps.kruise.io
  resources:
  - statefulsets/scale
  - uniteddeployments/scale
  - clonesets/scale
  verbs:
  - get
  - list
  - watch
  - update
  - patch
- apiGroups:
  - autoscaling.kce.ksyun.com
  resources:
  - elasticworkloads/scale
  verbs:
  - get
  - list
  - watch
  - update
  - patch
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: kubernetes-cronhpa-controller
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  creationTimestamp: null
  name: kubernetes-cronhpa-controller-rolebinding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: kubernetes-cronhpa-controller-role
subjects:
- kind: ServiceAccount
  name: kubernetes-cronhpa-controller
  namespace: kube-system
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kubernetes-cronhpa-controller
  namespace: kube-system
  labels:
    app: kubernetes-cronhpa-controller
    controller-tools.k8s.io: "2.0"
spec:
  replicas: 1 # The default is primary and standby mode (currently cold standby)
  selector:
    matchLabels:
      app: kubernetes-cronhpa-controller
      controller-tools.k8s.io: "2.0"
  template:
    metadata:
      labels:
        app: kubernetes-cronhpa-controller
        controller-tools.k8s.io: "2.0"
    spec:
      containers:
      - image: hub.kce.ksyun.com/ksyun/kubernetes-cronhpa-controller:v1.0.0
        imagePullPolicy: Always
        name: kubernetes-cronhpa-controller
        env:
        - name: TZ
          value: "Asia/Shanghai"
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
          requests:
            cpu: 100m
            memory: 100Mi
      serviceAccount: kubernetes-cronhpa-controller
  • 查看插件是否安装成功
# 查看自定义资源是否安装
$ kubectl api-resources | grep cronhpa
cronhorizontalpodautoscalers      cronhpa      autoscaling.kce.ksyun.com      true         CronHorizontalPodAutoscaler

# 查看CronHPA controller是否安装
$ kubectl get deploy kubernetes-cronhpa-controller -n kube-system
NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-cronhpa-controller   1/1     1            1                 4m11s

功能测试

成功安装CronHPA插件后,以下举例如何部署具体的cronhpa并进行测试。

  • 部署测试对象与cronhpa。
$ kubectl apply -f cronhpa-example.yaml
  • cronhpa-example.yaml如下:
---
apiVersion: apps/v1 # for versions before 1.8.0 use apps/v1beta1
kind: Deployment
metadata:
  name: nginx-deployment-basic
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9 # replace it with your exactly <image_name:tags>
        ports:
        - containerPort: 80

---     
apiVersion: autoscaling.kce.ksyun.com/v1beta1
kind: CronHorizontalPodAutoscaler
metadata:
  labels:
    controller-tools.k8s.io: "1.0"
  name: cronhpa-sample
spec:
   scaleTargetRef:
      apiVersion: apps/v1beta2
      kind: Deployment
      name: nginx-deployment-basic
   excludeDates:
   - "* * * 15 11 *"                            # exclude November 15th
   - "* * * * * 5"                              # exclude every Friday
   jobs:
   - name: "scale-down"
     schedule: "30 */1 * * * *"                 # 每分钟的第30秒,将deployment/nginx-deployment-basic 副本数调整为 1 
     targetSize: 1
   - name: "scale-up"
     schedule: "0 */1 * * * *"                  # 每分钟的第0秒,将deployment/nginx-deployment-basic 副本数调整为 3
     targetSize: 3
  • 各字段的解释说明如下:
字段说明备注
scaleTargetRefscaleTargetRef指定去扩大缩容对象。如果对象支持scale子资源,cronhpa即可支持除比例子资源外,还支持HPA,以稳定性优先原则,在扩展缩容时,以cronHPA与HPA设置副本数中截断值作为扩展缩容最终值
excludeDatesexcludeDates 是日期数组。当遇到符合excludeDates 描述的日期时任务将会被跳过最小单位为天
jobs 支持在一个规格中设置多个cronhpa任务。每个cronhpa任务可以配置以下分段:
- name:它在一个cronhpa中应是唯一的,这样就可以通过name 来区分不同的任务
- schedule:它的策略和crontab类似
- targetSize:到计划时间时,您想扩缩容到的Pod的数量
- runOnce:如果runOnce 设置为true ,那么任务将只执行一次,第一次执行完则exit
cron表达式格式:
Field nameMandatoryAllowed valuesAllowed special characters
SecondsYes0-59* / , -
MinutesYes0-59* / , -
HoursYes0-23* / , -
Day of monthYes1-31* / , - ?
MonthYes1-12 or JAN-DEC* / , -
Day of weekYes0-6 or SUN-SAT* / , - ?
  • 查看 cronhpa 实例
$ kubectl get cronhpa 
NAME             AGE
cronhpa-sample   15s
  • 查看cronhpa/cronhpa-sample详情
$ kubectl describe cronhpa cronhpa-sample
Events:
  Type    Reason  Age            From                                   Message
  ----    ------  ----           ----                                   -------
  Normal  Succeed  8m31s                cron-horizontal-pod-autoscaler  cron hpa job scale-down executed successfully. current replicas:2, desired replicas:1.
  Normal  Succeed  31s (x8 over 7m31s)  cron-horizontal-pod-autoscaler  cron hpa job scale-down executed successfully. current replicas:3, desired replicas:1.
  Normal  Succeed  1s (x9 over 8m1s)    cron-horizontal-pod-autoscaler  cron hpa job scale-up executed successfully. current replicas:1, desired replicas:3.
  • 查看 deploy/nginx-deployment-basic 副本数状态变化情况
$ kubectl get deploy nginx-deployment-basic  -w
NAME                    READY   UP-TO-DATE   AVAILABLE      AGE
nginx-deployment-basic   1/1      1          1             3m31s
nginx-deployment-basic   1/3      1          1             3m48s
nginx-deployment-basic   1/3      1          1             3m48s
nginx-deployment-basic   1/3      3          1             3m48s   
nginx-deployment-basic   2/3      3          2             3m50s
nginx-deployment-basic   3/3      3          3             3m50s
nginx-deployment-basic   3/1      3          3             4m18s
nginx-deployment-basic   3/1      3          3             4m18s
nginx-deployment-basic   1/1      1          1             4m18s
nginx-deployment-basic   1/3      1          1             4m48s
nginx-deployment-basic   1/3      1          1             4m48s
nginx-deployment-basic   1/3      1          1             4m48s
nginx-deployment-basic   1/3      3          1             4m48s
nginx-deployment-basic   2/3      3          2             4m49s
nginx-deployment-basic   3/3      3          3             4m49s

金山云,开启您的云计算之旅

免费注册