Pod自动扩缩容
为什么要扩缩容?
在实际的业务场景中,我们经常会遇到某个服务需要扩容的场景(如:对服务器性能压测、电商平台秒杀、大促活动、或由于资源紧张、工作负载降低等都需要对服务实例数进行扩缩容操作。)
node节点默认可以跑110个pod
在k8s中扩容分为两种:
1、node层面:
在使用k8s集群经常遇到一个问题是,我应该保持多大的节点规模来满足应用需求呢?cluster-autoscaler出现解决了这个问题,可以通过cluster-autoscaler实现节点级别的动态添加与删除,动态调整容器资源池,应对峰值流量。(这个技术基于云厂商的平台实现
)
2、pod层面
我们一般会使用deployment中的replicas参数,设置多个副本集来保证服务的高可用,但是这是一个固定的值,比如我们设置10个副本,就会启动10个pod同时running来提供服务。
如果我这个服务平时流量很少的时候,也就是10个pod同时running,而流量突然暴增时,又可能出现10个pod不够用的情况。针对这种情况怎么办?这时候就需要自动扩缩容:
k8s对pod的扩缩容分为:
手动和自动两种
1、手动模式:通过kubectl scale命令,这样需要每次去手动操作一次,而且不确定业务什么时候请求量就很大了,所以如果不能做到自动化的去扩缩容,这也是一件很麻烦的事。
2、自动模式:如果k8s系统能够根据pod当前的负载变化情况来自动的进行扩缩容就好了,因为这个过程本来就是不固定的,频繁发生的,所以纯手动的方式不现实。
自动扩缩容的方案有哪些?
kubernetes HPA(Horizontal Pod Autoscaling)生产用的多
通过此功能,只需简单的配置,便可以利用监控指标(cpu使用率、内存使用率)自动的扩容或缩容服务中的pod数量,当业务需求增加时,系统将无缝地自动增加适量pod容器,提高系统稳定性。
kubernetes KPA(Knative Pod Autoscaler)
基于请求数对pod自动扩缩容,KPA的主要限制在于它不支持基于CPU的自动扩缩容。
kubernetes VPA(Vertical Pod Autoscaler)
垂直pod自动扩缩容,VPA会基于Pod的资源使用情况自动为集群设置资源占用的限制,从而让集群将Pod调度到有足够资源的最佳节点上。VPA也会保持最初容器定义中资源request和limit的占用比。
它会根据容器资源使用率自动设置pod的CPU和内存的requests,从而允许节点上进行适当的调度,以便为每个Pod提供适当的可用节点。它既可以缩小过度请求资源的容器,也可以根据其使用情况随时提升资源不足的容量。
如何实现k8s中pod应用自动扩缩容?
基于HPA
要想实现自动扩缩容,需要考虑如下几点:
1、通过哪些指标决定扩缩容?
HPA v1 版本可以根据CPU使用率来进行自动扩缩容:
但是并非所有的系统都可以仅依靠CPU或内存指标来扩容,对于大多数web应用的后端来说,基于每秒的请求数量进行弹性伸缩来处理流量会更加的靠谱,所以对于一个自动扩缩容系统来说,我们不能局限于CPU、内存基础监控数据,每秒请求数RPS等自定义指标也十分重要。
HPA v2版本可以根据自定义的指标进行自动扩缩容
2、如何采集资源指标?
如果我们的系统默认依赖于prometheus,自定义的metrics指标则可以从各种数据源或者exporter中获取,基于拉模型的promethes会定期从数据源中拉取数据,也可以基于metrics-server自动获取节点和pod的资源指标。
基于KPA
1、根据并发请求数实现自动扩缩容
2、设置扩缩容边界实现自动扩缩容
扩缩容边界指应用程序提供服务的最小和最大pod数量。通过设置应用程序提供服务的最小和最大pod数量实现自动扩缩容。
相比HPA、KPA会考虑更多的场景,其中一个比较重要的流量突发的时候
基于VPA
当目前运行pod节点资源达不到VPA的推荐值,就会执行pod驱逐,重新部署新的足够资源的服务。VPA是k8s比较新的功能,目前不建议个人不建议生产环境使用,还没有在生产环境大规模实践过,不建议在线上环境使用自动更新模式,但是使用推荐模式你可以更好了解服务的资源使用情况。
官网:https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler
利用HPA基于CPU指标实现pod自动扩缩容
HPA 全称是 Horizontal Pod Autoscaler,翻译成中文是 POD 水平自动伸缩, HPA 可以基于 CPU 利用率对 deployment 、StatefulSet中的 pod 数量进行自动扩缩容(除了 CPU 也可以基于自定义的指标进行自 动扩缩容)。pod 自动缩放不适用于无法缩放的对象,比如 DaemonSets。
HPA 由 Kubernetes API 资源和控制器实现。控制器会周期性的获取平均 CPU 利用率,并与目标 值相比较后调整 deployment 中的副本数量。
HorizontalPodAutoscaler 控制 Deployment 及其 ReplicaSet 的规模
监控指标从哪里来?
K8S 从 1.8 版本开始,CPU、内存等资源的 metrics 信息可以通过 Metrics API 来获取,用户可以 直接获取这些 metrics 信息(例如通过执行 kubect top 命令),HPA 使用这些 metics 信息来实现动态 伸缩。
Metrics server:
1、Metrics server 是 K8S 集群资源使用情况的聚合器
2、从 1.8 版本开始,Metrics server 可以通过 yaml 文件的方式进行部署
3、Metrics server 收集所有 node 节点的 metrics 信息和 pod 的指标信息(主要是 cpu 和内存)
安装数据采集组件 metric-server
metrics-server 是一个集群范围内的资源数据集和工具,同样的,metrics-server 也只是显示数 据,并不提供数据存储服务,主要关注的是资源度量 API 的实现,比如 CPU、内存等指标,metricserver 收集数据给 k8s 集群内使用,如kubectl,hpa,scheduler 等。
Github 地址:
https://github.com/kubernetes-sigs/metrics-server/
https://github.com/kubernetes-sigs/metrics-server/releases/tag/v0.6.1
1、部署 metrics-server 组件
通过离线包方式导入镜像
需要的镜像是:registry.cn-hangzhou.aliyuncs.com/google_containers/metricsserver:v0.6.1,导入到k8s每个节点上。
ctr -n=k8s.io images import metrics-server-0.6.1.tar.gz
部署metrics-server服务
在/etc/kubernetes/manifests 里面改一下 apiserver 的配置
注意:这个是 k8s 在 1.17 的新特性,如果是 1.16 版本的可以不用添加,1.17 以后要添加。这个参 数的作用是 Aggregation 允许在不修改 Kubernetes 核心代码的同时扩展 Kubernetes API。
#只有master节点修改
vim /etc/kubernetes/manifests/kube-apiserver.yaml
- --enable-aggregator-routing=true
重新更新apiserver配置:
#重启k8s所有节点
[root@k8s-master ~]# systemctl restart kubelet.service
[root@k8s-slave1 ~]# systemctl restart kubelet.service
部署metrics-server服务
[root@k8s-master ~]# cat components.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:
- /metrics-server
- --cert-dir=/tmp
- --secure-port=4443
- --kubelet-insecure-tls
- --kubelet-preferred-address-types=InternalIP
- --kubelet-use-node-status-port
- --metric-resolution=15s
image: registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server:v0.6.1
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
path: /livez
port: https
scheme: HTTPS
periodSeconds: 10
name: metrics-server
ports:
- containerPort: 4443
name: https
protocol: TCP
readinessProbe:
httpGet:
path: /readyz
port: https
scheme: HTTPS
initialDelaySeconds: 20
periodSeconds: 10
resources:
requests:
cpu: 100m
memory: 10Mi
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
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
查看pod资源
创建一个pod
在名称空间cheng-svc-test 里面创建一个pod,cpu、内存各100m
[root@k8s-master cheng-svc-test]# cat cheng-svc-pod-test.yaml
# 基于deployment创建3个pod,加上标签。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: cheng-svc-test
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:latest
name: container-0
resources:
limits:
cpu: 100m
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
创建HPA v1(CPU)
nginx 服务正在运行,使用 kubectl autoscale 创建自动缩放器,实现对 nginx 这个 deployment 创建的 pod 自动扩缩容,下面的命令将会创建一个 HPA,HPA 将会根据 CPU,内存等资 源指标增加或减少副本数,创建一个可以实现如下目的的 hpa:
1)让副本数维持在 1-10 个之间(这里副本数指的是通过 deployment 部署的 pod 的副本数)
2)将所有 Pod 的平均 CPU 使用率维持在 20%(运行的每个 pod 如果是 100 毫核,这意味着平均 CPU 利用率为 20 毫核)
给上面nignx 这个 deployment 创建 HP
kubectl -n cheng-svc-test autoscale deployment nginx --cpu-percent=20 --min=1 --max=10
kubectl -n cheng-svc-test get hpa
给nginx创建一个svc,生产中也是访问svc的ip或者域名,不会直接访问pod ip
[root@k8s-master cheng-svc-test]# cat cheng-clusterip.yaml
# 集群内,开启一个固定死的ip,svc的ip地址,负载均衡代理一组pod
apiVersion: v1
kind: Service
metadata:
name: cheng-clusterip # Service的名称 ,svc ip,dns,自定义,做好按业务名称,通俗易懂
namespace: cheng-svc-test #和之前创建的后端放一个名称空间中
spec:
selector: # Label Selector,选择包含app=nginx标签的Pod,后面只要这个命名空间中带这个标签的server IP就会自动发现
app: nginx #之前创建pod中的保持一致
ports:
- name: service0
targetPort: 80 # Pod的端口
port: 80 # Service对外暴露的端口,也就是ClusterIP的port
protocol: TCP # 转发协议类型,支持TCP和UDP
type: ClusterIP # Service的类型
删除HPA
kubectl -n cheng-svc-test get hpa
kubectl -n cheng-svc-test delete hpa nginx
创建HPA v2(内存)
创建pod
[root@k8s-slave1 ~]# cat cheng.yaml
apiVersion: v1
kind: Namespace
metadata:
name: cheng
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: cheng
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:latest
name: container-0
resources:
limits:
cpu: 100m
memory: 60Mi
requests:
cpu: 100m
memory: 60Mi
---
apiVersion: v1
kind: Service
metadata:
name: cheng-clusterip # Service的名称 ,svc ip,dns,自定义,做好按业务名称,通俗易懂
namespace: cheng #和之前创建的后端放一个名称空间中
spec:
selector: # Label Selector,选择包含app=nginx标签的Pod,后面只要这个命名空间中带这个标签的server IP就会自动发现
app: nginx #之前创建pod中的保持一致
ports:
- name: service0
targetPort: 80 # Pod的端口
port: 80 # Service对外暴露的端口,也就是ClusterIP的port
protocol: TCP # 转发协议类型,支持TCP和UDP
type: ClusterIP # Service的类型
创建基于内存的hpa
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: nginx-hpa
namespace: cheng # 根据你的命名空间进行修改
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: nginx # 根据你的Deployment名称进行修改
minReplicas: 1 # 最小副本数
maxReplicas: 5 # 最大副本数
metrics:
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 15 # 设置目标内存利用率为80%
[root@k8s-slave1 ~]# cat hpa-v1.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: nginx-hpa
namespace: cheng
spec:
maxReplicas: 10
minReplicas: 1
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: nginx
metrics:
- type: Resource
resource:
name: memory
target:
averageUtilization: 30
type: Utilization
[root@k8s-slave1 ~]#
进入pod,创建点数据
kubectl -n cheng exec -it nginx-cbc6577bd-kb6sn -- /bin/bash
dd if=/dev/zero of=/tmp/a
pod数据实时刷新
watch -n 1 kubectl top pod -n cheng
标签:name,扩缩容,server,metrics,pod,k8s
From: https://www.cnblogs.com/9527com/p/18009748