Kubernetes 实践案例分享|将 Node.js 应用从 PaaS 平台移动到 Kubernetes Tutorial

2016-08-11

Kubernetes实践案例分享|在这次的 RisingStack 案例分享中,我们可以在 Kubernetes Tutorial 中学习到如何从 PaaS 供应商中迁移 Node.js 应用,同时降低响应时间、提高安全性、减少成本。


在谈到为什么、以及如何将我们的服务迁移到 Kubernetes 的故事之前,需要强调的是,使用 PaaS 平台是完全没错的。如果要开发一个新的产品,PaaS 是一个很完美的平台,同时它还是一个很好的快速迭代的解决方案——当然,这取决于你的需求和资源。


PaaS

RisingStack 的产品 Trace,我们的 Node.js 监控解决方案运行在最大的 PaaS 提供商之一上已有半年多。我们在其它解决方案中选择了 PaaS,因为我们想要重点关注产品而不是基础设施。

我们的需求其实和简单;我们需要:

  • 快速部署
  • 简单弹性伸缩
  • 无宕机部署
  • 回滚功能
  • 环境变量管理
  • 不同的 Node.js 版本
  • 无需开发运维人员

使用 PaaS 平台时,我们不希望有的副作用:

  • 服务间网络延时大
  • 缺乏 VPC
  • 多租户技术引起的响应时间高峰
  • 更高的成本(为每个进程支付,无论大小:clock,内部 API 等等)。

Trace 是作为一组微服务来开发的,所以你可以想象一下,网络延迟和服务费很快就开始对我们造成损害。


Kubernetes Tutorial

从 PaaS 经验来看,我们正在寻找一种解决方案,只需要少量的开发运维工作、同时保持原有的开发流程不变。我们并不想失去任何我们上面提到过的优势——但是,我们也曾想要修补那些明显的漏洞。

我们那时候正在寻找更加配置化的,团队中任何人都可以修改的基础设施。

Kubernetes 关注配置、基于容器、微服务友好型的特性,折服了我们。

让我用以下的章节来说明一下,在这些专业术语背后的意思。

什么是 Kubernetes?


Kubernetes 是一个自动部署,弹性调度和管理容器化应用程序的开源系统。

在这里我对 Kubernetes 就不多做介绍了,但是要看懂这篇帖子接下来要介绍的东西,Kubernetes 基础结构还是要了解的。

我的解释不一定完全正确,但是对于 Kubernetes 来说,你可以把它想象成一个 PaaS 平台:

  • pod:是一个和环境变量,磁盘等等一起的处于运行状态的容器化应用程序。Pods 的生成,消亡都很快,比如在部署的时候:

PaaS:目前正在运行的应用程序

  • Deployment:你的应用程序的配置描述了你需要的状态(CPU,内存,环境变量,Docker 镜像版本,运行的实例的数量,部署策略等等):

PaaS:应用设置

  • Secret:你可以将你的证书从环境变量中分离出来,

PaaS:不存在,就好像已分享的分开的 secret 环境变量,对于DB证书等等来说。

  • Service:通过 label 将运行的 pods 暴露到其他应用上,或者在理想的 IP 或者端口上暴露到外部世界。


PaaS:内置非配置负载均衡器

如何设置运行的 Kubernetes 集群?

在这里你有几个选项。最容易的一个就是,在谷歌云上创建一个容器引擎。它跟其它的谷歌云组件也都整合得很好,比如负载均衡器和磁盘。

同时你也要了解,Kubernetes 能够在任何地方,比如 AWS,DigitalOcean,Azure 等地方运行。想要了解更多信息,请点击:https://coreos.com/kubernetes/docs/latest/getting-started.html


运行应用程序

首先,我们需要先让我们的应用程序处于在 Docker 环境中跟Kubernetes运行得很好的状态。

如果你正在寻找关于如何用 Kubernetes 开启应用程序的 tutorial,查看他们的 tutorial 初级教程。

Docker 容器内的 Node.js 应用

Kubernetes 基于容器,所以首先我们需要把我们的应用都容器化。关于怎么容器话应用,如果你不确定的话,请点击我们之前的帖子:https://blog.risingstack.com/minimal-docker-containers-for-node-js/。

如果你是 NPM 个人用户,那么这个可能对你比较有帮助:https://blog.risingstack.com/private-npm-with-docker/。

Kubernetes 中的“Procfile”

我们为每个应用都创建一个 Docker 镜像(Git Repository)。如果 repository 包括了多个进程,比如:server,worker 和 clock,我们用一个环境变量在他们之间进行选择。你可能会觉得这很奇怪,但是我们不想从一样的源代码中创建,推进多个 Docker 镜像,这将会拖慢我们的 CI。


环境,回滚和服务发现


预发布,产品

在我们的 PaaS 阶段,我们给我们的服务命名:trace-foo,trace-foo-staging,预发布阶段和产品应用程序阶段的差别就是名字前缀,和不同的环境变量。在 Kubernetes 中是可以定义命名空间的。每个命名空间总体上来说是互相独立的,而且并不分享任何资源比如 secrets,config 等等。


应用程序版本

在容器化的基础设施上,每个应用程序版本应该都是打了 tag 标签的不同容器镜像。我们用 Git 短 hash 函数作为一个 Docker 镜像 tag。

要部署你的应用程序的新版本,你只需要在你的应用程序的部署配置中修改镜像 tag,剩下的 Kubernetes 会帮你做。

在你部署文件中,任何的修改都会被发布到版本中,于是你就可以在任何时间回滚回去。


