Kubernetes

Kubernetes(一)

K8S概述和特性

K8S基本介绍

K8S用于管理云平台容器化,使用K8S进行容器化部署.

K8S有利于应用扩展.

K8S的目标实施让部署容器化应用更加简洁和高效.

K8S功能

自动装箱

基于容器对应用运行环境的资源配置要求,自动部署应用容器.

自我修复

当容器失败时,会对容器进行重新部署和重新调度.

当容器未通过检查的时候,会关闭此容器,直到容器正常运行的时候才会对外开放服务.

image-20210201115940923

如果某个服务器上的应用不响应了.K8S会自动在其他地方创建一个

image-20210201120108167

水平扩展

通过简单的命令、用户UI界面或基于CPU等资源的使用情况,对容器应用进行规模扩大或者规模裁剪

需要处理大量的请求,可以通过增加副本的数量,从而达到水平扩展的效果.

服务发现

K8S不需要额外的服务发现机制(eureka、nacos).基于自身的能力实现 服务发现负载均衡

对外提供统一的入口,让它来做节点的调度和负载均衡,相当于 微服务里面的 网关.

image-20210201121359385

滚动更新

可以根据应用的变化,对应容器运行的应用,进行一次性或批量式的更新

在添加应用的时候不是马上启用,而要先去判断新增的应用是否能够正常使用

版本回退

可以根据应用部署的情况,对应用容器运行的应用,进行历史版本的回退.

类似Git的回滚

密钥和配置管理

在不需要构建新镜像的情况下,可以部署和更新密钥应用配置,类似热部署.

存储编排

自动实现存储系统的挂载和应用.对有状态的应用实现数据持久化非常重要.

存储系统可以来自于本地目录、网络存储(NFS)、公共云储存服务.

批量处理

提供一次性任务,定时任务.满足批量数据处理和分析的场景.

K8S架构组件

完整架构图

image-20210201122343100

image-20210201135100668

架构细节

K8S架构主要包含两部分: master(主控节点) 和 node(工作节点)

master节点架构图

image-20210201135441276

Node节点架构图

image-20210201135515359

K8S集群控制节点,对集群进行调度管理.接受集群外用户去集群操作请求.

  • maser:主控节点
    • API Server:集群统一入口,以restful风格进行操作,同时交给etcd存储
      • 提供认证、授权、访问控制、API注册和发现等机制
    • scheduler:节点的调度,选择node节点应用部署
    • controller-manager:处理集群中常规后台任务,一个资源对应一个控制器.
    • etcd:存储系统,用于保存集群中的相关数据.
  • work node:工作节点
    • kubelet: master派到node节点的代表,管理本机容器.
      • 一个集群中每个节点上运行的代理,它保证容器都运行在Pod中
      • 负责维护容器的生命周期,同时也负责Volume(CSI)和网络(CNI)的管理
    • kube-proxy:提供网络代理,负载均衡等操作.
  • 容器运行环境[container runtime]
    • 容器运行环境是负责运行容器的软件
    • K8S支持多个容器运行环境:Docker、container、cri-o、rktlet以及任何实现kubernetes CRI(容器运行环境接口)的软件.
  • fluentd:是一个守护进程,有助于提升 集群层面日志

K8S核心概念

Pod

  • Pod是K8S中最小的单元.
  • 一组容器的集合
  • 共享网络[一个Pod中的所有容器共享同一个网络]
  • 生命周期是短暂的(服务重启后,找不到了)

Volume

  • 声明在Pod容器中可以访问的文件目录
  • 可以被挂载到Pod中的一个或多个容器指定路径下
  • 支持多种后端存储抽象[本地存储、分布式存储、云存储]

Controller

  • 确保预期的pod副本数量 [ReplicaSet]
  • 无状态应用部署 [Depoltment]
    • 无状态是指,不需要依赖于网络或者ip
  • 有状态应用部署[StatefulSet]
    • 有状态需要特定的条件
  • 确保所有的node运行同一个pod [DaemonSet]
  • 一次性任务和定时任务 [Job和CronJob]

Deployment

  • 定义一组Pod副本数目、版本等
  • 通过控制器[Controller] 维持Pod数目 [自动恢复失败的Pod]
  • 通过控制器以指定的策略控制版本 [滚动升级、回滚等]

image-20210201164414281

Service

定义一组pod的访问规则

pod的负载均衡,提供一个或多个pod的稳定访问地址

支持多种方式 [ClusterIP、NodePort、LoadBalancer]

image-20210201165328828

可以用来组合pod,同时对外提供服务.

label

label: 标签,用于对象资源查询,筛选

image-20210201174246734

Namespace

命名空间,逻辑隔离

  • 一个集群内部的逻辑隔离机制 [鉴权、资源]
  • 每个资源都属于一个namespace
  • 同一个namespace所有资源不能重复
  • 不同的namespace可以资源名重复

API

我们通过K8S的API来操作整个集群

同时我们可以通过kubectl、ui、curl最终发送http + json/yaml 方式的请求给API Server,然后控制整个K8S集群,K8S中所有的资源对象都可以采用 yaml 或 json 格式的文件定义或描述.

例: 使用yaml部署一个nginx的pod

image-20210202092956877

完整流程

image-20210202093232805

通过kubectl提交一个创建RC(Replication Controller) 的请求,该请求通过APIserver写入etcd

此时controller manager 通过API Server的监听资源变化的接口监听到此RC事件

分析之后,发现当前集群中还没有它所对应的pod实例

于是根据RC里的Pod模板定义一个生产Pod对象,通过APIServer写入etcd

此事件被scheduler发现,它立即执行一个复杂的调度流程,为这个新的Pod选定一个落户的Node,然后通过API Server将这一结果写入到etcd中.

目标Node上运行的kubelet进程通过API Server监测到这个“新的Pod”,并按照它的定义,启动该pod并负责到底,直到这个Pod的生命周期结束.

随后,我们通过kubectl提交一个新的映射到该Pod的Service的创建请求

ControllerManager通过Label标签查询到关联的Pod实例,然后生成service的endpoints信息,并通过APIServer写入到etcd中.

接下来,所有node上运行的proxy进程通过APIserver查询并监听service对象与其对应的endpoints信息,建立一个软件方式的负载均衡器来实现service访问到后端Pod的流量转发功能.

核心技术Pod

Pod概述

pod是K8S可以创建和管理的最小单元,是资源对象模型中由用户创建或部署的最小资源对象模型,也是在K8S上运行容器化应用的资源对象,其他的资源对象都是用来支撑或者扩展Pod对象功能的.

比如:

控制器对象 是用来管理Pod对象的.

Service或者ingress资源对象 是用来暴露Pod引用对象的.

PersistentVolume资源对象 是用来为Pod 提供存储的

K8S不会直接处理容器,而是通过Pod.Pod 是由一个或者多个容器组成的.

Pod是K8S最重要的概念,每个Pod都有一个特殊的被称为“根容器”的pause容器.

pause容器对应的镜像属于K8S平台的一部分,除了pause容器,每个pod还包含一个或者多个紧密相关的用户业务容器.

image-20210203135533106

Pod的基本概念

  • 最小的部署单元
  • Pod里面由一个或者多个容器组成[一组容器的集合]
  • 一个Pod中的容器 是共享网络 命名空间
  • Pod是 短暂的
  • 每个Pod包含一个或多个紧密相关的用户业务容器

Pod存在的意义

  • 创建容器使用的是docker,一个docker对应一个容器,一个容器运行一个应用进程.
  • Pod是多进程设计,运用多个应用程序,也就是一个Pod里面有多个容器,而一个容器里面运行一个应用程序.

image-20210203140616037

  • Pod的存在就是为了亲密性应用.
    • 两个应用进行交互
    • 两个网络之间调用 [通过127.0.0.1 或者 socket]
    • 两个应用之间需要频繁调用

Pod是在K8S集群中运行部署应用或服务的最小单元,它是可以支持多容器的.Pod的设计理念是支持多个容器在Pod中共享 网络 和文件系统,可以通过 进程通信 和 文件共享这种简单高效的方式组合完成服务.同时Pod对多容器的支持是K8S中最基础的设计理念.

在生产环境中,通常各自开发构建自己的 容器镜像,在部署的时候组合成一个微服务对外提供服务.

Pod是K8S集群中所有业务类型的基础,可以把pod看作是运行在K8S上集群的小机器人,不同类型的业务就需要不同类型的小机器人去执行.

目前K8S的业务可以分为以下几种

  • 长期伺服型: long-running
  • 批处理型: batch
  • 节点后台支撑型: node-daemon
  • 有状态应用型: stateful application

上述几种类型,分别对应小机器人控制器为: deployment、job、daemonSet和statefulSet

Pod的实现机制

主要有两大机制

网络共享

文件存储

共享网络

容器之间是互相隔离的,一般是通过 namespacegroup 进行隔离,Pod里面的容器如何实现通信?

​ 首先需要满足在同一个 namespace 之间

关于Pod的实现原理,首先会在Pod中创建一个根容器:pause容器.

然后在我们创建业务容器 [nginx和redis] 的时候,会把它添加到 info 容器中.

