Skip to content

Instantly share code, notes, and snippets.

@ndrean
Last active August 21, 2021 16:48
Show Gist options
  • Save ndrean/fc848097f9417ff5e348b9622d10867f to your computer and use it in GitHub Desktop.
Save ndrean/fc848097f9417ff5e348b9622d10867f to your computer and use it in GitHub Desktop.
k8 manifests for Rails, Postgres, Redis, AcitonCable standalone, Nginx in front passing websockets

emptyDir: {}

spec.volumes:
  - name: shared-data
    emptyDir: {}
spec.containers:
  - name: nginx
    image: nginx:1.21.1-alpine
    volumeMounts:
      - name: shared-data
        mountPath: /usr/share/nginx/html
  - name: rails
    image: usr/rails-base
    volumeMounts:
    - name: shared-data
      mountPath: /public

httpGet ReadinessProbe

readinessProbe:
httpGet:
  path: /ready
  port: 3000
  scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 30
timeoutSeconds: 2

POstgreSQL Deployment

#pg-dep.yml
apiVersion: v1
kind: Service
metadata:
name: pg-svc
labels:
  app: pg # <- must match with the pod
spec:
ports:
  - protocol: TCP
    port: 5432 # <- service port opened for Rails
selector:
  # the set of pods with the name 'pg' is targeted by this service
  app: pg

---
# Deployment
apiVersion: apps/v1
kind: StatefulSet
metadata:
# about the deployment itself. Gives a name of the DEPLOYMENT
name: pg-dep
labels:
  app: pg
spec: # of the deployment
serviceName: pg-dep
replicas: 1
selector:
  # the deployment must match all pods with the label "app: pg"
  matchLabels:
    # the label for the POD that the deployment is targeting
    app: pg # match spec.template.labels for the pod
template: # blue print of a pod
  metadata:
    name: pg-pod
    # label for the POD that the deployment is deploying
    labels:
      app: pg # match spec.selector.matchlabels
  spec:
    volumes:
      - name: pg-pv # must match PV
        persistentVolumeClaim:
          claimName: pg-pvc # must match PVC
    containers:
      - name: pg-container
        image: postgres:13.3-alpine
        imagePullPolicy: "IfNotPresent"
        resources:
          limits:
            memory: "128Mi"
            cpu: "50m"
        ports:
          - containerPort: 5432
        volumeMounts:
          - mountPath: $(PGDATA)
            name: pg-pv # must match pv
            readOnly: false
        envFrom:
          - configMapRef:
              name: config
          - secretRef:
              name: secrets
---
# we bind the resource PV to the pod
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pg-pvc
spec:
#storageClassName: standard
accessModes:
  - ReadWriteMany
resources:
  requests:
    storage: 100Mi
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pg-pv
  labels:
    app: pg
spec:
  storageClassName: standard
  capacity:
    storage: 150Mi
  accessModes:
    - ReadWriteMany
  hostPath: # for Minikube, emulate net. attached vol.
    path: "/tmp/data"

#nginx Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-dep
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - image: usr/nginx-ws
          imagePullPolicy: "Always"
          name: frontend
          ports:
            - containerPort: 9000
          resources:
            limits:
              cpu: "32m"
              memory: "16Mi"
          volumeMounts:
            - mountPath: "/etc/nginx/conf.d" # mount nginx-conf volume to /etc/nginx
              readOnly: true
              name: nginx-conf
      volumes:
        - name: nginx-conf
          configMap:
            name: nginx-conf # place ConfigMap `nginx-conf` on /etc/nginx
            items:
              - key: myconfig.conf
                path: default.conf

--------
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  labels:
    app: nginx
spec:
  type: LoadBalancer # NodePort # LoadBalancer # <- external service
  selector:
    app: nginx
  ports:
    - protocol: TCP
      # port exposed by the container
      port: 80
      # the port the app is listening on targetPort
      targetPort: 9000
      nodePort: 31000

and config:

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-conf
data:
  myconfig.conf: |
    upstream puma {
      server rails-svc:3000;
      keepalive 1024;
    }

    access_log  /dev/stdout main;
    error_log   /dev/stdout info;

    server {
      listen 9000 default_server;
      root /usr/share/nginx/html;
      try_files  $uri @puma;
      access_log  off;
      gzip_static on; 
      expires     max;
      add_header  Cache-Control public;
      add_header  Last-Modified "";
      add_header  Etag "";

      location @puma {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header Host $http_host;
        proxy_pass_header   Set-Cookie;
        proxy_redirect off;
        proxy_pass http://puma;
      }

      location /cable {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_pass "http://cable-svc:28080";
      }

      error_page 500 502 503 504 /500.html;
      error_page 404             /404.html;
      location = /50x.html {
        root /usr/share/nginx/html;
      }
    }

Redis

apiVersion: v1
kind: PersistentVolume
metadata:
  name: data
  labels:
    app: data
spec:
  # storageClassName: "standard"
  capacity:
    storage: 150Mi
  accessModes:
    - ReadWriteMany
  hostPath: # for dvpt on single-node such as Minikube, to emulate network attached vol
    path: "/data"

apiVersion: v1
kind: Service
metadata:
 name: redis-svc
spec:
 ports:
   - port: 6379
     targetPort: 6379
     name: client
 selector:
   app: redis

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
 name: redis-dep
 labels:
   app: redis
spec:
 serviceName: redis
 selector:
   matchLabels:
     app: redis # match spec.template.labels
 replicas: 1
 template:
   metadata:
     name: redis-pod
     labels:
       app: redis # match spec.selector.matchLabels
   spec:
     containers:
       - name: redis
         image: redis:6.2.4-alpine
         imagePullPolicy: "IfNotPresent"
         command: ["redis-server"]
         ports:
           - containerPort: 6379
         resources:
           limits:
             cpu: "50m"
             memory: "50Mi"
         livenessProbe:
           exec:
             command: ["redis-cli", "ping"]
           initialDelaySeconds: 30
           periodSeconds: 30
           timeoutSeconds: 3
         volumeMounts:
           # -  mountPath: /redis-master  # <- the config vol is mounted here
           #    name: config
           #    readOnly: true
           - name: data
             mountPath: "/data"
             readOnly: false
     # volumes:
     #   - name: config-redis
     #     configMap:
     #       name: redis-conf
     # items:
     # - key: redis-config
     # path: redis.conf
 volumeClaimTemplates:
   - metadata:
       name: data
     spec:
       accessModes: ["ReadWriteMany"] # <- changed from many
       # storageClassName: ""
       resources:
         requests:
           storage: 110Mi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment