Initial commit
This commit is contained in:
362
manifests/alaska/alaska.yaml
Normal file
362
manifests/alaska/alaska.yaml
Normal file
@@ -0,0 +1,362 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: alaska
|
||||
labels:
|
||||
name: alaska
|
||||
environment: production
|
||||
app.kubernetes.io/name: alaska
|
||||
app.kubernetes.io/managed-by: manuals
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: alaska-config
|
||||
namespace: alaska
|
||||
labels:
|
||||
app.kubernetes.io/name: alaska-config
|
||||
app.kubernetes.io/part-of: alaska
|
||||
data:
|
||||
NATS_URL: "nats://nats.workolik.com:4222"
|
||||
LOG_LEVEL: "info"
|
||||
ALLOWED_ORIGINS: "http://localhost:3001,http://localhost:3000,https://queue.workolik.com,https://console.nearlexpress.com"
|
||||
EXTERNAL_BASE_URL: "https://jupiter.nearle.app"
|
||||
WORKER_CONCURRENCY: "10"
|
||||
RETRY_ATTEMPTS: "5"
|
||||
RETRY_DELAY_SECONDS: "5"
|
||||
NATS_STREAM: "EVENTS"
|
||||
NATS_SUBJECT: "api.>"
|
||||
NATS_CONSUMER: "worker_consumer"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: nats-credentials
|
||||
namespace: alaska
|
||||
labels:
|
||||
app.kubernetes.io/name: nats-credentials
|
||||
app.kubernetes.io/part-of: alaska
|
||||
type: Opaque
|
||||
stringData:
|
||||
username: admin
|
||||
password: package@321#
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: external-endpoint-secrets
|
||||
namespace: alaska
|
||||
labels:
|
||||
app.kubernetes.io/name: external-endpoint-secrets
|
||||
app.kubernetes.io/part-of: alaska
|
||||
type: Opaque
|
||||
stringData:
|
||||
api_key: "" # Add your API key securely
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: deliveries
|
||||
namespace: alaska
|
||||
labels:
|
||||
app.kubernetes.io/name: deliveries
|
||||
app.kubernetes.io/instance: deliveries-primary
|
||||
app.kubernetes.io/part-of: alaska
|
||||
app.kubernetes.io/component: backend
|
||||
spec:
|
||||
serviceName: "deliveries" # Required for StatefulSet
|
||||
replicas: 4
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: deliveries
|
||||
app.kubernetes.io/instance: deliveries-primary
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: deliveries
|
||||
app.kubernetes.io/instance: deliveries-primary
|
||||
app.kubernetes.io/part-of: alaska
|
||||
app.kubernetes.io/component: backend
|
||||
annotations:
|
||||
prometheus.io/scrape: "true"
|
||||
prometheus.io/port: "8000"
|
||||
prometheus.io/path: "/metrics"
|
||||
spec:
|
||||
securityContext:
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
fsGroup: 2000
|
||||
tolerations:
|
||||
- key: dedicated
|
||||
operator: Equal
|
||||
value: apps
|
||||
effect: NoSchedule
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: node-role.workolik/app
|
||||
operator: In
|
||||
values:
|
||||
- "true"
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: app.kubernetes.io/name
|
||||
operator: In
|
||||
values:
|
||||
- deliveries
|
||||
topologyKey: kubernetes.io/hostname
|
||||
topologySpreadConstraints:
|
||||
- maxSkew: 1
|
||||
topologyKey: kubernetes.io/hostname
|
||||
whenUnsatisfiable: ScheduleAnyway
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: deliveries
|
||||
containers:
|
||||
- name: deliveries
|
||||
image: workolik360/alaska:v1.2.0
|
||||
imagePullPolicy: Always
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
ports:
|
||||
- containerPort: 8000
|
||||
name: http
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: alaska-config
|
||||
env:
|
||||
- name: NATS_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nats-credentials
|
||||
key: username
|
||||
- name: NATS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nats-credentials
|
||||
key: password
|
||||
resources:
|
||||
requests:
|
||||
memory: "256Mi"
|
||||
cpu: "200m"
|
||||
limits:
|
||||
memory: "1Gi"
|
||||
cpu: "1000m"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8000
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /ready
|
||||
port: 8000
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: deliveries-service
|
||||
namespace: alaska
|
||||
labels:
|
||||
app.kubernetes.io/name: deliveries
|
||||
app.kubernetes.io/part-of: alaska
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 8000
|
||||
targetPort: 8000
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app.kubernetes.io/name: deliveries
|
||||
app.kubernetes.io/instance: deliveries-primary
|
||||
sessionAffinity: None
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: deliveries-loadbalancer
|
||||
namespace: alaska
|
||||
labels:
|
||||
app.kubernetes.io/name: deliveries
|
||||
app.kubernetes.io/part-of: alaska
|
||||
annotations:
|
||||
# Service health check port for LoadBalancer
|
||||
# service.kubernetes.io/klipper-lb.healthcheck-port: "8201"
|
||||
spec:
|
||||
type: NodePort
|
||||
externalTrafficPolicy: Cluster
|
||||
selector:
|
||||
app.kubernetes.io/name: deliveries
|
||||
app.kubernetes.io/instance: deliveries-primary
|
||||
ports:
|
||||
- name: http
|
||||
port: 8201 # external LB port
|
||||
targetPort: 8000 # API container port
|
||||
nodePort: 30662
|
||||
protocol: TCP
|
||||
- name: https
|
||||
port: 8441 # optional HTTPS passthrough
|
||||
targetPort: 8000
|
||||
protocol: TCP
|
||||
---
|
||||
apiVersion: policy/v1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: deliveries-pdb
|
||||
namespace: alaska
|
||||
labels:
|
||||
app.kubernetes.io/name: deliveries
|
||||
app.kubernetes.io/part-of: alaska
|
||||
spec:
|
||||
minAvailable: 50%
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: deliveries
|
||||
---
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: deliveries-hpa
|
||||
namespace: alaska
|
||||
labels:
|
||||
app.kubernetes.io/name: deliveries
|
||||
app.kubernetes.io/part-of: alaska
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
name: deliveries
|
||||
minReplicas: 4
|
||||
maxReplicas: 20
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 60
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 70
|
||||
---
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: Gateway
|
||||
metadata:
|
||||
name: gateway
|
||||
namespace: alaska
|
||||
labels:
|
||||
app.kubernetes.io/name: gateway
|
||||
app.kubernetes.io/part-of: alaska
|
||||
spec:
|
||||
gatewayClassName: standard
|
||||
listeners:
|
||||
- name: http
|
||||
protocol: HTTP
|
||||
port: 8201
|
||||
allowedRoutes:
|
||||
namespaces:
|
||||
from: All
|
||||
- name: https
|
||||
protocol: HTTPS
|
||||
port: 8441
|
||||
allowedRoutes:
|
||||
namespaces:
|
||||
from: All
|
||||
tls:
|
||||
mode: Terminate
|
||||
certificateRefs:
|
||||
- name: deliveries-tls-cert
|
||||
- name: nearle-http
|
||||
protocol: HTTP
|
||||
port: 8202
|
||||
allowedRoutes:
|
||||
namespaces:
|
||||
from: All
|
||||
- name: nearle-https
|
||||
protocol: HTTPS
|
||||
port: 8442
|
||||
allowedRoutes:
|
||||
namespaces:
|
||||
from: All
|
||||
tls:
|
||||
mode: Terminate
|
||||
certificateRefs:
|
||||
- name: nearle-tls-cert
|
||||
namespace: nearle # Must copy secret to alaska or use ReferenceGrant. For now assume secret is in Alaska or copied.
|
||||
# Actually, simpler: Use 'nearle-tls-cert' but putting secret in alaska namespace is required for cross-namespace ref usually unless ReferenceGrant used.
|
||||
# Let's keep it simple: We will COPY the secret to 'alaska' namespace.
|
||||
---
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: deliveries-route
|
||||
namespace: alaska
|
||||
labels:
|
||||
app.kubernetes.io/name: deliveries-route
|
||||
app.kubernetes.io/part-of: alaska
|
||||
spec:
|
||||
parentRefs:
|
||||
- name: gateway
|
||||
namespace: alaska
|
||||
hostnames:
|
||||
- "queue.workolik.com"
|
||||
rules:
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /live
|
||||
backendRefs:
|
||||
- name: deliveries-service
|
||||
port: 8000
|
||||
weight: 100
|
||||
backendRefs:
|
||||
- name: deliveries-service
|
||||
port: 8000
|
||||
weight: 100
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /live/api/v1/mob/orders
|
||||
backendRefs:
|
||||
- name: fiesta
|
||||
namespace: nearle
|
||||
port: 80
|
||||
weight: 100
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /live/api/v1/web/products
|
||||
backendRefs:
|
||||
- name: fiesta
|
||||
namespace: nearle
|
||||
port: 80
|
||||
weight: 100
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /health
|
||||
backendRefs:
|
||||
- name: deliveries-service
|
||||
port: 8000
|
||||
weight: 100
|
||||
328
manifests/alaska/k8s-dashboard.yaml
Normal file
328
manifests/alaska/k8s-dashboard.yaml
Normal file
@@ -0,0 +1,328 @@
|
||||
# Kubernetes Dashboard - Official Web UI
|
||||
# Deploy with: kubectl apply -f manifests/alaska/k8s-dashboard.yaml
|
||||
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: kubernetes-dashboard
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: admin-user
|
||||
namespace: kubernetes-dashboard
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: admin-user
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: cluster-admin
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: admin-user
|
||||
namespace: kubernetes-dashboard
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: admin-user
|
||||
namespace: kubernetes-dashboard
|
||||
annotations:
|
||||
kubernetes.io/service-account.name: "admin-user"
|
||||
type: kubernetes.io/service-account-token
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: kubernetes-dashboard-admin
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: cluster-admin
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: kubernetes-dashboard
|
||||
namespace: kubernetes-dashboard
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: kubernetes-dashboard
|
||||
namespace: kubernetes-dashboard
|
||||
labels:
|
||||
k8s-app: kubernetes-dashboard
|
||||
spec:
|
||||
replicas: 1
|
||||
revisionHistoryLimit: 10
|
||||
selector:
|
||||
matchLabels:
|
||||
k8s-app: kubernetes-dashboard
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: kubernetes-dashboard
|
||||
spec:
|
||||
containers:
|
||||
- name: kubernetes-dashboard
|
||||
image: kubernetesui/dashboard:v2.7.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 8443
|
||||
protocol: TCP
|
||||
args:
|
||||
- --auto-generate-certificates
|
||||
- --namespace=kubernetes-dashboard
|
||||
- --enable-skip-login
|
||||
- --enable-insecure-login
|
||||
- --insecure-port=9090
|
||||
volumeMounts:
|
||||
- name: kubernetes-dashboard-certs
|
||||
mountPath: /certs
|
||||
- name: tmp-volume
|
||||
mountPath: /tmp
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
runAsUser: 1001
|
||||
runAsGroup: 2001
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
scheme: HTTPS
|
||||
path: /
|
||||
port: 8443
|
||||
initialDelaySeconds: 30
|
||||
timeoutSeconds: 30
|
||||
periodSeconds: 10
|
||||
failureThreshold: 3
|
||||
resources:
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 256Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
volumes:
|
||||
- name: kubernetes-dashboard-certs
|
||||
secret:
|
||||
secretName: kubernetes-dashboard-certs
|
||||
- name: tmp-volume
|
||||
emptyDir: {}
|
||||
serviceAccountName: kubernetes-dashboard
|
||||
nodeSelector:
|
||||
"kubernetes.io/os": linux
|
||||
tolerations:
|
||||
- key: node-role.kubernetes.io/master
|
||||
operator: Exists
|
||||
effect: NoSchedule
|
||||
- key: node-role.kubernetes.io/control-plane
|
||||
operator: Exists
|
||||
effect: NoSchedule
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: kubernetes-dashboard
|
||||
namespace: kubernetes-dashboard
|
||||
labels:
|
||||
k8s-app: kubernetes-dashboard
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 443
|
||||
targetPort: 8443
|
||||
protocol: TCP
|
||||
name: https
|
||||
- port: 9090
|
||||
targetPort: 9090
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
k8s-app: kubernetes-dashboard
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: kubernetes-dashboard
|
||||
namespace: kubernetes-dashboard
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: kubernetes-dashboard
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["*"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: ["apps"]
|
||||
resources: ["*"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: ["networking.k8s.io"]
|
||||
resources: ["*"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: kubernetes-dashboard
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: kubernetes-dashboard
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: kubernetes-dashboard
|
||||
namespace: kubernetes-dashboard
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: kubernetes-dashboard-secrets
|
||||
namespace: kubernetes-dashboard
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["secrets"]
|
||||
verbs: ["get", "update", "create"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: kubernetes-dashboard-secrets
|
||||
namespace: kubernetes-dashboard
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: kubernetes-dashboard-secrets
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: kubernetes-dashboard
|
||||
namespace: kubernetes-dashboard
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: kubernetes-dashboard-certs
|
||||
namespace: kubernetes-dashboard
|
||||
type: Opaque
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: kubernetes-dashboard-csrf
|
||||
namespace: kubernetes-dashboard
|
||||
type: Opaque
|
||||
data:
|
||||
csrf: "" # Will be auto-generated by dashboard
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: dashboard-proxy-config
|
||||
namespace: kubernetes-dashboard
|
||||
data:
|
||||
nginx.conf: |
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
http {
|
||||
upstream k8s_dashboard {
|
||||
server kubernetes-dashboard:443;
|
||||
}
|
||||
server {
|
||||
listen 8083;
|
||||
server_name _;
|
||||
location / {
|
||||
proxy_pass https://k8s_dashboard;
|
||||
proxy_ssl_verify off;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
}
|
||||
}
|
||||
}
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: dashboard-proxy
|
||||
namespace: kubernetes-dashboard
|
||||
labels:
|
||||
app.kubernetes.io/name: dashboard-proxy
|
||||
app.kubernetes.io/part-of: kubernetes-dashboard
|
||||
spec:
|
||||
serviceName: "dashboard-proxy"
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: dashboard-proxy
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: dashboard-proxy
|
||||
app.kubernetes.io/part-of: kubernetes-dashboard
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:alpine
|
||||
ports:
|
||||
- containerPort: 8083
|
||||
volumeMounts:
|
||||
- name: nginx-config
|
||||
mountPath: /etc/nginx/nginx.conf
|
||||
subPath: nginx.conf
|
||||
resources:
|
||||
requests:
|
||||
memory: "64Mi"
|
||||
cpu: "50m"
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "100m"
|
||||
volumes:
|
||||
- name: nginx-config
|
||||
configMap:
|
||||
name: dashboard-proxy-config
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: dashboard-proxy
|
||||
namespace: kubernetes-dashboard
|
||||
labels:
|
||||
app.kubernetes.io/name: dashboard-proxy
|
||||
spec:
|
||||
type: NodePort
|
||||
selector:
|
||||
app.kubernetes.io/name: dashboard-proxy
|
||||
ports:
|
||||
- port: 8083
|
||||
targetPort: 8083
|
||||
nodePort: 30826
|
||||
protocol: TCP
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: dashboard-loadbalancer
|
||||
namespace: kubernetes-dashboard
|
||||
labels:
|
||||
app.kubernetes.io/name: kubernetes-dashboard
|
||||
app.kubernetes.io/component: loadbalancer
|
||||
spec:
|
||||
type: NodePort
|
||||
selector:
|
||||
k8s-app: kubernetes-dashboard
|
||||
ports:
|
||||
- name: http
|
||||
port: 9090
|
||||
targetPort: 9090 # Dashboard HTTP port
|
||||
nodePort: 30827 # Fixed NodePort for nginx proxy
|
||||
protocol: TCP
|
||||
19
manifests/core/core-config.yaml
Normal file
19
manifests/core/core-config.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: core-config
|
||||
namespace: core
|
||||
labels:
|
||||
app.kubernetes.io/name: core-config
|
||||
app.kubernetes.io/part-of: core
|
||||
data:
|
||||
NATS_URL: "nats://66.116.226.161:4222"
|
||||
LOG_LEVEL: "info"
|
||||
ALLOWED_ORIGINS: "http://localhost:3001,http://localhost:3000,https://queue.workolik.com,https://console.nearlexpress.com"
|
||||
EXTERNAL_BASE_URL: "https://jupiter.nearle.app"
|
||||
WORKER_CONCURRENCY: "10"
|
||||
RETRY_ATTEMPTS: "5"
|
||||
RETRY_DELAY_SECONDS: "5"
|
||||
NATS_STREAM: "EVENTS"
|
||||
NATS_SUBJECT: "api.>"
|
||||
NATS_CONSUMER: "worker_consumer"
|
||||
6
manifests/core/core-namespace.yaml
Normal file
6
manifests/core/core-namespace.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: core
|
||||
labels:
|
||||
name: core
|
||||
25
manifests/core/core-secrets.yaml
Normal file
25
manifests/core/core-secrets.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: nats-credentials
|
||||
namespace: core
|
||||
labels:
|
||||
app.kubernetes.io/name: nats-credentials
|
||||
app.kubernetes.io/part-of: core
|
||||
type: Opaque
|
||||
stringData:
|
||||
username: admin
|
||||
password: package@321#
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: external-endpoint-secrets
|
||||
namespace: core
|
||||
labels:
|
||||
app.kubernetes.io/name: external-endpoint-secrets
|
||||
app.kubernetes.io/part-of: core
|
||||
type: Opaque
|
||||
stringData:
|
||||
api_key: "" # Add your API key securely
|
||||
76
manifests/core/ingress-unified.yaml
Normal file
76
manifests/core/ingress-unified.yaml
Normal file
@@ -0,0 +1,76 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: queue-ingress
|
||||
namespace: alaska
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.middlewares: alaska-common-cors@kubernetescrd
|
||||
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||
# Cert resolver if you have it configured globally in Traefik (usually k3s-provided)
|
||||
# traefik.ingress.kubernetes.io/router.tls.certresolver: "letsencrypt"
|
||||
spec:
|
||||
rules:
|
||||
- host: queue.workolik.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: deliveries-service
|
||||
port:
|
||||
number: 8000
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nearle-ingress
|
||||
namespace: nearle
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||
spec:
|
||||
rules:
|
||||
- host: jupiter.nearle.app
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: jupiter-cors-proxy
|
||||
port:
|
||||
number: 80
|
||||
- host: fiesta.nearle.app
|
||||
http:
|
||||
paths:
|
||||
- path: /live/api/v1/mob/orders/createorder
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: fiesta
|
||||
port:
|
||||
number: 8000
|
||||
- path: /live/api/v1/web/products/create
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: fiesta
|
||||
port:
|
||||
number: 8000
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: fiesta
|
||||
port:
|
||||
number: 80
|
||||
- host: atlantis.nearle.app
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: atlantis
|
||||
port:
|
||||
number: 80
|
||||
12
manifests/core/kustomization.yaml
Normal file
12
manifests/core/kustomization.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: core
|
||||
|
||||
resources:
|
||||
- core-namespace.yaml
|
||||
- core-secrets.yaml
|
||||
- core-config.yaml
|
||||
- worker-script.yaml
|
||||
- workers.yaml
|
||||
- worker-pdb.yaml
|
||||
41
manifests/core/traefik-middlewares.yaml
Normal file
41
manifests/core/traefik-middlewares.yaml
Normal file
@@ -0,0 +1,41 @@
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: common-cors
|
||||
namespace: alaska
|
||||
spec:
|
||||
headers:
|
||||
accessControlAllowMethods:
|
||||
- GET
|
||||
- POST
|
||||
- PUT
|
||||
- PATCH
|
||||
- DELETE
|
||||
- OPTIONS
|
||||
accessControlAllowOriginList:
|
||||
- "*"
|
||||
accessControlAllowHeaders:
|
||||
- "*"
|
||||
accessControlMaxAge: 600
|
||||
addVaryHeader: true
|
||||
---
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: common-cors
|
||||
namespace: nearle
|
||||
spec:
|
||||
headers:
|
||||
accessControlAllowMethods:
|
||||
- GET
|
||||
- POST
|
||||
- PUT
|
||||
- PATCH
|
||||
- DELETE
|
||||
- OPTIONS
|
||||
accessControlAllowOriginList:
|
||||
- "*"
|
||||
accessControlAllowHeaders:
|
||||
- "*"
|
||||
accessControlMaxAge: 600
|
||||
addVaryHeader: true
|
||||
13
manifests/core/worker-pdb.yaml
Normal file
13
manifests/core/worker-pdb.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
apiVersion: policy/v1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: worker-pdb
|
||||
namespace: core
|
||||
labels:
|
||||
app.kubernetes.io/name: worker
|
||||
app.kubernetes.io/part-of: core
|
||||
spec:
|
||||
minAvailable: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: worker
|
||||
261
manifests/core/worker-script.yaml
Normal file
261
manifests/core/worker-script.yaml
Normal file
@@ -0,0 +1,261 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: worker-script
|
||||
namespace: core
|
||||
data:
|
||||
worker.py: |
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
NATS Worker - "New Idea" Implementation
|
||||
- Single Domain per Worker (Stream + Consumer)
|
||||
- Persistent HTTP Session (Connection Pooling)
|
||||
- JetStream Native Retries (NAK)
|
||||
- No internal retry loops
|
||||
"""
|
||||
import os
|
||||
import json
|
||||
import asyncio
|
||||
import aiohttp
|
||||
import nats
|
||||
from nats.errors import TimeoutError as NatsTimeoutError
|
||||
from prometheus_client import Counter, Histogram, Gauge, start_http_server
|
||||
import signal
|
||||
import sys
|
||||
from typing import Any, Dict, List, Union, Tuple
|
||||
|
||||
# Prometheus metrics
|
||||
messages_processed = Counter('worker_messages_processed_total', 'Total messages processed', ['status', 'endpoint'])
|
||||
message_duration = Histogram('worker_message_duration_seconds', 'Message processing duration', ['endpoint'])
|
||||
messages_in_flight = Gauge('worker_messages_in_flight', 'Messages currently being processed')
|
||||
|
||||
# Configuration
|
||||
NATS_URL = os.getenv("NATS_URL", "nats://nats-server:4222")
|
||||
NATS_USER = os.getenv("NATS_USER", "admin")
|
||||
NATS_PASSWORD = os.getenv("NATS_PASSWORD", "package@321#")
|
||||
|
||||
# Domain Configuration (Env Vars from Deployment)
|
||||
NATS_STREAM = os.getenv("NATS_STREAM", "ORDERS")
|
||||
NATS_CONSUMER = os.getenv("NATS_CONSUMER", "orders-worker")
|
||||
# Supports comma-separated subjects: "api.v1.orders.*,api.v2.orders.*"
|
||||
FILTER_SUBJECTS = os.getenv("FILTER_SUBJECT", "api.v1.mob.orders.*").split(",")
|
||||
|
||||
WORKER_CONCURRENCY = int(os.getenv("WORKER_CONCURRENCY", "10"))
|
||||
BASE_URL = os.getenv("EXTERNAL_BASE_URL", "https://jupiter.nearle.app")
|
||||
|
||||
# Endpoint mapping is still useful for constructing the target URL
|
||||
ENDPOINT_MAPPING = {
|
||||
"/live/api/v1/deliveries/createdeliveries": f"{BASE_URL}/live/api/v1/deliveries/createdeliveries",
|
||||
"/live/api/v1/deliveries/updatedelivery": f"{BASE_URL}/live/api/v1/deliveries/updatedelivery",
|
||||
"/live/api/v2/partners/createriderlog": f"{BASE_URL}/live/api/v2/partners/createriderlog",
|
||||
"/live/api/v2/deliveries/createdeliverylog": f"{BASE_URL}/live/api/v2/deliveries/createdeliverylog",
|
||||
"/live/api/v2/partners/createbreaklog": f"{BASE_URL}/live/api/v2/partners/createbreaklog",
|
||||
"/live/api/v2/partners/updatebreaklog": f"{BASE_URL}/live/api/v2/partners/updatebreaklog",
|
||||
"/live/api/v1/mob/orders/createorder": f"{BASE_URL}/live/api/v1/mob/orders/createorder",
|
||||
"/live/api/v1/web/products/create": f"{BASE_URL}/live/api/v1/web/products/create",
|
||||
"/live/api/v1/mob/customers/login": f"{BASE_URL}/live/api/v1/mob/customers/login",
|
||||
"/live/api/v1/mob/customers/create": f"{BASE_URL}/live/api/v1/mob/customers/create",
|
||||
}
|
||||
|
||||
# Global State
|
||||
nc = None
|
||||
js = None
|
||||
session: aiohttp.ClientSession = None
|
||||
running = True
|
||||
semaphore = None # Initialized in main
|
||||
|
||||
def signal_handler(sig, frame):
|
||||
global running
|
||||
print("\n?? Shutdown signal received...")
|
||||
running = False
|
||||
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
signal.signal(signal.SIGTERM, signal_handler)
|
||||
|
||||
async def forward_to_external(endpoint: str, payload: dict, api_key: str = None, method: str = "POST") -> tuple[str, Any]:
|
||||
"""
|
||||
Forward to external API using global session.
|
||||
Returns (status_code, response_data).
|
||||
Does NOT retry internally.
|
||||
"""
|
||||
external_url = ENDPOINT_MAPPING.get(endpoint)
|
||||
if not external_url:
|
||||
print(f"?? Unknown endpoint: {endpoint}, dropping.")
|
||||
return "DROP", None
|
||||
|
||||
headers = {"Content-Type": "application/json"}
|
||||
if api_key:
|
||||
headers["Authorization"] = f"Bearer {api_key}"
|
||||
|
||||
data_to_forward = payload.get("data", payload)
|
||||
|
||||
# Payload Normalization for logs
|
||||
if endpoint == "/live/api/v2/deliveries/createdeliverylog":
|
||||
if isinstance(data_to_forward, dict):
|
||||
data_to_forward = [data_to_forward]
|
||||
elif not isinstance(data_to_forward, list):
|
||||
data_to_forward = [data_to_forward]
|
||||
|
||||
http_method = method.upper() if method else "POST"
|
||||
|
||||
try:
|
||||
# We use the global 'session' here
|
||||
async with session.request(
|
||||
method=http_method,
|
||||
url=external_url,
|
||||
json=data_to_forward if http_method != "GET" else None,
|
||||
params=data_to_forward if http_method == "GET" else None,
|
||||
headers=headers,
|
||||
timeout=aiohttp.ClientTimeout(total=30)
|
||||
) as response:
|
||||
|
||||
body = None
|
||||
try:
|
||||
body = await response.json()
|
||||
except:
|
||||
body = await response.text()
|
||||
|
||||
if 200 <= response.status < 300:
|
||||
return "OK", body
|
||||
elif response.status >= 500:
|
||||
print(f"?? Server Error {response.status} from {endpoint}: {body}")
|
||||
return "RETRY", body
|
||||
else:
|
||||
print(f"?? Client Error {response.status} from {endpoint}: {body}")
|
||||
return "DROP", body # 4xx errors should generally not be retried infinitely
|
||||
|
||||
except asyncio.TimeoutError:
|
||||
print(f"?? Timeout calling {endpoint}")
|
||||
return "RETRY", None
|
||||
except Exception as e:
|
||||
print(f"?? Network/Client Error calling {endpoint}: {e}")
|
||||
return "RETRY", None
|
||||
|
||||
async def process_message(msg):
|
||||
async with semaphore:
|
||||
messages_in_flight.inc()
|
||||
start_time = asyncio.get_event_loop().time()
|
||||
endpoint = "unknown"
|
||||
|
||||
try:
|
||||
payload = json.loads(msg.data.decode())
|
||||
endpoint = payload.get("endpoint", payload.get("original_path", "unknown"))
|
||||
http_method = payload.get("method", "POST")
|
||||
|
||||
print(f"?? Processing {endpoint}")
|
||||
|
||||
api_key = os.getenv("EXTERNAL_ENDPOINT_API_KEY", "")
|
||||
|
||||
# Single attempt
|
||||
status, response_data = await forward_to_external(endpoint, payload, api_key, http_method)
|
||||
|
||||
if status == "OK":
|
||||
await msg.ack()
|
||||
messages_processed.labels(status="success", endpoint=endpoint).inc()
|
||||
|
||||
# Request-Reply Logic
|
||||
if msg.reply:
|
||||
reply_payload = json.dumps(response_data) if isinstance(response_data, (dict, list)) else str(response_data)
|
||||
await nc.publish(msg.reply, reply_payload.encode())
|
||||
|
||||
elif status == "DROP":
|
||||
# Unrecoverable error or unknown endpoint
|
||||
await msg.term() # Terminate stops redelivery
|
||||
messages_processed.labels(status="dropped", endpoint=endpoint).inc()
|
||||
|
||||
else: # RETRY
|
||||
# Let JetStream handle backoff
|
||||
await msg.nak(delay=2) # Custom delay before redelivery if desired, or just nak()
|
||||
messages_processed.labels(status="retried", endpoint=endpoint).inc()
|
||||
|
||||
except json.JSONDecodeError:
|
||||
print("?? Invalid JSON, terminating message")
|
||||
await msg.term()
|
||||
except Exception as e:
|
||||
print(f"? Critical Worker Error: {e}")
|
||||
await msg.nak()
|
||||
finally:
|
||||
messages_in_flight.dec()
|
||||
duration = asyncio.get_event_loop().time() - start_time
|
||||
message_duration.labels(endpoint=endpoint).observe(duration)
|
||||
|
||||
async def main():
|
||||
global nc, js, session, semaphore
|
||||
|
||||
print(f"?? Starting Worker for Domain: {NATS_CONSUMER}")
|
||||
print(f"?? Stream: {NATS_STREAM}, Subjects: {FILTER_SUBJECTS}")
|
||||
print(f"?? Concurrency: {WORKER_CONCURRENCY}")
|
||||
|
||||
semaphore = asyncio.Semaphore(WORKER_CONCURRENCY)
|
||||
session = aiohttp.ClientSession()
|
||||
|
||||
try:
|
||||
nc = await nats.connect(
|
||||
servers=[NATS_URL],
|
||||
user=NATS_USER,
|
||||
password=NATS_PASSWORD,
|
||||
reconnect_time_wait=2,
|
||||
max_reconnect_attempts=-1
|
||||
)
|
||||
js = nc.jetstream()
|
||||
print("? Connected to NATS JetStream")
|
||||
|
||||
# Create Pull Subscriptions for each filter subject
|
||||
# All sharing the same Consumer Name ensuring load balancing if multiple pods run this
|
||||
|
||||
subs = []
|
||||
for subject in FILTER_SUBJECTS:
|
||||
subject = subject.strip()
|
||||
if not subject: continue
|
||||
|
||||
# FIX: On WorkQueue streams, we cannot reuse the same durable name for different filters
|
||||
# We append a sanitized version of the subject to ensure uniqueness per filter
|
||||
clean_subject_suffix = subject.replace(".", "_").replace("*", "all").replace(">", "all")
|
||||
durable_name = f"{NATS_CONSUMER}_{clean_subject_suffix}"
|
||||
|
||||
print(f"?? Subscribing to {subject} on durable consumer '{durable_name}'")
|
||||
try:
|
||||
sub = await js.pull_subscribe(
|
||||
subject,
|
||||
durable=durable_name,
|
||||
stream=NATS_STREAM
|
||||
)
|
||||
subs.append(sub)
|
||||
except Exception as e:
|
||||
print(f"? Failed to subscribe to {subject}: {e}")
|
||||
|
||||
if not subs:
|
||||
print("? No active subscriptions!")
|
||||
return
|
||||
|
||||
start_http_server(9090)
|
||||
print("?? Metrics on :9090")
|
||||
|
||||
while running:
|
||||
# Poll all subscriptions
|
||||
for sub in subs:
|
||||
try:
|
||||
# Batch size 10, short timeout to keep loop responsive
|
||||
msgs = await sub.fetch(10, timeout=0.5)
|
||||
for m in msgs:
|
||||
asyncio.create_task(process_message(m))
|
||||
except NatsTimeoutError:
|
||||
pass
|
||||
except Exception as e:
|
||||
print(f"?? Fetch Error: {e}")
|
||||
await asyncio.sleep(1)
|
||||
|
||||
# Small sleep to prevent tight loop if no messages
|
||||
# await asyncio.sleep(0.01)
|
||||
|
||||
except Exception as e:
|
||||
print(f"?? Fatal Error: {e}")
|
||||
finally:
|
||||
if session:
|
||||
await session.close()
|
||||
if nc:
|
||||
await nc.close()
|
||||
print("?? Worker Shutdown")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
129
manifests/core/worker-statefulset.yaml
Normal file
129
manifests/core/worker-statefulset.yaml
Normal file
@@ -0,0 +1,129 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: worker
|
||||
namespace: core
|
||||
labels:
|
||||
app.kubernetes.io/name: worker
|
||||
app.kubernetes.io/instance: worker-primary
|
||||
app.kubernetes.io/part-of: core
|
||||
app.kubernetes.io/component: worker
|
||||
spec:
|
||||
serviceName: "worker" # Required for StatefulSet
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: worker
|
||||
app.kubernetes.io/instance: worker-primary
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: worker
|
||||
app.kubernetes.io/instance: worker-primary
|
||||
app.kubernetes.io/part-of: core
|
||||
app.kubernetes.io/component: worker
|
||||
annotations:
|
||||
prometheus.io/scrape: "true"
|
||||
prometheus.io/port: "9090"
|
||||
prometheus.io/path: "/metrics"
|
||||
spec:
|
||||
securityContext:
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
fsGroup: 2000
|
||||
tolerations:
|
||||
- key: dedicated
|
||||
operator: Equal
|
||||
value: workers
|
||||
effect: NoSchedule
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: node-role.workolik/worker
|
||||
operator: In
|
||||
values:
|
||||
- "true"
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: app.kubernetes.io/name
|
||||
operator: In
|
||||
values:
|
||||
- worker
|
||||
topologyKey: kubernetes.io/hostname
|
||||
topologySpreadConstraints:
|
||||
- maxSkew: 1
|
||||
topologyKey: kubernetes.io/hostname
|
||||
whenUnsatisfiable: ScheduleAnyway
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: worker
|
||||
containers:
|
||||
- name: worker
|
||||
image: workolik360/nats-worker:v1.1.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
ports:
|
||||
- containerPort: 9090
|
||||
name: metrics
|
||||
command: ["python3", "-u", "/scripts/worker.py"]
|
||||
volumeMounts:
|
||||
- name: worker-script-vol
|
||||
mountPath: /scripts
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: core-config
|
||||
env:
|
||||
- name: NATS_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nats-credentials
|
||||
key: username
|
||||
- name: NATS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nats-credentials
|
||||
key: password
|
||||
- name: EXTERNAL_ENDPOINT_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: external-endpoint-secrets
|
||||
key: api_key
|
||||
optional: true
|
||||
resources:
|
||||
requests:
|
||||
memory: "256Mi"
|
||||
cpu: "200m"
|
||||
limits:
|
||||
memory: "512Mi"
|
||||
cpu: "500m"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /metrics
|
||||
port: 9090
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 10
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /metrics
|
||||
port: 9090
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
volumes:
|
||||
- name: worker-script-vol
|
||||
configMap:
|
||||
name: worker-script
|
||||
542
manifests/core/workers.yaml
Normal file
542
manifests/core/workers.yaml
Normal file
@@ -0,0 +1,542 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: worker-orders
|
||||
namespace: core
|
||||
labels:
|
||||
app.kubernetes.io/name: worker-orders
|
||||
app.kubernetes.io/component: worker
|
||||
spec:
|
||||
serviceName: "worker-orders"
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: worker-orders
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: worker-orders
|
||||
app.kubernetes.io/component: worker
|
||||
annotations:
|
||||
prometheus.io/scrape: "true"
|
||||
prometheus.io/port: "9090"
|
||||
prometheus.io/path: "/metrics"
|
||||
spec:
|
||||
tolerations:
|
||||
- key: dedicated
|
||||
operator: Equal
|
||||
value: workers
|
||||
effect: NoSchedule
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: node-role.workolik/worker
|
||||
operator: In
|
||||
values:
|
||||
- "true"
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: app.kubernetes.io/name
|
||||
operator: In
|
||||
values:
|
||||
- worker-orders
|
||||
topologyKey: kubernetes.io/hostname
|
||||
topologySpreadConstraints:
|
||||
- maxSkew: 1
|
||||
topologyKey: kubernetes.io/hostname
|
||||
whenUnsatisfiable: ScheduleAnyway
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: worker-orders
|
||||
containers:
|
||||
- name: worker
|
||||
image: workolik360/nats-worker:v1.1.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
command: ["python3", "-u", "/scripts/worker.py"]
|
||||
volumeMounts:
|
||||
- name: worker-script-vol
|
||||
mountPath: /scripts
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: core-config
|
||||
env:
|
||||
- name: NATS_STREAM
|
||||
value: "ORDERS"
|
||||
- name: NATS_CONSUMER
|
||||
value: "orders-worker"
|
||||
- name: FILTER_SUBJECT
|
||||
value: "api.v1.mob.orders.createorder"
|
||||
- name: WORKER_CONCURRENCY
|
||||
value: "20"
|
||||
- name: NATS_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nats-credentials
|
||||
key: username
|
||||
- name: NATS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nats-credentials
|
||||
key: password
|
||||
- name: EXTERNAL_ENDPOINT_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: external-endpoint-secrets
|
||||
key: api_key
|
||||
optional: true
|
||||
- name: EXTERNAL_BASE_URL
|
||||
value: "http://10.43.229.168"
|
||||
resources:
|
||||
requests:
|
||||
memory: "128Mi"
|
||||
cpu: "100m"
|
||||
limits:
|
||||
memory: "256Mi"
|
||||
cpu: "500m"
|
||||
ports:
|
||||
- containerPort: 9090
|
||||
name: metrics
|
||||
volumes:
|
||||
- name: worker-script-vol
|
||||
configMap:
|
||||
name: worker-script
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: worker-deliveries
|
||||
namespace: core
|
||||
labels:
|
||||
app.kubernetes.io/name: worker-deliveries
|
||||
app.kubernetes.io/component: worker
|
||||
spec:
|
||||
serviceName: "worker-deliveries"
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: worker-deliveries
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: worker-deliveries
|
||||
app.kubernetes.io/component: worker
|
||||
annotations:
|
||||
prometheus.io/scrape: "true"
|
||||
prometheus.io/port: "9090"
|
||||
prometheus.io/path: "/metrics"
|
||||
spec:
|
||||
tolerations:
|
||||
- key: dedicated
|
||||
operator: Equal
|
||||
value: workers
|
||||
effect: NoSchedule
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: node-role.workolik/worker
|
||||
operator: In
|
||||
values:
|
||||
- "true"
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: app.kubernetes.io/name
|
||||
operator: In
|
||||
values:
|
||||
- worker-deliveries
|
||||
topologyKey: kubernetes.io/hostname
|
||||
topologySpreadConstraints:
|
||||
- maxSkew: 1
|
||||
topologyKey: kubernetes.io/hostname
|
||||
whenUnsatisfiable: ScheduleAnyway
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: worker-deliveries
|
||||
containers:
|
||||
- name: worker
|
||||
image: workolik360/nats-worker:v1.1.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
command: ["python3", "-u", "/scripts/worker.py"]
|
||||
volumeMounts:
|
||||
- name: worker-script-vol
|
||||
mountPath: /scripts
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: core-config
|
||||
env:
|
||||
- name: NATS_STREAM
|
||||
value: "DELIVERIES"
|
||||
- name: NATS_CONSUMER
|
||||
value: "deliveries-worker"
|
||||
- name: FILTER_SUBJECT
|
||||
value: "api.v1.deliveries.createdeliveries,api.v1.deliveries.updatedelivery,api.v2.deliveries.createdeliverylog"
|
||||
- name: WORKER_CONCURRENCY
|
||||
value: "10"
|
||||
- name: NATS_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nats-credentials
|
||||
key: username
|
||||
- name: NATS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nats-credentials
|
||||
key: password
|
||||
- name: EXTERNAL_BASE_URL
|
||||
value: "http://10.43.224.63"
|
||||
resources:
|
||||
requests:
|
||||
memory: "128Mi"
|
||||
cpu: "80m"
|
||||
limits:
|
||||
memory: "256Mi"
|
||||
cpu: "400m"
|
||||
ports:
|
||||
- containerPort: 9090
|
||||
name: metrics
|
||||
volumes:
|
||||
- name: worker-script-vol
|
||||
configMap:
|
||||
name: worker-script
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: worker-customers
|
||||
namespace: core
|
||||
labels:
|
||||
app.kubernetes.io/name: worker-customers
|
||||
app.kubernetes.io/component: worker
|
||||
spec:
|
||||
serviceName: "worker-customers"
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: worker-customers
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: worker-customers
|
||||
app.kubernetes.io/component: worker
|
||||
annotations:
|
||||
prometheus.io/scrape: "true"
|
||||
prometheus.io/port: "9090"
|
||||
prometheus.io/path: "/metrics"
|
||||
spec:
|
||||
tolerations:
|
||||
- key: dedicated
|
||||
operator: Equal
|
||||
value: workers
|
||||
effect: NoSchedule
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: node-role.workolik/worker
|
||||
operator: In
|
||||
values:
|
||||
- "true"
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: app.kubernetes.io/name
|
||||
operator: In
|
||||
values:
|
||||
- worker-customers
|
||||
topologyKey: kubernetes.io/hostname
|
||||
topologySpreadConstraints:
|
||||
- maxSkew: 1
|
||||
topologyKey: kubernetes.io/hostname
|
||||
whenUnsatisfiable: ScheduleAnyway
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: worker-customers
|
||||
containers:
|
||||
- name: worker
|
||||
image: workolik360/nats-worker:v1.1.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
command: ["python3", "-u", "/scripts/worker.py"]
|
||||
volumeMounts:
|
||||
- name: worker-script-vol
|
||||
mountPath: /scripts
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: core-config
|
||||
env:
|
||||
- name: NATS_STREAM
|
||||
value: "CUSTOMERS"
|
||||
- name: NATS_CONSUMER
|
||||
value: "customers-worker"
|
||||
- name: FILTER_SUBJECT
|
||||
value: "api.v1.mob.customers.login,api.v1.mob.customers.create"
|
||||
- name: WORKER_CONCURRENCY
|
||||
value: "30"
|
||||
- name: NATS_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nats-credentials
|
||||
key: username
|
||||
- name: NATS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nats-credentials
|
||||
key: password
|
||||
- name: EXTERNAL_ENDPOINT_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: external-endpoint-secrets
|
||||
key: api_key
|
||||
optional: true
|
||||
- name: EXTERNAL_BASE_URL
|
||||
value: "http://10.43.229.168"
|
||||
resources:
|
||||
requests:
|
||||
memory: "128Mi"
|
||||
cpu: "60m"
|
||||
limits:
|
||||
memory: "256Mi"
|
||||
cpu: "300m"
|
||||
ports:
|
||||
- containerPort: 9090
|
||||
name: metrics
|
||||
volumes:
|
||||
- name: worker-script-vol
|
||||
configMap:
|
||||
name: worker-script
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: worker-rider-logs
|
||||
namespace: core
|
||||
labels:
|
||||
app.kubernetes.io/name: worker-rider-logs
|
||||
app.kubernetes.io/component: worker
|
||||
spec:
|
||||
serviceName: "worker-rider-logs"
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: worker-rider-logs
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: worker-rider-logs
|
||||
app.kubernetes.io/component: worker
|
||||
annotations:
|
||||
prometheus.io/scrape: "true"
|
||||
prometheus.io/port: "9090"
|
||||
prometheus.io/path: "/metrics"
|
||||
spec:
|
||||
tolerations:
|
||||
- key: dedicated
|
||||
operator: Equal
|
||||
value: workers
|
||||
effect: NoSchedule
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: node-role.workolik/worker
|
||||
operator: In
|
||||
values:
|
||||
- "true"
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: app.kubernetes.io/name
|
||||
operator: In
|
||||
values:
|
||||
- worker-rider-logs
|
||||
topologyKey: kubernetes.io/hostname
|
||||
topologySpreadConstraints:
|
||||
- maxSkew: 1
|
||||
topologyKey: kubernetes.io/hostname
|
||||
whenUnsatisfiable: ScheduleAnyway
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: worker-rider-logs
|
||||
containers:
|
||||
- name: worker
|
||||
image: workolik360/nats-worker:v1.1.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
command: ["python3", "-u", "/scripts/worker.py"]
|
||||
volumeMounts:
|
||||
- name: worker-script-vol
|
||||
mountPath: /scripts
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: core-config
|
||||
env:
|
||||
- name: NATS_STREAM
|
||||
value: "RIDER"
|
||||
- name: NATS_CONSUMER
|
||||
value: "rider-logs-worker"
|
||||
- name: FILTER_SUBJECT
|
||||
value: "api.v2.partners.createriderlog,api.v2.partners.createbreaklog,api.v2.partners.updatebreaklog"
|
||||
- name: WORKER_CONCURRENCY
|
||||
value: "10"
|
||||
- name: NATS_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nats-credentials
|
||||
key: username
|
||||
- name: NATS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nats-credentials
|
||||
key: password
|
||||
- name: EXTERNAL_ENDPOINT_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: external-endpoint-secrets
|
||||
key: api_key
|
||||
optional: true
|
||||
- name: EXTERNAL_BASE_URL
|
||||
value: "http://10.43.224.63"
|
||||
resources:
|
||||
requests:
|
||||
memory: "128Mi"
|
||||
cpu: "40m"
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "200m"
|
||||
ports:
|
||||
- containerPort: 9090
|
||||
name: metrics
|
||||
volumes:
|
||||
- name: worker-script-vol
|
||||
configMap:
|
||||
name: worker-script
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: worker-products
|
||||
namespace: core
|
||||
labels:
|
||||
app.kubernetes.io/name: worker-products
|
||||
app.kubernetes.io/component: worker
|
||||
spec:
|
||||
serviceName: "worker-products"
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: worker-products
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: worker-products
|
||||
app.kubernetes.io/component: worker
|
||||
annotations:
|
||||
prometheus.io/scrape: "true"
|
||||
prometheus.io/port: "9090"
|
||||
prometheus.io/path: "/metrics"
|
||||
spec:
|
||||
tolerations:
|
||||
- key: dedicated
|
||||
operator: Equal
|
||||
value: workers
|
||||
effect: NoSchedule
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: node-role.workolik/worker
|
||||
operator: In
|
||||
values:
|
||||
- "true"
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: app.kubernetes.io/name
|
||||
operator: In
|
||||
values:
|
||||
- worker-products
|
||||
topologyKey: kubernetes.io/hostname
|
||||
topologySpreadConstraints:
|
||||
- maxSkew: 1
|
||||
topologyKey: kubernetes.io/hostname
|
||||
whenUnsatisfiable: ScheduleAnyway
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: worker-products
|
||||
containers:
|
||||
- name: worker
|
||||
image: workolik360/nats-worker:v1.1.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
command: ["python3", "-u", "/scripts/worker.py"]
|
||||
volumeMounts:
|
||||
- name: worker-script-vol
|
||||
mountPath: /scripts
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: core-config
|
||||
env:
|
||||
- name: NATS_STREAM
|
||||
value: "PRODUCTS"
|
||||
- name: NATS_CONSUMER
|
||||
value: "products-worker"
|
||||
- name: FILTER_SUBJECT
|
||||
value: "api.v1.web.products.create"
|
||||
- name: WORKER_CONCURRENCY
|
||||
value: "5"
|
||||
- name: NATS_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nats-credentials
|
||||
key: username
|
||||
- name: NATS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nats-credentials
|
||||
key: password
|
||||
- name: EXTERNAL_ENDPOINT_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: external-endpoint-secrets
|
||||
key: api_key
|
||||
optional: true
|
||||
- name: EXTERNAL_BASE_URL
|
||||
value: "http://10.43.229.168"
|
||||
resources:
|
||||
requests:
|
||||
memory: "128Mi"
|
||||
cpu: "40m"
|
||||
limits:
|
||||
memory: "256Mi"
|
||||
cpu: "200m"
|
||||
ports:
|
||||
- containerPort: 9090
|
||||
name: metrics
|
||||
volumes:
|
||||
- name: worker-script-vol
|
||||
configMap:
|
||||
name: worker-script
|
||||
13
manifests/doormile/firebase-service-account.json
Normal file
13
manifests/doormile/firebase-service-account.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"type": "service_account",
|
||||
"project_id": "doormile-abee7",
|
||||
"private_key_id": "66e9b8b66fb40961271f095dd924935eff19452b",
|
||||
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDLBD8DlrQwvwo8\ngkW9j/z1+eLPZYAT2TA4xWT1l+i8LV5he8wZ2TjxJT385OGS+zjIVUHQKtvStdDB\no9/0NXnSC6n88puNhQp9xCRjxEU+FLiSnqJGRUzSO4pu+0TuukGsouDII6QhJFNf\ndmtTOMmjV4V+wAOLfbE3qI5kZQ5trqf8wNBPZKxp9fhrqHdP080HUbOs14jiSrHl\n3OYRj0ZhDTsavboV6QTbdJn5ivH19nboFfdzuJrS5ApMhLqIGdoSEqjjQj8t6f6I\nm1RgQMfztIZLRPliA5MyJieEDZZdy5mmDQDnqCP6zFtH+WRVBe9Lo2A7F+Rf1vv4\n8/5FRd3HAgMBAAECggEACmEEsbPGMYnKxa4pT5gpaA/m6xB23EzpvLVGxJGIGfq9\nzQENvbKPyTBMu32eFKwYSpGlRDW0uFCIRCYTIIKNYFItVhu3HSSUlTpuW9VgbtyT\nVRecFziaxVK68JKTAxttmRxYnpLH5NPdGU/OC9qm4F1smz7Iz5xU75ID+Zj7BFtm\nkjZsgU9ALT7ikm205KhjYepc16ZQODIvvGW8vdNwxaxNl+5+RpkXdq+NK3KiAjK4\noqsuvDRRcchHttXU/qhri7f4nT0VBIuMnPDtRWGEaWtgCt4urLFAD4fZE91i1SHe\n7vV0iYdS9lzjrwl3Umzcf4k0pSPN8Sky1ZjN9hvF5QKBgQD+p2NMePwHY4uksA98\nVWT6y6haM+rIGxSsBL06UnCGO4E1gEWd++G5osDNc9hQk29xFg64pyIPKovw/Qez\nZ+gyCySC8KJoC4q740mxqn1EmANHXAvxGUMgPHmeiX+j3i1MwJWG1w7uyLwQ2216\nEgHy6Mqzk3jLUnD8vXf08CAUxQKBgQDMFvrRwRwpqsLR2yHWiu8uWykU276m1mKI\n8saR/iQ+jXQ9NZsgVdOjaV9EIv7jLwzSwEcXHVh9+SB5pnlCOhovGmmiSIdLVr5f\n1XOyWY6n2NzM6tm2RXjWOnwpVviOtdAwVVWXQNwaNbRLMZZkv+0bpOwk7i/ONv2z\n1bNP5pHJGwKBgQCo8LeJxkG9TScZTMwZOjXRxEaeAQ9jTcP7EvHOvV51Twi7S6vj\n0XTAyN6L7qy1V/p41Z9SlV6dHSbV66euN+LtQEMqsyWrTOzvFSyQt4B/fzG9p60s\neAv2WOh+as3JEt6Oqr0IRahcdcN+k3Qfpc6xLgs78zwR91GJ+tCYKK2/2QKBgBNX\nfi/Q0F12jH4c+Wj+w8ot44fRh5ECMlZuQ7lkT4UKHOEMKoZ2+9a5zsiDVIqtU9bJ\nWDNtmYxexuAgkc9f+ElMhIRXwVK3htVIQm29pRJtMAfPnhBzJw+OfWPhlS7ZNkDO\nZY0vHWzyeALEUU99DPiYubSKSkeN2J9pelPxMxHPAoGBAOOTd5XJRQOnFpd0eVwE\nlJ65zeQyT82V1OX/OPLKOcFwzNNKYF0Toto98nLK5rqqAGNUPp0fBMdUi7b76i79\nwve7aEZtCQWbhQsOUXsWocZyr8w5EexYtbxWa6q7jzmJaL/UfagE8pZWUI2k59CN\nRajHiJG83UxGMUN8KbSgv7h7\n-----END PRIVATE KEY-----\n",
|
||||
"client_email": "firebase-adminsdk-fbsvc@doormile-abee7.iam.gserviceaccount.com",
|
||||
"client_id": "108510619961572391178",
|
||||
"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/firebase-adminsdk-fbsvc%40doormile-abee7.iam.gserviceaccount.com",
|
||||
"universe_domain": "googleapis.com"
|
||||
}
|
||||
89
manifests/doormile/miletruth.yaml
Normal file
89
manifests/doormile/miletruth.yaml
Normal file
@@ -0,0 +1,89 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: doormile
|
||||
|
||||
Read 1 file
|
||||
|
||||
Found the critical issue — INTERNAL_API_KEY not set in the manifest means
|
||||
all /internal/* endpoode explicitly rejects empty keys). That plus the NATS_URL duplicate.
|
||||
|
||||
Here's the corrected miletruth.yaml with all missing env vars added. Run
|
||||
this on the server:
|
||||
|
||||
cat > /root/kuberneteh.yaml << 'EOF'
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: doormile
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: doormile
|
||||
namespace: doormile
|
||||
spec:
|
||||
serviceName: "doormile-service"
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: doormile
|
||||
app-group: doormile-api
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: doormile
|
||||
app-group: do
|
||||
spec:
|
||||
containers:
|
||||
- name: doormile
|
||||
image: doormi
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name: ENV
|
||||
value: "production"
|
||||
- name: APP_PORT
|
||||
value: "8081"
|
||||
- name: DB_HO
|
||||
value: "31.97.228.132"
|
||||
- name: DB_PO
|
||||
value: "5433"
|
||||
- name: DB_NA
|
||||
value: "logistics"
|
||||
- name: DB_US
|
||||
value: "admin"
|
||||
- name: DB_PASSWORD
|
||||
value: "Pac
|
||||
- name: REDIS_HOST
|
||||
value: "31.97.228.132"
|
||||
- name: REDIS
|
||||
value: "6379"
|
||||
- name: REDIS_USER
|
||||
value: "adm
|
||||
- name: REDIS_PASSWORD
|
||||
value: "Package@321#"
|
||||
- name: JWT_S
|
||||
value: "DoormileSuperSecretJWTKey2026!"
|
||||
- name: NATS_
|
||||
value: "nats://66.116.226.161:4223"
|
||||
- name: NATS_
|
||||
value: "doormile"
|
||||
- name: NATS_PASSWORD
|
||||
value: "Pac
|
||||
- name: INTERNAL_API_KEY
|
||||
value: "doormile-internal-2024"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: doormile-service
|
||||
namespace: doormile
|
||||
spec:
|
||||
type: NodePort
|
||||
selector:
|
||||
app-group: doormile-api
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8081
|
||||
targetPort: 808
|
||||
nodePort: 30830
|
||||
61
manifests/nearle/atlantis-sts.yaml
Normal file
61
manifests/nearle/atlantis-sts.yaml
Normal file
@@ -0,0 +1,61 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: atlantis
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: atlantis
|
||||
spec:
|
||||
serviceName: "atlantis"
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: atlantis
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: atlantis
|
||||
spec:
|
||||
tolerations:
|
||||
- key: dedicated
|
||||
operator: Equal
|
||||
value: apps
|
||||
effect: NoSchedule
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: node-role.workolik/app
|
||||
operator: In
|
||||
values:
|
||||
- "true"
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: atlantis
|
||||
topologyKey: kubernetes.io/hostname
|
||||
topologySpreadConstraints:
|
||||
- maxSkew: 1
|
||||
topologyKey: kubernetes.io/hostname
|
||||
whenUnsatisfiable: ScheduleAnyway
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: atlantis
|
||||
containers:
|
||||
- name: backend
|
||||
image: nearlecommerce/atlantis:v0.0.41
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
env:
|
||||
- name: PORT
|
||||
value: "3000"
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: nearle-config
|
||||
- secretRef:
|
||||
name: app-secrets
|
||||
16
manifests/nearle/atlantis-svc.yaml
Normal file
16
manifests/nearle/atlantis-svc.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: atlantis
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: atlantis
|
||||
spec:
|
||||
type: NodePort
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 3000
|
||||
nodePort: 30825
|
||||
protocol: TCP
|
||||
selector:
|
||||
app: atlantis
|
||||
514
manifests/nearle/fiesta-gateway.yaml
Normal file
514
manifests/nearle/fiesta-gateway.yaml
Normal file
@@ -0,0 +1,514 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: fiesta-gateway-script
|
||||
namespace: nearle
|
||||
data:
|
||||
app.py: |
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
FastAPI application with multiple endpoints that publish to NATS JetStream
|
||||
Each endpoint corresponds to an external API that workers will forward to
|
||||
"""
|
||||
import os
|
||||
import json
|
||||
import asyncio
|
||||
from fastapi import FastAPI, HTTPException, Request, Body
|
||||
from fastapi.responses import JSONResponse
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
from starlette.requests import Request as StarletteRequest
|
||||
from starlette.responses import Response as StarletteResponse
|
||||
from pydantic import BaseModel
|
||||
import nats
|
||||
import nats.errors
|
||||
|
||||
from prometheus_client import Counter, Histogram, generate_latest, REGISTRY
|
||||
from starlette.responses import Response
|
||||
import uvicorn
|
||||
from typing import Optional, Dict, Any, List, Union
|
||||
|
||||
# Prometheus metrics
|
||||
request_count = Counter('http_requests_total', 'Total HTTP requests', ['method', 'endpoint', 'status'])
|
||||
request_duration = Histogram('http_request_duration_seconds', 'HTTP request duration', ['method', 'endpoint'])
|
||||
|
||||
app = FastAPI(title="NATS Backend API - Multi-Endpoint", version="1.0.0")
|
||||
|
||||
# Custom CORS middleware to ensure headers are always added
|
||||
class CORSHeaderMiddleware(BaseHTTPMiddleware):
|
||||
async def dispatch(self, request: StarletteRequest, call_next):
|
||||
origin = request.headers.get("origin", "*")
|
||||
response = await call_next(request)
|
||||
response.headers["Access-Control-Allow-Origin"] = origin
|
||||
response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, PATCH, DELETE, OPTIONS"
|
||||
response.headers["Access-Control-Allow-Headers"] = "*"
|
||||
response.headers["Access-Control-Allow-Credentials"] = "false"
|
||||
response.headers["Access-Control-Max-Age"] = "600"
|
||||
return response
|
||||
|
||||
# Add custom CORS middleware first
|
||||
app.add_middleware(CORSHeaderMiddleware)
|
||||
|
||||
# Also add FastAPI's CORS middleware as backup
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origin_regex=r".*", # Match all origins
|
||||
allow_credentials=False,
|
||||
allow_methods=["*"], # Allow all HTTP methods
|
||||
allow_headers=["*"], # Allow all headers
|
||||
expose_headers=["*"], # Expose all headers
|
||||
max_age=600,
|
||||
)
|
||||
|
||||
# NATS connection (will be initialized on startup)
|
||||
nc = None
|
||||
js = None
|
||||
|
||||
# Configuration
|
||||
NATS_URL = os.getenv("NATS_URL", "nats://nats-server:4222")
|
||||
NATS_USER = os.getenv("NATS_USER", "admin")
|
||||
NATS_PASSWORD = os.getenv("NATS_PASSWORD", "package@321#")
|
||||
|
||||
# Endpoint to NATS subject mapping
|
||||
ENDPOINT_ROUTES = {
|
||||
"/live/api/v1/deliveries/createdeliveries": "api.v1.deliveries.createdeliveries",
|
||||
"/live/api/v1/deliveries/updatedelivery": "api.v1.deliveries.updatedelivery",
|
||||
"/live/api/v2/partners/createriderlog": "api.v2.partners.createriderlog",
|
||||
"/live/api/v2/deliveries/createdeliverylog": "api.v2.deliveries.createdeliverylog",
|
||||
"/live/api/v2/partners/createbreaklog": "api.v2.partners.createbreaklog",
|
||||
"/live/api/v2/partners/updatebreaklog": "api.v2.partners.updatebreaklog",
|
||||
"/live/api/v1/mob/orders/createorder": "api.v1.mob.orders.createorder",
|
||||
"/live/api/v1/web/products/create": "api.v1.web.products.create",
|
||||
# Customer Endpoints (Sync)
|
||||
"/live/api/v1/mob/customers/login": "api.v1.mob.customers.login",
|
||||
"/live/api/v1/mob/customers/create": "api.v1.mob.customers.create",
|
||||
}
|
||||
|
||||
@app.on_event("startup")
|
||||
async def startup():
|
||||
"""Initialize NATS connection on startup"""
|
||||
global nc, js
|
||||
try:
|
||||
print(f"Connecting to NATS at {NATS_URL}...")
|
||||
nc = await nats.connect(
|
||||
servers=[NATS_URL],
|
||||
user=NATS_USER,
|
||||
password=NATS_PASSWORD,
|
||||
reconnect_time_wait=2,
|
||||
max_reconnect_attempts=10
|
||||
)
|
||||
js = nc.jetstream()
|
||||
print("✅ Connected to NATS JetStream")
|
||||
print(f"✅ Configured {len(ENDPOINT_ROUTES)} endpoint routes")
|
||||
except Exception as e:
|
||||
print(f"❌ Failed to connect to NATS: {e}")
|
||||
raise
|
||||
|
||||
@app.on_event("shutdown")
|
||||
async def shutdown():
|
||||
"""Close NATS connection on shutdown"""
|
||||
global nc
|
||||
if nc:
|
||||
await nc.close()
|
||||
print("NATS connection closed")
|
||||
|
||||
@app.options("/{full_path:path}")
|
||||
async def options_handler(full_path: str, request: Request):
|
||||
"""Handle OPTIONS requests for CORS preflight"""
|
||||
origin = request.headers.get("origin")
|
||||
return JSONResponse(
|
||||
status_code=200,
|
||||
content={},
|
||||
headers={
|
||||
"Access-Control-Allow-Origin": origin if origin else "*",
|
||||
"Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
|
||||
"Access-Control-Allow-Headers": "*",
|
||||
"Access-Control-Allow-Credentials": "false",
|
||||
"Access-Control-Max-Age": "600",
|
||||
}
|
||||
)
|
||||
|
||||
@app.get("/health")
|
||||
async def health():
|
||||
"""Health check endpoint"""
|
||||
return {"status": "healthy", "nats_connected": nc.is_connected if nc else False}
|
||||
|
||||
@app.get("/ready")
|
||||
async def ready():
|
||||
"""Readiness check endpoint"""
|
||||
if nc and nc.is_connected:
|
||||
return {"status": "ready"}
|
||||
raise HTTPException(status_code=503, detail="Not ready")
|
||||
|
||||
async def publish_to_nats(endpoint: str, data: Union[Dict[str, Any], List[Dict[str, Any]]], request_method: str = "POST"):
|
||||
"""Publish message to NATS with endpoint metadata"""
|
||||
payload = {
|
||||
"endpoint": endpoint,
|
||||
"method": request_method,
|
||||
"data": data,
|
||||
"received_at": int(asyncio.get_event_loop().time() * 1000),
|
||||
"original_path": endpoint
|
||||
}
|
||||
|
||||
# Get NATS subject for this endpoint
|
||||
subject = ENDPOINT_ROUTES.get(endpoint, "api.unknown")
|
||||
|
||||
if js:
|
||||
try:
|
||||
ack = await js.publish(subject, json.dumps(payload).encode())
|
||||
return ack.seq
|
||||
except Exception as e:
|
||||
print(f"❌ Failed to publish to NATS: {e}")
|
||||
raise HTTPException(status_code=500, detail=f"Failed to publish message: {str(e)}")
|
||||
else:
|
||||
raise HTTPException(status_code=503, detail="NATS not connected")
|
||||
|
||||
async def publish_request_to_nats(endpoint: str, data: Dict[str, Any], request_method: str = "POST", timeout: int = 10):
|
||||
"""
|
||||
Publish to NATS and WAIT for a reply (Request-Reply pattern).
|
||||
Used for synchronous endpoints like Login.
|
||||
"""
|
||||
payload = {
|
||||
"endpoint": endpoint,
|
||||
"method": request_method,
|
||||
"data": data,
|
||||
"received_at": int(asyncio.get_event_loop().time() * 1000),
|
||||
"original_path": endpoint
|
||||
}
|
||||
|
||||
subject = ENDPOINT_ROUTES.get(endpoint, "api.unknown")
|
||||
|
||||
if not js:
|
||||
raise HTTPException(status_code=503, detail="NATS by connected")
|
||||
|
||||
try:
|
||||
# Create a unique inbox for the reply
|
||||
inbox = nc.new_inbox()
|
||||
|
||||
# Subscribe to the inbox first
|
||||
sub = await nc.subscribe(inbox, max_msgs=1)
|
||||
|
||||
# Publish request with reply inbox
|
||||
# Note: We use js.publish to ensure it goes to the Stream (Queue), but attach a reply subject
|
||||
await js.publish(subject, json.dumps(payload).encode(), reply=inbox)
|
||||
|
||||
# Wait for valid response
|
||||
try:
|
||||
msg = await sub.next_msg(timeout=timeout)
|
||||
response_data = json.loads(msg.data.decode())
|
||||
return response_data
|
||||
except nats.errors.TimeoutError:
|
||||
raise HTTPException(status_code=504, detail="Gateway Timeout: Upstream service did not respond in time")
|
||||
finally:
|
||||
await sub.unsubscribe()
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
print(f"❌ Failed to request from NATS: {e}")
|
||||
raise HTTPException(status_code=500, detail=f"RPC Error: {str(e)}")
|
||||
|
||||
# Endpoint 1: Update Delivery (v1) - External API requires PUT
|
||||
@app.put("/live/api/v1/deliveries/updatedelivery")
|
||||
async def update_delivery_v1(data: Dict[str, Any], request: Request):
|
||||
"""Update Delivery endpoint - forwards to NATS (PUT only, as external API requires PUT)"""
|
||||
start_time = asyncio.get_event_loop().time()
|
||||
endpoint = "/live/api/v1/deliveries/updatedelivery"
|
||||
method = "PUT" # Always use PUT for this endpoint
|
||||
|
||||
try:
|
||||
message_id = await publish_to_nats(endpoint, data, method)
|
||||
duration = asyncio.get_event_loop().time() - start_time
|
||||
request_duration.labels(method="PUT", endpoint=endpoint).observe(duration)
|
||||
request_count.labels(method="PUT", endpoint=endpoint, status="200").inc()
|
||||
|
||||
return JSONResponse(
|
||||
status_code=200,
|
||||
content={"status": "accepted", "message_id": message_id, "endpoint": endpoint}
|
||||
)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
request_count.labels(method="PUT", endpoint=endpoint, status="500").inc()
|
||||
print(f"❌ Error processing {endpoint}: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
# Endpoint: Create Deliveries (v1)
|
||||
@app.post("/live/api/v1/deliveries/createdeliveries")
|
||||
async def create_deliveries_v1(data: Union[Dict[str, Any], List[Dict[str, Any]]], request: Request):
|
||||
"""Create Deliveries endpoint - forwards payload to NATS"""
|
||||
start_time = asyncio.get_event_loop().time()
|
||||
endpoint = "/live/api/v1/deliveries/createdeliveries"
|
||||
method = request.method
|
||||
|
||||
try:
|
||||
message_id = await publish_to_nats(endpoint, data, method)
|
||||
duration = asyncio.get_event_loop().time() - start_time
|
||||
request_duration.labels(method=method, endpoint=endpoint).observe(duration)
|
||||
request_count.labels(method=method, endpoint=endpoint, status="200").inc()
|
||||
|
||||
return JSONResponse(
|
||||
status_code=200,
|
||||
content={"status": "accepted", "message_id": message_id, "endpoint": endpoint}
|
||||
)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
request_count.labels(method=method, endpoint=endpoint, status="500").inc()
|
||||
print(f"❌ Error processing {endpoint}: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
# Endpoint 2: Create Rider Log (v2)
|
||||
@app.post("/live/api/v2/partners/createriderlog")
|
||||
async def create_rider_log_v2(data: Dict[str, Any], request: Request):
|
||||
"""Create Rider Log endpoint - forwards to NATS"""
|
||||
start_time = asyncio.get_event_loop().time()
|
||||
endpoint = "/live/api/v2/partners/createriderlog"
|
||||
method = request.method
|
||||
|
||||
try:
|
||||
message_id = await publish_to_nats(endpoint, data, method)
|
||||
duration = asyncio.get_event_loop().time() - start_time
|
||||
request_duration.labels(method=method, endpoint=endpoint).observe(duration)
|
||||
request_count.labels(method=method, endpoint=endpoint, status="200").inc()
|
||||
|
||||
return JSONResponse(
|
||||
status_code=200,
|
||||
content={"status": "accepted", "message_id": message_id, "endpoint": endpoint}
|
||||
)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
request_count.labels(method=method, endpoint=endpoint, status="500").inc()
|
||||
print(f"❌ Error processing {endpoint}: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
# Endpoint 3: Create Delivery Log (v2)
|
||||
@app.post("/live/api/v2/deliveries/createdeliverylog")
|
||||
async def create_delivery_log_v2(
|
||||
request: Request,
|
||||
data: List[Dict[str, Any]] = Body(
|
||||
...,
|
||||
example=[{
|
||||
"logid": 0,
|
||||
"tenantid": 1,
|
||||
"partnerid": 44,
|
||||
"locationid": 1,
|
||||
"orderheaderid": 123456,
|
||||
"deliveryid": 654321,
|
||||
"userid": 1111,
|
||||
"orderid": "1-20231624",
|
||||
"orderstatus": "active",
|
||||
"starttime": "2025-12-10 17:51:03",
|
||||
"logdate": "2025-12-10 18:14:04",
|
||||
"latitude": "11.0050664",
|
||||
"longitude": "76.9508776"
|
||||
}]
|
||||
)
|
||||
):
|
||||
"""
|
||||
Create Delivery Log endpoint - forwards to NATS.
|
||||
Accepts either a single dict or a list of dicts to align with external API expectations.
|
||||
"""
|
||||
start_time = asyncio.get_event_loop().time()
|
||||
endpoint = "/live/api/v2/deliveries/createdeliverylog"
|
||||
method = request.method
|
||||
|
||||
try:
|
||||
# Expect only a list of dicts
|
||||
if not isinstance(data, list) or not all(isinstance(item, dict) for item in data):
|
||||
raise HTTPException(status_code=422, detail="Body must be a list of objects")
|
||||
|
||||
normalized_data = data
|
||||
|
||||
message_id = await publish_to_nats(endpoint, normalized_data, method)
|
||||
duration = asyncio.get_event_loop().time() - start_time
|
||||
request_duration.labels(method=method, endpoint=endpoint).observe(duration)
|
||||
request_count.labels(method=method, endpoint=endpoint, status="200").inc()
|
||||
|
||||
return JSONResponse(
|
||||
status_code=200,
|
||||
content={"status": "accepted", "message_id": message_id, "endpoint": endpoint}
|
||||
)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
request_count.labels(method=method, endpoint=endpoint, status="500").inc()
|
||||
print(f"❌ Error processing {endpoint}: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
# Endpoint 4: Create Break Rider Log (v2)
|
||||
@app.post("/live/api/v2/partners/createbreaklog")
|
||||
async def create_break_log_v2(data: Dict[str, Any], request: Request):
|
||||
"""Create Break Rider Log endpoint - forwards to NATS"""
|
||||
start_time = asyncio.get_event_loop().time()
|
||||
endpoint = "/live/api/v2/partners/createbreaklog"
|
||||
method = request.method
|
||||
|
||||
try:
|
||||
message_id = await publish_to_nats(endpoint, data, method)
|
||||
duration = asyncio.get_event_loop().time() - start_time
|
||||
request_duration.labels(method=method, endpoint=endpoint).observe(duration)
|
||||
request_count.labels(method=method, endpoint=endpoint, status="200").inc()
|
||||
|
||||
return JSONResponse(
|
||||
status_code=200,
|
||||
content={"status": "accepted", "message_id": message_id, "endpoint": endpoint}
|
||||
)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
request_count.labels(method=method, endpoint=endpoint, status="500").inc()
|
||||
print(f"❌ Error processing {endpoint}: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
# Endpoint 5: Update Break Rider Log (v2) - Supports both POST and PUT
|
||||
@app.post("/live/api/v2/partners/updatebreaklog")
|
||||
@app.put("/live/api/v2/partners/updatebreaklog")
|
||||
async def update_break_log_v2(data: Dict[str, Any], request: Request):
|
||||
"""Update Break Rider Log endpoint - forwards to NATS"""
|
||||
start_time = asyncio.get_event_loop().time()
|
||||
endpoint = "/live/api/v2/partners/updatebreaklog"
|
||||
method = request.method # Will be POST or PUT
|
||||
|
||||
try:
|
||||
message_id = await publish_to_nats(endpoint, data, method)
|
||||
duration = asyncio.get_event_loop().time() - start_time
|
||||
request_duration.labels(method=method, endpoint=endpoint).observe(duration)
|
||||
request_count.labels(method=method, endpoint=endpoint, status="200").inc()
|
||||
|
||||
return JSONResponse(
|
||||
status_code=200,
|
||||
content={"status": "accepted", "message_id": message_id, "endpoint": endpoint}
|
||||
)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
request_count.labels(method=method, endpoint=endpoint, status="500").inc()
|
||||
print(f"❌ Error processing {endpoint}: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
@app.get("/metrics")
|
||||
async def metrics():
|
||||
"""Prometheus metrics endpoint"""
|
||||
return Response(content=generate_latest(REGISTRY), media_type="text/plain")
|
||||
|
||||
@app.get("/routes")
|
||||
async def list_routes():
|
||||
"""List all configured routes"""
|
||||
return {
|
||||
"routes": ENDPOINT_ROUTES,
|
||||
"total": len(ENDPOINT_ROUTES)
|
||||
}
|
||||
|
||||
|
||||
# Endpoint 6: Create Order (Mob V1)
|
||||
@app.post("/live/api/v1/mob/orders/createorder")
|
||||
async def create_order_mob_v1(data: Dict[str, Any], request: Request):
|
||||
"""Create Order endpoint (Mobile) - forwards to NATS"""
|
||||
start_time = asyncio.get_event_loop().time()
|
||||
endpoint = "/live/api/v1/mob/orders/createorder"
|
||||
method = request.method
|
||||
|
||||
try:
|
||||
message_id = await publish_to_nats(endpoint, data, method)
|
||||
duration = asyncio.get_event_loop().time() - start_time
|
||||
request_duration.labels(method=method, endpoint=endpoint).observe(duration)
|
||||
request_count.labels(method=method, endpoint=endpoint, status="200").inc()
|
||||
|
||||
return JSONResponse(
|
||||
status_code=200,
|
||||
content={"status": "accepted", "message_id": message_id, "endpoint": endpoint}
|
||||
)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
request_count.labels(method=method, endpoint=endpoint, status="500").inc()
|
||||
print(f"❌ Error processing {endpoint}: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
# Endpoint 7: Create Product (Web V1)
|
||||
@app.post("/live/api/v1/web/products/create")
|
||||
async def create_product_web_v1(data: Dict[str, Any], request: Request):
|
||||
"""Create Product endpoint (Web) - forwards to NATS"""
|
||||
start_time = asyncio.get_event_loop().time()
|
||||
endpoint = "/live/api/v1/web/products/create"
|
||||
method = request.method
|
||||
|
||||
try:
|
||||
message_id = await publish_to_nats(endpoint, data, method)
|
||||
duration = asyncio.get_event_loop().time() - start_time
|
||||
request_duration.labels(method=method, endpoint=endpoint).observe(duration)
|
||||
request_count.labels(method=method, endpoint=endpoint, status="200").inc()
|
||||
|
||||
return JSONResponse(
|
||||
status_code=200,
|
||||
content={"status": "accepted", "message_id": message_id, "endpoint": endpoint}
|
||||
)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
request_count.labels(method=method, endpoint=endpoint, status="500").inc()
|
||||
print(f"❌ Error processing {endpoint}: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
|
||||
# Endpoint 8: Customer Login (Sync Request-Reply)
|
||||
@app.post("/live/api/v1/mob/customers/login")
|
||||
async def customer_login(data: Dict[str, Any], request: Request):
|
||||
"""Customer Login - Waits for response from worker"""
|
||||
start_time = asyncio.get_event_loop().time()
|
||||
endpoint = "/live/api/v1/mob/customers/login"
|
||||
method = request.method
|
||||
|
||||
try:
|
||||
# Wait for reply!
|
||||
response_data = await publish_request_to_nats(endpoint, data, method)
|
||||
|
||||
duration = asyncio.get_event_loop().time() - start_time
|
||||
request_duration.labels(method=method, endpoint=endpoint).observe(duration)
|
||||
request_count.labels(method=method, endpoint=endpoint, status="200").inc()
|
||||
|
||||
# Return the actual backend response
|
||||
return JSONResponse(
|
||||
status_code=200,
|
||||
content=response_data
|
||||
)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
request_count.labels(method=method, endpoint=endpoint, status="500").inc()
|
||||
print(f"❌ Error processing {endpoint}: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
# Endpoint 9: Customer Create (Sync Request-Reply)
|
||||
@app.post("/live/api/v1/mob/customers/create")
|
||||
async def customer_create(data: Dict[str, Any], request: Request):
|
||||
"""Customer Create - Waits for response from worker"""
|
||||
start_time = asyncio.get_event_loop().time()
|
||||
endpoint = "/live/api/v1/mob/customers/create"
|
||||
method = request.method
|
||||
|
||||
try:
|
||||
# Wait for reply!
|
||||
response_data = await publish_request_to_nats(endpoint, data, method)
|
||||
|
||||
duration = asyncio.get_event_loop().time() - start_time
|
||||
request_duration.labels(method=method, endpoint=endpoint).observe(duration)
|
||||
request_count.labels(method=method, endpoint=endpoint, status="200").inc()
|
||||
|
||||
return JSONResponse(
|
||||
status_code=200,
|
||||
content=response_data
|
||||
)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
request_count.labels(method=method, endpoint=endpoint, status="500").inc()
|
||||
print(f"❌ Error processing {endpoint}: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
if __name__ == "__main__":
|
||||
uvicorn.run(app, host="0.0.0.0", port=8000)
|
||||
|
||||
99
manifests/nearle/fiesta-sts.yaml
Normal file
99
manifests/nearle/fiesta-sts.yaml
Normal file
@@ -0,0 +1,99 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: fiesta
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: fiesta
|
||||
spec:
|
||||
serviceName: "fiesta"
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: fiesta
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: fiesta
|
||||
spec:
|
||||
tolerations:
|
||||
- key: dedicated
|
||||
operator: Equal
|
||||
value: apps
|
||||
effect: NoSchedule
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: node-role.workolik/app
|
||||
operator: In
|
||||
values:
|
||||
- "true"
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: fiesta
|
||||
topologyKey: kubernetes.io/hostname
|
||||
topologySpreadConstraints:
|
||||
- maxSkew: 1
|
||||
topologyKey: kubernetes.io/hostname
|
||||
whenUnsatisfiable: ScheduleAnyway
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: fiesta
|
||||
containers:
|
||||
- name: backend
|
||||
image: nearlecommerce/fiesta:v1.3.67
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 1122
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: nearle-config
|
||||
- secretRef:
|
||||
name: app-secrets
|
||||
env:
|
||||
- name: PORT
|
||||
value: "1122"
|
||||
- name: NATS_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nats-credentials
|
||||
key: username
|
||||
- name: NATS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nats-credentials
|
||||
key: password
|
||||
- name: gateway
|
||||
image: workolik360/alaska:v1.2.0
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 8000
|
||||
name: http
|
||||
volumeMounts:
|
||||
- name: gateway-script
|
||||
mountPath: /app/app.py
|
||||
subPath: app.py
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: nearle-config
|
||||
env:
|
||||
- name: NATS_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nats-credentials
|
||||
key: username
|
||||
- name: NATS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nats-credentials
|
||||
key: password
|
||||
volumes:
|
||||
- name: gateway-script
|
||||
configMap:
|
||||
name: fiesta-gateway-script
|
||||
21
manifests/nearle/fiesta-svc.yaml
Normal file
21
manifests/nearle/fiesta-svc.yaml
Normal file
@@ -0,0 +1,21 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: fiesta
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: fiesta
|
||||
spec:
|
||||
type: NodePort
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 1122
|
||||
nodePort: 30823
|
||||
protocol: TCP
|
||||
name: main
|
||||
- port: 8000
|
||||
targetPort: 8000
|
||||
name: gateway
|
||||
protocol: TCP
|
||||
selector:
|
||||
app: fiesta
|
||||
97
manifests/nearle/jupiter-cors-proxy.yaml
Normal file
97
manifests/nearle/jupiter-cors-proxy.yaml
Normal file
@@ -0,0 +1,97 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: jupiter-cors-config
|
||||
namespace: nearle
|
||||
data:
|
||||
nginx.conf: |
|
||||
events {}
|
||||
http {
|
||||
upstream jupiter_backend {
|
||||
server jupiter:80;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
|
||||
location / {
|
||||
proxy_pass http://jupiter_backend;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
add_header 'Access-Control-Allow-Origin' '*' always;
|
||||
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, PATCH, DELETE' always;
|
||||
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With, Accept, Origin, X-Auth-Token' always;
|
||||
|
||||
if ($request_method = 'OPTIONS') {
|
||||
add_header 'Access-Control-Allow-Origin' '*';
|
||||
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, PATCH, DELETE';
|
||||
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With, Accept, Origin, X-Auth-Token';
|
||||
add_header 'Access-Control-Max-Age' 1728000;
|
||||
add_header 'Content-Type' 'text/plain; charset=utf-8';
|
||||
add_header 'Content-Length' 0;
|
||||
return 204;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: jupiter-cors-proxy
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: jupiter-cors-proxy
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: jupiter-cors-proxy
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: jupiter-cors-proxy
|
||||
spec:
|
||||
tolerations:
|
||||
- key: dedicated
|
||||
operator: Equal
|
||||
value: apps
|
||||
effect: NoSchedule
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:alpine
|
||||
ports:
|
||||
- containerPort: 80
|
||||
volumeMounts:
|
||||
- name: nginx-config
|
||||
mountPath: /etc/nginx/nginx.conf
|
||||
subPath: nginx.conf
|
||||
resources:
|
||||
requests:
|
||||
memory: "32Mi"
|
||||
cpu: "10m"
|
||||
limits:
|
||||
memory: "64Mi"
|
||||
cpu: "100m"
|
||||
volumes:
|
||||
- name: nginx-config
|
||||
configMap:
|
||||
name: jupiter-cors-config
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: jupiter-cors-proxy
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: jupiter-cors-proxy
|
||||
spec:
|
||||
selector:
|
||||
app: jupiter-cors-proxy
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
protocol: TCP
|
||||
77
manifests/nearle/jupiter-sts.yaml
Normal file
77
manifests/nearle/jupiter-sts.yaml
Normal file
@@ -0,0 +1,77 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: jupiter
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: jupiter
|
||||
spec:
|
||||
serviceName: "jupiter"
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: jupiter
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: jupiter
|
||||
spec:
|
||||
tolerations:
|
||||
- key: dedicated
|
||||
operator: Equal
|
||||
value: apps
|
||||
effect: NoSchedule
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: node-role.workolik/app
|
||||
operator: In
|
||||
values:
|
||||
- "true"
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: jupiter
|
||||
topologyKey: kubernetes.io/hostname
|
||||
topologySpreadConstraints:
|
||||
- maxSkew: 1
|
||||
topologyKey: kubernetes.io/hostname
|
||||
whenUnsatisfiable: ScheduleAnyway
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: jupiter
|
||||
containers:
|
||||
- name: jupiter
|
||||
image: nearlecommerce/jupiter:v2.7.53
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 1009
|
||||
env:
|
||||
- name: PORT
|
||||
value: "1009"
|
||||
- name: TZ
|
||||
value: "Asia/Kolkata"
|
||||
volumeMounts:
|
||||
- name: tz-config
|
||||
mountPath: /etc/localtime
|
||||
readOnly: true
|
||||
- name: tz-data
|
||||
mountPath: /usr/share/zoneinfo
|
||||
readOnly: true
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: nearle-config
|
||||
- secretRef:
|
||||
name: app-secrets
|
||||
volumes:
|
||||
- name: tz-config
|
||||
hostPath:
|
||||
path: /usr/share/zoneinfo/Asia/Kolkata
|
||||
- name: tz-data
|
||||
hostPath:
|
||||
path: /usr/share/zoneinfo
|
||||
16
manifests/nearle/jupiter-svc.yaml
Normal file
16
manifests/nearle/jupiter-svc.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: jupiter
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: jupiter
|
||||
spec:
|
||||
type: NodePort
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 1009
|
||||
nodePort: 30822
|
||||
protocol: TCP
|
||||
selector:
|
||||
app: jupiter
|
||||
23
manifests/nearle/nearle-app-secrets.yaml
Normal file
23
manifests/nearle/nearle-app-secrets.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: app-secrets
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: fiesta
|
||||
type: Opaque
|
||||
stringData:
|
||||
# The IP of your BigRock Server
|
||||
DATABASE_HOST: "66.116.207.225"
|
||||
DB_HOST: "66.116.207.225"
|
||||
|
||||
# The user we confirmed works
|
||||
DATABASE_USERNAME: "admin"
|
||||
DB_USER: "admin"
|
||||
|
||||
# The password we confirmed works
|
||||
DATABASE_PASSWORD: "Package@123#"
|
||||
DB_PASSWORD: "Package@123#"
|
||||
|
||||
# The rest...
|
||||
JWT_SECRET_KEY: "nearle"
|
||||
99
manifests/nearle/nearle-ariane.yaml
Normal file
99
manifests/nearle/nearle-ariane.yaml
Normal file
@@ -0,0 +1,99 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: ariane
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: ariane
|
||||
spec:
|
||||
serviceName: "ariane"
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: ariane
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: ariane
|
||||
spec:
|
||||
tolerations:
|
||||
- key: dedicated
|
||||
operator: Equal
|
||||
value: apps
|
||||
effect: NoSchedule
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: node-role.workolik/app
|
||||
operator: In
|
||||
values:
|
||||
- "true"
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: ariane
|
||||
topologyKey: kubernetes.io/hostname
|
||||
topologySpreadConstraints:
|
||||
- maxSkew: 1
|
||||
topologyKey: kubernetes.io/hostname
|
||||
whenUnsatisfiable: ScheduleAnyway
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: ariane
|
||||
containers:
|
||||
- name: backend
|
||||
image: nearlecommerce/ariane:v1.0.22
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 1000
|
||||
env:
|
||||
- name: PORT
|
||||
value: "1000"
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: nearle-config
|
||||
- secretRef:
|
||||
name: app-secrets
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: ariane
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: ariane
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 1000
|
||||
protocol: TCP
|
||||
selector:
|
||||
app: ariane
|
||||
---
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: ariane-route
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: ariane
|
||||
spec:
|
||||
parentRefs:
|
||||
- name: gateway
|
||||
namespace: alaska
|
||||
hostnames:
|
||||
- "ariane.nearle.app"
|
||||
rules:
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /
|
||||
backendRefs:
|
||||
- name: ariane
|
||||
port: 80
|
||||
100
manifests/nearle/nearle-atlantis.yaml
Normal file
100
manifests/nearle/nearle-atlantis.yaml
Normal file
@@ -0,0 +1,100 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: atlantis
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: atlantis
|
||||
spec:
|
||||
serviceName: "atlantis"
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: atlantis
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: atlantis
|
||||
spec:
|
||||
tolerations:
|
||||
- key: dedicated
|
||||
operator: Equal
|
||||
value: apps
|
||||
effect: NoSchedule
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: node-role.workolik/app
|
||||
operator: In
|
||||
values:
|
||||
- "true"
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: atlantis
|
||||
topologyKey: kubernetes.io/hostname
|
||||
topologySpreadConstraints:
|
||||
- maxSkew: 1
|
||||
topologyKey: kubernetes.io/hostname
|
||||
whenUnsatisfiable: ScheduleAnyway
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: atlantis
|
||||
containers:
|
||||
- name: backend
|
||||
image: nearlecommerce/atlantis:v0.0.41
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
env:
|
||||
- name: PORT
|
||||
value: "3000"
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: nearle-config
|
||||
- secretRef:
|
||||
name: app-secrets
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: atlantis
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: atlantis
|
||||
spec:
|
||||
type: NodePort
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 3000
|
||||
nodePort: 30825
|
||||
protocol: TCP
|
||||
selector:
|
||||
app: atlantis
|
||||
---
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: atlantis-route
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: atlantis
|
||||
spec:
|
||||
parentRefs:
|
||||
- name: gateway
|
||||
namespace: alaska
|
||||
hostnames:
|
||||
- "atlantis.nearle.app"
|
||||
rules:
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /
|
||||
backendRefs:
|
||||
- name: atlantis
|
||||
port: 80
|
||||
23
manifests/nearle/nearle-config.yaml
Normal file
23
manifests/nearle/nearle-config.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nearle-config
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: fiesta
|
||||
data:
|
||||
NATS_URL: "nats://66.116.226.161:4222"
|
||||
LOG_LEVEL: "info"
|
||||
# The stream is set to ORDERS as per your request
|
||||
NATS_STREAM: "ORDERS"
|
||||
# Base subject pattern - the app likely appends the path to this or uses it as a listener filter
|
||||
NATS_SUBJECT: "api.>"
|
||||
ALLOWED_ORIGINS: "*"
|
||||
ENV: "production"
|
||||
DATABASE_NAME: "nearledb"
|
||||
DB_NAME: "nearledb"
|
||||
DATABASE_PORT: "5432"
|
||||
DB_PORT: "5432"
|
||||
DATABASE_SERVER_HOST: "66.116.207.225"
|
||||
DB_HOST: "66.116.207.225"
|
||||
USER_CONTEXT_KEY: "nearle"
|
||||
157
manifests/nearle/nearle-fiesta.yaml
Normal file
157
manifests/nearle/nearle-fiesta.yaml
Normal file
@@ -0,0 +1,157 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: fiesta
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: fiesta
|
||||
spec:
|
||||
serviceName: "fiesta"
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: fiesta
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: fiesta
|
||||
spec:
|
||||
tolerations:
|
||||
- key: dedicated
|
||||
operator: Equal
|
||||
value: apps
|
||||
effect: NoSchedule
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: node-role.workolik/app
|
||||
operator: In
|
||||
values:
|
||||
- "true"
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: fiesta
|
||||
topologyKey: kubernetes.io/hostname
|
||||
topologySpreadConstraints:
|
||||
- maxSkew: 1
|
||||
topologyKey: kubernetes.io/hostname
|
||||
whenUnsatisfiable: ScheduleAnyway
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: fiesta
|
||||
containers:
|
||||
- name: backend
|
||||
image: nearlecommerce/fiesta:v1.3.50
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 1122
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: nearle-config
|
||||
- secretRef:
|
||||
name: app-secrets
|
||||
env:
|
||||
- name: PORT
|
||||
value: "1122"
|
||||
- name: NATS_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nats-credentials
|
||||
key: username
|
||||
- name: NATS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nats-credentials
|
||||
key: password
|
||||
- name: gateway
|
||||
image: workolik360/alaska:v1.2.0
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 8000
|
||||
name: http
|
||||
volumeMounts:
|
||||
- name: gateway-script
|
||||
mountPath: /app/app.py
|
||||
subPath: app.py
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: nearle-config
|
||||
env:
|
||||
- name: NATS_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nats-credentials
|
||||
key: username
|
||||
- name: NATS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nats-credentials
|
||||
key: password
|
||||
volumes:
|
||||
- name: gateway-script
|
||||
configMap:
|
||||
name: fiesta-gateway-script
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: fiesta
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: fiesta
|
||||
spec:
|
||||
type: NodePort
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 1122
|
||||
nodePort: 30823
|
||||
protocol: TCP
|
||||
name: main
|
||||
- port: 8000
|
||||
targetPort: 8000
|
||||
name: gateway
|
||||
protocol: TCP
|
||||
selector:
|
||||
app: fiesta
|
||||
---
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: fiesta-route
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: fiesta
|
||||
spec:
|
||||
parentRefs:
|
||||
- name: gateway
|
||||
namespace: alaska
|
||||
hostnames:
|
||||
- "fiesta.nearle.app"
|
||||
rules:
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /live/api/v1/mob/orders/createorder
|
||||
backendRefs:
|
||||
- name: fiesta
|
||||
port: 8000
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /live/api/v1/web/products/create
|
||||
backendRefs:
|
||||
- name: fiesta
|
||||
port: 8000
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /
|
||||
backendRefs:
|
||||
- name: fiesta
|
||||
port: 80
|
||||
27
manifests/nearle/nearle-gateway.yaml
Normal file
27
manifests/nearle/nearle-gateway.yaml
Normal file
@@ -0,0 +1,27 @@
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: Gateway
|
||||
metadata:
|
||||
name: gateway
|
||||
namespace: nearle
|
||||
labels:
|
||||
app.kubernetes.io/name: gateway
|
||||
app.kubernetes.io/part-of: nearle
|
||||
spec:
|
||||
gatewayClassName: standard
|
||||
listeners:
|
||||
- name: http
|
||||
protocol: HTTP
|
||||
port: 8202
|
||||
allowedRoutes:
|
||||
namespaces:
|
||||
from: Same
|
||||
- name: https
|
||||
protocol: HTTPS
|
||||
port: 8442
|
||||
allowedRoutes:
|
||||
namespaces:
|
||||
from: Same
|
||||
tls:
|
||||
mode: Terminate
|
||||
certificateRefs:
|
||||
- name: nearle-tls-cert
|
||||
94
manifests/nearle/nearle-jupiter.yaml
Normal file
94
manifests/nearle/nearle-jupiter.yaml
Normal file
@@ -0,0 +1,94 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: jupiter
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: jupiter
|
||||
spec:
|
||||
serviceName: "jupiter"
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: jupiter
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: jupiter
|
||||
spec:
|
||||
tolerations:
|
||||
- key: dedicated
|
||||
operator: Equal
|
||||
value: apps
|
||||
effect: NoSchedule
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: node-role.workolik/app
|
||||
operator: In
|
||||
values:
|
||||
- "true"
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: jupiter
|
||||
topologyKey: kubernetes.io/hostname
|
||||
topologySpreadConstraints:
|
||||
- maxSkew: 1
|
||||
topologyKey: kubernetes.io/hostname
|
||||
whenUnsatisfiable: ScheduleAnyway
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: jupiter
|
||||
containers:
|
||||
- name: jupiter
|
||||
image: nearlecommerce/jupiter:v2.7.31
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 1009
|
||||
env:
|
||||
- name: PORT
|
||||
value: "1009"
|
||||
- name: TZ
|
||||
value: "Asia/Kolkata"
|
||||
volumeMounts:
|
||||
- name: tz-config
|
||||
mountPath: /etc/localtime
|
||||
readOnly: true
|
||||
- name: tz-data
|
||||
mountPath: /usr/share/zoneinfo
|
||||
readOnly: true
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: nearle-config
|
||||
- secretRef:
|
||||
name: app-secrets
|
||||
volumes:
|
||||
- name: tz-config
|
||||
hostPath:
|
||||
path: /usr/share/zoneinfo/Asia/Kolkata
|
||||
- name: tz-data
|
||||
hostPath:
|
||||
path: /usr/share/zoneinfo
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: jupiter
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: jupiter
|
||||
spec:
|
||||
type: NodePort
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 1009
|
||||
nodePort: 30822
|
||||
protocol: TCP
|
||||
selector:
|
||||
app: jupiter
|
||||
6
manifests/nearle/nearle-namespace.yaml
Normal file
6
manifests/nearle/nearle-namespace.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: nearle
|
||||
labels:
|
||||
name: nearle
|
||||
14
manifests/nearle/nearle-reference-grant.yaml
Normal file
14
manifests/nearle/nearle-reference-grant.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
apiVersion: gateway.networking.k8s.io/v1beta1
|
||||
kind: ReferenceGrant
|
||||
metadata:
|
||||
name: allow-alaska-gateway
|
||||
namespace: nearle
|
||||
spec:
|
||||
from:
|
||||
- group: gateway.networking.k8s.io
|
||||
kind: HTTPRoute
|
||||
namespace: alaska
|
||||
to:
|
||||
- group: ""
|
||||
kind: Service
|
||||
name: fiesta
|
||||
11
manifests/nearle/nearle-secrets.yaml
Normal file
11
manifests/nearle/nearle-secrets.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: nats-credentials
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: fiesta
|
||||
type: Opaque
|
||||
stringData:
|
||||
username: admin
|
||||
password: package@321#
|
||||
91
manifests/nearle/nearle-titan.yaml
Normal file
91
manifests/nearle/nearle-titan.yaml
Normal file
@@ -0,0 +1,91 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: titan
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: titan
|
||||
spec:
|
||||
serviceName: "titan"
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: titan
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: titan
|
||||
spec:
|
||||
tolerations:
|
||||
- key: dedicated
|
||||
operator: Equal
|
||||
value: apps
|
||||
effect: NoSchedule
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: node-role.workolik/app
|
||||
operator: In
|
||||
values:
|
||||
- "true"
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: titan
|
||||
topologyKey: kubernetes.io/hostname
|
||||
topologySpreadConstraints:
|
||||
- maxSkew: 1
|
||||
topologyKey: kubernetes.io/hostname
|
||||
whenUnsatisfiable: ScheduleAnyway
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: titan
|
||||
containers:
|
||||
- name: backend
|
||||
image: groomgear/groomgear:v1.0.41
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 1006
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: titan
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: titan
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 1006
|
||||
protocol: TCP
|
||||
selector:
|
||||
app: titan
|
||||
---
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: titan-route
|
||||
namespace: nearle
|
||||
labels:
|
||||
app: titan
|
||||
spec:
|
||||
parentRefs:
|
||||
- name: gateway
|
||||
namespace: alaska
|
||||
hostnames:
|
||||
- "titan.nearle.app"
|
||||
rules:
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /
|
||||
backendRefs:
|
||||
- name: titan
|
||||
port: 80
|
||||
Reference in New Issue
Block a user