☰
Deploying DjangoBlog on Kubernetes: A Step-by-Step Cloud-Native Deployment Guide
2026/9/28 3:09:41 网站建设 项目流程
  • 后端
  • 前端
  • CMS

【免费下载链接】DjangoBlog

🍺基于Django的博客系统

项目地址:https://gitcode.com/gh_mirrors/dj/DjangoBlog
点击查看免费下载

这篇技术指南以仓库中的 deploy/k8s 目录为核心,完整讲解如何在 Kubernetes(K8s)集群上部署 DjangoBlog 及其配套服务栈(Nginx、MySQL、Redis、Elasticsearch)。读完本文你将掌握:这套部署方案的微服务化架构设计、从创建命名空间到首次初始化的六个完整部署步骤、每个 YAML 清单中关键字段的源码级含义,以及如何验证与排障部署结果。

Architecture Overview

本次部署采用微服务化的云原生架构,仓库中的 deploy/k8s 目录下提供了全套.yaml配置文件,其架构要点如下:

  • 核心组件独立部署:每个核心服务(DjangoBlog、Nginx、MySQL、Redis、Elasticsearch)都作为独立的Deployment运行,见 deploy/k8s/deployment.yaml。
  • 配置管理:Nginx 的配置文件与 Django 应用的环境变量通过ConfigMap统一管理,见 deploy/k8s/configmap.yaml。注意:敏感信息(如数据库密码)强烈建议改用Secret管理,ConfigMap仅适合存放非敏感配置。
  • 服务发现:所有服务都通过ClusterIP类型的Service在集群内部暴露,并以服务名(如djangoblog:8000、db:3306)相互通信,见 deploy/k8s/service.yaml。
  • 外部访问:使用Ingress资源将外部 HTTP 流量路由到 Nginx 服务,Nginx 作为整个博客应用的统一入口,见 deploy/k8s/gateway.yaml。
  • 数据持久化:采用基于节点本地路径的local-storage方案,需要在指定 K8s 节点上手动创建存储目录,并通过PersistentVolume(PV)与PersistentVolumeClaim(PVC)进行静态绑定,见 deploy/k8s/pv.yaml 与 deploy/k8s/pvc.yaml。

1. Prerequisites

开始部署之前,请确保已具备以下环境:

  • 一个正在运行的 Kubernetes 集群。
  • kubectl命令行工具已配置并能够连接到你的集群。
  • 集群中已安装并配置好Nginx Ingress Controller(用于解析gateway.yaml中的ingressClassName: nginx规则)。
  • 对集群中的一个节点(默认为master节点)拥有文件系统访问权限,用于创建本地存储目录。

2. Deployment Steps

下面按顺序完成六个部署步骤。所有清单文件均已限定在djangoblog命名空间下,因此先创建该命名空间。

Step 1: Create a Namespace

建议将 DjangoBlog 相关的所有资源都部署在一个独立命名空间中,便于统一管理和清理:

# 创建一个名为 djangoblog 的命名空间 kubectl create namespace djangoblog

Step 2: Configure Persistent Storage

本方案使用Local Persistent Volume(本地持久卷),需要先在某一个集群节点(pv.yaml 中默认为master节点)上创建数据存储目录:

# 登录到你的 master 节点 ssh user@master-node # 创建所需的存储目录 sudo mkdir -p /mnt/local-storage-db sudo mkdir -p /mnt/local-storage-djangoblog sudo mkdir -p /mnt/resource/ sudo mkdir -p /mnt/local-storage-elasticsearch # 退出节点 exit

注意:如果你希望将数据存储在其他节点或使用不同的路径,必须同步修改 deploy/k8s/pv.yaml 中的nodeAffinity与local.path字段。仓库默认通过nodeSelectorTerms将 PV 绑定到主机名为master的节点上,而local.path则指向上述手动创建的目录。

目录创建完成后,依次应用存储相关的三个清单:

# 应用 StorageClass kubectl apply -f deploy/k8s/storageclass.yaml # 应用 PersistentVolume (PV) kubectl apply -f deploy/k8s/pv.yaml # 应用 PersistentVolumeClaim (PVC) kubectl apply -f deploy/k8s/pvc.yaml

