¿Puedes "jugar" K8 en 30 minutos? ¡Una visita obligada para los novatos!

Si entiendes Pod, entiendes la mitad de Kubernetes

Kubernetes puede entenderse como un servicio API estándar que abstrae recursos de computación en la nube, como computación, redes y almacenamiento.

Casi todas las operaciones en Kubernetes, ya sea utilizando la herramienta de línea de comandos kubectl, o en la interfaz de usuario o CD Pipeline, equivalen a llamar a su API REST.

Mucha gente dice que Kubernetes es complicado. Además de su compleja arquitectura de implementación, otra razón es que existen más de 20 tipos de API de recursos nativos y la curva de aprendizaje es relativamente pronunciada. Pero no se preocupe, siempre que comprendamos la esencia: una plataforma que proporciona capacidades informáticas de contenedores, podremos delinearla y comprenderla rápida y fácilmente.

En K8S, el recurso más importante y básico es Pod, que se traduce como "pod". Usemos el siguiente contenedor Nginx más básico como ejemplo para comprender la vida de un pod, y K8S comprenderá la mitad.

No es necesario estudiar cómo construir Kubernetes. Se recomienda utilizar OrbStack para instalar un entorno Docker y K8S localmente con un solo clic y comenzar a experimentar rápidamente. Primero, escribe un archivo Yaml como este.

# nginx.yamlapiVersion: v1kind: Podmetadata:  name: nginx  labels:    app: nginxspec:  containers:    - name: web      image: nginx      ports:        - name: web          containerPort: 80          protocol: TCP

Luego use kubectl para crear el Pod nginx y agregue  -v8 el modo de registro detallado después del comando para ver qué ha hecho kubectl. ​​​​​​​

kubectl create pod -f nginx.yaml -v8
kubectl get pod -v8

En herramientas de visualización como OpenLens o K9S, podemos ver que "nace" un Pod llamado Nginx y también podemos ver POST / GET y otra información de solicitud del registro detallado de kubectl. ​​​​​​​

I1127 14:55:06.886901   83798 round_trippers.go:463] GET http://127.0.0.1:60649/77046cfbc5f80b52d9a1501954ee0672/api/v1/namespaces/default/pods?limit=500I1127 14:55:06.886916   83798 round_trippers.go:469] Request Headers:I1127 14:55:06.886921   83798 round_trippers.go:473]     User-Agent: kubectl...I1127 14:55:07.166333   83798 round_trippers.go:580]     Cache-Control: no-cache, private

Se puede ver que después de crear el Pod, el Pod real tiene más campos que los campos que declaramos en Yaml. Estos campos adicionales son prueba de la experiencia del Pod desde su nacimiento : programado por el programador en los nodos disponibles en el clúster. y entregado a kubelet Administre el ciclo de vida del Pod, asigne IP de red, monte almacenamiento temporal, extraiga la imagen para iniciar el contenedor cuando el contenedor se esté ejecutando, coordine y corrija el estado de ejecución del controlador, etc.

apiVersion: v1kind: Podmetadata:  name: nginx  namespace: defaultstatus:  phase: Running  hostIP: 10.....  podIP: 10.....  conditions:    - type: Initialized      status: 'True'      lastProbeTime: null      lastTransitionTime: '2023-11-27T06:59:13Z'    - type: Ready      status: 'True'      lastProbeTime: null    .....spec:  volumes:    - name: kube-api-access-72rkq      ......  containers:    - name: web      image: nginx      ports:        - name: web          containerPort: 80          protocol: TCP      resources: {}      volumeMounts:        - name: kube-api-access-72rkq          readOnly: true          mountPath: /var/run/secrets/kubernetes.io/serviceaccount      terminationMessagePath: /dev/termination-log      terminationMessagePolicy: File      imagePullPolicy: Always  restartPolicy: Always  terminationGracePeriodSeconds: 30  dnsPolicy: ClusterFirst  serviceAccountName: default  serviceAccount: default  securityContext: {}  schedulerName: default-scheduler  tolerations:    - key: node.kubernetes.io/not-ready      operator: Exists      effect: NoExecute      tolerationSeconds: 300    - key: node.kubernetes.io/unreachable      operator: Exists      effect: NoExecute      tolerationSeconds: 300  priority: 0  enableServiceLinks: true  preemptionPolicy: PreemptLowerPriority

Para expandirse, ejecutar un contenedor requiere tres componentes principales: informática, red y almacenamiento.

  1. Los recursos informáticos , es decir, CPU/Mem/GPU, se declaran en la parte contenedora de la especificación. En este caso, la cantidad de recursos necesarios no está establecida y las solicitudes y los recursos.límites están vacíos, lo que significa que pueden ocupar todo el host. Este es generalmente el caso. Se llama nivel QoS de mejor esfuerzo y la prioridad de programación es relativamente baja.

  2. En situaciones reales, generalmente se establecen solicitudes/límites razonables para alcanzar el nivel de QoS ampliable o las solicitudes y límites se establecen exactamente iguales para alcanzar el nivel de Garantía. Después de que el programador programe el Pod en un determinado nodo, se entregará a una interfaz llamada CRI (Container Runtime Interface), lo que permite la implementación de CRI para construir realmente el contenedor, generalmente contenedord, cri-o, podman, docker. , etc. espera.

  3. En términos de red , puede ver que hay un campo PodIP adicional en el estado. Esto es para llamar a la interfaz subyacente llamada CNI (Container Network Interface) y dejar que la capa de implementación CNI proporcione la IP. Este proceso es relativamente complicado e involucra un proceso llamado Con respecto al contenedor de pausa, puede ignorar estos detalles al comenzar.

  4. En términos de almacenamiento , puede ver que un volumen/volumeMounts se monta automáticamente. Este es almacenamiento adicional para el Pod. Puede ser un archivo de configuración o una clave, o puede ser un almacenamiento persistente proporcionado por algunos proveedores de nube, como EBS. , Los discos EFS involucrarán el tercer tipo de interfaz subyacente K8S, CSI (Container Storage Interface). Las versiones de distribución de Kubernetes de los proveedores de nube que utilizamos generalmente tienen implementaciones CSI integradas.

Con el almacenamiento de la red informática, el Pod se está ejecutando. Si queremos actualizar el Pod, podemos usar las interfaces de Actualización y Parche. Sin embargo, el Pod es un recurso atómico de Kubernetes y solo puede actualizar algunos campos, como image y readinessGate. .

Si desea finalizar este Pod, puede usar la interfaz Eliminar para hacer que el Pod entre en el estado Terminando. Eventualmente será eliminado por el controlador, los recursos informáticos se reciclarán y el archivo de imagen del contenedor eventualmente será eliminado por GC. .

Este es solo el proceso más básico. Para obtener información detallada sobre el ciclo de vida del Pod, consulte aquí: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/, especialmente algunas actividades del ciclo de vida que están estrechamente relacionadas con el Negocios Por ejemplo, postStart inicia el enlace en paralelo, preStop detiene el enlace en serie, envía SIGTERM para intentar finalizar el proceso, envía la señal SIGKILL después del Graceful Period, etc., lo cual es muy útil para los negocios.

Computación, redes y almacenamiento desde la perspectiva del clúster de Kubernetes

En este punto, entendemos cómo se asignan los recursos de almacenamiento de la red informática al Pod del operador. Entonces, ¿cómo se llama en Kubernetes el conjunto de recursos de informática, red y almacenamiento?

El nodo informático del clúster de Kubernetes se llama Nodo. ​​A diferencia de la definición de máquinas de hardware de la plataforma de nube tradicional, Nodo también es un recurso abstracto. Puede crecer o morir. No está directamente vinculado al contenedor que se está ejecutando, sino a través de una etiqueta. /selector Los mecanismos relacionados con la programación, como la afinidad, están asociados con los Pods.

El recurso de almacenamiento en bloque del clúster de Kubernetes se llama PersistentVolume. En escenarios de uso reales, generalmente se implementa mediante un sistema de archivos distribuido. Según las solicitudes de disco comerciales, lo que crea automáticamente un PersistentVolume se llama StorageClass.

La red Kubernetes se divide en varias capas : una red Pod que convierte todo el clúster en una gran intranet; una red de servicios que permite que los servicios del clúster accedan entre sí con equilibrio de carga L4 integrado; y una Ingress/GatewayAPI/L7. Red ServiceMesh para una gestión detallada del tráfico. También hay recursos NetworkPolicy que controlan las políticas de acceso a la red.

Primero, veamos la red Pod: aunque los principios de red implementados por diferentes CNI varían mucho, el propósito es el mismo: asignar una IP a cada Pod y abrir rutas con otros Pods. Por ejemplo, AWS utiliza una forma muy inteligente de implementarlo: asigna directamente la IP secundaria de la subred VPC actual al Pod. Se reutilizan DHCP y tablas de enrutamiento. El método de comunicación entre Pods es exactamente el mismo que entre los EC2 existentes. nodos. .

Veamos la red de servicios como un equilibrador de carga interno L4 . A cada recurso de servicios K8S se le asigna una IP virtual (ClusterIP). Después de asignar ClusterIP, el componente kube-proxy es responsable de crear la ruta para esta IP virtual y la corrección en tiempo real de los cambios del Pod Endpoint.


Tomemos como ejemplo AWS EKS. EKS usa el modo iptables de forma predeterminada . kube-proxy escribirá la IP de cada servicio ClusterIP en iptables en cada nodo. Puede usar el comando iptables para ver los detalles de implementación.

  • Debido a la modificación de iptables causada por cada cambio, los clústeres a gran escala tienen problemas de rendimiento al utilizar el equilibrio de carga del servicio integrado de K8S, que se puede resolver cambiando al modo ipvs;

  • También hay un servicio sin cabeza sin ClusterIP, que utiliza DNS para realizar el descubrimiento automático de puntos finales y no es un equilibrio de carga L4 convencional;

  • Si necesita exponer directamente un servicio a la red pública y hay servicios de tipo NodePort/LoadBalancer, kube-proxy escuchará el puerto NodePort en cada nodo del clúster e iptables escribirá las reglas DNAT correspondientes al NodePort;

  • El servicio tipo LoadBalancer/NodePort también tiene un campo clave "externalTrafficPolicy". Una comprensión simple es si se trata de un modo de equilibrio de carga entre nodos o un modo de conexión directa de nodo local. El equilibrio de carga entre nodos también provocará una falla en la verificación de estado del LB externo y la imposibilidad de obtener servicios internos. Los problemas de IP del cliente deben ser manejados por el lado de la plataforma y no necesitan preocuparse por el lado comercial. El equipo comercial debe recordar un principio: nunca use el servicio NodePort.

# https://zhuanlan.zhihu.com/p/196393839iptables -L -n# Chain OUTPUT (policy ACCEPT)# target     prot opt source               destination         # KUBE-PROXY-FIREWALL  all  --  anywhere             anywhere             ctstate NEW /* kubernetes load balancer firewall */# KUBE-SERVICES  all  --  anywhere             anywhere             ctstate NEW /* kubernetes service portals */# KUBE-FIREWALL  all  --  anywhere             anywhere          
iptables -L -t nat#Chain KUBE-SVC-TCOU7JCQXEZGVUNU (1 references)#target     prot opt source               destination         #KUBE-SEP-HI2KQBDGYW5OVKWN  all  --  anywhere             anywhere             /* kube-system/kube-dns:dns -> 10.52.xx.xx:53 */ statistic mode random probability 0.50000000000#KUBE-SEP-XQT5TF2PMBOMEGDC  all  --  anywhere             anywhere             /* kube-system/kube-dns:dns -> 10.52.xx.xx:53 */

Finalmente, echemos un vistazo a la red de servicios L7, que generalmente es proporcionada por un balanceador de carga de tráfico de aplicaciones como Nginx Ingress/Envoy. Para negocios, simplemente divida la configuración de nginx en fragmentos de yaml. Ingress administra directamente el tráfico norte-sur, mientras que Service Mesh administra todo el tráfico este-oeste y sur, y también puede implementar algunos comportamientos más complejos que Nginx conf, como cifrado de tráfico, autenticación, inyección de fallas, degradación del disyuntor, reintento, etc.

Otros recursos nativos son para muñecos nido Pod o para fines auxiliares.

El diseño de API de Kubernetes es muy consistente con el Principio de Responsabilidad Única (SRP). Un Pod es un pod simple que contiene un contenedor. Una vez eliminado, desaparece.

Pero, ¿qué debe hacer si desea ejecutar un servicio? No importa. Según el principio de responsabilidad única, implementar nuevas funciones es como una muñeca matrioska. Kubernetes abstrae algo llamado Deployment y lo envuelve en algo llamado ReplicaSet. ReplicaSet luego envuelve el Pod.

De esta manera, la implementación solo cambia y procesa la rotación RS, y RS solo garantiza que se estén ejecutando n pods. Si el pod no se regenera, se reiniciará si muere. Esto también refleja el pensamiento típico de Erlang de dejar que se bloquee.

Un día dices que quieres entrenar un modelo de IA para acabar con OpenAI y Kubernetes te proporciona una abstracción llamada CronJob y Job. CronJob atrapa Job y Job atrapa Pod. El trabajo es solo algo que se ejecuta una sola vez. Es necesario reintentarlo varias veces y cuánto tiempo lleva eliminar el Pod. Cronjob es un cron distribuido natural, que simplemente genera el trabajo a intervalos regulares. CronJob y Job se utilizan ampliamente en campos como canales de procesamiento de big data, canales CICD y capacitación en inteligencia artificial. OpenAI también está entrenado en un enorme clúster de Kubernetes que contiene más de 8.000 nodos.

Un día querrás volver a utilizar Kubernetes para ejecutar una base de datos. Felicitaciones por aprender el recurso nativo más complejo, StatefulSet. La implementación trata a los pods como ganado y puedes matarlos si lo deseas. StatefulSet trata a los pods como mascotas. Las mascotas no. Es fácil de mantener. Cada Pod no se puede mover casualmente. Al actualizar, solo se puede actualizar uno por uno en orden.

Además de estos recursos para los muñecos anidados de Pod, el resto puede entenderse como auxiliar, como el Ingress que introduce tráfico al clúster, el Servicio para el equilibrio de carga del tráfico interno, el ConfigMap de configuración distribuida y el almacenamiento de claves distribuido proporcionado para cada Pod. Secreto. También hay algunas clases auxiliares para el control de políticas y cuotas de recursos, que no se discutirán una por una aquí.

Repensar qué es Kubernetes

En este punto, hemos descubierto aproximadamente qué significa Kubernetes para los usuarios. Desde la vista de componentes del propio Kubernetes, incluye estas cosas:

  • Cada máquina está instalada con un Agente llamado kubelet para controlar lo que ejecuta la máquina.

  • Cada máquina se instala con un proxy kube para alojar las reglas de firewall de la red y una implementación CNI para controlar la asignación de IP del Pod y el enrutamiento de la red dentro del clúster.

  • Opcional, instale una implementación CSI para hacerse cargo de la creación y montaje de discos de almacenamiento persistentes.

  • Todas estas cosas están conectadas al centro de control compuesto por API Server + Controller Manager + Scheduler. Este centro de control expone un conjunto de API REST escalables estándar y todos los datos se almacenan en el clúster de metadatos ETCD.

, permítanos operar clústeres distribuidos, ya no necesitamos usar comandos de shell, todos los comandos están basados ​​​​en API y todos los recursos se convierten en registros de datos ETCD.


Después de entender esto, entendemos que Kubernetes es esencialmente una encapsulación de tecnologías existentes, formando un conjunto de sistemas operativos de recursos en la nube. El trabajo real es solo el proceso en el servidor, y el verdadero aislamiento de recursos son cgroups y espacios de nombres. Algo nativo de el núcleo de Linux.

