This guide explains how to create the manifest files necessary to deploy your application on a Kubernetes cluster.
For demonstration purposes, we will use a sample docker-compose file descibing a simple application with a MySql database and convert its services into proper manifest files.
version: '3'
services:
mysql:
image: mysql:8.2
ports:
- "3406:3306"
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: my-app-db
MYSQL_USER: username
MYSQL_PASSWORD: secret
volumes:
- 'mysql-data:/var/lib/mysql'
my-app:
image: registry/my-app:1.0.0
ports:
- "8080:8080"
environment:
SERVER_PORT: 8080
DB_HOST: mysql:3306
DB_DATABASE: bookstack
DB_USERNAME: my-app-db
DB_PASSWORD: secret
volumes:
- 'app-data:/home/app/data'
volumes:
mysql-data:
app-data:If your application relies on database or other third-party software, you should use their corresponding Helm charts. In this repository, you can find several examples of using Helm charts to deploy databases and other tools. Here are some examples:
Remember to add required secrets within the
templatesfolder
You need to create the following resource files for each service in your docker-compose. So the first step is to create the folder structure for your application within the proper environment directory.
Here is the folder structure for the demo application:
ionos_<env>/
└── app-name/
└── mysql/
└── templates/
└── Chart.yaml
...
└── my-app/
└── deployment.yaml
...
⚠️ The resources described below are those required for deploying the sample application. Other applications may require additional resources or may not need all those described.
A Deployment provides declarative updates for Pods and ReplicaSets. You describe a desired state in a Deployment, and the Deployment Controller changes the actual state to the desired state.
Here is the deployment file for the demo application:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: my-app
labels:
app.kubernetes.io/instance: my-app
app.kubernetes.io/name: my-app
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/instance: my-app
app.kubernetes.io/name: my-app
template:
metadata:
labels:
app.kubernetes.io/instance: my-app
app.kubernetes.io/name: my-app
spec:
containers:
- name: my-app
image: registry/my-app:1.0.0
env:
- name: SERVER_PORT
value: 8080
- name: DB_HOST
value: "<name of mysql service>:3306"
- name: DB_DATABASE
value: my-app-db
- name: DB_USERNAME
value: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: my-app-secret
key: DB_PASSWORD
ports:
- containerPort: 8080
name: http
protocol: TCP
volumeMounts:
- mountPath: /home/app/data
name: my-app-storage
volumes:
- name: my-app-storage
persistentVolumeClaim:
claimName: my-app-pvcNotes
- The name of MySql service should be set in the corresponding Helm Chart within the values file
- The value of
claimnamemust match the one used in the Persistent Volume Claim file.
A PersistentVolumeClaim (PVC) is a request for storage by a user. Claims can request specific size and access modes.
Here is the PVC file for the demo application:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-app-pvc
namespace: my-app
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5GiA Service is a method for exposing a network application that is running as one or more Pods in your cluster.
Here is the service file for the demo application:
apiVersion: v1
kind: Service
metadata:
name: my-app
namespace: my-app
spec:
type: ClusterIP
selector:
app.kubernetes.io/instance: my-app
app.kubernetes.io/name: my-app
ports:
- name: http
port: 8080
protocol: TCP
targetPort: 8080A Ingress is an API object that manages external access to the services in a cluster, typically HTTP. Ingress may provide load balancing, SSL termination and name-based virtual hosting.
Here is the ingress file for the demo application:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
namespace: my-app
annotations:
cert-manager.io/cluster-issuer: letsencrypt-dev-issuer
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
spec:
ingressClassName: nginx
rules:
- host: my-app.dome-marketplace-dev.org
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app
port:
number: 8080
tls:
- hosts:
- my-app.dome-marketplace-dev.org
secretName: my-app-tls-secretNotes
- Hosts are automatically craeted and managed by External-DNS
- The value of
backend.service.namemust match the name of the Service - The value of
backend.service.port.numbermust match the one defined in the Service
A Secret is an object that contains a small amount of sensitive data such as a password, a token, or a key. Using a Secret means that you don't need to include confidential data in your application code.
Here is the secret file for the demo application:
apiVersion: v1
kind: Secret
metadata:
name: my-app-secret
namespace: my-app
stringData:
DB_PASSWORD: "secret"
⚠️ Remember, plain secrets should never be pushed to the repository. You should first encrypt them using SealedSecret as described here.