在Kubernetes上运行Flask

635 阅读12分钟

在本教程中,我们将首先了解Kubernetes和容器编排的一般情况,然后我们将通过一个分步骤的教程,详细介绍如何将一个基于Flask的微服务(以及Postgres和Vue.js)部署到Kubernetes集群。

这是一个中级别的教程。请回顾《用Python、Flask和Docker进行测试驱动开发》课程,以了解这些工具的更多信息。

依赖性。

目标

在本教程结束时,你将能够。

  1. 解释什么是容器编排,以及为什么你可能需要使用一个编排工具
  2. 讨论使用Kubernetes与其他协调工具(如Docker Swarm和Elastic Container Service(ECS))的利弊。
  3. 解释以下Kubernetes基元。节点、Pod、服务、标签、部署、入口和体积
  4. 使用Docker Compose在本地启动一个基于Python的微服务
  5. 用Minikube配置一个Kubernetes集群在本地运行
  6. 在Kubernetes集群中设置一个卷来保存Postgres数据
  7. 使用Kubernetes Secrets来管理敏感信息
  8. 在Kubernetes上运行Flask、Gunicorn、Postgres和Vue
  9. 通过Ingress将Flask和Vue暴露给外部用户

什么是容器编排(Container Orchestration)?

当你从在单台机器上部署容器到在多台机器上部署时,你需要一个协调工具来管理(和自动化)整个系统中容器的安排、协调和可用性。

协调工具有助于。

  1. 跨服务器的容器通信
  2. 横向扩展
  3. 服务发现
  4. 负载平衡
  5. 安全/TLS
  6. 零停机时间的部署
  7. 回滚
  8. 记录
  9. 监控

这就是Kubernetes与其他一些协调工具(如Docker SwarmECSMesosNomad)配合的地方。

你应该使用哪一个?

  • 如果你需要管理大型、复杂的集群,就使用Kubernetes
  • 如果你刚开始工作和/或需要管理中小型集群,就使用Docker Swarm
  • 如果你已经在使用一些AWS服务,就使用ECS
工具优点缺点
Kubernetes庞大的社区,灵活,大多数功能,时髦设置复杂,学习曲线高,时髦
Docker Swarm易于设置,非常适合小型集群受限于Docker的API
ECS完全管理的服务,与AWS集成厂商锁定

市场上也有一些管理型的Kubernetes服务。

  1. 谷歌Kubernetes引擎(GKE)
  2. 弹性Kubernetes服务(EKS)
  3. Azure Kubernetes服务(AKS)
  4. DigitalOcean Kubernetes

更多信息,请查看《选择正确的容器化和集群管理工具》博文。

Kubernetes的概念

在深入研究之前,让我们看看你必须从Kubernetes API中获得的一些基本构建块。

  1. **节点**是为运行Kubernetes而配置的工作机。每个Node都由Kubernetes主站管理。
  2. **Pod**是一个逻辑上紧密耦合的应用容器组,在Node上运行。Pod中的容器被部署在一起并共享资源(如数据卷和网络地址)。多个Pod可以在一个节点上运行。
  3. **服务**是一个逻辑上的Pod集合,执行类似的功能。它可以实现负载平衡和服务发现。它是Pod上的一个抽象层;Pod是短暂的,而服务是更持久的。
  4. **部署**是用来描述Kubernetes的理想状态的。它们决定了Pod的创建、部署和复制的方式。
  5. **标签**是连接到资源(如Pod)的键/值对,用于组织相关的资源。你可以把它们想成是CSS选择器。比如说。
    • 环境-dev,testprod
    • 应用程序版本-beta1.2.1
    • 类型-client,serverdb
  6. **Ingress**是一组路由规则,用于控制基于请求主机或路径的服务的外部访问。
  7. ****是用来在容器寿命结束后持久保存数据的。它们对于像Redis和Postgres这样的有状态的应用特别重要。
    • *PersistentVolume*定义了一个独立于正常Pod生命周期的存储卷。它是在它所在的特定Pod之外管理的。
    • *PersistentVolumeClaim*是一个用户使用PersistentVolume的请求。

欲了解更多信息,请查看学习Kubernetes基础教程以及Kubernetes概念讲座中的Kubernetes概念幻灯片,该讲座是用Kubernetes扩展Flask

项目设置

克隆flask-vue-kubernetesrepo,然后构建镜像并启动容器。

创建并播种数据库books 表。

在你选择的浏览器中测试以下服务器端的端点。

http://localhost:5001/books/ping

container_id 是应用程序所运行的Docker容器的ID。

http://localhost:5001/books。

导航到http://localhost:8080。确保基本的CRUD功能按预期运行。

在继续前进之前,快速浏览一下代码。

想了解如何建立这个项目?请查看《用Flask和Vue.js开发单页应用程序》博文。

Minikube

Minikube是一个工具,它允许开发者在本地使用和运行Kubernetes集群。这是一个快速启动和运行集群的好方法,因此你可以开始与Kubernetes API互动。

按照官方的入门指南,将Minikube与以下内容一起安装。

  1. 一个管理程序(如VirtualBoxHyperKit)来管理虚拟机
  2. Kubectl来部署和管理Kubernetes上的应用程序

如果你使用的是Mac,我们建议用Homebrew安装Kubectl和Minikube。

然后,启动集群,拉出Minikube仪表板

minikube dashboard

值得注意的是,配置文件将位于~/.kube目录下,而所有的虚拟机位将位于~/.minikube目录下。

现在我们可以开始通过Kubernetes API创建对象。

如果你遇到Minikube的问题,通常最好是完全删除它并重新开始。

比如说。

创建对象

要在Kubernetes中创建一个新的对象,你必须提供一个 "规格",描述它所期望的状态。

例如。

必要的字段。

  1. apiVersion -Kubernetes API版本
  2. kind - 你想创建的对象的类型
  3. metadata - 关于该对象的信息,以便它可以被唯一识别
  4. spec - 对象的预期状态

在上面的例子中,该规范将为Flask应用程序创建一个新的部署,并带有一个副本(Pod)。请注意containers 部分。在这里,我们指定了Docker镜像以及应用程序要运行的容器端口。

为了运行我们的应用程序,我们需要设置以下对象。

objects

流量

同样,由于容器是短暂的,我们需要通过PersistentVolumePersistentVolumeClaim来配置一个卷,以存储Pod之外的Postgres数据。

请注意kubernetes/persistent-volume.yml中的YAML文件。

这个配置将在Node内的"/data/postgres-pv "创建一个hostPathPersistentVolume。卷的大小为2吉字节,访问模式为ReadWriteOnce,这意味着该卷可以被单个节点挂载为读写。

值得注意的是,Kubernetes只支持在单节点集群上使用hostPath。

创建卷。

查看细节。

你应该看到。

你也应该在仪表板上看到这个对象。

minikube dashboard

kubernetes/persistent-volume-claim.yml

创建卷的要求。

查看细节。

minikube dashboard

秘密

密是用来处理敏感信息的,如密码、API令牌和SSH密钥。我们将设置一个Secret来存储我们的Postgres数据库凭证。

kubernetes/secret.yml

userpassword 字段是base64编码的字符串(通过隐蔽性的安全)。

请记住,任何能够访问集群的用户都能够读取明文的值。如果你想在传输过程中和休息时对秘密进行加密,可以看看Vault

添加Secrets对象。

minikube dashboard

Postgres

在集群中设置了卷和数据库凭证后,我们现在可以配置Postgres数据库本身。

我们可以使用kubernetes/postgres-deployment.yml

这里发生了什么?

  1. metadata
    • name 字段定义了部署的名称------。postgres
    • labels 定义部署的标签 -name: database
  2. spec
    • replicas 定义要运行的Pod的数量 -1
    • selector 定义了部署如何找到要管理的Pod
    • template
      • metadata
        • labels 指出哪些标签应该被分配给Pod -service: postgres
      • spec
        • containers 定义与每个Pod相关的容器
        • volumes 定义卷要求 -postgres-volume-mount
        • restartPolicy 定义重启政策-Always

此外,Pod的名称是postgres ,图像是postgres:13-alpine ,它将从Docker Hub提取。从Secret对象中获取的数据库凭证也会被传入。

最后,当应用时,卷要求将被安装到Pod中。卷要求被挂载到"/var/lib/postgresql/data"--默认位置--而数据将被存储在PersistentVolume,"/data/postgres-pv"。

创建部署。

状态。

kubernetes/postgres-service.yml

这里发生了什么?

  1. metadata
    • name 字段定义了服务名称 -postgres
    • labels 定义该服务的标签 -name: database
  2. spec
    • selector 定义服务所适用的Pod标签和值 - 定义服务的类型service: postgres
    • type 定义了服务的类型 ClusterIP
    • ports
      • port 定义暴露在集群中的端口

花点时间回到部署规范中去。服务中的selector 是如何与部署相关联的?

由于服务的类型ClusterIP ,它不对外公开,所以它只能从集群内部被其他对象访问。

创建该服务。

创建books 数据库,使用Pod名称。

验证创建情况。

你也可以通过以下方式获得Pod名称。

将该值分配给一个变量,然后创建数据库。

花点时间查看Flask项目结构以及Dockerfileentrypoint.sh文件。

  1. "services/server"
  2. services/server/Dockerfile
  3. services/server/entrypoint.sh

kubernetes/flask-deployment.yml

这看起来应该与Postgres部署规范类似。最大的区别是,你可以使用我在Docker Hub上预建和预推的镜像,mjhea0/flask-kubernetes ,或者建立和推送你自己的。

比如说。

如果你使用你自己的,请确保在kubernetes/flask-deployment.yml中用你的Docker Hub名称替换mjhea0

另外,如果不想把镜像推送到Docker注册中心,在本地构建镜像后,你可以把image-pull-policy 标志设为Never ,以便始终使用本地镜像。

创建部署。

minikube dashboard

这将立即启动一个新的Pod。

minikube dashboard

kubernetes/flask-service.yml

targetPort 以及它与port 的关系感到好奇吗?查看正式的服务指南

创建服务。

确保Pod与服务相关联。

minikube dashboard

应用迁移并为数据库添加种子。

验证。

入站

为了使流量能够访问集群内的Flask API,你可以使用NodePort、LoadBalancer或Ingress。

  1. NodePort在节点上的一个开放端口上暴露一个服务。
  2. 顾名思义,LoadBalancer创建一个外部负载平衡器,指向集群中的一个服务。
  3. 与前两种方法不同,Ingress不是服务的一种类型;相反,它位于服务之上,是进入集群的一个入口。

更多信息,请查阅官方发布服务指南

在这里,我们定义了以下的HTTP规则:1.kubernetes/minikube-ingress.yml

在这里,我们定义了以下HTTP规则。

  1. / - 将请求路由到Vue服务(我们还需要设置)。
  2. /books - 将请求路由到Flask服务

启用Ingress插件

创建Ingress对象。

如果你看到一个Internal error occurred: failed calling webhook "validate.nginx.ingress.kubernetes.io" 的错误,尝试删除ValidatingWebhookConfiguration

更多信息,请查看Stack Overflow的这个主题

接下来,你需要更新你的*/etc/hosts*文件,将请求从我们定义的主机,hello.world ,路由到Minikube实例。

在*/etc/hosts*中添加一个条目。

试试吧。

hello.world/books/ping。

hello.world/books。

Vue

继续前进,查看Vue项目以及相关的Docker文件。

  1. "服务/客户"
  2. /services/client/Dockerfile
  3. /services/client/Dockerfile-minikube

kubernetes/vue-deployment.yml

同样,要么使用我的镜像,要么构建并推送你自己的镜像到Docker Hub。

创建部署。

验证Pod是否与部署一起被创建。

你如何验证Pod和部署在仪表板上被成功创建?

kubernetes/vue-service.yml

创建服务。

确保hello.world/,按预期工作。

bookshelf app

缩放

Kubernetes可以很容易地进行扩展,当流量负荷过大,单个Pod无法处理时,可以根据需要添加额外的Pod。

例如,让我们在集群中添加另一个Flask Pod。

确认。

向服务发出几个请求。

你应该看到不同的container_id,表明请求正在通过两个副本之间的轮回算法进行适当的路由。

如果你在流量冲击集群的时候缩小规模,会发生什么?打开两个终端窗口,在你的电脑上测试一下。你应该看到流量被适当地重新分配了。再试一次,但这次要扩大规模。

有用的命令

命令解释
minikube start启动一个本地Kubernetes集群
minikube ip显示集群的IP地址
minikube dashboard在浏览器中打开Kubernetes仪表板
kubectl version显示Kubectl的版本
kubectl cluster-info显示集群的信息
kubectl get nodes列表中的节点
kubectl get pods列表中的Pod
kubectl get deployments列出部署情况
kubectl get services列出服务
minikube stop停止一个本地Kubernetes集群
minikube delete移除本地Kubernetes集群

查看Kubernetes Cheatsheet了解更多命令。

自动化脚本

准备好把所有东西放在一起了吗?

看看项目根中的deploy.sh脚本。这个脚本。

  1. 创建一个PersistentVolume和一个PersistentVolumeClaim
  2. 通过Kubernetes Secrets添加数据库凭证
  3. 创建Postgres部署和服务
  4. 创建Flask部署和服务
  5. 启用Ingress
  6. 应用Ingress规则
  7. 创建Vue部署和服务

试试吧!

一旦完成,创建books 数据库,应用迁移,并为数据库播种。

更新*/etc/hosts*,然后在浏览器中进行测试。

总结

在本教程中,我们研究了如何在Kubernetes上运行一个基于Flask的微服务。

至此,你应该对Kubernetes的工作原理有了基本的了解,并且能够部署一个集群,在上面运行一个应用。

其他资源。

  1. 学习Kubernetes基础知识
  2. 配置最佳实践
  3. 使用Kubernetes扩展Flask
  4. 在Docker Swarm上运行Flask(对比在Docker Swarm和Kubernetes上运行Flask)。
  5. 用Kubernetes将Node应用部署到谷歌云上

你可以在GitHub上的flask-vue-kubernetesrepo中找到这些代码。