Kubernetes-7.Ingress
- docker version:20.10.2 
- kubernetes version:1.20.1 
本文概述Kubernetes Ingress基本原理和官方维护的Nginx-Ingress的基本安装使用。
Ingress是对集群中服务的外部访问进行管理的API对象,典型的访问方式是HTTP。Ingress可以提供负载均衡、SSL termination和基于名称的虚拟托管。
虽然K8S集群内部署的Pod、Service都有自己的IP,但是无法对外提供灵活的访问,NodePort虽然能够提供对外访问,但是灵活性有限。
Ingress是什么
Ingress公开了从集群外部到集群内服务的HTTP和HTTPS路由。流量路由由Ingress资源上定义的规则控制。
下面是一个将所有流量都发送到同一Service的简单Ingress示例:

可以将Ingress配置为服务提供外部可访问的URL、负载均衡流量、终止SSL/TLS,以及提供基于名称的虚拟主机等能力。Ingress控制器通常负责通过负载均衡器来实现Ingress,尽管它也可以配置边缘路由器或其他前端来帮助处理流量。
Ingress不会公开任意端口或协议。将HTTP和HTTPS以外的服务公开到Internet时,通常使用Service.Type=NodePort或Service.Type=LoadBalancer类型的服务。
Ingress Controller
要使Ingress资源工作,集群必须有一个运行的Ingress控制器。
与作为kube-controller-manager可执行的一部分运行的其他类型的控制器不同,Ingress控制器不是随集群自动启动的。
Ingress controller能够监控集群变化,使集群始终保持期望的状态。能够实施感知Ingress路由规则集合的变化,再与API Server交互,获取Service、Pod在集群中的信息,而后根据信息更新代理服务。
Kubernetes项目目前维护AWS、GCE和Nginx Ingress控制器。
其他主流第三方项目:
- Apache APISIX Ingress 控制器
- HAProxy Ingress
- Traefik
- Envoy
- Nginxinc NGINX-Ingress
注意:Kubernetes社区维护的Nginx ingress与Nginx官方开发维护的并不是同一版本,Kubernetes官方维护的使用Go/Lua实现,Nginx官方维护的使用Go/Python实现。
可以在集群中部署任意数量的ingress控制器。创建ingress时,使用适当的ingress.class注解每个Ingress以表明在集群中如果有多个Ingress控制器时,应该使用哪个Ingress控制器。
如果不定义ingress.class,云提供商可能使用默认的Ingress控制器。
安装Ingress Controller
在自建的Kubernetes上部署Ingress Controller,选用Kubernetes官方维护的ingress-nginx:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.44.0/deploy/static/provider/baremetal/deploy.yaml
注意:官方的默认文件中使用的镜像是从Google镜像站点下载的,由于某些原因可能无法访问,请确保能够访问下载,不然会导致无法成功安装。也可以下载github上此项目的release版本进行安装。
在不同的平台上搭建Kubernetes集群,则部署方式中的配置也略有不同,官方提供各平台的常用一键部署方式,具体查看官方资料
此部署清单会使用NodePort方式暴露服务,但未指定NodePort具体端口,使用随机端口。此外会部署到集群中所有节点上,在正式环境使用中可能不符合需求,可以通过节点亲和性、污点容忍度等方式指定部署到有需要的节点上。如果需要修改则更改部署清单文件中相关配置即可。
部署清单中会创建一个名为ingress-nginx的Namespace,其属于Namespace级别的相关服务都会创建到此Namespace下。还会使用到ServiceAccount、ConfigMap、RBAC、Job控制器等,均会自动创建,需要了解则详细查看此部署清单即可。
Ingress使用示例
创建web服务,使用Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - name: http
          containerPort: 80
        lifecycle:
          postStart:
           exec:
            command: ["/bin/sh", "-c", "echo $HOSTNAME>/usr/share/nginx/html/hostname.html"]
创建svc:
apiVersion: v1
kind: Service
metadata:
  name: ingress-demo-svc
spec:
  selector:
    app: nginx
  ports:
    - name: web-port
      protocol: TCP
      port: 80
      targetPort: 80
创建Ingress资源:
kind: Ingress
metadata:
  name: ingress-demo
  annotations:
    # use the shared ingress-nginx
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: myingress.foo.org
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: ingress-demo-svc
            port:
              number: 80
