Kubernetes

Arquitectura

Notas

  1. Los 'Service' que van anidados a un deployment usan el valor de 'spec' -> 'selector' -> 'app', que está especificado en el deployment en 'metadata' -> 'lebels' -> 'app'

Distros

  • Bottlerocket

    Distro imutable para funcionar como worker que se actualiza automáticamente.

  • K3S

    Versión más minimalista de K8S en un solo binario.

    Tiene el socket en /run/k3s/containerd/containerd.sock

    Tiene todo en el namespace de containerd; k8s.io

sudo ctr -n=k8s.io [comandos] -a /run/k3s/containerd/containerd.sock

sudo crictl --runtime-endpoint unix:///run/k3s/containerd/containerd.sock

  • RKEv2 (Goberment)

    Versión de K3S para seguridad.

    No trae containerd instalado, si no que lo tiene embebido. Se recomienda instalar containerd para poder administrarlo fuera del propio rkev2.

Tools

  • Creador de Deployment / StatefulSet / DaemonSet

  • Creador de Deployment / Service / Ingress

  • CI/CD

    • Jenkins (CI/CD, opensource)
    • Terraform (CD, opensource)
    • Spinnaker (CD, opensource)
    • IO (CD, opensource)
  • Métricas;

    • Prometheus
  • Monitoreo general;

    • DataDog (pago)
    • Sematext Monitoring (pago)
    • Cast.ai (pago)
    • Jaeger (open source)
  • Monitoreo desde métricas;

    • Grafana
  • Monitoreo desde Service mesh (específico de la red en los PODS);

    • istio (open source)
  • Análisis de seguridad;

    • kube-lint (YAML, opensource)
    • kube-bench (deployment, opensource)
    • Trivy (runner, opensource)
    • Tenable/Terrascan (IAC, opensource)

Temaplates

Deployment template

El modo por defecto para desplegar una aplicación/es.

apiVersion: apps/v1  # Define la versión de la API que se usa para manejar este recurso.
kind: Deployment  # Especifica que este manifiesto es un Deployment.
metadata:
  name: my-deployment  # Nombre del Deployment.
  namespace: default  # Namespace en el cual se desplegará este Deployment (por defecto es 'default').
  labels:
    app: my-app  # Etiquetas que permiten identificar y organizar recursos.
  annotations:
    description: "Este Deployment despliega una aplicación con múltiples configuraciones."  # Anotaciones adicionales para describir el recurso.

spec:
  replicas: 3  # Número de réplicas del pod a desplegar.
  selector:  # Define cómo se seleccionarán los Pods creados por este Deployment.
    matchLabels:
      app: my-app  # Etiquetas que deben coincidir para que un pod sea considerado parte de este Deployment.
  strategy:  # Estrategia de actualización de los Pods.
    type: RollingUpdate  # Define cómo se actualizarán los pods, opciones: RollingUpdate o Recreate.
    rollingUpdate:  # Parámetros específicos para una actualización progresiva.
      maxUnavailable: 1  # Número o porcentaje máximo de pods no disponibles durante la actualización.
      maxSurge: 1  # Número o porcentaje máximo de pods adicionales que pueden crearse temporalmente durante la actualización.

  template:  # Define la plantilla para los pods que serán gestionados por este Deployment.
    metadata:
      labels:
        app: my-app  # Las etiquetas que los pods llevarán. Deben coincidir con el selector.
    spec:
      containers:
        - name: my-container  # Nombre del contenedor.
          image: nginx:1.19  # Imagen del contenedor.
          ports:
            - containerPort: 80  # Puerto expuesto dentro del contenedor.
          resources:  # Define los recursos solicitados y límites para este contenedor.
            requests:
              memory: "64Mi"  # Memoria mínima solicitada.
              cpu: "250m"  # CPU mínima solicitada.
            limits:
              memory: "128Mi"  # Memoria máxima permitida.
              cpu: "500m"  # CPU máxima permitida.
          env:  # Variables de entorno para configurar el contenedor.
            - name: ENVIRONMENT
              value: production
            - name: LOG_LEVEL
              valueFrom:
                configMapKeyRef:
                  name: app-config  # Toma el valor desde un ConfigMap.
                  key: log-level
          envFrom:  # Cargar variables de entorno desde ConfigMap o Secret.
            - configMapRef:
                name: app-config  # Nombre del ConfigMap.
            - secretRef:
                name: app-secrets  # Nombre del Secret.
          volumeMounts:  # Define los volúmenes que se montarán dentro del contenedor.
            - name: config-volume
              mountPath: /etc/config
            - name: logs
              mountPath: /var/log/nginx
          livenessProbe:  # Configuración de liveness para comprobar si el contenedor sigue funcionando.
            httpGet:
              path: /healthz
              port: 80
            initialDelaySeconds: 10  # Espera antes de la primera comprobación.
            periodSeconds: 10  # Intervalo de tiempo entre las comprobaciones.
            timeoutSeconds: 1  # Tiempo límite para cada comprobación.
            failureThreshold: 3  # Número de fallos consecutivos antes de considerarse fallido.
          readinessProbe:  # Configuración para verificar si el contenedor está listo para recibir tráfico.
            httpGet:
              path: /ready
              port: 80
            initialDelaySeconds: 5
            periodSeconds: 5
          startupProbe:  # Verificación de que el contenedor ha arrancado correctamente.
            httpGet:
              path: /startup
              port: 80
            initialDelaySeconds: 20
            periodSeconds: 10
          imagePullPolicy: Always  # Política de pull de la imagen: Always, IfNotPresent, Never.

      initContainers:  # Contenedores que se ejecutarán antes que los contenedores principales.
        - name: init-my-service
          image: busybox:1.28
          command: ['sh', '-c', 'echo Initializing... && sleep 5']
          resources:
            requests:
              memory: "32Mi"
              cpu: "100m"

      volumes:  # Define los volúmenes que se montarán en los contenedores.
        - name: config-volume
          configMap:
            name: app-config  # Nombre del ConfigMap del que se cargará la configuración.
        - name: logs
          emptyDir: {}  # Volumen temporal que desaparece cuando el pod se reinicia o se borra.

      nodeSelector:  # Define en qué nodos pueden desplegarse los pods.
        disktype: ssd  # Ejemplo de nodo con un determinado tipo de disco.

      affinity:  # Afinidad de los pods con respecto a nodos.
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: kubernetes.io/e2e-az-name
                    operator: In
                    values:
                      - e2e-az1
                      - e2e-az2
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            labelSelector:
              matchExpressions:
                - key: security
                  operator: In
                  values:
                    - S1
            topologyKey: "kubernetes.io/hostname"

      tolerations:  # Define tolerancias para nodos con taints específicos.
        - key: "key1"
          operator: "Equal"
          value: "value1"
          effect: "NoSchedule"

      restartPolicy: Always  # Política de reinicio del contenedor: Always, OnFailure, Never.
      dnsPolicy: ClusterFirst  # Política DNS para los pods.
      serviceAccountName: my-service-account  # Cuenta de servicio que se utilizará.
      securityContext:  # Configuración de seguridad para todo el pod.
        runAsUser: 1000
        fsGroup: 2000
      schedulerName: default-scheduler  # Define el scheduler que gestionará este pod.
      hostNetwork: false  # Si se debe usar el networking del host.
      priorityClassName: high-priority  # Define la prioridad de los pods.

  minReadySeconds: 5  # Tiempo que un pod debe estar listo antes de ser considerado disponible.
  revisionHistoryLimit: 10  # Número máximo de réplicas anteriores mantenidas.
  progressDeadlineSeconds: 600  # Tiempo máximo para considerar que una actualización es exitosa.
  paused: false  # Si el deployment está pausado o no.

Daemon Set

Un DaemonSet asegura que un Pod específico esté corriendo en cada nodo (o en nodos seleccionados) del clúster.

No maneja el estado de las aplicaciones.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: my-daemonset  # Nombre del DaemonSet.
  namespace: default  # Namespace donde se desplegará el DaemonSet.
  labels:
    app: my-daemon-app  # Etiquetas para identificar el DaemonSet.
  annotations:
    description: "DaemonSet para ejecutar un pod en cada nodo del clúster."

spec:
  selector:
    matchLabels:
      app: my-daemon-app  # Etiquetas que deben coincidir con los pods gestionados por el DaemonSet.
  
  template:  # Define la plantilla para los Pods gestionados por este DaemonSet.
    metadata:
      labels:
        app: my-daemon-app  # Etiquetas que deben coincidir con el selector.
    spec:
      containers:
        - name: my-daemon-container  # Nombre del contenedor.
          image: busybox:1.28  # Imagen del contenedor.
          args:  # Argumentos pasados al contenedor.
            - "/bin/sh"
            - "-c"
            - "while true; do echo Hello DaemonSet; sleep 3600; done"
          resources:  # Configura los recursos solicitados y límites para este contenedor.
            requests:
              memory: "64Mi"
              cpu: "250m"
            limits:
              memory: "128Mi"
              cpu: "500m"
          volumeMounts:
            - name: logs
              mountPath: /var/log/daemonset
          ports:
            - containerPort: 80
              name: http
          livenessProbe:  # Verificación de si el contenedor está vivo.
            httpGet:
              path: /healthz
              port: 80
            initialDelaySeconds: 10
            periodSeconds: 10
          readinessProbe:  # Verificación de si el contenedor está listo para recibir tráfico.
            httpGet:
              path: /ready
              port: 80
            initialDelaySeconds: 5
            periodSeconds: 5

      initContainers:  # Contenedores que se ejecutarán antes del contenedor principal.
        - name: init-container
          image: busybox:1.28
          command: ['sh', '-c', 'echo Initializing DaemonSet... && sleep 5']

      volumes:  # Define los volúmenes que se utilizarán.
        - name: logs
          emptyDir: {}

      nodeSelector:  # Reglas para limitar los nodos donde se ejecutará el DaemonSet.
        disktype: ssd

      affinity:  # Define la afinidad de los Pods con respecto a nodos.
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: kubernetes.io/e2e-az-name
                    operator: In
                    values:
                      - e2e-az1
                      - e2e-az2

      tolerations:  # Define tolerancias a ciertos taints de los nodos.
        - key: "key1"
          operator: "Equal"
          value: "value1"
          effect: "NoSchedule"

  updateStrategy:  # Estrategia de actualización de los DaemonSets.
    type: RollingUpdate  # Opciones: RollingUpdate o OnDelete.
    rollingUpdate:
      maxUnavailable: 1  # Número o porcentaje máximo de pods no disponibles durante la actualización.
      
  revisionHistoryLimit: 10  # Número máximo de revisiones guardadas para el DaemonSet.

Stateful Set

El StatefulSet gestiona el despliegue y el escalado de un conjunto de Pods, garantizando un orden de despliegue, actualización y eliminación, manteniendo una identidad única para cada Pod.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: my-statefulset  # Nombre del StatefulSet.
  namespace: default  # Namespace donde se desplegará.
  labels:
    app: my-stateful-app
  annotations:
    description: "StatefulSet para manejar aplicaciones con estado que requieren una identidad única en cada pod."

spec:
  replicas: 3  # Número de réplicas gestionadas por el StatefulSet.
  serviceName: "my-service"  # Nombre del Headless Service asociado al StatefulSet.
  selector:
    matchLabels:
      app: my-stateful-app

  template:  # Plantilla para los pods gestionados por el StatefulSet.
    metadata:
      labels:
        app: my-stateful-app
    spec:
      containers:
        - name: my-stateful-container
          image: postgres:13  # Ejemplo con una base de datos Postgres.
          ports:
            - containerPort: 5432
              name: postgres
          env:
            - name: POSTGRES_USER
              value: "admin"
            - name: POSTGRES_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: postgres-secret
                  key: password
          volumeMounts:
            - name: postgres-data
              mountPath: /var/lib/postgresql/data  # Donde se almacenan los datos persistentes.

      initContainers:
        - name: init-container
          image: busybox:1.28
          command: ['sh', '-c', 'echo Initializing StatefulSet... && sleep 5']

  volumeClaimTemplates:  # Define volúmenes persistentes para cada pod.
    - metadata:
        name: postgres-data  # Nombre del volumen.
      spec:
        accessModes: ["ReadWriteOnce"]  # Modo de acceso del volumen.
        resources:
          requests:
            storage: 1Gi  # Espacio de almacenamiento solicitado.
        storageClassName: standard  # Define la StorageClass que gestionará este PVC.

  podManagementPolicy: Parallel  # Controla cómo se crean o eliminan los pods. Opciones: OrderedReady, Parallel.
  updateStrategy:
    type: RollingUpdate  # Estrategia de actualización.
    rollingUpdate:
      partition: 1  # Permite actualizar solo una parte de los pods a la vez.
  revisionHistoryLimit: 10  # Número de revisiones mantenidas.
  persistentVolumeClaimRetentionPolicy:  # Define la política de retención de los volúmenes persistentes.
    whenDeleted: Retain  # Mantener el PVC cuando se elimine el StatefulSet.
    whenScaled: Retain  # Mantener el PVC cuando se escale el StatefulSet hacia abajo.

Service template

  • Cluster IP

Descripción:

Este es el tipo de Service por defecto. Expone el servicio dentro del clúster a través de una IP interna, llamada ClusterIP. Solo los recursos dentro del clúster (como otros Pods) pueden acceder a este servicio.

Uso:

Se utiliza cuando solo necesitas exponer tu aplicación dentro del clúster, sin necesidad de que sea accesible desde fuera. Ideal para microservicios que necesitan comunicarse entre sí dentro del clúster. No es accesible desde fuera del clúster.

Ejemplo de uso: Imagina que tienes un conjunto de microservicios que se comunican entre ellos, pero no necesitas exponerlos al mundo exterior.

apiVersion: v1
kind: Service
metadata:
  name: my-clusterip-service  # Nombre del Service
  namespace: default  # Namespace donde se despliega el Service
  labels:
    app: my-app  # Etiquetas para identificar el Service
  annotations:
    description: "ClusterIP Service que expone la aplicación solo dentro del cluster."

spec:
  type: ClusterIP  # Tipo de Service: expone el servicio solo dentro del cluster.
  selector:
    app: my-app  # Selecciona los Pods que coinciden con esta etiqueta.
  ports:
    - protocol: TCP  # Protocolo, puede ser TCP o UDP
      port: 80  # Puerto que expone el Service dentro del cluster.
      targetPort: 8080  # Puerto donde está escuchando la aplicación en los Pods.
      name: http  # Nombre del puerto, útil para algunas herramientas.
  clusterIP: None  # Si se desea crear un Headless Service, se debe establecer `None`.
  sessionAffinity: None  # Controla la afinidad de sesiones, opciones: None o ClientIP.
  externalTrafficPolicy: Cluster  # Define cómo manejar el tráfico externo. Opciones: Cluster, Local.
  ipFamilies:
    - IPv4  # Define la familia de IPs para el servicio: IPv4, IPv6, o ambas.
  ipFamilyPolicy: SingleStack  # Define la política de familia de IP: SingleStack, PreferDualStack o RequireDualStack.
  • NodePort

Descripción:

Un NodePort expone el servicio a través de un puerto específico en cada nodo del clúster. Además de ser accesible dentro del clúster como un ClusterIP, este tipo de servicio permite que los usuarios accedan al servicio desde fuera del clúster a través del IP del nodo y un puerto específico en el rango 30000-32767.

Uso:

Se usa cuando necesitas exponer tu aplicación externamente y no tienes un balanceador de carga (por ejemplo, en entornos on-premise o de desarrollo). El servicio es accesible desde el exterior usando la IP de cualquier nodo del clúster y el puerto especificado. Es más simple que usar un LoadBalancer, pero tiene la desventaja de que debes lidiar manualmente con la exposición a través de los nodos.

Ejemplo de uso: Ideal para entornos de desarrollo o pruebas donde quieres acceder a tu servicio desde fuera del clúster sin la complejidad de configurar un balanceador de carga.

apiVersion: v1
kind: Service
metadata:
  name: my-nodeport-service
  namespace: default
  labels:
    app: my-app
  annotations:
    description: "NodePort Service que expone el servicio en todos los nodos del cluster."

spec:
  type: NodePort  # Tipo de Service: expone el servicio en un puerto específico de todos los nodos.
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80  # Puerto que expone el Service dentro del cluster.
      targetPort: 8080  # Puerto donde está escuchando la aplicación en los Pods.
      nodePort: 30036  # Puerto en los nodos donde estará disponible (rango: 30000-32767).
      name: http
  sessionAffinity: ClientIP  # Mantiene la afinidad de sesión basada en la IP del cliente.
  externalTrafficPolicy: Local  # Tráfico externo se envía solo a nodos con pods activos.
  healthCheckNodePort: 32000  # Puerto adicional para verificaciones de salud de los nodos (opcional).

  • LoadBalancer

Descripción: Un LoadBalancer crea un balanceador de carga externo que distribuye el tráfico entre los pods de tu servicio. Este tipo de servicio asigna automáticamente una IP externa y maneja la creación del balanceador de carga en la nube (si estás en un proveedor de nube como AWS, GCP o Azure).

Uso:

Es ideal para exponer aplicaciones al exterior en producción en la nube. El proveedor de la nube gestionará el balanceador de carga. Permite distribuir el tráfico entre los diferentes pods que respaldan el servicio. Soporta la especificación de rangos IP para restringir el acceso externo.

Ejemplo de uso: Perfecto para exponer aplicaciones web o APIs que necesitan estar accesibles desde internet. Un proveedor de nube creará automáticamente un balanceador de carga y manejará la distribución del tráfico.

apiVersion: v1
kind: Service
metadata:
  name: my-loadbalancer-service
  namespace: default
  labels:
    app: my-app
  annotations:
    description: "LoadBalancer Service que expone el servicio a través de un balanceador de carga externo."
    service.beta.kubernetes.io/aws-load-balancer-type: nlb  # Ejemplo de anotación específica de AWS para usar un Network Load Balancer.
  
spec:
  type: LoadBalancer  # Tipo de Service: expone el servicio a través de un Load Balancer externo.
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80  # Puerto que el balanceador expone públicamente.
      targetPort: 8080  # Puerto donde está escuchando la aplicación en los Pods.
      name: http
    - protocol: TCP
      port: 443  # Puerto adicional para HTTPS, por ejemplo.
      targetPort: 8443
      name: https
  loadBalancerIP: 192.168.0.100  # IP externa preasignada para el balanceador de carga (opcional, depende del proveedor).
  externalTrafficPolicy: Cluster  # Cómo manejar el tráfico externo.
  sessionAffinity: None  # Controla la afinidad de sesiones, opciones: None o ClientIP.
  loadBalancerSourceRanges:
    - 203.0.113.0/24  # Restringe el acceso al balanceador de carga a estos rangos de IP (opcional).

  • ExternalName

Descripción:

Un ExternalName no redirige el tráfico a los Pods del clúster, sino que actúa como un alias para un nombre DNS externo. Básicamente, resuelve el nombre de servicio en un nombre DNS externo (como una redirección).

Uso:

Se usa cuando necesitas acceder a un servicio externo, fuera del clúster, mediante un nombre DNS específico. No crea ningún ClusterIP, ni interactúa con los Pods. Sirve para configurar aplicaciones dentro del clúster para que accedan a servicios externos sin tener que modificar el código de la aplicación, solo cambiando el nombre de servicio.

Ejemplo de uso: Si tienes una base de datos o una API externa (por ejemplo, una API SaaS) a la que necesitas acceder desde dentro de tu clúster, puedes usar un ExternalName para simplificar la configuración.

apiVersion: v1
kind: Service
metadata:
  name: my-externalname-service
  namespace: default
  labels:
    app: my-app
  annotations:
    description: "ExternalName Service que actúa como un alias DNS para servicios externos."

spec:
  type: ExternalName  # Tipo de Service: actúa como un alias para un nombre DNS externo.
  externalName: my-external-service.example.com  # Nombre DNS al que se redirige el tráfico.
  ports:
    - protocol: TCP
      port: 80  # Puerto que usará el servicio para redirigir el tráfico (opcional).

Ingress template

Descripción:

El recurso Ingress en Kubernetes permite gestionar el acceso externo a los servicios dentro de un clúster, normalmente mediante HTTP y HTTPS. Ingress proporciona reglas para enrutar solicitudes basadas en nombres de host, rutas, o incluso basándose en headers, hacia los servicios correspondientes dentro del clúster. A diferencia de NodePort o LoadBalancer, Ingress ofrece más control sobre el enrutamiento de tráfico y permite configurar reglas para múltiples servicios en un solo punto de entrada (puerta de enlace).

Uso:

Ingress se utiliza para exponer servicios HTTP/HTTPS a través de reglas de enrutamiento. Permite:

  1. Enrutar solicitudes basadas en el nombre de dominio (host).
  2. Dirigir diferentes rutas (URL) a diferentes servicios.
  3. Gestionar certificados SSL para el tráfico HTTPS.
  4. Utilizar un único punto de acceso para múltiples servicios.
  5. Configurar reglas avanzadas como redireccionamientos, autenticación o balanceo de carga.

Uso común de Ingress:

  1. Controlar el acceso HTTP/HTTPS de manera centralizada.
  2. Proveer un único dominio para múltiples servicios en el clúster, cada uno con diferentes rutas.
  3. Implementar balanceo de carga HTTP avanzado y TLS (SSL).
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress  # Nombre del recurso Ingress.
  namespace: default  # Namespace donde se despliega el Ingress.
  labels:
    app: my-app
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /  # Ejemplo de anotación para reescribir URL.
    kubernetes.io/ingress.class: "nginx"  # Especifica la clase de controlador Ingress.
    nginx.ingress.kubernetes.io/ssl-redirect: "true"  # Redirige automáticamente HTTP a HTTPS.
    cert-manager.io/cluster-issuer: "letsencrypt-prod"  # Para gestionar certificados SSL con cert-manager.

spec:
  rules:
    - host: example.com  # Define el nombre de dominio que será gestionado por el Ingress.
      http:
        paths:
          - path: /  # Ruta principal.
            pathType: Prefix  # Especifica que todas las rutas con este prefijo serán redirigidas.
            backend:
              service:
                name: my-service  # Nombre del servicio al que se redirige.
                port:
                  number: 80  # Puerto del servicio (puerto HTTP en este caso).

          - path: /api  # Ruta para la API.
            pathType: Prefix
            backend:
              service:
                name: api-service  # Servicio que manejará las solicitudes de la ruta "/api".
                port:
                  number: 8080

          - path: /static  # Ruta para servir contenido estático.
            pathType: Prefix
            backend:
              service:
                name: static-service  # Servicio para manejar la ruta "/static".
                port:
                  number: 8081

  tls:  # Configuración para el manejo de certificados SSL.
    - hosts:
        - example.com  # Nombre de dominio que se asegura con TLS.
      secretName: tls-secret  # Nombre del Secret que contiene el certificado TLS.

  defaultBackend:  # Define un backend por defecto si no se cumplen las reglas anteriores.
    service:
      name: default-service  # Servicio por defecto al que se enviará el tráfico si ninguna regla coincide.
      port:
        number: 80

POD identities

Utilizan el IAM de la nube en conjunto con cuentas de servicio del propio K8S para proveer un token en las variables de entorno.

Firewall

- Master

sudo firewall-cmd --permanent --add-port=6443/tcp

sudo firewall-cmd --permanent --add-port=2379-2380/tcp

sudo firewall-cmd --permanent --add-port=10250/tcp

sudo firewall-cmd --permanent --add-port=10259/tcp

sudo firewall-cmd --permanent --add-port=10257/tcp

sudo firewall-cmd --reload

- Worker

sudo firewall-cmd --permanent --add-port=10250/tcp

sudo firewall-cmd --permanent --add-port=30000-32767/tcp

sudo firewall-cmd --reload

SELinux

sudo setenforce 1

sed -i 's/SELINUX=permissive/SELINUX=enforcing/g' /etc/selinux/config

CRI-O

curl https://raw.githubusercontent.com/cri-o/packaging/main/get | sudo bash

sudo systemctl enable --now crio

sudo systemctl enable --now podman.socket

Kube repo

  • /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.29/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.29/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni

sudo dnf install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

kube-controller-manager

Archivo; /etc/kubernetes/manifests/kube-controller-manager.yaml

Debe llevar los siguientes flags;

  • "--allocate-node-cidrs=true"
  • "--cluster-cidr="

Ubicaciones

  • Kubeconfig

Todas las distribuciones

~/.kube/config

kubectl --kubeconfig [path_location]

$KUBECONFIG

Rancher Goverment (RKEv2)

/etc/rancher/rke2/rke2.yaml

Kubernetes bare metal

/etc/kubernetes/admin.conf

Tags - Roles

Posibles roles para los nodos;

  • worker
  • control-plane
  • etcd
  • master

Asignar un rol

kubectl label node [node_name] node-role.kubernetes.io/[role]=[tag_any_name]

Borrar un rol

kubectl label node [node_name] node-role.kubernetes.io/[role]-

Persistent Volume (PV)

Sirve para que independientemente de la instancia de POD, se pueda usar el volumes en cada despliegue, se definen mediante el StorageClass.

Si se maneja bien los espacios y los nombres, se puede usar un PV y su PVC para pods especificos.

A diferencia de los volumenes comunes, estos no varian dependiendo de la instancia, por eso son "persistent".

El PV no se usa en el master, si no que afecta a los worker.

  • Volumen persistente manual
apiVersion: v1
kind: PersistentVolume
metadata:
  name: [pv_name]
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"

Luego se puede crear el PersistentVolumeClaim para que pueda usar un espacio determinado según el PV que lo satisfaga

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: [pvc_name]
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi

Ejemplo de un POD con un PVC específico

apiVersion: v1
kind: Pod
metadata:
  name: task-pv-pod
spec:
  volumes:
    - name: task-pv-storage
      persistentVolumeClaim:
        claimName: task-pv-claim
  containers:
    - name: task-pv-container
      image: nginx
      ports:
        - containerPort: 80
          name: "http-server"
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: task-pv-storage

Backups

  • ETCD

Rancher Goverment (RKEv2)

rke2 etcd-snapshot save --name pre-upgrade-snapshot

systemctl stop rke2-server && rke2 server --cluster-reset --cluster-reset-restore-path=[PATH-TO-SNAPSHOT] && systemctl start rke2-server

Comandos

sudo KUBECONFIG=[path_absoluto] kubectl ....

- Unir al cluster

Kubernetes bare metal

kubeadm join --discovery-token [master_token] --discovery-token-ca-cert-hash sha256:[HASH] --control-plane [master_IP]:6443

- Aplicar deployment

Apply sobre escribirá si ya existe el recurso

kubectl apply -f [file_or_URLfile]

  • "-l [key]=[value]" asignar tag
  • "-k [ditectory]" aplica varios deployments a la vez

Mientras que "create" no sobre escribirá

kubectl create -f [file_or_URLfile]

  • "-l [key]=[value]" asignar tag
  • "-k [ditectory]" aplica varios deployments a la vez

En ambos ("create" y "apply") los tipos que se soportan son;

  1. clusterrole
  2. clusterrolebinding
  3. configmap
  4. cronjob
  5. deployment
  6. ingress
  7. job
  8. namespace
  9. poddisruptionbudget
  10. priorityclass
  11. quota
  12. role
  13. rolebinding
  14. secret
  15. secret docker-registry
  16. secret generic
  17. secret tls
  18. service
  19. service clusterip
  20. service externalname
  21. service loadbalancer
  22. service nodeport
  23. serviceaccount
  24. token
  25. pv
  26. pvc

- Editar deployment

Se usa el editor especificado en la variable de entorno KUBE_EDITOR ó EDITOR

kubectl edit [type]/[resource_name]

  • "-o json" edita usando el modo json
  • "-o yaml" edita usando el modo yaml

- Mostrar eventos

Para todo el clúster

kubectl events --all-namespaces

Para un pod específico

kubectl events --for pod/[pod_name] --watch

- Customizar salida

... -o [yaml,json,wide,etc]

- Obtener información

kubectl get [info] -o yaml

  1. nodes
  2. deployments
  3. pods
  4. svc (services)
  5. rc (replication controller)
  6. pv (persistent volume)
  7. pvc (persistent volume claim)

kubectl cluster-info

  • "--storage-driver-password [string]" contraseña para la base de datos
  • "--storage-driver-host [ip]:[port]" ip y puerto para la base de datos
  • "--storage-driver-db [name]" nombre de la base de datos
  • "--storage-driver-table [name]" nombre de la tabla
  • "--storage-driver-user [name]" nombre de usuario
  • "-s [ip]:[port]" ip y puerto del servidor

- Obtener una descripción

kubectl describe [recurso] -o yaml

Recursos compatibles

  1. nodes
  2. deployments
  3. pods
  4. svc (services)
  5. rc (replication controller)

- Inspeccionar pod

kubectl inspect pods/[podname]

- Ver registros (logs)

kubectl logs [pod_name]

  • "--tail=X" las últimas X líneas
  • "--since=Xh" las últimas X horas
  • "-c [container_name]" de un contenedor específico de ese POD
  • "--previous" contenedores previos fallidos
  • "--all-containers" todos los contenedores de ese pod

- Adjuntar a container

kubectl attach [pod_name]

  • "-c [container_name]" a un contenedor específico
  • "... -i -t" interactive y TTY
  • "rs/[pod_name]" primera réplica del pod

- Ejecutar en un contenedor

kubectl exec [pod_name] -c [container] -i -t -- [comand] [command_arguments]

- Auditar autenticación

kubectl auth

  • "--storage-driver-password [string]" contraseña para la base de datos
  • "--storage-driver-host [ip]:[port]" ip y puerto para la base de datos
  • "--storage-driver-db [name]" nombre de la base de datos
  • "--storage-driver-table [name]" nombre de la tabla
  • "--storage-driver-user [name]" nombre de usuario
  • "-s [ip]:[port]" ip y puerto del servidor

- Setear auto escalado horizontal

kubectl autoscale [type] [resource] --min=[X] --max=[Y] --cpu-percent=[Z]

Tipos;

  1. deployments
  2. pods
  3. svc (services)
  4. rc (replication controller)

- Setear escalado manual

kubectl scale --replicas=[X] [type]/[resource_name]

- Aprobar una solicitud de firmar un certificado (CSR: Certificate Signing Request)

kubectl certificate approve [CSR_name]

  • "-f [file_or_URLFile]" si no está el nombre, se puede usar un archivo
  • "-R" si se usó "-f" y son más de un archivo se puede especificar esto para que lea todo el directorio
  • "--force"
  • "-h"

- Marcar nodo como inusable

Esto hace que el scheduler del master no mande algo a ejecutar

kubectl cordon [node]

También se lo puede marcar como "drain" para realizar tareas de mantenimiento

kubectl dran [node]

- Copiar desde/hacia el POD

El src ó dest puede ser la máquina local, el otro tiene que ser el POD.

El pod se especifica; [namespace]/[pod_name]:[absolute_path]

kubectl cp [src] [dest]

- Debug resource

kubectl debug [type]/[resource_name] -it --image=[busybox,debian,etc]

  • "-c [containers_pod]" especificamente para los tipos; pod

- Borrar recursos

kubectl delete [type-1],[type-n] [resource_name]

- Ver diferencias entre configuraciones

La diferencia es entre el archivo de deployment original y la configuración actual del recurso

kubectl diff -f [file]

- Crear un servicio en un pod existente

kubectl expose [type] [resource_name] --port=[host_port] --target-port=[container_port] --name=[service_name]

  • "-f [archivo].yaml" también se puede usar un archivo en vez de especificar el tipo

- Actualizar labels en un recurso

kubectl label --overwrite [type] [resource_name] [label]=[value]

  • "-f [archivo].yaml" también se puede usar un archivo en vez de especificar el tipo

- Exponer puerto sin crear servicios

kubectl port-forward [type]/[resoource_name] [host_port]:[container_port] --address [ip_where_allow_incoming]

- Proxy HTTP para acceder a la API de Kubernetes

Se inicia un proxy entre el host donde ejecutamos y el clúster para poder consumir la API de Kubernetes

kubectl proxy --port=[port_to_use] --address=[ip_master_node]

La URL luego tiene esta forma;

http://localhost:8080/api/v1/proxy/namespaces/[namespace]/services/[service]

Se debe usar kubectl config para especificar usar ese proxy

kubectl config set-context [name] --proxy=http://[proxy_ip]:[port]

kubectl proxy -n default --url http://[proxy_ip]:[port]

- Remplazar/actualizar POD

kubectl replace -f [file].[yaml/json]

- Rollback

Son soportados; deployments, daemonsts, statefulsets.

kubectl rollout undo [type]/[resource_name]

kubectl rollout status [type]/[resource_name]

kubectl rollout restart [type]/[resource_name]

kubectl rollout history

kubectl rollout [pause/resume] [type]/[resource_name]

kubectl rollout undo [type]/[resource_name]

Se puede incluir el argumento "--selector=app=[name]" en vez del tipo y nombre_recurso.

- Crear POD

kubectl run [name] --image=[image] --port=[container_port] --env=[environment_variable] --labels="[var]=[value],[var2]=[value2]" --restart=[Never/Always] -t -i

- Ver consumo de recursos

kubectl top [node/pod]/[resource_name]