Skip to content

在 OpenShift 本地 (CRC) 上托管 n8n(Hosting n8n on OpenShift Local (CRC))#

本指南将带你了解如何在 OpenShift Local (CRC) 上部署 n8n,这是 Red Hat 用于运行本地 OpenShift 集群的工具。它与 AWS/EKS 部署类似,但完全运行在你的本地机器上。它旨在在本地 OpenShift 环境中测试 n8n,而无需支付云费用。

🌐 This guide walks you through deploying n8n on OpenShift Local (CRC), Red Hat's tool for running a local OpenShift cluster. It mirrors AWS/EKS deployment, but runs entirely on your local machine. It's designed for testing n8n in an OpenShift environment locally, without cloud costs.

考虑到 OpenShift 本身消耗的资源如此之多,你将需要一台拥有大量可用资源的机器。

🌐 You will need a machine with significant resources available, given how many resources OpenShift itself consumes.

OpenShift 概念与标准 Kubernetes(OpenShift concepts vs standard Kubernetes)#

OpenShift 构建在 Kubernetes 之上,但使用不同的术语并具有更严格的安全默认设置。如果你熟悉标准 Kubernetes,或者熟悉针对托管 Kubernetes 服务(如 EKS)的指南,下面的表格将映射等效的概念,以便你了解预期内容。

🌐 OpenShift is built on Kubernetes but uses different terminology and has stricter security defaults. If you are familiar with standard Kubernetes, or with a guide that targets a managed Kubernetes service such as EKS, the table below maps the equivalent concepts so you know what to expect.

标准 Kubernetes / EKS OpenShift 本地 (CRC)
kubectl oc(OpenShift CLI;也理解 kubectl 命令)
Namespace 项目(相同概念,不同命令)
Ingress / 负载均衡器 Route(内置于 OpenShift,无需控制器)
EBS StorageClass (gp3) CRC 内置存储提供者(无需设置)
RDS PostgreSQL 集群内 PostgreSQL via Helm(Bitnami)
ElastiCache Redis 集群内 Redis via Helm(Bitnami)
AWS S3 集群内 MinIO(兼容 S3)
Pod 身份 / IRSA 通过 Kubernetes Secret 使用访问密钥
AWS 负载均衡器控制器 不需要(Route 内置)
OIDC / IAM 不需要
~$135–400/月 免费(在你的机器上运行)

先决条件(Prerequisites)#

在开始之前,确认你的机器具备:

🌐 Before starting, confirm your machine has:

  • CPU:4 个或更多物理核心(不仅仅是线程),并支持虚拟化
  • 内存(RAM):至少32 GB可用(CRC为其虚拟机保留9 GB)
  • 磁盘:100 GB 可用
  • 操作系统:Ubuntu(22.04 LTS 或更新版本)

准备 Ubuntu(Prepare Ubuntu)#

打开终端(Open a terminal)#

按下 Ctrl+Alt+T 或在应用菜单中搜索 终端

🌐 Press Ctrl+Alt+T or search for Terminal in the Applications menu.

本指南中的每条命令都是在终端中输入并按 Enter 键运行的。

🌐 Every command in this guide is typed into the terminal and run by pressing Enter.

更新你的系统(Update your system)#

从系统更新开始,以避免依赖问题:

🌐 Start with a system update to avoid dependency issues:

1
sudo apt update && sudo apt upgrade -y

超级用户权限

sudo 意味着“以管理员身份运行”。系统会提示你输入密码。你输入的字符不会显示在屏幕上,这是正常的。

检查 CPU 虚拟化支持(Check CPU virtualization support)#

CRC 运行一个虚拟机。你的 CPU 必须支持硬件虚拟化:

🌐 CRC runs a virtual machine. Your CPU must support hardware virtualization:

1
egrep -c '(vmx|svm)' /proc/cpuinfo
  • 输出 0:虚拟化已被禁用。进入你的 BIOS/UEFI 设置并启用 VT-x(Intel)或 AMD-V(AMD),然后重启并重试。
  • 输出 1 或更高:你可以继续。

安装 KVM 和 libvirt(Install KVM and libvirt)#

KVM 是 Linux 内置的虚拟机管理程序。CRC 使用它来运行 OpenShift 集群虚拟机:

🌐 KVM is Linux’s built-in hypervisor. CRC uses it to run the OpenShift cluster VM:

1
sudo apt install -y qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils

安装 virtiofsd,CRC 需要它与集群虚拟机共享文件系统:

🌐 Install virtiofsd, which CRC requires to share the filesystem with the cluster VM:

1
sudo apt install -y virtiofsd

启动 libvirt 服务并配置其在启动时自动运行:

🌐 Start the libvirt service and configure it to start automatically on boot:

1
2
sudo systemctl start libvirtd
sudo systemctl enable libvirtd

验证它是否正在运行:

🌐 Verify it's running:

1
sudo systemctl status libvirtd

在绿色中查找 Active: active (running)。按 q 退出。

🌐 Look for Active: active (running) in green. Press q to exit.

将用户添加到所需的组(Add user to required groups)#

这使你能够在使用 KVM 和 libvirt 时无需为每个命令输入 sudo