Después de comprender esto, comprenderá por qué la falla de Kubernetes no afecta los servicios en ejecución. ¿Por qué deberíamos ajustar el rendimiento de las aplicaciones en los clústeres de Kubernetes cuando observamos qué tipo de instancia utiliza EC2, qué generación de almacenamiento fotovoltaico EBS o EFS es o cómo optimizar la latencia RTT y mejorar el ancho de banda entre las VPC del kernel de subred?

Kubernetes es todo lo que es un clúster distribuido, pero Kubernetes no es nada.

El lado A/B de Kubernetes

Los mayores beneficios que aporta Kubernetes son la estandarización, la elasticidad y la escalabilidad.

La interfaz de administración que ofrece REST API está completamente estandarizada,

Guardar un registro ETCD para crear o corregir el estado de los recursos brinda una flexibilidad extrema, y ​​la expansión y contracción de la capacidad es muy sencilla.

Desarrollar un recurso personalizado para implementar cualquier función brinda una gran escalabilidad y desarrolla un enorme ecosistema CloudNative.

Necesitamos ambos, estándares, elasticidad y escalabilidad. Los tenemos todos . Parece perfecto, pero todo tiene dos caras. Estas ventajas de Kubernetes también son fuente de desventajas.

El lado oscuro de la estandarización es la complejidad. El estándar debe tener en cuenta todas las situaciones, por lo que este estándar no puede ser simple: solo una especificación de Pod tiene docenas de campos, y probablemente menos de la mitad de los campos nunca han sido vistos por la mayoría de las personas. La dificultad de aprender Kubernetes y la dificultad de la operación y mantenimiento de construcción propia se pueden ver en las instituciones de capacitación y certificación. Incluso para las grandes empresas, es mejor no tener la idea de construir su propio Kubernetes. Cada uno de los componentes de Kubernetes tiene cientos de parámetros de inicio. O los jóvenes no entienden cuán grandes son los obstáculos o las personas que fingen para entender. , o alguien que realmente lo entienda en un proveedor de nube.

El lado oscuro de la elasticidad es la volatilidad. Los nodos de un clúster pueden crecer y desaparecer en cualquier momento, lo que provoca una intrusión en la arquitectura de la aplicación. Los servicios con estado que se ejecutan en Kubernetes deben tener la capacidad de descubrirlos y configurarlos dinámicamente en el código. Se acabaron las IP estáticas. También descubrí un efecto provocado por Kubernetes, "ansiedad por pérdida de registros". Probablemente nadie en la VM se preocuparía por no recopilar los registros. Los pods en Kubernetes están flotando. La gente siempre pregunta, ¿qué pasa con la última línea de registros antes del ¿El servicio se cuelga? ¿Qué debo hacer si no puedo atenderlo?

El lado oscuro de la escalabilidad es que hay una mezcla de cosas buenas y malas. No todos los productos en CNCF Landscape y la comunidad de código abierto son productos excelentes, e incluso algunas cosas con grandes problemas se han vuelto populares. Por ejemplo, un colega del equipo anterior leyó atentamente el código del operador de Clickhouse y la calidad del código de este proyecto de 1,5K estrellas puede estar por debajo de la línea de aprobación. Hace cuatro años, otro colega y yo intentamos utilizar ES Operador y Kafka Helm Chart para operar y mantener ES/Kafka, pero en ese momento la madurez estaba lejos de alcanzar el nivel de uso de producción. Además, Helm, la herramienta de administración de paquetes más popular para Kubernetes, también es un representante típico de "peor es mejor". Después de que el autor y filósofo de Helm, Matt Butcher, propusiera la idea de OAM, se puso a trabajar en la "computación en la nube de próxima generación". "Ecosistema WASM.

La complejidad es el precio del crecimiento .

Fuente: https://code2life.top/2023/11/24/0074-k8s-in-30-min/

Supongo que te gusta

Origin blog.csdn.net/LinkSLA/article/details/135379486
Recomendado
Clasificación