k8s篇-网络-Ingress对象详解

一、什么是Ingress

为什么需要 Ingress:

Ingress 也是为了解决在集群之外,访问集群内部Service服务的问题。

实际上,将service的type设置为nodePort或LoadBalancer,也能实现将集群内部的服务暴露给外部访问。那Ingress岂不是多余的?肯定不是。

先回顾下,LoadBalancer类型的Service访问流程,如下:

                                      .————————————————————————————————————————————————
                                      |  集群内部                        .-------> Pod  |
                                      |                                /               |
集群外部(用户) ----> LoadBalancer -----+--> node_ip:nodePort ----> Service              |
                                      |                                \               |
                                      |                                 '-------> Pod  |
                                      |                                                |
                                      '————————————————————————————————————————————————

LoadBalancer 类型的 Service 一般应用于云平台环境中,这个LoadBalancer是由云厂商提供的,位于k8s集群外部,当用户在云平台上创建一个该类型的Service时,同时会为该 Service 创建一个对应的负载均衡器。可以发现,每个 Service 都要有一个负载均衡器,这种做法实际上是成本比较高的。

Ingress除了能将集群内部的服务暴露给外界访问,它也是一个负载均衡器,专门是为集群内部的Service提供负载均衡服务

Ingress 与 LoadBalancer 类型的 Service 有点类似,但区别在于,Ingress是一个k8s集群内部的全局的负载均衡器,作为k8s集群中的一个对象资源而存在,而LoadBalancer类型则是一个集群外部的负载均衡服务器。

Ingress 工作原理:

Ingress,是K8s的一个资源对象,定义了一系列路由转发规则(或反向代理规则)。它规定了外部进来的HTTP/HTTPS请求,应该被转发到哪个Service上。

具体说,Ingress就是一段nginx服务的反向代理配置,它能根据请求中不同的Host和URL路径,将请求转发到不同的Service所对应的后端Pod上。

Ingress Controller相当于是一个反向代理程序,负责解析Ingress的反向代理规则,并实时感知Ingress转发规则的变化。一旦Ingress规则有变化,Ingress Controller会及时更新自己相应的转发规则,并根据这些规则,将接收到的请求转发到对应的Service。

Ingress Controller是通过API Server获取Ingress资源的变化,并动态地生成Load Balancer(如Nginx程序)所需的配置文件(如nginx.conf),然后重新加载Load Balancer(如执行nginx -s load重新加载Nginx)来生成新的路由转发规则。

Ingress与手动部署反向代理服务器的思路是一样的。如果反向代理服务器使用的是Nginx程序,Ingress Controller 会将 Ingress 规则变化生成一段Nginx的配置,然后将这个配置写到Ingress Controller管理下的Nginx Pod中,然后reload。

二、安装 Nginx Ingress

部署 Ingress :

Ingress组件需要提前部署到k8s集群中,它包括 Ingress Service 与 Ingress Controller,以及Ingress Controller管理下的两个Nginx Pod。反向代理服务器有Nginx、Apache、traefik等,这里选择用Nginx。

官网部署手册:https://github.com/kubernetes/ingress-nginx/blob/main/docs/deploy/index.md

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.3.1/deploy/static/provider/cloud/deploy.yaml

当部署好后,在环境中能看到有一个Ingress Service、Ingress Controller、Nginx Pod,如下:

查看Ingress Service:

# 该Service用的是LoadBalancer方式对外暴露服务(也可以用nodePort方式)
$ kubectl -n kube-system get svc nginx-ingress-lb
NAME               TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
nginx-ingress-lb   LoadBalancer   172.17.216.4   10.10.33.4    80:31366/TCP,443:30489/TCP   487d

$ kubectl -n kube-system describe svc nginx-ingress-lb
Name:                     nginx-ingress-lb
Namespace:                kube-system
Labels:                   app=nginx-ingress-lb
Annotations:              .....
Selector:                 app=ingress-nginx
Type:                     LoadBalancer
IP:                       172.17.216.4
LoadBalancer Ingress:     10.10.33.4
Port:                     http  80/TCP
TargetPort:               80/TCP
NodePort:                 http  31366/TCP
Endpoints:                172.16.1.130:80,172.16.1.131:80
Port:                     https  443/TCP
TargetPort:               443/TCP
NodePort:                 https  30489/TCP
Endpoints:                172.16.1.130:443,172.16.1.131:443
Session Affinity:         None
External Traffic Policy:  Local
HealthCheck NodePort:     30135
Events:                   <none>

查看Ingress Controller:

$ kubectl -n kube-system get deploy nginx-ingress-controller
NAME                       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-ingress-controller   2         2         2            2           487d

查看Ingress Controller下的两个Nginx Pod:

