This is an automated email from the ASF dual-hosted git repository.
kuanhsun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/submarine.git
The following commit(s) were added to refs/heads/master by this push:
new c15baa7 SUBMARINE-1130. New route to serve pod
c15baa7 is described below
commit c15baa7fbe7bf314061559a8514be6220b66bb63
Author: jeff-901 <[email protected]>
AuthorDate: Sun Dec 12 10:31:31 2021 +0800
SUBMARINE-1130. New route to serve pod
### What is this PR for?
Add a new route to serve pod.
new route: http://\{submarine ip}/{model name}/{model
version}/api/v1.0/predictions
### What type of PR is it?
Feature
### Todos
### What is the Jira issue?
https://issues.apache.org/jira/browse/SUBMARINE-1130
### How should this be tested?
### Screenshots (if appropriate)
### Questions:
* Do the license files need updating? No
* Are there breaking changes for older versions? No
* Does this need new documentation? No
Author: jeff-901 <[email protected]>
Signed-off-by: kuanhsun <[email protected]>
Closes #829 from jeff-901/SUBMARINE-1130 and squashes the following commits:
2ea9c5a6 [jeff-901] create virtual service for serve pod
---
.../artifacts/submarine/submarine-rbac.yaml | 13 ++
.../serve/istio/IstioHTTPDestination.java | 54 ++++++++
.../serve/istio/IstioHTTPMatchRequest.java | 39 ++++++
.../submarine/serve/istio/IstioHTTPRoute.java | 67 +++++++++
.../submarine/serve/istio/IstioVirtualService.java | 153 +++++++++++++++++++++
.../submarine/serve/utils/IstioConstants.java | 42 ++++++
.../server/submitter/k8s/K8sSubmitter.java | 43 +++++-
7 files changed, 405 insertions(+), 6 deletions(-)
diff --git a/submarine-cloud-v2/artifacts/submarine/submarine-rbac.yaml
b/submarine-cloud-v2/artifacts/submarine/submarine-rbac.yaml
index f568dac..58d8264 100644
--- a/submarine-cloud-v2/artifacts/submarine/submarine-rbac.yaml
+++ b/submarine-cloud-v2/artifacts/submarine/submarine-rbac.yaml
@@ -68,6 +68,19 @@ rules:
- patch
- update
- apiGroups:
+ - networking.istio.io
+ resources:
+ - virtualservices
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - delete
+ - deletecollection
+ - patch
+ - update
+- apiGroups:
- ""
resources:
- pods
diff --git
a/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioHTTPDestination.java
b/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioHTTPDestination.java
new file mode 100644
index 0000000..fc375de
--- /dev/null
+++
b/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioHTTPDestination.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.submarine.serve.istio;
+
+import com.google.gson.annotations.SerializedName;
+import org.apache.submarine.serve.utils.IstioConstants;
+
+public class IstioHTTPDestination {
+ @SerializedName("destination")
+ private IstioDestination destination;
+
+ public IstioHTTPDestination(String host){
+ this.destination = new IstioDestination(host);
+ }
+
+
+ public static class IstioDestination{
+ @SerializedName("host")
+ private String host;
+
+ @SerializedName("port")
+ private IstioPort port;
+
+ public IstioDestination(String host) {
+ this.host = host;
+ this.port = new IstioPort(IstioConstants.DEFAULT_SERVE_POD_PORT);
+ }
+ }
+
+ public static class IstioPort {
+ @SerializedName("number")
+ private Integer number;
+
+ public IstioPort(Integer port){
+ this.number = port;
+ }
+ }
+}
diff --git
a/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioHTTPMatchRequest.java
b/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioHTTPMatchRequest.java
new file mode 100644
index 0000000..18e0b6c
--- /dev/null
+++
b/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioHTTPMatchRequest.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.submarine.serve.istio;
+
+import com.google.gson.annotations.SerializedName;
+
+public class IstioHTTPMatchRequest {
+ @SerializedName("uri")
+ private IstioPrefix prefix;
+
+ public IstioHTTPMatchRequest(String prefix) {
+ this.prefix = new IstioPrefix(prefix);
+ }
+
+ public static class IstioPrefix {
+ @SerializedName("prefix")
+ private String path;
+
+ public IstioPrefix(String path){
+ this.path = path;
+ }
+ }
+}
diff --git
a/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioHTTPRoute.java
b/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioHTTPRoute.java
new file mode 100644
index 0000000..7f7ff9a
--- /dev/null
+++
b/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioHTTPRoute.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.submarine.serve.istio;
+
+import com.google.gson.annotations.SerializedName;
+import org.apache.submarine.serve.utils.IstioConstants;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class IstioHTTPRoute {
+ @SerializedName("match")
+ private List<IstioHTTPMatchRequest> match = new ArrayList<>();
+
+ @SerializedName("route")
+ private List<IstioHTTPDestination> route = new ArrayList<>();
+
+ @SerializedName("rewrite")
+ private IstioRewrite rewrite;
+
+ public IstioHTTPRoute() {
+ this.rewrite = new IstioRewrite(IstioConstants.REWRITE_URL);
+ }
+
+ @Override
+ public String toString() {
+ return "'rewrite': {'uri': " + rewrite.getRewrite() + "}";
+
+ }
+
+ public void addHTTPMatchRequest(IstioHTTPMatchRequest match){
+ this.match.add(match);
+ }
+
+ public void addHTTPDestination(IstioHTTPDestination destination){
+ this.route.add(destination);
+ }
+ public static class IstioRewrite{
+ @SerializedName("uri")
+ private String uri;
+
+ public IstioRewrite(String rewrite){
+ this.uri = rewrite;
+ }
+
+ public String getRewrite() {
+ return uri;
+ }
+ }
+
+}
diff --git
a/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioVirtualService.java
b/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioVirtualService.java
new file mode 100644
index 0000000..dbe90de
--- /dev/null
+++
b/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioVirtualService.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.submarine.serve.istio;
+
+import com.google.gson.annotations.SerializedName;
+import io.kubernetes.client.models.V1ObjectMeta;
+import org.apache.submarine.serve.utils.IstioConstants;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class IstioVirtualService {
+ @SerializedName("apiVersion")
+ private String apiVersion = IstioConstants.API_VERSION;
+
+ @SerializedName("kind")
+ private String kind = IstioConstants.KIND;
+
+ @SerializedName("metadata")
+ private V1ObjectMeta metadata;
+
+ @SerializedName("spec")
+ private IstioVirtualServiceSpec spec;
+
+ // transient to avoid being serialized
+ private transient String group = IstioConstants.GROUP;
+
+ private transient String version = IstioConstants.VERSION;
+
+ private transient String plural = IstioConstants.PLURAL;
+
+ public IstioVirtualService(String modelName, Integer modelVersion) {
+ V1ObjectMeta metadata = new V1ObjectMeta();
+ metadata.setName(modelName);
+ metadata.setNamespace(IstioConstants.DEFAULT_NAMESPACE);
+ setMetadata(metadata);
+ setSpec(new IstioVirtualServiceSpec(modelName, modelVersion));
+ }
+
+ public String getApiVersion() {
+ return apiVersion;
+ }
+
+ public void setApiVersion(String apiVersion) {
+ this.apiVersion = apiVersion;
+ }
+
+ public String getKind() {
+ return kind;
+ }
+
+ public void setKind(String kind) {
+ this.kind = kind;
+ }
+
+ public V1ObjectMeta getMetadata() {
+ return metadata;
+ }
+
+ public void setMetadata(V1ObjectMeta metadata) {
+ this.metadata = metadata;
+ }
+
+ public String getGroup() {
+ return group;
+ }
+
+ public void setGroup(String group) {
+ this.group = group;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public String getPlural() {
+ return plural;
+ }
+
+ public void setPlural(String plural) {
+ this.plural = plural;
+ }
+
+ public IstioVirtualServiceSpec getSpec() {
+ return spec;
+ }
+
+ public void setSpec(IstioVirtualServiceSpec istioVirtualServiceSpec){
+ this.spec = istioVirtualServiceSpec;
+ }
+
+ public static class IstioVirtualServiceSpec {
+ @SerializedName("hosts")
+ private List<String> hosts = new ArrayList<>();
+ @SerializedName("gateways")
+ private List<String> gateways = new ArrayList<>();
+ @SerializedName("http")
+ private List<IstioHTTPRoute> httpRoute = new ArrayList<>();
+
+ public IstioVirtualServiceSpec(String modelName, Integer modelVersion) {
+ hosts.add(IstioConstants.DEFAULT_INGRESS_HOST);
+ gateways.add(IstioConstants.DEFAULT_GATEWAY);
+ IstioHTTPDestination destination = new IstioHTTPDestination(
+ modelName + "-" + IstioConstants.DEFAULT_NAMESPACE);
+ IstioHTTPMatchRequest matchRequest = new IstioHTTPMatchRequest("/" +
modelName
+ + "/" + String.valueOf(modelVersion) + "/");
+ IstioHTTPRoute httpRoute = new IstioHTTPRoute();
+ httpRoute.addHTTPDestination(destination);
+ httpRoute.addHTTPMatchRequest(matchRequest);
+ setHTTPRoute(httpRoute);
+ }
+
+ public List<String> getHosts() {
+ return this.hosts;
+ }
+
+ public void addHost(String host) {
+ hosts.add(host);
+ }
+
+ public List<String> getGateways() {
+ return this.gateways;
+ }
+
+ public void addGateway(String gateway) {
+ gateways.add(gateway);
+ }
+
+ public void setHTTPRoute(IstioHTTPRoute istioHTTPRoute){
+ this.httpRoute.add(istioHTTPRoute);
+ }
+ }
+}
diff --git
a/submarine-serve/src/main/java/org/apache/submarine/serve/utils/IstioConstants.java
b/submarine-serve/src/main/java/org/apache/submarine/serve/utils/IstioConstants.java
new file mode 100644
index 0000000..10ae72d
--- /dev/null
+++
b/submarine-serve/src/main/java/org/apache/submarine/serve/utils/IstioConstants.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.submarine.serve.utils;
+
+public class IstioConstants {
+ public static final String API_VERSION = "networking.istio.io/v1beta1";
+
+ public static final String KIND = "VirtualService";
+
+ public static final String GROUP = "networking.istio.io";
+
+ public static final String VERSION = "v1beta1";
+
+ public static final String PLURAL = "virtualservices";
+
+ public static final String REWRITE_URL = "/";
+
+ public static final String DEFAULT_NAMESPACE = "default";
+
+ public static final String DEFAULT_GATEWAY = "istio-system/seldon-gateway";
+
+ public static final Integer DEFAULT_SERVE_POD_PORT = 8000;
+
+ public static final String DEFAULT_INGRESS_HOST = "*";
+
+}
diff --git
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/K8sSubmitter.java
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/K8sSubmitter.java
index c1e8298..131e927 100644
---
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/K8sSubmitter.java
+++
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/K8sSubmitter.java
@@ -57,6 +57,7 @@ import io.kubernetes.client.util.Watch;
import org.apache.submarine.commons.utils.SubmarineConfiguration;
import org.apache.submarine.commons.utils.exception.SubmarineRuntimeException;
+import org.apache.submarine.serve.istio.IstioVirtualService;
import org.apache.submarine.serve.pytorch.SeldonPytorchServing;
import org.apache.submarine.serve.seldon.SeldonDeployment;
import org.apache.submarine.serve.tensorflow.SeldonTFServing;
@@ -117,7 +118,6 @@ public class K8sSubmitter implements Submitter {
public void initialize(SubmarineConfiguration conf) {
try {
String path = System.getenv(KUBECONFIG_ENV);
- // path = System.getProperty("user.home") + "/.kube/config";
//TODO(tmp)
KubeConfig config = KubeConfig.loadKubeConfig(new FileReader(path));
client = ClientBuilder.kubeconfig(config).build();
} catch (Exception e) {
@@ -522,16 +522,39 @@ public class K8sSubmitter implements Submitter {
public void createServe(ServeSpec spec)
throws SubmarineRuntimeException {
SeldonDeployment seldonDeployment = parseServeSpec(spec);
-
+ IstioVirtualService istioVirtualService = new
IstioVirtualService(spec.getModelName(),
+ spec.getModelVersion());
try {
api.createNamespacedCustomObject(seldonDeployment.getGroup(),
- seldonDeployment.getVersion(),
+ seldonDeployment.getVersion(),
+ "default",
+ seldonDeployment.getPlural(),
+ seldonDeployment,
+ "true");
+ } catch (ApiException e) {
+ LOG.error(e.getMessage(), e);
+ throw new SubmarineRuntimeException(e.getCode(), e.getMessage());
+ }
+ try {
+ api.createNamespacedCustomObject(istioVirtualService.getGroup(),
+ istioVirtualService.getVersion(),
"default",
- seldonDeployment.getPlural(),
- seldonDeployment,
+ istioVirtualService.getPlural(),
+ istioVirtualService,
"true");
} catch (ApiException e) {
LOG.error(e.getMessage(), e);
+ try {
+ api.deleteNamespacedCustomObject(seldonDeployment.getGroup(),
+ seldonDeployment.getVersion(),
+ "default",
+ seldonDeployment.getPlural(),
+ seldonDeployment.getMetadata().getName(),
+ new
V1DeleteOptionsBuilder().withApiVersion(seldonDeployment.getApiVersion()).build(),
+ null, null, null);
+ } catch (ApiException e1) {
+ LOG.error(e1.getMessage(), e1);
+ }
throw new SubmarineRuntimeException(e.getCode(), e.getMessage());
}
}
@@ -540,7 +563,8 @@ public class K8sSubmitter implements Submitter {
public void deleteServe(ServeSpec spec)
throws SubmarineRuntimeException {
SeldonDeployment seldonDeployment = parseServeSpec(spec);
-
+ IstioVirtualService istioVirtualService = new
IstioVirtualService(spec.getModelName(),
+ spec.getModelVersion());
try {
api.deleteNamespacedCustomObject(seldonDeployment.getGroup(),
seldonDeployment.getVersion(),
@@ -549,6 +573,13 @@ public class K8sSubmitter implements Submitter {
seldonDeployment.getMetadata().getName(),
new
V1DeleteOptionsBuilder().withApiVersion(seldonDeployment.getApiVersion()).build(),
null, null, null);
+ api.deleteNamespacedCustomObject(istioVirtualService.getGroup(),
+ istioVirtualService.getVersion(),
+ "default",
+ istioVirtualService.getPlural(),
+ istioVirtualService.getMetadata().getName(),
+ new
V1DeleteOptionsBuilder().withApiVersion(istioVirtualService.getApiVersion()).build(),
+ null, null, null);
} catch (ApiException e) {
LOG.error(e.getMessage(), e);
throw new SubmarineRuntimeException(e.getCode(), e.getMessage());
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]