一、pod介绍
一个pod是一组紧密相关的容器,它们总是一起运行在同一个工作节点上,以及同一个Linux命名空间中。每个pod就像一个独立的逻辑机器,拥有自己的IP、主机名、进程等,运行一个独立的应用程序。应用程序可以是单个进程,运行在单个容器中,也可以是一个主应用进程或者其他支持进程,每个进程都在自己的容器中运行。、
一个pod绝不会跨越多个工作节点
一个pod的所有容器都运行在同一个逻辑机器上,而其他pod中的容器,即使运行在同一个工作节点上,也会出现在不同的节点上。
多个容器比单个容器中包含多个进程要好
容器被设计为每个容器只运行一个进程(除非进程本身产生子进程)。如果在单个容器中运行多个不相关的进程,那么保持所有进程运行、管理它们的日志等将很困难。
由于不能将多个进程聚集在一个单独的容器中,所以需要另一种更高级的结构来将容器绑定在一起,并将它们作为一个单元进行管理,这就是pod背后的根本原理。
在包含容器的pod下,我们可以同时运行一些密切相关的进程,并为它们提供(几乎)相同的环境,此时这些进程就好像全部运行于单个容器中一样,同时又保持着一定的隔离。这样一来,我们便能全面地利用容器所提供的特性,同时对这些进程来说它们就像运行在一起一样,实现两全其美。
同一pod中容器之间的部分隔离
期望隔离容器组,而不是单个容器,并让每个容器组内的容器共享一些资源,而不是全部(换句话说,没有完全隔离)。Kubernetes通过配置Docker来让一个pod内的所有容器共享相同的Linux命名空间,而不是每个容器都有自己的一组命名空间。
容器如何共享相同的IP和端口空间
由于一个pod中的容器运行于相同的Network命名空间中,因此它们共享相同的IP地址和端口空间。这意味着在同一pod中的容器运行的多个进程需要注意不能绑定到相同的端口号,否则会导致端口冲突,但这只涉及同一pod中的容器。由于每个pod都有独立的端口空间,对于不同pod中的容器来说则永远不会遇到端口冲突。
将多层应用分散到多个pod中
不应该将应用程序都放到单一pod中的原因就是扩缩容。pod也是扩缩容的基本单位,对于Kubernetes来说,它不能横向扩缩单个容器,只能扩缩整个pod。
何时在pod中使用多个容器
将多个容器添加到单个pod的主要原因是应用可能由一个主进程和一个或多个辅助进程组成。
总结:pod是逻辑主机,其行为与非容器世界中的物理主机或虚拟机非常相似。此外,运行在同一个pod中的进程与运行在同一物理机或虚拟机上的进程相似,只是每个进程都封装在一个容器之中。
二、以YAML或JSON描述文件创建pod
pod和其他Kubernetes资源通常是通过向Kubernetes RESTAPI提供JSON或YAML描述文件来创建的。此外还有其他更简单的创建资源的方法,比如使用kubect1 run
命令,但这些方法通常只允许配置一组有限的属性。另外,通过YAML文件定义所有的Kubernetes对象之后,还可以将它们存储在版本控制系统中,充分利用版本控制所带来的便利性。
检查现有pod的YAML描述文件
$ kubect1 get po kubia-zxzij -o yaml
为pod创建一个简单的YAML描述文件
apiVersion:v1 #描述文件遵循v1版本的Kubernetes API
kind:pod #说明在描述一个pod
metadata:
name:kubia-manual-v2 #pod的名称
spec:
containers:
-image:luksa/kubia #创建容器所用的镜像
name:kubia #容器的名称
ports:
-containerPort:8080 #应用监听的端口
protocol:TCP
使用kubectl create
来创建 pod
使用kubectl create
命令从YAML文件创建pod:
$ kubectl create -f kubia-manual.yaml
kubect1 create -f
命令用于从YAML或JSON文件创建任何资源(不只是pod)。
得到运行中pod的完整定义
$ kubect1 get po kubia-manual -o yaml
也可以让kubect1返回JSON格式而不是YAML格式(即使使用YAML创建pod,同样也可以获取JSON格式的描述文件)
$ kubect1 get po kubia-manual -o json
在pod列表中查看新创建的pod
$ kubectl get pods
查看应用程序日志
使用ssh命令登录到pod正在运行的节点,并使用docker logs命令查看其日志。(有点麻烦)
$ docker logs <container id>
Kubernetes提供了一种更为简单的方法。
$ kubectl logs kubia-manual
获取多容器pod的日志时指定容器名称
$ kubectl logs kubia-manual -c kubia
向pod发送请求
将本地网络端口转发到pod中的端口
如果想要在不通过service的情况下与某个特定的pod进行通信(出于调试或其他原因),Kubernetes将允许我们配置端口转发到该pod。可以通过kubect1 port-forward
命令完成上述操作。例如以下命令会将机器的本地端口8888转发到我们的kubia-manual
pod的端口8080:
$ kubectl port-forward kubia-manual 8888:8080
此时端口转发正在运行,可以通过本地端口连接到我们的pod。
通过端口转发连接到pod
在另一个终端中,通过运行在localhost:8888
上的kubectl port-forward
代理,可以使用cur1
命令向pod发送一个HTTP请求:
$ curl localhost:8888
三、使用标签组织pod
标签是可以附加到资源的任意键值对,用以选择具有该确切标签的资源(这是通过标签选择器完成的)。只要标签的key在资源内是唯一的,一个资源便可以拥有多个标签。
创建一个名为kubia-manual-with-labels.yaml的新文件。
apiVersion:v1 #描述文件遵循v1版本的Kubernetes API
kind:pod #说明在描述一个pod
metadata:
name:kubia-manual #pod的名称
labels:
creation_method:manual #两个标签被附加到pod上
env:prod
spec:
containers:
-image:luksa/kubia #创建容器所用的镜像
name:kubia #容器的名称
ports:
-containerPort:8080 #应用监听的端口
protocol:TCP
kubect1 get pods
命令默认不会列出任何标签,但我们可以使用--show-labels
选项来查看:
$ kubectl get po --show-labels
如果只对某些标签感兴趣,可以使用-L
选项指定它们并将它们分别显示在自己的列中,而不是列出所有标签。
$ kubectl get po -L creation_method,env
修改现有pod的标签
标签也可以在现有pod上进行添加和修改。由于pod kubia-manual
也是手动创建的,所以为其添加creation_method=manual
标签:
$ kubectl label po kubia-manual creation_method=manual
更改现有标签时,需要使用--overwrite
选项。
$ kubectl label po kubia-manual-v2 env=debug --overwrite
四、通过标签选择器列出pod子集
使用标签选择器列出pod:
$ kubectl get po -l creation method=manual
列出包含env
标签的所有pod,无论其值如何:
$ kubectl get po -l env
列出没有env
标签的pod:
$ kubectl get po -l '!env'
五、使用标签和选择器来约束pod调度
使用标签分类工作节点
假设集群中的一个节点刚添加完成,它包含一个用于通用GPU计算的GPU。希望向节点添加标签来展示这个功能特性,可以通过将标签gpu=true
添加到其中一个节点来实现(只需从kubect1 get nodes
返回的列表中选择一个):
$ kubectl label node gke-kubia-85f6-node-0rrx gpu=true
将pod调度到特定节点
假设我们想部署一个需要GPU来执行其工作的新pod。为了让调度器只在提供适当GPU的节点中进行选择,我们需要在pod的YAML文件中添加一个节点选择器。使用以下代码清单中的内容创建一个名为kubia-gpu.yaml的文件,然后使用kubect1 create -f kubia-gpu.yaml
命令创建该pod。
apiVersion:v1
kind:Pod
metadata:
name:kubia-gpu
spec:
nodeSelector:
gpu:"true" #节点选择器要求Kubernetes只将pod部署到包含标签gpu=true的节点上
containers:
-image:luksa/kubia
name:kubia
六、注解pod
添加和修改注解
$ kubectl annotate pod kubia-manual mycompany.com/someannotation="foo bar"
七、使用命名空间对资源进行分组
列出集群中的所有命名空间:
$ kubectl get ns
使用kubect1命令指定命名空间来列出只属于该命名空间的pod:
$ kubectl get po --namespace kube-system
可以使用-n
来代替--namespace
创建一个命名空间
从YAML文件创建命名空间
apiVersion:v1
kind:Namespace
metadata:
name:custom-namespace #这是命名空间的名称
使用kubect1将文件提交到Kubernetes API服务器:
$ kubectl create -f custom-namespace.yaml
使用kubectl create namespace
命令创建命名空间
$ kubectl create namespace custom-namespace
管理其他命名空间中的对象
如果想要在刚创建的命名空间中创建资源,可以选择在metadata
字段中添加一个namespace:custom-namespace
属性,也可以在使用kubectl create
命令创建资源时指定命名空间:
$ kubectl create -f kubia-manual.yaml -n custom-namespace
八、停止和移除pod
按名称删除pod
$ kubectl delete po kubia-gpu
还可以通过指定多个空格分隔的名称来删除多个pod
使用标签选择器删除 pod
$ kubectl delete po -l creation_method=manual
通过删除整个命名空间来删除pod
$ kubectl delete ns custom-namespace
删除命名空间中的所有pod,但保留命名空间
$ kubectl delete po --all
会保留一些备份---ReplicationCcontroller
删除命名空间中的(几乎)所有资源
通过使用单个命令删除当前命名空间中的所有资源,可以删除ReplicationCcontroller
和pod,以及我们创建的所有service:
$ kubectl delete all --al1
命令中的第一个all
指定正在删除所有资源类型,而--a11
选项指定将删除所有资源实例,而不是按名称指定它们。