k8s学习之路 | Day20 k8s 工作负载 Deployment(下)

3. HPA 动态扩缩容

3.1 HPA

Horizontal Pod Autoscaler 可以根据 CPU 利用率自动扩缩 ReplicationController、 Deployment、ReplicaSet 或 StatefulSet 中的 Pod 数量

image-20230305130606096

HorizontalPodAutoscaler(简称 HPA ) 自动更新工作负载资源(例如 Deployment 或者 StatefulSet), 目的是自动扩缩工作负载以满足需求。

水平扩缩意味着对增加的负载的响应是部署更多的 Pod。 这与 “垂直(Vertical)” 扩缩不同,对于 Kubernetes, 垂直扩缩意味着将更多资源(例如:内存或 CPU)分配给已经为工作负载运行的 Pod。

如果负载减少,并且 Pod 的数量高于配置的最小值, HorizontalPodAutoscaler 会指示工作负载资源(Deployment、StatefulSet 或其他类似资源)缩减。

3.2 安装 metrics-server

有关 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

image-20230305131522989

查看一下状态

kubectl get pod -n kube-system

image-20230305131601302

查看一下指标

##节点使用情况
kubectl top nodes --use-protocol-buffers

##pod使用情况
kubectl top pods --use-protocol-buffers

image-20230305131845365

3.3 验证指标收集

我们可以登陆 Dashboard 上去查看信息收集

image-20230305132701907

image-20230305132723914

3.4 扩缩容的实现

HPA 也是 k8s 中的一种资源,就是写这个资源的 yaml 文件来实现的

image-20230305134103259

准备一个镜像

来自1.21版本的k8s 官方文档

FROM php:5-apache
COPY index.php /var/www/html/index.php
RUN chmod a+rx index.php

index.php 文件内容

<?php
  $x = 0.0001;
  for ($i = 0; $i <= 1000000; $i++) {
    $x += sqrt($x);
  }
  echo "OK!";
?>

构建一下这个镜像:docker build -t hpa-example .

image-20230305134821735

准备 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

启动一下

image-20230305135358262

编写 HPA

怎么写这个东西呢?直接描述就行了 kubectl explain hpa

如果不是整合第三方的话,这个资源能写的信息很少

image-20230305135947624

FIELDS:
   maxReplicas  <integer> -required- ## 自动缩放器可设置的数量上限,不能小于Min
     upper limit for the number of pods that can be set by the autoscaler;
     cannot be smaller than MinReplicas.

   minReplicas  <integer>
     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       <Object> -required- ##缩放资源类型
     reference to scaled resource; horizontal pod autoscaler will learn the
     current resource consumption and will set the desired number of pods by
     using its Scale subresource.

   targetCPUUtilizationPercentage       <integer>  ##目标平均CPU利用率
     target average CPU utilization (represented as a percentage of requested
     CPU) over all the pods; if not specified the default autoscaling policy
     will be used.

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

image-20230305141007348

3.5 增加负载

动态监控一下

kubectl get hpa -w
kubectl get pod -l run=php-apache -w

增加负载

##一直访问
while true;do curl 10.96.169.3;done

image-20230305142100227

动态观察结果

运行一段发现负载升高,实现了自动扩容

image-20230305142212237

image-20230305142219160

image-20230305142231701

3.6 降低负载

Ctrl + C 取消循环后,资源利用率会降下去,但是会有一个缓冲时间才会进行缩容

image-20230305142729382

等一段时间后(好像是5分钟),最终会缩容到一个

image-20230305142758619

3.7 更多的度量指标

有很多度量指标,参考最新版本的地址:https://kubernetes.io/zh-cn/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/#autoscaling-on-multiple-metrics-and-custom-metrics

基于多项度量指标和自定义度量指标自动扩缩

4. 金丝雀部署

4.1 蓝绿部署

  • 系统存在两个版本:V1 和 V2(绿和蓝)
  • 将一些流量请求发往蓝色的版本的,如果发现是对的,就将系统切换到蓝版本

a6324354-canary

4.2 金丝雀部署

金丝雀部署来源于矿场的一个场景:矿工进矿洞之前会放入金丝雀,金丝雀对瓦斯气体很敏感,如果放进去了没有叽叽喳喳声音,矿工就不会进去了

  • 现在有2个版本:V1 和 V2
  • 先部署一个 V2 版本,请求流量会走向 V1和 V2
  • 再逐渐增加 V2 数量,将全部流量走向 V2,销毁 V1

与滚动发布相比

滚动发布:

  • 也都是同时存在2个版本,都能接受流量
  • 滚动发布短时间就直接结束了,不能直接控制新老版本的存活时间

4.3 金丝雀部署的实现

首先准备一个 service

  • 选择“app: canary-nginx”标签进行一个对外负载访问
##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

访问检查

image-20230305170250716

再启动一个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

访问一下

image-20230305173606080

v2版本没问题,我们进行一个扩容操作

##更改canary-deploy-demo2.yaml的.spec.replicas字段信息
  replicas: 5

image-20230305173845980

这个时候,通往 v2 版本的流量就增加了

image-20230305173947067

我们的新版本就OK,就可以删除v1版本了

image-20230305174107366

5. Deployment 状态与排查

5.1 进行中的 Deployment

执行下面的任务期间,Kubernetes 标记 Deployment 为进行中(Progressing)_:

  • Deployment 创建新的 ReplicaSet
  • Deployment 正在为其最新的 ReplicaSet 扩容
  • Deployment 正在为其旧有的 ReplicaSet(s) 缩容
  • 新的 Pod 已经就绪或者可用(就绪至少持续了 MinReadySeconds 秒)。

当上线过程进入“Progressing”状态时,Deployment 控制器会向 Deployment 的 .status.conditions 中添加包含下面属性的状况条目:

  • type: Progressing
  • status: "True"
  • reason: NewReplicaSetCreated | reason: FoundNewReplicaSet | reason: ReplicaSetUpdated

监视 Deployment 进度:kubectl rollout status deploy nginx-deployment

5.2 完成的 Deployment

当 Deployment 具有以下特征时,Kubernetes 将其标记为完成(Complete);

  • 与 Deployment 关联的所有副本都已更新到指定的最新版本,这意味着之前请求的所有更新都已完成。
  • 与 Deployment 关联的所有副本都可用。
  • 未运行 Deployment 的旧副本。

当上线过程进入“Complete”状态时,Deployment 控制器会向 Deployment 的 .status.conditions 中添加包含下面属性的状况条目:

  • type: Progressing
  • status: "True"
  • reason: NewReplicaSetAvailable

5.3 失败的 Deployment

Deployment 可能会在尝试部署其最新的 ReplicaSet 受挫,一直处于未完成状态。 造成此情况一些可能因素如下:

  • 配额(Quota)不足
  • 就绪探测(Readiness Probe)失败
  • 镜像拉取错误
  • 权限不足
  • 限制范围(Limit Ranges)问题
  • 应用程序运行时的配置错误

描述性查看 Deployment 情况:kubectl describe deployment nginx-deployment

5.4 对失败 Deployment 的操作

可应用于已完成的 Deployment 的所有操作也适用于失败的 Deployment。 你可以对其执行扩缩容、回滚到以前的修订版本等操作,或者在需要对 Deployment 的 Pod 模板应用多项调整时,将 Deployment 暂停。

清理策略

可以在 Deployment 中设置 .spec.revisionHistoryLimit 字段以指定保留此 Deployment 的多少个旧有 ReplicaSet。其余的 ReplicaSet 将在后台被垃圾回收。 默认情况下,此值为 10。

将此字段设置为 0 将导致 Deployment 的所有历史记录被清空,造成 Deployment 将无法回滚

万能的排错方式kubectl describe xxxxxx

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值