Kubernetes 监控:CertManager 自动 HTTPS
cert-manager 是一种自动执行证书管理的工具,它可以与 Istio Gateway 集成以管理 TLS 证书,当然也可以很方便地和前面我们配置的 ingress-nginx 或者 traefik 配合使用。对于和 Istio 的集成使用,无需特殊配置即可。
在进行本节实验之前记得将前面章节的实验内容进行清空。
安装
要在 Kubernetes 集群上安装 cert-manager 也非常简单,官方提供了一个单一的资源清单文件,包含了所有的资源对象,所以直接安装即可:
# Kubernetes 1.15+
$ kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.16.1/cert-manager.yaml
# Kubernetes <1.15
$ kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.16.1/cert-manager-legacy.yaml
上面的命令会创建一个名为 cert-manager 的命名空间,安装大量的 CRD 以及 AdmissionWebhook 对象,可以通过如下命令来查看是否安装成功:
$ kubectl get pods --namespace cert-manager
NAME READY STATUS RESTARTS AGE
cert-manager-7ddc5b4db-56nln 1/1 Running 0 4m46s
cert-manager-cainjector-6644dc4975-zthcj 1/1 Running 0 4m47s
cert-manager-webhook-7b887475fb-9fbp4 1/1 Running 0 4m45s
正常情况下可以看到 cert-manager、cert-manager-cainjector 以及 cert-manager-webhook 这几个 Pod 处于 Running 状态。我们可以通过下面的测试来验证下是否可以签发基本的证书类型,创建一个 Issuer 资源对象来测试 webhook 工作是否正常(在开始签发证书之前,必须在群集中至少配置一个 Issuer 或 ClusterIssuer 资源):
$ cat <<EOF > test-resources.yaml
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:
dnsNames:
- example.com
secretName: selfsigned-cert-tls
issuerRef:
name: test-selfsigned
EOF
这里我们创建了一个名为 cert-manager-test 的命名空间,创建了一个 Issuer 的证书颁发机构,然后使用这个 Issuer 来创建一个证书 Certificate 对象,直接创建上面的资源清单即可:
$ kubectl apply -f test-resources.yaml
namespace/cert-manager-test created
issuer.cert-manager.io/test-selfsigned created
certificate.cert-manager.io/selfsigned-cert created
创建完成后可以检查新创建的证书状态,在 cert-manager 处理证书请求之前,可能需要稍微等几秒:
$ kubectl describe certificate -n cert-manager-test
Name: selfsigned-cert
Namespace: cert-manager-test
......
Spec:
Dns Names:
example.com
Issuer Ref:
Name: test-selfsigned
Secret Name: selfsigned-cert-tls
Status:
Conditions:
Last Transition Time: 2020-08-16T01:50:40Z
Message: Certificate is up to date and has not expired
Reason: Ready
Status: True
Type: Ready
Not After: 2020-11-14T01:50:39Z
Not Before: 2020-08-16T01:50:39Z
Renewal Time: 2020-10-15T01:50:39Z
Revision: 1
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Issuing 64s cert-manager Issuing certificate as Secret does not exist
Normal Generated 64s cert-manager Stored new private key in temporary Secret resource "selfsigned-cert-25ftw"
Normal Requested 64s cert-manager Created new CertificateRequest resource "selfsigned-cert-p2sbx"
Normal Issuing 63s cert-manager The certificate has been successfully issued
从上面的 Events 事件中我们可以证书已经成功签发了,到这里证明我们的 cert-manager 已经安装成功了。而且我们需要注意的是 cert-manager 的功能非常强大,不只是可以支持 ACME 类型的证书签发,还支持其他众多的类型,比如 SelfSigned(自签名)、CA、Vault、Venafi、External、ACME,只是我们一般主要是使用 ACME 来帮我们生成自动化的证书。
环境配置
由于通过 ACME 做自动化证书的时候,需要暴露 80 和 443 端口,当然如果我们使用 DNS 校验方式也可以,但是有时候我们根本就没有域名的情况下想要实现自动化证书,我们可以使用 xip.io 这类的服务来实现。前面我们部署 istio-ingressgateway 的时候是通过 NodePort 类暴露的服务,所以我们需要在前面加一个 LB 来转发下请求。这里为了简单,我直接使用 haproxy 来监听节点的 80 和 443 端口,将请求转发到后端的 NodePort 端口。
首先安装 haproxy:
$ yum install -y haproxy
然后配置 haproxy,配置文件 /etc/haproxy/haproxy.cfg,内容如下所示:
listen stats
bind *:9000
mode http
stats enable
stats hide-version
stats uri /stats
stats refresh 30s
stats realm Haproxy\ Statistics
stats auth Admin:Password
frontend istio-https
bind *:443
mode tcp
option tcplog
tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }
default_backend istio-https-svc
backend istio-https-svc
mode tcp
option tcplog
option tcp-check
balance roundrobin
default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100
server istio-http-svc-1 127.0.0.1:30951 check
frontend istio-http
bind *:80
mode tcp
option tcplog
default_backend istio-http-svc
backend istio-http-svc
mode tcp
option tcplog
option tcp-check
balance roundrobin
default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100
server istio-http-svc-1 127.0.0.1:32193 check
其中的 32193 与 30951 端口是 istio-ingressgateway 的 NodePort 端口:
$ kubectl get svc istio-ingressgateway -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway NodePort 10.102.120.128 <none> 15020:31093/TCP,80:32193/TCP,443:30951/TCP,31400:31871/TCP,15443:31367/TCP 68d
配置完成后直接启动 haproxy 即可:
$ sudo systemctl start haproxy
$ sudo systemctl enable haproxy
$ sudo systemctl status haproxy
然后我们可以通过上面 9000 端口监控我们的 haproxy 的运行状态:

