在阿里云托管kubernetes上利用 cert-manager 自动签发 TLS 证书[无坑版]
前言
排错的过程是痛苦的也是有趣的。
运维乃至IT,排错能力是拉开人与人之间的重要差距。
本篇会记录我的排错之旅。
由来
现如今我司所有业务都运行在阿里云托管kubernetes环境上,因为前端需要对外访问,所以需要对外域名,考虑申请https证书过于麻烦,所以希望借助免费的工具自动生成tls证书。
借鉴于网上或者阿里云的相关文档是存在大坑的,我认为有必要写一篇无坑版的利用cert-manager自动签发TLS证书。
思路
cert-manager是Kubernetes上一个管理SSL证书的插件,配合nginx-ingress可以对网站配置https访问,在加上letsencrypt提供免费的SSL证书,所有就产生了cert-manager+nginx-ingress+letsencrypt的免费套餐。详情请到GitHub查看:cert-manager
本文将介绍:基于阿里云托管kubernetes+cert-manager的 单域名,通配符域名证书申请。
部署
注:网上大多都使用helm 部署的,而helm部署确实非常简单,我认为最好最好不要使用他人的helm清单,不然出问题,就不晓得是怎么一个部署逻辑,还需要去分析资源清单。
前提
kubectl create namespace cert-manager #创建 cert-manager 命名空间
kubectl label namespace cert-manager certmanager.k8s.io/disable-validation=true #标记 cert-manager 命名空间以禁用资源验证
配置CRDs
wget https://github.com/jetstack/cert-manager/releases/download/v0.15.1/cert-manager-legacy.crds.yaml
kubectl apply --validate=false -f cert-manager-legacy.crds.yaml
配置cert-manager
# wget https://github.com/jetstack/cert-manager/releases/download/v0.15.1/cert-manager.yaml
# kubectl apply --validate=false -f cert-manager.yaml
这里会发现pod一直处于ContainerCreating 容器创建中
# kubectl get pods -n cert-manager
NAME READY STATUS RESTARTS AGE
cert-manager-75856bb467-fr5zz 0/1 ContainerCreating 0 16m
cert-manager-cainjector-597f5b4768-jqsvp 0/1 ContainerCreating 0 16m
cert-manager-webhook-5c9f7b5f75-gnphd 0/1 ContainerCreating 0 16m
#查看pod 详情,会发现是因为拉取镜像的问题,我的解决方案
#在香港机上拉取镜像打标签,推送到镜像仓库然后修改cert-manager.yaml的镜像地址
#查看原资源清单镜像
# cat cert-manager.yaml |grep image
image: "quay.io/jetstack/cert-manager-cainjector:v0.15.1"
image: "quay.io/jetstack/cert-manager-controller:v0.15.1"
image: "quay.io/jetstack/cert-manager-webhook:v0.15.1"
#香港机拉取--> 打标签 --> 推送
# docker pull quay.io/jetstack/cert-manager-cainjector:v0.15.1
# docker tag quay.io/jetstack/cert-manager-cainjector:v0.15.1 registry.cn-shenzhen.aliyuncs.com/realibox_test/cert-manager:cert-manager-cainjector-v0.15.1
# docker push registry.cn-shenzhen.aliyuncs.com/realibox_test/cert-manager:cert-manager-cainjector-v0.15.1
# docker pull quay.io/jetstack/cert-manager-controller:v0.15.1
# docker tag quay.io/jetstack/cert-manager-controller:v0.15.1 registry.cn-shenzhen.aliyuncs.com/realibox_test/cert-manager:cert-manager-controller-v0.15.1
# docker push registry.cn-shenzhen.aliyuncs.com/realibox_test/cert-manager:cert-manager-controller-v0.15.1
# docker pull quay.io/jetstack/cert-manager-webhook:v0.15.1
# docker tag quay.io/jetstack/cert-manager-webhook:v0.15.1 registry.cn-shenzhen.aliyuncs.com/realibox_test/cert-manager:cert-manager-webhook-v0.15.1
# docker push registry.cn-shenzhen.aliyuncs.com/realibox_test/cert-manager:cert-manager-webhook-v0.15.1
#现资源清单镜像 【临时镜像仓库地址为公开】
# cat cert-manager.yaml |grep image
#image: "quay.io/jetstack/cert-manager-cainjector:v0.15.1"
image: "registry.cn-shenzhen.aliyuncs.com/realibox_test/cert-manager:cert-manager-cainjector-v0.15.1"
#image: "quay.io/jetstack/cert-manager-controller:v0.15.1"
image: "registry.cn-shenzhen.aliyuncs.com/realibox_test/cert-manager:cert-manager-controller-v0.15.1"
#image: "quay.io/jetstack/cert-manager-webhook:v0.15.1"
image: "registry.cn-shenzhen.aliyuncs.com/realibox_test/cert-manager:cert-manager-webhook-v0.15.1"
# kubectl apply --validate=false -f cert-manager.yaml
# kubectl get pods -n cert-manager
NAME READY STATUS RESTARTS AGE
cert-manager-75856bb467-fr5zz 1/1 Running 0 1h
cert-manager-cainjector-597f5b4768-jqsvp 1/1 Running 0 1h
cert-manager-webhook-5c9f7b5f75-gnphd 1/1 Running 0 1h
验证cert-manager
# cat test-cert-manager.yaml
##########################################################################
#Author: zisefeizhu
#QQ: 2********0
#Date: 2020-08-11
#FileName: test-cert-manager.yaml
#URL: https://www.cnblogs.com/zisefeizhu/
#Description: The test script
#Copyright (C): 2020 All rights reserved
###########################################################################
apiVersion: v1
kind: Namespace
metadata:
name: cert-manager-test
---
apiVersion: cert-manager.io/v1alpha2
kind: Issuer
metadata:
name: test-selfsigned
namespace: cert-manager-test
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
name: selfsigned-cert
namespace: cert-manager-test
spec:
commonName: example.com
secretName: selfsigned-cert-tls
issuerRef:
name: test-selfsigned
# kubectl apply -f test-cert-manager.yaml
Normal GeneratedKey 20s cert-manager Generated a new private key
Normal Requested 20s cert-manager Created new CertificateRequest resource "selfsigned-cert-2334779822"
Normal Issued 20s cert-manager Certificate issued successfully
# kubectl delete -f test-cert-manager.yaml
通过dns配置域名证书
这里样式的是阿里云DNS操作的流程,如果需要其他平台的方法,可以自行开发,或者找已开源webhook,这是官方的例子:https://github.com/jetstack/cert-manager-webhook-example
这里用的是这个包:https://github.com/pragkent/alidns-webhook
配置alidns的webhook
# wget https://raw.githubusercontent.com/pragkent/alidns-webhook/master/deploy/bundle.yaml
# kubectl apply -f bundle.yaml
# kubectl get pods -n cert-manager #查看webhook
NAME READY STATUS RESTARTS AGE
cert-manager-webhook-alidns-6b87bc8597-tc9pk 1/1 Running 2 1h
配置Issuer
cert-manager
提供了Issuer
和 ClusterIssuer
两种类型的签发机构,Issuer
只能用来签发自己所在命名空间下的证书,ClusterIssuer
可以签发任意命名空间下的证书。
通过阿里云RAM创建一个账号,并授权AliyunDNSFullAccess,管理云解析(DNS)的权限
,将账号的AK记下来,并通过下面的命令创建secret,这个secret用于webhook在DNS认证的时候,会向DNS解析里面写入一条txt类型的记录,认证完成后删除。
创建 alidns AccessKey Id 和 Secret
# kubectl -n cert-manager create secret generic alidns-access-key-id --from-literal=accessKeyId='xxxxxxx'
# kubectl -n cert-manager create secret generic alidns-access-key-secret --from-literal=accessKeySecret='xxxxxxx'
我这里用 ClusterIssuer
为例,创建 letsencrypt-prod.yaml
文件
# cat letsencrypt-prod.yaml
##########################################################################
#Author: zisefeizhu
#QQ: 2********0
#Date: 2020-08-10
#FileName: letsencrypt-prod.yaml
#URL: https://www.cnblogs.com/zisefeizhu/
#Description: The test script
#Copyright (C): 2020 All rights reserved
###########################################################################
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
labels:
name: letsencrypt-prod
name: letsencrypt-prod # 自定义的签发机构名称,后面会引用
spec:
acme:
email: zisefeizhu@rexxxxx.com # 你的邮箱,证书快过期的时候会邮件提醒,不过我们可以设置自动续期
solvers:
- http01:
ingress:
class: nginx
privateKeySecretRef:
name: letsencrypt-prod # 指示此签发机构的私钥将要存储到哪个 Secret 对象中
server: https://acme-v02.api.letsencrypt.org/directory # acme 协议的服务端,我们用Let's Encrypt
让我们看看acme协议的服务端信息
{
"Dmrr3rQDHDQ": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417",
"keyChange": "https://acme-v02.api.letsencrypt.org/acme/key-change",
"meta": {
"caaIdentities": [
"letsencrypt.org"
],
"termsOfService": "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf",
"website": "https://letsencrypt.org"
},
"newAccount": "https://acme-v02.api.letsencrypt.org/acme/new-acct",
"newNonce": "https://acme-v02.api.letsencrypt.org/acme/new-nonce",
"newOrder": "https://acme-v02.api.letsencrypt.org/acme/new-order",
"revokeCert": "https://acme-v02.api.letsencrypt.org/acme/revoke-cert"
}
应用 yaml
# kubectl apply -f letsencrypt-prod.yaml
查看状态
# kubectl get ClusterIssuer
NAME READY AGE
letsencrypt-prod True 1h
至此,在kubernetes上利用 cert-manager 自动签发 TLS 证书 理论上部署完毕,下面进行验证!
验证
在这里我将提供两种验证方法:1. 手动签发证书 2. 自动签发证书
注意:这里存在一个大坑,请留意!
手动签发证书
# cat test-manual-cert.yaml
##########################################################################
#Author: zisefeizhu
#QQ: 2********0
#Date: 2020-08-11
#FileName: test-manual-cert.yaml
#URL: https://www.cnblogs.com/zisefeizhu/
#Description: The test script
#Copyright (C): 2020 All rights reserved
###########################################################################
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
name: test-monkeyrun-net-cert
spec:
secretName: tls-test-monkeyrun-net # 证书保存的 secret 名
duration: 2160h # 90d
renewBefore: 360h # 15d
organization:
- jetstack
isCA: false
keySize: 2048
keyAlgorithm: rsa
keyEncoding: pkcs1
dnsNames:
- test01.advance.realibox.com
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
group: cert-manager.io
# kubectl apply -f test-manual-cert.yaml
certificate.cert-manager.io/test-monkeyrun-net-cert created
大坑
预警:坑要来了!!!
# kubectl get certificate #检查是否生成证书文件
NAME READY SECRET AGE
test-monkeyrun-net-cert False tls-test-monkeyrun-net 27s
# # kubectl get certificate
NAME READY SECRET AGE
test-monkeyrun-net-cert False tls-test-monkeyrun-net 27s
# kubectl describe certificate test-monkeyrun-net-cert #查看详情
Status:
Conditions:
Last Transition Time: 2020-08-11T02:53:06Z
Message: Waiting for CertificateRequest "test-monkeyrun-net-cert-1270901994" to complete
Reason: InProgress
Status: False
Type: Ready
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Requested 40s cert-manager Created new CertificateRequest resource "test-monkeyrun-net-cert-1270901994"
这里证书生成是失败了的,原因:Waiting for CertificateRequest "test-monkeyrun-net-cert-1270901994" to complete
一直在请求,也就是说请求不到。这个问题从上周五就开始困扰着我。这也是个大坑,可看到的文档基本没有讲到
解决
查看有关证书生成的组件落到的节点:
# kubectl get pods -n cert-manager -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
cert-manager-75856bb467-fr5zz 1/1 Running 0 18h 192.168.0.98 cn-shenzhen.172.16.0.123 <none> <none>
cert-manager-cainjector-597f5b4768-jqsvp 1/1 Running 0 18h 192.168.0.101 cn-shenzhen.172.16.0.123 <none> <none>
cert-manager-webhook-5c9f7b5f75-gnphd 1/1 Running 0 18h 192.168.0.99 cn-shenzhen.172.16.0.123 <none> <none>
cert-manager-webhook-alidns-6b87bc8597-tc9pk 1/1 Running 2 17h 192.168.0.13 cn-shenzhen.172.16.0.122 <none> <none>
发现它们落在不同的节点上,灵光一闪,想起来了一件事:https://www.cnblogs.com/zisefeizhu/p/13262239.html 或许这个问题和自处一样呢?证书颁发者的pod与负载均衡器缠绕在不同的节点上,因此它无法通过入口与其自身进行通信。有可能哦
登陆阿里云看此kubernetes集群的外部流量引入策略
还真是的呢?根据之前对externaltrafficpolicy 的原理性了解,我有90%的把握是此处的问题,改为cluster
注:为什么我要在这里 我要登陆aliyun 点击更改而不是用命令 导出资源清单更改呢?这是因为阿里云的托管k8s有坑,这里如果用命令来改会导致nginx-ingress的lb的IP 也就是对外的公网IP发生变化,这样你的域名就全失效了因为IP变了.... 这个需要固定IP
再次测试
# kubectl delete -f test-manual-cert.yaml
certificate.cert-manager.io "test-monkeyrun-net-cert" deleted
# kubectl apply -f test-manual-cert.yaml
certificate.cert-manager.io/test-monkeyrun-net-cert created
# kubectl get certificate
NAME READY SECRET AGE
test-monkeyrun-net-cert True tls-test-monkeyrun-net 4s
! 此问题解决,手动签发证书成功,下面进行自动签发证书!
自动签发证书
资源清单
# cat test-nginx.yaml
##########################################################################
#Author: zisefeizhu
#QQ: 2********0
#Date: 2020-08-10
#FileName: test-nginx.yaml
#URL: https://www.cnblogs.com/zisefeizhu/
#Description: The test script
#Copyright (C): 2020 All rights reserved
###########################################################################
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-nginx
spec:
replicas: 1
selector:
matchLabels:
run: test-nginx
template:
metadata:
labels:
run: test-nginx
spec:
containers:
- name: test-nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: test-nginx
labels:
app: test-nginx
spec:
ports:
- port: 80
protocol: TCP
name: http
selector:
run: test-nginx
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-nginx
annotations:
kubernetes.io/ingress.class: "nginx"
kubernetes.io/tls-acme: "true"
certmanager.k8s.io/cluster-issuer: "letsencrypt-prod"
spec:
rules:
- host: test.advance.realibox.com
http:
paths:
- backend:
serviceName: test-nginx
servicePort: 80
path: /
tls:
- secretName: tls-test-monkeyrun-net
hosts:
- test.advance.realibox.com
测试
# kubectl apply -f test-nginx.yaml
deployment.apps/test-nginx created
service/test-nginx created
ingress.extensions/test-nginx created
# kubectl get pods,ingress -n test
NAME READY STATUS RESTARTS AGE
pod/test-nginx-6dcd7c6dc5-fd5xx 1/1 Running 0 31s
NAME HOSTS ADDRESS PORTS AGE
ingress.extensions/test-nginx test.advance.realibox.com xxxxxxx 80, 443 31s
# kubectl get secrets -n test
NAME TYPE DATA AGE
acr-credential-560b66540f01e51c18524b09ad7f575f kubernetes.io/dockerconfigjson 1 87m
acr-credential-5dee66918cdf5d93de4aa5cd90247f73 kubernetes.io/dockerconfigjson 1 87m
acr-credential-6731ef77d88edc24b279ebf20860f30f kubernetes.io/dockerconfigjson 1 87m
acr-credential-bab42ef118a2913b05cd8cdb95441d70 kubernetes.io/dockerconfigjson 1 87m
acr-credential-be55512166dd26eda658d0706de5a06a kubernetes.io/dockerconfigjson 1 87m
default-token-22cwv kubernetes.io/service-account-token 3 87m
tls-test-monkeyrun-net kubernetes.io/tls 3 10m
登陆aliyun 查看证书信息
浏览器访问
!
在阿里云托管kubernetes上利用 cert-manager 自动签发 TLS 证书[无坑版]的更多相关文章
- 基于阿里云托管kubernetes的版本升级
前言 因为阿里云的knative对应得k8s版本大于1.15,而我们目前得集群环境是1.14.8,因此需要对预发环境进行版本升级.基于aliyun托管的kubernetes集群版本升级本没有什么可写, ...
- 在阿里云Centos7.6上利用docker搭建Jenkins来自动化部署Django项目
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_84 一般情况下,将一个项目部署到生产环境的流程如下: 需求分析-原型设计-开发代码-内网部署-提交测试-确认上线-备份数据-外网更 ...
- 构建基于阿里云OSS文件上传服务
转载请注明来源:http://blog.csdn.net/loongshawn/article/details/50710132 <构建基于阿里云OSS文件上传服务> <构建基于OS ...
- 在阿里云容器服务上开发基于Docker的Spring Cloud微服务应用
本文为阿里云容器服务Spring Cloud应用开发系列文章的第一篇. 一.在阿里云容器服务上开发Spring Cloud微服务应用(本文) 二.部署Spring Cloud应用示例 三.服务发现 四 ...
- 一个空行引起的阿里云负载均衡上部署https证书的问题
今天在阿里云上购买了WoSign的https证书,在证书签发后,在控制台下载证书文件,一共有2个文件,一个是.key文件(私钥文件),一个是.pem文件(证书文件). 然后在阿里云负载均衡“证书管理” ...
- Thinkphp整合阿里云OSS图片上传实例
Thinkphp3.2整合阿里云OSS图片上传实例,图片上传至OSS可减少服务器压力,节省宽带,安全又稳定,阿里云OSS对于做负载均衡非常方便,不用传到各个服务器了 首先引入阿里云OSS类库 < ...
- 阿里云服务器ECS上ubuntu安装nginx后默认站点页面打开错误,显示无法访问此网站
问题:在新买的阿里云服务器ECS上安装nginx后打开默认页面失败,如下图所示. 系统环境:Ubuntu 16.04.4 LTS64版本. 步骤回顾: root用户下运行命令 apt-get inst ...
- PHP实现阿里云OSS文件上传(支持批量)
上传文件至阿里云OSS,整体逻辑是,文件先临时上传到本地,然后在上传到OSS,最后删除本地的临时文件(也可以不删,具体看自己的业务需求),具体实现流程如下: 1.下载阿里云OSS对象上传SDK(P ...
- Knative 应用在阿里云容器服务上的最佳实践
作者|元毅 阿里云智能事业群高级开发工程师 相信通过前面几个章节的内容,大家对 Knative 有了初步的体感,那么在云原生时代如何在云上玩转 Knative?本篇内容就给你带来了 Knative 应 ...
随机推荐
- IOS上传图片方向问题
在显示上传完毕的图片的时候遇到了一个问题, 图片莫名其妙被逆时针旋转了90度就很离谱 如下图 经过一番查询, 原来是 IOS 的相机拍照的时候会把方向角写入到图片里面 因为我用的是 element 的 ...
- 2020年20个Flutter最漂亮的UI库和项目
Best-Flutter-UI-Templates 地址:https://github.com/mitesh77/Best-Flutter-UI-Templates The History of Ev ...
- JAVA 实现将多目录多层级文件打成ZIP包后保留层级目录下载 ZIP压缩 下载
将文件夹保留目录打包为 ZIP 压缩包并下载 上周做了一个需求,要求将数据库保存的 html 界面取出后将服务器下的css和js文件一起打包压缩为ZIP文件,返回给前台:在数据库中保存的是html标签 ...
- 理解Linux的硬链接与软链接-转载
理解Linux的硬链接与软链接 来自:https://www.ibm.com/developerworks/cn/linux/l-cn-hardandsymb-links/index.html
- mysql 联合唯一
CREATE TABLE `NewTable` ( `id` int NOT NULL , `name` varchar(255) NULL , `phone` varchar(255) NULL , ...
- js获得url传过来的参数
function getParam(url) { var arr = url.split('?'); //取?以后 var a ...
- SpringSecurity+Oauth2+Jwt实现toekn认证和刷新token
简单描述:最近在处理鉴权这一块的东西,需求就是用户登录需要获取token,然后携带token访问接口,token认证成功接口才能返回正确的数据,如果访问接口时候token过期,就采用刷新token刷新 ...
- 一个完全关于android编程的技术博客网站
https://www.oschina.net/android/96/file-process
- Aliyun Linux2安装Docker
安装教程 使用手册
- 配置mongoDB的错误
1,将启动配置到服务的时候没有反应,后来发现没有用管理员模式打开shell命令,所以没有反应. 2,用管理员模式的时候报错 格式问题,将由空格的路径用“”包住即可 3.启动的时候报错windows不能 ...