searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

Kubernetes 的基本概念

2023-08-30 02:16:00
7
0

Kubernetes 是什么

Kubernetes 将集群中的机器分为一个 Master 和一些 Node

在 Master 上运行着集群管理相关的一组进程:

  • kube-apiserver
  • kube-controller-manager
  • kube-scheduler

Node 作为集群中的工作节点, 运行真正的应用程序

在 Node 上 Kubernetes 管理的最小运行单元是 Pod

在 Node 上运行着 Kubernetes 的 kubelet,kube-proxy

Kubernetes 的基本概念和术语

Master

Master 指的是集群控制节点

所有控制命令都发给它, 它负责具体的执行过程

在 Master 上运行着以下关键进程:

  • Kubernetes API Server (kube-apiserver)
    • 集群控制的入口进程
    • 集群资源的增删改查操作入口
  • Kubernetes Controller Manager (kube-controller-manager)
    • 所有资源对象的自动化控制中心
  • Kubernetes Scheduler (kube-scheduler)
    • 负责资源调度的进程

Node

在每个 Node 上运行以下关键进程:

  • kubelet
    • 负责 Pod 对应的容器的创建, 启停等任务
  • kube-proxy
    • 实现 Services 的通信与负载均衡机制
  • 容器运行时

Pod

每个 Pod 都有一个特殊的”根容器” Pause容器

Pause容器 对应的镜像术语 Kubernetes 平台的一部分

每个 Pod 还包含一个或多个紧密相关的用户业务容器

引入业务无关的 Pause容器 作为 Pod 的根容器, 以它的状态代表整个容器组的状态

多个业务容器共享 Pause容器 的 IP, 共享 Pause容器 挂载的 Volume. 简化了关联的容器之间的通信问题, 解决了它们之间的文件共享问题

Kubernetes 为每个 Pod 都分配了唯一的 IP 地址, 称之为 Pod IP

一个 Pod 中的多个容器共享 Pod IP 地址

Kubernetes 要求底层网络支持集群内任意两个 Pod 之间的 TCP/IP 直接通信

这通常采用虚拟二层网络技术来实现

在 Kubernetes 中, 一个 Pod 里的容器与另外主机上的 Pod 容器能够直接通信

Pod 有两种类型:

  • 普通 Pod
  • 静态 Pod (Static Pod)

Static Pod 没有被存储在 etcd 中, 而是被存放在某个具体的 Node 中一个具体文件上, 并且只在此 Node 上启动, 运行

当 Pod 里的某个容器停止时, Kubernetes 会自动检测到这个问题并且重新启动这个 Pod (重启 Pod 里的所有容器)

 

Label

DeploymentReplicaSetDaemonSetJob 可以在 Selector 中使用基于集合的筛选条件定义:

selector:
  matchLabels:
    app: myweb
  matchExpressions:
    - {key: tier, operator: In, values: [frontend]}
    - {key: environment, operator: NotIn, values: [dev]}

可用运算符包括:

  • In
  • NotIn
  • Exists
  • DoesNotExist

Label Selector 的重要使用场景:

  • kube-controller-manager 通过 Label Selector 来筛选要监控的 Pod 副本数量
  • kube-proxy 通过 Service 的 Label Selector 来选择对应的 Pod
  • kube-scheduler 可以实现 Pod 定向调度的特性

ReplicationController

在 Kubernetes 1.2 中, ReplicationController 升级为另外一个新概念: ReplicaSet

ReplicaSet 支持基于集合的 Label Selector

ReplicationController 只支持基于等式的 Label Selector

很少单独使用 ReplicaSet, 它主要被 Deployment 这个更高层的资源对象所使用

Deployment

Deployment 内部使用了 ReplicaSet

Deployment 随时知道当前 Pod “部署”的进度

Horizontal Pod Autoscaler

横向 Pod 自动扩容

HPA

HPA 也是一种资源对象

HPA 通过跟踪分析指定 ReplicaSet 控制的所有目标 Pod 的负载变化情况, 来确定是否需要有针对性地调整目标 Pod 的副本数量

HPA 有如下 Pod 负载度量指标:

  • CPUUtilizationPercentage
  • 应用程序自定义度量指标, 如 TPS, QPS

CPUUtilizationPercentage 是一个算数平均值, 即目标 Pod 所有副本自身的 CPU 利用率的平均值

