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),以减小最终镜像的体积。它可能大致如下工作:

  1. 基础阶段 :使用一个包含Composer的PHP镜像作为构建器(Builder),将 composer.json composer.lock 复制进去,运行 composer install --no-dev --optimize-autoloader 来安装生产依赖(不安装开发依赖,优化自动加载)。
  2. 最终阶段 :使用一个更轻量的、为运行环境优化的PHP镜像(如 php:fpm-alpine )。从构建器阶段复制已安装好的 vendor/ 目录和整个 web/ 目录。同时,会安装必要的PHP扩展(如 gd , pdo_mysql , opcache 等),并设置正确的文件权限(确保 www-data 用户对 sites/default/files 有写权限)。
  3. 健康检查 :通常会添加 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会:

  1. database 服务拉取MariaDB镜像(如果本地没有)。
  2. 创建并启动 database 容器,根据环境变量初始化数据库。
  3. 基于刚才构建的 my-drupal-app 镜像(或在 docker-compose.yml 中指定的镜像)创建并启动 drupal 容器。
  4. 将本地 web config 目录挂载到 drupal 容器内。
  5. 将宿主机的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 完整的开发-提交-部署循环

结合以上两点,一个标准的开发工作流如下:

  1. 本地开发 :在 http://localhost 上进行修改(安装新模块、修改配置、创建基础内容)。
  2. 导出变更
    • 配置变更: drush cex
    • 基础内容变更: drush dcer ...
  3. 代码管理 :将导出的YAML/JSON文件以及可能更新的 composer.json (如果安装了新模块)提交到Git。
  4. CI/CD流水线 :代码推送到远程仓库(如GitHub)后,触发CI/CD流程(例如GitHub Actions)。流程可能包括:运行测试、构建新的Docker镜像、将镜像推送到镜像仓库(如Docker Hub)。
  5. 生产部署 :在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 对象。
    # 通过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'
    
    在Deployment中通过环境变量引用它: 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 可能包含以下步骤:

  1. 代码检查 :运行PHPCS(代码风格检查)、PHPStan(静态分析)。
  2. 构建与测试
    • 构建Docker镜像。
    • 运行容器化测试(如单元测试、功能测试)。
  3. 推送镜像 :将测试通过的镜像打上标签(如 ${{ github.sha }} )推送到Docker Hub、GitHub Container Registry等。
  4. 部署到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核心与模块的升级流程

升级流程在本地开发环境进行,与项目文档所述一致,但需更谨慎:

  1. 备份 :确保本地数据库和代码仓库已提交。
  2. 更新依赖 :在项目根目录运行 docker compose exec drupal composer update 。这会根据 composer.json 中的版本约束,更新Drupal核心、贡献模块和第三方库到最新兼容版本。 强烈建议先更新 composer.json 中指定的版本范围,然后运行 composer update --dry-run 预览变更
  3. 更新数据库 :运行 docker compose exec drupal drush updatedb -y (或简写 drush updb -y )。Drupal会执行任何必要的数据库模式更新。
  4. 导出配置 :运行 docker compose exec drupal drush config:export -y 。这一步 至关重要 ,因为核心或模块的更新可能会自带默认配置的变更,导出操作会将这些变更捕获到你的 config/ 目录中。
  5. 全面测试 :在本地彻底测试网站的所有关键功能。
  6. 提交与部署 :将 composer.lock config/ 目录的变更提交到Git,触发CI/CD流程,将新镜像部署到生产环境。

7.3 常见问题与排查技巧实录

即使准备充分,在生产环境中也可能遇到问题。以下是一些常见场景及排查思路:

问题1:新Pod启动后,网站显示“Service Unavailable”或连接数据库错误。

  • 排查思路
    1. 检查Pod状态 kubectl get pods 查看Pod是否处于 Running Ready 状态。
    2. 查看Pod日志 kubectl logs <pod-name> 查看启动日志,重点看PHP-FPM错误或Drupal安装/更新脚本的输出。
    3. 检查环境变量 kubectl describe pod <pod-name> 查看Pod详情,确认 DRUPAL_DATABASE_* 等环境变量是否已正确从ConfigMap/Secret注入。
    4. 手动测试数据库连接 kubectl exec -it <pod-name> -- bash 进入容器,尝试用 mysql 命令或 php -r 脚本连接数据库,验证网络和凭据。
    5. 检查就绪探针 :如果就绪探针( readinessProbe )路径设置不当(如指向一个不存在的 /health 路径),Pod会一直处于未就绪状态,Service不会将流量导入。可以临时调整探针路径或初始延迟进行测试。

问题2:用户上传的文件在Pod重启后丢失。

  • 原因与解决 sites/default/files 目录没有使用持久化存储。必须确保Deployment中配置了PVC并正确挂载到该目录。检查PVC的绑定状态: kubectl get pvc

问题3:执行 drush config:import 时报告配置冲突。

  • 排查思路 :这通常是因为生产数据库中的某些配置与代码库中的YAML文件不一致,且这些不一致不是由本次部署的配置变更引起的。
    1. 在导入前,先在非生产环境(或从生产数据库备份恢复的环境)中运行 drush config:status ,查看哪些配置有差异。
    2. 分析差异原因。是上次部署后有人在生产后台直接修改了配置?还是某个模块的更新导致了意外的配置变更?
    3. 黄金法则 :生产环境的配置修改 必须 通过代码流程进行。如果出现冲突,通常的解决步骤是:a) 将生产数据库的配置导出;b) 与代码库中的配置进行差异比较和合并;c) 将合并后的正确配置提交到代码库;d) 重新部署。

问题4:网站性能缓慢,Pod内存或CPU使用率飙升。

  • 排查思路
    1. 资源监控 :使用 kubectl top pods 查看资源使用情况。如果持续接近或超过 limits ,可能需要调整限制或优化代码。
    2. Drupal缓存 :确保Drupal的缓存机制(如Internal Page Cache, Dynamic Page Cache)已启用并正确配置。考虑集成Redis作为外部缓存后端。
    3. PHP OPcache :确保PHP-FPM的OPcache已启用并配置了足够的内存。
    4. 镜像优化 :检查Docker镜像是否过大,是否包含了不必要的开发文件。使用多阶段构建和Alpine基础镜像可以有效减小体积。

将Drupal部署到Kubernetes是一个系统工程,它要求开发者同时具备应用开发、容器化和平台运维的知识。 geerlingguy/drupal-for-kubernetes 这个项目提供了一个绝佳的起点和范式。它不仅仅是一套代码,更展示了一种可重复、可扩展、符合云原生理念的现代化应用管理方法。从本地开发到生产部署,每一个环节的设计都值得仔细推敲和学习。当你真正按照这个模式走通整个流程后,你会发现,管理一个复杂、高可用的Drupal站点,从此变得清晰和可控。

更多推荐