🌐 This allows you to use KVM and libvirt without typing sudo for every command:

1
2
sudo usermod -aG libvirt $USER
sudo usermod -aG kvm $USER

警告

你必须注销并重新登录(或重启)才能生效。 如果跳过此步骤,CRC 将因“权限被拒绝”错误而失败。

立即重启:

🌐 Reboot now:

1
sudo reboot

重新登录后,打开终端并验证组成员身份:

🌐 After logging back in, open a terminal and verify group membership:

1
groups

你应该能看到 libvirtkvm 列在其中。

🌐 You should see libvirt and kvm listed.

安装 NetworkManager(Install NetworkManager)#

CRC要求NetworkManager管理集群内部域(*.apps-crc.testingapi.crc.testing)的DNS条目:

🌐 CRC requires NetworkManager to manage DNS entries for the cluster’s internal domains (*.apps-crc.testing, api.crc.testing):

1
2
3
sudo apt install -y network-manager
sudo systemctl start NetworkManager
sudo systemctl enable NetworkManager

验证是否已连接:

🌐 Verify it's connected:

1
nmcli general status

STATE 列应显示 connected

🌐 The STATE column should show connected.

安装工具(Install tools)#

获取一个红帽账户并获取拉取密钥(Get a Red Hat account and pull secret)#

CRC 需要一个免费的 Red Hat 账户来拉取容器镜像。

🌐 CRC requires a free Red Hat account to pull container images.

  1. 创建一个免费的红帽账户,如果你还没有的话。
  2. console.redhat.com/openshift/create/local 上,点击 下载 OpenShift 本地版本
  3. 选择 Linux,并将 .tar.xz 文件下载到 ~/Downloads
  4. 在 Red Hat 控制台的同一页面上,点击 复制拉取密钥。将其粘贴到文本文件中并保存以备后用。

安装 CRC(Install CRC)#

在你的下载文件夹中打开终端。

🌐 Open a terminal in your Downloads folder.

1
cd ~/Downloads

解压存档。

🌐 Extract the archive.

1
tar xf crc-linux-amd64.tar.xz

crc 二进制文件移动到系统范围的位置,以便在任何终端中都可用:

🌐 Move the crc binary to a system-wide location, so it's available in any terminal:

1
sudo mv crc-*-linux-amd64/crc /usr/local/bin/

验证安装:

🌐 Verify the installation:

1
crc version

版本号应该打印到终端。

🌐 A version number should print to the terminal.

安装 Helm(Install Helm)#

Helm 将 n8n 及其支持服务安装到集群中:

🌐 Helm installs n8n and supporting services into the cluster:

1
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

验证:

🌐 Verify:

1
helm version

设置环境变量(Set environment variables)#

1
2
export NAMESPACE=n8n-$(date +%Y%m%d)
echo "Namespace:$NAMESPACE"

变量持久性

这些变量只在当前终端会话中有效。每次打开新终端时,在继续之前请重新运行这一行。

启动 OpenShift 本地(Start OpenShift Local)#

运行 CRC 设置(Run CRC setup)#

你只需要运行一次即可。它会配置 KVM 网络、检查系统要求,并下载 CRC 打包包(约 2.5 GB):

🌐 You only need to run this once. It configures KVM networking, checks system requirements, and downloads the CRC bundle (~2.5 GB):

1
crc setup

这需要几分钟。如果它报告有任何缺少的软件包,请使用 sudo apt install -y <package-name> 安装它们,然后重新运行。

🌐 This takes several minutes. If it reports any missing packages, install them with sudo apt install -y <package-name> and re-run.

配置 CRC 内存并启动集群(Configure CRC memory and start the cluster)#

CRC 默认为其虚拟机分配 9 GB 的 RAM。n8n 及其支持服务需要更多的内存余量。启动前将内存设置为 14 GB:

🌐 CRC defaults to 9 GB of RAM for its VM. n8n and its supporting services need more headroom. Set the memory to 14 GB before starting:

1
crc config set memory 14336

你只需要运行一次。该设置会在 crc stop / crc start 周期中保持。

🌐 You only need to run this once. The setting persists across crc stop / crc start cycles.

推荐:先将你的拉取密钥保存到文件中,这样就不必每次都粘贴它:

1
2
3
4
5
# Open the file, paste your pull secret (from earlier), then Ctrl+O to save, Ctrl+X to exit
nano ~/pull-secret.txt

# Restrict permissions so only you can read it
chmod 600 ~/pull-secret.txt

使用文件启动 CRC:

🌐 Start CRC using the file:

1
crc start --pull-secret-file ~/pull-secret.txt

或者,在没有标志的情况下运行 crc start,并在提示时粘贴密钥。

🌐 Alternatively, run crc start without the flag and paste the secret when prompted.

这需要 10–15 分钟。 完成后,你会看到类似这样的内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Started the OpenShift cluster.

The server is accessible via web console at:
  https://console-openshift-console.apps-crc.testing

Log in as administrator:
  Username: kubeadmin
  Password: <generated-password>

Log in as user:
  Username: developer
  Password: developer

现在保存 kubeadmin 密码。 你将在下一步需要它。你以后可以使用 crc console --credentials 来获取它。

