Kubernetes之资源监控

  • Post author:
  • Post category:其他


一、k8s容器资源限制

Kubernetes采用request和limit两种限制类型来对资源进行分配。

  • request(资源需求):即运行Pod的节点必须满足运行Pod的最基本需求才能运行Pod。
  • limit(资源限额):即运行Pod期间,可能内存使用量会增加,那最多能使用多少内存,这就是资源限额

资源类型:

  • CPU 的单位是核心数,内存的单位是字节。
  • 一个容器申请0.5个CPU,就相当于申请1个CPU的一半,你也可以加个后缀m 表示千分之一的概念。比如说100m的CPU,100豪的CPU和0.1个CPU都是一样的。

内存单位:

  • K、M、G、T、P、E          #以1000为换算标准
  • Ki、Mi、Gi、Ti、Pi、Ei     #以1024为换算标准

内存限制示例:

apiVersion: v1
kind: Pod
metadata:
  name: memory-demo
spec:
  containers:
  - name: memory-demo
    image: reg.harbor.com/library/stress    
    args:
    - --vm
    - "1"
    - --vm-bytes
    - 200M
    resources:
      requests:
        memory: 50Mi
      limits:
        memory: 100Mi
kubectl create -f memory.yaml
kubectl get pod

如果容器超过其内存限制,则会被终止。如果可重新启动,则与所有其他类型的运行时故障一样,kubelet 将重新启动它。

如果一个容器超过其内存请求,那么当节点内存不足时,它的 Pod 可能被逐出。

CPU限制示例:

apiVersion: v1
kind: Pod
metadata:
  name: cpu-demo
spec:
  containers:
  - name: cpu-demo
    image: reg.harbor.com/library/stress
    resources:
      limits:
        cpu: "10"
      requests:
        cpu: "5"
    args:
    - -c
    - "2"
kubectl create -f cpu.yaml
kubectl get pod
kubectl describe pod cpu-demo   

调度失败是因为申请的CPU资源超出集群节点所能提供的资源但CPU使用率过高,不会被杀死

为namespace设置资源限制:

apiVersion: v1
kind: LimitRange
metadata:
  name: limitrange-memory
spec:
  limits:
  - default:
      cpu: 0.5
      memory: 512Mi
    defaultRequest:
      cpu: 0.1
      memory: 256Mi
    max:
      cpu: 1
      memory: 1Gi
    min:
      cpu: 0.1
      memory: 100Mi
    type: Container
kubectl create -f limit.yaml
kubectl describe limitranges   #LimitRange 在 namespace 中施加的最小和最大内存限制只有在创建和更新 Pod 时才会被应用。改变 LimitRange 不会对之前创建的 Pod 造成影响。

为namespace设置资源配额:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: mem-cpu-demo
spec:
  hard:
    requests.cpu: "1"
    requests.memory: 1Gi
    limits.cpu: "2"
    limits.memory: 2Gi

创建的ResourceQuota对象将在default名字空间中添加以下限制:

  • 每个容器必须设置内存请求(memory request),内存限额(memory limit),cpu请求(cpu request)和cpu限额(cpu limit)。
  • 所有容器的内存请求总额不得超过1 GiB。
  • 所有容器的内存限额总额不得超过2 GiB。
  • 所有容器的CPU请求总额不得超过1 CPU。
  • 所有容器的CPU限额总额不得超过2 CPU。

为 Namespace 配置Pod配额:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: pod-demo
spec:
  hard:
    pods: "2"

设置Pod配额以限制可以在namespace中运行的Pod数量。

最后删除刚才的配置

二、kubernetes资源监控

1. Metrics-Server部署

Metrics-Server是集群核心监控数据的聚合器,用来替换之前的heapster

容器相关的 Metrics 主要来自于 kubelet 内置的 cAdvisor 服务,有了Metrics-Server之后,用户就可以通过标准的 Kubernetes API 来访问到这些监控数据。

  • Metrics API 只可以查询当前的度量数据,并不保存历史数据。
  • Metrics API URI 为 /apis/metrics.k8s.io/,在 k8s.io/metrics 维护。
  • 必须部署 metrics-server 才能使用该 API,metrics-server 通过调用 Kubelet SummaryAPI 获取数据

