My goal was to achieve that only 1 pod of my application executes a scheduled job.
I have implemented a following simple example using kubernetes election leader functionality and it works:
1.Maven dependencies:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.3</version>
<relativePath/>
</parent>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-fabric8-leader</artifactId>
</dependency>
2.application.yaml:
spring:
cloud:
kubernetes:
leader:
enabled: true
autoStartup: true
3.Code with @Scheduled
job:
import lombok.extern.log4j.Log4j2;
import org.springframework.context.event.EventListener;
import org.springframework.integration.leader.event.OnGrantedEvent;
import org.springframework.integration.leader.event.OnRevokedEvent;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Log4j2
@Component
public class ScheduledJob {
private boolean isLeader = false;
@EventListener(OnGrantedEvent.class)
public void onLeaderGranted(OnGrantedEvent event) {
log.info("Leadership granted to this instance.");
isLeader = true;
}
@EventListener(OnRevokedEvent.class)
public void onLeaderRevoked(OnRevokedEvent event) {
log.info("Leadership revoked from this instance.");
isLeader = false;
}
@Scheduled(fixedRate = 2000)
public void foo() {
if (isLeader) {
log.info("I am foo leader.");
} else {
log.info("Skipping foo because I'm not the leader.");
}
}
}
Now I want to implement a scenario where different pods run different scheduled jobs, with each pod being responsible for running its own job, so pod-1 can be leader to run job-1, pod-2 for job-2.
Job 1:
@Log4j2
@Component
public class ScheduledJob1 {
private boolean isLeader = false;
@EventListener(OnGrantedEvent.class)
public void onLeaderGranted(OnGrantedEvent event) {
log.info("Leadership for ScheduledJob1 granted to this instance.");
isLeader = true;
}
@EventListener(OnRevokedEvent.class)
public void onLeaderRevoked(OnRevokedEvent event) {
log.info("Leadership for ScheduledJob1 revoked from this instance.");
isLeader = false;
}
@Scheduled(fixedRate = 2000)
public void foo1() {
if (isLeader) {
log.info("I am foo 1 leader.");
} else {
log.info("Skipping foo 1 because I'm not the leader.");
}
}
}
Job 2:
@Log4j2
@Component
public class ScheduledJob2 {
private boolean isLeader = false;
@EventListener(OnGrantedEvent.class)
public void onLeaderGranted(OnGrantedEvent event) {
log.info("Leadership for ScheduledJob2 granted to this instance");
isLeader = true;
}
@EventListener(OnRevokedEvent.class)
public void onLeaderRevoked(OnRevokedEvent event) {
log.info("Leadership for ScheduledJob2 revoked from this instance.");
isLeader = false;
}
@Scheduled(fixedRate = 2000)
public void foo2() {
if (isLeader) {
log.info("I am foo2 leader.");
} else {
log.info("Skipping foo2 because I'm not the leader.");
}
}
}
How can I achieve this?
Probably with different roles, but I don't understand how to set up them...
If you need any clarification, let me know, thank you in advance!
Usually in such cases you leader appoint lieutenant to do his jobs for him.
So leader should get all the gang and distribute task between them. Then call them using, for example, REST and tell them to do tasks.