From 879e3be4b85efa043acdede5886fd1ab2008d27b Mon Sep 17 00:00:00 2001 From: DaMandal0rian Date: Thu, 25 Sep 2025 00:53:17 +0300 Subject: [PATCH 1/4] chore: refactor and productionize --- k8s/README.md | 182 ++++++++++++++---- k8s/auth.sh | 13 ++ k8s/{ => base}/deployment.yaml | 22 ++- k8s/base/kustomization.yaml | 10 + k8s/base/namespace.yaml | 6 + k8s/base/podmonitor.yaml | 15 ++ k8s/base/service.yaml | 15 ++ k8s/base/serviceaccount.yaml | 9 + k8s/base/servicemonitor.yaml | 15 ++ k8s/configmap.yaml | 55 ------ k8s/environments/mainnet/apply.sh | 32 +++ k8s/environments/mainnet/auth.sh | 13 ++ k8s/environments/mainnet/config.secret.yaml | 45 +++++ k8s/environments/mainnet/config.yaml | 49 +++++ k8s/environments/mainnet/diff.sh | 14 ++ k8s/environments/mainnet/kustomization.yaml | 27 +++ .../mainnet/persistent-volume-claim.yaml | 28 +++ .../mainnet/restart-deployments.sh | 11 ++ k8s/environments/testnet/apply.sh | 27 +++ k8s/environments/testnet/auth.sh | 13 ++ k8s/environments/testnet/config.secret.yaml | 46 +++++ k8s/environments/testnet/config.yaml | 49 +++++ k8s/environments/testnet/diff.sh | 14 ++ k8s/environments/testnet/kustomization.yaml | 27 +++ .../testnet/persistent-volume-claim.yaml | 28 +++ .../testnet/restart-deployments.sh | 11 ++ k8s/persistent-volume-claim.yaml | 40 ---- k8s/secrets.yaml.example | 56 ------ 28 files changed, 682 insertions(+), 190 deletions(-) create mode 100755 k8s/auth.sh rename k8s/{ => base}/deployment.yaml (84%) create mode 100644 k8s/base/kustomization.yaml create mode 100644 k8s/base/namespace.yaml create mode 100644 k8s/base/podmonitor.yaml create mode 100644 k8s/base/service.yaml create mode 100644 k8s/base/serviceaccount.yaml create mode 100644 k8s/base/servicemonitor.yaml delete mode 100644 k8s/configmap.yaml create mode 100755 k8s/environments/mainnet/apply.sh create mode 100755 k8s/environments/mainnet/auth.sh create mode 100644 k8s/environments/mainnet/config.secret.yaml create mode 100644 k8s/environments/mainnet/config.yaml create mode 100755 k8s/environments/mainnet/diff.sh create mode 100644 k8s/environments/mainnet/kustomization.yaml create mode 100644 k8s/environments/mainnet/persistent-volume-claim.yaml create mode 100755 k8s/environments/mainnet/restart-deployments.sh create mode 100755 k8s/environments/testnet/apply.sh create mode 100755 k8s/environments/testnet/auth.sh create mode 100644 k8s/environments/testnet/config.secret.yaml create mode 100644 k8s/environments/testnet/config.yaml create mode 100755 k8s/environments/testnet/diff.sh create mode 100644 k8s/environments/testnet/kustomization.yaml create mode 100644 k8s/environments/testnet/persistent-volume-claim.yaml create mode 100755 k8s/environments/testnet/restart-deployments.sh delete mode 100644 k8s/persistent-volume-claim.yaml delete mode 100644 k8s/secrets.yaml.example diff --git a/k8s/README.md b/k8s/README.md index ce0a610..ccf2b71 100644 --- a/k8s/README.md +++ b/k8s/README.md @@ -1,81 +1,184 @@ # Service Quality Oracle - Kubernetes Deployment -This directory contains Kubernetes manifests for deploying the Service Quality Oracle with persistent state management. +This directory contains Kubernetes manifests for deploying the Service Quality Oracle in different environments using Kustomize with persistent state management. + +## Structure + +``` +k8s/ +├── README.md # This file +├── auth.sh # Global auth script (configure for your cluster) +├── base/ # Common base resources +│ ├── kustomization.yaml +│ ├── namespace.yaml +│ ├── deployment.yaml +│ ├── service.yaml +│ ├── servicemonitor.yaml +│ ├── serviceaccount.yaml +│ └── podmonitor.yaml +└── environments/ + ├── mainnet/ # Production environment + │ ├── kustomization.yaml + │ ├── config.yaml # Mainnet configuration + │ ├── config.secret.yaml # Mainnet secrets (configure before use) + │ ├── persistent-volume-claim.yaml + │ ├── auth.sh + │ ├── apply.sh + │ ├── diff.sh + │ └── restart-deployments.sh + └── testnet/ # Staging environment + ├── kustomization.yaml + ├── config.yaml # Testnet configuration + ├── config.secret.yaml # Testnet secrets (configure before use) + ├── persistent-volume-claim.yaml + ├── auth.sh + ├── apply.sh + ├── diff.sh + └── restart-deployments.sh +``` ## Prerequisites - Kubernetes cluster (version 1.19+) - `kubectl` configured to access your cluster +- Kustomize (built into kubectl v1.14+) - Docker image published to `ghcr.io/graphprotocol/service-quality-oracle` - **Storage class configured** (see Storage Configuration below) ## Quick Start -### 1. Create Secrets (Required) +### 1. Configure Cluster Access + +Update `auth.sh` with your GKE cluster details: + +```bash +# Edit auth.sh +vim auth.sh + +# Connect to your cluster +./auth.sh +``` + +### 2. Deploy to Testnet + +```bash +cd environments/testnet + +# Configure secrets (replace placeholder values) +vim config.secret.yaml + +# Preview changes +./diff.sh + +# Deploy +./apply.sh + +# Monitor +kubectl logs -f deployment/service-quality-oracle -n service-quality-oracle +``` + +### 3. Deploy to Mainnet ```bash -# Copy the example secrets file -cp k8s/secrets.yaml.example k8s/secrets.yaml +cd environments/mainnet -# Edit with your actual credentials -# IMPORTANT: Never commit secrets.yaml to version control -nano k8s/secrets.yaml +# Configure secrets (replace placeholder values with production keys) +vim config.secret.yaml + +# Configure mainnet contract address +vim config.yaml +# Update BLOCKCHAIN_CONTRACT_ADDRESS with actual mainnet contract + +# Preview changes +./diff.sh + +# Deploy (includes safety checks) +./apply.sh + +# Monitor +kubectl logs -f deployment/service-quality-oracle -n service-quality-oracle ``` -**Required secrets:** +## Environment Configuration + +### Environment Differences + +| Setting | Testnet | Mainnet | +|---------|---------|---------| +| Chain | Arbitrum Sepolia | Arbitrum One | +| Contract | 0x6d5...91f6 | Configure in config.yaml | +| Image Tag | testnet-latest | mainnet-latest | +| Labels | environment: testnet, variant: staging | environment: mainnet, variant: production | + +### Secret Configuration + +Before deploying, you must configure the following secrets in each environment's `config.secret.yaml`: + - **`google-credentials`**: Service account JSON for BigQuery access -- **`blockchain-private-key`**: Private key for Arbitrum Sepolia transactions +- **`blockchain-private-key`**: Private key for blockchain transactions (64 chars, no 0x) +- **`etherscan-api-key`**: Etherscan API key - **`arbitrum-api-key`**: API key for Arbiscan contract verification -- **`slack-webhook-url`**: Webhook URL for operational notifications +- **`studio-api-key`**: The Graph Studio API key +- **`studio-deploy-key`**: The Graph Studio deploy key +- **`slack-webhook-url`**: Slack webhook for notifications -### 2. Configure Storage (Required) +## Storage Configuration ```bash # Check available storage classes kubectl get storageclass -# If you see a default storage class (marked with *), skip to step 3 -# Otherwise, edit persistent-volume-claim.yaml and uncomment the appropriate storageClassName +# The manifests use 'ssd-retain' storage class by default +# Edit environments/{mainnet,testnet}/persistent-volume-claim.yaml if needed ``` **Common storage classes by platform:** - **AWS EKS**: `gp2`, `gp3`, `ebs-csi` -- **Google GKE**: `standard`, `ssd` +- **Google GKE**: `standard`, `ssd` - **Azure AKS**: `managed-premium`, `managed` - **Local/Development**: `hostpath`, `local-path` -### 3. Deploy to Kubernetes +## Operations + +### Restart Deployments ```bash -# Apply all manifests -kubectl apply -f k8s/ +./restart-deployments.sh +``` + +### View Logs -# Verify deployment -kubectl get pods -l app=service-quality-oracle -kubectl get pvc -l app=service-quality-oracle +```bash +kubectl logs -f deployment/service-quality-oracle -n service-quality-oracle ``` -### 4. Monitor Deployment +### Check Status ```bash -# Check pod status -kubectl describe pod -l app=service-quality-oracle +kubectl get all -n service-quality-oracle +``` -# View logs -kubectl logs -l app=service-quality-oracle -f +### Delete Environment -# Check persistent volumes -kubectl get pv +```bash +kubectl delete -k . ``` +## Monitoring + +- Prometheus scraping enabled via annotations +- ServiceMonitor and PodMonitor configured for metrics collection +- Metrics exposed on port 8000 at `/metrics` endpoint +- Labels applied for environment-specific alerting + ## Architecture ### Persistent Storage The service uses **two persistent volumes** to maintain state across pod restarts: -- **`service-quality-oracle-data` (5GB)**: Circuit breaker state, last run tracking, BigQuery cache, CSV outputs -- **`service-quality-oracle-logs` (2GB)**: Application logs +- **`service-quality-oracle-data` (10GB)**: Circuit breaker state, last run tracking, BigQuery cache, CSV outputs +- **`service-quality-oracle-logs` (5GB)**: Application logs **Mount points:** - `/app/data` → Critical state files (circuit breaker, cache, outputs) @@ -83,8 +186,8 @@ The service uses **two persistent volumes** to maintain state across pod restart ### Configuration Management -**Non-sensitive configuration** → `ConfigMap` (`configmap.yaml`) -**Sensitive credentials** → `Secret` (`secrets.yaml`) +**Non-sensitive configuration** → `ConfigMap` (generated from `config.yaml`) +**Sensitive credentials** → `Secret` (generated from `config.secret.yaml`) This separation provides: - ✅ Easy configuration updates without rebuilding images @@ -98,7 +201,7 @@ This separation provides: - Memory: 512M **Limits (maximum):** -- CPU: 1000m (1.0 core) +- CPU: 1000m (1.0 core) - Memory: 1G ## State Persistence Benefits @@ -127,7 +230,7 @@ kubectl describe pod -l app=service-quality-oracle # Common issues: # - Missing secrets -# - PVC provisioning failures +# - PVC provisioning failures # - Image pull errors ``` @@ -151,13 +254,16 @@ kubectl exec -it deployment/service-quality-oracle -- env | grep -E "(BIGQUERY|B kubectl exec -it deployment/service-quality-oracle -- ls -la /etc/secrets ``` -## Security Best Practices +## Security -✅ **Secrets never committed** to version control +✅ **Never commit actual secrets** - `config.secret.yaml` files contain placeholders only +✅ **Mainnet deployment safety checks** for production secrets +✅ **Non-root containers** with dropped capabilities ✅ **Service account** with minimal BigQuery permissions ✅ **Private key** stored in Kubernetes secrets (base64 encoded) ✅ **Resource limits** prevent resource exhaustion -✅ **Read-only filesystem** where possible +✅ **Workload Identity** configured for secure GCP access +✅ **SSD storage with retention** for data persistence ## Production Considerations @@ -171,7 +277,7 @@ kubectl exec -it deployment/service-quality-oracle -- ls -la /etc/secrets ## Next Steps 1. **Test deployment** in staging environment -2. **Verify state persistence** across pod restarts +2. **Verify state persistence** across pod restarts 3. **Set up monitoring** and alerting 4. **Configure backup** for persistent volumes -5. **Enable quality checking** after successful validation \ No newline at end of file +5. **Enable quality checking** after successful validation diff --git a/k8s/auth.sh b/k8s/auth.sh new file mode 100755 index 0000000..d1dce12 --- /dev/null +++ b/k8s/auth.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# Get cluster credentials for service-quality-oracle deployment +# Update the following values based on your GKE cluster configuration: +# - PROJECT: Your GCP project ID +# - CLUSTER: Your GKE cluster name +# - ZONE: Your GKE cluster zone/region + +PROJECT="graph-mainnet" +CLUSTER="network" +ZONE="us-central1-a" + +gcloud container clusters get-credentials $CLUSTER --project $PROJECT --zone $ZONE diff --git a/k8s/deployment.yaml b/k8s/base/deployment.yaml similarity index 84% rename from k8s/deployment.yaml rename to k8s/base/deployment.yaml index ff11dd9..c6f9c63 100644 --- a/k8s/deployment.yaml +++ b/k8s/base/deployment.yaml @@ -13,10 +13,20 @@ spec: metadata: labels: app: service-quality-oracle + annotations: + prometheus.io/scrape: "true" + prometheus.io/path: "/metrics" + prometheus.io/port: "8000" spec: + imagePullSecrets: + - name: docker-registry containers: - name: service-quality-oracle image: ghcr.io/graphprotocol/service-quality-oracle:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 8000 + name: metrics envFrom: # Load all non-sensitive configuration from ConfigMap - configMapRef: @@ -89,6 +99,15 @@ spec: - "import os; assert os.path.exists('/app/healthcheck'), 'Healthcheck file missing'" initialDelaySeconds: 10 periodSeconds: 30 + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 1000 + readOnlyRootFilesystem: false + capabilities: + drop: + - ALL volumes: - name: data-volume persistentVolumeClaim: @@ -96,4 +115,5 @@ spec: - name: logs-volume persistentVolumeClaim: claimName: service-quality-oracle-logs - restartPolicy: Always \ No newline at end of file + serviceAccountName: service-quality-oracle + restartPolicy: Always diff --git a/k8s/base/kustomization.yaml b/k8s/base/kustomization.yaml new file mode 100644 index 0000000..0ea547a --- /dev/null +++ b/k8s/base/kustomization.yaml @@ -0,0 +1,10 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - namespace.yaml + - deployment.yaml + - service.yaml + - servicemonitor.yaml + - serviceaccount.yaml + - podmonitor.yaml diff --git a/k8s/base/namespace.yaml b/k8s/base/namespace.yaml new file mode 100644 index 0000000..f9520de --- /dev/null +++ b/k8s/base/namespace.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: service-quality-oracle + labels: + name: service-quality-oracle diff --git a/k8s/base/podmonitor.yaml b/k8s/base/podmonitor.yaml new file mode 100644 index 0000000..537b85d --- /dev/null +++ b/k8s/base/podmonitor.yaml @@ -0,0 +1,15 @@ +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + name: service-quality-oracle + labels: + app: service-quality-oracle +spec: + selector: + matchLabels: + app: service-quality-oracle + podMetricsEndpoints: + - port: metrics + path: /metrics + interval: 30s + scrapeTimeout: 10s diff --git a/k8s/base/service.yaml b/k8s/base/service.yaml new file mode 100644 index 0000000..a9695f8 --- /dev/null +++ b/k8s/base/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: service-quality-oracle + labels: + app: service-quality-oracle +spec: + selector: + app: service-quality-oracle + ports: + - name: metrics + port: 8000 + targetPort: 8000 + protocol: TCP + type: ClusterIP diff --git a/k8s/base/serviceaccount.yaml b/k8s/base/serviceaccount.yaml new file mode 100644 index 0000000..8ea6edf --- /dev/null +++ b/k8s/base/serviceaccount.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: service-quality-oracle + labels: + app: service-quality-oracle + annotations: + iam.gke.io/gcp-service-account: service-quality-oracle@graph-mainnet.iam.gserviceaccount.com +automountServiceAccountToken: false diff --git a/k8s/base/servicemonitor.yaml b/k8s/base/servicemonitor.yaml new file mode 100644 index 0000000..4da96ae --- /dev/null +++ b/k8s/base/servicemonitor.yaml @@ -0,0 +1,15 @@ +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: service-quality-oracle + labels: + app: service-quality-oracle +spec: + selector: + matchLabels: + app: service-quality-oracle + endpoints: + - port: metrics + path: /metrics + interval: 30s + scrapeTimeout: 10s diff --git a/k8s/configmap.yaml b/k8s/configmap.yaml deleted file mode 100644 index 6fa14af..0000000 --- a/k8s/configmap.yaml +++ /dev/null @@ -1,55 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: service-quality-oracle-config - labels: - app: service-quality-oracle -data: - # BigQuery Configuration - BIGQUERY_LOCATION_ID: "US" - BIGQUERY_PROJECT_ID: "graph-mainnet" - BIGQUERY_DATASET_ID: "internal_metrics" - BIGQUERY_TABLE_ID: "metrics_indexer_attempts" - BIGQUERY_CURATION_TABLE_ID: "metrics_curator_signals" - BIGQUERY_CURATOR_MAINNET_TABLE_ID: "curator_name_signal_dimensions_daily" - BIGQUERY_CURATOR_ARBITRUM_TABLE_ID: "curator_name_signal_dimensions_arbitrum_daily" - BIGQUERY_SUBGRAPH_LOOKUP_TABLE_ID: "subgraph_version_id_lookup" - BIGQUERY_ANALYSIS_PERIOD_DAYS: "28" - - # Blockchain Configuration (Arbitrum Sepolia) - BLOCKCHAIN_CONTRACT_ADDRESS: "0x6d5550698F930210c3f50efe744bF51C55D791f6" - BLOCKCHAIN_FUNCTION_NAME: "allowIndexers" - BLOCKCHAIN_CHAIN_ID: "421614" - BLOCK_EXPLORER_URL: "https://sepolia.arbiscan.io" - TX_TIMEOUT_SECONDS: "30" - - # RPC Provider URLs (Arbitrum Sepolia) - BLOCKCHAIN_RPC_URL_1: "https://arbitrum-sepolia.drpc.org" - BLOCKCHAIN_RPC_URL_2: "https://sepolia-rollup.arbitrum.io/rpc" - BLOCKCHAIN_RPC_URL_3: "https://api.zan.top/arb-sepolia" - BLOCKCHAIN_RPC_URL_4: "https://arbitrum-sepolia.gateway.tenderly.co" - - # Scheduling Configuration - SCHEDULED_RUN_TIME: "10:00" - - # Subgraph URLs - SUBGRAPH_URL_PRE_PRODUCTION: "https://api.studio.thegraph.com/query/110664/issuance-eligibility-oracle/v0.1.4" - SUBGRAPH_URL_PRODUCTION: "https://gateway.thegraph.com/api/subgraphs/id/" - - # Processing Configuration - BATCH_SIZE: "125" - MAX_AGE_BEFORE_DELETION: "120" - - # Caching Configuration - CACHE_MAX_AGE_MINUTES: "30" - FORCE_BIGQUERY_REFRESH: "false" - - # Eligibility Criteria - MIN_ONLINE_DAYS: "5" - MIN_SUBGRAPHS: "10" - MAX_LATENCY_MS: "5000" - MAX_BLOCKS_BEHIND: "50000" - MIN_CURATION_SIGNAL: "500" - - # Runtime Configuration - RUN_ON_STARTUP: "true" \ No newline at end of file diff --git a/k8s/environments/mainnet/apply.sh b/k8s/environments/mainnet/apply.sh new file mode 100755 index 0000000..9a9522a --- /dev/null +++ b/k8s/environments/mainnet/apply.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +set -e + +# Apply Kubernetes manifests for service-quality-oracle (mainnet) +echo "Applying service-quality-oracle mainnet manifests..." + +# Ensure we're authenticated to the correct cluster +echo "Authenticating to cluster..." +./auth.sh + +# Check if config.secret.yaml has been configured +if ! grep -q "your-key-id-here" config.secret.yaml 2>/dev/null; then + echo "✓ Secret configuration appears to be customized" +else + echo "WARNING: config.secret.yaml contains placeholder values." + echo "Please configure your actual secrets before deploying to mainnet!" + read -p "Continue anyway? (y/N) " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi +fi + +# Apply using kustomize +kubectl apply -k . + +echo "All mainnet manifests applied successfully!" +echo "" +echo "To check status:" +echo " kubectl get all -n service-quality-oracle" +echo " kubectl logs -f deployment/service-quality-oracle -n service-quality-oracle" diff --git a/k8s/environments/mainnet/auth.sh b/k8s/environments/mainnet/auth.sh new file mode 100755 index 0000000..d1dce12 --- /dev/null +++ b/k8s/environments/mainnet/auth.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# Get cluster credentials for service-quality-oracle deployment +# Update the following values based on your GKE cluster configuration: +# - PROJECT: Your GCP project ID +# - CLUSTER: Your GKE cluster name +# - ZONE: Your GKE cluster zone/region + +PROJECT="graph-mainnet" +CLUSTER="network" +ZONE="us-central1-a" + +gcloud container clusters get-credentials $CLUSTER --project $PROJECT --zone $ZONE diff --git a/k8s/environments/mainnet/config.secret.yaml b/k8s/environments/mainnet/config.secret.yaml new file mode 100644 index 0000000..b5f457b --- /dev/null +++ b/k8s/environments/mainnet/config.secret.yaml @@ -0,0 +1,45 @@ +# Mainnet Secrets for Service Quality Oracle# IMPORTANT: This is a TEMPLATE file - DO NOT commit actual secrets! +# +# Usage: +# 1. Replace all placeholder values with your actual mainnet secrets +# 2. This file is used by kustomize secretGenerator +# +# Security: Kubernetes automatically base64 encodes stringData values + +# Google Cloud Service Account JSON for BigQuery access +# Create a dedicated service account with BigQuery Data Viewer + Job User roles +# Download JSON key from Google Cloud Console > IAM > Service Accounts + google-credentials: | + { + "type": "service_account", + "project_id": "graph-mainnet", + "private_key_id": "your-key-id-here", + "private_key": "-----BEGIN PRIVATE KEY-----\nYOUR-PRIVATE-KEY-CONTENT-HERE\n-----END PRIVATE KEY-----\n", + "client_email": "service-quality-oracle@graph-mainnet.iam.gserviceaccount.com", + "client_id": "your-client-id-here", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/service-quality-oracle%40graph-mainnet.iam.gserviceaccount.com" + } + +# Blockchain private key for Arbitrum Sepolia transactions (without 0x prefix) +# CRITICAL: This key controls blockchain transactions - keep secure + blockchain-private-key: "your-64-character-private-key-here" + +# Etherscan API key for mainnet contract verification (if needed) +# Get from: https://etherscan.io/apis + etherscan-api-key: "your-etherscan-api-key-here" + +# Arbitrum API key for contract verification on Arbitrum networks +# Get from: https://arbiscan.io/apis + arbitrum-api-key: "your-arbitrum-api-key-here" + +# The Graph Studio API credentials +# Get from: https://thegraph.com/studio/apikeys + studio-api-key: "your-studio-api-key-here" + studio-deploy-key: "your-studio-deploy-key-here" + +# Slack webhook URL for operational notifications +# Create webhook: Slack App > Incoming Webhooks > Add New Webhook + slack-webhook-url: "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX" diff --git a/k8s/environments/mainnet/config.yaml b/k8s/environments/mainnet/config.yaml new file mode 100644 index 0000000..a463c75 --- /dev/null +++ b/k8s/environments/mainnet/config.yaml @@ -0,0 +1,49 @@ +# Mainnet Configuration for Service Quality Oracle +# BigQuery Configuration +BIGQUERY_LOCATION_ID: "US" +BIGQUERY_PROJECT_ID: "graph-mainnet" +BIGQUERY_DATASET_ID: "internal_metrics" +BIGQUERY_TABLE_ID: "metrics_indexer_attempts" +BIGQUERY_CURATION_TABLE_ID: "metrics_curator_signals" +BIGQUERY_CURATOR_MAINNET_TABLE_ID: "curator_name_signal_dimensions_daily" +BIGQUERY_CURATOR_ARBITRUM_TABLE_ID: "curator_name_signal_dimensions_arbitrum_daily" +BIGQUERY_SUBGRAPH_LOOKUP_TABLE_ID: "subgraph_version_id_lookup" +BIGQUERY_ANALYSIS_PERIOD_DAYS: "28" + +# Blockchain Configuration (Arbitrum One - Mainnet) +BLOCKCHAIN_CONTRACT_ADDRESS: "0x0000000000000000000000000000000000000000" # TODO: Replace with mainnet contract +BLOCKCHAIN_FUNCTION_NAME: "allowIndexers" +BLOCKCHAIN_CHAIN_ID: "42161" +BLOCK_EXPLORER_URL: "https://arbiscan.io" +TX_TIMEOUT_SECONDS: "30" + +# RPC Provider URLs (Arbitrum One - Mainnet) +BLOCKCHAIN_RPC_URL_1: "https://arbitrum.drpc.org" +BLOCKCHAIN_RPC_URL_2: "https://arb1.arbitrum.io/rpc" +BLOCKCHAIN_RPC_URL_3: "https://api.zan.top/node/v1/arb/one" +BLOCKCHAIN_RPC_URL_4: "https://arbitrum-one.gateway.tenderly.co" + +# Scheduling Configuration +SCHEDULED_RUN_TIME: "10:00" + +# Subgraph URLs +SUBGRAPH_URL_PRE_PRODUCTION: "https://api.studio.thegraph.com/query/110664/issuance-eligibility-oracle/v0.1.4" +SUBGRAPH_URL_PRODUCTION: "https://gateway.thegraph.com/api/subgraphs/id/" + +# Processing Configuration +BATCH_SIZE: "125" +MAX_AGE_BEFORE_DELETION: "120" + +# Caching Configuration +CACHE_MAX_AGE_MINUTES: "30" +FORCE_BIGQUERY_REFRESH: "false" + +# Eligibility Criteria +MIN_ONLINE_DAYS: "5" +MIN_SUBGRAPHS: "10" +MAX_LATENCY_MS: "5000" +MAX_BLOCKS_BEHIND: "50000" +MIN_CURATION_SIGNAL: "500" + +# Runtime Configuration +RUN_ON_STARTUP: "true" diff --git a/k8s/environments/mainnet/diff.sh b/k8s/environments/mainnet/diff.sh new file mode 100755 index 0000000..6ae6dcf --- /dev/null +++ b/k8s/environments/mainnet/diff.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -e + +# Show diff of what would change when applying manifests (mainnet) +echo "Showing diff for service-quality-oracle mainnet manifests..." + +# Ensure we're authenticated to the correct cluster +echo "Authenticating to cluster..." +./auth.sh + +kubectl diff -k . || true + +echo "Mainnet diff complete." diff --git a/k8s/environments/mainnet/kustomization.yaml b/k8s/environments/mainnet/kustomization.yaml new file mode 100644 index 0000000..5a85fc8 --- /dev/null +++ b/k8s/environments/mainnet/kustomization.yaml @@ -0,0 +1,27 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: service-quality-oracle + +resources: + - ../../base + - persistent-volume-claim.yaml + +secretGenerator: + - name: service-quality-oracle-secrets + files: + - config.secret.yaml + +configMapGenerator: + - name: service-quality-oracle-config + files: + - config.yaml + +images: + - name: ghcr.io/graphprotocol/service-quality-oracle + newName: ghcr.io/graphprotocol/service-quality-oracle + newTag: mainnet-latest + +commonLabels: + environment: mainnet + variant: production diff --git a/k8s/environments/mainnet/persistent-volume-claim.yaml b/k8s/environments/mainnet/persistent-volume-claim.yaml new file mode 100644 index 0000000..53d4668 --- /dev/null +++ b/k8s/environments/mainnet/persistent-volume-claim.yaml @@ -0,0 +1,28 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: service-quality-oracle-data + labels: + app: service-quality-oracle +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi + storageClassName: "ssd-retain" # Production storage class with retention + +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: service-quality-oracle-logs + labels: + app: service-quality-oracle +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi + storageClassName: "ssd-retain" # Production storage class with retention diff --git a/k8s/environments/mainnet/restart-deployments.sh b/k8s/environments/mainnet/restart-deployments.sh new file mode 100755 index 0000000..46b46df --- /dev/null +++ b/k8s/environments/mainnet/restart-deployments.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -e + +# Restart deployments for service-quality-oracle (mainnet) +echo "Restarting service-quality-oracle mainnet deployment..." + +kubectl rollout restart deployment/service-quality-oracle -n service-quality-oracle +kubectl rollout status deployment/service-quality-oracle -n service-quality-oracle --timeout=300s + +echo "Mainnet deployment restarted successfully!" diff --git a/k8s/environments/testnet/apply.sh b/k8s/environments/testnet/apply.sh new file mode 100755 index 0000000..ee91658 --- /dev/null +++ b/k8s/environments/testnet/apply.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +set -e + +# Apply Kubernetes manifests for service-quality-oracle (testnet) +echo "Applying service-quality-oracle testnet manifests..." + +# Ensure we're authenticated to the correct cluster +echo "Authenticating to cluster..." +./auth.sh + +# Check if config.secret.yaml has been configured +if ! grep -q "your-key-id-here" config.secret.yaml 2>/dev/null; then + echo "✓ Secret configuration appears to be customized" +else + echo "WARNING: config.secret.yaml contains placeholder values." + echo "Please configure your actual secrets before deploying!" +fi + +# Apply using kustomize +kubectl apply -k . + +echo "All testnet manifests applied successfully!" +echo "" +echo "To check status:" +echo " kubectl get all -n service-quality-oracle" +echo " kubectl logs -f deployment/service-quality-oracle -n service-quality-oracle" diff --git a/k8s/environments/testnet/auth.sh b/k8s/environments/testnet/auth.sh new file mode 100755 index 0000000..acdf61b --- /dev/null +++ b/k8s/environments/testnet/auth.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# Get cluster credentials for service-quality-oracle deployment +# Update the following values based on your GKE cluster configuration: +# - PROJECT: Your GCP project ID +# - CLUSTER: Your GKE cluster name +# - ZONE: Your GKE cluster zone/region + +PROJECT="graph-mainnet" +CLUSTER="testnet" +ZONE="us-central1-a" + +gcloud container clusters get-credentials $CLUSTER --project $PROJECT --zone $ZONE diff --git a/k8s/environments/testnet/config.secret.yaml b/k8s/environments/testnet/config.secret.yaml new file mode 100644 index 0000000..74cd51b --- /dev/null +++ b/k8s/environments/testnet/config.secret.yaml @@ -0,0 +1,46 @@ +# Testnet Secrets for Service Quality Oracle +# IMPORTANT: This is a TEMPLATE file - DO NOT commit actual secrets! +# +# Usage: +# 1. Replace all placeholder values with your actual testnet secrets +# 2. This file is used by kustomize secretGenerator +# +# Security: Kubernetes automatically base64 encodes stringData values + +# Google Cloud Service Account JSON for BigQuery access +# Create a dedicated service account with BigQuery Data Viewer + Job User roles +# Download JSON key from Google Cloud Console > IAM > Service Accounts + google-credentials: | + { + "type": "service_account", + "project_id": "graph-mainnet", + "private_key_id": "your-key-id-here", + "private_key": "-----BEGIN PRIVATE KEY-----\nYOUR-PRIVATE-KEY-CONTENT-HERE\n-----END PRIVATE KEY-----\n", + "client_email": "service-quality-oracle@graph-mainnet.iam.gserviceaccount.com", + "client_id": "your-client-id-here", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/service-quality-oracle%40graph-mainnet.iam.gserviceaccount.com" + } + +# Blockchain private key for Arbitrum Sepolia transactions (without 0x prefix) +# CRITICAL: This key controls blockchain transactions - keep secure + blockchain-private-key: "your-64-character-private-key-here" + +# Etherscan API key for mainnet contract verification (if needed) +# Get from: https://etherscan.io/apis + etherscan-api-key: "your-etherscan-api-key-here" + +# Arbitrum API key for contract verification on Arbitrum networks +# Get from: https://arbiscan.io/apis + arbitrum-api-key: "your-arbitrum-api-key-here" + +# The Graph Studio API credentials +# Get from: https://thegraph.com/studio/apikeys + studio-api-key: "your-studio-api-key-here" + studio-deploy-key: "your-studio-deploy-key-here" + +# Slack webhook URL for operational notifications +# Create webhook: Slack App > Incoming Webhooks > Add New Webhook + slack-webhook-url: "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX" diff --git a/k8s/environments/testnet/config.yaml b/k8s/environments/testnet/config.yaml new file mode 100644 index 0000000..c0357ce --- /dev/null +++ b/k8s/environments/testnet/config.yaml @@ -0,0 +1,49 @@ +# Testnet Configuration for Service Quality Oracle +# BigQuery Configuration +BIGQUERY_LOCATION_ID: "US" +BIGQUERY_PROJECT_ID: "graph-mainnet" +BIGQUERY_DATASET_ID: "internal_metrics" +BIGQUERY_TABLE_ID: "metrics_indexer_attempts" +BIGQUERY_CURATION_TABLE_ID: "metrics_curator_signals" +BIGQUERY_CURATOR_MAINNET_TABLE_ID: "curator_name_signal_dimensions_daily" +BIGQUERY_CURATOR_ARBITRUM_TABLE_ID: "curator_name_signal_dimensions_arbitrum_daily" +BIGQUERY_SUBGRAPH_LOOKUP_TABLE_ID: "subgraph_version_id_lookup" +BIGQUERY_ANALYSIS_PERIOD_DAYS: "28" + +# Blockchain Configuration (Arbitrum Sepolia - Testnet) +BLOCKCHAIN_CONTRACT_ADDRESS: "0x6d5550698F930210c3f50efe744bF51C55D791f6" +BLOCKCHAIN_FUNCTION_NAME: "allowIndexers" +BLOCKCHAIN_CHAIN_ID: "421614" +BLOCK_EXPLORER_URL: "https://sepolia.arbiscan.io" +TX_TIMEOUT_SECONDS: "30" + +# RPC Provider URLs (Arbitrum Sepolia - Testnet) +BLOCKCHAIN_RPC_URL_1: "https://arbitrum-sepolia.drpc.org" +BLOCKCHAIN_RPC_URL_2: "https://sepolia-rollup.arbitrum.io/rpc" +BLOCKCHAIN_RPC_URL_3: "https://api.zan.top/arb-sepolia" +BLOCKCHAIN_RPC_URL_4: "https://arbitrum-sepolia.gateway.tenderly.co" + +# Scheduling Configuration +SCHEDULED_RUN_TIME: "10:00" + +# Subgraph URLs +SUBGRAPH_URL_PRE_PRODUCTION: "https://api.studio.thegraph.com/query/110664/issuance-eligibility-oracle/v0.1.4" +SUBGRAPH_URL_PRODUCTION: "https://gateway.thegraph.com/api/subgraphs/id/" + +# Processing Configuration +BATCH_SIZE: "125" +MAX_AGE_BEFORE_DELETION: "120" + +# Caching Configuration +CACHE_MAX_AGE_MINUTES: "30" +FORCE_BIGQUERY_REFRESH: "false" + +# Eligibility Criteria +MIN_ONLINE_DAYS: "5" +MIN_SUBGRAPHS: "10" +MAX_LATENCY_MS: "5000" +MAX_BLOCKS_BEHIND: "50000" +MIN_CURATION_SIGNAL: "500" + +# Runtime Configuration +RUN_ON_STARTUP: "true" diff --git a/k8s/environments/testnet/diff.sh b/k8s/environments/testnet/diff.sh new file mode 100755 index 0000000..bc3cbe1 --- /dev/null +++ b/k8s/environments/testnet/diff.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -e + +# Show diff of what would change when applying manifests (testnet) +echo "Showing diff for service-quality-oracle testnet manifests..." + +# Ensure we're authenticated to the correct cluster +echo "Authenticating to cluster..." +./auth.sh + +kubectl diff -k . || true + +echo "Testnet diff complete." diff --git a/k8s/environments/testnet/kustomization.yaml b/k8s/environments/testnet/kustomization.yaml new file mode 100644 index 0000000..646304f --- /dev/null +++ b/k8s/environments/testnet/kustomization.yaml @@ -0,0 +1,27 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: service-quality-oracle + +resources: + - ../../base + - persistent-volume-claim.yaml + +secretGenerator: + - name: service-quality-oracle-secrets + files: + - config.secret.yaml + +configMapGenerator: + - name: service-quality-oracle-config + files: + - config.yaml + +images: + - name: ghcr.io/graphprotocol/service-quality-oracle + newName: ghcr.io/graphprotocol/service-quality-oracle + newTag: testnet-latest + +commonLabels: + environment: testnet + variant: staging diff --git a/k8s/environments/testnet/persistent-volume-claim.yaml b/k8s/environments/testnet/persistent-volume-claim.yaml new file mode 100644 index 0000000..53d4668 --- /dev/null +++ b/k8s/environments/testnet/persistent-volume-claim.yaml @@ -0,0 +1,28 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: service-quality-oracle-data + labels: + app: service-quality-oracle +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi + storageClassName: "ssd-retain" # Production storage class with retention + +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: service-quality-oracle-logs + labels: + app: service-quality-oracle +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi + storageClassName: "ssd-retain" # Production storage class with retention diff --git a/k8s/environments/testnet/restart-deployments.sh b/k8s/environments/testnet/restart-deployments.sh new file mode 100755 index 0000000..804a40b --- /dev/null +++ b/k8s/environments/testnet/restart-deployments.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -e + +# Restart deployments for service-quality-oracle (testnet) +echo "Restarting service-quality-oracle testnet deployment..." + +kubectl rollout restart deployment/service-quality-oracle -n service-quality-oracle +kubectl rollout status deployment/service-quality-oracle -n service-quality-oracle --timeout=300s + +echo "Testnet deployment restarted successfully!" diff --git a/k8s/persistent-volume-claim.yaml b/k8s/persistent-volume-claim.yaml deleted file mode 100644 index ff79393..0000000 --- a/k8s/persistent-volume-claim.yaml +++ /dev/null @@ -1,40 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: service-quality-oracle-data - labels: - app: service-quality-oracle -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 5Gi - # Storage class - uncomment and modify based on your cluster: - # storageClassName: "" # Use default storage class (most common) - # storageClassName: "gp2" # AWS EKS - # storageClassName: "standard" # GKE - # storageClassName: "managed-premium" # Azure AKS - # storageClassName: "local-path" # K3s/Rancher - # storageClassName: "hostpath" # Local development - ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: service-quality-oracle-logs - labels: - app: service-quality-oracle -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 2Gi - # Storage class - should match the data PVC above - # storageClassName: "" # Use default storage class (most common) - # storageClassName: "gp2" # AWS EKS - # storageClassName: "standard" # GKE - # storageClassName: "managed-premium" # Azure AKS - # storageClassName: "local-path" # K3s/Rancher - # storageClassName: "hostpath" # Local development \ No newline at end of file diff --git a/k8s/secrets.yaml.example b/k8s/secrets.yaml.example deleted file mode 100644 index 4dbbc53..0000000 --- a/k8s/secrets.yaml.example +++ /dev/null @@ -1,56 +0,0 @@ -# Kubernetes Secrets for Service Quality Oracle -# IMPORTANT: This is an EXAMPLE file - DO NOT commit actual secrets! -# -# Usage: -# 1. Copy this file to secrets.yaml -# 2. Replace all placeholder values with your actual secrets -# 3. Apply: kubectl apply -f secrets.yaml -# 4. Add secrets.yaml to .gitignore to prevent accidental commits -# -# Security: Kubernetes automatically base64 encodes stringData values - -apiVersion: v1 -kind: Secret -metadata: - name: service-quality-oracle-secrets - labels: - app: service-quality-oracle -type: Opaque -stringData: - # Google Cloud Service Account JSON for BigQuery access - # Create a dedicated service account with BigQuery Data Viewer + Job User roles - # Download JSON key from Google Cloud Console > IAM > Service Accounts - google-credentials: | - { - "type": "service_account", - "project_id": "graph-mainnet", - "private_key_id": "your-key-id-here", - "private_key": "-----BEGIN PRIVATE KEY-----\nYOUR-PRIVATE-KEY-CONTENT-HERE\n-----END PRIVATE KEY-----\n", - "client_email": "service-quality-oracle@graph-mainnet.iam.gserviceaccount.com", - "client_id": "your-client-id-here", - "auth_uri": "https://accounts.google.com/o/oauth2/auth", - "token_uri": "https://oauth2.googleapis.com/token", - "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", - "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/service-quality-oracle%40graph-mainnet.iam.gserviceaccount.com" - } - - # Blockchain private key for Arbitrum Sepolia transactions (without 0x prefix) - # CRITICAL: This key controls blockchain transactions - keep secure - blockchain-private-key: "your-64-character-private-key-here" - - # Etherscan API key for mainnet contract verification (if needed) - # Get from: https://etherscan.io/apis - etherscan-api-key: "your-etherscan-api-key-here" - - # Arbitrum API key for contract verification on Arbitrum networks - # Get from: https://arbiscan.io/apis - arbitrum-api-key: "your-arbitrum-api-key-here" - - # The Graph Studio API credentials - # Get from: https://thegraph.com/studio/apikeys - studio-api-key: "your-studio-api-key-here" - studio-deploy-key: "your-studio-deploy-key-here" - - # Slack webhook URL for operational notifications - # Create webhook: Slack App > Incoming Webhooks > Add New Webhook - slack-webhook-url: "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX" \ No newline at end of file From e21e1392d98b5b4bb8a5946e4f1eca8ecab213f5 Mon Sep 17 00:00:00 2001 From: DaMandal0rian Date: Thu, 25 Sep 2025 01:28:47 +0300 Subject: [PATCH 2/4] remove old auth.sh --- k8s/auth.sh | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100755 k8s/auth.sh diff --git a/k8s/auth.sh b/k8s/auth.sh deleted file mode 100755 index d1dce12..0000000 --- a/k8s/auth.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -# Get cluster credentials for service-quality-oracle deployment -# Update the following values based on your GKE cluster configuration: -# - PROJECT: Your GCP project ID -# - CLUSTER: Your GKE cluster name -# - ZONE: Your GKE cluster zone/region - -PROJECT="graph-mainnet" -CLUSTER="network" -ZONE="us-central1-a" - -gcloud container clusters get-credentials $CLUSTER --project $PROJECT --zone $ZONE From 4fc1896574c7a64a5facbaaba5dbd223f9f4a00a Mon Sep 17 00:00:00 2001 From: DaMandal0rian Date: Thu, 25 Sep 2025 18:26:47 +0300 Subject: [PATCH 3/4] rename service --- k8s/README.md | 45 +++++---- k8s/base/deployment.yaml | 38 +++---- k8s/base/namespace.yaml | 4 +- k8s/base/podmonitor.yaml | 6 +- k8s/base/service.yaml | 6 +- k8s/base/serviceaccount.yaml | 6 +- k8s/base/servicemonitor.yaml | 6 +- k8s/configmap.yaml | 55 +++++++++++ k8s/deployment.yaml | 99 +++++++++++++++++++ k8s/environments/mainnet/apply.sh | 8 +- k8s/environments/mainnet/auth.sh | 2 +- k8s/environments/mainnet/config.secret.yaml | 6 +- k8s/environments/mainnet/diff.sh | 2 +- k8s/environments/mainnet/kustomization.yaml | 10 +- .../mainnet/persistent-volume-claim.yaml | 8 +- .../mainnet/restart-deployments.sh | 8 +- k8s/environments/testnet/apply.sh | 8 +- k8s/environments/testnet/auth.sh | 2 +- k8s/environments/testnet/config.secret.yaml | 6 +- k8s/environments/testnet/diff.sh | 2 +- k8s/environments/testnet/kustomization.yaml | 10 +- .../testnet/persistent-volume-claim.yaml | 8 +- .../testnet/restart-deployments.sh | 8 +- k8s/persistent-volume-claim.yaml | 40 ++++++++ k8s/restart-deployments.sh | 11 +++ k8s/secrets.yaml.example | 56 +++++++++++ 26 files changed, 363 insertions(+), 97 deletions(-) create mode 100644 k8s/configmap.yaml create mode 100644 k8s/deployment.yaml create mode 100644 k8s/persistent-volume-claim.yaml create mode 100644 k8s/restart-deployments.sh create mode 100644 k8s/secrets.yaml.example diff --git a/k8s/README.md b/k8s/README.md index ccf2b71..9dc3ffa 100644 --- a/k8s/README.md +++ b/k8s/README.md @@ -42,7 +42,7 @@ k8s/ - Kubernetes cluster (version 1.19+) - `kubectl` configured to access your cluster - Kustomize (built into kubectl v1.14+) -- Docker image published to `ghcr.io/graphprotocol/service-quality-oracle` +- Docker image published to `ghcr.io/graphprotocol/rewards-eligibility-oracle` - **Storage class configured** (see Storage Configuration below) ## Quick Start @@ -74,7 +74,7 @@ vim config.secret.yaml ./apply.sh # Monitor -kubectl logs -f deployment/service-quality-oracle -n service-quality-oracle +kubectl logs -f deployment/rewards-eligibility-oracle -n rewards-eligibility-oracle ``` ### 3. Deploy to Mainnet @@ -96,7 +96,7 @@ vim config.yaml ./apply.sh # Monitor -kubectl logs -f deployment/service-quality-oracle -n service-quality-oracle +kubectl logs -f deployment/rewards-eligibility-oracle -n rewards-eligibility-oracle ``` ## Environment Configuration @@ -133,6 +133,7 @@ kubectl get storageclass ``` **Common storage classes by platform:** + - **AWS EKS**: `gp2`, `gp3`, `ebs-csi` - **Google GKE**: `standard`, `ssd` - **Azure AKS**: `managed-premium`, `managed` @@ -149,13 +150,13 @@ kubectl get storageclass ### View Logs ```bash -kubectl logs -f deployment/service-quality-oracle -n service-quality-oracle +kubectl logs -f deployment/rewards-eligibility-oracle -n rewards-eligibility-oracle ``` ### Check Status ```bash -kubectl get all -n service-quality-oracle +kubectl get all -n rewards-eligibility-oracle ``` ### Delete Environment @@ -177,10 +178,11 @@ kubectl delete -k . The service uses **two persistent volumes** to maintain state across pod restarts: -- **`service-quality-oracle-data` (10GB)**: Circuit breaker state, last run tracking, BigQuery cache, CSV outputs -- **`service-quality-oracle-logs` (5GB)**: Application logs +- **`rewards-eligibility-oracle-data` (10GB)**: Circuit breaker state, last run tracking, BigQuery cache, CSV outputs +- **`rewards-eligibility-oracle-logs` (5GB)**: Application logs **Mount points:** + - `/app/data` → Critical state files (circuit breaker, cache, outputs) - `/app/logs` → Application logs @@ -190,6 +192,7 @@ The service uses **two persistent volumes** to maintain state across pod restart **Sensitive credentials** → `Secret` (generated from `config.secret.yaml`) This separation provides: + - ✅ Easy configuration updates without rebuilding images - ✅ Secure credential management with base64 encoding - ✅ Clear separation of concerns @@ -197,10 +200,12 @@ This separation provides: ### Resource Allocation **Requests (guaranteed):** + - CPU: 250m (0.25 cores) - Memory: 512M **Limits (maximum):** + - CPU: 1000m (1.0 core) - Memory: 1G @@ -217,7 +222,7 @@ With persistent volumes, the service maintains: The deployment uses **file-based health checks** (same as docker-compose): -**Liveness probe:** Checks `/app/healthcheck` file modification time +**Liveness probe:** Checks `/app/healthcheck` file modification time **Readiness probe:** Verifies `/app/healthcheck` file exists ## Troubleshooting @@ -226,11 +231,11 @@ The deployment uses **file-based health checks** (same as docker-compose): ```bash # Check events -kubectl describe pod -l app=service-quality-oracle +kubectl describe pod -l app=rewards-eligibility-oracle # Common issues: # - Missing secrets -# - PVC provisioning failures +# - PVC provisioning failures # - Image pull errors ``` @@ -241,28 +246,28 @@ kubectl describe pod -l app=service-quality-oracle kubectl get pvc # Check if volumes are mounted correctly -kubectl exec -it deployment/service-quality-oracle -- ls -la /app/data +kubectl exec -it deployment/rewards-eligibility-oracle -- ls -la /app/data ``` ### Debug Configuration ```bash # Check environment variables -kubectl exec -it deployment/service-quality-oracle -- env | grep -E "(BIGQUERY|BLOCKCHAIN)" +kubectl exec -it deployment/rewards-eligibility-oracle -- env | grep -E "(BIGQUERY|BLOCKCHAIN)" # Verify secrets are mounted -kubectl exec -it deployment/service-quality-oracle -- ls -la /etc/secrets +kubectl exec -it deployment/rewards-eligibility-oracle -- ls -la /etc/secrets ``` ## Security -✅ **Never commit actual secrets** - `config.secret.yaml` files contain placeholders only -✅ **Mainnet deployment safety checks** for production secrets -✅ **Non-root containers** with dropped capabilities -✅ **Service account** with minimal BigQuery permissions -✅ **Private key** stored in Kubernetes secrets (base64 encoded) -✅ **Resource limits** prevent resource exhaustion -✅ **Workload Identity** configured for secure GCP access +✅ **Never commit actual secrets** - `config.secret.yaml` files contain placeholders only +✅ **Mainnet deployment safety checks** for production secrets +✅ **Non-root containers** with dropped capabilities +✅ **Service account** with minimal BigQuery permissions +✅ **Private key** stored in Kubernetes secrets (base64 encoded) +✅ **Resource limits** prevent resource exhaustion +✅ **Workload Identity** configured for secure GCP access ✅ **SSD storage with retention** for data persistence ## Production Considerations diff --git a/k8s/base/deployment.yaml b/k8s/base/deployment.yaml index c6f9c63..9422c99 100644 --- a/k8s/base/deployment.yaml +++ b/k8s/base/deployment.yaml @@ -1,18 +1,18 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: service-quality-oracle + name: rewards-eligibility-oracle labels: - app: service-quality-oracle + app: rewards-eligibility-oracle spec: replicas: 1 # Single instance due to state management selector: matchLabels: - app: service-quality-oracle + app: rewards-eligibility-oracle template: metadata: labels: - app: service-quality-oracle + app: rewards-eligibility-oracle annotations: prometheus.io/scrape: "true" prometheus.io/path: "/metrics" @@ -21,8 +21,8 @@ spec: imagePullSecrets: - name: docker-registry containers: - - name: service-quality-oracle - image: ghcr.io/graphprotocol/service-quality-oracle:latest + - name: rewards-eligibility-oracle + image: ghcr.io/graphprotocol/rewards-eligibility-oracle:latest imagePullPolicy: IfNotPresent ports: - containerPort: 8000 @@ -30,43 +30,43 @@ spec: envFrom: # Load all non-sensitive configuration from ConfigMap - configMapRef: - name: service-quality-oracle-config + name: rewards-eligibility-oracle-config env: # Secrets from Kubernetes Secret - name: GOOGLE_APPLICATION_CREDENTIALS valueFrom: secretKeyRef: - name: service-quality-oracle-secrets + name: rewards-eligibility-oracle-secrets key: google-credentials - name: BLOCKCHAIN_PRIVATE_KEY valueFrom: secretKeyRef: - name: service-quality-oracle-secrets + name: rewards-eligibility-oracle-secrets key: blockchain-private-key - name: ETHERSCAN_API_KEY valueFrom: secretKeyRef: - name: service-quality-oracle-secrets + name: rewards-eligibility-oracle-secrets key: etherscan-api-key - name: ARBITRUM_API_KEY valueFrom: secretKeyRef: - name: service-quality-oracle-secrets + name: rewards-eligibility-oracle-secrets key: arbitrum-api-key - name: STUDIO_API_KEY valueFrom: secretKeyRef: - name: service-quality-oracle-secrets + name: rewards-eligibility-oracle-secrets key: studio-api-key - name: STUDIO_DEPLOY_KEY valueFrom: secretKeyRef: - name: service-quality-oracle-secrets + name: rewards-eligibility-oracle-secrets key: studio-deploy-key - name: SLACK_WEBHOOK_URL valueFrom: secretKeyRef: - name: service-quality-oracle-secrets + name: rewards-eligibility-oracle-secrets key: slack-webhook-url volumeMounts: - name: data-volume @@ -78,7 +78,7 @@ spec: memory: "512M" # Match docker-compose reservations cpu: "250m" limits: - memory: "1G" # Match docker-compose limits + memory: "1G" # Match docker-compose limits cpu: "1000m" # Match docker-compose '1.0' cpus # Use file-based healthcheck like docker-compose (not HTTP) livenessProbe: @@ -94,7 +94,7 @@ spec: readinessProbe: exec: command: - - python + - python - -c - "import os; assert os.path.exists('/app/healthcheck'), 'Healthcheck file missing'" initialDelaySeconds: 10 @@ -111,9 +111,9 @@ spec: volumes: - name: data-volume persistentVolumeClaim: - claimName: service-quality-oracle-data + claimName: rewards-eligibility-oracle-data - name: logs-volume persistentVolumeClaim: - claimName: service-quality-oracle-logs - serviceAccountName: service-quality-oracle + claimName: rewards-eligibility-oracle-logs + serviceAccountName: rewards-eligibility-oracle restartPolicy: Always diff --git a/k8s/base/namespace.yaml b/k8s/base/namespace.yaml index f9520de..d316dd9 100644 --- a/k8s/base/namespace.yaml +++ b/k8s/base/namespace.yaml @@ -1,6 +1,6 @@ apiVersion: v1 kind: Namespace metadata: - name: service-quality-oracle + name: rewards-eligibility-oracle labels: - name: service-quality-oracle + name: rewards-eligibility-oracle diff --git a/k8s/base/podmonitor.yaml b/k8s/base/podmonitor.yaml index 537b85d..8814b67 100644 --- a/k8s/base/podmonitor.yaml +++ b/k8s/base/podmonitor.yaml @@ -1,13 +1,13 @@ apiVersion: monitoring.coreos.com/v1 kind: PodMonitor metadata: - name: service-quality-oracle + name: rewards-eligibility-oracle labels: - app: service-quality-oracle + app: rewards-eligibility-oracle spec: selector: matchLabels: - app: service-quality-oracle + app: rewards-eligibility-oracle podMetricsEndpoints: - port: metrics path: /metrics diff --git a/k8s/base/service.yaml b/k8s/base/service.yaml index a9695f8..0907e9a 100644 --- a/k8s/base/service.yaml +++ b/k8s/base/service.yaml @@ -1,12 +1,12 @@ apiVersion: v1 kind: Service metadata: - name: service-quality-oracle + name: rewards-eligibility-oracle labels: - app: service-quality-oracle + app: rewards-eligibility-oracle spec: selector: - app: service-quality-oracle + app: rewards-eligibility-oracle ports: - name: metrics port: 8000 diff --git a/k8s/base/serviceaccount.yaml b/k8s/base/serviceaccount.yaml index 8ea6edf..b0464b1 100644 --- a/k8s/base/serviceaccount.yaml +++ b/k8s/base/serviceaccount.yaml @@ -1,9 +1,9 @@ apiVersion: v1 kind: ServiceAccount metadata: - name: service-quality-oracle + name: rewards-eligibility-oracle labels: - app: service-quality-oracle + app: rewards-eligibility-oracle annotations: - iam.gke.io/gcp-service-account: service-quality-oracle@graph-mainnet.iam.gserviceaccount.com + iam.gke.io/gcp-service-account: rewards-eligibility-oracle@graph-mainnet.iam.gserviceaccount.com automountServiceAccountToken: false diff --git a/k8s/base/servicemonitor.yaml b/k8s/base/servicemonitor.yaml index 4da96ae..4addeac 100644 --- a/k8s/base/servicemonitor.yaml +++ b/k8s/base/servicemonitor.yaml @@ -1,13 +1,13 @@ apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: - name: service-quality-oracle + name: rewards-eligibility-oracle labels: - app: service-quality-oracle + app: rewards-eligibility-oracle spec: selector: matchLabels: - app: service-quality-oracle + app: rewards-eligibility-oracle endpoints: - port: metrics path: /metrics diff --git a/k8s/configmap.yaml b/k8s/configmap.yaml new file mode 100644 index 0000000..036158a --- /dev/null +++ b/k8s/configmap.yaml @@ -0,0 +1,55 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: rewards-eligibility-oracle-config + labels: + app: rewards-eligibility-oracle +data: + # BigQuery Configuration + BIGQUERY_LOCATION_ID: "US" + BIGQUERY_PROJECT_ID: "graph-mainnet" + BIGQUERY_DATASET_ID: "internal_metrics" + BIGQUERY_TABLE_ID: "metrics_indexer_attempts" + BIGQUERY_CURATION_TABLE_ID: "metrics_curator_signals" + BIGQUERY_CURATOR_MAINNET_TABLE_ID: "curator_name_signal_dimensions_daily" + BIGQUERY_CURATOR_ARBITRUM_TABLE_ID: "curator_name_signal_dimensions_arbitrum_daily" + BIGQUERY_SUBGRAPH_LOOKUP_TABLE_ID: "subgraph_version_id_lookup" + BIGQUERY_ANALYSIS_PERIOD_DAYS: "28" + + # Blockchain Configuration (Arbitrum Sepolia) + BLOCKCHAIN_CONTRACT_ADDRESS: "0x6d5550698F930210c3f50efe744bF51C55D791f6" + BLOCKCHAIN_FUNCTION_NAME: "allowIndexers" + BLOCKCHAIN_CHAIN_ID: "421614" + BLOCK_EXPLORER_URL: "https://sepolia.arbiscan.io" + TX_TIMEOUT_SECONDS: "30" + + # RPC Provider URLs (Arbitrum Sepolia) + BLOCKCHAIN_RPC_URL_1: "https://arbitrum-sepolia.drpc.org" + BLOCKCHAIN_RPC_URL_2: "https://sepolia-rollup.arbitrum.io/rpc" + BLOCKCHAIN_RPC_URL_3: "https://api.zan.top/arb-sepolia" + BLOCKCHAIN_RPC_URL_4: "https://arbitrum-sepolia.gateway.tenderly.co" + + # Scheduling Configuration + SCHEDULED_RUN_TIME: "10:00" + + # Subgraph URLs + SUBGRAPH_URL_PRE_PRODUCTION: "https://api.studio.thegraph.com/query/110664/issuance-eligibility-oracle/v0.1.4" + SUBGRAPH_URL_PRODUCTION: "https://gateway.thegraph.com/api/subgraphs/id/" + + # Processing Configuration + BATCH_SIZE: "125" + MAX_AGE_BEFORE_DELETION: "120" + + # Caching Configuration + CACHE_MAX_AGE_MINUTES: "30" + FORCE_BIGQUERY_REFRESH: "false" + + # Eligibility Criteria + MIN_ONLINE_DAYS: "5" + MIN_SUBGRAPHS: "10" + MAX_LATENCY_MS: "5000" + MAX_BLOCKS_BEHIND: "50000" + MIN_CURATION_SIGNAL: "500" + + # Runtime Configuration + RUN_ON_STARTUP: "true" diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml new file mode 100644 index 0000000..ae04d37 --- /dev/null +++ b/k8s/deployment.yaml @@ -0,0 +1,99 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: rewards-eligibility-oracle + labels: + app: rewards-eligibility-oracle +spec: + replicas: 1 # Single instance due to state management + selector: + matchLabels: + app: rewards-eligibility-oracle + template: + metadata: + labels: + app: rewards-eligibility-oracle + spec: + containers: + - name: rewards-eligibility-oracle + image: ghcr.io/graphprotocol/rewards-eligibility-oracle:latest + envFrom: + # Load all non-sensitive configuration from ConfigMap + - configMapRef: + name: rewards-eligibility-oracle-config + env: + # Secrets from Kubernetes Secret + - name: GOOGLE_APPLICATION_CREDENTIALS + valueFrom: + secretKeyRef: + name: rewards-eligibility-oracle-secrets + key: google-credentials + - name: BLOCKCHAIN_PRIVATE_KEY + valueFrom: + secretKeyRef: + name: rewards-eligibility-oracle-secrets + key: blockchain-private-key + - name: ETHERSCAN_API_KEY + valueFrom: + secretKeyRef: + name: rewards-eligibility-oracle-secrets + key: etherscan-api-key + - name: ARBITRUM_API_KEY + valueFrom: + secretKeyRef: + name: rewards-eligibility-oracle-secrets + key: arbitrum-api-key + - name: STUDIO_API_KEY + valueFrom: + secretKeyRef: + name: rewards-eligibility-oracle-secrets + key: studio-api-key + - name: STUDIO_DEPLOY_KEY + valueFrom: + secretKeyRef: + name: rewards-eligibility-oracle-secrets + key: studio-deploy-key + - name: SLACK_WEBHOOK_URL + valueFrom: + secretKeyRef: + name: rewards-eligibility-oracle-secrets + key: slack-webhook-url + volumeMounts: + - name: data-volume + mountPath: /app/data + - name: logs-volume + mountPath: /app/logs + resources: + requests: + memory: "512M" # Match docker-compose reservations + cpu: "250m" + limits: + memory: "1G" # Match docker-compose limits + cpu: "1000m" # Match docker-compose '1.0' cpus + # Use file-based healthcheck like docker-compose (not HTTP) + livenessProbe: + exec: + command: + - python + - -c + - "import os, time; assert os.path.exists('/app/healthcheck') and time.time() - os.path.getmtime('/app/healthcheck') < 300, 'Healthcheck failed'" + initialDelaySeconds: 60 # Match docker-compose start_period + periodSeconds: 120 # Match docker-compose interval (5m -> 300s, but use 2m for faster detection) + timeoutSeconds: 30 # Match docker-compose timeout + failureThreshold: 3 # Match docker-compose retries + readinessProbe: + exec: + command: + - python + - -c + - "import os; assert os.path.exists('/app/healthcheck'), 'Healthcheck file missing'" + initialDelaySeconds: 10 + periodSeconds: 30 + volumes: + - name: data-volume + persistentVolumeClaim: + claimName: rewards-eligibility-oracle-data + - name: logs-volume + persistentVolumeClaim: + claimName: rewards-eligibility-oracle-logs + restartPolicy: Always diff --git a/k8s/environments/mainnet/apply.sh b/k8s/environments/mainnet/apply.sh index 9a9522a..ed9467d 100755 --- a/k8s/environments/mainnet/apply.sh +++ b/k8s/environments/mainnet/apply.sh @@ -2,8 +2,8 @@ set -e -# Apply Kubernetes manifests for service-quality-oracle (mainnet) -echo "Applying service-quality-oracle mainnet manifests..." +# Apply Kubernetes manifests for rewards-eligibility-oracle (mainnet) +echo "Applying rewards-eligibility-oracle mainnet manifests..." # Ensure we're authenticated to the correct cluster echo "Authenticating to cluster..." @@ -28,5 +28,5 @@ kubectl apply -k . echo "All mainnet manifests applied successfully!" echo "" echo "To check status:" -echo " kubectl get all -n service-quality-oracle" -echo " kubectl logs -f deployment/service-quality-oracle -n service-quality-oracle" +echo " kubectl get all -n rewards-eligibility-oracle" +echo " kubectl logs -f deployment/rewards-eligibility-oracle -n rewards-eligibility-oracle" diff --git a/k8s/environments/mainnet/auth.sh b/k8s/environments/mainnet/auth.sh index d1dce12..e3ab19b 100755 --- a/k8s/environments/mainnet/auth.sh +++ b/k8s/environments/mainnet/auth.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Get cluster credentials for service-quality-oracle deployment +# Get cluster credentials for rewards-eligibility-oracle deployment # Update the following values based on your GKE cluster configuration: # - PROJECT: Your GCP project ID # - CLUSTER: Your GKE cluster name diff --git a/k8s/environments/mainnet/config.secret.yaml b/k8s/environments/mainnet/config.secret.yaml index b5f457b..10219de 100644 --- a/k8s/environments/mainnet/config.secret.yaml +++ b/k8s/environments/mainnet/config.secret.yaml @@ -1,5 +1,5 @@ # Mainnet Secrets for Service Quality Oracle# IMPORTANT: This is a TEMPLATE file - DO NOT commit actual secrets! -# +# # Usage: # 1. Replace all placeholder values with your actual mainnet secrets # 2. This file is used by kustomize secretGenerator @@ -15,12 +15,12 @@ "project_id": "graph-mainnet", "private_key_id": "your-key-id-here", "private_key": "-----BEGIN PRIVATE KEY-----\nYOUR-PRIVATE-KEY-CONTENT-HERE\n-----END PRIVATE KEY-----\n", - "client_email": "service-quality-oracle@graph-mainnet.iam.gserviceaccount.com", + "client_email": "rewards-eligibility-oracle@graph-mainnet.iam.gserviceaccount.com", "client_id": "your-client-id-here", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", - "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/service-quality-oracle%40graph-mainnet.iam.gserviceaccount.com" + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/rewards-eligibility-oracle%40graph-mainnet.iam.gserviceaccount.com" } # Blockchain private key for Arbitrum Sepolia transactions (without 0x prefix) diff --git a/k8s/environments/mainnet/diff.sh b/k8s/environments/mainnet/diff.sh index 6ae6dcf..5227232 100755 --- a/k8s/environments/mainnet/diff.sh +++ b/k8s/environments/mainnet/diff.sh @@ -3,7 +3,7 @@ set -e # Show diff of what would change when applying manifests (mainnet) -echo "Showing diff for service-quality-oracle mainnet manifests..." +echo "Showing diff for rewards-eligibility-oracle mainnet manifests..." # Ensure we're authenticated to the correct cluster echo "Authenticating to cluster..." diff --git a/k8s/environments/mainnet/kustomization.yaml b/k8s/environments/mainnet/kustomization.yaml index 5a85fc8..86837e8 100644 --- a/k8s/environments/mainnet/kustomization.yaml +++ b/k8s/environments/mainnet/kustomization.yaml @@ -1,25 +1,25 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization -namespace: service-quality-oracle +namespace: rewards-eligibility-oracle resources: - ../../base - persistent-volume-claim.yaml secretGenerator: - - name: service-quality-oracle-secrets + - name: rewards-eligibility-oracle-secrets files: - config.secret.yaml configMapGenerator: - - name: service-quality-oracle-config + - name: rewards-eligibility-oracle-config files: - config.yaml images: - - name: ghcr.io/graphprotocol/service-quality-oracle - newName: ghcr.io/graphprotocol/service-quality-oracle + - name: ghcr.io/graphprotocol/rewards-eligibility-oracle + newName: ghcr.io/graphprotocol/rewards-eligibility-oracle newTag: mainnet-latest commonLabels: diff --git a/k8s/environments/mainnet/persistent-volume-claim.yaml b/k8s/environments/mainnet/persistent-volume-claim.yaml index 53d4668..18bfc98 100644 --- a/k8s/environments/mainnet/persistent-volume-claim.yaml +++ b/k8s/environments/mainnet/persistent-volume-claim.yaml @@ -1,9 +1,9 @@ apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: service-quality-oracle-data + name: rewards-eligibility-oracle-data labels: - app: service-quality-oracle + app: rewards-eligibility-oracle spec: accessModes: - ReadWriteOnce @@ -16,9 +16,9 @@ spec: apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: service-quality-oracle-logs + name: rewards-eligibility-oracle-logs labels: - app: service-quality-oracle + app: rewards-eligibility-oracle spec: accessModes: - ReadWriteOnce diff --git a/k8s/environments/mainnet/restart-deployments.sh b/k8s/environments/mainnet/restart-deployments.sh index 46b46df..932be32 100755 --- a/k8s/environments/mainnet/restart-deployments.sh +++ b/k8s/environments/mainnet/restart-deployments.sh @@ -2,10 +2,10 @@ set -e -# Restart deployments for service-quality-oracle (mainnet) -echo "Restarting service-quality-oracle mainnet deployment..." +# Restart deployments for rewards-eligibility-oracle (mainnet) +echo "Restarting rewards-eligibility-oracle mainnet deployment..." -kubectl rollout restart deployment/service-quality-oracle -n service-quality-oracle -kubectl rollout status deployment/service-quality-oracle -n service-quality-oracle --timeout=300s +kubectl rollout restart deployment/rewards-eligibility-oracle -n rewards-eligibility-oracle +kubectl rollout status deployment/rewards-eligibility-oracle -n rewards-eligibility-oracle --timeout=300s echo "Mainnet deployment restarted successfully!" diff --git a/k8s/environments/testnet/apply.sh b/k8s/environments/testnet/apply.sh index ee91658..41dbd3e 100755 --- a/k8s/environments/testnet/apply.sh +++ b/k8s/environments/testnet/apply.sh @@ -2,8 +2,8 @@ set -e -# Apply Kubernetes manifests for service-quality-oracle (testnet) -echo "Applying service-quality-oracle testnet manifests..." +# Apply Kubernetes manifests for rewards-eligibility-oracle (testnet) +echo "Applying rewards-eligibility-oracle testnet manifests..." # Ensure we're authenticated to the correct cluster echo "Authenticating to cluster..." @@ -23,5 +23,5 @@ kubectl apply -k . echo "All testnet manifests applied successfully!" echo "" echo "To check status:" -echo " kubectl get all -n service-quality-oracle" -echo " kubectl logs -f deployment/service-quality-oracle -n service-quality-oracle" +echo " kubectl get all -n rewards-eligibility-oracle" +echo " kubectl logs -f deployment/rewards-eligibility-oracle -n rewards-eligibility-oracle" diff --git a/k8s/environments/testnet/auth.sh b/k8s/environments/testnet/auth.sh index acdf61b..76c7eba 100755 --- a/k8s/environments/testnet/auth.sh +++ b/k8s/environments/testnet/auth.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Get cluster credentials for service-quality-oracle deployment +# Get cluster credentials for rewards-eligibility-oracle deployment # Update the following values based on your GKE cluster configuration: # - PROJECT: Your GCP project ID # - CLUSTER: Your GKE cluster name diff --git a/k8s/environments/testnet/config.secret.yaml b/k8s/environments/testnet/config.secret.yaml index 74cd51b..89b92d6 100644 --- a/k8s/environments/testnet/config.secret.yaml +++ b/k8s/environments/testnet/config.secret.yaml @@ -1,6 +1,6 @@ # Testnet Secrets for Service Quality Oracle # IMPORTANT: This is a TEMPLATE file - DO NOT commit actual secrets! -# +# # Usage: # 1. Replace all placeholder values with your actual testnet secrets # 2. This file is used by kustomize secretGenerator @@ -16,12 +16,12 @@ "project_id": "graph-mainnet", "private_key_id": "your-key-id-here", "private_key": "-----BEGIN PRIVATE KEY-----\nYOUR-PRIVATE-KEY-CONTENT-HERE\n-----END PRIVATE KEY-----\n", - "client_email": "service-quality-oracle@graph-mainnet.iam.gserviceaccount.com", + "client_email": "rewards-eligibility-oracle@graph-mainnet.iam.gserviceaccount.com", "client_id": "your-client-id-here", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", - "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/service-quality-oracle%40graph-mainnet.iam.gserviceaccount.com" + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/rewards-eligibility-oracle%40graph-mainnet.iam.gserviceaccount.com" } # Blockchain private key for Arbitrum Sepolia transactions (without 0x prefix) diff --git a/k8s/environments/testnet/diff.sh b/k8s/environments/testnet/diff.sh index bc3cbe1..1314178 100755 --- a/k8s/environments/testnet/diff.sh +++ b/k8s/environments/testnet/diff.sh @@ -3,7 +3,7 @@ set -e # Show diff of what would change when applying manifests (testnet) -echo "Showing diff for service-quality-oracle testnet manifests..." +echo "Showing diff for rewards-eligibility-oracle testnet manifests..." # Ensure we're authenticated to the correct cluster echo "Authenticating to cluster..." diff --git a/k8s/environments/testnet/kustomization.yaml b/k8s/environments/testnet/kustomization.yaml index 646304f..193e906 100644 --- a/k8s/environments/testnet/kustomization.yaml +++ b/k8s/environments/testnet/kustomization.yaml @@ -1,25 +1,25 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization -namespace: service-quality-oracle +namespace: rewards-eligibility-oracle resources: - ../../base - persistent-volume-claim.yaml secretGenerator: - - name: service-quality-oracle-secrets + - name: rewards-eligibility-oracle-secrets files: - config.secret.yaml configMapGenerator: - - name: service-quality-oracle-config + - name: rewards-eligibility-oracle-config files: - config.yaml images: - - name: ghcr.io/graphprotocol/service-quality-oracle - newName: ghcr.io/graphprotocol/service-quality-oracle + - name: ghcr.io/graphprotocol/rewards-eligibility-oracle + newName: ghcr.io/graphprotocol/rewards-eligibility-oracle newTag: testnet-latest commonLabels: diff --git a/k8s/environments/testnet/persistent-volume-claim.yaml b/k8s/environments/testnet/persistent-volume-claim.yaml index 53d4668..18bfc98 100644 --- a/k8s/environments/testnet/persistent-volume-claim.yaml +++ b/k8s/environments/testnet/persistent-volume-claim.yaml @@ -1,9 +1,9 @@ apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: service-quality-oracle-data + name: rewards-eligibility-oracle-data labels: - app: service-quality-oracle + app: rewards-eligibility-oracle spec: accessModes: - ReadWriteOnce @@ -16,9 +16,9 @@ spec: apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: service-quality-oracle-logs + name: rewards-eligibility-oracle-logs labels: - app: service-quality-oracle + app: rewards-eligibility-oracle spec: accessModes: - ReadWriteOnce diff --git a/k8s/environments/testnet/restart-deployments.sh b/k8s/environments/testnet/restart-deployments.sh index 804a40b..16ccfd2 100755 --- a/k8s/environments/testnet/restart-deployments.sh +++ b/k8s/environments/testnet/restart-deployments.sh @@ -2,10 +2,10 @@ set -e -# Restart deployments for service-quality-oracle (testnet) -echo "Restarting service-quality-oracle testnet deployment..." +# Restart deployments for rewards-eligibility-oracle (testnet) +echo "Restarting rewards-eligibility-oracle testnet deployment..." -kubectl rollout restart deployment/service-quality-oracle -n service-quality-oracle -kubectl rollout status deployment/service-quality-oracle -n service-quality-oracle --timeout=300s +kubectl rollout restart deployment/rewards-eligibility-oracle -n rewards-eligibility-oracle +kubectl rollout status deployment/rewards-eligibility-oracle -n rewards-eligibility-oracle --timeout=300s echo "Testnet deployment restarted successfully!" diff --git a/k8s/persistent-volume-claim.yaml b/k8s/persistent-volume-claim.yaml new file mode 100644 index 0000000..593bb71 --- /dev/null +++ b/k8s/persistent-volume-claim.yaml @@ -0,0 +1,40 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: rewards-eligibility-oracle-data + labels: + app: rewards-eligibility-oracle +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi + # Storage class - uncomment and modify based on your cluster: + # storageClassName: "" # Use default storage class (most common) + # storageClassName: "gp2" # AWS EKS + # storageClassName: "standard" # GKE + # storageClassName: "managed-premium" # Azure AKS + # storageClassName: "local-path" # K3s/Rancher + # storageClassName: "hostpath" # Local development + +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: rewards-eligibility-oracle-logs + labels: + app: rewards-eligibility-oracle +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 2Gi + # Storage class - should match the data PVC above + # storageClassName: "" # Use default storage class (most common) + # storageClassName: "gp2" # AWS EKS + # storageClassName: "standard" # GKE + # storageClassName: "managed-premium" # Azure AKS + # storageClassName: "local-path" # K3s/Rancher + # storageClassName: "hostpath" # Local development diff --git a/k8s/restart-deployments.sh b/k8s/restart-deployments.sh new file mode 100644 index 0000000..62843f9 --- /dev/null +++ b/k8s/restart-deployments.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -e + +# Restart deployments for rewards-eligibility-oracle +echo "Restarting rewards-eligibility-oracle deployment..." + +kubectl rollout restart deployment/rewards-eligibility-oracle -n rewards-eligibility-oracle +kubectl rollout status deployment/rewards-eligibility-oracle -n rewards-eligibility-oracle --timeout=300s + +echo "Deployment restarted successfully!" diff --git a/k8s/secrets.yaml.example b/k8s/secrets.yaml.example new file mode 100644 index 0000000..dddcbc4 --- /dev/null +++ b/k8s/secrets.yaml.example @@ -0,0 +1,56 @@ +# Kubernetes Secrets for Service Quality Oracle +# IMPORTANT: This is an EXAMPLE file - DO NOT commit actual secrets! +# +# Usage: +# 1. Copy this file to secrets.yaml +# 2. Replace all placeholder values with your actual secrets +# 3. Apply: kubectl apply -f secrets.yaml +# 4. Add secrets.yaml to .gitignore to prevent accidental commits +# +# Security: Kubernetes automatically base64 encodes stringData values + +apiVersion: v1 +kind: Secret +metadata: + name: rewards-eligibility-oracle-secrets + labels: + app: rewards-eligibility-oracle +type: Opaque +stringData: + # Google Cloud Service Account JSON for BigQuery access + # Create a dedicated service account with BigQuery Data Viewer + Job User roles + # Download JSON key from Google Cloud Console > IAM > Service Accounts + google-credentials: | + { + "type": "service_account", + "project_id": "graph-mainnet", + "private_key_id": "your-key-id-here", + "private_key": "-----BEGIN PRIVATE KEY-----\nYOUR-PRIVATE-KEY-CONTENT-HERE\n-----END PRIVATE KEY-----\n", + "client_email": "rewards-eligibility-oracle@graph-mainnet.iam.gserviceaccount.com", + "client_id": "your-client-id-here", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/rewards-eligibility-oracle%40graph-mainnet.iam.gserviceaccount.com" + } + + # Blockchain private key for Arbitrum Sepolia transactions (without 0x prefix) + # CRITICAL: This key controls blockchain transactions - keep secure + blockchain-private-key: "your-64-character-private-key-here" + + # Etherscan API key for mainnet contract verification (if needed) + # Get from: https://etherscan.io/apis + etherscan-api-key: "your-etherscan-api-key-here" + + # Arbitrum API key for contract verification on Arbitrum networks + # Get from: https://arbiscan.io/apis + arbitrum-api-key: "your-arbitrum-api-key-here" + + # The Graph Studio API credentials + # Get from: https://thegraph.com/studio/apikeys + studio-api-key: "your-studio-api-key-here" + studio-deploy-key: "your-studio-deploy-key-here" + + # Slack webhook URL for operational notifications + # Create webhook: Slack App > Incoming Webhooks > Add New Webhook + slack-webhook-url: "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX" From 220e6e27ac29a3607e2d335a1367b4ece598e96f Mon Sep 17 00:00:00 2001 From: DaMandal0rian Date: Thu, 25 Sep 2025 18:36:02 +0300 Subject: [PATCH 4/4] remove podmonitor --- k8s/base/kustomization.yaml | 1 - k8s/base/podmonitor.yaml | 15 --------------- 2 files changed, 16 deletions(-) delete mode 100644 k8s/base/podmonitor.yaml diff --git a/k8s/base/kustomization.yaml b/k8s/base/kustomization.yaml index 0ea547a..4a729fb 100644 --- a/k8s/base/kustomization.yaml +++ b/k8s/base/kustomization.yaml @@ -7,4 +7,3 @@ resources: - service.yaml - servicemonitor.yaml - serviceaccount.yaml - - podmonitor.yaml diff --git a/k8s/base/podmonitor.yaml b/k8s/base/podmonitor.yaml deleted file mode 100644 index 8814b67..0000000 --- a/k8s/base/podmonitor.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: monitoring.coreos.com/v1 -kind: PodMonitor -metadata: - name: rewards-eligibility-oracle - labels: - app: rewards-eligibility-oracle -spec: - selector: - matchLabels: - app: rewards-eligibility-oracle - podMetricsEndpoints: - - port: metrics - path: /metrics - interval: 30s - scrapeTimeout: 10s