关于kubernetes:Kubernetes-实战-03-pod-运行于-Kubernetes-中的容器

48次阅读

共计 9594 个字符,预计需要花费 24 分钟才能阅读完成。

介绍 pod P53

pod 是 Kubernetes 中最为重要的外围概念,而其余对象仅仅用于 pod 治理、pod 裸露或被 pod 应用。pod 是一组并置的容器,代表了 Kubernetes 中的根本构建模块。P53

当一个 pod 蕴含多个容器时,这些容器总是运行于同一个工作节点上——一个 pod 绝不会逾越多个工作节点。P54

为何须要 pod P54

为何多个容器比单个容器中蕴含多个过程要好 P54

假如一个由多个过程组成的应用程序,无论是通过 IPC(过程间通信)还是本地存储文件进行通信,都要求它们运行于同一台机器上。如果在单个容器中运行多个不相干的过程,那么放弃所有过程运行、治理它们的日志等将会是咱们的责任。例如,咱们须要蕴含一种在过程奔溃时可能主动重启的机制;同时这些过程都将记录到雷同的规范输入中,而此时咱们将很难确定每个过程别离记录了什么。P54

理解 pod P55

因为不能将多个过程汇集在一个独自的容器中,咱们须要另一种更高级的构造来将容器绑定在一起,并将它们作为一个单元进行治理,这就是 pod 背地的真正起因。P55

在蕴含容器的 pod 下,咱们能够同时运行一些密切相关的过程,并为它们提供(简直)雷同的环境,此时这些过程就如同全副运行于单个容器中一样,同时又放弃着肯定的间隔。这样一来,咱们便能全面地利用容器所提供的个性,同时对这些过程来说它们就像运行在一起一样。P55

同一 pod 中容器之间的局部隔离 P55

Kubernetes 通过配置 Docker 来让一个 pod 内的所有容器共享雷同的 Linux 命名空间,而不是每个容器都有本人的一组命名空间。P55

因为一个 pod 中的所有容器都在雷同的 Network 和 UTS 命名空间下运行([01. Kubernetes 介绍](https://mp.weixin.qq.com/s/nf…),所以它们都共享雷同的主机名和网络接口。同样地,这些容器也都在雷同的 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

通过 pod 正当治理容器 P56
  • 将多层利用扩散到多个 pod 中 P57
  • 基于扩缩容思考而宰割到多个 pod 中:Kubernetes 不能横向扩缩单个容器,只能扩缩整个 pod P57
  • 严密耦合到容器组能够增加到同一个 pod 中:通常为一个主容器和若干个反对容器 P57

    • 主容器:能够是 Web 服务器
    • 反对容器:能够是日志轮转器、收集器、数据处理器、通信适配器等

  • 除非有特定的起因要求容器是同一个 pod 中的一部分,否则应该在独自的 pod 中运行容器 P58

    • 它们须要一起运行还是能够在不同的主机上运行?
    • 它们代表的是一个整体还是互相独立的组件?
    • 它们必须一起进行扩缩容还是能够别离进行?

以 YAML 或 JSON 形容文件创建 pod P58

通过 YAML 文件定义所有的 Kubernetes 对象之后,还能够将它们存储在版本控制系统中,充分利用版本控制所带来的便利性。P59

查看现有 pod 的 YAML 形容文件 P59

kubectl get pod -o yam <pod-name> 命令能够查看指定 pod 的残缺 YAML 定义。P59

介绍 pod 定义的次要局部 P59

  • YAML 中应用的 Kubernetes API 版本
  • YAML 形容的资源类型
  • metadata: 包含名称、命名空间、标签和对于该容器的其余信息
  • spec: 蕴含 pod 内容的理论阐明,例如 pod 的容器、卷和其余数据
  • status: 蕴含运行中的 pod 的以后信息,例如 pod 所处的条件、每个容器的形容和状态,以及外部 IP 和其余根本信息

    • status 蕴含只读的运行时数据,该数据展现了给定时刻的资源状态。在创立新的 pod 时,status 局部不须要提供
创立一个简略的 YAML 形容文件 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

  • 每个应用集群的人都能够疾速查看每个 pod 对外裸露的端口
  • 容许为每个端口指定一个名称

能够应用 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

向 pod 发送申请 P65

将本地网络端口转发到 pod 中到端口 P65

kubectl port-forward kubia-manual 8888:8080 能够将本地端口 8888 转发到 kubia-manual pod 到端口 8080,这样咱们就能够在本地应用 curl localhost:8888 向 pod 发送一个 HTTP 申请。P65

应用标签组织 pod P66

微服务架构下可能会部署很多组件,这些组件可能是正本(部署同一组件的多个正本)和多个不同的公布版本(stable, beta, canary 等)同时运行,零碎中可能领有数百个 pod,如果没有能够无效组织这些组件的机制,将会导致微小的凌乱。P66

介绍标签 P66

标签是一种简略却功能强大的 Kubernetes 个性,不仅能够组织 pod,还能够组织所有其余的 Kubernetes 资源。标签是能够附加到资源的任意键值对,用以抉择具备该确切标签的资源(通过标签选择器实现)。只有标签的 key 在资源内是惟一的,一个资源便能够领有多个标签。通常在咱们创立资源时就会将标签附加到资源上,但之后咱们也能够再增加其余标签,或者批改现有标签的值,而无须从新创立资源。P67

咱们以图 3.6 中的微服务为例,通过给这些 pod 增加标签,能够失去一个更组织化的零碎,以便咱们了解。此时每个 pod 都标有两个标签:P67

  • app: 基于利用的横向纬度,指定 pod 属于哪一个利用、组件或微服务
  • rel: 基于版本的纵向纬度,显示在 pod 中运行的应用程序版本 (stable, beta, canary)

    • 金丝雀版 (canary):部署新版本时,只让一小部分用户体验新版本以察看新版本的体现,而后再向所有用户进行推广,这样能够避免裸露有问题的版本给过多的用户

创立 pod 时指定标签 P67

基于 kubia-manual.yaml 创立一个新的形容文件 kubia-manual-with-labels.yaml,并增加 metadata.labels 属性,指定 creation_method=manualenv=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: 创立一个新 pod
  • kubectl 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
批改现有 pod 的标签 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

通过标签选择器列出 pod 子集 P69

标签选择器容许咱们抉择标记有特定标签的 pod 子集,并对这些 pod 执行操作,它能够依据资源的以下条件来抉择资源:P68

  • 蕴含(或不蕴含)应用特定键的标签
  • 蕴含具备特定键和值的标签
  • 蕴含具备特定键的标签,但其值与咱们指定但不同
应用标签选择器列出 pod P69
  • kubectl get pods -l creation_method=manual: 列出蕴含 creation_method=manual 标签的所有 pod
  • kubectl get pods -l env: 列出有 env 标签的所有 pod,无论其值为如何
  • kubectl get pods -l '!env': 列出没有 env 标签的所有 pod
  • kubectl get pods -l creation_method!=manual: 列出有 creation_method 标签但其值不等于 manual 的所有 pod
  • kubectl get pods -l 'env in (debug, prod)': 列出有 env 标签并且其值为 debugprod 的所有 pod
  • kubectl get pods -l 'env notin (debug, prod)': 列出没有 env 标签,或者有 env 标签并且其值不为 debugprod 的所有 pod

应用标签选择器 app=pc 抉择后面所述示例中属于 product catalog 微服务的所有 pod。P70

在标签选择器中应用多个条件 P71
  • kubectl get pods -l creation_method=manual -l env=debug: 列出蕴含 creation_method=manual 标签和 env=debug 标签的所有 pod
  • kubectl get pods -l 'creation_method=manual, env in (debug, prod)': 列出蕴含 creation_method=manual 标签,且含有 env 标签并且其值为 debugprod 的所有 pod

应用标签选择器 app=pc,rel=beta 抉择后面所述示例中属于 product catalog 微服务的 beta 版本所有 pod。P71

应用标签和标签选择器来束缚 pod 调度 P71

某些状况下,咱们心愿对将 pod 调度到何处持有肯定发言权,例如:硬件基础设施不同质。P71

  • 某些工作节点应用机械硬盘,其余节点应用固态硬盘。可能想将一些 pod 调度到一组节点,同时将其余 pod 调度到另一组节点
  • 将执行 GPU 密集型运算的 pod 调度到理论提供 GPU 减速到节点上

这种状况下,咱们应该用某种形式形容对节点的需要,使 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 标签的所有节点
将 pod 调度到特定节点 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

注解 pod P73

注解也是键值对,实质上与标签十分类似。P73

  • 注解并不是为了保留标识信息而存在的,它们不能像标签一样用于对对象进行分组
  • 注解能够包容更多信息,并且次要用于工具应用
  • Kubernetes 也会将一些注解主动增加到对象,但其余的注解则须要由用户手动增加
  • 向 Kubernetes 引入新个性时,通常会应用注解

    • 一般来说,新性能的 alpha 和 beta 版本不会向 API 对象引入任何新字段,因而应用的是注解而不是字段。一旦所需的 API 更改变得清晰并且失去所有相干人员的认可,就会引入新的字段并废除相干注解
  • 大量应用注解能够为每个 pod 或其余 API 对象增加阐明,以便每个应用该集群的人都能够疾速查找无关每个独自对象的信息。例如,指定创建对象的人员姓名的注解能够使在集群中工作的人员之间的合作更加便当
  • 标签应该简短,注解能够蕴含绝对更多的数据(总共不超过 256KB)
查找对象的注解 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 requiredP74

应用前缀格局的注解键来防止键抵触是一个好办法,能够避免其余工具或库意外地笼罩本人的注解。P75

应用命名空间对资源进行分组 P75

Kubernetes 命名空间简略地为对象名称提供了一个作用域。此时咱们并不会将所有资源都放在同一个命名空间中,而是将它们组织到多个命名空间中,这样能够容许咱们屡次应用雷同的资源名称(跨不同的命名空间)。P75

理解对命名空间的需要 P75

在应用多个命名空间的前提下,咱们能够将蕴含大量组件的简单零碎拆分成更小的不同组,这些不同组也能够用于在多租户环境中分配资源,将资源分配为生产、开发和 QA 环境,或者以其余任何须要的形式分配资源。资源名称只须要在命名空间内放弃惟一即可,因而两个不同的命名空间能够蕴含同名的资源。P75

大多数类型的资源都与命名空间相干,但仍有一些与它们无关,其中之一便是全局且未被束缚于繁多命名空间但节点资源。P75

发现其余命名空间及其 pod 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

进行和移除 pod P78

按名称删除 pod P78

kubectl delete pod -n <namespace-name> <pod-name-1> [<pod-name-2> ...]: 删除指定命名空间下的指定 pod。P79

在删除 pod 的过程中,实际上咱们在批示 Kubernetes 终止该 pod 中的所有容器。Kubernetes 向过程发送一个 SIGTERM 信号并期待肯定的秒数(默认为 30 秒),使其失常敞开,如果它没有即便敞开,则通过 SIGKILL 终止该过程。因而,为了确保你的过程总是失常敞开,过程须要正确处理 SIGTERM 信号。P79

应用标签选择器删除 pod P79

kubectl delete pod -n <namespace-name> -l <label-key>=<label-value>: 删除指定命名空间下含有指定标签的所有 pod。P79

在微服务示例中,通过指定 rel=canary 标签选择器,能够一次删除所有金丝雀 pod。P79

通过删除整个命名空间来删除 pod P80

kubectl delete namespace custom-namespace: 删除整个 custom-namespace 命名空间(pod 将会随命名空间主动删除)

删除命名空间中的所有 pod,但保留命名空间 P80

kubectl delete pod -n <namespace-name> --all: 删除指定命名空间中的所有 pod。P80

删除命名空间中的(简直)所有资源 P80

kubectl delete all -n <namespace-name> --all: 删除指定命名空间中的所有资源。all 指定删除所有资源类型,--all 选项指定删除所有资源实例。P81

留神 :应用 all 关键字并不会真的齐全删除所有内容。一些资源会被保留下来,并且须要被明确指定删除。P81

留神 :该命令也会删除名为 kubernetesService,但它会在几分钟后主动从新创立。P81

本文首发于公众号:满赋诸机(点击查看原文)开源在 GitHub:reading-notes/kubernetes-in-action

正文完
 0