首页 > 其他分享 >k8s 深入篇———— k8s 的pod[五]

k8s 深入篇———— k8s 的pod[五]

时间:2023-06-24 16:11:07浏览次数:38  
标签:容器 Container name Infra 深入 pod k8s initContainers Pod

前言

简单整理一下pod的相关知识。

正文

为什么我们需要pod。

前面我们知道了k8s一个最重要的作用是解决容器的编排功能,那么为什么有一个pod的东西。

这就是实际中遇到的问题。

那就是容器和容器之间,那就是如何表达容器和容器之间的关系。

就是有些场景下,容器与容器之间是存在关系的。

如果把k8s 比作操作系统,容器比作进程,那么进程组就是pod。

之所以有这个pod,就是因为一些容器他们之间需要在公共的namespace、cgroup 下面运行。

也可以理解他们原本就应该在一台虚拟机下面执行。

像这样容器间的紧密协作,我们可以称为“超亲密关系”。

这些具有“超亲密关系”容器的典型特征包括但不限于:互相之间会发生直接的文件交换、使用 localhost 或者 Socket 文件进行本地通信、

会发生非常频繁的远程调用、需要共享某些 Linux Namespace(比如,一个容器要加入另一个容器的 Network Namespace)等等。

不过,Pod 在 Kubernetes 项目里还有更重要的意义,那就是:容器设计模式。

首先,关于 Pod 最重要的一个事实是:它只是一个逻辑概念。

也就是说,Kubernetes 真正处理的,还是宿主机操作系统上 Linux 容器的 Namespace
和 Cgroups,而并不存在一个所谓的 Pod 的边界或者隔离环境。
那么,Pod 又是怎么被“创建”出来的呢?
答案是:Pod,其实是一组共享了某些资源的容器。

具体的说:Pod 里的所有容器,共享的是同一个 Network Namespace,并且可以声明
共享同一个 Volume。

所以,在 Kubernetes 项目里,Pod 的实现需要使用一个中间容器,这个容器叫作 Infra 容器。

在这个 Pod 中,Infra 容器永远都是第一个被创建的容器,而其他用户定义的容器,则通过 Join Network Namespace 的方式,与 Infra 容器关联在一起。

这样的组织关系,可以用下面这样一个示意图来表达:

这个 Pod 里有两个用户容器 A 和 B,还有一个 Infra 容器。很容易理解,在Kubernetes 项目里,Infra 容器一定要占用极少的资源,所以它使用的是一个非常特殊的镜像,叫作:k8s.gcr.io/pause。

这个镜像是一个用汇编语言编写的、永远处于“暂停”状态的容器,解压后的大小也只有 100~200 KB 左右。

而在 Infra 容器“Hold 住”Network Namespace 后,用户容器就可以加入到 Infra 容器的 Network Namespace 当中了。

所以,如果你查看这些容器在宿主机上的 Namespace文件(这个 Namespace 文件的路径,我已经在前面的内容中介绍过),它们指向的值一定是完全一样的。

当然,其他的所有网络资源,都是一个 Pod 一份,并且被该 Pod 中的所有容器共享;Pod 的生命周期只跟 Infra 容器一致,而与容器 A 和 B 无关。

比如:

apiVersion: "v1"
kind: "Pod"
metadata:
  name: two-contrains
  namespace: name01
spec:
  restartPolicy: "Always"
  volumes:
  - name: shared-data
    hostPath:
      path: /data
  containers:
  - name: nginx-controller
    image: nginx
    volumeMounts:
    - name: shared-data
      mountPath: /usr/share/nginx/html
  - name: debian-container
    image: debian
    volumeMounts:
    - name: shared-data
      mountPath: /pod-data
    command: ["/bin/sh"]
    args: ["-c","echo Hello from the debian container ! > /pod-data/index.html"]

pod 声明了一个volume,然后容器nginx-controller、debian-container 使用。

来看下怎么实现的。

来看下docker 现象。

对于volumeMounts 而言,其实就是绑定/pod-data 到 /data 中。

对于网络而言:

其实就是pod 内的几个容器共享网络。

对上面而言用的是infra的网络。

再举一个例子, 介绍一个initContainers:

k8s中的initContainers和Containers都是用于定义Pod中容器的部分,但是它们的主要区别在于:

  1. 生命周期不同:initContainers是在Pod中所有容器之前启动的,并且只有在initContainers完成后才会启动其他容器。而Containers则是同时启动的。

  2. 用途不同:initContainers主要用于在启动Pod之前完成一些初始化操作,例如配置环境变量、检查依赖等。而Containers则是用于运行应用程序或服务。

  3. 状态不同:initContainers完成后会退出,而Containers会继续运行。

总之,initContainers主要用于在Pod启动时完成一些初始化工作,而Containers则是用于运行应用程序或服务。

是的,initContainers是按照它们在Pod中的顺序依次运行的,每个initContainer必须在前一个initContainer完成后才能开始运行。只有所有的initContainers都成功完成后,Pod中的其他容器才会启动。

在定义initContainers时,可以使用spec.initContainers字段来指定它们的顺序。例如,下面的示例定义了两个initContainers,分别用于执行初始化操作:

spec:
  initContainers:
  - name: init-container-1
    image: busybox
    command: ['sh', '-c', 'echo "init container 1"']
  - name: init-container-2
    image: busybox
    command: ['sh', '-c', 'echo "init container 2"']
  containers:
  - name: my-app
    image: my-image
    command: ['sh', '-c', 'echo "my app"']

在这个示例中,init-container-1将在init-container-2之前执行。当Pod启动时,先运行init-container-1,然后等待它完成后再运行init-container-2,最后才启动my-app容器。

那么举一个实际中用到的例子,现在这个例子没什么用了,因为现在java 打包就集成了tomcat,而不是在外面包裹一层:

apiVersion: v1
kind: Pod
metadata:
  name: javaweb-2
spec:
  initContainers:
  - image: geektime/sample:v2
    name: war
    command: ["cp", "/sample.war", "/app"]
    volumeMounts:
    - mountPath: /app
      name: app-volume
  containers:
  - image: geektime/tomcat:7.0
    name: tomcat
    command: ["sh","-c","/root/apache-tomcat-7.0.42-v2/bin/start.sh"]
    volumeMounts:
    - mountPath: /root/apache-tomcat-7.0.42-v2/webapps
      name: app-volume
    ports:
    - containerPort: 8080
      hostPort: 8001
  volumes:
  - name: app-volume
    emptyDir: {}

上面大体意思是将sample.war拷贝到app下面,然后将挂载出来,然后geektime/tomcat:7.0 就可以使用这个war 包了。

实际上,这个所谓的“组合”操作,正是容器设计模式里最常用的一种模式,它的名字叫:sidecar

顾名思义,sidecar 指的就是我们可以在一个 Pod 中,启动一个辅助容器,来完成一些独立于主进程(主容器)之外的工作。

比如,在我们的这个应用 Pod 中,Tomcat 容器是我们要使用的主容器,而 WAR 包容器的存在,只是为了给它提供一个 WAR 包而已。

所以,我们用 Init Container 的方式优先运行 WAR 包容器,扮演了一个 sidecar 的角色。

这样做就有用给好处,就是每次都更新的是war包,而不需要关注tomcat运行环境,减少包的大小。

比如,我现在有一个应用,需要不断地把日志文件输出到容器的 /var/log 目录中。

这时,我就可以把一个 Pod 里的 Volume 挂载到应用容器的 /var/log 目录上。

然后,我在这个 Pod 里同时运行一个 sidecar 容器,它也声明挂载同一个 Volume 到自己的 /var/log 目录上。

这样,接下来 sidecar 容器就只需要做一件事儿,那就是不断地从自己的 /var/log 目录里读取日志文件,转发到 MongoDB 或者 Elasticsearch 中存储起来。这样,一个最基本的日志收集工作就完成了。

跟第一个例子一样,这个例子中的 sidecar 的主要工作也是使用共享的 Volume 来完成对文件的操作。

但不要忘记,Pod 的另一个重要特性是,它的所有容器都共享同一个 NetworkNamespace。

这就使得很多与 Pod 网络相关的配置和管理,也都可以交给 sidecar 完成,而完全无须干涉用户容器。

这里最典型的例子莫过于 Istio 这个微服务治理项目了。

Istio 项目使用 sidecar 容器完成微服务治理的原理,我在后面很快会讲解到。

下面一点需要区分:

在 Kubernetes 中,Infra Container 和 Init Container 都是容器,但它们有不同的用途和生命周期。

Infra Container 是一个在 Pod 中运行的辅助容器,用于提供一些共享资源或服务,例如网络命名空间、存储卷、日志收集、监控等。Infra Container 在 Pod 启动后一直运行直到 Pod 终止。

Init Container 是一种特殊类型的容器,它是在 Pod 中其他容器启动之前运行的,用于初始化或准备一些资源。例如,可以使用 Init Container 下载应用程序代码、初始化数据库、生成配置文件等。Init Container 在它的工作完成后立即退出,然后 Pod 中的其他容器才开始启动。

因此,Infra Container 和 Init Container 的主要区别在于它们的用途和生命周期。Infra Container 是一个持久的辅助容器,为 Pod 提供一些共享资源或服务;而 Init Container 是一个短暂的容器,用于在其他容器启动之前初始化或准备一些资源。

然后:

如果在 Kubernetes 中未定义 Infra Container,则 Kubernetes 会自动添加一个名为 `pause` 的 Infra Container。这是一个非常轻量级的容器,它的作用是为 Pod 中的其他容器创建 Linux 命名空间和网络 namespace,并为网络 namespace 分配 IP 地址。

在 Pod 中自动添加的 `pause` 容器是一个 Infra Container,它会在其他容器之前启动,并在其他容器退出之后保持运行状态。因此,即使在 Pod 定义文件中未定义 Infra Container,Kubernetes 仍然会确保 Infra Container 在 Pod 启动时运行。

需要注意的是,如果在 Pod 定义文件中显式定义 Infra Container,则 Kubernetes 不会自动添加 `pause` 容器。在这种情况下,Infra Container 的定义顺序决定了它的启动顺序。

一般情况下,我们是不填这个Infra Container。

标签:容器,Container,name,Infra,深入,pod,k8s,initContainers,Pod
From: https://www.cnblogs.com/aoximin/p/17489783.html

相关文章

  • 深入理解Spring Boot:简化Java应用开发的利器
    这篇文章主要介绍了SpringBoot的理论知识和核心概念。【摘要】SpringBoot是一个用于简化Java应用开发的框架,通过提供自动化配置和约定优于配置的原则,使得开发人员可以快速构建独立、可执行的、生产级别的应用程序。本文将深入探讨SpringBoot的核心理论和关键概念,帮助读者更好......
  • k8s驱逐篇(6)-kube-controller-manager驱逐-NodeLifecycleController源码分析
    概述k8sv1.16版本中NodeController已经分为了NodeIpamController与NodeLifecycleController,本文主要介绍NodeLifecycleController。NodeLifecycleController主要功能有:(1)定期检查node的心跳上报,某个node间隔一定时间都没有心跳上报时,更新node的readycondition值为false或unkno......
  • K8S安装记录
    https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes/https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/ 在master和worker节点上安装containerd、kubelet、kubeadm、kubectllsmod|grepbr_n......
  • k8s部署nacos
    首先创建数据库nacos执行以下语句CREATETABLE`config_info`(`id`bigint(20)NOTNULLAUTO_INCREMENTCOMMENT'id',`data_id`varchar(255)NOTNULLCOMMENT'data_id',`group_id`varchar(255)DEFAULTNULL,`content`longtextNOTNULLCOMME......
  • k8s安装部署集群
    说明这里准备了三台服务器,一台作为主节点(Master),两台作为子节点(Node)每个步奏分为:ALL=所有服务器Master=主节点Node=子节点详细步骤查看ip(ALL)ipaddr这里地址很重要,最好保存下来,后续会用到配置HostName(ALL)配置sudohostnamectlset-hostnamemasters......
  • k8s 深入篇———— k8s 的本质[四]
    前言简单整理一下k8s的本质。正文首先,Kubernetes项目要解决的问题是什么?编排?调度?容器云?还是集群管理?实际上,这个问题到目前为止都没有固定的答案。因为在不同的发展阶段,Kubernetes需要着重解决的问题是不同的。但是,对于大多数用户来说,他们希望Kubernetes项目带来的体验......
  • 深入了解ApacheZeppelin:如何构建高效的数据科学平台
    目录引言随着数据科学和人工智能的快速发展,如何构建高效的数据科学平台已经成为一个重要议题。ApacheZeppelin是一个开源的数据科学平台,其提供了一种简单、高效的方式来处理和存储数据,并且具有高度可定制性和灵活性。在本文中,我们将深入探讨ApacheZeppelin的技术原理、实现......
  • 手写K8S的YAML很痛苦,看完这篇让你信手拈来
    写在开篇对于刚刚接触K8s的新手来说,手动编写K8s的YAML配置文件可能会是一件很麻烦的事情。因为,配置文件包含了许多复杂的对象和属性。比如Pod对象的各个字段、它们的含义以及可接受的值都有哪些?看完本篇可能会让你功力大增。本篇的内容虽然很基础,但很实用,说不定还真就有不知道的......
  • 手写K8S的YAML很痛苦,看完这篇让你信手拈来
    写在开篇对于刚刚接触K8s的新手来说,手动编写K8s的YAML配置文件可能会是一件很麻烦的事情。因为,配置文件包含了许多复杂的对象和属性。比如Pod对象的各个字段、它们的含义以及可接受的值都有哪些?看完本篇可能会让你功力大增。本篇的内容虽然很基础,但很实用,说不定还真就有不知道的......
  • 习惯“白嫖”的行为特征:深入了解和识别
    引言:在网络社交环境中,我们常常遇到那些经常寻求免费资源或希望无需任何付出就能得到回报的人。这种现象在互联网语境下,被称为"白嫖"。为了更好地理解这种行为,我们将深入探讨其背后的特点和动机。1.明显的“白嫖”行为特征一般而言,习惯“白嫖”的人可能会有以下的一些表现:频......