对存储清单做进一步说明,便于理解其绑定关系:

  • storageclass.yaml 定义名为local-storage的 StorageClass,provisioner为kubernetes.io/no-provisioner(即本地存储不会动态供给,必须预先创建 PV),volumeBindingMode为Immediate,并通过 annotation 将其标记为默认存储类。
  • pv.yaml 定义了 4 个 PV,均采用ReadWriteOnce访问模式与Retain回收策略:local-pv-db(10Gi,/mnt/local-storage-db)、local-pv-djangoblog(5Gi,/mnt/local-storage-djangoblog)、local-pv-resource(5Gi,/mnt/resource/)、local-pv-elasticsearch(5Gi,/mnt/local-storage-elasticsearch)。
  • pvc.yaml 定义了对应的 4 个 PVC(db-pvc、djangoblog-pvc、resource-pvc、elasticsearch-pvc),通过volumeName字段与上述 PV 一一静态绑定,容量申请与 PV 容量一致。

Step 3: Configure the Application

在部署应用之前,需要编辑 deploy/k8s/configmap.yaml,修改其中的敏感信息和个性化配置。

强烈建议修改以下字段:

  • DJANGO_SECRET_KEY:修改为一个随机且复杂的字符串。仓库中默认值为k8s-test-secret-key-12345678,仅用于测试,生产环境必须替换。
  • DJANGO_MYSQL_PASSWORD与MYSQL_ROOT_PASSWORD:修改为你自己的数据库密码。仓库中默认值为QQQQwww123!@#,且DJANGO_MYSQL_PASSWORD、MYSQL_ROOT_PASSWORD、MYSQL_PASSWORD三处必须保持一致,否则 MySQL 容器初始化与 Django 连接会不匹配。
# 编辑 ConfigMap 文件 vim deploy/k8s/configmap.yaml # 应用配置 kubectl apply -f deploy/k8s/configmap.yaml

该文件实际包含两个ConfigMap 对象:

  1. djangoblog-env:Django 与 MySQL 的环境变量,包括数据库名djangoblog、用户root、主机db(对应 MySQL 服务的 ClusterIP 服务名)、端口3306、Redis 地址redis:6379,以及DJANGO_DEBUG=False等。这些变量通过 Deployment 中的envFrom.configMapRef注入容器。
  2. web-nginx-config:完整的 Nginx 配置,被挂载进 Nginx 容器,包含:
    • nginx.conf:主配置,启用 gzip(gzip_comp_level 8)、sendfile、keepalive_timeout 65等;
    • djangoblog.conf:站点配置,将/请求通过proxy_pass http://djangoblog:8000反向代理到 Django 应用,/static/直接由alias /code/djangoblog/collectedstatic/提供静态文件,并单独处理robots.txt、favicon.ico、百度/谷歌验证文件等;
    • resource.lylinux.net.conf与lylinux.resource.conf:静态资源子域名的访问与缓存策略配置。

Step 4: Deploy the Application Stack

现在部署全部核心服务:

# 部署 Deployments (DjangoBlog, MySQL, Redis, Nginx, ES) kubectl apply -f deploy/k8s/deployment.yaml # 部署 Services (为 Deployments 创建内部访问端点) kubectl apply -f deploy/k8s/service.yaml

deployment.yaml 中共定义了 5 个 Deployment,关键配置如下:

Deployment镜像副本数端口关键特性
djangoblogliangliangyy/djangoblog:latest(imagePullPolicy: Always)38000通过configMapRef注入环境变量;配置/health/就绪与存活探针;挂载djangoblog-pvc到collectedstatic、resource-pvc到/resource
redisredis:latest16379轻量资源配额
dbmysql:latest13306注入 MySQL 相关环境变量;使用mysqladmin ping探针;数据挂载到/var/lib/mysql(db-pvc)
nginxnginx:latest180将web-nginx-config中的配置以subPath方式挂载到/etc/nginx/nginx.conf与/etc/nginx/conf.d/等路径;同时挂载静态资源 PVC
elasticsearchliangliangyy/elasticsearch-analysis-ik:8.6.119200单节点模式(discovery.type=single-node)、ES_JAVA_OPTS=-Xms256m -Xmx256m、关闭 xpack 安全认证、数据挂载到/usr/share/elasticsearch/data/(elasticsearch-pvc)

