How to remove the server header from Kubernetes deployed applications - kubernetes

I am asking this question in the style of question then answer.
If you create your Ingress objects for Helm charts or regular "kubectl apply" deployments, after deployment to your cluster, you might see the server header in your responses. This is regarded as a security concern. It should not be present.
You might not have control of your cluster or Ingress Controllers. How can you remove the header in question?

You might not have control of your cluster or Ingress Controllers, but you do have control of your Ingress manifests.
In each of your Ingress manifest files (maybe inside your Helm charts) you can update your Ingress definition(s).
apiVersion: networking.k8s.io/v1beta1 # for versions before 1.14 use extensions/v1beta1
kind: Ingress
metadata:
name: {{ .Release.Name}}-{{ .Values.baseName }}-ingress-spa
namespace: {{ .Values.global.config.namespace }}
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/configuration-snippet: |
more_clear_headers "Server";
spec:
tls:
- hosts:
The key part is:
nginx.ingress.kubernetes.io/configuration-snippet: |
more_clear_headers "Server";
This instructs nginx to clear the server header. After redeploying your application you should now see:
And voila, the server header is gone.

You can do this for the whole nginx ingress controller in the settings ConfigMap:
server-tokens: "false"

Related

Nginx Ingress returns 413 Entity Too Large

on my Cluster, I'm trying to upload a big file but when I try, I get the 413 Error
error parsing HTTP 413 response body: invalid character '<' looking for beginning of value: "<html>\r\n<head><title>413 Request Entity Too Large</title></head>\r\n<body>\r\n<center><h1>413 Request Entity Too Large</h1></center>\r\n<hr><center>nginx/1.19.3</center>\r\n</body>\r\n</html>\r\n"
I know that this is caused by a default parameter of nginx and I need to override it. On the documentation I've found that this can be done using two ways:
using annotation on ingress config
using a configMap
I have tried both ways with no result.
Here are my yaml:
ingress.yml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/proxy-body-size: "700m"
name: nginx-ingress
spec:
rules:
- host: example.com
http:
paths:
- backend:
serviceName: nginx-service
servicePort: 80
path: /
and configmap.yml:
apiVersion: v1
data:
proxy-body-size: "800m"
kind: ConfigMap
metadata:
name: ingress-nginx-controller
labels:
app.kubernetes.io/name: nginx-ingress
app.kubernetes.io/part-of: nginx-ingress
For future searchs, It works for me:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "0"
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
name: docker-registry
namespace: docker-registry
spec:
For NGINX, an 413 error will be returned to the client when the size in a request exceeds the maximum allowed size of the client request body. This size can be configured by the parameter
To configure this setting globally for all Ingress rules, the proxy-body-size value may be set in the NGINX ConfigMap. To use custom values in an Ingress rule define these annotation:
nginx.ingress.kubernetes.io/proxy-body-size: 8m
https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#custom-max-body-size
for node.js you might set
app.use(express.json({ limit: '50mb' }));
app.use(express.urlencoded({ limit: '50mb' }));
I was with the same problem using Nginx Ingress on GKE.
These are the annotations that worked for me:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.org/client-max-body-size: "0"
nginx.org/proxy-connect-timeout: 600s
nginx.org/proxy-read-timeout: 600s
Don't forget to put the correct values for you.
For more details you can see these docs:
Using Annotations
Client Max Body Size
PS I've installed my "Nginx Ingress Controller" following this tutorial.
There are some good answers here already to avoid that 413.
As for example editing the Ingress (better redeploying) with the following annotations:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "0"
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
Furthermore, for NGINX an 413 error will be returned to the client when the size in a request exceeds the maximum allowed size of the client request body. This size can be configured by the parameter client_max_body_size reference.
There are few things to have in mind while setting this up:
It is better to recreate the Ingress object rather than edit it to make sure that the configuration will be loaded correctly. Delete the Ingress and recreate it again with the proper annotations.
If that's still not working you can try to use the ConfigMap approach, for example:
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx
namespace: ingress-nginx
labels:
app: ingress-nginx
data:
proxy-body-size: "8m"
Notice that setting size to 0 disables checking of client request body size.
Remember to set the value greater than the size of data that you are trying to push.
Use the proper apiVersion based on your Kubernetes version. Notice that:
The extensions/v1beta1 and networking.k8s.io/v1beta1 API versions
of Ingress will no longer be served in v1.22.
Migrate manifests and API clients to use the networking.k8s.io/v1 API version, available since v1.19.
All existing persisted objects are accessible via the new API
Below configurations worked out for me:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: cs-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/proxy-body-size: 16m
reference: https://github.com/kubernetes/ingress-nginx/issues/4825
Maybe my experience will help somebody. All my settings were Ok in nginx, but nginx stood behind CloudFlare in Proxy mode. So try to set it to "DNS only" in order to make sure there is nothing between you and nginx.

Ingress controller name for the ingress class

I am setting up my ingress controller, ingress class and ingress to expose a service outside the cluster. This is fresh cluster setup.
I have setup the nginx-ingress controller using
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.41.0/deploy/static/provider/baremetal/deploy.yaml
The next step based on my understanding is to create the ingress class https://v1-18.docs.kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class
apiVersion: networking.k8s.io/v1beta1
kind: IngressClass
metadata:
name: external-lb
spec:
controller: example.com/ingress-controller
parameters:
apiGroup: k8s.example.com/v1alpha
kind: IngressParameters
name: external-lb
How did they get the name of the controller example.com/ingress-controller?
I have run multiple scenarios with IngressClass, Ingress and Nginx Ingress Controller.
Scenario 1
IngressClass with custom name
Nginx Ingress Controller with default --ingress-class value which is nginx
Ingress using ingressClassName same as IngressClass name
Output: Response 404
Scenario 2
IngressClass with custom name
Nginx Ingress Controller with owningress-class ingress-test
Ingress using ingressClassName same as IngressClass name
Output: Response 404
Scenario 3
IngressClass with test name
Nginx Ingress Controller --ingress-class with value test
Ingress using test in ingressClassName
Output: Proper response
Senario 4
IngressClass with nginx name
Nginx Ingress Controller --ingress-class with value nginx
Ingress using nginx in ingressClassName
Output: Proper response
Conclusion
First of all, please keep in mind that there are 3 types of Nginx. Open Source Nginx Ingress Controller, you are probably using it. Nginx Incorporaton (nginx inc) and Nginx Incorporaton Plus.
In one of the scenarios, when I have used spec.controller: nginx.org/ingress-controller with Nginx Ingress Controller with argument --ingress-class=nginx, in Nginx Ingress Controller pod you will see entry which is pointing to k8s.io/ingress-nginx.
To reproduce this behavior, you will need to deploy IngressClass with specific controller and then deploy nginx.
apiVersion: networking.k8s.io/v1beta1
kind: IngressClass
metadata:
name: nginx
spec:
controller: nginx.org/ingress-controller
After deploying Nginx Ingress Controller, controller pod will be in CrashLoopBackOff state. In logs you will find entry:
E1118 15:42:19.008911 8 main.go:134] Invalid IngressClass (Spec.Controller) value "nginx.org/ingress-controller". Should be "k8s.io/ingress-nginx"
It works only when IngressClass name is set to nginx.
I would say that nginx.org/ingress-controller is for Nginx Incorporated and k8s.io/ingress-nginx for Open Source Nginx Ingress.
If custom value is used for --ingress-class argument in the controller Deployment manifest, presence or absence of IngressClass object with the same name doesn't made any difference in, how the cluster works, if only you keep Ingress spec.ingressClass value the same with controller argument. Moreover, if it's present, IngressClass spec.controller can have any value that match the required pattern "domain like" and that didn't affect Ingress workflow behavior on my cluster at all.
In addition, Ingress works fine if I put the correct value of the ingress-class either to spec.ingressClass property or to metadata.annotation.kubernetes.io/ingress.class accordingly. It gives an error like the following if you try to put both values to the same Ingres object:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: test-ingress
annotations:
kubernetes.io/ingress.class: nginx
spec:
ingressClassName: nginx
The Ingress "test-ingress" is invalid: annotations.kubernetes.io/ingress.class: Invalid value: "nginx": can not be set when the class field is also set
Please keep in mind it was tested only for Nginx Ingress Controlle. If you would like to use IngressClass with other Ingress Controllers like Traefik or Ambasador, you would check their release notes.
You will create the IngressClass as part of the Installation with Manifests steps (Step 3 here). That will create an IngressClass that looks like:
apiVersion: networking.k8s.io/v1beta1
kind: IngressClass
metadata:
name: nginx
# annotations:
# ingressclass.kubernetes.io/is-default-class: "true"
spec:
controller: nginx.org/ingress-controller
Then, to configure an Ingress resource to be consumed by nginx, just specify ingressClassName: nginx in the Ingress spec, as shown here, and pasted again below:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: cafe-ingress
spec:
ingressClassName: nginx
tls:
- hosts:
- cafe.example.com
secretName: cafe-secret
rules:
- host: cafe.example.com
. . .

