iac/infrastructure/cert-manager/aero/configs/clusterissuer-letsencrypt.yaml
emelinda 565faa0e17 feat(aero): базовый слой контура — Vault↔k3s, GitOps-синхронизация, выход наружу
Топология k3s: 1 мастер + 2 воркера (убран k3s-worker-3 с томом).

Vault ↔ k3s. Vault живёт в compose, вне кластера, поэтому получает
статический IP 172.28.0.13, DNS-мост в namespace vault и token reviewer
(SA vault-auth + system:auth-delegator). Ansible включает auth/kubernetes,
передавая адрес apiserver, CA и JWT ревьюера явно, и заводит политику с
ролями. Секрет token reviewer'а читается целиком в JSON: вариант
-o jsonpath={.data.ca\.crt} НЕ работает — модуль command разбирает строку
через shlex, съедает обратный слэш, kubectl возвращает пустую строку с
кодом 0, и отказ остаётся незамеченным до падения vault write.

Синхронизация репозитория в gitea. Нужное подмножество путей (замыкание
ссылок clusters/aero) едет архивом на хост и коммитится там: gitea не
публикуется дальше самого хоста, контур остаётся замкнутым. flux-bootstrap
вынесен в отдельную волну — до неё Vault получает auth/kubernetes, а
репозиторий наполняется, иначе первая реконсиляция падает на пустом репо.

Инфраструктура: vault-agent-injector (чарт vault-contour в режиме внешнего
Vault), local-path-provisioner взамен встроенного в k3s (--disable=
local-storage; путь данных прежний), rabbitmq и minio с кредами из Vault.

Выход наружу: порты 80/443 k3s-server опубликованы (istio ingressgateway
занимает эти hostPort), общий contour-gateway на wildcard-хост, сертификат
Let's Encrypt через http01. Имена в сертификате перечислены явно —
http01 не выдаёт wildcard, для них нужен dns01.

Разорваны два дедлока Flux: infra-configs больше не зависит от
infra-controllers (издатели не должны зависеть от здоровья чартов, которые
их используют), istio-config получил disableWait.

Модули ядра iptable_nat и смежные грузятся на хосте: ноды k3s —
контейнеры, istio-init правит iptables через ядро хоста, а на RED OS 8
(nf_tables) legacy-модули не загружены, из-за чего любой под с
istio-injection навсегда вставал в Init:Error.

Собственные Gateway/VirtualService/Certificate чартов rabbitmq и dashboard
отключены — маршрутизация описана централизованно. У rabbitmq это сделано
postRenderers, а не values: kustomize нормализует null в {}, а пустую карту
Helm сливает с дефолтами, возвращая их целиком.
2026-08-08 09:36:08 +03:00

48 lines
3.0 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Боевой издатель контура: Let's Encrypt через ACME.
#
# Раньше здесь был только внутренний CA (clusterissuer-ca.yaml) — исходили из
# того, что контур закрытый и до ACME-сервера не достучаться. Это оказалось не
# так: домены контура резолвятся в публичном DNS
# sarex.local.lonsdaleites.ru → 158.160.38.249
# *.sarex.local.lonsdaleites.ru → 158.160.38.249
# а порты 80/443 хоста опубликованы наружу (см. docker-compose.yaml, k3s-server).
# Значит http01-проверка проходит, и сертификаты можно брать настоящие.
#
# ВАЖНО ПРО WILDCARD: решатель http01 принципиально НЕ выдаёт wildcard-
# сертификаты — Let's Encrypt требует для них dns01. Поэтому сертификат контура
# перечисляет имена явно (см. infrastructure/istio-config/aero). Wildcard
# остался только в hosts самого Gateway, где сертификат не нужен.
#
# Внутренний CA (aero-ca-issuer) НЕ удалён: он остаётся запасным вариантом на
# случай, когда ACME недоступен, и для внутренних имён, которых нет в публичном
# DNS.
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-issuer-istio
spec:
acme:
# На этот адрес Let's Encrypt шлёт предупреждения об истечении.
email: "emelinda1990@gmail.com"
# ОТДЕЛЬНОЕ имя секрета, НЕ общепринятое в репозитории letsencrypt-secret-key.
#
# Тот секрет создаёт сам чарт cert-manager-infra (метки managed-by=Helm,
# аннотация helm.sh/resource-policy: keep) и кладёт в поле tls.key
# ЗАГЛУШКУ — невалидный PEM. cert-manager читает её как ключ ACME-аккаунта
# и падает:
# Account private key is invalid: error decoding private key PEM block
# Reason: ErrVerifyACMEAccount
# Удалить заглушку нельзя: чарт пересоздаст её на следующем апгрейде и
# затрёт настоящий ключ аккаунта. Поэтому издателю выдан собственный
# секрет — его создаёт и владеет им cert-manager, Helm его не трогает.
privateKeySecretRef:
name: letsencrypt-issuer-istio-account-key
server: "https://acme-v02.api.letsencrypt.org/directory"
solvers:
# class istio — challenge-Ingress обслуживает istio-ingressgateway,
# тот самый, что занимает hostPort 80/443 на k3s-server.
- http01:
ingress:
class: istio