Skip to content

Conversation

@Abhijeet212004
Copy link

Fix memory limits not persisting after Jenkins restart

Problem

Memory limits configured for Kubernetes agent pods reset to default (1024 MB) after Jenkins restarts, even when explicitly set to higher values like 3072 MB in the cloud configuration.

Root Cause

The issue was in PodTemplate.readResolve(). When users configure memory limits through the Jenkins UI on a PodTemplate, the deprecated setter setResourceLimitMemory() is called. This setter tries to apply the value to the first container using getFirstContainer().ifPresent().

If the containers list is empty at that point (which is common in modern configs), ifPresent() does nothing and the value only gets stored in the deprecated PodTemplate.resourceLimitMemory field.

After Jenkins restarts, readResolve() runs to migrate old configs. However, it only checked for containers == null (legacy v0.8 configs), not containers.isEmpty(). So these deprecated field values were never migrated to actual container resource limits, and pods ended up with default memory limits.

Solution

Extended the readResolve() migration logic to handle two additional cases:

  1. When containers list is empty but has an image - create a container from the deprecated fields
  2. When containers exist but don't have resource limits - apply the deprecated field values

This maintains backward compatibility with v0.8 configs while fixing the modern usage pattern.

Testing done

Unit Tests:
Added comprehensive test coverage in ResourceLimitPersistenceTest.java:

  • testContainerTemplateResourceLimitMemoryPersistsAfterXStreamSerialization - Verifies XStream serialization works correctly
  • testPodTemplateWithContainerResourceLimitsPersists - Verifies container-level limits persist
  • testPodTemplateLegacyFieldsMigrateToContainer - Reproduces and verifies the bug fix - simulates the exact scenario from issue [JENKINS-76163] Kubernetes plugin doesnt save memory limits #2766 with deprecated fields and empty containers list

All tests pass:

#2787 - Fixed counter leak with ephemeral templates after restart
#2785 - Fixed Reaper not detecting ImagePullBackOff state

Submitter checklist

  • Make sure you are opening from a topic/feature/bugfix branch (right side) and not your main branch!
  • Ensure that the pull request title represents the desired changelog entry
  • Please describe what you did
  • Link to relevant issues in GitHub or Jira
  • Link to relevant pull requests, esp. upstream and downstream changes
  • Ensure you have provided tests that demonstrate the feature works or the

Fixes #2766

Fixes jenkinsci#2783
Partially addresses jenkinsci#2737

The problem: When you create pod templates in pipelines (ephemeral templates),
their reference becomes null after Jenkins restarts. The cleanup code was
checking 'if (template != null)' before decrementing counters, so it never
ran - causing a permanent leak.

The fix: Use cloudName and templateId instead of the template object. These
fields survive restarts, so counters get cleaned up correctly.
Prevents attempting to decrement counters for nodes that were
never registered (e.g., in eviction scenarios). Checks if counters
exist before decrementing to avoid spurious warnings.
- Restructure unregisterByIds() to check and decrement counters independently
- Improve test to simulate ephemeral template removal with cloud.removeTemplate()
- Keep logging simple for consistency with existing patterns
@Abhijeet212004 Abhijeet212004 requested a review from a team as a code owner January 8, 2026 20:41
The issue was in PodTemplate.readResolve() - it only migrated deprecated
resource limit fields when containers was null (old v0.8 configs), but not
when the list was empty (which happens with modern configs).

When users set memory limits through the UI, the deprecated setter tries to
apply them to the first container. If no containers exist yet, it does nothing
and the values just sit in deprecated fields. After restart, readResolve()
skipped migration because it only checked for null, not isEmpty().

Now we handle both empty containers and apply deprecated fields to existing
containers that don't have limits set yet.

Fixes jenkinsci#2766
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[JENKINS-76163] Kubernetes plugin doesnt save memory limits

1 participant