一、背景¶
- Kubernetes集群规模大、动态变化快,而且容器化应用部署和服务治理机制的普 及,传统的基础设施监控方式已经无法满足Kubernetes集群的监控需求。
- 需要使用专门针对Kubernetes集群设计的监控工具来监控集群的状态和服务质量。
Prometheus则是目前Kubernetes集群中最常用的监控工具之一,它可以通过 Kubernetes API中的 metrics-server 获取 Kubernetes 集群的指标数据,从而实现对Kubernetes集群的应用层面监控,以及基于它们的水平自动伸缩对象HorizontalPodAutoscaler。
二、Metrics-server¶
资源指标管道 Metrics API | Kubernetes
Metrics Server 是一个专门用来收集 Kubernetes 核心资源指标(metrics)的工具, 它定时从所有节点的kubelet里采集信息,但是对集群的整体性能影响极小,每个节点只大约会占用 1m 的 CPU 和 2MB 的内存,所以性价比非常高。
Metrics Server 工作原理:

图中从右到左的架构组件包括以下内容:
- cAdvisor: 用于收集、聚合和公开 Kubelet 中包含的容器指标的守护程序。
- kubelet: 用于管理容器资源的节点代理。 可以使用 /metrics/resource 和 /stats kubelet API 端点访问资源指标。
- Summary API: kubelet 提供的 API,用于发现和检索可通过 /stats 端点获得的每 个节点的汇总统计信息。
- metrics-server: 集群插件组件,用于收集和聚合从每个 kubelet 中提取的资源指 标。 API 服务器提供 Metrics API 以供 HPA、VPA 和 kubectl top 命令使用。 Metrics Server 是 Metrics API 的参考实现。
- Metrics API: Kubernetes API 支持访问用于工作负载自动缩放的 CPU 和内存。 要在你的集群中进行这项工作,你需要一个提供 Metrics API 的 API 扩展服务器。
2.1 Metrics-server部署配置¶
Metrics Server 的项目网址(https://github.com/kubernetes-sigs/metrics-server)
$ wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml && mv components.yaml metrics-server.yaml
修改 YAML 文件
# 修改镜像为registry.cn-hangzhou.aliyuncs.com/github_images1024/metrics-server:v0.7.2
# 添加- --kubelet-insecure-tls配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: metrics-server
namespace: kube-system
spec:
containers:
- args:
- --kubelet-insecure-tls
- --cert-dir=/tmp
- --secure-port=10250
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --kubelet-use-node-status-port
- --metric-resolution=15s
image: registry.cn-hangzhou.aliyuncs.com/github_images1024/metrics-server:v0.7.2
imagePullPolicy: IfNotPresent
...
...
# 完整配置文件
cat metrics-server.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
k8s-app: metrics-server
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rbac.authorization.k8s.io/aggregate-to-edit: "true"
rbac.authorization.k8s.io/aggregate-to-view: "true"
name: system:aggregated-metrics-reader
rules:
- apiGroups:
- metrics.k8s.io
resources:
- pods
- nodes
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
k8s-app: metrics-server
name: system:metrics-server
rules:
- apiGroups:
- ""
resources:
- nodes/metrics
verbs:
- get
- apiGroups:
- ""
resources:
- pods
- nodes
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
k8s-app: metrics-server
name: metrics-server-auth-reader
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
k8s-app: metrics-server
name: metrics-server:system:auth-delegator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
k8s-app: metrics-server
name: system:metrics-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:metrics-server
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: v1
kind: Service
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
spec:
ports:
- name: https
port: 443
protocol: TCP
targetPort: https
selector:
k8s-app: metrics-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
spec:
selector:
matchLabels:
k8s-app: metrics-server
strategy:
rollingUpdate:
maxUnavailable: 0
template:
metadata:
labels:
k8s-app: metrics-server
spec:
containers:
- args:
- --kubelet-insecure-tls
- --cert-dir=/tmp
- --secure-port=10250
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --kubelet-use-node-status-port
- --metric-resolution=15s
image: registry.cn-hangzhou.aliyuncs.com/github_images1024/metrics-server:v0.7.2
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
httpGet:
path: /livez
port: https
scheme: HTTPS
periodSeconds: 10
name: metrics-server
ports:
- containerPort: 10250
name: https
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /readyz
port: https
scheme: HTTPS
initialDelaySeconds: 20
periodSeconds: 10
resources:
requests:
cpu: 100m
memory: 200Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
seccompProfile:
type: RuntimeDefault
volumeMounts:
- mountPath: /tmp
name: tmp-dir
nodeSelector:
kubernetes.io/os: linux
priorityClassName: system-cluster-critical
serviceAccountName: metrics-server
volumes:
- emptyDir: {}
name: tmp-dir
---
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
labels:
k8s-app: metrics-server
name: v1beta1.metrics.k8s.io
spec:
group: metrics.k8s.io
groupPriorityMinimum: 100
insecureSkipTLSVerify: true
service:
name: metrics-server
namespace: kube-system
version: v1beta1
versionPriority: 100
Metrics Server 默认使用 TLS 协议 ,要验证证书才能与 kubelet 实现安全通信,而我们的内网环境里没有这个必要。
- --kubelet-insecure-tls
部署:
$ kubectl apply -f metrics-server.yaml
测试验证:
$ kubectl top node
$ kubectl top pod -n kube-system
三、HorizontalPodAutoscaler¶
HorizontalPodAutoscaler (HPA)是Kubernetes中的一个控制器,用于动态地调整Pod副 本的数量。HPA可以根据Metrics-server提供的指标(如CPU使用率、内存使用率等)或 内部指标(如每秒的请求数)来自动调整Pod的副本数量,以确保应用程序具有足够的资源,并且不会浪费资源。
HPA是Kubernetes扩展程序中非常常用的部分,特别是在负载高峰期自动扩展应用程序时。
3.1 使用HorizontalPodAutoscaler¶
创建一个 Nginx 应用,定义 Deployment 和 Service,作为自动伸缩的目标对象:
# 编写资源文件
[root@master01 7]# vim nginx-hpa-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ngx-hpa-dep
spec:
replicas: 1
selector:
matchLabels:
app: ngx-hpa-dep
template:
metadata:
labels:
app: ngx-hpa-dep
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/abroad_images/nginx:alpine
name: nginx
ports:
- containerPort: 80
resources:
requests:
cpu: 50m
memory: 10Mi
limits:
cpu: 100m
memory: 20Mi
---
apiVersion: v1
kind: Service
metadata:
name: ngx-hpa-svc
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: ngx-hpa-dep
# 应用
[root@master01 7]# kaf nginx-hpa-deploy.yaml
# 验证
[root@master01 7]# kg -f nginx-hpa-deploy.yaml
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/ngx-hpa-dep 1/1 1 1 87s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/ngx-hpa-svc ClusterIP 192.168.12.200 <none> 80/TCP 87s
注意在它的 spec 里一定要用 resources 字段写清楚资源配额,否则HorizontalPodAutoscaler 会无法获取 Pod 的指标,也就无法实现自动化扩缩容。
接下来我们要用命令 kubectl autoscale 创建一个 HorizontalPodAutoscaler 的样板 YAML 文件,它有三个参数:
- min,Pod 数量的最小值,也就是缩容的下限。
- max,Pod 数量的最大值,也就是扩容的上限。
- cpu-percent,CPU 使用率指标,当大于这个值时扩容,小于这个值时缩容。
现在我们就来为刚才的 Nginx 应用创建 HorizontalPodAutoscaler,指定 Pod 数量最少 2 个,最多 8 个,CPU 使用率指标设置的小一点,5%,方便我们观察扩容现象:
$ kubectl autoscale deploy ngx-hpa-dep --min=2 --max=8 --cpu-percent=5 --dry-run=client -o yaml > nginx-demo-hpa.yaml
YAML 描述文件:
[root@master01 7]# vim nginx-demo-hpa.yaml
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: ngx-hpa
spec:
maxReplicas: 8
minReplicas: 2
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: ngx-hpa-dep
targetCPUUtilizationPercentage: 5
# 应用
[root@master01 7]# kaf nginx-demo-hpa.yaml
# 验证
[root@master01 7]# kg hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
ngx-hpa Deployment/ngx-hpa-dep 0%/5% 2 8 2 34s
通过kubectl apply创建这个 HorizontalPodAutoscaler 后,它会发现 Deployment 里的实例只有 1 个,不符合 min 定义的下限的要求,就先扩容到 2 个:
[root@master01 7]# kubectl get deploy | grep ngx-hpa-dep
ngx-hpa-dep 2/2 2 2 8m6s
3.2 测试验证¶
下面我们来给 Nginx 加上压力流量,运行一个测试 Pod,使用的镜像是httpd:alpine,它里面有 HTTP 性能测试工具 ab(Apache Bench):
$ kubectl run test -it --image=registry.cn-hangzhou.aliyuncs.com/abroad_images/httpd:alpine -- sh
然后我们向 Nginx 发送一百万个请求,持续 1 分钟,再用 kubectl get hpa 来观察 HorizontalPodAutoscaler 的运行状况:
$ ab -c 10 -t 60 -n 1000000 'http://ngx-hpa-svc/'
[root@master01 7]# kubectl get po | grep ngx-hpa-dep
ngx-hpa-dep-d9cd855cb-25zhc 1/1 Running 0 10s
ngx-hpa-dep-d9cd855cb-29czd 1/1 Running 0 10s
ngx-hpa-dep-d9cd855cb-825x4 1/1 Running 0 5m25s
ngx-hpa-dep-d9cd855cb-9hf8m 1/1 Running 0 11m
ngx-hpa-dep-d9cd855cb-d2kvj 1/1 Running 0 10s
ngx-hpa-dep-d9cd855cb-mqgjz 1/1 Running 0 10s
ngx-hpa-dep-d9cd855cb-sfm5d 1/1 Running 0 25s
ngx-hpa-dep-d9cd855cb-sllkd 1/1 Running 0 25s
四、总结¶
- 1、 Metrics Server是Kubernetes中的一个组件,它可以将集群中的散布的资源使用情况数据收集并聚合起来。收集的数据包括节点的CPU和内存使用情况等。
-
2、通过API提供给 Kubernetes中的其它组件(如HPA)使用。 Metrics Server可以帮助集群管理员和应用程序开发者更好的了解集群中资源的使用情况,并根据这些数据做出合理的决策,例如调整Pod副本数、扩展集群等。
-
3、 Metrics Server对于Kubernetes中的资源管理和应用程序扩展非常重要。