-
-
Notifications
You must be signed in to change notification settings - Fork 5.2k
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
Add app-root annotation support for kubernetes ingress #2522
Conversation
WDYT @containous/kubernetes ? |
PTAL thx |
I can see that this replicates the behaviour of the ngnix controller... but It seems a bit strange that this would only work when the path is set to I mean this does keep it consistent with how people expect this particular annotation to work so this is probably fine, and in any case I don't think implementing in this way precludes making this smarter in the future. So um yeah I think this will be fine, but will require a note in the documentation that gets added to say this annotation only has any effect when the path is Other than that this seems reasonable in that it is only small change, follows the existing "defacto" standard and if not enabled has no way of effecting anything seriously. So yeah with docs + tests I will be 👍 |
What keeps us from implementing the feature such that it would also work when a path other than |
Nginix only works when the path is |
@aledbf could you shed some light on why the Thanks! |
In my case, this annotation helps when I have a home page serving at "a.com/foo" but I want to redirect all "a.com" root requests to "a.com/foo", so that every time I want to browse this page I don't need to complete the full path manually which can be painful.. And at times, especially when the full path is rather long, typos will waste time. This will mostly happen when we put webpages on some static resouce servers. e.g. Apache?Nginx? |
BTW, I will add some tests but IDK where can I document this annotation? Should I add documentation into code/function comment? |
@yue9944882 Documentation of the annotation should go into |
f47495a
to
ca907db
Compare
@@ -158,6 +158,7 @@ The following security annotations can be applied to the ingress object to add s | |||
| `ingress.kubernetes.io/public-key:VALUE` | Adds pinned HTST public key header. | | |||
| `ingress.kubernetes.io/referrer-policy:VALUE` | Adds referrer policy header. | | |||
| `ingress.kubernetes.io/is-development:false` | This will cause the `AllowedHosts`, `SSLRedirect`, and `STSSeconds`/`STSIncludeSubdomains` options to be ignored during development.<br>When deploying to production, be sure to set this to false. | | |||
| `ingress.kubernetes.io/app-root:VALUE` | Explicitly make Ingress Controller redirects `/` requests to the defined path. | |
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.
As we're documenting the Ingress controller, can we simplify this to
Redirects all requests for /
to the defined path.
and also have another sentence to clearly describe what happens for non-root paths:
Non-root paths will not be affected by this annotation and handled normally.
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.
Make perfect sense. 👍
provider/kubernetes/kubernetes.go
Outdated
@@ -385,6 +386,10 @@ func getRuleForPath(pa v1beta1.HTTPIngressPath, i *v1beta1.Ingress) string { | |||
rules = append(rules, ruleTypeReplacePath+":"+rewriteTarget) | |||
} | |||
|
|||
// HACK: When multiple "ReplacePath" present, only the one at the last order of rule string will work |
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.
This should be handled less implicitly: we should either log a warning when we observe two ReplacePath
rules being used; or even log an error and ignore the Ingress in order to force the user to make a conscious decision.
I'm not sure if it's possible technically, but doesn't Traefik support applying a series of replacement rules already? In that case, we could let them resolve naturally. The downside is that it makes things more complicated to understand.
Whatever we do, we must document the behavior beyond a code comment. And the word HACK should get dropped.
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.
https://github.com/containous/traefik/blob/328be161d6e8cd04c1066d5884e4bf35f396b40f/server/rules.go#L97
https://github.com/containous/traefik/blob/328be161d6e8cd04c1066d5884e4bf35f396b40f/server/rules.go#L184
I believe traefik doesn't support a series of replacement rules yet. And the last ReplacePath
will override all the previous ReplacePath
declaration because the rules is iterated as an array in the order of their occurrence in the rule-string. WDYT?
a88b63f
to
40bfc21
Compare
@timoreimann PTAL thx |
@ldez @timoreimann @errm BTW, this PR should be a feature-request. Seems like I should have launched an issue or a discussion on Slack asking for further permission before this PR. Sorry for my negligence. |
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 more change request and one general note left.
We need to decide if we want to treat multiple replacement rules as warnings with last-rewrite-wins semantics, or as errors where we skip the offending Ingress. Having thought a bit more about it, I'm sort of leaning towards the latter with my rationale being that an explicit annotation indicates a specifically desirable behavior. Not being able to implement this behavior might be better exposed through a clear error.
I'm open to debate though.
@@ -158,6 +158,7 @@ The following security annotations can be applied to the ingress object to add s | |||
| `ingress.kubernetes.io/public-key:VALUE` | Adds pinned HTST public key header. | | |||
| `ingress.kubernetes.io/referrer-policy:VALUE` | Adds referrer policy header. | | |||
| `ingress.kubernetes.io/is-development:false` | This will cause the `AllowedHosts`, `SSLRedirect`, and `STSSeconds`/`STSIncludeSubdomains` options to be ignored during development.<br>When deploying to production, be sure to set this to false. | | |||
| `ingress.kubernetes.io/app-root:VALUE` | Redirects all requests for / to the defined path. On the other hand, non-root paths will not be affected by this annotation and handled normally. | |
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.
Can we drop the on the other hand part? I think it's better to keep the prose to the necessary minimum in the formal documentation.
provider/kubernetes/kubernetes.go
Outdated
@@ -381,10 +382,18 @@ func getRuleForPath(pa v1beta1.HTTPIngressPath, i *v1beta1.Ingress) string { | |||
|
|||
rules := []string{ruleType + ":" + pa.Path} | |||
|
|||
rewrited := false |
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.
Should be called rewritten
.
provider/kubernetes/kubernetes.go
Outdated
if rewriteTarget := i.Annotations[annotationKubernetesRewriteTarget]; rewriteTarget != "" { | ||
rules = append(rules, ruleTypeReplacePath+":"+rewriteTarget) | ||
rewrited = true |
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 just realized that we also have the case where the rule is explicitly set to ReplacePath
. We can either handle that in this PR too or do a follow up.
@timoreimann As far as I'm concerned, if we just skip the offending Ingresses, it might cause some unexpected accident or loss especially in production environment, e.g. making one or more web-site managed in the same Ingress unavailable. How about put an error log and ignore this annotation when at least one |
128e738
to
f3f0b4d
Compare
@yue9944882 my hypothesis is that failing hard and early in case the Ingress spec isn't consistent helps surfacing the problem more quickly than if we try to make the best out of it somehow. It's true that the latter could help making the Ingress work sometimes or even most of the time but may also cause it to fail in subtle, hard-to-spot corner cases. Personally I'd expect users to verify their Ingresses function properly prior to rolling them out to production systems, which seems easier to do when they don't work at all in case some error exists. Those are my two cents. Let's hear more voices before making a decision. |
c736e54
to
b109b4a
Compare
@timoreimann PTAL thx |
provider/kubernetes/kubernetes.go
Outdated
templateObjects.Frontends[baseName].Routes[pa.Path] = types.Route{ | ||
rule, err := getRuleForPath(pa, i) | ||
if err != nil { | ||
log.Errorf("fail to get rule from ingress path: %s", err) |
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.
Please update the log message as following:
log.Errorf("Failed to get rule for ingress %s/%s: %s", i.Namespace, i.Name, err)
(grammar/style of the first word + inclusion of the Ingress object's namespace and name)
provider/kubernetes/kubernetes.go
Outdated
templateObjects.Frontends[baseName].Routes[pa.Path] = types.Route{ | ||
rule, err := getRuleForPath(pa, i) | ||
if err != nil { | ||
log.Errorf("fail to get rule from ingress path: %s", err) |
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.
My code coverage tool tells me that this line is not tested. Could you check please?
provider/kubernetes/kubernetes.go
Outdated
if rewriteTarget := getStringValue(i.Annotations, annotationKubernetesRewriteTarget, ""); rewriteTarget != "" { | ||
if pathReplaceAnnotation != "" { | ||
return "", fmt.Errorf("rewrite-target must not be used together with annotation %q", pathReplaceAnnotation) |
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 failed to see it in my previous review round, but this part seems to be missing code coverage too.
0d5815e
to
d0d7728
Compare
@timoreimann @ldez PTAL thx |
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. Thanks a ton! 👏
provider/kubernetes/kubernetes.go
Outdated
rule, err := getRuleForPath(pa, i) | ||
if err != nil { | ||
log.Errorf("Failed to get rule for ingress %s/%s: %s", i.Namespace, i.Name, err) | ||
delete(templateObjects.Frontends, r.Host+pa.Path) |
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.
could you replace r.Host+pa.Path
by baseName
provider/kubernetes/kubernetes.go
Outdated
continue | ||
} | ||
if rule != "" { | ||
templateObjects.Frontends[r.Host+pa.Path].Routes[pa.Path] = types.Route{ |
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.
could you replace r.Host+pa.Path
by baseName
@@ -127,6 +127,7 @@ The following general annotations are applicable on the Ingress object: | |||
| `traefik.ingress.kubernetes.io/rewrite-target: /users` | Replaces each matched Ingress path with the specified one, and adds the old path to the `X-Replaced-Path` header. | | |||
| `traefik.ingress.kubernetes.io/rule-type: PathPrefixStrip` | Override the default frontend rule type. Default: `PathPrefix`. | | |||
| `traefik.ingress.kubernetes.io/whitelist-source-range: "1.2.3.0/24, fe80::/16"` | A comma-separated list of IP ranges permitted for access. all source IPs are permitted if the list is empty or a single range is ill-formatted. | | |||
| `traefik.ingress.kubernetes.io/app-root: "/index.html"` | Redirects all requests for / to the defined path. Non-root paths will not be affected by this annotation and handled normally. This annotation may not be combined with the ReplacePath rule type or any other annotation leveraging that rule type. Trying to do so leads to an error and the corresponding Ingress object being ignored. | |
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.
Redirects all requests for `/` to the defined path. Non-root paths will not be affected by this annotation and handled normally. This annotation may not be combined with the `ReplacePath` rule type or any other annotation leveraging that rule type. Trying to do so leads to an error and the corresponding Ingress object being ignored.
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
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
Rediret only root path elsewhere by ingress annotation Output error log when app-root and path violates Ignore app-root when ReplacePath already exists move docs to another section & rephrase error msg chore: rephrase docs & errror msg
a9e55a3
to
ad9797e
Compare
What does this PR do?
Rediret only root path elsewhere by ingress annotation. Like Nginx Ingress Controller documented. Implementing this annotation will only perform
ReplacePath
on/
path on all hosts present in the annotated ingress.ingress.kubernetes.io/app-root
ortraefik.ingress.kubernetes.io/app-root
Motivation
We catch this use case in production deployment.
More
Additional Notes
Seems like many new annotation support will be added to Kubernetes provider on 1.5 release, I hope this annotation can also be supported.