225 lines
7.6 KiB
Markdown
225 lines
7.6 KiB
Markdown
# Accessing my first application: `service`
|
|
|
|
## Introduction
|
|
|
|
In this section you will learn how to access your application from outside your cluster, and do service discovery.
|
|
|
|
## Prerequisites
|
|
|
|
If it's not already done install the `minikube` addon `ingress`:
|
|
|
|
```sh
|
|
$ minikube addons enable ingress
|
|
✅ ingress was successfully enabled
|
|
```
|
|
|
|
## First `service`
|
|
|
|
You are able to deploy an image with multiple replicas, but it is not very convenient to access it. You need to know the IP of a `pod` to be able to target your application. And it's not accessible from the outside of the cluster.
|
|
|
|
What we need is a `service`. It'll allow us to access our pods internally or externally.
|
|
|
|
First apply the `deployment`:
|
|
|
|
```sh
|
|
$ kubectl apply -f 08-service/01-simple-deployment.yml
|
|
deployment.apps "simple-deployment" created
|
|
```
|
|
|
|
Now start another container. We will use it to see what we can access internally inside Kubernetes:
|
|
|
|
Apply the pod:
|
|
|
|
```sh
|
|
$ kubectl apply -f 08-service/02-bash.yml
|
|
pod "bash" created
|
|
```
|
|
|
|
And connect to it:
|
|
|
|
```sh
|
|
$ kubectl exec -it bash -- /bin/bash
|
|
root@bash:/#
|
|
```
|
|
|
|
Install `dnsutils` & `curl` in the container, you will need them:
|
|
|
|
```sh
|
|
root@bash:/# apt update && apt install dnsutils curl
|
|
[...]
|
|
```
|
|
|
|
You now have a shell inside a Kubernetes pod running in your cluster. Let this console open so you can type commands.
|
|
Try to curl one of the pods created by the deployment above. How can you access the `deployment` **without** targeting a specific `pod`?
|
|
|
|
Ok, now let's create our first service [03-internal-service.yml](03-internal-service.yml):
|
|
|
|
```yml
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: simple-internal-service
|
|
spec:
|
|
ports:
|
|
- port: 80
|
|
targetPort: 9876
|
|
selector:
|
|
app: simple-deployment
|
|
```
|
|
|
|
Let's have a look at the manifest:
|
|
|
|
* `kind`: A `service` has the kind `Service`
|
|
* `spec`:
|
|
* `ports`: the list of ports to expose. Here we export `port` `80`, but redirect internally all traffic to the `targetPort` `9876`
|
|
* `selector`: which pods to give access to
|
|
|
|
The selector part
|
|
|
|
```yml
|
|
selector:
|
|
app: simple-deployment
|
|
```
|
|
|
|
is central to Kubernetes. It is with those fields that you will tell Kubernetes which pods to give access through this `service`.
|
|
|
|
Apply the service:
|
|
|
|
```sh
|
|
$ kubectl apply -f 08-service/03-internal-service.yml
|
|
service "simple-service" created
|
|
```
|
|
|
|
Your service is now accessible internally, try this in your `bash` container:
|
|
|
|
```sh
|
|
root@bash:/# nslookup simple-internal-service
|
|
Server: 10.96.0.10
|
|
Address: 10.96.0.10#53
|
|
|
|
Name: simple-internal-service.default.svc.cluster.local
|
|
Address: 10.96.31.244
|
|
```
|
|
|
|
Try to curl the `/health` url, remember the `ports` we choose in the `service`.
|
|
|
|
Can you access this service from the outside of Kubernetes?
|
|
|
|
The answer is no, it's not possible. To do this you need an `ingress`. Ingress means "entering into".
|
|
|
|
## Ingress
|
|
|
|
You need to connect internet to the `ingress` that'll connect it to a service:
|
|
|
|
```txt
|
|
internet
|
|
|
|
|
[ ingress ]
|
|
--|-----|--
|
|
[ service ]
|
|
```
|
|
|
|
Let's create our ingress:
|
|
|
|
```yml
|
|
apiVersion: extensions/v1beta1
|
|
kind: Ingress
|
|
metadata:
|
|
name: simple-ingress
|
|
annotations:
|
|
nginx.ingress.kubernetes.io/ssl-redirect: "false"
|
|
spec:
|
|
backend:
|
|
serviceName: simple-internal-service
|
|
servicePort: 80
|
|
```
|
|
|
|
Let's have a look at the manifest:
|
|
|
|
* `kind`: Ingress
|
|
* `metadata`:
|
|
* `annotations`: some annotations specific to the ingress
|
|
* `nginx.ingress.kubernetes.io/ssl-redirect`: To fix a redirect, see [this](https://github.com/kubernetes/ingress-nginx/issues/1567). This is only used if you use the nginx ingress
|
|
* `spec`:
|
|
* `backend`: the default backend to redirect all the requests to
|
|
* `serviceName`: the name of the Kubernetes traffic to redirect to
|
|
* `servicePort`: the port of the service
|
|
|
|
Apply the ingress:
|
|
|
|
```sh
|
|
$ kubectl apply -f 08-service/04-ingress.yml
|
|
ingress.extensions "simple-ingress" created
|
|
```
|
|
|
|
Get the IP of your minikube cluster:
|
|
|
|
```sh
|
|
$ minikube ip
|
|
192.168.99.100
|
|
```
|
|
|
|
Open a browser on `http://192.168.99.100/info`
|
|
|
|
With this manifest we have a `deployment` that manages pods. A `service` that gives access to the pods, and an `ingress` that gives access to the pod to the external world.
|
|
|
|
## Global overview
|
|
|
|
You have seen a lot different `kind` of Kubernetes, let's take a step back and see how each `kind` interact with each other:
|
|
|
|
```text
|
|
+----------------------------------------------------------------------------------+
|
|
| |
|
|
| +-----------------------------+ |
|
|
| | | |
|
|
| | +-------------+ | |
|
|
| | | | | |
|
|
| | -> Pod | | |
|
|
| | --/ | | | |
|
|
+-------------+ +-------------+ | ---/ +-------------+ | |
|
|
| | | | | | --/ | |
|
|
| Ingress -----> Service ------------------\ | |
|
|
| | | | | | --\ +-------------+ | |
|
|
+-------------+ +-------------+ | ---\ | | | |
|
|
| | --\ | Pod | | |
|
|
| | -> | | |
|
|
| | +-------------+ | |
|
|
| | | |
|
|
| | Deployment | |
|
|
| +-----------------------------+ |
|
|
| |
|
|
| |
|
|
| |
|
|
| Kubernetes |
|
|
+----------------------------------------------------------------------------------+
|
|
```
|
|
|
|
## Exercises
|
|
|
|
1. Deploy an nginx and expose it internally
|
|
2. Read [this](https://kubernetes.io/docs/concepts/services-networking/ingress/#simple-fanout) and modify the ingress to have:
|
|
* `/simple` that goes to the `simple-service`
|
|
* `/nginx` that goes to your nginx deployment
|
|
3. Change the `selector` in your `simple-service` look at what is happening
|
|
|
|
## Clean up
|
|
|
|
```sh
|
|
kubectl delete ingress,service,deployment,rs,pod --all
|
|
```
|
|
|
|
## Answers
|
|
|
|
For 2), you need to add the metadata `nginx.ingress.kubernetes.io/rewrite-target: /` to the ingress:
|
|
|
|
* Don't forget to create 2 deployments and 2 services.
|
|
* You can either change your `/etc/hosts` to add the name resolution for `foo.bar.com`, or use `curl http://YOUR-IP -H "Host: foo.bar.com"`
|
|
|
|
## Links
|
|
|
|
* https://kubernetes.io/docs/concepts/services-networking/service/
|
|
* https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/
|
|
* https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/
|
|
* https://kubernetes.io/docs/concepts/services-networking/ingress/
|
|
* https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/
|