-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support multiple feed-ingress controllers per environment #195
Conversation
b05cd5d
to
98f3fb8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've suggested a few changes from the current setup, however, I always wanted to bring up a slight change to the way it's implemented. Rather than having it a global option I think this should be to support multiple elb ingresses which means some of the code can come out of the controller and into the elb code. Additionally we can rename the flag elb-ingress-name-tag-value
? I think making it global makes it seem like this is supported across all of the updaters, which it isn't (and the implementation my be very different for those too).
cmd/feed-ingress/main.go
Outdated
@@ -40,6 +40,8 @@ var ( | |||
pushgatewayIntervalSeconds int | |||
pushgatewayLabels cmd.KeyValues | |||
controllerConfig controller.Config | |||
mainIngress bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it might be clearer to call this variable defaultIngress
and have ingressName
default to main
so that as a user, by default this feed instance can act as the default controller and attach to the main elb pair.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
have
ingressName
default tomain
so that as a user, by default this feed instance can act as the default controller and attach to the main elb pair.
I thought about this but decided it was safer to not default to main. The reason is that if a test instance is deployed without this configuration it would then attach to the main ELBs and potentially break the main ingress. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
couldn't we have an ingress without a name? and avoid this main boolean?
I am just unsure as of why do we need it. If we want to maintain backwards compatibility, a nameless feed would be a way to have it, and if you want specific ingresses, you name them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
couldn't we have an ingress without a name? and avoid this main boolean?
I am just unsure as of why do we need it. If we want to maintain backwards compatibility, a nameless feed would be a way to have it, and if you want specific ingresses, you name them
The three of us discussed the two approaches:
- The current implementation of a 'main' feed that handles ingresses that don't have an ingress name specified for backwards compatibility
- requires the main elbs to be tagged and feed-ingress can only attach if it's given the tag value
- this is a safety feature to ensure that test feed-ingress pods that haven't been configured don't attach to the main elbs
- requires an extra bool argument so that the main feed-ingress instance know to handle ingresses without a name, for backwards compatibility
- An ingress that doesn't have a name that will be the main ingress
- don't add the ingress-name tag to the main elb and never add ingress-name to ingresses that are for the main / default elb
- doesn't require the main-ingress bool to handle two cases
- may need to update the logic that attaches to the elb to handle the no tag case
- potential risk that test pods without ingress-name specified could attach to the main elb
- could mitigate this by e.g. requiring the ingress-name arg and checking that it's not the same as a default randomly generated string (although, there's still a chance that someone will set a required arg to an empty string if they are just playing around :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- don't add the ingress-name tag to the main elb ...
- may need to update the logic that attaches to the elb to handle the no tag case
we also said that we could intentionally add the tag our current elb with an empty name, so that the logic needs no change. I think an empty string is valid (unnamed).
- (although, there's still a chance that someone will set a required arg to an empty string if they are just playing around :)
given that the params should be given as either --main-ingress
(option 1) or --ingress-name ""
(option 2), I'd say that there are more chances of people accidentally using --main-ingress.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
--main-ingress
defaults to false so this would need to be given as --main-ingress=true
(or one of the other variants of true) so you would have to intentionally being setting it. Still not fool proof so not ideal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think flags are not really the mechanism we would use to prevent one feed-ingress attaching to an incorrect elb by miss-configuration. It would probably be more on the side of "does this instance of feed has credentials with permissions to attach itself to this elb?"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In our case, test elbs can't actually attach to the main elb because they get a different role. But that's just how we've done it (recently) and not provided by feed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah great! In my opinion this should be that safety mechanism :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am of the opinion that the boolean field may not be necessary. This is because we are anyways advertising this as a breaking change, which means we can lose backwards compatibility. I would suggest for the feed ingress to process only those entries with the name annotation matching the name of the ingress and ignore anything which does not contain the name.
It would still be a seamless change for the application teams at least in our case because we can make the change in k8plugin to have a name defaulted to "the main ingress" (which is the equivalent of the current breed of ingress we have). There can be a cut-off date before which all the teams should specify the ingress name.
I am not fully convinced that we need to protect the test app getting processed by the main/default ingress. Such a mechanism does not exist now and also there's nothing stopping from the test ingress attaching to the main ELB by starting with the corresponding name. Such mistakes can be caught via monitoring and alerting and am not convinced we need a boolean flag to protect.
I would simply make the name mandatory for the ingress to start and a corresponding ELB with a tag matching the ingress name, without which the ingress should not get to running state.
elb/elb.go
Outdated
initMetrics() | ||
log.Infof("ELB Front end region: %s cluster: %s expected frontends: %d", region, labelValue, expectedNumber) | ||
log.Infof("ELB Front end region: %s cluster: %s expected frontends: %d", region, frontendTagValue, expectedNumber) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to include the ingress name tag here too
elb/elb.go
Outdated
clusterFrontEnds[lb.Scheme] = lb | ||
} | ||
for _, elbDescription := range output.TagDescriptions { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New line can be removed
elb/elb.go
Outdated
} | ||
} | ||
} | ||
return clusterFrontEnds, nil | ||
} | ||
|
||
func tagsDoMatch(elbTags []*aws_elb.Tag, tagsToMatch map[string]string) bool { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New line can be removed
As discussed the ELB updater, nginx updater and ingress updater all have to apply these changes. Actually the nginx updater doesn't need to do anything special as the controller filters the ingresses but if it didn't then the nginx updater would have to. So I do think it's a global change as all parts have to work together for this to work. |
} | ||
|
||
return isValid | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this could be simplified as
} | |
if ingressName, ok := ingress.Annotations[ingressNameAnnotation]; ok { | |
return ingressName == c.ingressName | |
} | |
return c.mainIngress |
elb/elb.go
Outdated
initMetrics() | ||
log.Infof("ELB Front end region: %s cluster: %s expected frontends: %d", region, labelValue, expectedNumber) | ||
log.Infof("ELB Front end region: %s, cluster: %s, expected frontends: %d, ingress name: %s", region, frontendTagValue, expectedNumber, ingressNameTagValue) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is cluster
the right label for frontendTagValue
?
cmd/feed-ingress/main.go
Outdated
@@ -40,6 +40,8 @@ var ( | |||
pushgatewayIntervalSeconds int | |||
pushgatewayLabels cmd.KeyValues | |||
controllerConfig controller.Config | |||
mainIngress bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
couldn't we have an ingress without a name? and avoid this main boolean?
I am just unsure as of why do we need it. If we want to maintain backwards compatibility, a nameless feed would be a way to have it, and if you want specific ingresses, you name them.
controller/controller.go
Outdated
if address := serviceMap[serviceName]; address != "" { | ||
if address := serviceMap[serviceName]; address == "" { | ||
skipped = append(skipped, fmt.Sprintf("%s/%s (service doesn't exist)", ingress.Namespace, ingress.Name)) | ||
} else if !c.validIngressName(ingress) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
based on this context, I am not sure validIngressName
is quite appropriate.
Is it not something more of the sorts of "can this feed handle this name"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simplifies this logic as per my above comment as it is mandatory for the ingress entries to have a name, else they will be ignored. No need to have an additional check on the boolean flag to allow these anonymous entries.
} | ||
|
||
return matches == len(tagsToMatch) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should approach this differently, so that we don't loop over the elbTags for each tag to Match:
- convert the elbTags to a map first (1 loop),
- iterate over the tagsToMatch (1 loop)
- if the tag to match key and value are not on the elb tags map, return false.
- return true.
I added a comment above but think it may get lost: #195 (comment) |
FoMO :D |
@@ -15,6 +15,7 @@ import ( | |||
"github.com/sky-uk/feed/k8s" | |||
"github.com/sky-uk/feed/util" | |||
v1 "k8s.io/client-go/pkg/api/v1" | |||
"k8s.io/client-go/pkg/apis/extensions/v1beta1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might need to use apps/v1
package for deployments now that we are on 1.10 k8s.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for the simplicity of the code for such a fundamental change and also for the test coverage. But, I am in favour of losing the boolean flag and making the change in the k8-plugin. This would mean that we will have to defer the rollout of this version of feed ingress till the time people have upgraded to the newer version of k8plugin. Most application teams just use the major version with a wildcard in their grade dependency eg. 22.+
This would mean a seamless change for them. But we will need to give some time for teams which don't do this and having a need to use feed ingress to upgrade to the version of k8s plugin which provides default ingress names.
There seem to be some outstanding questions around the implementation of this and I think we should come to an agreement together before making further changes to the code. I'll assign it back to @domleb so we can discuss and agree a solution. |
Removed from review as this is in the backlog at the moment and not being worked on |
Also instruct go to update the packages in setup to ensure local and travis build are run with the latest version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtM!
We aren't using a default ingress-controller name now so Pete's review is no longer applicable
instructs feed-ingress to process ingress resources without the sky.uk/ingress-controller-name annotation
@totahuanocotl I have added the |
on ingress resources instead of our custom sky one
After our group discussion I have renamed the ingress resource flag to be the standard Travis is complaining about formatting. Goodness knows why... locally works fine:
|
Use a consistent term for ELB tag and feed-ingress command-line flag
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One occurrence missed 🙈
elb/elb.go
Outdated
@@ -45,7 +45,7 @@ func New(region string, frontendTagValue string, ingressControllerNameTagValue s | |||
metadata: ec2metadata.New(session), | |||
awsElb: aws_elb.New(session), | |||
frontendTagValue: frontendTagValue, | |||
ingressControllerNameTagValue: ingressControllerNameTagValue, | |||
ingressControllerNameTagValue: ingressClassTagValue, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
elb.ingressControllerNameTagValue -> el.ingressClassTagValue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
D'oh!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtM!
For https://github.com/sky-uk/core-infrastructure/issues/3414
This is a breaking change for
feed-ingress
to support creating multiple ingresses per environment. This could be used for testingfeed-ingress
itself and for splitting traffic into different isolated ingresses per environment each with its own set of ELBs.The change has been applied to
feed-ingress
but notfeed-dns
. However the shared modules are backwards compatible and support both.This change now requires the
--ingress-controller-name
argument to be passed to thefeed-ingress
container and the target ELBs must be tagged withsky.uk/KubernetesClusterIngressControllerName
. It won't attached to an ELB if it can't find the tag and thus it's a breaking change. This was done to avoid the situation where a test instance could attach to the main ELBs for an environment if they haven't been tagged yet.The
sky.uk/KubernetesClusterIngressControllerName
tag must match with--ingress-controller-name
forfeed-ingress
to attach to the ELBs.Ingress resources should be tagged with the
kubernetes.io/ingress.class
annotation that should match the name of the feed-ingress instance (specified with the--ingress-controller-name
flag). Feed will adopt those ingress resources whose annotations match.For migration the (new, deprecated)
--include-unnamed-ingresses
flag may be supplied, in which case feed-ingress will adopt all ingresses without the annotation, in addition to those that match the controller name.required by https://github.com/sky-uk/core-infrastructure/issues/3414