Understanding Pod Template Inheritance

Issue

  • I defined a pod template but it appears another one is running.
  • Some parts of my pod template definition are not taken into account.
  • I don’t understand which pod template Jenkins is using.

Environment

Resolution

This article will guide you towards the various ways of defining a pod template.

Vocabulary

There are primarily two ways to define a pod template:

  1. Through the UI

This is the first way, directly from Jenkins in a Pod template definition page.
Here is a simple example defining a pod template named hello-kb containing a maven container using the maven:3.6.3-jdk-11 image:

Details on the various fields of a pod template are outside of the scope of this article, have a look to the references for more information.

Properties of a pod template defined this way will be called UI defined properties in this document.

  1. Through YAML

There are two ways of defining pod templates through YAML:

a. In the Jenkins Pod template definition page, with the Raw yaml for the Pod field:

b. In a Jenkinsfile, for instance:

podTemplate(yaml: """
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: maven
    image: maven:3.6.3-jdk-11
    command:
    - cat
    tty: true
"""
) {
    node(POD_LABEL) {
      container('maven') {
        sh "hostname"
      }
    }
}

Note: there are a lot of various ways to define a pod template in a Jenkinsfile, have a look to the Kubernetes Plugin for more information.

Properties of a pod template defined this way will be called YAML defined properties in this document.

Suggested Approach

We strongly suggest to avoid using the inheritance feature as well as defining global pod template.
Our recommendation is to use explicit YAML configuration in your templates.
This way you are certain that what you define is what you will get.
In case you want to avoid repetition, then extract the definition into a shared library.
If you follow those advices, you can skip the rest of this article.

Building the pod template

To build the pod template from the UI and YAML defined properties Jenkins will always use the UI properties first, then use the YAML values for properties that have not yet been defined in the UI.
In short, it means that the UI takes precedence over the YAML, you cannot override a UI defined property with YAML.

The recommendation here would be to avoid mixing UI and YAML defined properties and use YAML only if possible.

There is an exception to this rule for properties that are arrays where the YAML definition will be appended to the UI definition.

Inheritance

Explicit inheritance

On top of what we already discussed, Jenkins supports pod template inheritance.
One can define a parent pod template either through the UI Pod template to inherit from field or in the Jenkinsfile with the inheritFrom property.

Implicit inheritance

One can also define a default pod template that will the parent of all the pod templates created in a given cloud.
This is set up directly in the Kubernetes Cloud Definition in the Defaults Provider Template Name field.

Resolving the inheritance

To build the final Pod Template, Jenkins will proceed as follow:
1. use the UI defined properties of the parent template.
2. use the UI defined properties of the child template, override the properties of the parent if necessary.

Once this is done, apply the YAML properties the same way than before, ie if a property has already been defined through steps 1 or 2, it is not overidden (except the array case like before).

3. for empty properties after step 2, use the YAML defined values of the parent template (except for arrays, append the values)
4. for empty properties after step 2, use the YAML defined values of the child template (except for arrays, append the values). For the values define in step 3, use the Yaml merge strategy of the pod template to define whether the values needs to be overriden (default behavior) or merged.

The case of the JNLP container

Each pod template has a JNLP container, this is the container that runs the Jenkins agent.
If you do not define one anywhere in the pod template hierarchy, the one defined by the org.csanchez.jenkins.plugins.kubernetes.pipeline.PodTemplateStepExecution.defaultImage property is taken into account.
See more about this feature in Change the default JNLP image for kubernetes agents provisioning.
If it does not exist, then the default one coming with your Jenkins version is used.

Debugging the pod template resolution

It can be a bit challenging to know exactly which template contributed to the effective pod template that is used by your Pipeline.
Here are a few tips.

Display the final template in the console output

Pod templates have a Show raw yaml in console that can help you determine whether what your Pipeline is running is what you expect.
For pod templates defined in a Jenkinsfile, this is turned on by default (you can still deactivate setting showRawYaml to false).

This displays what CloudBees CI is sending to the Kubernetes API.
It should match what gets created by Kubernetes minus modifications injected for instance by admission hooks.

Display the resolution steps

One can activate a logger that will show the different resolution steps taken by the Kubernetes plugin that lead to the final pod template.
For this follow Configure Loggers for Jenkins and add a logger for org.csanchez.jenkins.plugins.kubernetes at ALL level.

Opening a support ticket

If you still cannot figure out what is happening, then please open a support ticket making sure to include the data as indicated in Required Data: Kubernetes Cloud.

References

Have more questions?

0 Comments

Please sign in to leave a comment.