kubernetes-hands-on/08-service/README.md

225 lines
7.6 KiB
Markdown
Raw Normal View History

2019-05-09 19:40:37 +06:00
# 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`:
2019-05-21 15:10:59 +06:00
```sh
2019-05-09 19:40:37 +06:00
$ 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`:
2019-05-21 15:10:59 +06:00
```sh
2019-05-09 19:40:37 +06:00
$ 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:
2019-05-09 19:40:37 +06:00
Apply the pod:
2019-05-21 15:10:59 +06:00
```sh
2019-05-09 19:40:37 +06:00
$ kubectl apply -f 08-service/02-bash.yml
pod "bash" created
```
And connect to it:
2019-05-21 15:10:59 +06:00
```sh
2019-05-09 19:40:37 +06:00
$ kubectl exec -it bash -- /bin/bash
root@bash:/#
```
Install `dnsutils` & `curl` in the container, you will need them:
2019-05-21 15:10:59 +06:00
```sh
2019-05-09 19:40:37 +06:00
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.
2019-05-09 19:40:37 +06:00
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):
2019-05-09 19:40:37 +06:00
```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`.
2019-05-09 19:40:37 +06:00
Apply the service:
2019-05-21 15:10:59 +06:00
```sh
$ kubectl apply -f 08-service/03-internal-service.yml
2019-05-09 19:40:37 +06:00
service "simple-service" created
```
Your service is now accessible internally, try this in your `bash` container:
2019-05-21 15:10:59 +06:00
```sh
2019-05-23 18:11:41 +06:00
root@bash:/# nslookup simple-internal-service
2019-05-14 20:26:37 +06:00
Server: 10.96.0.10
Address: 10.96.0.10#53
2019-05-09 19:40:37 +06:00
2019-05-23 18:11:41 +06:00
Name: simple-internal-service.default.svc.cluster.local
2019-05-09 19:40:37 +06:00
Address: 10.96.31.244
```
Try to curl the `/health` url, remember the `ports` we choose in the `service`.
2019-05-09 19:40:37 +06:00
Can you access this service from the outside of Kubernetes?
2019-05-09 19:40:37 +06:00
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:
2019-05-23 18:11:41 +06:00
serviceName: simple-internal-service
2019-05-09 19:40:37 +06:00
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
2019-05-09 19:40:37 +06:00
* `servicePort`: the port of the service
Apply the ingress:
2019-05-21 15:10:59 +06:00
```sh
2019-05-09 19:40:37 +06:00
$ kubectl apply -f 08-service/04-ingress.yml
ingress.extensions "simple-ingress" created
```
Get the IP of your minikube cluster:
2019-05-21 15:10:59 +06:00
```sh
2019-05-09 19:40:37 +06:00
$ 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:
2019-05-09 19:40:37 +06:00
```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:
2019-05-14 20:26:37 +06:00
* `/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
2019-05-09 19:40:37 +06:00
## Clean up
2019-05-21 15:10:59 +06:00
```sh
2019-05-09 19:40:37 +06:00
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:
2019-05-09 19:40:37 +06:00
* 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/