cert-manager安装

cert-manager安装

参考: https://cert-manager.io/docs/

参考: https://cert-manager.io/docs/getting-started/

前面装好ingress之后,默认只提供80端口的http访问。如果要使用https,需要在ingress中配置tls。

配置tls需要提供证书和key。

  • 购买域名的时候,有的域名服务商会给购买的域名提供免费的域名证书服务。
  • 也可以用openssl等工具自签证书,但浏览器和各操作系统,一般是不认自签证书的,会提示不安全,问你要不要继续访问。
  • 大部分域名权威机构或其二级机构,需要单独购买域名证书,才提供域名证书服务。
  • letsencrypt也是一家域名二级机构,提供免费的域名证书服务。

前面用openssl工具自签过一个证书,用于测试。正常来说,是需要向权威机构申请域名证书的。

k8s的cert-manager基于上述机构(主要是letsencrypt)的证书服务,自动提供,自动更新域名证书。

参考: https://cert-manager.io/docs/

cert-manager adds certificates and certificate issuers as resource types in Kubernetes clusters, and simplifies the process of obtaining, renewing and using those certificates. cert-manager 将证书和证书颁发者添加为 Kubernetes 集群中的资源类型,并简化了获取、更新和使用这些证书的过程。

参考: https://cert-manager.io/docs/getting-started/

参考: https://cert-manager.io/docs/tutorials/acme/nginx-ingress/

prerequisite

安装k8s

私网安装metallb或云服务商提供loadbalancer实现

安装nginx-ingress

开始

参考: https://cert-manager.io/docs/getting-started/

主要是参考其中如下部分:

Learn how to deploy cert-manager and how to configure it to get certificates for the NGINX Ingress controller from Let’s Encrypt.

本章节主要学习实践如何部署cert-manager, 并为 ingress-nginx控制器配置来自 Let’s Encrypt的证书。

至于对其他云厂商和ingress controller环境下的配置,略,有需要再看。

helm安装cert-manager

这里采用helm安装方式。

参考: https://cert-manager.io/docs/installation/

参考: https://cert-manager.io/docs/installation/helm/

添加helm仓库:

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

更新仓库缓存:

helm repo update

创建命名空间

kubectl create ns cert-manager

设为当前默认命名空间

kubectl config set-context --current --namespace cert-manager

开始安装cert-manager组件

官网这里提供了两种方式安装。

  • 一种单独安装自定义资源类型(custom resource defination), 然后用helm安装剩余部分。
  • 另一种直接用helm安装所有内容,包含crd。

生产环境建议第一种方式,原因是,卸载helm装的cert-manager时,不会卸载crd部分,也不会移除已经生成的证书,防止对外的https服务异常。

这里使用第一种方式。

看下helm仓库当前的cert-manager版本

root@wangjm-B550M-K-1:~/k8s/helm/cert-manager# helm search repo jetstack
NAME                                    CHART VERSION   APP VERSION     DESCRIPTION                                       
jetstack/cert-manager                   v1.14.5         v1.14.5         A Helm chart for cert-manager                     
jetstack/cert-manager-approver-policy   v0.14.0         v0.14.0         approver-policy is a CertificateRequest approve...
jetstack/cert-manager-csi-driver        v0.8.0          v0.8.0          cert-manager csi-driver enables issuing secretl...
jetstack/cert-manager-csi-driver-spiffe v0.5.0          v0.5.0          csi-driver-spiffe is a Kubernetes CSI plugin wh...
jetstack/cert-manager-google-cas-issuer v0.8.0          v0.8.0          A Helm chart for jetstack/google-cas-issuer       
jetstack/cert-manager-istio-csr         v0.8.1          v0.8.1          istio-csr enables the use of cert-manager for i...
jetstack/cert-manager-trust             v0.2.1          v0.2.0          DEPRECATED: The old name for trust-manager. Use...
jetstack/trust-manager                  v0.9.2          v0.9.2          trust-manager is the easiest way to manage TLS ...
jetstack/version-checker                v0.5.4          v0.5.4          A Helm chart for version-checker           

嗯, v1.14.5

下载对应的crd

参考: https://cert-manager.io/docs/installation/helm/#option-1-installing-crds-with-kubectl

看了下github的分支和tag,已经有v1.12.3了,下载对应的crd

wget https://github.com/cert-manager/cert-manager/releases/download/v1.14.5/cert-manager.crds.yaml

创建对应的crd资源

kubectl create -f ./cert-manager.crds.yaml

helm安装cert-manager

helm install \
  cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --version v1.14.5

前面已经安装crd了,如果没有安装的话,也可以按前面说的第二种方式安装

helm install \
  cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --version v1.12.3 \
  # --set installCRDs=true

安装完成的输出:

root@wangjm-B550M-K-1:~/k8s/helm/cert-manager# helm install \
  cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --version v1.14.5
NAME: cert-manager
LAST DEPLOYED: Thu May  9 21:10:22 2024
NAMESPACE: cert-manager
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
cert-manager v1.14.5 has been deployed successfully!

