---
title: "Аддон Nginx Ingress для Kubernetes"
description: "Аддон Nginx Ingress для Kubernetes. Установка, настройка, примеры использования. Документация и инструкции по работе с облачными сервисами Timeweb Cloud."
---

# Nginx Ingress

> Полный индекс документации для ИИ-агентов: [llms.txt](https://timeweb.cloud/llms.txt).

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

## Установка Nginx Ingress

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

![Image2](https://content.timeweb.com/assets/83134417-3b7b-47cd-bbe9-af31473436a1.png?width=1025&height=934)

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

```shell
kubectl get pods -n ingress-nginx
```

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

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

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

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

```shell
kubectl create namespace ingress-example
```

Чтобы отличать сервисы друг от друга, создадим `ConfigMap` с тремя разными HTML-страницами. Создайте файл `configmap.yaml` с таким содержанием:

```shell
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>
```

Теперь опишем деплойменты:

**service1-deployment.yaml**:

```yml
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 по умолчанию раздает контент.
    

3.  **Service**
    

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

Манифесты для `service2` и `service3` аналогичны, отличается только имя сервиса и используемый HTML-файл.

**service2-deployment.yaml**:

```yml
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**:

```yml
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
```

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

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

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

```shell
kubectl get pods -n ingress-example
```

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

## Создание Ingress 

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

```yml
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`.
    

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

```shell
kubectl apply -f ingress.yaml
```

## Создание LoadBalancer

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

```yml
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
```

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

```shell
kubectl apply -f loadbalancer.yaml
```

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

```shell
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.

> [!NOTE]
> Если вы хотите автоматизировать выпуск и продление сертификатов (например, через Let’s Encrypt), рекомендуем использовать инструмент [cert-manager](https://timeweb.cloud/docs/k8s/addons/cert-manager).

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

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

![Image1](https://content.timeweb.com/assets/b5cadaa3-8dae-4e85-8009-d10cf4e75af4.png?width=1035&height=541)

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

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

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

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

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

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

```shell
kubectl apply -f tls-secret.yaml
```

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

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

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

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

```yml
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
```

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

```shell
kubectl apply -f ingress.yaml
```

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

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

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

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

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