与 Istio 集成
这里我们来通过 cert-manager 为前面的 httpbin 应用配置自动的 HTTPS,首先单独创建一个用户 cert-manager 的自定义的 Gateay,如下所示:
$ cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: acme-gateway
labels:
app: ingressgateway
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- "*.xip.io"
port:
number: 80
name: http
protocol: HTTP
# tls:
# httpsRedirect: true
- hosts:
- "*.xip.io"
port:
name: https
number: 443
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: "xip-cert"
---
EOF
gateway.networking.istio.io/acme-gateway created
需要注意的是在配置 Gateway 的时候 tls 的 credentialName 代表的是 cert-manager 自动生成的证书名称。
接下来创建 VirtulService 对象,这里我们使用 https 方式的 ACME 证书校验方式,除了 http 方式之外还有 tls 与 dns 方式的校验,dns 方式的证书校验支持通配符的域名。所以我们需要为 /.well-known/ 这个 PATH 路径做一个正确的配置,方便进行 http 校验:
$ cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
gateways:
- acme-gateway
hosts:
- httpbin.123.59.188.12.xip.io
http:
- route:
- destination:
host: httpbin
port:
number: 8000
EOF
virtualservice.networking.istio.io/httpbin created
部署完成后我们可以通过访问 http://httpbin.123.59.188.12.xip.io 来验证是否已经部署成功:

接下来创两个 ClusterIssuer,一个用于测试,一个用于正式使用:
$ cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: icnych@xxx.com
privateKeySecretRef:
name: letsencrypt-staging
solvers:
- http01:
ingress:
class: istio
EOF
clusterissuer.cert-manager.io/letsencrypt-staging created
$ cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1beta1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: icnych@xxx.com
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: istio
EOF
clusterissuer.cert-manager.io/letsencrypt-prod created
$ kubectl describe clusterissuer
......
Status:
Acme:
Last Registered Email: icnych@xxx.com
Uri: https://acme-v02.api.letsencrypt.org/acme/acct/94057742
Conditions:
Last Transition Time: 2020-08-16T07:37:40Z
Message: The ACME account was registered with the ACME server
Reason: ACMEAccountRegistered
Status: True
Type: Ready
Events: <none>
然后创建一个 Certificate 对象来获取证书,由于 Istio 需要在它的命名空间下面有证书,所以我们需要在 istio-system 这个命名空间下面创建:
$ cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1beta1
kind: Certificate
metadata:
name: httpbin-cert
namespace: istio-system # 这里必须是 istio-system 空间
spec:
secretName: xip-cert # 这个就是上面 gateway 所配置的证书名称
issuerRef:
kind: ClusterIssuer
name: letsencrypt-staging
commonName: httpbin.123.59.188.12.xip.io
dnsNames:
- httpbin.123.59.188.12.xip.io
EOF
certificate.cert-manager.io/httpbin-cert created
创建完成后这时候查看 istio-system 空间应该会有一个 cm-acme-http-solver- 这个开头的 Pod、Servie、Ingress 资源对象:
$ kubectl get pods -n istio-system
NAME READY STATUS RESTARTS AGE
cm-acme-http-solver-8tpbn 1/1 Running 0 16s
$ kubectl get svc -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cm-acme-http-solver-w6sf7 NodePort 10.106.174.20 <none> 8089:32135/TCP
$ kubectl get ingress -n istio-system
NAME HOSTS ADDRESS PORTS AGE
cm-acme-http-solver-jkrs2 httpbin.123.59.188.12.xip.io 80 45s
隔一小会儿去查看上面部署的 Certificate 对象的状态:
$ kubectl describe certificate httpbin-cert -n istio-system
......
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Issuing 13m cert-manager Issuing certificate as Secret does not exist
Normal Generated 13m cert-manager Stored new private key in temporary Secret resource "http-cert-6cml8"
Normal Requested 13m cert-manager Created new CertificateRequest resource "http-cert-9wcg2"
Normal Issuing 6m17s cert-manager The certificate has been successfully issued
看到最后的信息 The certificate has been successfully issued 证明我们的证书获取成功了,但是这个时候如果我们通过 https 去访问的话还是会提示证书错误的,因为我们获取的是 staging 环境的证书:

这个时候我们重新更新 httpbin-cert 这个 Certificate 对象中引用的 issuer,更改为正式环境的 issuer,或者使用正式的签名机构新建一个证书对象,正常就可以获得线上环境的证书了。
Kubernetes 监控:CertManager 自动 HTTPS的更多相关文章
- 在阿里云托管kubernetes上利用 cert-manager 自动签发 TLS 证书[无坑版]
前言 排错的过程是痛苦的也是有趣的. 运维乃至IT,排错能力是拉开人与人之间的重要差距. 本篇会记录我的排错之旅. 由来 现如今我司所有业务都运行在阿里云托管kubernetes环境上,因为前端需要对 ...
- 【译】Kubernetes监控实践(2):可行监控方案之Prometheus和Sensu
本文介绍两个可行的K8s监控方案:Prometheus和Sensu.两个方案都能全面提供系统级的监控数据,帮助开发人员跟踪K8s关键组件的性能.定位故障.接收预警. 拓展阅读:Kubernetes监控 ...
- Kubernetes 监控--Prometheus 高可用: Thanos
前面我们已经学习了 Prometheus 的使用,了解了基本的 PromQL 语句以及结合 Grafana 来进行监控图表展示,通过 AlertManager 来进行报警,这些工具结合起来已经可以帮助 ...
- 探索Windows Azure 监控和自动伸缩系列1 - 连接中国区Azure
最近准备基于Microsoft Azure Management Libraries 实现虚拟机的监控.主要的需求就是获取虚拟机内置的性能计数器数据,基于性能计数器实现后续的监控和自动伸缩. 作为这一 ...
- [博客迁移]探索Windows Azure 监控和自动伸缩系列1 - 连接中国区Azure
最近准备基于Microsoft Azure Management Libraries 实现虚拟机的监控.主要的需求就是获取虚拟机内置的性能计数器数据,基于性能计数器实现后续的监控和自动伸缩. 作为这一 ...
- Kubernetes监控:部署Heapster、InfluxDB和Grafana
本节内容: Kubernetes 监控方案 Heapster.InfluxDB和Grafana介绍 安装配置Heapster.InfluxDB和Grafana 访问 grafana 访问 influx ...
- tomcat监控,自动重启shell脚本
tomcat监控,自动重启shell脚本如下,取名 monitor_tomcat.sh: #!/bin/sh # func:自动监控tomcat脚本并且执行重启操作 # 获取tomcat进程ID(其中 ...
- Kubernetes 监控方案之 Prometheus Operator(十九)
目录 一.Prometheus 介绍 1.1.Prometheus 架构 1.2.Prometheus Operator 架构 二.Helm 安装部署 2.1.Helm 客户端安装 2.2.Tille ...
- kubernetes监控和性能分析工具:heapster+influxdb+grafana
1.部署heapster 下载 heapster 相关 yaml 文件 [root@master dashboard]# wget https://raw.githubusercontent.com/ ...
随机推荐
- 创建多线程程序的第一种方式_创建Thread类的子类
创建多线程程序的第一种方式:创建Thread类的子类java.lang.Thread类:是描述线程的类,我们想要实现多线程程序,就必须继承Thread类 实现步骤: 1.创建一个Thread类的子类 ...
- 项目git commit时卡主不良代码:husky让Git检查代码规范化工作
看完 <前端规范之Git工作流规范(Husky + Commitlint + Lint-staged) https://www.cnblogs.com/Yellow-ice/p/15349873 ...
- C++指针和结构体基础知识
学习C++首先要回忆起C语言当中的指针和结构体知识,本文作者将通过一段代码来总结指针和结构体基础知识:指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址.就像其他变量或常量一样,您必须在使 ...
- Solution -「树状数组」 题目集合
T1 冒泡排序 题目描述 clj 想起当年自己刚学冒泡排序时的经历,不禁思绪万千 当年,clj 的冒泡排序(伪)代码是这样的: flag=false while (not flag): flag=tr ...
- 彻底理解DDS(信号发生器)的fpga实现(verilog设计代码)
DDS(Direct Digital Synthesis)是一种把一系列数字信号通过D/A转换器转换成模拟信号的数字合成技术. 它有查表法和计算法两种基本合成方法.在这里主要记录DDS查表法的fpga ...
- 第九天python3 闭包、nonlocal、默认值的作用域
闭包 自由变量:未在本地作用域中定义的变量,例如定义在内存函数外的外层函数的作用域中的变量: 闭包:出现在嵌套函数中,指的是内层函数引用到了外层函数的自由变量,就形成了闭包: 示例1: # -*- c ...
- openstack 虚拟机网卡被重名为cirename0
虚拟机网卡被重名为cirename0 在虚拟机挂载多网卡情况下,你在虚拟机上卸载网卡后,再创建新的port挂给虚拟机使用,如果虚拟机不经过重启的话,是不会有任何问题的.但是,如果虚拟机重启了,你 ...
- 常用的函数式接口Consumer接口练习字符串拼接输出
题目 下面的字符串数组当中有多条信息,请按照格式"姓名: XX 性别: XX"的格式将信息打印出来,要求将 打印姓名的动作为第一个Consumer接口的Lambda实例,将打印性别 ...
- Object类中wait代餐方法和notifyAll方法和线程间通信
Object类中wait代餐方法和notifyAll方法 package com.yang.Test.ThreadStudy; import lombok.SneakyThrows; /** * 进入 ...
- Git 07 IDEA集成Git
参考源 https://www.bilibili.com/video/BV1FE411P7B3?spm_id_from=333.999.0.0 版本 本文章基于 Git 2.35.1.2 IDEA 是 ...