k8s - Helm

Helm 官方文档:https://helm.sh/zh/docs/

本文使用的 Helm 的版本为 3.4.1

一、概述

在没使用 helm 之前,向 kubernetes 部署应用,我们要依次部署 deployment、svc 等,步骤较繁琐。况且随着很多项目微服务化,复杂的应用在容器中部署以及管理显得较为复杂,helm 通过打包的方式,支持发布的版本管理和控制,很大程度上简化了 Kubernetes 应用的部署和管理

Helm 本质就是让 K8s 的应用管理(Deployment,Service 等 ) 可配置,能动态生成。通过动态生成 K8s 资源清单文件(deployment.yaml,service.yaml)。然后调用 Kubectl 自动执行 K8s 资源部署

Helm 是官方提供的类似于 YUM 的包管理器,是部署环境的流程封装。Helm 有两个重要的概念:chartrelease

  • chart 是创建一个应用的信息集合,包括各种 Kubernetes 对象的配置模板、参数定义、依赖关系、文档说明等。chart 是应用部署的自包含逻辑单元。可以将 chart 想象成 apt、yum 中的软件安装包
  • releasechart运行实例,代表了一个正在运行的应用。当 chart 被安装到 Kubernetes 集群,就生成一个 releasechart 能够多次安装到同一个集群,每次安装都是一个 release

Helm 包含两个组件:Helm 客户端和 Tiller 服务器,如下图所示

在这里插入图片描述

二、Helm 部署

越来越多的公司和团队开始使用 Helm 这个 Kubernetes 的包管理器,我们也将使用 Helm 安装 Kubernetes 的常用组件。 Helm 的安装十分简单。 下载 helm 命令行工具到 master 节点的 /usr/local/bin 下,我使用的是 Centos7,这里下载的是 3.4.1 版本:

wget https://get.helm.sh/helm-v3.4.1-linux-amd64.tar.gz
tar -zxvf helm-v3.4.1-linux-amd64.tar.gz
cd linux-amd64/
cp helm /usr/local/bin
chmod a+x /usr/local/bin/helm

其它版本请或者其它系统请移步官网:https://helm.sh/zh/docs/intro/install/

三、Helm 下载

  1. 访问 Helm 仓库:https://artifacthub.io/
  2. 搜索需要的包
  3. 按照 install 步骤操作即可
    在这里插入图片描述
    在这里插入图片描述

四、Helm 自定义模板

1. Helm 目录结构

chart 是一个组织在文件目录中的集合。

在这个目录中,Helm 期望可以匹配以下结构:

Chart.yaml          # 包含了chart信息的YAML文件
LICENSE             # 可选: 包含chart许可证的纯文本文件
README.md           # 可选: 可读的README文件
values.yaml         # chart 默认的配置值
values.schema.json  # 可选: 一个使用JSON结构的values.yaml文件
charts/             # 包含chart依赖的其他chart
crds/               # 自定义资源的定义
templates/          # 模板目录, 当和values 结合时,可生成有效的Kubernetes manifest文件
templates/NOTES.txt # 可选: 包含简要使用说明的纯文本文件

2. Chart.yaml 结构

Chart.yaml 文件是 chart 必需的。包含了以下字段:

apiVersion: chart API 版本 (必需)
name: chart名称 (必需)
version: 版本(必需)
kubeVersion: 兼容Kubernetes版本的语义化版本(可选)
description: 一句话对这个项目的描述(可选)
type: chart类型 (可选)
keywords:
  - 关于项目的一组关键字(可选)
home: 项目home页面的URL (可选)
sources:
  - 项目源码的URL列表(可选)
dependencies: # chart 必要条件列表 (可选)
  - name: chart名称 (nginx)
    version: chart版本 ("1.2.3")
    repository: 仓库URL ("https://example.com/charts") 或别名 ("@repo-name")
    condition: (可选) 解析为布尔值的yaml路径,用于启用/禁用chart (e.g. subchart1.enabled )
    tags: # (可选)
      - 用于一次启用/禁用 一组chart的tag
    enabled: (可选) 决定是否加载chart的布尔值
    import-values: # (可选)
      - ImportValue 保存源值到导入父键的映射。每项可以是字符串或者一对子/父列表项
    alias: (可选) chart中使用的别名。当你要多次添加相同的chart时会很有用
