欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

K8S III 入门:资源调度

最编程 2024-03-24 07:24:48
...

『K8S 入门』三:资源调度

一、Label 和 Selector

在这里插入图片描述

  1. 可以通过 Selector 基于 Label 匹配需要的资源

Label 标签

  1. 配置文件中(metadata.labels)配置
metadata: # Pod相关的元数据,用于描述Pod的数据
  name: nginx-demo #Pod的名称
  labels: # 定义Pod的标签,这个标签可以自己任意指定,是无所谓的
    type: app # 自定义label标签,名字为type,值为app
    version: 1.0.0 # 自定义label标签,描述版本号
  namespace: 'default' # 命名空间的配置
  1. 查看 Labels
# 查看 Labels
kubectl get po --show-labels
# 通过命名空间查看
kubectl  get po --show-labels -n kube-system

在这里插入图片描述
3. 临时创建 Labels

  • 这些临时的 Labels 会丢失
# 添加 Labels
kubectl label po nginx-demo author=xz
# 复写 Labels
kubectl label po nginx-demo author=xzz --overwrite

在这里插入图片描述

  • 如果要永久修改只能修改配置文件,或者使用下面方式修改
kubectl edit po nginx-demo

Selector 选择器

  1. 配置值
# 匹配某个 label
kubectl get po -l type=app
# 展示所有信息
kubectl get po -A -l type=app
# 顺便查询 labels
kubectl get po -A -l type=app --show-labels
# 刻画描述
kubectl get po -A -l 'version in (1.0.0, 1.1.0, 1.2.0)'
kubectl get po -A -l 'version in (1.0.0, 1.1.0, 1.2.0),type=app'

在这里插入图片描述

二、Deployment

在这里插入图片描述

  1. 创建
  • 创建一个 deployment
kubectl create deploy nginx-deploy --image=nginx:1.7.9

# 查看资源
kubectl get deployments
kubectl get deploy

在这里插入图片描述

  • depoy、replicaset、po 层级关系
    • 可以看到名字是有层级规范的
kubectl get deploy
kubectl get replicaset
kubectl get po

在这里插入图片描述

  • 获取 deployments 的配置文件
    • 不要 status 部分,就可以获取这些配置值
# 把 deployments 的配置按照 yaml 形式输出
kubectl get deploy nginx-deploy -o yaml
# === 配置值描述 === 
# 注释的都是会默认生成的
apiVersion: apps/v1 # deployment api 版本
kind: Deployment # 资源类型为 deployment
metadata: # 元信息
  #annotations:
  #  deployment.kubernetes.io/revision: "1"
  #creationTimestamp: "2023-12-15T19:54:44Z"
  #generation: 1
  labels: # 标签
    app: nginx-deploy # 具体的 key: value 配置形式
  name: nginx-deploy # deployment 的名字
  namespace: default # 所在的命名空间
  #resourceVersion: "73676"
  #uid: 79be9a06-7f20-42ac-a427-1e9cd5b089de
spec:
  #progressDeadlineSeconds: 600
  replicas: 1 # 期望副本数
  revisionHistoryLimit: 10 # 进行滚动更新后,保留的历史版本数
  selector: # 选择器,用于找到匹配的 RS
    matchLabels: # 按照标签匹配
      app: nginx-deploy # 匹配的标签 key/value
  strategy: # 更新策略
    rollingUpdate:  # 滚动更新配置
      maxSurge: 25% # 进行滚动更新时,更新的个数最多可以超过期望副本数的个数/比例
      maxUnavailable: 25% # 进行滚动更新时,最大不可用比例更新比例,表示在所有副本数中,最多可以有多少个不更新成功
    type: RollingUpdate # 更新类型,采用滚动更新
  template: # pod 模板
    metadata: # pod 的元信息
      #creationTimestamp: null 
      labels: # pod 的标签
        app: nginx-deploy
    spec: # pod 期望信息
      containers:  # pod 的容器
      - image: nginx:1.7.9 # 镜像
        imagePullPolicy: IfNotPresent # 拉取策略
        name: nginx # 容器名称
        #resources: {}
        #terminationMessagePath: /dev/termination-log
        #terminationMessagePolicy: File
      #dnsPolicy: ClusterFirst
      restartPolicy: Always # 重启策略
      #schedulerName: default-scheduler
      #securityContext: {}
      terminationGracePeriodSeconds: 30 # 删除操作最多宽限多长时间

在这里插入图片描述

  1. 滚动更新
  • 滚动更新时,修改本地文件是无效果的
  • 如果不更新 template 的配置,是不会触发自动更新
  • 例如,先查看 deploy 中的标签
kubectl get deploy --show-labels

在这里插入图片描述

  • 然后修改标签值,但是这时候并不会重发自动更新
kubectl edit deploy nginx-deploy

# ===== 更新 ===== 
...
  labels:
    app: nginx-deploy
    test: "123" # 添加这个
...

# 通过这个命令可以看到 events 事件没有什么变化 
kubectl describe deploy nginx-deploy

在这里插入图片描述

  • 先做一个事情,增加一下副本数,这时候 po 变成 3 个,rs、deploy 还是 1 个
# ===== 更新 ===== 
...
spec:
  progressDeadlineSeconds: 600
  replicas: 3 # 更新这个
...

在这里插入图片描述

  • (重点)尝试去修改镜像版本
# ===== 更新 ===== 
...
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx-deploy
    spec:
      containers:
      - image: nginx:1.9.1 # 更新这个
...
# 通过这个命令就可以看到 deploy 在更新
kubectl rollout status deploy nginx-deploy
# 或者用这个
kubectl get deploy --show-labels
# 或者看 events
kubectl describe deploy nginx-deploy

在这里插入图片描述

  • 从这也可以看到这个更新过程(describe)
    • 先创建两个 rs,先把其中 1 个 rs 的 pod 移到另外 1 个 rs,最后再清理旧的 rs
    • 如果在更新过程中,快速地再次修改,k8s 会把上次的 rs 直接停止,再重新进行一次流程
      在这里插入图片描述
      在这里插入图片描述
  • 从这也可以看出来旧的 rs 已经被替代
    在这里插入图片描述
  1. 回滚
  • 首先先对版本更新一个有问题的版本,查看更新过程,发现版本已经卡死
kubectl set image deployment/nginx-deploy nginx=nginx:1.91

在这里插入图片描述

  • 因为相应的镜像死活拉不下来,其中一个 pod 拉取镜像失败,也可以通过下面命令查看一下情况
kubectl describe po nginx-deploy-f7f5656c7-z2bw7

在这里插入图片描述

  • 先查看历史版本(因为没使用, record,所以才 none),可以看到有 3 个历史版本
kubectl rollout history deployment/nginx-deploy

# 只有这样 change-cause 才不会显示 none
kubectl set image deployment/nginx-deploy nginx=nginx:1.91 --record ***

在这里插入图片描述

  • 查看 2 号版本的信息
kubectl rollout history deployment/nginx-deploy --revision=2

在这里插入图片描述

  • (重点)回滚上一个版本
kubectl rollout undo deployment/nginx-deploy --to-revision=2

# 通过这个命令看到已经回退到 1.9.1 版本
kubectl edit deploy nginx-deploy
  • 查看 rs 也可以看到也就只有第一个 rs 有数量了
    在这里插入图片描述
  • (注意)可以通过设置 .spec.revisonHistoryLimit 来指定 deployment 保留多少 revison,如果设置为 0,则不允许 deployment 回退了
  1. 扩容缩容
  • 扩容:执行下面命令进行扩缩容,这时候并不会变更 rs
kubectl scale --replicas=6 deploy nginx-deploy

在这里插入图片描述

  • 缩容:其实一样的,只是设置数字少点
kubectl scale --replicas=3 deploy nginx-deploy
  1. 暂停与恢复
  • 由于每次对 pod template 中的信息发生修改后,都会触发更新 deployment 操作,那么此时如果频繁修改信息,就会产生多次更新,而实际上只需要执行最后一次更新即可,当出现此类情况时我们就可以暂停 deployment 的 rollout
  • 首先先暂停配置
kubectl rollout pause deploy nginx-deploy
  • 然后往模板中添加下面配置,会发现 rs 并没有新增加
kubectl edit deploy nginx-deploy

# ===== 更新 ===== 
...
    spec: # pod 期望信息
      containers:  # pod 的容器
		....
        resources: # 下面这部分都是更新
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 512Mi
...

# 可以通过这个命令看到最新版本的 change 没改变
kubectl rollout history deploy nginx-deploy --revision=4

在这里插入图片描述

  • 恢复之后,通过 rs 或者 deploy 查看,已经有新增
kubectl rollout resume deploy nginx-deploy

在这里插入图片描述

三、StatefulSet

在这里插入图片描述

  1. 创建
  • 首先创建目录,并且把 web.yml 放到里面
mkdir statefulset 
cd statefulset 
touch web.yml
  • 其中 web.yml 内容如下
--- # 嵌套另外一个 yaml 的内容,暂时先不用管这个
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet # StatefulSet 类型的资源
metadata:
  name: web # StatefulSet 对象的名字
spec:
  selector:
    matchLabels:
      app: nginx # 使用哪个 service 来管理 dns,就是和上面的 metadata.name 的 “nginx” 匹配
  serviceName: "nginx"
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports: # 容器内部要暴露的端口
        - containerPort: 80 # 具体暴露的端口号
          name: web # 该端口配置的名字
  • 执行 web.yml
kubectl create -f web.yml

# 如果出错可以执行下面的命令删除创建
kubectl delete sts web
kubectl delete svc nginx

在这里插入图片描述

  • 通过下面命令会看到 pod 的创建
kubectl get po

在这里插入图片描述

  • 下面尝试是否可以 ping 通。使用万能工具包
    • 注意)容器主机内,用宿主机无法 ping 通
kubectl run -it --image busybox:1.28.4 dns-test --restart=Never --rm /bin/sh

# 测试下面命令
ping web-0.nginx # DNS 命名格式为:statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local 一般只要 statefulSetName-{0..N-1}.serviceName 就可
ping web-1.nginx
nslookup web-0.nginx

在这里插入图片描述
2. 扩容缩容

  • 首先看到现在的容器也只有 3 个
    在这里插入图片描述
  • 这时扩容到 5 个
kubectl  scale sts web --replicas=5
# 查看扩容过程
kubectl describe sts web

在这里插入图片描述

  • 缩容也是用同样的命令,他是按数字从大到小进行缩容
    在这里插入图片描述
  1. 镜像更新
  • 目前还不支持直接更新 image,需要 patch 来间接实现,通过补丁,可以发现版本已经更新到 1.9.1
kubectl patch sts web --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"nginx:1.9.1"}]'
# 查看版本更新版本
kubectl rollout history sts web
# 查看第 2 个版本的变化历史
kubectl rollout history sts web --revision=2
# 查看更新的动作
kubectl rollout status sts web

在这里插入图片描述

  • 因为我们在配置中配置的实现是 RollingUpdate 更新策略,在 StatefulSet 中更新时是基于 pod 的顺序倒序更新的。利用滚动更新中的 partition 属性,可以实现简易的灰度发布的效果
kubectl edit sts web

在这里插入图片描述
4. 灰度发布
在这里插入图片描述

  • 首先把服务扩容到 5 台
  • 修改滚动策略的 partition 为 3
# 修改
kubectl edit sts web
  • 其中修改配置如下
...
    spec:
      containers:
      - image: nginx:1.7.9
...
  updateStrategy:
    rollingUpdate:
      partition: 3 
    type: RollingUpdate
...
  • 然后分别查看一下每个 web-* 的 pod,会发现 3,4 已经更新版本到 1.7.9
kubectl describe po web-2
  • 直接把 partition 改为 0,直接全量发布
  1. onDelete 策略
  • 只有在 pod 被删除时会进行更新操作
  • 先修改更新策略
kubectl edit sts web
  • 修改的配置如下
...
  updateStrategy:
    type: OnDelete
...
  • 然后再次修改 nginx 版本配置为 1.9.1,你会发现每个 web-* 的 pod 都根本不会变化,除非执行下面命令。你就可以每个 pod 操作一次之后,才会更新版本
kubectl describe pod web-4
  1. 级联删除
  • 级联删除:删除 StatefulSet 时会同时删除 pod
kubectl delete statefulset web

  • 非级联删除:删除 StatefulSet 时不会删除 pod,删除 sts 后,pod 就没人管了,此时再删除 pod 不会重建的
# 先重新创建
kubectl delete service nginx # 这个也要执行一下,好像 service 没删除
kubectl create -f web.yml
# 非级联删除
kubectl delete sts web --cascade=false
  • StatefulSet 删除后 PVC 还会保留着,数据不再使用的话也需要删除
kubectl delete pvc ***

四、DaemonSet

在这里插入图片描述

  1. 解释
  • 它是可以专门筛选节点,来帮助自动在节点层面创建 pod,例如那种专门采集日志数据的进程就有必要
    在这里插入图片描述
  1. 不指定 Node 节点
  • 不指定 Node 创建文件
# fluentd-ds.yml
apiVersion: apps/v1
kind: DaemonSet # 创建 DaemonSet 资源
metadata:
  name: fluentd # 名字
spec:
  selector: # 一定要写的
    matchLabels:
      app: logging # 匹配标签的值,和下面的 labels.app 对应
  template: # 模板配置
    metadata:
      labels:
        app: logging
        id: fluentd
      name: fluentd # 容器名
    spec:
      containers:
      - name: fluentd-es
        image: agilestacks/fluentd-elasticsearch:v1.3.0
        env: # 环境变量
         - name: FLUENTD_ARGS
           value: -qq
        volumeMounts: # 加载数据卷
         - name: containers # 把下面命名为 containers 的容器卷加载到下面路径去
           mountPath: /var/lib/docker/containers
         - name: varlog
           mountPath: /varlog
      volumes: # 定义数据卷,主机路径模式,与 node 共享目录
         - hostPath:
             path: /var/lib/docker/containers # node 中的共享目录
           name: containers
         - hostPath:
             path: /var/log
           name: varlog
  • 执行创建,默认会在我们的 2 个节点中创建