$ kubectl -n kube-system get pods -owide  -l app=ingress-nginx
NAME                                        READY   STATUS    RESTARTS   AGE    IP             NODE                                
nginx-ingress-controller-787644849b-nmsbm   1/1     Running   0          487d   172.16.1.130   node1
nginx-ingress-controller-787644849b-tn7bq   1/1     Running   0          487d   172.16.1.131   node1

Ingress 使用:

Ingress能将来自于不同域名的请求转发到不同的Service上,也可以将同一个域名下的请求,根据不同URI接口转发到不同的Service上。

Ingress对象字段说明:

spec:
    backend: 全局默认后端。若不匹配任何规则的请求,都会代理到默认后端
        serviceName: service的名称。要将请求代理到哪个Service上
        servicePort: service的端口
    rules: 定义入站流量的转发规则
        host: 第一条规则,检查入站流量是否匹配此处定义的域名
        http:
            paths:
                path: 第二条规则,检查入站流量的URI路径,是否匹配此处定义的path(省略即为"/")
                backend: 自定义后端。所有入站流量都会先匹配host与path规则,当两个都匹配时,才会将流量代理到下面定义的service上,否则会发送到默认backend
                    serviceName:
                    servicePort:
    tls: 配置HTTPS

示例1:根据不同域名转发到不同的service上

1)先创建两个service,分别是my-service-1和my-service-2。

my-service-1:

apiVersion: v1
kind: Service
metadata:
  name: my-service-1
  namespace: default
spec:
  selector:
    app: my-nginx-web1
  ports:
  - name: nginx
    port: 80
    targetPort: 80
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx-deploy
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-nginx-web1
  template:
    metadata:
      labels:
        app: my-nginx-web1
    spec:
      containers:
      - name: nginx-web1
        image: nginx:1.7.9
        ports:
        - name: http
          containerPort: 80

my-service-2:

apiVersion: v1
kind: Service
metadata:
  name: my-service-2
  namespace: default
spec:
  selector:
    app: my-nginx-web2
  ports:
  - name: nginx
    port: 8080
    targetPort: 80
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx-deploy-2
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-nginx-web2
  template:
    metadata:
      labels:
        app: my-nginx-web2
    spec:
      containers:
      - name: nginx-web2
        image: nginx:1.7.9
        ports:
        - name: http
          containerPort: 80

2)创建一个Ingress规则,根据不同域名转发到不同的service上

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-demo-0915
  namespace: default
spec:
  rules:
    - host: my.test.com                    #将来自于my.test.com域名的请求代理到my-service-1上
      http:
        paths:
          - backend:
              serviceName: my-service-1
              servicePort: 80
    - host: a.test.com                     #将来自于a.test.com域名的请求代理到my-service-2上
      http:
        paths:
          - backend:
              serviceName: my-service-2
              servicePort: 8080

3)查看service与pod信息

#查看两个service
$ kubectl get svc -o wide
NAME           TYPE        CLUSTER-IP     	EXTERNAL-IP   PORT(S)    AGE   SELECTOR
my-service-1   ClusterIP   172.17.171.2   	<none>        80/TCP     35m   app=my-nginx-web1
my-service-2   ClusterIP   172.17.101.107   <none>        8080/TCP   59m   app=my-nginx-web2

$ kubectl describe svc my-service-1
Name:              my-service-1
Namespace:         default
Labels:            <none>
Annotations:       ...
Selector:          app=my-nginx-web1
Type:              ClusterIP
IP:                172.17.171.2
Port:              nginx  8080/TCP
TargetPort:        80/TCP
Endpoints:         172.16.1.150:80,172.16.2.156:80
Session Affinity:  None
Events:            <none>

$ kubectl describe svc my-service-2
Name:              my-service-2
Namespace:         default
Labels:            <none>
Annotations:       ...
Selector:          app=my-nginx-web2
Type:              ClusterIP
IP:                172.17.101.107
Port:              nginx  8080/TCP
TargetPort:        80/TCP
Endpoints:         172.16.1.151:80
Session Affinity:  None
Events:            <none>

#查看service的Pod
$ kubectl get pods -o wide
NAME                                  READY   STATUS    RESTARTS   AGE    IP              NODE    NOMINATED NODE
my-nginx-deploy-6fb9f56545-8k4mk      1/1     Running   0          87s    172.16.2.156    node1   <none>
my-nginx-deploy-6fb9f56545-c7gcx      1/1     Running   0          87s    172.16.1.150    node2   <none>
my-nginx-deploy-2-7f47d46589-mnpbl    1/1     Running   0          67m    172.16.1.151    node2   <none>

查看Ingress信息:

# 查看ingress
$ kubectl get ingress ingress-demo-0915
NAME                HOSTS                    ADDRESS      PORTS   AGE
ingress-demo-0915   my.test.com,a.test.com   10.10.33.4   80      3h14m

