🌈 Update HAProxy example to use literal blue/green deployment

This commit is contained in:
Jérôme Petazzoni
2021-11-28 20:30:38 +01:00
parent c9507b4c83
commit 4adb75f0cb
3 changed files with 240 additions and 68 deletions

View File

@@ -1,18 +1,16 @@
global
daemon
maxconn 256
defaults
mode tcp
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
timeout connect 5s
timeout client 50s
timeout server 50s
frontend the-frontend
listen very-basic-load-balancer
bind *:80
default_backend the-backend
backend the-backend
server google.com-80 google.com:80 maxconn 32 check
server ibm.fr-80 ibm.fr:80 maxconn 32 check
server blue color.blue.svc:80
server green color.green.svc:80
# Note: the services above must exist,
# otherwise HAproxy won't start.

147
k8s/rainbow.yaml Normal file
View File

@@ -0,0 +1,147 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: blue
labels:
app: rainbow
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: rainbow
color: blue
name: color
namespace: blue
spec:
selector:
matchLabels:
app: color
color: blue
template:
metadata:
labels:
app: color
color: blue
spec:
containers:
- image: jpetazzo/color
name: color
---
apiVersion: v1
kind: Service
metadata:
labels:
app: color
color: blue
name: color
namespace: blue
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
selector:
app: color
color: blue
type: ClusterIP
---
apiVersion: v1
kind: Namespace
metadata:
name: green
labels:
app: rainbow
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: rainbow
color: green
name: color
namespace: green
spec:
selector:
matchLabels:
app: color
color: green
template:
metadata:
labels:
app: color
color: green
spec:
containers:
- image: jpetazzo/color
name: color
---
apiVersion: v1
kind: Service
metadata:
labels:
app: color
color: green
name: color
namespace: green
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
selector:
app: color
color: green
type: ClusterIP
---
apiVersion: v1
kind: Namespace
metadata:
name: red
labels:
app: rainbow
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: rainbow
color: red
name: color
namespace: red
spec:
selector:
matchLabels:
app: color
color: red
template:
metadata:
labels:
app: color
color: red
spec:
containers:
- image: jpetazzo/color
name: color
---
apiVersion: v1
kind: Service
metadata:
labels:
app: color
color: red
name: color
namespace: red
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
selector:
app: color
color: red
type: ClusterIP

View File

@@ -344,32 +344,94 @@ We'll cover them just after!*
---
## Passing a configuration file with a configmap
## Example: HAProxy configuration
- We will start a load balancer powered by HAProxy
- We are going to deploy HAProxy, a popular load balancer
- We will use the [official `haproxy` image](https://hub.docker.com/_/haproxy/)
- It expects to find its configuration in a specific place:
- It expects to find its configuration in `/usr/local/etc/haproxy/haproxy.cfg`
`/usr/local/etc/haproxy/haproxy.cfg`
- We will provide a simple HAproxy configuration, `k8s/haproxy.cfg`
- We will create a ConfigMap holding the configuration file
- It listens on port 80, and load balances connections between IBM and Google
- Then we will mount that ConfigMap in a Pod running HAProxy
---
## Creating the configmap
## Blue/green load balancing
- In this example, we will deploy two versions of our app:
- the "blue" version in the `blue` namespace
- the "green" version in the `green` namespace
- In both namespaces, we will have a Deployment and a Service
(both named `color`)
- We want to load balance traffic between both namespaces
(we can't do that with a simple service selector: these don't cross namespaces)
---
## Deploying the app
- We're going to use the image `jpetazzo/color`
(it is a simple "HTTP echo" server showing which pod served the request)
- We can create each Namespace, Deployment, and Service by hand, or...
.exercise[
- Go to the `k8s` directory in the repository:
- We can deploy the app with a YAML manifest:
```bash
cd ~/container.training/k8s
kubectl apply -f ~/container.training/k8s/rainbow.yaml
```
- Create a configmap named `haproxy` and holding the configuration file:
]
---
## Testing the app
- Reminder: Service `x` in Namespace `y` is available through:
`x.y`, `x.y.svc`, `x.y.svc.cluster.local`
- Since the `cluster.local` suffix can change, we'll use `x.y.svc`
.exercise[
- Check that the app is up and running:
```bash
kubectl create configmap haproxy --from-file=haproxy.cfg
kubectl run --rm -it --restart=Never --image=nixery.dev/curl my-test-pod \
curl color.blue.svc
```
]
---
## Creating the HAProxy configuration
Here is the file that we will use, @@LINK[k8s/haproxy.cfg]:
```
@@INCLUDE[k8s/haproxy.cfg]
```
---
## Creating the ConfigMap
.exercise[
- Create a ConfigMap named `haproxy` and holding the configuration file:
```bash
kubectl create configmap haproxy --from-file=~/container.training/k8s/haproxy.cfg
```
- Check what our configmap looks like:
@@ -381,37 +443,21 @@ We'll cover them just after!*
---
## Using the configmap
## Using the ConfigMap
We are going to use the following pod definition:
Here is @@LINK[k8s/haproxy.yaml], a Pod manifest using that ConfigMap:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: haproxy
spec:
volumes:
- name: config
configMap:
name: haproxy
containers:
- name: haproxy
image: haproxy
volumeMounts:
- name: config
mountPath: /usr/local/etc/haproxy/
@@INCLUDE[k8s/haproxy.yaml]
```
---
## Using the configmap
- The resource definition from the previous slide is in `k8s/haproxy.yaml`
## Creating the Pod
.exercise[
- Create the HAProxy pod:
- Create the HAProxy Pod:
```bash
kubectl apply -f ~/container.training/k8s/haproxy.yaml
```
@@ -430,27 +476,21 @@ spec:
## Testing our load balancer
- The load balancer will send:
- If everything went well, when we should see a perfect round robin
- half of the connections to Google
- the other half to IBM
(one request to `blue`, one request to `green`, one request to `blue`, etc.)
.exercise[
- Access the load balancer a few times:
- Send a few requests:
```bash
for i in $(seq 10); do
curl $IP
curl $IP
curl $IP
done
```
]
We should see connections served by Google, and others served by IBM.
<br/>
(Each server sends us a redirect page. Look at the URL that they send us to!)
---
## Exposing configmaps with the downward API
@@ -490,27 +530,14 @@ We should see connections served by Google, and others served by IBM.
We are going to use the following pod definition:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: registry
spec:
containers:
- name: registry
image: registry
env:
- name: REGISTRY_HTTP_ADDR
valueFrom:
configMapKeyRef:
name: registry
key: http.addr
@@INCLUDE[k8s/registry.yaml]
```
---
## Using the configmap
- The resource definition from the previous slide is in `k8s/registry.yaml`
- The resource definition from the previous slide is in @@LINK[k8s/registry.yaml]
.exercise[