Как разрешить доступ к приложению внутри кластера только от Ingress-контроллера?
Если необходимо ограничить доступ к вашему приложению внутри кластера исключительно от подов Ingress-контроллера, необходимо в под с приложением добавить контейнер с kube-rbac-proxy, как показано в примере ниже:
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: my-app
5 namespace: my-namespace
6spec:
7 selector:
8 matchLabels:
9 app: my-app
10 replicas: 1
11 template:
12 metadata:
13 labels:
14 app: my-app
15 spec:
16 serviceAccountName: my-sa
17 containers:
18 - name: my-cool-app
19 image: mycompany/my-app:v0.5.3
20 args:
21 - "--listen=127.0.0.1:8080"
22 livenessProbe:
23 httpGet:
24 path: /healthz
25 port: 443
26 scheme: HTTPS
27 - name: kube-rbac-proxy
28 image: flant/kube-rbac-proxy:v0.1.0
29 # Рекомендуется использовать прокси из репозитория Deckhouse.
30 args:
31 - "--secure-listen-address=0.0.0.0:443"
32 - "--config-file=/etc/kube-rbac-proxy/config-file.yaml"
33 - "--v=2"
34 - "--logtostderr=true"
35 # Если kube-apiserver недоступен, аутентификация и авторизация пользователей невозможна.
36 # Stale Cache хранит результаты успешной авторизации и используется лишь в случае, если apiserver недоступен.
37 - "--stale-cache-interval=1h30m"
38 ports:
39 - containerPort: 443
40 name: https
41 volumeMounts:
42 - name: kube-rbac-proxy
43 mountPath: /etc/kube-rbac-proxy
44 volumes:
45 - name: kube-rbac-proxy
46 configMap:
47 name: kube-rbac-proxy
Приложение принимает запросы на адресе 127.0.0.1
, это означает, что по незащищенному соединению к нему можно подключиться только внутри пода.
Прокси прослушивает порт на адресе 0.0.0.0
и перехватывает весь внешний трафик к поду.
Как выдать минимальные права для ServiceAccount?
Чтобы аутентифицировать и авторизовывать пользователей с помощью kube-apiserver, у прокси должны быть права на создание TokenReview
и SubjectAccessReview
.
В кластерах DKP уже есть готовая ClusterRole — d8-rbac-proxy, создавать её самостоятельно не требуется! Свяжите её с ServiceAccount вашего Deployment’а, как показано в примере ниже.
1---
2apiVersion: v1
3kind: ServiceAccount
4metadata:
5 name: my-sa
6 namespace: my-namespace
7---
8apiVersion: rbac.authorization.k8s.io/v1
9kind: ClusterRoleBinding
10metadata:
11 name: my-namespace:my-sa:d8-rbac-proxy
12roleRef:
13 apiGroup: rbac.authorization.k8s.io
14 kind: ClusterRole
15 name: d8:rbac-proxy
16subjects:
17- kind: ServiceAccount
18 name: my-sa
19 namespace: my-namespace
Конфигурация Kube-RBAC-Proxy
1apiVersion: v1
2kind: ConfigMap
3metadata:
4 name: kube-rbac-proxy
5data:
6 config-file.yaml: |+
7 excludePaths:
8 - /healthz
9 # Не требуем авторизацию для liveness пробы.
10 upstreams:
11 - upstream: http://127.0.0.1:8081/
12 # Адрес upstream-сервиса, на который будет перенаправлен входящий трафик.
13 path: /
14 # Путь, обрабатываемый прокси, по которому принимаются запросы и перенаправляются на upstream.
15 authorization:
16 resourceAttributes:
17 namespace: my-namespace
18 apiGroup: apps
19 apiVersion: v1
20 resource: deployments
21 subresource: http
22 name: my-app
Согласно конфигурации, у пользователя должны быть права доступа к Deployment с именем my-app
и его дополнительному ресурсу http
в пространстве имён my-namespace
.
Выглядят такие права в виде RBAC следующим образом:
1---
2apiVersion: rbac.authorization.k8s.io/v1
3kind: Role
4metadata:
5 name: kube-rbac-proxy:my-app
6 namespace: my-namespace
7rules:
8- apiGroups: ["apps"]
9 resources: ["deployments/http"]
10 resourceNames: ["my-app"]
11 verbs: ["get", "create", "update", "patch", "delete"]
12---
13apiVersion: rbac.authorization.k8s.io/v1
14kind: RoleBinding
15metadata:
16 name: kube-rbac-proxy:my-app
17 namespace: my-namespace
18roleRef:
19 apiGroup: rbac.authorization.k8s.io
20 kind: Role
21 name: kube-rbac-proxy:my-app
22subjects:
23# Все пользовательские сертификаты ingress-контроллеров выписаны для одной конкретной группы.
24- kind: Group
25 name: ingress-nginx:auth
Для Ingress-ресурса добавьте параметры:
1nginx.ingress.kubernetes.io/backend-protocol: HTTPS
2nginx.ingress.kubernetes.io/configuration-snippet: |
3 proxy_ssl_certificate /etc/nginx/ssl/client.crt;
4 proxy_ssl_certificate_key /etc/nginx/ssl/client.key;
5 proxy_ssl_protocols TLSv1.2;
6 proxy_ssl_session_reuse on;
Подробнее о том, как работает аутентификация по сертификатам, можно прочитать в документации Kubernetes.
Как сконфигурировать балансировщик нагрузки для проверки доступности IngressNginxController?
В ситуации, когда IngressNginxController
размещен за балансировщиком нагрузки, рекомендуется сконфигурировать балансировщик для проверки доступности
узлов IngressNginxController
с помощью HTTP-запросов или TCP-подключений. В то время как тестирование с помощью TCP-подключений представляет собой простой и универсальный механизм проверки доступности, мы рекомендуем использовать проверку на основе HTTP-запросов со следующими параметрами:
- протокол:
HTTP
; - путь:
/healthz
; - порт:
80
(в случае использования инлетаHostPort
нужно указать номер порта, соответствующий параметру httpPort.
Как настроить работу через MetalLB с доступом только из внутренней сети?
Пример MetalLB с настройками доступа только из внутренней сети:
1apiVersion: deckhouse.io/v1
2kind: IngressNginxController
3metadata:
4 name: main
5spec:
6 ingressClass: "nginx"
7 inlet: "LoadBalancer"
8 loadBalancer:
9 sourceRanges:
10 - 192.168.0.0/24
Для работы необходимо включить параметр svcSourceRangeCheck
в модуле cni-cilium.
Как добавить дополнительные поля для логирования в nginx-controller?
Пример добавления дополнительных полей:
1apiVersion: deckhouse.io/v1
2kind: IngressNginxController
3metadata:
4 name: main
5spec:
6 ingressClass: "nginx"
7 inlet: "LoadBalancer"
8 additionalLogFields:
9 my-cookie: "$cookie_MY_COOKIE"
Как включить HorizontalPodAutoscaling для IngressNginxController?
Режим HPA возможен только для контроллеров с инлетом LoadBalancer
или LoadBalancerWithProxyProtocol
.
Режим HPA возможен только при minReplicas
!= maxReplicas
, в противном случае deployment hpa-scaler
не создается.
Для включения HPA используйте атрибуты minReplicas
и maxReplicas
в IngressNginxController CR.
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).
Deployment hpa-scaler
обладает HardPodAntiAffinity (запрет на размещение подов с одинаковыми метками на одном узле), поэтому он попытается выделить для себя новый узел (если это возможно
в рамках своей группы узлов), куда автоматически будет размещен еще один instance Ingress-контроллера.
- Минимальное реальное количество реплик IngressNginxController не может быть меньше минимального количества узлов в группе узлов, куда он разворачивается.
- Максимальное реальное количество реплик IngressNginxController не может быть больше максимального количества узлов в группе узлов, куда он разворачивается.
Как использовать IngressClass с установленными IngressClassParameters?
Начиная с версии 1.1 IngressNginxController, Deckhouse создает объект IngressClass самостоятельно. Если вы хотите использовать свой IngressClass с установленными IngressClassParameters, достаточно добавить к нему label ingress-class.deckhouse.io/external: "true"
:
1apiVersion: networking.k8s.io/v1
2kind: IngressClass
3metadata:
4 labels:
5 ingress-class.deckhouse.io/external: "true"
6 name: my-super-ingress
7spec:
8 controller: ingress-nginx.deckhouse.io/my-super-ingress
9 parameters:
10 apiGroup: elbv2.k8s.aws
11 kind: IngressClassParams
12 name: awesome-class-cfg
В этом случае, при указании данного IngressClass в CRD IngressNginxController, Deckhouse не будет создавать объект, а использует существующий.
Как отключить сборку детализированной статистики Ingress-ресурсов?
По умолчанию Deckhouse собирает подробную статистику со всех Ingress-ресурсов в кластере. Этот процесс может приводить к высокой нагрузке системы мониторинга.
Для отключения сбора статистики добавьте лейбл ingress.deckhouse.io/discard-metrics: "true"
к соответствующему пространству имён или Ingress-ресурсу.
Пример отключения сбора статистики (метрик) для всех Ingress-ресурсов в пространстве имен review-1
:
1kubectl label ns review-1 ingress.deckhouse.io/discard-metrics=true
Пример отключения сбора статистики (метрик) для всех Ingress-ресурсов test-site
в пространстве имен development
:
1kubectl label ingress test-site -n development ingress.deckhouse.io/discard-metrics=true
Как корректно вывести из эксплуатации (drain) узел с запущенным IngressNginxController?
Доступно два способа корректного вывода из эксплуатации узла, на котором запущен IngressNginxController.
-
С помощью аннотации.
Аннотация будет автоматически удалена после завершения операции.
1 kubectl annotate node <node_name> update.node.deckhouse.io/draining=user
-
С помощью kubectl drain.
При использовании стандартной команды kubectl drain необходимо указать флаг
--force
даже при наличии--ignore-daemonsets
, поскольку IngressNginxController развёрнут с использованием Advanced DaemonSet:1 kubectl drain <node_name> --delete-emptydir-data --ignore-daemonsets --force
Как включить Web Application Firewall (WAF)?
Для защиты веб-приложений от L7-атак используется программное обеспечение известное как Web Application Firewall (WAF).
В ingress-nginx контроллер встроен WAF под названием ModSecurity
(проект Open Worldwide Application Security).
По умолчанию ModSecurity выключен.
Включение ModSecurity
Для включения ModSecurity необходимо задать параметры в кастомном ресурсе IngressNginxController, в секции config
:
1apiVersion: deckhouse.io/v1
2kind: IngressNginxController
3metadata:
4 name: <имя_контроллера>
5spec:
6 config:
7 enable-modsecurity: "true"
8 modsecurity-snippet: |
9 Include /etc/nginx/modsecurity/modsecurity.conf
После применения настроек ModSecurity начнет работать для всего трафика, проходящего через данный ingress-nginx контроллер.
При этом используется режим аудита (DetectionOnly
) и базовая рекомендуемая конфигурация.
Настройка ModSecurity
ModSecurity можно настраивать двумя способами:
- Для всего ingress-nginx контроллера
- необходимые директивы описываются в секции
config.modsecurity-snippet
в кастомном ресурсе IngressNginxController, как в примере выше.
- необходимые директивы описываются в секции
- Для каждого кастомного ресурса Ingress по отдельности
- необходимые директивы описываются в аннотации
nginx.ingress.kubernetes.io/modsecurity-snippet: |
непосредственно в манифестах Ingress.
- необходимые директивы описываются в аннотации
Чтобы включить выполнение правил (а не только логирование), добавьте директиву SecRuleEngine On
по примеру ниже:
1apiVersion: deckhouse.io/v1
2kind: IngressNginxController
3metadata:
4 name: <имя_контролера>
5spec:
6 config:
7 enable-modsecurity: "true"
8 modsecurity-snippet: |
9 Include /etc/nginx/modsecurity/modsecurity.conf
10 SecRuleEngine On
Полный перечень и описание директив вы можете найти в официальной документации.
На данный момент использование набора правил OWASP Core Rule Set (CRS) недоступно.