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中所有的容器。
- 按名称删除pod
$ kubectl delete po test-gpu pod "test-gpu" deleted - 使用标签选择器删除pod
$ kubectl delete po -l creation_method=manual pod "mytest-manual" deleted pod "mytest-manual-v2" deleted - 通过删除整个命名空间来删除pod
$ kubectl delete ns custom-namespace namespace "custom-namespace" deleted - 删除命名空间中的所有pod,但保存命名空间
$ kubectl delete po --all - 删除命名空间中的(几乎)所有资源
命令中的第一个all指定正在删除所有资源类型,而--all选项指定将删除所有资源实例$ kubectl delete all --all

浙公网安备 33010602011771号