一、简介
Cert-Manager是一款用于 Kubernetes 集群中自动化管理 TLS 证书的开源工具,它使用了 Kubernetes 的自定义资源定义(CRD)机制,让证书的创建、更新和删除变得非常容易。
二、设计理念
Cert-Manager 是将 TLS 证书视为一种资源,就像 Pod、Service 和 Deployment 一样,可以使用 Kubernetes API 进行管理。它使用了自定义资源定义(CRD)机制,通过扩展 Kubernetes API,为证书的生命周期提供了标准化的管理方式。
三、架构
Cert-Manager 支持多种证书颁发机构,包括**自签名证书selfSigned**、Let's Encrypt、HashiCorp Vault、Venafi 等。它还支持多种验证方式,包括 HTTP 验证、DNS 验证。这些验证方式可以帮助确保证书的颁发机构是可信的,并且确保证书的私钥不会泄露。
Issuer/ClusterIssuer:用于指示 cert-manager 签发证书的方式。
Issuer 与 ClusterIssuer 之间的区别是:Issuer 只能用来签发自身所在 namespace 下的证书,ClusterIssuer 可以签发任意 namespace 下的证书。
Certificate:用于向 cert-manager 传递域名证书的信息、签发证书所需要的配置,以及对 Issuer/ClusterIssuer 的引用。
四、安装
在线安装:
1、部署cert-manager.crds
kubectl apply -f //github.com/cert-manager/cert-manager/releases/download/v1.14.5/cert-manager.crds.yaml
2、在线部署cert-manager
helm repo add jetstack //charts.jetstack.io
helm install cert-manager jetstack/cert-manager --namespace cert-manager --version v1.14.5
3、查看资源
五、使用方法
1、创建自签证书颁发者
# 创建对象
kubectl apply -f - <<EOF
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: selfsigned-issuer
namespace: default # 指定 Namespace
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: selfsigned-cluster-issuer
spec:
selfSigned: {}
EOF
Issuer 类型资源对象仅作用于集群内单个指定的命名空间
ClusterIssuer 类型资源对象可以作用于集群内所有的命名空间
# 查看对象
kubectl get issuer
kubectl get clusterissuer
2、创建自签证书
# 创建对象
kubectl apply -f - <<EOF
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: selfsigned-cert
namespace: default
spec:
dnsNames:
- Example Domain
secretName: selfsigned-cert-tls
issuerRef:
name: selfsigned-issuer
EOF
会自动创建 selfsigned-cert 和 selfsigned-secret 对象
# 查看对象
kubectl get cert
kubectl get secret
六、管理内网k8s环境证书
在内网,做不了域名验证,无法使用Let's Encrypt颁发和自动更新证书,所以采用自签名CA证书+由此CA颁发证书的方式。
1、创建自签名发行者
# selfsigned-issuer.issuer.yaml
# 参考:cert-manager.io/docs/configuration/selfsigned/
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: selfsigned-issuer
namespace: cert-manager
spec:
selfSigned: {}
2、生成CA证书
# ca-example-com.certificate.cert-manager.yaml
# 参考:cert-manager.io/docs/usage/certificate/
# api参考:cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1alpha3.Certificate
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: ca-example-com ###
namespace: cert-manager ### 修改为cert-manager的namespace,以让ClusterIssuer的CA Issuer可以使用此证书
spec:
# Secret names are always required.
secretName: ca-example-com-tls ### Secret名字
duration: 2160h # 90d
renewBefore: 360h # 15d
subject:
organizations:
- Example Inc. ###
# The use of the common name field has been deprecated since 2000 and is
# discouraged from being used.
commonName: ca.example.com ###
isCA: true ### 修改为true,isCA将将此证书标记为对证书签名有效。这会将cert sign自动添加到usages列表中。
privateKey:
algorithm: RSA
encoding: PKCS1
size: 2048
#usages: ### 注释了usages,使用情况是证书要求的x509使用情况的集合。默认为digital signature,key encipherment如果未指定。
# - server auth
# - client auth
# At least one of a DNS Name, URI, or IP address is required.
dnsNames:
- ca.example.com ###
#uris: ### 注释了uris、ipAddresses
#- spiffe://cluster.local/ns/sandbox/sa/example
#ipAddresses:
#- 192.168.0.5
# Issuer references are always required.
issuerRef:
name: selfsigned-issuer ### 指定为自签名发行人
# We can reference ClusterIssuers by changing the kind here.
# The default value is Issuer (i.e. a locally namespaced Issuer)
kind: Issuer
# This is optional since cert-manager will default to this value however
# if you are using an external issuer, change this to that issuer group.
group: cert-manager.io
我们将要把CA Issuer创建为ClusterIssuer,因ClusterIssuer只能访问cert-manager下的Secret,所以这个CA Certificate创建在此名字空间下,其Secret也会被创建在此名字空间下。当然也可以更改ClusterIssuer默认可访问的名字空间,参考:cert-manager.io/docs/faq/cluster-resource/
3、创建CA发行者(ClusterIssuer)
# ca-issuer.clusterissuer.yaml
# 参考:cert-manager.io/docs/configuration/ca/
apiVersion: cert-manager.io/v1
kind: ClusterIssuer ### ClusterIssuer
metadata:
name: ca-issuer
namespace: cert-manager ### ClusterIssuer下namespace无效
spec:
ca:
secretName: ca-example-com-tls ###
CA Issuer创建为ClusterIssuer,可为其他名字空间的Certificate发行证书
4、生成证书
# site-example-com.certificate.example-com.yaml
# 参考:cert-manager.io/docs/usage/certificate/
# api参考:cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1alpha3.Certificate
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: site-example-com ###
namespace: example-com ### 所在名字空间
spec:
# Secret names are always required.
secretName: site-example-com-tls ### Secret名字
duration: 2160h # 90d
renewBefore: 360h # 15d
subject:
organizations:
- Example Inc. ###
# The use of the common name field has been deprecated since 2000 and is
# discouraged from being used.
commonName: site.example.com ###
isCA: false
privateKey:
algorithm: RSA
encoding: PKCS1
size: 2048
#usages: ### 注释了usages,使用情况是证书要求的x509使用情况的集合。默认为digital signature,key encipherment如果未指定。
# - server auth
# - client auth
# At least one of a DNS Name, URI, or IP address is required.
dnsNames:
- site.example.com ###
#uris: ### 注释了uris、ipAddresses
#- spiffe://cluster.local/ns/sandbox/sa/example
#ipAddresses:
#- 192.168.0.5
# Issuer references are always required.
issuerRef:
name: ca-issuer ### 使用CA Issuer
# We can reference ClusterIssuers by changing the kind here.
# The default value is Issuer (i.e. a locally namespaced Issuer)
kind: ClusterIssuer ### CA Issuer是ClusterIssuer
# This is optional since cert-manager will default to this value however
# if you are using an external issuer, change this to that issuer group.
group: cert-manager.io
5、将证书配置到Ingress
# site-example-com.ingress.example-com.yaml
# 参考:kubernetes.io/zh/docs/concepts/services-networking/ingress/#tls
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: site-example-com
namespace: example-com
annotations:
kubernetes.io/ingress.class: nginx
spec:
tls:
- hosts:
- site.example.com
secretName: site-example-com-tls
rules:
- host: site.example.com
http:
paths:
- path: /
pathType: ImplementationSpecific
backend:
serviceName: nginx
servicePort: 80