kubernetes资源对象应用类(一)

kubernetes资源对象应用类

Kubernetes中属于应用类的概念和相应的资源对象类型最多,所以应用类也是我们要重点学习的一类。

Service和Pod

  应用类相关的资源对象主要是围绕Service(服务)和Pod这两个核心对象展开的。

  一般说来,Service指的是无状态服务,通常由多个程序副本提供服务,在特殊情况下也可以是有状态的单例服务,比如MySQL这种数据存储类的服务。与我们常规理解的服务不同,Kubernetes里的Service具有一个全局唯一的虚拟ClusterIP地址,Service一旦被创建,Kubernetes就会自动为它分配一个可用的ClusterIP地址,而且在Service的整个生命周期中,它的ClusterIP地址都不会改变,客户端可以通过这个虚拟IP地址+服务的端口直接访问该服务,再通过部署Kubernetes集群的DNS服务,就可以实现Service Name(域名)到ClusterIP地址的DNS映射功能,我们只要使用服务的名称(DNS名称)即可完成到目标服务的访问请求。“服务发现”这个传统架构中的棘手问题在这里首次得以完美解决,同时,凭借ClusterIP地址的独特设计,Kubernetes进一步实现了Service的透明负载均衡和故障自动回复的高级特性。

  通过分析、识别并建模系统中的所有服务为微服务–Kubernetes Service,我们的系统最终由多个提供不同业务能力而又彼此独立的微服务单元组成,服务之间通过TCP/IP进行通信,从而形成强大又灵活的弹性网格,拥有强大的分布式能力、弹性扩展能力、容错能力,程序架构也变得简单和直观许多。

  接下来说说与Service密切相关的核心资源对象–Pod

  Pod是Kubernetes中最重要的基本概念之一,每个Pod都有一个特殊的被称为“根容器”的 Pause 容器。Pause 容器对应的镜像属于 Kubernetes 平台的一部分,除了 Pause 容器,每个 Pod 都还包含一个或多个紧密相关的用户业务容器。

  为什么 Kubernetes 会设计出一个全新的 Pod 概念并且 Pod 有这样特殊的组成结构?原因如下。

  • 为多进程之间的协作提供一个抽象模型,使用 Pod 作为基本的调度、复制等管理工作的最小单位,让多个应用进程能一起有效地调度和伸缩。
  • Pod 里的多个业务容器共享 Pause 容器的 IP ,共享 Pause 容器挂接的 Volume,这样既简化了密切关联的业务容器之间的通信问题,也很好地解决了它们之间的文件共享问题。

  Kubernetes 为每个 Pod 都分配了唯一的 IP 地址,称之为 Pod IP,一个 Pod 里的多个容器共享 Pod IP 地址。Kubernetes 要求底层网络支持集群内任意两个 Pod 之间的 TCP/IP 直接通信,这通常采用虚拟二层网络技术实现 例如 Flannel、Open vSwitch 等,因此我们需要牢记一点:在 Kubernetes 里,一个 Pod 里的容器与另外主机上的 Pod 容器能够直接通信。

  Pod其实有两种类型:普通的 Pod 及静态 Pod (Static Pod)。后者比较特殊,它并没被存放在 Kubernetes 的 etcd 中,而是被存放在某个具体的 Node 上的一个具体文件中,并且只能在此 Node 上启动、运行。而普通的 Pod 一旦被创建,就会被放入 etcd 中存储,随后被 Kubernetes Master 调度到某个具体的 Node 上并绑定(Binding),该 Pod 被对应的 Node 上的 kubelet 进程实例化成一组相关的 Docker 容器并启动。在默认情况下,当 Pod 里的某个容器停止时, Kubernetes 会自动检测到这个问题并且重新启动这个 Pod (重启 Pod 里的所有容器),如果 Pod 所在的 Node 宕机,就会将这个 Node 上的所有 Pod 都重新调度到其他节点上。

  下面是我们在之前的 Hello World 例子里用到的 myweb 这个 Pod 的资源定义文件:

apiVersion: v1
kind: Pod
metadata:
  name: myweb
  labels:
    name: myweb
spec:
  containers:
  - name: myweb
  image: kubeguide/tomcat-app: v1
  ports:
  - containerPort: 8080

  在以上定义中,kind 属性的值为 Pod,表明这是一个 Pod 类型的资源对象; metadata 里的 name 属性为 Pod 的名称,在metadata 里还能定义资源对象的标签,这里声明 myweb 拥有一个 name=myweb 标签。在 Pod 里所包含的容器组的定义则在 spec 部分中声明,这里定义了一个名为 myweb 且对应的镜像为 kubeguide/tomcat-app: v1 的容器,并在 8080 端口(containerPort)启动容器进程。Pod 的 IP 加上这里的容器端口(containerPort)组成了一个新的概念–Endpoint,代表此 Pod 里的一个服务进程的对外通信地址。一个 Pod 也存在具有多个 Endpoint 的情况,比如当我们把 Tomcat 定义为一个 Pod 时,可以对外暴露管理端口与服务端口这两个 Endpoint。

  我们所熟悉的 Docker Volume 在 Kubernetes 里也有对应的概念-- Pod Volume, Pod Volume 是被定义在 Pod 上,然后被各个容器挂载到自己的文件系统中的。 Volume 简单来说就是被挂载到 Pod 里的文件目录。

  这里顺便提一下 Kubernetes 的 Event 概念。 Event 是一个时间的记录,记录了事件的最早产生时间、最后重现时间、重复次数、发起者、类型,以及导致此事件的原因等众多信息。 Event 通常会被关联到某个具体的资源对象上,是排查故障的重要参考信息。之前我们看到在 Node 的描述信息中包括 Event,而 Pod 同样有 Event 记录,当我们发现某个 Pod 迟迟无法创建时,可以用 kubectl describe pod xxxx 来查看它的描述信息,以定位问题的成因。比如下面这个 Event 记录信息就表明 Pod 里的一个容器被探针检测为失败一次:

Events:

FirstSeenLastSeenCountFromSubobjectPathTypeReasonMessage
10h12m32{kubelet k8s-node-1}spec.containers{kube2sky}WarningUnhealthy Liveness probe failed: Get http://172.17.1.2:8080/healthz:net/http:request canceled(Client.Timeout.exceeded while awaiting headers)

Pod 与 Development

  前面提到,大部分 Service 都是无状态的服务,可以由多个 Pod 副本实例提供服务。通常情况下,每个 Service 对应的 Pod 服务实例数量都是固定的,如果一个一个地手工创建 Pod 实例,就太麻烦了,最好是用模板的思路,即提供一个 Pod 模板(Template),然后由程序根据我们指定的模板自动创建指定数量的 Pod 实例。这就是 Deployment 这个资源对象所要完成的事情了。

  先看看之前例子中的 Deployment 案例(省略部分内容)

apiVersion: apps/v1
kind: Deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myweb
  template:
    metadata:
      labels:
        app: myweb
    spec:

  这里有几个很重要的属性。

  • replicas:Pod的副本数量
  • selector:目标 Pod 的标签选择器
  • template:用于自动创建新 Pod 副本的模板。

  只有一个 Pod 副本实例时,我们是否也需要 Deployment 来自动创建 Pod 呢?在大多数情况下,这个答案是“需要”。这是因为 Deployment 除自定创建 Pod 副本外,还有一个很重要的特性:自动控制。举个例子,如果 Pod 所在节点发生宕机事件,Kubernetes 就会第一时间观察到这个故障,并自动创建一个新的 Pod 对象,将其调度到其他合适的节点上,Kubernetes 会实时监控集群中目标 Pod 的副本数量,并且尽力与 Deployment 中声明 replicas 数量保持一致。

  下面创建一个名为 tomcat-deployment.yaml 的 Deployment 描述文件,内容如下:

tomcat-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  replicas: 1
  selector:
    matchLabels:
      tier: frontend
    matchExpressions:
    - {key: tier, operator: In, values: [frontend]}
  template:
    metadata:
      labels:
        app: app-demo
        tier: frontend
    spec:
      containers:
      - name: tomcat-demo
        image: tomcat
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080

运行以下命令创建 Deployment 对象:

kubectl create -f tomcat-deployment.yaml

运行以下命令查看 Deployment 的信息:

kubectl get deployment

对以上输出中各字段的含义解释如下。

  • DESIRED:Pod 副本数量的期望值,即在 Deployment 里定义的 replicas。
  • CURRENT:当前 replicas 的值,实际上是 Deployment 创建的 ReplicaSet 对象里的 replicas 值,这个值不断增加,直到达到 DESIRED 为止,表明整个部署过程完成。
  • UP-TO-DATE:最新版本的 Pod 的副本数量,用于指示在滚动升级的过程中,有多少个 Pod 副本已经成功升级。
  • AVAILABLE:当前集群中可用的 Pod 副本数量,即集群中当前存活的 Pod 数量。

  Deployment资源对象其实还与 ReplicaSet 资源对象密切相关,Kubernetes 内部会根据 Deployment 对象自动创建相关联的 ReplicaSet 对象,通过以下命令,我们可以看到它的命名与 Deployment 的名称有对应关系:

kubectl get replicaset

不仅如此,我们发现 Pod 的命名也是以 Deployment 对应的 ReplicaSet 对象的名称为前缀的,这种命名很清晰地表明了一个 ReplicaSet 对象创建了哪些 Pod,对于 Pod 滚动升级(Pod Rolling update)这种复杂的操作过程来说,很容易排查错误:

kubectl get pods

  关于 Deployment 就先说到这里,最后总结一下它的典型使用场景。

  • 创建一个 Deployment 对象来完成相应 Pod 副本数量的创建。
  • 检查 Deployment 的状态来看部署动作是否完成(Pod 副本数量是否达到预期的值)。
  • 更新 Deployment 以创建新的 Pod(比如镜像升级),如果当前 Deployment 不稳定,则回滚到一个早先的 Deployment 版本。
  • 扩展 Deployment 以应对高负载。

  Deployment和Service的逻辑关系

Kubernetes 的 Service 定义了一个服务的访问入口地址,前端的应用(Pod)通过这个入口地址访问其背后的一组由 Pod 副本组成的集群实例。 Service 与其后端 Pod 副本集群之间是通过 Label Selector 实现无缝对接的,Deployment 实际上用于保证 Service 的服务能力和服务质量始终符合预期标准。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值