「Kubernetes」- 部署 cert-manager 组件(v1.7)

  CREATED BY JENKINSBOT

问题描述

该笔记将记录:在 Kubernetes Cluster 1.22 中,部署 cert-manager 1.7 组件,以及相关问题解决办法。

解决方案

环境信息

版本:cert-manager v1.7 (Supported Kubernetes versions: 1.18-1.23) / Kubernetes Cluster v1.22.3-aliyun.1

# 07/05/2022 适用于 cert-mananger v1.8.2 / kubernetes 1.20.15

补充说明

1)作为系列部署资源,cert-manager 运行在 Kubernetes Cluster 中,并利用 CRD 来配置 CA 并请求证书;
2)部署方式:我们使用官方文档中推荐的 cmctl 命令,不再使用原始的 YAML 清单文件;
3)在部署 cert-manager 组件之后,需要创建代表 CA 的 Issuer 或 ClusterIssuer 资源;
4)在集群中部署多个 cert-manager 实例会出现意外行为(以前 v1.3 文档提到过,该版本不清楚是否存在该限制);

准备工作

安装命令:

OS=$(go env GOOS); ARCH=$(go env GOARCH); curl -sSL -o cmctl.tar.gz https://github.com/cert-manager/cert-manager/releases/download/v1.7.2/cmctl-$OS-$ARCH.tar.gz
tar xzf cmctl.tar.gz
sudo mv cmctl /usr/local/bin

第一步、部署组件

// ---------------------------------------------------------------------------- // 通过 cmctl 部署

// 最开始我们采用 cmctl 部署,但是后续我们将不再采用 cmctl 工具进行部署,原因是:
// 1)官方暂且未提供通过 cmctl 升级 cert-manager 的方法;
// 2)在升级实践中,仍旧需要通过 HELM 进行升级,而且需要单独升级 CRD 资源;

# cmctl x install --dry-run
...

# cmctl x install --version v1.7
Creating the cert-manager CRDs
creating 6 resource(s)
Clearing discovery cache
...
https://cert-manager.io/docs/usage/ingress/

// ---------------------------------------------------------------------------- // 通过 HELM 部署

helm repo add jetstack https://charts.jetstack.io
helm repo update

helm pull jetstack/cert-manager --version v1.7.3                                # cert-manager-v1.7.3.tgz

helm show values ./cert-manager-v1.7.3.tgz > cert-manager-v1.7.3.helm-values.yaml
...(1)installCRDs: true

helm --namespace cert-manager                                                  \
    install cert-manager ./cert-manager-v1.7.3.tgz                             \
    -f cert-manager-v1.7.3.helm-values.yaml                                    \
    --create-namespace

helm --namespace cert-manager                                                  \
    upgrade cert-manager ./cert-manager-v1.7.3.tgz                             \
    -f cert-manager-v1.7.3.helm-values.yaml

第二步、验证安装

# cmctl check api --wait=2m
The cert-manager API is ready

# kubectl get pods --namespace cert-manager
NAME                                       READY   STATUS    RESTARTS   AGE
cert-manager-75cf8df6b6-t2xns              1/1     Running   0          2m37s
cert-manager-cainjector-857f5bd88c-5xzd7   1/1     Running   0          2m37s
cert-manager-webhook-5cd99556d6-s6jf5      1/1     Running   0          2m37s

第三步、签发测试

验证方法:通过创建自签名证书,并检查证书是否能够自动签发(参考 Verifying the Installation 文档,以获取具体细节)

我们有使用手工方式来验证(我们通过文档中提到的社区工具来验证,但是失败):

# cat > test-resources.yaml  <<EOF
apiVersion: v1
kind: Namespace
metadata:
  name: cert-manager-test
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: test-selfsigned
  namespace: cert-manager-test
spec:
  selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: selfsigned-cert
  namespace: cert-manager-test
spec:
  dnsNames:
    - example.com
  secretName: selfsigned-cert-tls
  issuerRef:
    name: test-selfsigned
EOF

# kubectl apply -f test-resources.yaml
...

# kubectl describe -n cert-manager-test certificates
...
Status:
  Conditions:
    Last Transition Time:  2022-04-01T09:51:50Z
    Message:               Certificate is up to date and has not expired
    Observed Generation:   1
    Reason:                Ready
    Status:                True
    Type:                  Ready
  Not After:               2022-06-30T09:51:50Z
  Not Before:              2022-04-01T09:51:50Z
  Renewal Time:            2022-05-31T09:51:50Z
  Revision:                1
...

# kubectl delete -f test-resources.yaml
namespace "cert-manager-test" deleted
issuer.cert-manager.io "test-selfsigned" deleted
certificate.cert-manager.io "selfsigned-cert" deleted

至此,已完成 cert-manager 部署,接下来便是使用 cert-manager 来申请 Let’s Encrypt 证书(结合我们的需求)。

通过 cert-manager 申请 Let’s Encrypt 证书

问题描述

前面步骤演示如何部署 cert-manager 组件,并成功申请自签名证书,但这并非我们的实际应用场景。

