Kubernetes Pod基础
Kubernetes Pod
介绍Pod
为何需要pod
pod是一组并置的容器, 代表了Kubemetes中的基本构建模块。 在实际应用中我们并不会单独部署容器, 更多的是针对一组pod的容器进行部署和操作。
为何多个容器比单个容器中包含多个进程要好
容器被设计为每个容器只运行一个进程(除非进程本身产生子进程)。 如果在单个容器中运行多个不相关的进程, 那么保持所有进程运行、 管理它们的日志等将会是我们的责任。 例如, 我们需要包含一种在进程崩溃时能够自动重启的机制。 同时这些进程都将记录到相同的标准输出中, 而此时我们将很难确定每个进程分别记
了解pod
由于不能将多个进程聚集在一个单独的容器中, 我们需要另 一种更高级的结构来将容器绑定在一起,并将它们作为一个单元进行管理,这就是 pod 背后的根本原理。在包含容器的 pod 下,我们可以同时运行一些密切相关的进程,并为它们提供(几乎) 相同的环境, 此时这些进程就好像全部运行于单个容器中一样, 同时又保待着一定的隔离。 这样一来, 我们便能全面地利用容器所提供的特性, 同时对这些进程来说它们就像运行在一起一样, 实现两全其美。
同一 pod 中容器之间的部分隔离
Kubemetes 通过配置 Docker 来让一个 pod 内的所有容器共享相同的 Linux 命名空间, 而不是每个容器都有自己的一组命名空间。由千一个 pod 中的所有容器都在相同的 network 和 UTS 命名空间下运行(在这里我们讨论的是 Linux 命名空间), 所以它们都共享相同的主机名和网络接口。 同样地, 这些容器也都在相同的 IPC 命名空间下运行, 因此能够通过 IPC 进行通信。 在最新的 Kubernetes 和 Docker 版本中, 它们也能够共享相同的 PID 命名空间, 但是该特征默认是未激活的。
容器如何共享相同的IP和端口空间
由于一个 pod 中的容器运行于相同的 Network 命名空间中, 因此它们共享相同的 IP 地址和端口空间。 这意味着在同一 pod 中的容器运行的多个进程需要注意不能绑定到相同的端口号, 否则会导致端口冲突, 但这只涉及同-pod 中的容器。 由千每个 pod都有独立的端口空间, 对于不同 pod 中的容器来说则永远不会遇到端口冲突。 此外, 一个 pod 中的所有容器也都具有相同的 loopback网络接口, 因此容器可以通过 localhost 与同一 pod 中的其他容器进行通信。
平坦pod间网络
Kubemetes 集群中的所有 pod 都在同一个共享网络地址空间中(如图 3.2 所示),这意味着每个 pod 都可以通过其他 pod 的 IP 地址来实现相互访问。 换句话说, 这也表示它们之间没有 NAT (网络地址转换) 网关。 当两个 pod 彼此之间发送网络数据包时, 它们都会将对方的实际 IP 地址看作数据包中的源 IP。
pod 之间的通信其实是非常简单的。 不论是将两个 pod 安排在单一的还是不同的工作节点上, 同时不管实际节点间的网络拓扑结构如何, 这些 pod 内的容器都能够像在无 NAT 的平坦网络中一样相互通信, 就像局域网 (LAN) 上的计算机一样。 此时, 每个 pod 都有自己的 IP 地址, 并且可以通过这个专门的网络实现 pod之间互相访问。 这个专门的网络通常是由额外的软件基于真实链路实现的。
通过Pod合理管理容器
将 pod 视为独立的机器, 其中每个机器只托管一个特定的应用。 过去我们习惯于将各种应用程序塞进同一 台主机, 但是 pod 不是这么干的。 由于 pod 比较轻量,我们可以在几乎不导致任何额外开销的前提下拥有尽可能多的 pod。 与将所有内容填充到一个 pod 中不同, 我们应该将应用程序组织到多个 pod 中, 而每个 pod 只包含紧密相关的组件或进程。
将多层应用分散到多个Pod中
如果前端和后端都在同一个容器中, 那么两者将始终在同一 台计算机上运行。如果你有一个双节点 Kubemetes 集群, 而只有一个单独的pod, 那么你将始终只会用一个工作节点, 而不会充分利用第二个节点上的计算资源 (CPU 和内存)。 因此更合理的做法是将pod 拆分到两个工作节点上, 允许 Kubemetes 将前端安排到一个节点, 将后端安排到另 一个节点, 从而提高基础架构的利用率。
基于扩缩容考虑而分割到多个Pod中
通常来说, 前端组件与后端组件具有完全不同的扩缩容需求, 所以我们倾向于分别独立地扩缩它们。更不用说, 像数据库这样的后端服务器, 通常比无状态的前端 web 服务器更难扩展。 因此, 如果你需要单独扩缩容器, 那么这个容器很明确地应该被部署在单独的pod中。
何时在 pod 中使用多个容器
将多个容器添加到单个pod的主要原因是应用可能由 一个主进程和一个或多个辅助进程组成,例如, 中的主容器可以是 个仅仅服务于某个目录中的文件的 服务器,而另 容器(所谓 id 容器) 定期从夕阳 源下载 容并将其存服务器目录中。sidecar 容器的其他例子包括日志轮转器和收集器、数据处理器、通信适配器等。
决定何时在 pod 中使用多个容器
我们需要问自己以下题:
它们需要 起运行还是可以在不同的主机上运行?
它们代表的是 体还是相互独立的组
它们必须一起进行扩缩容还是可 分别进行?
检查现有 pod YAML/Json 描述文件
1.安装bash-completion工具
yum install bash-completion -y
否则报错:
-bash: _get_comp_words_by_ref: command not found
2.执行bash_completion
source /usr/share/bash-completion/bash_completion
3.加载kubectl completion
echo "source <(kubectl completion bash)" >> ~/.bashrc # 在您的 bash shell 中永久的添加自动补全
source ~/.bashrc
4.您还可以为 kubectl 使用一个速记别名,该别名也可以与 completion 一起使用:
alias k=kubectl
apiVersion: v1 //Kubernetes API版本
kind: Pod // 资源类型
metadata: // Pod元数据(名称, 标签和注解等)
annotations:
kubernetes.io/created-by: ...
ereatonTmestamp: 2016-03-l8Tl2:3750Z
generateName: kubia-
labels:
run: kub
name: kubia-zxzij
namespace: default
resourceVersion: "294"
selfLink: /api/v1/anamespaces/default/pods/kubia-zxzij
uid: 3a564dc0-ed06-ll5-ba3b-42010af00004
spec: // pod规格/内容(pod的容器列表, volume)
cotaiers:
- image: luksa/kub
imagePullPolicy: IfNotPresent
name: kubia
ports:
- containerPort: 8080
protocol: TCP
resources:
requests:
cpu: 100m
terminationMessagePath: /dev/termination-log
volumeMounts:
- mountPath: /var/run/secrets/k8s.io/service
name: default-token-kvcqa
readOnly: true
dnsPolicy: ClusterFirst
nodeName: gke-kubia-e8fe08b9-node-txje
restartPolicy: Always
serviceAccount: default
terminationGracePeriodSeconds: 30
volumes:
- name: default-token-kvcqa
secret:
secretName: default-token-kvcqa
status: // pod及其内部容器的详细状态
conditions:
- lastProbeTime: null
lastTransitionTime: null
status: "True"
type: Ready
containerStatuses:
- containerID: docker://f0232
image: luksa/kubia
imageID: docker://4cafdaf
lastState: {}
name: kubia
ready: true
restartCount: 0
state:
running:
starteAt: 2016-03-18T12:46:05Z
hostIP: 10.132.0.4
phase: Running
podIP: 10.0.2.3
startTime: 2016-03-18T12:44:05Z
kubectl 创建及查看pod(yaml)
- 创建:
- 快速创建deployments:
kubectl create deployment kubia-manual --image=luksa/kubia -o yaml>kubia-manual.yaml
- 通过yaml文件:
kubectl create -f kubia-manual.yaml
- 创建并更新:
kubeclt apply -f kubia-manual.yaml
- 快速创建deployments:
- 查看
kubectl get po kubia-manual -o yaml
kubectl get po kubia-manual -o json
- 使用 kubectl logs 命令获取 pod 日志
kubectl logs kubia-manual
- 获取多容器 pod 的日志时指定容器名称
kubectl logs kubia-manual -c kubia
向pod发送请求
在实际操作中看到该状态
- 将本地网络端口转发到 pod 中的端口
- 将机器的本地端口 8888转发到我们的kubia-manual pod的端口8080:
kubect1 port-forward kubia-manual 8888:8080
- 将机器的本地端口 8888转发到我们的kubia-manual pod的端口8080:
- 通过端口转发连接到 pod
curl localhost:8888
通过标签选择器列出pod子集
介绍标签
标签是一种简单却功能强大的Kubemetes特性, 不仅可以组织pod, 也可以组织所有其他的Kubemetes资源。 详细来讲, 标签是可以附加到资源的任意键值对,用以选择具有该确切标签的资源(这是通过标答选择器完成的 )。 只要标签的key在资源内是唯一的, 一个资源便可以拥有多个标签。 通常在我们创建资源时就会将标签附加到资源上,但之后我们也可以在添加其他标签, 或者修改现有标签的值, 无须重新创建资源。
创建pod时指定标签
apiVersion: vl
kind: Pod
metadata:
name: kubia-manual-v2
labels:
creation method: manual
env: prod
spec:
containers:
- image: luksa/kubia
name: kubia
ports:
- containerPort: 8080
protocol: TCP
查看标签: kubectl get pod --show-labels
特定标签: kubectl get pod -L create_method, env
修改现有pod的标签
添加: kubectl label pod kubia-manual creation_method=manual
修改: kubectl label pod kubia-manual env=debug --overwrite
通过标签的选择pod
- creation_rnethod!=rnanual 选择带有creation_rnethod标签, 并且值不等于manual的pod
- env in (prod, devel)选择带有env标签且值为prod或devel的pod
- env notin (prod, devel)选择带有env标签, 但其值不是prod或devel的pod
使用标签选择器将Pod调度到特定节点: kubia-gpu.yaml
apiVersion: vl
kind: Pod
metadata:
name: kubia-gpu
spec:
nodeSelector.
gpU: "true"
containers:
- image: luksa/kubia
name: kubia
注解
概念: 注解也是键值对,所以它们本质上与标签非常相似。但与标签不同,注解并不是为了保存标识信息而 存在的,它们不能像标签 一 样用千对对象进行分组。注解 可以容纳更多的信息,并且主要用于工具使用。Kubemetes也会将一些注解自动添加到对象,但 其他的注解则需要由用户手动添加。
好处: 大量使用注解可以为每个pod或其他API对象添加说明,以便每个使用该集群的入都可以快速查找有关每个
单独对象的信息。
添加和修改注解:kubect1 annotate pod kubia-manual mycompany.com/someannotation="foo bar"
命名空间
创建命名空间: kubectl creat ns custom-namespace
删除整个命名空间来删除 pod: kubectl delete ns custom-namespace
删除当前命名空间中的所有pod: kubectl delete pod --all
查看Kubernetes资源信息:kubectl explain