问题
我想知道如何配置 Nginx Ingress 控制器以便在调用外部 IP 地址时重定向到 URL。
入口控制器 yaml
apiVersion: v1
kind: Service
metadata:
labels:
helm.sh/chart: ingress-nginx-3.4.1
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.40.2
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: controller
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
type: NodePort
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
- name: https
port: 443
protocol: TCP
targetPort: https
externalIPs:
- ip1
- ip2
- ip3
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/component: controller
如果我在浏览器中输入我的外部 IP,我当然会进入 Nginx 404 页面。在这个特殊情况下,我想设置重定向到其特定域,例如 google.com。我想提高公共 K8s 集群的安全性。我尚未配置这个特殊情况,想知道是否有可能设置这样的转发过程。所有配置的 Ingress 资源都将其服务发布到互联网。
答案1
裸机环境缺乏传统云环境所提供的商品,传统云环境提供网络负载均衡器,单个 K8s 清单足以为 NGINX 入口控制器提供单点联系。当然,我们必须记住,内部重定向遵循入口资源,然后入口资源会相应地配置入口控制器。
和外部 IP方法 HTTP 的源 IP 不会被保留,因此尽管它看起来很简单,但不建议使用它。因此,您将丢失有关请求的信息(除非您将监控入口控制器)
要回答如何在 Nginx Ingress Controller 中配置外部 IP 重定向的问题,我们必须首先了解 Ingress 实际上是什么:
Ingress 将集群外部的 HTTP 和 HTTPS 路由暴露给集群内的服务。流量路由由 Ingress 资源上定义的规则控制。必须有一个 Ingress 控制器来满足 Ingress 要求。仅创建 Ingress 资源不起作用。
为了实现预期结果,您应该创建两个单独的入口对象(而不是控制器)。第一个没有指定主机,因此规则适用于通过指定的 IP 地址的所有入站 HTTP 流量,如入口规则:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/permanent-redirect: "https://www.google.com"
name: ingress-redirect
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
serviceName: example
servicePort: 12
第二个入口对象具有提供的主机(例如,hello-world.info,以便规则适用于该主机。如下例所示:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-host
spec:
rules:
- host: hello-world.info
http:
paths:
- path: /
pathType: Prefix
backend:
serviceName: web
servicePort: 80
如下所示,上述配置在 nginx-ingress-controller 的 nginx.conf 中创建了以下部分。一个部分负责处理带有特定 Host: 标头的请求,另一个部分负责处理不带 Host: 标头的请求,例如,如果请求直接发送到 IP 地址:
enter http {
# works when no Host header is provided
## start server _
server {
server_name _ ;
listen 80 default_server reuseport backlog=511 ;
listen 443 default_server reuseport backlog=511 ssl http2 ;
location / {
set $namespace "default";
set $ingress_name "ingress-redirect";
set $service_name "";
set $service_port "";
set $location_path "/";
return 301 https://www.google.com;
# works when specific Host header is provided
## start server hello-world.info
server {
server_name hello-world.info ;
listen 80 ;
listen 443 ssl http2 ;
location / {
set $namespace "default";
set $ingress_name "ingress-host";
set $service_name "web";
set $service_port "80";
set $location_path "/";
}
}
## end server hello-world.info
为了测试目的,我快速部署了这两个 ingress 对象和 nginx pod:
➜ kubectl run --image nginx web
并将其暴露给第二个入口对象后面的服务:
➜ kubectl expose pod web --port 80
正如您所见,当卷曲重定向按预期工作时:
➜ ~ curl $(minikube ip) -I
HTTP/1.1 301 Moved Permanently
Server: nginx/1.19.0
Date: Tue, 27 Oct 2020 13:22:06 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://www.google.com
如果你使用主机名 curl 相同的地址,它会重定向到 nginx pod:
➜ ~ curl $(minikube ip) -H "Host: hello-world.info"
---
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
---
另外值得一提的是,Kubernetes 文档也提供了很好的例子基于名称的虚拟主机。它支持将 HTTP 流量路由到同一 IP 地址的多个主机名。文档中的示例告诉后备负载均衡器根据主机头。
例如在文档页面上述路由将请求的流量路由first.bar.com
到service1
,将请求的流量second.foo.com
路由到,并将任何发往请求中未定义(即没有提供请求标头)service2
的 IP 地址的流量路由到。hostname
service3
答案2
此注释的形式为 nginx.ingress.kubernetes.io/default-backend:,用于指定自定义默认后端。这是对您应用此注释的同一命名空间内的服务的引用。此注释将覆盖全局默认后端。
无关:为了提高安全性,我将我的 IP(ingress-nginx)隐藏在 cloudflares 网络后面。我只允许 cloudflare IP 通过脚本连接到我的网络服务器。独立主机的示例: https://raw.githubusercontent.com/cloudpanel-io/scripts/master/cloudflare/whitelist_ips
优点:
- 没人知道我的真实 IP
- 用户只需通过“真实” DNS 记录即可连接
缺点:
- 您必须使用 Cloudflare(提供免费计划)
- 更高的 TTFB
附言:我与 cloudflare 没有任何关系,也不为他们工作。