maintainers: # (可选)
  - name: 维护者名字 (每个维护者都需要)
    email: 维护者邮箱 (每个维护者可选)
    url: 维护者URL (每个维护者可选)
icon: 用做icon的SVG或PNG图片URL (可选)
appVersion: 包含的应用版本(可选)。不需要是语义化的
deprecated: 不被推荐的chart (可选,布尔值)
annotations:
  example: 按名称输入的批注列表 (可选).
  • apiVersion:在 Helm3 中,apiVersion=v2;在 Helm3 之前的版本,apiVersion=v1

3. 内置对象

(1) Values

Values 对象是为 Chart 模板提供值,这个对象的值有4个来源,后面的可以覆盖前面的:

  1. chart 包中的 values.yaml 文件
  2. 父 chart 包的 values.yaml 文件
  3. 通过 helm install 或者 helm upgrade-f 或者 --values 参数传入的自定义的 yaml 文件
  4. 通过 --set 参数传入的值

在模板文件中,通过 { {.Values}} 对象来访问设置的值。

  • 例如:定义一个 values.yaml

    image:
      repository: wangyanglinux/myapp
      tag: 'v1'
    
  • 在模板文件中就可以通过 { {.Values}} 对象访问到:

    apiVersion: v1
    kind: Pod
    metadata:
      name: test
    spec:
      template:
        spec:
          containers:
            - name: nginx
              image: {
          
          {
          
           .Values.image.repository }}:{
          
          {
          
           .Values.image.tag }}
              ports:
                - containerPort: 80
                  protocol: TCP
    

(2)其它内置对象

对象.属性 说明
Release.Name 版本名称(非chart的)
Release.Namespace 发布的chart版本的命名空间
Release.Service 组织版本的服务
Release.IsUpgrade 如果当前操作是升级或回滚,设置为true
Release.IsInstall 如果当前操作是安装,设置为true
Chart Chart.yaml的内容。因此,chart的版本可以从 Chart.Version 获得, 并且维护者在Chart.Maintainers里。

4. Helm 实例一,简单创建一个Nginx

(1)创建文件夹

# 创建文件夹
$ mkdir ./hello-world
$ cd ./hello-world

(2)创建 Chart.yaml

创建一个 hello-worldChart.yaml,这里只写了必需的字段:

$ cat <<'EOF' > ./Chart.yaml
apiVersion: v2
name: hello-world
version: 1.0.0
EOF

(3)创建 values.yaml

文件名如果不是 values.yaml,则需要在 helm install 时,通过 -f 指定 yaml 文件的位置

$ cat <<'EOF' > ./values.yaml
image:
  repository: wangyanglinux/myapp
  tag: 'v1'
EOF

(4)创建模版文件(templates)

模板文件, 用于生成 Kubernetes 资源清单(manifests)

注意:模板文件所有的目录必须是 templates

$ mkdir ./templates

cat <<'EOF' > ./templates/deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: hello-world
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: hello-world
    spec:
      containers:
        - name: hello-world
          image: {
    
    {
    
     .Values.image.repository }}:{
    
    {
    
     .Values.image.tag }}
          ports:
            - containerPort: 80
              protocol: TCP
EOF

$ cat <<'EOF' > ./templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: hello-world
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    app: hello-world
EOF

(5)创建 Release

使用命令 helm install RELATIVE_PATH_TO_CHART 创建一次 Release

$ helm install hello-world .
NAME: hello-world
LAST DEPLOYED: Wed Nov 18 05:40:09 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

5. Helm 一些操作

拉取Chart

  • 命令格式:helm pull [chart URL | repo/chartname] [...] [flags]

(1)安装

  • 命令格式:helm install [NAME] [CHART] [flags]
  • 常用参数:
    • -f, --values:指定 values.yaml 文件
    • --set:在命令行中直接设置 values 的值
    • --dry-run:模拟执行,测试能不能创建,但不创建
    • --debug:允许冗长的输出(输出多余信息)

(2)查看信息

# 查看 releases 列表
$ helm list
$ helm ls
NAME       	NAMESPACE	REVISION	UPDATED                                	STATUS  	CHART            	APP VERSION
hello-world	default  	1       	2020-11-18 09:24:37.117596257 +0800 CST	deployed	hello-world-1.0.0

# 查看 release 状态
$ helm status hello-world

(3)更新

  • 命令格式:helm upgrade [RELEASE] [CHART] [flags]
$ helm upgrade hello-world .
Release "hello-world" has been upgraded. Happy Helming!
NAME: hello-world
LAST DEPLOYED: Wed Nov 18 06:03:00 2020
NAMESPACE: default
STATUS: deployed
REVISION: 2
TEST SUITE: None

(4)历史版本/回滚

# 查看 releases 历史信息
# helm history RELEASE_NAME [flags]
$ helm history hello-world
REVISION	UPDATED                 	STATUS    	CHART            	APP VERSION	DESCRIPTION
1       	Wed Nov 18 05:40:09 2020	superseded	hello-world-1.0.0	           	Install complete
2       	Wed Nov 18 06:03:00 2020	deployed  	hello-world-1.0.0	           	Upgrade complete

# helm rollback <RELEASE> [REVISION] [flags]
$ helm rollback hello-world 1
Rollback was a success! Happy Helming!

(5)删除

# helm delete RELEASE_NAME [...] [flags]
$ helm delete hello-world
release "hello-world" uninstalled

五、Helm 部署 dashboard

仓库地址:https://artifacthub.io/packages/helm/k8s-dashboard/kubernetes-dashboard

1. 添加仓库

helm repo add k8s-dashboard https://kubernetes.github.io/dashboard

2. 下载 Chart

helm pull kubernetes-dashboard/kubernetes-dashboard

# 解压
tar -zxvf kubernetes-dashboard-2.8.3.tgz

3. 创建 kubernetes-dashboard.yaml

image:
  repository: kubernetesui/dashboard
  tag: v2.0.4
ingress:
  enabled: true
  hosts:
    - k8s.frognew.com
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
  tls:
    - secretName: frognew-com-tls-secret
      hosts:
        - k8s.frognew.com
rbac:
  clusterAdminRole: true

4. 安装

helm install kubernetes-dashboard . \
--namespace kube-system \
-f kubernetes-dashboard.yaml

5. 更改 svc

$ kubectl edit svc kubernetes-dashboard -n kube-system
将 spec.type 的值修改为 NodePort

# 查看端口(端口为:30354)
$ kubectl get svc -n kube-system
NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                  AGE
kubernetes-dashboard   NodePort    10.111.147.196   <none>        443:30354/TCP            51m

6. 访问地址

  1. 浏览器访问地址:https://192.168.66.10:30354/
    在这里插入图片描述

  2. 查看 kubernetes-dashboard-token 的名字

    $ kubectl get secret -n kube-system | grep kubernetes-dashboard-token
    kubernetes-dashboard-token-9kvm2                 kubernetes.io/service-account-token   3      77m
    
  3. 查看该 Secret 中的 Token

    kubectl describe secret kubernetes-dashboard-token-9kvm2 -n kube-system
    

    在这里插入图片描述

  4. 将 Token 复制到浏览器中,即可登录成功

7. 赋权

登录成功后,进去界面,发现什么资源都显示不了,是因为 dashboard 默认的 serviceaccount 并没有权限,所以我们需要给予它授权。

  1. 创建 dashboard-admin.yaml ,内容如下

    注意:这里直接赋予了 cluster-admin 权限,也就是集群所有的权限

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: kubernetes-dashboard
      namespace: kube-system
    subjects:
      - kind: ServiceAccount
        name: kubernetes-dashboard
        namespace: kube-system
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cluster-admin
    
  2. 应用资源文件 dashboard-admin.yaml

    kubectl apply -f dashboard-admin.yaml
    
  3. 授权成功,可以通过 dashboard 查看到资源
    在这里插入图片描述

六、Helm 部署 Prometheus

Prometheus github 地址:https://github.com/coreos/kube-prometheus

1. 组件说明

  1. MetricServer:是 kubernetes 集群资源使用情况的聚合器,收集数据给 kubernetes 集群内使用,如 kubectl,hpa,scheduler 等。
  2. PrometheusOperator:是一个系统监测和警报工具箱,用来存储监控数据。
  3. NodeExporter:用于各 node 的关键度量指标状态数据。
  4. KubeStateMetrics:收集 kubernetes 集群内资源对象数据,制定告警规则。
  5. Prometheus:采用 pull 方式收集 apiserver,scheduler,controller-manager,kubelet 组件数据,通过 http 协议传输。
  6. Grafana:是可视化数据统计和监控平台。

在这里插入图片描述