How to set max request body size in traefik ingress controller for kubernetes?

It's very easy to set up max request body size with nginx using client_max_body_size directive. How can I do the same with kubernetes traefik ingress controller. I know there is maxrequestbodybytes directive to do so but, I'm lost with how to set it up in yaml file describing my ingress.
Wasn't so easy to figure this out. There is a funky multiline way of specifying this config in yaml file. Please check option traefik.ingress.kubernetes.io/buffering to see he pipe (|) oprator in acction.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: example
labels:
domain: example.com
deployment: production
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/frontend-entry-points: http
traefik.ingress.kubernetes.io/buffering: |
maxrequestbodybytes: 31457280
memrequestbodybytes: 62914560
spec:
etc....

Kong Ingress Controller has no effect on Kong Plugins

I have gone through kong-ingress-controller deployment and getting started doc and done everything mentioned.
Update User Permissions
Deploy Kong Ingress Controller
Setup environment variables
Created Ingress with Routes
Everything works fine, I can access my applications based on the routes. But when I added rate-limit plugins or any other plugins it does not take any effect.
ingress.yaml :
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress
namespace: default
annotations:
kubernetes.io/ingress.class: kong
plugins.konghq.com: http-ratelimit, http-auth
spec:
rules:
- host: foo.bar
http:
paths:
- path: /users
backend:
serviceName: my-service
servicePort: 80
rate-limit.yaml :
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: http-ratelimit
labels:
global: 'true'
config:
minute: 5
plugin: rate-limiting
But the rate limit plugin has no effect on my ingress.
NB: The kong-ingress-controller is in kong namespace but the other resources are in default namespace. I tried to move everything to kong namespace then the plugins works but service does not work as it is in default namespace.
Thanks in advance.
Looking at the Kong docs, the rate-limit YAML looks correct. If the resource is configured correctly, Kong is not matching the request against the ingress resource because the user is not sending the correct request.
KongPlugin, KongIngress should be in same namespace as Service. YAML provides looks correct.
There must be something wrong in ingress yamls annotation and configuration.Is your service annotated with Ingress object?
I think you need to add this annotation to your KongPlugin:
annotations:
kubernetes.io/ingress.class: kong
So try with
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: http-ratelimit
annotations:
kubernetes.io/ingress.class: kong
[...]
In my scenario, I wanted to apply the KongPlugin on a specific Ingress Resource/Route.
What worked for me was to create the KongPlugin object in the same namespace where the Ingress Resource (and therefore, the target service) lived.

kubernetes v1.1 baremetal => how to connect ingress to outside world

I have a setup of kubernetes on a coreos baremetal.
For now I did the connection from outside world to service with a nginx reverse-proxy.
I'm trying the new Ingress resource.
for now I have added a simple ingress:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: kube-ui
spec:
backend:
serviceName: kube-ui
servicePort: 80
that starts like this:
INGRESS
NAME RULE BACKEND ADDRESS
kube-ui - kube-ui:80
My question is how to connect from the outside internet to that ingress point as this resource have no ADDRESS ... ?
POSTing this to the API server will have no effect if you have not configured an Ingress controller. You need to choose the ingress controller implementation that is the best fit for your cluster, or implement one. Examples and instructions can be found here.
check this gist
This is for the ingress-nginx, not kubernetes-ingress
Pre-requirement
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
Exposing hostNetwork (hope you know what you are doing. As documented, other than this, you can use nodePort or loadbalancer.)
kubectl edit deployment.apps/nginx-ingress-controller -n ingress-nginx
add
template:
spec:
hostNetwork: true
port forwarding
apiVersion: v1
kind: ConfigMap
metadata:
name: tcp-services
namespace: ingress-nginx
data:
9000: "default/example-go:8080"
Also, you can use ingress object to expose the service