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

如何使用gRPC向Kubernetes容器发送RPC请求触发脚本?

你的工作流程思路基本正确,几个细节调整+实现示例

首先得纠正一个小误区:gin是HTTP Web框架,和gRPC完全不是一个体系的哦~如果用Go开发gRPC客户端/服务端,直接用官方的google.golang.org/grpc库就好,生态成熟,文档也很完善。

接下来我把整个实现流程拆解清楚,附带代码片段和K8s配置:

1. 先定义gRPC服务协议(核心是.proto文件)

gRPC基于Protocol Buffers(简称Protobuf),首先得把服务接口和消息格式定义好,这是客户端和服务端的“约定”:

// script_executor.proto
syntax = "proto3";

package scriptrunner;

option go_package = "./scriptrunner";

// 定义服务:接收请求,执行脚本,返回结果
service ScriptExecutor {
  rpc RunScript (ScriptRequest) returns (ScriptResponse);
}

// 请求消息:可以给脚本传参数
message ScriptRequest {
  string script_args = 1;
}

// 响应消息:返回脚本的退出码、标准输出、错误输出
message ScriptResponse {
  int32 exit_code = 1;
  string stdout = 2;
  string stderr = 3;
}

写完后用protoc工具生成Go代码(需要先安装protoc和Go的gRPC插件):

protoc --go_out=. --go-grpc_out=. script_executor.proto

2. 实现gRPC服务端(容器内运行,负责接收请求触发脚本)

服务端要监听指定端口,收到请求后调用你的脚本,然后把执行结果返回给客户端:

// server.go
package main

import (
  "context"
  "os/exec"
  "scriptrunner" // 刚才生成的Protobuf代码包
  "google.golang.org/grpc"
  "log"
  "net"
)

// 实现gRPC服务接口
type server struct {
  scriptrunner.UnimplementedScriptExecutorServer
}

// 处理RunScript请求的核心逻辑
func (s *server) RunScript(ctx context.Context, req *scriptrunner.ScriptRequest) (*scriptrunner.ScriptResponse, error) {
  // 替换成你实际的脚本路径,比如./my-script.sh
  cmd := exec.Command("/bin/sh", "./my-script.sh", req.ScriptArgs)
  
  // 执行脚本,捕获输出和错误
  stdout, err := cmd.Output()
  var stderr []byte
  exitCode := 0

  if err != nil {
    // 如果是脚本执行退出错误,提取错误输出和退出码
    if exitErr, ok := err.(*exec.ExitError); ok {
      stderr = exitErr.Stderr
      exitCode = exitErr.ExitCode()
    } else {
      return nil, err
    }
  }

  // 返回执行结果
  return &scriptrunner.ScriptResponse{
    ExitCode: int32(exitCode),
    Stdout:   string(stdout),
    Stderr:   string(stderr),
  }, nil
}

func main() {
  // 监听你指定的端口,比如50051
  lis, err := net.Listen("tcp", ":50051")
  if err != nil {
    log.Fatalf("failed to listen: %v", err)
  }

  // 创建gRPC服务实例并注册我们的实现
  grpcServer := grpc.NewServer()
  scriptrunner.RegisterScriptExecutorServer(grpcServer, &server{})

  log.Printf("gRPC server listening at %v", lis.Addr())
  if err := grpcServer.Serve(lis); err != nil {
    log.Fatalf("failed to serve: %v", err)
  }
}

3. 实现gRPC客户端(用来触发脚本的请求工具)

客户端代码负责连接容器的gRPC服务,发送请求并获取结果:

// client.go
package main

import (
  "context"
  "scriptrunner"
  "google.golang.org/grpc"
  "google.golang.org/grpc/credentials/insecure"
  "log"
)

func main() {
  // 连接容器的地址+端口,比如Pod的IP或者K8s Service的地址,端口和服务端一致
  conn, err := grpc.Dial("your-pod-ip:50051", grpc.WithTransportCredentials(insecure.NewCredentials()))
  if err != nil {
    log.Fatalf("could not connect to server: %v", err)
  }
  defer conn.Close()

  // 创建客户端实例
  client := scriptrunner.NewScriptExecutorClient(conn)

  // 发送请求,这里可以给脚本传参数
  resp, err := client.RunScript(context.Background(), &scriptrunner.ScriptRequest{ScriptArgs: "param1 param2"})
  if err != nil {
    log.Fatalf("failed to trigger script: %v", err)
  }

  // 打印脚本执行结果
  log.Printf("Exit Code: %d\n--- Stdout ---\n%s\n--- Stderr ---\n%s", resp.ExitCode, resp.Stdout, resp.Stderr)
}

4. K8s Pod配置(暴露gRPC端口)

要让外部能访问容器的gRPC服务,需要在Pod的容器配置里声明暴露的端口:

apiVersion: v1
kind: Pod
metadata:
  name: script-runner-pod
spec:
  containers:
  - name: script-runner-container
    image: your-custom-image:latest # 这个镜像要包含gRPC服务端二进制、你的脚本和依赖环境
    ports:
    - containerPort: 50051 # 和服务端监听的端口保持一致
      name: grpc-port

如果需要从K8s集群外部访问,还可以配置NodePort类型的Service,或者支持gRPC的Ingress(比如NGINX Ingress)。

几个额外注意事项

  • 打包镜像时,要确保脚本有可执行权限(可以在Dockerfile里加RUN chmod +x /path/to/your-script.sh)
  • 生产环境不要用insecure.NewCredentials(),要配置TLS加密gRPC连接
  • 脚本依赖的工具(比如Python、curl等)也要包含在镜像里

内容的提问来源于stack exchange,提问作者jtee

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 03:54:05