Horizontal Pod Autoscaler 可以根据 CPU 利用率自动扩缩 ReplicationController、 Deployment、ReplicaSet 或 StatefulSet 中的 Pod 数量
HorizontalPodAutoscaler(简称 HPA ) 自动更新工作负载资源(例如 Deployment 或者 StatefulSet), 目的是自动扩缩工作负载以满足需求。
水平扩缩意味着对增加的负载的响应是部署更多的 Pod。 这与 “垂直(Vertical)” 扩缩不同,对于 Kubernetes, 垂直扩缩意味着将更多资源(例如:内存或 CPU)分配给已经为工作负载运行的 Pod。
如果负载减少,并且 Pod 的数量高于配置的最小值, HorizontalPodAutoscaler 会指示工作负载资源(Deployment、StatefulSet 或其他类似资源)缩减。
有关 metrics-server 地址:https://github.com/kubernetes-sigs/metrics-server#readme
Metrics Server是 k8s 内置自动缩放管道的可扩展、高效的容器资源度量源。
Metrics Server 从 Kubelets 收集资源度量,并通过Metrics API在Kubernetes apiserver中公开这些度量,供Horizontal Pod Autoscaler和Vertical Pod Autocaler使用。kubectl top还可以访问Metrics API,从而更容易调试自动缩放管道。
准备 yaml
文件
##### 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:
- pods
- nodes
- nodes/stats
- namespaces
- configmaps
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
- --kubelet-insecure-tls
- --secure-port=4443
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --kubelet-use-node-status-port
image: registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/metrics-server:v0.4.3
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
httpGet:
path: /livez
port: https
scheme: HTTPS
periodSeconds: 10
name: metrics-server
ports:
- containerPort: 4443
name: https
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /readyz
port: https
scheme: HTTPS
periodSeconds: 10
securityContext:
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
查看一下状态
kubectl get pod -n kube-system
查看一下指标
##节点使用情况
kubectl top nodes --use-protocol-buffers
##pod使用情况
kubectl top pods --use-protocol-buffers
我们可以登陆 Dashboard 上去查看信息收集
HPA
也是 k8s 中的一种资源,就是写这个资源的 yaml
文件来实现的
准备一个镜像
来自1.21版本的k8s 官方文档
FROM php:5-apache
COPY index.php /var/www/html/index.php
RUN chmod a+rx index.php
index.php 文件内容
$x = 0.0001;
for ($i = 0; $i <= 1000000; $i++) {
$x += sqrt($x);
}
echo "OK!";
?>
构建一下这个镜像:docker build -t hpa-example .
准备 Deployment
###hpa-example.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: php-apache
spec:
selector:
matchLabels:
run: php-apache
replicas: 1
template:
metadata:
labels:
run: php-apache
spec:
containers:
- name: php-apache
imagePullPolicy: Never
image: hpa-example
ports:
- containerPort: 80
resources:
limits:
cpu: 500m
requests:
cpu: 200m
---
apiVersion: v1
kind: Service
metadata:
name: php-apache
labels:
run: php-apache
spec:
ports:
- port: 80
selector:
run: php-apache
启动一下
编写 HPA
怎么写这个东西呢?直接描述就行了 kubectl explain hpa
如果不是整合第三方的话,这个资源能写的信息很少
FIELDS:
maxReplicas > -required- ## 自动缩放器可设置的数量上限,不能小于Min
upper limit for the number of pods that can be set by the autoscaler;
cannot be smaller than MinReplicas.
minReplicas >
minReplicas is the lower limit for the number of replicas to which the
autoscaler can scale down. It defaults to 1 pod. minReplicas is allowed to
be 0 if the alpha feature gate HPAScaleToZero is enabled and at least one
Object or External metric is configured. Scaling is active as long as at
least one metric value is available.
scaleTargetRef
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata: ##元数据
name: php-apache
spec:
maxReplicas: 10 ##最大10个
minReplicas: 1 ##最小1个
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment ##资源类型,将于动态扩缩容的目标引用
name: php-apache
targetCPUUtilizationPercentage: 50 ## 目标CPU使用率就扩容,低于就缩容
创建一下 HPA
动态监控一下
kubectl get hpa -w
kubectl get pod -l run=php-apache -w
增加负载
##一直访问
while true;do curl 10.96.169.3;done
动态观察结果
运行一段发现负载升高,实现了自动扩容
Ctrl + C
取消循环后,资源利用率会降下去,但是会有一个缓冲时间才会进行缩容
等一段时间后(好像是5分钟),最终会缩容到一个
有很多度量指标,参考最新版本的地址:https://kubernetes.io/zh-cn/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/#autoscaling-on-multiple-metrics-and-custom-metrics
基于多项度量指标和自定义度量指标自动扩缩
金丝雀部署来源于矿场的一个场景:矿工进矿洞之前会放入金丝雀,金丝雀对瓦斯气体很敏感,如果放进去了没有叽叽喳喳声音,矿工就不会进去了
与滚动发布相比
滚动发布:
首先准备一个 service
##canary-test.yaml
apiVersion: v1
kind: Service
metadata:
name: canary-test
namespace: default
spec:
selector:
app: canary-nginx
type: NodePort ## 浏览器可以直接访问
ports:
- name: canary-test
port: 80 ###
targetPort: 80 ## Pod的访问端口
protocol: TCP
nodePort: 31666 ## 浏览器访问端口
准备三个版本镜像
##v1版本:nginx-demo1
FROM nginx
ENV version="v1"
RUN echo $version > /usr/share/nginx/html/index.html
##v2版本:nginx-demo2
FROM nginx
ENV version="v2"
RUN echo $version > /usr/share/nginx/html/index.html
##v3版本:nginx-demo3
FROM nginx
ENV version="v3"
RUN echo $version > /usr/share/nginx/html/index.html
构建镜像
docker build -t nginx:demo1 .
准备一个 v1 版本的 Deployment
###canary-deploy-demo1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: canary-dep-v1
namespace: default
labels:
app: canary-dep-v1
spec:
selector:
matchLabels:
app: canary-nginx
version: v1
replicas: 1
template:
metadata:
labels:
app: canary-nginx
version: v1
spec:
containers:
- name: nginx
image: nginx:demo1
imagePullPolicy: Never
创建一次 Deployment
kubectl apply -f canary-deploy-demo1.yaml
访问检查
再启动一个v2版本
###canary-deploy-demo2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: canary-dep-v2
namespace: default
labels:
app: canary-dep-v2
spec:
selector:
matchLabels:
app: canary-nginx
version: v2
replicas: 1
template:
metadata:
labels:
app: canary-nginx
version: v2
spec:
containers:
- name: nginx
image: nginx:demo2
imagePullPolicy: Never
访问一下
v2版本没问题,我们进行一个扩容操作
##更改canary-deploy-demo2.yaml的.spec.replicas字段信息
replicas: 5
这个时候,通往 v2 版本的流量就增加了
我们的新版本就OK,就可以删除v1版本了
执行下面的任务期间,Kubernetes 标记 Deployment 为进行中(Progressing)_:
当上线过程进入“Progressing”状态时,Deployment 控制器会向 Deployment 的 .status.conditions
中添加包含下面属性的状况条目:
type: Progressing
status: "True"
reason: NewReplicaSetCreated
| reason: FoundNewReplicaSet
| reason: ReplicaSetUpdated
监视 Deployment
进度:kubectl rollout status deploy nginx-deployment
当 Deployment 具有以下特征时,Kubernetes 将其标记为完成(Complete);
当上线过程进入“Complete”状态时,Deployment 控制器会向 Deployment 的 .status.conditions
中添加包含下面属性的状况条目:
type: Progressing
status: "True"
reason: NewReplicaSetAvailable
Deployment 可能会在尝试部署其最新的 ReplicaSet 受挫,一直处于未完成状态。 造成此情况一些可能因素如下:
描述性查看 Deployment
情况:kubectl describe deployment nginx-deployment
可应用于已完成的 Deployment 的所有操作也适用于失败的 Deployment。 你可以对其执行扩缩容、回滚到以前的修订版本等操作,或者在需要对 Deployment 的 Pod 模板应用多项调整时,将 Deployment 暂停。
清理策略
可以在 Deployment 中设置 .spec.revisionHistoryLimit
字段以指定保留此 Deployment 的多少个旧有 ReplicaSet。其余的 ReplicaSet 将在后台被垃圾回收。 默认情况下,此值为 10。
将此字段设置为 0 将导致 Deployment 的所有历史记录被清空,造成 Deployment 将无法回滚
万能的排错方式:kubectl describe xxxxxx