README.md 35.4 KB
Newer Older
Manuel Franco's avatar
Manuel Franco committed
1
2
# Kubernetes: backend cri-o y almacenamiento en Ceph.

Manuel Franco's avatar
Manuel Franco committed
3
1. [Introducción](#introducción)
Manuel Franco's avatar
Manuel Franco committed
4

Manuel Franco's avatar
Manuel Franco committed
5
    1.1 [¿Qué es Kubernetes?](#qúe-es-kubernetes)
Manuel Franco's avatar
Manuel Franco committed
6

Manuel Franco's avatar
Manuel Franco committed
7
    1.2 [¿Qué es Cri-o? y ¿Por qué?](#qué-es-cri-o-y-por-qué)
Manuel Franco's avatar
Manuel Franco committed
8

Manuel Franco's avatar
Manuel Franco committed
9
    1.3 [¿Qué es Ceph?](#qué-es-ceph)
Manuel Franco's avatar
Manuel Franco committed
10

Manuel Franco's avatar
Manuel Franco committed
11
2. [Escenario](#escenario)
Manuel Franco's avatar
Manuel Franco committed
12

Manuel Franco's avatar
Manuel Franco committed
13
3. [Instalación](#instalación)
Manuel Franco's avatar
Manuel Franco committed
14

Manuel Franco's avatar
Manuel Franco committed
15
    4.1 [Cri-o](#cri-o)
Manuel Franco's avatar
Manuel Franco committed
16

Manuel Franco's avatar
Manuel Franco committed
17
    4.2 [Kubernetes](#kubernetes)
Manuel Franco's avatar
Manuel Franco committed
18

Manuel Franco's avatar
Manuel Franco committed
19
    4.3 [Ceph](#ceph)
Manuel Franco's avatar
Manuel Franco committed
20
21
    
    4.4 [Rbd-provisioner](#despliegue-de-rbd-provisioner)
Manuel Franco's avatar
Manuel Franco committed
22

Manuel Franco's avatar
Manuel Franco committed
23
4. [Funcionamiento](#funcionamiento)
Manuel Franco's avatar
Manuel Franco committed
24

Manuel Franco's avatar
Manuel Franco committed
25
5. [Conclusión](#conclusión)
Manuel Franco's avatar
Manuel Franco committed
26

Manuel Franco's avatar
Manuel Franco committed
27
6. [Trabajo por hacer](#trabajo-por-hacer)
Manuel Franco's avatar
Manuel Franco committed
28

Manuel Franco's avatar
Manuel Franco committed
29
7. [Fuentes](#fuentes)
Manuel Franco's avatar
Manuel Franco committed
30
31
32
33
34

---

## Introducción

Manuel Franco's avatar
Manuel Franco committed
35
36
37
El objetivo de este proyecto es llegar a conocer el funcionamiento de tres tecnologías nuevas como son: Kubernetes, Ceph y Cri-o. Estas tecnologías las voy a combinar y demostrar el 
potencial que tiene la mezcla de estas tres tecnologías. Los roles que van a tener cada una de las tecnologías es la siguiente:

Manuel Franco's avatar
Manuel Franco committed
38
39
* Ceph: Clúster de almacenamiento nos va a proveer los volúmenes rbd
* Cri-o: Backend de Kubernetes encargado de generar contenedores
Manuel Franco's avatar
Manuel Franco committed
40
* Kubernetes: Orquestar los anteriores elementos para poner en producción aplicaciones. 
Manuel Franco's avatar
Manuel Franco committed
41
42

Vamos ver mas detenidamente cada uno de los elementos que he tocado en el proyecto.
Manuel Franco's avatar
Manuel Franco committed
43

Manuel Franco's avatar
Manuel Franco committed
44
45
### ¿Qúe es Kubernetes?

Manuel Franco's avatar
Manuel Franco committed
46
47
48
Kubernetes se trata de un orquestador de contenedores de aplicación escrito en Go y con licencia Apache-2.0, fue lanzado el 21 de julio de 2015 por Google que rápidamente se alió
con la Linux Foundation para crear la Cloud Native Computing Foundation (CNCF) y dejó el proyecto en sus manos. Este lanzamiento eclipsó a la competencia, tanto Docker Swarm como 
Apache Mesos, creando una fiebre hacia Kubernetes fuera de toda duda y dejándolo como el orquestador de contenedores más expandido hasta la fecha.
Manuel Franco's avatar
Manuel Franco committed
49

Manuel Franco's avatar
Manuel Franco committed
50
Aquí una gráfica comparando los principales orquestadores de contenedores: Kubernetes(Azul), Mesos(Rojo) y Swarm(Amarillo). También he añadido OpenShift(verde) que siendo su backend Kubernetes es una alternativa a las otras tecnologías.
Manuel Franco's avatar
Ceph    
Manuel Franco committed
51
52

![Leyenda](/images/description.png)
Manuel Franco's avatar
Manuel Franco committed
53
54
55

![Grafica Comparativa](/images/graph.png)

Manuel Franco's avatar
Manuel Franco committed
56
57
58
Ahora, Kubernetes está siendo utilizado por diversas compañías como base de otras tecnologías que están desarrollando, la más potente y conocida es
Openshift la solución de RedHat.

Manuel Franco's avatar
Manuel Franco committed
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
Algunos conceptos que tenemos que tener en cuenta son los siguientes:

* Deployment: Se declaran los contenedores que queremos desplegar y las características que van a tener.
* ReplicaSet: Mantiene el número de pods que le hemos pedido.
* Pod: Es la combinación de contenedor o contenedores, espacio de red y almacenamiento, es la únidad básica en Kubernetes.
* Service: La manera que tenemos de exponer un deployment.
* Volume: Pensado para los StatefulSet para mantener la información de manera persistente.
* Namespace: Para el aislamiento de Pods.
* Label: El marcado de recursos del clúster es fundamental para poder hacer acciones en lote con una o varias label declaradas.
* Jobs: Es un pod que realiza un proceso determinado y cuando lo ejecuta guarda el resultado hasta que se elimina.

En Kubernetes podemos diferenciar dos tipos de componentes:

* "Master Components" o componentes que solo los encontramos en los nodos que hacen de master.
* "Node Components" estos los que nos encontramos en todos los nodos de Kubernetes.

**MASTER COMPONENTS:**

*Kube-apiserver:*  

Manuel Franco's avatar
Manuel Franco committed
79
Se encarga de exponer la API de Kubernetes y ejecutar/validar las órdenes en el clúster.
Manuel Franco's avatar
Manuel Franco committed
80
81

*Etcd:*  
Manuel Franco's avatar
Manuel Franco committed
82

Manuel Franco's avatar
Manuel Franco committed
83
84
85
86
En una base de datos clave/valor que almacena toda la información del clúster, es extremadamente rápida y es capaz de estar distribuida y sincronizada.

*Kube-Scheduler:*  

Manuel Franco's avatar
Manuel Franco committed
87
Su propósito es elegir a que nodo va a ir cada pod dependiendo de las condiciones que le pongamos en el deployment: affinitys, antiaffinitys, workloads, data locality...
Manuel Franco's avatar
Manuel Franco committed
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

*Kube-controller-manager:*  

Se encarga de ejecutar todos los controladores:
* Node controller: Vigila que todos los nodos estén en estado "ready".
* Replication controller: Mantiene el número solicitado de pods en el clúster.
* Endpoints controller: Propaga los endpoints.
* Service Accounts y Token Controllers: Permisos y tokens.

*Cloud-controller-manager:*  

En caso que despleguemos nuestro clúster de Kubernetes en un entorno cloud como AWS o GKE este componente se va a encargar de interactuar con la API del entorno.

**NODE COMONENTS:**

*Kubelet:*

Manuel Franco's avatar
Manuel Franco committed
105
Se encuentra en todos los nodos de nuestra infraestructura, es el primario, trabaja en términos de PodSpec (yaml que descirbe un pod), y se encarga de controlar los contenedores creados por Kubernetes y comparar el estado deseado con el estado actual. A la hora del despliegue es el que enlaza las máquinas.
Manuel Franco's avatar
Manuel Franco committed
106
107
108

*Kube-proxy:*

Manuel Franco's avatar
Manuel Franco committed
109
Refleja los servicios definidos en la API de Kubernetes en cada nodo con con peticiones TCP/UDP simples o balanceadas a través de los diferentes backends. Las direcciónes del clúster IP y puerto d elos diferentes Docker-links están disponibles mediante variables de entorno abiertas por el servidor proxy.
Manuel Franco's avatar
Manuel Franco committed
110
111
112
113
114

*Container Runtime:*

Es el software que se encarga de crear los contendores. Kubernetes originalmente estaba pensado para contenedores Docker pero con el paso de tiempo han ido habilitando nuevos backends como RKT o en nuestro caso uno bastante reciente
y en estado prematuro como cri-o.
Manuel Franco's avatar
Manuel Franco committed
115
116

### ¿Qué es Cri-o? y ¿Por qué?
Manuel Franco's avatar
Manuel Franco committed
117

Manuel Franco's avatar
Manuel Franco committed
118
119
Cri-o es un software de creación de contenedores escrito go y desarrollado por Red-Hat dentro del proyecto Atomic. Red-Hat ha querido seguir la filosofía UNIX en este proyecto, ya que para intentar hacer competencia a docker,
ha creado diferentes softwares para emularlo. Por ejemplo tenemos cri-o como creador de contenedor, buildah para crear imágenes y no un software pesado y gigantesco que lo engloba todo.
Manuel Franco's avatar
Cri-o    
Manuel Franco committed
120

Manuel Franco's avatar
Manuel Franco committed
121
Esto no es todo, cri-o además, es compatible con imágenes Docker por lo podremos reutilizar las ya desplegadas. Cri-o, además es capaz de realizar centralizados de logs y métricas, así como soportar diferentes sistemas de ficheros.
Manuel Franco's avatar
Cri-o    
Manuel Franco committed
122
123
124

Y poco más hay que contar, se dedica a crear contendores, sin más.

Manuel Franco's avatar
Manuel Franco committed
125
El motivo de haber elegido cri-o como backend par Kubernetes es ese, al ser un software que solo se dedica a crear contenedores nuestro entorno requerirá menos recursos "en teoría"
Manuel Franco's avatar
Manuel Franco committed
126
127
para desplegar nuestro clúster de Kubernetes.

Manuel Franco's avatar
Manuel Franco committed
128
### ¿Qué es Ceph?
Manuel Franco's avatar
Manuel Franco committed
129

Manuel Franco's avatar
Manuel Franco committed
130
131
Es un sistema de almacenamiento distribuido y diseñado bajo licencia GPL como software libre, tiene parte de su código escrito en Python y otro en C++. Nos permite almacenamiento de objetos,
ofrecer dispositivos de bloques para almacenamiento y desplegar un sistema de ficheros.
Manuel Franco's avatar
Ceph    
Manuel Franco committed
132

Manuel Franco's avatar
Manuel Franco committed
133
134
135
136
137
138
139
140
141
142
143
144
145
La base de este sistema de almacenamiento es RADOS (Reliable Autonomic Distributed Object Store) y CRUSH (Controlled Replication Under Scalable Hashing), este último es el algoritmo que optimiza la utilización de los datos.
Nos proporciona también una interfaz REST que la expone Ceph Object Gateway (RGW) y los discos virtuales Ceph Block Device (RBD).

Ceph es una gran alternativa a sistemas de almacenamiento tipo SAN o NAS, pero ¿por qué elegí Ceph en lugar de soluciones como trident o nfs? Ceph nos proporcina las siguiente características:

* Rendimiento bastante alto
* Coste relativamente bajo
* Para crecer, solo es necesario añadir más equipos, elasticidad horizontal
* Muy flexible
* Control total al ser software libre
* Independencia de fabricantes

Ceph tiene diversos componentes que se comunican entre si para mantener la integridad del clúster de almacenamiento estos componentes son:
Manuel Franco's avatar
Ceph    
Manuel Franco committed
146
147
148

*OSD's:*

Manuel Franco's avatar
Manuel Franco committed
149
Es el demonio de almacenamiento de objetos, suele estar en el nodo que contiene los discos que son utilizados por el clúster, no se mezcla con el monitor. Además de maneja la replicación de los objetos y su recuperación. Balancea la carga de datos por el clúster y proporciona
Manuel Franco's avatar
Ceph    
Manuel Franco committed
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
datos del estado a los monitores y managers.

El mínimo son 3.

*Monitor:*

Se encarga de mantener un estado coherente en el clúster, además del mapeo de de los componentes en el esquema. Es esencial para la coordinación de los demonios.

Para entornos de producción serían necesarios un mínimo de 3.

*Servidor de metadatos:*

Almacena los metadatos de Ceph Filesystem, permite comandos básicos de POSIX filesystem y quita carga al clúster de almacenamiento ceph.

Mínimo 1.

*Managers:*

Incluido en la versión luminous se encarga de las métricas y del estado del clúster, así como de la utilización del espacio del clúster. Permite plugins de monitorización basados en pyton, incluye frontal web y REST API.

Necesarios mínimos 2 para alta disponibilidad.

Manuel Franco's avatar
Manuel Franco committed
172
## Escenario
Manuel Franco's avatar
Manuel Franco committed
173

Manuel Franco's avatar
Manuel Franco committed
174
175
176
177
178
179
180
El escenario se basa en dos nodos físicos:

* nodo1: 4 cores, 16GB de ram e hipervisor KVM
* nodo2: 8 cores, 8GB de ram e hipervisor KVM

En el nodo 1 se encuentra el clúster de Kubernetes repartido en tres máquina virtuales con Ubuntu 16.04 cada una de ellas con 2GB de RAM y 2 cores virtuales.

Manuel Franco's avatar
Manuel Franco committed
181
En el nodo2 está el clúster de almacemiento de Ceph en cuatro máquinas virtuales Debian Stretch, cada una de 1 GB de ram, 1 core virtual y un disco adicional de 20 GB.
Manuel Franco's avatar
Manuel Franco committed
182
183

Cada clúster está en una red diferentes por lo que he tenido que crear un router para enlazarlas. Mientra que Kubernetes está en la red doméstica 192.168.1.0/24, Ceph está en una red interna aislada en la 192.168.122.0/24.
Manuel Franco's avatar
Manuel Franco committed
184

Manuel Franco's avatar
Manuel Franco committed
185
El esquema es el siguiente:
Manuel Franco's avatar
Manuel Franco committed
186

Manuel Franco's avatar
Manuel Franco committed
187
![Esquema](/images/schema.png)
Manuel Franco's avatar
Manuel Franco committed
188

Manuel Franco's avatar
Manuel Franco committed
189
## Instalación
Manuel Franco's avatar
Manuel Franco committed
190

Manuel Franco's avatar
Manuel Franco committed
191
### Cri-o
Manuel Franco's avatar
Manuel Franco committed
192

Manuel Franco's avatar
Manuel Franco committed
193
Ahora voy a hacer la instalación de cri-o, esta instalación se ha realizado en cada uno de los nodos del clúster de Kubernetes para utilizarlo como backend.
Manuel Franco's avatar
Manuel Franco committed
194

Manuel Franco's avatar
Manuel Franco committed
195
Los binarios que voy a tener al final del proceso serán:
Manuel Franco's avatar
Manuel Franco committed
196
197
198
199
200
201
202
203

* crio - El software que maneja los pods
* crictl - El cliente CRI
* cni - La interfaz de red para los contendores.
* runc - El runtime con el estandar OCI para lanzar contendores.

#### runc

Manuel Franco's avatar
Manuel Franco committed
204
Descargo el binarios de Runc:
Manuel Franco's avatar
Manuel Franco committed
205
206
207
208
209

``` 
wget https://github.com/opencontainers/runc/releases/download/v1.0.0-rc4/runc.amd64
```

Manuel Franco's avatar
Manuel Franco committed
210
Le doy permisos de ejecución al binario:
Manuel Franco's avatar
Manuel Franco committed
211
212
213
214
215

```
chmod +x runc.amd64 && sudo mv runc.amd64 /usr/bin/runc
```

Manuel Franco's avatar
Manuel Franco committed
216
Para ver la correcta instalación veo la versión de Runc:
Manuel Franco's avatar
Manuel Franco committed
217
218
219
220
221
222
223

```
runc -version
```

#### cri-o

Manuel Franco's avatar
Manuel Franco committed
224
Para cri-o necesito instalarlo desde las fuentes, ya que no dispone de binario.
Manuel Franco's avatar
Manuel Franco committed
225

Manuel Franco's avatar
Manuel Franco committed
226
Instalo el runtime de Go:
Manuel Franco's avatar
Manuel Franco committed
227
228
229
230
231
232
233
234

```
wget https://storage.googleapis.com/golang/go1.8.5.linux-amd64.tar.gz
sudo tar -xvf go1.8.5.linux-amd64.tar.gz -C /usr/local/
mkdir -p $HOME/go/src
export GOPATH=$HOME/go && export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin
```

Manuel Franco's avatar
Manuel Franco committed
235
Instalo crictl
Manuel Franco's avatar
Manuel Franco committed
236
237
238
239
240
241
242
243

```
go get github.com/kubernetes-incubator/cri-tools/cmd/crictl
cd $GOPATH/src/github.com/kubernetes-incubator/cri-tools
make
make install
```

Manuel Franco's avatar
Manuel Franco committed
244
Compilo desde las fuentes:
Manuel Franco's avatar
Manuel Franco committed
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
```
sudo apt-get update && apt-get install -y libglib2.0-dev \
                                          libseccomp-dev \
                                          libgpgme11-dev \
                                          libdevmapper-dev \
                                          make \
                                          git
```

```
go get -d github.com/kubernetes-incubator/cri-o
cd $GOPATH/src/github.com/kubernetes-incubator/cri-o
make install.tools
sudo make install.config
make
sudo make install
```
Manuel Franco's avatar
Manuel Franco committed
262
Una vez se haya instalado todo, voy a habilitar los registries en el fichero de configuración de cri-o ``` /etc/crio/crio.conf ``` para que pueda acceder a descargar imágenes docker.
Manuel Franco's avatar
Manuel Franco committed
263
264
265
266
267

```
registries = ['registry.access.redhat.com', 'registry.fedoraproject.org', 'docker.io']
```

Manuel Franco's avatar
Manuel Franco committed
268
Creo el demonio de cri-o:
Manuel Franco's avatar
Manuel Franco committed
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
 
 ```
sudo sh -c 'echo "[Unit]
Description=OCI-based implementation of Kubernetes Container Runtime Interface
Documentation=https://github.com/kubernetes-incubator/cri-o

[Service]
ExecStart=/usr/local/bin/crio --log-level debug
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target" > /etc/systemd/system/crio.service'
 ```

Manuel Franco's avatar
Manuel Franco committed
284
Lo activo:
Manuel Franco's avatar
Manuel Franco committed
285
286
287
288
289

```
sudo systemctl daemon-reload && systemctl enable crio && systemctl start crio
```

Manuel Franco's avatar
Manuel Franco committed
290
Creo el endpoint de crio:
Manuel Franco's avatar
Manuel Franco committed
291
292
293
294
295

```
sudo crictl --runtime-endpoint unix:///var/run/crio/crio.sock version
```

Manuel Franco's avatar
Manuel Franco committed
296
Para hacerlo permanente tengo que exportar la siguiente variable de entorno:
Manuel Franco's avatar
Manuel Franco committed
297
298
299
300
301

```
export $CRI_RUNTIME_ENDPOINT=unix:///var/run/crio/crio.sock version
```

Manuel Franco's avatar
Manuel Franco committed
302
#### CNI
Manuel Franco's avatar
Manuel Franco committed
303

Manuel Franco's avatar
Manuel Franco committed
304
305
306
307
308
309
310
Para descargar CNI:

```
go get -d github.com/containernetworking/plugins
cd $GOPATH/src/github.com/containernetworking/plugins
```

Manuel Franco's avatar
Manuel Franco committed
311
Hago build a CNI plugins:
Manuel Franco's avatar
Manuel Franco committed
312
313
314
315
316

```
./build.sh
```

Manuel Franco's avatar
Manuel Franco committed
317
Instalo los plugins:
Manuel Franco's avatar
Manuel Franco committed
318
319
320
321
322
323

```
sudo mkdir -p /opt/cni/bin
sudo cp bin/* /opt/cni/bin/
```

Manuel Franco's avatar
Manuel Franco committed
324
#### Configurar CNI
Manuel Franco's avatar
Manuel Franco committed
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358

```
sudo mkdir -p /etc/cni/net.d
```

```
sudo sh -c 'cat >/etc/cni/net.d/10-mynet.conf <<-EOF
{
    "cniVersion": "0.2.0",
    "name": "mynet",
    "type": "bridge",
    "bridge": "cni0",
    "isGateway": true,
    "ipMasq": true,
    "ipam": {
        "type": "host-local",
        "subnet": "10.88.0.0/16",
        "routes": [
            { "dst": "0.0.0.0/0"  }
        ]
    }
}
EOF'
```

```
sudo sh -c 'cat >/etc/cni/net.d/99-loopback.conf <<-EOF
{
    "cniVersion": "0.2.0",
    "type": "loopback"
}
EOF'
```

Manuel Franco's avatar
Manuel Franco committed
359
E instalar skopeo-containers desde el repositorio de proyecto atomic:
Manuel Franco's avatar
Manuel Franco committed
360
361
362
363
364
365
366

```
sudo add-apt-repository ppa:projectatomic/ppa
sudo apt-get update
sudo apt-get install skopeo-containers -y
```

Manuel Franco's avatar
Manuel Franco committed
367
Y aplico los cambios a crio:
Manuel Franco's avatar
Manuel Franco committed
368
369
370
371

```
sudo systemctl restart crio
```
Manuel Franco's avatar
Manuel Franco committed
372

Manuel Franco's avatar
Manuel Franco committed
373
### Kubernetes
Manuel Franco's avatar
Manuel Franco committed
374

Manuel Franco's avatar
Manuel Franco committed
375
Durante la instalación de Kubernetes he encontrado una peculiaridad para tener crio como backend:
Manuel Franco's avatar
Manuel Franco committed
376
377
378

* ```Necesitamos tener docker instalado obligatoriamente, este "error" está corregido en la siguiente release de Kubernetes (1.11).```

Manuel Franco's avatar
Manuel Franco committed
379
Teniendo esto en cuenta voy a instalar el clúster de Kubernetes:
Manuel Franco's avatar
Manuel Franco committed
380
381
382
383
384
385
386
387
388
389
390
391
392

#### Instalar kubeadm, kubelet y kubectl

```
apt-get update && apt-get install -y apt-transport-https curl
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubelet kubeadm kubectl
```

Manuel Franco's avatar
Manuel Franco committed
393
Una vez instalados modifico el demonio de kubelet para que busque el socket de cri-o:
Manuel Franco's avatar
Manuel Franco committed
394
395
396
397
398
399
400
401
402
403
404
405
406

<pre>[Service]
Environment=&quot;KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf&quot;
Environment=&quot;KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true --container-runtime=remote --container-runtime-endpoint=unix:///var/run/crio/crio.sock --runtime-request-timeout=10m &quot;
Environment=&quot;KUBELET_NETWORK_ARGS=--network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin&quot;
Environment=&quot;KUBELET_DNS_ARGS=--cluster-dns=10.96.0.10 --cluster-domain=cluster.local&quot;
Environment=&quot;KUBELET_AUTHZ_ARGS=--authorization-mode=Webhook --client-ca-file=/etc/kubernetes/pki/ca.crt&quot;
Environment=&quot;KUBELET_CADVISOR_ARGS=--cadvisor-port=0&quot;
Environment=&quot;KUBELET_CERTIFICATE_ARGS=--rotate-certificates=true --cert-dir=/var/lib/kubelet/pki&quot;
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_SYSTEM_PODS_ARGS $KUBELET_NETWORK_ARGS $KUBELET_DNS_ARGS $KUBELET_AUTHZ_ARGS $KUBELET_CADVISOR_ARGS $KUBELET_CERTIFICATE_ARGS $KUBELET_EXTRA_ARGS
</pre>

Manuel Franco's avatar
Manuel Franco committed
407
También tengo que modificar el fichero de configuración de cni ```/etc/cni/net.d/10-mynet.conf```:
Manuel Franco's avatar
Manuel Franco committed
408
409
410
411
412
413
414

<pre>{
     &quot;name&quot;: &quot;mynet&quot;,
     &quot;type&quot;: &quot;flannel&quot;
}
</pre>

Manuel Franco's avatar
Manuel Franco committed
415
Una vez esté todo iniciado el servicio de kubelet, pero al ver su estado veo que se encuentra en estado de error, esto es por lo que he dicho antes:
Manuel Franco's avatar
Manuel Franco committed
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445

<pre>
jun 09 10:58:22 k8s-node2 systemd[1]: kubelet.service: Service hold-off time over, scheduling restart.
jun 09 10:58:22 k8s-node2 systemd[1]: Stopped kubelet: The Kubernetes Node Agent.
jun 09 10:58:22 k8s-node2 systemd[1]: Started kubelet: The Kubernetes Node Agent.
jun 09 10:58:23 k8s-node2 kubelet[1982]: I0609 10:58:23.001939    1982 feature_gate.go:226] feature gates: &amp;{{} map[]}
jun 09 10:58:23 k8s-node2 kubelet[1982]: I0609 10:58:23.020298    1982 server.go:376] Version: v1.10.3
jun 09 10:58:23 k8s-node2 kubelet[1982]: I0609 10:58:23.020330    1982 feature_gate.go:226] feature gates: &amp;{{} map[]}
jun 09 10:58:23 k8s-node2 kubelet[1982]: I0609 10:58:23.020407    1982 plugins.go:89] No cloud provider specified.
jun 09 10:58:23 k8s-node2 kubelet[1982]: W0609 10:58:23.020427    1982 server.go:517] standalone mode, no API client
jun 09 10:58:23 k8s-node2 kubelet[1982]: W0609 10:58:23.022902    1982 server.go:433] No api server defined - no events will be sent to API server.
jun 09 10:58:23 k8s-node2 kubelet[1982]: I0609 10:58:23.023128    1982 server.go:614] --cgroups-per-qos enabled, but --cgroup-root was not specified.  defaulting to /
jun 09 10:58:23 k8s-node2 kubelet[1982]: I0609 10:58:23.023416    1982 container_manager_linux.go:242] container manager verified user specified cgroup-root exists: /
jun 09 10:58:23 k8s-node2 kubelet[1982]: I0609 10:58:23.023533    1982 container_manager_linux.go:247] Creating Container Manager object based on Node Config: {RuntimeCgroupsName: SystemCgroupsName: KubeletCgroupsName: ContainerRuntime:docker CgroupsPerQOS:true CgroupRoot:/ CgroupDriver:cgroupfs KubeletRootDir:/var/lib/kubelet ProtectKernelDefaults:false NodeAllocatableConfig:{KubeReservedCgroupName: SystemReservedCgroupName: EnforceNodeAllocatable:map[pods:{}] KubeReserved:map[] SystemReserved:map[] HardEvictionThresholds:[{Signal:nodefs.inodesFree Operator:LessThan Value:{Quantity:&lt;nil&gt; Percentage:0.05} GracePeriod:0s MinReclaim:&lt;nil&gt;} {Signal:imagefs.available Operator:LessThan Value:{Quantity:&lt;nil&gt; Percentage:0.15} GracePeriod:0s MinReclaim:&lt;nil&gt;} {Signal:memory.available Operator:LessThan Value:{Quantity:100Mi Percentage:0} GracePeriod:0s MinReclaim:&lt;nil&gt;} {Signal:nodefs.available Operator:LessThan Value:{Quantity:&lt;nil&gt; Percentage:0.1} GracePeriod:0s MinReclaim:&lt;nil&gt;}]} ExperimentalQOSReserved:map[] ExperimentalCPUManagerPolicy:none ExperimentalCPUManagerReconcilePeriod:10s ExperimentalPodPidsLimit:-1 EnforceCPULimits:true}
jun 09 10:58:23 k8s-node2 kubelet[1982]: I0609 10:58:23.023891    1982 container_manager_linux.go:266] Creating device plugin manager: true
jun 09 10:58:23 k8s-node2 kubelet[1982]: I0609 10:58:23.024017    1982 state_mem.go:36] [cpumanager] initializing new in-memory state store
jun 09 10:58:23 k8s-node2 kubelet[1982]: I0609 10:58:23.024170    1982 state_mem.go:84] [cpumanager] updated default cpuset: &quot;&quot;
jun 09 10:58:23 k8s-node2 kubelet[1982]: I0609 10:58:23.024276    1982 state_mem.go:92] [cpumanager] updated cpuset assignments: &quot;map[]&quot;
jun 09 10:58:23 k8s-node2 kubelet[1982]: W0609 10:58:23.025777    1982 kubelet_network.go:139] Hairpin mode set to &quot;promiscuous-bridge&quot; but kubenet is not enabled, falling back to &quot;hairpin-veth&quot;
jun 09 10:58:23 k8s-node2 kubelet[1982]: I0609 10:58:23.025914    1982 kubelet.go:558] Hairpin mode set to &quot;hairpin-veth&quot;
jun 09 10:58:23 k8s-node2 kubelet[1982]: I0609 10:58:23.026729    1982 client.go:75] Connecting to docker on unix:///var/run/docker.sock
jun 09 10:58:23 k8s-node2 kubelet[1982]: I0609 10:58:23.026864    1982 client.go:104] Start docker client with request timeout=2m0s
jun 09 10:58:23 k8s-node2 kubelet[1982]: E0609 10:58:23.027044    1982 kube_docker_client.go:91] failed to retrieve docker version: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
jun 09 10:58:23 k8s-node2 kubelet[1982]: W0609 10:58:23.027171    1982 kube_docker_client.go:92] Using empty version for docker client, this may sometimes cause compatibility issue.
jun 09 10:58:23 k8s-node2 kubelet[1982]: F0609 10:58:23.027409    1982 server.go:233] failed to run Kubelet: failed to create kubelet: failed to get docker version: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
jun 09 10:58:23 k8s-node2 systemd[1]: <b>kubelet.service: Main process exited, code=exited, status=255/n/a</b>
jun 09 10:58:23 k8s-node2 systemd[1]: <b>kubelet.service: Unit entered failed state.</b>
jun 09 10:58:23 k8s-node2 systemd[1]: <b>kubelet.service: Failed with result &apos;exit-code&apos;.</b>
</pre>

