K3s/K8s实现阿里云https自动签发和续签

默认安装好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]# kubectl get pods -n cert-manager -w
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 #base64编码后的AccessKey ID。
secret-key: KEYSECRET #base64编码后的AccessKey Secret。

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
#vim letsencrypt-staging.yaml
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 #须和bundle.yaml文件中定义的groupname 一致
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
#vim certificate.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: hello.domain.com-tls
spec:
secretName: hello-domain-com-tls
dnsNames: #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]# kubectl get certificate -A
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
kubectl get secrets -A
1
2
3
4
5
6
7
8
9
10
11
12
13
[root@ynhjy k3s]# kubectl get secrets -A
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
# 省略service等配置
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 # letsencrypt-prod为ClusterIssuer名称
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

K3s/K8s实现阿里云https自动签发和续签

https://blog.yhan219.com/k3s-ali-cert/

作者

yhan219

发布于

2023-12-18

更新于

2023-12-18

许可协议