在使用Let’s Encrypt时,我们知道由它颁发的证书有效期只有90天,因此最好是使用自动化方式去申请和续期。而cert-manager可以将certificates和certificate issuers作为资源类型添加到k8s集群中,这样就能简化证书的申请,续期等操作,它可以确保证书有效并在证书过期前一段时间(可配置)对证书进行续期。
cert-manager除了支持Let’s Encrypt,还支持HashiCorp Vault,Venafi以及私有PKI。
我们直接采用helm方式部署,比较简单,前提是确保相关镜像能获取到。
先添加并更新对应的repo,
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.8.2 \
--set installCRDs=true
等待一会,就可以查看下对应资源是否被创建,
[root@master ~]# kubectl get pod -n cert-manager
NAME READY STATUS RESTARTS AGE
cert-manager-5bb7949947-z2qmx 1/1 Running 1 4d18h
cert-manager-cainjector-5ff98c66d-v98pt 1/1 Running 1 4d18h
cert-manager-startupapicheck-7nbgt 0/1 Completed 0 4d18h
cert-manager-webhook-fb48856b5-lz9sl 1/1 Running 1 4d18h
部署好cert-manager后第一件事要做的就是添加Issuer,也就是证书颁发机构。作为k8s资源类型,Issuer是一个namespace域内的资源,只能给这个namespace的应用颁发证书,如果要用于整个集群,就需要创建ClusterIssuer资源。
这里我们就以Let’s Encrypt为例,使用http-01认证方式,
cat <<EOF > cluster-issuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: user@email.com
privateKeySecretRef:
name: letsencrypt-staging
solvers:
- http01:
ingress:
class: nginx
EOF
然后部署该issuer,
[root@master cert-manager]# kubectl apply -f cluster-issuer.yaml
clusterissuer.cert-manager.io/letsencrypt-staging created
[root@master cert-manager]# kubectl get ClusterIssuer
NAME READY AGE
letsencrypt-staging True 8s
同样对于DNS-01认证,只需要修改最后一部分配置,
cat <<EOF > cluster-issuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: user@email.com
privateKeySecretRef:
name: letsencrypt-staging
solvers:
- dns01:
route53:
region: us-east-1
role: arn:aws:iam::YYYYYYYYYYYY:role/dns-manager
hostedZoneID: AABBCCDD
EOF
我们以example.com域名为例,为该域名申请证书,因为我只是测试,且该域名并非我所有,所以肯定是会失败的,我们只是测试一下,
cat <<EOF > acme-crt.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: acme-crt
namespace: crt-test
spec:
secretName: acme-crt-secret
dnsNames:
- example.com
- foo.example.com
issuerRef:
name: letsencrypt-staging
kind: ClusterIssuer
EOF
然后就是创建证书,我们创建一个测试namespace,
[root@master cert-manager]# kubectl create ns crt-test
[root@master cert-manager]# kubectl apply -f acme-crt.yaml
certificate.cert-manager.io/acme-crt created
[root@master cert-manager]# kubectl get cert -A
NAMESPACE NAME READY SECRET AGE
crt-test acme-crt False acme-crt-secret 9m46s
失败自然是预期的,我们并没有该域名控制权,可以查看cert-manager对应日志,
E0731 09:56:47.019024 1 sync.go:186] cert-manager/challenges "msg"="propagation check failed" "error"="wrong status code '404', expected '200'" "dnsName"="example.com" "resource_kind"="Challenge" "resource_name"="acme-crt-nth9l-1488463194-3621207799" "resource_namespace"="crt-test" "resource_version"="v1" "type"="HTTP-01"
E0731 09:56:47.840614 1 sync.go:186] cert-manager/challenges "msg"="propagation check failed" "error"="failed to perform self check GET request 'http://foo.example.com/.well-known/acme-challenge/hqnyZvnJ8MZ9JwUzrRcNUzwOUcy14TuoxyEtuZgqjBg': Get \"http://foo.example.com/.well-known/acme-challenge/hqnyZvnJ8MZ9JwUzrRcNUzwOUcy14TuoxyEtuZgqjBg\": dial tcp: lookup foo.example.com on 10.96.0.10:53: no such host" "dnsName"="foo.example.com" "resource_kind"="Challenge" "resource_name"="acme-crt-nth9l-1488463194-3800426641" "resource_namespace"="crt-test" "resource_version"="v1" "type"="HTTP-01"
参考文档: