Skip to content

Instantly share code, notes, and snippets.

@halkyon
Last active July 15, 2020 00:53
Show Gist options
  • Save halkyon/2f1d9759a3a941e0e7d9b27723a5f7af to your computer and use it in GitHub Desktop.
Save halkyon/2f1d9759a3a941e0e7d9b27723a5f7af to your computer and use it in GitHub Desktop.
Kubernetes YAML (namespace, service, ingress, deployment) for running a very simple setup of Ghost (https://github.com/TryGhost/Ghost)
# Simple setup of Ghost in Kubernetes.
#
# Some points to consider:
# - Content is stored in a single persistent disk, and database is SQLite. Using a dedicated database would be ideal
# for bigger deployments, and using distributed storage would allow pods to horizontally scale, e.g. GlusterFS, EFS.
#
# - A load balancer is provisioned for external traffic to access the blog service. For a multi-tenanted approach,
# nginx ingress controller (https://kubernetes.github.io/ingress-nginx/deploy/) could be used.
#
# - No TLS for the service. This could be accomplished using GCP, or AWS managed certs on the load balancer.
# A more flexible option that uses Let's Encrypt would be cert-manager (https://cert-manager.io/docs/) which is
# slightly more setup and management, but offers more flexibility.
#
apiVersion: v1
kind: Namespace
metadata:
name: blog
labels:
app.kubernetes.io/name: blog
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: blog
namespace: blog
labels:
app.kubernetes.io/name: blog
rules: []
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: blog
namespace: blog
labels:
app.kubernetes.io/name: blog
subjects:
- kind: ServiceAccount
name: blog
roleRef:
kind: Role
name: blog
apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: blog
namespace: blog
labels:
app.kubernetes.io/name: blog
automountServiceAccountToken: false
---
apiVersion: v1
kind: Service
metadata:
name: blog
namespace: blog
labels:
app.kubernetes.io/name: blog
spec:
type: LoadBalancer
externalTrafficPolicy: Local
ports:
- name: http
port: 80
protocol: TCP
targetPort: 2368
selector:
app.kubernetes.io/name: blog
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: blog
namespace: blog
labels:
app.kubernetes.io/name: blog
spec:
rules:
- host: mydomain.com
http:
paths:
- path: /
backend:
serviceName: blog
servicePort: 80
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: blog-content
namespace: blog
labels:
app.kubernetes.io/name: blog
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: blog
namespace: blog
labels:
app.kubernetes.io/name: blog
spec:
selector:
matchLabels:
app.kubernetes.io/name: blog
revisionHistoryLimit: 10
minReadySeconds: 0
template:
metadata:
labels:
app.kubernetes.io/name: blog
spec:
serviceAccountName: blog
securityContext:
fsGroup: 10001
volumes:
- name: content
persistentVolumeClaim:
claimName: blog-content
containers:
- name: ghost
image: ghost:3-alpine
imagePullPolicy: IfNotPresent
securityContext:
runAsNonRoot: true
runAsUser: 10001
runAsGroup: 10001
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
volumeMounts:
- name: content
mountPath: /var/lib/ghost/content
ports:
- name: http
containerPort: 2368
protocol: TCP
env:
- name: url
value: http://mydomain.com
readinessProbe:
httpGet:
path: /
port: 2368
scheme: HTTP
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 1
successThreshold: 1
failureThreshold: 3
resources:
limits:
cpu: 1000m
memory: 500Mi
requests:
cpu: 100m
memory: 50Mi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment