blackopsrepl commited on
Commit
f870b34
Β·
1 Parent(s): 2d2ce73

feat(deploy): add kubernetes manifest

Browse files
.pre-commit-config.yaml CHANGED
@@ -3,6 +3,7 @@ repos:
3
  rev: v2.3.0
4
  hooks:
5
  - id: check-yaml
 
6
  - id: end-of-file-fixer
7
  - id: trailing-whitespace
8
 
 
3
  rev: v2.3.0
4
  hooks:
5
  - id: check-yaml
6
+ args: ['--allow-multiple-documents']
7
  - id: end-of-file-fixer
8
  - id: trailing-whitespace
9
 
Makefile CHANGED
@@ -1,4 +1,4 @@
1
- .PHONY: help venv install run test lint format clean setup-secrets
2
 
3
  PYTHON=python
4
  PIP=pip
@@ -15,6 +15,7 @@ help:
15
  @echo " lint Run pre-commit hooks (includes black, yaml, gitleaks)"
16
  @echo " format Format code with black"
17
  @echo " setup-secrets Copy and edit secrets template for local dev"
 
18
  @echo " clean Remove Python cache and virtual environment"
19
 
20
  venv:
@@ -41,6 +42,9 @@ setup-secrets:
41
  cp -n tests/secrets/nebius_secrets.py.template tests/secrets/cred.py; \
42
  echo "Edit tests/secrets/cred.py to add your own API credentials."
43
 
 
 
 
44
  clean:
45
  rm -rf $(VENV) __pycache__ */__pycache__ .pytest_cache .mypy_cache .coverage .hypothesis
46
  find . -type f -name '*.pyc' -delete
 
1
+ .PHONY: help venv install run test lint format clean setup-secrets deploy-k8s
2
 
3
  PYTHON=python
4
  PIP=pip
 
15
  @echo " lint Run pre-commit hooks (includes black, yaml, gitleaks)"
16
  @echo " format Format code with black"
17
  @echo " setup-secrets Copy and edit secrets template for local dev"
18
+ @echo " deploy-k8s Deploy application to Kubernetes"
19
  @echo " clean Remove Python cache and virtual environment"
20
 
21
  venv:
 
42
  cp -n tests/secrets/nebius_secrets.py.template tests/secrets/cred.py; \
43
  echo "Edit tests/secrets/cred.py to add your own API credentials."
44
 
45
+ deploy-k8s:
46
+ ./scripts/deploy-k8s.sh
47
+
48
  clean:
49
  rm -rf $(VENV) __pycache__ */__pycache__ .pytest_cache .mypy_cache .coverage .hypothesis
50
  find . -type f -name '*.pyc' -delete
deploy/kubernetes.yaml ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Kubernetes manifest for Yuga Planner
2
+ # Note: This file contains environment variable placeholders that need to be substituted before deployment
3
+ # Use the provided deploy script or substitute manually: envsubst < kubernetes.yaml | kubectl apply -f -
4
+ ---
5
+ apiVersion: v1
6
+ kind: Secret
7
+ metadata:
8
+ name: yuga-planner-secrets
9
+ labels:
10
+ app: yuga-planner
11
+ type: Opaque
12
+ stringData:
13
+ # These values will be populated from environment variables during deployment
14
+ NEBIUS_API_KEY: "${NEBIUS_API_KEY}"
15
+ NEBIUS_MODEL: "${NEBIUS_MODEL}"
16
+ MODAL_TOKEN_ID: "${MODAL_TOKEN_ID}"
17
+ MODAL_TOKEN_SECRET: "${MODAL_TOKEN_SECRET}"
18
+ HF_MODEL: "${HF_MODEL}"
19
+ HF_TOKEN: "${HF_TOKEN}"
20
+
21
+ ---
22
+ apiVersion: v1
23
+ kind: ConfigMap
24
+ metadata:
25
+ name: yuga-planner-config
26
+ labels:
27
+ app: yuga-planner
28
+ data:
29
+ JAVA_HOME: "/usr/lib/jvm/temurin-21-jdk-amd64"
30
+ PATH: "/usr/lib/jvm/temurin-21-jdk-amd64/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
31
+
32
+ ---
33
+ apiVersion: apps/v1
34
+ kind: Deployment
35
+ metadata:
36
+ name: yuga-planner
37
+ labels:
38
+ app: yuga-planner
39
+ spec:
40
+ replicas: 1
41
+ selector:
42
+ matchLabels:
43
+ app: yuga-planner
44
+ template:
45
+ metadata:
46
+ labels:
47
+ app: yuga-planner
48
+ spec:
49
+ containers:
50
+ - name: yuga-planner
51
+ image: ghcr.io/blackopsrepl/yuga-planner-test:latest
52
+ imagePullPolicy: Always
53
+ ports:
54
+ - containerPort: 7860
55
+ name: http
56
+ protocol: TCP
57
+ env:
58
+ - name: JAVA_HOME
59
+ valueFrom:
60
+ configMapKeyRef:
61
+ name: yuga-planner-config
62
+ key: JAVA_HOME
63
+ - name: PATH
64
+ valueFrom:
65
+ configMapKeyRef:
66
+ name: yuga-planner-config
67
+ key: PATH
68
+ - name: NEBIUS_API_KEY
69
+ valueFrom:
70
+ secretKeyRef:
71
+ name: yuga-planner-secrets
72
+ key: NEBIUS_API_KEY
73
+ - name: NEBIUS_MODEL
74
+ valueFrom:
75
+ secretKeyRef:
76
+ name: yuga-planner-secrets
77
+ key: NEBIUS_MODEL
78
+ - name: MODAL_TOKEN_ID
79
+ valueFrom:
80
+ secretKeyRef:
81
+ name: yuga-planner-secrets
82
+ key: MODAL_TOKEN_ID
83
+ - name: MODAL_TOKEN_SECRET
84
+ valueFrom:
85
+ secretKeyRef:
86
+ name: yuga-planner-secrets
87
+ key: MODAL_TOKEN_SECRET
88
+ - name: HF_MODEL
89
+ valueFrom:
90
+ secretKeyRef:
91
+ name: yuga-planner-secrets
92
+ key: HF_MODEL
93
+ - name: HF_TOKEN
94
+ valueFrom:
95
+ secretKeyRef:
96
+ name: yuga-planner-secrets
97
+ key: HF_TOKEN
98
+ command: ["python", "src/app.py"]
99
+ args:
100
+ - "--server-name"
101
+ - "0.0.0.0"
102
+ - "--server-port"
103
+ - "7860"
104
+ resources:
105
+ requests:
106
+ memory: "512Mi"
107
+ cpu: "250m"
108
+ limits:
109
+ memory: "2Gi"
110
+ cpu: "1000m"
111
+ livenessProbe:
112
+ httpGet:
113
+ path: /
114
+ port: 7860
115
+ initialDelaySeconds: 30
116
+ periodSeconds: 10
117
+ timeoutSeconds: 5
118
+ failureThreshold: 3
119
+ readinessProbe:
120
+ httpGet:
121
+ path: /
122
+ port: 7860
123
+ initialDelaySeconds: 10
124
+ periodSeconds: 5
125
+ timeoutSeconds: 3
126
+ failureThreshold: 3
127
+ securityContext:
128
+ runAsNonRoot: true
129
+ runAsUser: 1000
130
+ runAsGroup: 1000
131
+ allowPrivilegeEscalation: false
132
+ readOnlyRootFilesystem: false
133
+ capabilities:
134
+ drop:
135
+ - ALL
136
+
137
+ ---
138
+ apiVersion: v1
139
+ kind: Service
140
+ metadata:
141
+ name: yuga-planner-service
142
+ labels:
143
+ app: yuga-planner
144
+ spec:
145
+ type: NodePort
146
+ ports:
147
+ - port: 80
148
+ targetPort: 7860
149
+ nodePort: 30860
150
+ protocol: TCP
151
+ name: http
152
+ selector:
153
+ app: yuga-planner
scripts/deploy-k8s.sh ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ # Yuga Planner Kubernetes Deployment Script
5
+ # This script loads credentials from environment variables or creds.py and deploys to Kubernetes
6
+
7
+ echo "πŸš€ Deploying Yuga Planner to Kubernetes..."
8
+
9
+ # Check if we're in the correct directory (project root)
10
+ if [ ! -f "deploy/kubernetes.yaml" ]; then
11
+ echo "❌ Error: kubernetes.yaml not found. Please run this script from the project root."
12
+ exit 1
13
+ fi
14
+
15
+ # Function to load credentials from creds.py if environment variables are not set
16
+ load_credentials() {
17
+ local creds_file="tests/secrets/creds.py"
18
+
19
+ if [ -f "$creds_file" ]; then
20
+ echo "πŸ“‹ Loading credentials from $creds_file..."
21
+
22
+ # Extract credentials from creds.py if environment variables are not set
23
+ if [ -z "$NEBIUS_API_KEY" ]; then
24
+ export NEBIUS_API_KEY=$(python3 -c "
25
+ import sys
26
+ sys.path.append('tests/secrets')
27
+ import creds
28
+ print(creds.NEBIUS_API_KEY)
29
+ " 2>/dev/null || echo "")
30
+ fi
31
+
32
+ if [ -z "$NEBIUS_MODEL" ]; then
33
+ export NEBIUS_MODEL=$(python3 -c "
34
+ import sys
35
+ sys.path.append('tests/secrets')
36
+ import creds
37
+ print(creds.NEBIUS_MODEL)
38
+ " 2>/dev/null || echo "")
39
+ fi
40
+
41
+ if [ -z "$MODAL_TOKEN_ID" ]; then
42
+ export MODAL_TOKEN_ID=$(python3 -c "
43
+ import sys
44
+ sys.path.append('tests/secrets')
45
+ import creds
46
+ print(creds.MODAL_TOKEN_ID)
47
+ " 2>/dev/null || echo "")
48
+ fi
49
+
50
+ if [ -z "$MODAL_TOKEN_SECRET" ]; then
51
+ export MODAL_TOKEN_SECRET=$(python3 -c "
52
+ import sys
53
+ sys.path.append('tests/secrets')
54
+ import creds
55
+ print(creds.MODAL_TOKEN_SECRET)
56
+ " 2>/dev/null || echo "")
57
+ fi
58
+
59
+ if [ -z "$HF_MODEL" ]; then
60
+ export HF_MODEL=$(python3 -c "
61
+ import sys
62
+ sys.path.append('tests/secrets')
63
+ import creds
64
+ print(creds.HF_MODEL)
65
+ " 2>/dev/null || echo "")
66
+ fi
67
+
68
+ if [ -z "$HF_TOKEN" ]; then
69
+ export HF_TOKEN=$(python3 -c "
70
+ import sys
71
+ sys.path.append('tests/secrets')
72
+ import creds
73
+ print(creds.HF_TOKEN)
74
+ " 2>/dev/null || echo "")
75
+ fi
76
+ else
77
+ echo "⚠️ Warning: $creds_file not found"
78
+ fi
79
+ }
80
+
81
+ # Check if credentials are available in environment variables
82
+ echo "πŸ” Checking for credentials..."
83
+
84
+ missing_vars=()
85
+ required_vars=("NEBIUS_API_KEY" "NEBIUS_MODEL" "MODAL_TOKEN_ID" "MODAL_TOKEN_SECRET" "HF_MODEL" "HF_TOKEN")
86
+
87
+ for var in "${required_vars[@]}"; do
88
+ if [ -z "${!var}" ]; then
89
+ missing_vars+=("$var")
90
+ fi
91
+ done
92
+
93
+ if [ ${#missing_vars[@]} -gt 0 ]; then
94
+ echo "πŸ“‚ Missing environment variables: ${missing_vars[*]}"
95
+ echo "πŸ”„ Attempting to load from creds.py..."
96
+ load_credentials
97
+
98
+ # Check again after loading from creds.py
99
+ missing_vars=()
100
+ for var in "${required_vars[@]}"; do
101
+ if [ -z "${!var}" ]; then
102
+ missing_vars+=("$var")
103
+ fi
104
+ done
105
+
106
+ if [ ${#missing_vars[@]} -gt 0 ]; then
107
+ echo "❌ Error: The following required environment variables are not set: ${missing_vars[*]}"
108
+ echo "πŸ’‘ Please set them in your environment or ensure tests/secrets/creds.py exists with the required values."
109
+ exit 1
110
+ fi
111
+ fi
112
+
113
+ echo "βœ… All credentials found"
114
+
115
+ # Check if envsubst is available
116
+ if ! command -v envsubst &> /dev/null; then
117
+ echo "❌ Error: envsubst is required but not installed. Please install gettext-base package."
118
+ exit 1
119
+ fi
120
+
121
+ # Check if kubectl is available
122
+ if ! command -v kubectl &> /dev/null; then
123
+ echo "❌ Error: kubectl is required but not installed."
124
+ exit 1
125
+ fi
126
+
127
+ # Substitute environment variables and apply to Kubernetes
128
+ echo "πŸ”§ Substituting environment variables and deploying..."
129
+ envsubst < deploy/kubernetes.yaml | kubectl apply -f -
130
+
131
+ echo "βœ… Deployment complete!"
132
+ echo "🌐 Access the application at: http://<node-ip>:30860"
133
+ echo "πŸ” Check deployment status: kubectl get pods -l app=yuga-planner"
134
+ echo "πŸ“‹ View logs: kubectl logs -l app=yuga-planner -f"