简体   繁体   English

K8s:使用 dbs 的 node.js 应用程序的部署模式

[英]K8s: deployment patterns for node.js apps with dbs

Hi!你好!

My problem is relevant with the deployment of node.js apps via k8s, architecture patterns, and connected them with DBs.我的问题与通过 k8s、架构模式部署 node.js 应用程序有关,并将它们与 DB 连接。

 alpha | beta | gamma1 | gamma2

I have the following node.js app services, some of them are scalable with app instances (like gamma), others are separate ones, all of them are built in a single docker image with .Dockefile and running from it.我有以下 node.js 应用程序服务,其中一些可通过应用程序实例(如 gamma)进行扩展,另一些是独立的,所有这些都构建在带有.Dockefile的单个 docker 映像中并从中运行。

And I also have a-non-cloud DBs, like elastic & mongo running from their containers with .env : mongo | elastic而且我还有一个非云数据库,比如弹性和 mongo 从他们的容器中运行.envmongo | elastic mongo | elastic

As for now, my docker-compose.yml is like a typical node.js example app, but with common volume and bridge-network (except I have more then one node.js app):就目前而言,我的docker-compose.yml就像一个典型的 node.js 示例应用程序,但具有通用卷和桥接网络(除了我有多个 node.js 应用程序):

version: '3'
services:
  node:
    restart: always
    build: .
    ports:
      - 80:3000
    volumes:
      - ./:/code
  mongo:
    image: mongo
    ports:
      - 27017:27017
    volumes:
      - mongodb:/data/db
volumes:
 mongodb:

networks:
  test-network:
    driver: bridge

Current deployment:当前部署:

All these things are running on a single heavy VPS (X CPU cores, Y RAM, Z SSD, everything loaded by 70%) from single docker-compose.yml file.所有这些东西都在单个docker-compose.yml文件的单个重型 VPS(X CPU 内核、Y RAM、Z SSD,所有内容加载 70%)上运行。

What I want to ask and achieve:我想问和实现的目标:

Since one VPS is already not enough, I'd like to start using k8s with rancher.由于一个 VPS 已经不够用了,我想开始使用k8s和 Rancher。 So the question is about correct deployment:所以问题是关于正确的部署:

For example, I have N VPSs connected within one private network, each VPS is a worker connected in one cluster, (with Rancher, of course, one of them is a master node) which gives me X cores, Y RAM, and other shared resources.例如,我有N个 VPS 连接在一个私有网络中,每个 VPS 是一个连接在一个集群中的工作程序,(使用 Rancher,当然其中一个是主节点)这给了我 X 核、Y RAM 和其他共享资源。

  1. Do I need another, separate cluster (or a VPS machine in a private network, but not part of a cluster) with DB running on it?我是否需要另一个单独的集群(或专用网络中的 VPS 机器,但不是集群的一部分),并在其上运行 DB? Or I could deploy DB in the same cluster?或者我可以在同一个集群中部署数据库? And what if each VPS (worker) in the cluster has only 40GB volume, and DB will grow more than this volume?如果集群中的每个 VPS(worker)只有 40GB 卷,而 DB 的增长会超过这个卷呢? Do shared resources from workers include the shared volume space?工作人员的共享资源是否包括共享卷空间?

  2. Is it right to have one image from which I can start all my apps, or in the case of k8s, I should I have a separate docker image for each service?拥有一个可以启动所有应用程序的图像是否正确,或者在 k8s 的情况下,我应该为每个服务拥有一个单独的 docker 图像吗? So if I have 5 node.js apps within one mono-repo, I should have 5 separate docker-image, not one common?因此,如果我在一个单一存储库中有 5 个 node.js 应用程序,我应该有 5 个单独的 docker-image,而不是一个常见的?

