ingress介绍

ingress是k8s提供的一种对外暴露服务的方式,它是全局的,为了代理不同后端Service而设置的负载均衡服务。

举个例子,假如我现在有这样一个站点:http://example.com,其中:
撸猫区:http://example.com/cat
撸狗区:http://example.com/dog
这两个系统,分别由名叫 cat 和 dog 这样两个 Deployment 来提供服务。

如何使用ingress来使得用户访问不同url时,能够访问到不同的Deployment?

ingress和ingress-controller

ingress和ingress-controller是两个概念

  • ingress:是k8s中的一个api对象,由yaml配置,作用是定义如何转发到service的规则,可以理解为转发规则的配置。
  • ingress-controller:具体实现负载均衡和反向代理的程序,对ingress规则进行解析,并根据规则进行转发。

上述例子,在 Kubernetes 里就需要通过 Ingress 对象来描述,如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: example-ing
spec:
rules:
- host: example.com
http:
paths:
- path: /cat
backend:
serviceName: cat-svc
servicePort: 80
- path: /dog
backend:
serviceName: dog-svc
servicePort: 80

上面的yaml文件中,最重要的rules字段,在 Kubernetes 里,这个字段叫作:IngressRule

rules下的host字段,必须是一个域名,而不能是ip地址。
host 字段定义的值,就是这个 Ingress 的入口。这意味着,当用户访问 example.com 的时候,实际上访问到的是这个 Ingress 对象,
这样就可以根据规则进行进一步转发。

而转发则依赖path字段,可以简单理解,每一个path对应一个service。

所谓 Ingress 对象,其实就是 Kubernetes 项目对“反向代理”的一种抽象。

有的Ingress对象后,接下来,需要部署一个Ingress Controller来提供对应的代理能力。
目前,业界常用的各种反向代理项目,比如 Nginx、HAProxy、Envoy、Traefik 等,都已经为 Kubernetes 专门维护了对应的 Ingress Controlle

部署nginx-ingress-controller

nginx提供的ingress controller,官方文档:https://docs.nginx.com/nginx-ingress-controller/overview/

这里采用helm来安装 NGINX Ingress Controller
helm的安装可以参考 Helm3的安装

  1. 添加Helm 仓库

    1
    2
    helm repo add nginx-stable https://helm.nginx.com/stable
    helm repo update
  2. 安装nginx-ingress

    1
    helm install nginx-ingress nginx-stable/nginx-ingress --set controller.hostNetwork=true

这里用到了一个参数controller.hostNetwork,设置成true,允许nginx-ingress的pod使用宿主机的网络命名空间(network namespace)

  1. 查看安装情况
    1
    2
    3
    4
    5
    6
    7
    root@codeeper:~# kubectl get deploy nginx-ingress-nginx-ingress
    NAME READY UP-TO-DATE AVAILABLE AGE
    nginx-ingress-nginx-ingress 1/1 1 1 13d
    root@codeeper:~#
    root@codeeper:~#
    root@codeeper:~# kubectl get pods | grep nginx
    nginx-ingress-nginx-ingress-5485cc6b-g8cr5 1/1 Running 0 13d

这样nginx-ingress-controller就部署完毕。

下面我们来使用一下

部署nginx

  1. 通过YAML文件创建一个Deployment

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: nginx-rc
    labels:
    app: nginx
    spec:
    selector:
    matchLabels:
    app: nginx
    replicas: 1
    template:
    metadata:
    labels:
    app: nginx
    spec:
    containers:
    - name: nginx
    image: registry.cn-shanghai.aliyuncs.com/lian_ns/nginx:1.19.2
    ports:
    - containerPort: 80
    1
    kubectl apply -f nginx-deployment.yaml

    查看deploy和pod

    1
    2
    3
    root@codeeper:~# kubectl get deploy,pod | grep nginx-rc
    deployment.apps/nginx-rc 1/1 1 1 14d
    pod/nginx-rc-74989f558d-5k884 1/1 Running 0 2d1h
  2. 创建service

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    apiVersion: v1
    kind: Service
    metadata:
    name: nginx-svc
    spec:
    ports:
    - port: 80
    targetPort: 80
    protocol: TCP
    name: http
    selector:
    app: nginx
    1
    kubectl apply -f nginx-service.yaml

    查看service

    1
    2
    root@codeeper:~# kubectl get svc | grep nginx-svc
    nginx-svc ClusterIP 10.98.15.89 <none> 80/TCP 3h4m
  3. 创建ingress

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
    name: nginx-ing
    annotations:
    kubernetes.io/ingress.class: "nginx"
    spec:
    rules:
    - host: test.codeeper.com
    http:
    paths:
    - path: /
    backend:
    serviceName: nginx-svc
    servicePort: 80

    这里的kubernetes.io/ingress.class: "nginx"是用来指定要使用的ingress-controller。nginx-ingress-controller默认的ingress class 是 nginx

    1
    kubectl apply -f nginx-ingress.yaml

    查看service

    1
    2
    root@codeeper:~/k8s_deploy# kubectl get ingress | grep nginx-ing
    nginx-ing <none> test.codeeper.com 80 14d

这里有一个地方可以注意一下,我们查看一下nginx-ingress的pod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
root@codeeper:~/k8s_deploy# kubectl get pod | grep nginx-ingress
nginx-ingress-nginx-ingress-5485cc6b-g8cr5 1/1 Running 0 14d

root@codeeper:~/k8s_deploy# kubectl exec -it nginx-ingress-nginx-ingress-5485cc6b-g8cr5 /bin/bash
nginx@codeeper:/$ cat /etc/nginx/conf.d/default-nginx-ing.conf
# configuration for default/nginx-ing

upstream default-nginx-ing-test.codeeper.com-nginx-svc-80 {
zone default-nginx-ing-test.codeeper.com-nginx-svc-80 256k;
random two least_conn;
server 192.168.94.116:80 max_fails=1 fail_timeout=10s max_conns=0;
}

server {
listen 80;
server_tokens on;
server_name test.codeeper.com;
location / {
proxy_http_version 1.1;
proxy_connect_timeout 60s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
client_max_body_size 1m;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering on;
proxy_pass http://default-nginx-ing-test.codeeper.com-nginx-svc-80;
}
}

进入容器,可以看到多了一个文件 default-nginx-ing.conf ,里面可以看到访问到 test.codeeper.com 域名的都代理到 default-nginx-ing-test.codeeper.com-nginx-svc-80这个服务上了,而这个正式我们上面定义的nginx-ingress

查看效果

在浏览器上访问页面,可以看到:

附件

nginx部署文件
https://github.com/dougaoyang/k8s_deploy