{"id":13776798,"url":"https://github.com/rrfeng/lua-resty-upstream-etcd","last_synced_at":"2026-01-16T19:47:55.355Z","repository":{"id":95905074,"uuid":"54019284","full_name":"rrfeng/lua-resty-upstream-etcd","owner":"rrfeng","description":"An OpenResty lua module that can use upstream config in etcd and Kubernetes.","archived":false,"fork":false,"pushed_at":"2020-04-27T04:36:40.000Z","size":100,"stargazers_count":83,"open_issues_count":0,"forks_count":37,"subscribers_count":10,"default_branch":"master","last_synced_at":"2024-02-14T18:33:29.511Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rrfeng.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2016-03-16T09:41:23.000Z","updated_at":"2023-11-25T16:57:34.000Z","dependencies_parsed_at":null,"dependency_job_id":"ce7cf230-b859-4d09-91c3-4847ee9560f1","html_url":"https://github.com/rrfeng/lua-resty-upstream-etcd","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rrfeng%2Flua-resty-upstream-etcd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rrfeng%2Flua-resty-upstream-etcd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rrfeng%2Flua-resty-upstream-etcd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rrfeng%2Flua-resty-upstream-etcd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rrfeng","download_url":"https://codeload.github.com/rrfeng/lua-resty-upstream-etcd/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253551673,"owners_count":21926334,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T18:00:33.190Z","updated_at":"2026-01-16T19:47:55.348Z","avatar_url":"https://github.com/rrfeng.png","language":"Lua","readme":"# lua-resty-upstream-etcd\n\nA lua module for OpenResty, can dynamically update the upstreams from etcd and kubernetes.\n\n- Upstream realtime change from etcd or kubernetes apiserver, without reload.\n- Weighted round robin load balancing (not for kubernetes because of no `weight` settings of pod).\n- Healthcheck\n- Request statistics\n\n## REQUIREMENTS\n\n- openresty-1.9.11.1 and newer\n- balancer_by_lua\n- ngx.worker.id\n- lua-resty-http\n- cjson\n\n## USAGE\n\n### Prepare Etcd:\n```\netcdctl set /v1/testing/services/${service_name}/${host}:${port} ${value}\n```\n\nThe `service_name` is upstream's name, should be string.\nThe `host` is upstream's ip address, domain name not supported.\nThe `port` is upstream's port.\nThe `value` should be a json, if json parse error, will use the default value below:\n```\n{\n    \"weight\": 100,\n    \"check_url\": \"/health\",\n    \"slow_start\": 30,\n    \"status\": \"up\"\n}\n```\n\n- weight: upstream peer weight as number, int or float.\n- check_url: for healthcheck, if enabled, checker will do http request to `http://${host}:${port}${check_url}`.\n- slow_start: number of seconds duration that the upstream peer's weight slowly increased from `0` to `${weight}`\n- status: indicates the peer is up or down, must be `up` if you want the peer work, any other value means peer down.\n\n### Init the module:\n```\nlua_socket_log_errors off;   # recommend\nlua_package_path \"/path/of/your/environment...\";\n\nlua_shared_dict lreu_shm 1m;     # for global storage\nlua_shared_dict lreu_shm_k8s 1m; # for global storage\n\ninit_worker_by_lua_block {\n    local syncer = require \"lreu.syncer\"\n    syncer.init({\n        etcd_host = \"127.0.0.1\",\n        etcd_port = 2379,\n        etcd_path = \"/v1/testing/services/\",\n        storage = ngx.shared.lreu_shm\n    })\n\n    -- if you want to use k8s\n    local syncer_k8s = require \"lreu.syncer_k8s\"\n    sycner_k8s.init({\n        apiserver_host = \"127.0.0.1\",\n        apiserver_port = \"6443\",\n        namespace = \"default\",\n        token = \"the token\",\n        storage = ngx.shared.lreu_shm_k8s\n    })\n\n    -- init the picker before using it in balancer_by_lua\n    local picker = require \"lreu.picker\"\n\n    -- you can use both etcd and k8s\n    picker.init(ngx.shared.lreu_shm, ngx.shared.lreu_shm_k8s, true, ngx.shared.hc)\n\n    -- if you want to use health check\n    local health = require \"lreu.health\"\n    health.init({\n        storage = ngx.shared.lreu_upstream,\n        healthcheck = {\n            enable = true,\n            timeout = 3,\n            interval = 5,\n            max_fails = 3,\n            ok_status = {200, 204, 301, 302, 401, 403, 404}\n        },\n        logcheck = {\n            enable = true,\n            interval = 5,\n            recover = 60\n        }\n    })\n}\n```\n\n### Use picker in upstream:\n```\nupstream test {\n    server 127.0.0.1:2222; # fake server\n\n    balancer_by_lua_block {\n        local balancer = require \"ngx.balancer\"\n        local picker = require \"lreu.picker\"\n        local s, err = u.rr(\"my_test_service\")\n        if not s then\n            ngx.log(ngx.ERR, err)\n            return ngx.exit(500)\n        end\n        local ok, err = balancer.set_current_peer(s.host, s.port)\n        if not ok then\n            ngx.log(ngx.ERR, \"failed to set current peer: \" .. err)\n            return ngx.exit(500)\n        end\n    }\n}\n```\n\n### Functions\n#### picker.init(first_shm, second_shm?, merge?, hcshm?)\n`first_shm` and `second_shm` should be the storage of syncer. One or two.\nIf the `second_shm` provided, both used. but the `merge` controls the behavior:\n- `merge`==`true`: all peers in both shm merged together for load balancing.\n- `merge`==`false`: picker try to find peers in the `first_shm`, if found, use it; if no peers in `first_shm`, picker try the `second_shm`.\n\n`hcshm` is the storeage of `health.lua` checker, if not set, will use the `first_shm`.\n\n## Todo\n\n- More docs to be added.\n- Etcd cluster support.\n- Add more load-balance-alg.","funding_links":[],"categories":["Libraries"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frrfeng%2Flua-resty-upstream-etcd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frrfeng%2Flua-resty-upstream-etcd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frrfeng%2Flua-resty-upstream-etcd/lists"}