服务网格ASM为ACK集群内的服务通信提供了一种非侵入式的生成遥测数据的能力。这种遥测功能提供了服务行为的可观测性,可以帮助运维人员对应用程序进行故障排除、维护和优化,而不会带来任何额外负担。根据监控的四个黄金指标维度(延迟、流量、错误和饱和度),服务网格ASM为管理的服务生成一系列指标。本文介绍如何使用ASM指标实现工作负载的自动弹性伸缩。
背景信息
服务网格ASM为管理的服务生成一系列指标。更多信息,请参见Istio标准指标。
自动伸缩是一种根据资源使用情况进行自动扩缩工作负载的方法。Kubernetes中的自动伸缩具有以下两个维度:
- 集群自动伸缩器CA(Cluster Autoscaler):用于处理节点伸缩操作,可以增加或减少节点。
- 水平自动伸缩器HPA(Horizontal Pod Autoscaler):用于自动伸缩应用部署中的Pod,可以调节Pod的数量。
Kubernetes提供的聚合层允许第三方应用程序将自身注册为API Addon组件来扩展Kubernetes API。这样的Addon组件可以实现Custom Metrics
API,并允许HPA访问任意指标。HPA会定期通过Resource Metrics API查询核心指标(例如CPU或内存)以及通过Custom Metrics API获取特定于应用程序的指标,包括ASM提供的可观测性指标。

