文章目录
概述
验证下使用 cert-manager 对 ingress-nginx 证书的 dns 认证、签发、自动 renew。其中认证有两种方式 dns01 认证 以及 http01 认证。
renew 一般不需要我们做什么事情,不过在某些公有云环境下,需要我们将证书上传到 slb 控制台,这种情况下需要程序员自己写代码实现自动化,使用公有云的 sdk。
环境部署安装
ingress-nginx
使用 helm 安装,下面安装命令使用了自定义的 ingressClass 名字,当一个集群中需要多个 ingress-nginx 的时候,需要这么做。
helm upgrade --install ingress-nginx ingress-nginx \
--repo https://kubernetes.github.io/ingress-nginx \
--namespace ingress-nginx --create-namespace \
--set controller.ingressClass=nginx-lr90,controller.ingressClassResource.name=nginx-lr90,controller.ingressClassResource.controllerValue=k8s.io/ingress-lr90
ingress-nginx 需要公网访问,所以其 service 类型为 loadbalancer。在私有化环境下,可以使用 metallb 分配地址。
根据 ingress-nginx multiple ingress controllers 文档,部署多个控制器的时候,还需要每一个控制器一个独立的 electionID:
controller:
electionID: ingress-controller-leader
ingressClass: internal-nginx # default: nginx
ingressClassResource:
name: internal-nginx # default: nginx
enabled: true
default: false
controllerValue: "k8s.io/internal-ingress-nginx" # default: k8s.io/ingress-nginx
cert-manager
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.1/cert-manager.yaml
部署 letsencrypt staging issuer,staging issuer 是测试环境下用的,签的是非正式证书,但是没有流控限制。触发 letsencrypt 的流控是比较难解的,除了 prod 环境,我们应该总是使用 staging 签证书。
下面 email 需要替换一下,替换成我们个人的或者公司的邮箱,另外我们使用 http01 进行 dns 验证,ingressclass 配置成我们安装 ingress-nginx 时的用的名字。
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: http01-staging
spec:
acme:
email: you@email.com
privateKeySecretRef:
name: http01-staging-issuer-account-key
server: https://acme-staging-v02.api.letsencrypt.org/directory
solvers:
- http01:
ingress:
ingressClassName: nginx-lr90
serviceType: ClusterIP
部署测试应用
部署 kuard 服务用于测试,service 的端口为 80。
部署 deployment 服务
参考文档 Securing NGINX-ingress 部署一个 deployment 以及 service。
apiVersion: apps/v1
kind: Deployment
metadata:
name: kuard
spec:
selector:
matchLabels:
app: kuard
replicas: 1
template:
metadata:
labels:
app: kuard
spec:
containers:
- image: gcr.io/kuar-demo/kuard-amd64:1
imagePullPolicy: Always
name: kuard
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: kuard
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
selector:
app: kuard
部署 ingress 资源
下面的配置有几个需要注意的地方:
- 使用
letsencrypt-staging
issuer,也就是我们上面创建的 issuer。 - 使用
nginx-lr90
这个 ingressClass。 - 配置 kuard 服务的 virtual host 为
kuard.cn-dev.mmoo.tech
,我们要使用这个 vhost 访问我们的服务。这个域名需要提前在公有云 dns 服务器处配置好,否则 dns http01 无法验证。 - 转发规则部分就是根据 host
kuard.cn-dev.mmoo.tech
转发到同命名空间的 servicekuard
。
root@mo-next-master0:~/lr90# cat ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kuard
namespace: lr90
annotations:
cert-manager.io/cluster-issuer: "http01-staging"
spec:
ingressClassName: nginx-lr90
tls:
- hosts:
- kuard.mo.cn-dev.mmoo.tech
secretName: kuard-tls
rules:
- host: kuard.mo.cn-dev.mmoo.tech
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kuard
port:
number: 80
创建完成之后,cert-manager 会自动帮我们创建 certificate,并处理后续证书的 renew,自动创建的证书名称跟上面的 secret kuard-tls
一致。
测试访问
使用 curl 命令进行测试。需要使用 -L
处理 308 Permanent Redirect
重定向,以及 -k
不验证证书,因为是 staging 环境签的证书。
lr90@sj pulumi % curl -L -k kuard.mo.cn-dev.mmoo.tech
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>KUAR Demo</title>
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
<link rel="stylesheet" href="/static/css/styles.css">
... ...
dns 验证
dns 验证是 ca 验证签证书的人真正拥有证书里面的域名,或者说对域名具有控制权,有下面两种方式。
http01 验证
http01 需要结合 ingress 使用,在使用这种方式时,需要事先在 dns 服务器处添加好 ingress 资源中的域名,比如上面的 kuard.mo.cn-dev.mmoo.tech
,cert-manager 在帮我们执行 http01 验证的时候,会在对应 ingress 资源同命名空间创建一个用于验证域名的 http 服务以及对应的临时 ingress。这个临时
+9q3.*6 ingress 的配置大概如下:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: cm-acme-http-solver-<random-suffix> # 动态生成的名字,带有随机后缀
namespace: <your-namespace> # Ingress 所在的命名空间
spec:
rules:
- host: example.com # 待验证的域名
http:
paths:
- path: /.well-known/acme-challenge/<token> # ACME 验证路径
pathType: Exact
backend:
service:
name: cm-acme-http-solver-<random-suffix> # 指向 cert-manager 创建的内部服务
port:
number: 8089 # cert-manager 服务监听的端口
上面的临时 ingress 以及整个 http01 验证我们都不需要关心,都是自动完成的。进行 dns 验证时,只要能访问通这个地址 kuard.mo.cn-dev.mmoo.tech/.well-known/acme-challenge/<token>
就认为验证是成功的。
dns01 验证
dns01 验证是指需要域名拥有者在域名服务出添加一个 txt 记录,证书提供商监听到这个 txt 记录之后,就认为域名是合法的。 参考 cert-manager webhook-example 实现 webhook 即可。总体来说就是实现下面几个接口,就是添加 txt 记录和删除 txt 记录,对于阿里云来说,就是需要我们调用阿里云的 dns sdk 去添加 txt 记录。
// Solver has the functionality to solve ACME challenges. This interface is
// implemented internally by RFC2136 DNS provider and by external webhook solver
// implementations see https://github.com/cert-manager/webhook-example
type Solver interface {
// Name is the name of this ACME solver as part of the API group.
// This must match what you configure in the ACME Issuer's DNS01 config.
Name() string
// Present should 'present' the ACME challenge solving parameters as
// defined in the given challenge resource.
// TODO: add notes about duplicate records with DNS01
Present(ch *whapi.ChallengeRequest) error
// CleanUp should remove any presented challenge records for the given
// challenge resource
// TODO: add notes about duplicate records with DNS01
CleanUp(ch *whapi.ChallengeRequest) error
// Initialize is called as a post-start hook when the apiserver starts.
// https://github.com/kubernetes/apiserver/blob/release-1.26/pkg/server/hooks.go#L32-L42
Initialize(kubeClientConfig *restclient.Config, stopCh <-chan struct{}) error
}