apiVersion: apps/v1
kind: Deployment
metadata:
# deployment name
name: my_app
namespace: default
spec:
selector:
matchLabels:
# label for the deployment used by Service to connect
app: my_app
template:
metadata:
labels:
app: my_app
spec:
containers:
# container name in pod
- name: php
# docker image used for this container
image: my-php-fpm
# always get the docker image from registry
imagePullPolicy: Always
ports:
# port to communicate
- containerPort: 9000
# load environment variables from config map
envFrom:
- configMapRef:
name: my_app
# load encoded secret from Secrets manifest
- secretRef:
name: my_app_secrets
# set resources
resources:
requests:
memory: "64Mi"
cpu: "10m"
limits:
memory: "512Mi"
cpu: "100m"
# (optional)
lifecycle:
# used to trigger actions after container starts
postStart:
exec:
command:
- "/bin/bash"
- "-c"
- 'curl -s -X GET --max-time 3000 http://${SERVICE_NAME}.notifications.svc.cluster.local/start/${HOSTNAME}/php >&1; exit 0'
# used to trigger actions before container stops
preStop:
exec:
command:
- "/bin/bash"
- "-c"
- 'curl -s -X GET --max-time 3000 http://${SERVICE_NAME}.notifications.svc.cluster.local/stop/${HOSTNAME}/php >&1; exit 0'
# mount volumes for this container
volumeMounts:
# thumbnails volume
- mountPath: /app/web/thumbs
name: thumbnails
# files uploads volume
- mountPath: /uploads
name: uploads
# similar to above explanations
- name: nginx
image: my-nginx
imagePullPolicy: Always
ports:
- containerPort: 80
envFrom:
- configMapRef:
name: my_app
resources:
requests:
memory: "32Mi"
cpu: "10m"
limits:
memory: "256Mi"
cpu: "100m"
lifecycle:
postStart:
exec:
command:
- "/bin/bash"
- "-c"
- 'curl -s -X GET --max-time 3000 http://${SERVICE_NAME}.notifications.svc.cluster.local/start/${HOSTNAME}/php >&1; exit 0'
preStop:
exec:
command:
- "/bin/bash"
- "-c"
- 'curl -s -X GET --max-time 3000 http://${SERVICE_NAME}.notifications.svc.cluster.local/stop/${HOSTNAME}/php >&1; exit 0'
volumeMounts:
- mountPath: /app/web/thumbs
name: thumbnails
# all init containers will run before the main containers
initContainers:
- name: update-database
image: my-app-nginx
envFrom:
- configMapRef:
name: my-app-config
command:
- "bin/console"
- "setup:install"
# set volumes per deployment that will be used by containers using volumeMounts
volumes:
# define thumbnails directory as empty volume every time
- name: thumbnails
emptyDir: {}
# load uploads directory from PersistentVolumeClaim
- name: uploads
persistentVolumeClaim:
claimName: my-app-uploads
apiVersion: v1
kind: Service
metadata:
name: my-app-node-port
namespace: default
spec:
type: NodePort
selector:
app: my_app
ports:
- port: 80
targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: my-app-cluster-ip
namespace: defualt
spec:
type: ClusterIP
selector:
app: my_app
ports:
- port: 80
targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: my-app-load-balancer
namespace: default
spec:
type: LoadBalancer
selector:
app: my-app
ports:
- port: 80
targetPort: 80
---
# External Name
apiVersion: v1
kind: Service
metadata:
name: database-host
namespace: default
spec:
type: ExternalName
externalName: "__RDS_HOST__"
---
# External IPs
apiVersion: v1
kind: Service
metadata:
name: my-service
namespaece: default
spec:
ports:
- name: mysql
protocol: TCP
port: 3306
targetPort: 3306
externalIPs:
- 10.10.10.10
# Documentation: https://kubernetes.io/docs/concepts/services-networking/ingress/
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
namespace: default
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
controller.scope.enabled: "true"
controller.scope.namespace: "default"
spec:
# (optional) if you want to listen to 443 port
tls:
- hosts:
- www.example.com
# secret defined for SSL certificate
secretName: example.com-tls
rules:
- host: www.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app
port:
number: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-resource-backend
namespace: default
spec:
defaultBackend:
resource:
apiGroup: k8s.example.com
kind: StorageBucket
name: static-assets
rules:
- http:
paths:
- path: /icons
pathType: ImplementationSpecific
backend:
resource:
apiGroup: k8s.example.com
kind: StorageBucket
name: icon-assets
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-wildcard-host
namespace: default
spec:
rules:
- host: "foo.bar.com"
http:
paths:
- pathType: Prefix
path: "/bar"
backend:
service:
name: service1
port:
number: 80
- host: "*.foo.com"
http:
paths:
- pathType: Prefix
path: "/foo"
backend:
service:
name: service2
port:
number: 80
apiVersion: v1
kind: ConfigMap
metadata:
# config map name, will be used by deployments, cronjobs, etc
name: my-app-config
namespace: default
data:
APP_ENV: prod
MYSQL_HOST: "127.0.0.1"
MYSQL_USER: mysql_username_here
UPLOAD_DIRECTORY: /data/uploads
apiVersion: v1
kind: Secret
metadata:
name: my-app-secrets
namespace: default
data:
my_db_password: a2lzcGhw # base64 encoded
redis_password: a2lzcGhw # base64 encoded
# you can create secrets with the following command
#
# kubectl create secret general secret-name --from-literal=MYSQL_PASSWORD=mypass123 --from-literal=APP_SECRET=qawsed1234 -o yaml --dry-run
#
apiVersion: v1
kind: PersistentVolume
metadata:
name: uploaded-files
# PVs don't have a namespace
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 20Gi
accessModes:
- ReadWriteMany
hostPath:
path: /mnt/nfs/uploaded_files
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-app-uploads
namespace: default
spec:
storageClassName: manual
accessModes:
- ReadWriteMany
resources:
requests:
storage: 20Gi
# if you define PVC for AWS EFS, just set the storage to 1Gi, no matter how big the EFS is
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: my-cron-job
namespace: default
labels:
app: my-cron-job
spec:
# run every minute
schedule: "* * * * *"
# do not allow concurrent jobs
concurrencyPolicy: Forbid
# delete successful pods
successfulJobsHistoryLimit: 0
# keep last 2 failed pods for debug
failedJobsHistoryLimit: 2
startingDeadlineSeconds: 120
suspend: false
jobTemplate:
spec:
template:
metadata:
labels:
app: my-cron-job
spec:
restartPolicy: Never
nodeSelector:
type: cron
containers:
# name of the container in pod
- name: app-cron
# docker image to load for this container
image: my-php-container:tag_name
# always download image from registry
imagePullPolicy: Always
# define necessary resources for this container
resources:
requests:
cpu: "1"
memory: "256Mi"
limits:
cpu: "1"
memory: "1Gi"
# load all variables defined in config map
envFrom:
- configMapRef:
name: my-app-config
env:
# set inline variable for container
- name: CONTAINER_PURPOSE
value: cron
# register a secret (password) to env vars from secrets manifests
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: my-app-secrets
# reference to variable name in secrets manifest
key: my_db_password
command:
- vendor/bin/codecept
args:
- run
- "--dry-run"
volumeMounts:
- name: project-data
mountPath: /stored_data
volumes:
# using aws EFS
- name: project-data
nfs:
server: 1a2b3c4d.efs.eu-central-1.amazonaws.com
path: /
# using PVC
- name: uploads
persistentVolumeClaim:
claimName: uploaded-files
apiVersion: batch/v1
kind: Job
metadata:
name: thumbs-cleanup
namespace: default
spec:
template:
spec:
restartPolicy: Never
containers:
- name: php
image: my-custom-container
imagePullPolicy: Always
command:
- vendor/bin/console
- cleanup:thumbs
envFrom:
- configMapRef:
name: my-config
env:
- name: CONTAINER_PURPOSE
value: job
- name: MY_DB_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-password
key: password