为何要用K8S
开发者 VS 运维
让开发者和运维做他们擅长的事情
- 运维
- 掌管生产部署,硬件设施
- 关心系统安全性,利用率以及其他开发人员不重视的方面
- 不想处理应用内在的依赖
- 不想怎么更改底层系统或者基础设施会影响应用
- 开发
- 喜欢开发新特性,提高用户体验
- 不想参与底层系统处理,希望将管理交给运维
K8S达到了上述目标:
-
通过抽象硬件,暴露出单独的管理平台
-
使开发者可以配置,部署应用
-
单体到微服务
-
微服务的难题
-
一台服务器跑多个微服务冲突问题
-
虚拟机隔离VS容器隔离
-
APPS在多个虚拟机 vs 多个容器
-
Docker运行
-
VM VS 容器
K8S
- 框架
容器技术
- Namespace:隔离环境
- Mount(mnt)
- ProcessID(PID)
- Network(NET)
- Inter-Process Communication(IPC)
- UTS
- User ID(user)
- CGroups:限制使用的资源,CPU,宽带,内存等等
Docker
- Images:包含应用及其环境,由Image Layers组成
- Registries:镜像中心
- Containers:隔离资源
示例
const http = require('http');
const os = require('os');
console.log("Kubia server starting...");
var handler = function(request, response) {
console.log("Received request from " + request.connection.remoteAddress);
response.writeHead(200);
response.end("You've hit " + os.hostname() + "\n");
};
var www = http.createServer(handler);
www.listen(8080);
- Dockerfile
- FROM:集成的基础镜像
- ADD:添加内容
- ENTRYPOINT:执行的命令
FROM node:7
ADD app.js /app.js
ENTRYPOINT ["node", "app.js"]
$ docker build -t kubia .
-
Docker镜像组成
-
Docker VS 虚拟机
运行对比
-
裸机,虚拟机,Docker
-
Docker核心开发流程
Kubernetes
好处:
- 简化应用部署
- 更合理的使用硬件资源
- 监控检测及自我修复
- 自动扩容
- 简化应用开发
K8S集群
总结
- 单体服务方便部署,但不方便扩展,很难维护,不方便开发
- 微服务方便开发各个模块,但很难像单体服务一样部署,配置
- Linux容器提供了一些虚拟机的好处,但更轻量,更好的利用硬件资源
- Docker提升了已有的Linux容器技术,更快,更简单的打包应用的环境
- Kubernetes将数据中心暴露给应用程序单个的可计算的资源
- 应用开发人员可以不需要系统运维的帮助,通过Kubernetes自己部署应用
- 运维人员可以自动弄化管理失败节点重试
基础组件
- Master
- K8S API Server:沟通
- Scheduler:分配资源
- Controller Manager:控制,比如复制,追踪处理失败节点等等
- etcd:分布式存储,存储配置等信息
- Worker
- 容器:Docker或其他容器
- Kubelet:沟通API Server,控制容器
- Kube-Proxy:负载均衡
运维的职责
NameSpace
- 属于namespace:
- pod
- service
- ReplicatSet
- Deployment
- PVC(Persistent Volume Claim) ...
- 不属于namespace
- node
- PV(persistent volume)
- namespace
Node
Pod
-
一个pod可以运行多个容器(最好是关联的进程)
-
Pod做为一个可以独立运行的服务单元,简化了应用部署的难度,以更高的抽象层次为应用部署管提供了极大的方便。
-
Pod做为最小的应用实例可以独立运行,因此可以方便的进行部署、水平扩展和收缩、方便进行调度管理与资源的分配。
-
Pod中的容器共享相同的数据和网络地址空间,Pod之间也进行了统一的资源管理与分配。
执行过程
POD网络分配
使用原则
- 一个容器不应该跑多个进程
- 如果两个容器不需要跑在同一个机器,不应该分在一个pod中
yml配置
Label
通过label分组pod
- nodeSelector
Annotating
ReplicationController
三个要素
- label selector: RC控制的范围
- replica count: 控制pods数量
- pod template: 创建pod使用
更新pod template,删除pod后才会更新替换
ReplicaSet
- ReplicationController升级版本,
DaemonSet
- 带有label selector
Job/CronJob
- 并行或串行
- completions:执行数
- parallelism:并行数
- activeDeadlineSeconds:限制执行时间
CronJob
- startingDeadlineSeconds:最晚延迟启动时间
Service
pod对外提供服务的难题
- Pod是短暂的,是随时可以挂掉的
- K8S在pod分配给node后,pod启动前,分配了一个静态的IP给pod,这样客户端无法提取知晓pod服务的地址
- 水平扩展意味着多个pod可能提供同样的服务,每一个pod都有自己的地址。而客户端想通过单一的地址访问pod服务
Service的用处
- 有固定的ip和端口,对外输出服务,负载均衡器
设置一致性访问,基于ip固定路由
!
通过port name引用
服务发现
NodePort Service
LoadBalancer
Ingress
具备Service没有的优势
-
基于Cookie的 affinity
-
Ingress Controller通过Service发现pod,然后直接转发pod,不经过Service
通过ingress访问多个服务
映射不同的host
-
Ingress处理TLS
服务的启动问题
- readiness probe
- Exec probe
- Http Get probe
- TCP Socket probe 与liveness probe不同之处:
- liveness通过替换掉不健康的pod来保持pod集群的正常使用
- readiness probe只有监控的pod可以接受请求服务
给pod添加readiness probe
Volumes
给容器挂载硬盘
- 每个容器都有自己的文件系统,容器重启,文件系统内的内容会丢失
- Volume同pod的生命周期,是pod的一部分,所以重启的容器能看到前一容器保存的内容
- 一个pod下的volume可以被多个容器共享
- 每个容器都可以将volume挂载在自己的文件系统下任何地方
volume类型
- emptyDir:空的目录,用于存储短暂数据
- hostPath:将work node的节点挂载到pod文件系统下
- configMap, secret, downwardAPI:特殊类型的volume,用于暴露K8S资源和集群信息给pod
- persistentVolumeClaim:使用预置或动态存储
- gitRepo:volume从git仓库初始化
- nfs:NFS系统挂载在pod下
- gcePersistentDisk (Google Compute Engine Persistent Disk), awsElastic BlockStore (Amazon Web Services Elastic Block Store Volume), azureDisk (Microsoft Azure Disk Volume):挂载云供应商的存储
- cinder, cephfs, iscsi, flocker, glusterfs, quobyte, rbd, flexVolume, vsphere Volume, photonPersistentDisk, scaleIO:其他网络类型的存储
emptyDir选择volume介质
gitRepo
hostPath
外部存储
解耦底层存储技术与pod
PersistentVolumes PersistentVolumeClaims
- 只需要管理员部署底层的存储,并通过PV注册在K8S集群,并可以控制PV控制大小和访问方式
- 用户创建PVC,描述使用大小及访问方式,并提交给K8S API Server,K8S负责找到找到适合的PV绑定到PVC
- PV并不属于任何的namespace
PVC
权限
- RWO-ReadWriteOnce:只有单个node可以挂载volume,读写
- ROX-ReadOnlyMany:多个node可以挂载volume,读
- RWX-ReadWriteMany:多个node可以挂载volume,读写
pod中使用pvc
与其他的区分
persistentVolumeReclaimPolicy:
+ Retain:保留,不可被重复利用
+ Recyle:删除内容,可被再次claim重复利用,可被不同的pvc使用
+ Delete:删除存储
StorageClass-动态的提供PV
用户更自主选择供应商
- PVC中claim StorageClass
StorageClass
PVC中使用
更简单的方式,不使用StorageClass
使用default pv
ConfigMap
配置应用的方式:
-
容器命令行传参
- 打包容器使用ENTRYPOINT指定容器启动后执行的命令
- CMD:传给ENTRYPOINT参数
pod中覆盖命令
-
给容器加环境变量
缺点:
- 配置跟pod文件融合在一起,导致不同环境,必须定义不同的pod文件,无法重用!
解耦
- 容器mount特殊的volume配置文件
环境变量+ConfigMap
ConfigMap的不同来源
pod中env引用ConfigMap
pod中的env全部来自ConfigMap
pod中命令行引用ConfigMap
ConfigMap Volume
-
subPath路径
-
defaultMode权限
Secret
- K8S确保每个Secret只分发给需要的node(运行相关的pod)
- node在内存存储Secret,绝不写到硬盘
- Secret配置需要被存储在加密的存储上
plain text
Downward API
暴露pod的metadata信息给pod中运行的容器:
- pod名词
- pod ip
- pod namespace
- pod node name
- 每个容器请求的CPU信息
- 每个容器的CPU的上下限
- pod的label
- pod的annotation
通过环境变量暴露
通过downwardAPI volume暴露
通过K8S RestAPI暴露
kubectl proxy
Talk to K8S API Server
ambassador
客户端库连接
Deployment
升级pod的步方式
-
先删除存在的旧pod,再启动新的pod
-
先启动新的pod,再删除旧的pod 切换label selector,一次性切换service
-
Rolling update(已经废弃)
imagePullPolicy
- Always
- IfNotPresent
Rolling update
使用kubectl rolling-update命令
更改label
请求同时路由到v1和v2版本
废弃rolling update:
- 更改了pod的label
- 更改了ReplicateController label selector
- 更新过程是通过client请求server完成的,网络出现问题会导致失败
使用Deployment声明式改动
- Deployment是更高层级的资源管理手段
- Deployment采用声明式的改动,K8S会对声明做处理
- Deployment可以同时拥有多个版本pod,不应该元数据中不应该引用app版本
- 隐藏了部署的详细细节
- 可以自动回退
示例
RollingUpdate策略
- Recreate:先删除老的pod,再创建新的pod
修改资源命令
流程
回退
部署历史像git一样管理部署
参数
revisionHistoryLimit:限制历史数
rollingUpdate:
maxSurge:允许Deployment过程中超过replicaCount最大pod数
maxUnavailable:允许Update中,允许最大的不可服务的pod比例
pause resume deployment
Readiness probe
minReadySeconds作用:当容器启动后,最少多长时间返回ready,这样允许做readiness probe探测,当探测失败,就会block住deployment更新! progressDeadlineSeconds
StatefulSet
无状态pod和有状态pod
通过共用PV,volume configmap Storage保存状态
每个pod分配一个ReplicaSet
同一个volume,每个pod单独的目录
问题:
- 不能一个pod模板配置,
- 每次重新部署升级,都会生成新的pod name及ip地址
使用固定ip的service
StatefulSet
每个pod在重新部署的时候,保留状态和识别信息
每个pod固定的域名a-0.foo.default.svc.cluster.local
更新pod流程
扩展StatefulSet,顺序的增删
实现POD PVC template分离
scale down时,需要手动删除pvc,随机删除pod上的存储数据
示例
部署过程中,一个pod启动后,再顺序部署下一个
查看详情
重新部署过程
SRV记录 映射service和hostname:port
深入理解K8S
理解架构
-
Control Plane
- etcd分布式存储
- API Server
- Scheduler
- Controller Manager
-
Worker nodes
- Kubelet
- kube-proxy
- Container Runtime(Docker, rkt, others)
-
Add-on 插件
- Kubernetes DNS Server
- The Dashboard
- Ingress Controller
- Heapster
- Container Network Interface network plugin
-
组件间通信通过API Server,组件间不直接通信,只有API Server连接etcd
-
etcd:存储集群状态及元数据
etcd分布式存储脑裂问题
API Server
注册监听模式,监听变化
Scheduler
- 查找符合硬件资源请求的node
Controller Manager
部署过程
Controller类别
- ReplicaSet
- Deployment
- StatefulSet
- Node
- Service
- Endpoint
- Namespace
- PersistentVolume
Controller间协调
pod间网络
没有nat
Service实现原理
资源分配
资源申请
node实际分配情况
Scheduler分配失败情况
没有限制最高资源的时候,按比例分配剩余资源
超出资源上限
pod淘汰的依据:资源QOS
- BestEffort(最低)
- Burstable
- Guaranteed(最高)
淘汰
最佳实战
pod删除事件
Helm k8s包管理器
- helm是一个命令行工具,用于本地开发及管理chart,chart仓库管理等
- Tiller是Helm的服务端。Tiller负责接收Helm的请求,与K8S的apiserver交互,根据chart来生成一个release并管理release
- chart Helm的打包格式叫做chart,所谓chart就是一系列文件,它描述了一组相关的K8S集群资源
- release 使用helm install命令在Kubernetes集群中部署的Chart称为release chart模板