测试效果:
# 获取Ingress Controller的NodePort端口;ingress-nginx-controller service的NodePort使用部署文件默认随机端口
kubectl get svc -n ingress-nginx
# 在集群外部主机上添加解析记录:myingress.foo.org指定到集群中任意节点,然后访问
for i in {{0..5}}; do curl myingress.foo.org:32733/hostname.html ;done
nginx-deployment-7c88b85cf8-2kfr4
nginx-deployment-7c88b85cf8-2kfr4
nginx-deployment-7c88b85cf8-ngb49
nginx-deployment-7c88b85cf8-ngb49
nginx-deployment-7c88b85cf8-2kfr4
nginx-deployment-7c88b85cf8-2kfr4
#
Ingress控制器通过创建一个NodePort方式的svc作为代理将服务暴露,用户通过创建Ingress资源,将集群内的svc的Endpoint绑定到Ingress控制器的代理Upstream中,从而用户访问Ingress控制器暴露的资源,而后被代理到真正的应用Pod上。
与Service不同的是,Ingress能够实现更多的负载均衡代理策略,能够提供HTTPS的代理,能够更好的管理统一入口。
NodePort方式在多个节点上向外暴露提供了服务,却还是缺少统一性管理入口。在云环境服务商上,可以通过部署清单申请LB作为前置,在自建环境中则需要自部署一些相关处理方式,如裸机环境中的扩展中描述的。
Ingress资源
如上示例,Ingress同样需要使用apiVersion、kind和metadata字段。Ingress经常使用注解(annotations)来配置一些选项,具体取决于Ingress控制器,例如重写目标注解。不同的Ingress控制器支持不同的注解。
Ingress规约提供了配置负载均衡器或者代理服务器所需的所有信息。最重要的是,其中包含与所有传入请求匹配的规则列表。Ingress资源仅支持用于转发HTTP流量的规则。
常用字段:
ingress.spec.defaultBackend:默认后端。没有rules的Ingress将所有流量发送到同一后端。defaultBackend通常是Ingress控制器的配置选项,而非在Ingress资源中指定。
ingress.spec.ingressClassName:在Kubernetes1.18版本引入ingressClassName字段,对ingressClass资源的引用,且包含用来替代注解中的kubernetes.io/ingress.class字段。
ingress.spec.rules:Ingress规则。
ingress.spec.rules.host:基于域名代理。被代理服务的域名,指定了此字段,访问时必须使用域名。
ingress.spec.rules.http:基于路径代理。
ingress.spec.rules.http.paths.path:代理的路径。
ingress.spec.rules.http.paths.pathType:路径类型;ImplementationSpecific,Exact,Prefix。
ingress.spec.rules.http.paths.backend.resource:资源后端,指向ObjectRef。
ingress.spec.rules.http.paths.backend.service:服务后端,指向服务。
ingress.spec.rules.http.paths.backend.service.name:后端的名称,即svc的名称。
ingress.spec.rules.http.paths.backend.service.port:后端的端口,支持name或number方式。
ingress.spec.tls:TLS类型代理。
ingress.spec.tls.hosts:代理的域名。
ingress.spec.tls.secretName:secret中保存此域名证书的名称。
资源后端
Resource后端是一个ObjectRef。Resource后端的一种常见用法是将所有入站数据导向带有静态资产的对象存储后端。
注意:backend中的resource和service不能同时使用。
示例:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-resource-backend
spec:
  defaultBackend:
    resource:
      apiGroup: k8s.example.com
      kind: StorageBucket
      name: static-assets
  rules:
    - http:
        paths:
          - path: /icons
            pathType: ImplementationSpecific
            backend:
              resource:
                apiGroup: k8s.example.com
                kind: StorageBucket
                name: icon-assets