I'll understand that my question can have a complex answer, so I will be glad to see, not just answer but links or anything that is connected with a problem.我会理解我的问题可能有一个复杂的答案,所以我会很高兴看到,不仅仅是答案,还有链接或与问题相关的任何内容。 It's much more easy to find or google for something, if you know and how to ask.如果您知道以及如何询问,则更容易找到或搜索某些内容。

A purist answer:一个纯粹的答案:

Each of your five services should have their own image, and their own database.您的五项服务中的每一项都应该有自己的映像和自己的数据库。 It's okay for the databases to be in the same cluster so long as you have a way to back them up, run migrations, and do other database-y things.只要您有办法备份它们、运行迁移和执行其他与数据库相关的事情,数据库就可以位于同一个集群中。 If your cloud provider offers managed versions of these databases then storing the data outside the cluster is fine too, and can help get around some of the disk-space issues you cite.如果您的云提供商提供这些数据库的托管版本,那么将数据存储在集群之外也很好,并且可以帮助解决您提到的一些磁盘空间问题。

I tend to use Helm for actual deployment mechanics as a way to inject things like host names and other settings at deploy time.我倾向于将Helm用于实际部署机制,作为在部署时注入主机名和其他设置等内容的一种方式。 Each service would have its own Dockerfile, its own Helm chart, its own package.json , and so on.每个服务都有自己的 Dockerfile、自己的 Helm 图表、自己的package.json等等。 Your CI system would build and deploy each service separately.您的 CI 系统将分别构建和部署每个服务。

A practical answer:一个实用的答案:

There's nothing technically wrong with running multiple containers off the same image doing different work.在同一个镜像上运行多个容器做不同的工作在技术上没有任何问题。 If you have a single repository and a single build system now, and you don't mind a change in one service causing all of them to redeploy, this approach will work fine.如果您现在有一个存储库和一个构建系统,并且您不介意更改一项服务会导致所有服务重新部署,那么这种方法将可以正常工作。

Whatever build system your repository has now, if you go with this approach, I'd put a single Dockerfile in the repository root and probably have a single Helm chart to deploy it.无论您的存储库现在有什么构建系统,如果您使用这种方法 go,我会在存储库根目录中放置一个 Dockerfile 并且可能有一个 Helm 图表来部署它。 In the Helm chart Deployment spec you can override the command to run with something like在 Helm 图表部署规范中,您可以覆盖命令以运行类似

# This fragment appears under containers: in a Deployment's Pod spec
# (this is Helm chart, Go text/template templated, YAML syntax)
image: {{ .Values.repository }}/{{ .Values.image }}:{{ .Values.tag }}
command: node service3/index.js

Kubernetes's terminology here is slightly off from Docker's, particularly if you use an entrypoint wrapper script.此处 Kubernetes 的术语与 Docker 的术语略有不同,特别是如果您使用入口点包装脚本。 Kubernetes command: overrides a Dockerfile ENTRYPOINT , and Kubernetes args: overrides CMD . Kubernetes command: args: CMD ENTRYPOINT

In either case:在任一情况下:

Many things in Kubernetes allocate infrastructure dynamically. Kubernetes 中的许多东西动态分配基础设施。 For example, you can set up a horizontal pod autoscaler to set the replica count of a Deployment based on load, or a cluster autoscaler to set up more (cloud) instances to run Pods if needed.例如,您可以设置一个水平 pod 自动扩缩器来根据负载设置部署的副本数,或者设置一个集群自动扩缩器来设置更多(云)实例来运行 Pod(如果需要)。 If you have a persistent volume provisioner then a Kubernetes PersistentVolumeClaim object can be backed by dynamically allocated storage (on AWS, for example, it creates an EBS volume), and you won't be limited to the storage space of a single node.如果您有一个持久卷配置器,那么 Kubernetes PersistentVolumeClaim object 可以由动态分配的存储支持(例如,在 AWS 上,它会创建一个 EBS 卷),并且您不会受到单个节点的存储空间的限制。 You can often find prebuilt Helm charts for the databases;您通常可以为数据库找到预构建的 Helm 图表; if not, use a StatefulSet to have Kubernetes create the PVCs for you.如果没有,请使用 StatefulSet 让 Kubernetes 为您创建 PVC。

