• ingress和ingressController


    ingress是一个API,是一个规则,是个虚拟的东西

    kubernetes提供service我们常用两种方式ClusterIP和NodePort,另外还有LoadBalance类型和ExternalName类型(目前这两种没用过,不做阐述)。ClusterIP是在集群内部用service的IP加端口来访问服务;而NodePort可以跨主机访问,只要能ping通k8s节点就能访问而不必局限在本集群环境,使用集群内部的节点IP加端口来访问,这种方式非常方便,但当有几十上百的服务在集群中运行时,NodePort的端口管理就比较困难。k8s还提供了一种集群维度暴露服务的方式,也就是ingress。Ingress 不是一种服务类型,ingress可以简单理解为service的service,它充当集群的入口点。 它可以将路由规则整合到一个资源中,因为它可以在同一IP地址下公开多个服务。

    需要知道的是,ingress只是个规则,你必须具有 IngressController 才能满足 Ingress 的要求。仅创建 Ingress资源本身没有任何效果。下面是一个官网上的ingress示例的修改版,我把其中host可选项去掉了,如果没有host的话就适用于通过指定 IP 地址的所有入站 HTTP 通信。 如果提供了 host(例如 foo.bar.com),则 rules 适用于该 host.

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: simple-fanout-example
    spec:
      rules:
      - http:
          paths:
          - path: /foo
            pathType: Prefix
            backend:
              service:
                name: service1
                port:
                  number: 4200
          - path: /bar
            pathType: Prefix
            backend:
              service:
                name: service2
                port:
                  number: 8080
    
    

    这个表示访问curl http://foo访问的是服务service1:4200端口,curl http://bar访问的是服务service2:8080端口。

    Ingress Controller是需要用户自己实现的

    Ingress是一个非常“极客”并需要DIY的产物,kubernetes只负责提供一个API定义,具体的IngressController需要用户自己实现!官方提供了Nginx Ingress Controller等其他几种Controller示例共开发者参考。实现一个IngressController大致框架是:List/Watch Kubernetes 的Service、Endpoints、Ingress对象,并根据这些信息刷新外部Load Balancer(例如nginx)的规则和配置。值得注意的是,如果想要通过域名访问Ingress,则需要用户自己配置域名和IngressIP的配置关系,例如host文件、自己的DNS(不是kube-dns). 下图是nginx官网给出的nginx-ingress-controller架构图

    ingress和ingressController创建实例

    Talk is cheap,show me the code.下面说一下我创建ingress和ingressController创建的过程,以及在这个过程中看到的一些思考和问题。

    创建ingress

    我使用如下YAML文件创建了一个ingress, 创建完之后除了可以kubectl get ingress有输出之外,不会有任何服务或者容器启动。只是创建了一个规则而已。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: nginx-ingress 
    spec:
      ingressClassName: nginx-ingress-controller 
      rules:
      - host: test-ko-mix-master-1 
        http:
          paths:
          - path: /index.html
            pathType: Prefix
            backend:
              service:
                name: nginx
                port:
                  number: 80
          - path: /bar
            pathType: Prefix
            backend:
              service:
                name: nginx2
                port:
                  number: 80
    
    

    注意,这里的http前面没有横杠,这里没有namespace,ingressClassName我暂且理解为指明你想用哪个ingressController,如果你没有定义一个class,那么你的云provider会使用缺省的ic.用这个创建之后查看ingress,得到如下结果:

    [root@test-ko-mix-master-1 20211109]# kubectl get ingress -A -o wide
    NAMESPACE   NAME            CLASS                      HOSTS                  ADDRESS   PORTS   AGE
    default     nginx-ingress   nginx-ingress-controller   test-ko-mix-master-1             80      2s
    

    这里,ADDRESS一栏是空的(后面设定了service后会更新为service的IP),如果没有设定ingressClassName那么CLASS这一栏是none.

    创建nginx-ingress-controller

    这个nginx-ingress-controller是官方写的一个ic示例,如果你需要controller其他的资源需要自己去开发,这个资源可以是daemonset,也可以是deployment.启动的容器会自动拉起一个nginx进程并且会根据ingress的规则配置容器内nginx的配置。我
    用如下的mandatory.yaml 文件来创建nginx-ingress-controller:

    点击查看代码
    [root@test-ko-mix-master-1 20211109]# cat mandatory.yaml 
    apiVersion: v1
    kind: Namespace
    metadata:
      name: ingress-nginx
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
    
    ---
    
    kind: ConfigMap
    apiVersion: v1
    metadata:
      name: nginx-configuration
      namespace: ingress-nginx
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
    
    ---
    kind: ConfigMap
    apiVersion: v1
    metadata:
      name: tcp-services
      namespace: ingress-nginx
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
    
    ---
    kind: ConfigMap
    apiVersion: v1
    metadata:
      name: udp-services
      namespace: ingress-nginx
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
    
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: nginx-ingress-serviceaccount
      namespace: ingress-nginx
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
    
    ---
    apiVersion: rbac.authorization.k8s.io/v1beta1
    kind: ClusterRole
    metadata:
      name: nginx-ingress-clusterrole
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
    rules:
      - apiGroups:
          - ""
        resources:
          - configmaps
          - endpoints
          - nodes
          - pods
          - secrets
        verbs:
          - list
          - watch
      - apiGroups:
          - ""
        resources:
          - nodes
        verbs:
          - get
      - apiGroups:
          - ""
        resources:
          - services
        verbs:
          - get
          - list
          - watch
      - apiGroups:
          - ""
        resources:
          - events
        verbs:
          - create
          - patch
      - apiGroups:
          - "extensions"
          - "networking.k8s.io"
        resources:
          - ingresses
        verbs:
          - get
          - list
          - watch
      - apiGroups:
          - "extensions"
          - "networking.k8s.io"
        resources:
          - ingresses/status
        verbs:
          - update
    
    ---
    apiVersion: rbac.authorization.k8s.io/v1beta1
    kind: Role
    metadata:
      name: nginx-ingress-role
      namespace: ingress-nginx
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
    rules:
      - apiGroups:
          - ""
        resources:
          - configmaps
          - pods
          - secrets
          - namespaces
        verbs:
          - get
      - apiGroups:
          - ""
        resources:
          - configmaps
        resourceNames:
          # Defaults to "<election-id>-<ingress-class>"
          # Here: "<ingress-controller-leader>-<nginx>"
          # This has to be adapted if you change either parameter
          # when launching the nginx-ingress-controller.
          - "ingress-controller-leader-nginx"
        verbs:
          - get
          - update
      - apiGroups:
          - ""
        resources:
          - configmaps
        verbs:
          - create
      - apiGroups:
          - ""
        resources:
          - endpoints
        verbs:
          - get
    
    ---
    apiVersion: rbac.authorization.k8s.io/v1beta1
    kind: RoleBinding
    metadata:
      name: nginx-ingress-role-nisa-binding
      namespace: ingress-nginx
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: nginx-ingress-role
    subjects:
      - kind: ServiceAccount
        name: nginx-ingress-serviceaccount
        namespace: ingress-nginx
    
    ---
    apiVersion: rbac.authorization.k8s.io/v1beta1
    kind: ClusterRoleBinding
    metadata:
      name: nginx-ingress-clusterrole-nisa-binding
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: nginx-ingress-clusterrole
    subjects:
      - kind: ServiceAccount
        name: nginx-ingress-serviceaccount
        namespace: ingress-nginx
    
    ---
    
    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: nginx-ingress-controller
      namespace: ingress-nginx
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
    spec:
    #  replicas: 1
      selector:
        matchLabels:
          app.kubernetes.io/name: ingress-nginx
          app.kubernetes.io/part-of: ingress-nginx
      template:
        metadata:
          labels:
            app.kubernetes.io/name: ingress-nginx
            app.kubernetes.io/part-of: ingress-nginx
          annotations:
            prometheus.io/port: "10254"
            prometheus.io/scrape: "true"
        spec:
          # wait up to five minutes for the drain of connections
          terminationGracePeriodSeconds: 300
          serviceAccountName: nginx-ingress-serviceaccount
          nodeSelector:
            kubernetes.io/hostname: test-ko-mix-master-1
          tolerations:
          - key: node-role.kubernetes.io/master
            effect: NoSchedule
          containers:
            - name: nginx-ingress-controller
              image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0
              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
              securityContext:
                allowPrivilegeEscalation: true
                capabilities:
                  drop:
                    - ALL
                  add:
                    - NET_BIND_SERVICE
                # www-data -> 101
                runAsUser: 101
              env:
                - name: POD_NAME
                  valueFrom:
                    fieldRef:
                      fieldPath: metadata.name
                - name: POD_NAMESPACE
                  valueFrom:
                    fieldRef:
                      fieldPath: metadata.namespace
              ports:
                - name: http
                  containerPort: 80
                  hostPort: 80
                  protocol: TCP
                - name: https
                  containerPort: 443
                  hostPort: 443
                  protocol: TCP
              livenessProbe:
                failureThreshold: 3
                httpGet:
                  path: /healthz
                  port: 10254
                  scheme: HTTP
                initialDelaySeconds: 10
                periodSeconds: 10
                successThreshold: 1
                timeoutSeconds: 10
              readinessProbe:
                failureThreshold: 3
                httpGet:
                  path: /healthz
                  port: 10254
                  scheme: HTTP
                periodSeconds: 10
                successThreshold: 1
                timeoutSeconds: 10
              lifecycle:
                preStop:
                  exec:
                    command:
                      - /wait-shutdown
    
    ---
    
    apiVersion: v1
    kind: LimitRange
    metadata:
      name: ingress-nginx
      namespace: ingress-nginx
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
    spec:
      limits:
      - min:
          memory: 90Mi
          cpu: 100m
        type: Container
    

    找到创建出来的nginx-ingress-controller容器,kubectl exec -ti -n ingress-nginx pod/nginx-ingress-controller-vt5lq cat /etc/nginx/nginx.conf ,可以看到ingress设定的一些规则:

            ## start server test-ko-mix-master-1
            server {
                    server_name test-ko-mix-master-1 ;
                    
                    listen 80  ;
                    listen 443  ssl http2 ;
                    
                    set $proxy_upstream_name "-";
            ...
                    location /foo {
                            
                            set $namespace      "default";
                            set $ingress_name   "nginx-ingress";
                            set $service_name   "";
                            set $service_port   "";
                            set $location_path  "/foo";
      
    

    这个时候你外集群外节点去curl ngin-ingress-controller所在主机的80 端口可以得到404网页返回。另外,我们查看nginx-ingress-controller的log,发现它一直在报错:err services "ingress-nginx" not found.这个是说我们创建nginx-ingress-controller中启动参数制定了publish-service为ingress-nginx:

    - /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
    
    

    因此我们要创建一个nodeport类型的service,name是ingress-nginx,创建该service的YAML文件如下:

    点击查看代码
    [root@test-ko-mix-master-1 20211109]# cat service-nodeport.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
        - name: https
          port: 443
          targetPort: 443
          protocol: TCP
      selector:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
    

    创建完ingress-nginx service之后再次查看ingress,ADDRESS栏位有了值,也就是service IP Address:

    [root@test-ko-mix-master-1 20211109]# kubectl get ingress -A -o wide 
    NAMESPACE   NAME            CLASS                      HOSTS                  ADDRESS           PORTS   AGE
    default     nginx-ingress   nginx-ingress-controller   test-ko-mix-master-1   192.168.255.207   80      48m
    [root@test-ko-mix-master-1 20211109]# kubectl describe ingress -n default     nginx-ingress 
    Name:             nginx-ingress
    Namespace:        default
    Address:          192.168.255.207
    Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
    Rules:
      Host                  Path  Backends
      ----                  ----  --------
      test-ko-mix-master-1  
                            /index.html   nginx:80 (10.8.188.31:80)
                            /bar          nginx2:80 (10.8.188.36:80)
    Annotations:            <none>
    Events:                 <none>
    
    

    正是有了这个nodeport类型的service我们才能在集群外的节点curl test-ko-mix-master-1:/index.html(这里test-ko-mix-master-1可以在/etc/hosts中配成集群的任何一个节点的IP)才能得到复杂的nginx容器的页面。否则只能把test-ko-mix-master-1在/etc/hosts中配成controller所在节点的IP才能访问(这是加nodePort或者80端口都可以访问,why?)。
    因为我们ingress制定的url foo后端的service是nginx,所以我们要创建这个service及其后面的endpoints.否则nginx-ingress-controller会报错说找不到nginx这个service. 创建完成之后我的理解就是在集群群外的节点输入curl test-ko-mix-master-1 /foo 就访问到那边呢?nginx service对应的endpoint pod上吗?还是负载到nginx-ingress-controller里面的nginx进程上呢?根据官网的架构图理解应该是先到nginx-ingress-controller的容器,由它负载到后面的service,也就是nginx service对应的endpoints我看到过有的文档说流量不经过service由nginx-ingress-controller直接负载到service后面的endpoint也就是pod上,但是我没有找到controller所在主机的80监听端口也没有找到ipvs转发主机80端口的规则。那么我不敢妄评说controller的流量到底是怎么转发的。有知道的大神可以在评论区指教!
    另外,我在集群主机上看到这样一条IPVS转发规则:

    TCP  172.18.8.203:32629 rr
      -> 10.8.188.30:80               Masq    1      0          0      
    

    意思就是访问本机(172.18.8.203)32629 端口的转发到10.8.188.30:80,其中10.8.188.30是nginx-ingress-controller 容器的IP Address.

    ingressClass

    当集群中存在多于一个的 Ingress Controller 时,就需要为 Ingress 指定对应的 Controller 是哪个,在 Kubernetes 1.18 之前,通常是在 Ingress 资源上通过 kubernetes.io/ingress.class 注解来指定使用的 Ingress Controller。虽然这个注解从未被正式定义过,但确是被各个 Ingress Controller 所广泛支持的。Kubernetes 1.18 起,正式提供了一个 IngressClass 资源,作用与 kubernetes.io/ingress.class 注解类似,例如:

    apiVersion: networking.k8s.io/v1
    kind: IngressClass
    metadata:
      name: external-lb
    spec:
      controller: nginx-ingress-internal-controller
      parameters:
        apiGroup: k8s.example.com
        kind: IngressParameters
        name: external-lb
    

    其中重要的属性是 metadata.name 和 spec.controller,前者是这个 IngressClass 的名称,需要设定在 Ingress 中,后者是 Ingress Controller 的名称。Ingress 中的 spec.ingressClassName 属性,可以用来指定对应的 IngressClass,并进而由 IngressClass 关联到对应的 Ingress Controller,如:

    kind: Ingress
    metadata:
      name: spring-k8s
    spec:
      ingressClassName: external-lb
      defaultBackend:
        service:
          name: spring-k8s
          port:
            number: 80
    

    注意,spec.ingressClassName 与 metadata.annotations.kubernetes.io/ingress.class 的作用并不完全相同,因为 ingressClassName 字段引用的是 IngressClass 资源的名称,IngressClass 资源中,除了指定了 Ingress Controller 的名称之外,还可能会通过 spec.parameters 属性定义一些额外的配置。

    题外话,正向代理和反向代理

    • 正向代理类似一个跳板机,代理访问外部资源。比如我们国内访问谷歌,直接访问访问不到,我们可以通过一个正向代理服务器,请求发到代理服,代理服务器能够访问谷歌,这样由代理去谷歌取到返回数据,再返回给我们,这样我们就能访问谷歌了。正向代理即是客户端代理, 代理客户端, 服务端不知道实际发起请求的客户端.
      正向代理的用途:
      (1)访问原来无法访问的资源,如google
      (2)可以做缓存,加速访问资源
      (3)对客户端访问授权,上网进行认证
      (4)代理可以记录用户访问记录(上网行为管理),对外隐藏用户信息
    • 反向代理(Reverse Proxy)实际运行方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。反向代理即是服务端代理, 代理服务端, 客户端不知道实际提供服务的服务端。
      反向代理的作用:
      (1)保证内网的安全,阻止web攻击,大型网站,通常将反向代理作为公网访问地址,Web服务器是内网
      (2)负载均衡,通过反向代理服务器来优化网站的负载

    参考

  • 相关阅读:
    [Swift实际操作]七、常见概念-(5)使用NSString对字符串进行各种操作
    [Swift]LeetCode326. 3的幂 | Power of Three
    [Swift]LeetCode303. 区域和检索
    [Swift]LeetCode292. Nim游戏 | Nim Game
    [Swift]LeetCode290. 单词模式 | Word Pattern
    SpringMVC框架中的异常解析器-ExceptionHandler和HandlerExceptionResolver
    一个Web报表项目的性能分析和优化实践(七):性能监测工具JavaMelody
    一个Web报表项目的性能分析和优化实践(七):性能监测工具JavaMelody
    百度Echarts-免费的商业产品图表库
    百度Echarts-免费的商业产品图表库
  • 原文地址:https://www.cnblogs.com/janeysj/p/15508193.html
Copyright © 2020-2023  润新知