原创内容:转载请注明出处
基本概念 - K8S的外部访问方式
NodePort
尽管通过 NodePort 访问的操作尽管简单,但同时也存在着致命的问题:
- 每个 Service 只能绑定一个端口;但是本身计算机端口数量有限,存在瓶颈
- 过多的端口数量不利于维护和管理
- 为了提高可用性,还需要额外的在外部设置一个负载均衡器
- Node节点的变更无法及时感知
LoadBalancer
通过云服务商的 LB 功能也可以达到相应的效果,同时也有一些小问题:
- 为了保证 LoadBalancer 的稳定性,一般需要依赖于云服务商
- 云服务商提供的功能付费
- 每个服务都必须要有一个自己的 IP,不论是内网 IP 或者外网 IP
Ingress
Ingress 事实上不是一种服务类型,它处于多个服务的前端,扮演着“智能路由”或者集群入口的角色
所以 Ingress 的基本功能包含了以下功能:
- 提供统一的访问入口
- 按照路由规则为 Service 提供外部可访问的 URL
- 负载均衡流量
- 卸载 SSL/TLS
- 基于名称的虚拟托管
Ingress 概念
Ingress 简介
Ingress 资源是在 Kubernetes V1.1 中引入的
Ingress 公开了从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源上定义的规则控制
举个简单的例子, 我们从对应的 ingress 发送流量到对应的 Service 中
如下图所示:
Ingress && ingress-controllers && ingress-class 基本概念
在开始前先描述下 ingress 和 ingress-controllers 的区别:
- Ingress 是一种资源,不负责接受请求和处理转发,只是一条转发规则而已
- Ingress-controllers 是一种解释 Ingress 的,并执行的组件; 常见的组件包含
- ingress-nginx
- ingress-kong
- Ingress-class 同一个集群中可以运行多个、多种 ingress-controllers, Ingress-class 则是用来区别这些 控制器 的类型的
针对 ingress-class 我们再补充几点:
试想一下,当我们的集群中存在多个 ingress-controllers (可以是不同的 控制器类型或者是同一种控制器但全局配置不同); 那么当前配置的这个 ingress 该交给谁来处理和解释呢?
- 如果所有的 ingress-controllers 都解析一次 ingress 会造成资源浪费
- 针对某些特定的场景,想特别的指定给某个 ingress-controllers
这个时候就可以通过 ingress-class 来区分对应的ingress解析工作交给谁去处理
从 1.14 开始必须要设置对应的 IngressClass, 否则会报错
在 Kubernetes 1.18 版本引入 IngressClass 资源和 ingressClassName 字段之前,Ingress 类是通过 Ingress 中的一个 kubernetes.io/ingress.class 注解来指定的
Ingress-nginx 原理说明
ingress-controllers 的内部构成
ingress-controllers 创建成功后,会自动的在集群中创建指定数量的 Pod
此刻我们进入 Pod 中, 查看对应的进程树信息
bash-5.1$ pstree
dumb-init---nginx-ingress-c-+-nginx-+-2*[nginx---32*[{nginx}]]
| `-nginx
`-14*[{nginx-ingress-c}]
bash-5.1$ pstree -p
dumb-init(1)---nginx-ingress-c(7)-+-nginx(27)-+-nginx(31)-+-{nginx}(67)
| | |-{.....}(68)
| | `-{nginx}(98)
| |-nginx(32)-+-{nginx}(35)
| | |-{.....}(36)
| | `-{nginx}(66)
| `-nginx(33)
|-{nginx-ingress-c}(8)
|-{.......}(9)
`-{nginx-ingress-c}(99)
bash-5.1$ ps
PID USER TIME COMMAND
1 www-data 0:00 /usr/bin/dumb-init -- /nginx-ingress-controller --election-id=ingress-controller-leader-nginx --ingress-class=nginx --watch-ingress-without-class --controller-class=k8s.io/ingress-nginx --configmap=kube-system/nginx
8 www-data 1:36 /nginx-ingress-controller --election-id=ingress-controller-leader-nginx --ingress-class=nginx --watch-ingress-without-class --controller-class=k8s.io/ingress-nginx --configmap=kube-system/nginx-configuration --tcp-s
27 www-data 0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /etc/nginx/nginx.conf
138 www-data 0:58 nginx: worker process
139 www-data 1:02 nginx: worker process
140 www-data 0:00 nginx: cache manager process
259 www-data 0:00 /bin/sh -c TERM=xterm-256color; export TERM; LANG=C.UTF-8; export LANG; [ -x /bin/bash ] && ([ -x /usr/bin/script ] && /usr/bin/script -q -c "/bin/bash" /dev/null || exec /bin/bash) || exec /bin/sh
265 www-data 0:00 /bin/bash
266 www-data 0:00 ps
如果获取不到 PPID 我们可以通过 top 指令来查看
根据上面得到的信息,我们就可以绘制出如下图所示的内容:
程序通过 dumb-init 启动了 nginx-ingress-controller, nginx-ingress-controller 唤起 nginx
- nginx-ingress-controller 根据集群中创建的 Ingress 和其他资源动态配置 NGINX
- nginx 用于实际上负责流量转发功能
- Master 控制 NGINX 工作进程
- Worker 处理客户端流量并将流量负载平衡到后端应用程序
- Cache Manager 应答缓存相关存储和处理
针对nginx的相关进程启动顺序,和运行模式这里不多做介绍
相关资料查阅关键字: master-worker 进程模型
ingress-controllers 的整体运行逻辑
nginx-ingress-c 通过与 api server
交互,监听存储于 etcd 中的 ingress、service、endpoint 等资源的变化
当数据产生变化后则会自动的更新 nginx 对应的配置信息,并 reload nginx 进程; 在此过程中, Pod 和 容器都不会重新创建、重启
ingress-controllers 内部细化逻辑
ingress-controllers 重载配置逻辑
程序运行后,主程序开启两个协程用于处理同步的数据:
- Store;用于监听变更并提供查询功能
- SyncQueue;用于执行 nginx.conf 生产和重启 nginx 服务
Store
和 api server
建立连接,监听 ingress 等资源的变化;当变化到达的时候,会写入一个名为 updateChannel 的通道,主程序消费数据并向同步队列追加同步任务(隔离开可以更好的对数据进行缓冲和处理);SyncQueue
定期的拉取处理任务,并向 Store
进行查询对应的 ingress/Service 的详细信息,根据模板生成对应的 nginx.conf 数据;根据变更的数据,判断是否执行重启操作
客户端通过 Ingress 访问 Pod 的流程
客户端首先通过DNS查找,DNS 返回对应的 IP 地址(前方可能存在防火墙、4层高可用代理); 客户端接着向 Ingress控制器 发送 HTTP 请求,并在 Host 头中指定对应的域名 a.domain.com. 控制器从该头部确认该客户端访问哪个服务,通过与服务关联的 Endpoint 对象查看 Pod IP,并将请求转发给其中一个 Pod
ingress 资源清单版本差异说明
在 1.9+ 相关的资源配置清单中,会存在差异
我们可以通过相关命令查看对应的资源类型
[root@simple-master-100 ~]# kubectl api-resources|grep ingress
ingresses ing extensions/v1beta1 true Ingress
ingressclasses networking.k8s.io/v1 false IngressClass
ingresses ing networking.k8s.io/v1 true Ingress
此处针对 ingress 的资源清单在不同版本中对应的配置不同;重点就在于 后端服务和资源的配置区别 ingresses.spec.rules.http.paths.backend
[root@simple-master-100 ~]# kubectl explain ingresses.spec.rules.http.paths.backend
KIND: Ingress
VERSION: networking.k8s.io/v1
RESOURCE: backend <Object>
DESCRIPTION:
Backend defines the referenced service endpoint to which the traffic will
be forwarded to.
IngressBackend describes all endpoints for a given service and port.
FIELDS:
resource <Object>
Resource is an ObjectRef to another Kubernetes resource in the namespace of
the Ingress object. If resource is specified, a service.Name and
service.Port must not be specified. This is a mutually exclusive setting
with "Service".
service <Object>
Service refe