一. 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
- 参考另一篇文章,将hello-world发布到k8s集群。springboot版本helloworld发布到k8s示例
四. 基本概念
1. Container
- Container(容器)是一种便携式、轻量级的操作系统级虚拟化技术
- 它使用 namespace 隔离不同的软件运行环境
- 通过镜像自包含软件的运行环境,从而使得容器可以很方便的在任何地方运行
- 容器体积小且启动快,因此可以在每个容器镜像中打包一个应用程序
2. Pod
- Kubernetes 使用 Pod 来管理容器
- 每个 Pod 可以包含一个或多个紧密关联的容器
- 共享 PID、IPC、Network 和 UTS namespace
- 是 Kubernetes 调度的基本单位
- 更多信息参考后面的资源对象部分
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这个概念?
- 一组容器作为一个单元,很难判断整体状态,以及对整体进行管控。新增业务无关的pause容器,用于管控整体
- 简化了关联容器通信和共享的问题
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架构图
- 简版架构图
- 数据流转图
1. Master节点的组件
apiServer
- 提供资源操作的唯一入口,提供api注册、发现、认证、访问控制等功能
etcd
- 一个key-value数据库
- 保存整个机器的状态
controller-manager
- 负责维护机器状态,比如:自动扩容、故障检查、滚动更新
- 实现集群自动化的关键组件
scheduler
- 负责资源调度
- 将未分配节点的pod调度到合适的节点上
2. Node节点的组件
kubelet
- 负责容器生命周期管理,比如:创建、删除
- 同时负责Volume,网络的管理
kube-proxy
- 负责为Service提供负载均衡、服务发现
Container Runtime
- 容器运行环境
- 默认是Docker,同时还支持其他容器引擎
参考文献
- 《Kubernetes权威指南》
- kubernetes指南