mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-02-22 07:03:28 +00:00
Merge pull request #133390 from SergeyKanzhelev/automated-cherry-pick-of-#132040-upstream-release-1.33
Automated cherry pick of #132040: Make nodeports scheduling plugin restartable initContainer aware
This commit is contained in:
@@ -50,9 +50,9 @@ const (
|
||||
ErrReason = "node(s) didn't have free ports for the requested pod ports"
|
||||
)
|
||||
|
||||
type preFilterState []*v1.ContainerPort
|
||||
type preFilterState []v1.ContainerPort
|
||||
|
||||
// Clone the prefilter state.
|
||||
// Clone the prefilter state.getContainerPorts(pod)
|
||||
func (s preFilterState) Clone() framework.StateData {
|
||||
// The state is not impacted by adding/removing existing pods, hence we don't need to make a deep copy.
|
||||
return s
|
||||
@@ -63,28 +63,9 @@ func (pl *NodePorts) Name() string {
|
||||
return Name
|
||||
}
|
||||
|
||||
// getContainerPorts returns the used host ports of Pods: if 'port' was used, a 'port:true' pair
|
||||
// will be in the result; but it does not resolve port conflict.
|
||||
func getContainerPorts(pods ...*v1.Pod) []*v1.ContainerPort {
|
||||
ports := []*v1.ContainerPort{}
|
||||
for _, pod := range pods {
|
||||
for j := range pod.Spec.Containers {
|
||||
container := &pod.Spec.Containers[j]
|
||||
for k := range container.Ports {
|
||||
// Only return ports with a host port specified.
|
||||
if container.Ports[k].HostPort <= 0 {
|
||||
continue
|
||||
}
|
||||
ports = append(ports, &container.Ports[k])
|
||||
}
|
||||
}
|
||||
}
|
||||
return ports
|
||||
}
|
||||
|
||||
// PreFilter invoked at the prefilter extension point.
|
||||
func (pl *NodePorts) PreFilter(ctx context.Context, cycleState *framework.CycleState, pod *v1.Pod) (*framework.PreFilterResult, *framework.Status) {
|
||||
s := getContainerPorts(pod)
|
||||
s := util.GetHostPorts(pod)
|
||||
// Skip if a pod has no ports.
|
||||
if len(s) == 0 {
|
||||
return nil, framework.NewStatus(framework.Skip)
|
||||
@@ -148,24 +129,19 @@ func (pl *NodePorts) isSchedulableAfterPodDeleted(logger klog.Logger, pod *v1.Po
|
||||
return framework.QueueSkip, nil
|
||||
}
|
||||
|
||||
// Get the used host ports of the deleted pod.
|
||||
usedPorts := make(framework.HostPortInfo)
|
||||
for _, container := range deletedPod.Spec.Containers {
|
||||
for _, podPort := range container.Ports {
|
||||
if podPort.HostPort > 0 {
|
||||
usedPorts.Add(podPort.HostIP, string(podPort.Protocol), podPort.HostPort)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the deleted pod doesn't use any host ports, it doesn't make the target pod schedulable.
|
||||
if len(usedPorts) == 0 {
|
||||
ports := util.GetHostPorts(deletedPod)
|
||||
if len(ports) == 0 {
|
||||
return framework.QueueSkip, nil
|
||||
}
|
||||
|
||||
// Construct a fake NodeInfo that only has the deleted Pod.
|
||||
// If we can schedule `pod` to this fake node, it means that `pod` and the deleted pod don't have any common port(s).
|
||||
// So, deleting that pod couldn't make `pod` schedulable.
|
||||
usedPorts := make(framework.HostPortInfo, len(ports))
|
||||
for _, p := range ports {
|
||||
usedPorts.Add(p.HostIP, string(p.Protocol), p.HostPort)
|
||||
}
|
||||
nodeInfo := framework.NodeInfo{UsedPorts: usedPorts}
|
||||
if Fits(pod, &nodeInfo) {
|
||||
logger.V(4).Info("the deleted pod and the target pod don't have any common port(s), returning QueueSkip as deleting this Pod won't make the Pod schedulable", "pod", klog.KObj(pod), "deletedPod", klog.KObj(deletedPod))
|
||||
@@ -193,10 +169,10 @@ func (pl *NodePorts) Filter(ctx context.Context, cycleState *framework.CycleStat
|
||||
|
||||
// Fits checks if the pod fits the node.
|
||||
func Fits(pod *v1.Pod, nodeInfo *framework.NodeInfo) bool {
|
||||
return fitsPorts(getContainerPorts(pod), nodeInfo)
|
||||
return fitsPorts(util.GetHostPorts(pod), nodeInfo)
|
||||
}
|
||||
|
||||
func fitsPorts(wantPorts []*v1.ContainerPort, nodeInfo *framework.NodeInfo) bool {
|
||||
func fitsPorts(wantPorts []v1.ContainerPort, nodeInfo *framework.NodeInfo) bool {
|
||||
// try to see whether existingPorts and wantPorts will conflict or not
|
||||
existingPorts := nodeInfo.UsedPorts
|
||||
for _, cp := range wantPorts {
|
||||
|
||||
@@ -17,7 +17,6 @@ limitations under the License.
|
||||
package nodeports
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -142,6 +141,34 @@ func TestNodePorts(t *testing.T) {
|
||||
name: "UDP hostPort conflict due to 0.0.0.0 hostIP",
|
||||
wantFilterStatus: framework.NewStatus(framework.Unschedulable, ErrReason),
|
||||
},
|
||||
{
|
||||
pod: st.MakePod().
|
||||
InitContainerPort(false /* sidecar */, []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
}).Obj(),
|
||||
nodeInfo: framework.NewNodeInfo(
|
||||
newPod("m1", "TCP/0.0.0.0/8001")),
|
||||
name: "non-sidecar initContainer using hostPort",
|
||||
wantPreFilterStatus: framework.NewStatus(framework.Skip),
|
||||
},
|
||||
{
|
||||
pod: st.MakePod().
|
||||
InitContainerPort(true /* sidecar */, []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
}).Obj(),
|
||||
nodeInfo: framework.NewNodeInfo(
|
||||
newPod("m1", "TCP/0.0.0.0/8001")),
|
||||
name: "TCP hostPort conflict from sidecar initContainer",
|
||||
wantFilterStatus: framework.NewStatus(framework.Unschedulable, ErrReason),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
@@ -188,120 +215,6 @@ func TestPreFilterDisabled(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetContainerPorts(t *testing.T) {
|
||||
tests := []struct {
|
||||
pod1 *v1.Pod
|
||||
pod2 *v1.Pod
|
||||
expected []*v1.ContainerPort
|
||||
}{
|
||||
{
|
||||
pod1: st.MakePod().ContainerPort([]v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8002,
|
||||
HostPort: 8002,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).ContainerPort([]v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8003,
|
||||
HostPort: 8003,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8004,
|
||||
HostPort: 8004,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).ContainerPort([]v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8005,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
}).Obj(),
|
||||
pod2: st.MakePod().ContainerPort([]v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8011,
|
||||
HostPort: 8011,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8012,
|
||||
HostPort: 8012,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).ContainerPort([]v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8013,
|
||||
HostPort: 8013,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8014,
|
||||
HostPort: 8014,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).ContainerPort([]v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8015,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
}).Obj(),
|
||||
expected: []*v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8002,
|
||||
HostPort: 8002,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8003,
|
||||
HostPort: 8003,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8004,
|
||||
HostPort: 8004,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8011,
|
||||
HostPort: 8011,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8012,
|
||||
HostPort: 8012,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8013,
|
||||
HostPort: 8013,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8014,
|
||||
HostPort: 8014,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
t.Run(fmt.Sprintf("case_%d", i), func(t *testing.T) {
|
||||
result := getContainerPorts(test.pod1, test.pod2)
|
||||
if diff := cmp.Diff(test.expected, result); diff != "" {
|
||||
t.Errorf("container ports: container ports does not match (-want,+got): %s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_isSchedulableAfterPodDeleted(t *testing.T) {
|
||||
podWithHostPort := st.MakePod().HostPort(8080)
|
||||
|
||||
|
||||
@@ -1164,13 +1164,11 @@ func (pi *PodInfo) calculateResource() podResource {
|
||||
|
||||
// updateUsedPorts updates the UsedPorts of NodeInfo.
|
||||
func (n *NodeInfo) updateUsedPorts(pod *v1.Pod, add bool) {
|
||||
for _, container := range pod.Spec.Containers {
|
||||
for _, podPort := range container.Ports {
|
||||
if add {
|
||||
n.UsedPorts.Add(podPort.HostIP, string(podPort.Protocol), podPort.HostPort)
|
||||
} else {
|
||||
n.UsedPorts.Remove(podPort.HostIP, string(podPort.Protocol), podPort.HostPort)
|
||||
}
|
||||
for _, port := range schedutil.GetHostPorts(pod) {
|
||||
if add {
|
||||
n.UsedPorts.Add(port.HostIP, string(port.Protocol), port.HostPort)
|
||||
} else {
|
||||
n.UsedPorts.Remove(port.HostIP, string(port.Protocol), port.HostPort)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2160,3 +2160,353 @@ func TestNodeInfoKMetadata(t *testing.T) {
|
||||
tCtx.Fatalf("unexpected output:\n%s", output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateUsedPorts_PodAdd(t *testing.T) {
|
||||
testCases := []struct {
|
||||
ports HostPortInfo
|
||||
pod *v1.Pod
|
||||
want HostPortInfo
|
||||
}{
|
||||
{
|
||||
ports: HostPortInfo{},
|
||||
pod: nil,
|
||||
want: HostPortInfo{},
|
||||
},
|
||||
{
|
||||
ports: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
},
|
||||
},
|
||||
pod: nil,
|
||||
want: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ports: HostPortInfo{},
|
||||
pod: st.MakePod().
|
||||
ContainerPort([]v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
Obj(),
|
||||
want: HostPortInfo{},
|
||||
},
|
||||
{
|
||||
ports: HostPortInfo{},
|
||||
pod: st.MakePod().
|
||||
ContainerPort([]v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
Obj(),
|
||||
want: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ports: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
},
|
||||
},
|
||||
pod: st.MakePod().
|
||||
ContainerPort([]v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8002,
|
||||
HostPort: 8002,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
Obj(),
|
||||
want: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
ProtocolPort{"TCP", 8002}: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ports: HostPortInfo{},
|
||||
pod: st.MakePod().
|
||||
InitContainerPort(false /* sidecar */, []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
Obj(),
|
||||
want: HostPortInfo{},
|
||||
},
|
||||
{
|
||||
ports: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
},
|
||||
},
|
||||
pod: st.MakePod().
|
||||
InitContainerPort(false /* sidecar */, []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8002,
|
||||
HostPort: 8002,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
Obj(),
|
||||
want: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ports: HostPortInfo{},
|
||||
pod: st.MakePod().
|
||||
InitContainerPort(true /* sidecar */, []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
Obj(),
|
||||
want: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ports: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
},
|
||||
},
|
||||
pod: st.MakePod().
|
||||
InitContainerPort(true /* sidecar */, []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
Obj(),
|
||||
want: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ports: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
},
|
||||
},
|
||||
pod: st.MakePod().
|
||||
InitContainerPort(true /* sidecar */, []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8002,
|
||||
HostPort: 8002,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
Obj(),
|
||||
want: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
ProtocolPort{"TCP", 8002}: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
ni := NodeInfo{UsedPorts: tc.ports}
|
||||
ni.updateUsedPorts(tc.pod, true)
|
||||
if diff := cmp.Diff(tc.want, ni.UsedPorts); diff != "" {
|
||||
t.Errorf("updateUsedPorts() unexpected diff (-want, +got):\n%s", diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateUsedPorts_PodRemove(t *testing.T) {
|
||||
testCases := []struct {
|
||||
ports HostPortInfo
|
||||
pod *v1.Pod
|
||||
want HostPortInfo
|
||||
}{
|
||||
{
|
||||
ports: HostPortInfo{},
|
||||
pod: nil,
|
||||
want: HostPortInfo{},
|
||||
},
|
||||
{
|
||||
ports: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
},
|
||||
},
|
||||
pod: nil,
|
||||
want: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ports: HostPortInfo{},
|
||||
pod: st.MakePod().
|
||||
ContainerPort([]v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
Obj(),
|
||||
want: HostPortInfo{},
|
||||
},
|
||||
{
|
||||
ports: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
},
|
||||
},
|
||||
pod: st.MakePod().
|
||||
ContainerPort([]v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
Obj(),
|
||||
want: HostPortInfo{},
|
||||
},
|
||||
{
|
||||
ports: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
},
|
||||
},
|
||||
pod: st.MakePod().
|
||||
ContainerPort([]v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8002,
|
||||
HostPort: 8002,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
Obj(),
|
||||
want: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ports: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
ProtocolPort{"TCP", 8002}: struct{}{},
|
||||
},
|
||||
},
|
||||
pod: st.MakePod().
|
||||
ContainerPort([]v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8002,
|
||||
HostPort: 8002,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
Obj(),
|
||||
want: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ports: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
},
|
||||
},
|
||||
pod: st.MakePod().
|
||||
InitContainerPort(false /* sidecar */, []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
Obj(),
|
||||
want: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ports: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
},
|
||||
},
|
||||
pod: st.MakePod().
|
||||
InitContainerPort(true /* sidecar */, []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
Obj(),
|
||||
want: HostPortInfo{},
|
||||
},
|
||||
{
|
||||
ports: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
},
|
||||
},
|
||||
pod: st.MakePod().
|
||||
InitContainerPort(true /* sidecar */, []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8002,
|
||||
HostPort: 8002,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
Obj(),
|
||||
want: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ports: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
ProtocolPort{"TCP", 8002}: struct{}{},
|
||||
},
|
||||
},
|
||||
pod: st.MakePod().
|
||||
InitContainerPort(true /* sidecar */, []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8002,
|
||||
HostPort: 8002,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
Obj(),
|
||||
want: HostPortInfo{
|
||||
"0.0.0.0": {
|
||||
ProtocolPort{"TCP", 8001}: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
ni := NodeInfo{UsedPorts: tc.ports}
|
||||
ni.updateUsedPorts(tc.pod, false)
|
||||
if diff := cmp.Diff(tc.want, ni.UsedPorts); diff != "" {
|
||||
t.Errorf("updateUsedPorts() unexpected diff (-want, +got):\n%s", diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -503,6 +503,20 @@ func (p *PodWrapper) ContainerPort(ports []v1.ContainerPort) *PodWrapper {
|
||||
return p
|
||||
}
|
||||
|
||||
// InitContainerPort creates an initContainer with ports valued `ports`,
|
||||
// and injects into the inner pod.
|
||||
func (p *PodWrapper) InitContainerPort(sidecar bool, ports []v1.ContainerPort) *PodWrapper {
|
||||
c := MakeContainer().
|
||||
Name("init-container").
|
||||
Image("pause").
|
||||
ContainerPort(ports)
|
||||
if sidecar {
|
||||
c.RestartPolicy(v1.ContainerRestartPolicyAlways)
|
||||
}
|
||||
p.Spec.InitContainers = append(p.Spec.InitContainers, c.Obj())
|
||||
return p
|
||||
}
|
||||
|
||||
// PVC creates a Volume with a PVC and injects into the inner pod.
|
||||
func (p *PodWrapper) PVC(name string) *PodWrapper {
|
||||
p.Spec.Volumes = append(p.Spec.Volumes, v1.Volume{
|
||||
|
||||
@@ -188,3 +188,39 @@ func As[T any](oldObj, newobj interface{}) (T, T, error) {
|
||||
}
|
||||
return oldTyped, newTyped, nil
|
||||
}
|
||||
|
||||
// GetHostPorts returns the used host ports of pod containers and
|
||||
// initContainers with restartPolicy: Always.
|
||||
func GetHostPorts(pod *v1.Pod) []v1.ContainerPort {
|
||||
var ports []v1.ContainerPort
|
||||
if pod == nil {
|
||||
return ports
|
||||
}
|
||||
|
||||
hostPort := func(p v1.ContainerPort) bool {
|
||||
return p.HostPort > 0
|
||||
}
|
||||
|
||||
for _, c := range pod.Spec.InitContainers {
|
||||
// Only consider initContainers that will be running the entire
|
||||
// duration of the Pod.
|
||||
if c.RestartPolicy == nil || *c.RestartPolicy != v1.ContainerRestartPolicyAlways {
|
||||
continue
|
||||
}
|
||||
for _, p := range c.Ports {
|
||||
if !hostPort(p) {
|
||||
continue
|
||||
}
|
||||
ports = append(ports, p)
|
||||
}
|
||||
}
|
||||
for _, c := range pod.Spec.Containers {
|
||||
for _, p := range c.Ports {
|
||||
if !hostPort(p) {
|
||||
continue
|
||||
}
|
||||
ports = append(ports, p)
|
||||
}
|
||||
}
|
||||
return ports
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import (
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/klog/v2/ktesting"
|
||||
extenderv1 "k8s.io/kube-scheduler/extender/v1"
|
||||
st "k8s.io/kubernetes/pkg/scheduler/testing"
|
||||
)
|
||||
|
||||
func TestGetPodFullName(t *testing.T) {
|
||||
@@ -546,3 +547,232 @@ func Test_As_KMetadata(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetHostPorts(t *testing.T) {
|
||||
tests := []struct {
|
||||
pod *v1.Pod
|
||||
want []v1.ContainerPort
|
||||
}{
|
||||
{
|
||||
pod: nil,
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
pod: st.MakePod().
|
||||
ContainerPort([]v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
Obj(),
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
pod: st.MakePod().
|
||||
InitContainerPort(true /* sidecar */, []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
Obj(),
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
pod: st.MakePod().
|
||||
InitContainerPort(false /* sidecar */, []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
Obj(),
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
pod: st.MakePod().
|
||||
ContainerPort([]v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
Obj(),
|
||||
want: []v1.ContainerPort{{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}},
|
||||
},
|
||||
{
|
||||
pod: st.MakePod().
|
||||
InitContainerPort(true /* sidecar */, []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
Obj(),
|
||||
want: []v1.ContainerPort{{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}},
|
||||
},
|
||||
{
|
||||
pod: st.MakePod().
|
||||
ContainerPort([]v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8002,
|
||||
HostPort: 8002,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
ContainerPort([]v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8003,
|
||||
HostPort: 8003,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8004,
|
||||
HostPort: 8004,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}}).
|
||||
ContainerPort([]v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8005,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
}).Obj(),
|
||||
want: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8002,
|
||||
HostPort: 8002,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8003,
|
||||
HostPort: 8003,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8004,
|
||||
HostPort: 8004,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
pod: st.MakePod().
|
||||
InitContainerPort(false /* sidecar */, []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8002,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
}).
|
||||
InitContainerPort(false /* sidecar */, []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8003,
|
||||
HostPort: 8003,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
}).
|
||||
InitContainerPort(true /* sidecar */, []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8004,
|
||||
HostPort: 8004,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8005,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8006,
|
||||
HostPort: 8006,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
}).
|
||||
ContainerPort([]v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8007,
|
||||
HostPort: 8007,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8008,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
}).Obj(),
|
||||
want: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8004,
|
||||
HostPort: 8004,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8006,
|
||||
HostPort: 8006,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8007,
|
||||
HostPort: 8007,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
pod: st.MakePod().
|
||||
InitContainerPort(true /* sidecar */, []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 9001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
}).
|
||||
ContainerPort([]v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8002,
|
||||
HostPort: 9002,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
}).Obj(),
|
||||
want: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 9001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8002,
|
||||
HostPort: 9002,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
t.Run(fmt.Sprintf("case_%d", i), func(t *testing.T) {
|
||||
result := GetHostPorts(test.pod)
|
||||
if diff := cmp.Diff(test.want, result); diff != "" {
|
||||
t.Errorf("GetHostPorts() unexpected diff (-want,+got): %s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -638,3 +638,389 @@ func TestNodeEvents(t *testing.T) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestHostPorts(t *testing.T) {
|
||||
type podPorts struct {
|
||||
container []v1.ContainerPort
|
||||
restartableInitContainer []v1.ContainerPort
|
||||
nonRestartableInitContainer []v1.ContainerPort
|
||||
}
|
||||
|
||||
// Tests run with one node for scheduling. The first pod must always be scheduable.
|
||||
tests := []struct {
|
||||
name string
|
||||
firstPorts podPorts
|
||||
secondPorts podPorts
|
||||
wantSecondScheduled bool
|
||||
}{
|
||||
{
|
||||
name: "Containers using same non-host port",
|
||||
firstPorts: podPorts{
|
||||
container: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
secondPorts: podPorts{
|
||||
container: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantSecondScheduled: true,
|
||||
},
|
||||
{
|
||||
name: "non-restartable initContainer and container using same non-host port",
|
||||
firstPorts: podPorts{
|
||||
nonRestartableInitContainer: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
secondPorts: podPorts{
|
||||
container: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantSecondScheduled: true,
|
||||
},
|
||||
{
|
||||
name: "restartable initContainer and container using same non-host port",
|
||||
firstPorts: podPorts{
|
||||
restartableInitContainer: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
secondPorts: podPorts{
|
||||
container: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantSecondScheduled: true,
|
||||
},
|
||||
{
|
||||
name: "container and non-restartable initContainer using same non-host port",
|
||||
firstPorts: podPorts{
|
||||
container: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
secondPorts: podPorts{
|
||||
nonRestartableInitContainer: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantSecondScheduled: true,
|
||||
},
|
||||
{
|
||||
name: "container and restartable initContainer using same non-host port",
|
||||
firstPorts: podPorts{
|
||||
container: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
secondPorts: podPorts{
|
||||
restartableInitContainer: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantSecondScheduled: true,
|
||||
},
|
||||
{
|
||||
name: "containers using same host port",
|
||||
firstPorts: podPorts{
|
||||
container: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
secondPorts: podPorts{
|
||||
container: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantSecondScheduled: false,
|
||||
},
|
||||
{
|
||||
name: "non-restartable initContainer and container using same host port",
|
||||
firstPorts: podPorts{
|
||||
nonRestartableInitContainer: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
secondPorts: podPorts{
|
||||
container: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantSecondScheduled: true,
|
||||
},
|
||||
{
|
||||
name: "restartable initContainer and container using same host port",
|
||||
firstPorts: podPorts{
|
||||
restartableInitContainer: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
secondPorts: podPorts{
|
||||
container: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantSecondScheduled: false,
|
||||
},
|
||||
{
|
||||
name: "container and non-restartable initContainer using same host port",
|
||||
firstPorts: podPorts{
|
||||
container: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
secondPorts: podPorts{
|
||||
nonRestartableInitContainer: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantSecondScheduled: true,
|
||||
},
|
||||
{
|
||||
name: "container and restartable initContainer using same host port",
|
||||
firstPorts: podPorts{
|
||||
container: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
secondPorts: podPorts{
|
||||
restartableInitContainer: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantSecondScheduled: false,
|
||||
},
|
||||
{
|
||||
name: "containers using different host ports",
|
||||
firstPorts: podPorts{
|
||||
container: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
secondPorts: podPorts{
|
||||
container: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8002,
|
||||
HostPort: 8002,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantSecondScheduled: true,
|
||||
},
|
||||
{
|
||||
name: "non-restartable initContainer and container using different host ports",
|
||||
firstPorts: podPorts{
|
||||
nonRestartableInitContainer: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
secondPorts: podPorts{
|
||||
container: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8002,
|
||||
HostPort: 8002,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantSecondScheduled: true,
|
||||
},
|
||||
{
|
||||
name: "restartable initContainer and container using different host ports",
|
||||
firstPorts: podPorts{
|
||||
restartableInitContainer: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
secondPorts: podPorts{
|
||||
container: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8002,
|
||||
HostPort: 8002,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantSecondScheduled: true,
|
||||
},
|
||||
{
|
||||
name: "container and non-restartable initContainer using different host ports",
|
||||
firstPorts: podPorts{
|
||||
container: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
secondPorts: podPorts{
|
||||
nonRestartableInitContainer: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8002,
|
||||
HostPort: 8002,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantSecondScheduled: true,
|
||||
},
|
||||
{
|
||||
name: "container and restartable initContainer using different host ports",
|
||||
firstPorts: podPorts{
|
||||
container: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8001,
|
||||
HostPort: 8001,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
secondPorts: podPorts{
|
||||
restartableInitContainer: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 8002,
|
||||
HostPort: 8002,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantSecondScheduled: true,
|
||||
},
|
||||
}
|
||||
|
||||
testCtx := testutils.InitTestSchedulerWithNS(t, "conflicting-host-ports")
|
||||
node, err := testutils.CreateNode(testCtx.ClientSet, st.MakeNode().
|
||||
Name("conflicting-host-ports-node").Obj())
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create %s: %v", node.Name, err)
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
p1, err := testutils.CreatePausePod(testCtx.ClientSet, testutils.InitPausePod(&testutils.PausePodConfig{
|
||||
Name: "p1",
|
||||
Namespace: testCtx.NS.Name,
|
||||
ContainerPorts: tc.firstPorts.container,
|
||||
RestartableInitContainerPorts: tc.firstPorts.restartableInitContainer,
|
||||
NonRestartableInitContainerPorts: tc.firstPorts.nonRestartableInitContainer,
|
||||
}))
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create Pod p1: %v", err)
|
||||
}
|
||||
err = testutils.WaitForPodToScheduleWithTimeout(testCtx.Ctx, testCtx.ClientSet, p1, 5*time.Second)
|
||||
if err != nil {
|
||||
t.Errorf("Pod %s didn't schedule: %v", p1.Name, err)
|
||||
}
|
||||
|
||||
p2, err := testutils.CreatePausePod(testCtx.ClientSet, testutils.InitPausePod(&testutils.PausePodConfig{
|
||||
Name: "p2",
|
||||
Namespace: testCtx.NS.Name,
|
||||
ContainerPorts: tc.secondPorts.container,
|
||||
RestartableInitContainerPorts: tc.secondPorts.restartableInitContainer,
|
||||
NonRestartableInitContainerPorts: tc.secondPorts.nonRestartableInitContainer,
|
||||
}))
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create Pod p2: %v", err)
|
||||
}
|
||||
|
||||
if tc.wantSecondScheduled {
|
||||
err = testutils.WaitForPodToScheduleWithTimeout(testCtx.Ctx, testCtx.ClientSet, p2, 5*time.Second)
|
||||
if err != nil {
|
||||
t.Errorf("Pod %s didn't schedule: %v", p2.Name, err)
|
||||
}
|
||||
} else {
|
||||
if err := testutils.WaitForPodUnschedulable(testCtx.Ctx, testCtx.ClientSet, p2); err != nil {
|
||||
t.Errorf("Pod %v got scheduled: %v", p2.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
testutils.CleanupPods(testCtx.Ctx, testCtx.ClientSet, t, []*v1.Pod{p1, p2})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -814,6 +814,9 @@ type PausePodConfig struct {
|
||||
PreemptionPolicy *v1.PreemptionPolicy
|
||||
PriorityClassName string
|
||||
Volumes []v1.Volume
|
||||
ContainerPorts []v1.ContainerPort
|
||||
RestartableInitContainerPorts []v1.ContainerPort
|
||||
NonRestartableInitContainerPorts []v1.ContainerPort
|
||||
}
|
||||
|
||||
// InitPausePod initializes a pod API object from the given config. It is used
|
||||
@@ -833,6 +836,7 @@ func InitPausePod(conf *PausePodConfig) *v1.Pod {
|
||||
{
|
||||
Name: conf.Name,
|
||||
Image: imageutils.GetPauseImageName(),
|
||||
Ports: conf.ContainerPorts,
|
||||
},
|
||||
},
|
||||
Tolerations: conf.Tolerations,
|
||||
@@ -847,6 +851,26 @@ func InitPausePod(conf *PausePodConfig) *v1.Pod {
|
||||
if conf.Resources != nil {
|
||||
pod.Spec.Containers[0].Resources = *conf.Resources
|
||||
}
|
||||
if conf.RestartableInitContainerPorts != nil {
|
||||
var containerRestartPolicyAlways = v1.ContainerRestartPolicyAlways
|
||||
pod.Spec.InitContainers = []v1.Container{
|
||||
{
|
||||
Name: conf.Name + "-init",
|
||||
Image: imageutils.GetPauseImageName(),
|
||||
RestartPolicy: &containerRestartPolicyAlways,
|
||||
Ports: conf.RestartableInitContainerPorts,
|
||||
},
|
||||
}
|
||||
}
|
||||
if conf.NonRestartableInitContainerPorts != nil {
|
||||
pod.Spec.InitContainers = []v1.Container{
|
||||
{
|
||||
Name: conf.Name + "-init",
|
||||
Image: imageutils.GetPauseImageName(),
|
||||
Ports: conf.NonRestartableInitContainerPorts,
|
||||
},
|
||||
}
|
||||
}
|
||||
return pod
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user