In order to begin issuing certificates, you will need to set up a ClusterIssuer
or Issuer resource (for example, by creating a 'letsencrypt-staging' issuer).

More information on the different types of issuers and how to configure them
can be found in our documentation:

https://cert-manager.io/docs/configuration/

For information on how to configure cert-manager to automatically provision
Certificates for Ingress resources, take a look at the `ingress-shim`
documentation:

https://cert-manager.io/docs/usage/ingress/

这里提示下一步,可以配置Issuer或者ClusterIssuer了,比如免费的letsencrypt。

如果要卸载cert-manager

helm --namespace cert-manager delete cert-manager

删除crd (危险!!!),先查一下有哪些资源

kubectl get Issuers,ClusterIssuers,Certificates,CertificateRequests,Orders,Challenges --all-namespaces

去当初安装安装crd的目录下

kubectl delete -f ./cert-manager.crds.yaml

删除命名空间

kubectl delete namespace cert-manager

如果删除命名空间的过程中,卡住了

kubectl delete apiservice v1beta1.webhook.cert-manager.io

使用cert-manager为ingress-nginx提供tls服务

参考: https://cert-manager.io/docs/tutorials/acme/nginx-ingress/

Step1 – Install Helm

略,前面章节已装

Step2 – Deploy the NGINX Ingress Controller

略,前面章节已装

Step3 – Assign a DNS name

略。买域名,去域名服务商网站那里配置。

绑一下ip

Step4 – Deploy an Example Service

创建test命名空间

kubectl create ns test

切换到test命名空间,做测试

kubectl config set-context --current --namespace test

下载demo相关yaml文件

wget https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/acme/example/deployment.yaml
wget https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/acme/example/service.yaml
wget https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/acme/example/ingress.yaml

部署deployment和service

kubectl create -f ./deployment.yaml
kubectl create -f ./service.yaml

ingress需要调整一下其中的域名,改为自己掌控的域名或其二级域名(需要在域名服务商那里做好ip绑定)

[root@jingmin-kube-archlinux cert-manager-demo]# vim ./ingress.yaml 
[root@jingmin-kube-archlinux cert-manager-demo]# cat ./ingress.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: kuard
  annotations: {}
    #cert-manager.io/issuer: "letsencrypt-staging"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - kuard.ole12138.cn
    secretName: quickstart-example-tls
  rules:
  - host: kuard.ole12138.cn
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: kuard
            port:
              number: 80

这里我使用二级域名kuard.ole12138.cn,并需要到域名服务商那里做下ingress controller(loadbalancer)的ip地址的绑定。

部署ingress

kubectl create -f ./ingress.yaml

查看ingress

[root@jingmin-kube-archlinux cert-manager-demo]# kubectl get ingress
NAME             CLASS   HOSTS               ADDRESS         PORTS     AGE
demo-external    nginx   demo.ole12138.cn    192.168.1.100   80, 443   35h
demo-localhost   nginx   demo.localdev.me    192.168.1.100   80, 443   35h
kuard            nginx   kuard.ole12138.cn   192.168.1.100   80, 443   4m39s

可以看到有一行是kuard

公网访问https://kuard.ole12138.cn/, 应该可以访通,但是浏览器会有警告,因为使用的是ingress-nginx默认的自签证书。

查看ingress-nginx控制器的日志,也能看到证书相关的提示

kubectl -n ingress-nginx logs pods/ingress-nginx-controller-5fcb5746fc-47q6m

Step5 – Deploy cert-manager

本文前面,已经装了相关的crd资源,以及helm安装了cert-manager

Step6 – Configure a Let’s Encrypt Issuer

许多CA提供的证书都是要钱的。Let‘s Encrypt则不然,可以提供免费的证书。而且有较好的验证接口。

但是生产环境的证书签注接口,Let‘s Encrypt有较为严格的调用次数限制,very strict rate limits. 同时它也提供了非生产环境,较为宽松的签注接口。

因此,我们部署两套Issuer,一套staging环境,一套production环境。(注意:Issuer这里特指这种crd,而且是namespaced的资源,如果想要cluster全局都可以使用,科室使用CluserIssuer这种crd,并修改对应位置的annotation)

将defaut设为默认命名空间,即之后创建的资源,默认是在default命名空间中的

kubectl config set-context --current --namespace test

创建staging-issuer

wget https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/acme/example/staging-issuer.yaml

修改其中的邮箱部分,用于创建账号,以及将来有证书将要过期相关的内容会发到对应的邮箱

[root@jingmin-kube-archlinux issuer]# vim staging-issuer.yaml 
[root@jingmin-kube-archlinux issuer]# cat staging-issuer.yaml 
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    # The ACME server URL
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration
    email: 784319947@qq.com
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt-staging
    # Enable the HTTP-01 challenge provider
    solvers:
      - http01:
          ingress:
            ingressClassName: nginx

部署staging-issuer

kubectl create -f ./staging-issuer.yaml 