验证 DNS 解析(Verify DNS resolution)#

在 Ubuntu 上,CRC 会自动通过 NetworkManager 和 systemd-resolved 配置系统解析器。不需要手动添加 /etc/hosts 条目。

🌐 On Ubuntu, CRC configures the system resolver automatically with NetworkManager and systemd-resolved. No manual /etc/hosts entries are needed.

验证 API 是否可访问:

🌐 Verify the API is reachable:

1
sudo ss -tlnp | grep 6443

你应该看到一个绑定到 127.0.0.1:6443 的进程。如果没有出现任何内容,请重新运行 crc start。如果 DNS 无法解析 *.apps-crc.testing,请查看故障排除部分。

🌐 You should see a process bound to 127.0.0.1:6443. If nothing appears, re-run crc start. If DNS doesn't resolve *.apps-crc.testing, see the troubleshooting section.

配置你的 shell(Configure your shell)#

CRC 将 oc CLI 打包在虚拟机内。此命令可在你的终端中使用它:

🌐 CRC bundles the oc CLI inside the VM. This command makes it available in your terminal:

1
eval $(crc oc-env)

要使其永久生效,这样你每次打开终端时就不必运行它:

🌐 To make this permanent so you don't have to run it every time you open a terminal:

1
2
echo 'eval $(crc oc-env)' >> ~/.bashrc
source ~/.bashrc

验证 oc 是否可用:

🌐 Verify oc works:

1
oc version

登录到集群(Log in to the cluster)#

1
oc login -u kubeadmin -p <your-kubeadmin-password> https://api.crc.testing:6443

<your-kubeadmin-password> 替换为在你配置 CRC 内存并启动集群 时打印的密码。

🌐 Replace <your-kubeadmin-password> with the password printed when you configured CRC memory and started the cluster.

请验证你已登录:

🌐 Verify you are logged in:

1
oc whoami

kubeadmin 应该输出到屏幕上。

独立部署(Standalone deployment)#

独立模式将 n8n 作为单个 pod 运行,并使用 SQLite。不需要外部数据库或 Redis。这非常适合本地探索 n8n 和测试工作流。

🌐 Standalone mode runs n8n as a single pod with SQLite. No external database or Redis is required. This is ideal for exploring n8n and testing workflows locally.

创建项目(Create the project)#

在 OpenShift 中,项目 与 Kubernetes 命名空间相同:是你的资源的一个隔离空间:

🌐 In OpenShift, a project is the same as a Kubernetes namespace: an isolated space for your resources:

1
oc new-project $NAMESPACE

授予所需的安全权限(Grant the required security permission)#

OpenShift 强制执行称为 安全上下文约束 (SCCs) 的严格安全策略。默认情况下,Pod 不能使用特定的用户 ID 运行。n8n Chart 以用户 ID 1000 运行,因此你必须显式允许这一点。

🌐 OpenShift enforces strict security policies called Security Context Constraints (SCCs). By default, pods can't run with a specific user ID. The n8n chart runs as user ID 1000, so you must explicitly allow this.

使用完整的显式形式。某些 OpenShift 版本中,简写 -z 标志可能会悄然失败:

🌐 Use the full explicit form. The shorthand -z flag can silently fail in some OpenShift versions:

1
2
oc adm policy add-scc-to-user anyuid \
  system:serviceaccount:$NAMESPACE:n8n

验证绑定是否已创建:

🌐 Verify the binding was created:

1
oc get rolebindings -n $NAMESPACE

你应该看到一个引用 system:openshift:scc:anyuid 的绑定。

🌐 You should see a binding referencing system:openshift:scc:anyuid.

创建所需的密钥(Create the required secret)#

1
2
3
4
5
6
oc create secret generic n8n-secrets \
  --namespace $NAMESPACE \
  --from-literal=N8N_ENCRYPTION_KEY="$(openssl rand -hex 32)" \
  --from-literal=N8N_HOST="localhost" \
  --from-literal=N8N_PORT="5678" \
  --from-literal=N8N_PROTOCOL="http"

立即备份加密密钥:

1
2
oc get secret n8n-secrets -n $NAMESPACE \
  -o jsonpath='{.data.N8N_ENCRYPTION_KEY}' | base64 --decode

复制该输出并将其存放在安全的地方。丢失它意味着工作流程中存储的所有凭据将永久不可读取。

🌐 Copy that output and store it somewhere safe. Losing it means all stored credentials in your workflows become permanently unreadable.

创建你的 values 文件(Create your values file)#

创建一个名为 n8n-standalone-values.yaml 的文件。你可以使用 nano(一个简单的文本编辑器):

🌐 Create a file called n8n-standalone-values.yaml. You can use nano (a simple text editor):

1
nano n8n-standalone-values.yaml

粘贴以下内容,然后按 Ctrl+O 保存,按 Ctrl+X 退出:

🌐 Paste the following, then press Ctrl+O to save and Ctrl+X to exit:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# n8n-standalone-values.yaml
# Single pod, SQLite database, no external dependencies.

queueMode:
  enabled: false

database:
  type: sqlite
  useExternal: false

redis:
  enabled: false

# PVC stores the SQLite database file.
persistence:
  enabled: true
  size: 5Gi
  # No storageClassName needed — CRC provides a default storage provisioner.

secretRefs:
  existingSecret: "n8n-secrets"

service:
  type: ClusterIP
  port: 5678

# OpenShift: securityContext must be enabled so the pod runs as UID 1000 (node user)
# with fsGroup 1000 (so the PVC is writable). The anyuid SCC granted above
# allows this. The seccompProfile line is removed from the chart template in
# "Deploy n8n" because OpenShift 4.14+ rejects it even with anyuid.
securityContext:
  enabled: true

resources:
  main:
    requests:
      cpu: 100m
      memory: 256Mi
    limits:
      cpu: "1"
      memory: 1Gi

config:
  timezone: UTC

部署 n8n(Deploy n8n)#

n8n Helm 图表在 pod 规范中硬编码了 seccompProfile: RuntimeDefault。OpenShift 4.14 及以上版本会将其转换为已弃用的 alpha 注解,该注解在准入时会被拒绝,即使授予了 anyuid SCC 也不例外。解决方法是本地拉取该图表,删除这两行,然后从修补后的副本安装。

🌐 The n8n Helm chart hard codes seccompProfile: RuntimeDefault in the pod spec. OpenShift 4.14+ converts this to a deprecated alpha annotation that's rejected at admission, even when anyuid SCC is granted. The fix is to pull the chart locally, remove those two lines, and install from the patched copy.

拉取并修补图表:

1
2
3
4
5
helm pull oci://ghcr.io/n8n-io/n8n-helm-chart/n8n --version 1.0.3 --untar
sed -i '/seccompProfile:/d; /type: RuntimeDefault/d' ~/n8n/templates/deployment-main.yaml

# Confirm the lines are gone (should return no output)
grep -n "seccomp\|RuntimeDefault" ~/n8n/templates/deployment-main.yaml

从修补后的图表安装:

1
2
3
4
5
helm install n8n ~/n8n/ \
  --namespace $NAMESPACE \
  --values n8n-standalone-values.yaml \
  --wait \
  --timeout 10m

使用端口转发访问 n8n(Access n8n using port forward)#

OpenShift 路由需要一个主机名,这增加了独立本地访问的复杂性。端口转发更简单:

🌐 OpenShift Routes require a hostname, which adds complexity for standalone local access. Port-forward is simpler:

1
oc port-forward service/n8n-main --namespace $NAMESPACE 5678:5678

保持运行状态,然后在浏览器中打开:

🌐 Leave this running, then open your browser to:

1
http://localhost:5678

n8n 会提示你创建一个管理员账户。

🌐 n8n will prompt you to create an owner account.

停止隧道

Ctrl+C 停止隧道。稍后重新运行 port-forward 命令以再次访问 n8n。

检查部署状态(Check deployment status)#

1
oc get pods -n $NAMESPACE

预期:

🌐 Expected:

1
2
NAME                       READY   STATUS    RESTARTS   AGE
n8n-main-7d9f8b-xxxx       1/1     Running   0          3m

独立部署完成。

多实例队列模式(Multi-instance queue mode)#

多实例队列模式运行多个 n8n 节点,共享数据库、消息队列和对象存储。它需要一个 n8n 企业版许可证

🌐 Multi-instance queue mode runs multiple n8n pods with a shared database, message queue, and object storage. It requires an n8n Enterprise license.

本指南没有使用 AWS 托管服务,而是使用了集群内的等效组件,这些组件类似于你在本地或客户 OpenShift 环境中会发现的内容:

🌐 Instead of AWS managed services, this guide uses in-cluster equivalents that mirror what you would find in an on-premises or customer OpenShift environment:

AWS 服务 本地等效服务
RDS PostgreSQL PostgreSQL(Bitnami Helm chart)
ElastiCache Redis Redis(Bitnami Helm chart)
S3 MinIO(兼容 S3,Bitnami Helm chart)

在集群内安装服务(Install in-cluster services)#

创建项目并添加 Bitnami Helm 仓库(Create the Project and add Bitnami Helm repo)#

1
oc new-project $NAMESPACE

添加 Bitnami 图表仓库(只需一次):

🌐 Add the Bitnami chart repository (only needed once):

1
2
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

安装 PostgreSQL(Install PostgreSQL)#

在下面的命令中,将 YourStrongPassword123 替换为一个合适的复杂密码。

🌐 In the command below, replace YourStrongPassword123 with a suitable complex password.

1
2
3
4
5
6
7
helm install postgresql bitnami/postgresql \
  --namespace $NAMESPACE \
  --set auth.username=n8n \
  --set auth.password='YourStrongPassword123' \
  --set auth.database=n8n_enterprise \
  --set global.compatibility.openshift.adaptSecurityContext=auto \
  --wait

global.compatibility.openshift.adaptSecurityContext=auto 标志告诉 Bitnami 让 OpenShift 自动分配正确的用户 ID(避免 SCC 错误)。

保存端点,因为它是为集群内服务固定的:

🌐 Save the endpoint, as it's fixed for in-cluster services:

1
postgresql.YOUR_NAMESPACE.svc.cluster.local

