只要容器服务Kubernetes版中的Java应用接入了AHAS应用防护组件后,您的应用实例就可以自动根据AHAS应用防护收集的指标(如QPS、平均响应时间等)进行弹性伸缩,系统可以自动根据实时的流量情况进行扩缩容,保证系统的可用性。本文介绍如何为接入了AHAS应用防护,且在容器服务Kubernetes版中部署的应用配置水平弹性伸缩。

前提条件

背景信息

弹性伸缩可以从调度层弹性,主要是负责修改负载的调度容量变化。例如,容器水平伸缩HPA(Horizontal Pod Autoscaling)是典型的调度层弹性组件,通过HPA可以调整应用的副本数,调整的副本数会改变当前负载占用的调度容量,从而实现调度层的伸缩。弹性伸缩是阿里云容器服务Kubernetes版ACK(Alibaba Cloud Container Service for Kubernetes)上被广泛采用的功能,更多信息,请参见弹性伸缩概述

步骤一:安装alibaba-cloud-metrics-adapter

您可以通过alibaba-cloud-metrics-adapter使用云指标进行Pod的水平伸缩(HPA)。

  1. 登录容器服务管理控制台
  2. 在控制台左侧导航栏,选择市场 > 应用市场
  3. 搜索名称为alibaba-cloud-metrics-adapter的应用并单击,然后在右上角单击一键部署
  4. 创建面板中,选择集群和命名空间,然后单击下一步
    命名空间发布名称为默认值,无需设置。
  5. 参数配置页面,设置相应参数,然后单击确定
    参数描述
    AccessKeyId您的阿里云AccessKeyId。
    AccessKeySecret您的阿里云AccessKeySecret。
    Region您集群所在的地域,例如cn-qingdao、ap-southeast-1。
    说明 如果您的集群和专有网络VPC之间有专线,专线会被自动使用。

步骤二:安装ack-ahas-sentinel-pilot

ack-ahas-sentinel-pilot是AHAS应用防护组件,只要为部署在ACK中的Java应用安装AHAS应用防护组件后,您无需修改任何代码,就能借助AHAS对Java应用进行全方位系统防护,针对性的对系统进行流量管控、服务降级等操作。

  1. 登录容器服务管理控制台
  2. 在控制台左侧导航栏,选择市场 > 应用市场
  3. 应用市场页面单击应用目录页签,然后搜索并选中ack-ahas-sentinel-pilot
  4. 在右侧创建区域,选择目标集群,然后单击创建

步骤三:为Java应用开启AHAS

  1. 容器服务管理控制台左侧导航栏单击集群
  2. 集群列表页面,单击目标集群名称或者目标集群右侧操作列下的详情
  3. 在集群管理页左侧导航栏,选择工作负载 > 无状态
  4. 为Java应用开启AHAS。

    以下步骤分别对应创建新应用和已有应用这两种情况:

    • 如需在创建新应用的同时开启AHAS应用防护,请按以下步骤操作。
      1. 无状态页面,单击右上角的使用模板创建
      2. 选择示例模板,并在模板中将以下annotations添加到spec>template>metadata层级下。
        annotations: 
          ahasPilotAutoEnable: "on"     //是否开启AHAS应用防护插件,on、true表示开启,off、false表示关闭。
          ahasAppName: "<your-deployment-name>"     //AHAS应用名。
          ahasLicenseKey: "<your-license>"    //AHAS license。公网环境需配置AHAS license,VPC环境无需配置,AHAS license可以在AHAS控制台>应用防护>新应用接入中获取。

        完整YAML示例模板如下:

        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: agent-foo-on-pilot
          labels:
            name: agent-foo-on-pilot
        spec:
          replicas: 1
          selector:
            matchLabels:
              name: agent-foo-on-pilot
          template:
            metadata:
              labels:
                name: agent-foo-on-pilot
              annotations:
                ahasAppName: "foo-service-on-pilot"
                ahasNamespace: "default"
            spec:
              containers:
                - name: master
                  image: registry.cn-hangzhou.aliyuncs.com/sentinel-docker-repo/foo-service:latest
                  imagePullPolicy: Always
                  ports:
                    - containerPort: 8700
                  volumeMounts:
                    - name: foo-service-logs
                      mountPath: /foo-service/logs
                    - name: foo-service-config
                      mountPath: /foo-service/config
                  resources:
                    limits:
                      cpu: "0.5"
                      memory: 500Mi
                    requests:
                      cpu: "0.5"
                      memory: 500Mi
              volumes:
                - name: foo-service-logs
                  emptyDir: {}
                - name: foo-service-config
                  configMap:
                    name: foo-service-cm-pilot
                    items:
                      - key: application.yaml
                        path: application.yml
    • 如需为现有应用开启AHAS应用防护,请按以下步骤操作。
      1. 单击无状态有状态页签,然后在目标应用右侧操作列中选择更多 > 查看YAML
      2. 编辑YAML对话框中将以下annotations添加到spec>template>metadata层级下,并单击更新
        annotations:
          ahasPilotAutoEnable: "on"
          ahasAppName: "<your-deployment-name>"
          ahasNamespace: "default"      //ahas namespace,命名空间,默认default。
          ahasLicenseKey: "<your-license>"    //ahas license,公网需要。
        说明 请将<your-deployment-name>替换为您的应用名称。
    部署成功后,登录AHAS控制台,在左侧导航栏选择流量防护 > 应用防护,在顶部菜单栏选择对应的地域和环境,可以看到该应用。
  5. 可选:在集群管理页左侧导航栏中,选择网络 > 服务,获取目标服务的外部端点IP。

    您可以通过SLB对外暴露的外部端点IP来访问该服务。

    服务外部端口IP.png

