Kubernetes资源管理之Ingress

1、概述

Service是四层调度器,无论是Iptable还是ipvs,都是工作在TCP/IP协议栈上。在生产环境中,提供的站点多为HTTPS请求,而后端多为HTTP服务

1.1、Service调度网络的缺陷:

基本的Service模式如下图,如果使用工作在四层的Service作为调度器,证书应该放置在何处?会话应该如何保持?https证书如何卸载?

16-K8s网络之ingress - 图1

1.2、解决缺陷的方案

1.2.1、解决方案一:

可以在集群中增加一个独立的Pod作为七层代理使用,比如Nginx。如下图

16-K8s网络之ingress - 图2

上述方式,用户在集群外发起请求后,通过LoadBanacer转发至K8s集群中的节点,节点上NodePort接收到请求,将服务转发至七层代理的Service,Service收到后将请求转发至七层代理Nginx,Nginx进行证书卸载再将请求转发至后端的Service,Service再转发至后端服务器。为了实现一个功能,增加了4层转发,效率极差。

1.2.2、解决方案二:

在节点上运行的容器可以使用自己的虚拟网络,但也可以共享宿主机的网络名称空间,如果使用宿主机的网络就相当于将端口直接监听在宿主机上。因此,在方案一的基础上,将Nginx Pod直接运行为共享模式。

16-K8s网络之ingress - 图3

此方案中,因为Nginx Pod运行为共享模式,因此在节点上只能运行一个服务,客户端访问也只能访问这一个节点,则会出现单点。

1.2.3、解决方案三:

为了防止出现单点,可以使用K8s中的DamonSet控制器,来在每一个节点上创建一个代理Pod。

16-K8s网络之ingress - 图4

上述这种方式就是Ingress Controller,详细调用方式如下图:

16-K8s网络之ingress - 图5

  • ingress:K8s中的一个抽象资源,给管理员提供一个暴露应用的入口定义方法。
  • ingress Controller:根据ingress生成具体的路由规则,为集群提供全局的负载均衡能力。ingress Controller本质上是一个DaemonSet的Pod,因此实现的方式有多种,可以基于Nginx、Haproxy等实现负载均衡。

2、Ingress使用流程

Ingress Crontroller通过与K8s API交互,动态感知集群中Ingress规则变化,根据规则生成Nginx配置,应用到管理的Nginx Pod中,然后热加载生效。

2.1、部署ingress crontroller

在K8s官网选择适合的Crontroller,https://kubernetes.io/zh/docs/concepts/services-networking/ingress-controllers/

  1. $ kubectl apply -f ingress-controller.yaml
  2. $ kubectl get pods -n ingress-nginx -o wide
  3. NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
  4. nginx-ingress-controller-k9c8k 1/1 Running 0 11m 10.211.55.103 k8s-slave2 <none> <none>
  5. nginx-ingress-controller-x2mpw 1/1 Running 0 11m 10.211.55.102 k8s-slave1 <none> <none>

2.2、创建基于HTTP转发的ingress规则

  • 创建规则之前先准备一组deployment的Pod和关联的service资源
$ kubectl get pod,svc
NAME                                READY   STATUS    RESTARTS   AGE
pod/webdepoyment-78cff8f5f7-2jc52   1/1     Running   0          3h20m
pod/webdepoyment-78cff8f5f7-2xhgc   1/1     Running   0          3h20m
pod/webdepoyment-78cff8f5f7-cdt8l   1/1     Running   0          3h20m

NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/web-service   NodePort    10.105.144.52   <none>        80:30080/TCP   3h20m
  • 创建的规则为使用web.test.com域名转发到web-service中。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: webingress
spec:
  rules:
  - host: web.test.com   # 域名
    http:
      paths:
      - path: /  # 转发规则,nginx中的location
        pathType: Prefix
        backend:  # 后端服务
          service:  
            name: web-service  # service名称
            port:
              number: 80   # 监听端口
  • 查看ingress规则
kubectl get ingress
NAME         CLASS    HOSTS          ADDRESS   PORTS   AGE
webingress   <none>   web.test.com             80      8s
  • 添加hosts文件
# 在client上绑定hosts文件
10.211.55.102 web.test.com
10.211.55.103 web.test.com

使用浏览器访问web.test.com即可。

2.3、创建基于HTTPs的Ingress规则

  • 准备证书文件,可以自建证书或者申请权威证书。

  • 将证书保存到K8s集群secret中。

$ kubectl create secret tls web-test-com --cert=web.test.com.pem --key=web.test.com-key.pem
secret/web-test-com created
$ kubectl get secret
NAME                  TYPE                                  DATA   AGE
default-token-hx8bm   kubernetes.io/service-account-token   3      5h51m
web-test-com          kubernetes.io/tls                     2      11s
  • 创建Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: webingress
spec:
  tls:  # 添加此段配置
  - hosts:
    - web.test.com  # 域名
    secretName: web-test-com  # 指定secret名称
  rules:
  - host: web.test.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80
  • 查看ingress规则
$ kubectl get ingress
NAME         CLASS    HOSTS          ADDRESS   PORTS     AGE
webingress   <none>   web.test.com             80, 443   19m
# PORTS处可以看到多监听了443端口。

使用https://web.test.com就可以访问了。