Serving: Runtime contract proposal: Inject revision, configuration and service names as env vars

Created on 3 Aug 2018  路  8Comments  路  Source: knative/serving

Use case:
Allow client libraries used inside the developer's code to get the service name, configuration name and revision name.

Example:

  • an error reporting library to report in which service and revision the crash occurred.
  • a tracing library like OpenCensus can annotate spans with the service name and revision name.
  • The same code can behave differently based on the configuration name (e.g. look for a prefix like "staging" vs "prod")

Proposal:

Similarly to Knative injecting a PORT environment variable, Knative also injects 3 environment variables with these values.

The env vars share the same prefix. I suggest SERVERLESS_, alternatively K_.

Values would be SERVERLESS_SERVICE, SERVERLESS_CONFIGURATION, SERVERLESS_REVISION

/area API
/kind feature
/kind spec

areAPI kinfeature kinspec

Most helpful comment

@steren I was interested in the suggestions
SERVERLESS_SERVICE, SERVERLESS_CONFIGURATION, SERVERLESS_REVISION
.. maybe it could be more clear as
SERVICELESS_SERVICE, CONFIGURATIONLESS_CONFIGURATION, REVISIONLESS_REVISION?

All 8 comments

I work on OpenCensus. I was looking for ways to improve the metadata we are collection on Knative, and @steren pointed out this issue to me.

Being able to filter and breakdown monitoring/tracing data by service name and version is fundamentally important to be able to setup SLOs and alerts properly, do canary analysis, perform root-cause analysis in production.

Metric data is being exported to a single resource in the analysis backends.
For example, in order to see latency metrics for a service and set SLOs, we need to label metrics with service name when uploading to the backend. Otherwise, you can also see an aggregate of all collected latency metrics which is useless.

The state of the things are better for traces but without labelling properly, it is hard to generate auto-analysis reports and service dependency graphs.

Without labelling, there is also no way to see how the new versions of the same service performs. This is critical for canary analysis.

@steren I was interested in the suggestions
SERVERLESS_SERVICE, SERVERLESS_CONFIGURATION, SERVERLESS_REVISION
.. maybe it could be more clear as
SERVICELESS_SERVICE, CONFIGURATIONLESS_CONFIGURATION, REVISIONLESS_REVISION?

Why not KNATIVE_?

@adriancole your comment is neither constructive nor respectful. Please remember the code of conduct

A KNATIVE_ or K_ prefix would work fine.
A short prefix might be preferred, so my preference goes for K_.

This seems reasonable, But leaving naming aside for a moment (I'd prefix with KNATIVE_ though to mirror the k8s resource types) are we sure separate per-resource env vars is the right mechanism? Just these three, or are there more?

Again, this seems like a good approach, but are there any downsides? E.g., do we risk polluting environments with more over time? Does it scale to hundreds of system-generated labels (not that I can think of anywhere near that many now)? Are there any alternative approaches to consider before we adopt this one as standard?

It'll be hard to walk back in favor of something else later on, so let's be convinced it's right.

A single variable with structured data such as json. Spring boot supports this with SPRING_APPLICATION_JSON. Cloud foundry also has a similar env var.

I discussed this offline with Steren a few days ago. This seems probably useful (will bring it up at the API WG), but more importantly, we should set up a documented place for operators to document the extensions to the runtime contract that they offer. There are at least four such extension points available:

  1. Environment Variables (as mentioned here)

    • Pros: Easy to access in a wide variety of languages. Error handling on missing var is generally fairly simple.
    • Cons: Cannot be changed after startup. Risk of conflict with existing names (i.e. a prefix like K_ might be preferable to bare SERVICE or REVISION).
  2. Local filesystem mounts:

    • Pros: Supports nested/namespaced names. Better support for structured data. Can be updated dynamically. Possibility of non-file types (e.g. named pipes to a sidecar).
    • Cons: Possibility of collision with disk image files. User code may read the file once and never reload for updates. May be harder for library-writers to integrate with. Higher number of failure edge cases which need to be handled (compare ioutil.ReadFile with os.Getenv, for example).
  3. Network API endpoints:

    • Pros: Can support nested/namespaced names and protocols. Natural support for dynamic updates. Good support for structured data. Possibility for dynamic content negotiation. Possibility of non-file types (e.g. socket to memcache service).
    • Cons: Difficult to test locally. Substantially more code required. Large number of failure edge cases. Possibility of collision with existing network services on the same segment. Varying degrees of library support, depending on protocol.
  4. Incoming request header decoration (i.e. X-Forwarded-For:):

    • Pros: Supports varying content per-request. Can (must) be updated dynamically. Easy to use for runtime decisions (few error conditions, simple code), but inappropriate for process-once information like database addresses.
    • Cons: Possibility of collision between operator-provided headers and user-provided headers. Possible security concerns if using header information for making trust decisions. Structured data is inconvenient. Increased payload size and request processing time. Somewhat difficult to test locally (must supply headers with each request).

I'll start a doc for a registry; my general preference would be in the order provided above (in the absence of existing interoperability factors).

With respect to this specific proposal, it sounds like @rakyll is in favor, and @spencergibb suggests packing a single environment variable with structured data instead of multiple environment variables.

I also like the idea of packing a single environment variable with structured data instead of multiple environment variables. In cloudfoundry we do something similar with VCAP_APPLICATION variable. I would be open to doing a PR and get feedback from all of you.

Was this page helpful?
0 / 5 - 0 ratings