步骤一:开启采集Prometheus监控指标
- 登录ASM控制台。
- 在左侧导航栏,选择。
- 在网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理。
- 在网格详情页面左侧导航栏选择,然后在右侧页面单击功能设置。
说明 请确保ASM实例的Istio为1.6.8.4及以上版本。
- 在功能设置更新面板中选中开启采集Prometheus监控指标,选中启用已有Prometheus,输入Prometheus地址,然后单击确定。
ASM将自动生成采集Prometheus监控指标相关的EnvoyFilter配置。
步骤二:部署自定义指标API Adapter
- 下载Adapter安装包,关于Adapter安装包请参见kube-metrics-adapter。然后在ACK集群中安装部署自定义指标API Adapter。
## 如果使用Helm v3。
helm -n kube-system install asm-custom-metrics ./kube-metrics-adapter --set prometheus.url=http://prometheus.istio-system.svc:9090
- 安装完成后,通过以下方式确认kube-metrics-adapter已启用。
- 确认autoscaling/v2beta已存在。
kubectl api-versions |grep "autoscaling/v2beta"
预期输出:
autoscaling/v2beta
- 确认kube-metrics-adapter Pod状态。
kubectl get po -n kube-system |grep metrics-adapter
预期输出:
asm-custom-metrics-kube-metrics-adapter-85c6d5d865-2cm57 1/1 Running 0 19s
- 列出Prometheus适配器提供的自定义外部指标。
kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1" | jq .
预期输出:
{
"kind": "APIResourceList",
"apiVersion": "v1",
"groupVersion": "external.metrics.k8s.io/v1beta1",
"resources": []
}
步骤三:部署示例应用
- 创建test命名空间。具体操作,请参见管理命名空间。
- 启用Sidecar自动注入。具体操作,请参见安装Sidecar代理。
- 部署示例应用。
- 创建podinfo.yaml文件。
apiVersion: apps/v1
kind: Deployment
metadata:
name: podinfo
namespace: test
labels:
app: podinfo
spec:
minReadySeconds: 5
strategy:
rollingUpdate:
maxUnavailable: 0
type: RollingUpdate
selector:
matchLabels:
app: podinfo
template:
metadata:
annotations:
prometheus.io/scrape: "true"
labels:
app: podinfo
spec:
containers:
- name: podinfod
image: stefanprodan/podinfo:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9898
name: http
protocol: TCP
command:
- ./podinfo
- --port=9898
- --level=info
livenessProbe:
exec:
command:
- podcli
- check
- http
- localhost:9898/healthz
initialDelaySeconds: 5
timeoutSeconds: 5
readinessProbe:
exec:
command:
- podcli
- check
- http
- localhost:9898/readyz
initialDelaySeconds: 5
timeoutSeconds: 5
resources:
limits:
cpu: 2000m
memory: 512Mi
requests:
cpu: 100m
memory: 64Mi
---
apiVersion: v1
kind: Service
metadata:
name: podinfo
namespace: test
labels:
app: podinfo
spec:
type: ClusterIP
ports:
- name: http
port: 9898
targetPort: 9898
protocol: TCP
selector:
app: podinfo
- 部署podinfo。
kubectl apply -n test -f podinfo.yaml
- 为了触发自动弹性伸缩,需要在命名空间test中部署负载测试服务,用于触发请求。
- 创建loadtester.yaml文件。
apiVersion: apps/v1
kind: Deployment
metadata:
name: loadtester
namespace: test
labels:
app: loadtester
spec:
selector:
matchLabels:
app: loadtester
template:
metadata:
labels:
app: loadtester
annotations:
prometheus.io/scrape: "true"
spec:
containers:
- name: loadtester
image: weaveworks/flagger-loadtester:0.18.0
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
command:
- ./loadtester
- -port=8080
- -log-level=info
- -timeout=1h
livenessProbe:
exec:
command:
- wget
- --quiet
- --tries=1
- --timeout=4
- --spider
- http://localhost:8080/healthz
timeoutSeconds: 5
readinessProbe:
exec:
command:
- wget
- --quiet
- --tries=1
- --timeout=4
- --spider
- http://localhost:8080/healthz
timeoutSeconds: 5
resources:
limits:
memory: "512Mi"
cpu: "1000m"
requests:
memory: "32Mi"
cpu: "10m"
securityContext:
readOnlyRootFilesystem: true
runAsUser: 10001
---
apiVersion: v1
kind: Service
metadata:
name: loadtester
namespace: test
labels:
app: loadtester
spec:
type: ClusterIP
selector:
app: loadtester
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
- 部署负载测试服务。
kubectl apply -n test -f loadtester.yaml
- 验证部署示例应用和负载测试服务是否成功。
- 确认Pod状态。
kubectl get pod -n test
预期输出:
NAME READY STATUS RESTARTS AGE
loadtester-64df4846b9-nxhvv 2/2 Running 0 2m8s
podinfo-6d845cc8fc-26xbq 2/2 Running 0 11m
- 进入负载测试器容器,并使用hey命令生成负载。
export loadtester=$(kubectl -n test get pod -l "app=loadtester" -o jsonpath='{.items[0].metadata.name}')
kubectl -n test exec -it ${loadtester} -c loadtester -- hey -z 5s -c 10 -q 2 http://podinfo.test:9898
返回结果,生成负载成功,说明示例应用和负载测试服务部署成功。
步骤四:使用ASM指标配置HPA
定义一个HPA,该HPA将根据每秒接收的请求数来扩缩Podinfo的工作负载数量。当平均请求流量负载超过10 req/sec时,将指示HPA扩大部署。
- 创建hpa.yaml。
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: podinfo
namespace: test
annotations:
metric-config.external.prometheus-query.prometheus/processed-requests-per-second: |
sum(
rate(
istio_requests_total{
destination_workload="podinfo",
destination_workload_namespace="test",
reporter="destination"
}[1m]
)
)
spec:
maxReplicas: 10
minReplicas: 1
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: podinfo
metrics:
- type: External
external:
metric:
name: prometheus-query
selector:
matchLabels:
query-name: processed-requests-per-second
target:
type: AverageValue
averageValue: "10"
- 部署HPA。
kubectl apply -f hpa.yaml
- 验证HPA是否部署成功。
列出Prometheus适配器提供的自定义外部指标。
kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1" | jq .
预期输出:
{
"kind": "APIResourceList",
"apiVersion": "v1",
"groupVersion": "external.metrics.k8s.io/v1beta1",
"resources": [
{
"name": "prometheus-query",
"singularName": "",
"namespaced": true,
"kind": "ExternalMetricValueList",
"verbs": [
"get"
]
}
]
}
返回结果中包含自定义的ASM指标的资源列表,说明HPA部署成功。
验证自动弹性伸缩
- 进入测试器容器,并使用hey命令生成工作负载请求。
kubectl -n test exec -it ${loadtester} -c loadtester -- sh
~ $ hey -z 5m -c 10 -q 5 http://podinfo.test:9898
- 查看自动伸缩状况。
说明 默认情况下,指标每30秒执行一次同步,并且只有在最近3分钟~5分钟内容器没有重新缩放时,才可以进行放大或缩小。这样,HPA可以防止冲突决策的快速执行,并为集群自动扩展程序预留时间。
watch kubectl -n test get hpa/podinfo
预期输出:
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
podinfo Deployment/podinfo 8308m/10 (avg) 1 10 6 124m
一分钟后,HPA将开始扩大工作负载,直到请求/秒降至目标值以下。负载测试完成后,每秒的请求数将降为零,并且HPA将开始缩减工作负载Pod数量,几分钟后上述命令返回结果中的REPLICAS副本数将恢复为一个。