Web Development

在 Kubernetes 中部署 Django 应用

Read this post in other languages:

Kubernetes 是一个开源容器编排平台,可以自动执行部署、扩缩和负载平衡,在 Django 应用程序的管理方面具有无与伦比的弹性和灵活性

无论是启动小型项目还是管理复杂应用程序,Kubernetes 都能提供稳健的环境来增强您的 Django 应用程序,确保它能够满足现代 Web 开发的需求。

通过自动执行容器化应用程序的部署、扩缩和运作,Kubernetes(或 K8s)为快速发展的科技行业中的组织提供了许多好处。

无论您是想要增强部署技能的 Django 开发者,还是渴望探索 Django 集成的 Kubernetes 爱好者,本指南都可以满足您的需求。

本教程简介探讨了 Django 与 Kubernetes 之间的共生关系,让您能够无缝容器化 Web 应用程序、跨集群分配工作负载,并确保高可用性。

Django

Django 框架作为一个高级 Python Web 框架,已经成为 Web 开发中高效和简洁的象征。 Django 诞生于创建快速、稳健且可维护的 Web 应用程序的需求,现已成为开发者和组织的首选。

Django 的核心是“自带电池”理念,搭载大量内置工具、库和约定,为开发流程提供便利。 它简化了 URL 路由、数据库集成和用户身份验证等复杂任务,使开发者能够专注于构建应用程序。

Django 最重要的优点之一是它遵循“避免重复代码”(DRY) 原则,减少冗余并增强代码可维护性。 它还遵循模型-视图-控制器 (MVC) 架构模式,使应用程序结构化且易于管理。

Django 还将安全性放在首位,因此不易出现常见的 Web 漏洞。 它包括开箱即用的跨站点脚本 (XSS) 和跨站点请求伪造 (CSRF) 防护等功能。 Django 兼具速度、简洁和安全,是希望以最小工作量创建稳健、功能丰富的 Web 应用程序的开发者的理想选择。

容器编排器

容器编排器是管理和自动执行容器化应用程序的部署、扩缩和运作的重要工具。 市场上有多种容器编排器,其中最受欢迎的包括:

1. 顶级开源容器编排平台 Kubernetes 为处理容器化应用程序提供了一个稳健且适应性强的环境。 它能够自动执行扩缩、负载平衡和容器状况检查等任务,并拥有广泛的扩展程序生态系统。

2. Docker Swarm 是 Docker 提供的容器编排解决方案。 它在设计上易于设置和使用,拥有与 Docker 相同的命令行界面和 API,适合已经在使用 Docker 的小型应用程序或组织。

3. OpenShift 是 Red Hat 开发的企业 Kubernetes 平台。 它在 Kubernetes 的基础上添加了开发者和运营工具,简化了容器化应用程序的部署和管理。

4. Nomad 由 HashiCorp 开发,是一款轻量级、人性化编排器,能够管理容器和非容器化应用程序。

5. Apache Mesos 是一种开源分布式系统内核,DC/OS(数据中心操作系统)是一个基于 Mesos 构建的企业级平台。 DC/OS 扩展了 Mesos,具备用于管理和扩缩容器化应用程序的额外功能。

软件团队主要与 AWS、Google Cloud Platform 和 Azure 等知名云提供商提供的托管平台合作。 这些云提供商提供 Amazon EKS、Google GKE 和 Azure AKS 等服务,它们都是托管的 Kubernetes 解决方案。 这些服务简化了 Kubernetes 集群的设置、扩展和管理,并与各自的云环境无缝集成,确保高效的容器编排和应用程序部署。

在 PyCharm 中创建 Django 应用程序

在本教程中,我们将首先生成一个最小的 Django 应用程序。 然后,我们将容器化应用程序,并在最后一步使用 Docker Desktop 将其部署到本地 Kubernetes 集群。

如果您刚接触 Django 框架,但想从头开始创建 Django 应用程序,可以阅读这篇博文

这里是本教程中使用的源代码。

首先,我们在 PyCharm 中创建一个新的 Django 应用程序

要创建项目,请启动 PyCharm 并点击 New Project(新建项目)。 如果 PyCharm 已经在运行,可以从主菜单中选择 File | New Project(文件 | 新建项目)。

利用 venv 或自定义环境提供项目名称、位置和解释器类型等基本信息。

然后,点击 Create(创建)。

PyCharm 将设置项目和创建虚拟环境。

Gunicorn

