李成笔记网

专注域名、站长SEO知识分享与实战技巧

精通k8s(3)深入pod内部探险1:两个busybox的实验

k8s和docker有些不同,docker是以容器为单位,而k8s是以pod为单位进行调度。下面一个图说明问题:

从外观上看,一个pod里面可能包含一组容器,它们组成一个整体的pod。

pod的特性

资料上是这么说:如果在 Pod 中运行多个容器,那么多个容器间是共享相同的 Pod 环境的。

共享环境中包括了 IPC 命名空间,共享的内存,共享的磁盘网络以及其他资源等。举一个具体的例子,运行在相同 Pod 中的所有容器都有相同的 IP 地址(Pod 的 IP 地址)。

这个听起来很神奇,pod内部的容器竟然IP地址相同,下面我们准备用实验来验证。

实验准备的镜像:busybox

busybox是一个工具镜像,它里面包含各种命令行工具,你可以把它想像成是一个带有各种工具的mini linux系统。我们想实现的是下面的拓扑结构:

小人表示我们,我们通过sh进到busybox内部,然后执行ip命令,就可以查看容器的网络。需要说下,在研究k8s的时候,我们应该先熟悉docker的相关操作,如果不熟悉可以尽快看书熟悉。

给k8s server发命令

拓扑结构清楚之后,我们接下来就给k8s发命令,也就是给它发送配置文件,如下:

apiVersion: v1
kind: Pod
metadata:
  name: simple-busybox-pod
spec:
  containers:
  # 第一个busybox容器,启动后休眠
  - name: busybox-1
    image: busybox:1.35
    command: ["sleep", "infinity"]  # 保持容器运行不退出

  # 第二个busybox容器,启动后休眠
  - name: busybox-2
    image: busybox:1.35
    command: ["sleep", "infinity"]  # 保持容器运行不退出

文件命名为:pod-busybox-test.yml,名字可以任意。

然后,我们通过kubectl发送命令:

kubectl apply -f pod-busybox-test.yml

kubectl apply的意思就是应用、部署等的意思,那么连起来就是:把pod-busybox-test.yml这个文件发给api server,然后让它执行。

为什么要让容器休眠?

容器有个特性,就是如果当前没有任何运行的进程,这个容器就自己退出。在实验中,我们不能让容器退出,因此让它休眠。

进入pod

再看下我们的网络拓扑结构:

master节点收到命令,也就是第一节课称为”“的东西之后,它马上就执行了,然后创建一个pod,但是我们看到集群有两个node节点,因此它就随机的在某个机器上创建。

查看pod

pod生成之后,我们想查看一下集群里面有多少个pod,就好比你是一家水果店老板,想盘点下店里还有多少个苹果。因此,查询是k8s里面非常频繁的动作,命令如下:

kubectl get pods

[root@k8s-master ~]# kubectl get pods

NAME READY STATUS RESTARTS AGE

simple-busybox-pod 2/2 Running 0 28s

--------------------------------

我们看到创建的pod,它的NAME和配置文件中的name一样。这个名字很重要,我们需要它来引用这个pod进行各种操作。

进入pod的某个容器

命令:

kubectl exec -it \
simple-busybox-pod -c busybox-1 \
-- sh

这个命令我们分段解释一下:

kubectl exec:它和docker exec很相似,表示在容器内部执行命令。

-it:表示打开输入和分配一个伪终端。这个地方在后面详细解释。

simply-busybox-pod:表示pod名。

-c busybox-1:表示进入哪个容器。

-- sh:表示要执行的命令。

全部连起来就是:进入simple-busybox-pod内的busybox-1容器内,然后执行sh命令

-it的解释

-it是一个比较绕的命令,我写下我的理解:

在C语言编程中,书本是这么说的,当一个进程打开后默认会打开三个文件描述符,输入,输出和错误输出。但是在容器中有点不同,当打开进程时,默认输入不是打开的,我在图中用键盘表示输入,也就是说一开始那根线是断的,为什么这样呢?一种说法是为了安全。

sh进程运行之后一看发现输入都没了,那我还傻等啥呢,命令都输不进来了,我也关闭算了。所以如果不打开输入,sh一会就关闭了,这就是-i的作用。

第二,为了让sh更好的完整的工作,我们专门还给它配一个伪终端。那么有的同学会问,我不分配又咋样?也没有问题,这样就是共享一个终端。打个比方说,你和同桌本来是一人一个桌子的,现在两个人共用一张桌子,那么同桌的动作可能就会干扰你的动作,在终端上的表现就是输出的东西混在一起。所以为了相互不打扰,就一人独占一个桌子,这就是分配一个伪终端的作用。

总结一下:sleep将容器休眠,然后再启动一个sh进程,让它输入畅通,再给它分配一个终端,这样准备工作就完成了。

执行ip命令

进入终端后,输入命令:

[root@k8s-master ~]# kubectl exec -it simple-busybox-pod -c busybox-1 -- sh
/ # ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
4: eth0@if20: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1480 qdisc noqueue
link/ether 9e:84:35:cc:28:ea brd ff:ff:ff:ff:ff:ff
#IP地址
inet 10.244.169.140/32 brd 10.244.169.140 scope global eth0 
valid_lft forever preferred_lft forever

输入exit退出,接着按着同样的方法,我们进入busybox-2容器,执行结果如下:

[root@k8s-master ~]# kubectl exec -it simple-busybox-pod -c busybox-2 -- sh
/ # ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
4: eth0@if20: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1480 qdisc noqueue
link/ether 9e:84:35:cc:28:ea brd ff:ff:ff:ff:ff:ff
#IP地址
inet 10.244.169.140/32 brd 10.244.169.140 scope global eth0
valid_lft forever preferred_lft forever

可以看到,两个容器的IP地址确实相同。

总结

这篇内容比较长,主要说明了下面的问题

  1. 部署一个pod,且该pod内部有两个容器。
  2. 验证pod的一个结论:pod内部的容器共享pod环境,比如具有相同的IP地址。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言