From 07b7f20f6a82e960b371c0b2bb84c371724f9bd9 Mon Sep 17 00:00:00 2001 From: Kuromesi <87558945+Kuromesi@users.noreply.github.com> Date: Mon, 6 Nov 2023 17:34:57 +0800 Subject: [PATCH] add lua scripts for istio (#178) * add lua scripts for istio Signed-off-by: Kuromesi * make some improvements for istio lua script Signed-off-by: Kuromesi --------- Signed-off-by: Kuromesi --- .../convert_test_case_to_lua_object.go | 2 +- .../traffic_routing_with_a_match.yaml | 49 +++++++ .../DestinationRule/trafficRouting.lua | 8 ++ .../testdata/rollout_with_three_steps.yaml | 122 +++++++++++++++++ .../traffic_routing_with_a_match.yaml | 61 +++++++++ .../traffic_routing_with_matches.yaml | 68 ++++++++++ .../testdata/traffic_routing_with_weight.yaml | 50 +++++++ .../VirtualService/trafficRouting.lua | 125 ++++++++++++++++++ 8 files changed, 484 insertions(+), 1 deletion(-) create mode 100644 lua_configuration/networking.istio.io/DestinationRule/testdata/traffic_routing_with_a_match.yaml create mode 100644 lua_configuration/networking.istio.io/DestinationRule/trafficRouting.lua create mode 100644 lua_configuration/networking.istio.io/VirtualService/testdata/rollout_with_three_steps.yaml create mode 100644 lua_configuration/networking.istio.io/VirtualService/testdata/traffic_routing_with_a_match.yaml create mode 100644 lua_configuration/networking.istio.io/VirtualService/testdata/traffic_routing_with_matches.yaml create mode 100644 lua_configuration/networking.istio.io/VirtualService/testdata/traffic_routing_with_weight.yaml create mode 100644 lua_configuration/networking.istio.io/VirtualService/trafficRouting.lua diff --git a/lua_configuration/convert_test_case_to_lua_object.go b/lua_configuration/convert_test_case_to_lua_object.go index dadf3ba9..c8481c4a 100644 --- a/lua_configuration/convert_test_case_to_lua_object.go +++ b/lua_configuration/convert_test_case_to_lua_object.go @@ -138,7 +138,7 @@ func objectToTable(path string) error { return fmt.Errorf("failed to open file: %s", err) } defer fileStream.Close() - header := "-- THIS IS GENERATED BY LUA.GO FOR DEBUGGING --\n" + header := "-- THIS IS GENERATED BY CONVERT_TEST_CASE_TO_LUA_OBJECT.GO FOR DEBUGGING --\n" _, err = io.WriteString(fileStream, header+objStr) if err != nil { return fmt.Errorf("failed to WriteString %s", err) diff --git a/lua_configuration/networking.istio.io/DestinationRule/testdata/traffic_routing_with_a_match.yaml b/lua_configuration/networking.istio.io/DestinationRule/testdata/traffic_routing_with_a_match.yaml new file mode 100644 index 00000000..3d5e3be4 --- /dev/null +++ b/lua_configuration/networking.istio.io/DestinationRule/testdata/traffic_routing_with_a_match.yaml @@ -0,0 +1,49 @@ +trafficRouting: + apiVersion: rollouts.kruise.io/v1alpha1 + kind: TrafficRouting + metadata: + name: tr-demo + spec: + strategy: + matches: + - headers: + - type: Exact + name: version + value: canary + objectRef: + - service: svc-demo + customNetworkRefs: + - apiVersion: networking.istio.io/v1beta1 + kind: DestinationRule + name: ds-demo +original: + apiVersion: networking.istio.io/v1beta1 + kind: DestinationRule + metadata: + name: ds-demo + spec: + host: svc-demo + trafficPolicy: + loadBalancer: + simple: ROUND_ROBIN + subsets: + - labels: + version: base + name: version-base +expected: + - apiVersion: networking.istio.io/v1beta1 + kind: DestinationRule + metadata: + name: ds-demo + spec: + host: svc-demo + trafficPolicy: + loadBalancer: + simple: ROUND_ROBIN + subsets: + - labels: + version: base + name: version-base + - labels: + istio.service.tag: gray + name: canary \ No newline at end of file diff --git a/lua_configuration/networking.istio.io/DestinationRule/trafficRouting.lua b/lua_configuration/networking.istio.io/DestinationRule/trafficRouting.lua new file mode 100644 index 00000000..3df3aace --- /dev/null +++ b/lua_configuration/networking.istio.io/DestinationRule/trafficRouting.lua @@ -0,0 +1,8 @@ +local spec = obj.data.spec +local canary = {} +canary.labels = {} +canary.name = "canary" +local podLabelKey = "istio.service.tag" +canary.labels[podLabelKey] = "gray" +table.insert(spec.subsets, canary) +return obj.data \ No newline at end of file diff --git a/lua_configuration/networking.istio.io/VirtualService/testdata/rollout_with_three_steps.yaml b/lua_configuration/networking.istio.io/VirtualService/testdata/rollout_with_three_steps.yaml new file mode 100644 index 00000000..0a9eb98b --- /dev/null +++ b/lua_configuration/networking.istio.io/VirtualService/testdata/rollout_with_three_steps.yaml @@ -0,0 +1,122 @@ +rollout: + apiVersion: rollouts.kruise.io/v1alpha1 + kind: Rollout + metadata: + name: rollouts-demo + annotations: + rollouts.kruise.io/rolling-style: canary + spec: + disabled: false + objectRef: + workloadRef: + apiVersion: apps/v1 + kind: Deployment + name: deploy-demo + strategy: + canary: + steps: + - matches: + - headers: + - type: Exact + name: user-agent + value: pc + - type: RegularExpression + name: name + value: ".*demo" + - matches: + - headers: + - type: Exact + name: user-agent + value: pc + - headers: + - type: RegularExpression + name: name + value: ".*demo" + - weight: 50 + trafficRoutings: + - service: svc-demo + customNetworkRefs: + - apiVersion: networking.istio.io/v1alpha3 + kind: VirtualService + name: vs-demo +original: + apiVersion: networking.istio.io/v1alpha3 + kind: VirtualService + metadata: + name: vs-demo + spec: + hosts: + - "*" + gateways: + - nginx-gateway + http: + - route: + - destination: + host: svc-demo +expected: + - apiVersion: networking.istio.io/v1alpha3 + kind: VirtualService + metadata: + name: vs-demo + spec: + hosts: + - "*" + gateways: + - nginx-gateway + http: + - match: + - headers: + user-agent: + exact: pc + name: + regex: .*demo + route: + - destination: + host: svc-demo-canary + - route: + - destination: + host: svc-demo + - apiVersion: networking.istio.io/v1alpha3 + kind: VirtualService + metadata: + name: vs-demo + spec: + hosts: + - "*" + gateways: + - nginx-gateway + http: + - match: + - headers: + name: + regex: .*demo + route: + - destination: + host: svc-demo-canary + - match: + - headers: + user-agent: + exact: pc + route: + - destination: + host: svc-demo-canary + - route: + - destination: + host: svc-demo + - apiVersion: networking.istio.io/v1alpha3 + kind: VirtualService + metadata: + name: vs-demo + spec: + hosts: + - "*" + gateways: + - nginx-gateway + http: + - route: + - destination: + host: svc-demo + weight: 50 + - destination: + host: svc-demo-canary + weight: 50 diff --git a/lua_configuration/networking.istio.io/VirtualService/testdata/traffic_routing_with_a_match.yaml b/lua_configuration/networking.istio.io/VirtualService/testdata/traffic_routing_with_a_match.yaml new file mode 100644 index 00000000..cd5b99cd --- /dev/null +++ b/lua_configuration/networking.istio.io/VirtualService/testdata/traffic_routing_with_a_match.yaml @@ -0,0 +1,61 @@ +trafficRouting: + apiVersion: rollouts.kruise.io/v1alpha1 + kind: TrafficRouting + metadata: + name: tr-demo + spec: + strategy: + matches: + - headers: + - type: Exact + name: user-agent + value: pc + - type: RegularExpression + name: name + value: ".*demo" + objectRef: + - service: svc-demo + customNetworkRefs: + - apiVersion: networking.istio.io/v1alpha3 + kind: VirtualService + name: vs-demo +original: + apiVersion: networking.istio.io/v1alpha3 + kind: VirtualService + metadata: + name: vs-demo + spec: + hosts: + - "*" + gateways: + - nginx-gateway + http: + - route: + - destination: + host: svc-demo + subset: base +expected: + - apiVersion: networking.istio.io/v1alpha3 + kind: VirtualService + metadata: + name: vs-demo + spec: + hosts: + - "*" + gateways: + - nginx-gateway + http: + - match: + - headers: + user-agent: + exact: pc + name: + regex: .*demo + route: + - destination: + host: svc-demo + subset: canary + - route: + - destination: + host: svc-demo + subset: base diff --git a/lua_configuration/networking.istio.io/VirtualService/testdata/traffic_routing_with_matches.yaml b/lua_configuration/networking.istio.io/VirtualService/testdata/traffic_routing_with_matches.yaml new file mode 100644 index 00000000..26c7d7db --- /dev/null +++ b/lua_configuration/networking.istio.io/VirtualService/testdata/traffic_routing_with_matches.yaml @@ -0,0 +1,68 @@ +trafficRouting: + apiVersion: rollouts.kruise.io/v1alpha1 + kind: TrafficRouting + metadata: + name: tr-demo + spec: + strategy: + matches: + - headers: + - type: Exact + name: user-agent + value: pc + - headers: + - type: RegularExpression + name: name + value: ".*demo" + objectRef: + - service: svc-demo + customNetworkRefs: + - apiVersion: networking.istio.io/v1alpha3 + kind: VirtualService + name: vs-demo +original: + apiVersion: networking.istio.io/v1alpha3 + kind: VirtualService + metadata: + name: vs-demo + spec: + hosts: + - "*" + gateways: + - nginx-gateway + http: + - route: + - destination: + host: svc-demo + subset: base +expected: + - apiVersion: networking.istio.io/v1alpha3 + kind: VirtualService + metadata: + name: vs-demo + spec: + hosts: + - "*" + gateways: + - nginx-gateway + http: + - match: + - headers: + name: + regex: .*demo + route: + - destination: + host: svc-demo + subset: canary + - match: + - headers: + user-agent: + exact: pc + route: + - destination: + host: svc-demo + subset: canary + - route: + - destination: + host: svc-demo + subset: base \ No newline at end of file diff --git a/lua_configuration/networking.istio.io/VirtualService/testdata/traffic_routing_with_weight.yaml b/lua_configuration/networking.istio.io/VirtualService/testdata/traffic_routing_with_weight.yaml new file mode 100644 index 00000000..9ab4bbb8 --- /dev/null +++ b/lua_configuration/networking.istio.io/VirtualService/testdata/traffic_routing_with_weight.yaml @@ -0,0 +1,50 @@ +trafficRouting: + apiVersion: rollouts.kruise.io/v1alpha1 + kind: TrafficRouting + metadata: + name: tr-demo + spec: + strategy: + weight: 50 + objectRef: + - service: svc-demo + customNetworkRefs: + - apiVersion: networking.istio.io/v1alpha3 + kind: VirtualService + name: vs-demo +original: + apiVersion: networking.istio.io/v1alpha3 + kind: VirtualService + metadata: + name: vs-demo + spec: + hosts: + - "*" + gateways: + - nginx-gateway + http: + - route: + - destination: + host: svc-demo + subset: base +expected: + - apiVersion: networking.istio.io/v1alpha3 + kind: VirtualService + metadata: + name: nginx-vs + namespace: demo + spec: + hosts: + - "*" + gateways: + - nginx-gateway + http: + - route: + - destination: + host: svc-demo + subset: base + weight: 50 + - destination: + host: svc-demo + subset: canary + weight: 50 diff --git a/lua_configuration/networking.istio.io/VirtualService/trafficRouting.lua b/lua_configuration/networking.istio.io/VirtualService/trafficRouting.lua new file mode 100644 index 00000000..27b9ace5 --- /dev/null +++ b/lua_configuration/networking.istio.io/VirtualService/trafficRouting.lua @@ -0,0 +1,125 @@ +spec = obj.data.spec + +if obj.canaryWeight == -1 then + obj.canaryWeight = 100 + obj.stableWeight = 0 +end + +function GetHost(destination) + local host = destination.destination.host + dot_position = string.find(host, ".", 1, true) + if (dot_position) then + host = string.sub(host, 1, dot_position - 1) + end + return host +end + +-- find routes of VirtualService with stableService +function GetRulesToPatch(spec, stableService, protocol) + local matchedRoutes = {} + if (spec[protocol] ~= nil) then + for _, rule in ipairs(spec[protocol]) do + -- skip routes contain matches + if (rule.match == nil) then + for _, route in ipairs(rule.route) do + if GetHost(route) == stableService then + table.insert(matchedRoutes, rule) + end + end + end + end + end + return matchedRoutes +end + +function CalculateWeight(route, stableWeight, n) + local weight + if (route.weight) then + weight = math.floor(route.weight * stableWeight / 100) + else + weight = math.floor(stableWeight / n) + end + return weight +end + +-- generate routes with matches, insert a rule before other rules, only support http headers, cookies etc. +function GenerateRoutesWithMatches(spec, matches, stableService, canaryService) + for _, match in ipairs(matches) do + local route = {} + route["match"] = {} + for key, value in pairs(match) do + local vsMatch = {} + vsMatch[key] = {} + for _, rule in ipairs(value) do + if rule["type"] == "RegularExpression" then + matchType = "regex" + elseif rule["type"] == "Exact" then + matchType = "exact" + elseif rule["type"] == "Prefix" then + matchType = "prefix" + end + if key == "headers" then + vsMatch[key][rule["name"]] = {} + vsMatch[key][rule["name"]][matchType] = rule.value + else + vsMatch[key][matchType] = rule.value + end + end + table.insert(route["match"], vsMatch) + end + route.route = { + { + destination = {} + } + } + -- stableService == canaryService indicates DestinationRule exists and subset is set to be canary by default + if stableService == canaryService then + route.route[1].destination.host = stableService + route.route[1].destination.subset = "canary" + else + route.route[1].destination.host = canaryService + end + table.insert(spec.http, 1, route) + end +end + +-- generate routes without matches, change every rule whose host is stableService +function GenerateRoutes(spec, stableService, canaryService, stableWeight, canaryWeight, protocol) + local matchedRules = GetRulesToPatch(spec, stableService, protocol) + for _, rule in ipairs(matchedRules) do + local canary + if stableService ~= canaryService then + canary = { + destination = { + host = canaryService, + }, + weight = canaryWeight, + } + else + canary = { + destination = { + host = stableService, + subset = "canary", + }, + weight = canaryWeight, + } + end + + -- incase there are multiple versions traffic already, do a for-loop + for _, route in ipairs(rule.route) do + -- update stable service weight + route.weight = CalculateWeight(route, stableWeight, #rule.route) + end + table.insert(rule.route, canary) + end +end + +if (obj.matches) +then + GenerateRoutesWithMatches(spec, obj.matches, obj.stableService, obj.canaryService) +else + GenerateRoutes(spec, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, "http") + GenerateRoutes(spec, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, "tcp") + GenerateRoutes(spec, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, "tls") +end +return obj.data