一、 为何多个容器比单个容器中包含的进程要好
    1、 想象一个由多个进程组成的应用程序,无论是通过ipc(进程通信)还是本地存储文件进行通信,都要求它们运行于同一台机器上。在kubernetes中,我们经常在容器中运行进程,由于每一个容器都像一台独立的机器,此时你可能认为在单个容器这运行多个进程是合乎逻辑的,然而在实践中这种做法并不合理。
    2、 容器被设计为每个容器只运行一个进程(除非进程本身产生进程)。如果在单个容器中运行多个不相关的进程,那么保持所有进程运行、管理它们的日志等将会是我们的责任

    二、 了解pod
    1、 由于不能将多个进程聚集在一个单独的容器中,我们需要另一种更高级的结构来将容器绑定在一起,并将它们作为一个单元进行管理,这就是pod背后的原理。
    2、 在包含容器的pod下,我们可以同时运行一些密切相关的进程,并为它们提供(几乎)相同的环境,此时这些进程就好像全部运行于单个容器中一样,同时又保持着一定的隔离。这样一来,我们便能全面地利用容器所提供的特性,同时对这些进程来说它们就像运行在一起一样,实现两全其美。
    3、 容器之间排彼此是完全隔离的,但此时我们期望的是隔离容器组,而不是单个容器并让每个容器组内的容器共享一些资源,而不是全部(换句话说,没有完全隔离)。Kubernetes通过配置Docker来让一个pod内的所有容器共享相同的linux命名空间,而不是每个容器都有自己的一组命名空间。
    4、 由于一个pod中的所有容器都在相同的network和UTS命名空间下运行(在这里我们讨论的是linux命名空间),所以它们都共享相同的主机名和网络接口。同样地,这些容器都在相同的IPC命名空间下运行,因此能通过IPC进行通信。在最新kubernetes和docker版本中,它们也能够共享相同的PID命名空间,但是该特征默认是未激活的。
    5、 但涉及文件系统时,情况就有所不同。由于大多数容器的文件系统来自容器镜像,因此默认情况下,每个容器的文件系统与其他容器完全隔离。但我们可以使用名为Volume的kubernetes资源来共享文件目录。
    三、 容器如何共享相同的IP和端口空间
    a) 强调的一点是,由于一个Pod中的容器运行相同的Network命名空间中,因此它们共享相同的IP地址和端口空间,这意味着在同一Pod中的容器运行的多个进程需要注意不能绑定到相同的端口号,否则会导致端口冲突,但这只涉及同一Pod中的容器。由于每个Pod都有独立的端口空间,对于不同Pod中的容器来说则不会遇到端口冲突。此外,一个Pod中的所有容器也都具有相同的loopback网络接口,因此容器可以通过localhost与同一Pod中的其他容器进行通信。
    b) 介绍平坦的pod间的网络
    i. Kubernetes集群中的所有pod都在同一个共享网络空间中,这意味着每个Pod都可以通过其他Pod的IP地址来实现相互访问。换句话说,这也表示它们之间没有NAT(网络地址转换)网关。当两个Pod彼此之间发生网络数据包时,它们都会将对方的实际IP地址看作数据包中的源IP。
    ii. 因此,Pod之间的通信其实是非常简单的。不论是将两个Pod安排在单一的还是不同的工作节点上,同时不管实际节点间的网络拓扑如何,这些Pod内的容器能够像在无NAT的平坦网络中一样相互通信,就像局域网(LAN)上的计算机一样此时,每个Pod都有自己的IP地址,并且可以通过这个专门的网络实现Pod之间互相访问。这个专门的网络通常是由额外的软件基于真实链路实现的。
    iii. 总结:Pod是逻辑主机,其行为与非容器世界中的物理组机或虚拟机非常相似。此外,运行在同一个Pod中的进程运行在同一物理机或者虚拟机上的进程相似,只是每个进程都封装在一个容器中。

    四、通过Pod合管理容器
    i. 将Pod视为独立的机器,其中每个机器托管一个特定的应用。过去我们习惯于将各种应用程序塞进同一台主机,但是Pod不是这么干。由于Pod比较轻量,我们可以在几乎不导致如何额外开销的前提下拥有尽可能多的Pod。与将所有内容填充到一个Pod中不同,我们应该将应用程序组织到多个Pod中,而每个Pod只包含紧密相关的组件或进程。
    ii. 说到这里,对于一个由前端应用服务器和后端数据库组成的多层应用程序,你认为应该将其配置为单个Pod还是两个Pod呢?下面我们将对该问题中进一步探讨。
    iii. 将多层应用分散到多个Pod中
    iv. 虽然我们可以在单个Pod中同时运行前端服务器和数据库这两个容器,但这种方式并不值得推荐。前面我们已经讨论过,同一Pod的所有容器总是运行在一起,但对于Web服务器和数据库来说,它们真的需要在同一台计算机上运行吗?答案显然是否定的,它们不应该被放到同一个Pod中。那假如你非要把它们放在一起,有错吗? 某种程度来说,是的
    v. 如果前端和后端都在同一个Pod中,那么两者将始终在同一台计算机运行。如果你有一个双节点Kubernetes集群,而只有一个单独的Pod,那么你始终只会用一个节点,而不会充分利用第二个节点上的计算资源(CPU和内存)。因此更合理的做法是将Pod拆分到两个工作节点,允许Kubernetes将前端安排到一个节点,将后端安排到另一个节点,从而提高基层架构的利用率。
    vi. 基于扩缩容考虑而分割到多个Pod中
    vii. 另外一个不应该将应用程序都放到单一Pod中的原因就是扩缩容的基本单位,对于kubernetes来说,它不能横向扩缩单个容器,只能扩缩整个Pod,这意味着如果你的Pod由一个前端和一个后端组成,那么当你扩大Pod的实例数量时,比如扩大为两个,最终会得到两个前端容器和两个后端容器。
    ii. 通常来说,前端组件与后端组件具有完全不同的扩缩需求,所以我们倾向于分别独立扩缩它们。更不用说,像数据库这样的后端服务器,通常比无状态的前端web服务器更难扩展。因此,如果你需要单独扩缩容器,那么这个容器很明确第应该被部署在单独的Pod中。
    1、 何时在Pod中使用多个容器
    1、 将多个容器添加到单个Pod的主要原因是应用可能由一个主进程和一个或多个辅助进程组成,
    2、 例如,Pod中的主容器可以是一个仅仅服务与某个目录中的Web服务器,而另一个(所谓的sidecar容器)则定期从外部源下载内容并将其存储在Web服务器目录中。sidecar容器的其他例子包括日志轮换和收集器、数据处理器、通信适配器等

    五、以yaml或json描述文件创建pod
    Pod和其他kubernetes资源通常是通过向kubernetes REST API提供json或yaml描述文件来创建

    介绍pod定义的主要部分
    Pod定义由这么几个部分组成:首先是yaml中使用的kubernetes API版本和yaml描述的资源类型;其次是几乎在所有kubernetes资源中都可以找到的三大重要部分:
     metadata:名称、名称空间、标签和关于该容器的其他信息
     spec:pod内容的实际说明,例如pod的容器、
     status:运行中的pod的当前信息,例如pod所处的条件、每个容器的描述和状态

    六、使用标签组织Pod
    对于微服务架构,部署的微服务数量可以轻松超过20个甚至更多。这些组件可能是副本(部署同一组件的多个副本)和多个不同的发布版本(stable、beta、canary等)同时运行。这样一来可能会导致我们在系统中拥有数百个pod,如果没有有效的组织这些组件的限制,将会导致巨大的混乱

    1. 介绍标签
      i. 标签是一种简单却功能强大的kubernetes特性,不仅可以组织Pod,也可以组织所有其他的kubernetes资源。详细来讲,标签是可以附加到资源的任意键值对,用以选择具有确切标签的资源(这是通过标签选择器完成的)。只要标签的key在资源内是唯一的,一个资源便可以拥有多个标签。通常在我们创建资源时就会将标签附加到资源上,但之后我们也可以再添加其他标签。或者相关现有标签的值,而无须重新创建资源
      ii. 使用标签和选择器来约束Pod调度
      a) 迄今为止,我们创建的所有Pod都是几乎随机地调度到工作节点上的。由于kubernetes将集群中的所有节点抽象为一个整体的大型部署平台,因此对于你的Pod实际调度到哪个节点而言是无关紧要的,对于每个Pod而言,它获得所请求的确切数量的计算资源(CPU 内存等)及其他pod的可访问性,完全不受该pod所调度的节点的影响,使用通常来说没有任何需要指定kubernetes把Pod调度到哪里的需求。
      i. 如果你想对一个Pod应该调度哪里拥有发言权,不应该直接指定一个确切的节点,而应该用某种方式描述对节点的需求,使kubernetes选择一个符合这些需求的节点,这恰恰可以通过节点标签和节点标签选择器完成
      2、 使用名称空间对资源进行分组
      i. 首先回到标签的概念,我们已经看到标签是如何将Pod和其他对象组织成组的。由于每个对象都可以有多个标签,因此这些对象组可以重叠,另外,当中集群中工作(例如通过kubectl)时,如果没有明确指定标签选择器,我们总能看到所有对象。
      ii. 但是,当你想将对象分割成完全独立且不重叠的组时,又该如何呢?可能你每次只想在一个小组内进行操作,因此kubernetes也能将对象分组到命名空间中。Kubernetes命名空间简单地为对象名称提供了一个作用域。此时我们并不会将所有资源都放在同一个命名空间中,而是将他们组织到多个命名空间中,这样可以允许我们多次使用相同的资源名称(跨不同的命名空间)
      iii. namespace使我们将不属于一组的资源放到不重叠的组中。如果有多个用户或用户组正在使用同一个kubernetes集群,并且它们都各自管理自己独特的资源集合,那么它们就应该分别使用各自的命名空间。这样一来,它们就不用特别担心无意中修改或删除其他用户的资源,也无须关心名称冲突。如前所述,命名空间为资源名称提供了一个作用域。除了隔离资源,命名空间还可用仅允许某些用户访问某些特定资源,甚至限制单个用户可用的计算资源数量
      iv. 可以使用 kubectl create -f kubia-manual.yaml -n custom-namespace 创建资源时指定命名空间
      v. 在结束命名空间这一部分之前,我们需要解释一下命名空间不提供什么——至少不是开箱即用的。尽管命名空间将对象分隔到不同组,只允许你对属于特定命名空间的对象进行操作,但实际上命名空间之间并不提供对正在运行对象的如何隔离。
      vi. 例如,你看会认为当不同的用户在不同的命名空间部署Pod时,这些Pod应该彼此隔离,并且无法通信,但事实并非如此。命名空间之间是否提供网络隔离取决于kubernetes所使用的网络解决方案。当解决方案不提供命名空间 间的网络隔离,如果命名空间foo中的某个Pod指定命名空间bar中pod的IP地址,那它就可以将流量(例如HTTP请求)发送到另外一个Pod
      停止和移除Pod
      删除Pod的过程中,实际上我们在指示Kubernetes终止该Pod中的所有容器。Kubernetes向进程发送一个SIGTERM信号并等待一定的秒数(默认为30),使其正常关闭。如果它没有及时关闭,则通过SIGKILL终止该进程。因此为了确保你的进程总是正常关闭,进程需要正常处理SIGTERM信号。
      使用标签选择删除Pod:
      Kubectl delete po -l name