<div><img src="https://top-fwz1.mail.ru/counter?id=3548135;js=na" style="position:absolute;left:-9999px;" alt="Top.Mail.Ru" /></div>
Бесплатный перенос IT-инфраструктуры в облако
На главную
25eb9e0a-a5a8-472a-ace7-940b8bd2adf0
Облачные сервисы

Nginx Ingress

Ingress — это ресурс Kubernetes, позволяющий организовать доступ к сервисам внутри кластера через HTTP и HTTPS. Он предоставляет маршрутизацию на основе URL, доменов и других параметров. В этой статье рассмотрим использование Nginx Ingress на примере трех деплойментов Nginx, имитирующих три разных сервиса. Мы также настроим SSL-сертификат для защиты соединения.

Установка Nginx Ingress

Для начала необходимо установить Nginx Ingress в кластере. В панели управления кластером перейдите во вкладку «Дополнения», нажмите на три точки рядом с Nginx Ingress и выберите «Установить».

Image2

После установки проверьте, что Ingress работает корректно. Выполните команду:

kubectl get pods -n ingress-nginx

Убедитесь, что все поды находятся в статусе Running.

Настройка деплойментов и сервисов

Для удобства создадим отдельный неймспейс, в котором будут находиться все манифесты:

kubectl create namespace ingress-example

Мы развернем три Deployment с образами Nginx, каждый будет имитировать отдельный сервис. К каждому Deployment мы создадим Service с типом ClusterIP — это служебный тип сервиса в Kubernetes, который выдает внутренний IP-адрес внутри кластера. Такой сервис не доступен извне напрямую, однако он может быть подцеплен к Ingress для публикации во внешнюю сеть.

service1-deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: service1
  namespace: ingress-example
spec:
  replicas: 2
  selector:
    matchLabels:
      app: service1
  template:
    metadata:
      labels:
        app: service1
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
        volumeMounts:
        - name: config-volume
          mountPath: /usr/share/nginx/html
      volumes:
      - name: config-volume
        configMap:
          name: service-config
          items:
          - key: service1.html
            path: index.html
---
apiVersion: v1
kind: Service
metadata:
  name: service1
  namespace: ingress-example
spec:
  selector:
    app: service1
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: ClusterIP

Пояснения к манифесту:

  1. Deployment

    • replicas: 2 указывает, что будет запущено две реплики подов с Nginx.

    • В секции selector и template.metadata.labels задаётся соответствие между подами и тем, как их будет находить сервис.

    • volumeMounts и volumes используются, чтобы подмонтировать файл service1.html из ConfigMap в директорию, откуда Nginx по умолчанию раздает контент.

  2. Service

    • ClusterIP означает, что сервис будет доступен только внутри кластера по выделенному IP-адресу. Для внешнего доступа мы будем использовать Ingress.

service2-deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: service2
  namespace: ingress-example
spec:
  replicas: 2
  selector:
    matchLabels:
      app: service2
  template:
    metadata:
      labels:
        app: service2
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
        volumeMounts:
        - name: config-volume
          mountPath: /usr/share/nginx/html
      volumes:
      - name: config-volume
        configMap:
          name: service-config
          items:
          - key: service2.html
            path: index.html
---
apiVersion: v1
kind: Service
metadata:
  name: service2
  namespace: ingress-example
spec:
  selector:
    app: service2
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: ClusterIP

service3-deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: service3
  namespace: ingress-example
spec:
  replicas: 2
  selector:
    matchLabels:
      app: service3
  template:
    metadata:
      labels:
        app: service3
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
        volumeMounts:
        - name: config-volume
          mountPath: /usr/share/nginx/html
      volumes:
      - name: config-volume
        configMap:
          name: service-config
          items:
          - key: service3.html
            path: index.html
---
apiVersion: v1
kind: Service
metadata:
  name: service3
  namespace: ingress-example
spec:
  selector:
    app: service3
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: ClusterIP

Чтобы отличать наши сервисы друг от друга, создадим ConfigMap с тремя разными HTML-страницами.

configmap.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: service-config
  namespace: ingress-example
data:
  service1.html: |
    <html>
    <head><title>Service 1</title></head>
    <body><h1>Welcome to Service 1!</h1></body>
    </html>
  service2.html: |
    <html>
    <head><title>Service 2</title></head>
    <body><h1>Welcome to Service 2!</h1></body>
    </html>
  service3.html: |
    <html>
    <head><title>Service 3</title></head>
    <body><h1>Welcome to Service 3!</h1></body>
    </html>

И применим манифесты:

kubectl apply -f configmap.yaml
kubectl apply -f service1-deployment.yaml
kubectl apply -f service2-deployment.yaml
kubectl apply -f service3-deployment.yaml

Проверим статус подов:

kubectl get pods -n ingress-example

Все поды должны иметь статус Running. На этом подготовительные работы можно считать завершенными.

Создание Ingress 

