Compare languages | The ingress-nginx module: FAQ

How do I limit access to the application in the cluster to Ingress controllers only?

Как разрешить доступ к приложению внутри кластера только от Ingress-контроллера?

If you need to limit access to your application inside the cluster exclusively from Ingress Pods, you should add a kube-rbac-proxy container to the application Pod as shown in the example below:

Если необходимо ограничить доступ к вашему приложению внутри кластера исключительно от подов Ingress-контроллера, необходимо в под с приложением добавить контейнер с kube-rbac-proxy, как показано в примере ниже:

yaml apiVersion: apps/v1 kind: Deployment metadata: name: my-app namespace: my-namespace spec: selector: matchLabels: app: my-app replicas: 1 template: metadata: labels: app: my-app spec: serviceAccountName: my-sa containers:

  • name: my-cool-app image: mycompany/my-app:v0.5.3 args:
  • ”–listen=127.0.0.1:8080” livenessProbe: httpGet: path: /healthz port: 443 scheme: HTTPS
  • name: kube-rbac-proxy image: flant/kube-rbac-proxy:v0.1.0 It is recommended to use a proxy from Deckhouse repository. args:
  • ”–secure-listen-address=0.0.0.0:443”
  • ”–config-file=/etc/kube-rbac-proxy/config-file.yaml”
  • ”–v=2”
  • ”–logtostderr=true” The user authentication and authorization are not possible if the kube-apiserver is not available. Stale Cache stores the results of successful authorization and is used only if the apiserver is not available.
  • ”–stale-cache-interval=1h30m” ports:
  • containerPort: 443 name: https volumeMounts:
  • name: kube-rbac-proxy mountPath: /etc/kube-rbac-proxy volumes:
  • name: kube-rbac-proxy configMap: name: kube-rbac-proxy

yaml apiVersion: apps/v1 kind: Deployment metadata: name: my-app namespace: my-namespace spec: selector: matchLabels: app: my-app replicas: 1 template: metadata: labels: app: my-app spec: serviceAccountName: my-sa containers:

  • name: my-cool-app image: mycompany/my-app:v0.5.3 args:
  • ”–listen=127.0.0.1:8080” livenessProbe: httpGet: path: /healthz port: 443 scheme: HTTPS
  • name: kube-rbac-proxy image: flant/kube-rbac-proxy:v0.1.0 Рекомендуется использовать прокси из репозитория Deckhouse. args:
  • ”–secure-listen-address=0.0.0.0:443”
  • ”–config-file=/etc/kube-rbac-proxy/config-file.yaml”
  • ”–v=2”
  • ”–logtostderr=true” Если kube-apiserver недоступен, аутентификация и авторизация пользователей невозможна. Stale Cache хранит результаты успешной авторизации и используется лишь в случае, если apiserver недоступен.
  • ”–stale-cache-interval=1h30m” ports:
  • containerPort: 443 name: https volumeMounts:
  • name: kube-rbac-proxy mountPath: /etc/kube-rbac-proxy volumes:
  • name: kube-rbac-proxy configMap: name: kube-rbac-proxy

The application only accepts localhost (127.0.0.1) requests. That means that an unsecured connection can only be established to it from within the Pod. At the same time, the proxy listens on 0.0.0.0 and intercepts all external traffic to the Pod.

Приложение принимает запросы на адресе 127.0.0.1, это означает, что по незащищенному соединению к нему можно подключиться только внутри пода. Прокси прослушивает порт на адресе 0.0.0.0 и перехватывает весь внешний трафик к поду.

How do I provide minimum rights to the Service Account?

Как выдать минимальные права для ServiceAccount?

The proxy needs permissions to create TokenReview and SubjectAccessReview to authenticate and authorize users using the kube-apiserver.

Чтобы аутентифицировать и авторизовывать пользователей с помощью kube-apiserver, у прокси должны быть права на создание TokenReview и SubjectAccessReview.

DKP clusters already have a ready-made ClusterRoled8-rbac-proxy, you don’t need to create it yourself! Link it to your Deployment’s ServiceAccount, as shown in the example below.

В кластерах DKP уже есть готовая ClusterRoled8-rbac-proxy, создавать её самостоятельно не требуется! Свяжите её с ServiceAccount вашего Deployment’а, как показано в примере ниже.

yaml

apiVersion: v1 kind: ServiceAccount metadata: name: my-sa namespace: my-namespace — apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: my-namespace:my-sa:d8-rbac-proxy roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: d8:rbac-proxy subjects:

  • kind: ServiceAccount name: my-sa namespace: my-namespace

yaml

apiVersion: v1 kind: ServiceAccount metadata: name: my-sa namespace: my-namespace — apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: my-namespace:my-sa:d8-rbac-proxy roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: d8:rbac-proxy subjects:

  • kind: ServiceAccount name: my-sa namespace: my-namespace

The Kube-RBAC-Proxy configuration

Конфигурация Kube-RBAC-Proxy

yaml apiVersion: v1 kind: ConfigMap metadata: name: kube-rbac-proxy data: config-file.yaml: |+ excludePaths:

  • /healthz No authorization for liveness probes is required. upstreams:
  • upstream: http://127.0.0.1:8081/ The destination address path: / The path to the proxy to forward requests to the upstream. authorization: resourceAttributes: namespace: my-namespace apiGroup: apps apiVersion: v1 resource: deployments subresource: http name: my-app

yaml apiVersion: v1 kind: ConfigMap metadata: name: kube-rbac-proxy data: config-file.yaml: |+ excludePaths:

  • /healthz Не требуем авторизацию для liveness пробы. upstreams:
  • upstream: http://127.0.0.1:8081/ Адрес upstream-сервиса, на который будет перенаправлен входящий трафик. path: / Путь, обрабатываемый прокси, по которому принимаются запросы и перенаправляются на upstream. authorization: resourceAttributes: namespace: my-namespace apiGroup: apps apiVersion: v1 resource: deployments subresource: http name: my-app

According to the configuration, the user must have access to the my-app Deployment and its http subresource in the my-namespace namespace.

Such permissions have the following RBAC form:

Согласно конфигурации, у пользователя должны быть права доступа к Deployment с именем my-app и его дополнительному ресурсу http в пространстве имён my-namespace.

yaml

apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: kube-rbac-proxy:my-app namespace: my-namespace rules:

  • apiGroups: [“apps”] resources: [“deployments/http”] resourceNames: [“my-app”] verbs: [“get”, “create”, “update”, “patch”, “delete”] — apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: kube-rbac-proxy:my-app namespace: my-namespace roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: kube-rbac-proxy:my-app subjects:

Выглядят такие права в виде RBAC следующим образом:

All user certificates of Ingress controllers are issued for one specific group.

  • kind: Group name: ingress-nginx:auth

For the Ingress resource, add parameters:

yaml

apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: kube-rbac-proxy:my-app namespace: my-namespace rules:

  • apiGroups: [“apps”] resources: [“deployments/http”] resourceNames: [“my-app”] verbs: [“get”, “create”, “update”, “patch”, “delete”] — apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: kube-rbac-proxy:my-app namespace: my-namespace roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: kube-rbac-proxy:my-app subjects:

yaml nginx.ingress.kubernetes.io/backend-protocol: HTTPS nginx.ingress.kubernetes.io/configuration-snippet: | proxy_ssl_certificate /etc/nginx/ssl/client.crt; proxy_ssl_certificate_key /etc/nginx/ssl/client.key; proxy_ssl_protocols TLSv1.2; proxy_ssl_session_reuse on;

Все пользовательские сертификаты ingress-контроллеров выписаны для одной конкретной группы.

  • kind: Group name: ingress-nginx:auth

Here you can read more about how certificate authentication works.

Для Ingress-ресурса добавьте параметры:

How do I configure an external load balancer to check if IngressNginxController is available?

yaml nginx.ingress.kubernetes.io/backend-protocol: HTTPS nginx.ingress.kubernetes.io/configuration-snippet: | proxy_ssl_certificate /etc/nginx/ssl/client.crt; proxy_ssl_certificate_key /etc/nginx/ssl/client.key; proxy_ssl_protocols TLSv1.2; proxy_ssl_session_reuse on;