示例:

  • http://127.0.0.1:8001/apis/metrics.k8s.io/v1beta1/nodes
  • http://127.0.0.1:8001/apis/metrics.k8s.io/v1beta1/nodes/<node-name>
  • http://127.0.0.1:8001/apis/metrics.k8s.io/v1beta1/namespace/<namespace-name>/pods/<pod-name>

Metrics Server 并不是 kube-apiserver 的一部分,而是通过 Aggregator 这种插件机制,在独立部署的情况下同 kube-apiserver 一起统一对外服务的。

kube-aggregator 其实就是一个根据 URL 选择具体的 API 后端的代理服务器。

Metrics-server属于Core metrics(核心指标),提供API metrics.k8s.io,仅提供Node和Pod的CPU和内存使用情况。而其他Custom Metrics(自定义指标)由Prometheus等组件来完成。

资源下载:

https://github.com/kubernetes-incubator/metrics-server

Metrics-server部署:

git clone https://github.com/kubernetes-incubator/metrics-server
##因为太慢,我用了码云加速 git clone https://gitee.com/zy_yhz/metrics-server.git
cd metrics-server
kubectl apply -f deploy/kubernetes


这时候查看pod发现出现问题

kubectl -n kube-system describe pods metrics-server-75d4fff9f-vv7gn

因为网络原因,拉取镜像失败

解决:从阿里云手动拉取,重新tag

docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6 k8s.gcr.io/metrics-server-amd64:v0.3.6
docker rmi registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6

因为刚才是部署在server2的,我是在server1拉取的,在这里打包发送给server2(可以直接server2拉取)

docker save -o metrics-server-amd64.tar k8s.gcr.io/metrics-server-amd64
scp metrics-server-amd64.tar root@server2:/mnt

server2节点load

docker load < /mnt/metrics-server-amd64.tar 

kubectl -n kube-system get deployment  ##查看pod

部署后查看Metrics-server的Pod日志:


错误1:

dial tcp: lookup server2 on 10.96.0.10:53: no such host

这是因为没有内网的DNS服务器,所以metrics-server无法解析节点名字。可以直接修改coredns的configmap,将各个节点的主机名加入到hosts中,这样所有Pod都可以从CoreDNS中解析各个节点的名字。

解决:

kubectl edit configmap coredns -n kube-system


报错2:

x509: certificate signed by unknown authority

Metric Server 支持一个参数 –kubelet-insecure-tls,可以跳过这一检查,然而官方也明确说了,这种方式不推荐生产使用。

解决:

启用TLS Bootstrap 证书签发

vim /var/lib/kubelet/config.yaml
...
serverTLSBootstrap: true   ##该设置打开
systemctl restart kubelet
kubectl get csr
kubectl certificate approve csr-n9pvr


报错3:

Error from server (ServiceUnavailable): the server is currently unable to handle the request (get nodes.metrics.k8s.io)

如果metrics-server正常启动,没有错误,一般为网络问题。修改metrics-server的Pod 网络模式:

hostNetwork: true


错误4:

v1beta1.metrics.k8s.io                 kube-system/metrics-server   False (FailedDiscoveryCheck)   9s

