怎么查看服务占用的端口微服务所占CPU

作者|Adam Drake编辑|薛命灯资深架构师 Adam Drake 在他的博客上分享了他对微服务的看法,他从自己的经验出发,结合 Martin Fowler 对微服务的见解,帮助想要采用微服务的公司重新审视微服务。以下内容已获得作者翻译授权。关于微服务的优势和劣势已经有过太多的讨论,不过我仍然看到很多成长型初创公司对它进行着“盲目崇拜”。冒着“重复发明轮子”的风险(Martin Fowler 已经写过“Microservice Premium”的文章),我想把我的一些想法写下来,在必要的时候可以发给客户,也希望能够帮助人们避免犯下我之前见过的那些错误。在进行架构或技术选型时,将网络上找到的一些所谓的最佳实践文章作为指南,一旦做出了错误的决定,就要付出惨重的代价。如果能够帮助哪怕一个公司避免犯下这种错误,那么写这篇文章都是值得的。如今微服务是个热门技术,微服务架构一直以来都存在(面向服务架构也算是吧?),但对于我所见过的大部分公司来说,微服务不仅浪费了他们的时间,分散了他们的注意力,而且让事情变得更糟糕。这听起来似乎很奇怪,因为大部分关于微服务的文章都会肯定微服务的各种好处,比如解耦系统、更好的伸缩性、移除开发团队之间的依赖,等等。如果你的公司有 Uber、Airbnb、Facebook 或 Twitter 那样的规模,那么就不存在什么问题。我曾经帮助一些大型组织转型到微服务架构,包括搭建消息系统和采用一些能够提升伸缩性的技术。不过,对于成长型初创公司来说,很少需要这些技术和微服务。Russ Miles 在他的《让微服务失效的八种方式》这篇文章中表达了他的首要观点,而在我看来,这些场景却到处可见。成长型初创公司总是想模仿那些大公司的最佳实践,用它们来弥补自身的不足。但是,最佳实践是要视情况而定的。有些东西对于 Facebook 来说是最佳实践,但对于只有不到百人的初创公司来说,它们就不一定也是最佳实践。如果你的公司比那些大公司小一些,你仍然能够在一定程度上从微服务架构中获得好处。但是,对于成长型初创公司来说,大规模地迁移到微服务是一种过错,而且对技术人来说是不公平的。
为什么选择微服务? 一般来说,成长型初创公司采用微服务架构最主要的目的是要减少或者消除开发团队间的依赖,或者提升系统处理大流量负载的能力(比如伸缩性)。开发人员经常抱怨的问题和常见的症状包括合并冲突、由未完整实现的功能引起的部署错误以及伸缩性问题。接下来让我们逐个说明这些问题。依赖在初创公司的早期阶段,开发团队规模不大,使用的技术也很简单。人们在一起工作,不会出现混乱,要实现一些功能也比较快。一切看起来都很美好。随着公司的不断发展,开发团队也在壮大,代码库也在增长,然后就出现了多个团队在同一个代码库上工作的情况。这些团队的大部分成员都是公司早期的员工。因为初创公司的早期员工一般都是初级开发人员,他们并没有意识到一个问题,那就是在团队规模增长和代码库增长的同时,沟通成本也会随之提升。对于缺乏经验的技术人员来说,他们倾向于通过技术问题来解决人的问题,并希望通过微服务来减少开发团队之间的依赖和耦合。实际上,他们真正需要做的是通过有效的沟通来解决人的问题。当一个初创公司有多个开发团队时,团队之间需要协调,团队成员需要知道每个人都在做什么,他们需要协作。在这样规模的企业里,软件开发其实具有了社交的性质。如果团队之间缺乏沟通或者缺乏信息分享,不管用不用微服务,一样会存在依赖问题,而就算使用了微服务,也仍然存在负面的技术问题。将代码模块化作为解决这个问题的技术方案,确实能够缓解软件开发固有的团队依赖问题,但团队间的沟通仍然要随着团队规模的增长而不断改进。切记不要混淆了解耦和分布式二者的含义。由模块和接口组成的单体可以帮助你达到解耦的目的,而且你也应该这么做。你没有必要把应用程序拆分成分布式的多个独立服务,在模块间定义清晰的接口也能达到解耦的目的。部分功能实现微服务里需要用到功能标志(feature flag),微服务开发人员需要熟悉这种技术。特别是在进行快速开发(下面会深入讨论)的时候,你可能需要部署一些功能,这些功能在某些平台上还没有实现,或者前端已经完全实现,但后端还没有,等等。随着公司的发展,部署和运维系统变得越来越自动化和复杂,功能标志变得越来越重要。水平伸缩通过部署同一个服务的多个实例来获得系统的伸缩性,这是微服务的优点之一。不过,大多数过早采用微服务的公司却在这些微服务背后使用了同一个存储系统。也就是说,这些服务具备了伸缩性,但整个应用并不具备伸缩性。如果你正打算使用这样的伸缩方式,那为什么不直接在负载均衡器后面部署多个单体实例呢?你可以以更简单的方式达到相同的目的。再者,水平伸缩应该被作为杀手锏来使用。你首先要关注的应该是如何提升应用程序的性能。一些简单的优化常常能带来数百倍的性能提升,这里也包括如何正确地使用其他服务。例如,我在一篇博文里提到的 Redis 性能诊断(文末有链接)。
我们为微服务做好准备了吗? 在讨论架构选型时,人们经常会忽略这个问题,但其他却是最重要的。高级技术人员在了解了开发人员或业务人员的抱怨或痛点之后,开始在网上找寻找解决方案,他们总是宣称能解决这些问题。但在这些信誓旦旦的观点背后,有很多需要注意的地方。微服务有利也有弊。如果你的企业足够成熟,并且具有一定的技术积累,那么采用微服务所面临的挑战会小很多,并且能够带来更多正面好处。那么怎样才算已经为微服务做好准备了呢?Martin Fowler 在多年前表达了他对微服务先决条件的看法,但是从我的经验来看,大多数成长型初创公司完全忽略了他的观点。Martin 的观点是一个很好的切入点,让我们来逐个说明。我敢说,大部分成长型初创公司几乎连一个先决条件都无法满足,更不用说满足所有的条件了。如果你的技术团队不具备快速配置、部署和监控能力,那么在迁移到微服务前必须先获得这些能力。接下来让我们更详细地讨论这些先决条件。1. 快速配置如果你的开发团队里只有少数几个人可以配置新服务、虚拟环境或其它配套设施,那说明你们还没有为微服务做好准备。你的每个团队里都应该要有几个这样的人,他们具备了配置基础设施和部署服务的能力,而且不需要求助于外部。要注意,光是有一个 DevOps 团队并不意味着你在实施 DevOps,开发人员应该参与管理与应用程序相关的组件,包括基础设施。类似的,如果你没有灵活的基础设施(易于伸缩并且可以由团队里的不同人员来管理)来支撑当前的架构,那么在迁移到微服务前必须先解决这个问题。你当然可以在裸机上运行微服务,以更低的成本获得出众的性能,但在服务的运维和部署方面也必须具备灵活性。2. 基本的监控如果你不曾对你的单体应用进行过性能监控,那么在迁移到微服务时,你的日子会很难过。你需要熟悉系统级别的度量指标(比如 CPU 和内存)、应用级别的度量指标(比如端点的请求延迟或端点的错误)和业务级别的度量指标(比如每秒事务数或每秒收益),这样才可以更好地理解系统的性能。在性能方面,微服务生态系统比单体系统要复杂得多,就更不用提诊断问题的复杂性了。你可以搭建一个监控系统(如 Prometheus),在将单体应用拆分成微服务之前对应用做一些增强,以便进行监控。3. 快速部署如果你的单体系统没有一个很好的持续集成流程和部署系统,那么要集成和部署好你的微服务几乎是件不可能的事。想象一下这样的场景:10 个团队和 100 个服务,它们都需要进行手动测试和部署,然后再将这些工作与测试和部署一个单体所需要的工作进行对比。100 个服务会出现多少种问题?而单体系统呢?这些先决条件很好地说明了微服务的复杂性。Phil Calcado 在 Fowler 的先决条件清单里添加了一些东西,不过我认为它们更像是重要的扩展,而不是真正的先决条件。
如果我们具备了这些先决条件呢? 就算具备了这些条件,仍然需要注意微服务的负面因素,确保微服务能够为你的业务带来真正的帮助。事实上,很多技术人员对微服务中存在的分布式计算谬论视而不见,但为了确保能够成功,这些问题是必须要考虑到的。对于大部分成长型初创公司来说,基于各种原因,他们应该避免使用微服务。1. 运营成本的增加快速部署这一先决条件已经涵盖了一部分成本,除此之外,对微服务进行容器化(可能使用 Docker)和使用容器编排系统(比如 Kubernetes)也需要耗费很多成本。Docker 和 Kubernetes 都是很优秀的技术,但是对于大部分成长型初创公司来说,它们都是一种负担。我见过初创公司使用 rsync 作为部署和编排工具,我也见过很多的初创公司陷入运维工具的复杂性泥潭里,他们因此浪费了很多时间,而这些时间本来可以用于为用户开发更多的功能。2. 你的应用会被拖慢如果你的单体系统里包含了多个模块,并且在模块间定义了良好的 API,那么 API 之间的交互就几乎没有什么额外开销。但对于微服务来说就不是这么一回事了,因为它们一般运行在不同的机器上,它们之间需要通过网络进行交互。这样会在一定程度上拖慢整个系统。如果一个请求需要多个服务进行同步的交互,那么情况会变得更加糟糕。我曾经工作过的一个公司,他们需要调用将近 10 个服务才能处理完某些请求。处理请求的每一个步骤都需要额外的网络开销和延迟,但实际上,他们可以把这些服务放在单个软件包里,按照不同的模块来区分,或者把它们设计成异步的。这样可以为他们节省大量的基础设施成本。3. 本地开发变得更加困难如果你有一个单体应用,后端只有一个数据库,那么在开发过程中,在本地运行这个应用是很容易的。如果你有 100 个服务,并使用了多个数据存储系统,而且它们之间互相依赖,那么本地开发就会变成一个噩梦。即使是 Docker 也无法把你从这种复杂性泥潭中拯救出来。虽然事情原本可以简单一些,不过仍然需要处理依赖问题。理论上说,微服务不存在这些问题,因为微服务被认为是相互独立的。不过,对于成长型初创公司来说,就不是这么一回事了。技术人员一般需要在本地运行所有(或者几乎所有)的服务才能进行新功能的开发和测试。这种复杂性是对资源的巨大浪费。4. 难以伸缩对单体系统进行伸缩的最简单方式是在负载均衡器后面部署单体系统的多个实例。在流量增长的情况下,这是一种非常简单的伸缩方式,而且从运维角度来讲,它的复杂性是最低的。你的系统在编排平台(如 Elastic Beanstalk)上运行的时间越长越好,你和你的团队就可以集中精力构建客户需要的东西,而不是忙于解决部署管道问题。使用合适的 CI/CD 系统可以缓解这个问题,但在微服务生态系统里,事情要复杂得多,而且这些复杂性所造成的麻烦已经超过了它们所能带来的好处。
然后呢? 如果你刚好处在一个成长型初创公司里,需要对架构做一些调整,而微服务似乎不能解决你的问题,这个时候应该怎么办?Fowler 提出的先决条件可以说是技术领域的能力成熟度模型,Fowler 在他的文章里对成熟度模型进行过介绍。如果这种成熟度模型对于公司来说是说得通的,那么我们可以按照 Fowler 提出的先决条件,并使用其他的一些中间步骤为向微服务迁移做好准备。下面的内容引用自 Fowler 的文章。关键你要认识到,成熟度模型的评估结果并不代表你的当前水平,它们只是在告诉你需要做哪些工作才能朝着改进的目标前进。你当前的水平只是一种中间工作,用于确定下一步该获得什么样的技能。那么,我们该做出怎样的改进,以及如何达成这些目标?我们需要经过一些简单的步骤,其中前面两步就可以解决很多在向微服务迁移过程中会出现的问题,而且不会带来相关的复杂性。清理应用程序。确保应用程序具有良好的自动化测试套件,并使用了最新版本的软件包、框架和编程语言。重构应用程序,把它拆分成多个模块,为模块定义清晰的 API。不要让外部代码直接触及模块内部,所有的交互应该通过模块提供的 API 来进行。从应用程序中选择一个模块,并把它拆分成独立的应用程序,部署在相同的主机上。你可以从中获得一些好处,而不会带来太多的运维麻烦。不过,你仍然需要解决这两个应用之间的交互问题,虽然它们都部署在同一个主机上。不过你可以无视微服务架构里固有的网络分区问题和分布式系统的可用性问题。把独立出来的模块移动到不同的主机上。现在,你需要处理跨网络交互问题,不过这样可以让这两个系统之间的耦合降得更低。如果有可能,可以重构数据存储系统,让另一个主机上的模块负责自己的数据存储。在我所见过的公司里,如果他们能够完成前面两个步骤就算万事大吉了。如果他们能够完成前面两个步骤,那么剩下的步骤一般不会像他们最初想象的那么重要了。如果你决定在这个过程的某个点上停下来,而系统仍然具有可维护性和比刚开始时更好的状态,那么就再好不过了。
我的总结 我不能说这些想法都是独一无二的,也不能说是我所独有的。我只是从其他遭遇了相同问题的人那里收集想法,并连同观察到的现象在这里作了一次总结。还有其他很多比我更有经验的人也写过这方面的文章,他们剖析地更加深入,比如 Sander Mak 写的有关模块和微服务的文章。不管怎样,对于正在考虑对他们的未来架构做出调整的公司来说,这些经验都是非常重要的。认真地思考每一个问题,确保微服务对你们的组织来说是一个正确的选择。最起码在完成了上述的前面两个步骤之后,再慎重考虑一下微服务对于你的组织来说是否是正确的方向。你之前的很多问题可能会迎刃而解。特别声明:本文为网易自媒体平台“网易号”作者上传并发布,仅代表该作者观点。网易仅提供信息发布平台。
一键安装官方客户端
重大事件及时推送 阅读更流畅
http://dingyue.nosdn.127.net/10jwdW0Z1N9UNAjQiS=vRd1WRME8l1hZCTnLh6lewaOA39.jpeg微服务化后的按需精细化资源控制 - Apache ServiceComb (incubating)
To enjoy in opensource community.
少于 1 分钟 阅读
   介绍了在K8S上快速部署Company示例,本文将继续在K8S上演示使用K8S的弹性伸缩能力进行Company示例的按需精细化资源控制,以此体验微服务化给大家带来的好处。
K8S环境准备:
  为使K8S具备弹性伸缩能力,需要先在K8S中安装监控器Heapster和Grafana:
  具体读者踩了坑后更新的heapster的安装脚本作者放在:,可直接获取下载获取,需要调整一个参数,后直接运行kube.sh脚本进行安装。
vi LinuxCon-Beijing-WorkShop/kubernetes/heapster/deploy/kube-config/influxdb/heapster.yaml
replicas: 1
task: monitoring
k8s-app: heapster
serviceAccountName: heapster
containers:
- name: heapster
image: gcr.io/google_containers/heapster-amd64:v1.4.1
imagePullPolicy: IfNotPresent
- /heapster
#集群内安装直接使用kubernetes
- --source=kubernetes
#集群外安装请直接将下面的服务地址替换为k8s api server地址
- --source=kubernetes:http://10.229.43.65:6443?inClusterConfig=false
- --sink=influxdb:http://monitoring-influxdb:8086
启动Company:
  下载Comany支持弹性伸缩的代码:
git clone https://github.com/ServiceComb/ServiceComb-Company-WorkShop.git
cd LinuxCon-Beijing-WorkShop/kubernetes/
bash start-autoscale.sh
  在Company的deployment.yaml中, 增加了如下限定资源的字段,这将限制每个pod被限制在200mill-core(1000毫core == 1 core)的cpu使用率以内。
resources:
  在 start-autoscale.sh 中,对每个deployment创建HPA(pod水平弹性伸缩器)资源,限定每个pod的副本数弹性伸缩时控制在1到10之间,并限定每个pod的cpu占用率小于50%,结合前面限定了200mcore,故,每个pod的的平均cpu占用率会被HPA通过弹性伸缩能力控制在100mcore以内。
# Create Horizontal Pod Autoscaler
kubectl autoscale deployment zipkin --cpu-percent=50 --min=1 --max=10
kubectl autoscale deployment company-bulletin-board --cpu-percent=50 --min=1 --max=10
kubectl autoscale deployment company-worker --cpu-percent=50 --min=1 --max=10
kubectl autoscale deployment company-doorman --cpu-percent=50 --min=1 --max=10
kubectl autoscale deployment company-manager --cpu-percent=50 --min=1 --max=10
kubectl autoscale deployment company-beekeeper --cpu-percent=50 --min=1 --max=10
  当运行start-autoscale.sh之后,具备弹性伸缩器的company已经被创建,可通过下面指令进行HPA的查询:
kubectl get hpa
启动压测:
export $HOST=&heapster-ip&:&heapster-port&
bash LinuxCon-Beijing-WorkShop/kubernetes/stress-test.sh
  该脚本不断循环执行 1s内向Company请求计算 fibonacci 数值200次,对Company造成请求压力:
FIBONA_NUM=`curl -s -H "Authorization: $Authorization" -XGET "http://$HOST/worker/fibonacci/term?n=6"`
测试过程与结果
  分别查看HPA状态以及Grafana,如下:
图1 启动阶段
图2 启动阶段
  从以上过程可以分析出,以下几点:
  1. 压力主要集中在company-manager这个pod上,K8S的autoscaler通过弹性增加该pod的副本数量,最终达到目标:每个pod的cpu占用率低于限定值的50%(图5,Usage default company-manager/Request default company-manager = 192/600 约等于图4中的33%),并保持稳定。
  2. 在弹性伸缩过程中,在还没稳定前可能造成丢包,如图3。
  3. Company启动会导致系统资源负载暂时性加大,故Grafana上看到的cpu占用率曲线会呈现波峰状,但随着系统稳定运行后,HPA会按照系统的稳定资源消耗准确找到匹配的副本数。图3中副本数已超过实际所需3个,但随着系统稳定,最终还是稳定维持在3个副本。
  4. 在HPA以及Grafana可以看到缩放和报告数据都会有延迟,按照官方文档说法,只有在最近3分钟内没有重新缩放的情况下,才会进行放大。 从最后一次重新缩放,缩小比例将等待5分钟。 而且,只有在avg/ Target降低到0.9以下或者增加到1.1以上(10%容差)的情况下,才可能会进行缩放。
  以上,就是本次对Compan示例弹性伸缩的全过程,Martin Fowler 在2014年3月的中提到:
  微服务是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。每个微服务仅关注于完成一件任务并很好地完成该任务。在所有情况下,每个任务代表着一个小的业务能力。
  国内实践微服务的先行者王磊先生也在《微服务架构与实践》一书中进行了全面论述。
  Company使用ServiceComb进行微服务化改造后,具备了微服务的属性,故可以对单个负载较大的company-manager这个微服务进行精细化的控制,达到按需的目的,相比传统单体架构来讲,这将大大帮助准确有效地化解应用瓶颈,提高资源的利用效率。
您的电子邮箱地址并不会被展示。请填写标记为必须的字段。 *
猜您还喜欢
Apache ServiceComb (incubating) Day Report
少于 1 分钟 阅读
LC3大会微服务Workshop-Apaceh ServiceComb(incubating) Day 演讲PPT
少于 1 分钟 阅读
Detailed Agenda of Apache ServiceComb (incubating) Day
少于 1 分钟 阅读
Real time updated information of Apache ServiceComb (incubating) Day
4 分钟 阅读linux cpu占用100%排查
某服务器上部署了若干tomcat实例,即若干垂直切分的Java站点服务,以及若干Java微服务,突然收到运维的CPU异常告警。
问:如何定位是哪个服务进程导致CPU过载,哪个线程导致CPU过载,哪段代码导致CPU过载?
步骤一、找到最耗CPU的进程
执行top -c ,显示进程运行信息列表
键入P (大写p),进程按照CPU使用率排序
如上图,最耗CPU的进程PID为10765
步骤二:找到最耗CPU的线程
top -Hp 10765 ,显示一个进程的线程运行信息列表
键入P (大写p),线程按照CPU使用率排序
如上图,进程10765内,最耗CPU的线程PID为10804
步骤三:将线程PID转化为16进制
工具:printf
方法:printf “%x” 10804
如上图,10804对应的16进制是0x2a34,当然,这一步可以用计算器。
之所以要转化为16进制,是因为堆栈里,线程id是用16进制表示的。
步骤四:查看堆栈,找到线程在干嘛
工具:pstack/jstack/grep
方法:jstack 10765 | grep ‘0x2a34’ -C5 --color
打印进程堆栈
通过线程id,过滤得到线程堆栈
如上图,找到了耗CPU高的线程对应的线程名称“AsyncLogger-1”,以及看到了该线程正在执行代码的堆栈。
来源:http://www.toutiao.com/i8749966/?ref=myread
没有更多推荐了,分享Kubernetes技术 - www.Kubernetes.org.cn
Kubernetes,微服务以及 Service Mesh
作者:Jolestar ,2015年初开始创业,作为技术合伙人,专注于打造一款团队通讯协作工具-
这是前一段时间在一个的 meetup 上的分享,整理成文章发布出来。
谈微服务之前,先澄清一下概念。微服务这个词的准确定义很难,不同的人有不同的人的看法。比如一个朋友是『微服务原教旨主义者』,坚持微服务一定是无状态的 http API 服务,其他的都是『邪魔歪道』,它和 SOA,RPC,分布式系统之间有明显的分界。而另外也有人认为微服务本身就要求把整体系统当做一个完整的分布式应用来对待,而不是原来那种把各种组件堆积在一起,『拼接』系统的做法。两种说法都有道理,因为如果微服务没有个明确的边界的话,你可能会发现微服务囊括了一切,但如果只是坚持无状态,那微服务相关的一些领域又无法涵盖。我个人对这个问题持开放式的看法,微服务本身代表了一种软件交付以及复用模式的变化,从依赖库到依赖服务,和
SOA 有相通之处,同时它也带来了新的挑战,对研发运维都有影响,所有因为和微服务相关而产生的变化,都可以囊括在大微服务主题下。
微服务带来的变化
微服务主要给我们带来的变化有三点,
部署单元 越来越小的粒度,加快交付效率,同时增加运维的复杂度。依赖方式 从依赖库到依赖服务,增加了开发者选择的自由(语言,框架,库),提高了复用效率,同时增加了治理的复杂度。架构模式 从单体应用到微服务架构,架构设计的关注点从分层转向了服务拆分。
##微服务涉及的技术点
服务注册与发现 服务目录 服务列表 配置中心进程间通讯 负载均衡服务生命周期管理 部署, 变更,升级,自动化运维服务依赖关系链路跟踪,限流,降级,熔断访问控制与监控微服务应用框架
这个是我浏览了众多微服务的话题之后摘要出来的一些技术点,不全面也不权威,不过可以看出,微服务主题涉及的面非常广,那这些问题在微服务之前就不存在么?为什么大家谈到微服务的时候才把这些东西拿出来说。这个需要从软件开发的历史说来。软件开发行业从十多年前开始,出现了一个分流,一部分是企业应用开发,软件要安装到企业客户自己的资源上,客户负责运维(或者通过技术支持),一部分是互联网软件,自己开发运维一套软件通过网络给最终用户使用。这两个领域使用的技术栈也逐渐分化,前者主要关注标准化,框架化(复用),易安装,易运维,后者主要关注高可用,高性能,纵向伸缩。而这两个领域到微服务时代,形成了一个合流,都在搞微服务化。主要原因我认为有两点:
SaaS 的兴起,使得一些企业应用厂商也开始采用互联网模式,遇到用户规模的问题。同时企业应用很难纯 SaaS 化,面对大客户的时候,势必面临私有部署的问题,所以必须探索一种既能支撑用户规模,同时要能方便私有化部署的架构。随着互联网技术领域为了应对新的业务变化,需要将原来的技术经验沉淀继承过来,开始关注标准化和框架化。
也就是说,这些技术点并不是新问题,但如何将这些技术点从业务逻辑中抽取出来,作为独立的,可复用的框架或者服务,这个是大家探寻的新问题。
为微服务而生的 Kubernetes
Kubernetes Pod – Sidecar 模式Kubernetes 支持微服务的一些特性Service Mesh 微服务的中间件层
我这样说,不仅仅是因为这是一个微服务的 meetup,微服务和 Kubernetes 确实是相辅相成的。一方面 Kubernetes 帮助微服务落地,另外一方面微服务促进了对容器和 Kubernetes 的需求。
我们先从 Kubernetes 的
机制带来的一种架构模式 — Sidecar 来说。下面这段配置文件是我从 Kubernetes 内置的 dns 的 deployment 中抽取出来的 Pod 描述文件,简化掉了资源限制,端口设置以及健康检查等内容。
apiVersion: v1
name: dnspod
containers:
- name: kubedns
image: gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.14.4
- --domain=cluster.local.
- --dns-port=10053
- --config-dir=/kube-dns-config
- containerPort: 10053
name: dns-local
protocol: UDP
- containerPort: 10053
name: dns-tcp-local
protocol: TCP
- name: dnsmasq
image: gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64:1.14.4
- -logtostderr
- -configDir=/etc/k8s/dns/dnsmasq-nanny
- -restartDnsmasq=true
- --cache-size=1000
- --log-facility=-
- --server=/cluster.local/127.0.0.1#10053
- --server=/in-addr.arpa/127.0.0.1#10053
- --server=/ip6.arpa/127.0.0.1#10053
- containerPort: 53
protocol: UDP
- containerPort: 53
name: dns-tcp
protocol: TCP
- name: sidecar
image: gcr.io/google_containers/k8s-dns-sidecar-amd64:1.14.4
- --logtostderr
- --probe=kubedns,127.0.0.1:10053,kubernetes.default.svc.cluster.local,5,A
- --probe=dnsmasq,127.0.0.1:53,kubernetes.default.svc.cluster.local,5,A
从这个配置文件可以看出,Kubernetes 的 Pod 里可以包含多个容器,同一个 Pod 的多个容器之间共享网络,Volume,IPC(需要设置),生命周期和 Pod 保持一致。上例中的 kube-dns 的作用是通过 Kubernetes 的 API 监听集群中的 Service 和 Endpoint 的变化,生成 dns 记录,通过 dns 协议暴露出来。dnsmasq 的作用是作为 dns 缓存,cluster 内部域名解析代理到 kube-dns,其他域名通过上游 dns server 解析然后缓存,供集群中的应用使用。sidecar
容器的作用是进行 dns 解析探测,然后输出监控数据。
通过这个例子可以看出来,Kubernetes 的 Pod 机制给我们提供了一种能力,就是将一个本来要捆绑在一起的服务,拆成多个,分为主容器和副容器(sidecar),是一种更细粒度的服务拆分能力。当然,没有 Kubernetes 的时候你也可以这么干,但如果你的程序需要几个进程捆绑在一起,要一起部署迁移,运维肯定想来打你。有了这种能力,我们就可以用一种非侵入的方式来扩展我们的服务能力,并且几乎没有增加运维复杂度。这个在我们后面的例子中也可以看到。
Kubernetes 上的服务发现
服务发现其实包含了两个方面的内容,一种是要发现应用依赖的服务,这个 Kubernetes 提供了内置的 dns 机制和 ClusterIP 机制,每个 Service 都自动注册域名,分配 ClusterIP,这样服务间的依赖可以从 IP 变为 name,这样可以实现不同环境下的配置的一致性。
apiVersion: v1
kind: Service
name: myservice
- port: 80
protocol: TCP
targetPort: 9376
app: my-app
clusterIP: 10.96.0.11
curl http://myservice
如上面的 Service 的例子,依赖方只需要通过 myservice 这个名字调用,具体这个 Service 后面的后端实例在哪,有多少个,用户不用关心,交由 Kubernetes 接管,相当于一种基于虚 IP(通过 iptables 实现) 的内部负载均衡器。(具体的 clusterIP 实现这里不再详述,可查阅相关资料)。
另外一种服务发现是需要知道同一个服务的其他容器实例,节点之间需要互相连接,比如一些分布式应用。这种需求可以通过 Kubernetes 的 API 来实现,比如以下实例代码:
endpoints, _ = client.Core().Endpoints(namespace).Get("myservice", metav1.GetOptions{})
addrs := []string{}
for _, ss := range endpoints {
for _, addr := range ss.Addresses {
ips = append(addrs, fmt.Sprintf(`"%s"`, addr.IP))
glog.Infof("Endpoints = %s", addrs)
Kubernetes 提供了 ServiceAccount 的机制,自动在容器中注入调用 Kubernetes API 需要的 token,应用代码中无需关心认证问题,只需要部署的时候在 yaml 中配置好合适的 ServiceAccount 即可。
关于服务发现再多说两句,没有 Kubernetes 这样的统一平台之前,大家做服务发现还主要依赖一些服务发现开源工具,比如 etcd,zookeeper,consul 等,进行自定义开发注册规范,在应用中通过 sdk 自己注册。但当应用部署到 Kubernetes 这样的平台上你会发现,应用完全不需要自己注册,Kubernetes 本身最清楚应用的节点状态,有需要直接通过 Kubernetes 进行查询即可,这样可以降低应用的开发运维成本。
通过 Kubernetes 进行 Leader 选举
有些分布式需要 Leader 选举,在之前,大家一般可能依赖 etcd 或者 zookeeper 这样的服务来实现。如果应用部署在 Kubernetes 中,也可以利用 Kubernetes 来实现选举,这样可以减少依赖服务。
Kubernetes 中实现 Leader 选举主要依赖以下特性:
Kubernetes 中的所有 API 对象类型,都有一个 ResourceVersion,每次变更,版本号都会增加。Kubernetes 中的所有对象,都支持 Annotation,支持通过 API 修改,这样可以附加一些自定义的 key-value 数据保存到 Kubernetes 中。Kubernetes 的所有 API 对象中,Endpoint/ConfigMap 属于『无副作用』对象,也就是说,创建后不会带来额外的影响,所以一般用这两种对象来保存选主信息。Kubernetes 的 Update/Replace 接口,支持 CAS 机制的更新,也就是说,更新时可以带上客户端缓存中的 ResourceVersion,如果服务器端该对象的 ResourceVersion 已经大于客户端传递的 ResourceVersion,则会更新失败。
这样,所有的节点都一起竞争更新同一个 Endpoint/ConfigMap,更新成功的,作为 Leader,然后把 Leader 信息写到 Annotation 中,其他节点也能获取到。为了避免竞争过于激烈,会有一个过期机制,过期时间也写入到 Annotation,Leader 定时 renew 过期时间,其他节点定时查询,发现过期就发起新一轮的竞争。这样相当于 Kubernetes 提供了一种以 client 和 API 一起配合实现的 Leader 选举机制,并且在 client sdk 中提供。当前 Kubernetes
的一些内部组件,比如 controller-manager,也是通过这种方式来实现选举的。
当然,如果觉得调用 client 麻烦,或者该语言的 sdk 尚未支持这个特性(应该只有 go 支持了),可以也可以通过 sidercar 的方式实现,参看 https://github.com/kubernetes/contrib/tree/master/election 。也就是说,通过一个 sidecar 程序去做选主,主程序只需要调用 sidecar 的一个 http api 去查询即可。
$ kubectl exec elector-sidecar -c nodejs -- wget -qO- http://localhost:8080
Master is elector-sidecar
Kubernetes 支持微服务的运维特性
Kubernetes 对微服务的运维特性上的支持,主要体现以下两方面:
滚动升级以及自动化伸缩
kubectl set image deployment &deployment& &container&=&image&
kubectl rollout status deployment &deployment&
kubectl rollout pause deployment &deployment&
kubectl rollout resume deployment &deployment&
kubectl rollout undo deployment &deployment&
kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10
滚动升级支持最大不可用节点设置,支持暂停,恢复,一键回滚。自动伸缩支持根据监控数据在一个范围内自动伸缩,很大程度上降低了微服务的运维成本。
日志与监控的标准化通过 Kubernetes 可以实现日志收集以及应用监控的标准化,自动化,这样应用不用关心日志和监控数据的收集展示,只需要按照系统标准输出日志和监控接口即可。
Service Mesh 微服务的中间件层
微服务这个话题虽然火了有很长时间了,关于微服务的各种框架也有一些。但这些框架大多是编程语言层面来解决的,需要用户的业务代码中集成框架的类库,语言的选择也受限。这种方案很难作为单独的产品或者服务给用户使用,升级更新也受限于应用本身的更新与迭代。直到 Service Mesh 的概念的提出。Service Mesh 貌似也没有比较契合的翻译(有的译做服务齿合层,有的翻译做服务网格),这个概念就是试图在网络层抽象出一层,来统一接管一些微服务治理的功能。这样就可以做到跨语言,无侵入,独立升级。其中前一段时间 Google,IBM,Lyft
联合开源的 istio 就是这样一个工具,先看下它的功能简介:
智能路由以及负载均衡跨语言以及平台全范围(Fleet-wide)策略执行深度监控和报告
是不是听上去就很厉害?有的还搞不明白是啥意思?我们看 istio 之前先看看 Service Mesh 能在网络层做些什么。
可视化 其实本质上微服务治理的许多技术点都包含可视化要求,比如监控和链路追踪,比如服务依赖弹性(Resiliency 或者应该叫柔性,因为弹性很容易想到 scale) 就是网络层可以不那么生硬,比如超时控制,重试策略,错误注入,熔断,延迟注入都属于这个范围。效率(Efficiency) 网络层可以帮应用层多做一些事情,提升效率。比如卸载 TLS,协议转换兼容流量控制 比如根据一定规则分发流量到不同的 Service 后端,但对调用方来说是透明的。安全保护 在网络层对流量加密/解密,增加安全认证机制,而对应用透明。
可以看出,如果接管了应用的进出流量,将网络功能可编程化,实际上可做的事情很多。那我们简单看下 istio 是如何做的。
大致看一下这个架构图,istio 在业务 Pod 里部署了一个 sidecar — Envoy,这是一个代理服务器,前面说的网络层功能基本靠它来实现,然后 Envoy 和上面的控制层组件(Mixer,Pilot,Istio-Auth)交互,实现动态配置,策略执行,安全证书获取等,对用户业务透明。实际部署的时候,并不需要开发者在自己的 Pod 声明文件里配置 Envoy 这个 sidecar,istio 提供了一个命令行工具,在部署前注入(解析声明配置文件然后自动修改)即可,这样 istio 的组件就可以和业务应用完全解耦,进行独立升级。
看到这里,Java 服务器端的研发人员可能会感觉到,这个思路和 Java 当初的 AOP(aspect-oriented programming) 有点像,确实很多 Java 微服务框架也是利用 AOP 的能力来尽量减少对应用代码的侵入。但程序语言的 AOP 能力受语言限制,有的语言里就非常难实现非侵入的 AOP,而如果直接在网络层面寻找切面就可以做到跨语言了。
当前其实已经有许多在网络层实现的中间件,比如有提供数据库安全审计功能的,有提供 APM 的,有提供数据库自动缓存的,但这些中间件遇到的最大问题是增加了用户应用的部署复杂度,实施成本比较高,很难做到对用户应用透明。可以预见,随着 Kubernetes 的普及,这类中间件也会涌现出来。
本质上,微服务的目的是想以一种架构模式,应对软件所服务的用户的规模增长。没有微服务架构之前,大多数应用是以单体模式出现的,只有当规模增长到一定程度,单体架构满足不了伸缩的需求的时候,才考虑拆分。而微服务的目标是在一开始的时候就按照这种架构实现,是一种面向未来的架构,也就是说用开始的选择成本降低以后的重构成本。用经济学的观点来说,微服务是技术投资,单体应用是技术债务,技术有余力那可以投资以期待未来收益,没余力那就只能借债支持当前业务,等待未来还债。而随着微服务基础设施的越来越完善,用很小的投资就可以获得未来很大的收益,就没有理由拒绝微服务了。
官方文档 istio 中文文档
没有更多推荐了,

我要回帖

更多关于 查看服务器磁盘占用 的文章

 

随机推荐