zoukankan      html  css  js  c++  java
  • nginx-ingress ~ 1

    先从外部看,k8s部署了nginx-controller之后,可以针对服务做请求路由,进一步看,就是一个nginx,那么nginx配置是啥?pod-服务-配置的关系是怎么联动的?

    所以先看下nginx.conf配置,他做了什么

    http {
    	lua_package_cpath "/usr/local/lib/lua/?.so;/usr/lib/lua-platform-path/lua/5.1/?.so;;";
    	lua_package_path "/etc/nginx/lua/?.lua;/etc/nginx/lua/vendor/?.lua;/usr/local/lib/lua/?.lua;;";
    	
    	init_by_lua_block {
    		require("resty.core")
    		collectgarbage("collect")
    		
    		local lua_resty_waf = require("resty.waf")
    		lua_resty_waf.init()
    		
    		-- init modules
    		local ok, res
    		
    		ok, res = pcall(require, "lua_ingress")
    		if not ok then
    		error("require failed: " .. tostring(res))
    		else
    		lua_ingress = res
    		end
    		
    		ok, res = pcall(require, "configuration")
    		if not ok then
    		error("require failed: " .. tostring(res))
    		else
    		configuration = res
    	configuration.nameservers = { "10.191.0.10" }
    		end
    		
    		ok, res = pcall(require, "balancer")
    		if not ok then
    		error("require failed: " .. tostring(res))
    		else
    		balancer = res
    		end
    		
    		ok, res = pcall(require, "monitor")
    		if not ok then
    		error("require failed: " .. tostring(res))
    		else
    		monitor = res
    		end
    		
    	}
    	
    	init_worker_by_lua_block {
    		lua_ingress.init_worker()
    		balancer.init_worker()
    		monitor.init_worker()
    	}
    

    通过lua在各阶段引入动态特性

    关键的服务配置

            location /hello {
                
                set $namespace      "helloworld";
                set $ingress_name   "helloworld-ingress-internal";
                set $service_name   "helloworld";
                set $service_port   "5000";
                set $location_path  "/hello";
                
                rewrite_by_lua_block {
                    balancer.rewrite()
                }
                
                access_by_lua_block {
                    balancer.access()
                }
                
                header_filter_by_lua_block {
                    
                }
                body_filter_by_lua_block {
                    
                }
                
                log_by_lua_block {
                    
                    balancer.log()
                    
                    monitor.call()
                    
                }
                
                port_in_redirect off;
                
                set $proxy_upstream_name    "helloworld-helloworld-5000";
                set $proxy_host             $proxy_upstream_name;
                
                client_max_body_size                    100m;
                
                proxy_set_header Host                   $best_http_host;
                
                # Pass the extracted client certificate to the backend
                
                # Allow websocket connections
                proxy_set_header                        Upgrade           $http_upgrade;
                
                proxy_set_header                        Connection        $connection_upgrade;
                
                proxy_set_header X-Request-ID           $req_id;
                proxy_set_header X-Real-IP              $the_real_ip;
                
                proxy_set_header X-Forwarded-For        $the_real_ip;
                
                proxy_set_header X-Forwarded-Host       $best_http_host;
                proxy_set_header X-Forwarded-Port       $pass_port;
                proxy_set_header X-Forwarded-Proto      $pass_access_scheme;
                
                proxy_set_header X-Original-URI         $request_uri;
                
                proxy_set_header X-Scheme               $pass_access_scheme;
                
                # Pass the original X-Forwarded-For
                proxy_set_header X-Original-Forwarded-For $http_x_forwarded_for;
                
                # mitigate HTTPoxy Vulnerability
                # https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/
                proxy_set_header Proxy                  "";
                
                # Custom headers to proxied server
                
                proxy_connect_timeout                   100s;
                proxy_send_timeout                      60s;
                proxy_read_timeout                      60s;
                
                proxy_buffering                         off;
                proxy_buffer_size                       4k;
                proxy_buffers                           4 4k;
                proxy_request_buffering                 on;
                
                proxy_http_version                      1.1;
                
                proxy_cookie_domain                     off;
                proxy_cookie_path                       off;
                
                # In case of errors try the next upstream server before returning an error
                proxy_next_upstream                     error timeout;
                proxy_next_upstream_tries               3;
                
                proxy_pass http://upstream_balancer;
                
                proxy_redirect                          off;
                
            }

    proxy_pass又是什么呢?继续找配置,原来是调的lua代码

        upstream upstream_balancer {
            server 0.0.0.1; # placeholder
            
            balancer_by_lua_block {
                balancer.balance()
            }
            
            keepalive 32;
            
            keepalive_timeout  60s;
            keepalive_requests 100;
            
        }

    那么这些lua代码打包在哪里呢?随便一搜,就在nginx/lua下

    好,那么切过来看下源码在哪里吧,下载ingress-nginx,先从刚才看到的脚本入手,看下nginx动态特性的lua实现在哪里,原来如此

    先从路由切入

    local ngx_balancer = require("ngx.balancer")
    local cjson = require("cjson.safe")
    local util = require("util")
    local dns_lookup = require("util.dns").lookup
    local configuration = require("configuration")
    local round_robin = require("balancer.round_robin")
    local chash = require("balancer.chash")
    local chashsubset = require("balancer.chashsubset")
    local sticky_balanced = require("balancer.sticky_balanced")
    local sticky_persistent = require("balancer.sticky_persistent")
    local ewma = require("balancer.ewma")
    local string = string
    local ipairs = ipairs
    local table = table
    local getmetatable = getmetatable
    local tostring = tostring
    local pairs = pairs
    local math = math
    local ngx = ngx
    
    -- measured in seconds
    -- for an Nginx worker to pick up the new list of upstream peers
    -- it will take <the delay until controller POSTed the backend object to the
    -- Nginx endpoint> + BACKENDS_SYNC_INTERVAL
    local BACKENDS_SYNC_INTERVAL = 1
    local BACKENDS_FORCE_SYNC_INTERVAL = 30
    
    local DEFAULT_LB_ALG = "round_robin"
    local IMPLEMENTATIONS = {
      round_robin = round_robin,
      chash = chash,
      chashsubset = chashsubset,
      sticky_balanced = sticky_balanced,
      sticky_persistent = sticky_persistent,
      ewma = ewma,
    }
    
    local PROHIBITED_LOCALHOST_PORT = configuration.prohibited_localhost_port or '10246'
    local PROHIBITED_PEER_PATTERN = "^127.*:" .. PROHIBITED_LOCALHOST_PORT .. "$"
    
    local _M = {}
    local balancers = {}
    local backends_with_external_name = {}
    local backends_last_synced_at = 0
    
    local function get_implementation(backend)
      local name = backend["load-balance"] or DEFAULT_LB_ALG
    
      if backend["sessionAffinityConfig"] and
         backend["sessionAffinityConfig"]["name"] == "cookie" then
        if backend["sessionAffinityConfig"]["mode"] == "persistent" then
          name = "sticky_persistent"
        else
          name = "sticky_balanced"
        end
    
      elseif backend["upstreamHashByConfig"] and
             backend["upstreamHashByConfig"]["upstream-hash-by"] then
        if backend["upstreamHashByConfig"]["upstream-hash-by-subset"] then
          name = "chashsubset"
        else
          name = "chash"
        end
      end
    
      local implementation = IMPLEMENTATIONS[name]
      if not implementation then
        ngx.log(ngx.WARN, backend["load-balance"], "is not supported, ",
                "falling back to ", DEFAULT_LB_ALG)
        implementation = IMPLEMENTATIONS[DEFAULT_LB_ALG]
      end
    
      return implementation
    end
    
    local function resolve_external_names(original_backend)
      local backend = util.deepcopy(original_backend)
      local endpoints = {}
      for _, endpoint in ipairs(backend.endpoints) do
        local ips = dns_lookup(endpoint.address)
        for _, ip in ipairs(ips) do
          table.insert(endpoints, { address = ip, port = endpoint.port })
        end
      end
      backend.endpoints = endpoints
      return backend
    end
    
    local function format_ipv6_endpoints(endpoints)
      local formatted_endpoints = {}
      for _, endpoint in ipairs(endpoints) do
        local formatted_endpoint = endpoint
        if not endpoint.address:match("^%d+.%d+.%d+.%d+$") then
          formatted_endpoint.address = string.format("[%s]", endpoint.address)
        end
        table.insert(formatted_endpoints, formatted_endpoint)
      end
      return formatted_endpoints
    end
    
    local function is_backend_with_external_name(backend)
      local serv_type = backend.service and backend.service.spec
                          and backend.service.spec["type"]
      return serv_type == "ExternalName"
    end
    
    local function sync_backend(backend)
      if not backend.endpoints or #backend.endpoints == 0 then
        balancers[backend.name] = nil
        return
      end
    
      if is_backend_with_external_name(backend) then
        backend = resolve_external_names(backend)
      end
    
      backend.endpoints = format_ipv6_endpoints(backend.endpoints)
    
      local implementation = get_implementation(backend)
      local balancer = balancers[backend.name]
    
      if not balancer then
        balancers[backend.name] = implementation:new(backend)
        return
      end
    
      -- every implementation is the metatable of its instances (see .new(...) functions)
      -- here we check if `balancer` is the instance of `implementation`
      -- if it is not then we deduce LB algorithm has changed for the backend
      if getmetatable(balancer) ~= implementation then
        ngx.log(ngx.INFO,
            string.format("LB algorithm changed from %s to %s, resetting the instance",
                          balancer.name, implementation.name))
        balancers[backend.name] = implementation:new(backend)
        return
      end
    
      balancer:sync(backend)
    end
    
    local function sync_backends_with_external_name()
      for _, backend_with_external_name in pairs(backends_with_external_name) do
        sync_backend(backend_with_external_name)
      end
    end
    
    local function sync_backends()
      local raw_backends_last_synced_at = configuration.get_raw_backends_last_synced_at()
      ngx.update_time()
      local current_timestamp = ngx.time()
      if current_timestamp - backends_last_synced_at < BACKENDS_FORCE_SYNC_INTERVAL
          and raw_backends_last_synced_at <= backends_last_synced_at then
        return
      end
    
      local backends_data = configuration.get_backends_data()
      if not backends_data then
        balancers = {}
        return
      end
    
      local new_backends, err = cjson.decode(backends_data)
      if not new_backends then
        ngx.log(ngx.ERR, "could not parse backends data: ", err)
        return
      end
    
      local balancers_to_keep = {}
      for _, new_backend in ipairs(new_backends) do
        if is_backend_with_external_name(new_backend) then
          local backend_with_external_name = util.deepcopy(new_backend)
          backends_with_external_name[backend_with_external_name.name] = backend_with_external_name
        else
          sync_backend(new_backend)
        end
        balancers_to_keep[new_backend.name] = true
      end
    
      for backend_name, _ in pairs(balancers) do
        if not balancers_to_keep[backend_name] then
          balancers[backend_name] = nil
          backends_with_external_name[backend_name] = nil
        end
      end
      backends_last_synced_at = raw_backends_last_synced_at
    end
    
    local function route_to_alternative_balancer(balancer)
      if balancer.is_affinitized(balancer) then
        -- If request is already affinitized to a primary balancer, keep the primary balancer.
        return false
      end
    
      if not balancer.alternative_backends then
        return false
      end
    
      -- TODO: support traffic shaping for n > 1 alternative backends
      local backend_name = balancer.alternative_backends[1]
      if not backend_name then
        ngx.log(ngx.ERR, "empty alternative backend")
        return false
      end
    
      local alternative_balancer = balancers[backend_name]
      if not alternative_balancer then
        ngx.log(ngx.ERR, "no alternative balancer for backend: ",
                tostring(backend_name))
        return false
      end
    
      if alternative_balancer.is_affinitized(alternative_balancer) then
        -- If request is affinitized to an alternative balancer, instruct caller to
        -- switch to alternative.
        return true
      end
    
      -- Use traffic shaping policy, if request didn't have affinity set.
      local traffic_shaping_policy =  alternative_balancer.traffic_shaping_policy
      if not traffic_shaping_policy then
        ngx.log(ngx.ERR, "traffic shaping policy is not set for balancer ",
                "of backend: ", tostring(backend_name))
        return false
      end
    
      local target_header = util.replace_special_char(traffic_shaping_policy.header,
                                                      "-", "_")
      local header = ngx.var["http_" .. target_header]
      if header then
        if traffic_shaping_policy.headerValue
           and #traffic_shaping_policy.headerValue > 0 then
          if traffic_shaping_policy.headerValue == header then
            return true
          end
        elseif traffic_shaping_policy.headerPattern
           and #traffic_shaping_policy.headerPattern > 0 then
          local m, err = ngx.re.match(header, traffic_shaping_policy.headerPattern)
          if m then
            return true
          elseif  err then
              ngx.log(ngx.ERR, "error when matching canary-by-header-pattern: '",
                      traffic_shaping_policy.headerPattern, "', error: ", err)
              return false
          end
        elseif header == "always" then
          return true
        elseif header == "never" then
          return false
        end
      end
    
      local target_cookie = traffic_shaping_policy.cookie
      local cookie = ngx.var["cookie_" .. target_cookie]
      if cookie then
        if cookie == "always" then
          return true
        elseif cookie == "never" then
          return false
        end
      end
    
      if math.random(100) <= traffic_shaping_policy.weight then
        return true
      end
    
      return false
    end
    
    local function get_balancer_by_upstream_name(upstream_name)
      return balancers[upstream_name]
    end
    
    local function get_balancer()
      if ngx.ctx.balancer then
        return ngx.ctx.balancer
      end
    
      local backend_name = ngx.var.proxy_upstream_name
    
      local balancer = balancers[backend_name]
      if not balancer then
        return nil
      end
    
      if route_to_alternative_balancer(balancer) then
        local alternative_backend_name = balancer.alternative_backends[1]
        ngx.var.proxy_alternative_upstream_name = alternative_backend_name
    
        balancer = balancers[alternative_backend_name]
      end
    
      ngx.ctx.balancer = balancer
    
      return balancer
    end
    
    function _M.init_worker()
      -- when worker starts, sync non ExternalName backends without delay
      sync_backends()
      -- we call sync_backends_with_external_name in timer because for endpoints that require
      -- DNS resolution it needs to use socket which is not available in
      -- init_worker phase
      local ok, err = ngx.timer.at(0, sync_backends_with_external_name)
      if not ok then
        ngx.log(ngx.ERR, "failed to create timer: ", err)
      end
    
      ok, err = ngx.timer.every(BACKENDS_SYNC_INTERVAL, sync_backends)
      if not ok then
        ngx.log(ngx.ERR, "error when setting up timer.every for sync_backends: ", err)
      end
      ok, err = ngx.timer.every(BACKENDS_SYNC_INTERVAL, sync_backends_with_external_name)
      if not ok then
        ngx.log(ngx.ERR, "error when setting up timer.every for sync_backends_with_external_name: ",
                err)
      end
    end
    
    function _M.rewrite()
      local balancer = get_balancer()
      if not balancer then
        ngx.status = ngx.HTTP_SERVICE_UNAVAILABLE
        return ngx.exit(ngx.status)
      end
    end
    
    function _M.balance()
      local balancer = get_balancer()
      if not balancer then
        return
      end
    
      local peer = balancer:balance()
      if not peer then
        ngx.log(ngx.WARN, "no peer was returned, balancer: " .. balancer.name)
        return
      end
    
      if peer:match(PROHIBITED_PEER_PATTERN) then
        ngx.log(ngx.ERR, "attempted to proxy to self, balancer: ", balancer.name, ", peer: ", peer)
        return
      end
    
      ngx_balancer.set_more_tries(1)
    
      local ok, err = ngx_balancer.set_current_peer(peer)
      if not ok then
        ngx.log(ngx.ERR, "error while setting current upstream peer ", peer,
                ": ", err)
      end
    end
    
    function _M.log()
      local balancer = get_balancer()
      if not balancer then
        return
      end
    
      if not balancer.after_balance then
        return
      end
    
      balancer:after_balance()
    end
    
    setmetatable(_M, {__index = {
      get_implementation = get_implementation,
      sync_backend = sync_backend,
      route_to_alternative_balancer = route_to_alternative_balancer,
      get_balancer = get_balancer,
      get_balancer_by_upstream_name = get_balancer_by_upstream_name,
    }})
    
    return _M
  • 相关阅读:
    LoadRunner FAQ
    LoadRunner下载文件脚本
    Loadrunner上传文件解决办法(大文件)
    LoadRunner中的IP欺骗的设置以及误区
    Loadrunner11在win7下录制脚本,ie打不开
    LoadRunner检查点实战
    设置Loadrunner负载机临时文件目录
    ArcGIS中国工具,版权声明,本人没有授权任何单位和个人销售,其他都是盗版,为了你个人和单位利益,请勿购买。 销售QQ:27652980,853740877,电话:18987281928,13108507190,qq群310964401
    勘测定界软件,增加平方米和公顷,小数进位面积不平,自动调平功能;不够线状扣除负面积自动处理功能 ​​​​
    arcgis 获得工具箱工具的个数
  • 原文地址:https://www.cnblogs.com/it-worker365/p/15216536.html
Copyright © 2011-2022 走看看