我们希望通过 cert-manager 组件,在集群内完成 Let’s Encrypt 证书申请和管理:
1)我们使用 阿里云 DNS,并通过 DNS01 完成域名所有权认证(部分集群在内网,无法使用 HTTP01 认证);

解决方案

需要阅读如下文档,以了解相关内容:
cert-manager/Configuration/ACME
—- cert-manager/Configuration/ACME/DNS01
——– cert-manager/Configuration/ACME/DNS01/Webhook

我们这里使用 DEVmachine-fr/cert-manager-alidns-webhook 来完成证书申请。

第一步、安装 Webhook 部分

# 添加仓库
helm repo add cert-manager-alidns-webhook https://devmachine-fr.github.io/cert-manager-alidns-webhook
helm repo update

# 网络原因,所以我们提前下载 helm chart 文件
helm pull cert-manager-alidns-webhook/alidns-webhook                            # alidns-webhook-0.6.1.tgz

# 导出并并修改相关变量
helm show values ./alidns-webhook-0.6.1.tgz > alidns-webhook-0.6.1.helm-values.yaml
...(1)修改 groupName 参数
...(3)修改 image.repository 参数(可选);

# 部署 Webhook 组件
helm --namespace cert-manager                                                  \
    install alidns-webhook ./alidns-webhook-0.6.1.tgz                          \
    -f alidns-webhook-0.6.1.helm-values.yaml                                   \
    --create-namespace

第二步、创建 ClusterIssuer 资源

伴随着 apiVersion 的变化,资源的 YAML 结构也将发生变化,如下配置仅提供参考,建议参照 DEVmachine-fr/cert-manager-alidns-webhook 的配置示例:

# 完成 DNS 质询需要访问阿里云接口来修改 DNS 记录,所以需要使用 KEY 与 TOKEN 来认证

cat > alidns-secret.yaml <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: alidns-secret
  namespace: cert-manager
stringData:
  access-token: your-token
  secret-key: your-secret-key
EOF

kubectl apply -f alidns-secret.yaml

# 创建 ClusterIssuer 资源

cat > letsencrypt-cluster-issuer.yaml <<EOF
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt
spec:
  acme:
    # 修改,邮箱地址
    email: contact@example.com
    # 修改,生产地址:https://acme-v02.api.letsencrypt.org/directory
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt
    solvers:
    - dns01:
        webhook:
            # 修改,应用我们刚才创建的 Secret 资源
            config:
              accessTokenSecretRef:
                key: access-token
                name: alidns-secret
              regionId: cn-beijing
              secretKeySecretRef:
                key: secret-key
                name: alidns-secret
            # 修改,需要填写在安装时指定的 groupName 信息
            groupName: example.com
            solverName: alidns-solver
EOF

kubectl apply -f letsencrypt-cluster-issuer.yaml

第三步、申请 Ingress TLS 证书

# 在 Ingress 中,使用 HTTPS 证书:

# https://cert-manager.io/docs/usage/ingress/
cat > ingress-testing.yaml <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    # 修改,指示要使用的 issuer 资源,由管理员提供(我们前面定义的 ClusterIssuer 使用 letsencrypt 名称)
    cert-manager.io/cluster-issuer: letsencrypt
  name: cert-manager-testing
  namespace: default
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    # 修改,需要签发证书的域名
    - cert-manager-testing.example.com
    # 修改,保存证书的 Secret 资源(cert-manger 负责创建)
    secretName: cert-manager-testing-tls
  rules:
  - http:
      paths:
      - path: /testpath
        pathType: Prefix
        backend:
          service:
            name: test
            port:
              number: 80
EOF

kubectl apply -f ingress-testing.yaml

版本升级(1.7 ⇒ 1.8)

Error: rendered manifests contain a resource that already exists. Unable to continue with install: CustomResourceDefinition · Discussion #3483 · cert-manager/cert-manager

鉴于我们最开始是通过 cmctl 进行安装,所以升级过程分为两步:
1)下载并升级 CRD 资源;
2)升级 cert-manager 服务;

// ---------------------------------------------------------------------------- // 第一步、下载并升级 CRD 资源

wget https://github.com/cert-manager/cert-manager/releases/download/v1.8.2/cert-manager.crds.yaml
kubectl apply -f cert-manager.crds.yaml

// ---------------------------------------------------------------------------- // 第二步、升级 cert-manager 服务

helm repo add jetstack https://charts.jetstack.io
helm repo update

helm pull jetstack/cert-manager --version v1.8.2                                # cert-manager-v1.8.2.tgz

helm show values ./cert-manager-v1.8.2.tgz > cert-manager-v1.8.2.helm-values.yaml

helm --namespace cert-manager                                                  \
    upgrade cert-manager ./cert-manager-v1.8.2.tgz                             \
    -f cert-manager-v1.8.2.helm-values.yaml
    
// ---------------------------------------------------------------------------- // 第三步、创建 Ingress TLS 进行测试

...

参考文献

GitHub – DEVmachine-fr/cert-manager-alidns-webhook
Installation | cert-manager
cmctl | cert-manager
Securing Ingress Resources | cert-manager