k8s 核心组件和架构

kubernetes

概述

kubenetes 是一个开源的容器编排引擎,用来对容器化应用进行自动化部署、 扩缩和管理

  • 插曲:Kubernetes 这个名字源于希腊语,意为“舵手”或“飞行员”。k8s 这个缩写是因为 k 和 s 之间有八个字符的关系
  • 能做什么?
    • 服务发现和负载均衡
    • 存储编排
    • 自动部署和回滚
    • 自动完成装箱计算
    • 自我修复
    • 密钥与配置管理
  • 怎么做的?
    • 服务发现和负载均衡
      Kubernetes 可以使用 DNS 名称或自己的 IP 地址来曝露容器。 如果进入容器的流量很大, Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定
    • 存储编排
      Kubernetes 允许你自动挂载你选择的存储系统,例如本地存储、公共云提供商等
    • 自动部署和回滚
      可以自动化 Kubernetes 来为你的部署创建新容器, 删除现有容器并将它们的所有资源用于新容器。

kubernetes 组件

当你部署完 Kubernetes,便拥有了一个完整的集群。

一组工作机器,称为 节点, 会运行容器化应用程序。每个集群至少有一个工作节点。

工作节点会托管 Pod ,而 Pod 就是作为应用负载的组件。 控制平面管理集群中的工作节点和 Pod。 在生产环境中,控制平面通常跨多台计算机运行, 一个集群通常运行多个节点,提供容错性和高可用性
k8s 架构图
图中蓝色虚线包裹起来的部分 是控制平面组件。

控制平面组件(Control Plane Components)

控制平面组件会为集群做出全局决策,比如资源的调度。 以及检测和响应集群事件,例如当不满足部署的 replicas 字段时, 要启动新的 pod)。

控制平面组件可以在集群中的任何节点上运行。 然而,为了简单起见,设置脚本通常会在同一个计算机上启动所有控制平面组件, 并且不会在此计算机上运行用户容器

  • kube-apiserver
  • etcd
  • kube-scheduler
  • kube-controller-manager
  • cloud-controller-manager

kube-apiserver
API 服务器是 Kubernetes 控制平面的组件, 该组件负责公开了 Kubernetes API,负责处理接受请求的工作。 API 服务器是 Kubernetes 控制平面的前端。

Kubernetes API 服务器的主要实现是 kube-apiserver。 kube-apiserver 设计上考虑了水平扩缩,也就是说,它可通过部署多个实例来进行扩缩。 你可以运行 kube-apiserver 的多个实例,并在这些实例之间平衡流量(负载均衡)。

etcd
一致且高度可用的键值存储,用作 Kubernetes 的所有集群数据的后台数据库,etcd作为中心节点保存每个运行的实例状态。

kube-scheduler

kube-scheduler 是控制平面的组件, 负责监视新创建的、未指定运行节点(node)的 Pods, 并选择节点来让 Pod 在上面运行。

调度决策考虑的因素包括单个 Pod 及 Pods 集合的资源需求、软硬件及策略约束、 亲和性及反亲和性规范、数据位置、工作负载间的干扰及最后时限。

kube-controller-manager
kube-controller-manager 是控制平面的组件, 负责运行控制器进程。

从逻辑上讲, 每个控制器都是一个单独的进程, 但是为了降低复杂性,它们都被编译到同一个可执行文件,并在同一个进程中运行。

这些控制器包括:

  • 节点控制器(Node Controller):负责在节点出现故障时进行通知和响应
  • 任务控制器(Job Controller):监测代表一次性任务的 Job 对象,然后创建 Pods 来运行这些任务直至完成
  • 端点控制器(Endpoints Controller):填充端点(Endpoints)对象(即加入 Service 与 Pod)
  • 服务帐户和令牌控制器(Service Account & Token Controllers):为新的命名空间创建默认帐户和 API 访问令牌

cloud-controller-manager
一个 Kubernetes 控制平面组件, 嵌入了特定于云平台的控制逻辑。 云控制器管理器(Cloud Controller Manager)允许你将你的集群连接到云提供商的 API 之上, 并将与该云平台交互的组件同与你的集群交互的组件分离开来。
cloud-controller-manager 仅运行特定于云平台的控制器。 因此如果你在自己的环境中运行 Kubernetes,或者在本地计算机中运行学习环境, 所部署的集群不需要有云控制器管理器。

与 kube-controller-manager 类似,cloud-controller-manager 将若干逻辑上独立的控制回路组合到同一个可执行文件中, 供你以同一进程的方式运行。 你可以对其执行水平扩容(运行不止一个副本)以提升性能或者增强容错能力。

下面的控制器都包含对云平台驱动的依赖:

  • 节点控制器(Node Controller):用于在节点终止响应后检查云提供商以确定节点是否已被删除
  • 路由控制器(Route Controller):用于在底层云基础架构中设置路由
  • 服务控制器(Service Controller):用于创建、更新和删除云提供商负载均衡器

Node 组件

节点组件会在每个节点上运行,负责维护运行的 Pod 并提供 Kubernetes 运行环境。

kubelet
kubelet 会在集群中每个节点(node)上运行。 它保证容器(containers)都运行在 Pod 中。

kubelet 接收一组通过各类机制提供给它的 PodSpecs, 确保这些 PodSpecs 中描述的容器处于运行状态且健康。 kubelet 不会管理不是由 Kubernetes 创建的容器。

kube-proxy
kube-proxy 是集群中每个节点(node)所上运行的网络代理, 实现 Kubernetes 服务(Service) 概念的一部分。

kube-proxy 维护节点上的一些网络规则, 这些网络规则会允许从集群内部或外部的网络会话与 Pod 进行网络通信。

如果操作系统提供了可用的数据包过滤层,则 kube-proxy 会通过它来实现网络规则。 否则,kube-proxy 仅做流量转发。

容器运行时(Container Runtime)
容器运行环境是负责运行容器的软件。

Kubernetes 支持许多容器运行环境,例如 containerd、 CRI-O 以及 Kubernetes CRI (容器运行环境接口) 的其他任何实现。

kubernetes 架构

  • 节点

    • Kubernetes 通过将容器放入在节点(Node)上运行的 Pod 中来执行你的工作负载。 节点可以是一个虚拟机或者物理机器,取决于所在的集群配置。 每个节点包含运行 Pod 所需的服务; 这些节点由 控制面 负责管理。
    • 节点上的组件包括 kubelet、容器运行时以及kube-proxy
  • 管理

    • 添加节点
      • 节点上的kubelet 向控制面执行自注册
      • 手动添加一个Node对象
    • 节点名称是用来标识Node对象,没有两个 Node 可以同时使用相同的名称。 Kubernetes 还假定名字相同的资源是同一个对象
    • 节点状态:kubectl describe node <节点名称>
      • 地址
        • HostName:由节点的内核报告。可以通过 kubelet 的 --hostname-override 参数覆盖。
        • ExternalIP:通常是节点的可外部路由(从集群外可访问)的 IP 地址。
        • InternalIP:通常是节点的仅可在集群内部路由的 IP 地址。
      • 状况
        • conditions字段
        • Ready为true 标识节点健康
        • DiskPressure True 表示节点存在磁盘空间压力,即磁盘可用量低, 否则为 False
        • MemoryPressure True 表示节点存在内存压力,即节点内存可用量低,否则为 False
        • PIDPressure True 表示节点存在进程压力,即节点上进程过多;否则为 False
        • NetworkUnavailable True 表示节点网络配置不正确;否则为 False
      • 容量与可分配
        • 节点上的可用资源:CPU、内存和可以调度到节点上的 Pod 的个数上限
        • capacity 块中的字段标示节点拥有的资源总量。 allocatable 块指示节点上可供普通 Pod 消耗的资源量。
      • 信息
        • info 指的是节点的一般信息,如内核版本、Kubernetes 版本(kubelet 和 kube-proxy 版本)、 容器运行时详细信息,以及节点使用的操作系统。 kubelet 从节点收集这些信息并将其发布到 Kubernetes API。
    • 节点心跳
      -Kubernetes 节点发送的心跳帮助你的集群确定每个节点的可用性,并在检测到故障时采取行动。

      对于节点,有两种形式的心跳:

      • 更新节点的 .status
      • kube-node-lease 名字空间中的 Lease(租约)对象。 每个节点都有一个关联的 Lease 对象。
        与 Node 的 .status 更新相比,Lease 是一种轻量级资源。 使用 Lease 来表达心跳在大型集群中可以减少这些更新对性能的影响。

      kubelet 负责创建和更新节点的 .status,以及更新它们对应的 Lease。

      • 当节点状态发生变化时,或者在配置的时间间隔内没有更新事件时,kubelet 会更新 .status。 .status 更新的默认间隔为 5 分钟(比节点不可达事件的 40 秒默认超时时间长很多)。
      • kubelet 会创建并每 10 秒(默认更新间隔时间)更新 Lease 对象。 Lease 的更新独立于 Node 的 .status 更新而发生。 如果 Lease 的更新操作失败,kubelet 会采用指数回退机制,从 200 毫秒开始重试, 最长重试间隔为 7 秒钟。
    • 节点控制器
      节点控制器
      节点控制器是 Kubernetes 控制面组件, 管理节点的方方面面。

      节点控制器在节点的生命周期中扮演多个角色。 第一个是当节点注册时为它分配一个 CIDR 区段(如果启用了 CIDR 分配)。无类别域间路由(Classless Inter-Domain Routing、CIDR)是一个用于给用户分配IP地址以及在互联网上有效地路由IP数据包的对IP地址进行归类的方法。

      第二个是保持节点控制器内的节点列表与云服务商所提供的可用机器列表同步。 如果在云环境下运行,只要某节点不健康,节点控制器就会询问云服务是否节点的虚拟机仍可用。 如果不可用,节点控制器会将该节点从它的节点列表删除。

      第三个是监控节点的健康状况。节点控制器负责:

      在节点不可达的情况下,在 Node 的 .status 中更新 Ready 状况。 在这种情况下,节点控制器将 NodeReady 状况更新为 Unknown。
      如果节点仍然无法访问:对于不可达节点上的所有 Pod 触发 API 发起的逐出操作。 默认情况下,节点控制器在将节点标记为 Unknown 后等待 5 分钟提交第一个驱逐请求。
      默认情况下,节点控制器每 5 秒检查一次节点状态,可以使用 kube-controller-manager 组件上的 --node-monitor-period 参数来配置周期

工作负载

概念:工作负载是在kubernetes上运行的应用程序。
在 Kubernetes 中,无论你的负载是由单个组件还是由多个一同工作的组件构成, 你都可以在一组 Pod 中运行它。 在 Kubernetes 中,Pod 代表的是集群上处于运行状态的一组 容器 的集合。

内置工作负载资源

  • Deployment 和 ReplicaSet

  • StatefulSet

  • DaemonSet

  • Job和CronJob

  • Deployment 很适合用来管理你的集群上的无状态应用,Deployment 中的所有 Pod 都是相互等价的,并且在需要的时候被替换。

  • StatefulSet 让你能够运行一个或者多个以某种方式跟踪应用状态的 Pod。 例如,如果你的负载会将数据作持久存储,你可以运行一个 StatefulSet,将每个 Pod 与某个 PersistentVolume 对应起来。你在 StatefulSet 中各个 Pod 内运行的代码可以将数据复制到同一 StatefulSet 中的其它 Pod 中以提高整体的服务可靠性

  • DaemonSet 定义提供节点本地支撑设施的 Pod。这些 Pod 可能对于你的集群的运维是 非常重要的,例如作为网络链接的辅助工具或者作为网络 插件 的一部分等等。每次你向集群中添加一个新节点时,如果该节点与某 DaemonSet 的规约匹配,则控制平面会为该 DaemonSet 调度一个 Pod 到该新节点上运行

  • Job 和 CronJob。 定义一些一直运行到结束并停止的任务。Job 用来执行一次性任务,而 CronJob 用来执行的根据时间规划反复运行的任务。

Pod

pod 是可以在kubernetes中创建和管理的最小可部署的计算单元

pod里有多个container,共享存储网络,可以相互访问网络

Pod 的共享上下文包括一组 Linux 名字空间、控制组(cgroup)和可能一些其他的隔离方面, 即用来隔离容器的技术。 在 Pod 的上下文中,每个独立的应用可能会进一步实施隔离。

Pod 类似于共享名字空间并共享文件系统卷的一组容器

k8s的集群中的Pod 主要有2种用法:

  • 运行单个容器的Pod,在这种情况下,可以将 Pod 看作单个容器的包装器,并且 Kubernetes 直接管理 Pod,而不是容器。
  • 运行多个协同工作的容器Pod,Pod 可能封装由多个紧密耦合且需要共享资源的共处容器组成的应用程序。 这些位于同一位置的容器可能形成单个内聚的服务单元 —— 一个容器将文件从共享卷提供给公众, 而另一个单独的 “边车”(sidecar)容器则刷新或更新这些文件。 Pod 将这些容器和存储资源打包为一个可管理的实体。

管理多个容器:

  • Pod 被设计成支持形成内聚服务单元的多个协作过程(形式为容器)。 Pod 中的容器被自动安排到集群中的同一物理机或虚拟机上,并可以一起进行调度。 容器之间可以共享资源和依赖、彼此通信、协调何时以及何种方式终止自身。

资源共享和通信
Pod 使它的成员容器间能够进行数据共享和通信。

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

    • Pod 联网

      • 每个 Pod 都在每个地址族中获得一个唯一的 IP 地址。 Pod 中的每个容器共享网络名字空间,包括 IP 地址和网络端口。 Pod 内的容器可以使用 localhost 互相通信。 当 Pod 中的容器与 Pod 之外的实体通信时,它们必须协调如何使用共享的网络资源(例如端口)。

      在同一个 Pod 内,所有容器共享一个 IP 地址和端口空间,并且可以通过 localhost 发现对方。 他们也能通过如 SystemV 信号量或 POSIX 共享内存这类标准的进程间通信方式互相通信。 不同 Pod 中的容器的 IP 地址互不相同,如果没有特殊配置,就无法通过 OS 级 IPC 进行通信。 如果某容器希望与运行于其他 Pod 中的容器通信,可以通过 IP 联网的方式实现。

      Pod 中的容器所看到的系统主机名与为 Pod 配置的 name 属性值相同 。

      • 总结:一个pod的容器之间通过本地回路(loopback)通信
        集群网络在不同的Pod之间提供通信
        Service 资源允许你 向外暴露 Pod 中运行的应用, 以支持来自于集群外部的访问。
        Ingress 提供专门用于暴露 HTTP 应用程序、网站和 API 的额外功能,简单来说就是用Ingress 可以让你在外部网络上访问到Pod里的资源。
    • Pod 存储
      • 一个 Pod 可以设置一组共享的存储卷。 Pod 中的所有容器都可以访问该共享卷,从而允许这些容器共享数据。 卷还允许 Pod 中的持久数据保留下来,即使其中的容器需要重新启动。
      • 扩展一下:
        • 卷:核心是一个目录,Pod中容器可以访问该目录中的数据;
        • 因为Container 中的文件在磁盘上是临时存放的,容器崩溃时文件会丢失;第二个原因同一个pod里面的不同Container会共享卷的内容。
        • 持久卷:(PersistentVolume,PV) 是集群中的一块存储,可以由管理员事先制备, 或者使用存储类(Storage Class)来动态制备。 持久卷是集群资源,就像节点也是集群资源一样。PV 持久卷和普通的 Volume 一样, 也是使用卷插件来实现的,只是它们拥有独立于任何使用 PV 的 Pod 的生命周期。

container 共享存储卷;

pod操作命令

  • kubectl get pod pod 列表

  • kubectl get pod -o wide 查看ip和node

  • kubectl discribe pod podname 查看pod详细信息

  • kubectl exec -it podname bash 进入pod

  • kubectl delete pod podname 删除pod

  • kubctl 通过API CMD 请求 到API SERVER ,然后由 scheduler 解析和转发到Controller Manager ,CM根据不同指令,实际应用到不同的node上的 kube-proxy ,由kube-proxy 转发到pod里面,由依赖的docker engine(构建);另外需要dashboard 监控网络,ECTD分布式组件 保存每个实例的运行状态,网络信息,这个是中心节点

yaml文件详解


# yaml格式的pod定义文件完整内容:
apiVersion: v1       #必选,版本号,例如v1
kind: Pod       #必选,Pod
metadata:       #必选,元数据
  name: string       #必选,Pod名称
  namespace: string    #必选,Pod所属的命名空间
  labels:      #自定义标签
    - name: string     #自定义标签名字
  annotations:       #自定义注释列表
    - name: string
