基于Kubernetes的Drupal现代化部署:从容器化到生产就绪的完整实践
1. 项目概述:一个为Kubernetes而生的Drupal实战范例
如果你正在寻找一个能直接扔进Kubernetes集群里跑起来的、配置完整的Drupal项目样板,那么
geerlingguy/drupal-for-kubernetes
这个仓库绝对值得你花时间深入研究。这不是一个简单的“Hello World”演示,而是一个由资深DevOps工程师Jeff Geerling构建的、经过实战检验的生产级项目范例。它完美地展示了如何将一个传统的、以服务器为中心的CMS(内容管理系统)现代化,改造为完全拥抱容器化和云原生理念的、可弹性伸缩的应用。对于任何计划将Drupal、乃至其他PHP应用迁移到K8s环境的开发者或运维工程师来说,这个项目就像一份详尽的“施工蓝图”,清晰地标明了从代码结构、容器构建到配置管理的每一个关键节点。
这个项目的核心价值在于它的“完整性”和“可操作性”。它不仅仅提供了一个Dockerfile和几个YAML文件,而是构建了一个完整的、遵循最佳实践的Drupal项目骨架。从使用Composer管理依赖、Drush进行运维,到利用Drupal 8+的配置管理(CMI)和内容导出功能,整个工作流都设计得井井有条。更重要的是,它明确区分了开发环境(通过Docker Compose快速拉起)和生产部署目标(Kubernetes),让你可以在本地轻松验证一切,然后信心十足地部署到复杂的K8s集群中。无论是为了学习K8s上的应用部署模式,还是为了给自己手头的Drupal项目寻找一个现代化的架构参考,这个项目都能提供极具深度的洞见。
2. 项目架构与设计哲学解析
2.1 为何选择“配置即代码”与“不可变基础设施”
这个项目的设计深深植根于两个现代运维的核心理念: 配置即代码(Configuration as Code) 和 不可变基础设施(Immutable Infrastructure) 。在传统的Drupal部署中,我们常常通过Web界面修改设置,这些配置存储在数据库里。当需要部署到新环境时,要么手动重复操作,要么依赖不完善的数据库同步,极易出错且难以版本控制。
drupal-for-kubernetes
项目彻底改变了这一点。它强制要求所有站点配置(如内容类型、视图、字段等)都通过Drupal的配置管理接口(CMI)导出为YAML文件,并纳入Git版本控制。这意味着,
你的站点状态是由代码仓库中的配置文件定义的,而不是数据库
。部署新环境时,只需执行
drush config:import
,就能精确复现一个完全一致的站点。这种做法带来了几个巨大优势:版本回滚变得轻而易举;团队协作可以通过代码评审(Code Review)来管理配置变更;生产环境与开发环境的差异被降到最低。
与之配套的是不可变基础设施的思想。项目中的Docker镜像一旦构建完成,就被视为一个不可变的单元。你不会通过SSH进入容器去修改文件或安装模块;任何变更都需要更新代码、重新构建镜像、然后部署新的容器实例。这种模式与Kubernetes的滚动更新、健康检查等特性是天作之合,确保了部署的一致性和可预测性。项目中的Dockerfile和
docker-compose.yml
正是为构建和运行这个“不可变”的应用单元而设计的。
2.2 面向Kubernetes的Drupal项目结构剖析
打开项目仓库,你会发现它的目录结构经过精心设计,清晰地分离了关注点:
drupal-for-kubernetes/
├── Dockerfile # 定义生产/开发容器镜像的蓝图
├── docker-compose.yml # 本地开发环境编排(包含Drupal、MySQL)
├── composer.json # PHP依赖管理(核心、模块、主题、库)
├── web/ # Drupal核心安装目录(通过Composer安装在此)
│ ├── core/
│ ├── modules/
│ ├── sites/default/ # 站点配置、文件存储
│ │ ├── settings.php # 主设置文件(包含环境变量注入逻辑)
│ │ └── services.yml
│ └── ...
├── config/ # **核心**:导出的Drupal配置YAML文件
├── docs/ # 项目详细文档
└── scripts/ # 辅助构建和部署的脚本
这个结构的关键在于
web/
目录是Composer项目的
webroot
。Drupal核心、贡献模块、自定义模块和主题都通过Composer安装到
web/
下的相应位置。
config/
目录独立存放导出的配置,与代码分离但又被同一仓库管理。
sites/default/settings.php
文件通常会包含从环境变量(如
DRUPAL_DATABASE_PASSWORD
)读取数据库凭据的逻辑,这是容器化应用十二要素原则的体现——将配置存储在环境中。
注意 :很多初次接触此模式的开发者会困惑于“代码”和“配置”的界限。简单来说,
web/modules/custom/下的自定义模块代码是“代码”,而通过Drupal后台设置的“内容类型有哪些字段”、“视图如何显示”等信息是“配置”。此项目强调将后者也纳入版本控制。
2.3 开发与生产环境的一致性保障策略
项目通过Docker Compose搭建的本地环境,旨在无限接近最终的生产Kubernetes环境。
docker-compose.yml
文件模拟了生产环境中的服务依赖关系:一个Drupal容器链接到一个MySQL容器。Drupal容器使用的镜像正是由项目根目录的
Dockerfile
构建而来。
这种做法的好处是, 你在本地开发时使用的PHP版本、扩展、Web服务器(通常是Nginx或Apache打包在镜像内)与生产环境完全一致 。避免了“在我机器上好好的,一上线就出问题”的经典困境。同时,因为配置管理(CMI)的存在,你在本地通过Drush导出的配置YAML文件,可以直接提交,并在生产环境的部署流程中被导入,确保了功能的一致性。
3. 核心组件与工具链深度解读
3.1 Dockerfile:构建可复现的Drupal镜像
项目的
Dockerfile
是构建应用的基石。一个典型的、为生产优化的Drupal Dockerfile会包含多个构建阶段(Multi-stage Build),以减小最终镜像的体积。它可能大致如下工作:
-
基础阶段
:使用一个包含Composer的PHP镜像作为构建器(Builder),将
composer.json和composer.lock复制进去,运行composer install --no-dev --optimize-autoloader来安装生产依赖(不安装开发依赖,优化自动加载)。 -
最终阶段
:使用一个更轻量的、为运行环境优化的PHP镜像(如
php:fpm-alpine)。从构建器阶段复制已安装好的vendor/目录和整个web/目录。同时,会安装必要的PHP扩展(如gd,pdo_mysql,opcache等),并设置正确的文件权限(确保www-data用户对sites/default/files有写权限)。 -
健康检查
:通常会添加
HEALTHCHECK指令,定期检查/health或/user/login等端点,以便Kubernetes感知容器是否就绪。
# 示例片段:多阶段构建
FROM composer:2 AS builder
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --optimize-autoloader
FROM php:8.2-fpm-alpine
RUN apk add --no-cache ... # 安装系统依赖和PHP扩展
COPY --from=builder /app/vendor /var/www/html/vendor
COPY web /var/www/html/web
COPY --chown=www-data:www-data scripts/docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost/ || exit 1
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["php-fpm"]
实操心得 :务必在构建器阶段使用
--no-dev标志,避免将xdebug等开发工具打包进生产镜像,这能显著减小镜像体积并提升安全性。同时,composer.lock文件必须提交到仓库,它是依赖树版本的唯一真实来源,能保证每次构建安装完全相同的库版本。
3.2 Docker Compose:本地开发环境的敏捷编排
docker-compose.yml
文件是本地开发的“一键启动器”。它定义了两个服务:
drupal
和
database
(通常是MySQL或MariaDB)。
version: '3.8'
services:
drupal:
build: .
ports:
- "80:80"
environment:
DRUPAL_DATABASE_HOST: database
DRUPAL_DATABASE_PASSWORD: secret
volumes:
- ./web:/var/www/html/web
- ./config:/var/www/html/config
depends_on:
- database
database:
image: mariadb:10.6
environment:
MYSQL_ROOT_PASSWORD: rootsecret
MYSQL_DATABASE: drupal
MYSQL_USER: drupal
MYSQL_PASSWORD: secret
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:
这里有几个关键设计:
-
卷挂载(Volumes)
:将本地的
web和config目录挂载到容器内。这意味着你在宿主机上使用IDE修改代码或配置文件,容器内能立即生效,无需重建镜像,极大提升了开发效率。 - 环境变量 :数据库连接信息通过环境变量传递,与生产环境(K8s ConfigMap/Secret)的配置方式保持一致。
-
数据持久化
:使用命名卷
db_data来持久化数据库文件,即使容器销毁,数据也不会丢失。
3.3 Composer与Drush:现代化的Drupal工作流支柱
这个项目完全拥抱了Drupal社区的现代工具链。
-
Composer
:管理所有PHP依赖,包括Drupal核心、贡献模块、主题、第三方库,甚至开发工具。
composer.json文件定义了项目的全部依赖关系。运行composer require drupal/module_name是添加新模块的标准方式,它会自动处理版本约束并更新composer.lock。 -
Drush
:Drupal的命令行瑞士军刀。在容器化环境中,你通过
docker compose exec drupal drush <command>来执行所有管理操作:安装站点、更新数据库、清除缓存、导入导出配置、管理用户等。项目文档中给出的安装、配置导出、内容导出等命令,都是基于Drush的。
这两者结合,构成了一个可重复、可脚本化的开发部署流程。例如,项目升级流程(
composer update
后跟
drush updb
和
drush cex
)就是一个经典范例。
4. 从零开始:本地开发环境搭建与站点初始化
4.1 环境准备与镜像构建
假设你已经在本地安装了Docker和Docker Compose,并且克隆了项目仓库。
第一步是构建Drupal镜像。这个镜像包含了运行Drupal所需的所有环境。
# 在项目根目录执行
docker build -t my-drupal-app .
这个命令会根据
Dockerfile
的指令,一步步构建出名为
my-drupal-app
的本地镜像。构建过程可能会花费几分钟,因为它需要下载基础镜像、安装系统包、PHP扩展,并通过Composer安装所有PHP依赖。构建成功后,你可以通过
docker images
命令看到它。
4.2 使用Docker Compose启动全套服务
镜像构建完成后,使用Docker Compose一键启动所有服务(Drupal和MySQL)。
docker compose up -d
-d
参数代表“分离模式”,让服务在后台运行。此时,Docker Compose会:
-
为
database服务拉取MariaDB镜像(如果本地没有)。 -
创建并启动
database容器,根据环境变量初始化数据库。 -
基于刚才构建的
my-drupal-app镜像(或在docker-compose.yml中指定的镜像)创建并启动drupal容器。 -
将本地
web和config目录挂载到drupal容器内。 -
将宿主机的80端口映射到
drupal容器的80端口。
启动后,可以使用
docker compose logs -f
来实时跟踪容器日志,特别是Drupal容器的日志,可以看到PHP-FPM和Web服务器的启动情况,以及任何初始化错误。
4.3 安装依赖与初始化Drupal站点
容器运行起来后,你需要进入Drupal容器内部完成Composer依赖的最终安装和Drupal的安装。
# 1. 安装Composer依赖(如果构建镜像时已安装,此步骤在挂载卷后可能需要重新生成自动加载文件)
docker compose exec drupal composer install
这一步确保容器内
vendor/
目录下的自动加载器与挂载的
web/
目录中的代码同步。
# 2. 使用Drush命令行安装Drupal(推荐,快速且可脚本化)
docker compose exec drupal bash -c 'drush site:install minimal \
--db-url="mysql://drupal:${DRUPAL_DATABASE_PASSWORD}@${DRUPAL_DATABASE_HOST}/drupal" \
--site-name="我的K8s Drupal站点" \
--existing-config -y'
这个命令是关键:
-
--db-url:从环境变量中动态获取数据库密码和主机名,这正体现了十二要素应用的原则。 -
--existing-config:这是 最核心的参数 。它告诉安装程序:“不要使用默认配置,请使用config/目录中已有的YAML文件来配置我的站点。” 这意味着,如果你的config/目录里已经有一些预先定义好的配置(比如内容类型、视图),安装完成后站点就会直接拥有这些配置,实现了“配置即代码”的部署。 -
-y:自动回答“yes”到所有提示,适用于自动化脚本。
安装完成后,Drush会在终端打印出管理员账户(通常是
admin
)的随机密码。记下它,然后就可以访问 http://localhost ,用
admin
和这个密码登录了。
踩坑记录 :如果你在Docker for Mac/Windows上操作,可能会遇到一个性能问题。在容器内执行
composer install后,由于宿主机和虚拟机之间文件同步的延迟,容器内的vendor/目录可能不会立即反映出所有变化,导致自动加载失败。一个解决办法是在宿主机(如果安装了PHP和Composer)上运行composer install,让文件直接写入本地挂载的目录,这样容器能更快识别。或者,耐心等待几秒钟让文件同步完成。
5. 配置与内容管理:贯穿开发与部署的核心工作流
5.1 配置的版本控制与同步
项目正常运行后,你可能会通过后台管理界面修改一些配置,比如增加一个内容类型的字段、修改一个视图的显示格式。在传统Drupal中,这些修改只保存在数据库里。而在这个项目中,你需要将它们“推”回代码库。
# 在Drupal容器内执行,将当前站点的所有配置导出到 config/ 目录
docker compose exec drupal bash -c 'drush config:export -y'
执行后,检查
config/
目录,你会发现很多
.yml
文件被创建或更新。这些文件就是当前站点配置的完整快照。接下来,你需要使用Git将这些变更提交到代码仓库。
git add config/
git commit -m "为文章内容类型添加摘要字段"
git push
为什么这样做?
想象一下生产环境。当你将包含新配置的代码部署到Kubernetes集群时,新的Pod(容器)会基于新代码启动。在Drupal的启动流程或部署脚本中,会执行
drush config:import -y
。这个命令会将
config/
目录下的YAML文件与数据库中的配置进行比对,并将差异
导入
到数据库,从而使生产站点的配置与代码库中的定义保持一致。这就实现了配置的同步和版本化管理。
5.2 内容的可迁移性处理
配置可以管理,那内容(如文章、页面)呢?理想情况下,生产站点的内容是由编辑人员在线创建的,不应混入代码库。但对于一些基础性、结构化的内容(如“关于我们”页面、默认分类术语、初始菜单项),我们可能希望像配置一样进行管理。
项目通过一个自定义模块
pidramble_default_content
(或其理念)来处理这个问题。它使用
drush dcer
(Default Content Exporter)等工具,将特定内容实体(如节点、分类术语)序列化并导出到指定目录(如
web/modules/custom/pidramble_default_content/content/
)。
# 导出ID为1的节点(例如“关于我们”页面)
docker compose exec drupal bash -c 'drush dcer --folder=modules/custom/pidramble_default_content/content/ node 1'
导出的内容文件(通常是JSON或YAML)会被提交到代码库。当这个模块在新环境(包括生产环境)被启用时,它会自动检测并导入这些内容文件。这为站点提供了一种可预测的初始内容状态。
注意事项 :内容导出/导入比配置管理更复杂,容易产生ID冲突或依赖问题(比如一篇文章引用的分类术语必须先存在)。因此,通常只对关键的、不变的基础内容使用此方法。动态的、用户生成的内容应通过数据库备份/恢复或专门的内容同步工具来处理。
5.3 完整的开发-提交-部署循环
结合以上两点,一个标准的开发工作流如下:
- 本地开发 :在 http://localhost 上进行修改(安装新模块、修改配置、创建基础内容)。
-
导出变更
:
-
配置变更:
drush cex -
基础内容变更:
drush dcer ...
-
配置变更:
-
代码管理
:将导出的YAML/JSON文件以及可能更新的
composer.json(如果安装了新模块)提交到Git。 - CI/CD流水线 :代码推送到远程仓库(如GitHub)后,触发CI/CD流程(例如GitHub Actions)。流程可能包括:运行测试、构建新的Docker镜像、将镜像推送到镜像仓库(如Docker Hub)。
-
生产部署
:在Kubernetes集群中,更新Deployment的镜像标签,触发滚动更新。新的Pod启动时,通过初始化容器(Init Container)或启动脚本执行
drush config:import和drush en pidramble_default_content等操作,使新实例达到预期状态。
6. 生产就绪:面向Kubernetes的部署考量
6.1 从Docker Compose到Kubernetes清单的思维转换
本地
docker-compose.yml
方便了开发,但生产环境需要Kubernetes的清单文件(Manifests)。你需要将Compose中的概念映射到K8s资源:
| Docker Compose 概念 | Kubernetes 等效资源 | 说明 |
|---|---|---|
service
(drupal)
|
Deployment
+
Service
|
Deployment
管理Pod(容器组)的副本和更新策略;
Service
为Pod提供稳定的网络访问入口。
|
service
(database)
| 通常使用云托管服务或独立的StatefulSet |
生产环境数据库通常外置(如云RDS),或使用有状态副本集
StatefulSet
管理。
|
environment
|
ConfigMap
+
Secret
|
将环境变量定义在
ConfigMap
(普通配置)和
Secret
(敏感信息,如密码)中,然后挂载到Pod。
|
ports
|
Service
的
type: NodePort
或
Ingress
|
对外暴露服务。通常通过
Ingress
控制器(如Nginx Ingress)提供HTTP/HTTPS路由。
|
volumes
|
PersistentVolumeClaim
(PVC)
|
为需要持久化的数据(如用户上传的文件
sites/default/files
)声明存储卷。
|
一个简化的Drupal
Deployment
可能长这样:
# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: drupal
spec:
replicas: 2 # 运行2个Pod副本以实现高可用
selector:
matchLabels:
app: drupal
template:
metadata:
labels:
app: drupal
spec:
containers:
- name: drupal
image: my-registry/my-drupal-app:latest # 你的私有镜像仓库地址
ports:
- containerPort: 80
envFrom:
- configMapRef:
name: drupal-config
- secretRef:
name: drupal-secrets
volumeMounts:
- name: files-volume
mountPath: /var/www/html/web/sites/default/files
livenessProbe: # 存活探针
httpGet:
path: /health
port: 80
initialDelaySeconds: 60
periodSeconds: 10
readinessProbe: # 就绪探针
httpGet:
path: /user/login
port: 80
initialDelaySeconds: 30
periodSeconds: 5
volumes:
- name: files-volume
persistentVolumeClaim:
claimName: drupal-files-pvc
6.2 关键生产配置详解
-
健康检查(Liveness & Readiness Probes)
:这是K8s中保证应用健壮性的关键。
livenessProbe失败,K8s会重启容器;readinessProbe失败,K8s会将该Pod从服务负载均衡中移除。对于Drupal,/health端点(可能需要额外模块或自定义)或/user/login(一个需要数据库连接的页面)是常用的检查路径。 -
资源请求与限制(Resources)
:务必为容器设置CPU和内存的
requests和limits。这有助于K8s调度器做出明智决策,并防止单个容器耗尽节点资源。resources: requests: memory: "256Mi" cpu: "250m" limits: memory: "512Mi" cpu: "500m" -
配置文件与密钥管理
:永远不要将数据库密码等硬编码在镜像或YAML文件中。使用Kubernetes
Secret对象。
在Deployment中通过环境变量引用它:# 通过kubectl create secret generic drupal-secrets --from-literal=database-password='supersecret' 创建 apiVersion: v1 kind: Secret metadata: name: drupal-secrets type: Opaque data: database-password: c3VwZXJzZWNyZXQ= # base64编码的'supersecret'env: - name: DRUPAL_DATABASE_PASSWORD valueFrom: secretKeyRef: name: drupal-secrets key: database-password。 -
文件存储持久化
:用户上传的文件必须持久化。你需要创建
PersistentVolumeClaim(PVC)来动态或静态地申请存储空间,并将其挂载到Pod中sites/default/files路径。多个Pod副本间共享此存储时,要确保存储后端支持ReadWriteMany访问模式。
6.3 持续集成与持续部署(CI/CD)流水线设计
一个自动化的流水线能极大提升效率和可靠性。以GitHub Actions为例,你的
.github/workflows/ci.yml
可能包含以下步骤:
- 代码检查 :运行PHPCS(代码风格检查)、PHPStan(静态分析)。
-
构建与测试
:
- 构建Docker镜像。
- 运行容器化测试(如单元测试、功能测试)。
-
推送镜像
:将测试通过的镜像打上标签(如
${{ github.sha }})推送到Docker Hub、GitHub Container Registry等。 -
部署到K8s
:使用
kubectl set image或Argo CD等GitOps工具,将新镜像版本更新到生产环境的Deployment。
项目的README中已经展示了一个CI徽章,背后正是这样的自动化流程。
7. 运维、升级与故障排查实战指南
7.1 日常运维与监控
一旦应用在K8s上运行,日常运维工作会发生变化:
-
日志查看
:不再登录服务器,而是使用
kubectl logs -f deployment/drupal查看Pod日志,或更佳方案是集成日志聚合系统(如ELK Stack、Loki)。 -
执行命令
:需要进入容器时,使用
kubectl exec -it <pod-name> -- bash。 - 监控 :为Pod配置好资源监控(通过Metrics Server和Prometheus),并设置告警(如内存使用率持续超过80%)。同时监控Drupal自身的性能(如使用Drupal模块或New Relic等APM工具)。
7.2 Drupal核心与模块的升级流程
升级流程在本地开发环境进行,与项目文档所述一致,但需更谨慎:
- 备份 :确保本地数据库和代码仓库已提交。
-
更新依赖
:在项目根目录运行
docker compose exec drupal composer update。这会根据composer.json中的版本约束,更新Drupal核心、贡献模块和第三方库到最新兼容版本。 强烈建议先更新composer.json中指定的版本范围,然后运行composer update --dry-run预览变更 。 -
更新数据库
:运行
docker compose exec drupal drush updatedb -y(或简写drush updb -y)。Drupal会执行任何必要的数据库模式更新。 -
导出配置
:运行
docker compose exec drupal drush config:export -y。这一步 至关重要 ,因为核心或模块的更新可能会自带默认配置的变更,导出操作会将这些变更捕获到你的config/目录中。 - 全面测试 :在本地彻底测试网站的所有关键功能。
-
提交与部署
:将
composer.lock和config/目录的变更提交到Git,触发CI/CD流程,将新镜像部署到生产环境。
7.3 常见问题与排查技巧实录
即使准备充分,在生产环境中也可能遇到问题。以下是一些常见场景及排查思路:
问题1:新Pod启动后,网站显示“Service Unavailable”或连接数据库错误。
-
排查思路
:
-
检查Pod状态
:
kubectl get pods查看Pod是否处于Running和Ready状态。 -
查看Pod日志
:
kubectl logs <pod-name>查看启动日志,重点看PHP-FPM错误或Drupal安装/更新脚本的输出。 -
检查环境变量
:
kubectl describe pod <pod-name>查看Pod详情,确认DRUPAL_DATABASE_*等环境变量是否已正确从ConfigMap/Secret注入。 -
手动测试数据库连接
:
kubectl exec -it <pod-name> -- bash进入容器,尝试用mysql命令或php -r脚本连接数据库,验证网络和凭据。 -
检查就绪探针
:如果就绪探针(
readinessProbe)路径设置不当(如指向一个不存在的/health路径),Pod会一直处于未就绪状态,Service不会将流量导入。可以临时调整探针路径或初始延迟进行测试。
-
检查Pod状态
:
问题2:用户上传的文件在Pod重启后丢失。
-
原因与解决
:
sites/default/files目录没有使用持久化存储。必须确保Deployment中配置了PVC并正确挂载到该目录。检查PVC的绑定状态:kubectl get pvc。
问题3:执行
drush config:import
时报告配置冲突。
-
排查思路
:这通常是因为生产数据库中的某些配置与代码库中的YAML文件不一致,且这些不一致不是由本次部署的配置变更引起的。
-
在导入前,先在非生产环境(或从生产数据库备份恢复的环境)中运行
drush config:status,查看哪些配置有差异。 - 分析差异原因。是上次部署后有人在生产后台直接修改了配置?还是某个模块的更新导致了意外的配置变更?
- 黄金法则 :生产环境的配置修改 必须 通过代码流程进行。如果出现冲突,通常的解决步骤是:a) 将生产数据库的配置导出;b) 与代码库中的配置进行差异比较和合并;c) 将合并后的正确配置提交到代码库;d) 重新部署。
-
在导入前,先在非生产环境(或从生产数据库备份恢复的环境)中运行
问题4:网站性能缓慢,Pod内存或CPU使用率飙升。
-
排查思路
:
-
资源监控
:使用
kubectl top pods查看资源使用情况。如果持续接近或超过limits,可能需要调整限制或优化代码。 - Drupal缓存 :确保Drupal的缓存机制(如Internal Page Cache, Dynamic Page Cache)已启用并正确配置。考虑集成Redis作为外部缓存后端。
- PHP OPcache :确保PHP-FPM的OPcache已启用并配置了足够的内存。
- 镜像优化 :检查Docker镜像是否过大,是否包含了不必要的开发文件。使用多阶段构建和Alpine基础镜像可以有效减小体积。
-
资源监控
:使用
将Drupal部署到Kubernetes是一个系统工程,它要求开发者同时具备应用开发、容器化和平台运维的知识。
geerlingguy/drupal-for-kubernetes
这个项目提供了一个绝佳的起点和范式。它不仅仅是一套代码,更展示了一种可重复、可扩展、符合云原生理念的现代化应用管理方法。从本地开发到生产部署,每一个环节的设计都值得仔细推敲和学习。当你真正按照这个模式走通整个流程后,你会发现,管理一个复杂、高可用的Drupal站点,从此变得清晰和可控。
更多推荐
所有评论(0)