美文网首页
Kubernetes addons 之 Ingress Cont

Kubernetes addons 之 Ingress Cont

作者: bern85 | 来源:发表于2019-06-19 12:03 被阅读0次

    Ingress

    管理群集中服务的外部访问的API对象,通常是HTTP。
    Ingress可以提供负载平衡,SSL 终止和基于名称的虚拟主机。

    Ingress是什么

    Ingress, Kubernetes v1.1开始增加的,暴露集群 services 的 http和https的路由。流量路由规则的控制是定义在Ingress resource。

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

    Ingress可以给service提供集群外部访问的URL、负载均衡、SSL终止、基于名称的虚拟主机。 Ingress controller 负责实现Ingress的功能, 通常是一个负载均衡器, 它监听Ingress和service的变化,并根据规则配置负载均衡并提供访问入口。
    Ingress不会暴露任意端口或协议。将HTTP和HTTPS以外的服务公开给Internet通常使用Service.Type = NodePort或Service.Type = LoadBalancer。

    The Ingress Resource

    最简单的Ingress Resource示例如下

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: test-ingress
      annotations:
        nginx.ingress.kubernetes.io/rewrite-target: /
    spec:
      rules:
      - http:
          paths:
          - path: /testpath
            backend:
              serviceName: test
              servicePort: 80
    

    与其他的Kubernetes resources一样,Ingress需要apiVersion, kind, 和 metadata 属性.
    有关配置的其他属性配置,参见 deploying applications, configuring containers, managing resources.
    Ingress经常使用注释来配置一些选项,具体取决于Ingress控制器, 参见例子 rewrite-target annotation.
    不同的 Ingress controller 支持不同的注释. 阅读你选择的Ingress controller的文档,查看支持那些注释.
    Ingress规范具有配置负载均衡器或代理服务器所需的所有信息。 最重要的是,它包含与所有传入请求匹配的规则列表。 Ingress资源仅支持HTTP流量的规则。

    Ingress 规则

    每个http规则都包含以下信息:

    • 可选主机。 在此示例中,未指定主机,因此该规则适用于通过指定的IP地址的所有入站HTTP流量。 如果提供了主机(例如,foo.bar.com),则规则适用于该主机。
    • 路径列表(例如,/ testpath),每个路径都会定义serviceName和servicePort关联后端。 主机和路径都必须与传入请求的内容匹配,以便负载均衡器能够直接引用到后端服务。
    • 后端是在 services 文档中定义的服务名称和端口名称的组合. 对Ingress匹配的主机和路由规则的HTTP(和HTTPS)请求将被发送到列出的后端。
      默认后端通常在Ingress控制器中配置,该控制器将为与规范中的路径不匹配的请求提供服务。

    默认后端

    没有规则的Ingress将所有流量发送到单个默认后端。 默认后端通常是Ingress控制器的一个配置选项,并且未在Ingress资源中指定。

    Ingress类型

    1、单服务Ingress
    现有的Kubernetes概念允许公开单个服务 (参见 alternatives)。也可以通过指定没有规则的默认后端来使用Ingress执行此操作。

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: test-ingress
    spec:
      backend:
        serviceName: testsvc
        servicePort: 80
    
    

    如果你使用 kubectl apply -f 你将会看到如下信息:

    kubectl get ingress test-ingress
    NAME           HOSTS     ADDRESS           PORTS     AGE
    test-ingress   *         107.178.254.228   80        59s
    

    其中107.178.254.228是Ingress controller为满足此Ingress而分配的IP。

    2、路由到多服务的Ingress

    多服务配置根据请求的HTTP URI将流量从单个IP地址路由到多个服务。Ingress允许将负载均衡器的数量降至最低。例如,设置如下:

    foo.bar.com -> 178.91.123.132 -> / foo    service1:4200
                                     / bar    service2:8080
    

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

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: simple-fanout-example
      annotations:
        nginx.ingress.kubernetes.io/rewrite-target: /
    spec:
      rules:
      - host: foo.bar.com
        http:
          paths:
          - path: /foo
            backend:
              serviceName: service1
              servicePort: 4200
          - path: /bar
            backend:
              serviceName: service2
              servicePort: 8080
    

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

    kubectl describe ingress simple-fanout-example
    
    Name:             simple-fanout-example
    Namespace:        default
    Address:          178.91.123.132
    Default backend:  default-http-backend:80 (10.8.2.3:8080)
    Rules:
      Host         Path  Backends
      ----         ----  --------
      foo.bar.com
                   /foo   service1:4200 (10.8.0.90:4200)
                   /bar   service2:8080 (10.8.0.91:8080)
    Annotations:
      nginx.ingress.kubernetes.io/rewrite-target:  /
    Events:
      Type     Reason  Age                From                     Message
      ----     ------  ----               ----                     -------
      Normal   ADD     22s                loadbalancer-controller  default/test
    

    只要服务(s1,s2)存在,Ingress控制器就会提供满足Ingress特定实现的负载均衡器。创建完成后,可以在Address 字段中查看负载均衡器的地址。

    3、基于名称的虚拟主机
    虚拟主机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: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: name-virtual-host-ingress
    spec:
      rules:
      - host: foo.bar.com
        http:
          paths:
          - backend:
              serviceName: service1
              servicePort: 80
      - host: bar.foo.com
        http:
          paths:
          - backend:
              serviceName: service2
              servicePort: 80
    

    如果你创建的Ingress resouce 没有在rules中定义任何主机,然后,基于 Ingress controller 的IP地址的web请求能够匹配到没有名称的虚拟主机。例如,以下Ingress resource 会将first.bar.com请求路由到service1,将second.foo.com路由到service2,其他只有IP地址没有定义hostname(即没有在header中定义hostname)将会路由到service3

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: name-virtual-host-ingress
    spec:
      rules:
      - host: first.bar.com
        http:
          paths:
          - backend:
              serviceName: service1
              servicePort: 80
      - host: second.foo.com
        http:
          paths:
          - backend:
              serviceName: service2
              servicePort: 80
      - http:
          paths:
          - backend:
              serviceName: service3
              servicePort: 80
    

    4、TLS
    您可以通过指定包含TLS私钥和证书的 secret 来加固Ingress。目前,Ingress仅支持一个TLS的端口 443,并假定TLS终止。如果Ingress中的TLS配置部分指定了不同的主机,它们将根据通过SNI TLS扩展指定的主机名在同一端口上复用(假设Ingress控制器支持SNI),TLS secret 必须包含名为tls.crt和tls.key的密钥,其中包含用于TLS的证书和私钥。例如:

    apiVersion: v1
    kind: Secret
    metadata:
      name: testsecret-tls
      namespace: default
    data:
      tls.crt: base64 encoded cert
      tls.key: base64 encoded key
    type: kubernetes.io/tls
    

    在Ingress引用此secret,就是告诉Ingress controller使用TLS保护从客户端到负载均衡器的信道。你需要确保你创建的TLS Secret来自包含sslexample.foo.com的CN的证书。

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: tls-example-ingress
    spec:
      tls:
      - hosts:
        - sslexample.foo.com
        secretName: testsecret-tls
      rules:
        - host: sslexample.foo.com
          http:
            paths:
            - path: /
              backend:
                serviceName: service1
                servicePort: 80
    

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

    4、负载均衡
    Ingress controller通过一些负载均衡策略设置进行自举,该策略设置适用于所有Ingress,例如负载平衡算法,后端权重方案等。 其他的一些高级的负载平衡概念(例如,持久会话,动态权重)没有通过Ingress公布。 不过你仍然可以通过负载均衡器获得这些功能。
    值得注意的是,即使健康检查没有直接通过Ingress公开,Kubernetes中也存在类似概念,例如readiness探针,它们可以实现相同的最终结果。你可以参阅controller的文档,了解它们如何处理健康检查 ( nginx, GCE)。

    5、更新Ingress
    要更新现有的Ingress以添加新主机,您可以通过编辑资源来更新它:

    kubectl describe ingress test
    
    Name:             test
    Namespace:        default
    Address:          178.91.123.132
    Default backend:  default-http-backend:80 (10.8.2.3:8080)
    Rules:
      Host         Path  Backends
      ----         ----  --------
      foo.bar.com
                   /foo   s1:80 (10.8.0.90:80)
    Annotations:
      nginx.ingress.kubernetes.io/rewrite-target:  /
    Events:
      Type     Reason  Age                From                     Message
      ----     ------  ----               ----                     -------
      Normal   ADD     35s                loadbalancer-controller  default/test
    
    kubectl edit ingress test
    

    这应该会弹出一个包含现有yaml的编辑器,修改它以包含新主机:

    spec:
      rules:
      - host: foo.bar.com
        http:
          paths:
          - backend:
              serviceName: s1
              servicePort: 80
            path: /foo
      - host: bar.baz.com
        http:
          paths:
          - backend:
              serviceName: s2
              servicePort: 80
            path: /foo
    ..
    

    保存yaml将更新API服务器中的资源,这会告诉Ingress controller重新配置负载均衡器。

    kubectl describe ingress test
    
    Name:             test
    Namespace:        default
    Address:          178.91.123.132
    Default backend:  default-http-backend:80 (10.8.2.3:8080)
    Rules:
      Host         Path  Backends
      ----         ----  --------
      foo.bar.com
                   /foo   s1:80 (10.8.0.90:80)
      bar.baz.com
                   /foo   s2:80 (10.8.0.91:80)
    Annotations:
      nginx.ingress.kubernetes.io/rewrite-target:  /
    Events:
      Type     Reason  Age                From                     Message
      ----     ------  ----               ----                     -------
      Normal   ADD     45s                loadbalancer-controller  default/test
    

    你可以通过在修改的Ingress yaml文件,然后调用kubectl replace -f来实现同样的目的。

    Ingress Controllers

    Ingress 正常工作需要集群中运行 Ingress Controller。Ingress Controller 与其他作为 kube-controller-manager 中的在集群创建时自动启动的 controller 成员不同,需要用户选择最适合自己集群的 Ingress Controller.
    Kubernetes项目目前支持和维护GCE and nginx controllers。
    Ingress Controller 以 Kubernetes Pod 的方式部署,以 daemon 方式运行,保持 watch Apiserver 的 /ingress 接口以更新 Ingress 资源,以满足 Ingress 的请求。比如可以使用 Nginx Ingress Controller
    其他 Ingress Controller 还有:

    使用多个Ingress controllers

    你可以在集群中部署多个 any number of ingress controllers. 当你在集群中部署多个ingress controllers时,你创建ingress时需要使用注释指定 ingress.class,这样集群才能选取正确的ingress controller.
    当你没有指定ingress.class,云提供商可能会使用默认的ingress 入口.
    一般而言,所有Ingress controllers都应满足此规范,但各种Ingress controllers的运行方式略有不同。

    查看Ingress controller的文档以了解选择它的注意事项
    我们接下来会具体介绍kubernetes/ingress-nginx,以此作为一个示例来介绍Ingress controllers.

    ingress-nginx

    Enterprise-grade application delivery for Kubernetes

    Kubernetes是一个开源容器调度和编排系统,最初由Google创建,然后捐赠给Cloud Native Computing Foundation。 Kubernetes自动调度容器在服务器集群中运行,解放了开发人员和运维人员容器编排的复杂的任务。 Kubernetes目前时最受欢迎的容器调度和编排系统。
    NGINX Ingress Controller 为Kubernetes应用程序提供企业级交付服务,为开源NGINX和NGINX Plus的用户带来便捷.使用NGINX Ingress Controller 可以提供一下特性,负载平衡、SSL / TLS终止、URI重写、SSL / TLS加密。NGINX Plus还可以为有状态的应用提供session 持久化支持,API的jwt身份验证等功能。

    ingress-nginx 安装

    1、先决条件和通用部署命令
    默认配置监视所有命名空间的Ingress对象。 要更改此行为,请使用--watch-namespace将范围限制为特定命名空间。
    如果多个Ingress为同一主机定义不同的路径,则 ingress controller 将合并定义。
    如果你正在使用GKE,则需要使用以下命令将当前用户初始化为集群管理员:kubectl create clusterrolebinding cluster-admin-binding \ --clusterrole cluster-admin \ --user $(gcloud config get-value account)

    yaml 文件:

    wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
    

    部署方式有两种,一种是创建service 使用NodePort暴露ingress-nginx,另外一种方式是使用本机网络,添加hostNetwork: true
    我们接下来使用这两种方式进行部署:
    1、创建ingress-nginx-service(官方文档)
    1.1、首先根据mandatory.yaml 文件创建对应的ingress相关

    [root@k8s ~]# kubectl apply -f mandatory.yaml 
    namespace/ingress-nginx created
    deployment.extensions/default-http-backend created
    service/default-http-backend 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.extensions/nginx-ingress-controller created
    

    验证安装
    检查ingress controller pods 是否正常启动,请运行下面的命令:

    kubectl get pods --all-namespaces -l app.kubernetes.io/name=ingress-nginx --watch
    
    [root@k8s ~]# kubectl get pods --all-namespaces -l app.kubernetes.io/name=ingress-nginx --watch
    NAMESPACE       NAME                                       READY   STATUS    RESTARTS   AGE
    ingress-nginx   nginx-ingress-controller-65795b86d-28lfr   1/1     Running   0          2m55s
    
    

    1.2、创建ingress-nginx-service.yaml文件,并apply

    ingress-nginx-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
        nodePort: 30080
      - 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@k8s ~]# kubectl apply -f ingress-nginx-service.yaml 
    service/ingress-nginx created
    
    

    1.3、测试
    Ingress Controller 部署部署好了,现在要写ingress的规则,注入到ingress-nginx pod的配置文件中

    [root@k8s ~]# cat test-nginx-service.yaml 
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: test-service-ingress
      namespace: default
    spec:
      rules:
      - host: ancs.nginx.com
        http:
          paths:
           - path: 
             backend:
               serviceName: nginx
               servicePort: 80
    
    [root@k8s ~]# kubectl apply -f test-nginx-service.yaml 
    ingress.extensions/test-service-ingress created
    

    查看ingress

    [root@k8s ~]# kubectl  get ingress
    NAME                   HOSTS            ADDRESS   PORTS   AGE
    test-service-ingress   ancs.nginx.com             80      33s
    
    

    访问的客户端的机器配置下域名解析


    hosts.png

    现在我们可以通过ancs.nginx.com:30080来访问到后端代理的pod了


    nginx.png

    这里是使用http访问的,如果要用https,首先我们要创建一个证书,步骤如下:

    自签证书
    [root@k8s https]#  openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/C=CN/ST=Beijing/L=Beijing/O=ancs/CN=ancs.nginx.com"
    Generating a 2048 bit RSA private key
    ......................+++
    ...........................+++
    writing new private key to 'tls.key'
    -----
    [root@k8s https]# ls
    tls.crt  tls.key
    
    

    当然也可以使用cfssl自签证书。It‘s up to you!
    创建 secret 资源, 证书生成好了,然后把证书转成secret

    [root@k8s https]#  kubectl create secret tls ancs-secret --key tls.key --cert tls.crt
    secret/ancs-secret created
    
    

    修改test-nginx-service.yaml文件

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

    现在我们可以通过https访问了


    ingress-https.png

    2、使用宿主机网络,增加 hostNetwork: true

    2.1 修改mandatory.yaml配置文件,在container中增加配置项 hostNetwork: true 表示使用本机网络


    hostNetwork.png

    注意事项:
    在创建ingress-nginx-controller容器之前,需要修改kube-proxy配置
    在/opt/kubernetes/cfg/kube-proxy配置文件里增加一行:--masquerade-all=true 然后重启kube-proxy 。
    [root@k8s cfg]# cat kube-proxy
    KUBE_PROXY_OPTS="--logtostderr=true
    --v=4
    --hostname-override=10.0.52.14
    --cluster-cidr=10.0.0.0/24
    --proxy-mode=ipvs
    --masquerade-all=true
    --kubeconfig=/opt/kubernetes/cfg/kube-proxy.kubeconfig"

    配置项--masquerade-all的意思,参见官网说明kube-proxy,里面描述为:
    --masquerade-all
    If using the pure iptables proxy, SNAT all traffic sent via Service cluster IPs (this not commonly needed)
    中文翻译:
    --masquerade-all
    如果使用纯 iptables 代理,SNAT 所有通过服务句群 IP 发送的流量(这通常不需要)
    说人话的意思就是:
    在kube-proxy中添加一个标志,以便为群集外流量维护伪装规则。 就像是:

    iptables -t nat -I POSTROUTING ! -s "${CLUSTER_CIDR}" -j MASQUERADE
    

    2.2、启动ingress-controller容器

    [root@k8s ~]# kubectl apply -f mandatory.yaml 
    namespace/ingress-nginx unchanged
    deployment.extensions/default-http-backend unchanged
    service/default-http-backend 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.extensions/nginx-ingress-controller configured
    [root@k8s ~]# kubectl get pods --all-namespaces -l app.kubernetes.io/name=ingress-nginx --watch
    NAMESPACE       NAME                                        READY   STATUS              RESTARTS   AGE
    ingress-nginx   nginx-ingress-controller-6b8cc9b76d-98szp   0/1     ContainerCreating   0          31s
    ingress-nginx   nginx-ingress-controller-6b8cc9b76d-98szp   0/1   Running   0     43s
    ingress-nginx   nginx-ingress-controller-6b8cc9b76d-98szp   1/1   Running   0     47s
    

    2.3、Ingress部署
    2.3.1、 http部署和上面一样,参考上面就可以了。不再重复描述了。
    2.3.2、https部署(使用cfssl)
    利用cfssl颁发证书:

    • 生成ca证书
    cat << EOF | tee ca-config.json
    {
      "signing": {
        "default": {
          "expiry": "87600h"
        },
        "profiles": {
          "www": {
             "expiry": "87600h",
             "usages": [
                "signing",
                "key encipherment",
                "server auth",
                "client auth"
            ]
          }
        }
      }
    }
    EOF
    
    cat << EOF | tee ca-csr.json
    {
        "CN": "www.ancs.com",
        "key": {
            "algo": "rsa",
            "size": 2048
        },
        "names": [
            {
                "C": "CN",
                "L": "Beijing",
                "ST": "Beijing"
            }
        ]
    }
    EOF
    
    cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
    
    • 生成server证书:
    cat << EOF | tee ancs-csr.json
    {
        "CN": "www.ancs.com",
        "hosts": [],
        "key": {
            "algo": "rsa",
            "size": 2048
        },
        "names": [
            {
                "C": "CN",
                "L": "Beijing",
                "ST": "Beijing"
            }
        ]
    }
    EOF
    
    cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www ancs-csr.json | cfssljson -bare www.ancs.com
    
    • 生成密钥
    [root@k8s cfssl]# kubectl create secret tls ancs-secret --cert=www.ancs.com.pem --key=www.ancs.com-key.pem
    secret/ancs-secret created
    
    
    • 部署ingress
    [root@k8s ~]# cat test-https-nginx-service.yaml 
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: test-service-ingress
      namespace: default
    spec:
      tls:
      - hosts:
        - ancs.nginx.cn
        secretName: ancs-secret
      rules:
      - host: ancs.nginx.com
        http:
          paths:
           - path: 
             backend:
               serviceName: nginx
               servicePort: 80
    [root@k8s ~]# kubectl apply -f test-https-nginx-service.yaml 
    ingress.extensions/test-service-ingress created
    [root@k8s ~]# 
    
    

    *配置hosts


    hosts.png
    • 浏览器访问


      https.png

    至此,我们ingress 部署就算完成了。

    相关文章

      网友评论

          本文标题:Kubernetes addons 之 Ingress Cont

          本文链接:https://www.haomeiwen.com/subject/eymaxctx.html