使用helm管理Ingress的TLS Secret证书
2018-09-12
为什么要管理TLS Secret证书 #
使用ingress将服务以https暴露到集群外边时,需要ssl证书。在https://github.com/kubernetes/contrib/tree/master/ingress/controllers/nginx/examples/tls
这个例子中, ingress的定义如下:
1apiVersion: extensions/v1beta1
2kind: Ingress
3metadata:
4 name: foo
5 namespace: default
6spec:
7 tls:
8 - hosts:
9 - foo.bar.com
10 secretName: foo-secret
11 rules:
12 - host: foo.bar.com
13 http:
14 paths:
15 - backend:
16 serviceName: echoheaders-x
17 servicePort: 80
18 path: /
对于域名foo.bar.com
的证书引用的是相同namespace下的secret foo-secret
。
这说明在Kubernetes中管理站点的TLS证书,使用的是Secret。
假设在已经取得foo.bar.com
的证书和私钥分别为foo.bar.com.crt
和foo.bar.com.key
,使用下面的命令就可以在default命名空间中创建TLS类型的Secret:
1kubectl create secret tls foo-secret --cert=foo.bar.com.crt --key=foo.bar.com.key -n default
实际情况中,我们的证书往往都是泛域名的证书,例如对于frognew.com
,是支持*.frognew.com
所有的二级域名的。
不同的服务的Ingress被创建在不同的namespace中,每个namespace中都需要创建TLS Secret。
因此需要一种更加整合和高效的方式管理TLS Secret。
先来看一下微服务在开发和部署上要考虑的两个问题:
- 微服务在开发上需要考虑如何“拆”的问题(拆分的时机、拆分的粒度、拆分的方式)
- 微服务在部署时需要考虑整合与集成的问题,即如何“合”
使用helm管理Ingress的TLS Secret证书 #
一个产品由多个微服务组成,这个产品部署到Kubernetes上,每个服务都可能需要在Kubernetes上创建下面几种资源:Ingress, Service, Deployment, ConfigMap, Secret,Job,CronJob等等。我们已经使用Helm,将产品的各个微服务在部署上当成一个逻辑整体,即为每个产品创建一个helm chart,这个helmchart包含了产品所有微服务的部署,将前面每个服务所需要的资源模板化。本篇要解决的是如何整合和高效的管理Ingress的TLS Secret,即将TLS Secret的创建也集成到产品的这个helm chart中。
helm的模板功能十分强大,这里演示一下如何使用heml chart在Kubernetes管理TLS证书,先简单实现一下:
chart的模板文件tls-secrets.yaml:
1{% raw %}
2{{- range $tlsSecretName, $tlsSecret := .Values.tlsSecrets }}
3apiVersion: v1
4kind: Secret
5type: kubernetes.io/tls
6metadata:
7 name: {{ $tlsSecretName }}
8 labels:
9 chart: {{ $.Chart.Name }}-{{ $.Chart.Version | replace "+" "_" }}
10 release: {{ $.Release.Name }}
11 heritage: {{ $.Release.Service }}
12data:
13 tls.crt: {{ $tlsSecret.certificate | b64enc }}
14 tls.key: {{ $tlsSecret.key | b64enc }}
15{{- end }}
16{% endraw %}
values.yaml:
1tlsSecrets:
2 foo-secret:
3 certificate: |-
4 -----BEGIN CERTIFICATE-----
5 .....
6 -----END CERTIFICATE-----
7 -----BEGIN CERTIFICATE-----
8 .....
9 -----END CERTIFICATE-----
10 key: |-
11 -----BEGIN PRIVATE KEY-----
12 ......
13 -----END PRIVATE KEY-----
values.yaml中提供每个TLS Secret的证书和私钥的文本内容,在tls-secrets.yaml中使用模板的b64enc函数,将证书内容编码成Secret所需的Base64。 这样TLS Secret也使用helm管理起来了。
我们的实践 #
我们实际实践中使用的是另一种方式,利用了helm的文件访问功能Accessing Files Inside Templates。
将证书文件直接放到Chart目录的files子目录下:
1.
2├── charts
3├── Chart.yaml
4├── files
5│ └── frognew.com
6│ ├── cert.pem
7│ ├── chain.pem
8│ ├── fullchain.pem
9│ ├── privkey.pem
10│ └── README
11├── templates
12 ├── ......
13│ └── tls-secrets.yaml
14├── values.yaml
chart的模板文件tls-secrets.yaml:
1{% raw %}
2{{- range $tlsSecretName, $tlsSecret := .Values.tlsSecrets }}
3apiVersion: v1
4kind: Secret
5type: kubernetes.io/tls
6metadata:
7 name: {{ $tlsSecretName }}
8 labels:
9 chart: {{ $.Chart.Name }}-{{ $.Chart.Version | replace "+" "_" }}
10 release: {{ $.Release.Name }}
11 heritage: {{ $.Release.Service }}
12data:
13 tls.crt: {{ $.Files.Get $tlsSecret.certificate | b64enc }}
14 tls.key: {{ $.Files.Get $tlsSecret.key | b64enc }}
15{{- end }}
16{% endraw %}
values.yaml:
1tlsSecrets:
2 frognew-tls-secret:
3 certificate: "files/frognew.com/fullchain.pem"
4 key: "files/frognew.com/privkey.pem"
使用Files.Get去读取证书文件内容,通过b64enc编码为Base64。
- 这种将证书文件放到Chart中的使用方式需要注意受限于Kubernetes限制,Chart的大小不能超过1MB。
- 关于在Helm模板中访问文件的能力还有很多高级用法,具体可以查看Accessing Files Inside Templates
总结 #
本文介绍了如何使用Helm在Kubernetes中整合管理Ingress的TLS Secret证书,其实对于其它类型的Secret也是通用的。例如对于Opaque Secret
、kubernetes.io/dockercfg Secret
都可以纳入到helm chart管理中。这样部署一个应用所需要的所有资源就全部纳入Helm Chart管理了。