类似的方式,创建production-issuer

wget https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/acme/example/production-issuer.yaml

同样,修改其中的邮箱为自己的邮箱

[root@jingmin-kube-archlinux issuer]# vim production-issuer.yaml 
[root@jingmin-kube-archlinux issuer]# cat production-issuer.yaml 
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    # The ACME server URL
    server: https://acme-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration
    email: 784319947@qq.com
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt-prod
    # Enable the HTTP-01 challenge provider
    solvers:
      - http01:
          ingress:
            ingressClassName: nginx

部署到当前命名空间中

kubectl create -f ./production-issuer.yaml

这两个issuer都通过http01的方式向Let’s Encrypt 发出challenge.

kubectl describe issuer

可以看到description中都有一条Message: The ACME account was registered with the ACME server

Step7 – Deploy a TLS Ingress Resource

修改前面部署的kuard demo ingress

删除tls部分(前面好像本来就没有加,默认用的ingress-nginx自动生成的自签证书)

annotations部分添加一行cert-manager相关的注解cert-manager.io/issuer: "letsencrypt-staging"

[root@jingmin-kube-archlinux issuer]# kubectl edit ingress kuard
[root@jingmin-kube-archlinux issuer]# kubectl get ingress kuard -o yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/issuer: letsencrypt-staging
  creationTimestamp: "2023-08-23T02:47:41Z"
  generation: 1
  name: kuard
  namespace: default
  resourceVersion: "411121"
  uid: 7f2c7dfb-12a6-446d-95a9-24dfebd9fa00
spec:
  ingressClassName: nginx
  rules:
  - host: kuard.ole12138.cn
    http:
      paths:
      - backend:
          service:
            name: kuard
            port:
              number: 80
        path: /
        pathType: Prefix
  tls:
  - hosts:
    - kuard.ole12138.cn
    secretName: quickstart-example-tls
status:
  loadBalancer:
    ingress:
    - ip: 192.168.1.100

这个时候,cert-manager会自动替我们向Let’s Encrypt申请域名证书,并维护证书的可用性(比如快过期时自动更新证书)。

[root@jingmin-kube-archlinux issuer]# kubectl get certificate
NAME                     READY   SECRET                   AGE
quickstart-example-tls   False   quickstart-example-tls   16s
[root@jingmin-kube-archlinux issuer]# kubectl get certificate
NAME                     READY   SECRET                   AGE
quickstart-example-tls   True    quickstart-example-tls   67s

可以看到,过了一会儿,才准备好证书。

这个时候,到浏览器中,请求前面的ingress域名, 我的是https://kuard.ole12138.cn

可以发现,还是提示不安全,但是点击浏览器那个证书图标(这里可能是个叹号图标),显示的证书内容已经更新(注意签发机构等内容)。

说明ingress中issuer的配置是可用的。

OK, 现在我们可以吧staging-issuer切换为producation-issuer了。

还是调整ingress中annotations中issuer相关的内容, 切换为正式的“letsencrypt-prod“

[root@jingmin-kube-archlinux issuer]# kubectl edit ingress kuard 
ingress.networking.k8s.io/kuard edited
[root@jingmin-kube-archlinux issuer]# kubectl get ingress kuard -o yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/issuer: letsencrypt-prod
  creationTimestamp: "2023-08-23T02:47:41Z"
  generation: 1
  name: kuard
  namespace: default
  resourceVersion: "412929"
  uid: 7f2c7dfb-12a6-446d-95a9-24dfebd9fa00
spec:
  ingressClassName: nginx
  rules:
  - host: kuard.ole12138.cn
    http:
      paths:
      - backend:
          service:
            name: kuard
            port:
              number: 80
        path: /
        pathType: Prefix
  tls:
  - hosts:
    - kuard.ole12138.cn
    secretName: quickstart-example-tls
status:
  loadBalancer:
    ingress:
    - ip: 192.168.1.100

然后查看对应的secrets,certificate, 确认已经更新(issuer相关的annotations字段)

kubectl get secrets,certificate -o yaml

浏览器再请求一下,前面的ingress域名, 我的是https://kuard.ole12138.cn。访问的时候,已经没有任何警告,点击浏览器里地址栏前面的锁头标志,提示地址是安全的,并可以看到具体的证书信息。

注意,前面创建的两个Issuer实例,都是namespaced受限的。如果要cluster中全局可用,请切换CluserIssuer,创建对应的资源。而且annotations注解也要调整为cert-manager.io/cluster-issuer(注意Let’s Encrypt 每个帐号能签发的证书个数是有限制的。Cluser情况注意下容易超限)

前面的时间算是基础,但是这样来一遍之后,基本已经可以在ingress中自动配置tls了。日常使用应该已经够了。

如果想要进一步了解其构成以及配置,以及使用自定义的CA服务商,可以阅读官网其他部分的文档。

比如如下内容:

https://cert-manager.io/docs/concepts/

https://cert-manager.io/docs/configuration/

https://cert-manager.io/docs/usage/


评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注