From b934759ceba7c3d5cf05c7d43f524b2be6e168b2 Mon Sep 17 00:00:00 2001 From: xguefer Date: Thu, 24 Jul 2025 18:02:33 +0200 Subject: [PATCH] first commit --- Clusterkey.txt | 30 + cephrook.md | 206 ++++++ cert-manager/clusterissuer-prod.yaml | 14 + cert-manager/clusterissuer-staging.yaml | 14 + cert-manager/kustomization.yaml | 6 + cert-manager/namespace.yaml | 4 + cert-manager/readme.md | 15 + comprobaciones.md | 72 ++ kubevirt-manager/deployments/deployment.yaml | 24 + kubevirt-manager/ingress/ingress.yaml | 26 + kubevirt-manager/kustomization.yaml | 7 + kubevirt-manager/namespace.yaml | 4 + kubevirt-manager/rbac/clusterrolebinding.yaml | 12 + kubevirt-manager/rbac/serviceaccount.yaml | 6 + kubevirt-manager/services/service.yaml | 14 + kubevirt.md | 65 ++ metallb/ipaddresspool.yaml | 7 + metallb/kustomization.yaml | 4 + metallb/l2advertisement.yaml | 5 + multus/nad-br-servicios.yaml | 19 + multus/test-multus-pod.yaml | 14 + readme-suse.md | 696 ++++++++++++++++++ readme.md | 43 ++ .../deployments/nfs-client-provisioner.yaml | 41 ++ storage/deployments/nfs-server.yaml | 43 ++ storage/kustomization.yaml | 8 + storage/namespace.yaml | 4 + storage/rbac/clusterrole.yaml | 20 + storage/rbac/clusterrolebinding.yaml | 12 + storage/rbac/serviceaccount.yaml | 5 + storage/readme.md | 17 + storage/storageclass/storageclass.yaml | 9 + traefik/configmaps/configmap.yaml | 16 + traefik/deployments/deployment.yaml | 28 + traefik/ingress/ingress.yaml | 32 + traefik/ingressclass.yaml | 6 + traefik/kustomization.yaml | 11 + traefik/namespace.yaml | 4 + traefik/rbac/clusterrole.yaml | 62 ++ traefik/rbac/clusterrolebinding.yaml | 12 + traefik/rbac/serviceaccount.yaml | 5 + traefik/services/service.yaml | 16 + 42 files changed, 1658 insertions(+) create mode 100644 Clusterkey.txt create mode 100644 cephrook.md create mode 100644 cert-manager/clusterissuer-prod.yaml create mode 100644 cert-manager/clusterissuer-staging.yaml create mode 100644 cert-manager/kustomization.yaml create mode 100644 cert-manager/namespace.yaml create mode 100644 cert-manager/readme.md create mode 100644 comprobaciones.md create mode 100644 kubevirt-manager/deployments/deployment.yaml create mode 100644 kubevirt-manager/ingress/ingress.yaml create mode 100644 kubevirt-manager/kustomization.yaml create mode 100644 kubevirt-manager/namespace.yaml create mode 100644 kubevirt-manager/rbac/clusterrolebinding.yaml create mode 100644 kubevirt-manager/rbac/serviceaccount.yaml create mode 100644 kubevirt-manager/services/service.yaml create mode 100644 kubevirt.md create mode 100644 metallb/ipaddresspool.yaml create mode 100644 metallb/kustomization.yaml create mode 100644 metallb/l2advertisement.yaml create mode 100644 multus/nad-br-servicios.yaml create mode 100644 multus/test-multus-pod.yaml create mode 100644 readme-suse.md create mode 100644 readme.md create mode 100644 storage/deployments/nfs-client-provisioner.yaml create mode 100644 storage/deployments/nfs-server.yaml create mode 100644 storage/kustomization.yaml create mode 100644 storage/namespace.yaml create mode 100644 storage/rbac/clusterrole.yaml create mode 100644 storage/rbac/clusterrolebinding.yaml create mode 100644 storage/rbac/serviceaccount.yaml create mode 100644 storage/readme.md create mode 100644 storage/storageclass/storageclass.yaml create mode 100644 traefik/configmaps/configmap.yaml create mode 100644 traefik/deployments/deployment.yaml create mode 100644 traefik/ingress/ingress.yaml create mode 100644 traefik/ingressclass.yaml create mode 100644 traefik/kustomization.yaml create mode 100644 traefik/namespace.yaml create mode 100644 traefik/rbac/clusterrole.yaml create mode 100644 traefik/rbac/clusterrolebinding.yaml create mode 100644 traefik/rbac/serviceaccount.yaml create mode 100644 traefik/services/service.yaml diff --git a/Clusterkey.txt b/Clusterkey.txt new file mode 100644 index 0000000..15196c1 --- /dev/null +++ b/Clusterkey.txt @@ -0,0 +1,30 @@ +Your Kubernetes control-plane has initialized successfully! + +To start using your cluster, you need to run the following as a regular user: + + mkdir -p $HOME/.kube + sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config + sudo chown $(id -u):$(id -g) $HOME/.kube/config + +Alternatively, if you are the root user, you can run: + + export KUBECONFIG=/etc/kubernetes/admin.conf + +You should now deploy a pod network to the cluster. +Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: + https://kubernetes.io/docs/concepts/cluster-administration/addons/ + +You can now join any number of control-plane nodes running the following command on each as root: + + kubeadm join 192.168.0.20:6443 --token iksja1.azpmfyakfg3j8q98 \ + --discovery-token-ca-cert-hash sha256:d41f0edb90c66c0555bdf4feca55f1e69019764be0fcd649a254e99ff124568f \ + --control-plane --certificate-key 06034ca8efb33004a3ee5eedbe887488db9819ede85394e8fb173361b16d4022 + +Please note that the certificate-key gives access to cluster sensitive data, keep it secret! +As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use +"kubeadm init phase upload-certs --upload-certs" to reload certs afterward. + +Then you can join any number of worker nodes by running the following on each as root: + +kubeadm join 192.168.0.20:6443 --token iksja1.azpmfyakfg3j8q98 \ + --discovery-token-ca-cert-hash sha256:d41f0edb90c66c0555bdf4feca55f1e69019764be0fcd649a254e99ff124568f diff --git a/cephrook.md b/cephrook.md new file mode 100644 index 0000000..9885e2b --- /dev/null +++ b/cephrook.md @@ -0,0 +1,206 @@ +# Despliegue de Rook-Ceph en clúster K3s (SUSE) con discos locales (Bluestore) + +Esta guía describe cómo desplegar un clúster Rook-Ceph sobre K3s en servidores SUSE con **discos locales** estándar (sin iSCSI). Se adapta a la arquitectura de 4 servidores: `srvfkvm1`, `srvfkvm2`, `srvfkvm3`, `srvfkvm4`, cada uno con 6 discos de \~900GB. + +--- + +## 1. Requisitos previos + +* 4 nodos K3s funcionando: `SRVFKVM01`, `SRVFKVM02`, `SRVFKVM03`, `SRVFKVM04` +* Cada nodo con 6 discos locales dedicados para Ceph (`/dev/sdj` a `/dev/sdo` en cada servidor) +* K3s y `kubectl` funcionando y configurado +* Acceso completo a Internet desde todos los nodos + +--- + +## 2. Preparar los nodos SUSE (sólo discos locales) + +No es necesario configurar iSCSI ni multipath. **Asegúrate de que los discos están vacíos y sin particionar,** o bien elimina las particiones creadas (Ceph las sobreescribirá). + +Verifica los discos en cada nodo: + +```bash +lsblk | grep sd[j-o] +``` + +--- + +## 3. Crear namespace y CRDs de Rook-Ceph + +```bash +kubectl create namespace rook-ceph + +# Clona el repositorio oficial de Rook +git clone https://github.com/rook/rook.git +cd rook/deploy/examples + +# Aplica CRDs y recursos comunes +kubectl apply -f crds.yaml +kubectl apply -f common.yaml +``` + +--- + +## 4. Desplegar el operador Rook-Ceph + +```bash +kubectl apply -f operator.yaml +``` + +--- + +## 5. Crear el clúster Ceph con discos locales + +Crea un archivo `ceph-cluster.yaml` con el siguiente contenido (ajusta nombres/discos según corresponda): + +```yaml +apiVersion: ceph.rook.io/v1 +kind: CephCluster +metadata: + name: rook-ceph + namespace: rook-ceph +spec: + cephVersion: + image: quay.io/ceph/ceph:v18 + dataDirHostPath: /var/lib/rook + mon: + count: 3 + allowMultiplePerNode: false + dashboard: + enabled: true + storage: + useAllNodes: false + useAllDevices: false + nodes: + - name: SRVFKVM01 + devices: + - name: /dev/sdj + - name: /dev/sdk + - name: /dev/sdl + - name: /dev/sdm + - name: /dev/sdn + - name: /dev/sdo + - name: SRVFKVM02 + devices: + - name: /dev/sdj + - name: /dev/sdk + - name: /dev/sdl + - name: /dev/sdm + - name: /dev/sdn + - name: /dev/sdo + - name: SRVFKVM03 + devices: + - name: /dev/sdj + - name: /dev/sdk + - name: /dev/sdl + - name: /dev/sdm + - name: /dev/sdn + - name: /dev/sdo + - name: SRVFKVM04 + devices: + - name: /dev/sdj + - name: /dev/sdk + - name: /dev/sdl + - name: /dev/sdm + - name: /dev/sdn + - name: /dev/sdo +``` + +> \*\*Asegúrate de que los nombres de los nodos (`name:`) coinciden con el valor mostrado por `kubectl get nodes`. + +Aplica el manifiesto: + +```bash +kubectl apply -f ceph-cluster.yaml +``` + +--- + +## 6. Verifica el despliegue de Ceph + +```bash +kubectl -n rook-ceph get pods +``` + +* Espera a que los pods estén en estado `Running`. + +Para comprobar el estado de Ceph: + +```bash +# Primero espera a que el pod rook-ceph-tools esté disponible +kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph status +``` + +--- + +## 7. Crear CephBlockPool y StorageClass (replica:2) + +**ceph-blockpool.yaml:** + +```yaml +apiVersion: ceph.rook.io/v1 +kind: CephBlockPool +metadata: + name: replicado-2x + namespace: rook-ceph +spec: + failureDomain: host + replicated: + size: 2 +``` + +**ceph-storageclass.yaml:** + +```yaml +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: ceph-rbd-replica2 +provisioner: rook-ceph.rbd.csi.ceph.com +parameters: + clusterID: rook-ceph + pool: replicado-2x + imageFormat: "2" + imageFeatures: layering + csi.storage.k8s.io/fstype: ext4 +reclaimPolicy: Delete +allowVolumeExpansion: true +mountOptions: + - discard +``` + +Aplica ambos: + +```bash +kubectl apply -f ceph-blockpool.yaml +kubectl apply -f ceph-storageclass.yaml +``` + +--- + +## 8. Accede al Ceph Dashboard + +Obtén el puerto del dashboard: + +```bash +kubectl -n rook-ceph get svc | grep dashboard +``` + +Obtén la contraseña: + +```bash +kubectl -n rook-ceph get secret rook-ceph-dashboard-password -o jsonpath="{.data.password}" | base64 -d +``` + +Accede en tu navegador a: + +``` +https://: +``` + +Usuario: `admin` +Contraseña: (la anterior) + +--- + +# Clúster Rook-Ceph listo para producción con discos locales y réplica cruzada en 4 nodos. diff --git a/cert-manager/clusterissuer-prod.yaml b/cert-manager/clusterissuer-prod.yaml new file mode 100644 index 0000000..4449b55 --- /dev/null +++ b/cert-manager/clusterissuer-prod.yaml @@ -0,0 +1,14 @@ +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-prod +spec: + acme: + email: xavor@hotmail.es + server: https://acme-v02.api.letsencrypt.org/directory + privateKeySecretRef: + name: letsencrypt-prod + solvers: + - http01: + ingress: + ingressClassName: traefik diff --git a/cert-manager/clusterissuer-staging.yaml b/cert-manager/clusterissuer-staging.yaml new file mode 100644 index 0000000..aa3272f --- /dev/null +++ b/cert-manager/clusterissuer-staging.yaml @@ -0,0 +1,14 @@ +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-staging +spec: + acme: + email: xavor@hotmail.es + server: https://acme-staging-v02.api.letsencrypt.org/directory + privateKeySecretRef: + name: letsencrypt-staging + solvers: + - http01: + ingress: + ingressClassName: traefik diff --git a/cert-manager/kustomization.yaml b/cert-manager/kustomization.yaml new file mode 100644 index 0000000..4acdc81 --- /dev/null +++ b/cert-manager/kustomization.yaml @@ -0,0 +1,6 @@ +namespace: cert-manager +resources: + - clusterissuer-prod.yaml + - clusterissuer-staging.yaml + + diff --git a/cert-manager/namespace.yaml b/cert-manager/namespace.yaml new file mode 100644 index 0000000..661039b --- /dev/null +++ b/cert-manager/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: cert-manager \ No newline at end of file diff --git a/cert-manager/readme.md b/cert-manager/readme.md new file mode 100644 index 0000000..158261a --- /dev/null +++ b/cert-manager/readme.md @@ -0,0 +1,15 @@ +# Cert Manager para Kubernetes + +Este repositorio contiene los manifiestos necesarios para desplegar [cert-manager](https://cert-manager.io), una herramienta que automatiza la gestión y renovación de certificados TLS en Kubernetes. + +Cert-manager se encarga de emitir y renovar automáticamente certificados mediante ACME (por ejemplo, Let's Encrypt), y es compatible con `Ingress` para habilitar TLS en tus servicios expuestos. + +--- + +## Despliegue + + kubectl apply -f namespace.yaml + kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml + kubectl apply -f clusterissuer-staging.yaml + kubectl apply -f clusterissuer-prod.yaml + diff --git a/comprobaciones.md b/comprobaciones.md new file mode 100644 index 0000000..63fa3d9 --- /dev/null +++ b/comprobaciones.md @@ -0,0 +1,72 @@ +# **Comprobaciones y diagnóstico habitual** + +### Estado de pods y despliegues + +```bash +kubectl get pods -A # Todos los pods de todos los namespaces +kubectl get pods -n traefik # Sólo los pods de Traefik +kubectl get pods -n cert-manager # Sólo cert-manager +kubectl get deployments -A # Todos los deployments +``` + +*Todos los pods deben estar en estado `Running` o `Completed`. Si alguno está en `CrashLoopBackOff` o `Error`, inspecciona con:* + +```bash +kubectl describe pod -n +kubectl logs -n +``` + +### Servicios, IPs y estado MetalLB + +```bash +kubectl get svc -A # Todos los servicios, revisa columna EXTERNAL-IP +kubectl get svc -n traefik # Servicio LoadBalancer de Traefik debe tener IP de MetalLB +``` + +### Certificados, secrets y recursos cert-manager + +```bash +kubectl get secrets -n traefik # Verifica el Secret TLS (ej: wildcard-cert) +kubectl describe secret wildcard-cert -n traefik +kubectl get certificate -A # (cert-manager) lista los recursos Certificate gestionados +kubectl describe certificate -n # Ver detalle y posibles errores +kubectl get clusterissuer,issuer -A # Ver emisores de cert-manager (staging, prod, etc.) +``` + +### Ingress, dominios y rutas + +```bash +kubectl get ingress -A +kubectl describe ingress -n +``` + +*Revisa que los hosts, paths y el campo `secretName` están correctos.* + +### Comprobar acceso SSL/TLS desde fuera + +```bash +openssl s_client -connect :443 -servername app1.miempresa.com +``` + +*Verifica el certificado servido y el SNI.* + +--- + +## g) **Comprobaciones útiles entre pasos** + +* Tras instalar Traefik y MetalLB: + Comprueba que el servicio Traefik tiene una IP del pool y responde en el puerto 80/443. + +* Tras instalar cert-manager y crear issuers: + Haz `kubectl get pods -n cert-manager` y revisa los logs si algún pod falla. + +* Tras crear un Secret TLS: + Haz `kubectl describe secret -n ` y asegúrate de que el tipo es `kubernetes.io/tls`. + +* Tras crear Ingress: + Comprueba con `kubectl get ingress -A` y revisa que los hosts y secrets estén bien referenciados. + +* Si accedes por navegador y hay error SSL: + Usa `openssl s_client` para ver qué certificado se está presentando realmente. + +--- \ No newline at end of file diff --git a/kubevirt-manager/deployments/deployment.yaml b/kubevirt-manager/deployments/deployment.yaml new file mode 100644 index 0000000..e3bd805 --- /dev/null +++ b/kubevirt-manager/deployments/deployment.yaml @@ -0,0 +1,24 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: kubevirt-manager + namespace: kubevirt-manager +spec: + replicas: 1 + selector: + matchLabels: + app: kubevirt-manager + template: + metadata: + labels: + app: kubevirt-manager + spec: + serviceAccountName: kubevirt-manager + containers: + - name: kubevirt-manager + image: kubevirtmanager/kubevirt-manager:1.4.0 + ports: + - containerPort: 8001 + env: + - name: BACKEND_URL + value: "http://localhost:8080" diff --git a/kubevirt-manager/ingress/ingress.yaml b/kubevirt-manager/ingress/ingress.yaml new file mode 100644 index 0000000..01204f9 --- /dev/null +++ b/kubevirt-manager/ingress/ingress.yaml @@ -0,0 +1,26 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: kubevirt-manager + namespace: kubevirt-manager + annotations: + cert-manager.io/cluster-issuer: "letsencrypt-prod" + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + nginx.ingress.kubernetes.io/backend-protocol: "HTTP" +spec: + ingressClassName: nginx + tls: + - hosts: + - kubevirt.manabo.org + secretName: kubevirt-manager-tls + rules: + - host: kubevirt.manabo.org + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: kubevirt-manager + port: + number: 80 diff --git a/kubevirt-manager/kustomization.yaml b/kubevirt-manager/kustomization.yaml new file mode 100644 index 0000000..3923093 --- /dev/null +++ b/kubevirt-manager/kustomization.yaml @@ -0,0 +1,7 @@ +resources: + - namespace.yaml + - deployments/deployment.yaml + - services/service.yaml +# - ingress/ingress.yaml + - rbac/serviceaccount.yaml + - rbac/clusterrolebinding.yaml diff --git a/kubevirt-manager/namespace.yaml b/kubevirt-manager/namespace.yaml new file mode 100644 index 0000000..232a17f --- /dev/null +++ b/kubevirt-manager/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: kubevirt-manager diff --git a/kubevirt-manager/rbac/clusterrolebinding.yaml b/kubevirt-manager/rbac/clusterrolebinding.yaml new file mode 100644 index 0000000..00934e5 --- /dev/null +++ b/kubevirt-manager/rbac/clusterrolebinding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: kubevirt-manager +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: +- kind: ServiceAccount + name: kubevirt-manager + namespace: kubevirt-manager diff --git a/kubevirt-manager/rbac/serviceaccount.yaml b/kubevirt-manager/rbac/serviceaccount.yaml new file mode 100644 index 0000000..71bde4a --- /dev/null +++ b/kubevirt-manager/rbac/serviceaccount.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: kubevirt-manager + namespace: kubevirt-manager + diff --git a/kubevirt-manager/services/service.yaml b/kubevirt-manager/services/service.yaml new file mode 100644 index 0000000..ded2a8d --- /dev/null +++ b/kubevirt-manager/services/service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: kubevirt-manager + namespace: kubevirt-manager +spec: + selector: + app: kubevirt-manager + ports: + - port: 80 + targetPort: 8001 + protocol: TCP + nodePort: 30081 # <--- puedes elegir el puerto, debe estar entre 30000-32767 + type: NodePort diff --git a/kubevirt.md b/kubevirt.md new file mode 100644 index 0000000..962a891 --- /dev/null +++ b/kubevirt.md @@ -0,0 +1,65 @@ +# Instalación de KubeVirt y CDI en Kubernetes (Ubuntu/SUSE) + +## 1. Instala KubeVirt y CDI + +KubeVirt permite crear y gestionar máquinas virtuales dentro de Kubernetes, integrando cargas virtualizadas junto a contenedores. CDI (Containerized Data Importer) facilita la gestión y carga de discos e ISOs para esas VMs. + +> **Nota:** Puedes usar manifiestos oficiales, o crear tu carpeta `kubevirt/` si deseas versionar los YAML personalizados. + +### Instala KubeVirt (recomendado hacerlo tras tener la red y almacenamiento) + +```bash +export KUBEVIRT_VERSION=$(curl -s https://api.github.com/repos/kubevirt/kubevirt/releases/latest | grep tag_name | cut -d '"' -f 4) +kubectl create namespace kubevirt +kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/kubevirt-operator.yaml +kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/kubevirt-cr.yaml +``` + +### Instala CDI (para gestión de discos/ISOs) + +```bash +export CDI_VERSION=$(curl -s https://api.github.com/repos/kubevirt/containerized-data-importer/releases/latest | grep tag_name | cut -d '"' -f 4) +kubectl create -f https://github.com/kubevirt/containerized-data-importer/releases/download/${CDI_VERSION}/cdi-operator.yaml +kubectl create -f https://github.com/kubevirt/containerized-data-importer/releases/download/${CDI_VERSION}/cdi-cr.yaml +``` + +--- + +## 2. Instala virtctl (CLI de KubeVirt) + +`virtctl` es una herramienta de línea de comandos para interactuar fácilmente con las máquinas virtuales de KubeVirt: arranque, apagado, consola, etc. + +```bash +curl -L -o virtctl https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/virtctl-${KUBEVIRT_VERSION}-linux-amd64 +chmod +x virtctl +sudo mv virtctl /usr/local/bin/ +``` + +--- + +## 3. Habilita KVM para tu usuario + +Para poder crear y gestionar máquinas virtuales, tu usuario debe pertenecer al grupo `kvm` (acceso al hardware de virtualización). + +```bash +sudo usermod -aG kvm $(whoami) +# Reinicia sesión o ejecuta 'newgrp kvm' para aplicar +``` + +--- + +## 4. Despliega kubevirt-manager + +`kubevirt-manager` es una interfaz web sencilla para gestionar tus máquinas virtuales desde el navegador. Esta sección aplica sus manifiestos en Kubernetes. + +La carpeta `kubevirt-manager/` contiene todos los manifiestos organizados por tipo: + +```bash +kubectl apply -k kubevirt-manager/ +``` + +Puedes comprobar el estado: + +```bash +kubectl get pods -n kubevirt-manager +``` diff --git a/metallb/ipaddresspool.yaml b/metallb/ipaddresspool.yaml new file mode 100644 index 0000000..bc5f778 --- /dev/null +++ b/metallb/ipaddresspool.yaml @@ -0,0 +1,7 @@ +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: single-ip +spec: + addresses: + - 192.168.1.100/32 diff --git a/metallb/kustomization.yaml b/metallb/kustomization.yaml new file mode 100644 index 0000000..aa029a0 --- /dev/null +++ b/metallb/kustomization.yaml @@ -0,0 +1,4 @@ +namespace: metallb-system +resources: + - ipaddresspool.yaml + - l2advertisement.yaml diff --git a/metallb/l2advertisement.yaml b/metallb/l2advertisement.yaml new file mode 100644 index 0000000..8f9ed7f --- /dev/null +++ b/metallb/l2advertisement.yaml @@ -0,0 +1,5 @@ +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: l2adv +spec: {} diff --git a/multus/nad-br-servicios.yaml b/multus/nad-br-servicios.yaml new file mode 100644 index 0000000..3019924 --- /dev/null +++ b/multus/nad-br-servicios.yaml @@ -0,0 +1,19 @@ +apiVersion: "k8s.cni.cncf.io/v1" +kind: NetworkAttachmentDefinition +metadata: + name: br-servicios + namespace: default +spec: + config: '{ + "cniVersion": "0.3.1", + "type": "bridge", + "bridge": "br-servicios", + "ipam": { + "type": "host-local", + "subnet": "192.168.200.0/22", + "rangeStart": "192.168.200.100", + "rangeEnd": "192.168.200.200", + "routes": [{"dst": "0.0.0.0/0"}], + "gateway": "192.168.200.1" + } + }' diff --git a/multus/test-multus-pod.yaml b/multus/test-multus-pod.yaml new file mode 100644 index 0000000..0249de4 --- /dev/null +++ b/multus/test-multus-pod.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Pod +metadata: + name: multus-test + annotations: + k8s.v1.cni.cncf.io/networks: br-servicios +spec: + containers: + - name: alpine + image: alpine + command: ["sleep", "infinity"] + securityContext: + capabilities: + add: ["NET_ADMIN"] diff --git a/readme-suse.md b/readme-suse.md new file mode 100644 index 0000000..2322d83 --- /dev/null +++ b/readme-suse.md @@ -0,0 +1,696 @@ +# 0. Ejemplo de configuración de red en SUSE con NetworkManager + +Aquí defines cómo se conectará tu servidor físicamente a la red en openSUSE/SLES: enlaces redundantes (bonding), VLANs para segmentar el tráfico, y bridges para conectar máquinas virtuales y pods a distintas redes. Esta configuración es la base para un clúster flexible y segmentado. + +> **Pre-requisitos:** +> +> * openSUSE/SLES con NetworkManager activo. +> * Interfaces físicas: `em1` y `em2` (ajusta según tu hardware). + +--- + +## 1. Crear el bond (LACP 802.3ad, rápido, hash layer3+4) + +```bash +nmcli con add type bond ifname bond0 mode 802.3ad +nmcli con mod bond0 bond.options "mode=802.3ad,miimon=100,updelay=200,downdelay=200,lacp_rate=fast,xmit_hash_policy=layer3+4" +``` + +## 2. Añadir interfaces físicas al bond + +```bash +nmcli con add type ethernet ifname em1 master bond0 +nmcli con add type ethernet ifname em2 master bond0 +``` + +## 3. Crear VLANs sobre el bond + +```bash +nmcli con add type vlan ifname vlan10 dev bond0 id 10 +nmcli con add type vlan ifname vlan20 dev bond0 id 20 +nmcli con add type vlan ifname vlan30 dev bond0 id 30 ip4 192.168.3.2/24 +nmcli con add type vlan ifname vlan40 dev bond0 id 40 ip4 192.168.4.2/24 +``` + +## 4. Crear bridges y unirlos a las VLANs + +```bash +# Bridge de administración (br-admin) sobre vlan10 +nmcli con add type bridge ifname br-admin +nmcli con add type bridge-slave ifname vlan10 master br-admin +nmcli con mod br-admin ipv4.addresses 192.168.0.42/24 +nmcli con mod br-admin ipv4.method manual +nmcli con mod br-admin ipv4.gateway 192.168.0.1 +nmcli con mod br-admin ipv4.dns "192.168.0.1 1.1.1.1 8.8.8.8" + +# Bridge de servicios (br-srv) sobre vlan20 +nmcli con add type bridge ifname br-srv +nmcli con add type bridge-slave ifname vlan20 master br-srv +nmcli con mod br-srv ipv4.addresses 192.168.200.2/22 +nmcli con mod br-srv ipv4.method manual +``` + +## 5. Sube todas las conexiones (en orden: bond, VLANs, bridges) + +```bash +nmcli con up bond0 +nmcli con up vlan10 +nmcli con up vlan20 +nmcli con up vlan30 +nmcli con up vlan40 +nmcli con up br-admin +nmcli con up br-srv +``` + +--- + +# Guía rápida: Instalar Kubernetes en openSUSE/SLES + +Esta guía cubre todos los pasos necesarios para instalar Kubernetes en openSUSE Leap, Tumbleweed o SLES, usando containerd como runtime y gestionando todo con zypper. Sigue el orden de los pasos para evitar problemas. + +# Guía definitiva de despliegue Kubernetes (openSUSE/SLES) + +> **Revisión y correcciones basadas en el history real de despliegue** + +## 1. Prerrequisitos del sistema (SUSE) + +Este paso parte de una instalación limpia de openSUSE/SLES actualizada y con permisos de administrador. Instala utilidades básicas, configura el repositorio oficial de Kubernetes y desactiva SWAP, igual que harías en Ubuntu, pero con comandos adaptados a zypper y la gestión de repositorios en SUSE. + +### a) Actualiza el sistema y paquetes básicos + +```bash +sudo zypper refresh +sudo zypper update +sudo zypper install -y curl ca-certificates keepalived chrony +``` + +### b) Añade el repositorio oficial de Kubernetes + +Crea el archivo de repositorio para Kubernetes (v1.33): + +```bash +cat < Cuando veas el aviso sobre la clave GPG, pulsa 'a' para aceptar siempre. + +### c) Configuración de Keepalived + +En SRVFKVM01 (MASTER): + +```bash +cat < Es **normal** que el servicio kubelet falle en bucle hasta que inicialices el clúster con `kubeadm init`. +> El error más frecuente es: +> +> * "failed to load Kubelet config file, path: /var/lib/kubelet/config.yaml" +> +> Tras ejecutar `kubeadm init`, kubelet arrancará correctamente. + +--- + +## 5b. (Opcional) Habilita cgroup v2 (solo SLES si necesario) + +Si necesitas cgroup v2 en SLES, añade esto al arranque del kernel (edita `/etc/default/grub`): + +``` +GRUB_CMDLINE_LINUX_DEFAULT="systemd.unified_cgroup_hierarchy=1 ..." +``` + +Y regenera el grub: + +```bash +sudo grub2-mkconfig -o /boot/grub2/grub.cfg +``` + +Reinicia para aplicar los cambios. + +--- + +# 6. Inicializa el clúster (openSUSE/SLES) + +Este paso crea el clúster de Kubernetes en el nodo principal (control-plane) sobre openSUSE/SLES. Aquí defines la red interna para los pods y la interfaz/VLAN física para el tráfico overlay del clúster, según tu diseño. + +--- + +## a) Inicializa el clúster especificando red de pods, la IP interna y la VIP + +> **Importante:** +> +> * Usa la opción `--apiserver-advertise-address` para forzar que el nodo control-plane escuche en la IP de la VLAN interna de clúster (ejemplo: `192.168.4.x` en tu VLAN 40). +> * Usa `--control-plane-endpoint` para indicar la IP virtual compartida (VIP) gestionada por Keepalived. Debe ser una IP accesible por todos los nodos control-plane (ejemplo: `192.168.0.20`). +> * Usa `--apiserver-cert-extra-sans` para añadir la VIP (y/o el FQDN) como SAN en el certificado TLS del API server, así todos los nodos confían en esa IP/nombre. +> * Usa `--pod-network-cidr=10.244.0.0/16` si vas a usar Flannel como CNI (ajusta si usas otro CNI). + +```bash +sudo kubeadm init \ + --apiserver-advertise-address=192.168.4.1 \ + --control-plane-endpoint="192.168.0.20:6443" \ + --apiserver-cert-extra-sans="192.168.0.20" \ + --pod-network-cidr=10.244.0.0/16 \ + --upload-certs +``` + +Cambia `192.168.4.1` por la IP interna del nodo donde ejecutas el comando (en la VLAN de clúster) y `192.168.0.20` por la IP VIP gestionada por Keepalived. + +--- + +## c) Configura kubectl para tu usuario + +Permite usar el comando `kubectl` como usuario normal copiando la configuración de administración del clúster a tu carpeta personal. + +En el nodo master (SRVFKVM01) + +```bash +mkdir -p $HOME/.kube +cd /etc/kubernetes +sudo cp -i admin.conf $HOME/.kube/config +sudo scp config admin.c3s@192.168.0.4X:/home/admin.c3s/admin.conf #a todos los nodos +sudo chown $(id -u):$(id -g) $HOME/.kube/config +``` + +## d) Instala la red de pods (Flannel) usando la VLAN interna del clúster + +Kubernetes solo define la infraestructura; necesitas un complemento de red (CNI) para que los pods puedan comunicarse entre sí. Flannel es la opción más sencilla y compatible, y puedes configurarla para usar una interfaz/VLAN específica para el tráfico overlay (muy recomendable si segmentas redes en tu clúster). + +### **¡ATENCIÓN! CNI Y PLUGINS:** + +Antes de aplicar Flannel, **asegúrate de tener los plugins CNI instalados en `/opt/cni/bin/`** (en SUSE esto NO siempre lo hace el paquete de Flannel): + +```bash +CNI_VERSION="v1.4.1" +ARCH="amd64" +curl -Lo cni-plugins.tgz https://github.com/containernetworking/plugins/releases/download/${CNI_VERSION}/cni-plugins-linux-${ARCH}-${CNI_VERSION}.tgz +sudo mkdir -p /opt/cni/bin +sudo tar -C /opt/cni/bin -xzf cni-plugins.tgz +``` + +Verifica que existen al menos: + +* `/opt/cni/bin/loopback` +* `/opt/cni/bin/flannel` +* `/opt/cni/bin/bridge` y otros + +Corrige permisos si hace falta: + +```bash +sudo chmod +x /opt/cni/bin/* +sudo chown root:root /opt/cni/bin/* +``` + +**Luego sí aplica Flannel:** + +```bash +kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml +``` + +--- + +## e) Comprueba que Flannel funciona + +```bash +kubectl -n kube-flannel get pods -o wide +``` + +> Todos los pods deben estar en estado `Running`. + +Si no levanta, **verifica logs y revisa `/opt/cni/bin/`**: + +* Los binarios deben ser para la arquitectura correcta (x86\_64/amd64). +* Deben tener permisos de ejecución y ser propiedad de root. + +--- + +## f) Une el resto de nodos control-plane + +En los demás nodos control-plane (tras configurar Keepalived y tener la VIP activa): + +```bash +sudo kubeadm join 192.168.0.20:6443 \ + --token \ + --discovery-token-ca-cert-hash \ + --control-plane \ + --certificate-key \ + --apiserver-advertise-address=192.168.4.2 +``` + +> **Importante:** Cambia la IP `192.168.4.2` por la correspondiente a cada servidor control-plane que estés uniendo. + +Recuerda usar los valores correctos de token, hash y certificate-key que te dará el comando `kubeadm init` o puedes volver a consultar desde el nodo principal: + +```bash +kubeadm token create --print-join-command --control-plane +``` + +Credenciales para todos (lo que le gusta al jefe): + +```bash +mkdir -p $HOME/.kube +cd +sudo cp -i admin.conf $HOME/.kube/config +sudo chown $(id -u):$(id -g) $HOME/.kube/config +``` + +--- + +## EXTRA: Si te ha caducado el TOKEN, o no lo guardaste + +Cuando el token de unión (`kubeadm join`) ha caducado, sigue estos pasos en el **nodo principal (control-plane)** para generar un nuevo token y el comando actualizado: + +```sh +# 1. Sube los certificados y obtén la nueva clave de certificado (certificate-key) +sudo kubeadm init phase upload-certs --upload-certs +``` + +> La salida mostrará la nueva `certificate key`, necesaria para añadir un nuevo nodo de control-plane. + +```sh +# 2. Genera un nuevo token y muestra el comando kubeadm join listo para usar +sudo kubeadm token create --print-join-command +``` + +> La salida mostrará el comando `kubeadm join` con el nuevo token y el hash actual del CA. + +### Ejemplo de salidas: + +``` +[upload-certs] Using certificate key: +588ee9d0441c0aea36b2a2a638beae4cfa81dd3498eb61205c8496f344f6c55d + +kubeadm join 192.168.0.20:6443 --token s9nlsp.gasv66tkc43zpiok --discovery-token-ca-cert-hash sha256:d41f0edb90c66c0555bdf4feca55f1e69019764be0fcd649a254e99ff124568f +``` + +--- + +## Comando completo para unir un nodo **como control-plane** + +Añade los parámetros `--control-plane --certificate-key --apiserver-advertise-address=192.168.4.2` al final del comando `kubeadm join` generado. Usando el ejemplo anterior, el comando final sería: + +```sh +sudo kubeadm join 192.168.0.20:6443 \ + --token s9nlsp.gasv66tkc43zpiok \ + --discovery-token-ca-cert-hash sha256:d41f0edb90c66c0555bdf4feca55f1e69019764be0fcd649a254e99ff124568f \ + --control-plane \ + --certificate-key 588ee9d0441c0aea36b2a2a638beae4cfa81dd3498eb61205c8496f344f6c55d \ + --apiserver-advertise-address=192.168.4.2 +``` + +> **Recuerda**: Cambia `192.168.4.2` por la IP real del nodo que se está uniendo. + +--- + +Con esto podrás unir cualquier nodo extra como nuevo control-plane, incluso cuando el token original haya caducado. + +--- + +## **Troubleshooting y buenas prácticas extra** + +* Si ves errores con el loopback CNI (`exec format error`, `permission denied`, etc.), **borra el contenido de `/opt/cni/bin/` y vuelve a instalar los plugins**. +* Siempre revisa que el módulo `br_netfilter` está cargado y los sysctl activos (`lsmod | grep br_netfilter`). +* Si el nodo aparece como NotReady, revisa `/etc/cni/net.d/`, los logs de kubelet, y repite la reinstalación del CNI. +* **Si limpias todo y reinicias, repite estos pasos:** + + * Reinstala CNI plugins + * Aplica Flannel + * Reinicia kubelet + + +# 8. Instala Multus (opcional, para múltiples redes) + +Multus permite que un pod tenga más de una interfaz de red (multi-homed), útil para appliances, firewalls, balanceadores, gateways, etc. Instálalo si necesitas conectar pods a varias redes físicas o VLANs (por ejemplo, mediante bridges y NADs). + +**Instalación:** + +```bash +kubectl apply -f https://raw.githubusercontent.com/k8snetworkplumbingwg/multus-cni/master/deployments/multus-daemonset.yml +``` + +**Verifica:** + +```bash +kubectl get pods -n kube-system | grep multus +``` + +--- + +# 9. (Opcional) Quita el taint del nodo master para poder programar pods en él + +Por defecto, Kubernetes no programa pods de usuario en el nodo principal (control-plane). Elimina este bloqueo para poder desplegar aplicaciones ahí. + +```bash +kubectl taint nodes --all node-role.kubernetes.io/control-plane- +kubectl taint nodes --all node-role.kubernetes.io/master- +``` +## Nota: Uso de taints en nodos control-plane (alta disponibilidad y ejecución de cargas) + +### ¿Qué es un taint? + +* Un **taint** en Kubernetes es una marca especial que se pone a un nodo para **evitar que los pods se programen ahí**, salvo que declaren una “toleration” explícita. +* Se usa para reservar nodos solo para tareas especiales (por ejemplo, el control-plane). +* Por defecto, los nodos control-plane llevan un taint: + + * `node-role.kubernetes.io/control-plane:NoSchedule` + +### ¿Por qué quitar el taint? + +* Si quieres que **los nodos control-plane puedan ejecutar pods de usuario** (además del plano de control), necesitas **quitar el taint**. +* Esto es común en clústeres pequeños o medianos, donde **todos los nodos cumplen doble función** (alta disponibilidad y ejecución de cargas). + +--- + +### **Comandos para quitar el taint de todos los nodos control-plane:** + +```bash +kubectl taint nodes --all node-role.kubernetes.io/control-plane- +kubectl taint nodes --all node-role.kubernetes.io/master- +``` + +* El `-` final indica “quitar”. +* Ejecuta ambos para máxima compatibilidad entre versiones. + +### **Comando para añadir el taint (dejar el nodo solo como control-plane):** + +```bash +kubectl taint nodes NOMBRE_DEL_NODO node-role.kubernetes.io/control-plane=:NoSchedule +``` + +* Así, ese nodo **solo ejecuta el plano de control** (salvo pods con toleration específica). + +--- + +# 10. Test rápido de Multus (NAD + pod con 2 interfaces) + +Puedes comprobar que Multus funciona creando una red secundaria y un pod de prueba con dos interfaces (una por defecto, una secundaria). + +En la carpeta `multus/` de tu repositorio, debes tener: + +* `multus/nad-br-servicios.yaml` (NetworkAttachmentDefinition) +* `multus/test-multus-pod.yaml` (pod Alpine multi-homed) + +**Despliega la NAD:** + +```bash +kubectl apply -f multus/nad-br-servicios.yaml +``` + +**Despliega el pod de test:** + +```bash +kubectl apply -f multus/test-multus-pod.yaml +``` + +**Comprueba las interfaces:** + +```bash +kubectl exec -it multus-test -- sh +ip a +``` + +* El pod debe mostrar una interfaz extra (además de la de Flannel), conectada a tu red secundaria (`br-servicios`, etc.). + +**Para limpiar:** + +```bash +kubectl delete pod multus-test +``` + +--- + +> **Nota:** Puedes crear tantas NADs (NetworkAttachmentDefinition) como bridges/VLANs quieras conectar a pods específicos (con Multus), ideal para appliances de red, gateways, SDN, pruebas de seguridad, etc. + +--- + +# 11. Instalación y configuración de MetalLB (LoadBalancer local) + +MetalLB permite asignar IPs flotantes de tu red LAN a servicios `LoadBalancer`, igual que hacen los clústeres en la nube. Es fundamental si quieres exponer servicios como ingress, dashboards, etc., accesibles desde tu red local. + +--- + +## a) Instala MetalLB + +```bash +kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.5/config/manifests/metallb-native.yaml +``` + +Esto crea el namespace `metallb-system` y los pods necesarios. + +--- + +## b) Declara múltiples pools de IP + +Puedes crear varios pools (por ejemplo, uno para producción y otro para test, o para diferentes VLANs/segmentos). Los pools se definen en el objeto `IPAddressPool`. + +**Ejemplo: `metallb/ipaddresspool.yaml`** + +```yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: pool-produccion + namespace: metallb-system +spec: + addresses: + - 192.168.1.100-192.168.1.110 +--- +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: pool-lab + namespace: metallb-system +spec: + addresses: + - 192.168.2.100-192.168.2.110 +``` + +**Ejemplo: `metallb/l2advertisement.yaml`** + +```yaml +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: advert-all + namespace: metallb-system +spec: {} +``` + +**Kustomization:** + +```yaml +resources: + - ipaddresspool.yaml + - l2advertisement.yaml +``` + +Para aplicar: + +```bash +kubectl apply -k metallb/ +``` + +--- + +## c) Asigna un pool concreto a un Service (anotaciones) + +Por defecto, los Services `LoadBalancer` usan cualquier pool disponible. Para forzar el uso de un pool específico, **añade esta anotación al Service**: + +```yaml +apiVersion: v1 +kind: Service +metadata: + name: ejemplo-prod + annotations: + metallb.universe.tf/address-pool: pool-produccion +spec: + selector: + app: ejemplo + ports: + - port: 80 + targetPort: 80 + type: LoadBalancer +``` + +* Cambia `pool-produccion` por el nombre de pool que quieras usar. + +Al crear el Service, MetalLB le asignará una IP **solo de ese pool**. + +--- + +## d) Comprobar el resultado + +```bash +kubectl get svc +``` + +Verás la IP asignada en la columna `EXTERNAL-IP`. + +--- + +> **Notas:** +> +> * Puedes definir tantos pools como necesites, uno por segmento/VLAN/uso. +> * Puedes versionar los manifiestos de MetalLB en una carpeta específica del repositorio (`metallb/`). + +--- + diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..036952f --- /dev/null +++ b/readme.md @@ -0,0 +1,43 @@ +# Guía Oficial de Instalación de Kubernetes en SUSE + +Este repositorio contiene los **manifiestos, scripts y documentación oficial** para desplegar y gestionar un clúster Kubernetes basado en SUSE Linux. + +> **NOTA:** Todo el proceso está documentado paso a paso, con comprobaciones, consideraciones y mejores prácticas. + +--- + +## Índice de documentos y referencias cruzadas + +| Documento | Descripción | Referencia | +| ------------------- | ------------------------------------------ | ------------------------ | +| `readme.md` | Índice y presentación general | (Este documento) | +| `comprobaciones.md` | Checklist y pruebas tras cada paso crítico | [Ver](comprobaciones.md) | +| `cephrook.md` | Instalación e integración de Ceph/Rook | [Ver](cephrook.md) | +| `Clusterkey.txt` | Clave actual del clúster y certificate-key | [Ver](Clusterkey.txt) | +| `kubevirt.md` | Despliegue de KubeVirt y gestión de VMs | [Ver](kubevirt.md) | +| `readme-suse.md` | Proceso de instalación detallado en SUSE | [Ver](readme-suse.md) | + +--- + +## Estado actual de los documentos + +| Documento | Estado | Comentario | +| ------------------- | -------------- | ------------------------------------- | +| `readme.md` | ✅ Completado | Actualizado | +| `comprobaciones.md` | ⚠️ En revisión | Añadir más pruebas específicas | +| `cephrook.md` | ⚠️ En revisión | Integración Ceph pendiente de validar | +| `Clusterkey.txt` | ✅ Completado | Clave generada y aplicada | +| `kubevirt.md` | ⚠️ En revisión | Revisar últimas pruebas de VMs | +| `readme-suse.md` | ✅ Completado | Instalación básica validada | + +--- + +## ¿Cómo usar este repositorio? + +1. Sigue el orden de los documentos desde `readme-suse.md`. +2. Comprueba cada paso con `comprobaciones.md`. +3. Consulta el resto de documentos según el despliegue requerido (Ceph, KubeVirt, etc). + +--- + +¿Dudas, mejoras o sugerencias? Haz un pull request o abre un issue. diff --git a/storage/deployments/nfs-client-provisioner.yaml b/storage/deployments/nfs-client-provisioner.yaml new file mode 100644 index 0000000..d238034 --- /dev/null +++ b/storage/deployments/nfs-client-provisioner.yaml @@ -0,0 +1,41 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nfs-client-provisioner + namespace: nfs-provisioner +spec: + replicas: 1 + selector: + matchLabels: + app: nfs-client-provisioner + template: + metadata: + labels: + app: nfs-client-provisioner + spec: + serviceAccountName: nfs-client-provisioner + containers: + - name: nfs-client-provisioner + image: k8s.gcr.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2 + volumeMounts: + - name: nfs-client-root + mountPath: /persistentvolumes + env: + - name: PROVISIONER_NAME + value: k8s-sigs.io/nfs-subdir-external-provisioner + - name: NFS_SERVER + value: 192.168.3.3 # VLAN 30 IP de niflheim + - name: NFS_PATH + value: / + - name: LABELS + value: "namespace,pvcName" + volumes: + - name: nfs-client-root + nfs: + server: 192.168.3.3 + path: / + tolerations: + - key: "storage" + operator: "Equal" + value: "only" + effect: "NoSchedule" \ No newline at end of file diff --git a/storage/deployments/nfs-server.yaml b/storage/deployments/nfs-server.yaml new file mode 100644 index 0000000..a747160 --- /dev/null +++ b/storage/deployments/nfs-server.yaml @@ -0,0 +1,43 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nfs-server + namespace: nfs-provisioner +spec: + replicas: 1 + selector: + matchLabels: + app: nfs-server + template: + metadata: + labels: + app: nfs-server + spec: + hostNetwork: true + containers: + - name: nfs-server + image: itsthenetwork/nfs-server-alpine:latest + ports: + - name: nfs + containerPort: 2049 + protocol: TCP + securityContext: + privileged: true + env: + - name: SHARED_DIRECTORY + value: /nfsshare + volumeMounts: + - name: nfs-data + mountPath: /nfsshare + volumes: + - name: nfs-data + hostPath: + path: /mnt/storage/k8s/nfsshare + type: Directory + tolerations: + - key: "storage" + operator: "Equal" + value: "only" + effect: "NoSchedule" + nodeSelector: + kubernetes.io/hostname: niflheim \ No newline at end of file diff --git a/storage/kustomization.yaml b/storage/kustomization.yaml new file mode 100644 index 0000000..b8907b0 --- /dev/null +++ b/storage/kustomization.yaml @@ -0,0 +1,8 @@ +resources: + - namespace.yaml + - rbac/clusterrolebinding.yaml + - rbac/clusterrole.yaml + - rbac/serviceaccount.yaml +# - deployments/nfs-server.yaml + - deployments/nfs-client-provisioner.yaml + - storageclass/storageclass.yaml diff --git a/storage/namespace.yaml b/storage/namespace.yaml new file mode 100644 index 0000000..52d071e --- /dev/null +++ b/storage/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: nfs-provisioner \ No newline at end of file diff --git a/storage/rbac/clusterrole.yaml b/storage/rbac/clusterrole.yaml new file mode 100644 index 0000000..4e15b02 --- /dev/null +++ b/storage/rbac/clusterrole.yaml @@ -0,0 +1,20 @@ +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: nfs-client-provisioner-runner +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: ["create", "update", "patch"] + - apiGroups: [""] + resources: ["endpoints"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] diff --git a/storage/rbac/clusterrolebinding.yaml b/storage/rbac/clusterrolebinding.yaml new file mode 100644 index 0000000..91775d0 --- /dev/null +++ b/storage/rbac/clusterrolebinding.yaml @@ -0,0 +1,12 @@ +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: run-nfs-client-provisioner +subjects: + - kind: ServiceAccount + name: nfs-client-provisioner + namespace: nfs-provisioner +roleRef: + kind: ClusterRole + name: nfs-client-provisioner-runner + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/storage/rbac/serviceaccount.yaml b/storage/rbac/serviceaccount.yaml new file mode 100644 index 0000000..147f8b3 --- /dev/null +++ b/storage/rbac/serviceaccount.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: nfs-client-provisioner + namespace: nfs-provisioner \ No newline at end of file diff --git a/storage/readme.md b/storage/readme.md new file mode 100644 index 0000000..92f9086 --- /dev/null +++ b/storage/readme.md @@ -0,0 +1,17 @@ +# k8s-storage + +Este mdulo despliega un driver de almacenamiento dinmico basado en NFS, apuntando a un servidor ZFS (`niflheim`, 192.168.1.10) con la ruta `/mnt/storage/k8s`. + +## Componentes incluidos + +- Namespace `nfs-provisioner` +- RBAC necesario +- Deployment del provisioner dinmico +- StorageClass predeterminado `nfs-manabo` + +## Cmo aplicar + + kubectl apply -f namespace.yaml + kubectl apply -f rbac/ + kubectl apply -f deployment/ + kubectl apply -f storageclass/ \ No newline at end of file diff --git a/storage/storageclass/storageclass.yaml b/storage/storageclass/storageclass.yaml new file mode 100644 index 0000000..5b9be18 --- /dev/null +++ b/storage/storageclass/storageclass.yaml @@ -0,0 +1,9 @@ +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: nfs-manabo + annotations: + storageclass.kubernetes.io/is-default-class: "true" +provisioner: k8s-sigs.io/nfs-subdir-external-provisioner +reclaimPolicy: Retain +volumeBindingMode: Immediate diff --git a/traefik/configmaps/configmap.yaml b/traefik/configmaps/configmap.yaml new file mode 100644 index 0000000..ef6a56f --- /dev/null +++ b/traefik/configmaps/configmap.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: traefik-config + namespace: traefik +data: + traefik.yml: | + api: + dashboard: true + log: + level: DEBUG + entryPoints: + web: + address: ":80" + websecure: + address: ":443" diff --git a/traefik/deployments/deployment.yaml b/traefik/deployments/deployment.yaml new file mode 100644 index 0000000..ff42d0a --- /dev/null +++ b/traefik/deployments/deployment.yaml @@ -0,0 +1,28 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: traefik + namespace: traefik +spec: + replicas: 1 + selector: + matchLabels: + app: traefik + template: + metadata: + labels: + app: traefik + spec: + serviceAccountName: traefik + containers: + - name: traefik + image: traefik:v3.0 + args: + - --configFile=/config/traefik.yml + volumeMounts: + - name: config + mountPath: /config + volumes: + - name: config + configMap: + name: traefik-config diff --git a/traefik/ingress/ingress.yaml b/traefik/ingress/ingress.yaml new file mode 100644 index 0000000..65579df --- /dev/null +++ b/traefik/ingress/ingress.yaml @@ -0,0 +1,32 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: traefik-dashboard + namespace: traefik + annotations: + cert-manager.io/cluster-issuer: letsencrypt-prod + kubernetes.io/ingress.class: traefik +spec: + ingressClassName: traefik + tls: + - hosts: + - traefik.manabo.org + secretName: traefik-dashboard-tls + rules: + - host: traefik.manabo.org + http: + paths: + - path: /dashboard + pathType: Prefix + backend: + service: + name: traefik + port: + number: 80 + - path: /api + pathType: Prefix + backend: + service: + name: traefik + port: + number: 80 diff --git a/traefik/ingressclass.yaml b/traefik/ingressclass.yaml new file mode 100644 index 0000000..5345ee2 --- /dev/null +++ b/traefik/ingressclass.yaml @@ -0,0 +1,6 @@ +apiVersion: networking.k8s.io/v1 +kind: IngressClass +metadata: + name: traefik +spec: + controller: traefik.io/ingress-controller diff --git a/traefik/kustomization.yaml b/traefik/kustomization.yaml new file mode 100644 index 0000000..83f43e9 --- /dev/null +++ b/traefik/kustomization.yaml @@ -0,0 +1,11 @@ +namespace: traefik +resources: + - namespace.yaml + - rbac/serviceaccount.yaml + - rbac/clusterrole.yaml + - rbac/clusterrolebinding.yaml + - configmaps/configmap.yaml + - deployments/deployment.yaml + - services/service.yaml + - ingressclass.yaml + - ingress/ingress.yaml diff --git a/traefik/namespace.yaml b/traefik/namespace.yaml new file mode 100644 index 0000000..c088a91 --- /dev/null +++ b/traefik/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: traefik diff --git a/traefik/rbac/clusterrole.yaml b/traefik/rbac/clusterrole.yaml new file mode 100644 index 0000000..1158f06 --- /dev/null +++ b/traefik/rbac/clusterrole.yaml @@ -0,0 +1,62 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: traefik +rules: + - apiGroups: + - "" + resources: + - configmaps + - endpoints + - nodes + - pods + - secrets + verbs: + - list + - watch + - apiGroups: + - "" + resources: + - nodes + verbs: + - get + - apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch + - apiGroups: + - networking.k8s.io + resources: + - ingresses + - ingressclasses + - ingresses/status + verbs: + - get + - list + - watch + - update + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - create + - update + - apiGroups: + - "" + resources: + - pods + verbs: + - get + - apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - list + - watch diff --git a/traefik/rbac/clusterrolebinding.yaml b/traefik/rbac/clusterrolebinding.yaml new file mode 100644 index 0000000..b953c71 --- /dev/null +++ b/traefik/rbac/clusterrolebinding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: traefik +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: traefik +subjects: + - kind: ServiceAccount + name: traefik + namespace: traefik diff --git a/traefik/rbac/serviceaccount.yaml b/traefik/rbac/serviceaccount.yaml new file mode 100644 index 0000000..4560cb3 --- /dev/null +++ b/traefik/rbac/serviceaccount.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: traefik + namespace: traefik diff --git a/traefik/services/service.yaml b/traefik/services/service.yaml new file mode 100644 index 0000000..6443a4f --- /dev/null +++ b/traefik/services/service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: traefik + namespace: traefik +spec: + type: LoadBalancer # <-- ¡Esto es lo importante con MetalLB! + ports: + - port: 80 + name: web + targetPort: 80 + - port: 443 + name: websecure + targetPort: 443 + selector: + app: traefik