status | title | creation-date | last-updated | authors | |||
---|---|---|---|---|---|---|---|
implemented |
Env in POD template |
2022-03-17 |
2022-12-22 |
|
- Summary
- Motivation
- Requirements
- Proposal
- Design Details
- Test Plan
- Design Evaluation
- Drawbacks
- Alternatives
- Infrastructure Needed (optional)
- Upgrade & Migration Strategy (optional)
- Implementation Pull request(s)
- References (optional)
Providing the users a functionality for specifying additional environment variables or overwriting existing environment
variables defined in Steps
and StepTemplate
of Task
at runtime through TaskRun
and PipelineRun
. In order to
achieve that, a Pod template should support
configuration of environment variables, which are combined with those defined in steps
and stepTemplate
, and then
passed to all step containers. This let the user specify common variables to the global level as well as overwrite
defaults specified on the particular step level.
One of the most important motivators for this feature is the ability to eliminate redundant code from
the PipelineRun
as well as TaskRun
specification. On average this can reduce 3-5 lines of yaml per
each environment variable per each task in the pipeline.
In case of complex pipelines, which consist of dozen or even hundreds of tasks, any kind of repetition
significantly impacts the final size of PipelineRun
and leads to resource exhaustion on the
Kubernetes ETCD limitation.
Besides, users quite frequently are willing to overwrite environment variable values
specified in a stepTemplate
in the single place when running pipelines.
That helps to optionally pass settings, without a need to define additional pipeline parameters.
Also, users can specify the global environment variables which needs to be added for every TaskRun
or
PipelineRun
, then users don't need to specify them in all Tasks
and changing the values of those environment
variables will also be not cumbersome as they can change it at single place in global default and can also overwrite
for particular run.
Having an env
field in the pod template allows to:
- specify global level defaults, what is important to reduce the size of
TaskRun
andPipelineRun
- override defaults from
stepTemplate
atTaskRun
andPipelineRun
level
-
The main goal of this proposal is to enable support for specification of environment variables at the time of execution.(
TaskRun
andPipelineRun
) -
Environment variables defined in the Pod template at
TaskRun
andPipelineRun
level take precedence over the ones defined insteps
andstepTemplate
. -
Allow cluster admin to define a list of default environment variables which gets added to all the
TaskRun
andPipelineRun
in config-defaults.yaml -
Allow cluster admin to define a list of cluster-wide forbidden environment variables by providing a field in
config-defaults
so that users won't overwrite important environment variables configured by admin. -
Define the order of precedence for the multiple locations where environment variables can be defined.
- Namespace specific environment variables are not proposed.
-
In the first case, common environment variables can be defined in a single place on a
PipelineRun
level orTaskRun
level. Values can be specified as literals or through Kubernetes references. Variables defined on aPipelineRun
orTaskRun
level are then available in all steps. That allows to simplify the Tekton run resource configuration and significantly reduce the size ofPipelineRun
andTaskRun
resource, by excluding the common environment variables like static global settings, common values coming from metadata etc -
Secondly, environment variables defined in steps can be easily overwritten by the ones from
PipelineRun
andTaskRun
. With that, common settings like API keys, connection details etc can be optionally overwritten in a single place. -
For Cloud Providers, it's very common to inject user credentials using Kubernetes API
valueFrom
to avoid credentials being exposed to the PodSpec. Since each cloud provider has different credential format, able to assign environment variables at thePipelineRun
andTaskRun
can reuse the same task with different Cloud Provider credentials. Kubernetes APIvalueFrom
can also refer to values in the pod labels/annotations for specific Kubernetes cluster information such as namespace, application labels, and service annotations. -
Allow users to reuse stock Tekton catalogs on different cloud environment by setting up a cloud specific global container spec.
-
User should be able to configure environment variable which needs to be provided to all workloads like for proxy settings, Users need to set environment variables like
HTTP_PROXY
,HTTPS_PROXY
andNO_PROXY
on all steps/containers.
- Need to define a spec field to provide environment variables at
PipelineRun
andTaskRun
level. - Need to provide a way to define a list of global environment variables.
- Need to provide a way to define a list of cluster-wide forbidden environment variables. When users define environment variables in the Taskrun and Pipelinerun spec, check the list of forbidden environment variables and throw out a validation error if any of the environment variables is forbidden.
- Since there are many places like listed below where user can define the environment variables, there needs to be a precedence order for different places.
- Global Level Forbidden Environment Variables
- Global Level Default Environment Variables in Tekton Default Pod Template
- PipelineRun Level Environment Variables in PipelineRun Pod Template
- TaskRun Level Environment Variables in TaskRun Pod Template
- Task Level Environment Variables in Task Step Template
- Step Level Environment Variables in Step Container Spec
- Environment variables can be defined in a single place on a
PipelineRun
andTaskRun
level. Values can be specified as literals or through references, e.g.:
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: mypipelinerun
spec:
podTemplate:
env:
- name: TOKEN_PATH
value: /opt/user-token
- name: TKN_PIPELINE_RUN
valueFrom:
fieldRef:
fieldPath: metadata.labels['tekton.dev/pipelineRun']
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
name: mytaskrun
namespace: default
spec:
taskRef:
name: mytask
podTemplate:
env:
- name: TOKEN_PATH
value: /opt/user-token
- name: TKN_TASKRUN_RUN
valueFrom:
fieldRef:
fieldPath: metadata.labels['tekton.dev/taskRun']
- Environment variables defined in steps can be easily overwritten by the ones from a
TaskRun
, e.g.:
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: mytask
namespace: default
spec:
steps:
- name: echo-msg
image: ubuntu
command: ["bash", "-c"]
args: ["echo $MSG"]
envs:
- name: "MSG"
value: "Default message"
---
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
name: mytaskrun
namespace: default
spec:
taskRef:
name: mytask
podTemplate:
envs:
- name: "MSG"
value: "Overwritten message"
- Environment variables defined in steps can be easily overwritten by the ones from a
PipelineRun
, e.g.:
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: mytask
namespace: default
spec:
steps:
- name: echo-msg
image: ubuntu
command: ["bash", "-c"]
args: ["echo $MSG $SECRET_PASSWORD $NAMESPACE"]
envs:
- name: "MSG"
value: "Default message"
- name: "SECRET_PASSWORD"
value: "Default secret password"
- name: "NAMESPACE"
value: "tekton-pipelines"
---
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: one-task-pipeline-run
namespace: default
spec:
pipelineSpec:
tasks:
- name: mytaskrun
taskRef:
name: mytask
podTemplate:
envs:
- name: "MSG"
value: "Overwritten message"
- Promote reusable tasks, users needs not to define different tasks just for the change of env value.
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: mytask
namespace: default
spec:
steps:
- name: echo-msg
image: ubuntu
command: ["bash", "-c"]
args: ["echo $MSG $SECRET_PASSWORD $NAMESPACE"]
envs:
- name: "MSG"
value: "Default message"
- name: "SECRET_PASSWORD"
value: "Default secret password"
- name: "NAMESPACE"
value: "tekton-pipelines"
---
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: three-task-pipeline-run
namespace: default
spec:
pipelineSpec:
tasks:
- name: mytaskrun
taskRef:
name: mytask
- name: mytaskrun2
taskRef:
name: mytask
runAfter:
- mytaskrun
- name: mytaskrun3
taskRef:
name: mytask
runAfter:
- mytaskrun2
podTemplate:
envs:
- name: "MSG"
valueFrom:
fieldRef:
fieldPath: metadata.labels['messages']
- name: "SECRET_PASSWORD"
valueFrom:
secretKeyRef:
name: mysecret
key: password
optional: false
- name: "NAMESPACE"
valueFrom:
fieldRef:
fieldPath: metadata.namespace
Without the ENV in podTemplate, every new PipelineRun
above will need to create a new Task
resource using
stepTemplate to run the same examples if there is some change in env value. e.g.:
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: mytask
namespace: default
spec:
stepTemplate:
envs:
- name: "MSG"
value: "Overwritten message"
steps:
- name: echo-msg
image: ubuntu
command: ["bash", "-c"]
args: ["echo $MSG $SECRET_PASSWORD $NAMESPACE"]
envs:
- name: "MSG"
value: "Default message"
- name: "SECRET_PASSWORD"
value: "Default secret password"
- name: "NAMESPACE"
value: "tekton-pipelines"
---
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: mytask2
namespace: default
spec:
stepTemplate:
envs:
- name: "MSG"
valueFrom:
fieldRef:
fieldPath: metadata.labels['messages']
- name: "SECRET_PASSWORD"
valueFrom:
secretKeyRef:
name: mysecret
key: password
optional: false
- name: "NAMESPACE"
valueFrom:
fieldRef:
fieldPath: metadata.namespace
steps:
- name: echo-msg
image: ubuntu
command: ["bash", "-c"]
args: ["echo $MSG $SECRET_PASSWORD $NAMESPACE"]
envs:
- name: "MSG"
value: "Default message"
- name: "SECRET_PASSWORD"
value: "Default secret password"
- name: "NAMESPACE"
value: "tekton-pipelines"
---
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: one-task-pipeline-run
namespace: default
spec:
pipelineSpec:
tasks:
- name: mytaskrun
taskRef:
name: mytask
---
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: three-task-pipeline-run
namespace: default
spec:
pipelineSpec:
tasks:
- name: mytaskrun
taskRef:
name: mytask2
- name: mytaskrun2
taskRef:
name: mytask2
runAfter:
- mytaskrun
- name: mytaskrun3
taskRef:
name: mytask2
runAfter:
- mytaskrun2
- Another use case is where admin can define a list of immutable environment variables in the cluster-wide configmap.
Then, user will get error if these envs get defined in podtemplate of
PipelineRun
orTaskRun
. List of forbidden environment variables are located at the "config-defaults" configmap at the Tekton controller namespace.
Tekton configmap
apiVersion: v1
kind: ConfigMap
metadata:
name: config-defaults
namespace: tekton-pipelines
labels:
app.kubernetes.io/instance: default
app.kubernetes.io/part-of: tekton-pipelines
data:
pod-template-rules:
forbidden-env-variables:
- "HTTP_PROXY"
Tekton pipelinerun
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: mytask
namespace: default
spec:
steps:
- name: echo-msg
image: ubuntu
command: ["bash", "-c"]
args: ["echo $HTTP_PROXY"]
---
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
name: mytaskrun
namespace: default
spec:
taskRef:
name: mytask
podTemplate:
envs:
- name: "HTTP_PROXY"
value: "8080"
The above pipeline will return "HTTP_PROXY" is not a valid environment variable to define in the podTemplate.
- User can also define a list of envs as part of global default pod template. All the tasks will have those envs set on steps.
Tekton configmap
apiVersion: v1
kind: ConfigMap
metadata:
name: config-defaults
namespace: tekton-pipelines
labels:
app.kubernetes.io/instance: default
app.kubernetes.io/part-of: tekton-pipelines
data:
default-pod-template:
envs:
- name: "MSG"
value: "Default message"
Tekton pipelinerun
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: mytask
namespace: default
spec:
steps:
- name: echo-msg
image: ubuntu
command: ["bash", "-c"]
args: ["echo $MSG"]
---
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
name: mytaskrun
namespace: default
spec:
taskRef:
name: mytask
The default "MSG" environment variable will be available in step since it's set as part of the global default pod template.
-
Forbidden Environment Variables are for pod template of
TaskRun
andPipelineRun
, are they also valid for global default pod Template? How will it be avoided then? How user will get the error for that? -
If forbidden environment variables are specified, should they be avoided at Task's
stepTemplate
field or Step'sEnv
field too ? -
Will there be option to pass different values of the same env, for different task in a pipeline? There can be a case that the same env requires different value in different tasks of a pipeline, and if we put it at pipelineRun
spec level, then we are overwriting in all tasks.
In case of some environment variables are not allowed to change, it can have a feature flag to opt-in with this new feature. Similar to the alpha API feature flag, we can let the validation webhook fail with an error message when the feature flag is disabled. The default behavior can change after 9 months of the Tekton release cycles.
Bring the task stepTemplate
spec to the taskRuns and pipelineRuns. Similar to stepTemplate
,
pipelineRun podTemplate
can overwrite the taskRun and taskRun podTemplate
can overwrite stepTemplate
.
In the podTemplate
struct, add the env variable field like:
type Template struct {
...
// List of environment variables that can be provided to the containers belonging to the pod.
// +optional
Envs []corev1.EnvVar `json:"envs,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"name" protobuf:"bytes,1,rep,name=envs"`
...
}
PipelineRun
spec already have podTemplate
field, so new Envs
field will be available here
type PipelineRunSpec struct {
....
// PodTemplate holds pod specific configuration
PodTemplate *PodTemplate `json:"podTemplate,omitempty"`
....
}
Also, TaskRun
spec have podTemplate
field, so Envs
will be available here
type TaskRunSpec struct {
...
// PodTemplate holds pod specific configuration
PodTemplate *PodTemplate `json:"podTemplate,omitempty"`
...
}
Global level default can be provided at the config-default
configmap under the default-pod-template
field and the
same podTemplate
field is getting used to read the default values.
apiVersion: v1
kind: ConfigMap
metadata:
name: config-defaults
namespace: tekton-pipelines
data:
default-pod-template:
envs:
-
-
-
...
We need to have the controller logic to act based on the envs available at different places. Controller should read all and merge them till last stage which is converting them to container. The order of Precedence will look like this with first being the higher.
a. Environment Variables in PipelineRun Pod Template or TaskRun Pod Template (Same priority as both are different places)
c. Global Level Default Environment Variables in Tekton Default Pod Template
d. Task Level Environment Variables in Task Step Template
e. Step Level Environment Variables in Step Container Spec
If some default is configured and user is providing as the time of PipelineRun
and TaskRun
, then it should overwrite
the default provided at global level.
There should be way to define the forbidden environment variables, which should not be overwritten by PipelineRun
or
TaskRun
. If done so, webhook will throw an error that these are forbidden envs.
apiVersion: v1
kind: ConfigMap
metadata:
name: config-defaults
namespace: tekton-pipelines
labels:
app.kubernetes.io/instance: default
app.kubernetes.io/part-of: tekton-pipelines
data:
pod-template-rules:
forbidden-env-variables :
- "HTTP_PROXY"
Define with a Top-level environment variable field. This new top-level field will be under the pipelinerun/taskrun spec level. Since the requirements also need to support Kubernetes value references such as secret, configmap, and Kubernetes downstream API, the type for this new spec will be an array of Kubernetes container V1 environment variable types.
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
name: mytaskrun
namespace: default
spec:
taskRef:
name: mytask
envs:
- name: "HTTP_PROXY"
value: "8080"
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: one-task-pipeline-run
namespace: default
spec:
pipelineSpec:
tasks:
- name: mytaskrun
taskRef:
name: mytask
envs:
- name: "MSG"
value: "Overwritten message"
No impact on existing features. No breaking APIs. But if users configures global default environment variable, then task env may get overridden and env have different values.
- Previously open: tektoncd/pipeline#3566
- tektoncd/pipeline#5699
Previously open