diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..6e4636d --- /dev/null +++ b/.dockerignore @@ -0,0 +1,37 @@ +# Git +.git +.gitignore + +# IDE +.vscode +.idea +*.swp +*.swo + +# Build +target +*.class +*.jar +*.war + +# Maven +.mvn/wrapper/maven-wrapper.jar +.mvn/wrapper/MavenWrapperDownloader.java + +# OS +.DS_Store +Thumbs.db + +# Docker +Dockerfile +docker-compose.yml +.dockerignore + +# Documentation +README.md +LICENSE +screenshots/ + +# Node/npm (if applicable) +node_modules +npm-debug.log diff --git a/Dockerfile b/Dockerfile index 92c47d4..8e08586 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,22 +1,40 @@ -# Build stage -FROM eclipse-temurin:21-jdk-alpine AS build -WORKDIR /app -COPY . . -RUN chmod +x mvnw && ./mvnw clean package -DskipTests -B +# # get the base image for Java +# FROM eclipse-temurin:21-jdk-jammy -# Run stage - alpine has significantly fewer CVEs than ubuntu/jammy -FROM eclipse-temurin:21-jre-alpine -WORKDIR /app +# #code in a working directory +# WORKDIR /app + +# #copy all the src code to the container +# COPY . . + +# # install the libraries with maven +# RUN chmod +x mvnw && ./mvnw clean package -DskipTests -B -# Pull latest security patches for OS libraries -RUN apk update && apk upgrade --no-cache +# #Expose the port that the application will run on +# EXPOSE 8080 -# Create a non-root user for security (Alpine uses addgroup/adduser instead of groupadd/useradd) -RUN addgroup -S devsecops && adduser -S -G devsecops devsecops -USER devsecops +# # run the application +# # CMD ["java", "-jar", "target/*.jar"] +# ENTRYPOINT ["sh", "-c", "java -jar target/*.jar"] -# Copy only the built artifact -COPY --from=build /app/target/*.jar app.jar +# Stage 1: Build +FROM eclipse-temurin:21-jdk-jammy AS builder +WORKDIR /app +COPY pom.xml ./ +COPY .mvn ./.mvn +COPY mvnw ./ +RUN dos2unix mvnw || sed -i 's/\r$//' mvnw +RUN chmod +x mvnw && ./mvnw dependency:resolve +COPY src ./src +RUN ./mvnw clean package -DskipTests -B + +# Stage 2: Runtime +FROM eclipse-temurin:21-jre-jammy +WORKDIR /app +RUN groupadd -r appuser && useradd -r -g appuser appuser +COPY --from=builder /app/target/*.jar app.jar EXPOSE 8080 -ENTRYPOINT ["java", "-jar", "app.jar"] +HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 CMD java -cp app.jar org.springframework.boot.loader.JarLauncher || exit 1 +USER appuser +ENTRYPOINT ["java", "-jar", "app.jar"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 2220669..71a002b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,53 +1,23 @@ +#docker build and run the application using docker-compose services: mysql: - image: mysql:8.0 - container_name: bankapp-mysql + image: mysql:latest + container_name: mysql environment: - MYSQL_ROOT_PASSWORD: Test@123 - MYSQL_DATABASE: bankappdb - ports: - - "3306:3306" - volumes: - - mysql-data:/var/lib/mysql + MYSQL_ROOT_PASSWORD: rootpassword + MYSQL_DATABASE: bankapp healthcheck: - test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-pTest@123"] interval: 10s timeout: 5s retries: 5 start_period: 30s - networks: - - bankapp-net - - ollama: - image: ollama/ollama - container_name: bankapp-ollama ports: - - "11434:11434" - volumes: - - ollama-data:/root/.ollama - healthcheck: - test: ["CMD", "ollama", "list"] - interval: 10s - timeout: 5s - retries: 5 - networks: - - bankapp-net - - ollama-pull-model: - image: ollama/ollama - container_name: ollama-pull-model - environment: - - OLLAMA_HOST=ollama + - "3306:3306" volumes: - - ollama-data:/root/.ollama - depends_on: - ollama: - condition: service_healthy - entrypoint: /bin/sh - command: -c "ollama pull tinyllama" + - mysql_data:/var/lib/mysql networks: - - bankapp-net - + - bankapp_network bankapp: build: . container_name: bankapp @@ -56,22 +26,21 @@ services: environment: MYSQL_HOST: mysql MYSQL_PORT: 3306 - MYSQL_DATABASE: bankappdb + MYSQL_DATABASE: bankapp MYSQL_USER: root MYSQL_PASSWORD: Test@123 - OLLAMA_URL: http://ollama:11434 depends_on: mysql: condition: service_healthy - ollama-pull-model: - condition: service_completed_successfully networks: - - bankapp-net + - bankapp_network +#docker network create +networks: + bankapp_network: + driver: bridge + +#docker volume create volumes: - mysql-data: - ollama-data: + mysql_data: -networks: - bankapp-net: - driver: bridge diff --git a/k8s/README.md b/k8s/README.md new file mode 100644 index 0000000..4086a59 --- /dev/null +++ b/k8s/README.md @@ -0,0 +1,78 @@ +# Kubernetes Deployment (Step-by-Step) + +This guide deploys the app stack (`bankapp` + `mysql` + `ollama`) into a local Kind cluster. + +## 0) Prerequisites + +- Docker running +- `kubectl` installed +- `kind` installed + +## 1) Build application image + +```bash +docker build -t santoshpathak7456/ai-bankapp-devops_bankapp:k8s . +``` + +## 2) Create Kind cluster + +```bash +kind create cluster --config setup-k8s/kind-config.yml +``` + +## 3) Load local image into Kind + +```bash +kind load docker-image santoshpathak7456/ai-bankapp-devops_bankapp:k8s --name tws-cluster +``` + +## 4) Install metrics-server (required for HPA) + +```bash +kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml +kubectl patch deployment metrics-server -n kube-system --type='json' -p='[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--kubelet-insecure-tls"}]' +kubectl rollout status deployment/metrics-server -n kube-system --timeout=120s +``` + +## 5) Apply manifests in order + +```bash +kubectl apply -f k8s/namespace.yaml +kubectl apply -f k8s/configMap.yaml +kubectl apply -f k8s/secrets.yaml +kubectl apply -f k8s/persistentVolume.yaml +kubectl apply -f k8s/pvc.yaml +kubectl apply -f k8s/mysql-deployment.yaml +kubectl apply -f k8s/ollama-deployment.yaml +kubectl apply -f k8s/bankapp-deployment.yaml +kubectl apply -f k8s/service.yaml +kubectl apply -f k8s/hpa.yaml +``` + +## 6) Verify deployment + +```bash +kubectl get all -n bankapp +kubectl get pvc,pv -n bankapp +kubectl get hpa -n bankapp +kubectl top pods -n bankapp +``` + +## 7) Access application + +Kind config maps node port `30080` to host `8080`. + +- Open: `http://localhost:8080` + +## 8) Test autoscaling + +```bash +kubectl run load-test --image=busybox:1.36 -n bankapp -- sh -c "while true; do wget -q -O- http://bankapp-service:8080/actuator/health >/dev/null 2>&1; done" +kubectl get hpa -n bankapp -w +``` + +Cleanup load pod: + +```bash +kubectl delete pod load-test -n bankapp +``` diff --git a/k8s/bankapp-deployment.yaml b/k8s/bankapp-deployment.yaml new file mode 100644 index 0000000..688a9be --- /dev/null +++ b/k8s/bankapp-deployment.yaml @@ -0,0 +1,111 @@ +# `apiVersion` apps/v1 use hota hai deployments manage karne ke liye. +apiVersion: apps/v1 +# `kind` is object ko Deployment define karta hai. +kind: Deployment +# `metadata` deployment ka naam, namespace aur labels rakhta hai. +metadata: + # Bank application deployment ka unique naam. + name: bankapp-deployment + # App resources ko bankapp namespace me isolate karta hai. + namespace: bankapp + # `labels` se logical grouping aur selection easy hota hai. + labels: + # App tier ko identify karne wala label. + app: bankapp +# `spec` desired number of pods aur pod template batata hai. +spec: + # 3 replicas high availability/load sharing ke basic use-case ke liye. + replicas: 3 + # `selector` batata hai deployment kin pods ko own karega. + selector: + matchLabels: + # Ye selector template label se match hona mandatory hai. + app: bankapp + # `template` naye pods ka exact blueprint provide karta hai. + template: + metadata: + labels: + # Service/deployment matching ke liye pod label. + app: bankapp + spec: + # Pod ke containers yahan define hote hain. + containers: + # Main bankapp container configuration. + - name: bankapp + # Docker image jisse application run hogi. + image: santoshpathak7456/ai-bankapp-devops_bankapp:k8s + # Container exposed ports list. + ports: + # Spring Boot default HTTP port 8080 par listen karta hai. + - containerPort: 8080 + # Runtime environment variables inject karne ka section. + env: + # App ka target database naam. + - name: MYSQL_DATABASE + valueFrom: + # Non-secret config ConfigMap se lena safe/maintainable hota hai. + configMapKeyRef: + # Source ConfigMap ka naam. + name: bankapp-config-map + # Required key jiska value env var banega. + key: MYSQL_DATABASE + # DB host jahan app connect karegi. + - name: MYSQL_HOST + valueFrom: + configMapKeyRef: + # Same central ConfigMap reuse karke config centralized rakhi gayi hai. + name: bankapp-config-map + # MySQL service name wali key. + key: MYSQL_HOST + # DB port app ko dynamic tarike se dene ke liye env var. + - name: MYSQL_PORT + valueFrom: + configMapKeyRef: + # ConfigMap source name. + name: bankapp-config-map + # Port key value. + key: MYSQL_PORT + # DB username jisse app authenticate karegi. + - name: MYSQL_USER + valueFrom: + configMapKeyRef: + # ConfigMap reference for username. + name: bankapp-config-map + # User key fetch hoti hai. + key: MYSQL_USER + # Root password sensitive hai isliye Secret se inject hota hai. + - name: MYSQL_PASSWORD + valueFrom: + secretKeyRef: + # Secret resource ka naam. + name: bankapp-secret + # App DB password secret key. + key: MYSQL_PASSWORD + # Ollama endpoint centralized config se inject hota hai. + - name: OLLAMA_URL + valueFrom: + configMapKeyRef: + name: bankapp-config-map + key: OLLAMA_URL + # HPA ko work karane ke liye CPU/memory requests required hote hain. + resources: + requests: + cpu: "100m" + memory: "256Mi" + limits: + cpu: "500m" + memory: "512Mi" + # Pod ready tab mark ho jab actuator health pass kare. + readinessProbe: + httpGet: + path: /actuator/health + port: 8080 + initialDelaySeconds: 30 + periodSeconds: 10 + # Liveness check unhealthy pod ko restart karne me help karti hai. + livenessProbe: + httpGet: + path: /actuator/health + port: 8080 + initialDelaySeconds: 60 + periodSeconds: 20 \ No newline at end of file diff --git a/k8s/bankapp-deployment.yml b/k8s/bankapp-deployment.yml deleted file mode 100644 index e283853..0000000 --- a/k8s/bankapp-deployment.yml +++ /dev/null @@ -1,67 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: bankapp - namespace: bankapp -spec: - replicas: 2 - selector: - matchLabels: - app: bankapp - template: - metadata: - labels: - app: bankapp - spec: - initContainers: - - name: wait-for-mysql - image: busybox:1.36 - command: ["/bin/sh", "-c", "until nc -z mysql-service 3306; do sleep 2; done"] - resources: - requests: - memory: "32Mi" - cpu: "50m" - limits: - memory: "64Mi" - cpu: "100m" - - name: wait-for-ollama - image: busybox:1.36 - command: ["/bin/sh", "-c", "until nc -z ollama-service 11434; do sleep 2; done"] - resources: - requests: - memory: "32Mi" - cpu: "50m" - limits: - memory: "64Mi" - cpu: "100m" - containers: - - name: bankapp - image: trainwithshubham/bankapp:k8s - imagePullPolicy: IfNotPresent - ports: - - containerPort: 8080 - envFrom: - - configMapRef: - name: bankapp-config - - secretRef: - name: bankapp-secret - resources: - requests: - memory: "256Mi" - cpu: "250m" - limits: - memory: "512Mi" - cpu: "500m" - readinessProbe: - httpGet: - path: /actuator/health - port: 8080 - initialDelaySeconds: 30 - failureThreshold: 15 - livenessProbe: - httpGet: - path: /actuator/health - port: 8080 - initialDelaySeconds: 60 - periodSeconds: 10 - failureThreshold: 5 diff --git a/k8s/configMap.yaml b/k8s/configMap.yaml new file mode 100644 index 0000000..7d9cb31 --- /dev/null +++ b/k8s/configMap.yaml @@ -0,0 +1,22 @@ +# `apiVersion` batata hai ki ConfigMap core v1 API me defined hai. +apiVersion: v1 +# `kind` se pata chalta hai yeh ConfigMap resource hai. +kind: ConfigMap +# `metadata` resource ka naam aur namespace jaisi identity values rakhta hai. +metadata: + # `name` ConfigMap ka unique naam hai jisse pods config fetch karenge. + name: bankapp-config-map + # `namespace` ensure karta hai ki config `bankapp` namespace ke andar hi rahe. + namespace: bankapp +# `data` ke andar plain-text key-value configuration store hoti hai. +data: + # App ka MySQL database naam; startup pe app isi DB se connect karegi. + MYSQL_DATABASE: bankappdb + # MySQL service DNS name; pod se DB reach karne ka standard tareeqa. + MYSQL_HOST: mysql-service + # MySQL port string form me; env var parsing issues avoid karne ke liye quoted. + MYSQL_PORT: "3306" + # DB user name; local/dev setups me often root use hota hai. + MYSQL_USER: root + # Ollama service endpoint; app LLM calls ke liye is URL ko use karegi. + OLLAMA_URL: http://ollama-service:11434 \ No newline at end of file diff --git a/k8s/configmap.yml b/k8s/configmap.yml deleted file mode 100644 index 055e9e3..0000000 --- a/k8s/configmap.yml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: bankapp-config - namespace: bankapp -data: - MYSQL_HOST: mysql-service - MYSQL_PORT: "3306" - MYSQL_DATABASE: bankappdb - OLLAMA_URL: http://ollama-service:11434 diff --git a/k8s/dashboard-admin.yml b/k8s/dashboard-admin.yml deleted file mode 100644 index 712c958..0000000 --- a/k8s/dashboard-admin.yml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: dashboard-admin - namespace: kubernetes-dashboard ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: dashboard-admin -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - name: dashboard-admin - namespace: kubernetes-dashboard diff --git a/k8s/gateway.yml b/k8s/gateway.yml deleted file mode 100644 index f3eb04f..0000000 --- a/k8s/gateway.yml +++ /dev/null @@ -1,38 +0,0 @@ -# Requires: Gateway API CRDs + Envoy Gateway (installed by setup.sh) -apiVersion: gateway.networking.k8s.io/v1 -kind: GatewayClass -metadata: - name: envoy-gateway -spec: - controllerName: gateway.envoyproxy.io/gatewayclass-controller ---- -apiVersion: gateway.networking.k8s.io/v1 -kind: Gateway -metadata: - name: bankapp-gateway - namespace: bankapp -spec: - gatewayClassName: envoy-gateway - listeners: - - name: http - protocol: HTTP - port: 80 ---- -apiVersion: gateway.networking.k8s.io/v1 -kind: HTTPRoute -metadata: - name: bankapp-route - namespace: bankapp -spec: - parentRefs: - - name: bankapp-gateway - hostnames: - - bankapp.local - rules: - - matches: - - path: - type: PathPrefix - value: / - backendRefs: - - name: bankapp-service - port: 8080 diff --git a/k8s/hpa.yaml b/k8s/hpa.yaml new file mode 100644 index 0000000..9d9004e --- /dev/null +++ b/k8s/hpa.yaml @@ -0,0 +1,19 @@ +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: bankapp-hpa + namespace: bankapp +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: bankapp-deployment + minReplicas: 2 + maxReplicas: 6 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 70 diff --git a/k8s/hpa.yml b/k8s/hpa.yml deleted file mode 100644 index a9e0b0e..0000000 --- a/k8s/hpa.yml +++ /dev/null @@ -1,37 +0,0 @@ -# ─── Horizontal Pod Autoscaler — BankApp ───────────────────────── -# Requires metrics-server to be installed in the cluster. -# Sized for t3.medium (2 vCPU / 4 GiB): max 4 replicas keeps -# total workload requests under node capacity. -# ───────────────────────────────────────────────────────────────── -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: bankapp-hpa - namespace: bankapp -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: bankapp - minReplicas: 2 - maxReplicas: 4 - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 70 - behavior: - scaleUp: - stabilizationWindowSeconds: 30 - policies: - - type: Pods - value: 2 - periodSeconds: 60 - scaleDown: - stabilizationWindowSeconds: 300 - policies: - - type: Pods - value: 1 - periodSeconds: 60 diff --git a/k8s/mysql-deployment.yaml b/k8s/mysql-deployment.yaml new file mode 100644 index 0000000..5ec9390 --- /dev/null +++ b/k8s/mysql-deployment.yaml @@ -0,0 +1,81 @@ +# `apiVersion` Deployment resource ke liye apps/v1 use hota hai. +apiVersion: apps/v1 +# `kind` batata hai ki yeh workload Deployment ke through manage hoga. +kind: Deployment +# `metadata` deployment ki identity aur grouping details rakhta hai. +metadata: + # Deployment ka unique naam; rollout aur updates is naam se track honge. + name: mysql-deployment + # Resource ko bankapp namespace me deploy karta hai. + namespace: bankapp + # `labels` organization aur selector matching ke liye useful metadata hai. + labels: + # MySQL related resources ko logically group karne ka label. + app: mysql +# `spec` desired state define karta hai jo controller maintain karega. +spec: + # Single MySQL instance chahiye, isliye replicas 1 rakha gaya hai. + replicas: 1 + # `selector` deployment ke managed pods identify karta hai. + selector: + matchLabels: + # Yeh label pod template labels se exact match hona zaroori hai. + app: mysql + # `template` naya pod create hone par uska blueprint hota hai. + template: + metadata: + labels: + # Service aur deployment selector dono isi label par rely karte hain. + app: mysql + spec: + # `containers` list me pod ke andar chalne wale containers define hote hain. + containers: + # MySQL container definition start hoti hai. + - name: mysql + # Official MySQL 8.0 image use karke DB run karaya ja raha hai. + image: mysql:8.0 + # `ports` container ke exposed network port ko describe karta hai. + ports: + # MySQL default TCP port. + - containerPort: 3306 + # `env` runtime environment variables inject karta hai. + env: + # DB name variable app/db initialization ke liye. + - name: MYSQL_DATABASE + valueFrom: + # ConfigMap se non-sensitive config pull karna best practice hai. + configMapKeyRef: + # Source ConfigMap ka naam. + name: bankapp-config-map + # ConfigMap key jiska value env me jayega. + key: MYSQL_DATABASE + # Root password sensitive hai, isliye Secret se liya gaya hai. + - name: MYSQL_ROOT_PASSWORD + valueFrom: + secretKeyRef: + # Source Secret ka naam. + name: bankapp-secret + # Secret key jiska decoded value env variable banega. + key: MYSQL_ROOT_PASSWORD + # `volumeMounts` persistent storage ko container path par attach karta hai. + volumeMounts: + # Mount config volume name se volumes section se map hoti hai. + - name: mysql-storage + # MySQL data directory; restart ke baad data survive karega. + mountPath: /var/lib/mysql + # `readinessProbe` check karti hai pod traffic lene ke liye ready hai ya nahi. + readinessProbe: + exec: + # Command successful hua to pod ready mark hota hai. + command: ["mysqladmin", "ping", "-h", "127.0.0.1"] + # Start ke baad pehla readiness check 15 sec baad chalega. + initialDelaySeconds: 15 + # Har 10 sec me readiness re-check hoti rahegi. + periodSeconds: 10 + # `volumes` pod level volume sources define karta hai. + volumes: + # Named volume jo container mount karega. + - name: mysql-storage + persistentVolumeClaim: + # PVC name jisse actual persistent disk bind hoti hai. + claimName: mysql-pvc \ No newline at end of file diff --git a/k8s/mysql-deployment.yml b/k8s/mysql-deployment.yml deleted file mode 100644 index f5de98f..0000000 --- a/k8s/mysql-deployment.yml +++ /dev/null @@ -1,57 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: mysql - namespace: bankapp -spec: - selector: - matchLabels: - app: mysql - strategy: - type: Recreate - template: - metadata: - labels: - app: mysql - spec: - containers: - - name: mysql - image: mysql:8.0 - ports: - - containerPort: 3306 - env: - - name: MYSQL_ROOT_PASSWORD - valueFrom: - secretKeyRef: - name: bankapp-secret - key: MYSQL_ROOT_PASSWORD - - name: MYSQL_DATABASE - valueFrom: - configMapKeyRef: - name: bankapp-config - key: MYSQL_DATABASE - resources: - requests: - memory: "256Mi" - cpu: "250m" - limits: - memory: "512Mi" - cpu: "500m" - volumeMounts: - - name: mysql-storage - mountPath: /var/lib/mysql - readinessProbe: - exec: - command: ["mysqladmin", "ping", "-h", "localhost"] - initialDelaySeconds: 15 - failureThreshold: 10 - livenessProbe: - exec: - command: ["mysqladmin", "ping", "-h", "localhost"] - initialDelaySeconds: 30 - periodSeconds: 10 - failureThreshold: 5 - volumes: - - name: mysql-storage - persistentVolumeClaim: - claimName: mysql-pvc diff --git a/k8s/namespace.yaml b/k8s/namespace.yaml new file mode 100644 index 0000000..1f4638a --- /dev/null +++ b/k8s/namespace.yaml @@ -0,0 +1,8 @@ +# `apiVersion` batata hai ki yeh object Kubernetes core v1 API use karega. +apiVersion: v1 +# `kind` se define hota hai ki hum Namespace resource bana rahe hain. +kind: Namespace +# `metadata` object resource ki basic identity/config rakhta hai. +metadata: + # `name` namespace ka unique naam hai jisme app ke resources isolate honge. + name: bankapp \ No newline at end of file diff --git a/k8s/namespace.yml b/k8s/namespace.yml deleted file mode 100644 index 0ea3fd2..0000000 --- a/k8s/namespace.yml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: bankapp diff --git a/k8s/ollama-deployment.yaml b/k8s/ollama-deployment.yaml new file mode 100644 index 0000000..8a0e631 --- /dev/null +++ b/k8s/ollama-deployment.yaml @@ -0,0 +1,29 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ollama-deployment + namespace: bankapp + labels: + app: ollama +spec: + replicas: 1 + selector: + matchLabels: + app: ollama + template: + metadata: + labels: + app: ollama + spec: + containers: + - name: ollama + image: ollama/ollama:latest + ports: + - containerPort: 11434 + resources: + requests: + cpu: "200m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "2Gi" diff --git a/k8s/ollama-deployment.yml b/k8s/ollama-deployment.yml deleted file mode 100644 index 4bf4dae..0000000 --- a/k8s/ollama-deployment.yml +++ /dev/null @@ -1,56 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: ollama - namespace: bankapp -spec: - selector: - matchLabels: - app: ollama - strategy: - type: Recreate - template: - metadata: - labels: - app: ollama - spec: - containers: - - name: ollama - image: ollama/ollama:latest - ports: - - containerPort: 11434 - resources: - requests: - memory: "1Gi" - cpu: "500m" - limits: - memory: "1.5Gi" - cpu: "1000m" - volumeMounts: - - name: ollama-storage - mountPath: /root/.ollama - lifecycle: - postStart: - exec: - command: - - /bin/sh - - -c - - | - until ollama list > /dev/null 2>&1; do sleep 2; done - ollama pull tinyllama - readinessProbe: - exec: - command: ["/bin/sh", "-c", "ollama list | grep -q tinyllama"] - initialDelaySeconds: 30 - failureThreshold: 30 - livenessProbe: - httpGet: - path: / - port: 11434 - initialDelaySeconds: 60 - periodSeconds: 10 - failureThreshold: 5 - volumes: - - name: ollama-storage - persistentVolumeClaim: - claimName: ollama-pvc diff --git a/k8s/persistentVolume.yaml b/k8s/persistentVolume.yaml new file mode 100644 index 0000000..53cad53 --- /dev/null +++ b/k8s/persistentVolume.yaml @@ -0,0 +1,28 @@ +# `apiVersion` core storage resources ke liye v1 batata hai. +apiVersion: v1 +# `kind` se declare hota hai ki yeh cluster-level PersistentVolume hai. +kind: PersistentVolume +# `metadata` PV ka identifier aur labels define karta hai. +metadata: + # `name` PV ka unique naam hai jise PVC indirectly bind karega. + name: mysql-pv + # `labels` selector-based binding/organization ke liye helpful hote hain. + labels: + # `app: mysql` label PVC selector ke sath match karne ke kaam aata hai. + app: mysql +# `spec` actual storage behavior aur capacity define karta hai. +spec: + # `storageClassName` manual provisioning scenario ko indicate karta hai. + storageClassName: manual + # `capacity` total available disk size define karti hai. + capacity: + # 5Gi ka persistent storage MySQL data files ke liye reserve hota hai. + storage: 5Gi + # `accessModes` se batta hai volume kitne tarike se mount ho sakta hai. + accessModes: + # `ReadWriteOnce` ek node pe read-write mount ke liye common DB mode hai. + - ReadWriteOnce + # `hostPath` local node filesystem ka path use karta hai (dev/test friendly). + hostPath: + # Node par actual directory jaha DB ka data persist hoga. + path: /mnt/data/mysqldb \ No newline at end of file diff --git a/k8s/pod.yaml b/k8s/pod.yaml new file mode 100644 index 0000000..c2413f3 --- /dev/null +++ b/k8s/pod.yaml @@ -0,0 +1,22 @@ +# `apiVersion` core Pod resource ke liye v1 set hota hai. +apiVersion: v1 +# `kind` se pata chalta hai ki yeh direct Pod manifest hai. +kind: Pod +# `metadata` pod ki identity aur scope define karta hai. +metadata: + # Pod ka naam; generally debug/testing single pod use-case me helpful. + name: bankapp + # Pod ko bankapp namespace me schedule karta hai. + namespace: bankapp +# `spec` pod ke runtime details define karta hai. +spec: + # `containers` pod ke andar run hone wale containers ki list hai. + containers: + # Bank application container ka logical naam. + - name: bankapp + # App image with `latest` tag; dev me quick iteration ke liye use hota hai. + image: santoshpathak7456/ai-bankapp-devops_bankapp:latest + # Container ke exposed network ports. + ports: + # HTTP traffic receive karne ke liye container port 80. + - containerPort: 80 \ No newline at end of file diff --git a/k8s/pod.yml b/k8s/pod.yml deleted file mode 100644 index aa3972e..0000000 --- a/k8s/pod.yml +++ /dev/null @@ -1,21 +0,0 @@ -# Standalone BankApp pod for learning kubectl commands -# Assumes MySQL and Ollama are already running -apiVersion: v1 -kind: Pod -metadata: - name: bankapp-pod - namespace: bankapp - labels: - app: bankapp -spec: - containers: - - name: bankapp - image: trainwithshubham/bankapp:k8s - imagePullPolicy: IfNotPresent - ports: - - containerPort: 8080 - envFrom: - - configMapRef: - name: bankapp-config - - secretRef: - name: bankapp-secret diff --git a/k8s/pv.yml b/k8s/pv.yml deleted file mode 100644 index 233473f..0000000 --- a/k8s/pv.yml +++ /dev/null @@ -1,29 +0,0 @@ -apiVersion: v1 -kind: PersistentVolume -metadata: - name: mysql-pv - labels: - app: mysql -spec: - storageClassName: manual - capacity: - storage: 5Gi - accessModes: - - ReadWriteOnce - hostPath: - path: /mnt/data/mysql ---- -apiVersion: v1 -kind: PersistentVolume -metadata: - name: ollama-pv - labels: - app: ollama -spec: - storageClassName: manual - capacity: - storage: 5Gi - accessModes: - - ReadWriteOnce - hostPath: - path: /mnt/data/ollama diff --git a/k8s/pvc.yaml b/k8s/pvc.yaml new file mode 100644 index 0000000..026c52a --- /dev/null +++ b/k8s/pvc.yaml @@ -0,0 +1,28 @@ +# `apiVersion` PVC ke liye core v1 API ko indicate karta hai. +apiVersion: v1 +# `kind` yeh resource ko PersistentVolumeClaim banata hai. +kind: PersistentVolumeClaim +# `metadata` claim ka name aur namespace scope set karta hai. +metadata: + # `name` claim identifier hai jise pods volume mount ke liye refer karte hain. + name: mysql-pvc + # `namespace` claim ko bankapp namespace me constrain karta hai. + namespace: bankapp +# `spec` me requested storage properties define hoti hain. +spec: + # `accessModes` desired mount behavior batata hai. + accessModes: + # `ReadWriteOnce` DB workloads ke liye safe/common option hai. + - ReadWriteOnce + # `storageClassName` ko PV ke class se match hona chahiye. + storageClassName: manual + # `resources` claim ko required minimum storage amount batata hai. + resources: + requests: + # 5Gi storage claim karke MySQL ko persistent disk milti hai. + storage: 5Gi + # `selector` specific labeled PV se bind karne ke liye use hota hai. + selector: + matchLabels: + # Yeh label `persistentVolume.yaml` ke `app: mysql` se match karta hai. + app: mysql \ No newline at end of file diff --git a/k8s/pvc.yml b/k8s/pvc.yml deleted file mode 100644 index 63dbe04..0000000 --- a/k8s/pvc.yml +++ /dev/null @@ -1,31 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: mysql-pvc - namespace: bankapp -spec: - storageClassName: manual - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 5Gi - selector: - matchLabels: - app: mysql ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: ollama-pvc - namespace: bankapp -spec: - storageClassName: manual - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 5Gi - selector: - matchLabels: - app: ollama diff --git a/k8s/secrets.yaml b/k8s/secrets.yaml new file mode 100644 index 0000000..82029be --- /dev/null +++ b/k8s/secrets.yaml @@ -0,0 +1,18 @@ +# `apiVersion` yeh batata hai ki Secret core v1 API object hai. +apiVersion: v1 +# `kind` define karta hai ki yeh Secret resource create hoga. +kind: Secret +# `metadata` me secret ka naam aur namespace diya jata hai. +metadata: + # `name` secret ka reference name hai jo deployments me use hota hai. + name: bankapp-secret + # `namespace` secret ko bankapp scope tak limit karta hai. + namespace: bankapp +# `type: Opaque` generic key-value secret ke liye common type hai. +type: Opaque +# `data` me values base64-encoded form me store hoti hain. +data: + # MySQL root password ka base64 value; prod me strong secret manager use karein. + MYSQL_ROOT_PASSWORD: cm9vdA== + # App/user level password ka base64 value; alag credentials use-case ke liye. + MYSQL_PASSWORD: VGVzdEAxMjM= \ No newline at end of file diff --git a/k8s/secrets.yml b/k8s/secrets.yml deleted file mode 100644 index 4edf117..0000000 --- a/k8s/secrets.yml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: bankapp-secret - namespace: bankapp -type: Opaque -data: - MYSQL_ROOT_PASSWORD: VGVzdEAxMjM= # Test@123 - MYSQL_USER: cm9vdA== # root - MYSQL_PASSWORD: VGVzdEAxMjM= # Test@123 diff --git a/k8s/service.yaml b/k8s/service.yaml new file mode 100644 index 0000000..24c9f26 --- /dev/null +++ b/k8s/service.yaml @@ -0,0 +1,55 @@ +# `apiVersion` batata hai ki Service core v1 API ka object hai. +apiVersion: v1 +# `kind` resource type ko Service declare karta hai. +kind: Service +# `metadata` service ka naam aur namespace details hold karta hai. +metadata: + # `name` internal DNS banata hai (`mysql-service.bankapp.svc`) jisse app DB tak pahuche. + name: mysql-service + # `namespace` service ko bankapp workloads ke saath group karta hai. + namespace: bankapp +# `spec` network routing rules define karta hai. +spec: + # `ClusterIP` service ko cluster ke andar private endpoint banata hai. + type: ClusterIP + # `selector` se woh pods choose hote hain jinke paas matching label ho. + selector: + # `app: mysql` label wale pods ko service backend banaya jayega. + app: mysql + # `ports` traffic forwarding ke source aur destination ports define karta hai. + ports: + # Service port jahan se dusre pods MySQL connect karenge. + - port: 3306 + # Pod/container ke actual port tak request forward hoti hai. + targetPort: 3306 + +--- + +apiVersion: v1 +kind: Service +metadata: + name: bankapp-service + namespace: bankapp +spec: + type: NodePort + selector: + app: bankapp + ports: + - port: 8080 + targetPort: 8080 + nodePort: 30080 + +--- + +apiVersion: v1 +kind: Service +metadata: + name: ollama-service + namespace: bankapp +spec: + type: ClusterIP + selector: + app: ollama + ports: + - port: 11434 + targetPort: 11434 diff --git a/k8s/service.yml b/k8s/service.yml deleted file mode 100644 index f9d77fe..0000000 --- a/k8s/service.yml +++ /dev/null @@ -1,38 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: mysql-service - namespace: bankapp -spec: - selector: - app: mysql - ports: - - port: 3306 ---- -apiVersion: v1 -kind: Service -metadata: - name: ollama-service - namespace: bankapp -spec: - selector: - app: ollama - ports: - - port: 11434 ---- -apiVersion: v1 -kind: Service -metadata: - name: bankapp-service - namespace: bankapp -spec: - type: NodePort - sessionAffinity: ClientIP - sessionAffinityConfig: - clientIP: - timeoutSeconds: 3600 - selector: - app: bankapp - ports: - - port: 8080 - nodePort: 30080 diff --git a/kind-config.yaml b/kind-config.yaml new file mode 100644 index 0000000..e69de29