Skip to content
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
35 changes: 35 additions & 0 deletions src/FSLibrary.Tests/Tests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,41 @@ type Tests(output: ITestOutputHelper) =
Assert.Null(spec.Affinity)
Assert.Equal(nCfgPlain.Nonce, nCfgPlain.PodLabels().[CfgVal.runNonceLabelKey])

[<Fact>]
member __.``HTTP proxy pod inherits mission node affinity and tolerations``() =
// Regression: the HTTP proxy Deployment must carry the mission's node
// placement (self.Affinity()/self.Tolerations()) like the core pods it
// fronts -- otherwise it cannot schedule onto a tainted/dedicated pool
// and stays Pending on a busy cluster.
let nCfg =
MakeNetworkCfg
{ ctx with
requireNodeLabels = [ ("purpose", Some "largetests") ]
tolerateNodeTaints = [ ("largetests", None) ]
installNetworkDelay = Some false }
[ coreSet ]
passOpt

let spec = nCfg.ToHttpProxyDeployment().Spec.Template.Spec

// Node affinity requires the mission node label.
Assert.NotNull(spec.Affinity)
Assert.NotNull(spec.Affinity.NodeAffinity)

let term =
Seq.exactlyOne spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms

let expr = Seq.exactlyOne term.MatchExpressions
Assert.Equal("purpose", expr.Key)
Assert.Equal("In", expr.OperatorProperty)
Assert.Equal("largetests", Seq.exactlyOne expr.Values)

// Tolerates the mission node taint.
Assert.True(
spec.Tolerations
|> Seq.exists (fun t -> t.Key = "largetests" && t.OperatorProperty = "Exists")
)

[<Fact>]
member __.``Core init commands look reasonable``() =
let nCfgWithoutSimulateApply =
Expand Down
11 changes: 10 additions & 1 deletion src/FSLibrary/StellarKubeSpecs.fs
Original file line number Diff line number Diff line change
Expand Up @@ -974,7 +974,16 @@ type NetworkCfg with
configMap = V1ConfigMapVolumeSource(name = self.HttpProxyConfigMapName)
)

let podSpec = V1PodSpec(containers = [| container |], volumes = [| volume |])
// Mirror the core pods' node placement so the proxy schedules onto the
// same (often tainted/dedicated) node pool it fronts -- otherwise it is
// confined to untainted capacity and can stay Pending on a busy cluster.
let podSpec =
V1PodSpec(
containers = [| container |],
volumes = [| volume |],
?affinity = self.Affinity(),
tolerations = self.Tolerations()
Comment thread
Jonathan-Eid marked this conversation as resolved.
)

let podTemplate =
V1PodTemplateSpec(metadata = V1ObjectMeta(labels = self.HttpProxyLabels), spec = podSpec)
Expand Down
Loading