YOUR_NAMESPACE 替换为你实际的 $NAMESPACE 值(例如 n8n-20260306)。

🌐 Replace YOUR_NAMESPACE with your actual $NAMESPACE value (e.g. n8n-20260306).

安装 Redis(Install Redis)#

1
2
3
4
5
6
helm install redis bitnami/redis \
  --namespace $NAMESPACE \
  --set auth.enabled=false \
  --set architecture=standalone \
  --set global.compatibility.openshift.adaptSecurityContext=auto \
  --wait

Redis 端点:redis-master.$NAMESPACE.svc.cluster.local

🌐 Redis endpoint: redis-master.$NAMESPACE.svc.cluster.local

安装 MinIO(兼容 S3 的存储)(Install MinIO (S3-compatible storage))#

在下面的命令中,将 MinioStrongPassword123 替换为一个合适的复杂密码。

🌐 In the command below, replace MinioStrongPassword123 with a suitable complex password.

1
2
3
4
5
6
helm install minio bitnami/minio \
  --namespace $NAMESPACE \
  --set auth.rootUser=minioadmin \
  --set auth.rootPassword='MinioStrongPassword123' \
  --set global.compatibility.openshift.adaptSecurityContext=auto \
  --wait

MinIO 端点:http://minio:9000(在相同命名空间内,只需服务名称即可)

🌐 MinIO endpoint: http://minio:9000 (within the same namespace, just the service name works)

在 MinIO 中创建 n8n 存储桶(Create the n8n storage bucket in MinIO)#

在 n8n 可以使用之前,MinIO 需要先创建一个存储桶。使用 MinIO 网页控制台:

🌐 MinIO needs a bucket created before n8n can use it. Use the MinIO web console:

打开 MinIO 控制台:

1
oc port-forward svc/minio 9001:9001 -n $NAMESPACE

让它一直运行,然后打开浏览器访问 http://localhost:9001

🌐 Leave this running, then open your browser to http://localhost:9001.

使用以下方式登录:

🌐 Log in with:

  • 用户名: minioadmin
  • 密码: MinioStrongPassword123

在控制台中:

🌐 In the console:

  1. 点击左侧边栏的 BucketsCreate Bucket
  2. 桶名称: n8n-data
  3. 点击 创建存储桶

回到终端并按 Ctrl+C 停止端口转发。

🌐 Go back to the terminal and press Ctrl+C to stop the port-forward.

部署 n8n(Deploy n8n)#

为 n8n 授予 SCC(Grant SCC for n8n)#

1
2
oc adm policy add-scc-to-user anyuid \
  system:serviceaccount:$NAMESPACE:n8n-enterprise

确认 oc get rolebindings -n $NAMESPACE 显示了对 system:openshift:scc:anyuid 的绑定。

🌐 Verify that oc get rolebindings -n $NAMESPACE shows a binding for system:openshift:scc:anyuid.

创建所需的密钥(Create required secrets)#

1
2
3
4
5
6
7
# Core n8n secrets
oc create secret generic n8n-enterprise-secrets \
  --namespace $NAMESPACE \
  --from-literal=N8N_ENCRYPTION_KEY="$(openssl rand -hex 32)" \
  --from-literal=N8N_HOST="localhost" \
  --from-literal=N8N_PORT="5678" \
  --from-literal=N8N_PROTOCOL="http"

立即备份加密密钥:

1
2
oc get secret n8n-enterprise-secrets -n $NAMESPACE \
  -o jsonpath='{.data.N8N_ENCRYPTION_KEY}' | base64 --decode

把那个值存放到安全的地方。

🌐 Store that value somewhere safe.

在下面的命令中,将 YourStrongPassword123MinioStrongPassword123 替换为前面步骤中的密码。

🌐 In the commands below, replace YourStrongPassword123 and MinioStrongPassword123 with the passwords from the earlier steps.

1
2
3
4
5
6
7
8
9
# Database password (must match what you set when installing PostgreSQL)
oc create secret generic n8n-enterprise-db-secret \
  --namespace $NAMESPACE \
  --from-literal=password='YourStrongPassword123'

# MinIO credentials
oc create secret generic n8n-minio-secret \
  --namespace $NAMESPACE \
  --from-literal=root-password='MinioStrongPassword123'

创建值文件(Create values file)#

创建 n8n-multimain-ocp-values.yaml。替换标记为 # <-- REPLACE3个占位符值

🌐 Create n8n-multimain-ocp-values.yaml. Replace the 3 placeholder values marked # <-- REPLACE:

1
nano n8n-multimain-ocp-values.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# n8n-multimain-ocp-values.yaml
# Multi-instance queue mode for OpenShift Local (CRC).
# Uses in-cluster PostgreSQL, Redis, and MinIO instead of AWS services.
# Requires Enterprise license.

# --- Enterprise license ---
license:
  enabled: true
  activationKey: "your-enterprise-license-key-here"  # <-- REPLACE

# --- Multi-main: 2 replicas (reduced for local resources) ---
multiMain:
  enabled: true
  replicas: 2

# --- Queue mode: 2 worker pods ---
queueMode:
  enabled: true
  workerReplicaCount: 2
  workerConcurrency: 5

