Blog CrtMgr - Zarządzanie Certyfikatami SSL/TLS

Eksperckie wskazówki dotyczące zarządzania certyfikatami SSL/TLS, rodzajów certyfikatów, wdrażania i najlepszych praktyk

Automatyzacja Certyfikatów SSL w Kubernetes z cert-manager

Kubernetes cert-manager Automatyzacja Let's Encrypt SSL DevOps

Jeśli kiedykolwiek musiałeś ręcznie aktualizować Kubernetes Secret z certyfikatem TLS - a potem pamiętać żeby zrobić to samo na stagingu, i przy okazji sprawdzić czy na produkcji certyfikat jeszcze nie wygasł - to wiesz o czym mówimy. cert-manager eliminuje ten koszmar całkowicie. Zamiast ręcznego żonglowania certyfikatami, deklarujesz co chcesz i cert-manager robi resztę automatycznie.

Czym Jest cert-manager?

cert-manager to natywny kontroler Kubernetes, który automatyzuje cały cykl życia certyfikatów TLS - od wystawienia, przez monitorowanie, aż po automatyczne odnowienie. Myśl o nim jako o osobnym administratorze certyfikatów, który nie śpi, nie idzie na urlop i nie zapomina o renewalach.

Narzędzie obsługuje Let’s Encrypt (ACME), HashiCorp Vault, Venafi, prywatne CA oraz własne integracje. Automatycznie wydaje i odnawia certyfikaty przed wygaśnięciem, integrując się z Ingress bez ręcznej interwencji. Całość jest w pełni zintegrowana z kubectl i gotowa na GitOps.

Instalacja cert-manager

Instalacja jest prosta i zajmuje kilka minut. Helm to najprostsze podejście - kilka komend i gotowe.

Przed instalacją potrzebujesz klastra Kubernetes w wersji 1.22+, skonfigurowanego kubectl i praw administratora. Zalecany jest również Helm 3.x.

Instalacja przez Helm

Najprostszy sposób to użycie Helm:

# Dodaj repozytorium Helm
helm repo add jetstack https://charts.jetstack.io
helm repo update

# Zainstaluj CRDs
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.3/cert-manager.crds.yaml

# Zainstaluj cert-manager
helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --version v1.13.3

# Weryfikacja instalacji
kubectl get pods -n cert-manager

Instalacja przez kubectl

Jeśli wolisz czysty YAML:

# Instalacja cert-manager z wszystkimi komponentami
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.3/cert-manager.yaml

# Sprawdzenie statusu
kubectl get pods -n cert-manager
kubectl get crds | grep cert-manager

Po instalacji powinieneś zobaczyć trzy pody:

  • cert-manager
  • cert-manager-cainjector
  • cert-manager-webhook

Konfiguracja Let’s Encrypt

ClusterIssuer vs Issuer

cert-manager oferuje dwa typy zasobów do wydawania certyfikatów:

Issuer - działa w ramach jednego namespace ClusterIssuer - działa w całym klastrze (zalecane)

Konfiguracja ClusterIssuer dla Let’s Encrypt

Zacznijmy od środowiska staging (do testów):

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    # Serwer staging Let's Encrypt (wyższe limity, certyfikaty testowe)
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    email: admin@example.com  # Twój email do powiadomień
    
    # Secret do przechowywania klucza prywatnego ACME
    privateKeySecretRef:
      name: letsencrypt-staging
    
    # HTTP-01 challenge
    solvers:
    - http01:
        ingress:
          class: nginx  # lub traefik, zależnie od Ingress Controller

Dla produkcji:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: admin@example.com
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
    - http01:
        ingress:
          class: nginx

Zastosuj konfigurację:

kubectl apply -f clusterissuer-staging.yaml
kubectl apply -f clusterissuer-prod.yaml

# Sprawdź status
kubectl get clusterissuer
kubectl describe clusterissuer letsencrypt-prod

Automatyczne Certyfikaty dla Ingress

Podstawowa Konfiguracja Ingress

Najprostszy sposób to dodanie adnotacji do Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-ingress
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    # Opcjonalnie: przekierowanie HTTP -> HTTPS
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - myapp.example.com
    secretName: myapp-tls  # cert-manager utworzy ten Secret automatycznie
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: myapp-service
            port:
              number: 80

Po zastosowaniu:

kubectl apply -f ingress.yaml

# Monitoruj proces wydawania certyfikatu
kubectl get certificate
kubectl describe certificate myapp-tls

# Sprawdź zdarzenia
kubectl get events --sort-by='.lastTimestamp'

Ręczne Zarządzanie Certyfikatami

Możesz też utworzyć zasób Certificate bezpośrednio:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: myapp-cert
  namespace: default
spec:
  secretName: myapp-tls
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer
  commonName: myapp.example.com
  dnsNames:
  - myapp.example.com
  - www.myapp.example.com
  # Automatyczne odnawianie 30 dni przed wygaśnięciem
  renewBefore: 720h  # 30 dni