spec:         #必选,Pod中容器的详细定义
  containers:      #必选,Pod中容器列表
  - name: string     #必选,容器名称
    image: string    #必选,容器的镜像名称
    imagePullPolicy: [Always | Never | IfNotPresent] #获取镜像的策略 Alawys表示下载镜像 IfnotPresent表示优先使用本地镜像,否则下载镜像,Nerver表示仅使用本地镜像
    command: [string]    #容器的启动命令列表,如不指定,使用打包时使用的启动命令
    args: [string]     #容器的启动命令参数列表
    workingDir: string     #容器的工作目录
    volumeMounts:    #挂载到容器内部的存储卷配置
    - name: string     #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
      mountPath: string    #存储卷在容器内mount的绝对路径,应少于512字符
      readOnly: boolean    #是否为只读模式
    ports:       #需要暴露的端口库号列表
    - name: string     #端口号名称
      containerPort: int   #容器需要监听的端口号
      hostPort: int    #容器所在主机需要监听的端口号,默认与Container相同
      protocol: string     #端口协议,支持TCP和UDP,默认TCP
    env:       #容器运行前需设置的环境变量列表
    - name: string     #环境变量名称
      value: string    #环境变量的值
    resources:       #资源限制和请求的设置
      limits:      #资源限制的设置
        cpu: string    #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数
        memory: string     #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
      requests:      #资源请求的设置
        cpu: string    #Cpu请求,容器启动的初始可用数量
        memory: string     #内存清楚,容器启动的初始可用数量
    livenessProbe:     #对Pod内个容器健康检查的设置,当探测无响应几次后将自动重启该容器,检查方法有exec、httpGet和tcpSocket,对一个容器只需设置其中一种方法即可
      exec:      #对Pod容器内检查方式设置为exec方式
        command: [string]  #exec方式需要制定的命令或脚本
      httpGet:       #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port
        path: string
        port: number
        host: string
        scheme: string
        HttpHeaders:
        - name: string
          value: string
      tcpSocket:     #对Pod内个容器健康检查方式设置为tcpSocket方式
         port: number
       initialDelaySeconds: 0  #容器启动完成后首次探测的时间,单位为秒
       timeoutSeconds: 0   #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
       periodSeconds: 0    #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
       successThreshold: 0
       failureThreshold: 0
       securityContext:
         privileged:false
    restartPolicy: [Always | Never | OnFailure]#Pod的重启策略,Always表示一旦不管以何种方式终止运行,kubelet都将重启,OnFailure表示只有Pod以非0退出码退出才重启,Nerver表示不再重启该Pod
    nodeSelector: obeject  #设置NodeSelector表示将该Pod调度到包含这个label的node上,以key:value的格式指定
    imagePullSecrets:    #Pull镜像时使用的secret名称,以key:secretkey格式指定
    - name: string
    hostNetwork:false      #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
    volumes:       #在该pod上定义共享存储卷列表
    - name: string     #共享存储卷名称 (volumes类型有很多种)
      emptyDir: {}     #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
      hostPath: string     #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
        path: string     #Pod所在宿主机的目录,将被用于同期中mount的目录
      secret:      #类型为secret的存储卷,挂载集群与定义的secre对象到容器内部
        scretname: string  
        items:     
        - key: string
          path: string
      configMap:     #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
        name: string
        items:
        - key: string
    --- 代表多个对象

官方参考:https://kubernetes.io/docs/reference/

关掉kubectl

kubectl delete deoplyment whoami-deployment

运行 kubectl

kubectl apply -f whoaim-deployment.yaml

查看运行节点

kubctl get pod -o wide

查看服务

kubectl get service
service 是负载均衡的

删除服务

kubectl delete service + 服务名

ReplicationController

作用:可以同时运行多个pod,按照配置的replicas数量 保持pod一直在这个数量运行,如果少了就会重新启动一个,多了就会删除一个。

查看ReplicationController(RC)

  • 查看 kubectl get ReplicationController
  • 删除 kubectl delete ReplicationController name
  • 扩容 kubectl scale rc nginx --replicas=5

ReplicaSet (RS)

支持多个条件的支持方式,RC的升级版,很少使用,被deployment替代

Deployment

  • 查看列表 kubectl get deployment -o wide
  • 查看 kubectl describe deployment name
  • 删除 kubectl delete deployment name
  • 更新镜像版本 kubectl set image deployment nginx-deployment nginx=ningx:1.9.1

    Label and Selectors

    打标签

  • 查看打的标签 kubectl get pods --show-labels
  • 打标签:kubectl label node w1 name=ingress

NameSpace

默认命名空间是default,资源名字在命名空间里是唯一的。namespace是多个用户之间划分集群资源的一种方法。

  • 查看当前命名空间 kubectl get namespace
  • 创建命名空间 :yaml文件里 name 就是命名空间
  • 把实例归属到命名空间:kubectl run nginx --image=nginx --namespace=存在的命名空间名字
  • 查找所有命名空间下的pod:kubectl get pods --all-namespaces
  • 查看命名空间下的pod:kubectl get pod -n namespace

Network

  • 同一个pod通信:docker网络通信 通过docker0虚拟网卡来通信的,k8s 同一个pod是通过pause容器来转发通信。
  • 不同的pod网络通信,外部的第三方网络模型 Calico
  • 通过service,转发到不同的pod
  • 外部访问pod,暴露接口到宿主机:kubectl expose deployment xxxx --type=NodePort,端口映射麻烦,通过Nginx 解决;
  • Ingress 也可以让外部访问pod,安装Ingress

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注