Cert-Manager 自动管理证书
前言
上一篇文章中说到了,Traefik 可以实现自动化 HTTPS 的加密,其原理是使用 Let’s Encrypt。
然而由于 Traefik 在开启 LE 时,不仅需要一个 PVC 用于存储创建的证书,并且由于依赖了 PVC 的缘故,不支持多副本扩容。
所以我们需要一个更加优秀的 HTTPS 方案,就是今天我们的主角 Cert-Manager 了。
原理介绍
Cert Manger 支持 HTTPS 的方式比较多,有 自签名 / CA 根证书 / Vault / Venafi / 外部引入 / ACME 的方式。
由于我们需要自动化 HTTPS,所以原理上和上一期一样,需要使用 ACME 自动化配置 Let’s Encrypted。
CertManage 名词
Issuer
Issuer 直接翻译过来就是颁发者,也就是用来颁发证书的单元。普通的 Issuer 是有命名空间隔离的资源。所以在整个集群中使用的话,需要 ClusterIssuer
Certificate
Certificate 就是证书的概念了,证书需要引用 Issuer 来颁发证书。
Certificate 引用了一个同命名空间的 Secret (不存在会自动创建) 用来存储 X509 证书。所以不用担心证书的存储问题,它使用了 Kubernetes 原生的方式来存储证书公私钥敏感信息。
CertificateRequest
CertificateRequest 是一个用来记录证书向 Issuer 请求资源的过程。
在一般情况下,都不需要手动创建,可以通过观察 CertificateRequest 的状态来判断证书的申请结果
安装 Traefik
Traefik 安装可以参考 Traefik Automatic Https
安装 Cert-Manager
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.11.0 \
--set installCRDs=true
创建 ClusterIssuer
Issuer 和 ClusterIssuer 一个是命名空间维度的,一个是集群维度的,这里我们为了方便直接创建 Cluster Issuer
我们使用 Acme 方式,这样能够自动签发证书
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: acme
spec:
acme:
email: <your-emaill-address>
preferredChain: ""
privateKeySecretRef:
name: acme-cert-key
server: https://acme-v02.api.letsencrypt.org/directory
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
key: api-token
name: cf-nsl-xyz-api-token
给 Ingress/IngressRoutes/GatewayAPI 签发证书
对于 Ingress 和 GatewayAPI 而言, Cert-Manager 已经做了集成,所以我们只需要在资源上添加注解即可,如下所示:
Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
# add an annotation indicating the issuer to use.
cert-manager.io/cluster-issuer: nameOfClusterIssuer
name: myIngress
namespace: myIngress
spec:
rules:
- host: example.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: myservice
port:
number: 80
tls: # < placing a host in the TLS config will determine what ends up in the cert's subjectAltNames
- hosts:
- example.com
secretName: myingress-cert # < cert-manager will store the created certificate in this secret.
Gateway
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: Gateway
metadata:
name: example
annotations:
cert-manager.io/issuer: foo
spec:
gatewayClassName: foo
listeners:
- name: http
hostname: example.com
port: 443
protocol: HTTPS
allowedRoutes:
namespaces:
from: All
tls:
mode: Terminate
certificateRefs:
- name: example-com-tls
对于 IngressRoute 而言,我们需要手动创建 Certificate, 如下所示
IngressRoute
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: example
spec:
entryPoints: # We listen to requests coming from ports 80 and 443
- web
- websecure
routes:
- match: Host(`example.domain.com`)
kind: Rule
services:
- name: example # Requests will be forwarded to this service
port: 80
tls:
secretName: example-cert
Certificate
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: example-cert
spec:
dnsNames:
- example.domain.com
secretName: example-cert
issuerRef:
name: acme
kind: ClusterIssuer