简介 cert-manager是kubernetes原生证书解决方案,可以通过多种机构颁发证书,证书最后以secret的形式存储在kubernetes中。可以支持Let’s encrypt,self signed,CA等。
架构
安装 创建资源
1 2 $ kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.14.0/cert-manager.crds.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 $ helm repo add jetstack https://charts.jetstack.io $ helm install \ cert-manager jetstack/cert-manager \ --namespace cert-manager \ --version v0.14.0 $ helm install \ --name cert-manager \ --namespace cert-manager \ --version v0.14.0 \ jetstack/cert-manager
检查 1 2 3 4 5 $ kubectl get pod -n cert-manager NAME READY STATUS RESTARTS AGE cert-manager-845c74ff94-5mdkk 1/1 Running 0 5h15m cert-manager-cainjector-648dd444df-h7jh5 1/1 Running 0 5h15m cert-manager-webhook-6dbcd48f9c-shh7z 1/1 Running 0 5h15m
配置 CA 手动创建根证书和私钥,或者从其他地方获取根证书及私钥。将证书存储在k8s的secret中,用来颁发证书,可以用内部的CA证书信任生成的签名证书。
创建根证书
1 2 $ openssl genrsa -out ca.key 2048 $ openssl req -x509 -new -nodes -key ca.key -subj "/CN=hqtest" -days 3650 -reqexts v3_req -extensions v3_ca -out ca.crt
1 2 3 4 $ kubectl create secret tls ca-key-pair \ --cert=ca.crt \ --key=ca.key \ --namespace=default
创建签发机构
1 2 3 4 5 6 7 8 9 $ cat issuer.yaml apiVersion: cert-manager.io/v1alpha2 kind: Issuer metadata: name: ca-issuer namespace: default spec: ca: secretName: ca-key-pair
创建资源
1 $ kubectl apply -f issuer.yaml
创建证书
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 $ cat certs.yaml apiVersion: cert-manager.io/v1alpha2 kind: Certificate metadata: name: example-com namespace: default spec: secretName: example-com-tls issuerRef: name: ca-issuer kind: Issuer commonName: ning.com organization: - CA dnsNames: - ning.com - nginx.ning.com
创建资源
1 $ kubectl apply -f certs.yaml
ingress使用证书
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 $ cat nginx.yaml apiVersion: apps/v1 kind: Deployment metadata: name: my-nginx spec: replicas: 1 selector: matchLabels: run: nginx template: metadata: labels: run: my-nginx spec: containers: - name: my-nginx image: nginx ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: my-nginx labels: app: my-nginx spec: ports: - port: 80 protocol: TCP name: http selector: run: my-nginx --- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: my-nginx annotations: kubernetes.io/ingress.class: "nginx" kubernetes.io/tls-acme: "true" certmanager.k8s.io/issuer: "ca-issuer" spec: rules: - host: nginx.ning.com http: paths: - backend: serviceName: my-nginx servicePort: 80 path: / tls: - secretName: nginx-secret hosts: - nginx.ning.com
创建资源
1 $ kubectl apply -f nginx.yaml
自签名证书 创建自签名证书Issuer 1 2 3 4 5 6 7 8 9 10 11 12 13 $ cat cert-resource.yaml apiVersion: v1 kind: Namespace metadata: name: cert-manager-test --- apiVersion: cert-manager.io/v1alpha2 kind: Issuer metadata: name: test -selfsigned namespace: cert-manager-test spec: selfSigned: {}
创建资源
1 $ kubectl apply -f cert-resource.yaml
生成证书
1 2 3 4 5 6 7 8 9 10 11 12 $ cat certificate-example-com.yaml apiVersion: cert-manager.io/v1alpha2 kind: Certificate metadata: name: selfsigned-cert namespace: cert-manager-test spec: dnsNames: - example.com secretName: selfsigned-cert-tls issuerRef: name: test -selfsigned
创建资源
1 $ kubectl apply -f certificate-example-com.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 [root@node1 selfsigne] apiVersion: apps/v1 kind: Deployment metadata: name: myapp-deploy namespace: cert-manager-test spec: replicas: 1 selector: matchLabels: app: myapp release: canary template: metadata: labels: app: myapp release: canary spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: http containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: myapp namespace: cert-manager-test spec: selector: app: myapp release: canary ports: - name: http port: 80 targetPort: 80 --- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-myapp namespace: cert-manager-test annotations: kubernetes.io/ingress.class: nginx cert-manager.io/issuer: test -selfsigned kubernetes.io/tls-acme: "true" spec: rules: - host: myapp.self.tech http: paths: - path: / backend: serviceName: myapp servicePort: 80 tls: - hosts: - myapp.self.tech secretName: myapp
创建资源
1 $ kubectl apply -f nginx-self.yaml
注意: 1. 自动创建证书中,标记ingress参数metadata.annotations.cert-manager.io/issuer: test-selfsigned,test-selfsigned为issuer名称
2. 若使用clusterissuer则参数为 metadata.annotations.cert-manager.io/cluster-issuer
letsencrypt 创建资源clusterissuer 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 $ cat clusterissuer.yaml apiVersion: cert-manager.io/v1alpha2 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: 845789131@qq.com privateKeySecretRef: name: letsencrypt-prod solvers: - http01: ingress: class: nginx
生成证书 生成证书方式和其他方式类似,可手动生成,也可以ingress自动生成,参考上节生成证书
注意:1.letsencrypt通过acme协议自动申请证书,其中包含两个sloving Challenge: http01,dns01,主要用来证明域名是属于你所有。
http01的校验原理是给你域名指向的 HTTP 服务增加一个临时 location ,Let’s Encrypt 会发送 http 请求到 http:///.well-known/acme-challenge/,YOUR_DOMAIN 就是被校验的域名,TOKEN是 ACME 协议的客户端负责放置的文件,在这里 ACME 客户端就是 cert-manager,它通过修改 Ingress 规则来增加这个临时校验路径并指向提供 TOKEN 的服务。此方法仅适用于给使用 Ingress 暴露流量的服务颁发证书,并且不支持泛域名证书。
dns01 的校验原理是利用 DNS 提供商的 API Key 拿到你的 DNS 控制权限, 在 Let’s Encrypt 为 ACME 客户端提供令牌后,ACME 客户端 (cert-manager) 将创建从该令牌和您的帐户密钥派生的 TXT 记录,并将该记录放在 _acme-challenge.。 然后 Let’s Encrypt 将向 DNS 系统查询该记录,如果找到匹配项,就可以颁发证书。此方法不需要你的服务使用 Ingress,并且支持泛域名证书。
验证
1 2 3 $ kubectl get svc -n ingress-nginx NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ingress-nginx NodePort 10.233.21.195 <none> 80:30773/TCP,443:30762/TCP 13d
添加 /etc/hosts解析(若有内部DNS,可配置DNS)
1 2 cat /etc/hosts 3.1.20.110 nginx.ning.com
注意:由于ingress-controller是nodeport暴露方式,这里需要写k8s其中一个node的IP
浏览器打开访问:https://nginx.ning.com:30762
注意:此处端口为ingress-controller暴露的443的nodeport端口,而非80
官网介绍: https://cert-manager.io/docs/configuration/acme/