当前位置: 首页 > 工具软件 > cert-manager > 使用案例 >

cert-manager使用

杨乐
2023-12-01

1 关于cert-manager

在使用Let’s Encrypt时,我们知道由它颁发的证书有效期只有90天,因此最好是使用自动化方式去申请和续期。而cert-manager可以将certificates和certificate issuers作为资源类型添加到k8s集群中,这样就能简化证书的申请,续期等操作,它可以确保证书有效并在证书过期前一段时间(可配置)对证书进行续期。

cert-manager除了支持Let’s Encrypt,还支持HashiCorp Vault,Venafi以及私有PKI。

2 部署cert-manager

我们直接采用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

3 添加Issuer

部署好cert-manager后第一件事要做的就是添加Issuer,也就是证书颁发机构。作为k8s资源类型,Issuer是一个namespace域内的资源,只能给这个namespace的应用颁发证书,如果要用于整个集群,就需要创建ClusterIssuer资源。

3.1 HTTP-01 验证

这里我们就以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
  • metadata.name 设置证书颁发机构的名称,后面创建证书时需要引用它
  • spec.acme.server 设置acme协议的API地址,我们这里用 Let’s Encrypt的测试环境,如果是生产环境,地址是,https://acme-v02.api.letsencrypt.org/directory
  • spec.acme.email 设置用户邮箱,用于证书过期提醒,或者续期时出错告知。cert-manager会通过acme协议自动为证书续期,所以主要关注续期时是否有异常。
  • spec.acme.privateKeySecretRef 设置k8s集群中存放颁发的私钥的secret名称
  • spec.acme.solvers 设置通过acme协议颁发证书时使用的认证方式为http01
  • spec.acme.solvers.http01.ingress 设置认证时使用的ingress class名称,我们默认部署的ingress-nginx的class name就是nginx

然后部署该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

3.2 DNS-01 验证

同样对于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
  • spec.acme.solvers 设置通过acme协议颁发证书时使用的认证方式为dns01,并且使用route53作为dns提供商
  • route53.region 设置对应的AWS区域
  • route53.role 设置访问AWS的role,当然也可以使用access key的方式,但是需要在集群中保存登录凭证,存在一定风险
  • route53.accessKeyID 设置访问AWS的key ID
  • route53.secretAccessKeySecretRef 设置访问AWS的secretAccessKey
  • route53.hostedZoneID 设置该issuer在AWSroute53的作用域

4 创建证书

我们以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
  • spec.issuerRef 设置证书的名字
  • spec.dnsNames 设置需要申请证书的域名
  • spec.issuerRef 设置证书颁发机构,也就是我们上面创建的issuer,记得名字要匹配

然后就是创建证书,我们创建一个测试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" 

参考文档:

  1. https://cert-manager.io/docs/
  2. https://cert-manager.io/docs/installation/helm/#option-2-install-crds-as-part-of-the-helm-release
  3. https://cert-manager.io/docs/configuration/acme/
  4. https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.Issuer
  5. https://cert-manager.io/docs/configuration/acme/dns01/route53/
 类似资料: