标签:离线 role let 介绍 属性 世界 网络 bug strong
P53
pod 是 Kubernetes 中最为重要的核心概念,而其他对象仅仅用于 pod 管理、 pod 暴露或被 pod 使用。 pod 是一组并置的容器,代表了 Kubernetes 中的基本构建模块。 P53
当一个 pod 包含多个容器时,这些容器总是运行于同一个工作节点上——一个 pod 绝不会跨越多个工作节点。 P54
P54
为何多个容器比单个容器中包含多个进程要好 P54
假设一个由多个进程组成的应用程序,无论是通过 IPC (进程间通信)还是本地存储文件进行通信,都要求它们运行于同一台机器上。如果在单个容器中运行多个不相关的进程,那么保持所有进程运行、管理它们的日志等将会是我们的责任。例如,我们需要包含一种在进程奔溃时能够自动重启的机制;同时这些进程都将记录到相同的标准输出中,而此时我们将很难确定每个进程分别记录了什么。 P54
P55
由于不能将多个进程聚集在一个单独的容器中,我们需要另一种更高级的结构来将容器绑定在一起,并将它们作为一个单元进行管理,这就是 pod 背后的真正原因。 P55
在包含容器的 pod 下,我们可以同时运行一些密切相关的进程,并为它们提供(几乎)相同的环境,此时这些进程就好像全部运行于单个容器中一样,同时又保持着一定的距离。这样一来,我们便能全面地利用容器所提供的特性,同时对这些进程来说它们就像运行在一起一样。 P55
同一 pod 中容器之间的部分隔离 P55
Kubernetes 通过配置 Docker 来让一个 pod 内的所有容器共享相同的 Linux 命名空间,而不是每个容器都有自己的一组命名空间。 P55
由于一个 pod 中的所有容器都在相同的 Network 和 UTS 命名空间下运行(01. Kubernetes 介绍),所以它们都共享相同的主机名和网络接口。同样地,这些容器也都在相同的 IPC 命名空间下运行,因此能够通过 IPC 进行通信。在最新的 Kubernetes 和 Docker 版本中,它们也能够共享相同的 PID 命名空间,但是该特性默认未开启。 P55
注意:当一个 pod 中的容器使用单独的 PID 命名空间时,在容器中执行 ps aux 就只会看到容器自己的进程。 P55
由于大多数容器的文件系统来自容器镜像,因此默认情况下,每个容器的文件系统与其他容器完全隔离。但我们可以使用名为 Volume
的 Kubernetes 资源来共享文件目录。 P55
容器如何共享相同的 IP 和端口空间 P55
由于同一个 pod 中的容器运行于相同的 Network 命名空间中,因此在同一个 pod 中的容器运行的多个进程需要注意不能绑定到相同的端口号,否则会导致端口冲突。同一个 pod 中的所有容器具有相同的 loopback 网络接口,因此容器可以通过 localhost
与同一 pod 中的其他容器进行通信。 P55
由于每个 pod 都有独立的端口空间,对于不同 pod 中的容器来说则永远不会遇到端口冲突。 P55
介绍扁平化 pod 间网络 P56
Kubernetes 集群中的所有 pod 都在同一个共享网络地址空间中,每个 pod 都可以通过其他 pod 的 IP 地址来实现相互访问,即这些 pod 之间没有 NAT (网络地址转换)网关。当两个 pod 彼此之间发送网络数据包时,它们都会将对方的实际 IP 地址看作数据包中的源 IP 。 P56
总结: pod 是逻辑主机,其行为与非容器世界中的物理主机或虚拟机非常相似。运行在同一个 pod 中的进程与运行在同一物理机或虚拟机上的进程相似,只是每个进程都封装在一个容器之中。 P56
P56
P57
P57
P57
P58
P58
通过 YAML 文件定义所有的 Kubernetes 对象之后,还可以将它们存储在版本控制系统中,充分利用版本控制所带来的便利性。 P59
P59
kubectl get pod -o yam <pod-name>
命令可以查看指定 pod 的完整 YAML 定义。 P59
介绍 pod 定义的主要部分 P59
P61
# 遵循 v1 版本的 Kubernetes API
apiVersion: v1
# 资源类型为 Pod
kind: Pod
metadata:
# pod 的名称
name: kubia-manual
spec:
containers:
# 创建容器所使用的镜像
- image: idealism/kubia
# 容器的名称
name: kubia
ports:
# 应用监听的端口
- containerPort: 8080
protocol: TCP
指定容器端口 P61
在 pod 定义中的端口仅仅是展示性的 (informational) ,忽略它们不影响客户端通过端口连接到 pod 。如果容器通过绑定到地址 0.0.0.0
的端口接受连接,那么即使端口未明确列出在 pod spec 中,其他 pod 也依旧能够连接到该端口。 P61
明确定义端口的意义: P62
可以使用 kubectl explain
发现可用的 API 对象字段, kubectl explain pod
可以查看 pod 的 各个属性,然后通过选择对应的属性 (kubectl explain pod.spec
) 深入了解每个属性的更多信息。 P62
kubectl create
来创建 pod P63
# kubectl create -f 可以从 YAML 或 JSON 文件创建任何资源,不仅仅是 pod
kubectl create -f kubia-manual.yaml
# 查看刚刚创建的 kubia-manual 的 完整描述文件
kubectl get pod kubia-manual -o yaml
P64
容器化的应用程序通常会将日志记录到标准输出和标准错误流,而不是写入文件,这就允许用户可以通过简单、标准的方式查看不同应用程序的日志。 P64
docker logs <container>
允许我们查看主机上指定容器的日志kubectl logs <pod-name> -c <container>
允许我们查看指定 pod 中指定容器的日志,如果该 pod 只包含一个容器,那么 -c <container>
可以省略当一个 pod 被删除时,它的日志也会被删除。如果希望在 pod 删除之后仍然可以获取其日志,我们需要设置中心化的、集群范围的日志系统,将所有日志存储到中央存储中。 P64
P65
将本地网络端口转发到 pod 中到端口 P65
kubectl port-forward kubia-manual 8888:8080
可以将本地端口 8888 转发到 kubia-manual
pod 到端口 8080 ,这样我们就可以在本地使用 curl localhost:8888
向 pod 发送一个 HTTP 请求。 P65
P66
微服务架构下可能会部署很多组件,这些组件可能是副本(部署同一组件的多个副本)和多个不同的发布版本(stable, beta, canary 等)同时运行,系统中可能拥有数百个 pod ,如果没有可以有效组织这些组件的机制,将会导致巨大的混乱。 P66
P66
标签是一种简单却功能强大的 Kubernetes 特性,不仅可以组织 pod ,还可以组织所有其他的 Kubernetes 资源。标签是可以附加到资源的任意键值对,用以选择具有该确切标签的资源(通过标签选择器完成)。只要标签的 key 在资源内是唯一的,一个资源便可以拥有多个标签。通常在我们创建资源时就会将标签附加到资源上,但之后我们也可以再添加其他标签,或者修改现有标签的值,而无须重新创建资源。 P67
我们以图 3.6 中的微服务为例,通过给这些 pod 添加标签,可以得到一个更组织化的系统,以便我们理解。此时每个 pod 都标有两个标签: P67
app
: 基于应用的横向纬度,指定 pod 属于哪一个应用、组件或微服务rel
: 基于版本的纵向纬度,显示在 pod 中运行的应用程序版本 (stable, beta, canary)
P67
基于 kubia-manual.yaml
创建一个新的描述文件 kubia-manual-with-labels.yaml
,并添加 metadata.labels
属性,指定 creation_method=manual
和 env=prod
标签。
# 遵循 v1 版本的 Kubernetes API
apiVersion: v1
# 资源类型为 Pod
kind: Pod
metadata:
# pod 的名称
name: kubia-manual-v2
# pod 的标签
labels:
creation_method: manual
env: prod
spec:
containers:
# 创建容器所使用的镜像
- image: idealism/kubia
# 容器的名称
name: kubia
ports:
# 应用监听的端口
- containerPort: 8080
protocol: TCP
kubectl create -f kubia-manual-with-labels.yaml
: 创建一个新 podkubectl get pods --show-labels
: 查看所有 pod 并列出全部标签NAME READY STATUS RESTARTS AGE LABELS
kubia-manual 1/1 Running 0 79m <none>
kubia-manual-v2 1/1 Running 0 3m11s creation_method=manual,env=prod
kubectl get pods -L creation_method -L env
: 查看所有 pod 并列出指定标签,每个标签自成一列NAME READY STATUS RESTARTS AGE CREATION_METHOD ENV
kubia-manual 1/1 Running 0 84m
kubia-manual-v2 1/1 Running 0 7m35s manual prod
P68
kubectl label pod kubia-manual creation_method=manual
: 对 kubia-manual
pod 添加 creation_method=manual
标签kubectl label pod kubia-manual-v2 env=debug --overwrite
: 将 kubia-manual-v2
pod 的 env=prod
标签更改为 env=debug
--overwrite
选项kubectl get pods -L env,creation_method
: 查看所有 pod 并列出指定标签,每个标签自成一列NAME READY STATUS RESTARTS AGE ENV CREATION_METHOD
kubia-manual 1/1 Running 0 90m manual
kubia-manual-v2 1/1 Running 0 13m debug manual
P69
标签选择器允许我们选择标记有特定标签的 pod 子集,并对这些 pod 执行操作,它可以根据资源的以下条件来选择资源: P68
P69
kubectl get pods -l creation_method=manual
: 列出包含 creation_method=manual
标签的所有 podkubectl get pods -l env
: 列出有 env
标签的所有 pod ,无论其值为如何kubectl get pods -l ‘!env‘
: 列出没有 env
标签的所有 podkubectl get pods -l creation_method!=manual
: 列出有 creation_method
标签但其值不等于 manual
的所有 podkubectl get pods -l ‘env in (debug, prod)‘
: 列出有 env
标签并且其值为 debug
或 prod
的所有 podkubectl get pods -l ‘env notin (debug, prod)‘
: 列出没有 env
标签,或者有 env
标签并且其值不为 debug
和 prod
的所有 pod使用标签选择器 app=pc
选择前面所述示例中属于 product catalog
微服务的所有 pod 。 P70
P71
kubectl get pods -l creation_method=manual -l env=debug
: 列出包含 creation_method=manual
标签和 env=debug
标签的所有 podkubectl get pods -l ‘creation_method=manual, env in (debug, prod)‘
: 列出包含 creation_method=manual
标签,且含有 env
标签并且其值为 debug
或 prod
的所有 pod使用标签选择器 app=pc,rel=beta
选择前面所述示例中属于 product catalog
微服务的 beta 版本所有 pod 。 P71
P71
某些情况下,我们希望对将 pod 调度到何处持有一定发言权,例如:硬件基础设施不同质。 P71
这种情况下,我们应该用某种方式描述对节点的需求,使 Kubernetes 选择一个符合这些需求的节点,这恰好可以通过节点标签和节点标签选择器完成。 P72
P72
向集群添加新节点时,可以通过附加标签来对节点进行分类,这些标签指定节点提供对硬件类型,或者任何调度 pod 时能提供便利对其他信息。 P72
kubectl label node minikube-m02 gpu=true
: 给节点 minikube-m02
添加 gpu=true
标签(在 02. 开始使用 Kubernetes 和 Docker 中已使用该命令给工作节点打上标签角色标签,使其 ROLES
设置为 worker
)
kubectl get nodes -l gpu=true
: 列出包含 gpu=true
标签的所有节点
P72
基于 kubia-manual-gpu.yaml
创建一个新的描述文件 kubia-manual-gpu.yaml
,并添加 spec.nodeSelector
属性,指定选择的标签为 gpu=true
。这样当我们创建该 pod 时,调度器将只在包含标签 gpu=true
的节点中选择。 P73
# 遵循 v1 版本的 Kubernetes API
apiVersion: v1
# 资源类型为 Pod
kind: Pod
metadata:
# pod 的名称
name: kubia-manual-gpu
# pod 的标签
labels:
creation_method: manual
env: prod
spec:
# 节点选择器
nodeSelector:
# 选择的标签
gpu: "true"
containers:
# 创建容器所使用的镜像
- image: idealism/kubia
# 容器的名称
name: kubia
ports:
# 应用监听的端口
- containerPort: 8080
protocol: TCP
P73
我们也可以将 pod 调度到某个确定的节点,由于每个节点都有一个唯一标签 kubernetes.io/hostname
,值为该节点的实际主机名,因此我们也可以将 pod 调度到某个确定的节点。但如果节点处于离线状态,那么可能会导致 pod 不可调度。我们绝不应该考虑单个节点,而是应该通过标签选择器考虑符合特定标准但逻辑节点组。 P73
P73
注解也是键值对,本质上与标签非常相似。 P73
P74
我们可以通过 kubectl get pod <pod-name> -o yaml
或者 kubectl describe pod <pod-name>
查看 pod 的详细信息,在其中就会看到对应的注解。
P75
kubectl annotate pod kubia-manual-gpu idealism/annotation=‘gpu required‘
: 对 pod kubia-manual-gpu
添加或修改注解 idealism/annotation
的值为 gpu required
。 P74
使用前缀格式的注解键来避免键冲突是一个好方法,可以防止其他工具或库意外地覆盖自己的注解。 P75
P75
Kubernetes 命名空间简单地为对象名称提供了一个作用域。此时我们并不会将所有资源都放在同一个命名空间中,而是将它们组织到多个命名空间中,这样可以允许我们多次使用相同的资源名称(跨不同的命名空间)。 P75
P75
在使用多个命名空间的前提下,我们可以将包含大量组件的复杂系统拆分成更小的不同组,这些不同组也可以用于在多租户环境中分配资源,将资源分配为生产、开发和 QA 环境,或者以其他任何需要的方式分配资源。资源名称只需要在命名空间内保持唯一即可,因此两个不同的命名空间可以包含同名的资源。 P75
大多数类型的资源都与命名空间相关,但仍有一些与它们无关,其中之一便是全局且未被约束于单一命名空间但节点资源。 P75
P75
kubectl get namespaces
: 列出集群中的所有命名空间kubectl get pods -n kube-system
: 列出 kube-system
命名空间下的所有 pod命名空间的优点 P76
P76
命名空间是一种和其他资源一样的 Kubernetes 资源,因此可以通过 YAML 文件提交到 Kubernetes API 服务器来创建该资源。 P76
从 YAML 文件创建命名空间 P77
kubectl create -f custom-namespace.yaml
可以通过 YAML 文件创建命名空间。
Kubernetes 中的所有内容都是一个 API 对象,可以通过向 API 服务器提交 YAML 文件来实现创建、读取、更新和删除。 P77
# 遵循 v1 版本的 Kubernetes API
apiVersion: v1
# 资源类型为 Namespace
kind: Namespace
metadata:
# 命名空间的名称
name: custom-namespace
使用 kubectl create namespace
命令创建命名空间 P77
kubectl create namespace <namespace-name>
: 创建一个指定名称的命名空间
P77
kubectl create -n custom-namespace -f kubia-manual.yaml
: 在 kubia-manual
命名空间中通过指定的 YAML 文件创建一个资源。
如果不指定命名空间, kubectl 将在当前上下文中配置的默认命名空间中执行操作。而当前上下文的命名空间和当前上下文本身都可以通过 kubectl config
命令进行更改。 P78
P78
尽管命名空间将对象分隔到不同更多组,只允许你对属于特定命名空间的对象进行操作,但实际上命名空间之间并不提供对正在运行对对象对任何隔离。 P78
P78
P78
kubectl delete pod -n <namespace-name> <pod-name-1> [<pod-name-2> ...]
: 删除指定命名空间下的指定 pod 。 P79
在删除 pod 的过程中,实际上我们在指示 Kubernetes 终止该 pod 中的所有容器。 Kubernetes 向进程发送一个 SIGTERM
信号并等待一定的秒数(默认为 30 秒),使其正常关闭,如果它没有即使关闭,则通过 SIGKILL
终止该进程。因此,为了确保你的进程总是正常关闭,进程需要正确处理 SIGTERM
信号。 P79
P79
kubectl delete pod -n <namespace-name> -l <label-key>=<label-value>
: 删除指定命名空间下含有指定标签的所有 pod 。 P79
在微服务示例中,通过指定 rel=canary
标签选择器,可以一次删除所有金丝雀 pod 。 P79
P80
kubectl delete namespace custom-namespace
: 删除整个 custom-namespace
命名空间( pod 将会随命名空间自动删除)
P80
kubectl delete pod -n <namespace-name> --all
: 删除指定命名空间中的所有 pod 。 P80
P80
kubectl delete all -n <namespace-name> --all
: 删除指定命名空间中的所有资源。 all
指定删除所有资源类型, --all
选项指定删除所有资源实例。 P81
注意:使用 all
关键字并不会真的完全删除所有内容。一些资源会被保留下来,并且需要被明确指定删除。 P81
注意:该命令也会删除名为 kubernetes
的 Service
,但它会在几分钟后自动重新创建。 P81
本文首发于公众号:满赋诸机(点击查看原文) 开源在 GitHub :reading-notes/kubernetes-in-action
Kubernetes 实战 —— 03. pod: 运行于 Kubernetes 中的容器
标签:离线 role let 介绍 属性 世界 网络 bug strong
原文地址:https://www.cnblogs.com/manfuzhuji/p/14532550.html