Kubernetes 资源详解【概念入门】

一、Kubernetes 资源概述

Kubernetes 中的所有内容都被抽象为资源,如 Pod、Deployment、Service、Node 等都是资源。

资源对象的创建、删除、修改都是通过 Kubernetes API,也就是 ApiServer 组件提供的 API 接口,这些是 RESTful 风格的 Api,与 Kubernetes 的“万物皆对象”理念相符。实际上,命令行工具 kubectl 也是调用 Kubernetes API。

kubectl 可以通过配置文件来创建这些资源对象,配置文件更像是描述对象“属性”的文件,配置文件格式可以是 “JSON” 或 “YAML”,常用 “.yaml” 格式的文件。

二、Pod

2.1、基本概念

Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。

Pod 表示集群上一组正在运行的容器。

一个 Pod 由一个或多个容器组成(当然,这些容器不一定得是 Docker 容器,Kubernetes还支持其他容器运行时,例如 containerd、CRI-O),Pod 中容器共享存储、网络和依赖,在同一台 Docker 主机上运行。在 Kubernetes 中,若要运行一个容器,则必须先创建 Pod,让容器在 Pod 中运行,Kubernetes 直接管理的是 Pod ,而不是容器。

Pod 天生地为其成员容器提供了两种共享资源:网络存储

Kubernetes 集群中的 Pod 可被用于以下两个主要用途:

  • 运行单个容器的 Pod
  • 运行多个协同工作的容器的 Pod
    • 一个 Pod 中同时封装了多个需要相互耦合互相协作的容器,各个容器之间需要共享资源。

如果希望横向扩展应用程序(例如,运行多个实例以提供更多的资源),则应该使用多个 Pod,每个实例使用一个 Pod。 在 Kubernetes 中,这通常被称为 副本(Replication)

2.2、Pod 中的存储

一个 Pod 可以设置一组共享的存储卷。 Pod 中的所有容器都可以访问该共享卷,从而允许一个 Pod 中的容器共享数据。

卷还允许 Pod 中的数据持久化保存,这样其中的容器重启也不会导致数据丢失。

2.3、Pod 中的网络

每个 Pod 都在每个地址族中获得一个唯一的 IP 地址。

Pod 内的容器可以使用 localhost 互相通信,类似于在同一个局域网内通信。

2.4、Pod 的生命周期

Pod 的状态 PodStatus

  • Pending
    • 挂起:Pod 被 Kubernetes 系统接收,但是有一个或者多个容器镜像尚未创建 ,等待的时间包括:调度 Pod 的时间,通过网络下载镜像的时间。
  • Running
    • 运行中:Pod 已经绑定到一个节点上,Pod 中的所有容器都已经被创建。
  • Successed
    • 成功:Pod 中的所有容器都被成功终止,且不再重启。
  • Failed
    • 失败:Pod 中至少有一个容器因为失败终止,即容器是以非 0 的状态退出或者被系统终止。
  • Unknown
    • 未知:因为某些原因无法取得 Pod 的状态。

三、ReplicationController

ReplicationController 简写 “RC” 或 “RCS”,即副本控制器。

作用:ReplicationController 确保在任何时候都有特定数量的 Pod 副本处于运行状态。

具体而言:当 Pods 数量过多时,ReplicationController 会终止多余的 Pod。当 Pod 数量太少时,ReplicationController 将会启动新的 Pod。

ReplicationController 对象的配置文件示例:

# 创建该对象所使用的 Kubernetes API 的版本
apiVersion: v1
# 指定类型是副本控制器
kind: ReplicationController
metadata:
  # 对象名称
  name: nginx
spec:
  # 副本数量,这里表示开启三个 Pod
  replicas: 3
  # 指定 ReplicationController 的 selector 和 Pod 的 “app: nginx” 标签
  # 可以实现 ReplicationController 和 Pod 的绑定关系
  selector:
    app: nginx
  # 指定 Pod 模板
  template:
    # 描述 Pod 的元信息
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      # 指定该 Pod 基于 nginx 镜像创建,容器开启 80 端口
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

四、Deployment

4.1、基本概念

Deployment 是用于管理 POD 和 ReplicaSets,提供声明式的更新能力的 Kubernetes 资源。

创建 Deployment 的示例:编写一个 nginx-deployment.yaml

# API 版本号
apiVersion: apps/v1
# 类型,如:Pod/ReplicationController/Deployment/Service/Ingress
kind: Deployment
# 元数据
metadata:
  # 创建的 Deployment 的名称
  name: nginx-deployment
  labels:
    app: nginx