# --- Webhook processors ---
webhookProcessor:
  enabled: true
  replicaCount: 1
  disableProductionWebhooksOnMainProcess: true

# --- PostgreSQL (in-cluster) ---
database:
  type: postgresdb
  useExternal: true
  host: "postgresql.YOUR_NAMESPACE.svc.cluster.local"   # <-- REPLACE YOUR_NAMESPACE
  port: 5432
  database: n8n_enterprise
  schema: "public"
  user: n8n
  passwordSecret:
    name: "n8n-enterprise-db-secret"
    key: "password"

# --- Redis (in-cluster, no TLS) ---
redis:
  enabled: true
  useExternal: true
  host: "redis-master.YOUR_NAMESPACE.svc.cluster.local"  # <-- REPLACE YOUR_NAMESPACE
  port: 6379
  tls: false

# --- MinIO (S3-compatible, in-cluster) ---
s3:
  enabled: true
  bucket:
    name: "n8n-data"
    region: "us-east-1"
  host: "http://minio:9000"
  auth:
    autoDetect: false
    accessKeyId: "minioadmin"
    secretAccessKeySecret:
      name: "n8n-minio-secret"
      key: "root-password"
  storage:
    mode: "s3"
    availableModes: "filesystem,s3"
  forcePathStyle: true

# --- Service account ---
serviceAccount:
  create: true
  name: n8n

保存并退出 nano(Ctrl+OCtrl+X)。

🌐 Save and exit nano (Ctrl+O, Ctrl+X).

在部署之前,将两个 YOUR_NAMESPACE 占位符替换为你实际的命名空间值:

1
2
3
4
5
# Check your namespace value
echo $NAMESPACE

# Replace in the file (this edits it automatically)
sed -i "s/YOUR_NAMESPACE/$NAMESPACE/g" n8n-multimain-ocp-values.yaml

验证替换项:

🌐 Verify the replacements:

1
grep "svc.cluster.local" n8n-multimain-ocp-values.yaml

两行都应该显示你实际的命名空间名称,而不是 YOUR_NAMESPACE

🌐 Both lines should show your actual namespace name, not YOUR_NAMESPACE.

部署 n8n(Deploy n8n)#

如果你之前没有修补此图表,现在拉取并修补它:

🌐 If you didn't patch the chart previously, pull and patch it now:

1
2
3
helm pull oci://ghcr.io/n8n-io/n8n-helm-chart/n8n --version 1.0.3 --untar
sed -i '/seccompProfile:/d; /type: RuntimeDefault/d' ~/n8n/templates/deployment-main.yaml
grep -n "seccomp\|RuntimeDefault" ~/n8n/templates/deployment-main.yaml  # should return nothing

从修补后的图表安装:

🌐 Install from the patched chart:

1
2
3
4
5
helm install n8n ~/n8n/ \
  --namespace $NAMESPACE \
  --values n8n-multimain-ocp-values.yaml \
  --wait \
  --timeout 15m

为外部访问创建一个路由(Create a route for external access)#

在 OpenShift 中,Route 将服务暴露给外部世界。它相当于 Kubernetes 的 Ingress 或 LoadBalancer,并且不需要额外的控制器:

🌐 In OpenShift, a Route exposes a service to the outside world. It's the equivalent of a Kubernetes Ingress or LoadBalancer, and requires no extra controller:

1
oc expose svc/n8n-main -n $NAMESPACE

获取网址:

🌐 Get the URL:

1
2
export ROUTE=$(oc get route n8n-main -n $NAMESPACE -o jsonpath='{.spec.host}')
echo "n8n URL: http://$ROUTE"

URL 看起来像这样:http://n8n-main-n8n-20260306.apps-crc.testing

🌐 The URL will look like: http://n8n-main-n8n-20260306.apps-crc.testing

更新主机密钥(Update the host secret)#

n8n 需要知道它的公共 URL。使用 Route 主机名更新密钥,然后重启 pods:

🌐 n8n needs to know its public URL. Update the secret with the Route hostname, then restart the pods:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
ENCRYPTION_KEY=$(oc get secret n8n-enterprise-secrets -n $NAMESPACE \
  -o jsonpath='{.data.N8N_ENCRYPTION_KEY}' | base64 --decode)

oc create secret generic n8n-enterprise-secrets \
  --namespace $NAMESPACE \
  --from-literal=N8N_ENCRYPTION_KEY="$ENCRYPTION_KEY" \
  --from-literal=N8N_HOST="$ROUTE" \
  --from-literal=N8N_PORT="5678" \
  --from-literal=N8N_PROTOCOL="http" \
  --dry-run=client -o yaml | oc apply -f -

oc rollout restart deployment -n $NAMESPACE

等待部署完成:

🌐 Wait for the rollout to complete:

1
oc rollout status deployment/n8n-main -n $NAMESPACE

验证所有 Pod 是否正在运行(Verify all pods are running)#

1
oc get pods -n $NAMESPACE

预期(所有 Running):

🌐 Expected (all Running):

1
2
3
4
5
6
7
8
9
NAME                                    READY   STATUS    RESTARTS   AGE
n8n-main-xxxx-aaaa                      1/1     Running   0          5m
n8n-main-xxxx-bbbb                      1/1     Running   0          5m
n8n-worker-xxxx-aaaa                    1/1     Running   0          5m
n8n-worker-xxxx-bbbb                    1/1     Running   0          5m
n8n-webhook-processor-xxxx-aaaa         1/1     Running   0          5m
postgresql-0                            1/1     Running   0          15m
redis-master-0                          1/1     Running   0          15m
minio-xxxx-xxxx                         1/1     Running   0          15m

在浏览器中打开上面打印的 URL。

🌐 Open your browser to the URL printed above.

多实例部署完成。

更新 n8n(Updating n8n)#

要更改配置或升级图表版本,请拉取并重新打补丁新的图表版本,然后升级:

🌐 To change configuration or upgrade the chart version, pull and re-patch the new chart version, then upgrade:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Remove the old local chart copy
rm -rf ~/n8n/

# Pull and patch the new version
helm pull oci://ghcr.io/n8n-io/n8n-helm-chart/n8n --version <new-version> --untar
sed -i '/seccompProfile:/d; /type: RuntimeDefault/d' ~/n8n/templates/deployment-main.yaml

# Standalone
helm upgrade n8n ~/n8n/ \
  --namespace $NAMESPACE \
  --values n8n-standalone-values.yaml

# Multi-instance
helm upgrade n8n ~/n8n/ \
  --namespace $NAMESPACE \
  --values n8n-multimain-ocp-values.yaml

停止和恢复 CRC(Stopping and resuming CRC)#

CRC 在会话之间不需要删除。你可以停止然后重新启动它:

🌐 CRC doesn't need to be deleted between sessions. You can stop and restart it:

1
2
3
4
5
# Stop the cluster (saves state)
crc stop

# Start it again later
crc start

重新启动后,重新运行:

🌐 After restarting, re-run:

1
2
3
eval $(crc oc-env)
export NAMESPACE=n8n-YYYYMMDD   # use your original date
oc login -u kubeadmin -p <password> https://api.crc.testing:6443

故障排除(Troubleshooting)#

crc setup 失败,显示“未找到 libvirt”(crc setup fails with “libvirt not found”)#

1
2
sudo apt install -y qemu-kvm libvirt-daemon-system libvirt-clients
sudo systemctl start libvirtd

然后重新运行 crc setup

🌐 Then re-run crc setup.

crc start 失败,显示“内存不足”(crc start fails with “insufficient memory”)#

CRC 需要至少 9 GB 的可用内存。请关闭其他应用后重试。如果你按照配置 CRC 内存的说明操作,CRC 已配置为使用 14 GB 内存。

🌐 CRC requires at least 9 GB of free RAM. Close other applications and try again. If you followed instructions for configuring CRC memory, CRC is configured to use 14 GB.

n8n Pod 卡在 Pending 或从未创建 SCC 错误(n8n pod stuck in Pending or never created SCC error)#

检查错误的事件:

🌐 Check events for the error:

1
oc get events -n $NAMESPACE --sort-by='.lastTimestamp' | tail -20

如果你看到 unable to validate against any security context constraintseccomp may not be set,图表的硬编码 seccompProfile: RuntimeDefault 正在被拒绝。OpenShift 4.14+ 会将其转换为一个弃用的 alpha 注释,即使授予了 anyuid SCC,也会被准入拒绝。

🌐 If you see unable to validate against any security context constraint or seccomp may not be set, the chart’s hard coded seccompProfile: RuntimeDefault is being rejected. OpenShift 4.14+ converts this to a deprecated alpha annotation that admission rejects even when anyuid SCC is granted.

1. 使用显式形式授予 anyuid 权限-z 简写可能会默默失败):

1
2
3
4
5
6
7
# For standalone
oc adm policy add-scc-to-user anyuid \
  system:serviceaccount:$NAMESPACE:n8n

# For multi-instance
oc adm policy add-scc-to-user anyuid \
  system:serviceaccount:$NAMESPACE:n8n-enterprise

验证:运行 oc get rolebindings -n $NAMESPACE。你应该能看到 system:openshift:scc:anyuid 的绑定。

🌐 Verify: run oc get rolebindings -n $NAMESPACE. You should see a binding for system:openshift:scc:anyuid.

2. 本地拉取图表并删除 seccompProfile 行:

1
2
3
4
5
helm pull oci://ghcr.io/n8n-io/n8n-helm-chart/n8n --version 1.0.3 --untar
sed -i '/seccompProfile:/d; /type: RuntimeDefault/d' ~/n8n/templates/deployment-main.yaml

# Confirm they're gone (should return no output)
grep -n "seccomp\|RuntimeDefault" ~/n8n/templates/deployment-main.yaml

3. 从修补过的图表中卸载并重新安装:

1
2
3
4
5
6
helm uninstall n8n -n $NAMESPACE
helm install n8n ~/n8n/ \
  --namespace $NAMESPACE \
  --values n8n-standalone-values.yaml \
  --wait \
  --timeout 10m

路由 URL 返回“应用不可用”(Route URL returns “Application not available”)#

Pods 可能仍在启动。检查:

🌐 The pods may still be starting. Check:

1
2
oc get pods -n $NAMESPACE
oc rollout status deployment/n8n-main -n $NAMESPACE

