k8s 深入篇———— k8s 的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中容器的部分,但是它们的主要区别在于:
生命周期不同:initContainers是在Pod中所有容器之前启动的,并且只有在initContainers完成后才会启动其他容器。而Containers则是同时启动的。
用途不同:initContainers主要用于在启动Pod之前完成一些初始化操作,例如配置环境变量、检查依赖等。而Containers则是用于运行应用程序或服务。
状态不同: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。
k8s 深入篇———— k8s 的pod[五]的更多相关文章
- docker+k8s基础篇五
Docker+K8s基础篇(五) service资源介绍 A:service资源的工作特性 service的使用 A:service字段介绍 B:ClusterIP的简单使用 C:NodePort的简 ...
- [转帖]我花了10个小时,写出了这篇K8S架构解析
我花了10个小时,写出了这篇K8S架构解析 https://www.toutiao.com/i6759071724785893891/ 每个微服务通过 Docker 进行发布,随着业务的发展,系统 ...
- docker+k8s基础篇四
Docker+K8s基础篇(四) pod控制器 A:pod控制器类型 ReplicaSet控制器 A:ReplicaSet控制器介绍 B:ReplicaSet控制器的使用 Deployment控制器 ...
- docker+k8s基础篇三
Docker+K8s基础篇(三) kubernetes上的资源 A:k8s上的常用资源 Pod的配置清单 A:Pod上的清单定义 B:Pod创建资源的方法 C:spec下其它字段的介绍 Pod的生命周 ...
- docker+k8s基础篇二
Docker+K8s基础篇(二) docker的资源控制 A:docker的资源限制 Kubernetes的基础篇 A:DevOps的介绍 B:Kubernetes的架构概述 C:Kubernetes ...
- docker+k8s基础篇一
Docker+K8s基础篇(一) docker的介绍 A:为什么是docker B:k8s介绍 docker的使用 A:docker的安装 B:docker的常用命令 C:docker容器的启动和操作 ...
- 使用 Tye 辅助开发 k8s 应用竟如此简单(五)
续上篇,这篇我们来进一步探索 Tye 更多的使用方法.本篇我们来了解一下如何在 Tye 中实现对分布式链路追踪. Newbe.Claptrap 是一个用于轻松应对并发问题的分布式开发框架.如果您是首次 ...
- kubernetes/k8s CRI分析-kubelet删除pod分析
关联博客<kubernetes/k8s CRI 分析-容器运行时接口分析> <kubernetes/k8s CRI分析-kubelet创建pod分析> 之前的博文先对 CRI ...
- 这一篇 K8S(Kubernetes)集群部署 我觉得还可以!!!
点赞再看,养成习惯,微信搜索[牧小农]关注我获取更多资讯,风里雨里,小农等你,很高兴能够成为你的朋友. 国内安装K8S的四种途径 Kubernetes 的安装其实并不复杂,因为Kubernetes 属 ...
- 泡面不好吃,我用了这篇k8s调度器,征服了他
1.1 调度器简介 来个小刘一起 装逼吧 ,今天我们来学习 K8的调度器 Scheduler是 Kubernetes的调度器,主要的任务是把定义的 pod分配到集群的节点上,需要考虑以下问题: 公平: ...
随机推荐
- C# 课堂管理系统(火影忍者界面!!!)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 usin ...
- VC-MFC(1) 随笔笔记+连接数据库
1 数据库语句: 2 CREATE DATABASE---创建新数据库 3 ALTER DATABASE-----修改数据库 4 CREATE TABLE ---- -创建新表 5 ALTER TAB ...
- Nacos服务跨分组调用
一. 问题背景 nacos有两种服务隔离的机制,一个是空间namespace,一般我们用namespace区分环境,另外一个是分组group,nacos的默认调用机制是同namespace下的同gro ...
- 案例8:将"picK"的大小写互换
最终输出结果为PICk. 需要先计算两个字母之间的间隔,比如a和A之间的间隔为多少. 然后在将大写字母转换为小写字母,加上间隔的值: 将小写字母转换为大写字母,减去间隔的值. 示例代码如下: #def ...
- .npmrc 项目的 默认安装配置
.npmrc registry=http://192.168.77.105:8081/nexus/content/groups/npm-all/
- 基于python的环境噪声实时监测系统
一 系统简介 1.简介 该系统可以实时显示噪声量大小,并进行一段时间的噪声统计. 2.特性 实现噪声值的统计 实现了噪声显示 完整的主题和样式控制 简单的内置日志窗口 二 源码解析 1.噪声分贝的 ...
- 为什么ASP.NET Core的路由处理器可以使用一个任意类型的Delegate
毫不夸张地说,路由是ASP.NET Core最为核心的部分.路由的本质就是注册一系列终结点(Endpoint),每个终结点可以视为"路由模式"和"请求处理器"的 ...
- C#中的For与Foreach循环:一场性能对话与实战解析
引言 在C#编程实践中,选择适当的循环结构对程序性能至关重要,尤其是在处理大量数据或追求极致运行效率时.本文将深入探讨C#中的两种主要迭代机制--传统的for循环和基于集合迭代器的foreach循环之 ...
- 记录--P0事故预警
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 背景 某一天,前端小余同学和后端别问我小哥在做登录业务接口对接,出于业务的特殊性和安全性的考虑,她和后端小哥约定"user&qu ...
- 记录--vue3优雅的使用element-plus的dialog
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 如何优雅的基于 element-plus,封装一个梦中情 dialog 优点 摆脱繁琐的 visible 的命名,以及反复的重复 dom. ...