Skip to content

Commit

Permalink
custom trafficRouting
Browse files Browse the repository at this point in the history
Signed-off-by: Kuromesi <[email protected]>
  • Loading branch information
Kuromesi committed Jul 17, 2023
1 parent 9a062e0 commit 62a9273
Show file tree
Hide file tree
Showing 10 changed files with 250 additions and 282 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
rollout:
apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:
name: rollouts-demo
namespace: demo
annotations:
rollouts.kruise.io/rolling-style: canary
spec:
disabled: false
objectRef:
workloadRef:
apiVersion: apps/v1
kind: Deployment
name: nginx-deployment
strategy:
canary:
steps:
- weight: 20
matches:
- headers:
- type: Exact
name: user-agent
value: pc
- type: RegularExpression
name: name
value: ".*demo"
- weight: 50
trafficRoutings:
- service: nginx-service
networkRefs:
- apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
name: nginx-vs
original:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx-vs
namespace: demo
spec:
hosts:
- "*"
gateways:
- nginx-gateway
http:
- route:
- destination:
host: nginx-service
expected:
- apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx-vs
namespace: demo
spec:
hosts:
- "*"
gateways:
- nginx-gateway
http:
- match:
- headers:
user-agent:
exact: pc
name:
regex: .*demo
route:
- destination:
host: nginx-service
weight: 80
- destination:
host: nginx-service-canary
weight: 20
- route:
- destination:
host: nginx-service
- apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx-vs
namespace: demo
spec:
hosts:
- "*"
gateways:
- nginx-gateway
http:
- route:
- destination:
host: nginx-service
weight: 50
- destination:
host: nginx-service-canary
weight: 50

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
-- obj = {
-- matches = {
-- {
-- headers = {
-- uri = {
-- {
-- name = "xxx",
-- value = "xxx",
-- type = "RegularExpression"
-- type = "Prefix"
-- }
-- }
-- }
Expand Down Expand Up @@ -41,37 +41,6 @@

spec = obj.data.spec

-- AN VIRUTALSERVICE EMXAPLE
-- apiVersion: networking.istio.io/v1alpha3
-- kind: VirtualService
-- metadata:
-- name: productpage
-- namespace: nsA
-- spec:
-- http:
-- - match:
-- - uri:
-- prefix: "/productpage/v1/"
-- route:
-- - destination:
-- host: productpage-v1.nsA.svc.cluster.local
-- - route:
-- - destination:
-- host: productpage.nsA.svc.cluster.local

function DeepCopy(original)
local copy
if type(original) == 'table' then
copy = {}
for key, value in pairs(original) do
copy[key] = DeepCopy(value)
end
else
copy = original
end
return copy
end

-- find matched route of VirtualService spec with stable svc
function FindMatchedRules(spec, stableService)
local matchedRoutes = {}
Expand Down Expand Up @@ -101,35 +70,6 @@ function FindMatchedRules(spec, stableService)
return matchedRoutes
end

function FindMatchedDestination(spec, stableService)
local matchedDst = {}
local rules = {}
if (spec.http) then
for _, http in ipairs(spec.http) do
table.insert(rules, http)
end
end
if (spec.tls) then
for _, tls in ipairs(spec.tls) do
table.insert(rules, tls)
end
end
if (spec.tcp) then
for _, tcp in ipairs(spec.tcp) do
table.insert(rules, tcp)
end
end
for _, rule in ipairs(rules) do
for _, route in ipairs(rule.route) do
if route.destination.host == stableService then
matchedDst = route.destination
return matchedDst
end
end
end
return matchedDst
end

-- generate routes with matches
function GenerateMatchedRoutes(spec, matches, stableService, canaryService, stableWeight, canaryWeight)
local route = {}
Expand All @@ -139,28 +79,33 @@ function GenerateMatchedRoutes(spec, matches, stableService, canaryService, stab
local vsMatch = {}
vsMatch[key] = {}
for _, rule in ipairs(value) do
if rule["type"] == "RegularExpression"
then
if rule["type"] == "RegularExpression" then
matchType = "regex"
else
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
vsMatch[key][rule["name"]] = {}
vsMatch[key][rule["name"]][matchType] = rule["value"]
end
table.insert(route["match"], vsMatch)
end
end
local matchedDst = FindMatchedDestination(spec, stableService)
route["route"] = {
{
destination = DeepCopy(matchedDst),
destination = {
host = stableService,
},
weight = stableWeight,
},
{
destination = {
host = canaryService,
port = DeepCopy(matchedDst.port)
},
weight = canaryWeight,
}
Expand All @@ -180,9 +125,6 @@ function GenerateRoutes(spec, stableService, canaryService, stableWeight, canary
}
for _, route in ipairs(rule.route) do
-- incase there are multiple versions traffic already
if (route.destination.host == stableService) then
canary.destination.port = DeepCopy(route.destination.port)
end
if (route.weight) then
route.weight = math.floor(route.weight * stableWeight / 100)
else
Expand Down
1 change: 1 addition & 0 deletions pkg/controller/rollout/rollout_canary.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ func (m *canaryReleaseManager) doCanaryFinalising(c *RolloutContext) (bool, erro
} else if !done {
return false, nil
}
m.trafficRoutingManager.RemoveTrafficRoutingController(tr)
klog.Infof("rollout(%s/%s) doCanaryFinalising success", c.Rollout.Namespace, c.Rollout.Name)
return true, nil
}
Expand Down
31 changes: 24 additions & 7 deletions pkg/trafficrouting/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ func (m *Manager) InitializeTrafficRouting(c *TrafficRoutingContext) error {
cService := getCanaryServiceName(sService, c.OnlyTrafficRouting)
// new network provider
key := fmt.Sprintf("%s.%s", c.Key, sService)
// if _, ok := ControllerMap[key]; ok {
// return nil
// }
if _, ok := ControllerMap[key]; ok {
return nil
}
trController, err := newNetworkProvider(m.Client, c, sService, cService)
if err != nil {
klog.Errorf("%s newNetworkProvider failed: %s", c.Key, err.Error())
Expand Down Expand Up @@ -204,6 +204,7 @@ func (m *Manager) DoTrafficRouting(c *TrafficRoutingContext) (bool, error) {
}

func (m *Manager) FinalisingTrafficRouting(c *TrafficRoutingContext, onlyRestoreStableService bool) (bool, error) {
var err error
if len(c.ObjectRef) == 0 {
return true, nil
}
Expand All @@ -217,12 +218,17 @@ func (m *Manager) FinalisingTrafficRouting(c *TrafficRoutingContext, onlyRestore
trController, ok := ControllerMap[key].(network.NetworkProvider)
if !ok {
klog.Errorf("failed to fetch newNetworkProvider: %s", key)
return false, nil
// when finalising, InitializeTrafficRouting checks are not necessary
trController, err = newNetworkProvider(m.Client, c, trafficRouting.Service, cServiceName)
if err != nil {
klog.Errorf("%s newTrafficRoutingController failed: %s", c.Key, err.Error())
return false, err
}
ControllerMap[key] = trController
}

cService := &corev1.Service{ObjectMeta: metav1.ObjectMeta{Namespace: c.Namespace, Name: cServiceName}}
// if canary svc has been already cleaned up, just return
if err := m.Get(context.TODO(), client.ObjectKeyFromObject(cService), cService); err != nil {
if err = m.Get(context.TODO(), client.ObjectKeyFromObject(cService), cService); err != nil {
if !errors.IsNotFound(err) {
klog.Errorf("%s get canary service(%s) failed: %s", c.Key, cServiceName, err.Error())
return false, err
Expand Down Expand Up @@ -271,10 +277,21 @@ func (m *Manager) FinalisingTrafficRouting(c *TrafficRoutingContext, onlyRestore
return false, err
}
klog.Infof("%s remove canary service(%s) success", c.Key, cService.Name)
// delete(ControllerMap, key)
return true, nil
}

// remove controller stored in controllerMap
func (m *Manager) RemoveTrafficRoutingController(c *TrafficRoutingContext) {
trafficRouting := c.ObjectRef[0]
key := fmt.Sprintf("%s.%s", c.Key, trafficRouting.Service)
_, ok := ControllerMap[key].(network.NetworkProvider)
if !ok {
klog.Errorf("TrafficRouting controller does not exist: %s", key)
} else {
delete(ControllerMap, key)
}
}

func newNetworkProvider(c client.Client, con *TrafficRoutingContext, sService, cService string) (network.NetworkProvider, error) {
trafficRouting := con.ObjectRef[0]
if trafficRouting.NetworkRefs != nil {
Expand Down
Loading

0 comments on commit 62a9273

Please sign in to comment.