@@ -41,7 +41,9 @@ import (
41
41
kubetypes "k8s.io/apimachinery/pkg/types"
42
42
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
43
43
"k8s.io/apimachinery/pkg/util/sets"
44
+ utilfeature "k8s.io/apiserver/pkg/util/feature"
44
45
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
46
+ "k8s.io/kubernetes/pkg/features"
45
47
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
46
48
"k8s.io/kubernetes/pkg/kubelet/events"
47
49
"k8s.io/kubernetes/pkg/kubelet/types"
@@ -86,13 +88,52 @@ func (m *kubeGenericRuntimeManager) recordContainerEvent(pod *v1.Pod, container
86
88
m .recorder .Event (ref , eventType , reason , eventMessage )
87
89
}
88
90
91
+ // startSpec wraps the spec required to start a container, either a regular/init container
92
+ // or an ephemeral container. Ephemeral containers contain all the fields of regular/init
93
+ // containers, plus some additional fields. In both cases startSpec.container will be set.
94
+ type startSpec struct {
95
+ container * v1.Container
96
+ ephemeralContainer * v1.EphemeralContainer
97
+ }
98
+
99
+ func containerStartSpec (c * v1.Container ) * startSpec {
100
+ return & startSpec {container : c }
101
+ }
102
+
103
+ func ephemeralContainerStartSpec (ec * v1.EphemeralContainer ) * startSpec {
104
+ return & startSpec {
105
+ container : (* v1 .Container )(& ec .EphemeralContainerCommon ),
106
+ ephemeralContainer : ec ,
107
+ }
108
+ }
109
+
110
+ // getTargetID returns the kubecontainer.ContainerID for ephemeral container namespace
111
+ // targeting. The target is stored as EphemeralContainer.TargetContainerName, which must be
112
+ // resolved to a ContainerID using podStatus. The target container must already exist, which
113
+ // usually isn't a problem since ephemeral containers aren't allowed at pod creation time.
114
+ // This always returns nil when the EphemeralContainers feature is disabled.
115
+ func (s * startSpec ) getTargetID (podStatus * kubecontainer.PodStatus ) (* kubecontainer.ContainerID , error ) {
116
+ if s .ephemeralContainer == nil || s .ephemeralContainer .TargetContainerName == "" || ! utilfeature .DefaultFeatureGate .Enabled (features .EphemeralContainers ) {
117
+ return nil , nil
118
+ }
119
+
120
+ targetStatus := podStatus .FindContainerStatusByName (s .ephemeralContainer .TargetContainerName )
121
+ if targetStatus == nil {
122
+ return nil , fmt .Errorf ("unable to find target container %v" , s .ephemeralContainer .TargetContainerName )
123
+ }
124
+
125
+ return & targetStatus .ID , nil
126
+ }
127
+
89
128
// startContainer starts a container and returns a message indicates why it is failed on error.
90
129
// It starts the container through the following steps:
91
130
// * pull the image
92
131
// * create the container
93
132
// * start the container
94
133
// * run the post start lifecycle hooks (if applicable)
95
- func (m * kubeGenericRuntimeManager ) startContainer (podSandboxID string , podSandboxConfig * runtimeapi.PodSandboxConfig , container * v1.Container , pod * v1.Pod , podStatus * kubecontainer.PodStatus , pullSecrets []v1.Secret , podIP string , podIPs []string ) (string , error ) {
134
+ func (m * kubeGenericRuntimeManager ) startContainer (podSandboxID string , podSandboxConfig * runtimeapi.PodSandboxConfig , spec * startSpec , pod * v1.Pod , podStatus * kubecontainer.PodStatus , pullSecrets []v1.Secret , podIP string , podIPs []string ) (string , error ) {
135
+ container := spec .container
136
+
96
137
// Step 1: pull the image.
97
138
imageRef , msg , err := m .imagePuller .EnsureImageExists (pod , container , pullSecrets , podSandboxConfig )
98
139
if err != nil {
@@ -115,7 +156,14 @@ func (m *kubeGenericRuntimeManager) startContainer(podSandboxID string, podSandb
115
156
restartCount = containerStatus .RestartCount + 1
116
157
}
117
158
118
- containerConfig , cleanupAction , err := m .generateContainerConfig (container , pod , restartCount , podIP , imageRef , podIPs )
159
+ target , err := spec .getTargetID (podStatus )
160
+ if err != nil {
161
+ s , _ := grpcstatus .FromError (err )
162
+ m .recordContainerEvent (pod , container , "" , v1 .EventTypeWarning , events .FailedToCreateContainer , "Error: %v" , s .Message ())
163
+ return s .Message (), ErrCreateContainerConfig
164
+ }
165
+
166
+ containerConfig , cleanupAction , err := m .generateContainerConfig (container , pod , restartCount , podIP , imageRef , podIPs , target )
119
167
if cleanupAction != nil {
120
168
defer cleanupAction ()
121
169
}
@@ -195,7 +243,7 @@ func (m *kubeGenericRuntimeManager) startContainer(podSandboxID string, podSandb
195
243
}
196
244
197
245
// generateContainerConfig generates container config for kubelet runtime v1.
198
- func (m * kubeGenericRuntimeManager ) generateContainerConfig (container * v1.Container , pod * v1.Pod , restartCount int , podIP , imageRef string , podIPs []string ) (* runtimeapi.ContainerConfig , func (), error ) {
246
+ func (m * kubeGenericRuntimeManager ) generateContainerConfig (container * v1.Container , pod * v1.Pod , restartCount int , podIP , imageRef string , podIPs []string , nsTarget * kubecontainer. ContainerID ) (* runtimeapi.ContainerConfig , func (), error ) {
199
247
opts , cleanupAction , err := m .runtimeHelper .GenerateRunContainerOptions (pod , container , podIP , podIPs )
200
248
if err != nil {
201
249
return nil , nil , err
@@ -239,7 +287,7 @@ func (m *kubeGenericRuntimeManager) generateContainerConfig(container *v1.Contai
239
287
}
240
288
241
289
// set platform specific configurations.
242
- if err := m .applyPlatformSpecificContainerConfig (config , container , pod , uid , username ); err != nil {
290
+ if err := m .applyPlatformSpecificContainerConfig (config , container , pod , uid , username , nsTarget ); err != nil {
243
291
return nil , cleanupAction , err
244
292
}
245
293
0 commit comments