其中,djangoblogDeployment 的就绪/存活探针指向/health/端点。该端点由仓库源码实现:djangoblog/urls.py 中定义了health_check视图并注册为path('health/', health_check),返回{'status': 'healthy'},探针配置为initialDelaySeconds: 60、periodSeconds: 30——即容器启动 60 秒后才开始探测,之后每 30 秒检查一次。ES 容器的探针则直接请求 9200 端口的/路径。

service.yaml 定义了 5 个ClusterIP类型的 Service,通过selector按app标签关联到对应 Pod:djangoblog:8000、nginx:80、redis:6379、db:3306、elasticsearch:9200。集群内服务之间直接使用服务名通信,这也是 ConfigMap 中DJANGO_MYSQL_HOST=db、DJANGO_REDIS_URL=redis:6379等配置能生效的基础。

部署需要一些时间,可用以下命令观察所有 Pod 是否都进入Running状态:

kubectl get pods -n djangoblog -w

Step 5: Expose the Application Externally

最后,应用Ingress规则,将外部流量引导至 Nginx 服务:

# 应用 Ingress 规则 kubectl apply -f deploy/k8s/gateway.yaml

gateway.yaml 使用的是networking.k8s.io/v1版本的 Ingress:ingressClassName: nginx指定由集群内的 Nginx Ingress Controller 处理;规则将路径/(pathType: Prefix)的所有 HTTP 流量转发到后端 Servicenginx的 80 端口。由于 Nginx 内部又通过proxy_pass http://djangoblog:8000反向代理到 Django 应用,整个请求链路为:外部流量 → Ingress → Nginx Service → Nginx Pod → Django 应用。

部署完成后,可以通过 Ingress Controller 的外部 IP 地址访问博客,用以下命令获取地址:

kubectl get ingress -n djangoblog

Step 6: First-Time Initialization

与 Docker 部署类似,首次运行时需要进入 DjangoBlog 应用的 Pod 执行数据库初始化和创建管理员账户:

# 首先,获取 djangoblog pod 的名称 kubectl get pods -n djangoblog | grep djangoblog # 进入其中一个 Pod (将 [pod-name] 替换为上一步获取到的名称) kubectl exec -it [pod-name] -n djangoblog -- bash # 在 Pod 内部执行以下命令: # 创建超级管理员账户 (请按照提示操作) python manage.py createsuperuser # (可选) 创建测试数据 python manage.py create_testdata # (可选,如果启用了 ES) 创建搜索索引 python manage.py rebuild_index # 退出 Pod exit

至此,你已成功在 Kubernetes 集群上完成 DjangoBlog 的部署!

深入理解:容器启动时的自动初始化流程

如果你使用的是liangliangyy/djangoblog:latest镜像,容器启动时并非直接拉起 Django 服务,而是由镜像的 ENTRYPOINT——deploy/entrypoint.sh——自动执行一串初始化命令:

python manage.py makemigrations && \ python manage.py migrate && \ python manage.py collectstatic --noinput && \ ... 校验 Vite 构建产物并复制 .vite 目录 ... python manage.py compress --force && \ python manage.py build_index && \ python manage.py compilemessages || exit 1 exec gunicorn djangoblog.wsgi:application \ --workers 1 --bind 0.0.0.0:8000 \ --worker-class gevent --threads 4

这意味着:数据库迁移(migrate)、静态文件收集(collectstatic)、压缩(compress)、索引构建(build_index)与消息编译(compilemessages)都会在 Pod 启动阶段自动完成,随后以gunicorn + gevent的方式在0.0.0.0:8000上提供服务。这也解释了deployment.yaml中探针initialDelaySeconds设为 60 秒的原因——需要给初始化流程留出时间。因此,Step 6 中的rebuild_index通常只在 ES 索引需要重建(例如修改了索引映射)时才有必要手动执行。对应镜像的构建过程见 Dockerfile:多阶段构建,先在node:20-alpine阶段用 Vite 构建前端资源,再在python:3.11阶段安装依赖并合并构建产物。

Elasticsearch 连接与索引说明

deployment.yaml 中的 ES 使用带 IK 中文分词插件的镜像liangliangyy/elasticsearch-analysis-ik:8.6.1,以单节点模式运行并关闭了安全认证。Django 侧对 ES 的连接配置支持通过环境变量注入,见 djangoblog/settings.py:当设置了DJANGO_ELASTICSEARCH_HOST环境变量时,会据此构建ELASTICSEARCH_DSL配置,并支持ELASTICSEARCH_VERIFY_CERTS、ELASTICSEARCH_USERNAME、ELASTICSEARCH_PASSWORD、ELASTICSEARCH_API_KEY、ELASTICSEARCH_CA_CERTS、ELASTICSEARCH_CLIENT_CERT、ELASTICSEARCH_CLIENT_KEY等可选参数,最终生成HAYSTACK_CONNECTIONS。因此如果需要在 K8s 环境中显式指定 ES 地址,可以在 configmap.yaml 的djangoblog-env中追加DJANGO_ELASTICSEARCH_HOST: "elasticsearch:9200"一类的配置。索引的完整重建则通过python manage.py rebuild_index完成。

部署验证与常见排查点

完成上述步骤后,可以按如下方式做整体验证:

# 检查所有资源是否就绪 kubectl get pods,svc,ingress,pv,pvc -n djangoblog # 查看 djangoblog 日志,确认 gunicorn 已启动 kubectl logs -n djangoblog <djangoblog-pod-name> # 进入 Pod 验证健康检查端点 kubectl exec -it <djangoblog-pod-name> -n djangoblog -- curl -s http://localhost:8000/health/

常见排查点与对应依据如下:

  1. Pod 一直处于 Pending/ContainerCreating:多为本地 PV 未绑定。确认节点上目录已创建、pv.yaml的nodeAffinity与目录所在节点一致,并用kubectl describe pvc -n djangoblog检查 PVC 是否已绑定到对应 PV。
  2. 应用无法连接数据库:检查djangoblog-envConfigMap 中的DJANGO_MYSQL_HOST=db是否与 service.yaml 中的db服务名一致,并确认 MySQL 探针(mysqladmin ping)已通过。
  3. 外部访问不通:确认集群已安装 Nginx Ingress Controller,且gateway.yaml的ingressClassName: nginx与控制器一致;再通过kubectl get ingress -n djangoblog查看 Ingress 的 ADDRESS 列是否已分配外部地址。
  4. 静态资源 404:检查djangoblog-pvc是否已挂载到/code/djangoblog/collectedstatic,因为 Nginx 的静态文件alias指向该目录,而它依赖容器启动时collectstatic的输出。

总结

DjangoBlog 的 K8s 部署方案在仓库的 deploy/k8s 目录中以 6 个 YAML 清单完整落地:storageclass.yaml/pv.yaml/pvc.yaml解决数据持久化,configmap.yaml统一管理 Nginx 配置与应用环境变量,deployment.yaml以多副本 Deployment 承载 5 个核心服务,service.yaml提供集群内服务发现,gateway.yaml通过 Ingress 暴露外部入口。配合 deploy/entrypoint.sh 的启动自动初始化与 djangoblog/urls.py 的健康检查端点,即可在生产集群上以云原生方式稳定运行整套博客服务。

  • 后端
  • 前端
  • CMS

【免费下载链接】DjangoBlog

🍺基于Django的博客系统

项目地址:https://gitcode.com/gh_mirrors/dj/DjangoBlog
点击查看免费下载
上一篇:RimWorld终极开局定制指南:如何用EdB Prepare Carefully打造完美殖民团队
下一篇:从抽屉到游戏战场:DsHidMini如何让PS3手柄在Windows上重获新生

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询