Skip to content

Commit

Permalink
tektoncd#7617 support k8s native sidecar
Browse files Browse the repository at this point in the history
  • Loading branch information
kgcarr committed Jul 11, 2024
1 parent 0db5ca2 commit 0bf94a1
Show file tree
Hide file tree
Showing 16 changed files with 374 additions and 9 deletions.
34 changes: 34 additions & 0 deletions docs/pipeline-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -4135,6 +4135,23 @@ other Step or Sidecar that does not also request this Workspace will
not have access to it.</p>
</td>
</tr>
<tr>
<td>
<code>restartPolicy</code><br/>
<em>
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#containerrestartpolicy-v1-core">
Kubernetes core/v1.ContainerRestartPolicy
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>RestartPolicy refers to kubernetes RestartPolicy. It can only be set for an
initContainer and must have it&rsquo;s policy set to &ldquo;Always&rdquo;. It is currently
left optional to help support Kubernetes versions prior to 1.29 when this feature
was introduced.</p>
</td>
</tr>
</tbody>
</table>
<h3 id="tekton.dev/v1.SidecarState">SidecarState
Expand Down Expand Up @@ -13459,6 +13476,23 @@ other Step or Sidecar that does not also request this Workspace will
not have access to it.</p>
</td>
</tr>
<tr>
<td>
<code>restartPolicy</code><br/>
<em>
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#containerrestartpolicy-v1-core">
Kubernetes core/v1.ContainerRestartPolicy
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>RestartPolicy refers to kubernetes RestartPolicy. It can only be set for an
initContainer and must have it&rsquo;s policy set to &ldquo;Always&rdquo;. It is currently
left optional to help support Kubernetes versions prior to 1.29 when this feature
was introduced.</p>
</td>
</tr>
</tbody>
</table>
<h3 id="tekton.dev/v1beta1.SidecarState">SidecarState
Expand Down
9 changes: 9 additions & 0 deletions examples/v1/taskruns/sidecar-ready.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ spec:
- -c
- sleep 5 && touch /shared/ready
timeoutSeconds: 10
# Adding startup probe for k8s native sidecar support
# Readiness Probe is not honored for k8s native sidecar support
startupProbe:
exec:
command:
- sh
- -c
- sleep 5 && touch /shared/ready
timeoutSeconds: 10
volumeMounts:
- name: shared
mountPath: /shared
Expand Down
37 changes: 36 additions & 1 deletion pkg/apis/pipeline/v1/container_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -543,10 +543,43 @@ type Sidecar struct {
// +optional
// +listType=atomic
Workspaces []WorkspaceUsage `json:"workspaces,omitempty"`

// RestartPolicy refers to kubernetes RestartPolicy. It can only be set for an
// initContainer and must have it's policy set to "Always". It is currently
// left optional to help support Kubernetes versions prior to 1.29 when this feature
// was introduced.
// +optional
RestartPolicy *corev1.ContainerRestartPolicy `json:"restartPolicy,omitempty"`
}

