每天5分钟玩转Kubernetes | Deployment

Posted COCOgsta

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了每天5分钟玩转Kubernetes | Deployment相关的知识,希望对你有一定的参考价值。

书籍来源:cloudman《每天5分钟玩转Kubernetes》

一边学习一边整理老师的课程内容及试验笔记,并与大家分享,侵权即删,谢谢支持!

附上汇总贴:每天5分钟玩转Kubernetes | 汇总_COCOgsta的博客-CSDN博客


5.1 Deployment

前面我们已经了解到,Kubernetes通过各种Controller来管理Pod的生命周期。为了满足不同业务场景,Kubernetes开发了 Deployment、ReplicaSet、DaemonSet、StatefuleSet、Job等多种Controller。我们首先学习最常用的Deployment。

5.1.1 运行Deployment

先从例子开始,运行一个Deployment:

[root@k8s-master ~]# cat deployment-nginx.yaml 
apiVersion: v1
kind: Namespace
metadata:
  name: dev
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      run: nginx
  template:
    metadata:
      labels:
        run: nginx
    spec:
      containers:
      - image: nginx:1.7.9
        name: nginx
        ports:
        - containerPort: 80
          protocol: TCP

[root@k8s-master ~]# 
kubectl apply -f deployment-nginx.yaml 

上面的命令将部署包含两个副本的Deployment nginx,容器的image为nginx:1.7.9。

下面详细分析Kubernetes都做了些什么工作,如图所示。

在图5-1中,通过kubectl get deployment命令查看nginx的状态,输出显示两个副本正常运行。

接下来我们用kubectl describe deployment了解更详细的信息,如图所示。

大部分内容都是自解释的,我们重点看图中Type,这里告诉我们创建了一个ReplicaSet nginx-7846f8d4d9,Events是 Deployment的日志,记录了ReplicaSet的启动过程。通过上面的分析,也验证了Deployment通过ReplicaSet来管理Pod的事实。接着我们将注意力切换到nginx-7846f8d4d9,执行kubectl describe replicaset,如图所示。

两个副本已经就绪,用kubectl describe replicaset查看详细信息, 如图所示。

Controlled By指明此ReplicaSet是由Deployment nginx创建的。图中底部是两个副本Pod创建的日志。接着我们来看Pod,执行 kubectl get pod,如图所示。

两个副本Pod都处于Running状态,然后用kubectl describe pod查看更详细的信息,如图所示。

[root@k8s-master ~]# kubectl describe pod nginx-7846f8d4d9-6kdw2
Name:         nginx-7846f8d4d9-6kdw2
Namespace:    default
Priority:     0
Node:         k8s-node1/192.168.1.145
Start Time:   Sun, 22 May 2022 18:30:17 -0400
Labels:       pod-template-hash=7846f8d4d9
              run=nginx
Annotations:  <none>
Status:       Running
IP:           10.244.2.12
IPs:
  IP:           10.244.2.12
Controlled By:  ReplicaSet/nginx-7846f8d4d9
Containers:
  nginx:
    Container ID:   docker://0c6701e28dcbd277068b156d2645fdd3a0298e2bf0364a07a367318a686b2594
    Image:          nginx:1.7.9
    Image ID:       docker-pullable://nginx@sha256:e3456c851a152494c3e4ff5fcc26f240206abac0c9d794affb40e0714846c451
    Port:           80/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Sun, 22 May 2022 18:30:47 -0400
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-47sgv (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  default-token-47sgv:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-47sgv
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age        From                Message
  ----    ------     ----       ----                -------
  Normal  Scheduled  <unknown>  default-scheduler   Successfully assigned default/nginx-7846f8d4d9-6kdw2 to k8s-node1
  Normal  Pulling    11m        kubelet, k8s-node1  Pulling image "nginx:1.7.9"
  Normal  Pulled     11m        kubelet, k8s-node1  Successfully pulled image "nginx:1.7.9"
  Normal  Created    11m        kubelet, k8s-node1  Created container nginx
  Normal  Started    11m        kubelet, k8s-node1  Started container nginx
[root@k8s-master ~]# 

Controlled By指明此Pod是由ReplicaSet nginx-7846f8d4d9创建的。Events记录了Pod的启动过程。如果操作失败(比如image不存在),也能在这里查到原因。

总结一下这个过程中,如图所示。

(1)用户通过kubectl创建Deployment。

(2)Deployment创建ReplicaSet。

(3)ReplicaSet创建Pod。

从图也可以看出,对象的命名方式是“子对象的名字=父对象名字+随机字符串或数字”。

5.1.2 命令vs配置文件

Kubernetes支持两种创建资源的方式:

(1)用kubectl命令直接创建,比如“kubectl run nginx-deployment --image=nginx:1.7.9--replicas=2”(该命令中replicas在新版本以失效),在命令行中通过参数指定资源的属性。

(2)通过配置文件和kubectl apply创建。要完成前面同样的工作,可执行命令“kubectl apply -f nginx.yml”。

资源的属性写在配置文件中,文件格式为YAML。

下面对这两种方式进行比较。

(1)基于命令的方式:

  • 简单、直观、快捷,上手快。
  • 适合临时测试或实验。

(2)基于配置文件的方式:

  • 配置文件描述了What,即应用最终要达到的状态。
  • 配置文件提供了创建资源的模板,能够重复部署。
  • 可以像管理代码一样管理部署。
  • 适合正式的、跨环境的、规模化部署。
  • 这种方式要求熟悉配置文件的语法,有一定难度。

后面我们都将采用配置文件的方式,大家需要尽快熟悉和掌握。

kubectl apply不但能够创建Kubernetes资源,也能对资源进行更新,非常方便。不过Kubernets还提供了几个类似的命令,例如kubectl create、kubectl replace、kubectl edit和kubectl patch。

为避免造成不必要的困扰,我们会尽量只使用kubectl apply,此命令已经能够应对百分之九十多的场景,事半功倍。

5.1.3 Deployment配置文件简介

既然要用YAML配置文件部署应用,现在就很有必要了解一下Deployment的配置格式了,其他Controller(比如DaemonSet)非常类似。

以nginx-deployment为例,配置文件如图所示。

① apiVersion是当前配置格式的版本。

② kind是要创建的资源类型,这里是Deployment。

③ metadata是该资源的元数据,name是必需的元数据项。

④ spec部分是该Deployment的规格说明。

⑤ replicas指明副本数量,默认为1。

⑥ template定义Pod的模板,这是配置文件的重要部分。

⑦ metadata定义Pod的元数据,至少要定义一个label。label的key和value可以任意指定。

⑧ spec描述Pod的规格,此部分定义Pod中每一个容器的属性,name和image是必需的。

此nginx.yml是一个最简单的Deployment配置文件,后面我们学习Kubernetes各项功能时会逐步丰富这个文件。

执行kubectl apply -f nginx.yml,如图所示。

部署成功。同样,也可以通过kubectl get查看nginx-deployment的各种资源,如图所示。

Deployment、ReplicaSet、Pod都已经就绪。如果要删除这些资 源,执行kubectl delete deployment nginx-deployment或者kubectl delete -f nginx.yml,如图所示。

5.1.4 伸缩

伸缩是指在线增加或减少Pod的副本数。

Deployment nginx-deployment初始是两个副本,如图所示。

k8s-node1和k8s-node2上各跑了一个副本。现在修改nginx.yml文件,将副本改成5个,如图所示。

再次执行kubectl apply,如图所示。

三个新副本被创建并调度到k8s-node1和k8s-node2上。

出于安全考虑,默认配置下Kubernetes不会将Pod调度到Master节点。如果希望将k8s-master也当作Node使用,可以执行如下命令:

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

如果要恢复Master Only状态,执行如下命令:

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

接下来修改配置文件,将副本数减少为3个,重新执行kubectl apply,如图所示。

可以看到两个副本被删除,最终保留了3个副本。

5.1.5 Failover

下面我们模拟k8s-node2故障,关闭该节点,如图所示。(实测halt时,pod一直处于running状态,关掉node所在的虚机才会标注为Terminating状态)

等待一段时间,Kubernetes会检查到k8s-node2不可用,将k8s-node2上的Pod标记为Unknown状态,并在k8s-node1上新创建两个 Pod,维持总副本数为3,如图所示。

当k8s-node2恢复后,Terminating的Pod会被删除,不过已经运行的Pod不会重新调度回k8s-node2,如图所示。

删除nginx-deployment,如图所示。

5.1.6 用label控制Pod的位置

默认配置下,Scheduler会将Pod调度到所有可用的Node。不过有些情况我们希望将Pod部署到指定的Node,比如将有大量磁盘I/O的 Pod部署到配置了SSD的Node;或者Pod需要GPU,需要运行在配置了GPU的节点上。

Kubernetes是通过label来实现这个功能的。

label是key-value对,各种资源都可以设置label,灵活添加各种自定义属性。比如执行如下命令标注k8s-node1是配置了SSD的节点。

kubectl label node k8s-node1 disktype=ssd

然后通过kubectl get node --show-labels查看节点的label,如图所示。

disktype=ssd已经成功添加到k8s-node1,除了disktype,Node还有几个Kubernetes自己维护的label。

有了disktype这个自定义label,接下来就可以指定将Pod部署到k8s-node1。编辑nginx.yml,如图所示。

在Pod模板的spec里通过nodeSelector指定将此Pod部署到具有label disktype=ssd的Node上。

部署Deployment并查看Pod的运行节点,如图所示。

全部6个副本都运行在k8s-node1上,符合我们的预期。要删除label disktype,执行如下命令:

kubectl label node k8s-node1 disktype-

- 即删除,如图所示。

不过此时Pod并不会重新部署,依然在k8s-node1上运行,如图所示。

除非在nginx.yml中删除nodeSelector设置,然后通过kubectl apply重新部署,如图所示。

Kubernetes会删除之前的Pod并调度和运行新的Pod。

以上是关于每天5分钟玩转Kubernetes | Deployment的主要内容,如果未能解决你的问题,请参考以下文章

每天5分钟玩转Kubernetes | Kubernetes Dashboard安装

每天5分钟玩转Kubernetes | Deployment

每天5分钟玩转Kubernetes | Heapster

每天5分钟玩转Kubernetes | Deployment

每天5分钟玩转Kubernetes | 先把Kubernetes跑起来

每天5分钟玩转Kubernetes | Network Policy