步骤四:创建HPA配置

本文针对示例Java应用来手动创建HPA,通过kubectl命令实现容器自动伸缩配置。

apiVersion: v1
kind: ConfigMap
metadata:
  name: foo-service-cm-pilot
data:
  application.yaml: |
    spring:
      application:
        name: foo-service
    server:
      port: 8700
    eureka:
      instance:
        preferIpAddress: true
      client:
        enabled: false
    logging:
      file: /foo-service/logs/application.log
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: agent-foo-on-pilot
  labels:
    name: agent-foo-on-pilot
spec:
  replicas: 1
  selector:
    matchLabels:
      name: agent-foo-on-pilot
  template:
    metadata:
      labels:
        name: agent-foo-on-pilot
      annotations:
        ahasAppName: "foo-service-on-pilot"
        ahasNamespace: "default"
    spec:
      containers:
        - name: master
          image: registry.cn-hangzhou.aliyuncs.com/sentinel-docker-repo/foo-service:latest
          imagePullPolicy: Always
          ports:
            - containerPort: 8700
          volumeMounts:
            - name: foo-service-logs
              mountPath: /foo-service/logs
            - name: foo-service-config
              mountPath: /foo-service/config
          resources:
            limits:
              cpu: "0.5"
              memory: 500Mi
            requests:
              cpu: "0.5"
              memory: 500Mi
      volumes:
        - name: foo-service-logs
          emptyDir: {}
        - name: foo-service-config
          configMap:
            name: foo-service-cm-pilot
            items:
              - key: application.yaml
                path: application.yml
---
apiVersion: v1
kind: Service
metadata:
  name: foo-service
  labels:
    name: foo-service
spec:
  ports:
  - port: 80
    targetPort: 8700
  selector:
    name: foo-service
  type: LoadBalancer
  externalTrafficPolicy: Local
    
说明

AHAS应用防护目前支持四种判断指标:

  • ahas_sentinel_total_qps:应用的总QPS(pass+block,平均到每台机器)。
  • ahas_sentinel_pass_qps:应用的通过QPS(平均到每台机器)。
  • ahas_sentinel_block_qps:应用的拒绝QPS(平均到每台机器)。
  • ahas_sentinel_avg_rt:应用的平均响应时间。

  1. 使用kubectl连接集群。

    关于kubectl的具体操作,请参见获取集群KubeConfig并通过kubectl工具连接集群

  2. 创建配置文件ahas-sentinel-hpa.yml

    示例:

    apiVersion: autoscaling/v2beta2
    kind: HorizontalPodAutoscaler
    metadata:
      name: ahas-sentinel-hpa
    spec:
      scaleTargetRef:
        apiVersion: apps/v1beta2
        kind: Deployment
        name: agent-foo-on-pilot
      minReplicas: 1
      maxReplicas: 3
      metrics:
        - type: External
          external:
            metric:
              name: ahas_sentinel_total_qps
              selector:
                matchLabels:
                # If you're using AHAS Sentinel pilot, then the appName and namespace
                # can be retrieved from the annotation of target Deployment automatically.
                # ahas.sentinel.app: "foo-service-on-pilot"
                # ahas.sentinel.namespace: "default"
            target:
              type: Value
              # ahas_sentinel_total_qps > 30
              value: 30

    上述的配置针对agent-foo-on-pilot Deployment对应的应用进行自动弹性伸缩,判断的指标是AHAS应用防护中统计的应用QPS(平均到每台机器),超过30就进行扩容,最大扩容副本数为3。

  3. 执行kubectl apply -f ahas-sentinel-hpa.yml来创建HPA配置。

验证弹性结果

本文提供了发送压测流量的镜像,方便测试弹性效果。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: flow-runner
  labels:
    name: flow-runner
spec:
  replicas: 1
  selector:
    matchLabels:
      name: flow-runner
  template:
    metadata:
      labels:
        name: flow-runner
    spec:
      containers:
        - name: runner
          image: registry.cn-hangzhou.aliyuncs.com/sentinel-docker-repo/flow-runner:0.1.0
          imagePullPolicy: Always
          env:
		    # 在此处更新为实际的地址
            - name: TARGET_URL
              value: "http://192.168.xx.xx/foo/time"
			# 每次请求的时间间隔(s),比如 0.1 就代表 QPS 为 10
            - name: SLEEP_TIME
              value: "0.1"
    

通过可以控制该runner的副本数来控制压测的QPS,例如上述示例中调整replica=3即对应30QPS。

  1. 在集群管理页左侧导航栏,选择工作负载 > 无状态
  2. 单击目标服务操作列的伸缩,在伸缩对话框,设置所需容器组数量4

    本文将replica数目调成4,使得QPS超过临界值,触发扩容。

    约5分钟后,可以看到对应的应用容器数目自动扩容成了2。replica.png

    登录AHAS控制台,在左侧导航栏选择流量防护 > 应用防护,单击应用卡片,然后在应用详情页的左侧导航栏选择机器监控,可以看到增加的实例。

  3. 将示例中的replica设置为3。
    约5分钟后,可以看到对应的应用容器数目自动缩容成了1。replica2.png

    容器服务管理控制台的左侧导航栏单击集群。在集群列表页面中,单击目标集群名称或者目标集群右侧操作列下的详情。在集群管理页左侧导航栏中,选择工作负载 > 无状态,可以看到容器组数量缩容为1。

    容器组数量