路径类型
Ingress中的每个路径都需要有对应的路径类型(pathType)。未明确设置pathType无法通过合法性检查。
当前支持的路径类型有三种:
- ImplementationSpecific:对于这种路径类型,匹配方法取决于IngressClass。具体实现可以将其作为单独的pathType处理或者与Prefix或Exact类型作相同处理。
- Exact:精确匹配URL路径,区分大小写。
- Prefix:基于以/分隔的的URL路径前缀匹配,匹配区分大小写。
Exact是精确匹配,如路径/foo只能够匹配到请求路径/foo,/foo/视为不匹配。
Prefix是前缀匹配,以/作为分隔。如路径/foo可以被请求路径/foo、/foo/、/foo/abc匹配到。路径/能够匹配所有请求路径。
注意:在某些情况下,Ingress中的多条路径会匹配同一个请求。这种情况下最长的匹配路径优先。如果仍然有两条同等的匹配路径,则精确路径类型优先于前缀路径类型。
主机名通配符
主机名可以是精确匹配(如foo.bar.com)或者使用通配符来匹配(如*.bar.com)。精确匹配要求HTTP host头部字段与host字段值完全匹配。通配符匹配则要求HTTP host头部字段与通配符规则中的后缀部分相同。
| 主机 | host | 匹配与否 | 
|---|---|---|
| *.foo.com | bar.foo.com | 匹配,后缀相同 | 
| *.foo.com | baz.bar.foo.com | 不匹配,通配符仅覆盖了一个DNS标签 | 
| *.foo.com | foo.com | 不匹配,通配符仅覆盖了一个DNS标签 | 
Ingress类
Ingress可以由不同的控制器实现,通常使用不同的配置。每个Ingress应当指定一个类,也就是一个对IngressClass资源的引用。IngressClass资源包含额外的配置,其中包括应当实现该类的控制器名称。
IngressClass资源包含一个可选的parameters字段,可用于为该类引用额外配置。
示例:
具体解释可通过命令查看kubectl explain ingressClass
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: external-lb
spec:
  controller: example.com/ingress-controller
  parameters:
    apiGroup: k8s.example.com
    kind: IngressParameters
    name: external-lb
在Kubernetes 1.18版本引入Ingress Class资源和ingressClassName字段之前,Ingress类是通过Ingress中的一个kubernetes.io/ingress.class注解来指定的。这个注解从未被正式定义过,但是得到了Ingress控制器的广泛支持。
默认Ingress类
将一个IngressClass资源的ingressclass.kubernetes.io/is-default-class注解设置为true,使其成为默认Ingress类。新创建的Ingress资源未指定IngressClassName字段时,将使用此默认Ingress类。集群中最多只能有一个IngressClass被标记为默认。
TLS示例
使用Ingress TLS必须首先创建TLS secret,secret必须包含名为tls.crt和tls.key的键名。
测试使用时,自签HTTP证书:
# 申请证书
openssl genrsa -out tls.key 2048
openssl req -new -x509 -key tls.key -out tls.crt -subj /C=CN/ST=Guangdong/L=Shenzhen/O=DevOps/CN=mytls.website.com
# 创建TLS secret
kubectl create secret tls mytls-ingress-tls --cert=tls.crt --key=tls.key
# 查看TLS secret
kubectl describe secret mytls-ingress-tls
创建TLS类型的Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-tls
  annotations:
    # use the shared ingress-nginx
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: mytls.website.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: ingress-demo-svc
            port:
              number: 80
  tls:
  - hosts:
    - mytls.website.com
    secretName: mytls-ingress-tls
使用之前示例中的svc绑定到ingress资源下,创建好tls类型的ingress后,在集群外节点上通过tls访问即可。注意要使用Ingress 443端口的NodePort端口访问。
裸机环境中的扩展
在云环境下,网络负载均衡器是按需提供的,只需要有部署清单申请了即可使用向外部提供联系。在裸机环境中(自建私有Kubernetes集群环境)缺少这种提供,需要额外来设置。

以下解决方案:
- MetalLB
- NodePort
- 共享主机网络
- 自部署边缘网络组件(如HAproxy),运行在Kubernetes集群环境之外
- External IPs
具体使用可根据自身需求查阅相关资料。
Kubernetes-7.Ingress的更多相关文章
- kubernetes nginx ingress 使用记录
		前言 ingress是一种可以暴露k8s集群内部service的方式,用户编辑配置文件定义一个ingress资源即可实现外部网络访问内网service. ingress controller是来管理所 ... 
- kubernetes之ingress及ingress controller
		什么是ingress Ingress是授权入站连接到达集群服务的规则集合. 从外部流量调度到nodeprot上的service 从service调度到ingress-controller ingres ... 
- kubernetes nginx ingress controller部署
		Kubernetes nginx ingress controller部署 1.下载kubernetes nginx的yaml文件 Wget https://raw.githubusercontent ... 
- 使用traefik作为kubernetes的ingress
		目录 说明 部署 创建一个独立的命名空间 配置rbac授权 配置secret 创建一个configmap用于存放traefik的配置文件 配置traefik的deployment文件 配置服务 通过p ... 
- 为什么我不使用Kubernetes的Ingress
		为什么我不使用Kubernetes的Ingress 很不幸,据我所知Kubernetes的文档不是很完美,这就是为什么有很多同学在使用它的时候会遇到很多的坑,Ingress这个组件就是这些坑中的一个. ... 
- kubernetes Traefik ingress配置详解
		理解Ingress 简单的说,ingress就是从kubernetes集群外访问集群的入口,将用户的URL请求转发到不同的service上.Ingress相当于nginx.apache等负载均衡方向代 ... 
- 【转帖】kubernetes 部署ingress
		kubernetes 部署ingress https://www.cnblogs.com/dingbin/p/9754993.html 明天尝试一下 之前的文档里面一直没有提 需要改host文件 我有 ... 
- 【转】Kubernetes的Ingress控制器比较
		Kubernetes的Ingress控制器比较 fiisio Kubernetes/云计算/资源调度/Go语言 21 人赞同了该文章 翻译:https://medium.com/flant-com/c ... 
- kubernetes 部署ingress
		kubernetes Ingess 是有2部分组成,Ingress Controller 和Ingress服务组成,常用的Ingress Controller 是ingress-nginx,工作的原理 ... 
- 干货分享:如何使用Kubernetes的Ingress API
		您可以通过使用诸如Kong for Kubernetes的Ingress控制器(使用自定义资源定义并提供许多插件)来极大地扩展Ingress资源的功能. Kubernetes正在整个技术行业中得到采用 ... 
随机推荐
- vue开发东京买菜,全栈项目,前端django,带手机GPS精准定位,带发票系统,带快递系统,带微信/支付宝/花呗/银行卡支付/带手机号一键登陆,等等
			因为博客园不能发视频,所以,完整的视频,开发文档,源码,请向博主索取 完整视频+开发文档+源码,duanshuiLu.com下载 vue+django手机购物商城APP,带支付,带GPS精准定位用户, ... 
- AtCoder Beginner Contest 179
			比赛链接:https://atcoder.jp/contests/abc179/tasks A - Plural Form 题意 给出一个由小写字母组成的单词,如果单词以 $s$ 结尾,在单词的末尾加 ... 
- GPLT L2-010 排座位 (并查集)
			Tips: 数据范围较小时可把二维数组当做map<pair<int,int>,int>使用. #include <bits/stdc++.h> using name ... 
- 洛谷P5496 回文自动机【PAM】模板
			回文自动机模板 1.一个串的本质不同的回文串数量是\(O(n)\)级别的 2.回文自动机的状态数不超过串长,且状态数等于本质不同的回文串数量,除了奇偶两个根节点 3.如何统计所有回文串的数量,类似后缀 ... 
- poj 1511-- Invitation Cards (dijkstra+优先队列)
			刚开始想复杂了,一直做不出来,,,其实就是两遍dijkstra+优先队列(其实就是板子题,只要能有个好的板子,剩下的都不是事),做出来感觉好简单...... 题意:有n个车站和n个志愿者,早上每个志愿 ... 
- Educational Codeforces Round 9 C. The Smallest String Concatenation(字符串排序)
			You're given a list of n strings a1, a2, ..., an. You'd like to concatenate them together in some or ... 
- python的re模块一些方法 && Tkinter图形界面设计  && 终止python运行函数  && python读写文件  && python一旦给字符串赋值就不能单独改变某个字符,除非重新给变量赋值
			Tkinter图形界面设计见:https://www.cnblogs.com/pywjh/p/9527828.html#radiobutton 终止python运行函数: 采用sys.exit(0)正 ... 
- VS Code 配置 Java IDE
			背景 维护的项目在一个内网环境,只能通过跳转机的FTP上传文件.项目是Java spring boot开发,之前的维护人员使用sts(https://spring.io/tools),使用起来体验极差 ... 
- c#记两个变量进行值交换
			今天腊月二十九啦,无心上班,专注划水.然后就在那里翻帖子消磨时光. 看到了这样一个问题,有人提问为什么 a=b+(b=a)*0 ??? 第一眼看上去,我也有点蒙,仔细推敲了一下,嗯~的确是交换了 ... 
- python程序配置守护进程
			参考博客 python Supervisor 使用与配置_a35155的博客-CSDN博客 Ubuntu系统下:apt-get install supervisor,通过这种方式安装后,自动设置为开机 ... 
