k8s ingress

ingress

  ingress为k8s集群中的服务提供了入口,可以提供复制均衡,ssl终止和基于名称的虚拟主机,再生产环境中,常用的ingress有Treafik,Nginx,HAProxy,Istio等

基本概念:

  在k8s1.1版本中添加的ingress用于集群外部的到集群内部service的HTTP和HTTPS路由,流量从internet到ingress再到service最后到pod上,通常情况下,ingress部署在所有的node节点上,

  ingress 可以配置,提供外部访问的url,负载均衡,终止ssl,并提供基于域名的虚拟主机,但是ingress不汇报了任意端口或协议

创建一个ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: simple-fanout-example
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - path: /foo
        pathType: Prefix
        backend:
          service:
            name: service1   #目标服务名称
            port:
              number: 4200 #目标服务端口
      - path: /bar
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 808

上述host:定义该ingress的域名,将其解析到任意node上即可访问

如果访问的是foo.bar.com/foo ,则被转发到service1的4200端口

如果访问的是foo.bar.com/bar , 则被转发到service2的8080端口

1,ingress rules

  host: 可选,一般都会匹配对应的域名

  path:每个路径都有一个对应的serviceName和servicePort,在流量到达服务之前,主机和路径都会与传入请求内容匹配

  backend:描述service和port的组合,对ingress匹配主机和路径的HTTP与HTTPS请求将被发送到对应的后端。

2,默认后端

  没有匹配到任何规则的流量将被发送到默认后端,默认后端通常是ingress controller的配置选项,并未在ingress资源中指定

创建一个自己写的ingress的yaml文件

[root@k8s-master01 ns-slx-study]# cat ingress.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: ingress
  labels:
    app: ingress
spec: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: ingress
  name: ingress-deploy
  labels:
    ingress: ingress-deploy
    app: nginx
spec:
  selector:
    matchLabels:
      app: nginx-pod
      env: test
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx-pod
        env: test
    spec:
      containers:
      - name: nginx-15
        image: registry.cn-beijing.aliyuncs.com/sunlixin/nginx-xiaoniaofeifei:v2
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
      restartPolicy: Always

---
apiVersion: v1
kind: Service
metadata:
  namespace: ingress
  name: service-test
  labels:
    app: nginx-service
    env: test
spec:
  selector:
    app: nginx-pod
    env: test
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: NodePort
---
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
  name: ingress-test
  namespace: ingress
spec:
  rules:
  - host: www.slx.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: service-test
            port:
              number: 80

路径类型pathType:

ingress中每个路径都需要有对应的路径类型,未明确设置路径无法用过合法性检测,当前支持三种路径类型:

  • ImplementationSpecific:对于这种路径类型,匹配方法取决于 IngressClass。 具体实现可以将其作为单独的 pathType 处理或者与 Prefix 或 Exact 类型作相同处理
  • Exact:精确匹配 URL 路径,且区分大小写。

  • Prefix:基于以 / 分隔的 URL 路径前缀匹配。匹配区分大小写,并且对路径中的元素逐个完成。 路径元素指的是由 / 分隔符分隔的路径中的标签列表。 如果每个 p 都是请求路径 p 的元素前缀,则请求与路径 p 匹配。

 如果路径的最后一个元素是请求路径中最后一个元素的子字符串,则不会匹配 (例如:/foo/bar 匹配 /foo/bar/baz, 但不匹配 /foo/barbaz)。

ingress类型:

1,单域名:单域名匹配多个path到不同的service

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: simple-fanout-example
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - path: /foo
        backend:
          serviceName: service1
          servicePort: 4200
      - path: /bar
        backend:
          serviceName: service2
          servicePort: 8080

此时,访问foo.bar.com/foo 到service1的4200,访问foo.bar.com/bar到service2的8080端口

2,多域名:基于域名的虚拟主机将支持http流量路由到同一IP地址的多个主机名:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: name-virtual-host-ingress
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - backend:
          serviceName: service1
          servicePort: 80
  - host: bar.foo.com
    http:
      paths:
      - backend:
          serviceName: service2
          servicePort: 80

此时,访问foo.bar.com到service1,访问bar.foo.com到service2。

3,基于TLS的ingress

首先创建证书,生成环境的正式为公司购买的证书

kubectl -n default create secret tls nginx-test-tls --key=tls.key --cert=tls.crt

定义ingress

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: nginx-https-test
  namespace: default
  annotations:
    kubernetes.io/ingress.class: traefik
spec:
  rules:
  - host: traefix-test.com
    http:
      paths:
      - backend:
          serviceName: nginx-svc
          servicePort: 80
  tls:
   - secretName: nginx-test-tls

 配置URL重新规则:

在一些使用场景中后端服务暴露的url与ingress规则中指定的路径不同,如果不进行url重写,所有的访问都将放回404,nginx的url重写可以通过Rewrite方法实现,使用“nginx.ingress.kubernetes.io/rewrite-target”注释可以实现不同路径的重写规则

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-test
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
    - host: 'rewrite.bar.com'
      http:
        paths:
          - path: '/something(/|$)(.*)'
            backend:
              serviceName: <your_service_name>  #替换为您的目标服务名称
              servicePort: 80

注意:只要有一个ingress使用了rewrite-target,则所有的ingress定义下同一个host下所有的path都会正则大小写敏感,包括没有使用rewrite-target的ingress

占位符$2表示将第二个括号(.*)中匹配到所有的字符填写到“nginx.ingress.kubernetes.io/rewrite-target”注解中。

上面的ingress定义将导致以下重写:

  • rewrite.bar.com/something 重写为 rewrite.bar.com/
  • rewrite.bar.com/something/ 重写为 rewrite.bar.com/
  • rewrite.bar.com/something/new 重写为 rewrite.bar.com/new

nginx-ingress-controller容器中,“/etc/nginx”路径下的nginx.conf文件可查看所有Ingress配置,重写规则将生成一条rewrite指令,并写入到nginx.com的location字段中

## start server rewrite.bar.com
        server {
                server_name rewrite.bar.com ;
                ...
                location ~* "^/something(/|$)(.*)" {
                        set $namespace      "default";
                        set $ingress_name   "ingress-test";
                        set $service_name   "<your_service_name>";
                        set $service_port   "80";
                        ...
                        rewrite "(?i)/something(/|$)(.*)" /$2 break;
                        ...
                }
        }
        ## end server rewrite.bar.com

上面的rewrite指令的语法结构为:

rewrite regex replacement [flag];
  • regex:匹配URI的正则表达式。在上述例子中,“(?i)/something(/|$)(.*)”即为匹配URI的正则表达式,其中“(?i)”表示不区分大小写。
  • replacement:重写内容。在上述例子中,“/$2”即为重写内容,表示把路径重写为第二个括号“(.*)”中匹配到的所有字符。
  • flag:表示重写形式的标记,包括:
    • last:表示本条规则匹配完成后继续向下匹配。
    • break:表示本条规则匹配完成后停止匹配。
    • redirect:表示临时重定向,返回状态码302。
    • permanent:表示永久重定向,返回状态码301。

创建负载均衡规则

原生的nginx支持多种负载均衡规则,期中常用的有加权轮询,IP hash等,nginx ingress在原生的nginx能力基础上,支持使用一致性的哈希方法进行负载均衡。

nginx默认支持的IP hash方法使用的线性hash空间,根据IP的hash运算值来选取后端的目标服务器。但是这种方法在添加删除节点时,所有的IP值都需要重新进行hash计算,然后重新路由,这样的话会导致大面积的会话或者缓存失效,因此nginx ingress 引入了一致性哈希来解决这个问题。

一致性hash是一种特殊的算法,通过构建环装的hash空间来替代普通的线性hash空间,在增删节点是仅需要将路由的目标含顺时针原则向下迁移,而其他路由无需改变,可以尽可能地减少重新路由,有效解决动态增删节点带来的负载均衡问题

通过配置一直性hash规则,在增加一台服务器时,新的服务器会尽量分担其他所有服务器压力。同样,在减少一台服务器时,其他的服务器,也可以尽量分担它的资源,可以有效的减少集群局部节点压力,防止由于某一节点宕机带来的集群雪崩效应、

Nginx Ingress可以通过“nginx.ingress.kubernetes.io/upstream-hash-by”注解实现一致性哈希规则的配置

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-test
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri"  #按照请求uri进行hash
spec:
  rules:
    - host: ''
      http:
        paths:
          - path: '/'
            backend:
              serviceName: <your_service_name>  #替换为您的目标服务名称
              servicePort: 80

注解“nginx.ingress.kubernetes.io/upstream-hash-by”的参数值支持nginx参数、文本值或任意组合,例如:

  • nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri"代表按照请求uri进行hash。
  • nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri$host"代表按照请求uri和域名进行hash。
  • nginx.ingress.kubernetes.io/upstream-hash-by: "${request_uri}-text-value"代表按照请求uri和文本值进行hash。

本篇随笔参考了:通过Kubectl命令行添加Nginx Ingress_云容器引擎 CCE_用户指南_旧版UI_网络管理_Ingress_华为云 (huaweicloud.com)  Ingress | Kubernetes

posted @ 2023-02-26 23:27  百因必有果  阅读(148)  评论(0编辑  收藏  举报