一.系统环境

服务器版本 docker软件版本 Kubernetes(k8s)集群版本 kube-bench版本 CPU架构
Ubuntu 18.04.5 LTS Docker version 20.10.14 v1.22.2 0.6.7 x86_64

Kubernetes集群架构:k8scludes1作为master节点,k8scludes2,k8scludes3作为worker节点。

服务器 操作系统版本 CPU架构 进程 功能描述
k8scludes1/192.168.110.128 Ubuntu 18.04.5 LTS x86_64 docker,kube-apiserver,etcd,kube-scheduler,kube-controller-manager,kubelet,kube-proxy,coredns,calico k8s master节点
k8scludes2/192.168.110.129 Ubuntu 18.04.5 LTS x86_64 docker,kubelet,kube-proxy,calico k8s worker节点
k8scludes3/192.168.110.130 Ubuntu 18.04.5 LTS x86_64 docker,kubelet,kube-proxy,calico k8s worker节点

二.前言

在现代的应用程序开发中,使用HTTPS来保护数据传输的安全性变得越来越重要。而在Kubernetes集群中配置Ingress支持HTTPS访问,可以为我们的应用程序提供更高的安全性。

本文将介绍如何在Kubernetes集群中配置Ingress支持HTTPS访问,使用Let's Encrypt和cert-manager工具来自动颁发和更新权威证书。

注意:上一篇博客《Kubernetes集群中配置Ingress支持HTTPS访问(一):cfssl》里,使用cfssl工具生成了证书,实现了https访问,但是那个证书是我们自定义的,不是权威机构颁发的证书,在浏览器里https访问还是有警告,此次使用cert-manager向Let’s Encrypt机构申请的证书,是权威证书,在浏览器里https访问是不会有警告的。

在Kubernetes集群中配置Ingress支持HTTPS访问的前提是已经有一套可以正常运行的Kubernetes集群,关于Kubernetes(k8s)集群的安装部署,可以查看博客《Ubuntu 安装部署Kubernetes(k8s)集群》https://www.cnblogs.com/renshengdezheli/p/17632858.html。

三.Let's Encrypt和cert-manager简介

Let’s Encrypt 是一家免费、开放、自动化的证书颁发机构(CA),它提供了免费的SSL/TLS证书。Let's Encrypt的证书由ACME协议自动颁发和更新。letsencrypt官网为:https://letsencrypt.org/zh-cn/,Let's Encrypt 的运作方式可以查看文档:https://letsencrypt.org/zh-cn/how-it-works/。

cert-manager是一个用于管理证书生命周期的工具,它可以自动化证书的颁发和更新。它与Kubernetes紧密集成,可以轻松地在集群中部署和配置。cert-manager官网为:https://cert-manager.io/。

Let’s Encrypt 可以免费提供证书,不过证书只有90天有效期,过期之后需要重新申请,使用cert-manager工具可以自动向Let’s Encrypt机构申请证书和续约证书,两者结合使用事半功倍。

四.部署cert-manager

4.1 安装cert-manager

在博客《Kubernetes集群中配置Ingress支持HTTPS访问(一):cfssl》里详细介绍了配置ingress对外发布服务的步骤,本文不再赘述。

cert-manager安装文档为:https://cert-manager.io/docs/installation/。

安装cert-manager之后,会建立CRD资源类型(自定义资源类型),Kubernetes 1.7之后,提供了CRD(CustomResourceDefinitions)自定义资源的二次开发能力来扩展kubernetes API,通过此扩展可以向kubernetes API中增加新的资源类型,会比修改kubernetes apiserver的源代码或创建自定义的apiserver来的更加的简洁和容易。

查看crd资源。

root@k8scludes1:~# kubectl get crd -o wide
NAME CREATED AT
bgpconfigurations.crd.projectcalico.org 2022-04-16T18:41:13Z
bgppeers.crd.projectcalico.org 2022-04-16T18:41:13Z
blockaffinities.crd.projectcalico.org 2022-04-16T18:41:13Z
caliconodestatuses.crd.projectcalico.org 2022-04-16T18:41:13Z
clusterinformations.crd.projectcalico.org 2022-04-16T18:41:13Z
felixconfigurations.crd.projectcalico.org 2022-04-16T18:41:13Z
globalnetworkpolicies.crd.projectcalico.org 2022-04-16T18:41:13Z
globalnetworksets.crd.projectcalico.org 2022-04-16T18:41:13Z
hostendpoints.crd.projectcalico.org 2022-04-16T18:41:13Z
ipamblocks.crd.projectcalico.org 2022-04-16T18:41:13Z
ipamconfigs.crd.projectcalico.org 2022-04-16T18:41:13Z
ipamhandles.crd.projectcalico.org 2022-04-16T18:41:13Z
ippools.crd.projectcalico.org 2022-04-16T18:41:13Z
ipreservations.crd.projectcalico.org 2022-04-16T18:41:13Z
kubecontrollersconfigurations.crd.projectcalico.org 2022-04-16T18:41:13Z
networkpolicies.crd.projectcalico.org 2022-04-16T18:41:13Z
networksets.crd.projectcalico.org 2022-04-16T18:41:13Z

创建cert-manager目录存放文件。

root@k8scludes1:~# mkdir cert-manager

root@k8scludes1:~# cd cert-manager/

下载cert-manager的安装yaml文件。

root@k8scludes1:~# wget https://github.com/cert-manager/cert-manager/releases/download/v1.8.0/cert-manager.yaml

root@k8scludes1:~/cert-manager# ls
cert-manager.yaml

查看 cert-manager.yaml 所需的镜像。

