ingress-nginx-helm/faq/index.html

55 lines
38 KiB
HTML
Raw Permalink Normal View History

2024-10-04 11:49:42 +00:00
<!doctype html><html lang=en class=no-js> <head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><link href=https://kubernetes.github.io/ingress-nginx/faq/ rel=canonical><link href=../developer-guide/code-overview/ rel=prev><link rel=icon href=../assets/images/favicon.png><meta name=generator content="mkdocs-1.5.3, mkdocs-material-9.4.5"><title>FAQ - Ingress-Nginx Controller</title><link rel=stylesheet href=../assets/stylesheets/main.6a10b989.min.css><link rel=stylesheet href=../assets/stylesheets/palette.356b1318.min.css><link rel=preconnect href=https://fonts.gstatic.com crossorigin><link rel=stylesheet href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback"><style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style><link rel=stylesheet href=../extra.css><script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script></head> <body dir=ltr data-md-color-scheme=default data-md-color-primary=teal data-md-color-accent=green> <input class=md-toggle data-md-toggle=drawer type=checkbox id=__drawer autocomplete=off> <input class=md-toggle data-md-toggle=search type=checkbox id=__search autocomplete=off> <label class=md-overlay for=__drawer></label> <div data-md-component=skip> <a href=#faq class=md-skip> Skip to content </a> </div> <div data-md-component=announce> </div> <header class="md-header md-header--shadow md-header--lifted" data-md-component=header> <nav class="md-header__inner md-grid" aria-label=Header> <a href=.. title="Ingress-Nginx Controller" class="md-header__button md-logo" aria-label="Ingress-Nginx Controller" data-md-component=logo> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"/></svg> </a> <label class="md-header__button md-icon" for=__drawer> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"/></svg> </label> <div class=md-header__title data-md-component=header-title> <div class=md-header__ellipsis> <div class=md-header__topic> <span class=md-ellipsis> Ingress-Nginx Controller </span> </div> <div class=md-header__topic data-md-component=header-topic> <span class=md-ellipsis> FAQ </span> </div> </div> </div> <label class="md-header__button md-icon" for=__search> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg> </label> <div class=md-search data-md-component=search role=dialog> <label class=md-search__overlay for=__search></label> <div class=md-search__inner role=search> <form class=md-search__form name=search> <input type=text class=md-search__input name=query aria-label=Search placeholder=Search autocapitalize=off autocorrect=off autocomplete=off spellcheck=false data-md-component=search-query required> <label class="md-search__icon md-icon" for=__search> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg> </label> <nav class=md-search__options aria-label=Search> <button type=reset class="md-search__icon md-icon" title=Clear aria-label=Clear tabindex=-1> <svg xmlns=http://www.w3.org/2000/svg view
2024-05-29 07:42:30 +00:00
</code></pre></div> <ul> <li>Use Helm to install the additional instance of the ingress controller</li> <li>Ensure you have Helm working (refer to the <a href=https://helm.sh/docs/ >Helm documentation</a>)</li> <li>We have to assume that you have the helm repo for the ingress-nginx controller already added to your Helm config. But, if you have not added the helm repo then you can do this to add the repo to your helm config;</li> </ul> <div class=highlight><pre><span></span><code>helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
</code></pre></div> <ul> <li>Make sure you have updated the helm repo data;</li> </ul> <div class=highlight><pre><span></span><code>helm repo update
</code></pre></div> <ul> <li>Now, install an additional instance of the ingress-nginx controller like this:</li> </ul> <div class=highlight><pre><span></span><code>helm install ingress-nginx-2 ingress-nginx/ingress-nginx \
--namespace ingress-nginx-2 \
--set controller.ingressClassResource.name=nginx-two \
--set controller.ingressClass=nginx-two \
--set controller.ingressClassResource.controllerValue=&quot;example.com/ingress-nginx-2&quot; \
--set controller.ingressClassResource.enabled=true \
--set controller.ingressClassByName=true
</code></pre></div> <p>If you need to install yet another instance, then repeat the procedure to create a new namespace, change the values such as names &amp; namespaces (for example from "-2" to "-3"), or anything else that meets your needs.</p> <p>Note that <code>controller.ingressClassResource.name</code> and <code>controller.ingressClass</code> have to be set correctly. The first is to create the IngressClass object and the other is to modify the deployment of the actual ingress controller pod.</p> <h3 id=i-cant-use-multiple-namespaces-what-should-i-do>I can't use multiple namespaces, what should I do?<a class=headerlink href=#i-cant-use-multiple-namespaces-what-should-i-do title="Permanent link"></a></h3> <p>If you need to install all instances in the same namespace, then you need to specify a different <strong>election id</strong>, like this:</p> <div class=highlight><pre><span></span><code>helm install ingress-nginx-2 ingress-nginx/ingress-nginx \
--namespace kube-system \
--set controller.electionID=nginx-two-leader \
--set controller.ingressClassResource.name=nginx-two \
--set controller.ingressClass=nginx-two \
--set controller.ingressClassResource.controllerValue=&quot;example.com/ingress-nginx-2&quot; \
--set controller.ingressClassResource.enabled=true \
--set controller.ingressClassByName=true
2024-07-21 16:40:28 +00:00
</code></pre></div> <h2 id=retaining-client-ipaddress>Retaining Client IPAddress<a class=headerlink href=#retaining-client-ipaddress title="Permanent link"></a></h2> <p>Question - How to obtain the real-client-ipaddress ?</p> <p>The goto solution for retaining the real-client IPaddress is to enable PROXY protocol.</p> <p>Enabling PROXY protocol has to be done on both, the Ingress NGINX controller, as well as the L4 load balancer, in front of the controller.</p> <p>The real-client IP address is lost by default, when traffic is forwarded over the network. But enabling PROXY protocol ensures that the connection details are retained and hence the real-client IP address doesn't get lost.</p> <p>Enabling proxy-protocol on the controller is documented <a href=https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#use-proxy-protocol>here</a> .</p> <p>For enabling proxy-protocol on the LoadBalancer, please refer to the documentation of your infrastructure provider because that is where the LB is provisioned.</p> <p>Some more info available <a href=https://kubernetes.github.io/ingress-nginx/user-guide/miscellaneous/#source-ip-address>here</a></p> <p>Some more info on proxy-protocol is <a href=https://kubernetes.github.io/ingress-nginx/user-guide/miscellaneous/#proxy-protocol>here</a></p> <h3 id=client-ipaddress-on-single-node-cluster>client-ipaddress on single-node cluster<a class=headerlink href=#client-ipaddress-on-single-node-cluster title="Permanent link"></a></h3> <p>Single node clusters are created for dev &amp; test uses with tools like "kind" or "minikube". A trick to simulate a real use network with these clusters (kind or minikube) is to install Metallb and configure the ipaddress of the kind container or the minikube vm/container, as the starting and ending of the pool for Metallb in L2 mode. Then the host ip becomes a real client ipaddress, for curl requests sent from the host.</p> <p>After installing ingress-nginx controller on a kind or a minikube cluster with helm, you can configure it for real-client-ip with a simple change to the service that ingress-nginx controller creates. The service object of --type LoadBalancer has a field service.spec.externalTrafficPolicy. If you set the value of this field to "Local" then the real-ipaddress of a client is visible to the controller.</p> <div class=highlight><pre><span></span><code>% kubectl explain service.spec.externalTrafficPolicy
KIND: Service
VERSION: v1
FIELD: externalTrafficPolicy &lt;string&gt;
DESCRIPTION:
externalTrafficPolicy describes how nodes distribute service traffic they
receive on one of the Service&#39;s &quot;externally-facing&quot; addresses (NodePorts,
ExternalIPs, and LoadBalancer IPs). If set to &quot;Local&quot;, the proxy will
configure the service in a way that assumes that external load balancers
will take care of balancing the service traffic between nodes, and so each
node will deliver traffic only to the node-local endpoints of the service,
without masquerading the client source IP. (Traffic mistakenly sent to a
node with no endpoints will be dropped.) The default value, &quot;Cluster&quot;, uses
the standard behavior of routing to all endpoints evenly (possibly modified
by topology and other features). Note that traffic sent to an External IP or
LoadBalancer IP from within the cluster will always get &quot;Cluster&quot; semantics,
but clients sending to a NodePort from within the cluster may need to take
traffic policy into account when picking a node.
Possible enum values:
- `&quot;Cluster&quot;` routes traffic to all endpoints.
- `&quot;Local&quot;` preserves the source IP of the traffic by routing only to
endpoints on the same node as the traffic was received on (dropping the
traffic if there are no local endpoints).
</code></pre></div> <h3 id=client-ipaddress-l7>client-ipaddress L7<a class=headerlink href=#client-ipaddress-l7 title="Permanent link"></a></h3> <p>The solution is to get the real client IPaddress from the <a href=https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For>"X-Forward-For" HTTP header</a></p> <p>Example : If your application pod behind Ingress NGINX controller, uses the NGINX webserver and the reverseproxy inside it, then you can do the following to preserve the remote client IP.</p> <ul> <li> <p>First you need to make sure that the X-Forwarded-For header reaches the backend pod. This is done by using a Ingress NGINX conftroller ConfigMap key. Its documented <a href=https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#use-forwarded-headers>here</a></p> </li> <li> <p>Next, edit <code>nginx.conf</code> file inside your app pod, to contain the directives shown below:</p> </li> </ul> <div class=highlight><pre><span></span><code>set_real_ip_from 0.0.0.0/0; # Trust all IPs (use your VPC CIDR block in production)
real_ip_header X-Forwarded-For;
real_ip_recursive on;
log_format main &#39;$remote_addr - $remote_user [$time_local] &quot;$request&quot; &#39;
&#39;$status $body_bytes_sent &quot;$http_referer&quot; &#39;
&#39;&quot;$http_user_agent&quot; &#39;
&#39;host=$host x-forwarded-for=$http_x_forwarded_for&#39;;
access_log /var/log/nginx/access.log main;
2025-02-03 12:03:43 +00:00
</code></pre></div> <h2 id=kubernetes-v122-migration>Kubernetes v1.22 Migration<a class=headerlink href=#kubernetes-v122-migration title="Permanent link"></a></h2> <p>If you are using Ingress objects in your cluster (running Kubernetes older than version 1.22), and you plan to upgrade your Kubernetes version to K8S 1.22 or above, then please read <a href=../user-guide/k8s-122-migration/ >the migration guide here</a>.</p> <h2 id=validation-of-path>Validation Of <strong><code>path</code></strong><a class=headerlink href=#validation-of-path title="Permanent link"></a></h2> <ul> <li> <p>For improving security and also following desired standards on Kubernetes API spec, the next release, scheduled for v1.8.0, will include a new &amp; optional feature of validating the value for the key <code>ingress.spec.rules.http.paths.path</code>.</p> </li> <li> <p>This behavior will be disabled by default on the 1.8.0 release and enabled by default on the next breaking change release, set for 2.0.0.</p> </li> <li> <p>When "<code>ingress.spec.rules.http.pathType=Exact</code>" or "<code>pathType=Prefix</code>", this validation will limit the characters accepted on the field "<code>ingress.spec.rules.http.paths.path</code>", to "<code>alphanumeric characters</code>", and "<code>/</code>", "<code>_</code>", "<code>-</code>". Also, in this case, the path should start with "<code>/</code>".</p> </li> <li> <p>When the ingress resource path contains other characters (like on rewrite configurations), the pathType value should be "<code>ImplementationSpecific</code>".</p> </li> <li> <p>API Spec on pathType is documented <a href=https://kubernetes.io/docs/concepts/services-networking/ingress/#path-types>here</a></p> </li> <li> <p>When this option is enabled, the validation will happen on the Admission Webhook. So if any new ingress object contains characters other than alphanumeric characters, and, "<code>/</code>", "<code>_</code>", "<code>-</code>", in the <code>path</code> field, but is not using <code>pathType</code> value as <code>ImplementationSpecific</code>, then the ingress object will be denied admission.</p> </li> <li> <p>The cluster admin should establish validation rules using mechanisms like "<code>Open Policy Agent</code>", to validate that only authorized users can use ImplementationSpecific pathType and that only the authorized characters can be used. <a href=https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#strict-validate-path-type>The configmap value is here</a></p> </li> <li> <p>A complete example of an Openpolicyagent gatekeeper rule is available <a href=https://kubernetes.github.io/ingress-nginx/examples/openpolicyagent/ >here</a></p> </li> <li> <p>If you have any issues or concerns, please do one of the following:</p> </li> <li>Open a GitHub issue</li> <li>Comment in our Dev Slack Channel</li> <li>Open a thread in our Google Group <a href=mailto:ingress-nginx-dev@kubernetes.io>&#105;&#110;&#103;&#114;&#101;&#115;&#115;&#45;&#110;&#103;&#105;&#110;&#120;&#45;&#100;&#101;&#118;&#64;&#107;&#117;&#98;&#101;&#114;&#110;&#101;&#116;&#101;&#115;&#46;&#105;&#111;</a></li> </ul> <h2 id=why-is-chunking-not-working-since-controller-v110>Why is chunking not working since controller v1.10 ?<a class=headerlink href=#why-is-chunking-not-working-since-controller-v110 title="Permanent link"></a></h2> <ul> <li> <p>If your code is setting the HTTP header <code>"Transfer-Encoding: chunked"</code> and the controller log messages show an error about duplicate header, it is because of this change <a href=http://hg.nginx.org/nginx/rev/2bf7792c262e>http://hg.nginx.org/nginx/rev/2bf7792c262e</a></p> </li> <li> <p>More details are available in this issue <a href=https://github.com/kubernetes/ingress-nginx/issues/11162>https://github.com/kubernetes/ingress-nginx/issues/11162</a></p> </li> </ul> </article> </div> </div> </main> <footer class=md-footer> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> Made with <a href=https://squidfunk.github.io/mkdoc