From 9bc71c6b43c05ca78b16c84d28d983a2987872f7 Mon Sep 17 00:00:00 2001 From: Syifa Date: Wed, 22 Oct 2025 09:00:44 +0700 Subject: [PATCH] added kubernetes base manifest for gitops workflow --- k8s | 1 - k8s/backend-deployment.yaml | 69 ++++++++++++++++++++++ k8s/config-map.yaml | 9 +++ k8s/frontend-deployment.yaml | 69 ++++++++++++++++++++++ k8s/kustomization.yaml | 11 ++++ k8s/mysql-deployment.yaml | 75 ++++++++++++++++++++++++ k8s/network-policy.yaml | 104 ++++++++++++++++++++++++++++++++++ k8s/rbac.yaml | 107 +++++++++++++++++++++++++++++++++++ k8s/secret.yaml | 10 ++++ 9 files changed, 454 insertions(+), 1 deletion(-) delete mode 160000 k8s create mode 100644 k8s/backend-deployment.yaml create mode 100644 k8s/config-map.yaml create mode 100644 k8s/frontend-deployment.yaml create mode 100644 k8s/kustomization.yaml create mode 100644 k8s/mysql-deployment.yaml create mode 100644 k8s/network-policy.yaml create mode 100644 k8s/rbac.yaml create mode 100644 k8s/secret.yaml diff --git a/k8s b/k8s deleted file mode 160000 index 1097dba..0000000 --- a/k8s +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 1097dbafa95e0bf2f8d898d65dea0cda10e8d83c diff --git a/k8s/backend-deployment.yaml b/k8s/backend-deployment.yaml new file mode 100644 index 0000000..73faa75 --- /dev/null +++ b/k8s/backend-deployment.yaml @@ -0,0 +1,69 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: backend-app-syifa + namespace: intern-workspace +spec: + replicas: 1 + selector: + matchLabels: + app: backend-datasiswa + template: + metadata: + labels: + app: backend-datasiswa + spec: + serviceAccountName: backend-sa-syifa + securityContext: + runAsUser: 1000 + runAsGroup: 3000 + fsGroup: 2000 + containers: + - name: backend + image: syifamaulidya/backend-app:v4 + ports: + - containerPort: 5000 + envFrom: + - configMapRef: + name: backend-config-syifa + - secretRef: + name: backend-secret-syifa + resources: + requests: + memory: "256Mi" + cpu: "250m" + limits: + memory: "512Mi" + cpu: "500m" + readinessProbe: + httpGet: + path: /api/health + port: 5000 + initialDelaySeconds: 60 + timeoutSeconds: 10 + periodSeconds: 5 + livenessProbe: + httpGet: + path: /api/health + port: 5000 + initialDelaySeconds: 60 + timeoutSeconds: 5 + periodSeconds: 10 + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + readOnlyRootFilesystem: false +--- +apiVersion: v1 +kind: Service +metadata: + name: backend-app-syifa + namespace: intern-workspace +spec: + type: ClusterIP + selector: + app: backend-datasiswa + ports: + - port: 5000 + targetPort: 5000 + \ No newline at end of file diff --git a/k8s/config-map.yaml b/k8s/config-map.yaml new file mode 100644 index 0000000..91f665f --- /dev/null +++ b/k8s/config-map.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: backend-config-syifa + namespace: intern-workspace +data: + DB_HOST: "mysql-app-syifa" + DB_NAME: "datasiswa" + \ No newline at end of file diff --git a/k8s/frontend-deployment.yaml b/k8s/frontend-deployment.yaml new file mode 100644 index 0000000..69adda3 --- /dev/null +++ b/k8s/frontend-deployment.yaml @@ -0,0 +1,69 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: frontend-app-syifa + namespace: intern-workspace +spec: + replicas: 1 + selector: + matchLabels: + app: frontend-datasiswa + template: + metadata: + labels: + app: frontend-datasiswa + spec: + serviceAccountName: frontend-sa-syifa + securityContext: + runAsUser: 1000 + runAsGroup: 3000 + fsGroup: 2000 + containers: + - name: frontend + image: syifamaulidya/frontend-app:v1 + ports: + - containerPort: 3000 + env: + - name: REACT_APP_API_URL + value: "http://backend-app-syifa:5000/api/auth/login" + resources: + requests: + memory: "256Mi" + cpu: "100m" + limits: + memory: "512Mi" + cpu: "200m" + readinessProbe: + httpGet: + path: / + port: 3000 + initialDelaySeconds: 30 + timeoutSeconds: 5 + periodSeconds: 10 + livenessProbe: + httpGet: + path: / + port: 3000 + initialDelaySeconds: 60 + timeoutSeconds: 5 + periodSeconds: 15 + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + readOnlyRootFilesystem: false +--- +apiVersion: v1 +kind: Service +metadata: + name: frontend-app-syifa + namespace: intern-workspace +spec: + type: NodePort + selector: + app: frontend-datasiswa + ports: + - port: 3000 + targetPort: 3000 + nodePort: 30067 + protocol: TCP + \ No newline at end of file diff --git a/k8s/kustomization.yaml b/k8s/kustomization.yaml new file mode 100644 index 0000000..de55c9a --- /dev/null +++ b/k8s/kustomization.yaml @@ -0,0 +1,11 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - backend-deployment.yaml + - frontend-deployment.yaml + - mysql-deployment.yaml + - config-map.yaml + - secret.yaml + - rbac.yaml + - network-policy.yaml \ No newline at end of file diff --git a/k8s/mysql-deployment.yaml b/k8s/mysql-deployment.yaml new file mode 100644 index 0000000..f9a4e37 --- /dev/null +++ b/k8s/mysql-deployment.yaml @@ -0,0 +1,75 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: mysql-pvc-syifa + namespace: intern-workspace +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 2Gi + volumeMode: Filesystem +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mysql-app-syifa + namespace: intern-workspace +spec: + replicas: 1 + selector: + matchLabels: + app: mysql-datasiswa + template: + metadata: + labels: + app: mysql-datasiswa + spec: + serviceAccountName: mysql-sa-syifa + securityContext: + runAsUser: 999 + runAsGroup: 999 + fsGroup: 999 + containers: + - name: mysql + image: mysql:8 + ports: + - containerPort: 3306 + env: + - name: MYSQL_ALLOW_EMPTY_PASSWORD + value: "yes" + - name: MYSQL_DATABASE + value: "datasiswa" + volumeMounts: + - mountPath: /var/lib/mysql + name: mysql-storage + resources: + requests: + memory: "256Mi" + cpu: "250m" + limits: + memory: "512Mi" + cpu: "500m" + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + readOnlyRootFilesystem: false + volumes: + - name: mysql-storage + persistentVolumeClaim: + claimName: mysql-pvc-syifa +--- +apiVersion: v1 +kind: Service +metadata: + name: mysql-app-syifa + namespace: intern-workspace +spec: + type: ClusterIP + selector: + app: mysql-datasiswa + ports: + - port: 3306 + targetPort: 3306 + \ No newline at end of file diff --git a/k8s/network-policy.yaml b/k8s/network-policy.yaml new file mode 100644 index 0000000..87ffa9c --- /dev/null +++ b/k8s/network-policy.yaml @@ -0,0 +1,104 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-frontend-to-backend + namespace: intern-workspace +spec: + podSelector: + matchLabels: + app: backend-datasiswa + policyTypes: + - Ingress + ingress: + - from: + - podSelector: + matchLabels: + app: frontend-datasiswa + ports: + - protocol: TCP + port: 5000 +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-backend-to-mysql + namespace: intern-workspace +spec: + podSelector: + matchLabels: + app: mysql-datasiswa + policyTypes: + - Ingress + - Egress + ingress: + - from: + - podSelector: + matchLabels: + app: backend-datasiswa + ports: + - protocol: TCP + port: 3306 + egress: + - to: + - podSelector: + matchLabels: + app: backend-datasiswa + ports: + - protocol: TCP + port: 5000 +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-backend-egress + namespace: intern-workspace +spec: + podSelector: + matchLabels: + app: backend-datasiswa + policyTypes: + - Egress + egress: + # Backend boleh akses MySQL + - to: + - podSelector: + matchLabels: + app: mysql-datasiswa + ports: + - protocol: TCP + port: 3306 + # Boleh keluar ke DNS (supaya backend tetap bisa resolve nama service) + - to: + - namespaceSelector: {} + ports: + - protocol: UDP + port: 53 +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-frontend-egress + namespace: intern-workspace +spec: + podSelector: + matchLabels: + app: frontend-datasiswa + policyTypes: + - Egress + egress: + # Frontend boleh kirim request ke backend + - to: + - podSelector: + matchLabels: + app: backend-datasiswa + ports: + - protocol: TCP + port: 5000 + # Boleh keluar ke DNS + - to: + - namespaceSelector: {} + ports: + - protocol: UDP + port: 53 + + \ No newline at end of file diff --git a/k8s/rbac.yaml b/k8s/rbac.yaml new file mode 100644 index 0000000..cd2757a --- /dev/null +++ b/k8s/rbac.yaml @@ -0,0 +1,107 @@ +# ========================================== +# FRONTEND RBAC +# ========================================== +apiVersion: v1 +kind: ServiceAccount +metadata: + name: frontend-sa-syifa + namespace: intern-workspace +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: frontend-role-syifa + namespace: intern-workspace +rules: + # Frontend boleh baca Service (buat resolve endpoint backend) + - apiGroups: [""] + resources: ["pods", "services"] + verbs: ["get", "list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: frontend-rolebinding-syifa + namespace: intern-workspace +subjects: + - kind: ServiceAccount + name: frontend-sa-syifa + namespace: intern-workspace +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: frontend-role-syifa + +# ========================================== +# BACKEND RBAC +# ========================================== +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: backend-sa-syifa + namespace: intern-workspace +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: backend-role-syifa + namespace: intern-workspace +rules: + # Backend boleh baca ConfigMap dan Secret (buat env) + - apiGroups: [""] + resources: ["configmaps", "secrets"] + verbs: ["get", "list"] + # Backend juga boleh cek pod dan service (buat internal komunikasi) + - apiGroups: [""] + resources: ["pods", "services"] + verbs: ["get", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: backend-rolebinding-syifa + namespace: intern-workspace +subjects: + - kind: ServiceAccount + name: backend-sa-syifa + namespace: intern-workspace +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: backend-role-syifa + +# ========================================== +# MYSQL RBAC +# ========================================== +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: mysql-sa-syifa + namespace: intern-workspace +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: mysql-role-syifa + namespace: intern-workspace +rules: + - apiGroups: [""] + resources: ["configmaps", "secrets"] + verbs: ["get", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: mysql-rolebinding-syifa + namespace: intern-workspace +subjects: + - kind: ServiceAccount + name: mysql-sa-syifa + namespace: intern-workspace +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: mysql-role-syifa + \ No newline at end of file diff --git a/k8s/secret.yaml b/k8s/secret.yaml new file mode 100644 index 0000000..1853794 --- /dev/null +++ b/k8s/secret.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Secret +metadata: + name: backend-secret-syifa + namespace: intern-workspace +type: Opaque +data: + DB_USER: cm9vdA== # hasil base64 dari "root" + DB_PASSWORD: "" # kosong, tetap valid + \ No newline at end of file