$ kubectl describe ingress ingress-demo-0915
Name:             ingress-demo-0915
Namespace:        default
Address:          10.10.33.4
Default backend:  default-http-backend:80 (<none>)
Rules:
  Host         Path  Backends
  ----         ----  --------
  my.test.com
                  my-service-1:80 (<none>)
  a.test.com
                  my-service-2:8080 (<none>)
Annotations:
  nginx.ingress.kubernetes.io/service-weight:        my-service-1: 100, my-service-2: 100
  ....
Events:  <none>

4)访问测试

因为我这里的Ingress Service使用的是LoadBalancer类型,所以需要通过LoadBalancer的IP访问Ingress,这个要先在本地/etc/hosts文件中绑定好域名解析后再访问。

$ echo '10.10.33.4 a.test.com my.test.com' >> /etc/hosts
$ curl a.test.com
$ curl my.test.com

示例2:根据同一个域名的不同请求接口转发到不同的service上

Ingress的yaml如下:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/service-weight: 'my-service-1: 100, my-service-2: 100'
  name: ingress-demo-0915-2
  namespace: default
spec:
  rules:
    - host: b.test.com
      http:
        paths:
          - backend:
              serviceName: my-service-1
              servicePort: 80
            path: /web1
          - backend:
              serviceName: my-service-2
              servicePort: 8080
            path: /web2

查看Ingress信息:

$ kubectl get ingress ingress-demo-0915-2
NAME                  HOSTS        ADDRESS      PORTS   AGE
ingress-demo-0915-2   b.test.com   10.10.33.4   80      70m

$ kubectl describe ingress ingress-demo-0915-2
Name:             ingress-demo-0915-2
Namespace:        default
Address:          10.10.33.4
Default backend:  default-http-backend:80 (<none>)
Rules:
  Host        Path  Backends
  ----        ----  --------
  b.test.com
              /web1   my-service-1:80 (<none>)
              /web2   my-service-2:8080 (<none>)
Annotations:
  nginx.ingress.kubernetes.io/service-weight:  my-service-2: 100, my-service-1: 100
Events:
  Type    Reason  Age                From                      Message
  ----    ------  ----               ----                      -------
  Normal  UPDATE  53m (x8 over 71m)  nginx-ingress-controller  Ingress default/ingress-demo-0915-2
  Normal  UPDATE  53m (x8 over 71m)  nginx-ingress-controller  Ingress default/ingress-demo-0915-2

访问测试:

因为我这里的Ingress Service使用的是LoadBalancer类型,所以需要通过LoadBalancer的IP访问Ingress,这个要先在本地/etc/hosts文件中绑定好域名解析后再访问。

$ echo '10.10.33.4 b.test.com' >> /etc/hosts
$ curl b.test.com/web1
$ curl b.test.com/web2

示例3:配置HTTPS

1、登录master节点, 创建私钥(tls.key)和证书(tls.crt)

$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/O=DevOps/CN=my.test.com"

2、创建一个Secret

$ kubectl create secret tls my-ingress-secret --cert=tls.crt --key=tls.key

$ kubectl get secret my-ingress-secret
NAME                TYPE                DATA   AGE
my-ingress-secret   kubernetes.io/tls   2      13s

$ kubectl describe secret my-ingress-secret
Name:         my-ingress-secret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  kubernetes.io/tls

Data
====
tls.crt:  1302 bytes
tls.key:  1679 bytes

3、创建Deployment和Service

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-web1
  labels:
    app: test-web1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test-web1
  template:
    metadata:
      labels:
        app: test-web1
    spec:
      containers:
      - name: test-web1
        image: nginx:1.7.9
        ports:
        - containerPort: 8080
--- 
apiVersion: v1
kind: Service
metadata:
  name: web1-service
spec:
  type: ClusterIP
  selector:
    app: test-web1
  ports:
    - port: 8080
      targetPort: 8080

4、创建一个ingress,并配置tls

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress-tls
  namespace: default
spec:
  tls:
  - hosts:
    - my.test.com
    secretName: my-ingress-secret
  rules:
  - host: my.test.com
    http:
      paths:
        - path:
          backend:
            serviceName: web1-service
            servicePort: 8080

查看ingress

$ kubectl get ingress my-ingress-tls
NAME             HOSTS         ADDRESS      PORTS     AGE
my-ingress-tls   my.test.com   10.10.33.4   80, 443   53s

$ kubectl describe ingress my-ingress-tls
Name:             my-ingress-tls
Namespace:        default
Address:          10.10.33.4
Default backend:  default-http-backend:80 (<none>)
TLS:
  my-ingress-secret terminates my.test.com
Rules:
  Host         Path  Backends
  ----         ----  --------
  my.test.com
                  web1-service:8080 (<none>)
Annotations:
.....

 5、用https协议访问测试

$ curl https://my.test.com

  • 0
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值