kubernetes pod 高级

一、pod资源限制

1、什么是pod的资源限制

在Kubernetes集群中,为了使系统能够稳定的运行,通常会对Pod的资源使用量进行限制。
在Kubernetes集群中,如果有一个程序出现异常,并占用大量的系统资源。如果未对该Pod进行资源限制的话,可能会影响其他的Pod正常运行,从而造成业务的不稳定性。

2、pod资源限制的实现方法

Kubernetes通过 Requests 和 Limits字段来实现对Pod的资源进行限制

  • Kubernetes通过 Requests 和 Limits字段来实现对Pod的资源进行限制
  • Limits: 限制 od 运行时最大可用的资源大小; (Pod在运行时Limits 比较重要)

3、资源限制的计算方法

  • CPU的计算方法

1核CPU等于1000毫核,当定义容器为0.5时,所能用到的CPU资源时1核心CPU的一半,对于 CPU 资源单位,表达式 .1 等价于表达式100m,可以看作 1 mitlicpu。

1 核心 =1000 millicpu(1 Core = 1000m)
0.5核=500millicpu(0.5 Core = 500m)

  • 内存的计算方法
    内存的基本单位是字节数(Bytes),也可以加上国际单位,十进制的E、P、T、G、M,K、m,或二进制的 Ei、Pi、Ti、Gi、Mi、Ki。
    1MB = 1000 KB = 100000 Bytes
    1Mi = 1024 KB = 1048576 bytes

4、安装metrics-server

  • GitHub下载地址
    metrics-server的GitHub地址

修改阿里云地址

image: registry.cn-huhehaote.aliyuncs.com/oldxu3957/metrics-server:v0.6.1
kubectl apply -f components.yaml

检查node和pod的资源使用

kubectl  top pod 
kubectl  top node 

二、CPU限制实践

1、设置cpu的限制

apiVersion: v1
kind: Pod
metadata:
  name: pod-resource-cpu
spec:
  containers:
  - name: cpu-demo
    image: vish/stress
    args:
    - "-cpus"
    - "2"
    resources:
      requests:
        cpu: "1000m"
      limits:
        cpu: "1000m"

kubernetes pod 高级_第1张图片

2、设置超过节点CPU的限制

设置CPU的请求的核心数为100核心

apiVersion: v1
kind: Pod
metadata:
  name: pod-resource-cpu
spec:
  containers:
  - name: cpu-demo
    image: vish/stress
    args:
    - "-cpus"
    - "2"
    resources:
      requests:
        cpu: "100"
      limits:
        cpu: "100"

kubernetes pod 高级_第2张图片
解析:
CPU的调度处于false 失败原因是master处于污点中,无法调度,3个node无法满足。pod状态处于pending中

3、如果不限制CPU的 limits会怎么样

如果没有为容器指定 CPU 限制,那么容器在可以使用的 CPU 资源是没有上限。因而可以使用所在节点上所有的可用 CPU 资源,这样可能会造成某一个Pod占用了大量的CPU时间,可能会影响其他的Pod正常运行从而造成业务的不稳定性。
这个也不用担心,在Kubernetes中,可以通过 LimitRange 自动为容器设定,所使用的CPU资源和内存资源最大最小值。

三、内存限制实践

1、限制pod内存

apiVersion: v1
kind: Pod
metadata:
  name: pod-resource-mem
spec:
  containers:
  - name: memory-demo-ctr
    image: polinux/stress
    command: ["stress"]
    args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1" ] # 告知容器尝试分配 150 MiB 内存 
    resources:
      requests:
        memory: "100Mi"
      limits:
        memory: "200Mi"

kubernetes pod 高级_第3张图片

2、运行容器内存限制的内存

apiVersion: v1
kind: Pod
metadata:
  name: pod-resource-mem
spec:
  containers:
  - name: memory-demo-ctr
    image: polinux/stress
    command: ["stress"]
    args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1" ] # 告知容器尝试分配 250 MiB 内存 
    resources:
      requests:
        memory: "100Mi"
      limits:
        memory: "200Mi"

在这里插入图片描述
kubernetes pod 高级_第4张图片
解析:
达到内存的运行的最大运行内存,会触发重启策略

四、pod的服务质量Qos

1、什么是QoS

QoS (Quality of Service) ,可译为 “服务质量等级",或者译作"服务质量保证",是作用在 Pod 上的一个配置,当 Kubernetes 创建一个 Pod 时,它就会给这个 Pod 分配一个 QoS 等级。

在Kubernetes的环境中,Kubernetes允许节点的Pod过载使用资源这意味着节点无法同时满足所有Pod以过载的方式运行。因此在内存资源紧缺的情况下,Kubernetes需要借助Pod对象的服务质量和优先级等完成判定,进而挑选对应的Pod杀死。Kubernetes根据pod的Requests和Limits属性,把Pod对象归类为三类 BestEffort、BurStable、Guaranteed。

2、QoS的等级

  • Guaranteed: Pod对象为每个容器都设置了CPU资源需求和资源限制,且两者的值相同;还同时为每个容器设置了内存需求与内存限制,并且两者的值相同。这类Pod对象具有最高级别服务质量。
  • Burstable: 至少有一个容器设置了CPU或内存资源Requests属性,但不满足Guaranteed,这类Pod具有中级服务质量。
  • BestEffort:没有为任何容器设置Requests和Limits属性,这类Pod对象服务质量是最低级别。

当 Kubernetes 集群内存资源紧缺,优先杀死BestEffort类别的容器,因为系统不为该类资源提供任何服务保证,但此类资源最大的好处就是能够尽可能的使用资源。

如果系统中没有BestEffort类别的容器,接下来就轮到Burstable类别的容器,如果有多个Burstable类别的容器,就看谁的内存资源占用多,就优先干掉谁。比如A容器申请1G内存资源,实际使用了95%,而B容器申请了2G内存资源,实际使用了80%,但任然会优先干掉A容器,虽然A
容器的用量少,但与自身的Requests值相比,它的占比要大于B容器。

对于Guaranteed类别的容器拥有最高优先级,它们不会被杀死,除非其内存资源需求超限,或者00M时没有其他更低优先级的Pod对象存在,才会干掉Guaranteed类容器。

3、实验

3.1 创建Guaranteed的Pod

对于 QoS 类为 Guaranteed 的 Pod:

  • Pod 中的每个容器都必须指定内存请求和内存限制,且Pod中每个容器内存请求必须等于内存限制。
  • pod 中的每个容器都必须指定CPU请求和CPU限制,且Pod中每个容器CPU请求必须等于CPU限制。

1.创建一个Pod,容器设置了内存请求和内存限制,值都是200MiB。容器设置了CPU请求和CPU限制,值都是70 mitLiCPU

apiVersion: v1
kind: Pod
metadata:
  name: pod-qos-guarantee
spec:
  containers:
  - name: qos-demo 
    image: nginx 
    resources :
      requests:
        cpu: "700m"
        memory: "200Mi"
      limits:
        cpu: "700m"
        memory: "200Mi"
kubectl describe pod  pod-qos-guarantee

kubernetes pod 高级_第5张图片

3.2 创建Burstable的Pod

如果满足下面条件,将会指定 Pod 的 QoS 类为 Burstable:

  • Pod 不符合 Guaranteed QoS 类的标准
  • Pod 中至少一个容器指定了,内存或 CPU 的请求或限制

1.创建一个Pod,容器设置了内存请求 100 MiB,以及内存限制 200MiB。

apiVersion: v1
kind: Pod
metadata:
  name: pod-qos-burstable
spec:
  containers:
  - name: qos-demo 
    image: nginx 
    resources :
      requests:
        memory: "100Mi"
      limits:
        memory: "200Mi"
kubectl describe  pod  pod-qos-burstable

kubernetes pod 高级_第6张图片

3.3 创建BestEffort的Pod

对于 QoS 类为 BestEffort 的 Pod,Pod 中的容器必须没有设置内
存和 CPU 限制或请求。
1.创建一个Pod,容器没有设置内存和 CPU 限制或请求

apiVersion: v1
kind: Pod
metadata:
  name: pod-qos-besteffort
spec:
  containers:
  - name: qos-demo 
    image: nginx 
kubectl describe pod pod-qos-besteffort

kubernetes pod 高级_第7张图片

3.4 创建多容器pod

创建一个Pod,一个容器指定了内存请求 200 MiB。 另外一个容器没有指定任何请求和限制。此 Pod 满足 Burstable QoS 类的标准但它不满足 Guaranteed QoS 类标准,因为它的一个容器设有内存请求。

apiVersion: v1
kind: Pod
metadata:
  name: pod-qos-mutil
spec:
  containers:
  - name: qos-demo 
    image: nginx 
    resources :
      requests:
        memory: "200Mi"
  - name: qos-demo2
    image: redis   

kubectl describe pod  pod-qos-mutil

kubernetes pod 高级_第8张图片

五、Downward API

1、什么是DownwardAPI

DownwardAPI可以让容器获取Pod的相关元数据信息,比如Pod名称Pod的IP,Pod的资源限制等,获取后通过env、volume的方式将相关的环境信息注入到容器中,从而让容器通过这些信息,来设定容器的运行特性。

  • 例如: Nginx进程根据节点的CPU核心数量自动设定要启动的worker进程数。
  • 例如: JVM虚拟根据Pod的内存资源限制,来设定对应容器的堆内存大小。
  • 例如: 获取Pod名称,以Pod名称注册到某个服务,当Pod结束后,调用prestop清理对应名称的注册信息。

2、DownwardAPI能够注入哪些元素

  • 查看命令
kubectl  explain  pod.spec.containers.env.valueFrom.fieldRef
  • metadata.name: Pod对象的名称
  • metadata.namespace: Pod对象隶属的名称空间
  • metadata.uid: Pod对象的UID
  • metadata.Labels[‘’]: 获取Label指定KEY对应的值
  • metadata.annotations[‘’]: 获取Annotations对应KEY的值
  • status.podIP:Pod对象的IP地址
  • status.hostIP: 节点IP
  • status.nodeName: 节点名称
  • spec.serviceAccountName: Pod对象使用的ServiceAccount资源名称

也可以通过yaml文件,拿相关详情信息

kubectl  get pod pod-qos-guarantee  -o yaml

kubernetes pod 高级_第9张图片
使用

kubectl  explain  pod.spec.containers.env.valueFrom.resourceFieldRef 

pod.spec.containers.env.valueFrom.resourceFieldRef 以注入的字段有:

  • requests .cpu
  • requests .memory
  • limits.cpu
  • limits.memory

3、通过环境变量的方式注入元数据

  • 1、创建Pod容器,将Pod相关环境变量注入到容器中,比如 (pod名称.命名空间、标签、以及cpu、内存的请求和限制)
apiVersion: v1
kind: Pod
metadata:
  name: pod-down-api
  labels:
    app: nginx-app
    role: backend
    zone: beijing
spec:
  containers:
  - name: pod-down-api
    image: nginx
    command: ["/bin/bash" ,  "-c", "env"]
    resources:
      requests:
        cpu: "200m"
        memory: "32Mi"
      limits:
        cpu: "200m"
        memory: "64Mi"

    env:
    - name: APP1_POD_NAME
      valueFrom:
        fieldRef:
          fieldPath: metadata.name

    - name: APP1_POD_NAMESPACE
      valueFrom:
        fieldRef:
          fieldPath: metadata.namespace

    - name: APP1_POD_LABELS
      valueFrom:
        fieldRef:
          fieldPath: metadata.labels['app']

    - name: APP1_CPU_REQUESTS
      valueFrom:
        resourceFieldRef:
          resource: requests.cpu

    - name: APP1_MEM_LIMITS
      valueFrom:
        resourceFieldRef:
          resource: limits.memory
          divisor: 1Mi                  # 输出的格式

查看注入的变量信息:

[root@master yaml]# kubectl  logs  pod-down-api   | grep APP1
APP1_POD_LABELS=nginx-app
APP1_POD_NAMESPACE=default
APP1_MEM_LIMITS=64
APP1_CPU_REQUESTS=1
APP1_POD_NAME=pod-down-api

4、通过存储卷的方式注入元数据

apiVersion: v1
kind: Pod
metadata:
  name: pod-down-api-volumes
  labels:
    app: nginx-app
    role: backend
    zone: beijing
spec:
  containers:
  - name: pod-down-api
    image: nginx
    resources:
      requests:
        cpu: "200m"
        memory: "32Mi"
      limits:
        cpu: "200m"
        memory: "64Mi"
    volumeMounts:
    - name: podinfo
      mountPath: /etc/info

  volumes:
  - name: podinfo
    downwardAPI:
      items:
      - path: pod_name
        fieldRef:
          fieldPath: metadata.name

      - path: pod_namespace
        fieldRef:
          fieldPath: metadata.namespace

      - path: pod_labels
        fieldRef:
          fieldPath: metadata.labels

      - path: req_cpu
        resourceFieldRef:
          containerName: pod-down-api
          resource: requests.cpu

      - path: limit_mem
        resourceFieldRef:
          containerName: pod-down-api
          resource: limits.memory

进入pod查看环境变量

kubectl  exec -it pod-down-api-volumes -- /bin/bash 

5、实战DownwordAPI为JVM注入堆内存大小限制

  • 步骤:
    1.运行一个默认的Tomcat,检查初始的JVM堆内存大小;
    2.对Tomcat设定资源限制,看看这个资源限制对Tomcat分配堆内存有没有什么影
    3.手动为TOmcat指定堆内存,300M,对Pod限制 100M;(死)
    4.将request limits的值,传递给jvm内存设定; (不会被频繁的Kill)因为,JVM认为自己最多能使用的就是200Mi,没有超过limits限制。

1、启动一个默认的Tomcat

apiVersion: v1
kind: Pod
metadata:
  name: pod-tomcat-downword
spec:
  containers:
  - name: tomcat 
    image: tomcat:9.0.63
    ports:
    - containerPort: 8080 
kubectl exec -it pod-tomcat-downword  -- /bin/bash 

在这里插入图片描述
在这里插入图片描述

  • 初始内存是60M 最大内存为1G
    在这里插入图片描述
    最大内存跟物理主机有关系,最大的堆内存是物理内存的1/4内存
    初始化内存是物理内存的1/64 ,
    4G=4096M 4096/64=64M 所以初始化内存符合初始化堆内存

2、启动一个现在内存大小为100M的pod

  • 准备工作
    安装ab 压测命令
yum -y install vim*
yum -y install httpd-tools
apiVersion: v1
kind: Pod
metadata:
  name: pod-tomcat-downword
spec:
  containers:
  - name: tomcat 
    image: tomcat:9.0.63
    ports:
    - containerPort: 8080 
    env:
    - name: JAVA_OPTS
      value: -server -Xms500m -Xmx500m -XX:+UseConcMarkSweepGC
    resources:
      requests:
        memory: 100Mi
      limits:
        memory: 100Mi
  • 跟踪内存使用量和pod 状态
watch -n 1 kubectl  top pod  pod-tomcat-downword 
watch -n 1 kubectl  get pod pod-tomcat-downword  -o wide 
  • ab压测pod的请求
ab -n 1000 -c 50 http://10.244.2.10:8080/
  • 测试结果
    kubernetes pod 高级_第10张图片

在这里插入图片描述

3 、将Tomcat的jvm的启动参数,以环境变量的方式注入jvm 参数中去

apiVersion: v1
kind: Pod
metadata:
  name: pod-tomcat-downward

spec:
  containers:
  - name: tomcat
    image: tomcat:9.0.63
    ports:
    - containerPort: 8080
    env:
    - name: JAVA_OPTS
      value: -server -Xms${JVM_XMS} -Xmx${JVM_XMX} -XX:+UseConcMarkSweepGC
    - name: JVM_XMS
      valueFrom:
        resourceFieldRef:
          resource: requests.memory
    - name: JVM_XMX
      valueFrom:
        resourceFieldRef:
          resource: limits.memory
    resources:
      requests:
        memory: 100Mi
      limits:
        memory: 100Mi

kubernetes pod 高级_第11张图片

  • 查看jvm的测试结果,符合jvm的启动参数,已经将JVM的启动参数,已经注入到pod的启动参数中。

6、为服务注册pod名称信息

  • 实验背景:
    1、当pod创建时,pod的名称,以pod名称创建数据库
    2、当pod发生改变,或者删除时,以pod名称创建的数据库名,自动删除

你可能感兴趣的:(devops,kubernetes,容器,云原生)