http - > Google Kubernetes引擎中的https重定向

时间:2018-02-04 17:07:32

标签: kubernetes google-cloud-platform google-compute-engine google-kubernetes-engine

我希望重定向来自

的所有流量

http://example.com - > https://example.com就像几乎所有网站一样。

我看过这个链接没有成功: Kubernetes HTTPS Ingress in Google Container Engine

并在我的ingress.yaml文件中尝试了以下注释。

nginx.ingress.kubernetes.io/configuration-snippet: |
  if ($http_x_forwarded_proto != 'https') {
    return 301 https://$host$request_uri;
  }
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
kubernetes.io/ingress.allow-http: "false"

一切都没有成功。为了清楚起见,我可以访问https://example.comhttp://example.com而没有任何错误,我需要http调用重定向到https。

由于

5 个答案:

答案 0 :(得分:3)

GKE使用GCE L7。您不支持在示例中引用的规则,并且应在应用程序级别控制HTTP到HTTPS重定向。

L7插入x-forwarded-proto标头,您可以使用它来了解前端流量是使用HTTP还是HTTPS。看看这里:Redirecting HTTP to HTTPS

在Nginx的链接中也有一个例子(为方便起见而复制):

# Replace '_' with your hostname.
server_name _;
if ($http_x_forwarded_proto = "http") {
    return 301 https://$host$request_uri;
}

答案 1 :(得分:3)

GKE使用自己的Ingress Controller,不支持强制https。

这就是为什么你必须自己管理NGINX Ingress Controller的原因。

有关如何在GKE上执行此操作,请参阅this post

希望它有所帮助。

答案 2 :(得分:3)

对于像我这样每个月大约搜索一次该问题的每个人,Google均已答复我们的请求,并正在其负载均衡器上测试HTTP-> HTTPS SSL重定向。 Their latest answer表示应该在2020年1月底之前的某个时间到达Alpha。

他们的评论:

感谢您在此问题上的耐心配合。该功能目前正在测试中,我们预计在一月底之前进入Alpha阶段。随着我们接近Alpha发布,我们的PM团队将发布更详细的公告。

更新:HTTP到HTTPS重定向现已普遍可用:https://cloud.google.com/load-balancing/docs/features#routing_and_traffic_management

答案 3 :(得分:2)

为了它的价值,我最终在NGINX中使用了反向代理。

  1. 您需要创建秘密并将其同步到您的容器中
  2. 您需要使用nginx配置在nginx中创建配置图,以及引用此附加配置文件的默认配置。
  3. 这是我的配置:

    worker_processes  1;
    
    events {
        worker_connections  1024;
    }
    
    
    http {
    
    default_type  application/octet-stream;
    
    # Logging Configs
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    
    access_log  /var/log/nginx/access.log  main;
    
    sendfile        on;
    keepalive_timeout  65;
    
    # Puntdoctor Proxy Config
    include /path/to/config-file.conf;
    
    # PubSub allows 10MB Files. lets allow 11 to give some space
    client_max_body_size 11M;
    
    }
    

    然后是config.conf

    server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
    }
    
    server {
    
    listen 443;
    server_name example.com;
    
    ssl_certificate           /certs/tls.crt;
    ssl_certificate_key       /certs/tls.key;
    
    ssl on;
    ssl_session_cache  builtin:1000  shared:SSL:10m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-RC4-SHA:AES128-GCM-SHA256:HIGH:!RC4:!MD5:!aNULL:!EDH:!CAMELLIA;
    ssl_prefer_server_ciphers on;
    
    location / {
    
      proxy_set_header        Host $host;
      proxy_set_header        X-Real-IP $remote_addr;
      proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header        X-Forwarded-Proto $scheme;
      proxy_set_header        X-Forwarded-Host $http_host;
    
      # Fix the “It appears that your reverse proxy set up is broken" error.
      proxy_pass          http://deployment-name:8080/;
      proxy_read_timeout  90;
    
      proxy_redirect      http://deployment-name:8080/ https://example.com/;
    }
    }
    
    1. 创建部署:
    2. 以下是.yaml文件

      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: puntdoctor-lb
      spec:
         ports:
          - name: https
            port: 443
            targetPort: 443
           - name: http
            port: 80
            targetPort: 80
        selector:
          app: puntdoctor-nginx-deployment
        type: LoadBalancer
        loadBalancerIP: 35.195.214.7
      ---
      apiVersion: extensions/v1beta1
      kind: Deployment
      metadata:
        name: puntdoctor-nginx-deployment
      spec:
         replicas: 2
        template:
          metadata:
            labels:
              app: puntdoctor-nginx-deployment
          spec:
             containers:
             - name: adcelerate-nginx-proxy
              image: nginx:1.13
               volumeMounts:
              - name: certs
                mountPath: /certs/
              - name: site-config
                mountPath: /etc/site-config/
              - name: default-config
                mountPath: /etc/nginx/
              ports:
              - containerPort: 80
                name: http
              - containerPort: 443
                name: https
            volumes:
            - name: certs
              secret:
                secretName: nginxsecret
            - name: site-config
              configMap:
                name: nginx-config
             - name: default-config
              configMap:
               name: default
      

      希望这有助于某人解决这个问题,感谢其他2个答案,他们都给了我宝贵的见解。

答案 4 :(得分:2)

当前,严重缺乏有关如何正确执行此操作的文档(注释,SSL / HTTPS,运行状况检查等),并且该文档已经太久了。我怀疑这是因为他们更喜欢您使用App Engine,这虽然神奇但价格昂贵。对于GKE,有两个选择:

  • 使用Google管理的SSL证书并在您的应用程序/网站前面添加其他NGINX服务器配置来吸引用户
  • 具有自我管理/第三方SSL证书的NGINX入口控制器

以下是使用前者进行工作设置的步骤。

1您的应用之门

nginx.conf:(省略号表示其他不相关的非强制性设置)

user  nginx;
worker_processes  auto;

events {
    worker_connections  1024;
}

http {
    ...

    keepalive_timeout  620s;

    ## Logging ##
    ...
    ## MIME Types ##
    ...
    ## Caching ##
    ...
    ## Security Headers ##
    ...
    ## Compression ##
    ....

    server {
        listen 80;

        ## HTTP Redirect ##
        if ($http_x_forwarded_proto = "http") {
            return 301 https://[YOUR DOMAIN]$request_uri;
        }

        location /health/liveness {
            access_log off;
            default_type text/plain;
            return 200 'Server is LIVE!';
        }

        location /health/readiness {
            access_log off;
            default_type text/plain;
            return 200 'Server is READY!';
        }

        root /usr/src/app/www;
        index index.html index.htm;
        server_name [YOUR DOMAIN] www.[YOUR DOMAIN];

        location / {
            try_files $uri $uri/ /index.html;
        }
    }
}

注意:仅一个服务端口。全局转发规则将http_x_forwarded_proto标头添加到通过它的所有流量中。因为到您域的所有流量现在都通过此规则(请记住,容器上的一个端口,服务和入口),所以将始终设置此标头(至关重要!)。请注意上面的检查和重定向:仅当标头值为“ https”时,它才会继续投放。根,索引和位置值可能因您的项目(这是一个有角度的项目)而异。 keepalive_timeout设置为值recommended by google。我更喜欢使用主要的nginx.conf文件,但是大多数人在/etc/nginx/conf.d中添加一个custom.conf文件。如果执行此操作,只需确保使用 includes 语句将文件导入到主要的nginx.conf http块中。这些注释会突出显示您在一切正常时可能要添加的其他设置,例如gzip / brotli,安全标题,保存日志的位置等等。

Dockerfile:

...
COPY nginx.conf /etc/nginx/nginx.conf
CMD ["nginx", "-g", "daemon off;"]

注意:仅最后两行。无需指定EXPOSE端口。 COPY用修改后的默认值替换默认的nginx.conf。 CMD启动了轻型服务器。

2创建部署清单并应用/创建

deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: uber-dp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: uber
  template:
    metadata:
      labels:
        app: uber
    spec:
      containers:
        - name: uber-ctr
          image: gcr.io/uber/beta:v1 // or some other registry
          livenessProbe:
            failureThreshold: 3
            initialDelaySeconds: 60
            httpGet:
              path: /health/liveness
              port: 80
              scheme: HTTP
          readinessProbe:
            failureThreshold: 3
            initialDelaySeconds: 30
            httpGet:
              path: /health/readiness
              port: 80
              scheme: HTTP
          ports:
            - containerPort: 80
          imagePullPolicy: Always

注意:只有一个指定的端口是必需的,因为我们将所有(HTTP和HTTPS)流量都指向该端口。为简单起见,我们使用相同的路径进行活跃性和就绪性调查;这些检查将在NGINX服务器上处理,但是您可以并且应该添加检查应用程序自身运行状况的检查(例如,专用页面返回200,如果运行状况良好)。GCE也将选择就绪探测器,默认情况下,它具有自己不可删除的健康检查。

3创建服务清单并应用/创建

service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: uber-svc
  labels:
    app: uber
spec:
  ports:
    - name: default-port
      port: 80
  selector:
    app: uber
  sessionAffinity: None
  type: NodePort

注意:default-port在容器上指定端口80。

4获取静态IP地址

在GCP的汉堡菜单中:VPC网络->外部IP地址。转换您自动生成的临时IP或创建一个新的临时IP。记下姓名和地址。

5 Create an SSL cert和默认区域

在汉堡菜单中:网络服务->负载平衡->单击“高级菜单”->证书->创建SSL证书。按照说明进行操作,创建或上传证书,并记下名称。然后,从菜单:Cloud DNS-> Create Zone。按照说明,create a default zone用于您的域。添加一个CNAME记录,其中www为DNS名称,您的域为规范名称。添加一个具有空DNS名称值和您的静态IP作为IPV4的A记录。保存。

6创建入口清单并应用/创建

ingress.yaml:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: mypt-ingress
  annotations:
    kubernetes.io/ingress.global-static-ip-name: [NAME OF YOUR STATIC IP ADDRESS]
    kubernetes.io/ingress.allow-http: "true"
    ingress.gcp.kubernetes.io/pre-shared-cert: [NAME OF YOUR GOOGLE-MANAGED SSL]
spec:
  backend:
    serviceName: mypt-svc
    servicePort: 80

注意:后端属性指向服务,指向服务器,该容器包含受服务器“保护”的应用程序。注释将您的应用程序与SSL连接,并强制允许使用http进行运行状况检查。服务和入口组合在一起配置G7 load balancer(组合的全局转发规则,后端和前端“服务”,SSL证书和目标代理等)。

7喝杯茶或其他东西

一切都需要约10分钟来配置。清除缓存并使用各种浏览器(Tor,Opera,Safari,IE等)测试您的域。一切都将通过https服务。

NGINX Ingress Controller怎么样? 我已经看到了更好的讨论,因为它更便宜/使用更少的资源并且更灵活。它并不便宜:它需要额外的部署/工作量和服务(GCE L4)。而且您需要进行更多配置。它更灵活吗?是。但是在处理大部分工作时,第一种选择为您提供了一种更重要的灵活性-即让您继续处理更紧迫的事情。