root@k8scludes1:~/cert-manager# grep image cert-manager.yaml
image: "quay.io/jetstack/cert-manager-cainjector:v1.8.0"
imagePullPolicy: IfNotPresent
image: "quay.io/jetstack/cert-manager-controller:v1.8.0"
imagePullPolicy: IfNotPresent
image: "quay.io/jetstack/cert-manager-webhook:v1.8.0"
imagePullPolicy: IfNotPresent

在k8s的worker节点提前下载 cert-manager.yaml 所需的镜像。

root@k8scludes2:~# docker pull quay.io/jetstack/cert-manager-cainjector:v1.8.0
root@k8scludes2:~# docker pull quay.io/jetstack/cert-manager-controller:v1.8.0
root@k8scludes2:~# docker pull quay.io/jetstack/cert-manager-webhook:v1.8.0 root@k8scludes3:~# docker pull quay.io/jetstack/cert-manager-cainjector:v1.8.0
root@k8scludes3:~# docker pull quay.io/jetstack/cert-manager-controller:v1.8.0
root@k8scludes3:~# docker pull quay.io/jetstack/cert-manager-webhook:v1.8.0

查看下载好的镜像。

root@k8scludes2:~/cert-manager# docker images | grep cert-manager
quay.io/jetstack/cert-manager-webhook v1.8.0 5efca4d28ca6 2 weeks ago 45.4MB
quay.io/jetstack/cert-manager-cainjector v1.8.0 7c3e4d23dcd7 2 weeks ago 38.6MB
quay.io/jetstack/cert-manager-controller v1.8.0 2b8eb1ab5ff9 2 weeks ago 57.4MB root@k8scludes3:~/cert-manager# docker images | grep cert-manager
quay.io/jetstack/cert-manager-webhook v1.8.0 5efca4d28ca6 2 weeks ago 45.4MB
quay.io/jetstack/cert-manager-cainjector v1.8.0 7c3e4d23dcd7 2 weeks ago 38.6MB
quay.io/jetstack/cert-manager-controller v1.8.0 2b8eb1ab5ff9 2 weeks ago 57.4MB

安装cert-manager。

root@k8scludes1:~/cert-manager# ls
cert-manager.yaml root@k8scludes1:~/cert-manager# kubectl apply -f cert-manager.yaml
namespace/cert-manager created
customresourcedefinition.apiextensions.k8s.io/certificaterequests.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/certificates.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/challenges.acme.cert-manager.io created
......
deployment.apps/cert-manager-webhook created
mutatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook created
validatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook created

查看cert-manager命名空间里的所有资源。

root@k8scludes1:~/cert-manager# kubectl get all -n cert-manager -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/cert-manager-b4d6fd99b-mndtp 1/1 Running 0 61s 10.244.1.96 k8scludes3 <none> <none>
pod/cert-manager-cainjector-74bfccdfdf-l6kh9 1/1 Running 0 61s 10.244.218.162 k8scludes2 <none> <none>
......
replicaset.apps/cert-manager-webhook-65b766b5f8 1 1 1 61s cert-manager quay.io/jetstack/cert-manager-webhook:v1.8.0 app.kubernetes.io/component=webhook,app.kubernetes.io/instance=cert-manager,app.kubernetes.io/name=webhook,pod-template-hash=65b766b5f8

可以看到crd是全局生效的,不受命名空间限制。

root@k8scludes1:~/cert-manager# kubectl get crd -o wide -n cert-manager
NAME CREATED AT
bgpconfigurations.crd.projectcalico.org 2022-04-16T18:41:13Z
bgppeers.crd.projectcalico.org 2022-04-16T18:41:13Z
blockaffinities.crd.projectcalico.org 2022-04-16T18:41:13Z
caliconodestatuses.crd.projectcalico.org 2022-04-16T18:41:13Z
certificaterequests.cert-manager.io 2022-04-24T17:07:46Z
certificates.cert-manager.io 2022-04-24T17:07:46Z
challenges.acme.cert-manager.io 2022-04-24T17:07:46Z
clusterinformations.crd.projectcalico.org 2022-04-16T18:41:13Z
clusterissuers.cert-manager.io 2022-04-24T17:07:46Z
felixconfigurations.crd.projectcalico.org 2022-04-16T18:41:13Z
globalnetworkpolicies.crd.projectcalico.org 2022-04-16T18:41:13Z
globalnetworksets.crd.projectcalico.org 2022-04-16T18:41:13Z
hostendpoints.crd.projectcalico.org 2022-04-16T18:41:13Z
ipamblocks.crd.projectcalico.org 2022-04-16T18:41:13Z
ipamconfigs.crd.projectcalico.org 2022-04-16T18:41:13Z
ipamhandles.crd.projectcalico.org 2022-04-16T18:41:13Z
ippools.crd.projectcalico.org 2022-04-16T18:41:13Z
ipreservations.crd.projectcalico.org 2022-04-16T18:41:13Z
issuers.cert-manager.io 2022-04-24T17:07:46Z
kubecontrollersconfigurations.crd.projectcalico.org 2022-04-16T18:41:13Z
networkpolicies.crd.projectcalico.org 2022-04-16T18:41:13Z
networksets.crd.projectcalico.org 2022-04-16T18:41:13Z
orders.acme.cert-manager.io 2022-04-24T17:07:46Z

查看和cert-manager相关的crd资源。

root@k8scludes1:~/cert-manager# kubectl get crd | grep cert
certificaterequests.cert-manager.io 2022-04-24T17:07:46Z
certificates.cert-manager.io 2022-04-24T17:07:46Z
challenges.acme.cert-manager.io 2022-04-24T17:07:46Z
clusterissuers.cert-manager.io 2022-04-24T17:07:46Z
issuers.cert-manager.io 2022-04-24T17:07:46Z
orders.acme.cert-manager.io 2022-04-24T17:07:46Z

4.2 创建clusterissuer

