Kubernetes学习笔记整理之Ingress Controller

一、概念理解

1. 简介

Ingress 是反向代理规则,用来规定 HTTP/S 请求应该被转发到哪个 Service 上,比如根据请求中不同的 Host 和 url 路径让请求落到不同的 Service 上

Kubernetes Ingress 文件大小设置 kubernetes ingress controller_Nginx

2. 两大组件

简单来说,Ingress 只有两大组件:Ingress Controller 和 Ingress

Ingress

其中,Ingress资源通过yaml文件申明规则配置

Ingress Controller

Ingress Controller 就是一个反向代理程序,它负责解析 Ingress 的反向代理规则,以Pod的形式运行,监控apiserver的/ingress端口后的backend services,如果 Ingress 有增删改的变动,所有的 Ingress Controller 都会及时更新自己相应的转发规则,当 Ingress Controller 收到请求后就会根据这些规则将请求转发到对应的 Service。

核心是一个deployment,实现方式有很多,比如nginx, Contour, Haproxy, trafik, Istio,需要编写的yaml有:Deployment, Service, ConfigMap, ServiceAccount(Auth),其中service的类型可以是NodePort或者LoadBalancer。

QA1:Ingress Controller具体怎么工作的呢?

实际上,Ingress Controller通过与 Kubernetes API 交互,动态的去感知集群中 Ingress 规则变化,然后读取它,按照自定义的规则(规则就是写明了哪个域名对应哪个service),生成一段 Nginx 配置,再写到 Nginx-ingress-control的 Pod 里,这个 Ingress Contronler 的pod里面运行着一个nginx服务,控制器会把生成的nginx配置写入/etc/nginx.conf文件中,然后 reload 一下 使用配置生效。以此来达到域名分配置及动态更新的问题。

Kubernetes Ingress 文件大小设置 kubernetes ingress controller_运维_02

QA2:Ingress Controller如何被集群外访问

有以下几种暴露内部流量的方式:

  • Ingress Controller 用 Deployment 方式部署,给它添加一个 Service,类型为 LoadBalancer,这样会自动生成一个 IP 地址,通过这个 IP 就能访问到了,并且一般这个 IP 是高可用的(前提是集群支持 LoadBalancer,通常云服务提供商才支持,自建集群一般没有,这也是最简单的方式)
  • 使用集群内部的某个或某些节点作为边缘节点,它们才是真正监听端口,让外界流量进入集群内部的节点,给这些边缘节点 node 添加 label 来标识(比如说设置ingress-controller=true),Ingress Controller 用 DaemonSet 方式部署(Deployment也可以),使用 nodeSelector 绑定到边缘节点,保证每个边缘节点启动一个 Ingress Controller 实例,用 hostPort 直接在这些边缘节点宿主机暴露端口,然后我们可以访问边缘节点中 Ingress Controller 暴露的端口,这样外部就可以访问到 Ingress Controller 了,多个边缘节点前面可以自己再搭一个负载均衡器,比如用Nginx或者有条件直接挂F5。
  • Ingress Controller 用 Deployment 方式部署,给它添加一个 Service,类型为 NodePort,部署完成后查看会给出一个端口,通过 kubectl get svc 我们可以查看到这个端口,这个端口在集群的每个节点都可以访问,通过访问集群节点的这个端口就可以访问 Ingress Controller 了。但是集群节点这么多,而且端口又不是 80和443,太不爽了,一般我们会在前面自己搭个负载均衡器,比如用 Nginx,将请求转发到集群各个节点的那个端口上,这样我们访问 Nginx 就相当于访问到 Ingress Controller 了

通常用的是前两种方式。

QA3:外部流量进集群POD是怎么被转发的

我们这里以上文中第二种方案(自建集群)画图说明,用到了3个边缘节点,流量从F5/LB进来,然后被转发到其中一个ingress controller的pod里面,并根据svc规则转发到svc对应的后端endpoint上(对应app pod),其中ingress controller是运行在某个ingress controller pod里面,直接watch API SERVER里面ingress规则的变更,这里就已经不需要ingress-nginx的svc了(不过一般还需要配置下,否则集群会一直提示err services "ingress-nginx" not found

Kubernetes Ingress 文件大小设置 kubernetes ingress controller_Nginx_03

图中可以看出,不需要Ingress Controller的SVC了,而且也跳过kube-proxy的转发功能,kube-proxy 不再起作用。

二、部署方案

1. 部署default.backend

为了让Ingress Controller 能够正常启动,还需要为它配置一个默认的backend,用于在客户端访问的URL地址不存在时,能够返回一个正确的404应答。这个backend服务用任何应用实现都可以,只要满足默认对路径的访问返回404应答,并且提供/healthz完成对它的健康检查。如下,default-backend.yaml 文件可以在 官方 Ingress 仓库 找到:kubectl create-f default-backend.yaml

2.部署Ingress Controller

部署文件也可以在 官方仓库找到,注意会需要拉取ingress-controller镜像,如果离线环境提前下载好。另外不同环境下载不同的部署yaml文件,这里只是示例,我们采用Helm方式来部署:

$ kubectl label node sysops00001 ingress-controller=true
node "sysops00001" labeled
helm install stable/nginx-ingress \
  --namespace ingress-nginx \
  --name nginx-ingress \
  --version=0.23.0 \
  --set controller.kind=DaemonSet \
  --set controller.daemonset.useHostPort=true \
  --set controller.nodeSelector.node=edge \
  --set controller.service.type=ClusterIP

查看状态
# kubectl get pods -n ingress-nginx -o wide
nginx-ingress-controller-b47h9                  1/1       Running   0          1h
nginx-ingress-default-backend-9c5d6df7d-7dwll   1/1       Running   0          1h

注意,ingress-controller 会监听node节点上的80和443端口,因此尽量在使用端口时保留80和443给ingress-controller使用

3. 部署ingress

直接编写ingress yaml文件并通过kubectl apply即可

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: cafe-ingress
spec:
  rules:
  # 配置七层域名
  - host: foo.bar.com
    http:
      paths:
      # 配置Context Path
      - path: /tea
        backend:
          serviceName: tea-svc
          servicePort: 80
      # 配置Context Path
      - path: /coffee
        backend:
          serviceName: coffee-svc
          servicePort: 80

注意,使用无域名的Ingress转发规则时,将默认禁用非安全HTTP,强制启用HTTPS. 可以在Ingress的定义中设置一个 annotation “ingress.kubernetes.io/ssl-redirect=false” 来关闭强制启用HTTPS的设置。