默认安装好k3s/k8s后,会自动监听80端口和443端口。如果再配置nginx显得多此一举。所以这里直接使用k3s的80端口和443端口,实现证书签发和自动续签。
cert-manager官方文档 https://cert-manager.io/docs/
cert-manager官方仓库 https://github.com/jetstack/cert-manager
K3s文档:https://docs.k3s.io/zh/
准备环境
- 安装好k3s
- 已获取到阿里云dns api的accessKey和accessSecret
安装cert-manager
1
| kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.3/cert-manager.yaml
|
查看安装情况
1 2 3 4 5
| [root@ynhjy k3s] NAME READY STATUS RESTARTS AGE cert-manager-cainjector-6cc9b5f678-6hcvt 1/1 Running 0 56m cert-manager-5c9d8879fd-k7jhk 1/1 Running 0 56m cert-manager-webhook-7bb7b75848-wcfrs 1/1 Running 0 56m
|
查看日志
1
| kubectl logs -f $(kubectl get pods -n cert-manager | grep cert-manager | grep -v 'cainjector\|webhook' | awk '{print $1}') -n cert-manager
|
配置阿里云域名解析和DNS自动办法证书
安装alidns-webhook
官方仓库 https://github.com/pragkent/alidns-webhook
1
| wget https://raw.githubusercontent.com/pragkent/alidns-webhook/master/deploy/bundle.yaml
|
替换域名
1
| sed -i s/'acme.yourcompany.com'/'hello.domain.com'/g bundle.yaml
|
创建阿里secret
1 2
| echo -n <AccessKey ID> | base64 echo -n <AccessKey Secret> | base64
|
1 2 3 4 5 6 7 8 9 10 11
| vim alidns-secret.yaml
apiVersion: v1 kind: Secret metadata: name: alidns-secret namespace: cert-manager data: access-key: KEYID secret-key: KEYSECRET
|
1
| kubectl apply -f alidns-secret.yaml
|
安装alidns-webhook
1
| kubectl apply -f bundle.yaml
|
创建ClusterIssuer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: email: email@gmail.com privateKeySecretRef: name: letsencrypt-prod server: https://acme-v02.api.letsencrypt.org/directory solvers: - dns01: webhook: groupName: hello.domain.com solverName: alidns config: region: "" accessKeySecretRef: name: alidns-secret key: access-key secretKeySecretRef: name: alidns-secret key: secret-key
|
- metadata.name 是我们创建的签发机构的名称,后面我们创建证书的时候会引用它
- spec.acme.email 是你自己的邮箱,证书快过期的时候会有邮件提醒,不过 cert-manager 会利用 acme 协议自动给我们重新颁发证书来续期
- spec.acme.server 是 acme 协议的服务端,我们这里用 Let’s Encrypt,这个地址就写死成这样就行
- spec.acme.privateKeySecretRef 指示此签发机构的私钥将要存储到哪个 Secret 对象中,名称不重要
- spec.acme.dns01 这里指示签发机构使用 DNS-01 的方式进行 acme 协议 (还可以用 DNS 方式,acme 协议的目的是证明这台机器和域名都是属于你的,然后才准许给你颁发证书)
1
| kubectl apply -f letsencrypt-staging.yaml
|
申请证书
创建证书
1 2 3 4 5 6 7 8 9 10 11 12
| apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: hello.domain.com-tls spec: secretName: hello-domain-com-tls dnsNames: - "*.topdata.cc" issuerRef: name: letsencrypt-prod kind: ClusterIssuer
|
- spec.secretName 指示证书最终存到哪个 Secret 中
- spec.issuerRef.kind 值为 ClusterIssuer 说明签发机构不在本 namespace 下,而是在全局
- spec.issuerRef.name 我们创建的签发机构的名称 (ClusterIssuer.metadata.name)
- spec.dnsNames 指示该证书的可以用于哪些域名,与域名解析的一致,支持泛域名和单个域名
1
| kubectl apply -f certificate.yaml
|
查看创建结果
1 2 3 4 5 6 7
| kubectl get certificate -A
[root@ynhjy k3s] NAMESPACE NAME READY SECRET AGE cert-manager alidns-webhook-ca True alidns-webhook-ca 38m cert-manager alidns-webhook-webhook-tls True alidns-webhook-webhook-tls 38m default hello.domain.com-tls True hello-domain-com-tls 32m
|
刚创建后查看certificate会发现ready状态为false, 稍等一会自动在dns解析里创建txt 记录,然后去签发证书,该字段就会变为true
查看签发证书
1 2 3 4 5 6 7 8 9 10 11 12 13
| [root@ynhjy k3s] NAMESPACE NAME TYPE DATA AGE kube-system k3s-serving kubernetes.io/tls 2 79m kube-system chart-values-traefik Opaque 1 79m kube-system chart-values-traefik-crd Opaque 0 79m kube-system sh.helm.release.v1.traefik-crd.v1 helm.sh/release.v1 1 78m kube-system sh.helm.release.v1.traefik.v1 helm.sh/release.v1 1 78m cert-manager cert-manager-webhook-ca Opaque 3 72m cert-manager letsencrypt-prod Opaque 1 69m cert-manager alidns-secret Opaque 2 47m cert-manager alidns-webhook-ca kubernetes.io/tls 3 39m cert-manager alidns-webhook-webhook-tls kubernetes.io/tls 3 39m default hello-domain-com-tls kubernetes.io/tls 2 33m
|
hello-domain-com-tls 这一行,此时DATA 变为2,说明里面存着真正的证书文件
Issuer 与 ClusterIssuer 的区别是 ClusterIssuer 可跨命名空间使用,而 Issuer 需在每个命名空间下配置后才可使用。这里我们使用 ClusterIssuer,其类型选择 Let‘s Encrypt
可以看到这个证书是个泛域名证书,此时我们ingress 可以直接使用该secert,不需要再去添加注解执行使用的issuer/cluseteissuer了
使用证书
创建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
| apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: test-app labels: app: test-app annotations: kubernetes.io/ingressClassName: traefik cert-manager.io/cluster-issuer: letsencrypt-prod spec: tls: - secretName: hello.domain.com-tls hosts: - hello.domain.com rules: - host: hello.domain.com http: paths: - path: / pathType: ImplementationSpecific backend: service: name: test-app port: number: 80
|