而在 info容器中 会独立 ip地址、mac地址、prot信息.然后实现网络共享.

image-20210203145139188

同pause容器,把其他业务容器加入到 info 容器中,让所有业务容器在同一个命名空间中,实现网络共享.

共享存储

Pod持久化数据,专门存储到某个地方中.

image-20210203145802698

使用 volume 容器数据卷进行共享储存

image-20210203145949565

Pod镜像拉取策略

拉取策略就是 imagePullPolicy

image-20210203150752502

拉取策略主要分为几种:

  • IfNotPresent: 默认值,镜像在宿主机上 不存在,才拉取.
  • Always: 每次创建Pod都会重新拉取一次镜像.
  • Never: Pod永远不会主动拉取这个镜像.

Pod资源限制

也就是我们Pod在进行调度的时候,可以对调度的资源进行限制.例如我们限制Pod调度的资源是2c4g,那么在调度对应的node节点时,只会占用对应的资源.对于不满足资源的节点,将不会进行调度.

image-20210203152102752

资源限制:

image-20210203152302077

这里分了两个部分.

  • request: 表示调度所需要的资源
  • limits: 表示最大所占用的资源

Pod重启机制

因为Pod包含了很多个容器,假设某个容器出现问题了,那么会触发Pod重启机制.

image-20210203152626955

重启策略主要分为3种:

  • Always: 当容器重启退出后,总是重启容器,默认策略.[nginx等,需要不断提供服务]
  • OnFailure: 当容器异常退出(退出状态码 !0)时,才重启容器.
  • Never: 当容器终止退出时,从不重启容器.[批量任务]

Pod健康检查

通过容器检查,原来我们使用下面的命令来检查

kubectl get pod

但是有的时候,程序可能出现了java堆栈内存溢出,程序还在运行,但是不能对外提供服务了.这个时候不能通过容器检查来判断服务是否可用.

使用应用层面的检查

1
2
3
4
5
# 存活检查,如果检查失败,将杀死容器.根据pod的restartPolicy[重启策略]来操作
livenessProbe

# 就绪检查,如果检查失败,k8s会把Pod从service endpoints中剔除
readinessProbe

image-20210203154150646

Probe支持以下三种检查方式

  • http Get: 发送http请求,返回200 - 400范围的状态码为成功.
  • exec: 执行shell命令状态码返回是0为成功.
  • tcpSocket:发起TCP Socket建立成功

Pod调度策略

创建Pod流程
  • 首先创建一个Pod,然后创建一个API Server 和 Etcd[把创建出来的信息储存在Etcd中]
  • 然后创建 Scheduler,监控API Server是否有新的Pod.如果有的话,会通过调度算法,把Pod调度到某个node上.
  • 在node节点,会通过 kubelet --apiserver读取etcd 拿到分配在当前node节点上的pod,然后通过docker创建容器.

image-20210203160432370

影响Pod调度的属性

Pod资源限制会对Pod的调度有影响.

根据request找到足够的node节点进行调度

image-20210203160748355

节点选择器标签影响pod调度

image-20210203161512460

关于节点选择器,其实就是有两个环境,然后环境之间所用的配置资源不同.

image-20210203161749628

我们可以通过以下命令,给节点新增标签,然后节点选择器就会根据标签进行调度

1
kubectl label node node1 env_role=prod

节点亲和性

节点亲和性 nodeAffinity和 之前的nodeSelector基本一样,根据节点上的标签约束来决定Pod调度到哪个节点上.

  • 硬亲和性: 约束条件必须满足
  • 软亲和性: 尝试满足,不保证

image-20210203172213630

支持常用操作符: in、NotIn、Gt、Lt、DoesNotExists

反亲和性:就是和亲和性刚刚相反.如 NotIn、DoesNotExists等

污点和污点容忍

概述

nodeSelector 和 NodeAffinity,都是prod调度到某个节点上的,属于pod属性,是在调度的时候实现的.

Taint污点:节点不做普通分配调度,是节点属性.

场景

专用节点[限制ip]

配置特定硬件的节点[固态硬盘]

基于Taint驱逐[在node1不放,在node2放]

查看污点情况

1
kubectl describe node k8smaster | grep Taint

污点值有三个

  • NoSchedule: 一定不被调度.
  • PreferNoSchedule: 尽量不被调度.
  • NoExecute: 不会调度,并且还会驱逐node已有的Pod

末节点添加污点

1
kubectl taint node [node] key=value:污点的三个值

例如:

1
kubectl taint node k8snode1 env_role=yes:NoSchedule

删除污点

1
kubectl taint node k8snode1 env_role:NoSchedule-

污点容忍

污点容忍就是某个node可能被调度也可能不被调度.