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

Only create & mount Downward API volume when necessary #4953

Merged
merged 1 commit into from
Jul 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions config/config-feature-flags.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ data:
# See https://github.com/tektoncd/pipeline/issues/2791 for more
# info.
disable-creds-init: "false"
# Setting this flag to "false" will stop Tekton from waiting for a
# TaskRun's sidecar containers to be running before starting the first
# step. This will allow Tasks to be run in environments that don't
# support the DownwardAPI volume type, but may lead to unintended
# behaviour if sidecars are used.
#
# See https://github.com/tektoncd/pipeline/issues/4937 for more info.
await-sidecar-readiness: "true"
# This option should be set to false when Pipelines is running in a
# cluster that does not use injected sidecars such as Istio. Setting
# it to false should decrease the time it takes for a TaskRun to start
Expand Down
17 changes: 12 additions & 5 deletions docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -355,11 +355,18 @@ To customize the behavior of the Pipelines Controller, modify the ConfigMap `fea
node in the cluster must have an appropriate label matching `topologyKey`. If some or all nodes
are missing the specified `topologyKey` label, it can lead to unintended behavior.

- `running-in-environment-with-injected-sidecars`: set this flag to `"true"` to allow the
Tekton controller to set the `tekton.dev/ready` annotation at pod creation time for
TaskRuns with no Sidecars specified. Enabling this option should decrease the time it takes for a TaskRun to
start running. However, for clusters that use injected sidecars e.g. istio
enabling this option can lead to unexpected behavior.
- `await-sidecar-readiness`: set this flag to `"false"` to allow the Tekton controller to start a
TasksRun's first step immediately without waiting for sidecar containers to be running first. Using
this option should decrease the time it takes for a TaskRun to start running, and will allow TaskRun
pods to be scheduled in environments that don't support [Downward API](https://kubernetes.io/docs/tasks/inject-data-application/downward-api-volume-expose-pod-information/)
volumes (e.g. some virtual kubelet implementations). However, this may lead to unexpected behaviour
with Tasks that use sidecars, or in clusters that use injected sidecars (e.g. Istio). Setting this flag
to `"false"` will mean the `running-in-environment-with-injected-sidecars` flag has no effect.

- `running-in-environment-with-injected-sidecars`: set this flag to `"false"` to allow the
Tekton controller to start a TasksRun's first step immediately if it has no Sidecars specified.
Using this option should decrease the time it takes for a TaskRun to start running.
However, for clusters that use injected sidecars (e.g. Istio) this can lead to unexpected behavior.

- `require-git-ssh-secret-known-hosts`: set this flag to `"true"` to require that
Git SSH Secrets include a `known_hosts` field. This ensures that a git remote server's
Expand Down
7 changes: 7 additions & 0 deletions pkg/apis/config/feature_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ const (
DefaultDisableCredsInit = false
// DefaultRunningInEnvWithInjectedSidecars is the default value for "running-in-environment-with-injected-sidecars".
DefaultRunningInEnvWithInjectedSidecars = true
// DefaultAwaitSidecarReadiness is the default value for "await-sidecar-readiness".
DefaultAwaitSidecarReadiness = true
// DefaultRequireGitSSHSecretKnownHosts is the default value for "require-git-ssh-secret-known-hosts".
DefaultRequireGitSSHSecretKnownHosts = false
// DefaultEnableTektonOciBundles is the default value for "enable-tekton-oci-bundles".
Expand All @@ -61,6 +63,7 @@ const (
disableAffinityAssistantKey = "disable-affinity-assistant"
disableCredsInitKey = "disable-creds-init"
runningInEnvWithInjectedSidecarsKey = "running-in-environment-with-injected-sidecars"
awaitSidecarReadinessKey = "await-sidecar-readiness"
requireGitSSHSecretKnownHostsKey = "require-git-ssh-secret-known-hosts" // nolint: gosec
enableTektonOCIBundles = "enable-tekton-oci-bundles"
enableCustomTasks = "enable-custom-tasks"
Expand All @@ -81,6 +84,7 @@ type FeatureFlags struct {
ScopeWhenExpressionsToTask bool
EnableAPIFields string
SendCloudEventsForRuns bool
AwaitSidecarReadiness bool
EmbeddedStatus string
}

Expand Down Expand Up @@ -118,6 +122,9 @@ func NewFeatureFlagsFromMap(cfgMap map[string]string) (*FeatureFlags, error) {
if err := setFeature(runningInEnvWithInjectedSidecarsKey, DefaultRunningInEnvWithInjectedSidecars, &tc.RunningInEnvWithInjectedSidecars); err != nil {
return nil, err
}
if err := setFeature(awaitSidecarReadinessKey, DefaultAwaitSidecarReadiness, &tc.AwaitSidecarReadiness); err != nil {
return nil, err
}
if err := setFeature(requireGitSSHSecretKnownHostsKey, DefaultRequireGitSSHSecretKnownHosts, &tc.RequireGitSSHSecretKnownHosts); err != nil {
return nil, err
}
Expand Down
36 changes: 31 additions & 5 deletions pkg/apis/config/feature_flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,25 @@ func TestNewFeatureFlagsFromConfigMap(t *testing.T) {
testCases := []testCase{
{
expectedConfig: &config.FeatureFlags{
RunningInEnvWithInjectedSidecars: config.DefaultRunningInEnvWithInjectedSidecars,
EnableAPIFields: "stable",
EmbeddedStatus: config.DefaultEmbeddedStatus,
DisableAffinityAssistant: false,
RunningInEnvWithInjectedSidecars: true,
RequireGitSSHSecretKnownHosts: false,

DisableCredsInit: config.DefaultDisableCredsInit,
AwaitSidecarReadiness: config.DefaultAwaitSidecarReadiness,
EnableTektonOCIBundles: config.DefaultEnableTektonOciBundles,
EnableCustomTasks: config.DefaultEnableCustomTasks,
EnableAPIFields: config.DefaultEnableAPIFields,
SendCloudEventsForRuns: config.DefaultSendCloudEventsForRuns,
EmbeddedStatus: config.DefaultEmbeddedStatus,
},
fileName: config.GetFeatureFlagsConfigName(),
},
{
expectedConfig: &config.FeatureFlags{
DisableAffinityAssistant: true,
RunningInEnvWithInjectedSidecars: false,
AwaitSidecarReadiness: false,
RequireGitSSHSecretKnownHosts: true,
EnableTektonOCIBundles: true,
EnableCustomTasks: true,
Expand All @@ -62,7 +71,12 @@ func TestNewFeatureFlagsFromConfigMap(t *testing.T) {
EnableTektonOCIBundles: true,
EnableCustomTasks: true,

DisableAffinityAssistant: config.DefaultDisableAffinityAssistant,
DisableCredsInit: config.DefaultDisableCredsInit,
RunningInEnvWithInjectedSidecars: config.DefaultRunningInEnvWithInjectedSidecars,
AwaitSidecarReadiness: config.DefaultAwaitSidecarReadiness,
RequireGitSSHSecretKnownHosts: config.DefaultRequireGitSSHSecretKnownHosts,
SendCloudEventsForRuns: config.DefaultSendCloudEventsForRuns,
EmbeddedStatus: config.DefaultEmbeddedStatus,
},
fileName: "feature-flags-enable-api-fields-overrides-bundles-and-custom-tasks",
Expand All @@ -73,7 +87,12 @@ func TestNewFeatureFlagsFromConfigMap(t *testing.T) {
EnableTektonOCIBundles: true,
EnableCustomTasks: true,

DisableAffinityAssistant: config.DefaultDisableAffinityAssistant,
DisableCredsInit: config.DefaultDisableCredsInit,
RunningInEnvWithInjectedSidecars: config.DefaultRunningInEnvWithInjectedSidecars,
AwaitSidecarReadiness: config.DefaultAwaitSidecarReadiness,
RequireGitSSHSecretKnownHosts: config.DefaultRequireGitSSHSecretKnownHosts,
SendCloudEventsForRuns: config.DefaultSendCloudEventsForRuns,
EmbeddedStatus: config.DefaultEmbeddedStatus,
},
fileName: "feature-flags-bundles-and-custom-tasks",
Expand All @@ -92,8 +111,15 @@ func TestNewFeatureFlagsFromConfigMap(t *testing.T) {
func TestNewFeatureFlagsFromEmptyConfigMap(t *testing.T) {
FeatureFlagsConfigEmptyName := "feature-flags-empty"
expectedConfig := &config.FeatureFlags{
RunningInEnvWithInjectedSidecars: true,
EnableAPIFields: "stable",
DisableAffinityAssistant: config.DefaultDisableAffinityAssistant,
DisableCredsInit: config.DefaultDisableCredsInit,
RunningInEnvWithInjectedSidecars: config.DefaultRunningInEnvWithInjectedSidecars,
AwaitSidecarReadiness: config.DefaultAwaitSidecarReadiness,
RequireGitSSHSecretKnownHosts: config.DefaultRequireGitSSHSecretKnownHosts,
EnableTektonOCIBundles: config.DefaultEnableTektonOciBundles,
EnableCustomTasks: config.DefaultEnableCustomTasks,
EnableAPIFields: config.DefaultEnableAPIFields,
SendCloudEventsForRuns: config.DefaultSendCloudEventsForRuns,
EmbeddedStatus: config.DefaultEmbeddedStatus,
}
verifyConfigFileWithExpectedFeatureFlagsConfig(t, FeatureFlagsConfigEmptyName, expectedConfig)
Expand Down
1 change: 1 addition & 0 deletions pkg/apis/config/testdata/feature-flags-all-flags-set.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ metadata:
data:
disable-affinity-assistant: "true"
running-in-environment-with-injected-sidecars: "false"
await-sidecar-readiness: "false"
require-git-ssh-secret-known-hosts: "true"
enable-tekton-oci-bundles: "true"
enable-custom-tasks: "true"
Expand Down
43 changes: 21 additions & 22 deletions pkg/pod/entrypoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,34 +108,31 @@ var (
// command, we must have fetched the image's ENTRYPOINT before calling this
// method, using entrypoint_lookup.go.
// Additionally, Step timeouts are added as entrypoint flag.
func orderContainers(commonExtraEntrypointArgs []string, steps []corev1.Container, taskSpec *v1beta1.TaskSpec, breakpointConfig *v1beta1.TaskRunDebug) ([]corev1.Container, error) {
func orderContainers(commonExtraEntrypointArgs []string, steps []corev1.Container, taskSpec *v1beta1.TaskSpec, breakpointConfig *v1beta1.TaskRunDebug, waitForReadyAnnotation bool) ([]corev1.Container, error) {
if len(steps) == 0 {
return nil, errors.New("No steps specified")
}

for i, s := range steps {
var argsForEntrypoint []string
var argsForEntrypoint = []string{}
idx := strconv.Itoa(i)
switch i {
case 0:
argsForEntrypoint = []string{
// First step waits for the Downward volume file.
"-wait_file", filepath.Join(downwardMountPoint, downwardMountReadyFile),
"-wait_file_content", // Wait for file contents, not just an empty file.
// Start next step.
"-post_file", filepath.Join(runDir, idx, "out"),
"-termination_path", terminationPath,
"-step_metadata_dir", filepath.Join(runDir, idx, "status"),
}
default:
// All other steps wait for previous file, write next file.
argsForEntrypoint = []string{
"-wait_file", filepath.Join(runDir, strconv.Itoa(i-1), "out"),
"-post_file", filepath.Join(runDir, idx, "out"),
"-termination_path", terminationPath,
"-step_metadata_dir", filepath.Join(runDir, idx, "status"),
if i == 0 {
if waitForReadyAnnotation {
argsForEntrypoint = append(argsForEntrypoint,
// First step waits for the Downward volume file.
"-wait_file", filepath.Join(downwardMountPoint, downwardMountReadyFile),
"-wait_file_content", // Wait for file contents, not just an empty file.
)
}
} else { // Not the first step - wait for previous
argsForEntrypoint = append(argsForEntrypoint, "-wait_file", filepath.Join(runDir, strconv.Itoa(i-1), "out"))
}
argsForEntrypoint = append(argsForEntrypoint,
// Start next step.
"-post_file", filepath.Join(runDir, idx, "out"),
"-termination_path", terminationPath,
"-step_metadata_dir", filepath.Join(runDir, idx, "status"),
)
argsForEntrypoint = append(argsForEntrypoint, commonExtraEntrypointArgs...)
if taskSpec != nil {
if taskSpec.Steps != nil && len(taskSpec.Steps) >= i+1 {
Expand Down Expand Up @@ -173,8 +170,10 @@ func orderContainers(commonExtraEntrypointArgs []string, steps []corev1.Containe
steps[i].Args = argsForEntrypoint
steps[i].TerminationMessagePath = terminationPath
}
// Mount the Downward volume into the first step container.
steps[0].VolumeMounts = append(steps[0].VolumeMounts, downwardMount)
if waitForReadyAnnotation {
// Mount the Downward volume into the first step container.
steps[0].VolumeMounts = append(steps[0].VolumeMounts, downwardMount)
}

return steps, nil
}
Expand Down
58 changes: 52 additions & 6 deletions pkg/pod/entrypoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,53 @@ func TestOrderContainers(t *testing.T) {
},
TerminationMessagePath: "/tekton/termination",
}}
got, err := orderContainers([]string{}, steps, nil, nil)
got, err := orderContainers([]string{}, steps, nil, nil, true)
if err != nil {
t.Fatalf("orderContainers: %v", err)
}
if d := cmp.Diff(want, got); d != "" {
t.Errorf("Diff %s", diff.PrintWantGot(d))
}
}

func TestOrderContainersWithNoWait(t *testing.T) {
steps := []corev1.Container{{
Image: "step-1",
Command: []string{"cmd"},
Args: []string{"arg1", "arg2"},
}, {
Image: "step-2",
Command: []string{"cmd1", "cmd2", "cmd3"}, // multiple cmd elements
Args: []string{"arg1", "arg2"},
VolumeMounts: []corev1.VolumeMount{volumeMount}, // pre-existing volumeMount
}}
want := []corev1.Container{{
Image: "step-1",
Command: []string{entrypointBinary},
Args: []string{
"-post_file", "/tekton/run/0/out",
"-termination_path", "/tekton/termination",
"-step_metadata_dir", "/tekton/run/0/status",
"-entrypoint", "cmd", "--",
"arg1", "arg2",
},
TerminationMessagePath: "/tekton/termination",
}, {
Image: "step-2",
Command: []string{entrypointBinary},
Args: []string{
"-wait_file", "/tekton/run/0/out",
"-post_file", "/tekton/run/1/out",
"-termination_path", "/tekton/termination",
"-step_metadata_dir", "/tekton/run/1/status",
"-entrypoint", "cmd1", "--",
"cmd2", "cmd3",
"arg1", "arg2",
},
VolumeMounts: []corev1.VolumeMount{volumeMount},
TerminationMessagePath: "/tekton/termination",
}}
got, err := orderContainers([]string{}, steps, nil, nil, false)
if err != nil {
t.Fatalf("orderContainers: %v", err)
}
Expand Down Expand Up @@ -127,7 +173,7 @@ func TestOrderContainersWithDebugOnFailure(t *testing.T) {
taskRunDebugConfig := &v1beta1.TaskRunDebug{
Breakpoint: []string{"onFailure"},
}
got, err := orderContainers([]string{}, steps, nil, taskRunDebugConfig)
got, err := orderContainers([]string{}, steps, nil, taskRunDebugConfig, true)
if err != nil {
t.Fatalf("orderContainers: %v", err)
}
Expand Down Expand Up @@ -205,7 +251,7 @@ func TestEntryPointResults(t *testing.T) {
},
TerminationMessagePath: "/tekton/termination",
}}
got, err := orderContainers([]string{}, steps, &taskSpec, nil)
got, err := orderContainers([]string{}, steps, &taskSpec, nil, true)
if err != nil {
t.Fatalf("orderContainers: %v", err)
}
Expand Down Expand Up @@ -246,7 +292,7 @@ func TestEntryPointResultsSingleStep(t *testing.T) {
VolumeMounts: []corev1.VolumeMount{downwardMount},
TerminationMessagePath: "/tekton/termination",
}}
got, err := orderContainers([]string{}, steps, &taskSpec, nil)
got, err := orderContainers([]string{}, steps, &taskSpec, nil, true)
if err != nil {
t.Fatalf("orderContainers: %v", err)
}
Expand Down Expand Up @@ -283,7 +329,7 @@ func TestEntryPointSingleResultsSingleStep(t *testing.T) {
VolumeMounts: []corev1.VolumeMount{downwardMount},
TerminationMessagePath: "/tekton/termination",
}}
got, err := orderContainers([]string{}, steps, &taskSpec, nil)
got, err := orderContainers([]string{}, steps, &taskSpec, nil, true)
if err != nil {
t.Fatalf("orderContainers: %v", err)
}
Expand Down Expand Up @@ -340,7 +386,7 @@ func TestEntryPointOnError(t *testing.T) {
},
TerminationMessagePath: "/tekton/termination",
}}
got, err := orderContainers([]string{}, steps, &taskSpec, nil)
got, err := orderContainers([]string{}, steps, &taskSpec, nil, true)
if err != nil {
t.Fatalf("orderContainers: %v", err)
}
Expand Down
Loading