如何将Lua脚本注入Kubernetes Ingress Nginx Controller配置以实现HTTP头路由
嘿,刚好我之前在项目里做过类似的自定义路由需求,给你梳理几种靠谱的方法,都是实际验证过的:
这是最快捷的方式,适合逻辑简单、只针对特定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变量来实现动态路由。
如果你的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脚本就会对所有路由生效了。
如果你的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