修改deployment重新部署

  1 ---
  2 apiVersion: v1
  3 kind: ServiceAccount
  4 metadata:
  5   name: metrics-server
  6   namespace: kube-system
  7 ---
  8 apiVersion: apps/v1
  9 kind: Deployment
 10 metadata:
 11   name: metrics-server
 12   namespace: kube-system
 13   labels:
 14     k8s-app: metrics-server
 15 spec:
 16   selector:
 17     matchLabels:
 18       k8s-app: metrics-server
 19   template:
 20     metadata:
 21       name: metrics-server
 22       labels:
 23         k8s-app: metrics-server
 24     spec:
 25       serviceAccountName: metrics-server
 26       volumes:
 27       - name: tmp-dir
 28         emptyDir: {}
 29       hostNetwork: true
 30       containers:
 31       - name: metrics-server
 32         image: reg.harbor.com/library/metrics-server-amd64
 33         imagePullPolicy: IfNotPresent
 34         args:
 35           - /metrics-server
 36           - --kubelet-preferred-address-types=InternalIP
 37           - --kubelet-insecure-tls   ##为了方便测试我这里直跳过安全tls,推荐配置相关证书
 38           - --cert-dir=/tmp
 39           - --secure-port=4443
 40         ports:
 41         - name: main-port
 42           containerPort: 4443
 43           protocol: TCP
 44         securityContext:
 45           readOnlyRootFilesystem: true
 46           runAsNonRoot: true
 47           runAsUser: 1000
 48         volumeMounts:
 49         - name: tmp-dir
 50           mountPath: /tmp
 51       nodeSelector:
 52         kubernetes.io/os: linux
 53         kubernetes.io/arch: "amd64"

部署成功后

kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes/server1"

kubectl top node

2. Dashboard部署

Dashboard可以给用户提供一个可视化的 Web 界面来查看当前集群的各种信息。用户可以用 Kubernetes Dashboard 部署容器化的应用、监控应用的状态、执行故障排查任务以及管理 Kubernetes 各种资源。

网址:

https://github.com/kubernetes/dashboard

下载部署文件:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-rc5/aio/deploy/recommended.yaml
kubectl -n kubernetes-dashboard get svc  #修改为NodePort方式,以便外部访问。

登陆dashboard需要认证,需要获取dashboard pod的token:

kubectl describe secrets kubernetes-dashboard-token-g2g6g -n kubernetes-dashboard

默认dashboard对集群没有操作权限,需要授权:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kubernetes-dashboard-admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard

Dashboard如果无法展示metrics-server的数据指标,可以通过以下两种方式解决:

  • 修改dashboard-metrics-scraper 的Pod网络模式: hostNetwork: true
  • 通过node或pod的亲和性设置,让dashboard-metrics-scraper和metrics-server的Pod处于同一个node节点。

三、HPA

官网:

https://kubernetes.io/zh/docs/tasks/run-application/horizontal-pod-autoscale- walkthrough/

运行deployment 服务:

kubectl run hpa-example --image=hpa-example --requests=cpu=200m --expose --port=80
kubectl get deployments.apps
kubectl autoscale deployment hpa-example --cpu-percent=50 --min=1 --max=10
kubectl get hpa
kubectl get svc hpa-example
kubectl run test -it --rm --image=busybox --restart=Never
kubectl get hpa

HPA伸缩过程:

  • 收集HPA控制下所有Pod最近的cpu使用情况(CPU utilization)
  • 对比在扩容条件里记录的cpu限额(CPUUtilization)
  • 调整实例数(必须要满足不超过
  • 每隔30s做一次自动扩容的判断

CPU utilization的计算方法是用cpu usage(最近一分钟的平均值,通过metrics可以直接获取到)除以cpu request(这里cpu request就是我们在创建容器时制定的cpu使用核心数)得到一个平均值,这个平均值可以理解为:平均每个Pod CPU核心的使用占比

HPA进行伸缩算法:

  • 计算公式:TargetNumOfPods = ceil(sum(CurrentPodsCPUUtilization) / Target)
  • ceil()表示取大于或等于某数的最近一个整数
  • 每次扩容后冷却3分钟才能再次进行扩容,而缩容则要等5分钟后。
  • 当前Pod Cpu使用率与目标使用率接近时,不会触发扩容或缩容:

    触发条件:avg(CurrentPodsConsumption) / Target >1.1 或 <0.9

HPAv2

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-example
spec:
  maxReplicas: 10
  minReplicas: 1
  scaleTargetRef:
    apiVersion: apps/v1
  kind: Deployment
  name: hpa-example
  metrics:
  - type: Resource
    resource:
    name: cpu
    target:
      averageUtilization: 60
      type: Utilization
  - type: Resource
    resource:
    name: memory
    target:
      averageValue: 50Mi
      type: AverageValue



版权声明:本文为qq_36023219原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。