机器准备
本机安装时相关配置
CPU:N100
RAM:32GB
系统
Ubuntu
安装K8s
禁用Swap
sudo swapoff -a
sudo sed -i '/[[:space:]]swap[[:space:]]/d' /etc/fstab
free -h确认 Swap 行为 0B即可
加载内核模块并配置 Sysctl
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system安装并配置containerd
sudo apt update && sudo apt install -y containerd编辑/etc/containerd/config.toml
如果没生成的话执行
sudo containerd config default | sudo tee /etc/containerd/config.toml找到 SystemdCgroup 并设为 true
sudo nano /etc/containerd/config.toml找到
SystemdCgroup = false改为
SystemdCgroup = true重启
sudo systemctl restart containerd && sudo systemctl enable containerd看到 active (running) 即可
安装kubeadm/kubelet/kubectl
安装组件
sudo apt install -y apt-transport-https ca-certificates curl gpg
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key | \
sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] \
https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /" | \
sudo tee /etc/apt/sources.list.d/kubernetes.list
# 确保 apt 源配置指向正确的仓库
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
# 修正权限,确保 _apt 用户可读取密钥文件
sudo chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg
sudo chmod 644 /etc/apt/sources.list.d/kubernetes.list
# 更新并安装
sudo apt update
sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl验证安装
kubeadm version
kubelet --version
kubectl version --client拉取镜像
sudo kubeadm config images pull \
--image-repository registry.aliyuncs.com/google_containers初始化集群
sudo kubeadm init \
--image-repository registry.aliyuncs.com/google_containers \
--pod-network-cidr=10.244.0.0/16配置kubectl
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 验证
kubectl get nodes
kubectl get pods -A
# 应显示节点,状态为 NotReady创建RBAC绑定
sudo kubectl --kubeconfig /etc/kubernetes/super-admin.conf create clusterrolebinding kubeadm:cluster-admins \
--clusterrole=cluster-admin \
--group=kubeadm:cluster-admins
sudo kubectl --kubeconfig /etc/kubernetes/super-admin.conf label node <node_name> \
node-role.kubernetes.io/control-plane="" \
node.kubernetes.io/exclude-from-external-load-balancers=""
# 验证普通 kubectl 权限
kubectl get nodes解除控制平面taint(单节点必须,否则业务 Pod 无法调度)
kubectl taint nodes --all node-role.kubernetes.io/control-plane-
# 如果报错 "taint not found",说明已移除过,可忽略安装CNI插件
kubectl apply -f https://cdn.jsdelivr.net/gh/flannel-io/flannel@master/Documentation/kube-flannel.yml观察节点状态,STATUS 从 NotReady 变为 Ready 则成功
kubectl get nodes查看Flannel主容器日志
FLANNEL_POD=$(kubectl get pods -n kube-flannel -l app=flannel -o jsonpath='{.items[0].metadata.name}')
kubectl logs -n kube-flannel $FLANNEL_POD -c kube-flannel --tail=50创建空间
kubectl create namespace deer-flow配置密钥
这里使用DeepSeek做演示
kubectl create secret generic deer-flow-deepseek-secret \
--from-literal=DEEPSEEK_API_KEY='sk-...' \
-n deer-flow拉取DeerFlow仓库
cd /opt
git clone https://github.com/bytedance/deer-flow.git
cd deer-flow正常来说,DeerFlow 2.0的基础能力已经足够强大,但我们依旧会选择把DeerFlow的目录进行挂载出来,为未来的二开做相应准备
sudo mkdir -p /data/deerflow/backend/app
sudo mkdir -p /data/deerflow/frontend
sudo mkdir -p /data/deerflow/skills
sudo mkdir -p /data/deerflow/.deer-flow/deer-flow/data
sudo mkdir -p /data/deerflow/.deer-flow/deer-flow/extensions-config
sudo touch /data/deerflow/config.yaml
# 后端代码
sudo rsync -av /opt/deer-flow/backend/app/ /data/deerflow/backend/app/
# 前端源码
sudo rsync -av /opt/deer-flow/frontend/ /data/deerflow/frontend/
# skills
sudo rsync -av /opt/deer-flow/skills/ /data/deerflow/skills/ 2>/dev/null
# 配置文件
sudo cp /opt/deer-flow/config.example.yaml /data/deerflow/config.yaml
sudo chown -R 1000:1000 /data/deerflow/backend/app
sudo chown -R 1000:1000 /data/deerflow/frontend
sudo chown -R 1000:1000 /data/deerflow/skills
sudo chown -R 1000:1000 /data/deerflow/.deer-flow
sudo chown 1000:1000 /data/deerflow/config.yaml
sudo chmod 644 /data/deerflow/config.yaml
# 验证
ls -ld /data/deerflow/backend/app /data/deerflow/frontend /data/deerflow/skills /data/deerflow/.deer-flow /data/deerflow/config.yaml构建Node.js
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
sudo npm install -g pnpm@10
cd /data/deerflow/frontend
pnpm install
pnpm build
# 验证
ls -la .next/配置config.yaml
找到models 模块
- name: deepseek
display_name: DeepSeek
use: deerflow.models.patched_deepseek:PatchedChatDeepSeek
model: deepseek-flash
api_base: https://api.deepseek.com/v1
api_key: $DEEPSEEK_API_KEY
timeout: 600.0
max_retries: 2
max_tokens: 8192
context_window: 1000000
supports_thinking: true
supports_vision: true
when_thinking_enabled:
extra_body:
thinking:
type: enabled
when_thinking_disabled:
extra_body:
thinking:
type: disabled找到database 模块
将
database:
backend: sqlite
sqlite_dir: .deer-flow/data改成
database:
backend: postgres
postgres_url: $DATABASE_URL安装Helm
拉取Helm
curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# 验证
helm version编辑values文件
这里用my-values.yaml做演示
image:
registry: ghcr.io/bytedance
tag: "latest"
pullPolicy: IfNotPresent
existingSecret: deer-flow-deepseek-secret
provisioner:
env:
- name: SANDBOX_IMAGE
value: "enterprise-public-cn-beijing.cr.volces.com/vefaas-public/all-in-one-sandbox:latest"
- name: K8S_NAMESPACE
value: "deer-flow"
- name: SANDBOX_SERVICE_TYPE
value: "ClusterIP"
gateway:
replicas: 1
scheduler:
multi_instance: true
run_ownership:
heartbeat_enabled: true
run_events:
backend: db
postgresql:
enabled: true
auth:
database: deerflow
username: deerflow
password: <pgsql-密码>
nginx:
service:
type: NodePort
port: 2026
nodePort: <自定义端口> # 必须在 30000-32767
config: |
config_version: 33
sandbox:
use: deerflow.community.aio_sandbox:AioSandboxProvider
provisioner_url: http://provisioner:8002
database:
backend: postgres
postgres_url: $DATABASE_URL
run_events:
backend: db二开模板改造
创建目录
mkdir -p /opt/deer-flow-deploy
cd /opt/deer-flow-deploy创建kustomization.yaml
cat > /opt/deer-flow-deploy/kustomization.yaml <<'EOF'
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- helm-rendered.yaml
patchesJson6902:
# ==================== gateway ====================
- target:
kind: Deployment
name: deer-flow-deer-flow-gateway
patch: |-
# --- volumes ---
- op: replace
path: /spec/template/spec/volumes/0
value:
name: config
hostPath:
path: /data/deerflow/config.yaml
type: File
# [1] extensions-seed 保持不变
- op: replace
path: /spec/template/spec/volumes/2
value:
name: skills
hostPath:
path: /data/deerflow/skills
type: Directory
- op: replace
path: /spec/template/spec/volumes/3
value:
name: home
hostPath:
path: /data/deerflow/.deer-flow
type: Directory
- op: add
path: /spec/template/spec/volumes/-
value:
name: code-app
hostPath:
path: /data/deerflow/backend/app
type: Directory
# --- containers[0].volumeMounts ---
# config 去掉 subPath(hostPath 指向文件本身)
- op: replace
path: /spec/template/spec/containers/0/volumeMounts/0
value:
name: config
mountPath: /app/backend/config.yaml
readOnly: true
- op: add
path: /spec/template/spec/containers/0/volumeMounts/-
value:
name: code-app
mountPath: /app/backend/app
# ==================== frontend ====================
- target:
kind: Deployment
name: deer-flow-deer-flow-frontend
patch: |-
- op: add
path: /spec/template/spec/volumes/-
value:
name: frontend-app
hostPath:
path: /data/deerflow/frontend
type: Directory
- op: add
path: /spec/template/spec/containers/0/volumeMounts/-
value:
name: frontend-app
mountPath: /app/frontend
EOF创建post-renderer.sh
cat > /opt/deer-flow-deploy/post-renderer.sh <<'EOF'
#!/bin/bash
set -euo pipefail
cat > /opt/deer-flow-deploy/helm-rendered.yaml
kustomize build /opt/deer-flow-deploy/
EOF
chmod +x /opt/deer-flow-deploy/post-renderer.sh验证补丁
backend
helm template deer-flow /opt/deer-flow/deploy/helm/deer-flow/ \
-n deer-flow -f /opt/deer-flow/my-values.yaml \
--post-renderer /opt/deer-flow-deploy/post-renderer.sh \
| yq 'select(.kind == "Deployment" and .metadata.name == "deer-flow-deer-flow-gateway") | {
volumes: [.spec.template.spec.volumes[] | {name: .name, type: (keys | map(select(. != "name")) | .[0])}],
containerMounts: .spec.template.spec.containers[0].volumeMounts
}'结果
volumes:
- {name: config, type: hostPath}
- {name: extensions-seed, type: configMap}
- {name: skills, type: hostPath}
- {name: home, type: hostPath}
- {name: code-app, type: hostPath}
containerMounts:
- {name: config, mountPath: /app/backend/config.yaml, readOnly: true} # 无 subPath
- {name: skills, mountPath: /app/skills, readOnly: true}
- {name: home, mountPath: /app/backend/.deer-flow, subPath: deer-flow}
- {name: code-app, mountPath: /app/backend/app}frontend
helm template deer-flow /opt/deer-flow/deploy/helm/deer-flow/ \
-n deer-flow -f /opt/deer-flow/my-values.yaml \
--post-renderer /opt/deer-flow-deploy/post-renderer.sh \
| yq 'select(.kind == "Deployment" and .metadata.name == "deer-flow-deer-flow-frontend") | {
volumes: [.spec.template.spec.volumes[] | {name: .name, type: (keys | map(select(. != "name")) | .[0])}],
containerMounts: .spec.template.spec.containers[0].volumeMounts
}'结果
volumes:
- {name: next-cache, type: emptyDir}
- {name: frontend-app, type: hostPath}
containerMounts:
- {name: next-cache, mountPath: /app/frontend/.next/cache}
- {name: frontend-app, mountPath: /app/frontend}部署Helm
cd /opt/deer-flow
helm dependency update deploy/helm/deer-flow 2>/dev/null || true
helm upgrade --install deer-flow deploy/helm/deer-flow/ \
-n deer-flow --create-namespace \
-f my-values.yaml \
--post-renderer /opt/deer-flow-deploy/post-renderer.sh验证安装
访问http://localhost:2026 或者http://<ip>:<nodePort>出现相关页面即可
PgSQL映射
获取相关lable
运行
kubectl get svc deer-flow-deer-flow-postgres -n deer-flow -o jsonpath='{.spec.selector}' | python3 -m json.tool
# 得到结果
{
"app.kubernetes.io/component": "postgres",
"app.kubernetes.io/instance": "deer-flow",
"app.kubernetes.io/name": "deer-flow"
}创建NodePort Service
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: deer-flow-postgres-external
namespace: deer-flow
spec:
type: NodePort
selector:
app.kubernetes.io/component: postgres
app.kubernetes.io/instance: deer-flow
app.kubernetes.io/name: deer-flow
ports:
- name: postgres
port: 5432
targetPort: 5432
nodePort: <自定义端口>
EOF验证
kubectl get svc deer-flow-postgres-external -n deer-flow输出结果为
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
deer-flow-postgres-external NodePort 10.104.153.118 <none> 5432:30432/TCP 5s即成功,接下来使用相关的数据库连接工具进行访问即可
二开后一键更新脚本
cat > /opt/deer-flow/reload.sh <<'SCRIPT_EOF'
#!/bin/bash
# ============================================================================
# DeerFlow 二开更新脚本
# ============================================================================
# 用法:
# ./reload.sh # 更新 gateway + frontend(后端代码/配置)
# ./reload.sh backend # 只更新 gateway
# ./reload.sh frontend # 只更新 frontend(会先 pnpm build)
# ./reload.sh config # 只更新 config.yaml(gateway 强制重建)
# ./reload.sh all # 全部(含前端 build)
# ============================================================================
set -uo pipefail
# 注意:不用 set -e,我们手动处理每个失败,保证失败时能打日志
NS="deer-flow"
GW_LABEL="app.kubernetes.io/component=gateway"
FE_LABEL="app.kubernetes.io/component=frontend"
DATA_DIR="/data/deerflow"
SECRET="deer-flow-deepseek-secret"
# 颜色
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
info() { echo -e "${GREEN}>>>${NC} $*"; }
warn() { echo -e "${YELLOW}!!!${NC} $*"; }
error() { echo -e "${RED}ERR${NC} $*" >&2; }
# ---------------------------------------------------------------------------
# 前置检查
# ---------------------------------------------------------------------------
preflight() {
info "前置检查"
# kubectl 可用
if ! command -v kubectl >/dev/null 2>&1; then
error "kubectl 不存在"
exit 1
fi
# 命名空间存在
if ! kubectl get ns "$NS" >/dev/null 2>&1; then
error "命名空间 $NS 不存在"
exit 1
fi
# 模型 Secret 存在
if ! kubectl get secret "$SECRET" -n "$NS" >/dev/null 2>&1; then
warn "Secret $SECRET 不存在,gateway 可能起不来(模型调用会失败)"
fi
# 挂载源目录存在
local missing=0
for d in "$DATA_DIR/backend/app" "$DATA_DIR/skills" "$DATA_DIR/.deer-flow" "$DATA_DIR/frontend"; do
if [ ! -d "$d" ]; then
error "目录不存在:$d"
missing=1
fi
done
if [ ! -f "$DATA_DIR/config.yaml" ]; then
error "文件不存在:$DATA_DIR/config.yaml"
missing=1
fi
[ "$missing" -eq 1 ] && exit 1
info "前置检查通过"
}
# ---------------------------------------------------------------------------
# 修正属主
# ---------------------------------------------------------------------------
fix_ownership() {
info "修正属主为 1000:1000"
sudo chown -R 1000:1000 \
"$DATA_DIR/backend/app" \
"$DATA_DIR/skills" \
"$DATA_DIR/.deer-flow" \
"$DATA_DIR/frontend" 2>/dev/null
sudo chown 1000:1000 "$DATA_DIR/config.yaml"
sudo chmod 644 "$DATA_DIR/config.yaml"
# 校验
local uid
uid=$(stat -c '%u' "$DATA_DIR/backend/app")
if [ "$uid" != "1000" ]; then
error "属主修正失败:$DATA_DIR/backend/app 属主为 $uid"
exit 1
fi
info "属主修正完成"
}
# ---------------------------------------------------------------------------
# 等待 Pod Ready(带超时 + 失败 dump)
# ---------------------------------------------------------------------------
wait_deploy() {
local label="$1" desc="$2" timeout="${3:-180}"
info "等待 $desc 就绪(${timeout}s)"
if kubectl rollout status deployment -n "$NS" -l "$label" --timeout="${timeout}s"; then
info "$desc 已就绪"; return 0
fi
error "$desc 未就绪,诊断信息:"
kubectl get pods -n "$NS" -l "$label"
for pod in $(kubectl get pods -n "$NS" -l "$label" -o name); do
echo "--- $pod 日志 ---"
kubectl logs -n "$NS" "$pod" --tail=50 2>&1 | tail -50
echo "--- $pod 事件 ---"
kubectl describe -n "$NS" "$pod" 2>&1 | grep -A 10 "Events:" | tail -15
done
return 1
}
# ---------------------------------------------------------------------------
# 更新 backend / gateway
# ---------------------------------------------------------------------------
reload_backend() {
info "重启 gateway deployment"
kubectl rollout restart deployment -n "$NS" -l "$GW_LABEL"
wait_deploy "$GW_LABEL" "gateway" 180 || return 1
kubectl logs -n "$NS" deploy/deer-flow-deer-flow-gateway --tail=20 2>&1 || true
}
# ---------------------------------------------------------------------------
# 更新 frontend
# ---------------------------------------------------------------------------
reload_frontend() {
if [ "${SKIP_FRONTEND_BUILD:-0}" != "1" ]; then
info "前端构建:pnpm build"
sudo -u '#1000' bash -c "cd $DATA_DIR/frontend && pnpm build" || {
error "前端构建失败"; return 1
}
else
warn "跳过前端构建"
fi
info "重启 frontend deployment"
kubectl rollout restart deployment -n "$NS" -l "$FE_LABEL"
wait_deploy "$FE_LABEL" "frontend" 120 || return 1
kubectl logs -n "$NS" deploy/deer-flow-deer-flow-frontend --tail=20 2>&1 || true
}
# ---------------------------------------------------------------------------
# 主流程
# ---------------------------------------------------------------------------
main() {
local mode="${1:-all}"
local rc=0
preflight
case "$mode" in
backend) fix_ownership || exit 1; reload_backend || rc=1 ;;
frontend) fix_ownership || exit 1; reload_frontend || rc=1 ;;
config) fix_ownership || exit 1; reload_backend || rc=1 ;;
all) fix_ownership || exit 1; reload_backend || rc=1; reload_frontend || rc=1 ;;
*) error "未知模式:$mode"; exit 1 ;;
esac
info "完成(退出码:$rc)"
kubectl get pods -n "$NS"
exit "$rc"
}
main "$@"
SCRIPT_EOF
sudo chmod +x /opt/deer-flow/reload.sh用法
# 后端代码 / config.yaml 改动
/opt/deer-flow/reload.sh backend
# 只改前端
/opt/deer-flow/reload.sh frontend
# 前后端都改
/opt/deer-flow/reload.sh all
# 跳过后端构建
SKIP_FRONTEND_BUILD=1 /opt/deer-flow/reload.sh frontend可能遇到问题
Q1:apt update占用apt锁
sudo apt update && sudo apt install -y containerd
Reading package lists... Done
E: Could not get lock /var/lib/apt/lists/lock. It is held by process 6329 (apt-get)
N: Be aware that removing the lock file is not a solution and may break your system.
E: Unable to lock directory /var/lib/apt/lists/解决方案
# 查看占用 apt 锁的进程
ps -p <pid> -o pid,ppid,cmd,etime
ps -ef | grep -E 'unattended|apt.systemd' | grep -v grep
# 杀掉卡死的 apt 进程
sudo kill -9 <pid>
# 停止并禁用自动更新
sudo systemctl stop unattended-upgrades
sudo systemctl disable --now unattended-upgrades
sudo systemctl mask unattended-upgrades
sudo systemctl disable --now apt-daily.timer apt-daily-upgrade.timer
sudo systemctl mask apt-daily.service apt-daily-upgrade.service
# 清理锁并修复 dpkg
sudo rm -f /var/lib/apt/lists/lock
sudo rm -f /var/lib/dpkg/lock-frontend
sudo rm -f /var/lib/dpkg/lock
sudo rm -f /var/cache/apt/archives/lock
sudo dpkg --configure -aQ2:curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to pkgs.k8s.io:443
解决方案
# 1. 删除不匹配的旧密钥
sudo rm -f /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# 2. 从 pkgs.k8s.io 官方源下载密钥(注意 URL 中的 v1.33)
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# 3. 验证密钥是否下载成功
sudo gpg --show-keys /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# 确保 apt 源配置指向正确的仓库
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
# 修正权限,确保 _apt 用户可读取密钥文件
sudo chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg
sudo chmod 644 /etc/apt/sources.list.d/kubernetes.list
# 更新并安装
sudo apt update
sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectlQ3:rpc error: code = DeadlineExceeded desc = failed to start sandbox
解决方法
# 1. 先看当前实际版本
grep "sandbox" /etc/containerd/config.toml
# 2. 用通配替换(避免版本号写死匹配不到)
sudo sed -i "s|sandbox = 'registry.k8s.io/pause:[^']*'|sandbox = 'registry.aliyuncs.com/google_containers/pause:3.10'|" /etc/containerd/config.toml
# 3. 验证
grep -A2 'pinned_images' /etc/containerd/config.toml
# 4. 重启 containerd
sudo systemctl restart containerd
# 5. 重置 kubeadm
sudo kubeadm reset -f
sudo systemctl restart containerd kubelet
sudo crictl images | grep pause
# 6. 重新初始化集群(注意 --image-repository)
sudo kubeadm init \
--image-repository registry.aliyuncs.com/google_containers \
--pod-network-cidr=10.244.0.0/16
# 7. 重置后必须重走以下步骤
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
sudo kubectl --kubeconfig /etc/kubernetes/super-admin.conf create clusterrolebinding kubeadm:cluster-admins \
--clusterrole=cluster-admin --group=kubeadm:cluster-admins
sudo kubectl --kubeconfig /etc/kubernetes/super-admin.conf label node <node_name> \
node-role.kubernetes.io/control-plane="" \
node.kubernetes.io/exclude-from-external-load-balancers=""
kubectl taint nodes --all node-role.kubernetes.io/control-plane-
kubectl apply -f https://cdn.jsdelivr.net/gh/flannel-io/flannel@master/Documentation/kube-flannel.yml
# 8. 确认节点 Ready
kubectl get nodesQ4:缺少ClusterRoleBinding、kube-proxy、CoreDNS
解决方法
# 缺少ClusterRoleBinding
sudo kubectl --kubeconfig /etc/kubernetes/super-admin.conf create clusterrolebinding kubeadm:kubelet-api-admin \
--clusterrole=system:kubelet-api-admin \
--user=kube-apiserver-kubelet-client
# 缺少kube-proxy
sudo kubeadm init phase addon kube-proxy \
--image-repository registry.aliyuncs.com/google_containers \
--pod-network-cidr 10.244.0.0/16
# 缺少CoreDNS
sudo kubeadm init phase addon coredns \
--image-repository registry.aliyuncs.com/google_containers \
--service-cidr 10.96.0.0/12 \
--pod-network-cidr 10.244.0.0/16 \
--service-dns-domain cluster.localQ5:Failed to check br_netfilter: stat /proc/sys/net/bridge/bridge-nf-call-iptables: no such file or directory
解决方法
# 加载模块
sudo modprobe br_netfilter
# 设置 sysctl 参数
sudo sysctl net.bridge.bridge-nf-call-iptables=1
# 验证模块已加载
lsmod | grep br_netfilter
# 应该能看到 br_netfilter 模块
# 确保系统重启后自动加载
cat /etc/modules-load.d/k8s.conf 2>/dev/null
echo -e "overlay\nbr_netfilter" | sudo tee /etc/modules-load.d/k8s.conf
# 持久化 sysctl 参数
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
# 重启 Flannel
kubectl delete pod -n kube-flannel -l app=flannelQ6:PgSQL在value.yaml设置密码和容器内密码不一致
chart首次初始化postgres时,若 postgresql.auth.password未被正确识别,会生成随机密码,导致数据库密码与 Secret、values 不一致
解决方法
# 1. 看实际密码
kubectl exec -n deer-flow deer-flow-deer-flow-postgres-0 -- env | grep POSTGRES_PASSWORD
# 2. 数据库里改成 values 中的密码
kubectl exec -n deer-flow deer-flow-deer-flow-postgres-0 -- \
env PGPASSWORD='<当前实际密码>' \
psql -U deerflow -d postgres \
-c "ALTER USER deerflow WITH PASSWORD 'ChangeMe-Strong-Password-2026';"
# 3. 确认 my-values.yaml 里 postgresql.auth.password 就是这个值
# 4. helm upgrade(而不是 patch secret)
cd /opt/deer-flow
helm upgrade --install deer-flow deploy/helm/deer-flow/ \
-n deer-flow -f my-values.yaml \
--post-renderer /opt/deer-flow-deploy/post-renderer.sh
# 5. 重启 gateway
kubectl rollout restart deployment -n deer-flow -l app.kubernetes.io/component=gatewayQ7:拉取image超时
解决方案
使用国内镜像源拉取
DeerFlow 三个业务镜像
原仓库
ghcr.io/bytedance/deer-flow-backend:latestghcr.io/bytedance/deer-flow-frontend:latestghcr.io/bytedance/deer-flow-provisioner:latest
# Backend
sudo ctr -n k8s.io images pull ghcr.1ms.run/bytedance/deer-flow-backend:latest
sudo ctr -n k8s.io images tag ghcr.1ms.run/bytedance/deer-flow-backend:latest ghcr.io/bytedance/deer-flow-backend:latest
# Frontend
sudo ctr -n k8s.io images pull ghcr.1ms.run/bytedance/deer-flow-frontend:latest
sudo ctr -n k8s.io images tag ghcr.1ms.run/bytedance/deer-flow-frontend:latest ghcr.io/bytedance/deer-flow-frontend:latest
# Provisioner
sudo ctr -n k8s.io images pull ghcr.1ms.run/bytedance/deer-flow-provisioner:latest
sudo ctr -n k8s.io images tag ghcr.1ms.run/bytedance/deer-flow-provisioner:latest ghcr.io/bytedance/deer-flow-provisioner:latestnginx
原仓库
docker.io/library/nginx:alpine
# DaoCloud 源
sudo ctr -n k8s.io images pull docker.m.daocloud.io/library/nginx:alpine
sudo ctr -n k8s.io images tag docker.m.daocloud.io/library/nginx:alpine docker.io/library/nginx:alpine
# 或轩辕源
sudo ctr -n k8s.io images pull docker.xuanyuan.me/library/nginx:alpine
sudo ctr -n k8s.io images tag docker.xuanyuan.me/library/nginx:alpine docker.io/library/nginx:alpine
# 或毫秒源
sudo ctr -n k8s.io images pull docker.1ms.run/library/nginx:alpine
sudo ctr -n k8s.io images tag docker.1ms.run/library/nginx:alpine docker.io/library/nginx:alpinebusybox
原仓库
docker.io/library/busybox:latestdocker.io/library/busybox:1.36
sudo ctr -n k8s.io images pull docker.m.daocloud.io/library/busybox:latest
sudo ctr -n k8s.io images tag docker.m.daocloud.io/library/busybox:latest docker.io/library/busybox:latest
# 补 1.36 tag(initContainer 用)
sudo ctr -n k8s.io images tag docker.io/library/busybox:latest docker.io/library/busybox:1.36
sudo ctr -n k8s.io images tag docker.io/library/busybox:latest busybox:1.36local-path-provisioner
原仓库
docker.io/rancher/local-path-provisioner:v0.0.37
# 华为云 SWR 源
sudo ctr -n k8s.io images pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/rancher/local-path-provisioner:v0.0.37
sudo ctr -n k8s.io images tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/rancher/local-path-provisioner:v0.0.37 docker.io/rancher/local-path-provisioner:v0.0.37postgres
原仓库
docker.io/library/postgres:16
sudo ctr -n k8s.io images pull docker.m.daocloud.io/library/postgres:16
sudo ctr -n k8s.io images tag docker.m.daocloud.io/library/postgres:16 docker.io/library/postgres:16redis
原仓库
docker.io/library/redis:7-alpine
sudo ctr -n k8s.io images pull docker.m.daocloud.io/library/redis:7-alpine
sudo ctr -n k8s.io images tag docker.m.daocloud.io/library/redis:7-alpine docker.io/library/redis:7-alpineQ8:如何重建Helm容器
解决方法
cd /opt/deer-flow
helm upgrade --install deer-flow deploy/helm/deer-flow/ \
-n deer-flow \
-f my-values.yaml \
--post-renderer /opt/deer-flow-deploy/post-renderer.sh
kubectl rollout restart deployment -n deer-flow -l app.kubernetes.io/component=gateway
kubectl rollout restart deployment -n deer-flow -l app.kubernetes.io/component=frontend
kubectl rollout status deployment -n deer-flow -l app.kubernetes.io/component=gateway
kubectl rollout status deployment -n deer-flow -l app.kubernetes.io/component=frontend