С помощью Ingress мы укажем, какой трафик (по доменам и путям) перенаправлять на соответствующие сервисы. Создадим манифест ingress.yaml:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  namespace: ingress-example
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: ingress1.example.com
    http:
      paths:
      - path: /service1
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 80
      - path: /service2
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 80
  - host: ingress2.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: service3
            port:
              number: 80

Пояснения к манифесту:

  • rules.host задает домен, к которому будет привязан Ingress.

  • paths определяет правила маршрутизации:

    • При обращении к ingress1.example.com/service1 будет перенаправление на service1.

    • При обращении к ingress1.example.com/service2 будет перенаправление на service2.

    • При обращении к ingress2.example.com/ будет перенаправление на service3.

Применим манифест:

kubectl apply -f ingress.yaml

Создание LoadBalancer

Чтобы обратиться к Nginx Ingress из внешней сети, создадим Service типа LoadBalancer, который будет отвечать за балансировку нагрузки и предоставит нам внешний IP-адрес. Подготовим для этого манифест loadbalancer.yaml следующего содержания:

apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
spec:
  selector:
    app.kubernetes.io/name: ingress-nginx
  ports:
    - name: http
      port: 80
      targetPort: 80
    - name: https
      port: 443
      targetPort: 443
  type: LoadBalancer

Применим манифест:

kubectl apply -f loadbalancer.yaml

Дождитесь, пока балансировщик создастся, и убедитесь, что у него появился внешний IP-адрес:

kubectl get services -n ingress-nginx

Внешний IP будет отображен в колонке EXTERNAL-IP.

Полученный IP-адрес необходимо прописать в DNS-настройках домена в виде А-записей для доменов ingress1.example.com и ingress2.example.com. После обновления DNS ваши домены будут указывать на этот балансировщик, и вы сможете обращаться к сервисам по внешним URL:

  • http://ingress1.example.com/service1 отобразится заголовок «Welcome to Service 1!».
  • http://ingress1.example.com/service2 — отобразится заголовок «Welcome to Service 2!».
  • http://ingress2.example.com/ — отобразится заголовок «Welcome to Service 3!».

Настройка SSL-сертификата

Для обеспечения защищенного соединения в Nginx Ingress необходимо добавить существующий SSL-сертификат в виде Kubernetes-секрета, а затем указать этот секрет в манифесте Ingress.

Если вы хотите автоматизировать выпуск и продление сертификатов (например, через Let’s Encrypt), рекомендуем использовать инструмент cert-manager.

Подготовка файлов сертификата и ключа

Сохраните файл ключа tls.key и сертификат tls.crt локально. Если вы заказывали сертификат в Timeweb Cloud, содержимое ключа и сертификата можно скопировать со страницы управления сертификатом в панели Timeweb Cloud. Убедитесь, что сертификат не просрочен и соответствует доменам, которые вы хотите защитить.

Image1

Создание Kubernetes-секрета

Чтобы добавить сертификат в кластер, необходимо закодировать файлы в Base64 и создать манифест секрета. Выполните в терминале команды:

base64 -w 0 ./tls.crt
base64 -w 0 ./tls.key

Затем создайте файл tls-secret.yaml следующего содержания:

apiVersion: v1
kind: Secret
metadata:
  name: ingress-example-tls
  namespace: ingress-example
type: kubernetes.io/tls
data:
  tls.crt: |-
    <BASE64_ЗАКОДИРОВАННЫЙ_СЕРТИФИКАТ>
  tls.key: |-
    <BASE64_ЗАКОДИРОВАННЫЙ_КЛЮЧ>

Сохраните файл и примените манифест:

kubectl apply -f tls-secret.yaml

Проверьте, что значения ключа и сертификата ненулевые. Для этого выполните:

kubectl describe secret ingress-example-tls -n ingress-example

Обновление манифеста Ingress

Обновите ваш манифест ingress.yaml, добавив секцию tls, и укажите имя созданного секрета:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  namespace: ingress-example
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  tls:
  - hosts:
    - ingress1.example.com
    - ingress2.example.com
    secretName: ingress-example-tls
  rules:
  - host: ingress1.example.com
    http:
      paths:
      - path: /service1
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 80
      - path: /service2
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 80
  - host: ingress2.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: service3
            port:
              number: 80

Примените измененный манифест:

kubectl apply -f ingress.yaml

Теперь при обращении к ingress1.example.com или ingress2.example.com по HTTPS браузер будет использовать сертификат, указанный в секрете ingress-example-tls. Таким образом, трафик к вашим сервисам будет защищен.

Если у вас несколько сертификатов для разных доменов, создайте Secret для каждого из них. Например, для доменов example.com и example.org создайте два секрета.

После этого обновите манифест Ingress, добавив секцию tls для каждого домена:

spec:
  tls:
  - hosts:
    - example.com
    secretName: example-com-tls
  - hosts:
    - example.org
    secretName: example-org-tls

После этого каждый домен будет использовать свой сертификат, указанный в соответствующем секрете.

Была ли статья полезна?
Ваша оценка очень важна
Пока нет комментариев