pod是一组并置的容器,一个pod总是要包含多个容器或者单个。一个pod中的所有容器都在相同的network和 UTS命名空间下运行,所以它们都共享相同的主机名和网络接口。同样地,这些容器也都在相同的IPC(进程间通信)命名空间下运行,因此能够通过IPC进行通信。由于一个 pod 中的容器运行于相同的Network命名空间
中, 因此它们共享相同的IP地址和端口空间。这意味着在同一pod中的容器运行的多个进程需要注意不能绑定到相同的端口号,否则会导致端口冲突.
Kubemetes 集群中的所有 pod 都在同一个共享网络地址空间中,这意味着每个pod都可以通过其他pod的IP 地址来实现相互访问。
不管实际节点间的网络拓扑结构如何,这些
pod内的容器都能够像在无NAT的平坦网络中一样相互通信,就像局域网 (LAN) 上的计算机一样。
通过POD管理容器。
使用多个容器
将多个容器添加到单个pod的主要原因是应用可能由一个主进程和一个或多个辅助进程组成。
例如,
pod中的主容器可以是个仅仅服务于某个目录中的文件的服务器,而另一个容器(所谓sidecar容器)则定期从外部资源下载内容,并将其存储在Web服务器的目录中。
用YAML描述文件创建POD
首先是YAML中使用的Kubernetes API版本和YAML描述的资源类型;其次是几乎在所有Kubernetes资源中都可以找到的三大重要部分:
- metadata 包括名称、命名空间、标签和关于该容器的其它信息。
- spec 包含pod内容的实际说明,例如pod的容器、卷和其他数据。
- status 包含运行中的pod的当前信息,例如pod所处的条件、每个容器的描述和状态,以及内部IP和其他基本信息。
apiVersion: v1 #遵循v1接口
kind: Pod #描述类型是pod
metadata:
name: kubia-manual #pod的名称
spec: #描述pod
containers:
- image: luksa/kubia #所使用的镜像
name: kubia #容器名称
ports:
- containerPort: 8080 #应用监听的端口
protocol: TCP
命令的基本使用
创建pod
kubectl create -f kubia-manual.yaml
kubectl create -f 命令用于从 YAML 或 JSON 文件创建任何资源
得到pod的完整定义
kubectl get po kubia-manual -o yaml
查看新创建的pod
kubectl get pods
查看应用程序日志
kubectl logs kubia-manual
如果pod包含多个容器,则在运行kubectl logs命令时,需要通过 -c <容器名称>来显式指定容器。
向pod发送请求
kubectl port-forward kubia-manual 8888:8080
此时端口转发正在运行,可以通过本地端口连接到我们的pod。在另一个终端中,运行命令curl localhost:8888得到返回结果。
使用标签组织pod
标签是可以附加到资源的任意键值对,用以选择具有该确切标签的资源(这是通过标答选择器完成的 )。只要标签的key在资源内是唯一的,一个资源便可以拥有多个标签。通过给这些pod添加标签,可以得到一个更组织化的系统。
如图,此时每个pod都标有两个标签:
- app, 它指定pod属于哪个应用、 组件或微服务。
- rel, 它显示在pod中运行的应用程序版本是stable、beta还是canary。
金丝雀发布:指在部署新版本时, 先只让一 小部分用户体验新版本以观察新版本的表现, 然后再向所有用户进行推广, 这样可以防止暴露有问题的版本给过多的用户。
- 为新版本应用程序创建一个新的Deployment对象,并为其添加一个新的标签,例如"app-version: v2"。
- 使用旧版本应用程序的Deployment对象的标签选择器(例如"app-version: v1")创建一个新的Service对象。这将确保只有旧版本应用程序接收到流量。
- 创建一个新的Ingress对象,将流量路由到旧版本应用程序的Service对象。
- 逐步修改Ingress对象的规则,将一部分流量引导到新版本应用程序的Service对象。可以使用不同的标签选择器来选择新版本应用程序的Pod。
创建pod时指定标签
kubia-manual-with-labels.yaml
apiVersion: v1
kind: Pod
metadata:
name: kubia-manual-v2
lables:
creation_method: manual
env: prod
spec:
containers:
- image: liksa/kubia
name: kubia
ports:
- containerPort: 8080
protocol: TCP
metadata.labels 部分已经包含了creation_method=manual和env=prod标签。现在来创建该 pod:
kubectl create -f kubia-manual-with-labels.yaml
可以使用--show-labels(-L)选项来查看:
kubectl get po --show-labels
修改现有的pod的标签
将pod上的env=prod标签更改为env=debug
kubecl label po {{container name}} env=debug --overwrite
通过标签选择器列出pod子集
标签要与标签选择器结合在一起。标签选择器允许我们选择标记有特定标签的pod子集,并对这些pod执行操作。可以说标签选择器是一种能够根据是否包含具有特定值的特定标签来过滤资源的准则。
使用标签选择器列出pod
列出creation—rnethod=manual的pod列表
kubectl get po -l creation_method=manual
列出包含env标签的pod列表:
kubectl get po -l env
列出不包含env标签的pod列表:
kubectl get po -l '!env'
使用标签和选择器来约束pod调度
我们创建的所有pod都是近乎随机地调度到工作节点上的。正如前一章我们所提到的,这恰恰是在Kubemetes集群中工作的正确方式。由于Kubernetes将集群中的所有节点抽象为一个整体的大型部署平台,因此对于你的pod实际调度到哪个节点而言是无关紧要的。如果你想对一个pod应该调度到哪里拥有发言权,应该用某种方式描述对节点的需求, 使Kubernetes选择一个符合这些需求的节点。
使用标签分类工作节点
假设我们集群中的一个节点刚添加完成,它包含一个用于通用GPU计算的GPU。我们希望向节点添加标签来展示这个功能特性,可以通过将标签gpu=true添加到其中一个节点来实现。
kubectl label node {{node name}} gpu=true
现在我们可以在列出节点时使用标签选择器,就像之前操作pod一样,列出只包含标签gpu=true的节点:
kubectl get nodes -l gpu=true
将pod调度到特定节点
kubia-gpu.yaml
apiVersion: v1
kind: Pod
metadata:
name: kubia-gpu
spec:
nodeSelector:
gpu: "true"
containers:
- image: luksa/kubia
name: kubia
我们只是在spec部分添加了一个nodeSelector字段。当我们创建该pod时,调度器将只在包含标签gpu=true的节点中选择
同样地,我们也可以将pod调度到某个确定的节点,由于每个节点都有一个唯一标签,其中键为kubernetes.io/hostname, 值为该节点的实际主机名,因此我们也可以将pod调度到某个确定的节点。但如果节点处于离线状态,通过hostname标签将nodeSelector设置为特定节点可能会导致pod不可调度。
注解pod
除标签外,pod和其他对象还可以包含庄解。注解也是键值对,所以它们本质上与标签非常相似。但与标签不同,注解并不是为了保存标识信息而存在的,它们不能像标签一样用于对对象进行分组。当我们可以通过标签选择器选择对象时,就不存在注解选择器这样的东西。 向Kubernetes引入新特性时,通常也会使用注解。使用注解可以为每个pod或其他API对象添加说明。例如,指定创建对象的人员姓名的注解可以使在集群中工作的人员之间的协作更加便利。
查找对象的人注解
kubectl get po kubia-zxzij -o yaml
kubernetes.io/created-by注解保存了创建该pod的对象的一些JSON数据,而没有涉及太多细节,因此注解并不会是我们想要放入标签的东西。相对而言,标签应该简短一些,而注解则可以包含相对更多的数据(总共不超过256KB)。
添加和修改注解
执行命令,将注解mycompany.com/someannotation添加为值foo bar
kubectl annotate pod kubia-manual mycompany.com/someannotation="foo bar"
使用命名空间对资源分组
Kubernetes也能将对象分组到命名空间中。这与用于相互隔离进程的Linux命名空间不一样(Linux命名空间是Linux内核提供的一种机制,用于隔离和限制进程在不同命名空间中的资源访问),Kubernetes命名空间简单地为对象名称提供了一个作用域。此时我们并不会将所有资源都放在同一个命名空间中,而是将它们组织到多个命名空间中,这样可以允许我们多次使用相同的资源名称(跨不同的命名空间)。
在使用多个namespace的前提下,我们可以将包含大量组件的复杂系统拆分为更小的不同组,这些不同组也可以用于在多租户环境中分配资源,将资源分配为生产、开发和QA环境,或者以其他任何你需要的方式分配资源。资源名称只需在命名空间内保持唯一即可,因此两个不同的命名空间可以包含同名的资源。
列出明明空间的pod
如下所示为属于 kube-system 命名空间的 pod:
kubectl get po --namespace kube-system
提示也可以使用 -n 来代替 --namespace , 一般没有指定namespace时,默认返回 default 的命名空间数据。
创建一个命名空间
custom-namespace.yaml:
apiVersion: v1
kind: Namespace
metadata:
name: custom-namespace
使用kubectl将文件提交到Kubernetes API服务器
kubectl create - f custom-namespace.yaml
不过一般来说,更建议使用以下命令创建命名空间:
kubectl create namespace custom-namespace
管理命名空间中的对象
如果想要在刚创建的命名空间中创建资源,可以选择在metadata字段中添加一个namespace: custom-namespace 属性,或者使用命令
kubectl create -f kubia-manual.yaml -n custom-namespace
在列出、描述、修改或删除其他命名空间中的对象时,需要给kubectl命令传递 --namespace(或 -n)选项。
要想快速切换到不同的命名空间,可以设置以下别名: alias kcd=’kubectl config set context $(kubectl config current-context) --namespace’。然后,可以使用 kcd some-namespace 在命名空 间之间进行切换。
含义:获取当前上下文,然后设置该上下文的默认命名空间为
<namespace>
命名空间提供的隔离
尽管命名空间将对象分隔到不同的组,只允许你对属于特定命名空间的对象进行操作,但实际上命名空间之间并不提供对正在运行的对象的任何隔离。 你可能会认为当不同的用户在不同的命名空间中部署 pod 时,这些 pod 应该彼此隔离,并且无法通信,但事实却并非如此。命名空间之间是否提供网络隔离取决于 Kubernetes 所使用的网络解决方案。当该解决方案不提供命名空间间的网络隔离时,如果命名空间foo中的某个pod知道命名空间bar中pod的IP地址,那它就可以将流量(例如HTTP请求)发送到另一个pod。
停止和移除pod
按名称删除pod
kubectl delete po {{name}}
删除pod的过程中,实际上我们在指示Kubernetes终止该pod中的所有容器。Kubernetes向进程发送一个 SIGTERM信号并等待一定的秒数(默认为30),使其正常关闭。如果它没有及时关闭,则通过SIGKILL终止该进程 。因此,为了确保你的进程总是正常关闭,进程需要正确处理SIGTERM信号。
还可以通过指定多个空格分隔的名称来删除多个 pod (例如 : kubectl delete po podl pod2)。
使用标签选择器删除 pod
通过指定rel=canary标签选择器,可以一次删除所有设置了该标签的pod:
kubectl delete po -l rel=canary
删除整个命名空间来删除pod
kubectl delete ns custom-namespace
删除命名空间中的所有pod,但保留命名空间
kubectl delete po --all
如果是通过
ReplicationCcontroller创建的pod,需要先删除ReplicationCcontroller
删除命名空间中(几乎)所有资源
kubectl delete all --all
小结
- 决定是否应将某些容器组合在一个pod中。
- pod 可以运行多个进程, 这和非容器世界中的物理主机类似。
- 可以编写 YAML 或 JSON 描述文件用于创建
pod, 然后查看pod的规格及其当前状态。 - 使用标签来组织pod, 并且一次在多个 pod 上执行操作。
- 可以使用节点标签将pod只调度到提供某些指定特性的节点上。
- 注解允许人们、工具或库将更大的数据块附加到 pod。
- 命名空间可用于允许不同团队使用同一集群,就像它们使用单独的Kuberetes集群一样。
- 使用
kubectl explain命令快速查看任何Kubernetes资源的信息。