一、什么是k8s
全称为Kubernetes,提供高性能可伸缩的容器应用管理服务,充分利用宿主机资源,支持企业级Kubernetes容器化应用的生命周期管理。容器服务 Kubernetes 版简化集群的搭建和扩容等运维工作,整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳的 Kubernetes 容器化应用运行环境。
二、具备哪些功能
网络
提供针对阿里云优化的高性能VPC/ENI网络插件性能优于普通网络方案20%。
支持容器访问策略和流控限制。
存储
支持阿里云云盘、文件存储NAS、对象存储OSS,提供标准的FlexVolume驱动。
支持存储卷动态创建,迁移。
日志
支持高性能日志自动采集和阿里云日志服务集成。
支持和第三方开源日志解决方案集成。
监控
支持容器级别和VM级别的监控。您还可以和第三方开源监控解决方案进行集成。
heapster(k8s自带监控)、Prometheus(开源监控系统)
权限
支持集群级别的RAM授权管理。
支持应用级别的权限配置管理。
应用管理
支持灰度发布,支持蓝绿发布。
支持应用监控,应用弹性伸缩。
内置应用商店,支持Helm应用一键部署;支持服务目录,简化云服务集成。
高可用调度策略
支持持服务级别的亲和性策略和横向扩展。
支持跨可用区高可用和灾难恢复。
支持集群和应用管理的 OpenAPI,轻松对接持续集成和私有部署系统。
操作审计
记录或追溯不同用户的日常操作
通过日志服务收集、分析审计日志,并根据您的需求为审计日志设置自定义的告警规则
三、产品架构设计
四、如何搭建一个适合的k8s集群
1、集群规划
在实际案例中发现,有不少同学使用了很多的小规格的ECS来构建K8S集群,这样其实即没有达到省钱的目的,也没有很好的发挥K8S集群的优势。因为通过大量的小型ECS构建集群有几个弊端:
小规格Woker ECS的网络资源受限
如果一个容器基本能占用掉一个小规格ECS,那么这个的机器的剩余资源就无法利用(构建新的容器或者是恢复失败的容器),在ECS数量多的情况,反而是一种浪费。
2、选择Worker ECS的规格
确定整个集群的日常使用的总核数以及可用度的容忍度。例如总的核数有160核,同时容忍10%的错误。那么最小选择10台ECS为16核的机器,并且高峰运行的负荷不要超过16090%=144核。如果容忍度是20%,那么最小选择5台32核的机器,并且高峰运行的负荷不要超过16080%=128核。这样确保,就算有一台机器整体crash都可以支持得住业务运行。
但是上面这个计算只是理论值,因为规格小的机器,很可能剩余不可利用的资源的比例就高。所以不是越小的机器越好。
选择好CPU:Memory的比例。对于使用内存比较多的应用例如java类应用,建议考虑使用1:8的机型。
举个例子,选择一个8核16GECS,只能部署一个4核8G的应用,因为每个ECS都会部署K8S所需的daemonset 进程,那么剩余的资源是不能再部署一个4核8G的应用的。如果选择16核32G的ECS,就可以部署三个4核8G的应用。利用率就很高。
3、选择高规格ECS
高规格的好处是,网络带宽大,对于大带宽类的应用,资源利用率也高。
在一台机器内容器建通信的比例增大,减少网络的传输
拉取镜像的效率更好。因为镜像只需要拉取一次就可以被多个容器使用。而对于小规格的ECS拉取镜像的此时就增多。在需要联动ECS做伸缩的场景,则需要花费的时间更长,反而达不到立即响应的目的
神龙服务器(阿里云文档有详细介绍),根据自己的业务量是否达到上面要求的场景,考虑是否使用神龙,毕竟成本会更高一些。
五、构建集群选项注意点
1、网络选择
如果需要连接外部的已有服务,如 rds等,则需要考虑复用原有的VPC,而不是取创建一个新的VPC。因为VPC间是隔离的。可以通过创建一个新的交换机,把k8s的机器都放在这个交换机,便于管理。
网络插件的选择:目前支持两种插件,一种是flannel,直通VPC,性能最高。一种是Terway,提供k8s的网络策略管理。
POD CIDR,整个集群的POD的网络。这个不能设置太小。因为设置太小,能支持的节点数量就受限了。这个与k8s集群创建时最下面的高级选项中“每个节点POD的数量"有关。例如POD CIDR是/16的网段,那么就有256*256个地址,如果每个节点POD数量是128,则最多可以支持512个节点。根据节点的配置,调整每个节点的pod数量。
2、磁盘的选择
系统盘尽量选择SSD盘,数据盘(日志)选择高效云盘
对于Worker节点,尽量选择“挂载数据盘”。因为这个盘是专门提供给/var/lib/docker,用来存放本地镜像的。避免后续如果镜像太多撑爆根磁盘。在运行一段时间后,本地会存在很多无用的镜像。比较快捷的方式就是,先移除这台机器,重新构建这个磁盘,然后再添加这个节点上线。
3、日常运维设置
对于ECS的监控,日常运维一定设置CPU, Memory,磁盘的告警。再次说明一下,尽量将/var/lib/docker放在独立一个盘上(数据盘上)
一定配置日志收集
六、K8S稳定性保障
1、Master节点规格
通过容器服务创建出来的Kubernetes集群,Master节点上运行着etcd、kube-apiserver、kube-controller等核心组件,对于Kubernetes集群的稳定性有着至关重要的影响,对于生产环境的集群,必须慎重选择Master规格。Master规格跟集群规模有关,集群规模越大,所需要的Master规格也越大。集群规模包含节点数量/Pod数量/部署频率/访问量……这里简单的认为集群规模就是集群里的节点数量。对于常见的集群规模,可以参考这种如下的方式选择Master节点的规格
1-5个节点,Master规格:4C8G
6-20个节点,Master规格:4C16G
21-100个节点,Master规格:8C32G
100-200个节点,Master规格:16C64G
2、磁盘大小选择
Kubernetes节点需要的磁盘空间也不小,docker镜像、系统日志、应用日志都保存在磁盘上。创建集群的时候,要考虑每个节点上要部署的Pod数量,每个Pod的日志大小、镜像大小、临时数据,再加上一些系统预留的值。
系统盘尽量选择SSD,数据盘选择高效云盘。例如ECS为32核64G,SSD为100G,高效云盘为:200G
3、设置每个Pod的资源配置
经常遇到的Kubernetes问题,就是一个节点上调度了太多的Pod,导致节点负载太高,完全没法对外提供服务。怎么避免这种情况出现呢?
在Kubernetes中部署Pod时,你可以指定这个Pod需要的资源,Kubernetes在部署这个Pod的时候,就会根据Pod的需求找一个具有充足空闲资源的节点部署这个Pod。下面的例子中,声明tomcat这个Pod需要3核CPU,6G的内存,运行中实际使用不能超过4核CPU和8G内存。
spec:
containers:
image: url/app/rdc:1.0.0
imagePullPolicy: Always
name: tomcat
resources:
limits:
cpu: ‘4’
memory: 8Gi
requests:
cpu: ‘3’
memory: 6Gi
Kubernetes采用静态资源调度方式,对于每个节点上的剩余资源,它是这样计算的:节点剩余资源=节点总资源-已经分配出去的资源,并不是实际使用的资源。如果你自己偷偷跑到节点上手工运行一个很耗资源的程序,Kubernetes并不能感知到。
4、配置监控
在Pod上配置了resource很大程度了避免了节点堆积太多Pod的问题,然而还不够。我们还可以再加一道保险:配置节点监控。通过添加监控告警规则,节点上的资源使用使用量很高的时候,我们可以知道出问题了。
通过容器服务创建Kubernetes集群时,会自动在云监控创建两个应用分组,一个对应Master节点,一个对应Worker节点。我们可以在这两个组下面添加一些报警规则,对组里所有的机器生效。后续加入的节点,也会自动出现在组里,不用单独再去配置报警规则。
主要配置ECS资源的报警规则就可以了。
5、优雅启动应用
应用或多或少都有一些外部依赖,比如从db读取数据或者依赖另外一个服务的接口。Kubernetes中多数运维操作都是自动的,不需要人工介入,比如部署应用,你不用自己选择节点,再到节点上启动应用,应用挂了,也不用自己跑过去重启,Kubernetes会自动把应用拉起来,负载高了,还可以通过HPA自动扩容。Kubernetes的最好的做法是启动时检查依赖,如果不满足,轮询等待,而不是直接退出。可以通过 Init Container完成这个功能。
6、配置restart policy
Pod上配置restartPolicy,可以在进程因为异常被kill调后,pod可以实现自动拉起。
apiVersion: v1
kind: Pod
metadata:
name: tomcat
spec:
containers:
- name: tomcat
image: tomcat
restartPolicy: OnFailure #
restartPolicy有三个可选值
Always: 总是自动重启
OnFailure:异常退出才自动重启 (进程退出状态非0)
Never:永远不重启
7、设置健康检查和就绪检查
健康检查:Liveness Probe 就绪检查:Readiness Probe
Pod处于Running状态和Pod能正常提供服务是完全不同的概念,一个Running状态的Pod,里面的进程可能发生了死锁而无法提供服务。但是因为Pod还是Running的,Kubernetes也不会自动重启这个Pod。所以我们要在所有Pod上配置Liveness Probe,探测Pod是否真的存活,是否还能提供服务。如果Liveness Probe发现了问题,Kubernetes会重启Pod。
Readiness Probe用于探测Pod是不是可以对外提供服务了。应用启动过程中需要一些时间完成初始化,在这个过程中是没法对外提供服务的,通过Readiness Probe,我们可以告诉Ingress或者Service能不能把流量转发给这个Pod上。当Pod出现问题的时候,Readiness Probe能避免新流量继续转发给这个Pod。
apiVersion: v1
kind: Pod
metadata:
name: tomcat
spec:
containers:
- name: tomcat
image: tomcat
livenessProbe:
httpGet:
path: /index.jsp
port: 8080
initialDelaySeconds: 3
periodSeconds: 3
readinessProbe:
httpGet:
path: /index.jsp
port: 8080
8、一个进程一个容器
在一个容器里如果塞入多个进程,监控进程、日志进程、sshd进程等。这种方式是有问题的。首先,判断Pod整体的资源占用会变复杂,不方便实施前面提到resource limit。其次,容器内只有一个进程的情况,进程挂了,外面的容器引擎可以清楚的感知到,然后重启容器,如果容器内有多个进程,某个进程挂了,容器未必受影响,外部的容器引擎感知不到容器内进程挂了,也不会对容器做任何操作,但是容器实际上已经不能正常工作了。
9、避免单点问题
如果应用只有一个实例,当实例挂掉的时候,虽然Kubernetes能够将实例重新拉起,但是中间不可避免的存在一段时间的不可用。甚至更新应用,发布一个新版本的时候,也会出现这种情况。在Kubernetes里,尽量避免直接使用Pod,尽可能使用Deployment/StatefulSet,并且让应用的scale在两个以上。
参考文档:https://help.aliyun.com/document_detail/86737.html?spm=a2c4g.11186623.6.542.147520d7ZDLqr1
10、master与node节点交互
##总结
由于k8s只接触了半年的时间,它的发展趋势不敢评论,但是,k8s在资源分配、监控报警、日志采集、部署发布、容器高可用、权限分发、安全审计等各方面都极大的提升了应用运维的效率,也证明了他在容器服务的中的地位会不断的提升。接下来k8s的发展前景,也是非常乐观的。