还要确认路线存在:

🌐 Also confirm the Route exists:

1
oc get route -n $NAMESPACE

n8n Pod 卡在 Pending,伴随 Insufficient memory(n8n pod stuck in Pending with Insufficient memory)#

CRC 节点的可用内存不足,无法调度该 Pod。

🌐 The CRC node doesn’t have enough free memory to schedule the pod.

修复: 增加 CRC 的虚拟机内存并重启:

1
2
3
crc stop
crc config set memory 14336
crc start

CRC 重启后,Pod 应该会自动调度。如果几分钟后 Pod 仍然处于待定状态,请删除它以强制重新调度:

🌐 After CRC restarts, the pod should schedule automatically. If the pod is still pending after a few minutes, delete it to force a reschedule:

1
oc delete pod -n $NAMESPACE -l app.kubernetes.io/component=main

如果你的机器无法腾出 14 GB,你也可以在 n8n-standalone-values.yaml 中降低 pod 的内存请求:

🌐 If your machine can’t spare 14 GB, you can also lower the pod’s memory request in n8n-standalone-values.yaml:

1
2
3
4
resources:
  main:
    requests:
      memory: 256Mi

然后升级:helm upgrade n8n ~/n8n/ -n $NAMESPACE -f n8n-standalone-values.yaml

🌐 Then upgrade: helm upgrade n8n ~/n8n/ -n $NAMESPACE -f n8n-standalone-values.yaml

DNS 无法解析 .apps-crc.testingapi.crc.testing(DNS not resolving .apps-crc.testing or api.crc.testing)#

在 Ubuntu 上,CRC 会自动配置 DNS。如果失败,请重启 NetworkManager:

🌐 On Ubuntu, CRC configures DNS automatically. If it fails, restart NetworkManager:

1
sudo systemctl restart NetworkManager

如果仍然损坏,请手动添加条目(CRC 通过 127.0.0.1 路由流量):

🌐 If still broken, add entries manually (CRC routes traffic through 127.0.0.1):

1
2
3
4
5
6
sudo tee -a /etc/hosts <<EOF
127.0.0.1 api.crc.testing
127.0.0.1 console-openshift-console.apps-crc.testing
127.0.0.1 oauth-openshift.apps-crc.testing
127.0.0.1 default-route-openshift-image-registry.apps-crc.testing
EOF

子域

当你在多实例部分公开路由时,会创建新的 *.apps-crc.testing 子域。如果你的浏览器无法访问它们,请将它们添加到指向 127.0.0.1/etc/hosts

n8n Pod 在向 /home/node/.n8n/ 写入时因 EACCES: permission denied 崩溃(n8n pod crashes with EACCES: permission denied writing to /home/node/.n8n/)#

这意味着该 Pod 正在以随机的 OpenShift 分配的 UID 运行,而不是 UID 1000(n8n 镜像期望的 node 用户)。当在 values 中设置了 securityContext.enabled: false 但没有设置 runAsUser: 1000fsGroup: 1000 时,就会发生这种情况,OpenShift 会分配一个无法写入 PVC 的随机 UID。

🌐 This means the pod is running as a random OpenShift-assigned UID instead of UID 1000 (the node user the n8n image expects). It happens when securityContext.enabled: false is set in values without runAsUser: 1000 and fsGroup: 1000, OpenShift assigns a random UID that can’t write to the PVC.

修复: 确保在你的 values 文件中设置了 securityContext.enabled: true,并且图表已被修改以移除 seccompProfile(参见上面的 SCC 错误部分)。两者需要同时存在。

查看 Pod 日志(View pod logs)#

1
2
3
4
5
6
7
8
# Main process
oc logs -n $NAMESPACE -l app.kubernetes.io/component=main --tail=50

# Workers
oc logs -n $NAMESPACE -l app.kubernetes.io/component=worker --tail=50

# Webhook processors
oc logs -n $NAMESPACE -l app.kubernetes.io/component=webhook-processor --tail=50

命名空间中的所有事件(All events in the namespace)#

1
oc get events -n $NAMESPACE --sort-by='.lastTimestamp'

快速参考(Quick Reference)#

重新打开终端后重新导出变量(Re-export variables after reopening terminal)#

1
2
3
eval $(crc oc-env)
export NAMESPACE=n8n-YYYYMMDD   # use the date from your original deployment
oc login -u kubeadmin -p <password> https://api.crc.testing:6443

检查集群状态(Check cluster status)#

1
crc status

打开 OpenShift 网页控制台(Open the OpenShift web console)#

1
crc console

使用 kubeadmin / 你的密码登录以查看所有正在运行内容的图形视图。

🌐 Log in with kubeadmin / your password to see a graphical view of everything running.

要保存的东西(Things to save)#

项目 重要原因
kubeadmin 密码 登录集群
n8n 加密密钥 丢失此密钥 = 所有存储的凭据无法读取
n8n-standalone-values.yaml helm upgrade 所需
n8n-multimain-ocp-values.yaml helm upgrade 所需
MinIO 根密码 访问 MinIO 控制台
PostgreSQL 密码 数据库访问

下一步步骤(Next steps)#