From c3739c6107163d2b35b1ba2704e35cc6ae97ebf3 Mon Sep 17 00:00:00 2001 From: Jayesh Mahajan Date: Mon, 26 May 2025 21:36:30 -0400 Subject: [PATCH 01/14] Create AI Example model serving tensorflow --- ai/model-serving-tensorflow/deployment.yaml | 34 +++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 ai/model-serving-tensorflow/deployment.yaml diff --git a/ai/model-serving-tensorflow/deployment.yaml b/ai/model-serving-tensorflow/deployment.yaml new file mode 100644 index 000000000..fb8eb0a86 --- /dev/null +++ b/ai/model-serving-tensorflow/deployment.yaml @@ -0,0 +1,34 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tf-serving + labels: + app: tf-serving +spec: + replicas: 1 + selector: + matchLabels: + app: tf-serving + template: + metadata: + labels: + app: tf-serving + spec: + containers: + - name: tensorflow-serving + image: tensorflow/serving:2.13.0 + args: + - "--model_name=my_model" + - "--port=8500" + - "--rest_api_port=8501" + - "--model_base_path=/models/my_model" + ports: + - containerPort: 8500 # gRPC + - containerPort: 8501 # REST + volumeMounts: + - name: model-volume + mountPath: /models/my_model + volumes: + - name: model-volume + persistentVolumeClaim: + claimName: my-model-pvc From 3a7b97108bc78e9800a0dee6045c039ced2c99d8 Mon Sep 17 00:00:00 2001 From: Jayesh Mahajan Date: Mon, 26 May 2025 21:37:35 -0400 Subject: [PATCH 02/14] ai/model-serving-tensorflow service.yaml --- ai/model-serving-tensorflow/service.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 ai/model-serving-tensorflow/service.yaml diff --git a/ai/model-serving-tensorflow/service.yaml b/ai/model-serving-tensorflow/service.yaml new file mode 100644 index 000000000..00a6e1027 --- /dev/null +++ b/ai/model-serving-tensorflow/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: tf-serving +spec: + selector: + app: tf-serving + ports: + - name: grpc + port: 8500 + targetPort: 8500 + - name: rest + port: 8501 + targetPort: 8501 + type: ClusterIP From 0a3ef1124e7735799ef604e9e92ac83a237ff823 Mon Sep 17 00:00:00 2001 From: Jayesh Mahajan Date: Mon, 26 May 2025 21:37:58 -0400 Subject: [PATCH 03/14] ai/model-serving-tensorflow ingress.yaml --- ai/model-serving-tensorflow/ingress.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 ai/model-serving-tensorflow/ingress.yaml diff --git a/ai/model-serving-tensorflow/ingress.yaml b/ai/model-serving-tensorflow/ingress.yaml new file mode 100644 index 000000000..3793f9b9d --- /dev/null +++ b/ai/model-serving-tensorflow/ingress.yaml @@ -0,0 +1,18 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: tf-serving-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: /$2 +spec: + rules: + - host: tf.example.com + http: + paths: + - path: /tf(/|$)(.*) + pathType: Prefix + backend: + service: + name: tf-serving + port: + number: 8501 From 38f5cbf93983c9ed3aa9728f6fe5897cd8ee9506 Mon Sep 17 00:00:00 2001 From: Jayesh Mahajan Date: Mon, 26 May 2025 21:39:54 -0400 Subject: [PATCH 04/14] ai/model-serving-tensorflow pv.yaml --- ai/model-serving-tensorflow/pv.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 ai/model-serving-tensorflow/pv.yaml diff --git a/ai/model-serving-tensorflow/pv.yaml b/ai/model-serving-tensorflow/pv.yaml new file mode 100644 index 000000000..3fdfa6afb --- /dev/null +++ b/ai/model-serving-tensorflow/pv.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + name: my-model-pv +spec: + capacity: + storage: 1Gi + accessModes: + - ReadOnlyMany + persistentVolumeReclaimPolicy: Retain + hostPath: + path: /mnt/models/my_model From 5ef3406f04ec98f8c99d225dfb7b5a6c0c1bbfa1 Mon Sep 17 00:00:00 2001 From: Jayesh Mahajan Date: Mon, 26 May 2025 21:40:16 -0400 Subject: [PATCH 05/14] ai/model-serving-tensorflow pvc.yaml --- ai/model-serving-tensorflow/pvc.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 ai/model-serving-tensorflow/pvc.yaml diff --git a/ai/model-serving-tensorflow/pvc.yaml b/ai/model-serving-tensorflow/pvc.yaml new file mode 100644 index 000000000..4dacae334 --- /dev/null +++ b/ai/model-serving-tensorflow/pvc.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: my-model-pvc +spec: + accessModes: + - ReadOnlyMany + resources: + requests: + storage: 1Gi + volumeName: my-model-pv From 7dcfcdcedd4b87e27b31961da88c3d983a4405b7 Mon Sep 17 00:00:00 2001 From: Jayesh Mahajan Date: Mon, 26 May 2025 21:43:31 -0400 Subject: [PATCH 06/14] Create Readme.md --- ai/model-serving-tensorflow/Readme.md | 35 +++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 ai/model-serving-tensorflow/Readme.md diff --git a/ai/model-serving-tensorflow/Readme.md b/ai/model-serving-tensorflow/Readme.md new file mode 100644 index 000000000..1ec3d09e9 --- /dev/null +++ b/ai/model-serving-tensorflow/Readme.md @@ -0,0 +1,35 @@ + +To expose this externally, ensure you have an Ingress Controller installed (e.g., NGINX). + +Adjust the host value in ingress.yaml to match your domain or use a LoadBalancer for direct access instead of Ingress. + +For basic testing: +``` +curl -X POST http:///tf/v1/models/my_model:predict -d '{ "instances": [[1.0, 2.0, 5.0]] }' +``` + +PVC + +โš ๏ธ Note: You must create a PersistentVolumeClaim named my-model-pvc that points to the directory where your SavedModel is stored (/models/my_model/1/saved_model.pb). + +๐Ÿ“Œ For demo/testing purposes, this uses a hostPath volume โ€” useful for single-node clusters (like Minikube or KIND). +Replace hostPath with a cloud volume (e.g., GCP PD, AWS EBS, NFS, etc.) in production environments. + + Directory Structure on Node (/mnt/models/my_model/) +Your model directory (mounted on the node at /mnt/models/my_model/) should look like this: + +``` +/mnt/models/my_model/ +โ””โ”€โ”€ 1/ + โ”œโ”€โ”€ saved_model.pb + โ””โ”€โ”€ variables/ +``` + +โœ… How to Load a Demo Model (if using local clusters) +``` +mkdir -p /mnt/models/my_model/1 +wget https://storage.googleapis.com/tf-serving-models/resnet_v2.tar.gz +tar -xzvf resnet_v2.tar.gz -C /mnt/models/my_model/1 --strip-components=1 +``` + + From ea6121e61cfad8862d6050c98739775a5e3d4773 Mon Sep 17 00:00:00 2001 From: Jayesh Mahajan Date: Mon, 26 May 2025 22:36:01 -0400 Subject: [PATCH 07/14] Rename Readme.md to README.md --- ai/model-serving-tensorflow/{Readme.md => README.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ai/model-serving-tensorflow/{Readme.md => README.md} (100%) diff --git a/ai/model-serving-tensorflow/Readme.md b/ai/model-serving-tensorflow/README.md similarity index 100% rename from ai/model-serving-tensorflow/Readme.md rename to ai/model-serving-tensorflow/README.md From 01cf1c41cf83f2f053a27e734419e7ce2f497e53 Mon Sep 17 00:00:00 2001 From: Jayesh Mahajan Date: Tue, 27 May 2025 19:20:46 -0400 Subject: [PATCH 08/14] Update with structure format for README.md --- ai/model-serving-tensorflow/README.md | 155 +++++++++++++++++++++++--- 1 file changed, 140 insertions(+), 15 deletions(-) diff --git a/ai/model-serving-tensorflow/README.md b/ai/model-serving-tensorflow/README.md index 1ec3d09e9..a0ed3de03 100644 --- a/ai/model-serving-tensorflow/README.md +++ b/ai/model-serving-tensorflow/README.md @@ -1,23 +1,74 @@ +# TensorFlow Model Serving on Kubernetes -To expose this externally, ensure you have an Ingress Controller installed (e.g., NGINX). +## ๐ŸŽฏ Purpose / What You'll Learn -Adjust the host value in ingress.yaml to match your domain or use a LoadBalancer for direct access instead of Ingress. +This example demonstrates how to deploy a TensorFlow model for inference using [TensorFlow Serving](https://www.tensorflow.org/tfx/serving) on Kubernetes. Youโ€™ll learn how to: -For basic testing: -``` -curl -X POST http:///tf/v1/models/my_model:predict -d '{ "instances": [[1.0, 2.0, 5.0]] }' +- Set up TensorFlow Serving with a pre-trained model +- Use a PersistentVolume to mount your model directory +- Expose the inference endpoint using a Kubernetes `Service` and `Ingress` +- Send a sample prediction request to the model + +--- + +## ๐Ÿ“š Table of Contents + +- [Prerequisites](#prerequisites) +- [Quick Start / TL;DR](#quick-start--tldr) +- [Detailed Steps & Explanation](#detailed-steps--explanation) +- [Verification / Seeing it Work](#verification--seeing-it-work) +- [Configuration Customization](#configuration-customization) +- [Cleanup](#cleanup) +- [Further Reading / Next Steps](#further-reading--next-steps) + +--- + +## โš™๏ธ Prerequisites + +- Kubernetes cluster (tested with v1.29+) +- `kubectl` configured +- Optional: `ingress-nginx` for external access +- x86-based machine (for running TensorFlow Serving image) +- Local hostPath support (for demo) or a cloud-based PVC + +--- + +## โšก Quick Start / TL;DR + +```bash +# Create demo model directory +mkdir -p /mnt/models/my_model/1 +wget https://storage.googleapis.com/tf-serving-models/resnet_v2.tar.gz +tar -xzvf resnet_v2.tar.gz -C /mnt/models/my_model/1 --strip-components=1 + +# Apply manifests +kubectl apply -f pvc.yaml +kubectl apply -f deployment.yaml +kubectl apply -f service.yaml +kubectl apply -f ingress.yaml # Optional ``` -PVC +--- + +## ๐Ÿงฉ Detailed Steps & Explanation -โš ๏ธ Note: You must create a PersistentVolumeClaim named my-model-pvc that points to the directory where your SavedModel is stored (/models/my_model/1/saved_model.pb). +### 1. PersistentVolume & PVC Setup -๐Ÿ“Œ For demo/testing purposes, this uses a hostPath volume โ€” useful for single-node clusters (like Minikube or KIND). -Replace hostPath with a cloud volume (e.g., GCP PD, AWS EBS, NFS, etc.) in production environments. +> โš ๏ธ Note: For local testing, `hostPath` is used to mount `/mnt/models/my_model`. In production, replace this with a cloud-native storage backend (e.g., AWS EBS, GCP PD, or NFS). - Directory Structure on Node (/mnt/models/my_model/) -Your model directory (mounted on the node at /mnt/models/my_model/) should look like this: +```yaml +# pvc.yaml (example snippet) +apiVersion: v1 +kind: PersistentVolume +metadata: + name: my-model-pv +spec: + hostPath: + path: /mnt/models/my_model +... +``` +Model folder structure: ``` /mnt/models/my_model/ โ””โ”€โ”€ 1/ @@ -25,11 +76,85 @@ Your model directory (mounted on the node at /mnt/models/my_model/) should look โ””โ”€โ”€ variables/ ``` -โœ… How to Load a Demo Model (if using local clusters) +--- + +### 2. Deploy TensorFlow Serving + +```yaml +# deployment.yaml (example snippet) +containers: + - name: tf-serving + image: tensorflow/serving:2.13.0 + args: + - --model_name=my_model + - --model_base_path=/models/my_model + volumeMounts: + - name: model-volume + mountPath: /models/my_model ``` -mkdir -p /mnt/models/my_model/1 -wget https://storage.googleapis.com/tf-serving-models/resnet_v2.tar.gz -tar -xzvf resnet_v2.tar.gz -C /mnt/models/my_model/1 --strip-components=1 + +--- + +### 3. Expose the Service + +- A `ClusterIP` service exposes gRPC (8500) and REST (8501). +- An optional `Ingress` exposes `/tf/v1/models/my_model:predict` to external clients. + +Update the `host` value in `ingress.yaml` to match your domain. + +--- + +## โœ… Verification / Seeing it Work + +If using ingress: + +```bash +curl -X POST http:///tf/v1/models/my_model:predict \ + -H "Content-Type: application/json" \ + -d '{ "instances": [[1.0, 2.0, 5.0]] }' +``` + +Expected output: + +```json +{ + "predictions": [...] +} +``` + +To verify the pod is running: + +```bash +kubectl get pods +kubectl logs ``` +--- + +## ๐Ÿ› ๏ธ Configuration Customization + +- Update `model_name` and `model_base_path` in the deployment +- Replace `hostPath` with `PersistentVolumeClaim` bound to cloud storage +- Modify resource requests/limits for TensorFlow container + +--- + +## ๐Ÿงน Cleanup + +```bash +kubectl delete -f ingress.yaml +kubectl delete -f service.yaml +kubectl delete -f deployment.yaml +kubectl delete -f pvc.yaml +``` + +--- + +## ๐Ÿ“˜ Further Reading / Next Steps + +- [TensorFlow Serving](https://www.tensorflow.org/tfx/serving) +- [TF Serving REST API Reference](https://www.tensorflow.org/tfx/serving/api_rest) +- [Kubernetes Ingress Controller](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/) +- [Persistent Volumes](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) + From ef286fb0adb594d6601d75fdffcd5c23b4aa20b1 Mon Sep 17 00:00:00 2001 From: Jayesh Mahajan Date: Wed, 28 May 2025 14:11:44 -0400 Subject: [PATCH 09/14] Correct link for serving in ai/model-serving-tensorflow/README.md Co-authored-by: Janet Kuo --- ai/model-serving-tensorflow/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ai/model-serving-tensorflow/README.md b/ai/model-serving-tensorflow/README.md index a0ed3de03..23a599db2 100644 --- a/ai/model-serving-tensorflow/README.md +++ b/ai/model-serving-tensorflow/README.md @@ -2,7 +2,7 @@ ## ๐ŸŽฏ Purpose / What You'll Learn -This example demonstrates how to deploy a TensorFlow model for inference using [TensorFlow Serving](https://www.tensorflow.org/tfx/serving) on Kubernetes. Youโ€™ll learn how to: +This example demonstrates how to deploy a TensorFlow model for inference using [TensorFlow Serving](https://www.tensorflow.org/serving) on Kubernetes. Youโ€™ll learn how to: - Set up TensorFlow Serving with a pre-trained model - Use a PersistentVolume to mount your model directory From 774d5a81da38fec0549253534acdfb1f7c64dc93 Mon Sep 17 00:00:00 2001 From: Jayesh Mahajan Date: Thu, 29 May 2025 14:03:19 -0400 Subject: [PATCH 10/14] Fix kubectl README.md --- ai/model-serving-tensorflow/README.md | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/ai/model-serving-tensorflow/README.md b/ai/model-serving-tensorflow/README.md index 23a599db2..816af4fee 100644 --- a/ai/model-serving-tensorflow/README.md +++ b/ai/model-serving-tensorflow/README.md @@ -36,21 +36,18 @@ This example demonstrates how to deploy a TensorFlow model for inference using [ ## โšก Quick Start / TL;DR ```bash -# Create demo model directory -mkdir -p /mnt/models/my_model/1 -wget https://storage.googleapis.com/tf-serving-models/resnet_v2.tar.gz -tar -xzvf resnet_v2.tar.gz -C /mnt/models/my_model/1 --strip-components=1 # Apply manifests -kubectl apply -f pvc.yaml -kubectl apply -f deployment.yaml -kubectl apply -f service.yaml -kubectl apply -f ingress.yaml # Optional +kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/refs/heads/master/ai/model-serving-tensorflow/pv.yaml +kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/refs/heads/master/ai/model-serving-tensorflow/pvc.yaml +kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/refs/heads/master/ai/model-serving-tensorflow/deployment.yaml +kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/refs/heads/master/ai/model-serving-tensorflow/service.yaml +kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/refs/heads/master/ai/model-serving-tensorflow/ingress.yaml # Optional ``` --- -## ๐Ÿงฉ Detailed Steps & Explanation +## ๐Ÿงฉ Explanation on PVC ### 1. PersistentVolume & PVC Setup From e6f8abdb2c0bdcac0dd1aeedcbfa017f53cfbcfa Mon Sep 17 00:00:00 2001 From: Jayesh Mahajan Date: Thu, 29 May 2025 14:06:36 -0400 Subject: [PATCH 11/14] Update README.md --- ai/model-serving-tensorflow/README.md | 40 +++++---------------------- 1 file changed, 7 insertions(+), 33 deletions(-) diff --git a/ai/model-serving-tensorflow/README.md b/ai/model-serving-tensorflow/README.md index 816af4fee..f678c27e8 100644 --- a/ai/model-serving-tensorflow/README.md +++ b/ai/model-serving-tensorflow/README.md @@ -53,17 +53,6 @@ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/refs/head > โš ๏ธ Note: For local testing, `hostPath` is used to mount `/mnt/models/my_model`. In production, replace this with a cloud-native storage backend (e.g., AWS EBS, GCP PD, or NFS). -```yaml -# pvc.yaml (example snippet) -apiVersion: v1 -kind: PersistentVolume -metadata: - name: my-model-pv -spec: - hostPath: - path: /mnt/models/my_model -... -``` Model folder structure: ``` @@ -75,24 +64,7 @@ Model folder structure: --- -### 2. Deploy TensorFlow Serving - -```yaml -# deployment.yaml (example snippet) -containers: - - name: tf-serving - image: tensorflow/serving:2.13.0 - args: - - --model_name=my_model - - --model_base_path=/models/my_model - volumeMounts: - - name: model-volume - mountPath: /models/my_model -``` - ---- - -### 3. Expose the Service +### 2. Expose the Service - A `ClusterIP` service exposes gRPC (8500) and REST (8501). - An optional `Ingress` exposes `/tf/v1/models/my_model:predict` to external clients. @@ -139,10 +111,12 @@ kubectl logs ## ๐Ÿงน Cleanup ```bash -kubectl delete -f ingress.yaml -kubectl delete -f service.yaml -kubectl delete -f deployment.yaml -kubectl delete -f pvc.yaml +kubectl delete -f https://raw.githubusercontent.com/kubernetes/examples/refs/heads/master/ai/model-serving-tensorflow/ingress.yaml # Optional +kubectl delete -f https://raw.githubusercontent.com/kubernetes/examples/refs/heads/master/ai/model-serving-tensorflow/service.yaml +kubectl delete -f https://raw.githubusercontent.com/kubernetes/examples/refs/heads/master/ai/model-serving-tensorflow/deployment.yaml +kubectl delete -f https://raw.githubusercontent.com/kubernetes/examples/refs/heads/master/ai/model-serving-tensorflow/pvc.yaml +kubectl delete -f https://raw.githubusercontent.com/kubernetes/examples/refs/heads/master/ai/model-serving-tensorflow/pv.yaml + ``` --- From 61dd508a7c3dc73c4f44ae476d75770a639e8fe9 Mon Sep 17 00:00:00 2001 From: Jayesh Mahajan Date: Mon, 2 Jun 2025 20:10:14 -0400 Subject: [PATCH 12/14] Update as per comments README.md --- ai/model-serving-tensorflow/README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ai/model-serving-tensorflow/README.md b/ai/model-serving-tensorflow/README.md index f678c27e8..3cb50dbd2 100644 --- a/ai/model-serving-tensorflow/README.md +++ b/ai/model-serving-tensorflow/README.md @@ -1,6 +1,6 @@ # TensorFlow Model Serving on Kubernetes -## ๐ŸŽฏ Purpose / What You'll Learn +## 1 Purpose / What You'll Learn This example demonstrates how to deploy a TensorFlow model for inference using [TensorFlow Serving](https://www.tensorflow.org/serving) on Kubernetes. Youโ€™ll learn how to: @@ -47,7 +47,7 @@ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/refs/head --- -## ๐Ÿงฉ Explanation on PVC +## 2. Expose the Servic ### 1. PersistentVolume & PVC Setup @@ -73,7 +73,7 @@ Update the `host` value in `ingress.yaml` to match your domain. --- -## โœ… Verification / Seeing it Work +## 3 Verification / Seeing it Work If using ingress: @@ -95,7 +95,8 @@ To verify the pod is running: ```bash kubectl get pods -kubectl logs +kubectl wait --for=condition=Available deployment/tf-serving --timeout=300s +kubectl logs deployment/tf-serving ``` --- @@ -121,7 +122,7 @@ kubectl delete -f https://raw.githubusercontent.com/kubernetes/examples/refs/hea --- -## ๐Ÿ“˜ Further Reading / Next Steps +## 4 Further Reading / Next Steps - [TensorFlow Serving](https://www.tensorflow.org/tfx/serving) - [TF Serving REST API Reference](https://www.tensorflow.org/tfx/serving/api_rest) From 267d2cd508092df12399b3a37df15c5c3163dc28 Mon Sep 17 00:00:00 2001 From: Jayesh Mahajan Date: Mon, 2 Jun 2025 20:13:55 -0400 Subject: [PATCH 13/14] Update tensorflow/serving:2.19.0 deployment.yaml --- ai/model-serving-tensorflow/deployment.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ai/model-serving-tensorflow/deployment.yaml b/ai/model-serving-tensorflow/deployment.yaml index fb8eb0a86..5b2358d47 100644 --- a/ai/model-serving-tensorflow/deployment.yaml +++ b/ai/model-serving-tensorflow/deployment.yaml @@ -16,7 +16,7 @@ spec: spec: containers: - name: tensorflow-serving - image: tensorflow/serving:2.13.0 + image: tensorflow/serving:2.19.0 args: - "--model_name=my_model" - "--port=8500" From e4acc7865b9fae4a51024a443e1796cc9c9c6ab7 Mon Sep 17 00:00:00 2001 From: Jayesh Mahajan Date: Mon, 2 Jun 2025 20:16:45 -0400 Subject: [PATCH 14/14] remove hostname ai/model-serving-tensorflow/ingress.yaml --- ai/model-serving-tensorflow/ingress.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ai/model-serving-tensorflow/ingress.yaml b/ai/model-serving-tensorflow/ingress.yaml index 3793f9b9d..72b392dae 100644 --- a/ai/model-serving-tensorflow/ingress.yaml +++ b/ai/model-serving-tensorflow/ingress.yaml @@ -6,8 +6,7 @@ metadata: nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: rules: - - host: tf.example.com - http: + - http: paths: - path: /tf(/|$)(.*) pathType: Prefix