在上一篇文章中 ,我们在k3s集群上部署了几个简单的网站。 这些是未加密的站点。 现在很好,它们可以工作,但是上个世纪是未加密的! 如今,大多数网站都是加密的。 在本文中,我们将安装cert-manager并将其用于在群集上部署TLS加密的站点。 这些站点不仅会被加密,而且还会使用有效的公共证书,这些证书会自动从Let's Encrypt设置和更新! 让我们开始吧!
所需材料
要继续阅读本文,您将需要我们在上一篇文章中构建的k3s Raspberry Pi集群 。 另外,您将需要一个公用的静态IP地址和一个您拥有的域名,并可以为其创建DNS记录。 如果您有一个动态DNS提供程序为您提供域名,那么它也可能会起作用。 但是,在本文中,我们将使用静态IP和CloudFlare手动创建DNS“ A”记录。
当我们在本文中创建配置文件时,如果您不想键入它们,都可以在此处下载它们。
我们为什么使用cert-manager?
机密 。 我认为, 秘密可以简单地通过名称来引用,因此更易于使用。 这就是我们在本文中使用cert-manager的主要原因。安装证书管理器
通常,我们只是简单地遵循cert-manager 文档在Kubernetes上进行安装。 但是,由于我们使用的是ARM体系结构,因此我们将进行一些更改,因此我们将在此处进行操作。
第一步是创建cert-manager名称空间。 命名空间有助于将cert-manager的pod排除在我们的默认命名空间之外,因此当我们执行诸如kubectl获取带有我们自己的pod的pod之类的操作时,我们不必看到它们。 创建名称空间很简单:
kubectl create namespace cert-manager
安装说明中,您下载了cert-manager YAML配置文件,并将它一步一步地应用于集群。 我们需要将其分为两个步骤,以便为基于ARM的Pi修改文件。 我们将下载文件并一步一步进行转换:
curl -sL \
https://github.com/jetstack/cert-manager/releases/download/v0.11.0/cert-manager.yaml |\
sed -r 's/
( image:.*
) :
( v.*
) $/\1-arm:\2/g' > cert-manager-arm.yaml
这将下载配置文件,并将所有包含的docker映像更新为ARM版本。 要检查它做了什么:
$ grep image
: cert-manager-arm.yaml
image
:
"quay.io/jetstack/cert-manager-cainjector-arm:v0.11.0"
image
:
"quay.io/jetstack/cert-manager-controller-arm:v0.11.0"
image
:
"quay.io/jetstack/cert-manager-webhook-arm:v0.11.0"
如我们所见,三个图像现在在图像名称上添加了-arm 。 现在我们有了正确的文件,我们只需将其应用于集群:
kubectl apply -f cert-manager-arm.yaml
这将安装所有的cert-manager。 我们可以通过kubectl --namespace cert-manager进行检查来知道安装何时完成,直到所有Pod都处于“ 运行”状态。
实际上就是用于证书管理器的安装!
让我们快速加密
让我们加密的好处是,它们免费为我们提供了经过公共验证的TLS证书! 这意味着我们可以拥有一个完全有效的TLS加密网站,任何人都可以访问我们的家庭或业余爱好网站,这些网站不会赚钱养家糊口,而无需自己掏钱购买TLS证书! 此外,当使用带有证书管理器的“让我们加密证书”时,采购证书的整个过程是自动化的。 证书续订也是自动的!
但这如何工作? 这是该过程的简化说明。 我们(或代表我们的证书管理者)向Let's Encrypt发出我们拥有的域名的证书请求。 让我们通过使用ACME DNS或HTTP验证机制来验证我们是否拥有该域。 如果验证成功,则让我们加密为我们提供证书,这些证书会由cert-manager安装在我们的网站(或其他TLS加密的终结点)中。 这些证书有效期为90天,需要重复该过程。 但是,证书管理员会自动为我们更新证书。
在本文中,我们将使用HTTP验证方法,因为它更易于设置并且适用于大多数用例。 这是幕后将发生的基本过程。 证书管理员将向Let's Encrypt发出证书请求。 作为回应,我们加密会发出所有权验证挑战。 面临的挑战是将HTTP资源放在请求证书的域名下的特定URL上。 从理论上讲,如果我们可以将该资源放在该URL上,并且让我们加密可以远程检索它,那么我们实际上必须是该域的所有者。 否则,要么我们无法将资源放置在正确的位置,要么我们无法操纵DNS以使“让我们加密”访问它。 在这种情况下,cert-manager会将资源放在正确的位置,并自动创建一个临时的Ingress记录,该记录会将流量路由到正确的位置。 如果“让我们加密”可以阅读质询,并且正确无误,它将把证书发回给cert-manager。 然后,证书管理员将证书存储为秘密,然后我们的网站(或其他任何网站)将使用这些证书通过TLS保护我们的流量。
为我们的网络做好准备以应对挑战
我假设您要在家庭网络上进行设置,并拥有一个以某种方式连接到更广泛的Internet的路由器/接入点。 如果不是这种情况,则可能不需要您执行以下过程。
为了使质询流程正常运行,我们需要一个域,该域正在请求证书以将其路由到端口80上的k3s集群。为此,我们需要告知全球DNS系统在哪里。 因此,我们需要将域名映射到我们的公共IP地址。 如果您不知道公用IP地址是什么,则可以转到WhatsMyIP之类的地方 ,它将告诉您。 接下来,我们需要输入DNS“ A”记录,该记录将我们的域名映射到我们的公共IP地址。 为了使此功能可靠地工作,您需要一个静态的公共IP地址,或者您可以使用动态的DNS提供程序。 一些动态DNS提供商会向您颁发一个域名,您可以按照这些说明使用它。 我没有尝试过,所以不能肯定地说它适用于所有提供商。
对于本文,我们将假定一个静态公共IP并使用CloudFlare设置DNS“ A”记录。 如果愿意,可以使用自己的DNS提供程序。 重要的是您可以设置“ A”记录。
在本文的其余部分中,我将使用k3s.carpie.net作为示例域,因为这是我拥有的域。 显然,您将用自己拥有的任何域替换它。
好的,为示例起见,假设我们的公共IP地址为198.51.100.42。 我们将转到DNS提供程序的DNS记录部分,并添加名称为k3s.carpie.net的类型为“ A”的记录 (CloudFlare假定为域,因此我们只需输入k3s ),然后输入198.51.100.42作为IPv4地址。
![](https://i-blog.csdnimg.cn/blog_migrate/fac613b0437ee7ac78f6eb3baa729b0e.png)
请注意,有时DNS更新要传播一段时间。 您可能需要几个小时才能解析该名称。 该名称必须在继续之前进行解析。 否则,我们所有的证书请求都将失败。
我们可以使用dig命令检查名称是否解析:
$ dig +short k3s.carpie.net
198.51.100.42
继续运行以上命令,直到返回IP。 只是有关CloudFlare的注释:ClouldFlare提供了通过代理流量来隐藏您的实际IP的服务。 在这种情况下,我们将取回CloudFlare IP,而不是IP。 对于我们的目的,这应该可以正常工作。
网络配置的最后一步是配置路由器,以将端口80和443上的传入流量路由到我们的k3s集群。 可悲的是,路由器配置屏幕的差异很大,因此我无法确切告诉您您的外观。 大多数时候,我们需要的管理页面位于“端口转发”或类似内容下。 我什至看到它列在“游戏”(显然是端口转发主要用于的游戏)下! 让我们看看路由器的配置是什么样的。
![](https://i-blog.csdnimg.cn/blog_migrate/da86296d61ea564bf283ba3d3f960c85.png)
如果您有我的设置,则将转到192.168.0.1登录到路由器管理应用程序。 对于此路由器,它位于NAT / QoS- > 端口转发下 。 在这里,我们将端口80 ( TCP协议)设置为转发到192.168.0.50(主节点kmaster的IP)端口80 。 我们还将端口443设置为也映射到kmaster 。 从技术上讲,这对于解决挑战不是必需的,但是在本文结尾,我们将部署一个启用TLS的网站,并且需要映射443才能访问它。 因此,现在进行地图绘制很方便。 我们保存并应用更改,我们应该一切顺利!
配置证书管理器以使用Lets Encrypt(分段)
现在,我们需要配置cert-manager来通过Let's Encrypt颁发证书。 让我们加密为我们提供了一个暂存(例如测试)环境,以整理我们的配置。 它容忍错误和请求的频率。 如果我们对生产环境不满意,我们将很快发现自己暂时被禁止! 因此,我们将使用登台环境手动测试请求。
创建一个包含以下内容的文件letsencrypt-issuer-staging.yaml :
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
# The ACME server URL
server: https://acme-staging-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: <your_email>@example.com
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-staging
# Enable the HTTP-01 challenge provider
solvers:
- http01:
ingress:
class: traefik
确保将电子邮件地址更新为您的地址。 如果出现问题或我们在做坏事,这就是Let's Encrypt与我们联系的方式!
现在,我们使用以下方法创建发行者:
kubectl apply -f letsencrypt-issuer-staging.yaml
我们可以使用以下方法检查发行者是否已成功创建:
kubectl get clusterissuers
Clusterissuers是由cert-manager创建的一种新的Kubernetes资源类型。
现在让我们手动请求测试证书。 对于我们的网站,我们不需要这样做; 我们只是在测试过程以确保我们的配置正确。
创建包含以下内容的证书请求文件le-test-certificate.yaml :
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
name: k3s-carpie-net
namespace: default
spec:
secretName: k3s-carpie-net-tls
issuerRef:
name: letsencrypt-staging
kind: ClusterIssuer
commonName: k3s.carpie.net
dnsNames:
- k3s.carpie.net
该记录仅表示我们要使用名为letencrypt-staging的ClusterIssuer (我们在上一步中创建的)请求域k3s.carpie.net的证书,并将证书文件存储在名为k3s-carpie-net的Kubernetes机密中-tls 。
像平常一样应用它:
kubectl apply -f le-test-certificate.yaml
我们可以通过以下方式查看状态:
kubectl get certificates
如果我们看到类似这样的内容:
NAME READY SECRET AGE
k3s-carpie-net True k3s-carpie-net-tls 30s
我们很好走! (这里的关键是READY为True )。
解决证书申请问题
那是幸福的道路。 如果READY为False ,我们可以花点时间再检查一下状态,以防万一。 如果仍然为False,则我们需要解决一个问题。 在这一点上,我们可以遍历Kubernetes资源链,直到找到一条告诉我们问题的状态消息。
假设我们执行了上面的请求,并且READY为False 。 我们从以下方面开始故障排除:
kubectl describe certificates k3s-carpie-net
这将返回很多信息。 通常,有用的内容在“ 事件:”部分中,该部分通常位于底部。 假设最后一个事件是Created new CertificateRequest资源“ k3s-carpie-net-1256631848” 。然后我们将描述该请求:
kubectl describe certificaterequest k3s-carpie-net-1256631848
现在让我们说最后一个事件是等待来自订单default / k3s-carpie-net-1256631848-2342473830的证书颁发 。
好的,我们可以描述顺序:
kubectl describe orders default/k3s-carpie-net-1256631848-2342473830
假设发生了一个事件,该事件为域“ k3s.carpie.net ”创建了质询资源“ k3s-carpie-net- 1256631848-2342473830-1892150396 ” 。 让我们描述一下挑战:
kubectl describe challenges k3s-carpie-net-1256631848-2342473830-1892150396
从这里返回的最后一个事件是使用http-01质询机制呈现的质询 。 看起来不错,因此我们扫描了描述输出,并看到一条消息, 等待http-01挑战传播:无法执行自检GET请求…没有此类主机 。 最后! 我们发现了问题! 在这种情况下, 没有这样的主机意味着DNS查找失败,因此我们将返回并手动检查我们的DNS设置,并且域的DNS将为我们正确解析并进行所需的任何更改。
清理我们的测试证书
我们实际上想要一个真正的域名证书,因此,让我们继续清理证书和我们刚刚创建的秘密:
kubectl delete certificates k3s-carpie-net
kubectl delete secrets k3s-carpie-net-tls
配置证书管理器以使用“加密”(生产)
现在我们已经有了测试证书,是时候开始生产了。 就像我们为“让我们加密”登台环境配置cert-manager一样,我们现在也需要对生产进行同样的操作。 创建一个名为letsencrypt-issuer-production.yaml的文件(如果需要,可以复制和修改阶段),其内容如下:
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
# The ACME server URL
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: <your_email>@example.com
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-prod
# Enable the HTTP-01 challenge provider
solvers:
- http01:
ingress:
class: traefik
(如果要从登台进行复制,则唯一更改的是服务器: URL。请不要忘记电子邮件)!
申请:
kubectl apply -f letsencrypt-issuer-production.yaml
为我们的网站申请证书
重要的是要注意,我们到目前为止完成的所有步骤都是一次设置的! 以后对于任何其他要求,我们可以从说明中开始!
让我们部署与上一篇文章中部署的站点相同的站点。 (如果仍然可用,则可以修改YAML文件。如果没有,则可能需要重新创建并重新部署)。
我们只需要将mysite .yaml的 Ingress部分修改为:
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: mysite-nginx-ingress
annotations:
kubernetes.io/ingress.class: "traefik"
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
rules:
- host: k3s.carpie.net
http:
paths:
- path: /
backend:
serviceName: mysite-nginx-service
servicePort: 80
tls:
- hosts:
- k3s.carpie.net
secretName: k3s-carpie-net-tls
请注意,上面仅显示了mysite.yaml的Ingress部分。 所做的更改是添加了cert-manager.io/cluster-issuer注释:letsencrypt-prod 。 这告诉traefik创建证书时使用哪个发行者。 唯一的其他增加是tls:块。 这告诉traefik我们希望在主机k3s.carpie.net上具有TLS ,并且我们希望TLS证书文件存储在秘密k3s-carpie-net-tls中 。
请记住,我们没有创建这些证书! (好吧,我们创建了名称相似的测试证书,但我们删除了这些证书。)Traefik将阅读此文件并继续寻找秘密。 当找不到它时,它会看到注释,说我们要使用letsencrypt-prod颁发者来购买它。 从那里,它将提出请求并为我们秘密安装证书!
大功告成! 让我们尝试一下。
它具有所有加密的TLS优点! 恭喜你!
翻译自: https://opensource.com/article/20/3/ssl-letsencrypt-k3s