k8s基础

本文是学习ali云的云原生课程的记录,目的是对基础概念的理解
原课程

K8S核心概念

架构

  • K8S的架构是CS架构:
    架构-1.png

  • master的结构如下:
    master结构.png

    • Api Server不仅是外部访问k8s的入口,也是k8s各组件内部的枢纽
    • Scheduler用于调度deployment的pod在哪个node节点运行
    • Controller用于控制状态,做一些检测,确定集群运行正常,当有节点宕机,将其上的pod运行到其他节点上。
    • etcd是一个分布式数据库
  • node的结构如下:
    master结构.png

    • pod翻译是豆荚,是k8s对容器的一种封装
    • kubelet,是node下的控制,接收自master的命令,运行pod
    • Container Runtime,容器运行环境,是容器实际运行的地方
    • storage plugin,存储插件,是云计算厂商实现的存储接口
    • network plugin,网络插件,同样也是云计算厂商实现
    • kube-proxy,是位置k8s内部service集群的代理
  • 示例
    一个例子.png

    这个例子是有一个pod要运行,先与api server进行交互,api server进行存储,然后交给scheduler进行调度,scheduler根据目前集群的状态,计算该pod运行的位置,并经过api server进行存储,下发给node上的kubelet,kubelet再在container Runtime下运行起相应的pod(容器)

核心概念

  • Pod

    pod.png

    • k8s最小的调度及资源单元
    • 由一个或多个容器组成
    • 为这些容器,提供共享的资源(网络、进程空间)
  • Volume

    • 声明再Pod中的容器可访问的文件目录
    • 支持多种后端存储的抽象:本地存储、分布式存储、云存储
  • Deployment

    • 部署的概念,定义一组pod的副本数、版本等。意思是告诉k8s,我想要这种状态。
    • k8s通过scheduler调度pod运行的节点
    • 通过Controller维持想要的这种状态,包括自愈,版本控制
  • service

    service.png

    既然服务可以运行多个容器,这些容器对外提供服务就需要用稳定的访问地址,service就是为多个pod而建立稳定的虚拟ip。

  • Namespaces

    namespace.png
    集群内部的逻辑隔离机制,每个资源都属于一个Namespace
    上述的概念都可认为是一种资源,namesapce为一套K8S运行多个产品做好了铺垫

API

api基础.png

Pod

Pod概念

  • 容器
    容器是一个试图被隔离、资源受限的进程(linux线程)
    容器里PID = 1的进程就是应用本身
    容器是单进程模型

  • k8s
    k8s是对容器的编排,等价于操作系统

  • pod
    pod中的容器共享一些资源,可以任务是进程组(linux进程)

    两个docker应该运行在以pod上时,应该有超亲密关系:

    • 会发生直接的文件操作
    • 通过localhost进行本地同喜
    • 非常频繁的rpc调用

实现机制

共享网络.png

通过Infra Container的方式来共享一个Network Namespace,将网络放到Infa Contanier中,也使得一个pod只有一个ip地址,整个pod的生命中期与infra container一致。

使用方式

  • InitContainer
    pod中的InitContainer按用户定义的顺序依次启动,其他容器并发启动,并且InitContainer运行完成后自动退出。
    用InitContainer来执行一些配置、预先准备资源的任务。

  • SideCar
    用边车来执行一些辅助且通用的工作,如:

    • 日志收集
      日志收集.png

    • 应用监控
      应用监控.png

应用编排

控制的核心

资源对象

  • spec:期望的状态
  • status: 观测到的状态
  • metadata

    • Lables
      key-value形式的标签,用于筛选资源,
      Selector: Tie=front

      Selector:
      Env in (test, gray)
      Tie notin (front, back)

    • Annotations
      存储资源的非标识性信息,可以包含特殊字符

    • OwnerReference
      资源创建者对象,如pod一般的所有者是replicas

控制

  • 控制循环
    控制循环.png
    主要是2部分:sensor、controller,不断使status趋近spec

  • sensor部分
    sensor部分.png
    通过不断的list & watch来获取变化,通过informer通知给controller部分来处理

  • controller部分
    controller.png
    hander发出指令,woker进行操作。

  • 示例:
    控制示例-1.png
    控制示例-2.png
    控制示例-3.png

deployment

本节应该算是运维重点

  • 用处
    定义一组pod的spec数量,controller会维持status与spec一致
    配置pod的发布方式,controller会暗中给定策略更新pod,保证发布过程可用
    如有发布问题,支持一键回滚

  • 基础
    deployment语法.png
    replicas: 期望的数量;
    template: pod模板

    deployment只负责管理不同版本的replicaSet,由ReplicaSet管理Pod副本数。每个ReplicaSet对应 deployment的一个版本,每个ReplicaSet下的pod都是相同的版本
    replicaSet与pod.png

  • 发布
    deployment扩容.png

  • 扩容
    发布模拟.png

  • 快速回滚
    kubectl rollout undo deployment/nginx-deployment // 回滚到上一版本

    kebectl rollout undo deployment.v1.apps/nginx-deployment –to-revision=2 // 回滚到固定版本

    回滚模拟.png

  • 控制字段

    • revisionHistroyLimit:保留历史resion(ReplicaSet)的数量,默认10
    • paused: 标志Deployment只做数量维持,不做新的发布
    • progressDeadlineSeconds: 判断deloyment失败的最大时间
    • MaxUnavailable: 发布过程中最多的pod不可用数目
    • MaxSurge: 发布过程中最多存在多少个Pod超过期望replicas数量

Job

  • 普通job

    Job可以看做是直接运行的任务进程,执行某种计算,完成之后就停止。

    Job示例.png
    用pod执行一个计算pi的任务

    在spec中指明

    • completions: 代表这个job执行的总次数
    • parallelism: 代表并发的个数

    kubectl get jobs

  • cronJob

    定时运行的job,与linux的cron相似
    cronJob.png

daemonSet

  • 用处
    如同守护进程类似,可以用来:

    • 保证集群每一个(或一些)节点都运行一组相同的Pod
    • 跟踪集群节点状态,保证新加入的节点自动创建对应的pod
    • 跟踪集群节点状态,保证移除的节点删除对应的pod
    • 跟踪pod状态,保证每个节点pod处于运行状态
  • 示例

deamonSet.png

应用配置

ConfigMap

主要管理容器运行所需的配置文件,环境便利,命令行参数等可变配置。用于解耦镜像和可变配置,从而保证pod的可移植性。

  • yml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    kind: ConfigMap 
    apiVersion: v1
    metadata:
    name: example-configmap
    data:
    # Configuration values can be set as key-value properties
    database: mongodb
    database_uri: mongodb://localhost:27017

    # Or set as complete file contents (even JSON!)
    keys:
    image.public.key=771
    rsa.public.key=42
  • 创建
    kubectl apply -f config-map.ymal

  • 使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    kind: Pod 
    apiVersion: v1
    metadata:
    name: pod-env-var
    spec:
    containers:
    - name: env-var-configmap
    image: k8s.gcr.io/busybox
    command: ["/bin/sh", "-c", "env"]
    envFrom:
    - configMapRef:
    name: example-configmap
  • 说明

    1. ConfigMap文件大小限制:1MB(ETCD限制)
    2. Pod只能引用同Namespace中的ConfigMap

Secret

Secret是用在集群中用于存储密码,token等敏感信息的资源对象,使用base-64编码

  • yml
    secret.png

  • 创建
    kubectl apply -f ~/kube/hello/registry-secret.yaml

  • 使用
    secret使用.png
    secret使用一般通过volume挂载到指定容器目录,供容器中业务使用。

ServiceAccount

secviceAccount主要用于解决Pod在集群中的身份认证问题。认证使用的授权信息,利用Secret

  • yml
    serviceAccount.png

  • 示例:私有镜像仓库
    私有镜像仓库.png

资源

主要是pod中配置所需要的cpu、memory、外存等

  • yml
    resource.png

  • 说明
    resource2.png

应用存储

存储与容器的隔离,pod的生命周期与volume的生命周期解耦

核心知识

  • 概念

    static volume provisioning: pv是静态的,当用户提交pvc,从静态中匹配合适的pv,这种容易找不到合适的pv staticVolumeProvisioning.png

    dynamic volume provisioning: 通过storage class分配pv的模板,K8s根据pvc与sc自动创建pv
    dynamicVolumeProvisioning.png

  • 示例1
    pod中的多个容器共享一个volume

    pv示例1.png

    • spec.volumes声明pod的volume
    • spec.containers.volumeMounts声明container如何使用volume
    • 多个container共享volume时,可以使用spec.containers.volumeMounts.subPath隔离不同容器上数据存储的路径
  • 示例2
    static volume provisoning

    pv示例2.png

    pv示例2-2.png

    pv示例2-3.png

  • 示例3
    dynamic volume provisioning

    系统员创建sc
    pv示例3-1.png

    pv示例3-2.png

    pv示例3-3.png

  • 字段

    AccessModes:PV访问策略控制,必须同PVC的访问策略控制匹配才能绑定

    ReadWriteOnce:只允许单node访问
    ReadOnlyMany:允许多node只读访问
    ReadWriteOnly:允许多node读写访问
    

    PersistentVolumeReclaimPolicy: PV被release之后再回收策略

    Delete:删除
    Retain:默认策略,保留
    

    StorageClassName:动态时,可以通过对应的storageClass动态生成新pv对象
    NodeAffinity: 限制可以访问该volume的node,影响使用该volume的pod调度

  • pv状态机
    pv状态机.png
    pv状态release后,无法再通过Reclaim Policy回收,而再次绑定新的PVC。原文给出2种方式,我觉得后一种比较靠谱一些:
    直接从PVC对象服用,即不unbound PVC和PV。statefulSet处理存储状态的原理。

  • pvc与node流程分析
    pvc-node流程-1.png
    pvc-node流程-2.png

存储快照

存储快照主要是数据的恢复与数据复制迁移场景

  • 基本概念
    存储快照基本概念.png

  • 示例
    存储快照示例.png

  • 流程
    存储快照流程.png

拓扑调度

拓扑调度应用场景是对volume的调度

  • 定义
    拓扑是针对k8s中node位置关系的一种人为划分,通过再node的labels中设置,以标志自己属于具体的拓扑域.3种拓扑域:

    • kubernetes.io/hostname => node范围
    • failure-domain.beta.kubernetes.io/region => Region范围
    • failure-domain.beta.kubernetes.io/zone => Zone范围
  • 背景
    k8s通过pvc与pv讲存储与计算分离,但有的存储有位置的限制,只能在特定的node上才能访问pv,这就需要拓扑域,来对node运行进行调度。如loval PV只能在制定的Node上被pod使用

  • 本质
    pv在binding或dynamic provision时,并不知道它会被哪些node所使用,而pv本身是有node限制的

    这样将binding或者dynamic provision pv的操作延迟到pod调度结果确定之后。再pod调度时,会根据pvc的要求,选择合适的node,然后再去做pv与pvc的binding或者pv的dynamic provision

  • local PV示例
    localpv示例.png

  • dynamic provision pv示例
    dynamicProvisionPv示例.png

网络基础

基本约束

k8s对Pod间的网络没有多少限制,但需要满足3个基本条件:

  • 所有Pod可以与其他Pod直接通信,无需显示使用NAT
  • 所有Node可以与所有Pod直接通信,无需显示使用NAT
  • Pod课间的IP地址确为其他Pod与其通信时所用,无需显示转换

    这就有4个方面:

  • 容器与容器间通信
  • Pod与Pod间通信
  • Pod与Service间通信
  • 外部与Service的通信

Netns

  • 本质
    netns.png

  • pod与netns的关系
    每个Pod拥有独立的Nets空间,Pod内的Container共享该空间。宿主机本身有一个Root Netns

    pod与netns.png

  • 典型的容器网络实现方案
    容器网络方案.png

service

  • k8s 服务发现

    由于pod生命周期短暂,IP地址随时变化,而deployment时pod组需要统一访问入口和负载均衡,所有需要Service

    service服务发现与负载均衡.png

  • 示例

    service-1.png
    service-2.png
    service-3.png

  • 集群外暴露Service
    向集群外暴露Service.png

可观测性

探测

  • 背景
    k8s如何知道应用运行是否正常?

  • liveness与readness
    通过liveness探测确定应用是否存活;
    通过readness探测确定应用是否就绪

    探测方式:
    httpGet、Exec脚本、tcpSocket

  • probe示例
    探测示例.png

  • 故障排查
    故障排查.png

监控

  • 类型

    资源监控:CPU、内存、网络等资源类的指标
    性能监控:通过Hook的机制在虚拟机层、字节码执行层隐式回调,或者在应用层显示注入,用来调优
    安全监控
    事件监控

  • k8s监控接口标准

    k8s提供了3种不同的metrics接口标准:
    监控接口标准.png

    注意这里k8s提供的是标准,而不是实现。
    Prometheus:开源社区的监控标准

日志

  • 类型
    主机内核的日志
    容器docker的日志
    k8s核心组件的日志
    部署应用的日志

    他们可以是宿主机文件,也可能是容器内文件,或者容器标准/错误输出的文件
    可以通过边车模式,用logging-agent-pod来读取文件

  • Fluentd日志采集方案
    日志采集方案.png