<p>I know this is topic that comes up every once in a while. I did read many of the existing posts and answers, bit wasn't able to figure it out.</p>
<p>What I need is nginx-ingress to redirect from <code>www.foo.bar</code> to just <code>foo.bar</code>. I set up a test environment on Minikube by installing the nginx ingress the minikube way: <code>minikube addons enable ingress</code> and put the following ingress manifest in place:</p>
<pre><code>apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.allow-http: &quot;false&quot;
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/configuration-snippet: |
      if ($host = 'www.foo.bar') {
        return 301 https://foo.bar;
      }
    nginx.ingress.kubernetes.io/proxy-body-size: 600m
    nginx.ingress.kubernetes.io/ssl-redirect: &quot;true&quot;
    nginx.org/client-max-body-size: 600m
  name: foo-ingress
spec:
  rules:
  - host: api.foo.bar
    http:
      paths:
      - backend:
          service:
            name: identity
            port:
              number: 80
        path: /identity
        pathType: ImplementationSpecific
      - backend:
          service:
            name: catalog
            port:
              number: 80
        path: /catalog
        pathType: ImplementationSpecific
      - backend:
          service:
            name: marketing
            port:
              number: 80
        path: /marketing
        pathType: ImplementationSpecific
      - backend:
          service:
            name: marketplace
            port:
              number: 80
        path: /marketplace
        pathType: ImplementationSpecific
      - backend:
          service:
            name: notification
            port:
              number: 80
        path: /notification
        pathType: ImplementationSpecific
      - backend:
          service:
            name: provider
            port:
              number: 80
        path: /provider
        pathType: ImplementationSpecific
  - host: www.foo.bar
    http:
      paths:
      - backend:
          service:
            name: frontend
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific
  - host: foo.bar
    http:
      paths:
      - backend:
          service:
            name: frontend
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific
  - host: blog.foo.bar
    http:
      paths:
      - backend:
          service:
            name: wordpress
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific
  tls:
  - hosts:
    - foo.bar
    - api.foo.bar
    - blog.foo.bar
    secretName: foo-cert
</code></pre>
<p>And it works:</p>
<pre><code>➜  ~ curl -k -v -o /dev/null https://www.foo.bar
  ...
&gt; GET / HTTP/2
&gt; Host: www.foo.bar
&gt; user-agent: curl/7.68.0
&gt; accept: */*
&gt; 
&lt; HTTP/2 301 
&lt; date: Sat, 27 Mar 2021 16:37:50 GMT
&lt; content-type: text/html
&lt; content-length: 162
&lt; location: https://foo.bar
</code></pre>
<p>Now, let me get to the problem: I have a production cluster on GCP (GKE) on which I installed nginx-ingress via Helm:</p>
<pre><code>helm -n nginx-ingress ls
NAME            NAMESPACE       REVISION    UPDATED                                 STATUS      CHART               APP VERSION
nginx-ingress   nginx-ingress   2           2021-03-27 15:05:41.229254628 +0000 UTC deployed    nginx-ingress-0.8.1 1.10.1  
</code></pre>
<p>The Ingress manifest I have is (I don't see a relevant difference to the one above):</p>
<pre><code>apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.allow-http: &quot;false&quot;
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/configuration-snippet: |
      if ($host = 'www.foo.bar') {
        return 301 https://foo.bar;
      }
    nginx.ingress.kubernetes.io/proxy-body-size: 600m
    nginx.ingress.kubernetes.io/ssl-redirect: &quot;true&quot;
    nginx.org/client-max-body-size: 600m
  name: foo-ingress
spec:
  rules:
  - host: api.foo.bar
    http:
      paths:
      - backend:
          service:
            name: identity
            port:
              number: 80
        path: /identity
        pathType: ImplementationSpecific
      - backend:
          service:
            name: catalog
            port:
              number: 80
        path: /catalog
        pathType: ImplementationSpecific
      - backend:
          service:
            name: marketing
            port:
              number: 80
        path: /marketing
        pathType: ImplementationSpecific
      - backend:
          service:
            name: marketplace
            port:
              number: 80
        path: /marketplace
        pathType: ImplementationSpecific
      - backend:
          service:
            name: notification
            port:
              number: 80
        path: /notification
        pathType: ImplementationSpecific
      - backend:
          service:
            name: provider
            port:
              number: 80
        path: /provider
        pathType: ImplementationSpecific
  - host: foo.bar
    http:
      paths:
      - backend:
          service:
            name: frontend
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific
  - host: www.foo.bar
    http:
      paths:
      - backend:
          service:
            name: frontend
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific
  - host: blog.foo.bar
    http:
      paths:
      - backend:
          service:
            name: wordpress
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific
  tls:
  - hosts:
    - foo.bar
    - api.foo.bar
    - www.foo.bar
    - blog.foo.bar
    secretName: foo-cert
</code></pre>
<p>You can see, the redirect is not working:</p>
<pre><code>➜  ~ curl -v -o /dev/null https://www.foo.bar
&gt; GET / HTTP/1.1
&gt; Host: www.foo.bar
&gt; User-Agent: curl/7.68.0
&gt; Accept: */*
&gt; 
&lt; HTTP/1.1 200 OK
&lt; Server: nginx/1.19.8
&lt; Date: Sat, 27 Mar 2021 16:42:18 GMT
&lt; Content-Type: text/html
&lt; Content-Length: 671097
&lt; Connection: keep-alive
&lt; Last-Modified: Tue, 09 Mar 2021 11:51:47 GMT
&lt; ETag: &quot;60476153-a3d79&quot;
&lt; Expires: Thu, 01 Jan 1970 00:00:01 GMT
&lt; Cache-Control: no-cache
&lt; Accept-Ranges: bytes
</code></pre>
<p>I noticed, that prod and Minikube deploy different images but don't really know what the difference is if there's any.</p>
<p>Prod:</p>
<pre><code>➜  ~ kubectl -n nginx-ingress get pod nginx-ingress-nginx-ingress-68f5bc7654-kffnm -o json | jq &quot;.spec.containers[0].image&quot;
&quot;nginx/nginx-ingress:1.10.1&quot;
</code></pre>
<p>Minikube:</p>
<pre><code>➜  ~ kubectl -n kube-system get pod ingress-nginx-controller-65cf89dc4f-xkdtn -o json | jq &quot;.spec.containers[0].image&quot;
&quot;us.gcr.io/k8s-artifacts-prod/ingress-nginx/controller:v0.40.2@sha256:46ba23c3fbaafd9e5bd01ea85b2f921d9f2217be082580edc22e6c704a83f02f&quot;
</code></pre>
<p>Any ideas what's going on?</p>

<p>The reason this is happening is that you've deploy different version of the nginx ingress controller called <code>nginxinc</code>into your GKE cluster. This is very common mistake made especially if you use helm you don't really check which you are deploying.</p>
<p>So <a href="https://github.com/kubernetes/ingress-nginx" rel="nofollow noreferrer">kubernetes/ingress-nginx</a> which you used in minikube is maintained by the Kubernetes open source community and the <a href="https://github.com/nginxinc/kubernetes-ingress" rel="nofollow noreferrer">nginxinc/kubernetes-ingress</a> is maintained by NGINX, Inc. You will notice many cases where the one maintained by Kubernetes will be commonly called community Ingress controller and second one NGINX's.</p>
<p>You can find the differences <a href="https://github.com/nginxinc/kubernetes-ingress/blob/master/docs/nginx-ingress-controllers.md#the-key-differences" rel="nofollow noreferrer">here</a> but main one that is causing you problems is that they both use differences annotation formula with different prefix. For example:</p>
<ul>
<li>Community ingress controller uses:  <code>nginx.ingress.kubernetes.io/server-snippet</code></li>
<li>NGINX's uses: <code>nginx.org/server-snippets</code></li>
</ul>
