Kubernetes对象之Ingress

我们知道,Kubernetes对外暴露服务的方式有三种:LoadBlancerExternalNameNodePort

采用 NodePort 方式暴露服务面临的一个问题是,服务一旦多起来,NodePort Service在每个节点上开启的端口会及其庞大,而且难以维护。这时候引出的思考问题是 “能不能使用 Nginx 啥的只监听一个端口,比如 80,然后按照域名向后转发?” 这思路很好,简单的实现就是使用 DaemonSet 在每个 node 上监听 80,然后写好规则,因为 Nginx外面绑定了宿主机 80 端口(就像 NodePort),本身又在集群内,那么向后直接转发到相应 Service IP 就行了。

从上面的思路,采用 Nginx 似乎已经解决了问题,但是其实这里面有一个很大缺陷:每次有新服务加入怎么改 Nginx 配置?总不能手动改或者来个 Rolling Update 前端 Nginx Pod 吧?为了解决这个问题,出现了Ingress。将nginx的配置,即配置各种域名对应哪个 Service,抽象成一个 Ingress 对象,你可以用 yml 创建,每次不需要修改Nginx的配置文件了,直接修改yml 然后创建/更新就行了。

Ingress Controller 通过与 Kubernetes API 交互,动态的去感知集群中 Ingress 规则变化,然后读取他,按照他自己模板生成一段 Nginx配置,再写到 Nginx Pod 里,最后 reload一下,从而使更新后的Nginx工作。

1. 准备工作

由于Ingress Controller并不是kube-controller-manager中的一部分,因此要使用Ingress,我们必须首先在Kubernetes集群中安装一个Ingress Controller。常见的Ingress Controller包括 Nginx,Traefik,Istio等等。

使用Helm安装方式Nginx Ingress Controller:

helm install stable/nginx-ingress --name my-nginx

查看安装的Nginx Ingress Controller版本:

POD_NAME=$(kubectl get pods -l app.kubernetes.io/name=ingress-nginx -o jsonpath='{.items[0].metadata.name}')
kubectl exec -it $POD_NAME -- /nginx-ingress-controller --version

2. 创建一个Ingress对象

下面是一个最简单的Ingress对象文件:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /testpath
        backend:
          serviceName: test
          servicePort: 80
  • Ingress通常使用annotation来定义一些可重写的选项。例如Nginx Ingress Controller可重写的选项包括:rewrite-target annotation
  • spec.rules则用于定义路由规则。通常包含三部分信息:host,path和service。host是可选的,如果未定义,则适用于该IP收到的所有请求。否则只适用于host规定的URL。path可以包含多个,用于将满足path的请求路由到对应的service中。
  • 如果一个请求找不到对应的路由规则,那么它将被转发到default backenddefault backend通常是Ingress Controller的一个可选配置项。Ingress对象文件无需定义它。

下面是一个复杂的Ingress定义:

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

上面的Ingress对象实现了如下路由规则:

foo.bar.com -> 178.91.123.132 -> / foo    service1:4200
                                 / bar    service2:8080

可以使用kubectl describe ingress simple-fanout-example命令查看:

Name:             simple-fanout-example
Namespace:        default
Address:          178.91.123.132
Default backend:  default-http-backend:80 (10.8.2.3:8080)
Rules:
  Host         Path  Backends
  ----         ----  --------
  foo.bar.com
               /foo   service1:4200 (10.8.0.90:4200)
               /bar   service2:8080 (10.8.0.91:8080)
Annotations:
  nginx.ingress.kubernetes.io/rewrite-target:  /
Events:
  Type     Reason  Age                From                     Message
  ----     ------  ----               ----                     -------
  Normal   ADD     22s                loadbalancer-controller  default/test

下面是一个启用了TLS的Ingress:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: cafe-ingress
  annotations:
    nginx.org/sticky-cookie-services: "serviceName=coffee-svc srv_id expires=1h path=/coffee"
    nginx.com/jwt-realm: "Cafe App"  
    nginx.com/jwt-token: "$cookie_auth_token"
    nginx.com/jwt-key: "cafe-jwk" 
spec:
  tls:
  - hosts:
    - cafe.example.com
    secretName: cafe-secret
  rules:
  - host: cafe.example.com
    http:
      paths:
      - path: /tea
        backend:
          serviceName: tea-svc
          servicePort: 80
      - path: /coffee
        backend:
          serviceName: coffee-svc
          servicePort: 80

更多关于TLS的Ingress,请参考:https://mritd.me/2017/03/04/how-to-use-nginx-ingress/

参考文章

  • https://kubernetes.io/docs/concepts/services-networking/ingress/
  • https://mritd.me/2017/03/04/how-to-use-nginx-ingress/

你可能感兴趣的:(Kubernetes对象之Ingress)