Deploy the Complete Stack for localhost access#
Now that we have deployed both the Storage Service and Discovery Service, we need to make both services accessible from your host machine. We’ll use kubectl port-forward so external clients can connect to the Discovery Service and the endpoints it provides.
The diagram below shows the service topology for this phase. The client first queries Discovery to resolve the Storage Service endpoint, then communicates directly with Storage using that endpoint.
┌─────────────────────────────────────────────────────────┐
│ Your Host Machine │
│ │
│ ┌───────────────┐ ┌───────────────────────┐ │
│ │ curl / Kit / │ │ kubectl port-forward│ │
│ │ Custom Client│ │ :8080 :8011 :50051 │ │
│ └──────┬────────┘ └────────────┬──────────┘ │
│ │ 1. GET /api/v1/services │ │
│ │──────────────────────────────>│ │
│ │ │ │
└─────────┼───────────────────────────────┼───────────────┘
│ │
┌─────────┼───────────────────────────────┼───────────────┐
│ │ MicroK8s Cluster │ │
│ │ ┌───────────────▼──────────┐ │
│ │ │ Discovery Service :8080│ │
│ │ │ returns REST + gRPC URLs│ │
│ │ └───────────────┬──────────┘ │
│ │ 2. REST/gRPC endpoint URLs │ │
│ │<──────────────────────────────│ │
│ │ │
│ │ 3. PUT/GET /v1beta/fileobject/... │
│ │───────────────────────────────────────────> │
│ │ ┌──────────────────────────────┐│
│ │ │ Storage Service :8011/:50051││
│ │ │ (filesystem adapter) ││
│ │<──────────────┴──────────────────────────────┘│
└─────────────────────────────────────────────────────────┘
For the full production architecture with cloud infrastructure, see Architecture.
Important
Before proceeding, stop any port-forward processes left running from the previous phase so ports 8011, 50051, and 8080 are free.
# Press Ctrl+C in any terminal window running kubectl port-forward, or kill by port:
pkill -f "kubectl port-forward" || true
Then delete the previous namespace so you start from a clean state:
microk8s kubectl delete namespace storage-apis-dev --ignore-not-found
Ready State#
Now re-create the namespace, secrets, and deploy the services.
Namespace#
# create the namespace
microk8s kubectl create namespace storage-apis-dev
Storage Service#
# cd into the storage-api-1.0.0-beta.2/filesystem_example directory
cd storage-api-1.0.0-beta.2/filesystem_example
# deploy the storage service
microk8s kubectl apply -f storage-service.yaml -n storage-apis-dev
NGC Pull Secret#
# create the NGC pull secret
microk8s kubectl create secret docker-registry ngcpull-secret --docker-server=nvcr.io --docker-username='$oauthtoken' --docker-password={NGC_API_KEY} -n storage-apis-dev
# validate the NGC pull secret was created
microk8s kubectl get secret ngcpull-secret -n storage-apis-dev
Discovery Service#
# cd into the discovery-service directory
cd discovery-service
# deploy the discovery service
microk8s helm install discovery-service . -f discovery-values.yaml --namespace storage-apis-dev
You can verify both services are running:
# Check Service
microk8s kubectl get pods -n storage-apis-dev -w | grep -E "(discovery-service|storage-service)"
Both should show pods in Running status.
Update Discovery Service Configuration#
Now we need to update the Discovery Service, as we plan to access through port-forwarding to on our host machine. For that to work, we align all the services being returned by discovery to have localhost as the host. Once we forward all ports to our host machine, these are the endpoints that need to be returned by the discovery service.
The Discovery Service is deployed using Helm, so we need to update the Helm values file and upgrade the deployment.
Navigate to your Discovery Service Helm chart directory:
# Change to the discovery-service chart directory
cd discovery-service
Edit your discovery-values.yaml file to update the service URLs to use external Ingress hostnames:
code discovery-values.yaml
Update the discovery services configuration to use external URLs:
discovery:
services:
- id: "storage-service-01"
name: "Storage service"
type: "storage"
endpoints:
grpc:
host: "localhost"
port: 50051
path: "/"
tls: false
rest:
host: "localhost"
port: 8011
path: "/"
tls: false
Upgrade the Discovery Service with the updated configuration:
# Upgrade the discovery service with new values
microk8s helm upgrade discovery-service . -f discovery-values.yaml --namespace storage-apis-dev
Wait for the Discovery Service pod to restart with the new configuration:
microk8s kubectl get pods -n storage-apis-dev -w
Press Ctrl+C once the discovery-service pod shows Running status.
Access Services from Your Host (Port-Forwarding)#
Currently, both services are ClusterIP services. To reach them from your host, use kubectl port-forward so they are exposed on localhost.
# port forward the discovery service
microk8s kubectl port-forward -n storage-apis-dev service/discovery-service 8080:8080
# port forward the storage service
microk8s kubectl port-forward -n storage-apis-dev service/storage-service 8011:8011
# port forward the storage service grpc endpoint
microk8s kubectl port-forward -n storage-apis-dev service/storage-service 50051:50051
Verify External Access#
Now let’s test that both services are accessible externally via Ingress.
Test Discovery Service:
# Test the discovery service via external URL
curl http://localhost:8080/api/v1/services
You should see the JSON response with external URLs (http://localhost:8011 and http://localhost:50051).
The response should look similar to:
{
"schema-version": 1,
"services": [
{
"id": "storage-service-01",
"name": "Storage service",
"type": "storage",
"grpc": "grpc://localhost:50051",
"rest": "http://localhost:8011"
}
]
}
Test Storage Service:
# Test writing to the storage service via external URL
curl -X PUT "http://localhost:8011/v1beta/fileobject/by-address/file-storage%3A%2F%2Ffileservice%2Fhello.txt?data_object_size=20" \
-H "Content-Type: application/octet-stream" \
--data "Hello from Storage API via localhost!"
# Test reading from the storage service via external URL
curl http://localhost:8011/v1beta/fileobject/by-address/file-storage%3A%2F%2Ffileservice%2Fhello.txt
You should see:
>> "Hello from Storage API via localhost!"
End-to-End Test#
Let’s verify the complete workflow: query Discovery Service to get Storage Service URL, then use that URL to access Storage Service.
# Step 1: Query Discovery Service via external URL
DISCOVERY_RESPONSE=$(curl -s http://localhost:8080/api/v1/services)
echo "$DISCOVERY_RESPONSE"
# Step 2: Extract Storage Service URL using jq
# We will use jq to parse the Discovery Service response and get the REST URL for the storage service.
STORAGE_URL=$(echo "$DISCOVERY_RESPONSE" | jq -r '.services[] | select(.type == "storage") | .rest')
echo "Storage service REST URL: $STORAGE_URL"
# Step 3: Use the Storage Service URL from Discovery response
curl "${STORAGE_URL}v1beta/fileobject/by-address/file-storage%3A%2F%2Ffileservice%2Fhello.txt"
This demonstrates the complete workflow: external client → Discovery Service → Storage Service.
Troubleshooting#
If localhost access stops working after port-forwarding, try these checks (in order):
Pods healthy
microk8s kubectl get pods -n storage-apis-dev microk8s kubectl describe pod -n storage-apis-dev -l app=storage-service microk8s kubectl describe pod -n storage-apis-dev -l app=discovery-service
Services and endpoints wired up
microk8s kubectl get svc,endpoints -n storage-apis-dev
Port-forward sessions still running
ps -ef | grep "kubectl port-forward" | grep -E "storage-service|discovery-service" || true # If they are not running, rerun the port-forward commands from above.
Curl with verbose output
curl -v http://localhost:8080/api/v1/services curl -v http://localhost:8011/v1beta/fileobject/by-address/file-storage%3A%2F%2Ffileservice%2Fhello.txt
Inspect logs
microk8s kubectl logs deployment/discovery-service -n storage-apis-dev microk8s kubectl logs deployment/storage-service -n storage-apis-dev
Next Steps#
Next, we will be testing the deployment with a Kit-based application to validate the end-to-end workflow. Consider running those tests before cleaning up the deployment.
Cleanup#
To cleanup the entire deployment, delete the namespace:
microk8s kubectl delete namespace storage-apis-dev
This will remove all resources (Storage Service, Discovery Service, ConfigMaps, PVCs, etc.).