cert-manager会创建clusterissuer自定义资源,clusterissuer会向letsencrypt机构申请证书和续约证书。

用户向clusterissuer提出申请证书请求,clusterissuer向letsencrypt机构申请证书,letsencrypt机构进行审核,假如申请的域名为www.nginxx.com,letsencrypt,机构会审核www.nginxx.com这个站点是不是你的?审核的方式有:http01和dns01。

  • 使用http01的审核方式:letsencrypt机构会登录到www.nginxx.com,看看能不能访问成功,访问成功就证明是你的网站,我们现在测试环境为内网环境,letsencrypt访问不了;
  • 使用dns01的审核方式:如果www.nginxx.com是你的站点,你肯定有dns服务器的操控权,在DNS服务器上生成一个api token,letsencrypt会尝试使用这个api token往DNS服务器写入内容,如果能写入成功,则说明www.nginxx.com站点是你的,就会审核通过。本文使用dns01的方式。

现在还没有clusterissuer资源,clusterissuer是全局生效的,不受命名空间限制。

root@k8scludes1:~/cert-manager# kubectl get clusterissuer
No resources found root@k8scludes1:~/cert-manager# kubectl get clusterissuer -n cert-manager
No resources found

创建Issuer和ClusterIssuer可以去官网找例子:https://cert-manager.io/docs/configuration/acme/dns01/。

letsencrypt审核域名的方式我们使用DNS01的方式,letsencrypt支持的DNS服务器有限,本次使用Cloudflare DNS服务器。

root@k8scludes1:~/cert-manager# cat clusterissuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
#ClusterIssuer的名字
name: letsencrypt-dns01
spec:
acme:
privateKeySecretRef:
name: letsencrypt-dns01
#ClusterIssuer去https://acme-v02.api.letsencrypt.org/directory申请证书
server: https://acme-v02.api.letsencrypt.org/directory
solvers:
- dns01:
cloudflare:
email: my-cloudflare-acc@example.com
apiTokenSecretRef:
key: api-token
name: cloudflare-api-token-secret

cert-manager配置cloudflare DNS的yaml文件可以查看官网示例:https://cert-manager.io/docs/configuration/acme/dns01/cloudflare/。

要使用Cloudflare DNS服务器,需要先注册一个Cloudflare账号,Cloudflare网址为:https://dash.cloudflare.com/login。

注册成功之后登录Cloudflare。

添加站点,但是域名没有注册,现在先去阿里云申请一个域名。

4.3 申请域名

登录阿里云,工作台-->点击域名。

点击注册域名。

输入域名--->查域名,我申请的域名为rengshengdezheli。

选择一个便宜的域名,加入清单。

点击域名清单。

结算一下。

经过个人信息审核之后,域名申请下来了,我的域名为rengshengdezheli.xyz。

在域名列表查看域名信息。

此时域名申请成功了。

4.4 Cloudflare添加站点

使用新申请到的域名,到Cloudflare添加站点。

选择免费的计划,点击继续。

点击继续。

点击确定。

4.5 修改阿里云的名称服务器为cloudflare名称服务器

按照要求要把阿里云的名称服务器更改为cloudflare名称服务器。

去到阿里云网站,找到域名,域名列表,点击修改DNS。

点击修改DNS服务器。

把DNS服务器修改为cloudflare的DNS服务器,最后点击确定。

现在就修改好了。

返回cloudflare网站,检查名称服务器。

配置好之后会出现如下界面。

现在域名rengshengdezheli.xyz的DNS服务器就是cloudflare服务器了。

4.6 获取API Tokens

根据cert-manager官网的指引:https://cert-manager.io/docs/configuration/acme/dns01/cloudflare/,我们获取API Tokens。

回到Cloudflare网站,点击获取您的API令牌。

点击创建令牌。

创建自定义令牌,点击开始使用。

填写API令牌的名称,权限和区域资源按照cert-manager的要求设置,点击继续以显示摘要。

点击创建令牌。

此时API令牌就创建好了。

测试我们创建的令牌是否正常。"success":true表示我们创建的令牌正常了。

root@k8scludes1:~/cert-manager# curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
> -H "Authorization: Bearer LKA4oW_7lHqgD66UgbTK5cMYq_4JUQ7kirCGCRj4" \
> -H "Content-Type:application/json"
{"result":{"id":"8ee3954262ba4d0aeaa90c6fbe94af69","status":"active"},"success":true,"errors":[],"messages":[{"code":10000,"message":"This API Token is valid and active","type":null}]}root@k8scludes1:~/cert-manager#

letsencrypt通过我们创建的API令牌就可以往我们的cloudflare DNS服务器里写入内容,如果成功写入内容,则证明站点rengshengdezheli.xyz是我们的,则审核通过。

4.7 创建secret存储API token

现在需要把API令牌告诉letsencrypt,通过clusterissuer告诉letsencrypt我们的API令牌。

因为创建clusterissuer需要存着API token的secret,所以现在创建secret。

查看 cert-manager命名空间的secret。

root@k8scludes1:~/cert-manager# kubectl get secrets -n cert-manager
NAME TYPE DATA AGE
cert-manager-cainjector-token-ltxpd kubernetes.io/service-account-token 3 19h
cert-manager-token-k5s55 kubernetes.io/service-account-token 3 19h
cert-manager-webhook-ca Opaque 3 19h
cert-manager-webhook-token-x94pp kubernetes.io/service-account-token 3 19h
default-token-wl2sx kubernetes.io/service-account-token 3 19h

创建一个secret存储API令牌,secret的创建方法,官网也有例子。

apiVersion: v1
kind: Secret
metadata:
name: cloudflare-api-token-secret
type: Opaque
stringData:
api-token: <API Token>

