Kubernetes学习之Ingress

一、认识Ingress
  Kubernetes提供了两种内建的负载均衡机制(cloud load balancing)用于发布公共应用,一种是工作于传输层的Service资源,它实现的是"TCP负载均衡器",另一种是Ingress资源,它实现的是"HTTP(S)负载均衡器"。
  Kubernetes中,Service资源和Pod资源的IP地址仅能用于集群网络内部的通信,所有的网络流量都无法穿透边界路由器(Edge Router)以实现集群内外通信。尽管可以为Service使用NodePort或者LoadBalancer类型通过节点引入外部流量,但它依然是四层流量转发,可用的负载均衡器也为传输层负载均衡机制。
  Ingress是Kubernetes API标准资源类型之一,它其实就是一组基于DNS名称(host)或URL路径把请求转发至指定的Service资源的规则,用于将集群外部的请求流量转发至集群内部完成服务发布。然而,Ingress资源自身并不能进行"流量穿透",它仅仅是一组路由规则的集合,这些规则要想真正发挥作用还需要其他功能的辅助,如监听某套接字,然后根据这些规则的匹配机制路由请求流量。这种能够为Ingress资源监听套接字并转发流量的组件被称为Ingress控制器(Ingress Controller)。
  Ingress控制器可以由任何具有反向代理(HTTP/HTTPS)功能的服务程序实现,如Nginx、Envoy、HAProxy、Vulcand和Traefik等等。Ingress控制器自身也是运行于集群中的Pod资源对象,它与被代理的运行为Pod资源的应用运行于同一网络中。
  Kubernetes学习之Ingress_第1张图片
  另一方面,使用Ingress资源进行流量分发时,Ingress控制器可基于某Ingress资源定义的规则将客户端请求流量直接转发至与Service对于的后端Pod资源之上,这种转发机制会绕过Service资源,从而省去了由kube-proxy实现的端口代理开销。Ingress规则需要由一个Service资源对象辅助识别相关的所有Pod对象,但是ingress-nginx控制器可经由api.linux.io规则的定义直接将请求流量调度至pod3或pod4,而无须经由Servcie对象API的再次转发,WAP相关规则的作用方式与此类同。

二、创建Ingress资源
  Ingress资源是基于HTTP虚拟主机或URL来转发规则,它在配置资源清单的spec字段中嵌套了rules、backend和tls等字段进行定义。Ingress Spec中的字段是定义Ingress资源的核心组成部分,它主要嵌套如下三个字段:
  rules:用于定义当前Ingress资源的转发规则列表;未由rules定义的规则,或者没有匹配到的任何规则时,所有流量都会转发到由backend定义的默认后端Servcie上。
  backend:默认的后端用于服务那些没有匹配到任何规则的请求;定义Ingress资源时,至少应该定义backend或者rules规则两者之一;此字段用于让负载均衡器指定一个全局默认的后端。
  tls:TLS配置,目前仅仅支持通过默认端口443提供服务;如果要配置指定的列表成员指向了不同的主机,则必须通过SNI TLS扩展机制来支持此功能。

1)编写Ingress的yaml文件

]# cat ingress.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: www.ilinux.io
    http:
      paths:
      - backend:
          serviceName: myapp-svc
          servicePort: 80

]# kubectl apply -f ingress.yaml 
ingress.extensions/my-ingress created

2)查看Ingress资源

]# kubectl get ingress -o wide 
NAME         CLASS    HOSTS           ADDRESS   PORTS   AGE
my-ingress   <none>   www.ilinux.io             80      8s

]# kubectl describe ingress my-ingress
Name:             my-ingress
Namespace:        default
Address:          
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
  Host           Path  Backends
  ----           ----  --------
  www.ilinux.io  
                    myapp-svc:80 (10.244.1.86:80,10.244.2.54:80)
Annotations:     kubernetes.io/ingress.class: nginx
Events:          <none>

三、Ingress资源类型
  基于HTTP暴露的每个Servcie资源均可发布于一个独立的FQDN主机名之上,如"www.linux.io";也可以发布于某主机的URL路径之上,从而将它们整合到同一个Web站点,如"www.linux.io/grafana"。至于是否需要发布为HTTPS类型的应用则取决于用户的业务需求。

