kubernetes - 在具有大量域的 kubernetes 应用程序上自动进行 Letencrypt

标签 kubernetes lets-encrypt caddy

我有一个节点应用程序,它根据域名加载其数据。域配置了 CNAME,如 app.service.com (这是节点应用程序)。

Node 应用程序看到请求域并向 API 发送请求以获取应用程序数据。

例如:domain.com CNAME app.service.com-> 然后节点应用程序向 api 请求 domain.com 数据

问题是为所有域设置 HTTPS(使用 letencrypt)。我认为 cert-manager 可以提供帮助,但不知道如何在无需手动更改每个新域的配置文件的情况下自动执行此操作。

或者有没有更好的方法在 Kubernetes 中实现这一目标?

最佳答案

支持多个域名和/或子域名的标准方法是使用一个 SSL 证书并实现 SAN(主题备用名称)。额外的域名一起存储在 SAN 中。所有 SSL 证书都支持 SAN,但并非所有证书颁发机构都会颁发多域证书。 Let's Encrypt 确实支持 SAN所以他们的证书将满足您的目标。

首先,您必须创建一个 job在我们的集群中,它使用一个图像来运行一个 shell 脚本。该脚本将启动一个 HTTP 服务,创建证书,并将它们保存到一个预定义的 secret 中。您的域和电子邮件是环境变量,因此请务必填写:

apiVersion: batch/v1
kind: Job
metadata:
  name: letsencrypt-job
  labels:
    app: letsencrypt
spec:
  template:
    metadata:
      name: letsencrypt
      labels:
        app: letsencrypt
    spec:
      containers:
      # Bash script that starts an http server and launches certbot
      # Fork of github.com/sjenning/kube-nginx-letsencrypt
      - image: quay.io/hiphipjorge/kube-nginx-letsencrypt:latest
        name: letsencrypt
        imagePullPolicy: Always
        ports:
        - name: letsencrypt
          containerPort: 80
        env:
        - name: DOMAINS
          value: kubernetes-letsencrypt.jorge.fail # Domain you want to use. CHANGE ME!
        - name: EMAIL
          value: jorge@runnable.com # Your email. CHANGE ME!
        - name: SECRET
          value: letsencrypt-certs
      restartPolicy: Never

您有一个作业正在运行,因此您可以创建一个服务来将流量引导至该作业:
apiVersion: v1
kind: Service
metadata:
  name: letsencrypt
spec:
  selector:
    app: letsencrypt
  ports:
  - protocol: "TCP"
    port: 80

这个作业现在可以运行了,但是在我们的工作真正成功之前,你还有三件事需要做,我们可以通过 HTTPs 访问我们的服务。

首先,您需要为作业创建一个 secret 来实际更新和存储我们的证书。由于我们创建 key 时您没有任何证书,因此该 key 将从空开始。
apiVersion: v1
kind: Secret
metadata:
  name: letsencrypt-certs
type: Opaque

# Create an empty secret (with no data) in order for the update to work

其次,您必须将 secret 添加到 Ingress Controller ,以便它获取证书。请记住,是 Ingress Controller 知道我们的主机,这就是为什么需要在此处指定我们的证书。将我们的 secret 添加到 Ingress Controller 看起来像这样:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: "kubernetes-demo-app-ingress-service"
spec:
  tls:
  - hosts:
    - kubernetes-letsencrypt.jorge.fail # Your host. CHANGE ME
    secretName: letsencrypt-certs # Name of the secret
  rules:

最后,您必须通过我们的 Nginx 部署将流量通过主机重定向到作业。为此,您需要在 Nginx 配置中添加一个新路由和一个上游:这可以通过添加 /.well-known/* 通过 Ingress Controller 完成。条目并将其重定向到 letencrypt 服务。这更复杂,因为您还必须向作业添加健康路线,因此您只需通过 Nginx 部署重定向流量:
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
  default.conf: |


...
    # Add upstream for letsencrypt job
    upstream letsencrypt {
      server letsencrypt:80 max_fails=0 fail_timeout=1s;
    }

    server {
      listen 80;


...
      # Redirect all traffic in /.well-known/ to letsencrypt
      location ^~ /.well-known/acme-challenge/ {
        proxy_pass http://letsencrypt;
      }
    }

应用所有这些更改后,销毁 Nginx Pod 以确保 ConfigMap 在新 Pod 中正确更新:
$ kubectl get pods | grep ngi | awk '{print $1}' | xargs kubectl delete pods

确保它有效。

为了验证这是否有效,您应该确保作业确实成功。您可以通过 kubectl 获取作业来完成此操作,您还可以查看 Kubernetes 仪表板。
$ kubectl get job letsencrypt-job
NAME              DESIRED   SUCCESSFUL   AGE
letsencrypt-job   1         1            1d

您还可以检查 key 以确保已正确填充证书。您可以通过 kubectl 或仪表板执行此操作:
$ kubectl describe secret letsencrypt-certs

Name:   letsencrypt-certs
Namespace:  default
Labels:   <none>
Annotations:
Type:   Opaque
Data
====
tls.crt:  3493 bytes
tls.key:  1704 bytes

现在您可以看到证书已成功创建,您可以执行整个过程的最后一步。为了让 Ingress Controller 获取 key 中的更改(从没有数据到拥有证书),您需要更新它以便重新加载。为此,我们只需将时间戳作为标签添加到 Ingress Controller :
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: "kubernetes-demo-app-ingress-service"
  labels:
    # Timestamp used in order to force reload of the secret
    last_updated: "1494099933"
...

请看:kubernetes-letsencrypt .

关于kubernetes - 在具有大量域的 kubernetes 应用程序上自动进行 Letencrypt,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59693665/

相关文章:

docker - 从Docker运行时如何禁用TLS?

docker - 无法在 Kubernetes 中使用 hostPath '/var/lib/docker/containers' 作为卷

docker - 由未知权威机构签署的 x509 证书 - Kubernetes

kubernetes - 将 kubernetes 入口分配给特定节点

redirect - 带有 HTTP 和 HTTPS 但没有重定向的 Nginx

php - Laravel Valet 不工作。 127.0.0.1 连接被拒绝

amazon-web-services - 我是否可以在不拥有域的情况下在 AWS 提供的 ALB 子域上设置 SSL?

docker - 即使容器摘要相同,即使指定了不同的图像标签,也请禁用Kubernetes Pod更新

ssl - 通过 DNS 为 Route53 颁发证书时,Certbot 无法找到 AWS 凭证

Docker Traefik 和 Letsencrypt 通配符