Make sure your CI system produces images with a unique tag, maybe based on a timestamp or source control commit ID.确保您的 CI 系统生成具有唯一标签的图像,可能基于时间戳或源代码控制提交 ID。 Don't use ...:latest or another fixed string: Kubernetes won't redeploy on update unless the text of the image: string changes.不要使用...:latest或其他固定字符串:Kubernetes 不会在更新时重新部署,除非image:字符串更改。

Multiple clusters is tricky in a lot of ways.多个集群在很多方面都很棘手。 In my day job we have separate clusters per environment (development, pre-production, production) but the application itself runs in a single cluster and there is no communication between clusters.在我的日常工作中,每个环境(开发、预生产、生产)都有单独的集群,但应用程序本身在单个集群中运行,并且集群之间没有通信。 If you can manage the storage then running the databases in the same cluster is fine.如果您可以管理存储,那么在同一个集群中运行数据库就可以了。

Several Compose options don't translate well to Kubernetes.几个 Compose 选项不能很好地转换为 Kubernetes。 I'd especially recommend removing the volumes: that bind-mount your code into the container and validating your image runs correctly, before you do anything Kubernetes-specific.我特别建议删除volumes:在您执行任何特定于 Kubernetes 的操作之前,将您的代码绑定到容器中并验证您的映像是否正确运行。 If you're replacing the entire source tree in the image then you're not really actually running the image, and it'll be much easier to debug locally.如果您要替换映像中的整个源代码树,那么您实际上并没有真正运行映像,并且在本地调试会容易得多。 In Kubernetes you also have almost no control over networks: but they're not really needed in Compose either.在 Kubernetes 中,您也几乎无法控制networks:但 Compose 中也不需要它们。

I can't answer the part of your question about the VPS machine setup, but I can make some suggestions about the image setup.我无法回答您关于 VPS 机器设置的部分问题,但我可以就图像设置提出一些建议。

Actually, while you have asked this question about a node app, it's actually applicable for more than just node.实际上,虽然您已经问过这个关于节点应用程序的问题,但它实际上不仅仅适用于节点。

Regarding the docker image and having a common image or separate ones;关于docker镜像,有共同镜像或单独镜像; generally it's up to you and/or your company as to whether you have a common or separate image.通常,您和/或您的公司是否拥有共同的或单独的形象取决于您和/或您的公司。

There's both pros and cons about both methods:两种方法各有利弊:

You could "bake in" the code into the image, and have a different image per app, but if you run into any security vulnerabilities, you have to patch, rebuild, and redeploy all the images.您可以将代码“烘焙”到映像中,并为每个应用程序提供不同的映像,但如果遇到任何安全漏洞,您必须修补、重建和重新部署所有映像。 If you had 5 apps all using the same library, but that library was not in the base image, then you would have to patch it 5 times, once in each image, rebuild the image and redeploy.如果您有 5 个应用程序都使用同一个库,但该库不在基础映像中,那么您必须对其进行 5 次修补,每个映像一次,重建映像并重新部署。

Or you could just use a single base image which includes the libraries needed, and mount the codebase in (for example as a configmap), and that base image would never need to change unless you had to patch something in the underlying operating system.或者,您可以只使用包含所需库的单个基础映像,并将代码库安装在其中(例如作为配置映射),除非您必须在底层操作系统中修补某些内容,否则该基础映像永远不需要更改。 The same vulnerability mentioned in the paragraph above, would only need to be patched in the base image, and the affected pods could be respun (no need to redeploy).上面段落中提到的相同漏洞只需要在基础映像中进行修补,并且可以重新启动受影响的 Pod(无需重新部署)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM