Перейти к содержимому

Настройка HTTPS-доступа к приложению с помощью Gateway API, NGINX Gateway Fabric и cert-manager

Kubernetes Gateway API — это набор ресурсов Kubernetes для настройки маршрутизации входящего трафика к приложениям. Для работы Gateway API необходим контроллер, который реализует спецификацию Gateway API и управляет сетевой инфраструктурой. В этом руководстве используется контроллер NGINX Gateway Fabric.

Для организации HTTPS-доступа к приложению нужно выпустить TLS-сертификат и настроить его использование в ресурсе Gateway. Автоматизировать выпуск и продление сертификатов позволяет оператор cert-manager. В качестве центра сертификации в этом руководстве выступает Let’s Encrypt

Чтобы развернуть приложение и настроить HTTPS-доступ к нему через Gateway API с использованием сертификатов:

  1. Подготовьте окружение для работы с кластером Managed Kubernetes.
  1. Создайте сервисный аккаунт с именем sa-mk8s и ролью registry.puller.

  2. Для сервисного аккаунта sa-mk8s создайте API-ключ и сохраните его.

  3. Создайте кластер Managed Kubernetes с публичным эндпоинтом и группу узлов для него. При создании группы используйте сервисный аккаунт sa-mk8s.

  4. Создайте NAT-шлюз для подсети, в которой развернут кластер Managed Kubernetes.

  5. Для прохождения руководства вам понадобится устройство, поддерживающее работу с командной строкой. Используйте личный компьютер или создайте промежуточную ВМ в той же сети, где расположен кластер Managed Kubernetes.

  1. Подключитесь к терминалу на вашем компьютере или к промежуточной ВМ.

  2. Установите и настройте утилиту MWS CLI:

  3. Аутентифицируйтесь в Artifact Registry:

    bash
    helm registry login -u apikey -p <API-ключ> registry.mwsapis.ru
  4. Установите утилиту командной строки kubectl.

  1. Установите Gateway API:

    bash
    kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || \
    kubectl apply --server-side -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.5.1/standard-install.yaml
  2. Убедитесь, что установка прошла успешно:

    bash
    kubectl api-resources --api-group=gateway.networking.k8s.io

    Ожидаемый результат:

    bash
    NAME SHORTNAMES APIVERSION NAMESPACED KIND
    backendtlspolicies btlspolicy gateway.networking.k8s.io/v1 true BackendTLSPolicy
    gatewayclasses gc gateway.networking.k8s.io/v1 false GatewayClass
    gateways gtw gateway.networking.k8s.io/v1 true Gateway
    grpcroutes gateway.networking.k8s.io/v1 true GRPCRoute
    httproutes gateway.networking.k8s.io/v1 true HTTPRoute
    listenersets lset gateway.networking.k8s.io/v1 true ListenerSet
    referencegrants refgrant gateway.networking.k8s.io/v1 true ReferenceGrant
    tlsroutes gateway.networking.k8s.io/v1 true TLSRoute

Чтобы развернуть тестовое приложение httpbin в новом пространстве имен gateway-test, выполните команду:

bash
kubectl apply -f - <<EOF
apiVersion: v1
kind: Namespace
metadata:
name: gateway-test
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: httpbin
namespace: gateway-test
---
apiVersion: v1
kind: Service
metadata:
name: httpbin
namespace: gateway-test
labels:
app: httpbin
service: httpbin
spec:
ports:
- name: http
port: 8000
targetPort: 8080
selector:
app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin
namespace: gateway-test
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
version: v1
template:
metadata:
labels:
app: httpbin
version: v1
spec:
serviceAccountName: httpbin
containers:
- image: registry.mwsapis.ru/mws-mk8s-images/customer/go-httpbin:v2.15.0
imagePullPolicy: IfNotPresent
name: httpbin
ports:
- containerPort: 8080
EOF

Ожидаемый результат:

bash
namespace/gateway-test created
serviceaccount/httpbin created
service/httpbin created
deployment.apps/httpbin created
  1. Установите NGINX Gateway Fabric:

    bash
    helm upgrade --install ngf oci://registry.mwsapis.ru/mws-mk8s-images/customer/charts/nginx-gateway-fabric \
    --version 2.4.2 \
    --create-namespace \
    -n nginx-gateway \
    --set nginx.service.externalTrafficPolicy=Cluster

    Ожидаемый результат:

    bash
    NAME: ngf
    LAST DEPLOYED: Tue Jun 16 20:55:50 2026
    NAMESPACE: nginx-gateway
    STATUS: deployed
    REVISION: 1
    TEST SUITE: None
  2. Убедитесь, что контроллер запущен:

    bash
    kubectl -n nginx-gateway get pods

    Ожидаемый результат:

    bash
    NAME READY STATUS RESTARTS AGE
    ngf-nginx-gateway-fabric-6b6d84fb47-t7dzr 1/1 Running 0 2m3s
  1. Установите cert-manager:

    bash
    helm upgrade --install cert-manager oci://registry.mwsapis.ru/mws-mk8s-images/customer/charts/cert-manager \
    --version v1.20.0 \
    --namespace cert-manager \
    --create-namespace \
    --set crds.enabled=true \
    --set config.enableGatewayAPI=true
  2. Убедитесь, что установка прошла успешно:

    bash
    kubectl get pods -n cert-manager

    Ожидаемый результат:

    bash
    NAME READY STATUS RESTARTS AGE
    cert-manager-6ff98c57db-2rjpg 1/1 Running 0 10m
    cert-manager-cainjector-7ccc4cf444-hrxlg 1/1 Running 0 10m
    cert-manager-webhook-67f6dbc76f-jz4rh 1/1 Running 0 10m

Оператор cert-manager использует ресурс ClusterIssuer для выпуска сертификатов через Let’s Encrypt. Сертификаты выпускаются после прохождения проверки HTTP-01.

Создайте ресурс ClusterIssuer:

bash
cat <<EOF > clusterissuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt
spec:
acme:
email: <адрес электронной почты для уведомлений>
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: issuer-account-key
solvers:
- http01:
gatewayHTTPRoute: {}
EOF
kubectl apply -f clusterissuer.yaml

Ожидаемый результат:

bash
clusterissuer.cert-manager.io/letsencrypt created

Если сертификаты требуются только в одном пространстве имен, вместо ClusterIssuer используйте ресурс Issuer.

Ресурс Gateway определяет правила приема входящего трафика, а ресурс HTTPRoute — правила маршрутизации входящего трафика к приложениям, запущенным в кластере.

  1. Создайте ресурс Gateway в пространстве имен gateway-test, в котором развернуто тестовое приложение:

    bash
    cat <<EOF > gateway.yaml
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
    name: httpbin-gateway-nginx-https
    namespace: gateway-test
    annotations:
    cert-manager.io/cluster-issuer: letsencrypt
    spec:
    gatewayClassName: nginx
    listeners:
    - name: http
    hostname: <доменное имя>
    port: 80
    protocol: HTTP
    allowedRoutes:
    namespaces:
    from: All
    - name: https
    hostname: <доменное имя>
    port: 443
    protocol: HTTPS
    allowedRoutes:
    namespaces:
    from: All
    tls:
    mode: Terminate
    certificateRefs:
    # cert-manager автоматически создаст секрет, где будет храниться сертификат
    - name: httpbin-tls-secret
    kind: Secret
    EOF
    kubectl apply -f gateway.yaml

    Ожидаемый результат:

    bash
    gateway.gateway.networking.k8s.io/httpbin-gateway-nginx-https created

    Подробнее конфигурация ресурса Gateway описана в официальной документации.


    После создания ресурса Gateway контроллер автоматически создаст сервис типа LoadBalancer (балансировщик нагрузки). Если вы хотите закрепить за балансировщиком внешний IP-адрес, зарезервируйте его и добавьте в spec.infrastructure аннотацию:

    yaml
    infrastructure:
    annotations:
    mk8s.mws.ru/load-balancer-external-ip-name: <имя зарезервированного внешнего IP-адреса>
  2. Создайте ресурс HTTPRoute в пространстве имен gateway-test, в котором развернуто тестовое приложение:

    bash
    cat <<EOF > HTTPRoute.yaml
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
    name: httpbin-nginx-https
    namespace: gateway-test
    spec:
    hostnames:
    - <доменное имя>
    parentRefs:
    - name: httpbin-gateway-nginx-https
    sectionName: http
    - name: httpbin-gateway-nginx-https
    sectionName: https
    rules:
    - matches:
    - path:
    type: PathPrefix
    value: /status
    backendRefs:
    - name: httpbin
    port: 8000
    weight: 1
    EOF
    kubectl apply -f HTTPRoute.yaml

    Ожидаемый результат:

    bash
    httproute.gateway.networking.k8s.io/httpbin-nginx-https created

    Подробнее конфигурация ресурса HTTPRoute описана в официальной документации.

Let’s Encrypt валидирует сертификаты (проверка HTTP-01) через HTTP-запросы на порт 80 с разных IP-адресов своей инфраструктуры, и эти IP-адреса не раскрываются. Для прохождения проверки HTTP-01 нужно разрешить доступ к порту TCP:80 из всего интернета.

  1. Узнайте, какой порт на узлах кластера соответствует порту 80 балансировщика:

    bash
    kubectl get svc httpbin-gateway-nginx-https-nginx

    Ожидаемый результат:

    bash
    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    httpbin-gateway-nginx-https-nginx LoadBalancer 10.22.119.230 2.59.82.255 80:30960/TCP,443:32179/TCP 21h

    Здесь:

    • EXTERNAL-IP — внешний IP-адрес балансировщика;
    • PORT(S)— порты, на которых балансировщик принимает трафик, и соответствующие им порты на рабочих узлах кластера (NodePort).
  2. Создайте правило файрвола со следующими параметрами:

    • Направление трафика — Ingress.
    • Действие в рамках правила — Allow.
    • Источник трафика — 0.0.0.0/0.
    • Назначение трафика — CIDR подсети, в которой расположен кластер Managed Kubernetes.
    • Протокол — TCP.
    • Порт — порт на узлах кластера (NodePort), соответствующий порту 80. В этом примере — 30960.
    • Опция Активировать правило сразу после сохранения — включена.
  1. Убедитесь, что оператор cert-manager запросил выпуск сертификата от Let’s Encrypt:

    bash
    kubectl get certificaterequests.cert-manager.io -n gateway-test

    Ожидаемый результат:

    bash
    NAME APPROVED DENIED READY ISSUER REQUESTER AGE
    httpbin-tls-secret-1 True True letsencrypt system:serviceaccount:cert-manager:cert-manager 89m
  2. Убедитесь, что сертификат выпущен:

    bash
    kubectl get certificate -n gateway-test

    Ожидаемый результат:

    bash
    NAME READY SECRET AGE
    httpbin-tls-secret True httpbin-tls-secret 86m
  3. Убедитесь, что секрет создан и содержит сертификат:

    bash
    kubectl get secrets httpbin-tls-secret -n gateway-test

    Ожидаемый результат:

    bash
    NAME TYPE DATA AGE
    httpbin-tls-secret kubernetes.io/tls 2 86m
  4. Убедитесь, что тестовое приложение доступно по HTTPS:

    bash
    curl -I https://<доменное имя>/status/200

    Ожидаемый результат:

    bash
    HTTP/2 200
    server: nginx
  5. Запросите информацию о сертификате:

    bash
    openssl s_client -connect <доменное имя>:443 -servername <доменное имя> </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates -ext subjectAltName

    Ожидаемый результат:

    bash
    subject=CN = <доменное имя>
    issuer=C = US, O = Let's Encrypt, CN = R12
    notBefore=Mar 25 10:02:26 2026 GMT
    notAfter=Jun 23 10:02:25 2026 GMT
    X509v3 Subject Alternative Name:
    DNS:<доменное имя>

Ресурсы, созданные в руководстве, тарифицируются. Если вы больше не планируете использовать их:

  1. Удалите промежуточную ВМ, если вы ее создавали.