本次使用命令行的方式创建secret,--from-literal指定键值对: api-token是键,LKA4oW_7lHqgD66UgbTK5cMYq_4JUQ7kirCGCRj4 就是我们创建的API令牌(API token )。

root@k8scludes1:~/cert-manager# kubectl create secret generic cloudflare-api-token-secret --from-literal=api-token=LKA4oW_7lHqgD66UgbTK5cMYq_4JUQ7kirCGCRj4 -n cert-manager
secret/cloudflare-api-token-secret created

查看创建的secrets。

root@k8scludes1:~/cert-manager# kubectl get secrets -n cert-manager
NAME TYPE DATA AGE
cert-manager-cainjector-token-ltxpd kubernetes.io/service-account-token 3 19h
cert-manager-token-k5s55 kubernetes.io/service-account-token 3 19h
cert-manager-webhook-ca Opaque 3 19h
cert-manager-webhook-token-x94pp kubernetes.io/service-account-token 3 19h
cloudflare-api-token-secret Opaque 1 116s
default-token-wl2sx kubernetes.io/service-account-token 3 19h

4.8 配置clusterissuer

存储API token的secret创建好了,就可以创建clusterissuer了。

root@k8scludes1:~/cert-manager# vim clusterissuer.yaml 

root@k8scludes1:~/cert-manager# cat clusterissuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
#ClusterIssuer名字
name: letsencrypt-dns01
spec:
acme:
privateKeySecretRef:
name: letsencrypt-dns01
#ClusterIssuer去https://acme-v02.api.letsencrypt.org/directory申请证书
server: https://acme-v02.api.letsencrypt.org/directory
solvers:
- dns01:
cloudflare:
email: 5386225891@qq.com
#指定存储着API token的secret,secret的名字为cloudflare-api-token-secret,secret的key为api-token
apiTokenSecretRef:
key: api-token
name: cloudflare-api-token-secret

下面创建clusterissuer。

root@k8scludes1:~/cert-manager# kubectl apply -f clusterissuer.yaml
clusterissuer.cert-manager.io/letsencrypt-dns01 created

clusterissuer创建成功。

root@k8scludes1:~/cert-manager# kubectl get clusterissuers.cert-manager.io
NAME READY AGE
letsencrypt-dns01 True 29s root@k8scludes1:~/cert-manager# kubectl get clusterissuers.cert-manager.io -o wide
NAME READY STATUS AGE
letsencrypt-dns01 True The ACME account was registered with the ACME server 33s

clusterissuers创建好之后,下面开始申请证书。

五.申请证书

查看现在是否有证书,现在没有证书。

root@k8scludes1:~/cert-manager# kubectl get certificate -o wide
No resources found in tls-ingress namespace.

编写申请证书的yaml文件。

root@k8scludes1:~/cert-manager# vim certificate.yaml 

root@k8scludes1:~/cert-manager# cat certificate.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
#cert-zheli-com是申请的证书名字
name: cert-zheli-com
spec:
dnsNames:
#www.rengshengdezheli.xyz表示申请的证书只给www.rengshengdezheli.xyz用
- www.rengshengdezheli.xyz
issuerRef:
kind: ClusterIssuer
#name: letsencrypt-dns01表示使用哪个ClusterIssuer申请证书
name: letsencrypt-dns01
#secretName: cert-zheli-com-tls表示申请到的证书放在哪个secret里面
secretName: cert-zheli-com-tls

现在申请证书。

root@k8scludes1:~/cert-manager# kubectl apply -f certificate.yaml
certificate.cert-manager.io/cert-zheli-com created

查看证书,有证书但是READY状态为False。

root@k8scludes1:~/cert-manager# kubectl get certificate -o wide
NAME READY SECRET ISSUER STATUS AGE
cert-zheli-com False cert-zheli-com-tls letsencrypt-dns01 Issuing certificate as Secret does not exist 26s

查看secret。

root@k8scludes1:~/cert-manager# kubectl get secrets -o wide
NAME TYPE DATA AGE
cert-zheli-com-btt2t Opaque 1 2m16s
default-token-mxb4r kubernetes.io/service-account-token 3 7d8h
test-tls-secret kubernetes.io/tls 2 3d8h

查看证书请求。

root@k8scludes1:~/cert-manager# kubectl get certificaterequests.cert-manager.io -o wide
NAME APPROVED DENIED READY ISSUER REQUESTOR STATUS AGE
cert-zheli-com-cbkt2 True True letsencrypt-dns01 system:serviceaccount:cert-manager:cert-manager Certificate fetched from issuer successfully 3m54s

查看challenges,challenges用来验证证书请求是否成功,当证书申请成功之后,challenges会消失,certificaterequests的READY状态变为True。

root@k8scludes1:~/cert-manager# kubectl get challenges.acme.cert-manager.io -o wide
No resources found in tls-ingress namespace.

现在cert-zheli-com证书申请成功,READY状态变为True。

root@k8scludes1:~/cert-manager# kubectl get certificate -o wide
NAME READY SECRET ISSUER STATUS AGE
cert-zheli-com True cert-zheli-com-tls letsencrypt-dns01 Certificate is up to date and has not expired 10m

secret由cert-zheli-com-btt2t变为cert-zheli-com-tls,现在证书就在cert-zheli-com-tls里面了。

root@k8scludes1:~/cert-manager# kubectl get secrets -o wide
NAME TYPE DATA AGE
cert-zheli-com-tls kubernetes.io/tls 2 11m
default-token-mxb4r kubernetes.io/service-account-token 3 7d8h
test-tls-secret kubernetes.io/tls 2 3d9h

六.配置ingress使用证书

删除存在的ingress规则。

root@k8scludes1:~/cert-manager# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
my-ingress <none> www.nginxx.com 192.168.110.129 80, 443 30h root@k8scludes1:~/cert-manager# kubectl delete ingress my-ingress
ingress.networking.k8s.io "my-ingress" deleted root@k8scludes1:~/cert-manager# kubectl get ingress
No resources found in tls-ingress namespace.

