cert-manager是应用于 kubernetes 集群内,用于管理 ssl 证书的组件,包括自签证书和CA机构颁发和续签证书,使用者创建后无需关注证书后续到期时间。初次接触的用户,不要理解为 k8s 的内部 apiserver 证书,这个证书是传递给 ingress、istio等网关给 k8s 内部服务使用 https 暴露应用使用的。
安装
https://cert-manager.io/docs/installation/
使用
目前我司仅用到了自签证书给 istio-ingressgateway 和 jks证书(java开发自用)
创建 Issuer(发行者)
- Issuer:只作用在所创建的 namespace 中作为发行者
- ClusterIssuer:作用在所有 namespace,可作为所有 namespace 的发行者
我这里只在 istio-system 的命名空间内部使用
kind: Issuer
apiVersion: cert-manager.io/v1
metadata:
name: selfsigned-issuer
namespace: istio-system
spec:
selfSigned: {}
创建 Certificate 证书
由Certificate资源来生成指定的 secret,其中默认包括 tls.crt、tls.key
kind: Certificate
apiVersion: cert-manager.io/v1
metadata:
name: selfsigned-certificate
namespace: istio-system
spec:
dnsNames:
- feiyiblog.com # 为指定的域名生成证书,此处可以是多域名
issuerRef:
name: selfsigned-issuer # 指定发行者
secretName: selfsigned-certificate-tls # 生成的tls证书secret name
commonName: feiyiblog.com # 表示证书保护的域名或者服务器,多域名时自定义就好了,或者直接不定义该字段即可
organization: company # 该域名属于的组织,一般写公司名字
country: CN # 所属国家,CN
查看签发情况,REDAY 字段为 TRUE 即可
$ kubectl get certificate -n istio-system
NAME READY SECRET AGE
selfsigned-certificate True selfsigned-certificate-tls 22h
查看 secret
$ kubectl get secret -n istio-system
NAME TYPE DATA AGE
selfsigned-certificate-tls kubernetes.io/tls 3 22h
查看证书内容
kubectl get secret -n istio-system selfsigned-certificate-tls -o jsonpath="{.data['tls\.key']}" | base64 -d > tls.key
kubectl get secret -n istio-system selfsigned-certificate-tls -o jsonpath="{.data['tls\.crt']}" | base64 -d > tls.crt
istio-ingressgateway
我的集群中通过 istio-ingressgateway 暴露服务,将上面最终创建的 secret 应用到 gateway 中,gateway 可以在任何命名空间中,一般和应用在同一个命名空间
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: backend-gateway
namespace: infra
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- 'feiyiblog.com' # 与证书中的域名一致
port: # port中的内容是istio-ingressgatewa的service资源的默认端口
number: 443
protocol: HTTPS
name: https
tls:
mode: SIMPLE
credentialName: selfsigned-certificate-tls # 这里指定证书存在的secret
创建VirtualService,在vs中指定gateway和后端应用
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: playground-backend-vs
namespace: infra
spec:
gateways:
# 指定上放创建的gateway,如果gateway和VirtualService不在同一命名空间,要指定namespace/backend-gateway
- backend-gateway
hosts:
- "*"
http:
- route:
- destination:
host: backend-service.infra.svc.cluster.local # 指定后端服务对应的service的内部dns
port:
number: 8000
jks
jks 是tomcat中使用的证书,我司开发也不道咋回事,登录接口写不明白,我nginx代理完,他登录接口自动强制http,反正就这样吧,世界就是个巨大的草台班子!
创建secret
这里创建的secret是用来存储 jks 的 password 的,从CA机构签发的没有 password 这个说法,自签的貌似都有
kind: Secret
apiVersion: v1
metadata:
name: tomcat-jks-pass
namespace: istio-system
data:
password: test123
type: Opaque
创建 Certificate 证书
和上面使用同一个发行者即可
kind: Certificate
apiVersion: cert-manager.io/v1
metadata:
name: jks-certificate
namespace: istio-system
spec:
dnsNames:
- jks.feiyiblog.com # 访问后端的域名
issuerRef:
name: selfsigned-issuer # 指定发行者
secretName: jks-certificate-tls # 最终生成的secret name
commonName: feiyiblog.com # 表示证书保护的域名或者服务器,多域名时自定义就好了,或者直接不定义该字段即可
organization: company # 该域名属于的组织,一般写公司名字
country: CN # 所属国家,CN、
keystores:
jks:
create: true
passwordSecretRef:
key: password # secret中的key
name: tomcat-jks-pass # 存储password的secret name
privateKey:
algorithm: ECDSA
size: 256
验证证书内容
# 导出证书
kubectl get secret -n istio-system jks-certificate-tls -o jsonpath="{.data['keystore\.jks']}" |base64 -d > keystore.jks
# 验证证书内容,注意结尾的密码
keytool -list -v -keystore keystore.jks -storepass test123
istio-ingressgateway
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: backend-gateway
namespace: infra
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- 'jks.feiyiblog.com '
port:
number: 443
protocol: HTTPS
name: https
tls:
mode: PASSTHROUGH # https流量透传给后端处理
virtualservice和上面一样即可
挂载使用
需要后端服务识别挂载路劲的 jks 证书,然后将secret挂载进去就可以了。
需要注意的是,我的例子中使用的是 Issuer,且在 istio-system 命名空间中,不能跨命名空间签发证书,生成的证书也在 istio-system 中。
最后jks这个示例,应该在应用所在的命名空间创建 Issuer 和 Certificate,包括含有密码的 secret,或者创建 ClusterIssuer,然后在应用所在的命名空间创建 Certificate,供应用挂载到 pod 内部使用。