Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 34 additions & 32 deletions accessing-your-application.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@

Deploying a pod is not enough to make it accessible from outside the cluster.

In this exercise you will learn how to make temporary connections to a pod inside the cluster via
In this exercise, you will learn how to make temporary connections to a pod inside the cluster via
`kubectl port-forward`.

## Port-forward

The `kubectl port-forward` command allows you to forward one or more local ports to a pod. This can
be used to access a pod that is running in the cluster, using for example a web browser or a
be used to access a pod that is running in the cluster, using a web browser or a
command line tool like `curl`.

The command takes two arguments: the pod name and the port to forward. The port is specified as
Expand All @@ -32,14 +32,16 @@ You can then access the pod on `localhost:8080`.
<details>
<summary>:bulb: How does this port-forward work?</summary>

Port forwarding is a network address translation that redirects internet packets form one IP address
with specified port number to another `IP:PORT` set.
Port forwarding is a network address translation that redirects Internet packets from one IP address
to another with a specified port number to another `IP:PORT` set.

In Kubernetes `port-forward` creates a tunnel between your local machine and Kubernetes cluster on
the specified `IP:PORT` pairs in order to establish connection to the cluster.
`kubectl port-forward` allows you to forward not only pods but also services, deployments and other.
The `port-forward` command in Kubernetes forwards incoming traffic to the machine, the command is
executed on, to the specified `IP:PORT` pairs inside the Kubernetes cluster. This effectively
lets traffic from outside the cluster reach applications running inside the cluster.
`kubectl port-forward` allows you to forward traffic to pods, services, deployments, and others.

More information can be found from [here](https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/)
More information can be found in the Kubernetes docs at
[Use Port Forwarding to Access Applications in a Cluster](https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/)

</details>

Expand All @@ -58,7 +60,7 @@ More information can be found from [here](https://kubernetes.io/docs/tasks/acces

> :bulb: If you get stuck somewhere along the way, you can check the solution in the done folder.

### Step by step instructions
### Step-by-step instructions

<details>
<summary>
Expand All @@ -78,7 +80,7 @@ The pod is defined in the `frontend-pod.yaml` file.

</details>

- Check that the pod is running with `kubectl get pods` command.
- Use the `kubectl get pods` command to verify that the pod is running.

You should see something like this:

Expand All @@ -87,32 +89,32 @@ NAME READY STATUS RESTARTS AGE
frontend 1/1 Running 0 2m
```

- Expose the frontend with port-forward
- Expose the frontend with `port-forward`

Port forward can be achieved with:
Port forwarding can be achieved with:

`kubectl port-forward --address 0.0.0.0 frontend 8080:5000`

> :bulb: We add the `--address 0.0.0.0` option to the port-forward command to make it accept
> commands coming from remote machines, like your laptop! `0.0.0.0` Means any address, so you
> probably don't want to do this on your own machine in, unless you want to expose something
> probably don't want to do this on your machine unless you want to expose something
> to the internet.
Comment on lines +100 to 101
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not safe, but necessary if you are running the port-forward in an online training infrastructure
and want to test the port forwarding from the browser on your laptop. You do not usually want to use this option.


It can now be accessed on `http://workstation-<number>.<prefix>.eficode.academy:8080`
(from the internet). Notice the plain, unencrypted `http` connection. It is not `https`, and your
browser may complain about it. TLS is an advanced topic and out of scope for now.
browser may complain about it. TLS is an advanced topic and is currently out of scope.

> :bulb: VSCode will ask you if you what to see the open port. Unfortunately vscode proxy does not
> proxy requests correctly back to the pod, so use the URL of the instance instead.
:bulb: VSCode will prompt you to view the open port. Unfortunately, vscode proxy does not
> proxy requests correctly back to the pod, so use the URL of the workstation instance instead.

- Look at it in the browser.

Now we will deploy both the frontend and backend pods.

- Stop the port-forward process by pressing `Ctrl-c` in the terminal.
- Delete the frontend pod with `kubectl delete pod frontend` command.
- Deploy the backend pod with `kubectl apply -f backend-pod.yaml` command.
- Check that the pod is running, and note down the IP with `kubectl get pods -o wide` command.
- Delete the frontend pod with the `kubectl delete pod frontend` command.
- Deploy the backend pod with the `kubectl apply -f backend-pod.yaml` command.
- Check that the pod is running, and note down the IP with the `kubectl get pods -o wide` command.

You should see something like this:

Expand All @@ -123,7 +125,7 @@ NAME READY STATUS RESTARTS AGE IP NODE
backend 1/1 Running 0 11s 10.0.40.196 ip-10-0-35-102.eu-west-1.compute.internal <none> <none>
```

In this case the IP is `10.0.40.196`, but it will be different in your case.
In this case, the IP is `10.0.40.196`, but it will be different in your case.

#### Add environment variables to the frontend pod

Expand Down Expand Up @@ -178,9 +180,9 @@ spec:

</details>

- Deploy the frontend pod with `kubectl apply -f frontend-pod.yaml` command.
- Deploy the frontend pod with the `kubectl apply -f frontend-pod.yaml` command.

- Check that the pod is running with `kubectl get pods` command.
- Check that the pod is running with the `kubectl get pods` command.

- Forward a local port to the pod using `kubectl port-forward`.

Expand All @@ -190,9 +192,9 @@ You should see something like this:

![alt](img/app-front-back.png)

(if you don't you might need to refresh the page)
(If you don't, you might need to refresh the page.)

- Exec into the frontend pod with `kubectl exec -it frontend -- /bin/sh` command.
- Exec into the frontend pod with the command `kubectl exec -it frontend -- /bin/sh`.

- Execute a curl command to the backend `curl http://<BACKEND_IP>:5000`.

Expand All @@ -205,10 +207,10 @@ Extra exercise

While still having the port-forward running

- Access the frontend in the browser and check that it still works and that frontend has access to
- Access the frontend in the browser and check that it still works and that the frontend has access to
the backend.
- Try to delete the backend pod with `kubectl delete pod backend` command.
- Try to recreate the backend pod with `kubectl apply -f backend-pod.yaml` command.
- Try to delete the backend pod with the command `kubectl delete pod backend`.
- Try to recreate the backend pod with the command `kubectl apply -f backend-pod.yaml`.
- Access the frontend in the browser.
- Does it still have access to the backend?

Expand All @@ -218,10 +220,10 @@ If not, why not?
<summary>Solution</summary>

The frontend pod is not configured to automatically re-resolve the backend IP address.
So when we deleted the pod, and recreated it, the IP address changed, but the frontend pod still
So when we deleted the pod and recreated it, the IP address changed, but the frontend pod still
has the old IP address in its environment variables.

Thankfully Kubernetes has a networking abstraction called `services` which solves this exact (and
Thankfully, Kubernetes has a networking abstraction called `services` which solves this exact (and
more!) problem, which we will learn about in the next exercise.

</details>
Expand All @@ -230,9 +232,9 @@ more!) problem, which we will learn about in the next exercise.

### Clean up

- Stop the port-forward with `Ctrl+C` command.
- Delete the pod with `kubectl delete pod frontend` command.
- Delete the pod with `kubectl delete pod backend` command.
- Stop the port-forward with the `Ctrl+C` command.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Stop the port-forward with the `Ctrl+C` command.
- Stop the port-forward by pressing `Ctrl+C`.

- Delete the pod with the `kubectl delete pod frontend` command.
- Delete the pod with the `kubectl delete pod backend` command.

Congratulations! You have now learned how to make temporary connections to a pod inside the cluster
via `kubectl port-forward`, and how to use environment variables to configure the pod.
Expand Down
4 changes: 2 additions & 2 deletions cheatsheet.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ kubectl config set-context $(kubectl config current-context) --namespace=my-name
# Change default namespace

kubectl help run # See help about run (or other commands)
kubectl explain pod.spec # Documenation on any resource attribute
kubectl explain pod.spec # Documentation on any resource attribute

kubectl get nodes # See nodes in cluster
kubectl get pods -o wide # See pods in current namespace
kubectl get pod <name> -o yaml # See info about pod <name> in yaml format
kubectl describe pod <name> # Show information about pod <name>
kubectl describe service <name> # Show information about service <name>

kubectl api-resources # See resources types and abbreviations
kubectl api-resources # See resource types and abbreviations

kubectl create namespace my-namespace # Create namespace
# Set default namespace
Expand Down
50 changes: 25 additions & 25 deletions configmaps-secrets.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
## Introduction

Configmaps and secrets are a way to store information that is used by several deployments and pods
in your cluster. This makes it easy to update the configuration in one place, when you want to
in your cluster. This makes it easy to update the configuration in one place when you want to
change it.

Both configmaps and secrets are generic `key-value` pairs, but secrets are `base64 encoded` and
configmaps are not.

> :bulb: Secrets are not encrypted, they are encoded. This means that if someone gets access to the
> :bulb: Secrets are not encrypted; they are encoded. This means that if someone gets access to the
> cluster, they will be able to read the values.

## ConfigMaps
Expand All @@ -23,10 +23,10 @@ You use a ConfigMap to keep your application code separate from your configurati

It is an important part of creating a [Twelve-Factor Application](https://12factor.net/).

This lets you change easily configuration depending on the environment (development, production,
This lets you change configuration easily depending on the environment (development, production,
testing, etc.) and to dynamically change configuration at runtime.

A ConfigMap manifest looks like this in yaml:
A ConfigMap manifest looks like this in YAML:

```yaml
apiVersion: v1
Expand Down Expand Up @@ -101,7 +101,7 @@ data:

`secrets` are used for storing configuration that is considered sensitive, and well ... _secret_.

When you create a `secret` Kubernetes will go out of it's way to not print the actual values of
When you create a `secret`, Kubernetes will go out of its way to not print the actual values of
secret object, to things like logs or command output.

You should use `secrets` to store things like passwords for databases, API keys, certificates, etc.
Expand All @@ -113,19 +113,19 @@ source these values from environment variables.
actual values are `base64` encoded. `base64` encoded means that the values are obscured, but can be
trivially decoded. When values from a `secret` are used, Kubernetes handles the decoding for you.

> :bulb: As `secrets` don't actually make their data secret for anyone with access to the cluster,
> :bulb: As `secrets` don't make their data secret for anyone with access to the cluster,
> you should think of `secrets` as metadata for humans, to know that the data contained within is
> considered secret.

## Using ConfigMaps and Secrets in a deployment

To use a configmap or secret in a deployment, you can either mount it in as a volume, or use it
To use a configmap or secret in a deployment, you can either mount it as a volume or use it
directly as an environment variable.

### Injecting a ConfigMap as environment variables

This will inject all key-value pairs from a configmap as environment variables in a container.
The keys will be the name of variables, and the values will be values of the variables.
The keys will be the names of variables, and the values will be the values of the variables.

```yaml
apiVersion: apps/v1
Expand All @@ -151,10 +151,10 @@ spec:

- Add the database part of the application
- Change the database user into a configmap and implement that in the backend
- Change the database password into a secret, and implement that in the backend.
- Change the database password to a secret, and implement that in the backend.
- Change database deployment to use the configmap and secret.

### Step by step instructions
### Step-by-step instructions

<details>
<summary>
Expand All @@ -168,7 +168,7 @@ Step by step:
We have already created the database part of the application, with a deployment and a service.

- Look at the database deployment file `postgres-deployment.yaml`.
Notice the database username and password are injected as hardcoded environment variables.
Notice that the database username and password are injected as hardcoded environment variables.

> :bulb: This is not a good practice, as we do not want to store these values in version control.
> We will fix this in the next steps.
Expand All @@ -194,10 +194,10 @@ postgres-6fbd757dd7-ttpqj 1/1 Running 0 4s
#### Refactor the database user into a configmap and implement that in the backend

We want to change the database user into a configmap, so that we can change it in one place, and
use it on all deployments that needs it.
use it on all deployments that need it.

- Create a configmap with the name `postgres-config` and filename `postgres-config.yaml` and the
information about database configuration as follows:
information about the database configuration as follows:

```yaml
data:
Expand Down Expand Up @@ -238,7 +238,7 @@ data:

</details>

- apply the configmap with `kubectl apply -f postgres-config.yaml`
- Apply the configmap with `kubectl apply -f postgres-config.yaml`
- In the `backend-deployment.yaml`, change the environment variables to use the configmap instead
of the hardcoded values.

Expand Down Expand Up @@ -266,14 +266,14 @@ data:
name: postgres-config
```

- re-apply the backend deployment with `kubectl apply -f backend-deployment.yaml`
- check that the website is still running.
- Re-apply the backend deployment with `kubectl apply -f backend-deployment.yaml`
- Check that the website is still running.

#### Change the database password into a secret, and implement that in the backend

We want to change the database password into a secret, so that we can change it in one place, and
use it on all deployments that needs it.
In order for this, we need to change the backend deployment to use the secret instead of the
We want to change the database password to a secret, so that we can change it in one place, and
use it on all deployments that need it.
For this, we need to change the backend deployment to use the secret instead of the
configmap for the password itself.

- create a secret with the name `postgres-secret` and the following data:
Expand Down Expand Up @@ -340,12 +340,12 @@ envFrom:

We are going to implement the configmap and secret in the database deployment as well.

The standard Postgres docker image can be configured by setting specific environment variables,
The standard Postgres Docker image can be configured by setting specific environment variables,
([you can see the documentation here](https://hub.docker.com/_/postgres)).
By populating these specific values we can configure the credentials for root user and the name of
the database to be created.
By populating these specific values, we can configure the credentials for the root user and the name
of the database to be created.

This means that we need to change the way we are injecting the environment variables, in order to
This means that we need to change the way we are injecting the environment variables, to
make sure the environment variables have the correct names.

- Open the `postgres-deployment.yaml` file, and change the way the environment variables are
Expand All @@ -371,8 +371,8 @@ env:
key: DB_PASSWORD
```

- re-apply the database deployment with `kubectl apply -f postgres-deployment.yaml`
- check that the website is still running, and that the new database can be reached from the backend.
- Re-apply the database deployment with `kubectl apply -f postgres-deployment.yaml`
- Check that the website is still running, and that the new database can be reached from the backend.

Congratulations! You have now created a configmap and a secret, and used them in your application.

Expand Down
Loading