DNS-01 Challenge dla Wildcard Certificates

Dla certyfikatów wildcard (*.example.com) musisz użyć DNS-01 challenge:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-dns
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: admin@example.com
    privateKeySecretRef:
      name: letsencrypt-dns
    solvers:
    - dns01:
        cloudflare:
          email: admin@example.com
          apiTokenSecretRef:
            name: cloudflare-api-token
            key: api-token

Stwórz Secret z API token Cloudflare:

kubectl create secret generic cloudflare-api-token \
  --from-literal=api-token='your-cloudflare-api-token'

Certificate dla wildcard:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: wildcard-cert
spec:
  secretName: wildcard-tls
  issuerRef:
    name: letsencrypt-dns
    kind: ClusterIssuer
  dnsNames:
  - "example.com"
  - "*.example.com"

Zanim przejdziesz do zaawansowanych konfiguracji, warto pomyśleć o monitoringu. cert-manager eksportuje metryki Prometheus, które możesz wpiąć w swój istniejący stack monitoringu. Szczegóły znajdziesz w artykule o monitoringu certyfikatów SSL z Prometheus i Grafana - tam opisujemy jak skonfigurować alerty i dashboardy.

Monitorowanie i Debugging

Sprawdzanie Statusu Certyfikatów

# Lista wszystkich certyfikatów
kubectl get certificate --all-namespaces

# Szczegóły certyfikatu
kubectl describe certificate myapp-tls

# Status CertificateRequest
kubectl get certificaterequest
kubectl describe certificaterequest <name>

# Status Order (ACME)
kubectl get order
kubectl describe order <name>

# Status Challenge
kubectl get challenge
kubectl describe challenge <name>

Logi cert-manager

# Główny kontroler
kubectl logs -n cert-manager deploy/cert-manager

# Webhook
kubectl logs -n cert-manager deploy/cert-manager-webhook

# CA injector
kubectl logs -n cert-manager deploy/cert-manager-cainjector

# Śledzenie logów na bieżąco
kubectl logs -n cert-manager deploy/cert-manager -f

Najczęstsze Problemy

Problem 1: Certificate w stanie “Pending”

# Sprawdź CertificateRequest
kubectl get certificaterequest
kubectl describe certificaterequest <name>

# Sprawdź Order
kubectl get order
kubectl describe order <name>

Często przyczyną są:

  • Błędna konfiguracja DNS
  • Brak dostępu do domeny przez Let’s Encrypt
  • Problemy z Ingress Controller

Problem 2: HTTP-01 challenge fails

# Sprawdź czy challenge pod został utworzony
kubectl get pods | grep cm-acme-http-solver

# Sprawdź czy Ingress dla challenge został utworzony
kubectl get ingress

Rozwiązanie:

  • Sprawdź czy domena wskazuje na klaster
  • Sprawdź czy port 80 jest otwarty
  • Sprawdź logi Ingress Controller

Problem 3: Zbyt wiele żądań (rate limiting)

Let’s Encrypt ma limity:

  • 50 certyfikatów na domenę tygodniowo
  • 5 duplikatów tygodniowo

Rozwiązanie:

  • Używaj staging podczas testów
  • Planuj wdrożenia produkcyjne

Integracja z Monitoringiem

Prometheus Metrics

cert-manager eksportuje metryki:

apiVersion: v1
kind: Service
metadata:
  name: cert-manager-metrics
  namespace: cert-manager
  labels:
    app: cert-manager
spec:
  ports:
  - name: metrics
    port: 9402
    targetPort: 9402
  selector:
    app: cert-manager

ServiceMonitor dla Prometheus Operator:

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: cert-manager
  namespace: cert-manager
spec:
  selector:
    matchLabels:
      app: cert-manager
  endpoints:
  - port: metrics
    interval: 30s

Grafana Dashboard

Importuj dashboard z ID: 11001 (cert-manager overview)

Kluczowe metryki:

  • certmanager_certificate_expiration_timestamp_seconds - data wygaśnięcia
  • certmanager_certificate_ready_status - status gotowości
  • certmanager_http_acme_client_request_count - żądania ACME
  • certmanager_controller_sync_call_count - wywołania synchronizacji

Alerting

Przykładowy alert Prometheus:

groups:
- name: cert-manager
  rules:
  - alert: CertificateExpiryIn7Days
    expr: (certmanager_certificate_expiration_timestamp_seconds - time()) / 86400 < 7
    for: 1h
    labels:
      severity: warning
    annotations:
      summary: "Certificate {{ $labels.name }} expires in less than 7 days"
      
  - alert: CertificateNotReady
    expr: certmanager_certificate_ready_status == 0
    for: 10m
    labels:
      severity: critical
    annotations:
      summary: "Certificate {{ $labels.name }} is not ready"

Zaawansowane Konfiguracje

Własne CA (Private Certificate Authority)

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: private-ca
spec:
  ca:
    secretName: ca-key-pair

Stworzenie CA:

# Wygeneruj klucz i certyfikat CA
openssl genrsa -out ca.key 4096
openssl req -new -x509 -key ca.key -out ca.crt -days 3650

# Stwórz Secret
kubectl create secret tls ca-key-pair \
  --cert=ca.crt \
  --key=ca.key \
  --namespace=cert-manager

HashiCorp Vault Integration

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: vault-issuer
spec:
  vault:
    server: https://vault.example.com
    path: pki/sign/example-dot-com
    auth:
      kubernetes:
        mountPath: /v1/auth/kubernetes
        role: cert-manager
        secretRef:
          name: cert-manager-vault-token
          key: token

Certificate Policies

Wymuszanie standardów organizacji:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: myapp-cert
spec:
  secretName: myapp-tls
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer
  dnsNames:
  - myapp.example.com
  # Minimalna długość klucza
  privateKey:
    algorithm: RSA
    size: 4096
  # Dodatkowe rozszerzenia
  usages:
  - digital signature
  - key encipherment
  - server auth
  - client auth

Podobne transformacje przeprowadzano w firmach różnej wielkości. Sprawdź nasze studium przypadku automatyzacji certyfikatów w firmie e-commerce - tam znajdziesz bardziej szczegółowe rozliczenie kosztów, oszczędności i pułapek, na które warto uważać.

Best Practices

1. Używaj Namespace dla cert-manager

# Wszystko w dedykowanym namespace
kubectl create namespace cert-manager

2. Limity Zasobów

resources:
  limits:
    cpu: 100m
    memory: 128Mi
  requests:
    cpu: 50m
    memory: 64Mi

3. Backup Secrets

# Backup certyfikatów
kubectl get secrets -n default -o yaml > certificates-backup.yaml

# Lub użyj Velero do automatycznych backupów

4. Staging przed Produkcją

Zawsze testuj na Let’s Encrypt staging przed produkcją.

5. Monitoring i Alerting

Monitoruj:

  • Daty wygaśnięcia
  • Status certyfikatów
  • Błędy odnowień

6. Dokumentacja

Prowadź dokumentację:

  • Lista używanych issuerów
  • Procedury odnowienia ręcznego (na wypadek awarii)
  • Kontakty i eskalacja

Migracja z Istniejących Certyfikatów

Import Istniejącego Certyfikatu

# Stwórz Secret z istniejącym certyfikatem
kubectl create secret tls existing-cert \
  --cert=path/to/cert.crt \
  --key=path/to/cert.key

# Stwórz Certificate zarządzany przez cert-manager
kubectl apply -f - <<EOF
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: existing-cert
spec:
  secretName: existing-cert
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer
  dnsNames:
  - example.com
EOF

Stopniowa Migracja

  1. Zainstaluj cert-manager obok istniejącego rozwiązania
  2. Skonfiguruj ClusterIssuers
  3. Testuj na środowisku staging
  4. Migruj pojedyncze aplikacje
  5. Monitoruj i waliduj
  6. Usuń stare rozwiązanie

Case Study: Migracja 50+ Aplikacji

Wyzwanie: Firma miała 50+ aplikacji w Kubernetes, każda z ręcznie zarządzanymi certyfikatami.

Rozwiązanie:

  1. Instalacja cert-manager
  2. Konfiguracja ClusterIssuers (prod + staging)
  3. Skrypt migracyjny dla wszystkich Ingress
  4. Automatyczne dodawanie adnotacji
  5. Monitoring w Grafana

Wyniki:

  • 95% redukcja czasu zarządzania certyfikatami
  • 0 incydentów z wygasłymi certyfikatami w ciągu roku
  • Ujednolicone podejście do SSL/TLS
  • Pełna automatyzacja odnowień

Kod skryptu migracyjnego:

#!/bin/bash
# migrate-ingresses.sh

for ingress in $(kubectl get ingress -A -o json | jq -r '.items[] | "\(.metadata.namespace)/\(.metadata.name)"'); do
  namespace=$(echo $ingress | cut -d/ -f1)
  name=$(echo $ingress | cut -d/ -f2)
  
  echo "Migrating $namespace/$name"
  
  kubectl annotate ingress $name -n $namespace \
    cert-manager.io/cluster-issuer=letsencrypt-prod \
    --overwrite
    
  echo "Done: $namespace/$name"
done

cert-manager to jeden z tych kontrolerów Kubernetes, które po wdrożeniu po prostu działają - i szybko zapominasz, że kiedyś certyfikaty były problemem. Automatyczne odnawianie, natywna integracja z Ingress, wsparcie dla Let’s Encrypt i prywatnych CA - to kompletne rozwiązanie dla każdego klastra Kubernetes obsługującego ruch HTTPS. Zacznij od stagingu, waliduj na produkcji, dodaj monitoring i ciesz się ciszą. A dla zewnętrznego monitoringu “oczami użytkownika”, CrtMgr doskonale uzupełnia cert-manager - weryfikuje że certyfikat jest nie tylko wystawiony, ale faktycznie widoczny z zewnątrz.

Related Articles