mirror of
https://github.com/jpetazzo/container.training.git
synced 2026-02-14 09:39:56 +00:00
Tweaks after Caen
This commit is contained in:
@@ -13,7 +13,7 @@ spec:
|
||||
mountPath: /usr/share/nginx/html/
|
||||
- name: git
|
||||
image: alpine
|
||||
command: [ "sh", "-c", "apk add --no-cache git && git clone https://github.com/octocat/Spoon-Knife /www" ]
|
||||
command: [ "sh", "-c", "apk add git && git clone https://github.com/octocat/Spoon-Knife /www" ]
|
||||
volumeMounts:
|
||||
- name: www
|
||||
mountPath: /www/
|
||||
|
||||
@@ -10,6 +10,29 @@
|
||||
|
||||
---
|
||||
|
||||
## What can we do with Kubernetes?
|
||||
|
||||
- Let's imagine that we have a 3-tier e-commerce app:
|
||||
|
||||
- web frontend
|
||||
|
||||
- API backend
|
||||
|
||||
- database (that we will keep out of Kubernetes for now)
|
||||
|
||||
- We have built images for our frontend and backend components
|
||||
|
||||
(e.g. with Dockerfiles and `docker build`)
|
||||
|
||||
- We are running them successfully with a local environment
|
||||
|
||||
(e.g. with Docker Compose)
|
||||
|
||||
- Let's see how we would deploy our app on Kubernetes!
|
||||
|
||||
---
|
||||
|
||||
|
||||
## Basic things we can ask Kubernetes to do
|
||||
|
||||
--
|
||||
|
||||
@@ -427,7 +427,7 @@ class: extra-details
|
||||
|
||||
- We need to change the selector of the `rng` service!
|
||||
|
||||
- Let's add another label to that selector (e.g. `enabled=yes`)
|
||||
- Let's add another label to that selector (e.g. `active=yes`)
|
||||
|
||||
---
|
||||
|
||||
@@ -445,11 +445,11 @@ class: extra-details
|
||||
|
||||
## The plan
|
||||
|
||||
1. Add the label `enabled=yes` to all our `rng` pods
|
||||
1. Add the label `active=yes` to all our `rng` pods
|
||||
|
||||
2. Update the selector for the `rng` service to also include `enabled=yes`
|
||||
2. Update the selector for the `rng` service to also include `active=yes`
|
||||
|
||||
3. Toggle traffic to a pod by manually adding/removing the `enabled` label
|
||||
3. Toggle traffic to a pod by manually adding/removing the `active` label
|
||||
|
||||
4. Profit!
|
||||
|
||||
@@ -464,7 +464,7 @@ be any interruption.*
|
||||
|
||||
## Adding labels to pods
|
||||
|
||||
- We want to add the label `enabled=yes` to all pods that have `app=rng`
|
||||
- We want to add the label `active=yes` to all pods that have `app=rng`
|
||||
|
||||
- We could edit each pod one by one with `kubectl edit` ...
|
||||
|
||||
@@ -474,9 +474,9 @@ be any interruption.*
|
||||
|
||||
.exercise[
|
||||
|
||||
- Add `enabled=yes` to all pods that have `app=rng`:
|
||||
- Add `active=yes` to all pods that have `app=rng`:
|
||||
```bash
|
||||
kubectl label pods -l app=rng enabled=yes
|
||||
kubectl label pods -l app=rng active=yes
|
||||
```
|
||||
|
||||
]
|
||||
@@ -495,7 +495,7 @@ be any interruption.*
|
||||
|
||||
.exercise[
|
||||
|
||||
- Update the service to add `enabled: yes` to its selector:
|
||||
- Update the service to add `active: yes` to its selector:
|
||||
```bash
|
||||
kubectl edit service rng
|
||||
```
|
||||
@@ -504,7 +504,7 @@ be any interruption.*
|
||||
```wait Please edit the object below```
|
||||
```keys /app: rng```
|
||||
```key ^J```
|
||||
```keys noenabled: yes```
|
||||
```keys noactive: yes```
|
||||
```key ^[``` ]
|
||||
```keys :wq```
|
||||
```key ^J```
|
||||
@@ -530,7 +530,7 @@ be any interruption.*
|
||||
|
||||
- If we want the string `"42"` or the string `"yes"`, we have to quote them
|
||||
|
||||
- So we have to use `enabled: "yes"`
|
||||
- So we have to use `active: "yes"`
|
||||
|
||||
.footnote[For a good laugh: if we had used "ja", "oui", "si" ... as the value, it would have worked!]
|
||||
|
||||
@@ -542,7 +542,7 @@ be any interruption.*
|
||||
|
||||
- Update the YAML manifest of the service
|
||||
|
||||
- Add `enabled: "yes"` to its selector
|
||||
- Add `active: "yes"` to its selector
|
||||
|
||||
<!--
|
||||
```wait Please edit the object below```
|
||||
@@ -566,7 +566,7 @@ If we did everything correctly, the web UI shouldn't show any change.
|
||||
|
||||
- We want to disable the pod that was created by the deployment
|
||||
|
||||
- All we have to do, is remove the `enabled` label from that pod
|
||||
- All we have to do, is remove the `active` label from that pod
|
||||
|
||||
- To identify that pod, we can use its name
|
||||
|
||||
@@ -600,7 +600,7 @@ If we did everything correctly, the web UI shouldn't show any change.
|
||||
|
||||
- In another window, remove the label from the pod:
|
||||
```bash
|
||||
kubectl label pod -l app=rng,pod-template-hash enabled-
|
||||
kubectl label pod -l app=rng,pod-template-hash active-
|
||||
```
|
||||
(The stream of HTTP logs should stop immediately)
|
||||
|
||||
@@ -623,7 +623,7 @@ class: extra-details
|
||||
|
||||
- If we scale up our cluster by adding new nodes, the daemon set will create more pods
|
||||
|
||||
- These pods won't have the `enabled=yes` label
|
||||
- These pods won't have the `active=yes` label
|
||||
|
||||
- If we want these pods to have that label, we need to edit the daemon set spec
|
||||
|
||||
|
||||
@@ -120,19 +120,13 @@
|
||||
|
||||
- We want our ingress load balancer to be available on port 80
|
||||
|
||||
- We could do that with a `LoadBalancer` service
|
||||
- The best way to do that would be with a `LoadBalancer` service
|
||||
|
||||
... but it requires support from the underlying infrastructure
|
||||
|
||||
- We could use pods specifying `hostPort: 80`
|
||||
- Instead, we are going to use the `hostNetwork` mode on the Traefik pods
|
||||
|
||||
... but with most CNI plugins, this [doesn't work or requires additional setup](https://github.com/kubernetes/kubernetes/issues/23920)
|
||||
|
||||
- We could use a `NodePort` service
|
||||
|
||||
... but that requires [changing the `--service-node-port-range` flag in the API server](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/)
|
||||
|
||||
- Last resort: the `hostNetwork` mode
|
||||
- Let's see what this `hostNetwork` mode is about ...
|
||||
|
||||
---
|
||||
|
||||
@@ -170,6 +164,26 @@
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## Other techniques to expose port 80
|
||||
|
||||
- We could use pods specifying `hostPort: 80`
|
||||
|
||||
... but with most CNI plugins, this [doesn't work or requires additional setup](https://github.com/kubernetes/kubernetes/issues/23920)
|
||||
|
||||
- We could use a `NodePort` service
|
||||
|
||||
... but that requires [changing the `--service-node-port-range` flag in the API server](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/)
|
||||
|
||||
- We could create a service with an external IP
|
||||
|
||||
... this would work, but would require a few extra steps
|
||||
|
||||
(figuring out the IP address and adding it to the service)
|
||||
|
||||
---
|
||||
|
||||
## Running Traefik
|
||||
|
||||
- The [Traefik documentation](https://docs.traefik.io/user-guide/kubernetes/#deploy-trfik-using-a-deployment-or-daemonset) tells us to pick between Deployment and Daemon Set
|
||||
|
||||
@@ -1,20 +1,76 @@
|
||||
# Exposing containers
|
||||
|
||||
- `kubectl expose` creates a *service* for existing pods
|
||||
- We can connect to our pods using their IP address
|
||||
|
||||
- A *service* is a stable address for a pod (or a bunch of pods)
|
||||
- Then we need to figure out a lot of thigns:
|
||||
|
||||
- If we want to connect to our pod(s), we need to create a *service*
|
||||
- how do we look up the IP address of the pod(s)?
|
||||
|
||||
- Once a service is created, CoreDNS will allow us to resolve it by name
|
||||
- how do we connect from outside the cluster?
|
||||
|
||||
(i.e. after creating service `hello`, the name `hello` will resolve to something)
|
||||
- how do we load balance traffic?
|
||||
|
||||
- There are different types of services, detailed on the following slides:
|
||||
- what if a pod fails?
|
||||
|
||||
- Kubernetes has a resource type named *Service*
|
||||
|
||||
- Services address all these questions!
|
||||
|
||||
---
|
||||
|
||||
## Services in a nutshell
|
||||
|
||||
- Services give us a *stable endpoint* to connect to a pod or a group of pods
|
||||
|
||||
- An easy way to create a service is to use `kubectl expose`
|
||||
|
||||
- If we have a deployment named `my-little-deploy`, we can run:
|
||||
|
||||
`kubectl expose deployment my-little-deploy --port=80`
|
||||
|
||||
... and this will create a service with the same name (`my-little-deploy`)
|
||||
|
||||
- Services are automatically added to an internal DNS zone
|
||||
|
||||
(in the example above, our code can now connect to http://my-little-deploy/)
|
||||
|
||||
---
|
||||
|
||||
## Advantages of services
|
||||
|
||||
- We don't need to look up the IP address of the pod(s)
|
||||
|
||||
(we resolve the IP address of the service using DNS)
|
||||
|
||||
- There are multiple service types; some of them allow external traffic
|
||||
|
||||
(e.g. `LoadBalancer` and `NodePort`)
|
||||
|
||||
- Services provide load balancing
|
||||
|
||||
(for both internal and external traffic)
|
||||
|
||||
- Service addresses are independent from pods' addresses
|
||||
|
||||
(when a pod fails, the service seamlessly sends traffic to its replacement)
|
||||
|
||||
---
|
||||
|
||||
## Many kinds and flavors of service
|
||||
|
||||
- There are different types of services:
|
||||
|
||||
`ClusterIP`, `NodePort`, `LoadBalancer`, `ExternalName`
|
||||
|
||||
- HTTP services can also use `Ingress` resources (more on that later)
|
||||
- There are also *headless services*
|
||||
|
||||
- Services can also have optional *external IPs*
|
||||
|
||||
- There is also another resource type called *Ingress*
|
||||
|
||||
(specifically for HTTP services)
|
||||
|
||||
- Wow, that's a lot! Let's start with the basics ...
|
||||
|
||||
---
|
||||
|
||||
@@ -73,24 +129,6 @@
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## `ExternalName`
|
||||
|
||||
- No load balancer (internal or external) is created
|
||||
|
||||
- Only a DNS entry gets added to the DNS managed by Kubernetes
|
||||
|
||||
- That DNS entry will just be a `CNAME` to a provided record
|
||||
|
||||
Example:
|
||||
```bash
|
||||
kubectl create service externalname k8s --external-name kubernetes.io
|
||||
```
|
||||
*Creates a CNAME `k8s` pointing to `kubernetes.io`*
|
||||
|
||||
---
|
||||
|
||||
## Running containers with open ports
|
||||
|
||||
- Since `ping` doesn't have anything to connect to, we'll have to run something else
|
||||
@@ -175,9 +213,7 @@ kubectl create service externalname k8s --external-name kubernetes.io
|
||||
|
||||
- As a result: you *have to* indicate the port number for your service
|
||||
|
||||
- Running services with arbitrary port (or port ranges) requires hacks
|
||||
|
||||
(e.g. host networking mode)
|
||||
(with some exceptions, like `ExternalName` or headless services, covered later)
|
||||
|
||||
---
|
||||
|
||||
@@ -218,7 +254,48 @@ Try it a few times! Our requests are load balanced across multiple pods.
|
||||
|
||||
class: extra-details
|
||||
|
||||
## If we don't need a load balancer
|
||||
## `ExternalName`
|
||||
|
||||
- Services of type `ExternalName` are quite different
|
||||
|
||||
- No load balancer (internal or external) is created
|
||||
|
||||
- Only a DNS entry gets added to the DNS managed by Kubernetes
|
||||
|
||||
- That DNS entry will just be a `CNAME` to a provided record
|
||||
|
||||
Example:
|
||||
```bash
|
||||
kubectl create service externalname k8s --external-name kubernetes.io
|
||||
```
|
||||
*Creates a CNAME `k8s` pointing to `kubernetes.io`*
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## External IPs
|
||||
|
||||
- We can add an External IP to a service, e.g.:
|
||||
```bash
|
||||
kubectl expose deploy my-little-deploy --port=80 --external-ip=1.2.3.4
|
||||
```
|
||||
|
||||
- `1.2.3.4` should be the address of one of our nodes
|
||||
|
||||
(it could also be a virtual address, service address, or VIP, shared by multiple nodes)
|
||||
|
||||
- Connections to `1.2.3.4:80` will be sent to our service
|
||||
|
||||
- External IPs will also show up on services of type `LoadBalancer`
|
||||
|
||||
(they will be added automatically by the process provisioning the load balancer)
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## Headless services
|
||||
|
||||
- Sometimes, we want to access our scaled services directly:
|
||||
|
||||
@@ -238,7 +315,7 @@ class: extra-details
|
||||
|
||||
class: extra-details
|
||||
|
||||
## Headless services
|
||||
## Creating a headless services
|
||||
|
||||
- A headless service is obtained by setting the `clusterIP` field to `None`
|
||||
|
||||
@@ -324,18 +401,32 @@ error: the server doesn't have a resource type "endpoint"
|
||||
|
||||
class: extra-details
|
||||
|
||||
## `ExternalIP`
|
||||
## The DNS zone
|
||||
|
||||
- When creating a servivce, we can also specify an `ExternalIP`
|
||||
- In the `kube-system` namespace, there should be a service named `kube-dns`
|
||||
|
||||
(this is not a type, but an extra attribute to the service)
|
||||
- This is the internal DNS server that can resolve service names
|
||||
|
||||
- It will make the service availableon this IP address
|
||||
- The default domain name for the service we created is `default.svc.cluster.local`
|
||||
|
||||
(if the IP address belongs to a node of the cluster)
|
||||
.exercise[
|
||||
|
||||
- Get the IP address of the internal DNS server:
|
||||
```bash
|
||||
IP=$(kubectl -n kube-system get svc kube-dns -o jsonpath={.spec.clusterIP})
|
||||
```
|
||||
|
||||
- Resolve the cluster IP for the `httpenv` service:
|
||||
```bash
|
||||
host httpenv.default.svc.cluster.local $IP
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## `Ingress`
|
||||
|
||||
- Ingresses are another type (kind) of resource
|
||||
|
||||
@@ -102,8 +102,6 @@
|
||||
|
||||
]
|
||||
|
||||
- Some tools like Helm will create namespaces automatically when needed
|
||||
|
||||
---
|
||||
|
||||
## Using namespaces
|
||||
|
||||
@@ -50,7 +50,7 @@ class: extra-details
|
||||
|
||||
- *Volumes*:
|
||||
|
||||
- appear in Pod specifications (see next slide)
|
||||
- appear in Pod specifications (we'll see that in a few slides)
|
||||
|
||||
- do not exist as API resources (**cannot** do `kubectl get volumes`)
|
||||
|
||||
@@ -232,7 +232,7 @@ spec:
|
||||
mountPath: /usr/share/nginx/html/
|
||||
- name: git
|
||||
image: alpine
|
||||
command: [ "sh", "-c", "apk add --no-cache git && git clone https://github.com/octocat/Spoon-Knife /www" ]
|
||||
command: [ "sh", "-c", "apk add git && git clone https://github.com/octocat/Spoon-Knife /www" ]
|
||||
volumeMounts:
|
||||
- name: www
|
||||
mountPath: /www/
|
||||
|
||||
Reference in New Issue
Block a user