HPA全称是Horizontal Pod Autoscaler,翻译成中文是POD水平自动伸缩,HPA可以基于CPU利用率对replication controller、deployment和replicaset中的pod数量进行自动扩缩容(除了CPU利用率也可以基于其他应程序提供的度量指标custom metrics进行自动扩缩容)。pod自动缩放不适用于无法缩放的对象,比如DaemonSets。
HPA由Kubernetes API资源和控制器实现。资源决定了控制器的行为。控制器会周期性的获取目标资源指标(如,平均CPU利用率),并与目标值相比较后来调整Pod副本数量。
1.安装metrics进行监控集群,获取指标
bash
root@k8s-master:/home/vagrant# cat metrics.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:
- --cert-dir=/tmp
- --secure-port=10250
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --kubelet-use-node-status-port
- --metric-resolution=15s
- --kubelet-insecure-tls
image: registry.k8s.io/metrics-server/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
root@k8s-master:/home/vagrant# kubectl apply -f metrics.yaml
root@k8s-master:/home/vagrant# kubectl get pods -n kube-system|grep metrics
metrics-server-587b667b55-tjhfp 1/1 Running 0 11m
2.创建测试Deployment
bash
root@k8s-master:/home/vagrant# cat php-apache.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: php-apache
labels:
app: apache
spec:
replicas: 1
selector:
matchLabels:
app: apache
template:
metadata:
name: apache
labels:
app: apache
spec:
containers:
- name: apache
image: httpd
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
name: httpd
resources:
limits:
cpu: 800m
requests:
cpu: 500m
---
kind: Service
apiVersion: v1
metadata:
name: apache-service
labels:
app: apache
spec:
selector:
app: apache
ports:
- name: http
targetPort: 80
port: 80
root@k8s-master:/home/vagrant# kubectl apply -f php-apache.yaml
deployment.apps/php-apache created
root@k8s-master:/home/vagrant# kubectl get svc,deployment,pods
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/apache-service ClusterIP 10.105.192.165 <none> 80/TCP 2m
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 43d
service/redis-svc ClusterIP 10.109.12.172 <none> 6379/TCP 23h
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/php-apache 1/1 1 1 24m
NAME READY STATUS RESTARTS AGE
pod/php-apache-b7cb67d98-b6qx9 1/1 Running 0 24m
3.创建HPA
bash
root@k8s-master:/home/vagrant# vim hpa.yaml
kind: HorizontalPodAutoscaler
apiVersion: autoscaling/v2
metadata:
name: php-apache
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
root@k8s-master:/home/vagrant# kubectl apply -f hpa.yaml
horizontalpodautoscaler.autoscaling/php-apache created
4.模拟php-apache Pod CPU使用率增加
bash
建议多开几个终端进行,效果更加明显
root@k8s-master:/home/vagrant# kubectl run -i --tty load-generator --rm --image=busybox:1.28 --restart=Never -- /bin/sh -c "while true; do wget -q -O- http://10.105.192.165; done"
root@k8s-master:/home/vagrant# kubectl get pods|grep load
load-generator 1/1 Running 0 54s
root@k8s-master:/home/vagrant# kubectl get deployment,po,hpa
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/php-apache 2/2 2 2 33m
NAME READY STATUS RESTARTS AGE
pod/load-generator 1/1 Running 0 105s
pod/load-generator2 1/1 Terminating 0 103s
pod/load-generator3 1/1 Running 0 24s
pod/php-apache-67fd659dcb-6z8tz 1/1 Running 0 23s
pod/php-apache-67fd659dcb-thb68 1/1 Running 0 114s
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
horizontalpodautoscaler.autoscaling/php-apache Deployment/php-apache cpu: 80%/50% 1 10 2 18m
root@k8s-master:/home/vagrant# kubectl get deployment,po,hpa
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/php-apache 10/10 10 10 36m
NAME READY STATUS RESTARTS AGE
pod/load-generator 1/1 Running 0 4m32s
pod/load-generator3 1/1 Running 0 3m11s
pod/load-generator4 1/1 Running 0 106s
pod/php-apache-67fd659dcb-2hdg5 1/1 Running 0 2m25s
pod/php-apache-67fd659dcb-52rcx 1/1 Running 0 2m40s
pod/php-apache-67fd659dcb-6z8tz 1/1 Running 0 3m10s
pod/php-apache-67fd659dcb-8wc7j 1/1 Running 0 2m25s
pod/php-apache-67fd659dcb-8zdf6 1/1 Running 0 2m40s
pod/php-apache-67fd659dcb-ckqkm 1/1 Running 0 2m9s
pod/php-apache-67fd659dcb-jncsb 1/1 Running 0 2m24s
pod/php-apache-67fd659dcb-pb89r 1/1 Running 0 2m25s
pod/php-apache-67fd659dcb-t66kv 1/1 Running 0 2m9s
pod/php-apache-67fd659dcb-thb68 1/1 Running 0 4m41s
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
horizontalpodautoscaler.autoscaling/php-apache Deployment/php-apache cpu: 40%/50% 1 10 10 21m
发现自动增加了Pod,实现自动扩容