Рубрики
Uncategorized

Как настроить Nginx Ingress с автоматически сгенерированными сертификатами letsEncrypt на Kubernetes

Предпосылки: после первого поиска вокруг есть много учебных пособий, чтобы показать, как это сделать, но … С тегами Kubernetes, Docker, LetsEncrypt, DevOps.

Справочная информация: После первого поиска вокруг есть множество учебных пособий, чтобы показать, как это сделать, но ни один из них не работал без модификаций, они были устарели или использовали шлем (который не нужен, и я хотел использовать как можно меньше инструментов ), поэтому мне пришлось искать несколько источников для его запуска. По сути, это получило сборник статей, найденных в Интернете, которые работали для меня.

Я пропускаю здесь большую часть справочной информации или объяснений, так как их можно найти в связанных учебниках. Вместо этого это должно служить кратким набором инструкций, чтобы заставить его работать.

В качестве бонуса мы также настроем пересылку порта для любой произвольной службы (не HTTP/HTTPS — как базы данных), чтобы стать доступным из Интернета по тем же IP/LoadBalancer, что и веб -сайты.

Я использую Kubernetes, предлагаемые Digitalocean, поэтому, если бы ваш новый был бы рад использовать свою ссылку Здесь Зарегистрироваться. Вы можете раскрутить кластер K8S, начиная с 10 $/месяц.

Предварительные условия

  • Основное понимание объектов/типов Kubernetes
  • Кластер K8S, с готовой/установкой kubectl
  • Доступ к поставщику DNS для настройки некоторых записей DNS для указания на ваш кластер

Источники

Кредиты источникам, используемым в этой статье (без особого заказа):

Создайте некоторые фиктивные развертывания «эхо»

Мы хотим, чтобы несколько фиктивных веб -сервисов просто ответили на HTTP -запросы. Создайте следующие два файла:

# echo1.yaml
apiVersion: v1
kind: Service
metadata:
  name: echo1
spec:
  ports:
  - port: 80
    targetPort: 5678
  selector:
    app: echo1
--------
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo1
spec:
  selector:
    matchLabels:
      app: echo1
  replicas: 2
  template:
    metadata:
      labels:
        app: echo1
    spec:
      containers:
      - name: echo1
        image: hashicorp/http-echo
        args:
        - "-text=echo1"
        ports:
        - containerPort: 5678
# echo2.yaml
apiVersion: v1
kind: Service
metadata:
  name: echo2
spec:
  ports:
  - port: 80
    targetPort: 5678
  selector:
    app: echo2
--------
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo2
spec:
  selector:
    matchLabels:
      app: echo2
  replicas: 1
  template:
    metadata:
      labels:
        app: echo2
    spec:
      containers:
      - name: echo2
        image: hashicorp/http-echo
        args:
        - "-text=echo2"
        ports:
        - containerPort: 5678

Применить оба развертывания:

$ kubectl apply -f echo1.yaml
$ kubectl apply -f echo2.yaml

Это создаст 2 развертывания вместе с 2 сервисами, прослушивая кластерный внутренний порт 80:

$ kubectl get service
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
echo1        ClusterIP   10.245.164.177           80/TCP    1h
echo2        ClusterIP   10.245.77.216            80/TCP    1h

Настройка Ingress nginx

Получение вступления и запуска требуется только две команды:

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml

namespace/ingress-nginx created
configmap/nginx-configuration created
configmap/tcp-services created
configmap/udp-services created
serviceaccount/nginx-ingress-serviceaccount created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
role.rbac.authorization.k8s.io/nginx-ingress-role created
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
deployment.apps/nginx-ingress-controller created
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/cloud-generic.yaml

service/ingress-nginx created

На этом этапе установка Nginx-Engress, и балансировщик нагрузки (осторожность: облачные поставщики платят за каждый балансировщик нагрузки). Это может занять несколько минут, чтобы появиться. Вы можете проверить статус со следующей командой:

$ kubectl get -n ingress-nginx service
NAME            TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)                      AGE
ingress-nginx   LoadBalancer   10.245.209.25   155.241.87.123   80:30493/TCP,443:30210/TCP   1h

ОБНОВИТЬ:

Существует открытая проблема, касающаяся сетевой маршрутизации, вызывающая проблемы позже, когда стручка пытается запросить сертификаты и сталкивается с временем, пытаясь самостоятельно проверить запрошенный домен.

Благодаря этому мы должны изменить «внешнюю обработкуполисики» только что созданного сервиса «Ingress-nginx». Создайте файл ‘Service Ingress-nginx.yaml’ с/следующим контентом:

# Service_ingress-nginx.yaml
kind: Service
apiVersion: v1
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  # default for externalTrafficPolicy = 'Local', but due to an issue
  # (https://stackoverflow.com/questions/59286126/kubernetes-cluterissuer-challenge-timeouts,
  # https://github.com/danderson/metallb/issues/287)
  # it has to be 'Cluster' for now
  externalTrafficPolicy: Cluster
  type: LoadBalancer
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: http
    - name: https
      port: 443
      protocol: TCP
      targetPort: https

Когда вы различаете/применяете этот файл, разница должна заключаться в том, что ExternalTrafficpolicy теперь является «кластером». Недостатком этого является то, что вы можете потерять отслеживание оригинальных услуг, запрашивающих IP, но для меня это не имеет значения и решает проблему с просьбой о сертификате.

kubectl diff -f Service_ingress-nginx.yaml # show differences
kubectl apply -f Service_ingress-nginx.yaml # activate changes

Обратите внимание на ваш внешний IP -адрес, так как мы будем использовать его в качестве одного ворота для услуг, которые мы хотим сделать общедоступным.

Теперь перейдите к своему поставщику DNS и создайте две записи (любого вида), чтобы указать на ваш внешний IP.

Создайте файл ‘echo_ingress.yaml’ и настраивайте его в соответствии с только что созданными записями DNS:

# echo_ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: echo-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"    
spec:
  rules:
  - host: echo1.yourdomain.com
    http:
      paths:
      - backend:
          serviceName: echo1
          servicePort: 80
  - host: echo2.yourdomain.com
    http:
      paths:
      - backend:
          serviceName: echo2
          servicePort: 80

Создайте вход, применяя его:

$ kubectl apply -f echo_ingress.yaml

Два сайта теперь должны быть доступны через http. Идите вперед и попробуйте посетить их в браузере.

сертификатор

Следующим шагом является установка Cert-Manager, который впоследствии будет использовать эмитенты, получающие наши сертификаты.

$ kubectl create namespace cert-manager
$ kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.12.0/cert-manager.yaml

Это устанавливает Cert-Manager. Вы можете проверить на запуск стручков:

$ kubectl get pods --namespace cert-manager
NAME                                       READY   STATUS    RESTARTS   AGE
cert-manager-5c47f46f57-n9bb6              1/1     Running   0          31s
cert-manager-cainjector-6659d6844d-6zjh5   1/1     Running   0          31s
cert-manager-webhook-547567b88f-9hj5f      1/1     Running   0          31s

Чтобы проверить, работает ли Cert-Manager, мы можем теперь выпустить сертификаты для тестирования. Сгенерируйте файл с именем «test-cert-manager.yaml»:

# test-cert-manager.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: cert-manager-test
--------
apiVersion: cert-manager.io/v1alpha2
kind: Issuer
metadata:
  name: test-selfsigned
  namespace: cert-manager-test
spec:
  selfSigned: {}
--------
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
  name: selfsigned-cert
  namespace: cert-manager-test
spec:
  commonName: example.com
  secretName: selfsigned-cert-tls
  issuerRef:
    name: test-selfsigned

Примените его и проверьте вывод:

$ kubectl apply -f test-cert-manager.yaml
$ kubectl describe certificate -n cert-manager-test

В событиях описания вывода должны указаны что -то вроде «Сертификата, выпущенного успешно».

Если все в порядке, удалите тестовые ресурсы:

$ kubectl delete -f test-cert-manager.yaml

С помощью Cert-Manager и работающего, нам не хватает окончательной пьесы; Эмитент (или, в нашем случае, мы выберем Clusterissuer, чтобы нам не нужно было указывать пространства имен, и он просто работает Globaly) для получения действительных сертификатов.

Clusterissuer’s

Мы создадим двух эмитентов. Первый (постановка) — проверить, правильно ли работает. В противном случае, если что -то не так, как неправильная настройка DNS, и мы просто используем эмитента производства, мы могли бы временно отказаться от серверов LetsEncrypt.

Создайте следующие два файла и настройте адрес электронной почты:

# staging_issuer.yaml
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    # The ACME server URL
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration
    email: me@example.com
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt-staging
    # Enable the HTTP-01 challenge provider
    solvers:
    - http01:
        ingress:
          class:  nginx
# prod_issuer.yaml
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    # The ACME server URL
    server: https://acme-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration
    email: me@example.com
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt-prod
    # Enable the HTTP-01 challenge provider
    solvers:
    - http01:
        ingress:
          class:  nginx

Создайте эмитентов:

$ kubectl create -f staging_issuer.yaml
$ kubectl create -f prod_issuer.yaml

Распространите ранее созданное «echo_ingress.yaml», чтобы это выглядело так:

# echo_ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: echo-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"    
    cert-manager.io/cluster-issuer: "letsencrypt-staging"
spec:
  tls:
  - hosts:
    - echo1.yourdomain.com
    - echo2.yourdomain.com
    secretName: letsencrypt-staging
  rules:
  - host: echo1.yourdomain.com
    http:
      paths:
      - backend:
          serviceName: echo1
          servicePort: 80
  - host: echo2.yourdomain.com
    http:
      paths:
      - backend:
          serviceName: echo2
          servicePort: 80

Примените корректировки:

$ kubectl apply -f echo_ingress.yaml

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

$ kubectl describe certificate letsencrypt-staging

Через некоторое время в нем должно указано что -то вроде «Сертификата, выпущенного успешно». Затем вы можете перезагрузить сайты в браузере и проверить сертификаты. Теперь они должны быть выпущены поддельные власти LetsEncrypt.

Если это удастся, мы, наконец, сможем дойти до последнего этапа замены эмитента производственным. Отрегулируйте ‘echo_ingress.yaml’ еще раз, переключившись на «LetsEncrypt-prod»:

# echo_ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: echo-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"    
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  tls:
  - hosts:
    - echo1.yourdomain.com
    - echo2.yourdomain.com
    secretName: letsencrypt-prod
  rules:
  - host: echo1.yourdomain.com
    http:
      paths:
      - backend:
          serviceName: echo1
          servicePort: 80
  - host: echo2.yourdomain.com
    http:
      paths:
      - backend:
          serviceName: echo2
          servicePort: 80

Примените корректировки еще раз:

$ kubectl apply -f echo_ingress.yaml

Теперь, опять же, через несколько минут, ваш сайт должен быть выдан действительный сертификат.

$ kubectl describe certificate letsencrypt-prod

Поздравляю! Наконец -то у нас есть наши сайты с действительными сертификатами. Хорошая вещь на этом этапе в том, что она масштабируется. Отныне легко добавить или удалить сайты.

Устранение неисправностей сертификата

Когда в какой -то момент сертификаты не выдаются, они могут помочь узнать, какие компоненты участвуют до успешного выпущения сертификата. В моем случае, например, проблемы не могут быть выполнены. Поэтому просто следуйте руководству на официальном сайте Cert-Manager, пока корень не будет идентифицирован:

https://cert-manager.io/docs/faq/acme/

Бонус — сделайте другие услуги предоставленными за пределами кластера

Скажем, у вас есть какой -то сервис, кроме веб -сайтов — например, база данных — работает внутри вашего кластера и вы хотите сделать его доступным снаружи.

Одним из методов было бы просто прикрепить к нему сервис «Nodeport», но это поставляется с ограничениями, например, только порты за 30000, и если один из ваших узлов будет вниз или будет заменен, IP для доступа к сервису необходимо скорректировать Анкет

Вместо этого мы можем просто добавить произвольные порты в нашу существующую сбалансированную нагрузку службу Nginx-Engress (TCP или UDP). Следовательно, должны быть внесены только некоторые небольшие модификации.

Вот пример открытия TCP -порта 9000 и пересылавшего его в некоторую службу, работающую внутренним в порту 27017.

Ранее мы только что применили ресурсы из URL ‘ https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml ‘и’ https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/cloud-generic.yaml

Они содержат два ресурса, которые являются активными, но должны быть скорректированы и повторно нанесены. Во-первых, создайте файл ‘Ingress-nginx-tcp-configmap.yaml’:

# ingress-nginx-tcp-configmap.yaml
kind: ConfigMap
apiVersion: v1
metadata:
  name: tcp-services
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
data:
  9000: "default/someservice:27017"

Во-вторых, создайте файл с именем ‘Ingress-nginx-service.yaml’:

# ingress-nginx-service.yaml
kind: Service
apiVersion: v1
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  externalTrafficPolicy: Local
  type: LoadBalancer
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: http
    - name: https
      port: 443
      protocol: TCP
      targetPort: https
    - name: proxied-tcp-9000
      port: 9000
      targetPort: 9000
      protocol: TCP

Примените корректировки.

$ kubectl apply -f ingress-nginx-tcp-configmap.yaml
$ kubectl apply -f ingress-nginx-service.yaml

Ваш сервис не может быть доступен извне кластера с тем же IP -адресом, что и веб -сайты.

Оригинал: «https://dev.to/chrisme/setting-up-nginx-ingress-w-automatically-generated-letsencrypt-certificates-on-kubernetes-4f1k»