修改ingress规则,- www.rengshengdezheli.xyz表示申请的证书只给www.rengshengdezheli.xyz这个域名用,secretName: cert-zheli-com-tls表示证书放在cert-zheli-com-tls这个secret里。

root@k8scludes1:~/cert-manager# vim ingress-rule.yaml 

root@k8scludes1:~/cert-manager# cat ingress-rule.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
tls:
- hosts:
- www.rengshengdezheli.xyz
secretName: cert-zheli-com-tls
rules:
- host: www.rengshengdezheli.xyz
http:
paths:
#访问网址目录
- path: /
pathType: Prefix
backend:
service:
name: nginx1svc
port:
number: 80
- path: /ingress
pathType: Prefix
backend:
service:
name: nginx3svc
port:
number: 80
- path: /n2
pathType: Prefix
backend:
service:
name: nginx2svc
port:
number: 80

应用ingress规则。

root@k8scludes1:~/cert-manager# kubectl apply -f ingress-rule.yaml
ingress.networking.k8s.io/my-ingress created root@k8scludes1:~/cert-manager# kubectl get ingress -o wide
NAME CLASS HOSTS ADDRESS PORTS AGE
my-ingress <none> www.rengshengdezheli.xyz 80, 443 9s

查看svc,443端口映射为31473了。

root@k8scludes1:~/cert-manager# kubectl get svc -o wide -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
ingress-nginx-controller NodePort 10.98.61.146 <none> 80:31853/TCP,443:31473/TCP 5d7h app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
ingress-nginx-controller-admission ClusterIP 10.102.212.60 <none> 443/TCP 5d7h app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx

七.客户端访问ingress服务

7.1 Windows客户端访问ingress服务

证书申请下来之后,使用Windows客户端访问ingress服务。

注意:C:/Windows/System32/drivers/etc/HOSTS里的IP域名映射也要修改。内容修改如下,192.168.110.129是ingress-nginx-controller所在的机器IP。

192.168.110.129 www.rengshengdezheli.xyz

浏览器访问https://www.rengshengdezheli.xyz:31473/,可以发现现在浏览器访问https://www.rengshengdezheli.xyz:31473/没有警告了。

查看证书,显示连接是安全的。

点击查看证书信息。

可以看到详细的证书信息。

7.2 Linux客户端访问ingress服务

下面使用Linux客户端访问ingress服务,可以看到证书颁发机构:issuer: CN=R3,O=Let's Encrypt,C=US。

[root@etcd2 ~]# curl https://www.rengshengdezheli.xyz:31473/
111 [root@etcd2 ~]# curl -kv https://www.rengshengdezheli.xyz:31473/
* About to connect() to www.rengshengdezheli.xyz port 31473 (#0)
* Trying 192.168.110.129...
* Connected to www.rengshengdezheli.xyz (192.168.110.129) port 31473 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate:
* subject: CN=www.rengshengdezheli.xyz
* start date: 4月 25 16:11:21 2022 GMT
* expire date: 7月 24 16:11:20 2022 GMT
* common name: www.rengshengdezheli.xyz
* issuer: CN=R3,O=Let's Encrypt,C=US
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: www.rengshengdezheli.xyz:31473
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Mon, 25 Apr 2022 17:51:19 GMT
< Content-Type: text/html
< Content-Length: 4
< Connection: keep-alive
< Last-Modified: Mon, 25 Apr 2022 17:34:19 GMT
< ETag: "6266db9b-4"
< Accept-Ranges: bytes
< Strict-Transport-Security: max-age=15724800; includeSubDomains
<
111
* Connection #0 to host www.rengshengdezheli.xyz left intact

八.配置clusterissuer自动申请证书

上一步,我们申请证书的步骤是创建certificate,然后clusterissuer使用certificate申请证书,最后带有certificate信息的secret和ingress一起使用。

我们现在使用另外一种方法,创建ingress的时候自动让clusterissuer申请证书,不用创建certificate yaml文件。

删除证书。

root@k8scludes1:~/cert-manager# kubectl get certificate
NAME READY SECRET AGE
cert-zheli-com True cert-zheli-com-tls 48m root@k8scludes1:~/cert-manager# kubectl delete certificate cert-zheli-com
certificate.cert-manager.io "cert-zheli-com" deleted root@k8scludes1:~/cert-manager# kubectl get certificate
No resources found in tls-ingress namespace.

删除secret。

root@k8scludes1:~/cert-manager# kubectl get secrets
NAME TYPE DATA AGE
cert-zheli-com-tls kubernetes.io/tls 2 47m
default-token-mxb4r kubernetes.io/service-account-token 3 7d8h
test-tls-secret kubernetes.io/tls 2 3d9h root@k8scludes1:~/cert-manager# kubectl delete secrets cert-zheli-com-tls
secret "cert-zheli-com-tls" deleted root@k8scludes1:~/cert-manager# kubectl get secrets
NAME TYPE DATA AGE
default-token-mxb4r kubernetes.io/service-account-token 3 7d8h
test-tls-secret kubernetes.io/tls 2 3d9h

修改ingress规则,添加cert-manager.io/cluster-issuer: "letsencrypt-dns01"表示使用名为letsencrypt-dns01的clusterissuer申请证书。

当我们创建ingress规则之后,会自动使用名为letsencrypt-dns01的clusterissuer申请证书,申请的证书放在名为cert-zheli-com-tls的secret里。

root@k8scludes1:~/cert-manager# vim ingress-rule.yaml 

root@k8scludes1:~/cert-manager# cat ingress-rule.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-dns01"
spec:
tls:
- hosts:
- www.rengshengdezheli.xyz
secretName: cert-zheli-com-tls
rules:
- host: www.rengshengdezheli.xyz
http:
paths:
#访问网址目录
- path: /
pathType: Prefix
backend:
service:
name: nginx1svc
port:
number: 80
- path: /ingress
pathType: Prefix
backend:
service:
name: nginx3svc
port:
number: 80
- path: /n2
pathType: Prefix
backend:
service:
name: nginx2svc
port:
number: 80

现在没有证书。

root@k8scludes1:~/cert-manager# kubectl get certificate
No resources found in tls-ingress namespace. root@k8scludes1:~/cert-manager# kubectl get secrets
NAME TYPE DATA AGE
default-token-mxb4r kubernetes.io/service-account-token 3 7d9h
test-tls-secret kubernetes.io/tls 2 3d10h

删除以前的ingress规则。

root@k8scludes1:~/cert-manager# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
my-ingress <none> www.rengshengdezheli.xyz 192.168.110.129 80, 443 53m root@k8scludes1:~/cert-manager# kubectl delete ingress my-ingress
ingress.networking.k8s.io "my-ingress" deleted
root@k8scludes1:~/cert-manager# kubectl get ingress
No resources found in tls-ingress namespace.

创建ingress规则。

root@k8scludes1:~/cert-manager# kubectl apply -f ingress-rule.yaml
ingress.networking.k8s.io/my-ingress created root@k8scludes1:~/cert-manager# kubectl get ingress -o wide
NAME CLASS HOSTS ADDRESS PORTS AGE
my-ingress <none> www.rengshengdezheli.xyz 80, 443 9s

现在创建ingress规则之后,就自动申请了证书了。

root@k8scludes1:~/cert-manager# kubectl get certificate -o wide
NAME READY SECRET ISSUER STATUS AGE
cert-zheli-com-tls True cert-zheli-com-tls letsencrypt-dns01 Certificate is up to date and has not expired 21s root@k8scludes1:~/cert-manager# kubectl get secrets -o wide
NAME TYPE DATA AGE
cert-zheli-com-tls kubernetes.io/tls 2 47s
default-token-mxb4r kubernetes.io/service-account-token 3 7d9h
test-tls-secret kubernetes.io/tls 2 3d10h root@k8scludes1:~/cert-manager# kubectl get clusterissuers.cert-manager.io -o wide
NAME READY STATUS AGE
letsencrypt-dns01 True The ACME account was registered with the ACME server 5h37m

证书到期之后,clusterissuers会自动给我们续约的。

可以查看我们创建的clusterissuer的yaml文件。

root@k8scludes1:~/cert-manager# kubectl get clusterissuers.cert-manager.io letsencrypt-dns01 -o yaml >letsencrypt-dns01.yaml

root@k8scludes1:~/cert-manager# cat letsencrypt-dns01.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"cert-manager.io/v1","kind":"ClusterIssuer","metadata":{"annotations":{},"name":"letsencrypt-dns01"},"spec":{"acme":{"privateKeySecretRef":{"name":"letsencrypt-dns01"},"server":"https://acme-v02.api.letsencrypt.org/directory","solvers":[{"dns01":{"cloudflare":{"apiTokenSecretRef":{"key":"api-token","name":"cloudflare-api-token-secret"},"email":"2484990158@qq.com"}}}]}}}
creationTimestamp: "2022-04-25T12:51:49Z"
generation: 1
name: letsencrypt-dns01
resourceVersion: "389137"
uid: 61ef0780-8889-486f-8fa7-a68ba0ce72da
spec:
acme:
preferredChain: ""
privateKeySecretRef:
name: letsencrypt-dns01
server: https://acme-v02.api.letsencrypt.org/directory
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
key: api-token
name: cloudflare-api-token-secret
email: 2484990158@qq.com
status:
acme:
uri: https://acme-v02.api.letsencrypt.org/acme/acct/515015057
conditions:
- lastTransitionTime: "2022-04-25T12:51:52Z"
message: The ACME account was registered with the ACME server
observedGeneration: 1
reason: ACMEAccountRegistered
status: "True"
type: Ready

九.没有域名的情况下申请证书

上面方法需要买一个域名才能进行,当我们没有域名的时候,也可以模拟使用cert-manager申请证书。

没有域名的情况下申请证书思路:先模拟一个CA(CA是权威机构),创建一个clusterissuer,再创建一个certificate去向CA申请证书。

删除clusterissuer。

root@k8scludes1:~# kubectl get clusterissuers.cert-manager.io
NAME READY AGE
letsencrypt-dns01 True 14h root@k8scludes1:~# kubectl delete clusterissuers.cert-manager.io letsencrypt-dns01
clusterissuer.cert-manager.io "letsencrypt-dns01" deleted

删除证书。

root@k8scludes1:~# kubectl get certificate
NAME READY SECRET AGE
cert-zheli-com-tls True cert-zheli-com-tls 8h root@k8scludes1:~# kubectl delete certificate cert-zheli-com-tls
certificate.cert-manager.io "cert-zheli-com-tls" deleted

删除secret。

root@k8scludes1:~# kubectl get secrets
NAME TYPE DATA AGE
cert-zheli-com-tls kubernetes.io/tls 2 8h
default-token-mxb4r kubernetes.io/service-account-token 3 7d18h
test-tls-secret kubernetes.io/tls 2 3d18h root@k8scludes1:~# kubectl delete secrets cert-zheli-com-tls
secret "cert-zheli-com-tls" deleted

删除ingress。

root@k8scludes1:~/cert-manager# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
my-ingress <none> www.rengshengdezheli.xyz 192.168.110.129 80, 443 9h root@k8scludes1:~/cert-manager# kubectl delete ingress my-ingress
ingress.networking.k8s.io "my-ingress" deleted

上一篇博客《Kubernetes集群中配置Ingress支持HTTPS访问(一):cfssl》里,我们已经创建了CA的证书(ca.pem)和ca的私钥(ca-key.pem)。

root@k8scludes1:~# cd TLS-ingress/tls/

root@k8scludes1:~/TLS-ingress/tls# ls
ca-config.json ca.csr ca-csr.json ca-key.pem ca.pem test.csr test-csr.json test-key.pem test.pem

把CA的证书和密钥写入到 secret里,创建一个tls类型的secret,里面包含CA证书,CA私钥。

root@k8scludes1:~/TLS-ingress/tls# kubectl create secret tls ca-secret --cert=ca.pem --key=ca-key.pem --namespace=cert-manager
secret/ca-secret created root@k8scludes1:~/TLS-ingress/tls# kubectl get secrets -o wide -n cert-manager
NAME TYPE DATA AGE
ca-secret kubernetes.io/tls 2 16s
cert-manager-cainjector-token-ltxpd kubernetes.io/service-account-token 3 34h
cert-manager-token-k5s55 kubernetes.io/service-account-token 3 34h
cert-manager-webhook-ca Opaque 3 34h
cert-manager-webhook-token-x94pp kubernetes.io/service-account-token 3 34h
cloudflare-api-token-secret Opaque 1 14h
default-token-wl2sx kubernetes.io/service-account-token 3 34h
letsencrypt-dns01 Opaque 1 14h

现在模拟的CA已经创建好了,接下来创建clusterissuer。

namespace: cert-manager这个可以不写,因为ClusterIssuer是全局的,无所谓命名空间,secretName: ca-secret指定ca证书放在哪个secret里面。

root@k8scludes1:~/TLS-ingress/tls# cd ~/cert-manager/

root@k8scludes1:~/cert-manager# vim clusterissuer-moni.yaml 

root@k8scludes1:~/cert-manager# cat clusterissuer-moni.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
#ClusterIssuer名字
name: letsencrypt-ca-moni
namespace: cert-manager
spec:
ca:
secretName: ca-secret

用自己创建的CA模拟签发机构。

创建clusterissuer。

root@k8scludes1:~/cert-manager# kubectl apply -f clusterissuer-moni.yaml
clusterissuer.cert-manager.io/letsencrypt-ca-moni created root@k8scludes1:~/cert-manager# kubectl get clusterissuer -o wide
NAME READY STATUS AGE
letsencrypt-ca-moni True Signing CA verified 21s

修改certificate配置文件。

root@k8scludes1:~/cert-manager# vim certificate-moni.yaml 

root@k8scludes1:~/cert-manager# cat certificate-moni.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
#name: cert-zheli-com-moni表示申请到证书命名为cert-zheli-com-moni
name: cert-zheli-com-moni
spec:
dnsNames:
- www.rengshengdezheli.xyz
issuerRef:
kind: ClusterIssuer
#name: letsencrypt-ca-moni表示使用letsencrypt-ca-moni这个clusterissuer申请证书
name: letsencrypt-ca-moni
#secretName: cert-zheli-com-moni-tls表示申请到的证书放在cert-zheli-com-moni-tls这个secret里
secretName: cert-zheli-com-moni-tls

申请证书。

root@k8scludes1:~/cert-manager# kubectl apply -f certificate-moni.yaml
certificate.cert-manager.io/cert-zheli-com-moni created

现在已经向我们自己创建的CA申请到证书了。

root@k8scludes1:~/cert-manager# kubectl get certificate -o wide
NAME READY SECRET ISSUER STATUS AGE
cert-zheli-com-moni True cert-zheli-com-moni-tls letsencrypt-ca-moni Certificate is up to date and has not expired 18s

证书在cert-zheli-com-moni-tls里面。

root@k8scludes1:~/cert-manager# kubectl get secrets -o wide
NAME TYPE DATA AGE
cert-zheli-com-moni-tls kubernetes.io/tls 3 93s
default-token-mxb4r kubernetes.io/service-account-token 3 7d18h
test-tls-secret kubernetes.io/tls 2 3d19h

修改ingress规则,- www.rengshengdezheli.xyz表示申请到的证书只能用于www.rengshengdezheli.xyz这个域名,secretName: cert-zheli-com-moni-tls表示证书放在cert-zheli-com-moni-tls这个secret里。

root@k8scludes1:~/cert-manager# vim ingress-rule-moni.yaml 

root@k8scludes1:~/cert-manager# cat ingress-rule-moni.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
tls:
- hosts:
- www.rengshengdezheli.xyz
secretName: cert-zheli-com-moni-tls
rules:
- host: www.rengshengdezheli.xyz
http:
paths:
#访问网址目录
- path: /
pathType: Prefix
backend:
service:
name: nginx1svc
port:
number: 80
- path: /ingress
pathType: Prefix
backend:
service:
name: nginx3svc
port:
number: 80
- path: /n2
pathType: Prefix
backend:
service:
name: nginx2svc
port:
number: 80

应用ingress规则。

root@k8scludes1:~/cert-manager# kubectl get ingress
No resources found in tls-ingress namespace. root@k8scludes1:~/cert-manager# kubectl apply -f ingress-rule-moni.yaml
ingress.networking.k8s.io/my-ingress created root@k8scludes1:~/cert-manager# kubectl get ingress -o wide
NAME CLASS HOSTS ADDRESS PORTS AGE
my-ingress <none> www.rengshengdezheli.xyz 192.168.110.129 80, 443 11s

查看svc,443端口映射为31473。

root@k8scludes1:~/cert-manager# kubectl get svc -o wide -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
ingress-nginx-controller NodePort 10.98.61.146 <none> 80:31853/TCP,443:31473/TCP 5d18h app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
ingress-nginx-controller-admission ClusterIP 10.102.212.60 <none> 443/TCP 5d18h app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx

下面使用Windows客户端访问ingress服务。

这次我们使用IE浏览器访问:https://www.rengshengdezheli.xyz:31473/ingress/,访问成功。

查看证书。

可以看到这个证书是我们自定义的证书。

十.总结

通过使用Let's Encrypt和cert-manager工具,我们可以在Kubernetes集群中配置Ingress支持HTTPS访问。这样可以为我们的应用程序提供更高的安全性,保护数据传输的机密性和完整性。

配置Ingress支持HTTPS访问(二):使用cert-manager申请证书的更多相关文章

  1. 安装配置ingress-nginx支持https访问

    说明: ​ 1.k8s版本:v1.23: ​ 2.内网测试环境1台master,2台node节点,使用 DaemonSet+HostNetwork+nodeSelector 方式部署 ingress- ...

  2. k8s配置ingress的https访问

    一.部署步骤 1.安装nginx-ingress-controller 2.创建secret绑定证书 3.创建测试服务 4.创建ingress 5.测试https访问 二.安装nginx-ingres ...

  3. nginx使用ssl模块配置支持HTTPS访问,腾讯云申请免费证书

    开始我尝试用 let's encrypt 让http 变 https 官方:https://github.com/certbot/certbot 参考:https://www.cnblogs.com/ ...

  4. Centos7.2下Nginx配置SSL支持https访问(站点是基于.Net Core2.0开发的WebApi)

    准备工作 1.基于nginx部署好的站点(本文站点是基于.Net Core2.0开发的WebApi,有兴趣的同学可以跳http://www.cnblogs.com/GreedyL/p/7422796. ...

  5. Windows下Nginx配置SSL实现Https访问(包含证书生成)

    Vincent.李   Windows下Nginx配置SSL实现Https访问(包含证书生成) Windows下Nginx配置SSL实现Https访问(包含证书生成) 首先要说明为什么要实现https ...

  6. 配置nginx支持Https

    配置nginx支持Https一定要先使用stop停止nginx然后重新代开不能使用reload 一:安装letsencrypt 1.从git上克隆下来git clone https://github. ...

  7. Springboot 配置 ssl 实现HTTPS 请求 & Tomcat配置SSL支持https请求

    SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议.TLS与 ...

  8. 微信小程序如何提交审核并发布?发布问题:小程序只支持https访问

    http://www.jisuapp.cn/news/305.html 发布问题:1.小程序只支持https访问 2.要配置服务域名

  9. libcurl 不支持https访问

    项目中使用libcurl 访问https的时候会报错,比如:“Unsupported protocol” 或者:“Protocol https not supported or disabled in ...

  10. nginx使用ssl模块配置支持HTTPS访问

    默认情况下ssl模块并未被安装,如果要使用该模块则需要在编译nginx时指定–with-http_ssl_module参数. 需求: 做一个网站域名为 www.localhost.cn 要求通过htt ...

随机推荐

  1. Numpy线性计算

    Numpy内置方法以及numpy.linalg模块可实现矩阵乘法.矩阵分解.矩阵行列式等线性代数的计算. In [1]: import numpy as np In [2]: x = np.arang ...

  2. redis 简单整理——哨兵部署业务图[二十九]

    前言 简单介绍一下哨兵的部署业务图,非部署步骤. 正文 看一下部署的拓扑图: 然后这里用docker 来部署一下哨兵模式. 搭建一主二从. version: '3.7' services: maste ...

  3. http json请求工具类

    import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import java.util.Sca ...

  4. 【vue】纯前端图形验证码实现

    [vue]纯前端图形验证码实现 感觉人不能在SQL里面淹死,得看看别的东西了 因为是上班摸鱼偷摸搞的,所以人比较懒,很多东西也懒得修修改改,直接放在一个html文件下了 页面如下 js的生成图形逻辑是 ...

  5. 力扣1077(MySQL)-项目员工Ⅲ(中等)

    题目: 写 一个 SQL 查询语句,报告在每一个项目中经验最丰富的雇员是谁.如果出现经验年数相同的情况,请报告所有具有最大经验年数的员工. 查询结果格式在以下示例中: employee_id 为 1 ...

  6. 力扣784(java)-字母大小写全排列(中等)

    题目: 给定一个字符串 s ,通过将字符串 s 中的每个字母转变大小写,我们可以获得一个新的字符串. 返回 所有可能得到的字符串集合 .以 任意顺序 返回输出. 示例 1: 输入:s = " ...

  7. 基于 KubeVela 的机器学习实践

    ​简介:本文主要介绍如何使用 KubeVela 的 AI 插件,来帮助工程师更便捷地完成模型训练及模型服务. 作者:KubeVela 社区 在机器学习浪潮迸发的当下,AI 工程师除了需要训练.调试自己 ...

  8. 源码解读:KubeVela 是如何将 appfile 转换为 K8s 特定资源对象的

    简介: KubeVela 是一个简单易用又高度可扩展的云原生应用管理引擎,是基于 Kubernetes 及阿里云与微软云共同发布的云原生应用开发模型 OAM 构建.本文主要目的是探索 KubeVela ...

  9. 融合趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

    简介: 本文由 T3 出行大数据平台负责人杨华和资深大数据平台开发工程师王祥虎介绍 Flink.Kylin 和 Hudi 湖仓一体的大数据生态体系以及在 T3 的相关应用场景. 本文由 T3 出行大数 ...

  10. [FAQ] crontab 执行curl xxx 好像没有执行 ?

      如果你的crontab任务中的curl命令没有执行,可能有几个原因需要检查: 1. 检查命令路径:确保你在crontab任务中指定了正确的curl命令路径.你可以使用 which curl 命令来 ...