一切福田,不離方寸,從心而覓,感無不通。

《K8S权威指南》读书笔记-入门篇

一. k8s介绍

1. 是什么

  • kubernetes:古希腊“舵手”的意思(指引鲸鱼-docker)
  • Production-Grade Container Orchestration:生产级别的容器编排系统
  • is an open-source system for automating deployment, scaling, and management of containerized applications:用于自动部署,扩展和管理容器化应用程序的开源系统

2. 发展历程

  • google内部使用十年之久的大规模机器管理系统-Borg,k8s是其他开源版本。
  • 2014年6月 谷歌在旧金山的发布会为这款新的开源工具揭牌
  • 2015年4月:google发布论文,高调宣传k8s
  • 2015年7月:发布1.0版本
  • 2015-2016:1.0-1.5,主要发布了五个版本
  • 2017年: 相继推出 1.6、1.7、1.8、1.9,围绕稳定性、性能和平台的 cloud availability 做了改进
  • 2018年3月27日,v1.10 发布。此版本持续增强了 Kubernetes
  • 2018年6月28 日,v1.11 发布。此版本增强了网络功能、可扩展性与灵活性。Kubernetes 1.11 功能的更新为任何基础架构、云或内部部署都能嵌入到 Kubernetes 系统中增添了更多可能性的成熟性、可扩展性以及可插拔性,并在存储、安全、网络增强了其稳定性
  • 2018年9月28日,v1.12 发布。此版本新增了两个备受期待的功能,Kubelet TLS Bootstrap 和对 Azure 虚拟机规模集支持(并已达到 GA 阶段)。同时该版本在安全性和 Azure 等关键功能上作出了改进;
  • 2018年12月4日,v1.13发布。此版本的三个主要特性已逐渐过渡到 GA。此版本中的显着特征包括:使用 kubeadm 简化集群管理、Container Storage Interface(CSI)、以 CoreDNS 作为默认 DNS
  • 大约每100天更新一次,如今已是 V 1.15.0版本(2019.7.17)

3. 特点

  • 一切以服务为中心
  • 自动化:自我扩展、自我诊断
  • 底层不仅仅依赖docker,还支持Rocket
  • 不局限于语言,对现有代码、框架没有任何侵入

4. 功能

  • 基于容器的、一站式的分布式平台和分布式解决方案
  • 主要功能是生产环境的容器编排,包括:
    • 滚动升级
    • 在线扩缩容
    • 资源自动调度
    • 资源配额管理
    • 服务注册、服务发现
    • 负载均衡
    • 故障发现和自我修复

5. 为什么要用k8s

  • 容器逐渐替代宿主机,k8s是业界广泛认可和看好的容器分布式解决方案
  • 轻装上阵开发业务系统,k8s帮我们做了很多底层的事
  • 全面拥抱微服务
  • 平滑的在公有云、私有云、混合云等环节迁移
  • 超强的横向扩展能力

二. 安装和用法

安装

参考我的另一篇文章:Centos7安装k8s集群1.15.0版本

基本用法

  • k8s主要通过命令行工具kubectl执行各种命令
  • kubectl解析命令行,并生成http请求发送给k8s中master节点的apiserver
  • kubectl不一定要安装在k8s集群中,可单独安装在任何机器,然后配置k8s的config文件,就可以和该k8s交互
  • kubectl常用命令,参考:

三. k8s简单的demo

四. 基本概念

1. Container

  • Container(容器)是一种便携式、轻量级的操作系统级虚拟化技术
  • 它使用 namespace 隔离不同的软件运行环境
  • 通过镜像自包含软件的运行环境,从而使得容器可以很方便的在任何地方运行
  • 容器体积小且启动快,因此可以在每个容器镜像中打包一个应用程序

2. Pod

  • Kubernetes 使用 Pod 来管理容器
  • 每个 Pod 可以包含一个或多个紧密关联的容器
  • 共享 PID、IPC、Network 和 UTS namespace
  • 是 Kubernetes 调度的基本单位
  • 更多信息参考后面的资源对象部分
pod

3. Node

  • Node 是 Pod 真正运行的主机,可以是物理机,也可以是虚拟机
  • 每个 Node 节点上至少要运行 container runtime(比如 docker 或者 rkt)
  • 集群工作节点,负责真正启动容器
  • Node向Master注册,并定期汇报自身信息
  • 包括的组件有:
    • kubelet:pod生命周期管理:创建、删除、启停、扩缩容
    • kube-proxy:service通讯与负载均衡
    • Docker引擎:容器创建与管理

4. Master

  • 集群控制节点,负责集群管理和控制
  • 包括的组件有:
    • kube-apiserver:所有资源增删改查的唯一入口
    • controller-manager:资源对象的自动化控制,保持"实际状态“处于”期望状态“
    • kube-scheduler:负责资源的调度

