├── service.yaml ├── configmap.yaml ├── Dockerfile ├── deployment-horizon.yaml ├── cronjob.yaml ├── ingress.yaml ├── .gitlab-ci.yml └── deployment-app.yaml /service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app: backend 6 | name: backend 7 | spec: 8 | ports: 9 | - name: http 10 | port: 80 11 | protocol: TCP 12 | selector: 13 | app: backend 14 | type: ClusterIP 15 | -------------------------------------------------------------------------------- /configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: backend-config 5 | data: 6 | APP_DEBUG: "false" 7 | APP_ENV: production 8 | APP_KEY: changeme 9 | APP_LOG_LEVEL: debug 10 | APP_NAME: "Laravel K8s" 11 | APP_URL: https://www.laravel.com 12 | BROADCAST_DRIVER: pusher 13 | CACHE_DRIVER: redis 14 | QUEUE_DRIVER: redis 15 | SESSION_DRIVER: redis 16 | DB_CONNECTION: mysql 17 | DB_DATABASE: backend 18 | DB_HOST: changeme 19 | DB_PASSWORD: beta1234 20 | DB_PORT: "3306" 21 | DB_USERNAME: beta 22 | REDIS_HOST: redis 23 | REDIS_PORT: "6379" 24 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ARG PHP_EXTENSIONS="apcu bcmath opcache pcntl pdo_mysql redis zip sockets imagick gd exif" 2 | FROM thecodingmachine/php:7.3-v2-slim-apache as php_base 3 | ENV TEMPLATE_PHP_INI=production \ 4 | APACHE_DOCUMENT_ROOT=/var/www/html/public 5 | COPY --chown=docker:docker . /var/www/html 6 | RUN composer install --quiet --optimize-autoloader --no-dev 7 | 8 | FROM node:10 as node_dependencies 9 | WORKDIR /var/www/html 10 | ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=false 11 | COPY --from=php_base /var/www/html /var/www/html 12 | RUN npm set progress=false && \ 13 | npm config set depth 0 && \ 14 | npm install && \ 15 | npm run prod && \ 16 | rm -rf node_modules 17 | 18 | FROM php_base 19 | COPY --from=node_dependencies --chown=docker:docker /var/www/html /var/www/html 20 | 21 | 22 | -------------------------------------------------------------------------------- /deployment-horizon.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: horizon 6 | name: horizon 7 | spec: 8 | replicas: 1 9 | revisionHistoryLimit: 1 10 | selector: 11 | matchLabels: 12 | app: horizon 13 | template: 14 | metadata: 15 | labels: 16 | app: horizon 17 | spec: 18 | containers: 19 | - args: 20 | - /bin/bash 21 | - -c 22 | - php artisan horizon 23 | envFrom: 24 | - configMapRef: 25 | name: backend-config 26 | image: changeme 27 | imagePullPolicy: Always 28 | name: horizon 29 | resources: 30 | limits: 31 | cpu: 200m 32 | memory: 1G 33 | requests: 34 | cpu: 100m 35 | memory: 500M 36 | -------------------------------------------------------------------------------- /cronjob.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1beta1 2 | kind: CronJob 3 | metadata: 4 | name: backend-cron 5 | spec: 6 | concurrencyPolicy: Replace 7 | failedJobsHistoryLimit: 1 8 | jobTemplate: 9 | spec: 10 | activeDeadlineSeconds: 120 11 | backoffLimit: 1 12 | template: 13 | spec: 14 | containers: 15 | - args: 16 | - /bin/bash 17 | - -c 18 | - php artisan schedule:run 19 | envFrom: 20 | - configMapRef: 21 | name: backend-config 22 | image: changeme 23 | imagePullPolicy: Always 24 | name: artisan-schedule 25 | resources: 26 | limits: 27 | cpu: 200m 28 | memory: 200M 29 | requests: 30 | cpu: 100m 31 | memory: 100M 32 | restartPolicy: Never 33 | schedule: "*/1 * * * *" 34 | startingDeadlineSeconds: 30 35 | successfulJobsHistoryLimit: 1 36 | -------------------------------------------------------------------------------- /ingress.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/force-ssl-redirect: "true" 6 | nginx.ingress.kubernetes.io/from-to-www-redirect: "true" 7 | nginx.ingress.kubernetes.io/proxy-body-size: 100m 8 | labels: 9 | app: backend 10 | name: backend 11 | spec: 12 | rules: 13 | - host: yourdomain.com 14 | http: 15 | paths: 16 | - backend: 17 | serviceName: backend 18 | servicePort: 80 19 | path: / 20 | # tls: 21 | # - hosts: 22 | # - yourdomain.com 23 | # secretName: yourdomain-com-tls 24 | # --- 25 | # apiVersion: certmanager.k8s.io/v1alpha1 26 | # kind: Certificate 27 | # metadata: 28 | # name: yourdomain.com 29 | # spec: 30 | # acme: 31 | # config: 32 | # - dns01: 33 | # provider: cf-dns 34 | # domains: 35 | # - yourdomain.com 36 | # commonName: yourdomain.com 37 | # dnsNames: 38 | # - yourdomain.com 39 | # issuerRef: 40 | # kind: ClusterIssuer 41 | # name: letsencrypt 42 | # secretName: yourdomain-com-tls 43 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | variables: 2 | DOCKER_DRIVER: "overlay2" 3 | REPOSITORY_URL: "changeme:latest" 4 | 5 | stages: 6 | - build 7 | - deploy 8 | 9 | services: 10 | - docker:dind 11 | 12 | build-app: 13 | stage: build 14 | tags: 15 | - docker 16 | script: 17 | - mkdir -p $HOME/.docker 18 | - apk add --no-cache curl jq python py-pip 19 | - pip install awscli 20 | - $(aws ecr get-login --no-include-email --region ap-southeast-1) 21 | - docker info 22 | - docker build -t ${REPOSITORY_URL} . 23 | - docker push ${REPOSITORY_URL} 24 | 25 | deploy-app: 26 | stage: deploy 27 | image: alpine 28 | only: 29 | - master 30 | script: 31 | - apk add --no-cache curl 32 | - curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl 33 | - chmod +x ./kubectl 34 | - mv ./kubectl /usr/local/bin/kubectl 35 | - kubectl config set-cluster k8s --server="$KUBE_URL" --insecure-skip-tls-verify=true 36 | - kubectl config set-credentials admin --token="$KUBE_TOKEN" 37 | - kubectl config set-context default --cluster=k8s --user=admin 38 | - kubectl config use-context default 39 | - cd k8s && kubectl apply -f - 40 | - kubectl patch deployment backend -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"`date +'%s'`\"}}}}}" 41 | -------------------------------------------------------------------------------- /deployment-app.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: backend 6 | name: backend 7 | spec: 8 | minReadySeconds: 5 9 | replicas: 3 10 | revisionHistoryLimit: 1 11 | selector: 12 | matchLabels: 13 | app: backend 14 | strategy: 15 | rollingUpdate: 16 | maxSurge: 1 17 | maxUnavailable: 50% 18 | type: RollingUpdate 19 | template: 20 | metadata: 21 | labels: 22 | app: backend 23 | spec: 24 | affinity: 25 | podAntiAffinity: 26 | preferredDuringSchedulingIgnoredDuringExecution: 27 | - podAffinityTerm: 28 | labelSelector: 29 | matchExpressions: 30 | - key: app 31 | operator: In 32 | values: 33 | - backend 34 | topologyKey: kubernetes.io/hostname 35 | weight: 100 36 | initContainers: 37 | - args: 38 | - /bin/bash 39 | - -c 40 | - (php artisan migrate || true) && (php artisan config:cache || true) && (php 41 | artisan route:cache || true) && (cp -rp /var/www/html /codebase) 42 | envFrom: 43 | - configMapRef: 44 | name: backend-config 45 | image: changeme 46 | imagePullPolicy: Always 47 | name: artisan 48 | volumeMounts: 49 | - mountPath: /codebase 50 | name: codebase 51 | 52 | containers: 53 | - name: app 54 | envFrom: 55 | - configMapRef: 56 | name: backend-config 57 | image: changeme 58 | imagePullPolicy: Always 59 | livenessProbe: 60 | initialDelaySeconds: 10 61 | periodSeconds: 15 62 | tcpSocket: 63 | port: 80 64 | timeoutSeconds: 30 65 | ports: 66 | - containerPort: 80 67 | readinessProbe: 68 | initialDelaySeconds: 10 69 | periodSeconds: 10 70 | tcpSocket: 71 | port: 80 72 | resources: 73 | limits: 74 | cpu: 200m 75 | memory: 400M 76 | requests: 77 | cpu: 100m 78 | memory: 200M 79 | volumeMounts: 80 | - mountPath: /var/www 81 | name: codebase 82 | 83 | volumes: 84 | - emptyDir: {} 85 | name: codebase 86 | --------------------------------------------------------------------------------