-
Notifications
You must be signed in to change notification settings - Fork 1k
add volcanojob interpreter #6790
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
Open
dekaihu
wants to merge
1
commit into
karmada-io:master
Choose a base branch
from
dekaihu:interpreter-vcjob
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+413
−0
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
228 changes: 228 additions & 0 deletions
228
...fault/thirdparty/resourcecustomizations/batch.volcano.sh/v1alpha1/Job/customizations.yaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,228 @@ | ||
apiVersion: config.karmada.io/v1alpha1 | ||
kind: ResourceInterpreterCustomization | ||
metadata: | ||
name: declarative-configuration-job | ||
spec: | ||
target: | ||
apiVersion: batch.volcano.sh/v1alpha1 | ||
kind: Job | ||
customizations: | ||
healthInterpretation: | ||
luaScript: > | ||
function InterpretHealth(observedObj) | ||
if observedObj.status == nil or observedObj.status.state == nil then | ||
return false | ||
end | ||
local phase = observedObj.status.state.phase | ||
if phase == nil or phase == '' then | ||
return false | ||
end | ||
if phase == 'Running' or phase == 'Completed' or phase == "Pending" or | ||
phase == "Aborting" or phase == "Aborted" or phase == "Restarting" or | ||
phase == "Completing" or phase == "Terminating" or phase == "Terminated" then | ||
return true | ||
end | ||
return false | ||
end | ||
componentResource: | ||
luaScript: | | ||
local kube = require("kube") | ||
local function get(obj, path) | ||
local cur = obj | ||
for i = 1, #path do | ||
if cur == nil then return nil end | ||
cur = cur[path[i]] | ||
end | ||
return cur | ||
end | ||
local function to_num(v, default) | ||
if v == nil or v == '' then | ||
return default | ||
end | ||
local n = tonumber(v) | ||
if n ~= nil then return n end | ||
return default | ||
end | ||
function GetComponents(observedObj) | ||
local components = {} | ||
local tasks = get(observedObj, {"spec","tasks"}) | ||
if tasks == nil then | ||
return components | ||
end | ||
for _, task in ipairs(tasks) do | ||
local replicas = to_num(task.minAvailable, 1) | ||
requires = kube.accuratePodRequirements(task.template) | ||
table.insert(components, { | ||
name = task.name, | ||
replicas = replicas, | ||
replicaRequirements = requires | ||
}) | ||
end | ||
return components | ||
end | ||
statusAggregation: | ||
luaScript: > | ||
local function durationVal(d) | ||
if type(d) == "number" then | ||
return d | ||
end | ||
if type(d) ~= "string" then | ||
return 0 | ||
end | ||
local totalSeconds = 0 | ||
for num, unit in string.gmatch(d, "([%d%.]+)([hms])") do | ||
num = tonumber(num) | ||
if unit == "h" then | ||
totalSeconds = totalSeconds + num * 3600 | ||
elseif unit == "m" then | ||
totalSeconds = totalSeconds + num * 60 | ||
elseif unit == "s" then | ||
totalSeconds = totalSeconds + num | ||
end | ||
end | ||
if totalSeconds > 0 then | ||
return totalSeconds | ||
end | ||
return tonumber(d) or 0 | ||
end | ||
local function omitEmpty(t) | ||
if t == nil then return nil end | ||
local out = {} | ||
for k, v in pairs(t) do | ||
if type(v) == "table" then | ||
local inner = omitEmpty(v) | ||
if inner ~= nil and next(inner) ~= nil then | ||
out[k] = inner | ||
end | ||
elseif v ~= nil and not (v == 0 or v == "" or v == "0s") then | ||
out[k] = v | ||
end | ||
end | ||
if next(out) ~= nil then | ||
return out | ||
else | ||
return nil | ||
end | ||
end | ||
function AggregateStatus(desiredObj, statusItems) | ||
if statusItems == nil then return desiredObj end | ||
if desiredObj.status == nil then desiredObj.status = {} end | ||
local status = { | ||
state = {}, | ||
minAvailable = 0, | ||
taskStatusCount = {}, | ||
pending = 0, | ||
running = 0, | ||
succeeded = 0, | ||
failed = 0, | ||
terminating = 0, | ||
unknown = 0, | ||
version = 0, | ||
retryCount = 0, | ||
controlledResources = {}, | ||
conditions = {}, | ||
runningDuration = "0s", | ||
state = {} | ||
} | ||
for i = 1, #statusItems do | ||
local s = statusItems[i].status | ||
if s ~= nil then | ||
status.minAvailable = status.minAvailable + (s.minAvailable or 0) | ||
status.pending = status.pending + (s.pending or 0) | ||
status.running = status.running + (s.running or 0) | ||
status.succeeded = status.succeeded + (s.succeeded or 0) | ||
status.failed = status.failed + (s.failed or 0) | ||
status.terminating = status.terminating + (s.terminating or 0) | ||
status.unknown = status.unknown + (s.unknown or 0) | ||
status.version = math.max(status.version, s.version or 0) | ||
status.retryCount = status.retryCount + (s.retryCount or 0) | ||
status.state = s.state | ||
if durationVal(s.runningDuration) > durationVal(status.runningDuration) then | ||
status.runningDuration = s.runningDuration | ||
end | ||
if s.taskStatusCount ~= nil then | ||
for taskName, taskStatus in pairs(s.taskStatusCount) do | ||
if status.taskStatusCount[taskName] == nil then | ||
status.taskStatusCount[taskName] = { phase = {} } | ||
end | ||
if taskStatus.phase ~= nil then | ||
for phaseName, count in pairs(taskStatus.phase) do | ||
status.taskStatusCount[taskName].phase[phaseName] = (status.taskStatusCount[taskName].phase[phaseName] or 0) + count | ||
end | ||
end | ||
end | ||
end | ||
if s.controlledResources then | ||
for k, v in pairs(s.controlledResources) do | ||
status.controlledResources[k] = v | ||
end | ||
end | ||
if s.conditions ~= nil then | ||
for _, c in ipairs(s.conditions) do | ||
table.insert(status.conditions, c) | ||
end | ||
end | ||
end | ||
end | ||
desiredObj.status = omitEmpty(status) or {} | ||
return desiredObj | ||
end | ||
statusReflection: | ||
luaScript: > | ||
function ReflectStatus(observedObj) | ||
local status = {} | ||
if observedObj == nil or observedObj.status == nil then | ||
return status | ||
end | ||
local s = observedObj.status | ||
status.minAvailable = s.minAvailable | ||
status.pending = s.pending | ||
status.running = s.running | ||
status.succeeded = s.succeeded | ||
status.failed = s.failed | ||
status.terminating = s.terminating | ||
status.unknown = s.unknown | ||
status.version = s.version | ||
status.retryCount = s.retryCount | ||
status.runningDuration = s.runningDuration | ||
status.taskStatusCount = {} | ||
if s.taskStatusCount ~= nil then | ||
for k, v in pairs(s.taskStatusCount) do | ||
status.taskStatusCount[k] = v | ||
end | ||
end | ||
status.controlledResources = {} | ||
if s.controlledResources ~= nil then | ||
for k, v in pairs(s.controlledResources) do | ||
status.controlledResources[k] = v | ||
end | ||
end | ||
if s.state ~= nil then | ||
status.state = s.state | ||
end | ||
dekaihu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
RainbowMango marked this conversation as resolved.
Show resolved
Hide resolved
|
||
status.conditions = {} | ||
if type(s.conditions) == "table" then | ||
for _, cond in ipairs(s.conditions) do | ||
table.insert(status.conditions, cond) | ||
end | ||
end | ||
return status | ||
end |
8 changes: 8 additions & 0 deletions
8
...thirdparty/resourcecustomizations/batch.volcano.sh/v1alpha1/Job/customizations_tests.yaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
tests: | ||
- desiredInputPath: testdata/desired-job.yaml | ||
statusInputPath: testdata/status-file.yaml | ||
operation: AggregateStatus | ||
- observedInputPath: testdata/observed-job.yaml | ||
operation: InterpretHealth | ||
- observedInputPath: testdata/observed-job.yaml | ||
operation: InterpretStatus |
59 changes: 59 additions & 0 deletions
59
...thirdparty/resourcecustomizations/batch.volcano.sh/v1alpha1/Job/testdata/desired-job.yaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
apiVersion: batch.volcano.sh/v1alpha1 | ||
kind: Job | ||
metadata: | ||
name: dk-job | ||
spec: | ||
maxRetry: 3 | ||
minAvailable: 3 | ||
plugins: | ||
env: [] | ||
ssh: [] | ||
svc: | ||
- --disable-network-policy=true | ||
queue: default | ||
schedulerName: volcano | ||
tasks: | ||
- minAvailable: 1 | ||
name: job-nginx1 | ||
replicas: 1 | ||
template: | ||
metadata: | ||
name: nginx1 | ||
spec: | ||
containers: | ||
- args: | ||
- sleep 10 | ||
command: | ||
- bash | ||
- -c | ||
image: nginx:latest | ||
imagePullPolicy: IfNotPresent | ||
name: nginx | ||
resources: | ||
requests: | ||
cpu: 100m | ||
nodeSelector: | ||
kubernetes.io/os: linux | ||
restartPolicy: OnFailure | ||
- minAvailable: 2 | ||
name: job-nginx2 | ||
replicas: 3 | ||
template: | ||
metadata: | ||
name: nginx2 | ||
spec: | ||
containers: | ||
- args: | ||
- sleep 30 | ||
command: | ||
- bash | ||
- -c | ||
image: nginx:latest | ||
imagePullPolicy: IfNotPresent | ||
name: nginx | ||
resources: | ||
requests: | ||
cpu: 100m | ||
nodeSelector: | ||
kubernetes.io/os: linux | ||
restartPolicy: OnFailure |
87 changes: 87 additions & 0 deletions
87
...hirdparty/resourcecustomizations/batch.volcano.sh/v1alpha1/Job/testdata/observed-job.yaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
apiVersion: batch.volcano.sh/v1alpha1 | ||
kind: Job | ||
metadata: | ||
name: dk-job | ||
spec: | ||
maxRetry: 3 | ||
minAvailable: 3 | ||
plugins: | ||
env: [] | ||
ssh: [] | ||
svc: | ||
- --disable-network-policy=true | ||
queue: default | ||
schedulerName: volcano | ||
tasks: | ||
- minAvailable: 1 | ||
name: job-nginx1 | ||
replicas: 1 | ||
template: | ||
metadata: | ||
name: nginx1 | ||
spec: | ||
containers: | ||
- args: | ||
- sleep 10 | ||
command: | ||
- bash | ||
- -c | ||
image: nginx:latest | ||
imagePullPolicy: IfNotPresent | ||
name: nginx | ||
resources: | ||
requests: | ||
cpu: 100m | ||
nodeSelector: | ||
kubernetes.io/os: linux | ||
restartPolicy: OnFailure | ||
- minAvailable: 2 | ||
name: job-nginx2 | ||
replicas: 3 | ||
template: | ||
metadata: | ||
name: nginx2 | ||
spec: | ||
containers: | ||
- args: | ||
- sleep 30 | ||
command: | ||
- bash | ||
- -c | ||
image: nginx:latest | ||
imagePullPolicy: IfNotPresent | ||
name: nginx | ||
resources: | ||
requests: | ||
cpu: 100m | ||
nodeSelector: | ||
kubernetes.io/os: linux | ||
restartPolicy: OnFailure | ||
status: | ||
conditions: | ||
- lastTransitionTime: "2025-09-29T10:57:03Z" | ||
status: Pending | ||
- lastTransitionTime: "2025-09-29T10:57:07Z" | ||
status: Running | ||
- lastTransitionTime: "2025-09-29T10:57:38Z" | ||
status: Completed | ||
failed: 0 | ||
minAvailable: 3 | ||
pending: 0 | ||
retryCount: 0 | ||
running: 0 | ||
runningDuration: 35.688396584s | ||
state: | ||
lastTransitionTime: "2025-09-29T10:57:38Z" | ||
phase: Completed | ||
succeeded: 4 | ||
taskStatusCount: | ||
job-nginx1: | ||
phase: | ||
Succeeded: 1 | ||
job-nginx2: | ||
phase: | ||
Succeeded: 3 | ||
terminating: 0 | ||
unknown: 0 | ||
version: 1 |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
state
might be overwritten unexpectly, for instance, we are aggreatingstate
s from two member clusters, the second state would overrite the first one.But it good enough for current stage, as Karmada not supports split Volcano Jobs currently.
It's hard to aggreate the state, we have met this situation when aggreating Kubernetes Jobs at https://github.com/karmada-io/karmada/blob/adef1e59748e1e1d31cb75fffe406b5dd69a66d7/pkg/util/helper/job.go#L76-L9.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dekaihu Any idea about how to handle the
state
aggregation?