# Deploy a Kubernetes application
The most common way to deploy an application on a plain Kubernetes is to use a deployment
. This does not yet make use of Knative, but only standard Kubernetes resources.
Here you can see an example of such a deployment, with all the additional parts included you need to make it work out of the box:
# cf-env-demo-app.yaml
---
# define our namespace "cf-env" where we place this standard Kubernetes deployment / app
apiVersion: v1
kind: Namespace
metadata:
labels:
app: cf-env
namespace.kubernetes.io/name: cf-env
name: cf-env
namespace: cf-env
---
# service account is optional, but we create one because it's good practice for Kubernetes "deployment"'s
apiVersion: v1
kind: ServiceAccount
metadata:
name: cf-env
namespace: cf-env
---
# the Kubernetes service that points to our app / deployment. It exposes container port 8080 to port 80 cluster-local wide.
apiVersion: v1
kind: Service
metadata:
name: cf-env
namespace: cf-env
spec:
ports:
- port: 80
targetPort: 8080
selector:
app: cf-env
app.kubernetes.io/component: app
app.kubernetes.io/instance: cf-env
app.kubernetes.io/name: cf-env
---
# this Ingress defines external access / routing to our app / deployment.
# it registers the route "cf-env.demo.kube-plus.cloud" and directs all HTTP(S) to the service specified above.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
# these annotations will give us automatic Lets-Encrypt integration with valid public certificates
cert-manager.io/cluster-issuer: letsencrypt-contour
ingress.kubernetes.io/force-ssl-redirect: "true"
kubernetes.io/ingress.class: contour # "contour" is the default ingress class you should use
kubernetes.io/tls-acme: "true"
name: cf-env
namespace: cf-env
spec:
tls:
- hosts:
- cf-env.demo.kube-plus.cloud # hostname / route we want our app to be
secretName: cf-env-tls
rules:
- host: cf-env.demo.kube-plus.cloud # hostname / route we want our app to be
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: cf-env
port:
number: 80
---
# finally our actual app deployment.
# it's just a simple HTTP app listening on port 8080.
apiVersion: apps/v1
kind: Deployment
metadata:
name: cf-env
namespace: cf-env
spec:
replicas: 2
revisionHistoryLimit: 5
selector:
matchLabels:
app: cf-env
app.kubernetes.io/component: app
app.kubernetes.io/instance: cf-env
app.kubernetes.io/name: cf-env
template:
metadata:
labels:
app: cf-env
app.kubernetes.io/component: app
app.kubernetes.io/instance: cf-env
app.kubernetes.io/name: cf-env
spec:
serviceAccountName: cf-env
securityContext:
fsGroup: 1007
runAsGroup: 1007
runAsUser: 1007
containers:
- name: cf-env
# here we specifiy which image we want to run. for this example its the simple "cf-env" app
image: index.docker.io/jamesclonk/cf-env@sha256:19ec75c211a2b05b5d9b78b5204dcf9b6d3240b275ffa35c42065d945d7f6508
securityContext:
allowPrivilegeEscalation: false
privileged: false
env:
- name: PORT
value: "8080"
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /
port: 8080
resources:
limits:
cpu: 100m
memory: 64Mi
requests:
cpu: 50m
memory: 32Mi
You can deploy this full-fledged example application via the kubectl
like this:
$ kubectl apply -f cf-env-demo-app.yaml
Here's how it should now look on the Kubernetes cluster:
$ kubectl -n cf-env get all,ing
NAME READY STATUS RESTARTS AGE
pod/cf-env-85c8ff55f5-4m97t 2/2 Running 0 29m
pod/cf-env-85c8ff55f5-rpnxc 2/2 Running 0 29m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/cf-env ClusterIP 10.100.156.35 <none> 80/TCP 29m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/cf-env 2/2 2 2 29m
NAME DESIRED CURRENT READY AGE
replicaset.apps/cf-env-85c8ff55f5 2 2 2 29m
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress.networking.k8s.io/cf-env <none> cf-env.demo.kube-plus.cloud a33e7d797ce6249d9b7b51891b9286da-1068130475.eu-central-1.elb.amazonaws.com 80, 443 29m
Afterwards you can access the application on the URL that was specified by the Ingress
definition. Simply point your browser here: cf-env.demo.kube-plus.cloud (opens new window)