在多个不同的子路径上运行nginx的多个docker应用程序

在多个不同的子路径上运行nginx的多个docker应用程序,nginx,kubernetes,nginx-location,Nginx,Kubernetes,Nginx Location,我试图在一个GKE实例中运行几个Docker应用程序,负载平衡器设置将它们公开。每个应用程序都包含一个简单的node.js应用程序,使用nginx为站点提供服务;一个简单的nginx配置公开应用程序,其中的位置块响应/。这在本地开发时效果很好,因为我可以在一个单独的端口上运行每个pod,并且只需在127.0.0.1:8080或类似位置访问它们 我遇到的问题是,当使用GCP负载平衡器时,虽然我可以轻松地将流量路由到Kubernetes服务,以便映射到我的fooservice/pod并转到我的bar

我试图在一个GKE实例中运行几个Docker应用程序,负载平衡器设置将它们公开。每个应用程序都包含一个简单的node.js应用程序,使用nginx为站点提供服务;一个简单的nginx配置公开应用程序,其中的位置块响应
/
。这在本地开发时效果很好,因为我可以在一个单独的端口上运行每个pod,并且只需在127.0.0.1:8080或类似位置访问它们

我遇到的问题是,当使用GCP负载平衡器时,虽然我可以轻松地将流量路由到Kubernetes服务,以便映射到我的
foo
service/pod并转到我的
bar
服务,
bar
pod会以404作为路径响应,
/bar
与位置块中指定的路径不匹配

这些豆荚的数量将大幅增加,因此我不希望提前手动知道每个豆荚将位于什么路径下,也不希望在我的git回购协议中体现这一点

是否有一种方法可以动态定义位置块匹配的路径(例如通过环境变量),以便将其定义为部署这些服务时使用的Helm图表的一部分?或者,是否可以匹配所有路径?这是一个可行的解决方案,还是只是问问题


感谢您的帮助。

只需使用入口即可。它将允许您将不同的路径映射到不同的后端
服务
。这一点在中、英文中都有很好的解释

典型的入口对象定义可能如下所示:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  backend:
    serviceName: my-products
    servicePort: 60001
  rules:
  - http:
      paths:
      - path: /
        backend:
          serviceName: my-products
          servicePort: 60000
      - path: /discounted
        backend:
          serviceName: my-discounted-products
          servicePort: 80
      - path: /special
        backend:
          serviceName: special-offers
          servicePort: 80
      - path: /news
        backend:
          serviceName: news
          servicePort: 80
           
当您在GKE上应用入口定义时,负载平衡器将自动创建。请注意,所有
服务
都可以使用相同的标准http端口,您不必使用任何自定义端口

您可能希望指定,出现在上面的示例中(
backend
部分,位于
spec
的右下方),但它是可选的。它将确保:

任何与规则字段中的路径不匹配的请求都将发送到 在后端字段中指定的服务和端口。例如,在 以下入口,不匹配/或/折扣的任何请求 发送到端口60001上名为my products的服务

使用GKE上提供的默认ingress controller时可能遇到的唯一问题是,目前不支持重写

如果您的nginx pod仅在
“/”
路径上公开应用程序内容,则不支持重写不应成为限制,据我所知,这适用于您的情况:

每个应用程序都包含一个简单的node.js应用程序,使用nginx为站点提供服务; 一个简单的nginx配置使用一个位置块公开应用程序 响应/

但是,如果您在某个时候决定需要进行上述重写,例如,您的一个应用程序不是在
/
下公开的,而是在
/Pod
中的
/bar
下公开的,那么您可以决定在GKE上部署,这也可以很容易地完成

因此,您只需要在以下场景中使用它:用户访问入口IP,后跟
/foo
->请求不仅被重定向到特定的后端
服务
,该服务公开您的nginx
Pod
,而且原始路径(
/foo
)也需要重写到新路径(
/bar
)应用程序在其下暴露在
Pod

更新:
感谢您的回复。以上入口配置非常简单 类似于我已经将转发/foo和/bar配置为 不同的pod。问题是路径被转发,并且(在 在这个问题上做更多的研究)我认为我需要重写 发送到pod的URL,因为我的 nginx配置与接收到的/foo或/bar路径不匹配 aodj 8月14日9:17

嗯,你是对的。原始访问路径,例如
/foo
确实会被转发到目标
Pod
。因此,选择
/foo
路径除了将您引导到入口资源中定义的相应
后端
之外,还意味着目标nginx服务器
Po中运行d
必须在
/foo
路径下提供其内容

我用GKE ingress对其进行了验证,并可以通过检查
Pod
日志确认发送到nginx
Pod
的http请求通过
/foo
路径确实到达
Pod
作为
/usr/share/nginx/html/foo
的请求,同时它在
/code>下提供其内容>,而不是来自
/usr/share/nginx/html的/foo。因此,请求目标服务器上不存在的内容不可避免地会导致
404错误

如前所述,GKE上可用的默认入口控制器不支持重写,因此如果出于某种原因想使用它,重新配置目标nginx服务器似乎是使其工作的唯一解决方案

幸运的是,我们还有另一个选项,即nginx-ingres-controller。它支持重写,因此可以轻松解决我们的问题。我们可以通过运行以下两个命令将其部署到GKE集群上:

kubectl create clusterrolebinding cluster-admin-binding \
  --clusterrole cluster-admin \
  --user $(gcloud config get-value account)

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.34.1/deploy/static/provider/cloud/deploy.yaml
是的,就是这么简单!您可以在中仔细查看安装过程

然后我们可以应用以下
入口
资源定义:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/rewrite-target: /$2
  name: rewrite
  namespace: default
spec:
  rules:
  - http:
      paths:
      - backend:
          serviceName: nginx-deployment-1
          servicePort: 80
        path: /foo(/|$)(.*)
      - backend:
          serviceName: nginx-deployment-2
          servicePort: 80
        path: /bar(/|$)(.*)
请注意,我们使用
kubernetes.io/ingres.class:“nginx”
注释来选择新部署的nginx-ingres控制器来处理该入口资源,而不是默认的GKE-ingres控制器

使用的重写将确保在到达目标之前重写原始访问路径apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment-1 labels: app: nginx-1 spec: replicas: 3 selector: matchLabels: app: nginx-1 template: metadata: labels: app: nginx-1 spec: initContainers: - name: init-myservice image: nginx:1.14.2 command: ['sh', '-c', "echo DEPLOYMENT-1 > /usr/share/nginx/html/index.html"] volumeMounts: - mountPath: /usr/share/nginx/html name: cache-volume containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80 volumeMounts: - mountPath: /usr/share/nginx/html name: cache-volume volumes: - name: cache-volume emptyDir: {}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-2
  labels:
    app: nginx-2
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-2
  template:
    metadata:
      labels:
        app: nginx-2
    spec:
      initContainers:
      - name: init-myservice
        image: nginx:1.14.2
        command: ['sh', '-c', "echo DEPLOYMENT-2 > /usr/share/nginx/html/index.html"]
        volumeMounts:
        - mountPath: /usr/share/nginx/html
          name: cache-volume
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /usr/share/nginx/html
          name: cache-volume
      volumes:
      - name: cache-volume
        emptyDir: {}
kubectl expose deployment nginx-deployment-1 --type NodePort --target-port 80 --port 80
kubectl expose deployment nginx-deployment-2 --type NodePort --target-port 80 --port 80