1)单Servcie资源型Ingress
  暴露单个服务的方法有很多种,如服务类型中的NodePort、LoadBalancer等,不过一样可以考虑使用Ingress资源来暴露服务,此时只需要为Ingress制定"default backend"即可。

]# cat ingress.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  backend:
    serviceName: my-svc
    servicePort: 80

]# kubectl apply -f ingress.yaml 
ingress.extensions/my-ingress created

]# kubectl describe ingress my-ingress
Name:             my-ingress
Namespace:        default
Address:          
Default backend:  my-svc:80 (10.244.1.87:80,10.244.2.55:80)
Rules:
  Host        Path     Backends
  ----        ----     --------
  *           *        my-svc:80 (10.244.1.87:80,10.244.2.55:80)
Annotations:  Events:  <none>

2)基于URL路径进行流量分发
  Ingress可以通过对不同的URL路径请求,转发至不同的后端Service上;例如,它将对www.iolinux.io/api的请求统统转发至API Servcie资源,将对www.ilinux.io/wap的请求转发至WAP Servcie资源。

]# cat url-ingress.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test
  annotations:
    ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: www.ilinux.io
    http: 
      paths:
      - path: /wap
        backend:
          serviceName: wap
          servicePort: 80
      - path: /api
        backend:
          serviceName: api
          servicePort: 80

]# kubectl apply -f url-ingress.yaml 
ingress.extensions/test created

]# kubectl describe ingress test
Name:             test
Namespace:        default
Address:          
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
  Host           Path  Backends
  ----           ----  --------
  www.ilinux.io  
                 /wap   wap:80 (10.244.1.88:80,10.244.2.56:80)
                 /api   api:80 (10.244.1.88:80,10.244.2.56:80)
Annotations:     ingress.kubernetes.io/rewrite-target: /
Events:          <none>

3)基于主机名称的虚拟主机
  Ingress还可以将每个应用分别以独立的FQDN主机名进行输出;实现将不同的主机名关联到不同的Service资源之上;这种实现方案其实就是Web站点部署中的"基于主机名的虚拟主机",将多个FQDN解析至同一个IP地址,然后根据"主机头(Host header)"进行转发。

]# cat fqdn-ingress.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test
spec:
  rules:
  - host: api.ik8s.io
    http:
      paths:
      - backend:
          serviceName: api
          servicePort: 80 
  - host: wap.ik8s.io
    http:
      paths:
      - backend:
          serviceName: wap
          servicePort: 80 

]# kubectl apply -f fqdn-ingress.yaml 
ingress.extensions/test created

]# kubectl get ingress -o wide 
NAME   CLASS    HOSTS                     ADDRESS   PORTS   AGE
test   <none>   api.ik8s.io,wap.ik8s.io             80      10s

]# kubectl describe ingress test 
Name:             test
Namespace:        default
Address:          
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
  Host         Path  Backends
  ----         ----  --------
  api.ik8s.io  
                  api:80 (10.244.1.88:80,10.244.2.56:80)
  wap.ik8s.io  
                        wap:80 (10.244.1.88:80,10.244.2.56:80)
Annotations:   Events:  <none>

4)TLS类型的Ingress资源
  这种类似于以HTTPS发布的Servcie资源,基于一个含有私钥和证书的Secret对象即可配置TLS协议的Ingress资源,目前来说,Ingress仅支持单TLS端口,并且还会卸载TLS会话。在Ingress资源中引用此Secret即可让Ingress控制器加载并配置为HTTPS服务。

]# cat tls-ingress.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: no-rules-map
spec:
  tls:
  - secretName: ikubernetessecret
  backend:
      serviceName: homesite
      servicePort: 80

]# kubectl apply -f tls-ingress.yaml 
ingress.extensions/no-rules-map created

]# kubectl get  ingress -o wide 
NAME           CLASS    HOSTS   ADDRESS   PORTS     AGE
no-rules-map   <none>   *                 80, 443   25s

]# kubectl describe ingress no-rules-map 
Name:             no-rules-map
Namespace:        default
Address:          
Default backend:  homesite:80 (10.244.1.89:80,10.244.2.57:80)
TLS:
  ikubernetessecret terminates 
Rules:
  Host        Path     Backends
  ----        ----     --------
  *           *        homesite:80 (10.244.1.89:80,10.244.2.57:80)
Annotations:  Events:  <none>

四、Ingress控制器
  Ingress控制器自身是运行于Pod中的容器应用,一般是Nginx或者Envoy一类具有代理及负载均衡功能的守护进程,它监视着来自API Server的Ingress对象的状态,并对其规则生成相应的应用程序专有格式的配置文件并通过重载或重启守护进程而使新配置生效。例如,对于Nginx来说,Ingress规则需要转换为Nginx的配置信息。简单来说,Ingress控制器其实就是托管于Kubernetes系统之上的用于实现在应用层发布服务的Pod资源,它将跟踪Ingress资源并实时生成配置规则。Ingress接入外部的请求流量方式一般有如下两种:
  以Deployment控制器管理Ingress控制器的Pod资源,并通过NodePort或者LoadBalancer类型的Service对象为其接入集群外部的请求流量,这就意味着,定义一个Ingress控制器时,必须在其前端定义一个专用的Service资源。
   Kubernetes学习之Ingress_第2张图片
   借助于DaemonSet控制器,将Ingress控制器的Pod资源各自以单一实例的方式运行于集群的所有或者部分工作节点之上,并配置这类Pod对象以hostPort的方式在当前节点接入外部流量。
   Kubernetes学习之Ingress_第3张图片

1)创建Ingress-Controller

Ingress-Controller控制器yaml文件地址

]# kubectl apply -f mandatory.yaml 
namespace/ingress-nginx unchanged
configmap/nginx-configuration unchanged
configmap/tcp-services unchanged
configmap/udp-services unchanged
serviceaccount/nginx-ingress-serviceaccount unchanged
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole unchanged
role.rbac.authorization.k8s.io/nginx-ingress-role unchanged
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding unchanged
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding unchanged
deployment.apps/nginx-ingress-controller unchanged
limitrange/ingress-nginx configured

2)查看Ingress-Controller

]# kubectl get pods -n ingress-nginx -o wide 
NAME                                        READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
nginx-ingress-controller-5b6fcd5bcd-xdzf6   1/1     Running   1          46h   10.244.2.61   node2   <none>           <none>

]# kubectl describe pods nginx-ingress-controller-5b6fcd5bcd-xdzf6 -n ingress-nginx
Name:         nginx-ingress-controller-5b6fcd5bcd-xdzf6
Namespace:    ingress-nginx
Priority:     0
Node:         node2/172.16.2.202
Start Time:   Tue, 25 Aug 2020 10:42:44 +0800
Labels:       app.kubernetes.io/name=ingress-nginx
              app.kubernetes.io/part-of=ingress-nginx
              pod-template-hash=5b6fcd5bcd
Annotations:  kubernetes.io/limit-ranger: LimitRanger plugin set: cpu, memory request for container nginx-ingress-controller
              prometheus.io/port: 10254
              prometheus.io/scrape: true
Status:       Running
IP:           10.244.2.61
IPs:
  IP:           10.244.2.61
Controlled By:  ReplicaSet/nginx-ingress-controller-5b6fcd5bcd
Containers:
  nginx-ingress-controller:
    Container ID:  docker://aff960a101abc2f2d1ed98d84fdeba731db1c0ed732cb8a8824aaf9c52bbf211
    Image:         quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.26.2
    Image ID:      docker-pullable://quay.io/kubernetes-ingress-controller/nginx-ingress-controller@sha256:675c709433f566f9872fd0d782c321da9c91b5809bb0e8cadf4996c9c6c545b1
    Ports:         80/TCP, 443/TCP
    Host Ports:    0/TCP, 0/TCP
    Args:
      /nginx-ingress-controller
      --configmap=$(POD_NAMESPACE)/nginx-configuration
      --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
      --udp-services-configmap=$(POD_NAMESPACE)/udp-services
      --publish-service=$(POD_NAMESPACE)/ingress-nginx
      --annotations-prefix=nginx.ingress.kubernetes.io
    State:          Running
      Started:      Tue, 25 Aug 2020 20:34:46 +0800
    Last State:     Terminated
      Reason:       Error
      Exit Code:    255
      Started:      Tue, 25 Aug 2020 10:42:45 +0800
      Finished:     Tue, 25 Aug 2020 20:34:33 +0800
    Ready:          True
    Restart Count:  1
    Requests:
      cpu:      100m
      memory:   90Mi
    Liveness:   http-get http://:10254/healthz delay=10s timeout=10s period=10s #success=1 #failure=3
    Readiness:  http-get http://:10254/healthz delay=0s timeout=10s period=10s #success=1 #failure=3
    Environment:
      POD_NAME:       nginx-ingress-controller-5b6fcd5bcd-xdzf6 (v1:metadata.name)
      POD_NAMESPACE:  ingress-nginx (v1:metadata.namespace)
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from nginx-ingress-serviceaccount-token-clcz4 (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             False 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  nginx-ingress-serviceaccount-token-clcz4:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  nginx-ingress-serviceaccount-token-clcz4
    Optional:    false
QoS Class:       Burstable
Node-Selectors:  kubernetes.io/os=linux
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:          <none>

3)创建对外暴露的Service资源
  在线的配置清单中采用了基于Deployment控制器部署Ingress Nginx的方式,因此接入外部流量之前还需要手动为其创建相关的NodePort或LoadBalancer类型的Service资源对象;下面的配置清单文件示例中对类型定义了NodePort,并明确指出了易记得端口和IP地址,方便用户使用。

]# cat service-ingress.yaml 
apiVersion: v1
kind: Service
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
spec:
  type: NodePort
  clusterIP: 10.99.99.99
  ports:
    - port: 80
      name: http
      nodePort: 30080
    - port: 443
      name: https
      nodePort: 30443
  selector: 
    app.kubernetes.io/name: ingress-nginx

]# kubectl get services -n ingress-nginx -o wide 
NAME                       TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)                      AGE   SELECTOR
nginx-ingress-controller   NodePort   10.99.99.99   <none>        80:30080/TCP,443:30443/TCP   16s   app.kubernetes.io/name=ingress-nginx

]# kubectl describe service nginx-ingress-controller -n ingress-nginx
Name:                     nginx-ingress-controller
Namespace:                ingress-nginx
Labels:                   <none>
Annotations:              Selector:  app.kubernetes.io/name=ingress-nginx
Type:                     NodePort
IP:                       10.99.99.99
Port:                     http  80/TCP
TargetPort:               80/TCP
NodePort:                 http  30080/TCP
Endpoints:                
Port:                     https  443/TCP
TargetPort:               443/TCP
NodePort:                 https  30443/TCP
Endpoints:                
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

4)创建集群内部的Ingress、Service资源

]# cat ingress.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
  namespace: ingress-nginx
spec:
  backend:
    serviceName: my-svc
    servicePort: 80

]# kubectl get ingress -n ingress-nginx -o wide 
NAME         CLASS    HOSTS   ADDRESS   PORTS   AGE
my-ingress   <none>   *                 80      9m32s

]# cat service-api.yaml 
apiVersion: v1
kind: Service
metadata:
  name: my-svc
  namespace: ingress-nginx
spec:
  selector:
    app: myapp
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

---
apiVersion: apps/v1
kind: Deployment
metadata: 
  name: myapp
  namespace: ingress-nginx
spec:
  replicas: 2
  selector: 
    matchLabels:
      app: myapp
  template:
    metadata: 
      labels:
        app: myapp
    spec:
      containers:
      - name: svc-pod
        image: ikubernetes/myapp:v1
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 80 

]# kubectl get svc -n ingress-nginx -o wide
NAME                       TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE     SELECTOR
my-svc                     ClusterIP   10.97.96.93    <none>        80/TCP                       7m32s   app=myapp
nginx-ingress-controller   NodePort    10.99.99.99    <none>        80:30080/TCP,443:30443/TCP   17m     app.kubernetes.io/name=ingress-nginx

5)查看Ingress与Service资源详情

]# kubectl get endpoints -n ingress-nginx
NAME                       ENDPOINTS                        AGE
my-svc                     10.244.0.74:80,10.244.0.75:80    9m59s
nginx-ingress-controller   10.244.2.65:443,10.244.2.65:80   19m


]# kubectl describe svc my-svc -n ingress-nginx 
Name:              my-svc
Namespace:         ingress-nginx
Labels:            <none>
Annotations:       Selector:  app=myapp
Type:              ClusterIP
IP:                10.97.96.93
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.0.74:80,10.244.0.75:80
Session Affinity:  None
Events:            <none>

]# kubectl describe  ingress my-ingress   -n ingress-nginx 
Name:             my-ingress
Namespace:        ingress-nginx
Address:          
Default backend:  my-svc:80 (10.244.0.74:80,10.244.0.75:80)
Rules:
  Host        Path  Backends
  ----        ----  --------
  *           *     my-svc:80 (10.244.0.74:80,10.244.0.75:80)
Annotations:  Events:
  Type        Reason  Age        From                      Message
  ----        ------  ----       ----                      -------
  Normal      CREATE  <invalid>  nginx-ingress-controller  Ingress ingress-nginx/my-ingress

可以看到此时集群内部的Ingress资源已经与集群内部的Service资源相关联;Ingrees-Controller控制器控制集群内部的Ingress资源,然后通过NodePort类型的Service资源对外暴露应用服务。

6)访问服务
Kubernetes学习之Ingress_第4张图片

五、阿里云Ingress资源对象使用

在这里插入图片描述

Kubernetes学习之Ingress_第5张图片

在这里插入图片描述

Kubernetes学习之Ingress_第6张图片

Kubernetes学习之Ingress_第7张图片

Kubernetes学习之Ingress_第8张图片

你可能感兴趣的:(Kubernetes学习)