2. 安装

  1. 安装 kube-prometheus

    这里要注意一下版本兼容问题,在官网下载对应的版本即可

    be-prometheus stack Kubernetes 1.14 Kubernetes 1.15 Kubernetes 1.16 Kubernetes 1.17 Kubernetes 1.18 Kubernetes 1.19
    lease-0.3
    lease-0.4 (v1.16.5+) ✔
    lease-0.5
    lease-0.6
    AD
    # 克隆相应的分支
    git clone -b release-0.3 https://github.com/coreos/kube-prometheus.git
    
    cd kube-prometheus/manifests
    
  2. 修改 grafana-service.yaml

    $ vim grafana-service.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: grafana
      namespace: monitoring
    spec:
      type: NodePort	# 添加内容
      ports:
        - name: http
        port: 3000
        targetPort: http
        nodePort: 30100 #添加内容
      selector:
        app: grafana
    
  3. 修改 prometheus-service.yaml

    $ vim prometheus-service.yaml
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        prometheus: k8s
      name: prometheus-k8s
      namespace: monitoring
    spec:
      type: NodePort	# 添加
      ports:
        - name: web
          port: 9090
          targetPort: web
          nodePort: 30200	# 添加
      selector:
        app: prometheus
        prometheus: k8s
      sessionAffinity: ClientIP
    
  4. 修改 alertmanager-service.yaml

    $ vim alertmanager-service.yaml
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        alertmanager: main
      name: alertmanager-main
      namespace: monitoring
    spec:
      type: NodePort	# 添加
      ports:
        - name: web
          port: 9093
          targetPort: web
          nodePort: 30300	# 添加
      selector:
        alertmanager: main
        app: alertmanager
      sessionAffinity: ClientIP
    
  5. 安装:

    # 在 kube-prometheus/manifests 目录下执行
    # 创建名称空间,prometheus 组件都在这个名称空间下
    kubectl create namespace monitoring
    
    # 这两个目录下的 yaml 都要创建
    kubectl apply -f ./setup
    kubectl apply -f .
    

    如果报了下面的错:

    unable to recognize "../manifests/alertmanager-alertmanager.yaml": no matches for kind "Alertmanager" in version "monitoring.coreos.com/v1" 
    unable to recognize "../manifests/alertmanager-serviceMonitor.yaml": no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1"
    unable to recognize "../manifests/grafana-serviceMonitor.yaml": no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1" 
    ...
    

    就多执行几遍下面的命令(每次执行前要确保上次执行的 pod 已经 Running):

    kubectl apply -f ./setup
    kubectl apply -f .
    
  6. kubectl top 命令查看集群资源

    $ kubectl top node
    NAME           CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
    k8s-master01   93m          4%     1183Mi          62%
    k8s-node01     72m          3%     1116Mi          58%
    k8s-node02     78m          3%     1151Mi          60%
    
    $ kubectl top pod -n monitoring
    NAME                                  CPU(cores)   MEMORY(bytes)
    alertmanager-main-0                   2m           21Mi
    alertmanager-main-1                   2m           22Mi
    

3. 访问 prometheus

查看 service

$ kubectl get svc -o wide -n monitoring
NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE   SELECTOR
alertmanager-main       NodePort    10.97.154.146    <none>        9093:30300/TCP               98m   alertmanager=main,app=alertmanager
grafana                 NodePort    10.104.110.200   <none>        3000:30100/TCP               98m   app=grafana
prometheus-k8s          NodePort    10.104.85.240    <none>        9090:30200/TCP               98m   app=prometheus,prometheus=k8s

根据前面安装时候的配置,prometheus 对应的 nodeport 端口为 30200,访问 http://MasterIP:30200

  1. 查看 prometheus 的节点状态:
    在这里插入图片描述

  2. 测试

    prometheus 的 WEB 界面上提供了基本的查询 K8S 集群中每个 Pod 的 CPU 使用情况,查询条件如下:

    sum by (pod_name)( rate(container_cpu_usage_seconds_total{
          
          image!="", pod_name!=""}[1m] ) )
    

    在这里插入图片描述

    上述的查询有出现数据,说明 node-exporterprometheus 中写入数据正常,接下来我们就可以部署 grafana 组件,实现更友好的 webui 展示数据了

    注意prometheus 对系统时间的要求比较高,要确保 k8s 每个节点的时间都同步。通过阿里云服务器同步中国上海时间:ntpdate ntp1.aliyun.com

3. 访问 grafana

查看 grafana 服务暴露的端口号:

$ kubectl get service -n monitoring | grep grafana
grafana                 NodePort    10.98.154.100   <none>        3000:30100/TCP               11h

如上可以看到 grafana 的端口号是 30100,浏览器访问:http://MasterIP:30100,用户名密码默认 admin/admin,第一次登录后会要求修改密码。

在这里插入图片描述

(1)添加数据源

在这里插入图片描述

在这里插入图片描述

(2)查看节点

  1. 点击 Home
    在这里插入图片描述

  2. 选择监控的对象,这里选择 Nodes

    在这里插入图片描述

4. Horizontal Pod Autoscaling(HPA)

HPA 的全称为(Horizontal Pod Autoscaling)它可以根据当前 pod 资源的使用率(如 CPU、磁盘、内存等),进行副本数的动态的扩容与缩容,以便减轻各个 pod 的压力。当 pod 负载达到一定的阈值后,会根据扩缩容的策略生成更多新的 pod 来分担压力,当 pod 的使用比较空闲时,在稳定空闲一段时间后,还会自动减少 pod 的副本数量。

若要实现自动扩缩容的功能,还需要部署 heapster 服务,用来收集及统计资源的利用率,支持 kubectl top 命令,heapster 服务集成在 prometheus(普罗米修斯) Mertric Server 服务中,所以说,要先安装 prometheus

官方文档:https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/

(1)创建 php-apache

为了测试 HPA,这里将使用 php-apachephp-apache 主要是一个 之后将通过请求访问该 Pod ,用来模拟请求的负载增加和减少,查看 Pod 的数量变化。

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
          image: "registry.cn-shenzhen.aliyuncs.com/cookcodeblog/hpa-example:latest"
          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

创建 deployment 和 servcie :

# 1. 创建
kubectl apply -f php-apache.yaml

# 2. 查看
kubectl get deployment php-apache
kubectl get svc php-apache
kubectl get pods -l run=php-apache -o wide

(2)创建 HPA

为上面创建的 deployment php-apache 创建 HPA,其中最小副本数1最大副本数10,保持该 deployment 的所有 Pod平均 CPU 使用率不超过 50%

# 默认创建的HPA名称和需要自动伸缩的对象名一致
# 可以通过--name来指定HPA名称
 

在本例中,deploymentpodresources.request.cpu200m200 milli-cores vCPU),所以 HPA 将保持所有 Pod 的平均 CPU 使用率不超过 100m。可以通过 kubectl top pods 查看 pod 的 CPU 使用情况。

  • 查看HPA:
    $ kubectl get hpa
    NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
    php-apache   Deployment/php-apache   0%/50%    1         10        1          25s
    

如果 TARGETS 列值格式为 <acutal>/<expected>,如果 actual 值总是为 unkown,则表示无法从 Metrics Server 中获取指标值。

  • HPA 默认每15秒从 Metrics Server 取一下指标来判断是否要自动伸缩。通过 --horizontal-pod-autoscaler-sync-period 来设置

  • Metrics Server 采集指标的默认间隔为60秒。可以使用 metrics-resolution 来修改,但不建议设置低于15s的值,因为这是 Kubelet 中计算的度量的分辨率。

(3)增加负载

打开一个新的 Terminal,创建一个临时的 pod load-generator,并在该 pod 中向 php-apache 服务发起不间断循环请求,模拟增加 php-apache 的负载(CPU使用率)。

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"
  • 查看 HPA 及 Pod

    # 监控 HPA
    $ kubectl get hpa -w
    NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
    php-apache   Deployment/php-apache   196%/50%   1         10        4          17m
    
    # 监控 Pod
    $ kubectl get pod -o wide
    NAME                          READY   STATUS    RESTARTS   AGE   IP             NODE         NOMINATED NODE   READINESS GATES
    load-generator                1/1     Running        0          16m   10.244.2.82    k8s-node02   <none>           <none>
    php-apache-5d8c7bfcd5-bsnnj   1/1     Running   0          13m   10.244.1.109   k8s-node01   <none>           <none>
    php-apache-5d8c7bfcd5-hs6gd   1/1     Running   0          14m   10.244.2.83    k8s-node02   <none>           <none>
    php-apache-5d8c7bfcd5-jmmpj   1/1     Running   0          53m   10.244.1.108   k8s-node01   <none>           <none>
    php-apache-5d8c7bfcd5-rdglr   1/1     Running   0          12m   10.244.2.84    k8s-node02   <none>           <none>
    
    # 当四个副本都运行之后,CPU 实际使用率已降低到49%
    $ kubectl get hpa -w
    NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
    php-apache   Deployment/php-apache   49%/50%    1         10        4          30m
    