kubectl create -f fluentd-ds.yml
kubecttl get daemonset
kubectl get po -o wide

在这里插入图片描述

  • 通过查看 Node 的时候,其实这时候并没有相应的 label,让我们 ds 选择部署到哪个节点去,所以默认就会往非 master 节点去部署
kubectl get nodes --show-labels
  1. 指定 Node 节点,使用节点选择器
  • 首先标签一下其中一个 node
kubectl label no k8s-node1 type=microservices
  • 编辑一下 ds
kubectl edit ds fluentd
  • 其中增加配置如下,保存后查看 ds,发现就剩下 1 个了
...
template:
  spec:
    nodeSelector:
      type: microservices
...

在这里插入图片描述

  • 当给 node2 也加一个同样标签,相应的 fluentd 就会多创建 1 个
kubectl label no k8s-node2 type=microservices

在这里插入图片描述
4. 滚动更新

  • 不建议使用 RollingUpdate,建议使用 OnDelete 模式,这样避免频繁更新 ds

五、HPA 自动扩缩容

  1. 概述
  • 通过观察 pod 的 cpu、内存使用率或自定义 metrics 指标进行自动的扩容或缩容 pod 的数量
  • 通常用于 Deployment,不适用于无法扩/缩容的对象,如 DaemonSet
  1. 开启指标服务
  • 首先先重新执行 nginx-deploy.yaml 创建 Deployment,这时候副本是 1 就够了
    在这里插入图片描述
  • nginx-deploy.yaml 先增加资源限制
...
spec:
  template: # pod 模板
    spec: # pod 期望信息
      containers:  # pod 的容器
      - image: nginx:1.7.9 # 镜像
        imagePullPolicy: IfNotPresent # 拉取策略
        name: nginx # 容器名称
        resources:  # 增加资源限制
          requests:
            cpu: 10m # 等会拿来测试
            memory: 128Mi
          limits:
            cpu: 200m
            memory: 128Mi
...
  • 替换一下配置文件
kubectl replace -f nginx-deploy.yaml
  • 创建 HPA 自动扩缩容
kubectl autoscale deploy nginx-deploy --cpu-percent=20 --min=2 --max=5

# 会发现已经创建了 2 个 pod
kubectl get deploy
  • 按照监测指标工具,否则没办法使用 top
# 下载 metrics-server 组件配置文件
wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml -O metrics-server-components.yaml

# 修改镜像地址为国内的地址
sed -i 's/registry.k8s.io\/metrics-server/registry.cn-hangzhou.aliyuncs.com\/google_containers/g' metrics-server-components.yaml

# 修改容器的 tls 配置,不验证 tls,在 containers 的 args 参数中增加这个参数
...
    spec:
      containers:
      - args:
        ....
        - --metric-resolution=15s
        - --kubelet-insecure-tls  # 加这个
...

# 安装组件
kubectl apply -f metrics-server-components.yaml

# 查看 pod 状态
kubectl get pods --all-namespaces | grep metrics

在这里插入图片描述

  • 下面就可以执行 top,查看 pod 使用资源情况
kubectl top pods
  • 为了能够把两个 pod 合到一起去,需要配置一下 service,首先先查看这 2 个 pod 有的标签,取 app=nginx 来进行匹配
kubectl get pod --show-labels

在这里插入图片描述

  • 创建 nginx-svc.yml,并执行
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  selector:
    app: nginx-deploy
  ports:
  - port: 80
    targetPort: 80
    name: web

在这里插入图片描述

  • 执行下面命令,查看 svc 端口,其中 CLUSTER-IP 代表的是容器 ip,而 port 是容器内端口,执行 curl 命令就可以查看到内容
kubectl get svc

在这里插入图片描述

  • 在另外一个 shell 里面,对 service 执行一个死循环,就会看到容器自动扩容了
while true; do wget -q -O- http://10.100.99.222 > /dev/null ; done

# 看到容器自动扩容
kubectl get pod
# cpu 飙升
kubectl get hpa
# 查看每个 pod 具体 cpu 使用率
kubectl top po

在这里插入图片描述

  • 当停止掉死循环之后,就会发现容器自动缩容了
# 查看缩容细节
kubectl describe hpa nginx-deploy
# 已经缩容
kubectl get hpa

在这里插入图片描述

推荐阅读