k8s从入门到实战(九):Ingress介绍与使用

3,536 阅读4分钟

ingress翻译过来是入口的意思,k8s希望ingress是整个集群流量的入口,引入ingress后整个请求如下图所示 image.png

为什么需要Ingress资源

由于K8S集群拥有强大的副本控制能力,Pod随时可能从一个节点上被驱逐到另一个节点上,或者直接销毁再来一个新的。

然而伴随着Pod的销毁和重生,Pod的IP等信息不断地在改变,此时使用K8S提供的Service机制可以解决这一问题,Service通过标签选定指定的Pod作为后端服务,并监听这些Pod的变化。

在对外暴露服务时,使用Service的NodePort是一个方法,但还会有以下几个问题

问题1 - 如何管理端口

当需要对外暴露的服务量比较多的时候,端口管理的问题便会暴露出来。并且service只支持4层代理,也就是只能根据ip+端口

此时的一个处理方案是使用一个代理服务(例如Nginx)根据请求信息将请求转发到不同的服务上去。

问题2 - 如何管理转发配置

每当有新服务加入,都需要对该服务的配置进行修改、升级,在服务数量逐渐变多后,该配置项目会变得越来越大,手工修改的风险也会逐渐增高。

那么需要一个工具来简化这一过程,希望可以通过简单的配置动态生成代理中复杂的配置,最好还可以顺手重新加载配置文件。

K8S刚好也提供了此类型资源。

安装ingress

默认k8s是不带ingress的,需要我们单独安装

下载安装文件

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.47.0/deploy/static/provider/baremetal/deploy.yaml

执行安装操作

kubectl apply -f deploy.yaml

查看安装的结果

kubectl get pod,svc -n ingress-nginx

因为ingress要接所有的请求流量,安装完还会产生一个NodePort类型的service,http(32083)、https(32099)

NAME                                            READY   STATUS      RESTARTS   AGE
pod/ingress-nginx-admission-create-xjcds        0/1     Completed   0          45s
pod/ingress-nginx-admission-patch-n929x         0/1     Completed   0          45s
pod/ingress-nginx-controller-65bf56f7fc-zf7t5   0/1     Running     0          45s

NAME                                         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
service/ingress-nginx-controller             NodePort    10.1.221.227   <none>        80:32083/TCP,443:32099/TCP   45s
service/ingress-nginx-controller-admission   ClusterIP   10.1.157.154   <none>        443/TCP                      45s

尝试访问下32083端口

image.png

因为是NodePort,所以你可以访问你k8s集群内任意一台服务的端口

域名访问

首先我们准备一段yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-server
spec:
  replicas: 2
  selector:
    matchLabels:
      app: hello-server
  template:
    metadata:
      labels:
        app: hello-server
    spec:
      containers:
      - name: hello-server
        image: registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/hello-server
        ports:
        - containerPort: 9000
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-demo
  name: nginx-demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-demo
  template:
    metadata:
      labels:
        app: nginx-demo
    spec:
      containers:
      - image: nginx
        name: nginx
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx-demo
  name: nginx-demo
spec:
  selector:
    app: nginx-demo
  ports:
  - port: 8000
    protocol: TCP
    targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: hello-server
  name: hello-server
spec:
  selector:
    app: hello-server
  ports:
  - port: 8000
    protocol: TCP
    targetPort: 9000

配置一个ingress,当我使用hello.com交给hello-server处理,使用demo.com交给nginx处理

apiVersion: networking.k8s.io/v1
kind: Ingress  
metadata:
  name: ingress-host-bar
spec:
  ingressClassName: nginx
  rules:
  - host: "hello.com"
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: hello-server
            port:
              number: 8000
  - host: "demo.com"
    http:
      paths:
      - pathType: Prefix
        path: "/nginx"  # 把请求会转给下面的服务,下面的服务一定要能处理这个路径,不能处理就是404
        backend:
          service:
            name: nginx-demo  ## java,比如使用路径重写,去掉前缀nginx
            port:
              number: 8000

执行上面文件

kubectl apply -f ing-rule.yaml

查看是否成功

[root@k8s-master opt]# kubectl get ing
NAME               CLASS   HOSTS                ADDRESS        PORTS   AGE
ingress-host-bar   nginx   hello.com,demo.com   172.16.55.77   80      38s

可以看到这边匹配到了hello.com,demo.com两个域名

现在修改下我本地的host来解析这两个域名

101.37.160.113 hello.com
101.37.160.113 demo.com

这时候我们访问是需要带上之前的端口的

service/ingress-nginx-controller             NodePort    10.1.221.227   <none>        80:32083/TCP,443:32099/TCP   45s

也就是可以使用hello.com32083 或者 hello.com:32099,另一个域名也是

路径重写

配置如下

在metadata里面加入了annotations(注解)

apiVersion: networking.k8s.io/v1
kind: Ingress  
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
  name: ingress-host-bar
spec:
  ingressClassName: nginx
  rules:
  - host: "hello.com"
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: hello-server
            port:
              number: 8000
  - host: "demo.com"
    http:
      paths:
      - pathType: Prefix
        path: "/nginx(/|$)(.*)"  # 把请求会转给下面的服务,下面的服务一定要能处理这个路径,不能处理就是404
        backend:
          service:
            name: nginx-demo  ## java,比如使用路径重写,去掉前缀nginx
            port:
              number: 8000
流量限制
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-limit-rate
  annotations:
    nginx.ingress.kubernetes.io/limit-rps: "1"
spec:
  ingressClassName: nginx
  rules:
  - host: "haha.atguigu.com"
    http:
      paths:
      - pathType: Exact
        path: "/"
        backend:
          service:
            name: nginx-demo
            port:
              number: 8000