可以看到 HPA TARGETS(CPU使用率)的 acutal 值逐渐升高到196% (超过了期望值50%),副本数 REPLICAS 也从 1 自动扩容到了 4。当4个副本都 RUNNING 之后,CPU 使用率降低到了 50% 左右。

HPA 通过自动扩容到 4 个副本,来分摊了负载,使得所有 Pod 的平均 CPU 使用率保持(近似)在目标值。

  • 查看 HPA 自动伸缩事件

    kubectl describe hpa php-apache
    

(4)减少负载

在运行 load-generatorTerminal,按下 Ctrl + C 来终止进程。

过一段时间后来查看 HPA,副本数已经降到了1个:

$ kubectl get hpa php-apache
NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   0%/50%    1         10        1          49m

如果观察HPA没有 scale down,需要再等待一段时间。Kuberntes 为了保证缩容时业务不中断,和防止频繁伸缩导致系统抖动,scale down 一次后需要等待一段时间才能再次 scale down,也叫伸缩冷却(cooldown)。默认伸缩冷却时间为5分钟。可以通过参数 --horizontal-pod-autoscaler-downscale-stabilization 修改

5. 资源限制

Kubernetes 对资源的限制实际上是通过 cgroup 来控制的,cgroup 是容器的一组用来控制内核如何运行进程的相关属性集合。针对内存、CPU 和各种设备都有对应的 cgroup

(1)Pod资源限制

默认情况下,Pod 运行没有 CPU 和内存的限额。 这意味着系统中的任何 Pod 将能够像执行该 Pod 所在的节点一样,消耗足够多的 CPU 和内存 。一般会针对某些应用的 pod 资源进行资源限制,这个资源限制是通过 resourcesrequestslimits 来实现

  • requests:要分分配的资源,可以简单理解为初始值
  • limits:为最高请求的资源值,可以简单理解为最大值
spec:
  containers:	# 在容器模板下进行设置
    - image: xxxx
      imagePullPolicy: Always
      name: auth
      ports:
        - containerPort: 8080
          protocol: TCP
      resources:
        limits:
          cpu: "4"	# 4个cpu
          memory: 2Gi
        requests:
          cpu: 250m #250MHz
          memory: 250Mi

(2)名称空间资源限制

当 pod 没有设置资源限制的话,pod 会使用当前名称空间下的最大资源,如果名称空间也没有设置资源限制的话,pod 就可以使用集群的最大资源,就很有可能出现 OOM。

  1. 计算资源配额

    apiVersion: v1
    kind: ResourceQuota
    metadata:
      name: compute-resources
      namespace: spark-cluster
    spec:
      hard:
        pods: "20"	# 创建pod的数量
        requests.cpu: "20"	# 所有pod加在一起总共20个
        requests.memory: 100Gi	# 所有pod加在一起总共100G
        limits.cpu: "40"
        limits.memory: 200Gi
    
  2. 配置对象数量配额限制

    apiVersion: v1
    kind: ResourceQuota
    metadata:
      name: object-counts
      namespace: spark-cluster
    spec:
      hard:
        configmaps: "10"	# configmap 最多创建10个
        persistentvolumeclaims: "4"
        replicationcontrollers: "20"
        secrets: "10"
        services: "10"
        services.loadbalancers: "2"
    
  3. 配置 CPU 和 内存 LimitRange

    LimitRange 是对指定名称空间下 podcontainer 进行设置默认的

    apiVersion: v1
    kind: LimitRange
    metadata:
      name: mem-limit-range
    spec:
      limits:
        - default:		# 默认最大值
            memory: 50Gi	# 最大可以用到 50G
            cpu: 5		# 最多可以使用 5 个cpu
      defaultRequest:	# 默认初始值
        memory: 1Gi		# 内存 1G
        cpu: 1			# 一个cpu
      type: Container	# 类型
    

猜你喜欢

转载自blog.csdn.net/zyx1260168395/article/details/109792398