You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

K8s技术问询:如何仅在部署NodeJS的节点各部署1个MySQL Router

你的Kubernetes部署需求解决方案

首先直接给结论:Kubernetes默认的原生资源(比如Deployment、DaemonSet、StatefulSet)并不支持这种“动态跟踪特定Pod所在节点并部署对应实例”的逻辑。默认组件要么是按固定副本数部署(Deployment),要么是在所有匹配标签的节点上部署(DaemonSet),无法自动感知其他Pod的分布并调整部署目标。

接下来咱们聊聊具体怎么实现你的需求:

方案一:动态节点标签 + DaemonSet(最易上手)

这个方案的核心思路是:

  1. 定期扫描命名空间X里的NodeJS Pod,给运行了至少一个NodeJS实例的节点打上专属标签
  2. 用DaemonSet部署MySQL Router,让它只在带有这个专属标签的节点上运行(DaemonSet天然保证每个节点只跑一个Pod)

步骤1:给NodeJS Pod打上统一标签

首先确保你的NodeJS Deployment/StatefulSet的Pod有统一标签,比如app: nodejs,这样方便后续识别:

# 示例NodeJS Deployment片段
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodejs-app
  namespace: X
spec:
  selector:
    matchLabels:
      app: nodejs
  template:
    metadata:
      labels:
        app: nodejs # 统一标签
    spec:
      containers:
      - name: nodejs
        image: your-nodejs-image:latest

步骤2:编写节点标签自动更新脚本

写一个简单的脚本,用来识别有NodeJS Pod的节点并打标签,同时移除没有NodeJS Pod的节点的标签:

#!/bin/bash
NAMESPACE="X"
NODEJS_LABEL="app=nodejs"
TARGET_LABEL="has-nodejs-app=true"

# 获取当前运行NodeJS Pod的所有节点(去重)
nodes_with_nodejs=$(kubectl get pods -n $NAMESPACE -l $NODEJS_LABEL -o json | jq -r '.items[].spec.nodeName' | sort | uniq)

# 获取当前带有目标标签的所有节点
nodes_with_label=$(kubectl get nodes -l has-nodejs-app=true -o json | jq -r '.items[].metadata.name')

# 给有NodeJS的节点打标签(覆盖已有标签)
for node in $nodes_with_nodejs; do
  kubectl label nodes $node has-nodejs-app=true --overwrite
done

# 移除没有NodeJS的节点的标签
for node in $nodes_with_label; do
  if ! echo "$nodes_with_nodejs" | grep -q "$node"; then
    kubectl label nodes $node has-nodejs-app-
  fi
done

步骤3:用CronJob定期运行脚本

把这个脚本做成Kubernetes CronJob,让它定期执行(比如每分钟一次,根据你的业务调整):

apiVersion: batch/v1
kind: CronJob
metadata:
  name: node-label-updater
  namespace: X
spec:
  schedule: "* * * * *" # 每分钟执行一次
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: node-labeler-sa # 需要给这个SA分配节点标签权限
          containers:
          - name: label-updater
            image: bitnami/kubectl:latest # 带kubectl和jq的镜像
            command: ["bash", "-c"]
            args:
            - |
              # 把上面的脚本内容粘贴到这里
              #!/bin/bash
              NAMESPACE="X"
              NODEJS_LABEL="app=nodejs"
              TARGET_LABEL="has-nodejs-app=true"

              nodes_with_nodejs=$(kubectl get pods -n $NAMESPACE -l $NODEJS_LABEL -o json | jq -r '.items[].spec.nodeName' | sort | uniq)
              nodes_with_label=$(kubectl get nodes -l has-nodejs-app=true -o json | jq -r '.items[].metadata.name')

              for node in $nodes_with_nodejs; do
                kubectl label nodes $node has-nodejs-app=true --overwrite
              done

              for node in $nodes_with_label; do
                if ! echo "$nodes_with_nodejs" | grep -q "$node"; then
                  kubectl label nodes $node has-nodejs-app-
                fi
              done
          restartPolicy: OnFailure

步骤4:部署MySQL Router的DaemonSet

创建DaemonSet,指定只在带有has-nodejs-app=true标签的节点上运行:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: mysql-router
  namespace: X
spec:
  selector:
    matchLabels:
      app: mysql-router
  template:
    metadata:
      labels:
        app: mysql-router
    spec:
      nodeSelector:
        has-nodejs-app: "true" # 只选择有NodeJS的节点
      containers:
      - name: mysql-router
        image: mysql/mysql-router:8.0
        # 这里添加你的MySQL Router配置,比如环境变量、端口映射等
        env:
        - name: MYSQL_HOST
          value: "mysql-group-replication-service.X.svc.cluster.local"
        ports:
        - containerPort: 6446

方案二:自定义控制器/Operator(更实时高效)

如果你的业务需要更实时的响应(比如NodeJS Pod刚部署到节点,Router立刻启动),可以写一个自定义控制器:

  • 监听命名空间X里的NodeJS Pod的CREATE、DELETE事件
  • 当节点上的NodeJS Pod数量从0变为1时,创建一个MySQL Router Pod绑定到该节点
  • 当节点上的NodeJS Pod数量从1变为0时,删除该节点上的MySQL Router Pod

你可以用Kubernetes Client SDK(比如Go的client-go、Python的kubernetes-client)来开发这个控制器,或者用Kubebuilder/Operator Framework快速生成脚手架。

额外注意:确保每个节点仅运行一个Router

如果不用DaemonSet(比如用Deployment),可以通过Pod反亲和性来保证同一个节点上只有一个Router:

affinity:
  podAntiAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
    - labelSelector:
        matchExpressions:
        - key: app
          operator: In
          values:
          - mysql-router
      topologyKey: kubernetes.io/hostname

这个规则会强制Kubernetes不会把第二个Router Pod调度到已经有Router的节点上。


内容的提问来源于stack exchange,提问作者Đinh Anh Huy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 19:23:14