2.1 通配符证书
TLS(旧称 SSL) 已经是网络数据传输的必备加密手段,如今是 2024 年,笔者认为已经没有必要讨论是否需要 TLS,而是需要确认要使用哪一个版本的,自建服务推荐最低使用 TLS 1.2 版本。
对于部署在集群中的服务,最常见的需求就是暴露到公网,然后通过域名访问它,这就涉及到配置 DNS 解析和签发 TLS 证书,配置解析简单,但签发证书就比较麻烦了。
常见的免费证书都是 DV 证书,只支持验证单个域名,如果使用这种证书,光是签发和维护就是很大的工作量,因此推荐使用通配符证书,它可以保护多个域名(主机),而无需为每个域名单独购买证书。证书中包含一个星号 (*) 通配符,表示该证书可以保护所有以该通配符开头的主域名。
acme.sh 是一个纯 shell 实现的证书申请工具,它实现了 acme 协议, 可以从 letsencrypt 生成免费的证书。
官方链接:acme.sh
笔者的域名托管在 cloudflare,它提供了 API 接口可用于txt 解析记录, 验证域名所有权,下面是通过 acme.sh 申请通配符证书的示例:
安装很简单, 一个命令:
curl https://get.acme.sh
安装过程执行了以下两步操作:
- 安装过程进行了以下几步把 acme.sh 安装到你的 home 目录下:~/.acme.sh,并创建一个 alias 方便使用: alias acme.sh=~/.acme.sh/acme.sh
- 自动创建 cronjob, 每天 0:00 点自动检测所有的证书, 如果快过期了, 需要更新, 则会自动更新证书
这里使用 DNS 的方式验证域名所有权,首先在 cloudflare 创建一个拥有编辑区域 DNS 权限的多区域 API 令牌:
然后选择一个域名进入首页可以查看到账户 ID
这样我们就得到了两个变量:CF_Token
与 CF_Account_ID
然后在终端执行以下命令:
export CF_Token=<多区域 API 令牌>
export CF_Token=<账户 ID>
acme.sh --issue --dns dns_cf -d wbuntu.com -d '*.wbuntu.com' -d '*.app.wbuntu.com'
这里我们签发了三个域名:
- wbuntu.com:对 wbuntu.com 主域名有效
- *.wbuntu.com:对 wbuntu.com 的所有一级子域名有效,如:www.wbuntu.com、test.wbuntu.com
- *.app.wbuntu.com:对 app.wbuntu.com 的所有一级子域名有效,如:caddy.app.wbuntu.com
letsencrypt 尚不支持多层级通配符证书,如:*.*.wbuntu.com
,由于后续演示的大多数应用都会用 app.wbuntu.com
的子域名,这里就多签发一个通配符。
等待命令运行成功后,可以在 ~/.acme.sh 下查看到证书(目前 acme.sh 默认生成 ecc 证书)
➜ ~ ls ~/.acme.sh
account.conf acme.sh acme.sh.env acme.sh.log ca deploy dnsapi http.header notify wbuntu.com_ecc
➜ ~ ls ~/.acme.sh/wbuntu.com_ecc
backup ca.cer fullchain.cer wbuntu.com.cer wbuntu.com.conf wbuntu.com.csr wbuntu.com.csr.conf wbuntu.com.key
其中 fullchain.cer 与 wbuntu.com.key 为我们需要的证书和对应的密钥。
K3s 自带了 traefik 作为 ingress-controller,我们可以把它当作集群的入口,像使用 nginx 一样配置转发规则,将请求从入向流量根据域名转发到对应的服务。
traefik 支持通过原生的 ingess 与自带的 ingressroute 配置转发规则,在下一节中会介绍,这里我们只需要将证书转换为 secret 保存即可。
使用 acme.sh 的 --install-cert
子命令可以拷贝和安装证书,且可以指定一个触发应用程序重新加载证书的命令,下面我们会先将证书拷贝到 /tmp 目录,然后执行一个脚本更新集群 kube-system 命名空间下的 secret:tls-cert
在 /root/dev/bin 创建一个脚本 update_cert.sh 内容如下:
#!/bin/bash
pushd /tmp
kubectl create secret tls tls-cert --cert=wbuntu.crt --key=wbuntu.key --dry-run=client -o yaml > /tmp/tls-cert.yaml
if kubectl -n kube-system get secret tls-cert &> /dev/null; then
echo "creating secret: kube-system/tls-cert..."
kubectl -n kube-system replace -f /tmp/tls.yaml
else
echo "updating secret: kube-system/tls-cert..."
kubectl -n kube-system apply -f /tmp/tls.yaml
fi
popd
然后执行安装证书命令:
acme.sh --install-cert -d wbuntu.com --key-file /tmp/wbuntu.key --fullchain-file /tmp/wbuntu.crt --reloadcmd "/root/dev/bin/update_cert.sh"
最后检查下 secret:
➜ ~ kubectl -n kube-system get secret tls-cert
NAME TYPE DATA AGE
tls-cert kubernetes.io/tls 2 575d
可以看到证书成功创建出来了,如果部署了 web 服务并通过 ingressroute 暴露了出来,就可以在浏览器中查看到证书信息: