Kubernetes安装Metrics-server
Metrics Server 简介
Metrics Server 是 Kubernetes 监控组件中的重要一部分,Metrics Server 主要分为 API 和 Server 两大部分。其中 Metrics API 部分主要通过 APIServer 对外暴露 Pod 资源使用情况,比如:HPA、kubectl top、Kubernetes dashboard 等。Metrics Server 是根据 Kubernetes 监控架构进行实施,该组件会定期通过 Summary API 从 Kubelet 所在集群节点获取服务指标,然后将指标汇总、存储到内存中,仅仅存储指标最新状态,一旦重启组件数据将会丢失。现在通过 Metrics Server 采集到了数据,也暴露了 API 那么通过 kube-aggregator 统一把 API Server(/apis/metrics) 数据转发给 Metrics Server,最后通过 metrics api 统一暴露出去。
Metrics Server 抽象了 HorizontalPodAutoscaler 资源对象,通过观察 Pod CPU、内存或者其它自定义指标自动缩放 Controller、Deployment、StatefulSet中的 Pod 数量,注意 HorizontalPodAutoscaler 不支持无法缩放的对象,比如 DaemonSet。
下载并修改配置
最好下载下来运行
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/high-availability-1.21+.yaml
#1.由于网络原因,修改资源文件中的镜像地址
image: registry.k8s.io/metrics-server/metrics-server:v0.7.1
修改为
image: registry.aliyuncs.com/google_containers/metrics-server:v0.7.1
#2.修改如下两处地方,否则启动会报错
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
修改为
- --kubelet-preferred-address-types=InternalIP
#增加配置
- --kubelet-insecure-tls
应用配置
kubectl apply -f high-availability-1.21+.yaml
查看是否运行
[root@k8s-master01 software]# kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
k8s-master01 134m 6% 2507Mi 79%
k8s-worker01 125m 6% 2222Mi 76%
k8s-worker02 134m 6% 2498Mi 79%
[root@k8s-master01 software]# kubectl top pod
NAME CPU(cores) MEMORY(bytes)
nginx-demo-7c8655954-92cmh 1m 43Mi
nginx-demo-7c8655954-zzgv7 1m 43Mi
HPA
HPA与VPA简介
前提要有metrics-server插件组件,metrics-server定期的(默认为15s)收集Pod资源的平均CPU负载情况。
- HPA: 根据Pod的CPU或内存的使用率为控制器管理的Pod资源副本数量实现自动扩缩容。
- VPA: 根据Pod容器的CPU和内存的使用率自动设置Pod容器的CPU和内存的requests资源量限制。
两个的差别
– HPA: 主要关注整个应用程序水平方向的伸缩,通过调整 Pod 的副本数量来应对负载变化;
– VPA 则关注 Pod 内部容器的垂直伸缩,通过调整容器的资源限制来优化资源利用和性能。
策略 | 缩放方向 | 实现手段 | CPU 或内存资源 |
---|---|---|---|
HPA | 水平缩放 (HPA) | 增加 Pod数量 | 减少现有的Pod的CPU或资源 |
VPA | 垂直缩放 (VPA) | 删除 pod | 增加现有的Pod的CPU或资源 |
HPA自动扩容缩容测试
部署测试应用
手动拉取镜像,防止拉不下来
crictl pull mirrorgooglecontainers/hpa-example
cat > hpa-pod.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: php-apache
name: php-apache
spec:
replicas: 1
selector:
matchLabels:
run: php-apache
template:
metadata:
labels:
run: php-apache
spec:
containers:
- image: mirrorgooglecontainers/hpa-example
name: php-apache
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
resources:
requests:
cpu: 200m
---
apiVersion: v1
kind: Service
metadata:
name: php-apache
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
run: php-apache
EOF
kubectl apply -f hpa-pod.yaml
创建hpa控制器
HorizontalPodAutoscaler 对象,默认最小副本数为 1,cpu 或者 内存达到定义的限制开始扩容,最大副本数量为 4
cat > hpa.yml << EOF
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
creationTimestamp: "2024-05-22T23:37:58Z"
name: php-apache
namespace: default
resourceVersion: "681529"
uid: 47495c14-d34e-41c5-9857-c0aedc178e90
spec:
maxReplicas: 10
metrics:
- resource:
name: cpu
target:
averageUtilization: 50
type: Utilization
type: Resource
minReplicas: 1
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
EOF
kubectl apply -f hpa.yml
或者使用命令创建HPA
kubectl autoscale deployment php-apache –cpu-percent=50 –min=1 –max=10
--min=<最小副本数>: 指定自动伸缩时的最小副本数。
--max=<最大副本数>: 指定自动伸缩时的最大副本数。
--cpu-percent=<requests资源量百分比阈值>: 指定自动伸缩的CPU利用率阈值百分比。当控制器资源的CPU利用率达到阈值时,将自动扩展副本数。
查看hpa
[root@k8s-master01 hpa]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache <unknown>/50% 1 10 0 5s
部署一个容器来给HPA测试容器压力
首先开另一个窗口监控
kubectl get hpa -w
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache 0%/50% 1 10 1 6m5s
创建busybox容器不段访问目标容器给与压力
kubectl run -i --tty load-generator --rm --image=busybox --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"
观察到随着压力pod数量逐渐增加
最终稳定在8个容器,平均cpu在50以下
删除压力测试pod load-generator
[root@k8s-master01 hpa]# kubectl delete pod load-generator
pod “load-generator” deleted
删除压力测试pod后,可以看到很长时间pod的数量才逐渐减小
HPA增加pod的策略比较积极,减少的策略比较消极,这是为了实际需求考虑,防止一次性减少的pod过多导致pod的数量又不够,还要再次增加pod,如此反复肯定不行
VPA
VPA简介
VPA主要由三个组件组成,分别为recommender、updater、admission-controller
1)recommender:引入VerticalPodAutoscaler对象,其由 Pod 的标签选择器、资源策略(控制 VPA 如何计算资源)、更新策略(控制如何将更改应用于 Pod)和推荐的 Pod 资源组成,其根据metric-server获取到的容器指标并观测 OOM 事件,计算推荐指标,最终更新VerticalPodAutoscaler对象
2)updater:其是负责Pod更新的组件。如果 Pod 在 “Auto” 模式下使用 VPA,则 Updater 可以决定使用推荐器资源对其进行更新。这只是通过驱逐Pod以便使用新资源重新创建它来实现的。简单来说,其是根据pod的request中设置的指标和recommend计算的推荐指标,在一定条件下驱逐pod,
3)admission-controller:这是一个webhook组件,所有 Pod 创建请求都通过 VPA Admission Controller,如果Pod与VerticalPodAutoscaler 对象匹配,把recommend计算出的指标应用到pod的request和limit,如果 Recommender 不可用,它会回退到 VPA 对象中缓存的推荐。
VPA四种运行模式
- “Auto”:VPA 在创建 pod 时分配资源请求,并使用首选更新机制在现有 pod 上更新它们。目前这相当于”Recreate”(见下文)。一旦 pod 请求的免重启(“就地”)更新可用,它可能会被该”Auto”模式用作首选的更新机制。注意:VPA 的此功能是实验性的,可能会导致您的应用程序停机,当目前运行的pod的资源达不到VPA的推荐值,就会执行pod驱逐,重新部署新的足够资源的服务
- “Recreate”:VPA 在创建 Pod 时分配资源请求,并在现有 Pod 上更新它们,当请求的资源与新建议有很大差异时(尊重 Pod 中断预算,如果定义)。这种模式应该很少使用,只有当您需要确保在资源请求发生变化时重新启动 Pod 时。否则,更喜欢这种”Auto”模式,一旦它们可用,就可以利用重新启动免费更新。注意:VPA 的此功能是实验性的,可能会导致您的应用程序停机
- “Initial”:VPA 仅在创建 pod 时分配资源请求,以后不会更改它们
- “Off”:VPA 不会自动更改 Pod 的资源需求。这些建议是经过计算的,并且可以在 VPA 对象中进行检查。这种模式仅获取资源推荐值,但是不更新Pod(这种用的比较多)
安装VPA
首先升级openssl
编译安装OpenSSL
因为vpa的要求,openssl必须不低于1.1版本
cd /usr/local/src
wget https://www.openssl.org/source/openssl-1.1.1k.tar.gz
解压源码包:
tar -zxvf openssl-1.1.1k.tar.gz
编译安装OpenSSL:
cd openssl-1.1.1k
./config --prefix=/usr/local/openssl
make
make install
更新系统库链接:
mv /usr/bin/openssl /usr/bin/openssl.old
ln -s /usr/local/openssl/bin/openssl /usr/bin/openssl
echo "/usr/local/openssl/lib" >> /etc/ld.so.conf
ldconfig -v
验证新版本:
openssl version
提前下载镜像
首先下载镜像,不然下不下来,注意版本可能不同,需要根据vertical-pod-autoscaler的版本来
ctr -n k8s.io images pull docker.io/giantswarm/vpa-admission-controller:1.1.2
ctr -n k8s.io images pull docker.io/giantswarm/vpa-recommender:1.1.2
ctr -n k8s.io images pull docker.io/giantswarm/vpa-updater:1.1.2
ctr -n k8s.io images tag docker.io/giantswarm/vpa-admission-controller:1.1.2 registry.k8s.io/autoscaling/vpa-admission-controller:1.1.2
ctr -n k8s.io images tag docker.io/giantswarm/vpa-recommender:1.1.2 registry.k8s.io/autoscaling/vpa-recommender:1.1.2
ctr -n k8s.io images tag docker.io/giantswarm/vpa-updater:1.1.2 registry.k8s.io/autoscaling/vpa-updater:1.1.2
ctr -n k8s.io image rm docker.io/giantswarm/vpa-admission-controller:1.1.2
ctr -n k8s.io image rm docker.io/giantswarm/vpa-recommender:1.1.2
ctr -n k8s.io image rm docker.io/giantswarm/vpa-updater:1.1.2
应用VPA并验证
git clone https://github.com/kubernetes/autoscaler.git
cd autoscaler/vertical-pod-autoscaler/deploy
sed -i 's/Always/IfNotPresent/g' recommender-deployment.yaml
sed -i 's/Always/IfNotPresent/g' admission-controller-deployment.yaml
sed -i 's/Always/IfNotPresent/g' updater-deployment.yaml
cd ../hack
./vpa-up.sh
验证VPA是否安装上了
[root@k8s-master01 hack]# kubectl get customresourcedefinition | grep verticalpodautoscalers
verticalpodautoscalers.autoscaling.k8s.io 2024-05-23T02:54:50Z
VPA测试
cat > vpa.yml <<EOF
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: nginx-vpa-test
spec:
targetRef:
apiVersion: "apps/v1"
kind: Deployment
name: php-apache
updatePolicy:
updateMode: "Off"
resourcePolicy:
containerPolicies:
- containerName: "php-apache"
minAllowed:
cpu: "250m"
memory: "100Mi"
maxAllowed:
cpu: "2000m"
memory: "2048Mi"
controlledResources: ["cpu", "memory"]
EOF
kubectl apply -f vpa.yml
[root@k8s-master01 hpa]# kubectl get vpa
NAME MODE CPU MEM PROVIDED AGE
nginx-vpa-test Off 250m 262144k True 21m
首先删除hap防止干扰,两者冲突,不要放在一起使用
kubectl delete hpa php-apache
开一个窗口监视
kubectl describe vpa nginx-vpa-test |tail -n 20
Conditions:
Last Transition Time: 2024-05-23T03:25:27Z
Status: True
Type: RecommendationProvided
Recommendation:
Container Recommendations:
Container Name: php-apache
Lower Bound:
Cpu: 250m
Memory: 262144k
Target:
Cpu: 250m
Memory: 262144k
Uncapped Target:
Cpu: 25m
Memory: 262144k
Upper Bound:
Cpu: 2
Memory: 332193153
Events: <none>
运行压力测试pod
kubectl run -i --tty load-generator --rm --image=busybox --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"
可以看到Uncapped Target变大了
ctrl +c结束 load-generator
high-availability-1.21+.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:
replicas: 2
selector:
matchLabels:
k8s-app: metrics-server
strategy:
rollingUpdate:
maxUnavailable: 1
template:
metadata:
labels:
k8s-app: metrics-server
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
k8s-app: metrics-server
namespaces:
- kube-system
topologyKey: kubernetes.io/hostname
containers:
- args:
- --cert-dir=/tmp
- --secure-port=10250
- --kubelet-preferred-address-types=InternalIP
- --kubelet-insecure-tls
- --kubelet-use-node-status-port
- --metric-resolution=15s
image: registry.aliyuncs.com/google_containers/metrics-server:v0.7.1
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: policy/v1
kind: PodDisruptionBudget
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
spec:
minAvailable: 1
selector:
matchLabels:
k8s-app: metrics-server
---
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 apply -f hpa.yml
error: resource mapping not found for name: “php-apache” namespace: “default” from “hpa.yml”: no matches for kind “HorizontalPodAutoscaler” in version “autoscaling/v2beta1”
ensure CRDs are installed first
原因apiVersion不对
1.26.8版本应该是
apiVersion: autoscaling/v2
而不是
apiVersion: autoscaling/v2beta1
安装VPA报错”unknown option -addext”
ERROR: Failed to create CA certificate for self-signing. If the error is “unknown option -addext”, update your openssl version or deploy VPA from the vpa-release-0.8 branch.
原因是openssl版本太低,要 version 1.1.1 or higher
切换到低版本的VPA安装
git checkout origin/vpa-release-0.8
./hack/vpa-up.sh
参考
浅谈 Kubernetes Metrics Server
【云原生-Kubernetes篇】HPA 与 Rancher管理工具
K8s降本增效之VPA上篇
一文带你掌握Kubernetes VPA(Pod纵向自动扩缩)