diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index a9d9c004..5461d275 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -1,4 +1,4 @@ -name: ci +name: docker-image on: push: diff --git a/.github/workflows/kustomize.yml b/.github/workflows/kustomize.yml new file mode 100644 index 00000000..74de914f --- /dev/null +++ b/.github/workflows/kustomize.yml @@ -0,0 +1,24 @@ +name: Create Cluster + +on: + push: + branches: + - 'master' + - 'staging' + +jobs: + create-cluster: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: recursive + - name: Create k8s Kind Cluster + uses: helm/kind-action@v1.1.0 + - name: Test + run: | + kubectl cluster-info + kubectl get storageclass standard + cp Resources/k8s/kustomize/secrets/postgres.env.sample Resources/k8s/kustomize/secrets/postgres.env + kubectl apply -k Resources/k8s/kustomize/ \ No newline at end of file diff --git a/Makefile b/Makefile index 12465581..56fb5fcd 100755 --- a/Makefile +++ b/Makefile @@ -100,3 +100,15 @@ hasura-apply: # Apply local Hasura configuration hasura-get-anon-schema: # Dumps GraphQL schema gq http://localhost:8080/v1/graphql --introspect > graphql/schema.graphql + +kustomize-apply: # (Kustomize) Run kubectl apply -k on the connected k8s cluster + kubectl apply -k Resources/k8s/kustomize/ + +k8s-migrate: # (k8s) Run any pending migrations + kubectl exec deployment/pokeapi -- python manage.py migrate --settings=config.docker-compose + +k8s-build-db: # (k8s) Build the database + kubectl exec deployment/pokeapi -- sh -c 'echo "from data.v2.build import build_all; build_all()" | python manage.py shell --settings=config.docker-compose' + +k8s-delete: # (k8s) Delete pokeapi namespace + kubectl delete namespace pokeapi \ No newline at end of file diff --git a/Resources/k8s/kustomize/config/haproxy-ingress-configmap.yaml b/Resources/k8s/kustomize/config/haproxy-ingress-configmap.yaml new file mode 100644 index 00000000..6635fc6b --- /dev/null +++ b/Resources/k8s/kustomize/config/haproxy-ingress-configmap.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: haproxy-ingress-configmap +data: + dynamic-scaling: "true" + ssl-redirect: "false" + app-root: "/" + stats-auth: pokeapi:pokeapi diff --git a/Resources/k8s/kustomize/config/pokeapi.env b/Resources/k8s/kustomize/config/pokeapi.env new file mode 100644 index 00000000..e964f3cf --- /dev/null +++ b/Resources/k8s/kustomize/config/pokeapi.env @@ -0,0 +1,2 @@ +ADMINS=PokeAPI,change.me@pokeapi.co +BASE_URL=http://localhost/ diff --git a/Resources/k8s/kustomize/deployments/default-deployment.yaml b/Resources/k8s/kustomize/deployments/default-deployment.yaml new file mode 100644 index 00000000..b0ad39d1 --- /dev/null +++ b/Resources/k8s/kustomize/deployments/default-deployment.yaml @@ -0,0 +1,25 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: default-backend + labels: + component: default-backend +spec: + replicas: 2 + selector: + matchLabels: + component: default-backend + template: + metadata: + labels: + component: default-backend + spec: + containers: + - name: default-backend + image: gcr.io/google_containers/defaultbackend:1.4 + ports: + - containerPort: 8080 + resources: + limits: + memory: "64Mi" + cpu: "50m" \ No newline at end of file diff --git a/Resources/k8s/kustomize/deployments/graphql-deployment.yaml b/Resources/k8s/kustomize/deployments/graphql-deployment.yaml new file mode 100644 index 00000000..fb86b7cb --- /dev/null +++ b/Resources/k8s/kustomize/deployments/graphql-deployment.yaml @@ -0,0 +1,43 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: graphql + labels: + component: graphql +spec: + replicas: 1 + selector: + matchLabels: + component: graphql + template: + metadata: + labels: + component: graphql + spec: + containers: + - name: graphql-engine + image: hasura/graphql-engine:v2.0.0-alpha.5 + ports: + - containerPort: 8080 + env: + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: postgres-env-secret + key: POSTGRES_PASSWORD + - name: HASURA_GRAPHQL_DATABASE_URL + value: postgres://ash:$(POSTGRES_PASSWORD)@postgresql:5432/pokeapi + - name: HASURA_GRAPHQL_ENABLE_CONSOLE + value: "true" + - name: HASURA_GRAPHQL_DEV_MODE + value: "false" + - name: HASURA_GRAPHQL_ENABLED_LOG_TYPES + value: startup, http-log, webhook-log, websocket-log, query-log + - name: HASURA_GRAPHQL_ADMIN_SECRET + value: pokemon + - name: HASURA_GRAPHQL_UNAUTHORIZED_ROLE + value: anon + - name: HASURA_GRAPHQL_ENABLE_TELEMETRY + value: "false" + resources: {} + diff --git a/Resources/k8s/kustomize/deployments/haproxy-ingress-controller.yaml b/Resources/k8s/kustomize/deployments/haproxy-ingress-controller.yaml new file mode 100644 index 00000000..d9b3e9bd --- /dev/null +++ b/Resources/k8s/kustomize/deployments/haproxy-ingress-controller.yaml @@ -0,0 +1,47 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: haproxy-ingress-controller + labels: + component: haproxy-ingress +spec: + selector: + matchLabels: + component: haproxy-ingress + template: + metadata: + labels: + component: haproxy-ingress + spec: + serviceAccountName: ingress-controller + containers: + - name: haproxy-ingress-controller + image: quay.io/jcmoraisjr/haproxy-ingress:v0.12.3 + resources: + limits: + memory: "256Mi" + cpu: "500m" + args: + - --default-ssl-certificate=$(POD_NAMESPACE)/tls-secret + - --configmap=$(POD_NAMESPACE)/haproxy-ingress-configmap + - --reload-strategy=native + ports: + - name: http + containerPort: 80 + - name: https + containerPort: 443 + - name: stat + containerPort: 1936 + livenessProbe: + httpGet: + path: /healthz + port: 10253 + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace diff --git a/Resources/k8s/kustomize/deployments/pokeapi-deployment.yaml b/Resources/k8s/kustomize/deployments/pokeapi-deployment.yaml new file mode 100644 index 00000000..1bbabc02 --- /dev/null +++ b/Resources/k8s/kustomize/deployments/pokeapi-deployment.yaml @@ -0,0 +1,58 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: pokeapi + labels: + component: pokeapi +spec: + replicas: 2 + selector: + matchLabels: + component: pokeapi + template: + metadata: + labels: + component: pokeapi + spec: + initContainers: + - name: postgres-connection-checker + image: postgres:13.3-alpine + command: ['sh', '-c', + 'until pg_isready -h postgresql -p 5432; + do echo waiting for database; sleep 2; done;'] + containers: + - name: pokeapi + image: pokeapi/pokeapi:staging + # imagePullPolicy: Always + ports: + - containerPort: 80 + env: + - name: POSTGRES_HOST + value: postgresql + - name: POSTGRES_USER + value: ash + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: postgres-env-secret + key: POSTGRES_PASSWORD + - name: POSTGRES_DB + value: pokeapi + - name: REDIS_CONNECTION_STRING + value: redis://redis:6379/1 + envFrom: + - configMapRef: + name: pokeapi-configmap + resources: {} + readinessProbe: + periodSeconds: 5 + initialDelaySeconds: 5 + httpGet: + path: /api/v2/ + port: 80 + livenessProbe: + periodSeconds: 5 + initialDelaySeconds: 5 + httpGet: + path: /api/v2/ + port: 80 diff --git a/Resources/k8s/kustomize/deployments/postgres-deployment.yaml b/Resources/k8s/kustomize/deployments/postgres-deployment.yaml new file mode 100644 index 00000000..5ae39a79 --- /dev/null +++ b/Resources/k8s/kustomize/deployments/postgres-deployment.yaml @@ -0,0 +1,41 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgresql + labels: + component: postgresql +spec: + replicas: 1 + selector: + matchLabels: + component: postgresql + template: + metadata: + labels: + component: postgresql + spec: + containers: + - name: postgresql + image: postgres:13.3-alpine + ports: + - containerPort: 5432 + env: + - name: POSTGRES_USER + value: ash + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: postgres-env-secret + key: POSTGRES_PASSWORD + - name: PGDATA + value: /var/lib/postgresql/data/pgdata + - name: POSTGRES_DB + value: pokeapi + resources: {} + volumeMounts: + - mountPath: /var/lib/postgresql/data + name: postgres-claim0 + volumes: + - name: postgres-claim0 + persistentVolumeClaim: + claimName: postgres-claim0 diff --git a/Resources/k8s/kustomize/deployments/redis-deployment.yaml b/Resources/k8s/kustomize/deployments/redis-deployment.yaml new file mode 100644 index 00000000..efb54eae --- /dev/null +++ b/Resources/k8s/kustomize/deployments/redis-deployment.yaml @@ -0,0 +1,29 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: redis + labels: + component: redis +spec: + replicas: 1 + selector: + matchLabels: + component: redis + template: + metadata: + labels: + component: redis + spec: + containers: + - name: redis + image: redis:6.2.3-alpine + ports: + - containerPort: 6379 + resources: {} + volumeMounts: + - mountPath: /data + name: redis-claim0 + volumes: + - name: redis-claim0 + persistentVolumeClaim: + claimName: redis-claim0 diff --git a/Resources/k8s/kustomize/jobs/load-graphql.yml b/Resources/k8s/kustomize/jobs/load-graphql.yml new file mode 100644 index 00000000..3cb82cd5 --- /dev/null +++ b/Resources/k8s/kustomize/jobs/load-graphql.yml @@ -0,0 +1,18 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: load-graphql + namespace: pokeapi +spec: + ttlSecondsAfterFinished: 200 + template: + spec: + containers: + - name: load-graphql + image: debian:buster + env: + - name: HASURA_GRAPHQL_ADMIN_SECRET + value: pokemon + command: ["sh", "-c"] + args: ["apt-get update && apt-get install -y git curl && curl -L https://github.com/hasura/graphql-engine/raw/stable/cli/get.sh | bash && hasura update-cli --version v2.0.0-alpha.5 && git clone https://github.com/PokeAPI/pokeapi.git && cd pokeapi && git checkout staging && hasura md apply --endpoint http://graphql:8080 --project graphql --admin-secret $(HASURA_GRAPHQL_ADMIN_SECRET)"] + restartPolicy: Never diff --git a/Resources/k8s/kustomize/kustomization.yaml b/Resources/k8s/kustomize/kustomization.yaml new file mode 100644 index 00000000..8fed03ee --- /dev/null +++ b/Resources/k8s/kustomize/kustomization.yaml @@ -0,0 +1,34 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: pokeapi + +configMapGenerator: + - name: pokeapi-configmap + files: + - config/pokeapi.env + +secretGenerator: + - name: postgres-env-secret + env: secrets/postgres.env # TODO: change in envs as kustomize release 2.0.4 + type: Opaque + +resources: + - other/namespace.yaml + - other/ingress-controller-rbac.yaml + - config/haproxy-ingress-configmap.yaml + - services/default-service.yaml + - services/pokeapi-service.yaml + - services/postgres-service.yaml + - services/redis-service.yaml + - services/graphql-service.yaml + - services/cloud.yaml + - volumes/postgres-persistentvolumeclaim.yaml + - volumes/redis-persistentvolumeclaim.yaml + - deployments/default-deployment.yaml + - deployments/postgres-deployment.yaml + - deployments/redis-deployment.yaml + - deployments/pokeapi-deployment.yaml + - deployments/graphql-deployment.yaml + - deployments/haproxy-ingress-controller.yaml + - other/ingress.yaml diff --git a/Resources/k8s/kustomize/other/ingress-controller-rbac.yaml b/Resources/k8s/kustomize/other/ingress-controller-rbac.yaml new file mode 100644 index 00000000..d3e21be1 --- /dev/null +++ b/Resources/k8s/kustomize/other/ingress-controller-rbac.yaml @@ -0,0 +1,123 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: ingress-controller +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: ingress-controller +rules: + - apiGroups: + - "" + resources: + - configmaps + - endpoints + - nodes + - pods + - secrets + verbs: + - list + - watch + - apiGroups: + - "" + resources: + - nodes + verbs: + - get + - apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch + - apiGroups: + - "extensions" + resources: + - ingresses + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - apiGroups: + - "extensions" + resources: + - ingresses/status + verbs: + - update +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: ingress-controller +rules: + - apiGroups: + - "" + resources: + - configmaps + - pods + - secrets + - namespaces + verbs: + - get + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - update + - apiGroups: + - "" + resources: + - configmaps + verbs: + - create + - apiGroups: + - "" + resources: + - endpoints + verbs: + - get + - create + - update +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: ingress-controller +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: ingress-controller +subjects: + - kind: ServiceAccount + name: ingress-controller + - apiGroup: rbac.authorization.k8s.io + kind: User + name: ingress-controller +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: ingress-controller +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: ingress-controller +subjects: + - kind: ServiceAccount + name: ingress-controller + - apiGroup: rbac.authorization.k8s.io + kind: User + name: ingress-controller diff --git a/Resources/k8s/kustomize/other/ingress.yaml b/Resources/k8s/kustomize/other/ingress.yaml new file mode 100644 index 00000000..733a911c --- /dev/null +++ b/Resources/k8s/kustomize/other/ingress.yaml @@ -0,0 +1,66 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: pokeapi-ingress + annotations: + kubernetes.io/ingress.class: "haproxy" + ingress.kubernetes.io/config-backend: | + compression algo gzip + compression type application/json +spec: + defaultBackend: + service: + name: default-backend + port: + number: 8080 + rules: + - http: + paths: + - path: /api/v2 + pathType: Prefix + backend: + service: + name: pokeapi + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: graphql-ingress + annotations: + kubernetes.io/ingress.class: "haproxy" + ingress.kubernetes.io/config-backend: | + http-request replace-path /graphql(.*) \1 +spec: + defaultBackend: + service: + name: default-backend + port: + number: 8080 + rules: + - http: + paths: + - path: /graphql + pathType: Prefix + backend: + service: + name: graphql + port: + number: 8080 +# apiVersion: extensions/v1beta1 +# kind: Ingress +# metadata: +# name: auth-ingress +# annotations: +# ingress.kubernetes.io/auth-type: basic +# ingress.kubernetes.io/auth-realm: Default realm +# ingress.kubernetes.io/auth-secret: bugs-frontend-secret +# spec: +# rules: +# - http: +# paths: +# - path: /bugs +# backend: +# serviceName: frontend-bugs +# servicePort: 8080 diff --git a/Resources/k8s/kustomize/other/namespace.yaml b/Resources/k8s/kustomize/other/namespace.yaml new file mode 100644 index 00000000..c8a37685 --- /dev/null +++ b/Resources/k8s/kustomize/other/namespace.yaml @@ -0,0 +1,6 @@ +kind: Namespace +apiVersion: v1 +metadata: + name: pokeapi + labels: + name: pokeapi diff --git a/Resources/k8s/kustomize/secrets/postgres.env b/Resources/k8s/kustomize/secrets/postgres.env new file mode 100644 index 00000000..e89c6d6a --- /dev/null +++ b/Resources/k8s/kustomize/secrets/postgres.env @@ -0,0 +1 @@ +POSTGRES_PASSWORD=pokeapi-change-me \ No newline at end of file diff --git a/Resources/k8s/kustomize/secrets/postgres.env.sample b/Resources/k8s/kustomize/secrets/postgres.env.sample new file mode 100644 index 00000000..e89c6d6a --- /dev/null +++ b/Resources/k8s/kustomize/secrets/postgres.env.sample @@ -0,0 +1 @@ +POSTGRES_PASSWORD=pokeapi-change-me \ No newline at end of file diff --git a/Resources/k8s/kustomize/services/cloud.yaml b/Resources/k8s/kustomize/services/cloud.yaml new file mode 100644 index 00000000..08bc3d98 --- /dev/null +++ b/Resources/k8s/kustomize/services/cloud.yaml @@ -0,0 +1,23 @@ +kind: Service +apiVersion: v1 +metadata: + name: haproxy-ingress + labels: + component: haproxy-ingress +spec: + type: LoadBalancer # TODO: Change to `LoadBalancer` + externalTrafficPolicy: Local + ports: + - name: public-http + port: 80 + targetPort: http + - name: public-https + port: 443 + targetPort: http + - name: public-stat + port: 1936 + targetPort: stat + selector: + component: haproxy-ingress +--- + diff --git a/Resources/k8s/kustomize/services/default-service.yaml b/Resources/k8s/kustomize/services/default-service.yaml new file mode 100644 index 00000000..dc308ba4 --- /dev/null +++ b/Resources/k8s/kustomize/services/default-service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: default-backend + labels: + component: default-backend +spec: + selector: + component: default-backend + ports: + - port: 8080 + targetPort: 8080 \ No newline at end of file diff --git a/Resources/k8s/kustomize/services/graphql-service.yaml b/Resources/k8s/kustomize/services/graphql-service.yaml new file mode 100644 index 00000000..e6804782 --- /dev/null +++ b/Resources/k8s/kustomize/services/graphql-service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: graphql + labels: + component: graphql +spec: + selector: + component: graphql + ports: + - port: 8080 + targetPort: 8080 diff --git a/Resources/k8s/kustomize/services/pokeapi-service.yaml b/Resources/k8s/kustomize/services/pokeapi-service.yaml new file mode 100644 index 00000000..aca4718a --- /dev/null +++ b/Resources/k8s/kustomize/services/pokeapi-service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: pokeapi + labels: + component: pokeapi + annotations: + ingress.kubernetes.io/balance-algorithm: leastconn +spec: + selector: + component: pokeapi + ports: + - port: 80 + targetPort: 80 diff --git a/Resources/k8s/kustomize/services/postgres-service.yaml b/Resources/k8s/kustomize/services/postgres-service.yaml new file mode 100644 index 00000000..bb404d29 --- /dev/null +++ b/Resources/k8s/kustomize/services/postgres-service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: postgresql + labels: + component: postgresql +spec: + selector: + component: postgresql + ports: + - port: 5432 + targetPort: 5432 diff --git a/Resources/k8s/kustomize/services/redis-service.yaml b/Resources/k8s/kustomize/services/redis-service.yaml new file mode 100644 index 00000000..00933212 --- /dev/null +++ b/Resources/k8s/kustomize/services/redis-service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: redis + labels: + component: redis +spec: + selector: + component: redis + ports: + - port: 6379 + targetPort: 6379 diff --git a/Resources/k8s/kustomize/volumes/postgres-persistentvolumeclaim.yaml b/Resources/k8s/kustomize/volumes/postgres-persistentvolumeclaim.yaml new file mode 100644 index 00000000..4866b63c --- /dev/null +++ b/Resources/k8s/kustomize/volumes/postgres-persistentvolumeclaim.yaml @@ -0,0 +1,27 @@ +kind: PersistentVolume +apiVersion: v1 +metadata: + name: postgres-volume0 + labels: + type: local + component: postgres +spec: + capacity: + storage: 10Gi + accessModes: + - ReadWriteOnce + hostPath: # TODO: change to a cloud-solution + path: "/mnt/data" +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: postgres-claim0 + labels: + component: postgres +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi diff --git a/Resources/k8s/kustomize/volumes/redis-persistentvolumeclaim.yaml b/Resources/k8s/kustomize/volumes/redis-persistentvolumeclaim.yaml new file mode 100644 index 00000000..d5f395c2 --- /dev/null +++ b/Resources/k8s/kustomize/volumes/redis-persistentvolumeclaim.yaml @@ -0,0 +1,27 @@ +kind: PersistentVolume +apiVersion: v1 +metadata: + name: redis-volume0 + labels: + type: local + component: redis +spec: + capacity: + storage: 2Gi + accessModes: + - ReadWriteOnce + hostPath: # TODO: change to a cloud-solution + path: "/mnt/data" +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-claim0 + labels: + component: redis +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 2Gi