K8s 之 Deployment 应用案例

K8s 之 Deployment 应用案例_第1张图片


目录

    • 一、YAML 配置文件
    • 二、运行服务
    • 三、更新 Deployment
      • 3.1 动态伸缩容
      • 3.2 触发上线
    • 四、故障自动转移
    • 五、指定节点运行 Pod
    • 六、删除 deployment


一、YAML 配置文件

我们要清楚,在 K8s 中有两种创建资源的方式:

(1)命令行方式:如 kubectl create ...

(2)配置文件方式:如 kubectl apply -f nginx.yml

命令行方式:

# 创建Seployment资源
kubectl create deployment nginx --image=nginx:1.20.0 --replicas=2

# 使用Service将Pod暴露出去
kubectl expose deployment nginx --port=8090 --target-port=80 --type=NodePort

配置文件方式:

配置文件采用的是 YAML 格式。

vim nginx.yml
apiVersion: apps/v1        # 指定deployment的api版本
kind: Deployment           # 指定创建资源的角色/类型 
metadata:                  # 指定Deployment的元数据
  name: nginx              # 创建名为nginx的Deployment
  labels:                  # 指定Deployment的标签(可自定义多个),这里的标签不需要与任何地方的标签匹配,根据实际场景随意自定义即可
    app: demo
spec:                      # Deployment的资源规格
  replicas: 2              # Deployment将创建2个Pod副本(默认为 1)
  selector:                # 匹配标签选择器,定义Deployment如何查找要管理的Pod,因此这里必须与Pod的template模板中定义的标签保持一致
    matchLabels:
      app: demo
  template:                # 指定Pod模板
    metadata:              # 指定Pod的元数据
      labels:              # 指定Pod的标签(可自定义多个)
        app: demo
    spec:                  # Pod的资源规格
      containers:          # 指定Pod运行的容器信息
      - name: nginx        # 指定Pod中运行的容器名
        image: nginx:1.20.0     # 指定Pod中运行的容器镜像与版本(不指定镜像版本号则默认为latest)
        ports:
        - containerPort: 80     # 指定容器的端口(即Nginx默认端口)

说明:对应资源的apiVersion须在kubectl api-versions中,如下图所示。

K8s 之 Deployment 应用案例_第2张图片

二、运行服务

kubectl apply -f nginx.yml

查看 Deployment 上线状态

kubectl get deployment

# 字段说明
# NAME:列出namespace中Deployment的名称(不指定namespace则默认为Default)
# READY:显示应用程序的可用的副本数。显示的模式是“就绪个数/期望个数”
# UP-TO-DATE:为了达到期望状态已经更新的副本数
# AVAILABLE:显示应用可供用户使用的副本数
# AGE:显示应用程序运行的总时间

image-20221215154541133

查看 Deployment 创建的 ReplicaSet

kubectl get rs
kubectl get replicaset

# 字段说明
# NAME:列出namespace中ReplicaSet的名称(不指定namespace则默认为Default)
# DESIRED:表示期望状态,显示应用的期望副本个数,即在创建Deployment时所定义的值
# CURRENT:显示当前运行状态中的副本个数
# READY:显示应用中有多少副本可以为用户提供服务
# AGE:显示应用已经运行的总时间

image-20221215155221009

注意:ReplicaSet 的名称始终被格式化为 [Deployment名称]-[哈希]。其中的哈希字符串与 ReplicaSet 上的 pod-template-hash 标签一致。

# 查看ReplicaSet的标签
kubectl get replicaset --show-labels

image-20221215160348797

我们都知道 Pod 副本通过 ReplicaSet 管理,而 ReplicaSet 又是创建于 Deployment,那为什么不直接通过 Deployment 来直接管理,而是 ReplicaSet呢?

原因是每个控制器的标签或者选择算符不能与其他控制器(包括其他 Deployment 和 StatefulSet)重叠,那 K8s 是如何保证各控制器之间标签的唯一性呢?就是通过 ReplicaSet,因为 Pod 的 PodTemplate标签就是通过 ReplicaSet 进行哈希处理,如下图,可看到 Pod 的 PodTemplate 标签值,此标签可确保了 Deployment 的子 ReplicaSets 不发生重叠现象。

K8s 之 Deployment 应用案例_第3张图片

三、更新 Deployment

3.1 动态伸缩容

所谓的伸缩容就是在线增加或减少 Pod 的副本数(只须修改 replicas 的值即可,大于当前值为伸,小于当前值为缩)。

1、修改配置文件

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: demo
spec:
  replicas: 5
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
      - name: nginx
        image: nginx:1.20.0
        ports:
        - containerPort: 80

2、执行 kubectl apply

kubectl apply -f nginx.yml

3、查看 Pod 运行状态

kubectl get pod -o wide

image-20221213163619736

出于安全考虑,默认情况下 K8s 不会将 Pod 调度到 master 节点,如果希望将 k8s-master 节点也作为 work 节点,可执行以下命令:

kubectl taint node k8s-master node-role.kubernetes.io/master-

再新增一个副本,此时可看到新增的这个 Pod 已经被调度到 Master 节点上了

image-20221213164259241

如果要恢复为原来的 Master Only,执行以下语句即可:

kubectl taint node k8s-master node-role.kubernetes.io/master="":NoSchedule

3.2 触发上线

需要注意的是,动态伸缩容不会触发上线动作,仅当 Deployment Pod 模板(即 .spec.template)发生改变时,例如模板的标签或容器镜像被更新,才会触发 Deployment 上线,以下为一个更新镜像版本的触发上线案例。

kubectl set image deployment.v1.apps/nginx nginx=nginx:1.20.2

# 或使用下面的命令:
kubectl set image deployment/nginx nginx=nginx:1.20.2
# 或使用下面的命令:直接编辑修改镜像版本即可
kubectl edit deployment/nginx

查看上线状态:

image-20221215170337761

看看 replicaset 状态:

image-20221215170534723

可看到 Deployment 通过创建新的 ReplicaSet 并将其扩容到 2 个副本并将旧 ReplicaSet 缩容到 0 个副本完成了 Pod 的更新操作。

Deployment 可确保在更新时仅关闭一定数量的 Pod。默认情况下,它确保至少所需 Pod 的 75% 处于运行状态(最大不可用比例为 25%)。 默认情况下,它可确保启动的 Pod 个数比期望个数最多多出 125%(最大峰值 25%)。

仔细查看下图的 Pod 变换情况 ,其流程是先创建一个新的 Pod,然后再删除旧的 Pod。但需要注意的是,更新时它不会立即杀死旧的 Pod,直到有足够数量的新 Pod 已经出现才会杀死旧的 Pod,因为它需要确保至少 2 个 Pod 可用, 同时最多总共 3 个 Pod 可用。

image-20221215170122738

也可以查看 Deployment 的详情来看到整体更新流程

kubectl describe deployments

image-20221215171801610

四、故障自动转移

故障前 Pod 运行的节点(work1 节点运行1个、work2 节点运行2个节点)

image-20221213170334741

模拟 k8s-work2 故障(关闭节点)

init 0    # 直接关机

image-20221213165326214

等待 5 分钟后会自动在其他可用 work 节点进行创建并运行,之所以要等待5分钟,这是因为 k8s 的 Taint(污点)与 Toleration(容忍)机制所造成。Taint和Toleration相互配合,可以避免pod被分配到不合适的节点上。每个节点上都可以应用一个或多个Taint,这表示对于那些不能容忍 Taint 的 pod,是不会被该节点接受的。如果将 Toleration 应用于 pod 上,则表示这些 pod 可以(但不要求)被调度到具有匹配 Taint 的节点上。

此时可看到 work2 上原来的两个节点已经 Terminating(终止),并转移到了 work1 上。

image-20221213171510077

因此,此服务中断时间=停机等待5分钟时间+重建时间+服务启动时间+readiness探针检测正常时间

疑问?那当 K8s-work2 节点恢复后,其原来的 Pod 还会被重新调度回来吗?

答案是:不会

此时我恢复 k8s-work2 节点

image-20221213172602657

再看看 Pod 的分布情况

image-20221213172532546

五、指定节点运行 Pod

默认情况下,Scheduler 会将 Pod 调度到所有可用的 Work 节点,不过在某些情况下我们需要将 Pod 部署到指定的 Work 节点,比如将有大量磁盘 I/O 的 Pod 部署到有 SSD 的 work 节点上来保证其 I/O。

因此,在 K8s 中可通过 label 来实现这个功能,label 是一对 key-value,各种资源都可以设置 label。具体操作如下。

1、先标记 work 节点

比如:我标记 work2 节点为配置有 SSD 的节点

kubectl label node k8s-work2 disktype=ssd

image-20221213174401273

如何查看节点已设置的标签?

kubectl get node --show-labels

K8s 之 Deployment 应用案例_第4张图片

2、修改配置文件

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: demo
spec:
  replicas: 4
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
      - name: nginx
        image: nginx:1.20.0
        ports:
        - containerPort: 80

3、执行 kubectl apply

kubectl apply -f nginx.yml

4、查看 这4个副本都只在 work2 节点运行

image-20221213180223675

如何删除标签?

kubectl label node k8s-work2 disktype-

K8s 之 Deployment 应用案例_第5张图片

此时 k8s-work2 节点上的 Pod 并不会因为其标签的删除而删除,依然是正常运行的,除非删除 nginx.yml 配置文件中的 nodeSelect 字段,并再次执行 kubectl apply ,master 才会自动调度到其他可用节点(当然也可以包括 work2),如下图所示:

image-20221213181237256

六、删除 deployment

会创建当然也要会删除,K8s 中删除资源的方法有以下两种。

1、直接删除

kubectl delete deployment nginx

2、或通过配置文件删除

kubectl delete -f nginx.yml

你可能感兴趣的:(云原生,kubernetes,运维,docker)