Skip to content
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 header-value annotation #3619

Merged
merged 2 commits into from
Feb 1, 2019

Conversation

minherz
Copy link
Contributor

@minherz minherz commented Jan 2, 2019

This PR extends the existing canary-by-header annotation.

What this PR does / why we need it:
This PR introduce more flexibility into the existing definition of the canary routing rules. The current implementation requires sending a header with a fixed value in order to trigger a canary routing which requires dedicated changes in the code of the application. This is less convenient when the application already has a header which can be used given its value represents a partition of users applicable to the canary testing (e.g. tenant id in the multi-tenant application).

Which issue this PR fixes (optional, in fixes #<issue number>(, fixes #<issue_number>, ...) format, will close that issue when PR gets merged): fixes #

Special notes for your reviewer:
This subject was already discussed in this message thread. Given we agree on implementation, I am going to add tests to the new annotation.

@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Jan 2, 2019
@minherz
Copy link
Contributor Author

minherz commented Jan 2, 2019

@ElvinEfendi , please have a look. I would like to better understand the suggestion you wrote in the message thread. Do you propose to have a single annotation that defines either header, cookie or weight or you like to have more complex condition like two headers or a header and cookie?

@clandry94
Copy link

clandry94 commented Jan 3, 2019

Could you please update the e2e tests to reflect the use-cases of these changes? https://github.com/kubernetes/ingress-nginx/blob/master/test/e2e/annotations/canary.go

@minherz
Copy link
Contributor Author

minherz commented Jan 3, 2019

@ElvinEfendi , @clandry94 what possible scenarios of canary traffic policies you think may be required?
my list is following:

  • header(s) expression evaluated to true (expressions are exists and equal to value)
  • cookie(s) expression evaluated to true (expressions are exists and equal to value)
  • coin tossing (a.k.a. weight)
    All three can be combined while the number of of headers and cookies has to be limited (e.g. to 1).
    Another question is whether preparing a lua expression and execute it via
expr = loadstring(traffic_shaping_policy.predicate)
if expr() then
  return true
else
  return false
end

or evaluate the policy basing on data structure like it is now?
The latter will not work well given we want dynamic number of entries or predicate that includes ORed and ANDed results.

@aledbf aledbf added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Jan 3, 2019
@minherz
Copy link
Contributor Author

minherz commented Jan 3, 2019

@clandry94, can you advise on possible reasoning for e2e tests failures? I see there failures for other modules beside canary. i am not experienced with the tests output. i cannot see the response headers or body, hence cannot identify the source of the problem.

@k8s-ci-robot k8s-ci-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Jan 4, 2019
@clandry94
Copy link

clandry94 commented Jan 4, 2019

@minherz You can add FOCUS="Annotations\s-\scanary" make e2e-test when running the tests to only have the canaries e2e tests run. If it still times out, CI will also run them

@minherz
Copy link
Contributor Author

minherz commented Jan 5, 2019

it seems that all "my" e2e tests pass. i have a problem to run it locally on my Windows 10 environment because Docker for Windows conflicts with minikube due different hypervisor platforms and ingress-nginx build scripts fail to run without minikube (even build). I will try to organize a Linux VM to run everything on it in a hope it works out of the box. However, e2e failures seem unrelated to my change.

@minherz
Copy link
Contributor Author

minherz commented Jan 5, 2019

@ElvinEfendi, @clandry94 I would like to propose the following annotation to replace the existing:

Define the annotation nginx.ingress.kubernetes.io/canary-by-policy so the name of the structure in Lua will make more sense. The annotation value will be a expression in a form:

<predicate> ::= <condition>*(<sp><bool_op><sp><condition>)
<bool_op> ::= "or" / "||" / "and" / "&&"
<condition> ::= <field><osp>"="<osp><value>
<sp> ::= SPACE / TAB
<osp> ::= *<sp>
<field> ::= "weight" / <cookie> / <header>
<value> ::= 1*UCHAR / """1*UCHAR"""
<cookie> ::= "@"<name>
<header> ::= "#"<name>
<name> ::= "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA

I don't know if there is a simple parsing package in go. If there is none, a simple one can be implemented here. The idea is to parse the predicate and run in a loop in Lua script on each condition.
Since basic one will be either a single header or cookie or weight and sometimes a combination of two or three, the above should be sufficient. I will open a separate issue to describe it if you are OK.

@minherz minherz force-pushed the add-canary-header-by-value branch from f4e308f to 0455a6a Compare January 5, 2019 16:39
@ElvinEfendi
Copy link
Member

@minherz regarding to supporting more complex expressions let's not address it just yet. I'm looking into introducing Lua code sandboxing into ingress-nginx for other purposes that can also be used here.

Also let's let the users use the existing canary feature and provide more feedback - I'd rather avoid implementing something that won't be used widely.

@aledbf
Copy link
Member

aledbf commented Jan 7, 2019

Also let's let the users use the existing canary feature and provide more feedback - I'd rather avoid implementing something that won't be used widely.

💯 that.

@minherz
Copy link
Contributor Author

minherz commented Jan 7, 2019

@minherz regarding to supporting more complex expressions let's not address it just yet. I'm looking into introducing Lua code sandboxing into ingress-nginx for other purposes that can also be used here.

Also let's let the users use the existing canary feature and provide more feedback - I'd rather avoid implementing something that won't be used widely.

Then I misinterpret the suggestion you wrote in the mail thread:

It would be even better if you implement a more general version of it: something like introducing a canary-by-predicate annotation which can have values such as "header(my-header) > 99"
or ``"header(my-header) == custom_value"or"cookie(my-cookie) > 99" etc
Do you suggest to replace the existing multiple annotations with a single one but having the same functionality?

@aledbf aledbf added the do-not-merge/blocked-paths Indicates that a PR should not merge because it touches files in blocked paths. label Jan 7, 2019
@minherz
Copy link
Contributor Author

minherz commented Jan 7, 2019

@ElvinEfendi can I mark the conversations as resolved?
One more question, some e2e tests seem to fail due timeout. it doesn't look like my change is the reason. what do i do with that?
@aledbf, what does the label blocked-paths means?

@minherz
Copy link
Contributor Author

minherz commented Jan 11, 2019

@ElvinEfendi and @aledbf , i have create a PR that implements the suggestion to replace current multiple canary annotations with one that follows the same routing logic.
Please, have a look and let me know if you prefer to replace this PR with the new one or we can move forward with this one.
Thank you.

P.S. the new PR doesn't have e2e tests yet. Before submitting it, I will edit existing tests to reflect the new format and structure.

@minherz
Copy link
Contributor Author

minherz commented Jan 19, 2019

ping @aledbf, @ElvinEfendi,
i don't know about you but i, personally, hate hanged PRs. it is to you to decide but either reject it or let's move forward with it.

@minherz
Copy link
Contributor Author

minherz commented Jan 26, 2019

ping @aledbf, @ElvinEfendi,@clandry94
fellows, is there any way to make a progress with this PR?
@ElvinEfendi, would you prefer to replace this PR with this change?

@aledbf
Copy link
Member

aledbf commented Jan 26, 2019

would you prefer to replace this PR with this change?

Please no. Annotations are just strings, no to store json or yaml definitions.

@aledbf
Copy link
Member

aledbf commented Jan 26, 2019

what does the label blocked-paths means?

Nothing in particular, is just a safety measure to avoid just one approve/lgtm command that will trigger the merge of the PR.

i don't know about you but i, personally, hate hanged PRs. it is to you to decide but either reject it or let's move forward with it.

@minherz apologies for the delay in the review of this PR. For this feature, I prefer to defer the first lgtm to @ElvinEfendi/@clandry94

@minherz
Copy link
Contributor Author

minherz commented Jan 26, 2019

@minherz apologies for the delay in the review of this PR. For this feature, I prefer to defer the first lgtm to @ElvinEfendi/@clandry94

ok, guys (@ElvinEfendi/@clandry94) I am waiting for your feedback about next steps with this PR and with the suggestion.

@k8s-ci-robot k8s-ci-robot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Jan 28, 2019
@minherz
Copy link
Contributor Author

minherz commented Jan 28, 2019

I think this PR looks good - as I mentioned earlier we should stick to simplest possible solution for now.
Please include some readme and rebase with master. (also squash commits into one)

Done

@ElvinEfendi
Copy link
Member

+2,235 −667

@minherz something must have went wrong with rebasing - there are a lot of unrelated changes.

@minherz
Copy link
Contributor Author

minherz commented Jan 28, 2019

+2,235 −667

@minherz something must have went wrong with rebasing - there are a lot of unrelated changes.

I synced master in my fork and then merged it into my work branch which I used for this PR. At the end I rebased it back by 8 commits but git produced 53. Reviewing the commits they all seem to happened between the change i made by Jan 5th and today.

@ElvinEfendi
Copy link
Member

@minherz after you pull remote master you should rebase your branch with that, not merge

@minherz minherz force-pushed the add-canary-header-by-value branch from d17fa48 to a8713e9 Compare January 30, 2019 21:23
@k8s-ci-robot k8s-ci-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Jan 30, 2019
add new annotation (header-value)
parse it and propogate to lua script
alter balancer rule to include it into the canary routing logic
add e2e test to validate fallback for canary-by-header-value
add description of canary-by-header-value to documentation
@minherz minherz force-pushed the add-canary-header-by-value branch from a8713e9 to de2a1ec Compare January 30, 2019 21:27
@minherz
Copy link
Contributor Author

minherz commented Jan 30, 2019

@ElvinEfendi it should be better now 😃

@ElvinEfendi
Copy link
Member

@minherz it's indeed better! Test failure seems to be legit.

@ElvinEfendi
Copy link
Member

ElvinEfendi commented Feb 1, 2019

@minherz please apply following patch:

diff --git a/rootfs/etc/nginx/lua/balancer.lua b/rootfs/etc/nginx/lua/balancer.lua
index 05650716d..f3b96f9d1 100644
--- a/rootfs/etc/nginx/lua/balancer.lua
+++ b/rootfs/etc/nginx/lua/balancer.lua
@@ -160,7 +160,7 @@ local function route_to_alternative_balancer(balancer)
   local target_header = util.replace_special_char(traffic_shaping_policy.header, "-", "_")
   local header = ngx.var["http_" .. target_header]
   if header then
-    if traffic_shaping_policy.headerValue then
+    if traffic_shaping_policy.headerValue and #traffic_shaping_policy.headerValue > 0 then
       if traffic_shaping_policy.headerValue == header then
         return true
       end

that will fix the bug that causes test to fail

@ElvinEfendi
Copy link
Member

/lgtm
/approve

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Feb 1, 2019
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: ElvinEfendi, minherz

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Feb 1, 2019
@ElvinEfendi
Copy link
Member

/hold cancel

@k8s-ci-robot k8s-ci-robot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Feb 1, 2019
@ElvinEfendi
Copy link
Member

@aledbf how do you cancel do-not-merge/blocked-paths?

@aledbf aledbf removed the do-not-merge/blocked-paths Indicates that a PR should not merge because it touches files in blocked paths. label Feb 1, 2019
@k8s-ci-robot k8s-ci-robot merged commit d4d25f6 into kubernetes:master Feb 1, 2019
@minherz minherz deleted the add-canary-header-by-value branch February 2, 2019 08:59
@minherz
Copy link
Contributor Author

minherz commented Feb 4, 2019

the idea indeed was to encode a canary policy via multi-string yaml. what is wrong with that? it is simple and straightforward.

Nothing. Just annotations are not designed for that. This is another example why CRDs are a better fit this use cases.

@aledbf @clandry94 would it be possible to use annotation to define a configMap that will describe the canary policy? the policy can be updated either each time the annotation is processed or each time the configMap resource is updated.

@Sarelbotavia
Copy link

can we use multiple values in canary-by-header-value?
there is an intention to support this in the future?
or there is some workaround?

@longwuyuan
Copy link
Contributor

I think we can safely say that currently you can use only one value.
No thought has been given to support multiple values.
There is o known workaround to use multiple values and expect match for any one of those values because of this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants