You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何将Lua脚本注入Kubernetes Ingress Nginx Controller配置以实现HTTP头路由

嘿,刚好我之前在项目里做过类似的自定义路由需求,给你梳理几种靠谱的方法,都是实际验证过的:

方法1:通过Ingress注解直接注入(适合简单脚本)

这是最快捷的方式,适合逻辑简单、只针对特定Ingress生效的Lua脚本。你可以用nginx.ingress.kubernetes.io/server-snippets或者nginx.ingress.kubernetes.io/configuration-snippet注解,把Lua脚本直接嵌入到Ingress资源里。

举个例子,假设你要根据请求头X-App-Version动态切换后端服务:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: custom-lua-ingress
  annotations:
    nginx.ingress.kubernetes.io/server-snippets: |
      # 定义一个变量存储目标服务名
      set $target_service "default-service";
      # 在请求处理阶段执行Lua逻辑
      access_by_lua_block {
          local app_version = ngx.req.get_headers()["X-App-Version"]
          if app_version == "v2" then
              ngx.var.target_service = "v2-service"
          end
      }
spec:
  ingressClassName: nginx
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: $target_service
            port:
              number: 80

这里server-snippets会把内容插入到Nginx对应的server块中,access_by_lua_block是OpenResty提供的指令,专门用来在请求访问阶段执行Lua脚本,修改Nginx变量来实现动态路由。

方法2:通过ConfigMap全局注入(适合全局通用脚本)

如果你的Lua脚本需要对所有Ingress路由生效,或者脚本内容比较长,推荐用ConfigMap来管理脚本,再挂载到Ingress Controller容器中。

第一步:创建包含Lua脚本的ConfigMap

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-custom-lua
  namespace: ingress-nginx  # 这里要填Ingress Controller所在的命名空间
data:
  custom-lua-rules.conf: |
    access_by_lua_block {
        # 示例:根据User-Agent判断是否是移动端,重写请求路径
        local user_agent = ngx.req.get_headers()["User-Agent"]
        if user_agent and string.find(user_agent, "Mobile") then
            ngx.req.set_uri("/mobile" .. ngx.var.uri)
        end
    }

第二步:挂载ConfigMap到Ingress Controller

编辑Ingress Controller的Deployment(如果是DaemonSet就编辑DaemonSet):

kubectl edit deployment ingress-nginx-controller -n ingress-nginx

在容器的volumeMounts中添加挂载配置:

volumeMounts:
# 原有的挂载项保留,新增下面这行
- name: custom-lua-config
  mountPath: /etc/nginx/conf.d/custom-lua-rules.conf
  subPath: custom-lua-rules.conf

然后在volumes部分添加ConfigMap引用:

volumes:
# 原有的volume项保留,新增下面这行
- name: custom-lua-config
  configMap:
    name: nginx-custom-lua

保存后,Ingress Controller会自动重启并加载新的配置,这个Lua脚本就会对所有路由生效了。

方法3:自定义Ingress Controller镜像(适合复杂Lua依赖)

如果你的Lua脚本需要用到第三方Lua库(比如lua-resty-http用来发起HTTP请求),或者需要深度定制Nginx配置,那最好是基于官方镜像构建自己的自定义镜像。

第一步:编写Dockerfile

# 基于官方Ingress Nginx Controller镜像,替换成你使用的版本
FROM k8s.gcr.io/ingress-nginx/controller:v1.8.2

# 切换到root用户安装依赖
USER root
# 使用OpenResty的包管理器opm安装第三方Lua库
RUN opm install openresty/lua-resty-http

# 切回nginx用户(官方镜像默认用这个用户运行)
USER nginx

第二步:构建并推送镜像

用Docker构建镜像,推送到你的私有镜像仓库:

docker build -t your-registry/ingress-nginx-custom:v1.8.2 .
docker push your-registry/ingress-nginx-custom:v1.8.2

第三步:替换Ingress Controller的镜像

编辑Ingress Controller的Deployment,把镜像替换成你自定义的镜像:

spec:
  template:
    spec:
      containers:
      - name: controller
        image: your-registry/ingress-nginx-custom:v1.8.2

之后你就可以用方法1或2注入脚本,自由使用第三方Lua库了。

一些注意事项
  • 官方的Ingress Nginx Controller镜像默认已经包含了OpenResty的Lua模块,不需要额外启用
  • 调试Lua脚本时,可以进入Ingress Controller容器查看日志:kubectl exec -it <ingress-controller-pod> -n ingress-nginx -- tail -f /var/log/nginx/error.log,能看到脚本的报错信息
  • 编写Lua脚本时尽量用非阻塞API,避免阻塞Nginx的事件循环,影响性能

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

火山引擎 最新活动