Manuel Franco's avatar
Manuel Franco committed
446
Kubelet no encuentra una versión de docker ni tampoco el socket de este, por eso tengo que instalarlo. Con la versión que nos proporciona ubuntu en sus repositorios está bien:
Manuel Franco's avatar
Manuel Franco committed
447
448
449
450
451

```
apt install docker.io
```

Manuel Franco's avatar
Manuel Franco committed
452
Con esto ya puedo desplegar el clúster de Kubernetes con la red para flannel e ignorando la comprobación de requisitos ya que me da un error al comprobar el estado de Docker:
Manuel Franco's avatar
Manuel Franco committed
453
454
455
456
457

``` 
kubeadm init --pod-network-cidr=10.244.0.0/16 --ignore-preflight-errors=all
```

Manuel Franco's avatar
Manuel Franco committed
458
Una vez arrancado creo el fichero .kube/config para poder interactuar con el clúster:
Manuel Franco's avatar
Manuel Franco committed
459
460
461
462
463

```
cd && mkdir .kube && cp /etc/kubernetes/admin.conf $HOME/.kube/config
```

Manuel Franco's avatar
Manuel Franco committed
464
Y con el token que nos proporcio añado los nodos al clúster.
Manuel Franco's avatar
Manuel Franco committed
465

Manuel Franco's avatar
Manuel Franco committed
466
Una vez añadidos despliego la red de overlay, la que he elegido es flannel:
Manuel Franco's avatar
Manuel Franco committed
467
468
469
470
471

```
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.10.0/Documentation/kube-flannel.yml
```

Manuel Franco's avatar
Manuel Franco committed
472
Y con esto ya tenemos el clúster de Kubernetes levantado y funcionando ahora voy a hacer algunas comprobaciones:
Manuel Franco's avatar
Manuel Franco committed
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491

#### Pods de sistema:

<pre>root@ubuntu:~# kubectl get pods -n kube-system
NAME                                    READY     STATUS    RESTARTS   AGE
etcd-ubuntu                             1/1       Running   10         13d
kube-apiserver-ubuntu                   1/1       Running   10         13d
kube-controller-manager-ubuntu          1/1       Running   10         13d
kube-dns-86f4d74b45-x5jst               3/3       Running   0          1h
kube-flannel-ds-b5zc7                   1/1       Running   7          13d
kube-flannel-ds-lbdvw                   1/1       Running   9          13d
kube-flannel-ds-q5885                   1/1       Running   0          53s
kube-proxy-dddxt                        1/1       Running   10         13d
kube-proxy-kszgn                        1/1       Running   0          53s
kube-proxy-ns4cg                        1/1       Running   7          13d
kube-scheduler-ubuntu                   1/1       Running   10         13d
kubernetes-dashboard-7d5dcdb6d9-gcv95   1/1       Running   0          1h
</pre>

Manuel Franco's avatar
Manuel Franco committed
492
Se ve como tengo todos los pods que necesito, un kube-proxy y kube-flannel por nodo, kube-dns, el apiserver, etcd, scheduler y el dashboard de kubernetes. Por aquí, todo correcto.
Manuel Franco's avatar
Manuel Franco committed
493
494
495

#### Runtime utilizado:

Manuel Franco's avatar
Manuel Franco committed
496
Voy a asegurar que todos los nodos estén utilizando cri-o como backend y no docker:
Manuel Franco's avatar
Manuel Franco committed
497
498
499
500
501
502
503
504
505

<pre>root@ubuntu:~# kubectl describe node ubuntu | grep Runtime
 Container <font color="#EF2929"><b>Runtime</b></font> Version:  cri-o://1.11.0-dev
root@ubuntu:~# kubectl describe node k8s-node1 | grep Runtime
 Container <font color="#EF2929"><b>Runtime</b></font> Version:  cri-o://1.11.0-dev
root@ubuntu:~# kubectl describe node k8s-node2 | grep Runtime
 Container <font color="#EF2929"><b>Runtime</b></font> Version:  cri-o://1.11.0-dev
</pre>

Manuel Franco's avatar
Manuel Franco committed
506
Y aunque Kubernetes diga que está utilizando cri-o, voy a comprobar en cada nodo con ```crictl``` los contenedores que están corriendo:
Manuel Franco's avatar
Manuel Franco committed
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541

<pre>root@ubuntu:~# crictl ps
CONTAINER ID        IMAGE                                                                                                           CREATED             STATE               NAME                      ATTEMPT
4b3df50462894       k8s.gcr.io/kubernetes-dashboard-amd64@sha256:dc4026c1b595435ef5527ca598e1e9c4343076926d7d62b365c44831395adbd0   2 hours ago         Running             kubernetes-dashboard      0
91d4a37001ffe       f0fad859c909baef1b038ef8d2f6e76fc252e25a3d9af37b82ce70623fb7cd6f                                                2 hours ago         Running             kube-flannel              9
5d242fe8e6405       4261d315109d99f7149dc8de048ec12c11a77c3cd7d3479654f630c0c14c0c60                                                2 hours ago         Running             kube-proxy                10
d360da376ef7b       353b8f1d102e959e7865da53e9a63554789212f881e8d92d3289b3948c59c9be                                                2 hours ago         Running             kube-scheduler            10
c2bdc36f7e644       e03746fe22c35cb7434d36ac9cf9fd8bd4810af28081058e40db59e1cbe4a674                                                2 hours ago         Running             kube-apiserver            10
2c7881d78feaa       40c8d10b2d11cbc3db2e373a5ffce60dd22dbbf6236567f28ac6abb7efbfc8a9                                                2 hours ago         Running             kube-controller-manager   10
ee4e16b1fd6f5       52920ad46f5bf730d0e35e11215ec12d04ca5f32835f2ceb8093d0bd38930735                                                2 hours ago         Running             etcd                      10
root@ubuntu:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
</pre>

<pre>root@k8s-node1:~# crictl ps
CONTAINER ID        IMAGE                                                                                                              CREATED             STATE               NAME                ATTEMPT
ff86dba968f7e       18ea23a675dae45702b278215a4b6d20583a907a98b2b82d2af709c3ba86c76a                                                   2 hours ago         Running             nginx               0
23326d801a1f0       18ea23a675dae45702b278215a4b6d20583a907a98b2b82d2af709c3ba86c76a                                                   2 hours ago         Running             nginx               0
7e4f7d8fe9b7e       k8s.gcr.io/k8s-dns-sidecar-amd64@sha256:23df717980b4aa08d2da6c4cfa327f1b730d92ec9cf740959d2d5911830d82fb           2 hours ago         Running             sidecar             0
5fb60b3821a12       k8s.gcr.io/k8s-dns-dnsmasq-nanny-amd64@sha256:93c827f018cf3322f1ff2aa80324a0306048b0a69bc274e423071fb0d2d29d8b     2 hours ago         Running             dnsmasq             0
bc4de70f8bf6f       k8s.gcr.io/k8s-dns-kube-dns-amd64@sha256:6d8e0da4fb46e9ea2034a3f4cab0e095618a2ead78720c12e791342738e5f85d          2 hours ago         Running             kubedns             0
6036c71c2b2ab       docker.io/library/owncloud@sha256:abb9b13f96fcd70d62984d29a3bfe28c4aabedda91296c38a14d6ef1a0fabca5                 2 hours ago         Running             guacamole           2
51597b88025c2       18ea23a675dae45702b278215a4b6d20583a907a98b2b82d2af709c3ba86c76a                                                   2 hours ago         Running             nginx               2
1b52905bf8bf6       quay.io/external_storage/rbd-provisioner@sha256:d20241503a59414791608e0b5b7c6ceeb7212510723accecb292c8ce95fe570a   2 hours ago         Running             rbd-provisioner     2
99ee664814cb1       docker.io/oznu/guacamole@sha256:eb7809bce91260eb47414c8e526d846502cdef1344178164ace110798b71821e                   2 hours ago         Running             guacamole           5
48fcf060920ed       f0fad859c909baef1b038ef8d2f6e76fc252e25a3d9af37b82ce70623fb7cd6f                                                   2 hours ago         Running             kube-flannel        7
621ab279c673d       4261d315109d99f7149dc8de048ec12c11a77c3cd7d3479654f630c0c14c0c60                                                   2 hours ago         Running             kube-proxy          7
</pre>

<pre>root@k8s-node2:/home/ubuntu# crictl ps
CONTAINER ID        IMAGE                                                              CREATED             STATE               NAME                ATTEMPT
06d69e717edfb       f0fad859c909baef1b038ef8d2f6e76fc252e25a3d9af37b82ce70623fb7cd6f   10 minutes ago      Running             kube-flannel        0
e54d0ab7619eb       4261d315109d99f7149dc8de048ec12c11a77c3cd7d3479654f630c0c14c0c60   11 minutes ago      Running             kube-proxy          0
</pre>

Manuel Franco's avatar
Manuel Franco committed
542
### Ceph
Manuel Franco's avatar
Manuel Franco committed
543

Manuel Franco's avatar
Manuel Franco committed
544
Una vez tengo instalado el clúster de Kubernetes ya funcionando con cri-o, me queda montar el sistema de almacenamiento. Esto lo haré con ceph-deploy que lo obtendré desde los repositorios.
Manuel Franco's avatar
Manuel Franco committed
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648

#### Preinstalación:

Importo la clave y repositorio e instalo los paquetes básicos:

```
sudo wget -q -O- 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc' | sudo apt-key add -
sudo echo deb https://download.ceph.com/debian-luminous/ $(lsb_release -sc) main | sudo tee /etc/apt/sources.list.d/ceph.list
```

Instalación de paquetes en ceph-deployer:

```
sudo apt update && sudo apt install apt-transport-https ceph-deploy -y
```

En ceph1, ceph2, ceph3:

```
sudo apt update && sudo apt install ca-certificates apt-transport-https -y
```

Debo de añadir todos los nodos al /etc/hosts de ceph-deployer:

```
192.168.122.2	deployer
192.168.122.3	ceph1
192.168.122.4	ceph2
192.168.122.5	ceph3
```

Creo un usuario para ceph en todos los nodos y un par de claves ssh sin frase de paso en ceph-deployer:

```
sudo useradd -m -s /bin/bash deployer
```

Lo añado al grupo de sudoers:

```
echo "deployer ALL = (root) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/deployer && sudo chmod 0440 /etc/sudoers.d/deployer
```

Paso la clave a ceph1, ceph2 y ceph3:

```
ssh-copy-id deployer@ceph1 && ssh-copy-id deployer@ceph2 && ssh-copy-id deployer@ceph3
```

Configuro ssh:

``` 
nano .ssh/config

```

```
Host ceph1
 Hostname ceph1
 User deployer
Host ceph2
 Hostname ceph2
 User deployer
Host ceph3
 Hostname ceph3
 User deployer
```

#### Despliegue:

Lo primero que hice es logarme con el usuario que he creado y crear un directorio para el clúster:

```
su - deployer
mkdir cluster && cd cluster
```

Creo un nuevo despliegue y genero todos los tokens necesarios:

```
ceph-deploy new ceph-deployer
```

Y despliego ceph en todos los nodos:

```
ceph-deploy install ceph1 ceph2 ceph3 ceph-deployer
```

Ahora voy a crear el primer monitor y propagar los keyrings a todos los nodos del clúster:

~~~
ceph-deploy mon create-initial
ceph-deploy admin ceph-deployer ceph1 ceph2 ceph3
~~~

Con esto, toda la paquetería de ceph estará presente en los nodos de nuestro clúster. 

El siguiente paso es desplegar los OSD's:

~~~
ceph-deploy osd create ceph1:sdb ceph2:sdb ceph3:sdb
~~~

Manuel Franco's avatar
Ceph    
Manuel Franco committed
649
650
651
652
653
654
655
656
657
Una vez haya acabado el proceso, voy a comprobar el estado del clúster con ``` ceph -s ``` y nos devuelve HEALTH_OK, entonces prosigo.

Voy a crear el servidor de metadatos y el monitor:

```
ceph-deploy mds create ceph-deployer
ceph-deploy mon create ceph-deployer
```

Manuel Franco's avatar
Manuel Franco committed
658
Podría añadir un segundo monitor hay que crear un ``` quorum ``` pero sería en una máquina que no tuviera OSD.
Manuel Franco's avatar
Ceph    
Manuel Franco committed
659
660
661
662
663
664
665
666
667
668
669
670
671

Y en otro máquina añado el manager:

```
ceph-deploy mgr create ceph1
```

Solo falta RGW:

```
ceph-deploy rgw create ceph-deployer
```

Manuel Franco's avatar
Manuel Franco committed
672
Listo los pools disponibles:
Manuel Franco's avatar
Ceph    
Manuel Franco committed
673
674
675
676

<pre>root@deployer:~# ceph osd lspools
0 rbd,1 .rgw.root,2 default.rgw.control,3 default.rgw.data.root,4 default.rgw.gc,5 default.rgw.log,6 default.rgw.users.uid,7 k8s-pool,8 kube,
</pre>
Manuel Franco's avatar
Manuel Franco committed
677

Manuel Franco's avatar
Manuel Franco committed
678
### Despliegue de RBD-provisioner
Manuel Franco's avatar
Manuel Franco committed
679

Manuel Franco's avatar
Manuel Franco committed
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
RBD-provisioner es la implementación que permite crear volúmenes dinámicamente desde un clúster de Kubernetes, para será necesario una serie de pasos:

Desde el clúster de ceph creamos el secret de admin:

~~~
ceph auth get client.admin 2>&1 |grep "key = " |awk '{print  $3'} |xargs echo -n > /tmp/secret
kubectl create secret generic ceph-admin-secret --from-file=/tmp/secret --namespace=kube-system
~~~

Y además el pool y el secret del usuario:

~~~
ceph osd pool create kube 8 8
ceph auth add client.kube mon 'allow r' osd 'allow rwx pool=kube'
ceph auth get client.kube 2>&1 |grep "key = " |awk '{print  $3'} |xargs echo -n > /tmp/secret
kubectl create secret generic ceph-secret --from-file=/tmp/secret --namespace=kube-system
~~~

Estos secrets que se muestran por pantalla los he introducido en ```rbd-provisioner/secrets.yaml```, con esto ya puedo proceder a crear el aprovisonamiento dinámico:

~~~
kubectl create -f rbd-provisioner/
~~~

rbd-provisioner se despliega en el namespace default pero accede a los secrets que están en el namespace kube-system, esto es la principal dificultad que me encontré en su despliegue. 
En la documentación de github, en clusterrole.yaml observamos los permisos que le asignan y faltan los permisos de "get" y "list" secrets en dicho namespace, por ello los añadí:

~~~
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: rbd-provisioner
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["list", "watch", "create", "update", "patch"]
  - apiGroups: [""]
    resources: ["services"]
    resourceNames: ["kube-dns"]
    verbs: ["list", "get"]
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get", "list"]
~~~

El estado que tiene que quedar es el siguiente:

<pre>root@ubuntu:~# kubectl get pods 
NAME                              READY     STATUS    RESTARTS   AGE
rbd-provisioner-bc956f5b4-ft7r2   1/1       Running   3          7d
</pre>
Manuel Franco's avatar
Manuel Franco committed
739

Manuel Franco's avatar
Manuel Franco committed
740
## Funcionamiento
Manuel Franco's avatar
Manuel Franco committed
741

Manuel Franco's avatar
Manuel Franco committed
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
Para comprobar el funcionamiento del clúster voy a desplegar una aplicación que haga uso de ese volumen, utilizaré owncloud. Pero antes voy a explicar como funciona rbd-provisioner:

![rbd-provisioner](/images/rbd-provider.png)

1. Insertamos yaml solicitando recursos.
2. Apiserver empieza a crear pods, deployments, daemonsets...
3. La api busca el endpoint del storageclass que está en el pod rbd-provisioner
4. Rbd-provisioner con los secrets y permisos sobre el pool solicita el volumen
5. Rbd-provisioner le pasa el volumen a la api
6. La api crea el pv y el pvc.

Despliegue de owncloud: 

![owncloud-deploy.yaml](/deploy/owncloud-deploy.yaml)

Manuel Franco's avatar
Manuel Franco committed
757
## Conclusión
Manuel Franco's avatar
Manuel Franco committed
758

Manuel Franco's avatar
Manuel Franco committed
759
760
La idea principal que he sacado de este proyecto es que una solución basada en Ceph ha de estar separada del gestor de contenedores ya que al intentar desplegar 
rook.io para la integración con ceph a los días de estar desplegado con aplicaciones los pods entraban en estado de ```error``` y se perdía la información. Mientras que con RBD-provisioner y un clúster externo ha sido totalmente consistente.
Manuel Franco's avatar
Manuel Franco committed
761

Manuel Franco's avatar
Manuel Franco committed
762
763
El resultado de la unión de estas dos tecnologías tan elásticas creo que es muy interesante ya que podemos incrementar la capacidad de ambas tecnologías tanto como hardware tengamos o incluso crecer en la nube
teniendo entornos híbridos.
Manuel Franco's avatar
Manuel Franco committed
764

Manuel Franco's avatar
Manuel Franco committed
765
766
Cri-o aparentemente parecía que iba a ser un backend para Kubernetes más ligero que Docker por la ausencia del entorno y por estar expresamente enfocadoa Kubernetes, pero para mi sorpresa es que de momento no, es igual que Docker
y en algunos momentos incluso más pesado. Esto posiblemente puede deberse al poco tiempo de Cri-o y la falta de optimización.
Manuel Franco's avatar
Manuel Franco committed
767

Manuel Franco's avatar
Manuel Franco committed
768
## Trabajo por hacer
Manuel Franco's avatar
Manuel Franco committed
769

Manuel Franco's avatar
Manuel Franco committed
770
771
772
773
774
775
776
777
El trabajo que queda por hacer es todavía amplio, puedo decir que este el primer paso para tener un cluster de Kubernetes listo para producción con altas cargas de trabajo, si en el futuro sigo con el proyecto o alguien quiere seguirlo dejo aquí una lista de tareas pendientes que bajo mi opinión serían interesantes:

* Alta disponibilidad del nodo master.
* Recolección de métricas con el operador de prometheus.
* Centralización de logs con fluentd
* Instalación de KubeVirt para alta disponibilidad de los nodos.
* Integración de multiarquitectura por si se integraran nodos ARM.

Manuel Franco's avatar
Manuel Franco committed
778
## Fuentes
Manuel Franco's avatar
Manuel Franco committed
779

Manuel Franco's avatar
Manuel Franco committed
780
781
782
783
784
785
Las fuentes han sido sobretodo documentaciones oficiales de las herramientas utilizadas.

Para Ceph:

https://manuelfrancoblog.wordpress.com/2018/02/19/ceph/

Manuel Franco's avatar
Manuel Franco committed
786
787
788
789
http://apprize.info/web/ceph/1.html

http://docs.ceph.com/docs/hammer/architecture/

Manuel Franco's avatar
Manuel Franco committed
790
791
https://www.ull.es/servicios/stic/2016/11/11/sistema-de-almacenamiento-ceph/

Manuel Franco's avatar
Manuel Franco committed
792
793
794
795
796
797
798
799
800
Cri-o:

https://github.com/kubernetes-incubator/cri-o/blob/master/tutorial.md

https://github.com/kubernetes-incubator/cri-o/blob/master/kubernetes.md

Kubernetes:

https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/
Manuel Franco's avatar
Manuel Franco committed
801

Manuel Franco's avatar
Manuel Franco committed
802
Rbd-provisioner:
Manuel Franco's avatar
Manuel Franco committed
803

Manuel Franco's avatar
Manuel Franco committed
804
https://github.com/kubernetes-incubator/external-storage/tree/master/ceph/rbd