文章482
标签257
分类63

配置Ingress处理TLS传输

在上一篇文章《国内在minikube中添加ingress-nginx插件》中,讲述了如何在国内网络环境安装Ingress-Nginx,并且对NodePort、LoadBalancer和Ingress分别进行了测试;

但是在实际项目中,我们只会用到HTTPS的连接,因此还需要为Ingress配置TLS证书;

本文讲述了如何在Ingress中配置TLS证书;

源代码:

系列文章:


配置Ingress处理TLS传输

2021年的今天,如果网站不用HTTPS,基本上整个网站都要被Ban了;

所以TLS是非常重要的;

对于K8S而言:

当客户端创建到Ingress的控制器的TLS连接时,控制器将终止TLS连接!

客户端和Ingress控制器之间的通信是加密的,而控制器和后端的Pod通信是非加密的(也无需加密)

因此,运行在Pod中的应用程序不需要支持TLS,只需接收正常的HTTP通信,并让Ingress处理和TLS相关的所有内容即可!

要在Ingress控制器中配置TLS相关内容,需要将证书和私钥附加至Ingress中;

下面我们开始为Ingress配置TLS;


创建证书并配置Secrets

创建TLS证书:

chapter5/create-cert.sh

openssl genrsa -out tls.key 2048

openssl req -new -x509 -key tls.key -out tls.cert -days 360 -subj /CN=kubia.example.com

添加证书至Secrets:

kubectl create secret tls tls-secret --cert=tls.cert --key=tls.key

查看:

[root@localhost chapter5]# kubectl get secrets
NAME                  TYPE                                  DATA   AGE
default-token-97zwj   kubernetes.io/service-account-token   3      46h
tls-secret            kubernetes.io/tls                     2      41m

创建成功;


配置Ingress

为Ingress添加TLS配置:

chapter5/kubia-ingress-tls.yaml

# k8s: v1.18.17
# info: https://kubernetes.io/blog/2019/07/18/api-deprecations-in-1-16/
apiVersion: networking.k8s.io/v1beta1
#apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: kubia-tls
spec:
  tls:
    - hosts:
      - kubia.example.com
      secretName: tls-secret
  rules:
    - host: kubia.example.com
      http:
        paths:
          - backend:
              serviceName: kubia-nodeport
              servicePort: 80
            path: /

在配置中添加了TLS相关的配置:

  • hosts:指定后方Ingress的域名地址;
  • secretName:所配置TLS证书的Secrets名称;

最后使用kubectl apply更新配置;

kubectl apply -f kubia-ingress-tls.yaml

查看配置:

[root@localhost chapter5]# kubectl describe ingress kubia-tls 
Name:             kubia-tls
Namespace:        default
Address:          192.168.49.3
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
TLS:
  tls-secret terminates kubia.example.com
Rules:
  Host               Path  Backends
  ----               ----  --------
  kubia.example.com  
                     /   kubia-nodeport:80 (10.244.0.12:8080,10.244.1.25:8080,10.244.2.26:8080)
Annotations:         <none>
Events:
  Type    Reason  Age   From                      Message
  ----    ------  ----  ----                      -------
  Normal  CREATE  34m   nginx-ingress-controller  Ingress default/kubia-tls
  Normal  UPDATE  34m   nginx-ingress-controller  Ingress default/kubia-tls

Rules中,可以看到我们的Ingress已经正确的被配置,并且解析到了服务地址;

配置完成;


测试TLS连接

最后,我们做一下测试吧;

首先查看我们Ingress-Nginx服务的端口映射情况:

[root@localhost chapter5]# kubectl get svc -n ingress-nginx
NAME                                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.104.211.117   <none>        80:31904/TCP,443:30310/TCP   15h
ingress-nginx-controller-admission   ClusterIP   10.101.176.66    <none>        443/TCP

可以看到端口映射是:

  • HTTP: 80:31904/TCP;
  • HTTPS:443:30310/TCP;

下面我们进行测试;

首先先测试HTTP连接:

[root@localhost chapter5]# curl -k -v https://kubia.example.com:31904/kubia
* About to connect() to kubia.example.com port 31904 (#0)
*   Trying 192.168.49.3...
* Connected to kubia.example.com (192.168.49.3) port 31904 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* NSS error -12263 (SSL_ERROR_RX_RECORD_TOO_LONG)
* SSL received a record that exceeded the maximum permissible length.
* Closing connection 0
curl: (35) SSL received a record that exceeded the maximum permissible length.

由于我们没有配置非HTTP连接的情况,因此如果直接使用HTTP进行连接,会报错;

下面测试HTTPS连接:

[root@localhost chapter5]# curl -k -v https://kubia.example.com:30310/kubia
* About to connect() to kubia.example.com port 30310 (#0)
*   Trying 192.168.49.3...
* Connected to kubia.example.com (192.168.49.3) port 30310 (#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=kubia.example.com
*       start date: May 31 00:33:42 2021 GMT
*       expire date: May 26 00:33:42 2022 GMT
*       common name: kubia.example.com
*       issuer: CN=kubia.example.com
> GET /kubia HTTP/1.1
> User-Agent: curl/7.29.0
> Host: kubia.example.com:30310
> Accept: */*
> 
< HTTP/1.1 200 OK
< Server: nginx/1.19.1
< Date: Mon, 31 May 2021 01:24:02 GMT
< Transfer-Encoding: chunked
< Connection: keep-alive
< Strict-Transport-Security: max-age=15724800; includeSubDomains
< 
You've hit kubia-replicaset-rl7tm
* Connection #0 to host kubia.example.com left intact

[root@localhost chapter5]# curl -k -v https://kubia.example.com:30310/kubia
* About to connect() to kubia.example.com port 30310 (#0)
*   Trying 192.168.49.3...
* Connected to kubia.example.com (192.168.49.3) port 30310 (#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=kubia.example.com
*       start date: May 31 00:33:42 2021 GMT
*       expire date: May 26 00:33:42 2022 GMT
*       common name: kubia.example.com
*       issuer: CN=kubia.example.com
> GET /kubia HTTP/1.1
> User-Agent: curl/7.29.0
> Host: kubia.example.com:30310
> Accept: */*
> 
< HTTP/1.1 200 OK
< Server: nginx/1.19.1
< Date: Mon, 31 May 2021 01:24:10 GMT
< Transfer-Encoding: chunked
< Connection: keep-alive
< Strict-Transport-Security: max-age=15724800; includeSubDomains
< 
You've hit kubia-replicaset-l99pk
* Connection #0 to host kubia.example.com left intact

从上面打出的日志可以看出,成功通过HTTPS建立了连接;

并且服务的负载均衡也正确的作用了;


后记

HTTPS作为现代服务最重要的基本配置之一,不得不学习;

上面的各种配置可以进行优化:

  • 在配置证书时可以使用CertificateSigningRequest(CSR)资源签署;

此外需要注意的是:

  • 对于Ingress功能的支持因不同的Ingress控制器的实现而异;

附录

源代码:

系列文章:



本文作者:Jasonkay
本文链接:https://jasonkayzk.github.io/2021/05/31/配置Ingress处理TLS传输/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可