// ToK8sContainer converts the Sidecar to a Kubernetes Container struct
func (s *Sidecar) ToK8sContainer() *corev1.Container {
if s.RestartPolicy == nil {
return &corev1.Container{
Name: s.Name,
Image: s.Image,
Command: s.Command,
Args: s.Args,
WorkingDir: s.WorkingDir,
Ports: s.Ports,
EnvFrom: s.EnvFrom,
Env: s.Env,
Resources: s.ComputeResources,
VolumeMounts: s.VolumeMounts,
VolumeDevices: s.VolumeDevices,
LivenessProbe: s.LivenessProbe,
ReadinessProbe: s.ReadinessProbe,
StartupProbe: s.StartupProbe,
Lifecycle: s.Lifecycle,
TerminationMessagePath: s.TerminationMessagePath,
TerminationMessagePolicy: s.TerminationMessagePolicy,
ImagePullPolicy: s.ImagePullPolicy,
SecurityContext: s.SecurityContext,
Stdin: s.Stdin,
StdinOnce: s.StdinOnce,
TTY: s.TTY,
}
}
return &corev1.Container{
Name: s.Name,
Image: s.Image,
Expand All @@ -561,6 +594,7 @@ func (s *Sidecar) ToK8sContainer() *corev1.Container {
VolumeDevices: s.VolumeDevices,
LivenessProbe: s.LivenessProbe,
ReadinessProbe: s.ReadinessProbe,
RestartPolicy: s.RestartPolicy,
StartupProbe: s.StartupProbe,
Lifecycle: s.Lifecycle,
TerminationMessagePath: s.TerminationMessagePath,
Expand All @@ -587,7 +621,7 @@ func (s *Sidecar) SetContainerFields(c corev1.Container) {
s.VolumeMounts = c.VolumeMounts
s.VolumeDevices = c.VolumeDevices
s.LivenessProbe = c.LivenessProbe
s.ReadinessProbe = c.ReadinessProbe
s.ReadinessProbe = c.ReadinessProbe // May need to move this into if statement
s.StartupProbe = c.StartupProbe
s.Lifecycle = c.Lifecycle
s.TerminationMessagePath = c.TerminationMessagePath
Expand All @@ -597,6 +631,7 @@ func (s *Sidecar) SetContainerFields(c corev1.Container) {
s.Stdin = c.Stdin
s.StdinOnce = c.StdinOnce
s.TTY = c.TTY
s.RestartPolicy = c.RestartPolicy
}

// GetVarSubstitutionExpressions walks all the places a substitution reference can be used
Expand Down
32 changes: 32 additions & 0 deletions pkg/apis/pipeline/v1/container_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,35 @@ func TestSidecarGetVarSubstitutionExpressions(t *testing.T) {
t.Fatalf("Unexpected result (-want, +got): %s", d)
}
}

func TestSidecarRestartPolicyToK8sContainer(t *testing.T) {
always := corev1.ContainerRestartPolicyAlways
s := Sidecar{
Name: "sidecarName",
RestartPolicy: &always,
}

expectedContainer := corev1.Container{
Name: "sidecarName",
RestartPolicy: &always,
}

c := s.ToK8sContainer()

if !(c.RestartPolicy == expectedContainer.RestartPolicy) {
t.Fatalf("Unexpected result with RestartPolicy")
}

s = Sidecar{
Name: "sidecarName",
}

expectedContainer = corev1.Container{
Name: "sidecarName",
}

c = s.ToK8sContainer()
if !(c.RestartPolicy == expectedContainer.RestartPolicy) {
t.Fatalf("Unexpected result without RestartPolicy")
}
}
7 changes: 7 additions & 0 deletions pkg/apis/pipeline/v1/openapi_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions pkg/apis/pipeline/v1/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -1325,6 +1325,10 @@
"description": "Periodic probe of Sidecar service readiness. Container will be removed from service endpoints if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes",
"$ref": "#/definitions/v1.Probe"
},
"restartPolicy": {
"description": "RestartPolicy refers to kubernetes RestartPolicy. It can only be set for an initContainer and must have it's policy set to \"Always\". It is currently left optional to help support Kubernetes versions prior to 1.29 when this feature was introduced.",
"type": "string"
},
"script": {
"description": "Script is the contents of an executable file to execute.\n\nIf Script is not empty, the Step cannot have an Command or Args.",
"type": "string"
Expand Down
5 changes: 5 additions & 0 deletions pkg/apis/pipeline/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions pkg/apis/pipeline/v1beta1/container_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -747,10 +747,43 @@ type Sidecar struct {
// +optional
// +listType=atomic
Workspaces []WorkspaceUsage `json:"workspaces,omitempty"`

// RestartPolicy refers to kubernetes RestartPolicy. It can only be set for an
// initContainer and must have it's policy set to "Always". It is currently
// left optional to help support Kubernetes versions prior to 1.29 when this feature
// was introduced.
// +optional
RestartPolicy *corev1.ContainerRestartPolicy `json:"restartPolicy,omitempty"`
}

// ToK8sContainer converts the Sidecar to a Kubernetes Container struct
func (s *Sidecar) ToK8sContainer() *corev1.Container {
if s.RestartPolicy == nil {
return &corev1.Container{
Name: s.Name,
Image: s.Image,
Command: s.Command,
Args: s.Args,
WorkingDir: s.WorkingDir,
Ports: s.Ports,
EnvFrom: s.EnvFrom,
Env: s.Env,
Resources: s.Resources,
VolumeMounts: s.VolumeMounts,
VolumeDevices: s.VolumeDevices,
LivenessProbe: s.LivenessProbe,
ReadinessProbe: s.ReadinessProbe,
StartupProbe: s.StartupProbe,
Lifecycle: s.Lifecycle,
TerminationMessagePath: s.TerminationMessagePath,
TerminationMessagePolicy: s.TerminationMessagePolicy,
ImagePullPolicy: s.ImagePullPolicy,
SecurityContext: s.SecurityContext,
Stdin: s.Stdin,
StdinOnce: s.StdinOnce,
TTY: s.TTY,
}
}
return &corev1.Container{
Name: s.Name,
Image: s.Image,
Expand All @@ -765,6 +798,7 @@ func (s *Sidecar) ToK8sContainer() *corev1.Container {
VolumeDevices: s.VolumeDevices,
LivenessProbe: s.LivenessProbe,
ReadinessProbe: s.ReadinessProbe,
RestartPolicy: s.RestartPolicy,
StartupProbe: s.StartupProbe,
Lifecycle: s.Lifecycle,
TerminationMessagePath: s.TerminationMessagePath,
Expand Down Expand Up @@ -801,4 +835,5 @@ func (s *Sidecar) SetContainerFields(c corev1.Container) {
s.Stdin = c.Stdin
s.StdinOnce = c.StdinOnce
s.TTY = c.TTY
s.RestartPolicy = c.RestartPolicy
}
7 changes: 7 additions & 0 deletions pkg/apis/pipeline/v1beta1/openapi_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions pkg/apis/pipeline/v1beta1/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -1932,6 +1932,10 @@
"default": {},
"$ref": "#/definitions/v1.ResourceRequirements"
},
"restartPolicy": {
"description": "RestartPolicy refers to kubernetes RestartPolicy. It can only be set for an initContainer and must have it's policy set to \"Always\". It is currently left optional to help support Kubernetes versions prior to 1.29 when this feature was introduced.",
"type": "string"
},
"script": {
"description": "Script is the contents of an executable file to execute.\n\nIf Script is not empty, the Step cannot have an Command or Args.",
"type": "string"
Expand Down
5 changes: 5 additions & 0 deletions pkg/apis/pipeline/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 36 additions & 6 deletions pkg/pod/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ const (

// TerminationReasonCancelled indicates a step was cancelled.
TerminationReasonCancelled = "Cancelled"

StepArtifactPathPattern = "step.artifacts.path"

// K8s version to determine if to use native k8s sidecar or Tekton sidecar
SidecarK8sMinorVersionCheck = 29
)

// These are effectively const, but Go doesn't have such an annotation.
Expand Down Expand Up @@ -174,6 +179,13 @@ func (b *Builder) Build(ctx context.Context, taskRun *v1.TaskRun, taskSpec v1.Ta
enableKeepPodOnCancel := featureFlags.EnableKeepPodOnCancel
setSecurityContext := config.FromContextOrDefaults(ctx).FeatureFlags.SetSecurityContext

// Kubernetes Version
dc := b.KubeClient.Discovery()
sv, err := dc.ServerVersion()
if err != nil {
return nil, err
}

// Add our implicit volumes first, so they can be overridden by the user if they prefer.
volumes = append(volumes, implicitVolumes...)
volumeMounts = append(volumeMounts, implicitVolumeMounts...)
Expand Down Expand Up @@ -426,11 +438,29 @@ func (b *Builder) Build(ctx context.Context, taskRun *v1.TaskRun, taskSpec v1.Ta
}

mergedPodContainers := stepContainers

// Merge sidecar containers with step containers.
for _, sc := range sidecarContainers {
sc.Name = names.SimpleNameGenerator.RestrictLength(fmt.Sprintf("%v%v", sidecarPrefix, sc.Name))
mergedPodContainers = append(mergedPodContainers, sc)
mergedPodInitContainers := initContainers

// Check if current k8s version is less than 1.29
// Since Kubernetes Major version cannot be 0 and if it's 2 then sidecar will be in
// we are only concerned about major version 1 and if the minor is less than 29 then
// we need to do the current logic
svMinorInt, _ := strconv.Atoi(sv.Minor)
svMajorInt, _ := strconv.Atoi(sv.Major)
if svMajorInt >= 1 && svMinorInt >= SidecarK8sMinorVersionCheck {
// Add RestartPolicy and Merge into initContainer
for i := range sidecarContainers {
sc := &sidecarContainers[i]
always := corev1.ContainerRestartPolicyAlways
sc.RestartPolicy = &always
sc.Name = names.SimpleNameGenerator.RestrictLength(fmt.Sprintf("%v%v", sidecarPrefix, sc.Name))
mergedPodInitContainers = append(mergedPodInitContainers, *sc)
}
} else {
// Merge sidecar containers with step containers.
for _, sc := range sidecarContainers {
sc.Name = names.SimpleNameGenerator.RestrictLength(fmt.Sprintf("%v%v", sidecarPrefix, sc.Name))
mergedPodContainers = append(mergedPodContainers, sc)
}
}

var dnsPolicy corev1.DNSPolicy
Expand Down Expand Up @@ -479,7 +509,7 @@ func (b *Builder) Build(ctx context.Context, taskRun *v1.TaskRun, taskSpec v1.Ta
},
Spec: corev1.PodSpec{
RestartPolicy: corev1.RestartPolicyNever,
InitContainers: initContainers,
InitContainers: mergedPodInitContainers,
Containers: mergedPodContainers,
ServiceAccountName: taskRun.Spec.ServiceAccountName,
Volumes: volumes,
Expand Down
Loading

0 comments on commit 0bf94a1

Please sign in to comment.