五. 资源对象

概述

  • k8s中大部分概念,如Node,Pod,Service都可以看做一种资源对象
  • 资源的描述:yaml文件或json文件
  • 资源的操作:对象可以通过kubectl(或者api)执行增、删、改、查
  • 资源的存储:信息在etcd中持久化
  • 重要的资源:Pod,Service

k8s通过对比资源的“实际状态”和etcd中的“期望状态”,实现自动化控制

  • 常用资源概述图

1. Pod

1.1 概述

  • Pod是k8s中最重要最基本的资源
  • pod是在容器之外又封装的一层概念
  • pod是容器调度的基本单元(不是docker容器)
  • 每个pod包含一个特殊的根容器:Pause容器,和一个或多个业务容器
  • 每个pod有唯一的ip,pod内的容器可通过localhost通讯

为什么要新增pod这个概念?

  1. 一组容器作为一个单元,很难判断整体状态,以及对整体进行管控。新增业务无关的pause容器,用于管控整体
  2. 简化了关联容器通信和共享的问题

1.2 pod整个生命周期的状态:

  • Pending:已经创建pod,pod正在创建,大部分是在拉取镜像
  • Running:pod内容器都已经创建,至少一个处于运行状态
  • Succeeded:pod内容器执行成功并退出,不会再重启
  • Failed:pod内容器都已退出,至少有一个处于失败状态
  • Unknown:无法获取pod信息,比如网络不通

1.3 kubelet重启pod的策略

  • Always:容器实效时,kubelet重启该容器
  • OnFailure:容器终止运行且退出码不为0,kubelet重启该容器
  • Nerver:无论如何都不重启

1.4 kublet重启pod的时间机制

  • 以2的指数倍秒增长,最大重启时间间隔为5min
  • 成功重启10min后重置该时间

1.5 pod调度控制

  • k8s中通过RC,Deployment等资源控制pod全自动调度(后面会介绍)

2. Label

  • Label是key=value的键值对
  • Label由用户自由指定,数量也不定
  • Label可被添加到任意资源上
  • 通过指定不同的label,对资源进行多维度管理
  • Label的重要使用场景:
    • controller通过筛选Pod的label,实现pod的数量一直是预期的
    • proxy通过筛选Pod的label,实现请求路由转发和负载均衡
    • scheduler通过筛选Node的label,实现pod定向调度
    • istio通过筛选namespace的label,实现sidecar自动注入

3. Replication Controller

  • 已经不推荐使用了,用Deployment代替
  • 实现pod的自动创建和数量控制
  • 用于定义pod的期望场景,包括:
    • 副本数
    • 模板
    • Label选择器:用于筛选目标
  • RC请求发送后,底层由Controller-Manager组件完成pod自动运维

4. Replica Sets

  • RC的升级版本
  • 支持集合的Label选择,不仅仅是等式Label选择

5. Deployment

  • RC的再次升级版本,为了更好的解决Pod编排
  • 可以随时知道Pod的部署进度
  • Deployment的使用场景包括:
    • 创建Deployment来生成Replia Set对象,并完成pod创建
    • 检查pod数量是否达到预期
    • 更新Deployment,创建新的pod

6. HPA

  • Pod的横向自动扩容
  • 通过自动追踪Pod的负载情况,自动调整pod数量
  • 负载判断指标包括:
    • 内置的cpu使用量
    • 自定义指标

7. Service

  • pod异常时,可能会被调度到另一台机器,导致pod的ip改变,使用ip访问服务不可靠

7.1概述

  • k8s里最核心的资源之一,类似微服务架构中的“微服务”
  • 前端应用通过入口地址访问服务,服务通过label对接到后端的pod
  • kube-proxy负责把service请求转发到后端,并做负载均衡
  • service整个生命周期内,ClusterIp不会变,对外提供的服务地址也就不会变
  • service通过label找到pod,即使pod的ip变了

7.2 服务发现

  • 最开始k8s采用linux系统环境变量,实现服务发现
  • 后来采用kube-dns插件实现服务发现
  • 新版本已经用CoreDNS代替kube-dns

7.3 外部系统访问service

先区分不同ip:

  • NodeIp:Node节点的Ip地址,k8s节点的真实ip地址
  • PodIP:pod的ip地址,docker网桥分配的地址
  • ClusterIP:服务ip地址,虚拟出来的ip,属于内部ip,外部无法直接访问

clusterIp无法被k8s集群外部访问,用户如何访问呢?

  • 方法一:指定service的port类型为NodePort。k8s在每个Node上开启一个tcp端口,外部通过Node的ip地址,加这个端口就可以访问
  • 方法二:方法一无法做到负载均衡,k8s提供了相应接口。公有云厂商可以去实现。然后type改为LoadBalancer

7.4 负载均衡

k8s提供两种负载均衡策略:

  • RoundRobin:轮询模式,默认模式
  • SessionAffinity:ip地址会话保持,统一ip的客户只会访问同一个pod

7.5 自定义负载均衡

  • 设置service的clusterIP属性为None
  • 称为Headless Service,无头服务
  • 使用场景:比如kafka配置的zk,就可以设置为无头服务

7.6 访问外部服务

  • 首先定义一个不带标签选择器的service(这时无法选择后端pod)
  • 然后定义一个和该service同名的kind为Endpints的资源,subset属性指定外部的ip地址和端口

8. Ingress

service提供了ip:port的访问方式,即工作在tcp/ip层,而http服务需要将不同的url对应到不同的后端服务,service是无法实现这一功能的。

  • Ingress提供http层的负载分发功能
  • Ingress可以实现不同的请求,分发到不同的后端服务
  • Ingress定义后,需要结合Ingress Controller,才能形成完整的功能

8.1 Ingress Controller定义

  • 可以使用公有云提供的Ingress Controller
  • 也可以使用google提供的Ingress Controller,以pod形式运行,功能如下:
    • 监听apiserver,获取ingress的定义
    • 基于ingress定义,生成nginx的配置文件的内容
    • 执行nginx -s reload,重新加载配置

8.2 Ingress定义

  • 创建类型为Ingress的yaml文件
  • 配置spec.rules,指定hostname中url和service的对应关系

9. Volume

  • volume是pod中被多个容器访问的共享目录
  • pod启动或停止时,volume中数据不会丢失
  • 支持多种类型存储,如:clusterFS,ceph

volme类型包括:

  • emptyDir:k8s在pod上创建的临时目录,pod移除时,目录也被删除
  • hostPath:在pod上挂载宿主机上的文件和目录
  • gcePersistentDisk:谷歌公有云存储
  • awsElasticBlockStore:亚马逊提供的公有云存储
  • nfs:需要部署一个nfs server
  • glusterfs:一个开源的分布式文件系统
  • rbd:linux块设备共享共享

10. Persistent Volume

  • pv是k8s中某个网络存储中对应的一个块存储
  • pv只能是网络存储,不属于某个node,但是node可以访问
  • pv需要单独定义,不是定义在pod之上
  • pv支持的类型包括:NFS、ClusterFS、Ceph、GCE、RBD等
  • pv的accessModes属性指定了访问模式
    • ReadWriteOnce:读写,只能被单个Node挂载
    • ReadOnlyMany:只读,允许被多个Node挂载
    • ReadWriteMany:读写,允许被多个Node挂载
  • pod想要使用pv,先要定义一个pvc。pvc指定使用哪个pv,pod再指定使用哪个pvc

11. Namespace

  • 命名空间用于实现多租户的资源隔离
  • 集群启动会默认创建default的namespace,不特殊指定的资源都属于default

12. Annotation

  • 注解与label类似,也使用key-value形式定义
  • 注解没有严格的命名规则
  • 用户可定义任意的附加信息,供外部查询

13. ConfigMap

  • 提供统一的集群配置管理方案
  • 内容为key:value形式,保存在k8s中。value不仅可以是数值、字符串,还可以是配置文件等
  • 典型应用:
    • 生成为容器内的环境变量
    • 设置为容器启动命令的启动参数
    • 以volume形式挂载为容器的目录
  • 使用方式:
    • yaml中指定spec.container.env.valueFrom.configMapRef.key
    • yamnl中指定spec.volumes.configMap.name
  • 使用注意:
    • 必须在创建pod前创建好
    • 可以属于某个namespace

五. 架构介绍

k8s架构图

  • 简版架构图

  • 数据流转图
k8s架构图

1. Master节点的组件

apiServer

  • 提供资源操作的唯一入口,提供api注册、发现、认证、访问控制等功能

etcd

  • 一个key-value数据库
  • 保存整个机器的状态

controller-manager

  • 负责维护机器状态,比如:自动扩容、故障检查、滚动更新
  • 实现集群自动化的关键组件

scheduler

  • 负责资源调度
  • 将未分配节点的pod调度到合适的节点上

2. Node节点的组件

kubelet

  • 负责容器生命周期管理,比如:创建、删除
  • 同时负责Volume,网络的管理

kube-proxy

  • 负责为Service提供负载均衡、服务发现

Container Runtime

  • 容器运行环境
  • 默认是Docker,同时还支持其他容器引擎

参考文献

作者:kinnylee
链接:https://juejin.cn/post/6844903892963049485
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。