zoukankan      html  css  js  c++  java
  • Kubernetes 第十章 Ingress

    术语

    在本篇文章中你将会看到一些在其他地方被交叉使用的术语,为了防止产生歧义,我们首先来澄清下。

    • 节点:Kubernetes集群中的一台物理机或者虚拟机。
    • 集群:位于Internet防火墙后的节点,这是kubernetes管理的主要计算资源。
    • 边界路由器:为集群强制执行防火墙策略的路由器。 这可能是由云提供商或物理硬件管理的网关。
    • 集群网络:一组逻辑或物理链接,可根据Kubernetes网络模型实现群集内的通信。 集群网络的实现包括Overlay模型的 flannel 和基于SDN的OVS
    • 服务:使用标签选择器标识一组pod成为的Kubernetes服务。 除非另有说明,否则服务假定在集群网络内仅可通过虚拟IP访问。

    什么是 Ingress?

    通常情况下,service 和 pod 的 IP 仅可在集群内部访问。集群外部的请求需要通过负载均衡转发到 service 在 Node 上暴露的 NodePort 上,然后再由 kube-proxy 通过边缘路由器 (edge router) 将其转发给相关的 Pod 或者丢弃。如下图所示

     internet
            |
      ------------
      [Services]

    而 Ingress 就是为进入集群的请求提供路由规则的集合,如下图所示

    //这张图说明了ingress 的数据处理流程,客户端通过 service 暴露的端口进去集群,然后数据转发到ingress , ingress 调度到 pods 。这时ingress 通过 kuberneters API 监听pods 对应service 变化,动态修改ingress nginx  配置

    Ingress 可以给 service 提供集群外部访问的 URL、负载均衡、SSL 终止、HTTP 路由等。为了配置这些 Ingress 规则,集群管理员需要部署一个 Ingress controller,它监听 Ingress 和 service 的变化,并根据规则配置负载均衡并提供访问入口。

    Ingress的组成部分

    Nginx:实现负载均衡到pod的集合

    Ingress Controller:从集群api获取services对应pod的ip到nginx配置文件中

    Ingress:为nginx创建虚拟主机

    1.创建ingress-nginx   controller  引擎

     标准安装 ingress controller 配置文件:  https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml   

    //需要先创建 ingress-controller ,选择引擎为 nginx 的nginx-ingress-controller 

    //这一步安装了 ingeess-controller  pod 

    [root@kube ~]# kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
    namespace/ingress-nginx created
    configmap/nginx-configuration created
    configmap/tcp-services created
    configmap/udp-services created
    serviceaccount/nginx-ingress-serviceaccount created
    clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
    role.rbac.authorization.k8s.io/nginx-ingress-role created
    rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
    clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
    deployment.apps/nginx-ingress-controller created
    [root@kube ~]# 
    [root@kube ~]# 
    [root@kube ~]# 
    [root@kube ~]# kubectl get namespace
    NAME              STATUS   AGE
    default           Active   41d
    ingress-nginx     Active   8s
    kube-node-lease   Active   41d
    kube-public       Active   41d
    kube-system       Active   41d
    new-namespace     Active   6d19h
    [root@kube ~]# 
    [root@kube test]# kubectl get pods -n ingress-nginx     //检查nginx-ingress-controller  是否创建成功   -n 为指定 namesapce 为 inrgess-nginx 
    NAME                                        READY   STATUS    RESTARTS   AGE
    nginx-ingress-controller-7995bd9c47-5qkr4   1/1     Running   0          6h4m
    [root@kube test]# 
    [root@kube test]# kubectl get pods --all-namespaces -l app.kubernetes.io/name=ingress-nginx --watch   //检查是否创建成功
    NAMESPACE       NAME                                        READY   STATUS    RESTARTS   AGE
    ingress-nginx   nginx-ingress-controller-7995bd9c47-5qkr4   1/1     Running   0          6h53m

    2. 创建 ingress-nginx   service 

      本次测试使用的ingress-nginx 是在NodePort 方式发布,因此需要先定义nodeport 类型的service 作为流量入口

    [root@kube test]# cat ingress-service.yaml 
    apiVersion: v1
    kind: Service
    metadata:
      name: ingress-nginx
      namespace: ingress-nginx
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
    spec:
      type: NodePort
      ports:
        - name: http
          port: 80
          targetPort: 80
          protocol: TCP
          nodePort: 30080    //在所有被允许的  node 上都暴露了相关的端口
    
        - name: https
          port: 443
          targetPort: 443
          protocol: TCP
          nodePort: 30443
      selector:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
    
    [root@kube test]# kubectl apply -f ingress-service.yaml
    service/ingress-nginx created
    [root@kube test]# kubectl get service -n ingress-nginx
    NAME            TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
    ingress-nginx   NodePort   10.107.89.78   <none>        80:30080/TCP,443:30443/TCP   2m27s
    [root@kube test]# 

    3.创建被调度的 service 资源

    [root@kube test]# cat ingress-demo.yaml 
    apiVersion: v1
    kind: Service            //service 部分
    metadata:
      name: myapp-ingress
      namespace: default
    spec:
      selector:
        app: myapp-ingress
      ports:
      - name: http
        port: 80
        targetPort: 80    
    
    ---
    
    apiVersion: apps/v1
    kind: Deployment     //deployment 部分
    metadata:
      name: my-ingress
      namespace: default
    spec:
      replicas: 2
      selector: 
        matchLabels:
          app: myapp-ingress
          release: canary-ingress
      template:       //pods 部分
        metadata:
          labels:
            app: myapp-ingress
            release: canary-ingress
        spec:
          containers:
          - name: myapp-pod
            image: nginx:1.7.9 
            ports:
            - name: http
              containerPort: 80
    [root@kube test]# 

    4.发布 ingress 资源

    [root@kube test]# cat ingress-my-ingress.yaml 
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: testname-ingress
    spec:
      rules:
      - host: zy.ingress.com
        http:
          paths:
          - path: 
            backend:
              serviceName: myapp-ingress
              servicePort: 80
    [root@kube test]# 
    [root@kube test]# 
    [root@kube test]# kubectl apply -f ingress-my-ingress.yaml
    ingress.extensions/test-ingress created
    [root@kube test]# kubectl  get ingress
    NAME           HOSTS   ADDRESS   PORTS   AGE
    test-ingress   *                 80      20s
    
    [root@kube test]# kubectl describe ingress test-ingress
    Name:             test-ingress
    Namespace:        default
    Address:          
    Default backend:  myapp-ingress:80 (10.244.1.17:80,10.244.2.39:80)
    Rules:
      Host  Path  Backends
      ----  ----  --------
      *     *     myapp-ingress:80 (10.244.1.17:80,10.244.2.39:80)
    Annotations:
      kubectl.kubernetes.io/last-applied-configuration:  {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{},"name":"test-ingress","namespace":"default"},"spec":{"backend":{"serviceName":"myapp-ingress","servicePort":80}}}
    
    Events:
      Type    Reason  Age   From                      Message
      ----    ------  ----  ----                      -------
      Normal  CREATE  69s   nginx-ingress-controller  Ingress default/test-ingress
    [root@kube test]# 
    [root@kube test]# kubectl describe  test-ingress        //修改了yaml 文件 ,添加了host
    error: the server doesn't have a resource type "test-ingress"
    [root@kube test]# kubectl describe  ingress test-ingress
    Name:             test-ingress
    Namespace:        default
    Address:          
    Default backend:  default-http-backend:80 (<none>)
    Rules:
      Host            Path  Backends
      ----            ----  --------
      zy.ingress.com  
                         myapp-ingress:80 (10.244.1.17:80,10.244.2.39:80)
    Annotations:
      kubectl.kubernetes.io/last-applied-configuration:  {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{},"name":"test-ingress","namespace":"default"},"spec":{"rules":[{"host":"zy.ingress.com","http":{"paths":[{"backend":{"serviceName":"myapp-ingress","servicePort":80},"path":null}]}}]}}
    
    Events:
      Type    Reason  Age   From                      Message
      ----    ------  ----  ----                      -------
      Normal  CREATE  37m   nginx-ingress-controller  Ingress default/test-ingress
      Normal  UPDATE  12m   nginx-ingress-controller  Ingress default/test-ingress
    [root@kube test]# 

    检查:

    [root@kube test]# kubectl exec -n ingress-nginx -it nginx-ingress-controller-7995bd9c47-5qkr4 -- /bin/bash
    www-data@nginx-ingress-controller-7995bd9c47-5qkr4:/etc/nginx$ cat nginx.conf 
    .....................................
    
        ## start server zy.ingress.com
        server {
            server_name zy.ingress.com ;
            
            listen 80;
            
            set $proxy_upstream_name "-";
            set $pass_access_scheme $scheme;
            set $pass_server_port $server_port;
            set $best_http_host $http_host;
            set $pass_port $pass_server_port;
    ....................................
    [root@kube test]# curl http://10.2.61.22:30080/     //在后续添加了  Host 字段因此用ip  访问失败
    <html>
    <head><title>404 Not Found</title></head>
    <body>
    <center><h1>404 Not Found</h1></center>
    <hr><center>openresty/1.15.8.1</center>
    </body>
    </html>
    [root@kube test]# curl http://zy.ingress.com:30080/     //换成域名成功
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
        body {
             35em;
            margin: 0 auto;
            font-family: Tahoma, Verdana, Arial, sans-serif;
        }
    </style>
    </head>
    <body>
    <h1>Welcome to nginx!</h1>
    <p>If you see this page, the nginx web server is successfully installed and
    working. Further configuration is required.</p>
    
    <p>For online documentation and support please refer to
    <a href="http://nginx.org/">nginx.org</a>.<br/>
    Commercial support is available at
    <a href="http://nginx.com/">nginx.com</a>.</p>
    
    <p><em>Thank you for using nginx.</em></p>
    </body>
    </html>
    [root@kube test]# 

    5.Ingress 类型

    单服务 Ingress
    多服务的 Ingress
    虚拟主机 Ingress
    TLS Ingress

    单服务 Ingress

    单服务 Ingress 即该 Ingress 仅指定一个没有任何规则的后端服务。

    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: test-ingress
    spec:
      backend:
        serviceName: testsvc
        servicePort: 80

    注:单个服务还可以通过设置 Service.Type=NodePort 或者 Service.Type=LoadBalancer 来对外暴露。

    多服务的 Ingress

    路由到多服务的 Ingress 即根据请求路径的不同转发到不同的后端服务上,比如

    foo.bar.com -> 178.91.123.132 -> / foo    s1:80
                                     / bar    s2:80
    

    可以通过下面的 Ingress 来定义:

    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: test
    spec:
      rules:
      - host: foo.bar.com
        http:
          paths:
          - path: /foo
            backend:
              serviceName: s1
              servicePort: 80
          - path: /bar
            backend:
              serviceName: s2
              servicePort: 80

    使用 kubectl create -f 创建完 ingress 后:

    $ kubectl get ing
    NAME      RULE          BACKEND   ADDRESS
    test      -
              foo.bar.com
              /foo          s1:80
              /bar          s2:80

    虚拟主机 Ingress

    虚拟主机 Ingress 即根据名字的不同转发到不同的后端服务上,而他们共用同一个的 IP 地址,如下所示

    foo.bar.com --|                 |-> foo.bar.com s1:80
                  | 178.91.123.132  |
    bar.foo.com --|                 |-> bar.foo.com s2:80
    

    下面是一个基于 Host header 路由请求的 Ingress:

    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: test
    spec:
      rules:
      - host: foo.bar.com
        http:
          paths:
          - backend:
              serviceName: s1
              servicePort: 80
      - host: bar.foo.com
        http:
          paths:
          - backend:
              serviceName: s2
              servicePort: 80

    注:没有定义规则的后端服务称为默认后端服务,可以用来方便的处理 404 页面。

    TLS Ingress

    TLS Ingress 通过 Secret 获取 TLS 私钥和证书 (名为 tls.crt 和 tls.key),来执行 TLS 终止。如果 Ingress 中的 TLS 配置部分指定了不同的主机,则它们将根据通过 SNI TLS 扩展指定的主机名(假如 Ingress controller 支持 SNI)在多个相同端口上进行复用。

    定义一个包含 tls.crt 和 tls.key 的 secret:

    apiVersion: v1
    data:
      tls.crt: base64 encoded cert
      tls.key: base64 encoded key
    kind: Secret
    metadata:
      name: testsecret
      namespace: default
    type: Opaque
    Ingress 中引用 secret:
    
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: no-rules-map
    spec:
      tls:
        - secretName: testsecret
      backend:
        serviceName: s1
        servicePort: 80

    注意,不同 Ingress controller 支持的 TLS 功能不尽相同。 请参阅有关 nginxGCE 或任何其他 Ingress controller 的文档,以了解 TLS 的支持情况。

  • 相关阅读:
    【Azure 应用服务】由 Azure Functions runtime is unreachable 的错误消息推导出 ASYNC(异步)和 SYNC(同步)混用而引起ThreadPool耗尽问题
    【Azure API 管理】是否可以将Swagger 的API定义导入导Azure API Management中
    【Azure 应用服务】Azure Function 不能被触发
    【Azure 环境】Azure Key Vault (密钥保管库)中所保管的Keys, Secrets,Certificates是否可以实现数据粒度的权限控制呢?
    【Azure 事件中心】为应用程序网关(Application Gateway with WAF) 配置诊断日志,发送到事件中心
    【Azure 事件中心】azure-spring-cloud-stream-binder-eventhubs客户端组件问题, 实践消息非顺序可达
    【Azure API 管理】Azure API Management通过请求中的Path来限定其被访问的频率(如1秒一次)
    【Azure 环境】前端Web通过Azure AD获取Token时发生跨域问题(CORS Error)
    【Azure 应用服务】记一次Azure Spring Cloud 的部署错误 (az spring-cloud app deploy -g dev -s testdemo -n demo -p ./hellospring-0.0.1-SNAPSHOT.jar --->>> Failed to wait for deployment instances to be ready)
    【Azure 应用服务】App Service中抓取 Web Job 的 DUMP 办法
  • 原文地址:https://www.cnblogs.com/zy09/p/11390021.html
Copyright © 2011-2022 走看看