一 要理解一个概念,首先要明白它是干什么用的,然后再去理解它是怎么实现的。Ingress的作用就是提供一个集群外部访问集群内部的入口。那么它是怎么实现的呢,我们知道,集群内部的Cluster IP外部是无法直接访问到的,而在 K8s集群中,集群外部访问内部pod中的应用大概有以下几种形式:

 1.  通过开启proxy模式访问Cluster IP。这种方式要求我们运行 kubectl 作为一个未认证的用户,  
 因此我们不能用这种方式把服务暴露到 internet 或者在生产环境使用。
 2.  直接访问pod,pod中定义hostPort,并设置pod级别的hostwork=true,直接将pod中的端口映射  
 到pod所在的物理主机或者虚拟机上。通过访问主机ip:hostPort即可访问集群内部pod;这种方式只  
     非常少量使用,否则和直接使用docker没多大区别。
 3.  先访问Service,Service可以直接通过集群内部负载均衡至pod中的应用,而外部访问集群中的    
 Service可以通过在Service中定义NodePort实现;这种方式在集群中的每台主机上开放一个随机的  
指定的端口,且每个端口只能提供一个服务,它是通过端口不同来区分不同应用,而不是通过域名,  
管理不便,不适合在大规模集群中部署。
 4.   通过LoadBlancer Service访问Service,这个需要接入云服务,每个服务都会由云服务提供一个  
 IP作为入口,转发相应的流量,但每个LoadBlancer Service都会产生费用,成本比较高。
 5.   Ingress,K8s中的API对象,定义了一组规则。Ingress本身只是定义了一组规则,需要配合  
 Ingress controllor才有意义,不理解Ingress controllor没关系,继续往下。

  二 如果不通过Ingress,我们也可以手动在Service前部署一个反向代理,比如nginx或者haproxy。

  1. nginx运行在集群中,所以可以访问到集群内部的Service,只需在nginx配置中proxy_pass指向相应  
  的Service Cluster IP或者dns即可,多一个服务也就是多配置一个nginx中的虚拟机主机。
  2. 通过设置hostPort即可从外部访问nginx,再通过nginx反向代理至后端应用的Service;或者不通过  
  hostPort,再在nginx前端再加一个Service,通过设置Service的NodePort来访问nginx。

  三 通过自己部署nginx反向代理这种方式好像就OK了啊,那一直说的Ingress又是什么?

         Ingress是K8s中的API对象,定义了一组规则,对应于nginx(或者haproxy,traefik等)的一  
    段配置,可以近似成一段虚拟主机的配置,其实Ingress和自己部署反向代理思路都是一样的,只  
    不过自己部署反向代理时,如果新增加一个服务,你自己需要去增加nginx中的配置并重新加载配  
    置,而在Ingress中你增加一个服务,你需要增加一个Ingress的配置并运行,Ingress会自己去请求  
    K8s的api以获得新增应用的nds或者Cluster Ip,然后将你写的Ingress规则转换成nginx配置,并修改  
    到ngixn中,然后自动reload nginx。
            简单来说,两者的区别就是:当新增后端应用时,一种需要增加nginx配置,另外一种需要增  
    加Ingress规则。你可以简单的把Ingress理解为一段类似nginx虚拟主机的配置,因为它会自动为  
    转换。

四 说道这里,部署Ingress就很简单了,不过在Ingress中有它自己的一些术语。一个完整的Ingress有以下几个组件:

    1.  反向代理,可以是nginx、traefik、Haproxy等。
    2.  Ingress controllor,即Ingress控制器,监听apiserver,获取服务新增,删除等变化,并结合  
    ingress规则动态更新到反向代理负载均衡器上,并重载配置使其生效。
    3.  Ingress,K8s的一个资源对象,定义了一组规则,你可以简单理解为一段对应nginx虚拟机主  
    机的配置。而实际上,Ingress controllor和反向代理,也就是上面的1,2两个组件,都是结合在一  
    起的。比如traefik,它同时具备反向代理和Ingress controllor的功能;如果使用nginx,那么你  
    需要部署专用的nginx,它也集成了Ingress   controllor。  
    4 .本文采用traefik来部署反向代理和Ingress controllor,有关traefik的详细介绍可以参考官网。

五 实际部署。

1. 如果K8s使用了rbac,而Ingress controllor需要访问apiserver,所以需要先为traefik配置一个  
Service Account。
cat > traefik-ingress-rbac.yaml << EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  name: traefik-ingress
  namespace: kube-system
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: traefik-ingress
subjects:
  - kind: ServiceAccount
    name: traefik-ingress
    namespace: kube-system
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io
EOF
kubectl apply -f traefik-ingress-rbac.yaml
        第一段配置定义了一个Service Account,第二段配置将定义的Service Account绑定到  
cluster-admin这个已经存在的ClusterRole上,cluster-admin是具有访问apiserver的权限的。 

2. 然后需要部署一个traefik,并且将它暴露到集群外,它既是反向代理也是Ingress controllor。
cat > traefik-ingress-controller.yaml << EOF
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: traefik-ingress-controller
  namespace: kube-system
  labels:
    k8s-app: traefik-ingress-lb
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: traefik-ingress-lb
  template:
    metadata:
      labels:
        k8s-app: traefik-ingress-lb
        name: traefik-ingress-lb
    spec:
      terminationGracePeriodSeconds: 60
      serviceAccountName: traefik-ingress
      containers:
      - image: traefik
        name: traefik-ingress-lb
        resources:
          limits:
            cpu: 200m
            memory: 30Mi
          requests:
            cpu: 100m
            memory: 20Mi
        ports:
        - containerPort: 80
          hostPort: 80
        - containerPort: 8080
        args:
        - --web
        - --kubernetes
EOF
kubectl apply -f traefik-ingress-controller.yaml
       这是traefik官方文档的部署文件,我只是在它里面加了个Service Account,可以看到,它采用设置  
pod的hostPort方式来将80端口暴露到集群外,80端口可以看做是反向代理http的端口,接收并转发所  
有的定义到Ingress的流量。而它在pod中还对集群内部有一个8080端口,8080端口一个后端应用,提  
供了traefik-web-ui。8080端口是traefik默认的webUI端口,8080端口定义为Pod的端口,集群外部是无  
法直接访问到的,所以我们还需要部署一个Service+Ingress。  

3. 部署Service+Ingress
cat > traefik-web-ui.yaml << EOF
apiVersion: v1
kind: Service
metadata:
  name: traefik-web-ui
  namespace: kube-system
spec:
  selector:
    k8s-app: traefik-ingress-lb
  ports:
  - port: 80
    targetPort: 8080
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: traefik-web-ui
  namespace: kube-system
spec:
  rules:
  - host: traefik-ui.com
    http:
      paths:
      - backend:
          serviceName: traefik-web-ui
          servicePort: 80
EOF
kubectl apply -f  traefik-web-ui.yaml
       当你真正要访问该traefik-ui.com时,你还需要将这个域名绑定到它对应的IP地址,也就是  
 hostPort所在的主机的IP。配置好hosts文件后,访问traefik-ui.com。OK

       1. 可以看到Ingress中,当访问traefik-ui.com这个域名时,对应会访问到名为traefik-web-ui的  
Service的80端口中。而Service的80端口对应后端的traefik web UI的8080端口。到此为止,一个  
完整的Ingress就部署完成了,它的访问流程是这样的:
       集群外部访问traefik-ui.com-->请求会到达traefik所在的主机的IP:hostPort上,也就是IP:80-->  
由于Ingress规则此时被转换成traefik中的反向代理配置,根据Ingress规则会被转发往traefik-web-ui  
这个Service:80上-->Service转发到后端标签为 traefik-ingress-lb的pod的8080端口中,实际上又  
回到了traefik,不过是8080端口。
       简单来说:请求域名---->traefik:80---->Ingress(只是Ingerss规则,实际还是由traefik完成)  
---->后端Service:80---->traefik:8080

      2. 部署其他后端服务时也是一样,把上面的后端Service和应用换成相应的就行了。比如部署一个  
tomcat,那么需要再部署3个K8s资源,分别是tomcat-deployment.yaml、tomcat-service.yaml、  
tomcat-Ingress.yaml,你请求的域名为Ingress中的host配置的域名,你请求流程为:
请求域名---->traefik:80---->Ingress(只是Ingerss规则,实际还是由traefik完成)---->  
tomcat-Service---->tomcat-deployment中的Pod。

      3. 上面是通过hostPort暴露traefik,可以直接访问80端口,如果需要在多台node上部署,可以通  
过给相应的node 设置lable,然后部署时指定nodeSelector。
      我们同样可以通过Service的NodePort暴露traefik,需要在traefik前再加一个Service,默认  
NodePort端口范围为30000-32767,如果想直接暴露80端口,需要修改apiserver的启动参数配置,  
tomcat采用该方式的请求流程为:
      请求---->traefik-service的Nodeport---->traefik---->Ingress(只是Ingerss规则,实际还是由  
traefik  完成)---->tomcat-Service---->tomcat-deployment中的Pod。