spec:
  # 部署的示例数量,默认为1
  replicas: 3
  # selector 字段定义 Deployment 如何查找要管理的 Pods。
  selector:
    # v1.16.0 之后增加了选择器配置
    matchLabels:
      # 这里的标签和下面 Pod 模板中定义的标签保持一致
      app: nginx
  # 创建 Pod Template
  template:
    metadata:
      # 容器标签的名字,发布 Service 时,selector 需要和这里对应
      # 这里表示 Pod 使用 labels 字段打上 app: nginx 标签
      labels:
        app: nginx
    # Pod 模板规约    
    spec:
      # 配置 Pod,这里是个数组类型,表示可以配置多个容器
      containers:
      # 创建一个容器并使用 name 字段将其命名为 nginx。
      - name: nginx
        # 容器运行版本为 1.14.2 的 nginx Docker Hub 镜像。
        image: nginx:1.14.2
        ports:
        # 开放容器的端口 80
        - containerPort: 80

4.2、创建 Deployment

  1. 创建 Deployment 的命令:
kubectl apply -f nginx-deployment.yaml
  1. 检查 Deployment 是否已创建:
kubectl get deployments

输出:

NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         0         0            0           1s
  • NAME 列出了集群中 Deployment 的名称。
  • READY 显示应用程序的可用的 副本 数。显示的模式是“就绪个数/期望个数”。
  • UP-TO-DATE 显示为了达到期望状态已经更新的副本数。
  • AVAILABLE 显示应用可供用户使用的副本数。
  • AGE 显示应用程序运行的时间。

这里 DESIRED 显示的副本数是根据 .spec.replicas 字段设置的 3。

  1. 查看 Deployment 上线状态:
kubectl rollout status deployment.v1.apps/nginx-deployment

完全启用时的状态:

NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         3         3            3           18s
  1. 查看 Deployment 创建的 ReplicaSet(rs):
kubectl get rs

NAME 列出名字空间中 ReplicaSet 的名称,名称始终被格式化为[Deployment名称]-[随机Hash字符串]

  1. 删除 Deployment 资源
kubectl delete -f nginx-deployment.yaml

4.3、更新 Deployment

仅当 Deployment Pod 模板(即 .spec.template)发生改变时,例如模板的标签或容器镜像被更新, 才会触发 Deployment 上线。

场景:将 nginx Pod 从使用nginx:1.14.2镜像升级到 nginx:1.16.1 镜像。

  1. 升级镜像命令:
kubectl --record deployment.apps/nginx-deployment set image \
   deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1

或:

kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record

或使用 edit Deployment 并将.spec.template.spec.containers.imagenginx:1.14.2 更改至 nginx:1.16.1

kubectl edit deployment.v1.apps/nginx-deployment
  1. 查看上线状态:
kubectl rollout status deployment.v1.apps/nginx-deployment

Deployment 可确保在更新时仅关闭一定数量的 Pod。默认情况下,它确保至少所需 Pods 75% 处于运行状态(最大不可用比例为 25%)。

Deployment 还确保仅所创建 Pod 数量只可能比期望 Pods 数高一点点。 默认情况下,它可确保启动的 Pod 个数比期望个数最多多出 25%(最大峰值 25%)。

对应:

RollingUpdateStrategy:  25% max unavailable, 25% max surge

滚动升级策略可以在创建 Deployment 时设定:

.spec.strategy 指定更新策略:

  • .spec.strategy.type==Recreate时: 表示创建新的 Pod 之前会删掉所有已经存在的 Pod;
  • .spec.strategy.type==RollingUpdate时:
    • .maxUnavailabe 是可选配置项,指定升级过程中不可用 Pod 的最大数量;
    • .maxSurge 是可选配置项,指定可以超过期望的 Pod 的最大数量。

五、Service

5.1、基本概念

官网解释:An abstract way to expose an application running on a set of Pods as a network service.

Service(svc)暴露 Kubernetes 内部的服务 (Deployment)供外部访问。

具体来说:Service 是一个应用服务的抽象,定义了 Pod 逻辑集合和访问这个 Pod 集合的策略。

为什么要使用 Service 呢?**为了解耦 **

每个 Pod 都有自己的 IP 地址,虽然可以设置固定 IP,但是这会增加程序的耦合度。并且 Pod 是有生命周期的,它们在销毁之后不会再启动,比如使用 Deployment 可以动态地创建和销毁 Pod。所以直接使用 Pod 来提供服务是不科学的,Service 就是对这一问题的抽象,它代理了 Pod 集合,对外提供统一的访问入口,访问该入口的请求将经过负载均衡,转发到后端 Pod 中的容器

所以说,Service 是对 Pod 访问方式的抽象, Pod 只提供功能,并不提供服务,Service 才是真正对外提供服务。

如果d。行的 Pod 集合可能与稍后运行该应用程序的 Pod 集合不同。

这导致了一个问题: 如果一组 Pod(称为“后端”)为集群内的其他 Pod(称为“前端”)提供功能, 那么前端如何找出并跟踪要连接的 IP 地址,以便前端可以使用工作量的后端部分?

官网给的一个更具体的例子:

一个图片处理后端,它运行了 3 个副本。这些副本是可互换的 —— 前端不需要关心它们调用了哪个后端副本。 然而组成这一组后端程序的 Pod 实际上可能会发生变化,也就是 IP 地址会发生变化, 前端客户端不应该也没必要知道,而且也不需要跟踪这一组后端的状态。 Service 定义的抽象能够解耦这种关联。

怎么实现这种解耦呢?通过 label 和 label selector

创建 Pod 时为它分配特定的 label,然后配置 Service 时通过 label selector 选择具有这些特定 label 的 Pod 来接受请求、提供服务。

在 Kubernetes 集群中微服务的负载均衡是由 kube-proxy 来实现的。

5.2、创建 Service

  1. 创建示例:my-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    # 标签选择器由 name 修改为 app
    app: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

以上这个 yaml 文件的功能:配置创建一个名称为 “my-service” 的 Service 对象,它会将请求代理到使用 TCP 端口 9376,并且具有标签 "app=MyApp" 的 Pod 上。

Kubernetes 为该服务分配一个 IP 地址(有时称为 “集群IP”),该 IP 地址由服务代理使用。 服务选择算符的控制器不断扫描与其选择器匹配的 Pod,然后将所有更新发布到也称为 “my-service” 的 Endpoint 对象。

  1. 部署
kubectl apply -f my-service.yaml
  1. 删除
kubectl delete -f my-service.yaml
  1. 查看 Service 列表
kubectl get service
  1. 查看 Service 详情
kubectl describe service my-service

六、集群访问方式

Kubernetes 外部访问入口

6.1、内部访问方式

ClusterIP 服务是 Kubernetes 的默认服务。它给你一个集群内的服务,集群内的其它应用都可以访问该服务。集群外部无法访问它。在某些场景下我们可以使用 Kubernetes 的 Proxy 模式来访问服务,比如调试服务时。

image-20201203161602041

6.2、外部访问方式

6.2.1、NodePort

NodePort 服务是引导外部流量到你的服务的最原始方式

使用 NodePort 方式会在所有节点(虚拟机)上开放一个特定端口,任何发送到该端口的流量都被转发到对应服务。

NodePort 服务特征如下:

  • 每个端口只能是一种服务
  • 端口范围只能是 30000-32767(可调)
  • 不在 YAML 配置文件中指定则会分配一个默认端口

建议: 不要在生产环境中使用这种方式暴露服务,大多数时候我们应该让 Kubernetes 来选择端口

image-20201203170017385

6.2.2、LoadBalancer

LoadBalancer 服务是暴露服务到 Internet 的标准方式。

所有通往你指定的端口的流量都会被转发到对应的服务。它没有过滤条件,没有路由等。这意味着你几乎可以发送任何种类的流量到该服务,像 HTTP,TCP,UDP,WebSocket,gRPC 或其它任意种类。

image-20201203170421810

6.2.3、Ingress

Ingress 事实上不是一种服务类型。相反,它处于多个服务的前端,扮演着 智能路由或者集群入口的角色。

通常情况下,Service 和 Pod 的 IP 仅可在集群内部访问。集群外部的请求需要通过负载均衡转发到 Service 在 Node 上暴露的 NodePort 上,然后再由 kube-proxy 通过边缘路由器 (edge router) 将其转发给相关的 Pod 或者丢弃。而 Ingress 就是为进入集群的请求提供路由规则的集合。

Ingress 可以给 Service 提供集群外部访问的 URL、负载均衡、SSL 终止、HTTP 路由等。为了配置这些 Ingress 规则,集群管理员需要部署一个 Ingress Controller,它监听 Ingress 和 Service 的变化,并根据规则配置负载均衡并提供访问入口。

image-20201203171227444

Ingress 提供了反向代理负载均衡功能。

Ingress 控制器有各种类型,包括 Google Cloud Load Balancer, Nginx,Contour,Istio,等等。它还有各种插件,比如 cert-manager (可以为服务自动提供 SSL 证书)。

七、PV、PVC、StorageClass

7.1、基本概念

Persistent Volume 子系统对存储的供应和使用做了抽象,以 API 形式提供给管理员和用户使用。要完成这一任务,引入了两个新的 API 资源:Persistent Volume(持久卷)Persistent Volume Claim(持久卷消费者)

Persistent Volume(PV)是集群之中的一块网络存储,它跟 Node 一样,也是集群的资源。

PV 跟 Volume (卷) 类似,不过会有独立于 Pod 的生命周期。这一 API 对象包含了存储的实现细节,例如 NFS、iSCSI 或者其他的云提供商的存储系统。

Persistent Volume Claim (PVC) 是用户的一个请求。跟 Pod 类似,Pod 消费 Node 的资源,PVC 消费 PV 的资源。Pod 能够申请特定的资源(CPU 和内存);Claim 能够请求特定的尺寸和访问模式(例如可以加载一个读写,以及多个只读实例)。

7.2、生命周期

  • 供应
    • 集群管理员会创建一系列的 PV。
    • 这些 PV 包含了为集群用户提供的真实存储资源,它们可利用 Kubernetes API 来消费。
  • 绑定
    • 用户创建一个包含了容量和访问模式的持久卷申请。
    • Master 会监听 PVC 的产生,并尝试根据请求内容查找匹配的 PV,并把 PV 和 PVC 进行绑定。用户能够获取满足需要的资源,并且在使用过程中可能超出请求数量。如果找不到合适的卷,这一申请就会持续处于非绑定状态,一直到出现合适的 PV。例如一个集群准备了很多的 50G 大小的持久卷,(虽然总量足够)也是无法响应 100G 的申请的,除非把 100G 的 PV 加入集群。
  • 使用
    • Pod 把申请作为卷来使用。
    • 集群会通过 PVC 查找绑定的 PV,并 Mount 给 Pod。对于支持多种访问方式的卷,用户在使用 PVC 作为卷的时候,可以指定需要的访问方式。一旦用户拥有了一个已经绑定的 PVC,被绑定的 PV 就归该用户所有了。用户的 Pods 能够通过在 Pod 的卷中包含的 PVC 来访问他们占有的 PV。
  • 释放
    • 当用户完成对卷的使用时,就可以利用 API 删除 PVC 对象了,而且他还可以重新申请。删除 PVC 后,对应的卷被视为 “被释放”,但是这时还不能给其他的 PVC 使用。之前的 PVC 数据还保存在卷中,要根据策略来进行后续处理。
  • 回收
    • PV 的回收策略向集群阐述了在 PVC 释放卷的时候,应如何进行后续工作。目前可以采用三种策略:保留,回收或者删除
    • 保留策略允许重新申请这一资源。
    • 在持久卷能够支持的情况下,删除策略会同时删除持久卷以及 AWS EBS/GCE PD 或者 Cinder 卷中的存储内容。
    • 如果插件能够支持,回收策略会执行基础的擦除操作(rm -rf /thevolume/*),这一卷就能被重新申请了。

7.3、创建 PV、PVC 示例

使用持久卷插件实现,可选方案:

  • GCEPersistentDisk (Google 旗下产品)
  • AWSElasticBlockStore(AWS 旗下产品)
  • NFS(Network File System 的简写,即网络文件系统)
  • iSCSI
  • RBD (Ceph Block Device)
  • Glusterfs
  • HostPath (单节点测试使用)
  • 本地持久卷

7.3.1、创建 PV 配置文件

  1. 定义 PV,nfs-pv-mysql.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv-mysql
spec:
  # 设置容量
  capacity:
    storage: 5Gi
  # 访问模式
  accessModes:
    # 该卷能够以读写模式被多个节点同时加载
    - ReadWriteMany
  # 回收策略,这里是基础擦除 `rm-rf/thevolume/*`
  persistentVolumeReclaimPolicy: Recycle
  # 使用 NFS 方式
  nfs:
    # NFS 服务端配置的路径
    path: "/usr/local/kubernetes/volumes"
    # NFS 服务端地址
    server: 192.168.141.140
    readOnly: false

Capacity(容量)

一般来说,PV 会使用 capcity 属性指定存储容量。

AccessModes(访问模式)

可选范围:

  • ReadWriteOnce(RWO):该卷能够以读写模式被加载到一个节点上

  • ReadOnlyMany(ROX):该卷能够以只读模式加载到多个节点上

  • ReadWriteMany(RWX):该卷能够以读写模式被多个节点同时加载

ecyclingPolicy(回收策略)

可选范围:

  • Retain:人工重新申请
  • Recycle:基础擦除(rm-rf/thevolume/*
  • Delete:相关的存储资产例如 AWS EBS,GCE PD 或者 OpenStack Cinder 卷一并删除

阶段(Phase)

一个卷会处于如下阶段之一:

  • Available:可用资源,尚未被绑定到 PVC 上
  • Bound:该卷已经被绑定
  • Released:PVC 已经被删除,但该资源尚未被集群回收
  • Failed:该卷的自动回收过程失败
# 部署
kubectl create -f nfs-pv-mysql.yml
# 删除
kubectl delete -f nfs-pv-mysql.yml
# 查看
kubectl get pv
  1. 定义 PVC,nfs-pvc-mysql-test.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc-mysql-test
spec:
  accessModes:
  # 需要使用和 PV 一致的访问模式
  - ReadWriteMany
  # 按需分配资源
  resources:
     requests:
       storage: 1Gi
# 部署
kubectl create -f nfs-pvc-mysql-test.yml
# 删除
kubectl delete -f nfs-pvc-mysql-test.yml
# 查看
kubectl get pvc

八、ConfigMap

ConfigMap 外部化配置。

ConfigMap 是用来存储配置文件的 Kubernetes 资源对象,所有的配置内容都存储在 etcd 中。它可以被用来保存单个属性,也可以用来保存整个配置文件或者 JSON 二进制对象。ConfigMap API 资源提供了将配置数据注入容器的方式,同时保证该机制对容器来说是透明的。配置应该从 Image 内容中解耦,以此来保持容器化应用程序的可移植性。

九、ReplicaSet

ReplicaSet 是 Replication Controller 的升级版。和 Replication Controller 一样用于确保任何给定时间指定的Pod副本数量,并提供声明式更新等功能。

官方建议使用 Deployment 管理 ReplicaSets,而不是直接使用 ReplicaSets,这就意味着不需要直接操作 ReplicaSet 对象。

十、Job、CronJob

Job: 一次性任务,运行完成后 Pod 销毁,不再重新启动新容器。

CronJob: 在 Job 基础上加上了定时功能。

参考文档

Kubernetes 官方文档

Kubernetes 实践

Kubernetes资源与对象简述

【附1】修改默认的端口范围

Kubernetes 服务的 NodePort 默认端口范围是 30000-32767,在某些场合下,这个限制不太适用,我们可以自定义它的端口范围,操作步骤如下:

编辑 vi /etc/kubernetes/manifests/kube-apiserver.yaml 配置文件,增加配置 --service-node-port-range=2-65535

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    component: kube-apiserver
    tier: control-plane
  name: kube-apiserver
  namespace: kube-system
spec:
  containers:
  - command:
    - kube-apiserver
    # 在这里增加配置即可
    - --service-node-port-range=2-65535
    - --advertise-address=192.168.141.150
    - --allow-privileged=true
    - --authorization-mode=Node,RBAC
    - --client-ca-file=/etc/kubernetes/pki/ca.crt
    - --enable-admission-plugins=NodeRestriction
    - --enable-bootstrap-token-auth=true
    - --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
    - --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
// 以下配置省略...

使用 docker ps 命令找到 kube-apiserver 容器,再使用 docker restart <ApiServer 容器 ID> 即可生效。

【附2】ImagePullPolicy

支持三种 ImagePullPolicy

  • Always: 不管镜像是否存在都会进行一次拉取
  • Never: 不管镜像是否存在都不会进行拉取
  • IfNotPresent: 只有镜像不存在时,才会进行镜像拉取

注意

  • 默认为 IfNotPresent,但 :latest 标签的镜像默认为 Always
  • 拉取镜像时 Docker 会进行校验,如果镜像中的 MD5 码没有变,则不会拉取镜像数据
  • 生产环境中应该尽量避免使用 :latest 标签,而开发环境中可以借助 :latest 标签自动拉取最新的镜像
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值