-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Consistent hashing to a subset of nodes. It works like consistent hash,
but instead of mapping to a single node, we map to a subset of nodes.
- Loading branch information
Showing
17 changed files
with
434 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
--- | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: nginx-deployment | ||
labels: | ||
app: nginxhello | ||
spec: | ||
replicas: 10 | ||
selector: | ||
matchLabels: | ||
app: nginxhello | ||
template: | ||
metadata: | ||
labels: | ||
app: nginxhello | ||
spec: | ||
containers: | ||
- name: nginxhello | ||
image: gcr.io/kubernetes-e2e-test-images/echoserver:2.2 | ||
ports: | ||
- containerPort: 8080 | ||
env: | ||
- name: NODE_NAME | ||
valueFrom: | ||
fieldRef: | ||
fieldPath: spec.nodeName | ||
- name: POD_NAME | ||
valueFrom: | ||
fieldRef: | ||
fieldPath: metadata.name | ||
- name: POD_NAMESPACE | ||
valueFrom: | ||
fieldRef: | ||
fieldPath: metadata.namespace | ||
- name: POD_IP | ||
valueFrom: | ||
fieldRef: | ||
fieldPath: status.podIP | ||
|
||
--- | ||
kind: Service | ||
apiVersion: v1 | ||
metadata: | ||
name: nginxhello | ||
labels: | ||
app: nginxhello | ||
spec: | ||
selector: | ||
app: nginxhello | ||
ports: | ||
- name: http | ||
port: 80 | ||
targetPort: 8080 | ||
|
||
--- | ||
apiVersion: extensions/v1beta1 | ||
kind: Ingress | ||
metadata: | ||
annotations: | ||
nginx.ingress.kubernetes.io/upstream-hash-by: "$arg_predictorid" | ||
nginx.ingress.kubernetes.io/upstream-hash-by-subset: "true" | ||
nginx.ingress.kubernetes.io/upstream-hash-by-subset-size: "3" | ||
name: nginxhello-ingress | ||
namespace: default | ||
spec: | ||
backend: | ||
serviceName: nginxhello | ||
servicePort: 80 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
-- Consistent hashing to a subset of nodes. Instead of returning the same node | ||
-- always, we return the same subset always. | ||
|
||
local resty_chash = require("resty.chash") | ||
local util = require("util") | ||
|
||
local _M = { name = "chashsubset" } | ||
|
||
local function build_subset_map(backend) | ||
local endpoints = {} | ||
local subset_map = {} | ||
local subsets = {} | ||
local subset_size = backend["upstreamHashByConfig"]["upstream-hash-by-subset-size"] | ||
|
||
for _, endpoint in pairs(backend.endpoints) do | ||
table.insert(endpoints, endpoint) | ||
end | ||
|
||
local set_count = math.ceil(#endpoints/subset_size) | ||
local node_count = set_count * subset_size | ||
|
||
-- if we don't have enough endpoints, we reuse endpoints in the last set to | ||
-- keep the same number on all of them. | ||
local j = 1 | ||
for _ = #endpoints+1, node_count do | ||
table.insert(endpoints, endpoints[j]) | ||
j = j+1 | ||
end | ||
|
||
local k = 1 | ||
for i = 1, set_count do | ||
local subset = {} | ||
local subset_id = "set" .. tostring(i) | ||
for _ = 1, subset_size do | ||
table.insert(subset, endpoints[k]) | ||
k = k+1 | ||
end | ||
subsets[subset_id] = subset | ||
subset_map[subset_id] = 1 | ||
end | ||
|
||
return subset_map, subsets | ||
end | ||
|
||
function _M.new(self, backend) | ||
local subset_map, subsets = build_subset_map(backend) | ||
|
||
local o = { | ||
instance = resty_chash:new(subset_map), | ||
hash_by = backend["upstreamHashByConfig"]["upstream-hash-by"], | ||
subsets = subsets, | ||
current_endpoints = backend.endpoints | ||
} | ||
setmetatable(o, self) | ||
self.__index = self | ||
return o | ||
end | ||
|
||
function _M.balance(self) | ||
local key = util.lua_ngx_var(self.hash_by) | ||
local subset_id = self.instance:find(key) | ||
local endpoints = self.subsets[subset_id] | ||
local endpoint = endpoints[math.random(#endpoints)] | ||
return endpoint.address .. ":" .. endpoint.port | ||
end | ||
|
||
function _M.sync(self, backend) | ||
local subset_map | ||
|
||
local changed = not util.deep_compare(self.current_endpoints, backend.endpoints) | ||
if not changed then | ||
return | ||
end | ||
|
||
self.current_endpoints = backend.endpoints | ||
|
||
subset_map, self.subsets = build_subset_map(backend) | ||
|
||
self.instance:reinit(subset_map) | ||
|
||
return | ||
end | ||
|
||
return _M |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.