一个 Pod 自身的 CPU 利用率是该 Pod 当前 CPU 的使用量除以它的 Pod Request 的值

如果目标 Pod 没有定义 Pod Request 的值, 则无法使用 CPUUtilizationPercentage 实现 Pod 的横向自动扩容

在 CPUUtilizationPercentage 计算过程中使用到的 Pod 的 CPU 使用量通常是 1 min 内的平均值

可以从 Kubernetes Monitoring Architecture 来获取目标资源对象的性能数据

HPA 定义例子:

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
  namespace: default
spec:
  maxReplicas: 1
  minReplicas: 10
  scaleTargetRef:
    kind: Deployment
    name: php-apache
  targetCPUUtilizationPercentage: 90

StatefulSet

StatefulSet 里的每个 Pod 都有稳定的, 唯一的网络标识

StatefulSet 控制的 Pod 副本的启停顺序是受控的

StatefulSet 里的 Pod 采用稳定的持久化存储卷, 通过 PV 或 PVC 来实现

StatefulSet 除了要与 PV 卷捆绑使用以存储 Pod 的状态数据, 还要与 Headless Service 配合使用

在每个 StatefulSet 定义中, 都要声明它属于哪个 Headless Service

Headless Service 与普通 Service 的关键区别在于, 它没有 Cluster IP

如果解析 Headless Service 的 DNS 域名, 则返回的是该 Service 对应的全部 Pod 的 Endpoint 列表

StatefulSet 在 Headless Service 的基础上又为 StatefulSet 控制的每个 Pod 实例都创建了一个 DNS 域名

这个域名格式为: ${podname}.${headless service name}

Service

运行在每个 Node 上的 kube-proxy 进程负责把对 Service 的请求转发到后端的某个 Pod 实例上, 并在内部实现服务的负载均衡与会话保持机制

每个 Service 都被分配了一个全局唯一的虚拟 IP 地址, 这个虚拟 IP 被称为 Cluster IP

在 Service 的整个生命周期中, 它的 Cluster IP 不会发生改变

外部系统访问 Service 的问题
  • Node IP: Node 的 IP 地址
  • Pod IP: Pod 的 IP 地址
  • Cluster IP: Service 的 IP 地址

Node IP 是 Kubernetes 集群中每个节点的物理网卡的 IP 地址, 是一个真实存在的物理网络

Pod IP:

  • 是每个 Pod 的 IP 地址
  • 根据 docker0 网桥的 IP 地址段进行分配
  • 通常是一个虚拟的二层网络
  • Kubernetes 要求位于不同 Node 上的 Pod 能够彼此直接通信, 所以 Kubernetes 里的一个 Pod 里的容器访问另一个 Pod 里的容器时, 就是通过 Pod IP 所在的虚拟二层网络进行通信的, 而真实的 TCP/IP 流量是通过 Node IP 所在的物理网卡流出的

Cluster IP:

  • Cluster IP 仅作用于 Kubernetes Service 对象, 并由 Kubernetes 管理和分配 IP 地址
  • Cluster IP 无法被 Ping, 因为没有一个”实体网络对象”来响应
  • Cluster IP 只能结果 Service Port 组成一个具体的通信端口, 单独的 Cluster IP 不具备 TCP/IP 通信的基础
  • 在 Kubernetes 集群内, Node IP,Pod IP,Cluster IP 之间的通信, 采用的是 Kubernetes 自己设计的一种编程方式的特殊路由规则

Service 的 Cluster IP 属于 Kubernetes 集群内部的地址, 无法在集群外部直接使用这个地址

可以采用 NodePort 来解决这个问题:

apiVersion: v1
kind: Service
metadata:
  name: tomcat-service
spec:
  type: NodePort
  ports:
    - port: 8080
    nodePort: 31002
  selector:
    tier: frontend

通过 http://<nodePort IP>:31002 即可访问

NodePort 的实现方式是在 Kubernetes 集群里的每个 Node 上都为需要外部访问的 Service 开启一个对应的 TCP 监听端口, 外部系统只要用任意一个 Node 的 IP 地址加上具体的 NodePort 端口号即可访问此服务

Job

Job 生成的 Pod 副本是不能自动重启的, 对应的 Pod 副本的 RestartPolicy 都被设置成 Never

