Kubernetes 的最小部署单元是 Pod。通过 Overlay 网络,比如 Calico,不同节点上的容器能够直接通过 Pod IP 进行通信。
Service 为一组具有相同功能的容器,提供统一的入口地址,并且将请求进行负载均衡,分发到后端的各个容器应用上。
Pod IP 实际存在于某个网卡(可能是虚拟设备)上,但没有网络设备为 Service Cluster IP 负责。它由 kube-proxy 使用 iptables 规则重新定向到其本地端口,再均衡到后端 Pod。当 kube-proxy 发现新 Service 后,它将在本地节点打开任意端口,建相应的 iptables 规则,将 Service Cluster IP 和 Port 重定向到新建的端口,开始接受到达该服务的连接。
当客户端访问 Service 时,客户端的流量被 iptables 规则重定向到 kube-proxy 为该 Service 打开的端口,kube-proxy 随机选择一个后端 Pod 来服务客户端。流程如下图所示:
注意:这里描述的是 user space 模式。
可见 Service 是 Kubernetes 集群内部的服务发现机制,同一个集群内的 Service 之间,可以通过 Service Name 或 Cluter IP 进行通信。但是无法从集群外部访问集群内部的 Service。
如下图所示,Kubernetes 集群外部的用户如果想访问集群内部的 Service,可以采用 Ingress 的方式。
除 Ingress 外,还可以通过 NodePort 和 LoadBalancer 的方式,对外暴露服务。
使用 NodePort 的方式时,在所有节点上开放一个特定端口,任何发送到该端口的流量都被转发到对应服务。因此每个服务需要一个端口,当对外暴露大量服务时,集群的每个节点将开放大量端口,将引入安全隐患;并且不同服务无法共用相同端口,比如无法通过 80 或 443 端口,同时暴露多个服务。下面是暴露单个服务的示意图:
使用 LoadBalancer 的方式时,自己搭建的集群需要部署 LoadBalancer 软件(云服务商的集群自带),比如 metallb 等。使用 LoadBalancer 暴露的每个服务都将获得自己的 IP 地址。通过下图可以看出,相比 NodePort,LoadBalancer 多一层代理。
云厂商的部署方式通常是 Ingress + LoadBalancer。
Kubernetes Ingress 是一种 API 对象,它提供路由规则来管理外部用户对 Kubernetes 集群内的 Service 的访问。而 Ingress Controller 是 Ingress API 的真正实现。Ingress Controller 通常是一个 LoadBalancer,用于将外部流量路由到 Kubernetes 集群,负责 L4 - L7 网络服务。
常用的 Ingress Controller 有:
下图是 Nginx Ingress Controller(简称 IC)处理新 Ingress 资源的流程:
用户创建新 Ingress 资源
在集群内部,IC 进程拥有资源的缓存。该缓存仅包含 IC 感兴趣的资源,比如 Ingress。缓存通过监听资源变更的方式,保持与 Kubernetes API 同步
一旦缓存有新 Ingress 资源,它通知控制循环关于被变更的资源
控制循环从缓存获取 Ingress 资源的最新版本。因为 Ingress 资源引用其它资源,比如 TLS Secret(Secret 也是 Kubernetes 的一种 API 对象),所以控制循环也获取所有被引用资源的最新版本
控制循环根据 TLS Secret 生成 TLS 证书和密钥,并且将它们写到文件系统
控制循环生成与 Ingress 资源相对应的 Nginx 配置文件,并且将它们写入文件系统
控制循环重载(reload)Nginx,等待 Nginx 重载成功。重载的部分包括:
控制循环为 Ingress 资源发出事件,更新它的状态。如果重载失败,那么事件包含错误信息