创建项目后,安装 Gunicorn – 一种流行的 Python Web 服务器网关接口 (WSGI) HTTP 服务器。 Gunicorn 是用于投放 Python Web 应用程序的预复刻工作进程模型 Web 服务器,通常与 Django、Flask 等 Web 框架结合使用,以部署 Web 应用程序并使其可通过互联网访问。

Python Packages(Python 软件包)工具窗口为预览和安装当前所选 Python 解释器的软件包提供了最快速、最简单的方式。

您可以通过 View | Tool Windows | Python Packages(视图 | 工具窗口 | Python 软件包)打开工具窗口。

Psycopg 2

Psycopg 2 是用于连接 PostgreSQL 数据库并与之交互的 Python 库。 它提供了一个 Python 接口用来与 PostgreSQL(最流行的开源关系数据库管理系统之一)协同工作。 Psycopg 2 允许 Python 开发者在 Python 程序内执行各种数据库操作,例如插入、更新和检索数据,以及执行 SQL 查询和管理数据库连接。

在安装 psycopg2 之前,您需要安装系统级依赖项,在 macOS 上是 brew install libpq,在 Linux 上是 apt-get install libpq-dev

参考:postgresql.org/docs/16/libpq.html

libpq 是用于 PostgreSQL 的客户端库。 它是一个 C 库,为客户端应用程序连接、交互和管理 PostgreSQL 数据库服务器提供必要功能。 

完成具体修改后,更新 settings.py 中与 DATABASES 相关的部分。

务必通过环境变量传递密钥凭据。

STATIC_ROOT

在 Django 中,STATIC_ROOT 是一个配置设置,用于指定运行 collectstatic 管理命令时存储收集的静态文件的绝对文件系统路径。 静态文件通常包括 CSS、JavaScript、镜像和 Web 应用程序使用的其他资源。 STATIC_ROOT 设置是生产环境中提供静态文件的重要部分。

在第 127 行为 STATIC_ROOT 设置环境变量。 此变量将指向 Kubernetes 持久卷的文件路径。 后续我将解释如何配置此设置。

要收集静态文件,请运行以下命令:

python manage.py collectstatic

此命令将收集静态文件并将其放入 STATIC_ROOT 目录。 然后,您可以直接通过 NGINX 或 Apache Web 服务器提供这些资源,这对于生产环境来说是一种更有效的方式。

Dockerfile

Dockerfile 是一个直观的文本文档,包含用于构建 Docker 镜像的指令。

1. FROM python:3.11:此行使用来自 Docker Hub 的官方 Python 3.11 镜像指定 Docker 镜像的基础镜像。 应用程序将在此已预装 Python 的基础镜像上构建和运行。

2. ENV PYTHONUNBUFFERED 1:此行将环境变量 PYTHONUNBUFFERED 设为 1。 通常建议在 Docker 容器内运行 Python 时设置此环境变量,确保 Python 不会缓冲输出。 这有助于从应用程序获取实时日志和调试信息。

3. WORKDIR /app:此行将 Docker 容器内的工作目录设为 /app。 所有后续命令都将在此目录中执行。

4. COPY . /app:此行将当前目录(Dockerfile 所在目录)的内容复制到容器内的 /app 目录。 这包括您的应用程序代码和 Docker 镜像所需的任何文件。

5. RUN pip install -r requirements.txt:此行运行 pip install 命令,安装 /app 目录中的 requirements.txt 文件列出的 Python 依赖项。 这是 Python 应用程序的常见做法,允许您管理应用程序的依赖项。

6. EXPOSE 8000:此行通知 Docker 容器侦听端口 8000。 它实际上并不发布端口。 它是一个元数据声明,用于指示容器可能使用的端口。

7. CMD ["gunicorn", "django_kubernetes_tutorial.wsgi:application", "--bind", "0.0.0.0:8000"]:此行指定容器启动时运行的默认命令。 它使用 Gunicorn 投放 Django 应用程序,并使用 django_kubernetes_tutorial.wsgi:application 中定义的 WSGI 应用程序绑定 Gunicorn 以侦听端口 8000 上的所有网络接口 (0.0.0.0)。

DockerHub

访问 hub.docker.com,然后在平台上登录或注册。

点击 Create repository(创建仓库)。

接下来,提供仓库名称并将公开范围设置为 Public(公开)。 如果您在处理敏感或机密信息,请将可见性设为 Private(不公开)。

创建仓库后,您需要构建 docker 镜像,然后将镜像推送到注册表。

执行命令前,运行以下命令来确保 requirements.txt 文件是最新的:

pip freeze > requirements.txt

要构建镜像,请执行以下命令: 

docker build -t mukulmantosh/django-kubernetes:1.0 .

docker build -t /django-kubernetes:1.0 .

此命令将根据具体情况而有所不同,并且您需要使用您的个人用户名。

然后,您需要向 Docker Hub 进行身份验证,以将镜像推送到注册表。

在终端中输入以下命令:

docker login

输入用户名和密码。 身份验证成功后,即可通过运行以下代码推送镜像:

docker push mukulmantosh/django-kubernetes:1.0 

docker push /django-kubernetes:1.0 

镜像成功推送后,您会在 Docker Hub 中观察到变化。

如果您不打算再向注册表推送镜像,可以运行以下命令退出登录:

docker logout

如果您想本地拉取此镜像,请访问 hub.docker.com/r/mukulmantosh/django-kubernetes

Kubernetes 配置:编写 YAML 文件

本节教程介绍如何将应用程序部署到本地 Kubernetes 集群。

在教程中,我们将使用 Docker Desktop,但您也可以使用 minikube 或 kind。

命名空间

在 Kubernetes 中,命名空间是集群内的虚拟分区,用于对资源和对象进行分组和隔离。 这是一种在单个物理群集中创建多个虚拟集群的方式。 

您可以使用 Kubernetes 命令行工具 kubectl 创建和管理命名空间,也可以在部署资源时在 YAML 清单中定义。 

  • 如果选择 Docker Desktop 作为运行 Kubernetes 的首选平台,务必在设置中点击 Enable Kubernetes(启用 Kubernetes)复选框来启用 Kubernetes。

在终端中运行以下命令创建命名空间:

kubectl create ns django-app

使用 K8s 部署数据库

首先,在本地环境的 Kubernetes 集群中建立一个 PostgreSQL 实例。

PersistentVolume

在 Kubernetes 中,持久卷 (PV) 是管理员在集群中配置的一部分存储空间。 通过以独立于 pod 生命周期的方式存储数据,PV 允许对存储资源进行更解耦、更灵活的管理和抽象。 这意味着即使使用数据的 pod 被删除或重新安排到集群中的其他节点,数据仍然可以持续存在。

创建一个持久卷,并将其命名为 pv.yml

此 YAML 配置会定义一个名为 postgres-pv 的 PersistentVolume 资源,容量为 1 GB,使用 ReadWriteOnce 访问模式挂载,由位于 /data/db 的节点文件系统上的本地路径提供。 此 PV 可用于为需要访问节点文件系统上目录的 pod 提供持久存储,适用于 PostgreSQL 等应用程序或其他需要持久存储的有状态服务。

对于生产,我们建议使用 AWS RDS 或 Google CloudSQL 等云解决方案,或者使用 Kubernetes StatefulSets

PersistentVolumeClaim

在 Kubernetes 中,PersistentVolumeClaim (PVC) 是一种资源对象,由 pod 用来向 PV 请求具有特定属性的特定数量的存储空间。 PVC 可以作为应用程序声明存储资源的一种方式,无需了解底层存储基础架构的详细信息。

通过创建和使用 PVC,Kubernetes 提供了一种为应用程序动态分配和管理存储资源的方式,同时抽象底层存储基础架构,有助于简化容器化环境中有状态应用程序的使用和管理。

我们创建一个 PVC,并将其命名为 pvc.yml

PVC 请求存储资源,并与提供实际存储空间的 PV 绑定。 

此 YAML 配置会在 django-app 命名空间中定义一个名为 postgres-pvc 的 PersistentVolumeClaim。 它以 ReadWriteOnce 访问模式请求 1 GB 的存储空间,并显式指定 manual StorageClass。 此 PVC 用于绑定到名为 postgres-pv 的现有 PV,进而有效保留该卷以供 django-app 命名空间内引用此 PVC 的 pod 使用。

ConfigMap

在 Kubernetes 中,ConfigMap 是一个 API 对象,用于以键值对形式存储配置数据。 ConfigMaps 提供了一种将配置数据与应用程序代码分离的方式,使配置更易管理和更新,无需修改和重新部署容器。 它们对于配置 Kubernetes 集群内的应用程序、微服务和其他组件特别有用。

我们创建一个 ConfigMap,并将其命名为 cm.yml

本教程使用 ConfigMaps,但出于安全考虑,建议将敏感凭据存储在 Kubernetes Secret 中,或尝试 Bitnami Sealed Secrets、AWS Parameter Store 或 HashiCorp Vault 等替代方案。

Deployment

在 Kubernetes 中,Deployment 是一种用于管理应用程序部署和扩缩的资源对象。 它是 Kubernetes API 组的一部分,提供了一种声明式方式来定义和管理应用程序的所需状态。

Deployment 是用于管理和扩缩应用程序 pod 的更高级别的 Kubernetes 资源。 

此 YAML 配置会在 django-app 命名空间中定义一个名为 postgres 的 Deployment。 它将部署具有持久存储的 PostgreSQL 数据库(版本 16.0)的单个副本。 数据库 pod 被标记为 app: postgresdb,存储空间由名为 postgres-pvc 的 PVC 提供。 PostgreSQL 容器的配置和凭据通过名为 db-secret-credentials 的 ConfigMap 提供。

Service

在 Kubernetes 中,Service 是一种用于将一组 pod 公开为网络服务的资源对象。 Service 在 Kubernetes 集群中运行的应用程序的不同部分之间实现网络通信,并为客户端提供访问这些部分的稳定端点。 Service 抽象底层网络基础架构,使应用程序的组件更易连接和发现。

此 YAML 配置会在 django-app 命名空间中定义一个名为 postgres-service 的 NodePort Service。 它在集群内端口 5432 上公开在标有“app: postgresdb”的 pod 中运行的 PostgreSQL 服务。 外部客户端可以使用端口 30004 访问任何节点的 IP 地址上的 Service。 Service 提供了一种从 Kubernetes 集群外部访问 PostgreSQL 数据库的方式。

为 Django 应用程序创建 YAML 配置

PersistentVolume

此 YAML 会定义一个名为 staticfiles-pv 的 PersistentVolume,具有 1 GB 存储,允许多个 pod 同时读写。 存储空间由位于 /data/static 的本地主机路径提供。 Django 静态文件将存储在此位置。

PersistentVolumeClaim

此 YAML 会在 django-app 命名空间中定义一个名为 staticfiles-pvc 的 PVC。 它从具有“manual”StorageClass 的 PV 请求容量至少为 1 GB 的存储空间,并指定需要 ReadWriteMany 访问权限。 声明显示绑定到名为 staticfiles-pv 的现有 PV 以满足其存储需求。 这允许 django-app 命名空间中的 pod 使用此 PVC 访问和使用关联 PV 提供的存储空间。

ConfigMap

此 YAML 会在 django-app 命名空间中定义一个名为 app-cm 的 ConfigMap,包含存储配置数据的多个键值对。 此 ConfigMap 可被 django-app 命名空间内的 pod 或其他资源用于访问配置设置,例如数据库连接信息和静态文件路径。

Deployment

此 YAML 会在 django-app 命名空间中定义一个名为 django-app-deploy 的 Deployment。 Deployment 将创建一个副本 (pod),运行带有特定 Docker 镜像和配置的容器。 pod 与 PVC 支持的两个卷 postgres-db-storagestaticfiles 相关联。 容器被配置为使用名为 app-cm 的 ConfigMap 中的环境变量并侦听端口 8000。 卷挂载于容器内的特定路径上,提供对数据库存储和静态文件的访问。 此 Deployment 是使用 Kubernetes 运行 Django 应用程序的常用方式。

如果您有兴趣从不公开注册表中拉取镜像,请阅读本文。 

Service

Service 侦听端口 8000,并将传入流量导向标有 app: django-application 的 pod。 这是一种常见配置,用于在运行同一应用程序的多个实例的 Kubernetes 集群中公开 Web 应用程序并对其进行负载平衡。 Service 可以确保流量在它们之间均匀分布。

NGINX

NGINX 是一种高性能 Web 和反向代理服务器,以其速度、可靠性和可扩缩性著称。 它能有效处理 Web 流量、负载平衡和内容分发,是投放网站和应用程序的热门选择。

ConfigMap

此 YAML 会在 django-app 命名空间中定义一个名为 nginx-cm 的 Kubernetes ConfigMap,包含一个键值对,其中键是 default.conf,值是将请求代理到后端服务器的多行 NGINX 配置文件。 

Deployment

此 YAML 会定义一个 Deployment,后者将创建和管理运行具有特定卷和配置的 NGINX 容器的 pod。 Deployment 确保此 pod 的一个副本始终在 django-app 命名空间中运行。 它还用 nginx-cm ConfigMap 替换默认 NGINX 配置,将其重写。

Service

此 YAML 配置会在 django-app 命名空间中创建一个名为 nginx-service 的 Kubernetes Service。 它在集群内的端口 80 上公开带有标签 app:nginx 的 pod,并使 Service 可在每个集群节点上的 NodePort 30005 上访问。 这样,外部流量就可以通过 NodePort 服务到达运行 NGINX 应用程序的 pod。

使用 Kubernetes 作业管理批处理工作负载

在 Kubernetes 中,Job 是一个资源对象,代表一个工作单元或一个有限任务。 Job 旨在以指定成功完成的次数将任务运行到完成。 

数据库迁移

此 YAML 配置会在 django-app 命名空间中定义一个名为 django-db-migrations 的 Kubernetes Job。 Job 使用用于 Django 迁移的自定义 Docker 镜像运行容器,并挂载 PVC 为数据库相关文件提供存储空间。 如果 Job 失败,最多可以重试 15 次,并且完成后它将保留其 pod 100 秒。 此 Job 将在 PostgreSQL 中创建新表。

静态文件

此 YAML 配置会在 django-app 命名空间中定义一个名为 django-staticfiles 的 Kubernetes Job。 Job 使用用于收集 Django 应用程序的静态文件的自定义 Docker 镜像运行容器,并挂载 PVC 为静态文件提供存储空间。 如果 Job 失败,最多可以重试 3 次,并且完成后它会将其 pod 保留 100 秒以用于调试。 此 Job 将静态文件复制到 mountPath,即 /data/static

启动应用程序

要启动应用程序,请导航到 k8s 目录并执行以下命令:

部署应用程序后,使用以下命令验证正在运行的 pod 的状态:

kubectl get pods -n django-app -w

在 Django 中创建超级用户

在所有应用程序启动并运行后,创建一个超级用户以作为 Django 管理员登录。

运行以下命令获取正在运行的 pod 的列表:

kubectl get pods -n django-app

要进入容器 shell,请运行:

kubectl exec -it -n django-app -- sh

然后,运行:

python manage.py createsuperuser

成功创建超级用户后,在浏览器中打开 http://127.0.0.1:30005。 您将被定向至默认欢迎页面。

然后,通过 http://127.0.0.1:30005/admin 转到 Django 管理。

输入您刚刚创建的用户名和密码。 

通过身份验证后,您将被重定向至 Django 管理页面。 

如果尝试通过 localhost:30005/admin 登录,您可能会收到 403 Forbidden (CSRF) 错误。

您可以在 CSRF_TRUSTED_ORIGINS 下的 settings.py 文件中解决此错误。

CSRF_TRUSTED_ORIGINS 是 Django 中的设置,用于为跨站点请求伪造 (CSRF) 防护指定可信来源列表。 CSRF 是一种安全漏洞,当攻击者诱使用户在不知情的情况下向 Web 应用程序发出不需要的请求时就会出现这种漏洞。 为了防止这种情况,Django 包含内置的 CSRF 保护。

通过 CSRF_TRUSTED_ORIGINS,您可以定义接受 CSRF 防护请求的来源(网站)列表。 任何来自列表外来源的请求都将被视为潜在恶意请求,并被妥善阻止。

此设置可用于允许对 Django 应用程序发出的某些跨源请求,同时保持安全以防范 CSRF 攻击。 它特别适合应用程序需要与托管在不同域上的其他 Web 服务或 API 交互的情况。

如果您使用 Kubernetes Dashboard 等 GUI 工具,您可以轻松直观呈现正在运行的 pod、部署和持久卷等。

PyCharm 中的 Kubernetes 支持 

PyCharm 提供专为 Kubernetes 定制的增强型编辑器和运行时支持,为简化 Kubernetes 管理提供了大量功能,包括:

  • 浏览集群对象,提取并编辑其配置,以及描述对象。
  • 查看事件。
  • 查看和下载 pod 日志。
  • 附加 pod 控制台。
  • 在 pod 中运行 shell。
  • 将端口转发到 pod。
  • 从编辑器应用资源 YAML 配置。
  • 从集群中删除资源。
  • 补全集群中的 ConfigMap 和 Secret 条目。
  • 配置 kubectl 路径。
  • 全局和按项目配置自定义 kubeconfig 文件。
  • 切换上下文和命名空间。
  • 使用来自有效集群的 API 架构(包括 CRD)编辑资源清单。

免费试用 PyCharm 执行 Kubernetes 任务!

参考

已经对 Kubernetes 有了扎实的了解? 那就在编程之旅中迈出下一步,探索云解决方案,查看有关 AWS EKSGoogle Kubernetes Engine 的教程。

本博文英文原作者:

Mukul Mantosh

Mukul Mantosh

image description

Discover more