kubernetes in action 第三章学习笔记

kubernetes in action 第三章学习笔记

第三章《pod:运行于Kubernetes中的容器》

pod简介

pod是一组并置的容器,代表了Kubernetes中的基本构建模块。当然一个pod可以仅包含一个单独容器,也可以包含多个容器。当一个pod包含多个容器时,这些容器总是运行在同一个工作节点上。

为什么需要pod

Q:为什么需要pod这种容器?为什么不直接使用容器?难道不能简单地把所有进程都放在一个单独的容器中吗?

A:如果在单个容器中运行多个不相关的进程,那么保持所有进程运行、管理它们的日志等将会是我们的责任。这些进程都将记录到相同的标准输出中,而此时我们很难确定每个进程分别记录了什么。

由此,不能将多个进程聚集在一个单独的容器中,所以我们需要另一种更高级的结构来将容器绑定在一起,并将它们作为一个单元进行管理,这就是pod背后的根本原理。

在pod下,我们可以同时运行一些密切相关的进程,并为他们提供(几乎)相同的环境,此时这些进程就好像全部运行于单个容器中一样,同时又保持一定的隔离。

Q:同一pod中容器的部分隔离如何实现

A:Kubernetes通过配置Docker来让一个pod内的所有容器共享相同的Linux命名空间,而不是每一个容器有自己的一组命名空间。
但当涉及文件系统时,情况有所不同。默认情况下,每个容器的文件系统与其他容器完全隔离,但我们可以使用名为Volume的Kubernetes资源来共享文件目录。


Q:同一pod中的容器如何共享相同的IP和端口空间

A:由于一个pod中的容器运行于相同的Network命名空间中,它们共享相同的IP地址和端口空间。因此在同一pod中的容器运行的多个进程需要注意不能绑定相同的端口号,否则会端口冲突。

pod是逻辑主机,其行为与非容器世界的物理主机或虚拟机非常相似。此外,运行在同一个pod中的进程与运行在同一物理机或虚拟机上的进程相似,只是每一个进程都封装在一个容器中。

决定何时在pod中使用多个容器

当决定是将两个容器放入一个pod还是两个单独的pod时,我们需要问自己以下的问题来确保合理:

  • 它们需要一起运行还是可以在不同的主机上运行?
  • 它们代表的是一个整体还是相互独立的组件?
  • 它们必须一起进行扩缩容还是可以分别进行?

以YAML或JSON描述文件创建pod

通过YAML文件定义所有的Kubernetes对象之后,可以将它们存储在版本控制系统中。

pod定义的三大主要部分:

  • metadata:包括名称、命名空间、标签以及关于容器的其他信息
  • spec:包含pod内容的实际说明,例如镜像、容器、卷和其他数据
  • status:包含运行中的pod的当前信息

创建新的pod时,永远不需要提供status部分。例如可以为pod创建一个简单的YAML描述文件如下:

apiVersion:v1
kind:Pod
metadata:
    name:mytest-manual //pod的名称
spec:
    containers:
    - image:yanch/mytest // 创建容器所用的镜像的名称
      name: mytest //容器的名称
      ports:
      - containerPort: 8080 //容器监听的端口
        protocal: TCP

使用kubectl create来创建pod

$ kubectl create -f mytest-manual.yaml
pod "mytest-manual" created

要注意 kubectl create -f 命令用于从YAML或JSON文件创建任何资源(不止是pod,可以在kind字段设置任何Kubernetes对象类型)

使用标签组织pod

随着pod数量的增加,将它们分类到子集的需求变得越来越明显。我们希望通过一次操作对属于某个组的所有pod进行操作,而不必单独为每个pod执行操作。

标签是可以附加到资源的任意键值对,用以选择具有该确切标签的资源。

创建pod时指定标签

创建一个名为 mytest-manual-with-labels.yaml的新文件如下

apiVersion:v1
kind:Pod
metadata:
    name:mytest-manual-v2 
    labels:
        creation_method: manual //两个标签被附加到pod上
        env: prod
spec:
    containers:
    - image:yanch/mytest 
      name: mytest 
      ports:
      - containerPort: 8080 
        protocal: TCP

创建该pod并使用 --show-labels选项查看

$ kubectl create -f mytest-manual-with-labels.yaml
pod "mytest-manual-v2" created

$ kubectl get po --show-labels

NAME                READY   STATUS      RESTARTS    AGE     LABELS
mytest-manual       1/1     Running     0           16m     <none>
mytest-manual-v2    1/1     Running     0           2m      creation_method=manual,env=prod

如果只对某些标签感兴趣,可以使用-L选项进行指定
$ kubectl get po -L creation_method,env

NAME                READY   STATUS      RESTARTS    AGE     CREATION_METHOD ENV
mytest-manual       1/1     Running     0           16m     <none>          <none>
mytest-manual-v2    1/1     Running     0           2m      manual          prod

更改现有标签时,需要使用 --overwrite选项,如下

kubectl label po mytest-manual-v2 env=debug --overwrite

使用标签和选择器来约束pod调度

我们不应说明pod应该调度到哪个节点上,因为这将会使应用程序和基础架构强耦合,,应该使用某种方式描述对节点的需求,使Kubernetes选择一个符合这些需求的节点。这可以通过标签选择器完成。

标签可以附加到任意Kubernetes资源上,假设集群中的一个节点刚添加完成,其包含一个GPU,我们希望向该节点添加标签描述这个特性,则可以向节点添加gpu-true来实现。

kubectl label node node-name gpu=true

比如想部署一个需要GPU来执行工作的新pod,为了让调度器只在提供适当GPU的节点中进行选择,我们需要在pod的YAML文件中添加一个节点选择器,比如

apiVersion:v1
kind:Pod
metadata:
    name: test-gpu
spec:
    nodeSelector:
        gpu: "true" //节点选择器要求k8s只将pod部署到包含标签gpu=true的节点上
    containers:
    - image: xxx/xxx
      name: test

使用命名空间对资源进行分组

需求

在使用多个namespace的前提下,我们可以将包含大量组件的复杂系统拆分为更小的不同组,这些不同组也可以用于在多租户环境中分配资源,将资源分配为生产、开发、QA环境。

namespace使我们能够将不属于一组的资源分配到不重叠的组中。如果有多个用户或用户组正在使用同一个Kubernetes集群,并且他们都各自管理自己独特的资源集合,那么它们就应该分别使用各自的命名空间。

创建命名空间

命名空间是一种和其他资源一样的Kubernetes资源,因此可以通过YAML文件定义并提交到Kubernetes API服务器来创建该资源。

可以创建custom-namespace.yaml文件如下

apiVersion:v1
kind:namespace
metadata:
    name:custom-namespace

使用kubectl将文件提交到Kubernetes API 服务器

$ kubectl create -f custom-namespace.yaml
namespace "custom-namespace" created

当然也可以直接使用命令来创建命名空间

$ kubectl create namespace custom-namespace
namespace "custom-namespace" created

管理其他命名空间中的对象

如果想在命名空间中创建资源,可以选择在metadata字段之中添加一个namespace:custom-namespace属性,也可以在使用命令创建资源时通过args参数指定命名空间

停止和移除pod

在删除pod的过程中,实际上我们在指示Kubernetes终止该pod中所有的容器。

  1. 按名称删除pod
    $ kubectl delete po test-gpu
    pod "test-gpu" deleted
    
  2. 使用标签选择器删除pod
    $ kubectl delete po -l creation_method=manual
    pod "mytest-manual" deleted
    pod "mytest-manual-v2" deleted
    
  3. 通过删除整个命名空间来删除pod
    $ kubectl delete ns custom-namespace
    namespace "custom-namespace" deleted
    
  4. 删除命名空间中的所有pod,但保存命名空间
    $ kubectl delete po --all
    
  5. 删除命名空间中的(几乎)所有资源
    $ kubectl delete all --all
    
    命令中的第一个all指定正在删除所有资源类型,而--all选项指定将删除所有资源实例
posted @ 2020-12-10 15:48  BuptWade  阅读(86)  评论(0)    收藏  举报