在部署的过程中,我们只是快速替换 Docker 镜像——他们只需要几秒钟就可以。


服务发现

Kubernetes 有个内置的,简单的服务发现解决方案:已创建的服务暴露他们的主机名和端口,作为每个 pod 的环境变量。

如果你不需要高级服务发现,你可以试一试,而不是把服务的URL复制到其它的环境变量中。是不是很酷!


应用构建

要进入一个新的技术的真正挑战其实是,去了解如何让你需要的东西在产品中处于已经好了的状态。在以下小节中,我们会列举你应该在应用中设置什么。

零宕机部署和故障转移

Kubernetes 有它特有的方式来更新你的应用程序,这样它就可以保持 pods 一直运行,并且以较小的步骤来部署你的修改——替代原来的那种先停止再开启的方式。

其实防止零宕机部署也没用了;它会在你部署错什么东西的时候,避免杀死你的应用程序。在 Kubernetes 发现新的 pod 是不健康的时候,你的错误会停止升级到所有在运行的 pod。

Kubernetes 支持几个策略来部署你的应用程序。你可以在 Deployment 策略文档中进行检查。

优雅停止

这也不是完全跟 Kubernetes 相关,但是如果没有以合适的方式开启或者停止你的进程的话,那就不可能有一个好的应用程序生命周期。


开启服务器


完美的服务器停顿


在 Kubernetes 中,你应该为你的应用程序定义好健康检查(活性探测)。有了这个,Kubernetes 就可以检测到你的应用程序什么时候需要重新启动。

网页服务器健康检查

你有好几个选项可以检查应用程序的健康,但是我觉得最容易一个就是,创建一个 GET/healthz 端点来检查你的应用 logic/DB 连接这里。有个重要的事情要提一下的就是,每个应用程序都是不一样的,只有你能够知道需要怎样的检查来确认它是否在正常工作。


Worker健康检查

对于我们的 worker 来说,我们也会用同样的/healthz 端点来设置非常小的 HTTP 服务器,同样都是活性探测,这个端点是用不同的标准来检查的。我们这么做是为了拥有公司水平的健康检查端点。

Readiness Probe

Readiness probe 跟Livenessprobe(健康检查)有点相似,但是它只对网页服务器可行。它会告诉 Kubernetes service(~负载均衡器),流量可以被重新传到特定的 pod。

在部署的时候避免服务中断是基本的要求。


日志

对于日志来说,你们可以从不同的途径选择,比如添加 side containers 到你的应用程序,收集你的日志并且发送到定制日志解决方案,或者你可以跟随着内置谷歌云的脚步。我们的选择是内置的那个。

为了能够在谷歌云上解析内置日志水平,你需要以特定的格式来登录。你可以用 winston-gke 模块轻松地完成。

如果你想要以特定的方式登录,Kubernetes 会用容器,Deployment 等等自动合并你的日志信息。元信息和谷歌云会以正确的方式展现出来。

为了完成这个,我们转换我们的npm start到静音,Dockerfile 中的 npm start-s:CMD ["npm","start", "-s"]


监控

我们用 Trace 来检查我们的应用程序,Trace 充分利用来监控,设想微服务架构。Trace 的服务地图在理解应用程序间的互相交流的时候到帮了我们很多,同样,在理解数据库和外部依赖是什么的时候也起到了作用。

既然 Trace 独立于环境,我们就没必要在代码库中修改任何东西,我们可以用它来验证迁移和我们对性能提升的期望。


例子

用 Kubernetes 和 CircleCI 为 Node.js 来检查我们的 example repository:

https://github.com/RisingStack/kubernetes-nodejs-example


工具

用 CI 进行连续部署

用 JSON 途径来更新 Kubernetes 部署,或者只更新镜像 tag 是可能的。在你的 CI 机器上有一个运行的 kubectl,你只需要运行这个命令就可以:


调试

在 Kubernetes,在任意的容器内运行 shell 都是可能的,就像下图一样容易:

另一个有用的事情就是用下图所示代码检查 pod events:

同样你也可以以下代码来获取任意的日志信息:


代码 Piping

在我们 PaaS 提供商层面,我们倾向于喜欢在预发布和产品基础设施这两个阶段间的代码 piping。在 Kubernetes 中,我们漏掉了这个部分,所以我们创建了我们自己的解决方案。

这是一个简单的 npm 库,能够从 staging 版本读取目前的镜像标签,并且在 production 版本部署时进行设置。

因为 Docker 容器很像,只有环境变量改变了。

SSL 终端(https)

Kubernetes 服务默认设置下不是作为 https 来暴露的,但是你能够很轻松地修改它。为了做到这样,点击网址了解如何用 Kubernetes 上的 TLS 来暴露你的应用程序。


结论

用一句话来总结我们使用 Kubernetes 的经历就是:我们十分满意。

我们在微服务架构中优化了应用程序的响应时间,成功地用应用间的私人网络配置(VPC)提高了安全性。

同样,我们降低了成本,并且用内置滚动更新策略和健康检查提高了故障转移效率。

如果你正在思考基础设施的未来,那么绝对应该考虑使用 Kubernetes。

如果在从 PaaS 转移到 Kubernetes 的过程中,有任何的疑问,欢迎留言评论~


文章由才云科技翻译,如若转载,必须注明转载自“才云科技”。查看原文请点击“阅读原文”。

原文作者:Péter Márton

点击体验,开启谷歌级数字化之旅
立即体验
立即咨询