Aws-cert-manager

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску


Для Ingress требуется автоматически выписывать сертефикаты для доменов которые "Хостятся" на нем

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

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

Возможные варианты решения

  • Использовать независимое от cloud-провайдера решение, Let's encrypt.
    • В завимсимости от того где лежит DNS-зона и как ей можно управлять, может требовать или не требовать ручной правкии зоны.
    • В случае если зона хостится на AWS Route53 возможно применить например такую автоматизацию обновления зоны
    • К плюсам можно отнести то что решение будет работать на любом клауде, не привязано к провайдеру.
    • Список возможных Issuers досаточно широк (https://cert-manager.io/docs/configuration/issuers/), для тестирования можно например использовать локально развернутый Hashicorp Vault


  • Использовать сертефикаты от AWS (это пока не реализовано)

cert-manager

Для решения этой задачи существует cert-manager
Примерный принцип работы (насколько я его понимаю)

  • Установка в том чимсле создания Custom Resource Definition (далее CRD)
  • Cоздается ресусурс типа Issuer или ClusterIssuer — описывает, откуда брать сертификаты
    • Разница в том что Issuer доступен только внутри namespace, в моем случае когда все сертефикаты нужны для нескольких копий приложения ("окружений"), например dev.domain.tld, staging.domain.tld, qa.domain.tld нужно будет изменить ClusterIssuer на Issuer. Пока окружение одно это не важно, но как только их несколько то не хочется иметь один сертефикат на всех с длинным списком Altnames (но это требует проверки)
  • После создания Certificate-ресурса — cert-manager следит за ним и выполняет выпуск согласно настройкам ресурса, результат сохраняет в Secret

cert-manager автоматически:

  • делает HTTP или DNS-проверку чтобы подтвердить владение доменом (в этом случае HTTP так как у него нет доступа к управлению ресурсами зоны!) Как именно определено в поле solvers
  • получает сертификат от CA, определенного в поле acme
  • сохраняет в Secret TODO
  • Мониторит и продлевает его до истечения срока действия.


Установка

helm repo add jetstack https://charts.jetstack.io
helm repo update
helm \
   install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --set installCRDs=true

Пример ClusterIssuer

Достаточно простой объект

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-http-cert-issuer
spec:
  acme:
    email: sirmax123@gmail.com
    privateKeySecretRef:
      name: letsencrypt-http
    server: https://acme-v02.api.letsencrypt.org/directory
    solvers:
    - http01:
        ingress:
          class: nginx
  • имя можно выбрать произвольное
  • email: sirmax123@gmail.com раньше был нужен что б Let's Encrypt мог прислать оповещение, но он уже давно это отключил и сецчас это просто ненужное но обязательное поле.
  • solvers способ подтверждения владения доменом
  • имя секрета в котором содержится ключ аккаунта, он создается автоматически если его нет. В целом его можно пересоздать, но тогда можно уперется в число запросов новых аккаунтов, потребуется повторная валидация домена и может еще что то, так что лучше его не удалять.

Icon-caution.gif

  • Не путать с TLS-сертификатами для доменов — они хранятся в другом секрете, указанном в Certificate.spec.secretName.
  • Один и тот же privateKeySecretRef можно использовать для многих доменов/сертификатов, чтобы сохранить "один аккаунт".

Генерация сертефикатов

Аннотация Ingress

Для того что бы включить генерацию сертефикатов требуется указать аннотацию у Ingress, в которой указать имя желаемого Issuer / ClusterIssuer

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-http-cert-issuer


При этом cert-manager проверить есть ли объект типа Certificate и если нет создаст его на основе значения
в секции .spec.tls.mpp-staging-tls объекта Ingress
Например, для такого Ingress:

  tls:
  - hosts:
    - be.staging.mydomain.tld
    - login.staging.mydomain.tld
    - log.staging.mydomain.tld
    - content.staging.mydomain.tld
    - fe.staging.mydomain.tld
    - ca.staging.mydomain.tld
    - shootin.mydomain.tld
    - seeble.staging.myseconddomain.tld
    - seeble2.staging.myseconddomain.tld
    secretName: mpp-staging-tls

будет создан объект типа Certificate (в том же namespace где находится Ingress)

kubectl -n mpp-staging get Certificate
NAME              READY   SECRET            AGE
mpp-staging-tls   True    mpp-staging-tls   6d20h

Icon-caution.gif

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

Решение простое - нет секрета, не включится https (но http продолжит работать).
Когда Cert-manager отработает, он создаст все нужные объекты)

Объект Certificate

Объект создается в том же namespace что и Ingress

kubectl -n mpp-staging get certificates mpp-staging-tls   -o wide
NAME              READY   SECRET            ISSUER                         STATUS                                          AGE
mpp-staging-tls   True    mpp-staging-tls   letsencrypt-http-cert-issuer   Certificate is up to date and has not expired   6d20h