Skip to content

Commit cc9fddc

Browse files
iantoweyIan
andauthored
[improve][functions] Allow customizing Kubernetes service domain suffix in Function Worker (#25872)
Co-authored-by: Ian <itowey@beyond.com>
1 parent 7ab0941 commit cc9fddc

5 files changed

Lines changed: 43 additions & 9 deletions

File tree

conf/functions_worker.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@ functionRuntimeFactoryConfigs:
198198
# # The Kubernetes pod name to run the function instances. It is set to
199199
# # `pf-<tenant>-<namespace>-<function_name>-<random_uuid(8)>` if this setting is left to be empty
200200
# jobName:
201+
# # Optional domain suffix to use when the Function Worker constructs the gRPC address to connect to function instances.
202+
# # If left blank, it defaults to `.svc.cluster.local`. Set this if your Function Worker is outside the cluster and connects via an external Gateway/Ingress.
203+
# kubernetesServiceDomainSuffix:
201204
# # the docker image to run function instance. by default it is `apachepulsar/pulsar`
202205
# pulsarDockerImageName:
203206
# # the docker image to run function instance according to different configurations provided by users.

pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/runtime/kubernetes/KubernetesRuntime.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,13 @@ public class KubernetesRuntime implements Runtime {
150150
private final Optional<KubernetesManifestCustomizer> manifestCustomizer;
151151
private String functionInstanceClassPath;
152152
private String downloadDirectory;
153+
private final String kubernetesServiceDomainSuffix;
153154

154155
KubernetesRuntime(AppsV1Api appsClient,
155156
CoreV1Api coreClient,
156157
String jobNamespace,
157158
String jobName,
159+
String kubernetesServiceDomainSuffix,
158160
Map<String, String> customLabels,
159161
Boolean installUserCodeDependencies,
160162
String pythonDependencyRepository,
@@ -193,6 +195,7 @@ public class KubernetesRuntime implements Runtime {
193195
this.instanceConfig = instanceConfig;
194196
this.jobNamespace = jobNamespace;
195197
this.jobName = jobName;
198+
this.kubernetesServiceDomainSuffix = kubernetesServiceDomainSuffix;
196199
this.customLabels = customLabels;
197200
this.functionDockerImages = functionDockerImages;
198201
this.pulsarDockerImageName = pulsarDockerImageName;
@@ -315,9 +318,7 @@ public void reinitialize() {
315318
private synchronized void setupGrpcChannelIfNeeded() {
316319
if (channel == null || stub == null) {
317320
channel = new ManagedChannel[instanceConfig.getFunctionDetails().getParallelism()];
318-
stub = new InstanceControlGrpc.InstanceControlStub[instanceConfig.getFunctionDetails()
319-
.getParallelism()];
320-
321+
stub = new InstanceControlGrpc.InstanceControlStub[instanceConfig.getFunctionDetails().getParallelism()];
321322
String jobName = createJobName(instanceConfig.getFunctionDetails(), this.jobName);
322323
for (int i = 0; i < instanceConfig.getFunctionDetails().getParallelism(); ++i) {
323324
String address = getServiceUrl(jobName, jobNamespace, i);
@@ -1152,11 +1153,11 @@ private static String createJobName(String tenant, String namespace, String func
11521153
final String shortHash = DigestUtils.sha1Hex(jobNameBase).toLowerCase().substring(0, 8);
11531154
return convertedJobName + "-" + shortHash;
11541155
}
1155-
1156-
private static String getServiceUrl(String jobName, String jobNamespace, int instanceId) {
1157-
return String.format("%s-%d.%s.%s.svc.cluster.local", jobName, instanceId, jobName, jobNamespace);
1156+
@VisibleForTesting
1157+
String getServiceUrl(String jobName, String jobNamespace, int instanceId) {
1158+
String suffix = isNotBlank(kubernetesServiceDomainSuffix) ? kubernetesServiceDomainSuffix : "svc.cluster.local";
1159+
return String.format("%s-%d.%s.%s.%s", jobName, instanceId, jobName, jobNamespace, suffix);
11581160
}
1159-
11601161
public static void doChecks(FunctionDetails functionDetails, String overridenJobName) {
11611162
final String jobName = createJobName(functionDetails, overridenJobName);
11621163
if (!jobName.equals(jobName.toLowerCase())) {

pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/runtime/kubernetes/KubernetesRuntimeFactory.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ public class KubernetesRuntimeFactory implements RuntimeFactory {
101101
private String functionInstanceClassPath;
102102
private String downloadDirectory;
103103
private int gracePeriodSeconds;
104+
private String kubernetesServiceDomainSuffix;
104105

105106
@ToString.Exclude
106107
@EqualsAndHashCode.Exclude
@@ -178,7 +179,7 @@ public void initialize(WorkerConfig workerConfig, AuthenticationConfig authentic
178179
if (!Paths.get(this.downloadDirectory).isAbsolute()) {
179180
this.downloadDirectory = this.pulsarRootDir + "/" + this.downloadDirectory;
180181
}
181-
182+
this.kubernetesServiceDomainSuffix = factoryConfig.getKubernetesServiceDomainSuffix();
182183
this.submittingInsidePod = factoryConfig.getSubmittingInsidePod();
183184
this.installUserCodeDependencies = factoryConfig.getInstallUserCodeDependencies();
184185
this.pythonDependencyRepository = factoryConfig.getPythonDependencyRepository();
@@ -318,6 +319,7 @@ public KubernetesRuntime createContainer(InstanceConfig instanceConfig, String c
318319
// get the namespace for this function
319320
overriddenNamespace,
320321
overriddenName,
322+
kubernetesServiceDomainSuffix,
321323
customLabels,
322324
installUserCodeDependencies,
323325
pythonDependencyRepository,

pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/runtime/kubernetes/KubernetesRuntimeFactoryConfig.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,12 @@ public class KubernetesRuntimeFactoryConfig {
4747
doc = "The docker image used to run function instance. By default it is `apachepulsar/pulsar`"
4848
)
4949
protected String pulsarDockerImageName;
50-
50+
@FieldContext(
51+
doc = "Optional domain suffix to use when the Function Worker constructs the gRPC address "
52+
+ "to connect to function instances. If left blank, it defaults to `.svc.cluster.local`. "
53+
+ "Set this if your Function Worker is outside the cluster and connects via an external Gateway/Ingress."
54+
)
55+
protected String kubernetesServiceDomainSuffix;
5156
@FieldContext(
5257
doc = "The function docker images used to run function instance according to different "
5358
+ "configurations provided by users. By default it is `apachepulsar/pulsar`"

pulsar-functions/runtime/src/test/java/org/apache/pulsar/functions/runtime/kubernetes/KubernetesRuntimeTest.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,29 @@ InstanceConfig createJavaInstanceConfig(FunctionDetails.Runtime runtime, boolean
343343
return config;
344344
}
345345

346+
@Test
347+
public void testGetServiceUrl() throws Exception {
348+
factory = createKubernetesRuntimeFactory(null, 10, 1.0, 1.0);
349+
InstanceConfig config = createJavaInstanceConfig(FunctionDetails.Runtime.JAVA, true);
350+
351+
KubernetesRuntime container1 = factory.createContainer(
352+
config, userJarFile, userJarFile, null, null, 30L);
353+
assertEquals(container1.getServiceUrl("my-job", "my-namespace", 0),
354+
"my-job-0.my-job.my-namespace.svc.cluster.local");
355+
356+
KubernetesRuntimeFactory factory2 = createKubernetesRuntimeFactory(null, 10, 1.0, 1.0);
357+
java.lang.reflect.Field field = KubernetesRuntimeFactory.class.getDeclaredField(
358+
"kubernetesServiceDomainSuffix");
359+
field.setAccessible(true);
360+
field.set(factory2, "custom.gateway.internal");
361+
362+
KubernetesRuntime container2 = factory2.createContainer(
363+
config, userJarFile, userJarFile, null, null, 30L);
364+
assertEquals(container2.getServiceUrl("my-job", "my-namespace", 0),
365+
"my-job-0.my-job.my-namespace.custom.gateway.internal");
366+
}
367+
368+
346369
@Test
347370
public void testRamPadding() throws Exception {
348371
verifyRamPadding(0, 1000, 1000);

0 commit comments

Comments
 (0)