
Pods and services
As already mentioned, Kubernetes does not deploy containers; instead, it launches pods. In its most simple form, a pod can actually be a single container; however, typically a pod is made up of several containers, storage, and networking.
The following is meant to be illustrative and not a practical example; we will be working through a practical example in the next chapter.
Think of a pod as a complete application; for example, if you were running a simple web application it would probably be running a single NGINX container—the pod definition file for this would look something like the following:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 8080
As you can see, we are providing some simple metadata about our pod, which in this case is just the name so we can identify it. We then have a single container defined, which is running the latest NGINX image from the Docker hub and port 8080 is exposed.
As it stands, this pod is quite useless as we are only going to display a Welcome to nginx! page. Next up, we need to add a volume to store our website data in. To do this, our pod definition file would look like this:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:latest
volumeMounts:
- mountPath: /srv/www
name: web-data
readOnly: true
ports:
- containerPort: 8080
volumes:
- name: web-data
emptyDir: {}
As you can see, we are now creating a volume called web-data and mounting it read-only at /srv/www, which is the default web root on our NGINX container. It is still a little pointless as our volume is empty, meaning that all our visitors will see is a 404 page.
Let's add a second container, which will sync our website's HTML from an Amazon S3 bucket:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:latest
volumeMounts:
- mountPath: /srv/www
name: web-data
readOnly: true
ports:
- containerPort: 8080
- name: sync
image: ocasta/sync-s3:latest
volumeMounts:
- mountPath: /data
name: web-data
readOnly: false
env:
- ACCESS_KEY: "awskey"
SECRET_KEY: "aws_secret"
S3_PATH: "s3://my-awesome-website/"
SYNC_FROM_S3: "true"
volumes:
- name: web-data
emptyDir: {}
Now we have two containers: the NGINX one and now a container running the s3 sync command (https://github.com/ocastastudios/docker-sync-s3/). This will copy all of our website data from the Amazon S3 bucket called my-awesome-website to the volume that is also being shared with the NGINX container. This means we now have a website; note that this time, as we want to write to the volume, we are not mounting it read-only.
So far, so good, you might be thinking to yourself; we have a pod serving our website that is being deployed from an Amazon S3 bucket, which is all true. However, we have not quite finished. We have a pod running, but we need to expose that pod to the network to be able to access it in a browser.
To do this, we need to launch a service. For our example, the service file would look something like:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 8080
As you can see, the service definition looks similar to the pod one. We are setting a name using the metadata section. We are then selecting our NGINX pod and mapping port 80 to port 8080, which is what our pod is listening on.
As already mentioned, we will look at this in more detail in the next chapter when we launch our first Kubernetes cluster, but for now, this should give you a good idea of how Kubernetes hangs together.