在多个不同的子路径上运行nginx的多个docker应用程序
我试图在一个GKE实例中运行几个Docker应用程序,负载平衡器设置将它们公开。每个应用程序都包含一个简单的node.js应用程序,使用nginx为站点提供服务;一个简单的nginx配置公开应用程序,其中的位置块响应在多个不同的子路径上运行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
/
。这在本地开发时效果很好,因为我可以在一个单独的端口上运行每个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
->请求不仅被重定向到特定的后端服务
,该服务公开您的nginxPod
,而且原始路径(/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
日志确认发送到nginxPod
的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