In case an IngressNginxController is deployed behind a load balancer, it is advisable to configure your load balancer so that it would check the availability of the IngressNginxController’s endpoints via a health check mechanism, periodically sending either HTTP-requests or TCP-packets. While it is possible to test the endpoints simply by checking if a relevant TCP port is open, we recommend implementing HTTP checks with the following parameters:

Подробнее о том, как работает аутентификация по сертификатам, можно прочитать в документации Kubernetes.

  • Protocol: HTTP
  • Path: /healthz
  • Port: 80 (or relevant httpPort value in case of using HostPort inlet).

Как сконфигурировать балансировщик нагрузки для проверки доступности IngressNginxController?

How do I configure MetalLB to be accessible from the internal network only?

В ситуации, когда IngressNginxController размещен за балансировщиком нагрузки, рекомендуется сконфигурировать балансировщик для проверки доступности узлов IngressNginxController с помощью HTTP-запросов или TCP-подключений. В то время как тестирование с помощью TCP-подключений представляет собой простой и универсальный механизм проверки доступности, мы рекомендуем использовать проверку на основе HTTP-запросов со следующими параметрами:

Below is an example of a MetalLB config with access from the internal network only:

  • протокол: HTTP;
  • путь: /healthz;
  • порт: 80 (в случае использования инлета HostPort нужно указать номер порта, соответствующий параметру httpPort.

yaml apiVersion: deckhouse.io/v1 kind: IngressNginxController metadata: name: main spec: ingressClass: “nginx” inlet: “LoadBalancer” loadBalancer: sourceRanges:

  • 192.168.0.0/24

Как настроить работу через MetalLB с доступом только из внутренней сети?

The svcSourceRangeCheck parameter should be enabled in cni-cilium module for correct work.

Пример MetalLB с настройками доступа только из внутренней сети:

How to add extra log fields to a nginx-controller?

yaml apiVersion: deckhouse.io/v1 kind: IngressNginxController metadata: name: main spec: ingressClass: “nginx” inlet: “LoadBalancer” loadBalancer: sourceRanges:

  • 192.168.0.0/24

Example of adding extra fields:

Для работы необходимо включить параметр svcSourceRangeCheck в модуле cni-cilium.

yaml apiVersion: deckhouse.io/v1 kind: IngressNginxController metadata: name: main spec: ingressClass: “nginx” inlet: “LoadBalancer” additionalLogFields: my-cookie: “$cookie_MY_COOKIE”

Как добавить дополнительные поля для логирования в nginx-controller?

How to enable HorizontalPodAutoscaling for IngressNginxController?

Пример добавления дополнительных полей:

HPA mode is possible only for controllers with inlet: LoadBalancer or LoadBalancerWithProxyProtocol.

yaml apiVersion: deckhouse.io/v1 kind: IngressNginxController metadata: name: main spec: ingressClass: “nginx” inlet: “LoadBalancer” additionalLogFields: my-cookie: “$cookie_MY_COOKIE”

HPA mode is possible only for minReplicas != maxReplicas otherwise deployment hpa-scaler will not be created.

Как включить HorizontalPodAutoscaling для IngressNginxController?

HPA is set with attributes minReplicas and maxReplicas in a IngressNginxController CR.

Режим HPA возможен только для контроллеров с инлетом LoadBalancer или LoadBalancerWithProxyProtocol.

The IngressNginxController is deployed using DaemonSet. DaemonSet does not provide horizontal scaling capabilities, so hpa-scaler Deployment will be created with the HPA resource, which is observing custom metric prometheus-metrics-adapter-d8-ingress-nginx-cpu-utilization-for-hpa. If CPU utilization exceeds 50%, the HPA-controller scales hpa-scaler Deployment with a new replica (with respect to minReplicas and maxReplicas).

Режим HPA возможен только при minReplicas != maxReplicas, в противном случае deployment hpa-scaler не создается.

hpa-scaler Deployment has HardPodAntiAffinity, and it will order a new Node (inside its NodeGroup), where one more ingress-controller will be set.

Для включения HPA используйте атрибуты minReplicas и maxReplicas в IngressNginxController CR.

Notes:

IngressNginxController разворачивается с помощью DaemonSet. DaemonSet не предоставляет возможности горизонтального масштабирования, поэтому создается дополнительный deployment hpa-scaler и HPA resource, который следит за предварительно созданной метрикой prometheus-metrics-adapter-d8-ingress-nginx-cpu-utilization-for-hpa. Если CPU utilization превысит 50%, HPA закажет новую реплику для hpa-scaler (с учетом minReplicas и maxReplicas).

  • The minimum actual number of IngressNginxController replicas cannot be less than the minimum number of nodes in the node group it is deployed to.
  • The maximum actual number of IngressNginxController replicas cannot be greater than the maximum number of nodes in the node group it is deployed to.

Deployment hpa-scaler обладает HardPodAntiAffinity (запрет на размещение подов с одинаковыми метками на одном узле), поэтому он попытается выделить для себя новый узел (если это возможно в рамках своей группы узлов), куда автоматически будет размещен еще один instance Ingress-контроллера.

How to use IngressClass with IngressClassParameters?

Since version 1.1 IngressNginxController Deckhouse creates an IngressClass object. If you want to use your own IngressClass with your customized IngressClassParameters, you need to add the label ingress-class.deckhouse.io/external: "true":

  • Минимальное реальное количество реплик IngressNginxController не может быть меньше минимального количества узлов в группе узлов, куда он разворачивается.
  • Максимальное реальное количество реплик IngressNginxController не может быть больше максимального количества узлов в группе узлов, куда он разворачивается.

yaml apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: labels: ingress-class.deckhouse.io/external: “true” name: my-super-ingress spec: controller: ingress-nginx.deckhouse.io/my-super-ingress parameters: apiGroup: elbv2.k8s.aws kind: IngressClassParams name: awesome-class-cfg

In this case Deckhouse will not create an IngressClass object and will use your own.

Как использовать IngressClass с установленными IngressClassParameters?

How to disable the collection of detailed Ingress resources statistics?

Начиная с версии 1.1 IngressNginxController, Deckhouse создает объект IngressClass самостоятельно. Если вы хотите использовать свой IngressClass с установленными IngressClassParameters, достаточно добавить к нему label ingress-class.deckhouse.io/external: "true":

By default, Deckhouse collects detailed statistics from all Ingress resources in the cluster, which generates a high load on the monitoring system.

yaml apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: labels: ingress-class.deckhouse.io/external: “true” name: my-super-ingress spec: controller: ingress-nginx.deckhouse.io/my-super-ingress parameters: apiGroup: elbv2.k8s.aws kind: IngressClassParams name: awesome-class-cfg

To disable statistics collection, add label ingress.deckhouse.io/discard-metrics: "true" to the corresponding Namespace or Ingress resource.

В этом случае, при указании данного IngressClass в CRD IngressNginxController, Deckhouse не будет создавать объект, а использует существующий.

Example of disabling statistics (metrics) collection for all Ingress resources in the review-1 namespace:

Как отключить сборку детализированной статистики Ingress-ресурсов?

shell kubectl label ns review-1 ingress.deckhouse.io/discard-metrics=true

По умолчанию Deckhouse собирает подробную статистику со всех Ingress-ресурсов в кластере. Этот процесс может приводить к высокой нагрузке системы мониторинга.

Example of disabling statistics (metrics) collection for all test-site Ingress resources in the development namespace:

Для отключения сбора статистики добавьте лейбл ingress.deckhouse.io/discard-metrics: "true" к соответствующему пространству имён или Ingress-ресурсу.

shell kubectl label ingress test-site -n development ingress.deckhouse.io/discard-metrics=true

Пример отключения сбора статистики (метрик) для всех Ingress-ресурсов в пространстве имен review-1:

How do I correctly drain a node running an IngressNginxController’s pods?

shell kubectl label ns review-1 ingress.deckhouse.io/discard-metrics=true

There are two ways to gracefully drain a node running IngressNginxController.

Пример отключения сбора статистики (метрик) для всех Ingress-ресурсов test-site в пространстве имен development:

  1. Using an annotation.

shell kubectl label ingress test-site -n development ingress.deckhouse.io/discard-metrics=true

The annotation will be automatically removed after the operation completes.

Как корректно вывести из эксплуатации (drain) узел с запущенным IngressNginxController?

shell kubectl annotate node update.node.deckhouse.io/draining=user

Доступно два способа корректного вывода из эксплуатации узла, на котором запущен IngressNginxController.

  1. Using kubectl drain.
  1. С помощью аннотации.

When using the standard kubectl drain command, you must specify the --force flag even if --ignore-daemonsets is present, since IngressNginxController is deployed using Advanced DaemonSet:

Аннотация будет автоматически удалена после завершения операции.

shell kubectl drain --delete-emptydir-data --ignore-daemonsets --force

shell kubectl annotate node update.node.deckhouse.io/draining=user

How to enable Web Application Firewall (WAF)?

  1. С помощью kubectl drain.

Software known as a Web Application Firewall (WAF) is used to protect web applications from Layer 7 attacks. Ingress-nginx controller has a built-in WAF called `ModSecurity’ (The Open Worldwide Application Security Project).

При использовании стандартной команды kubectl drain необходимо указать флаг --force даже при наличии --ignore-daemonsets, поскольку IngressNginxController развёрнут с использованием Advanced DaemonSet:

ModSecurity is disabled by default.

shell kubectl drain --delete-emptydir-data --ignore-daemonsets --force

Enabling ModSecurity

Как включить Web Application Firewall (WAF)?

To enable ModSecurity, you must specify the following parameters in the config section of the CR IngressNginxController:

Для защиты веб-приложений от L7-атак используется программное обеспечение известное как Web Application Firewall (WAF). В ingress-nginx контроллер встроен WAF под названием ModSecurity (проект Open Worldwide Application Security).

yaml apiVersion: deckhouse.io/v1 kind: IngressNginxController metadata: name: spec: config: enable-modsecurity: "true" modsecurity-snippet: | Include /etc/nginx/modsecurity/modsecurity.conf

По умолчанию ModSecurity выключен.

After applying the settings, ModSecurity will start working for all traffic passing through this Ingress nginx controller. This uses the audit mode (DetectionOnly) and basic recommended configuration.

Включение ModSecurity

Setting up ModSecurity

Для включения ModSecurity необходимо задать параметры в кастомном ресурсе IngressNginxController, в секции config:

You can configure ModSecurity in two ways:

  1. For the entire ingress-nginx controller
    • the necessary directives are described in the section config.modsecurity-snippet in CR IngressNginxController, as in the example above.
  2. For each CR Ingress separately
    • the necessary directives are described in the annotation nginx.ingress.kubernetes.io/modsecurity-snippet : | directly in Ingress manifests.

yaml apiVersion: deckhouse.io/v1 kind: IngressNginxController metadata: name: <имя_контроллера> spec: config: enable-modsecurity: "true" modsecurity-snippet: | Include /etc/nginx/modsecurity/modsecurity.conf

To enable the execution of rules (and not just logging), add the SecRuleEngine On directive as shown below:

После применения настроек ModSecurity начнет работать для всего трафика, проходящего через данный ingress-nginx контроллер. При этом используется режим аудита (DetectionOnly) и базовая рекомендуемая конфигурация.

yaml apiVersion: deckhouse.io/v1 kind: IngressNginxController metadata: name: spec: config: enable-modsecurity: "true" modsecurity-snippet: | Include /etc/nginx/modsecurity/modsecurity.conf SecRuleEngine On

Настройка ModSecurity

A full list and description of the directives can be found in the official documentation.

ModSecurity можно настраивать двумя способами:

  1. Для всего ingress-nginx контроллера
    • необходимые директивы описываются в секции config.modsecurity-snippet в кастомном ресурсе IngressNginxController, как в примере выше.
  2. Для каждого кастомного ресурса Ingress по отдельности
    • необходимые директивы описываются в аннотации nginx.ingress.kubernetes.io/modsecurity-snippet: | непосредственно в манифестах Ingress.

Currently, the OWASP Core Rule Set (CRS) is not available.

Чтобы включить выполнение правил (а не только логирование), добавьте директиву SecRuleEngine On по примеру ниже:

 

yaml apiVersion: deckhouse.io/v1 kind: IngressNginxController metadata: name: <имя_контролера> spec: config: enable-modsecurity: "true" modsecurity-snippet: | Include /etc/nginx/modsecurity/modsecurity.conf SecRuleEngine On

 

Полный перечень и описание директив вы можете найти в официальной документации.

 

На данный момент использование набора правил OWASP Core Rule Set (CRS) недоступно.