-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Refactor datadog hostname/port env vars #9466
Conversation
This addresses an issue reported here: Kong#7954 While the tests set a null value to instead inherit the environment variables, this does not work in a Kubernetes context. For example, if I have this config: ``` config: host: null port: 8125 ``` The hostname still resolves to `localhost` once it gets through the schema.lua defaults. This approach reverses the order of ENV var evaluation, so that environment variables are used if set, and config if not.
This changes behaviour, so is a breaking change. |
the proper way to specify a
|
Even with that setup, the plugin renders it as localhost. Here are my configs (this is using the helm charts). Helm will interpret any null as "don't put that key in place":
Helm chart:
Datadog config as rendered by k8s
And thus the Datadog config as interpreted by kong
My solution as prescribed should leave those using ENV vars in non-k8s context still working as expected, and those using configs still working as expected. The only anticipated change in behaviour could be if someone has both env vars and config setup, and they expect their config to be used. I'm open to other suggested approaches. |
If that is the case then this is a major issue. Why doesn't helm/k8s stick to the JSON semantics???? There are many places where the Kong admin API relies on a JSON-null value to be specified by the user to clear a configuration item, or a default value. |
I would presume because it's YAML underneath, and not JSON. Be that as it may, the issue we're trying to fix issue number 7954 has some k8s specific work arounds, that aren't viable if one is unable to use k8s 1.22+ for whatever reason. |
Nope, the example before is the YAML way of expressing a JSON-null; config:
host:
port: 8125 |
Would you be able to detail the scenarios under which this may be a breaking change? Do you have alternative solutions to the approach suggested? |
Both are valid: https://yaml.org/spec/1.2.2/#10211-null However, this is not germane, and unproductive. |
if both plugin config and envvars are set, it previously used plugin config, and will now pick up envvars. That's a breaking change. |
Would you accept a configuration parameter that would default the current logic, but if set apply the logic I've implemented? |
It appears this approach has been suggested in the past: #8106 (comment) Have replied in that thread, with hope we can get a good direction going with this. |
In my opinion there is two different problems at play here:
My personal opinion is that for 1, Helm/K8s is interpreting the YAML spec wrong. Admittedly, the spec mentions that:
But commonly resolved is not the same as should always be resolved, which is what seems to be happening. In fact, on the description about null, this is addressed specifically.
Emphasis mine. I think Helm/K8s is at fault; they should not be adding nulls to people's yaml files. As for 2: Ideally we should have a way to handle environment variables inside schemas. At least we should have the option of making the
Or even add a new exclusive schema field, just for this purpose:
I don't know which option is better yet, but it is clear to me that this shouldn't be resolved by individual plugins every time they to read env variables for default values. The change needs to happen on the schema level, and then all plugins will be able to use it. |
I did some digging, and I think it might be the kubernetes-ingress-controller (on top of what k8s does). I can use helm/k8s to create an object that, when empty in the config, ends up with a
This is the same if I look at the object as JSON. Note that if I edit the value to be non-null, then re-edit to be blank, the key is removed entirely. This sounds like a k8s-ism, though helm may be converting empty keys to This said, when pulling this data to post to kong, the kubernetes-ingress-controller will This means that, even if k8s did maintain an empty value (or While the kong world may say |
Kong now has Secret Management built in. So there is another option:
|
Can you provide guidance (or documentation?) on how this would work in a k8s context? This might be a viable approach! The workaround suggested here is also viable if one is able to upgrade to k8s 1.21+ - I think this is the approach we're going to have to take. Is it worthwhile doing a documentation update on these behaviours with plugins that can have ENV vars, where there is an incompatibility with how k8s interprets blank/null values? |
I have found that this behaviour is actually (also) enforced by Kubernetes Ingress Controller. The addition of this goes pretty far back, but there isn't any description in the commit/PR as to why this particular method was chosen or what specific problem(s) it was trying to solve: |
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.
We should not change the precedence for kong.conf
and the environment variable. I've suggested the other solution.
I assume your use case to be that leave host and port not set, and provide them via environment variable,
|
||
function statsd_mt:new(conf) | ||
local sock = udp() | ||
local host = conf.host or env_datadog_agent_host | ||
local port = conf.port or env_datadog_agent_port | ||
local host = env_datadog_agent_host or conf.host |
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 makes the environment variable takes precedence over kong.conf
, which has different behavior compared to what this originally intended.
Maybe we could remove the default value for kong.conf
, and:
- check if
conf.host
is set; use that if so; - check if
'KONG_DATADOG_AGENT_HOST'
env is set; use that if so; - use the default value
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.
Check
kong/kong/plugins/datadog/schema.lua
Line 76 in 4ac5e91
{ host = typedefs.host({ default = "localhost" }), }, |
removing those default values will get us a nil
when the option is omitted.
local host = conf.host or env_datadog_agent_host | ||
local port = conf.port or env_datadog_agent_port | ||
local host = env_datadog_agent_host or conf.host | ||
local port = tonumber(env_datadog_agent_port or conf.port) |
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.
local port = tonumber(env_datadog_agent_port or conf.port) | |
local port = tonumber(env_datadog_agent_port) or conf.port |
host = "no-such-config.com", -- plugin takes above env var value, if env var is set | ||
port = 8125, -- plugin takes above env var value, if env var is set |
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 means env takes precedence over kong.conf
.
We currently have dead code in the plugin where @StarlightIbuki |
@jaswanthikolla this is not dead code, @chazdnato As of current state, i would suggest use secrets management (env var: https://docs.konghq.com/gateway/latest/kong-enterprise/secrets-management/getting-started/) as a workaround; please also open an issue at https://github.com/Kong/kubernetes-ingress-controller to actually fix the default value issue. |
So, the later part of the |
@jaswanthikolla It will, you can verify simply with |
Isn't that more confusing and against the mainstream? Let's go through it ( actually what you proposed doesn't work more on that later)
Bug:
Sample Plugin config :
This bug is just a demonstration how fickle the contract of leaving empty vs configuring it. I think we should rather fix it by |
@jaswanthikolla My previous comment was simply to point out the logic of code, that it's not a bug and code is executed correctly as designed. I do agree on the bad user experience here. IMO the proper way of solving this is not to going back and forth on designing how a null value should be handled in kong, but rather to provide a proper way for user to configure plugins and other kong entities. And the answer to this as @bungle has proposed:
|
@jaswanthikolla Apologies for misleading you and others. The way this will look to an operator is:
The end result should be the same and this should provide a much better user experience to all the users. |
Will this work with non-enterprise Kong, and which version do we need to run to get this feature? Does this work with the kubernetes-ingress-controller (which version)? Thanks! |
Absolutely. Environment variable based secrets are supported in open-source Kong.
The version of the ingress controller shouldn't matter but the Kong gateway version will matter (needs to be latest). |
A gentle ping to move this forward @chazdnato @jaswanthikolla. |
I am content to close out this investigation, as the [workaround suggested previously] (#7954 (comment)) is fine. I would like to test this on Kong 3.x, but we're not upgraded yet. The only documentation I can find for Thank you for looping back! |
I think there is some confusion. |
Given the solutions discussed and the way forward, I am closing this in favour of #10484 |
Summary
This addresses an issue reported here:
#7954
While the tests set a null value to instead inherit the environment variables, this does not work in a Kubernetes context. For example, if I have this config:
The hostname still resolves to
localhost
once it gets through the schema.lua defaults.This approach reverses the order of ENV var evaluation, so that environment variables are used if set, and config if not.
Full changelog
Issue reference
Fix #7954