Job 所控制的 Pod 副本的工作模式能够多实例并行计算

Volume

Volume (存储卷) 是Pod 中能够被多个容器访问的共享目录

Volume 被定义在 Pod 上

使用:

spec:
  volumes:
    - name: datavol
      emptyDir: {}
  containers:
    - name: tomcat-demo
      image: tomcat
      volumeMounts:
        - mountPath: /mydata-data
          name: datavol
      imagePullPolicy: IfNotPresent

Volume 类型

emptyDir

一个 emptyDir Volume 是在 Pod 分配到 Node 时创建的

初始内容为空, 无须指定宿主机上对应的目录文件

因为这是 Kubernetes 自动分配的一个目录

当 Pod 从 Node 移除时, emptyDir 中的数据也会被永久删除

emptyDir 的一些用途:

  • 临时空间
  • CheckPoint 的临时保存目录
  • 多容器共享目录

目前, 用户无法控制 emptyDir 使用的介质种类

hostPath

hostPath 为在 Pod 上挂载宿主机上的文件或目录

用途:

  • 容器应用程序生成的日志文件需要永久保存时
  • 需要访问宿主机上 Docker 引擎内部数据结构的容器应用时, 可以通过定义 hostPath 为宿主机 /var/lib/docker 目录, 使容器内部应用可以直接访问 Docker 的文件系统

注意:

  • 可能会因为宿主机上的目录和文件不同, 导致对 Volume 上目录和文件的访问结果不一致
  • 如果使用了资源配额管理, 则 Kubernetes 无法将 hostPath 在宿主机上使用的资源纳入管理
NFS

使用 NFS 网络文件系统提供的共享目录存储数据时, 需要在系统中部署一个 NFS Server

volumes:
  - name: nfs
    nfs:
      server: nfs-server.localhost
      path: "/"

Persistent Volume

PV 可以理解为 Kubernetes 集群中的某个网络存储对应的一块存储

  • PV 只能是网络存储, 不属于任何 Node, 但可以在每个 Node 上访问
  • PV 并不是被定义在 Pod 上的, 而是独立于 Pod 之外定义的
  • PV 目前支持的类型包括
    • FC (Fibre Channel)
    • Flocker
    • NFS
    • GlusterFS
    • HostPath (仅供单机测试)

Example - NFS 类型的 PV 定义:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0003
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  nfs:
    path: /somepath
    server: 172.17.0.1

PV 的 accessModes 属性:

  • ReadWriteOnce: 读写权限, 并且只能被单个 Node 挂载
  • ReadOnlyMany: 只读权限, 允许被多个 Node 挂载
  • ReadWriteMany: 读写权限, 允许被多个 Node 挂载

如果某个 Pod 想申请某种类型的 PV, 则首先需要定义一个 PersistentVolumeClaim 对象:

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 8Gi

然后, 在 Pod 的 Volume 定义中引用上述 PersistentVolumeClaim 即可:

volumes:
  - name: mypd
    persistentVolumeClaim:
      claimName: myclaim

PV 是有状态的对象:

  • Available: 空闲状态
  • Bound: 已经绑定到某个 PVC 上
  • Released: 对应的 PVC 已经被删除, 但资源还没有被集群回收
  • Failed: PV 自动回收失败

Namespace

用于实现多租户的资源隔离

默认会创建并使用一个名称为 default 的 Namespace

使用 --namespace 参数来指定 Namespace

Annotation

用户任意定义的附加信息

ConfigMap

配置项可以作为 Map 表中的一个项, 整个 Map 的数据可以被持久化存储在 Kubernetes 的 Etcd 数据库中, 然后提供 API 以方便 Kubernetes 相关组件或客户应用 CRUD 操作这些数据

这个专门用来保存配置参数的 Map 就是 Kubernetes ConfigMap 资源对象

Kubernetes 提供了一种内建机制, 将存储在 etcd 中的 ConfigMap 通过 Volume 映射的方式变成目标 Pod 内的配置文件

不管目标 Pod 被调度到哪台服务器上, 都会完成自动映射

如果 ConfigMap 中的 key-value 数据被修改, 则映射到 Pod 中的”配置文件”也会随之自动更新

0条评论
0 / 1000
李****灏
3文章数
0粉丝数
李****灏
3 文章 | 0 粉丝