Muchos administradores de sistemas ven las redes como uno de los elementos más complejos en un entorno de Kubernetes. Esto es especialmente cierto cuando se aloja su propio clúster de Kubernetes en lugar de pagar por él.
Adaptarse al paradigma de los microservicios, donde los servicios dependen en gran medida de la red para la comunicación, requiere fundamentos de red extensos. Si bien las habilidades de redes muy básicas son parte de la caja de herramientas de cada administrador de sistemas, los administradores de sistemas rara vez tienen una comprensión profunda de las redes. Esto hace que sea más difícil razonar sobre las complejas topologías de red que a menudo acompañan a los entornos de Kubernetes.
En esta serie de artículos, lo guiaré a través de las diferentes capas de la pila de redes de Kubernetes y veré cómo se comunican los contenedores, los pods y los nodos. Estos artículos se centrarán en profundizar en estos conceptos mediante el uso de herramientas como la captura de paquetes para comprender realmente el tráfico que pasa por la red.
Si bien operar un clúster de Kubernetes normal rara vez requiere un conocimiento profundo, este conocimiento puede ayudarlo a mantener y solucionar problemas de cargas de trabajo que se ejecutan en Kubernetes.
Tabla de Contenidos
Conceptos básicos de redes de pods
La unidad de trabajo básica en un clúster de Kubernetes es el Pod, que proporciona un punto de partida ideal para comprender las redes de Kubernetes. Un pod consta de uno o más contenedores que comparten un espacio de nombres específico.
Puede parecer extraño tener varios contenedores en un pod, pero este enfoque es bastante común.por ejemplo, un Inicializar el contenedor Puede ejecutarse antes de que el contenedor de la aplicación comience a realizar la configuración de la carga de trabajo. Esta configuración puede incluir la obtención de secretos del almacén de secretos o la realización de otra configuración de tiempo de ejecución que no se puede integrar fácilmente en la imagen del contenedor. Este enfoque también es común en las mallas de servicios, donde los contenedores sidecar se ejecutan junto con los contenedores de aplicaciones para proporcionar capacidades de red avanzadas.
[ Learn how to manage your Linux environment for success. ]
Desde una perspectiva de red, cada contenedor en un pod comparte el mismo espacio de nombres de red. Esto permite que cada contenedor acceda a los mismos recursos de red, como la dirección IP del pod. Los contenedores en el mismo pod también pueden comunicarse entre sí a través de localhost.
Para comprender mejor cómo funciona esto en la práctica, iniciaré algunos pods y examinaré sus pilas de red.
Vaina multicontenedor
Este artículo usa minikube para construir rápidamente un clúster para pruebas. Si no ha usado minikube antes, es fácil de instalar. Un clúster de un solo nodo con la configuración predeterminada es suficiente para este laboratorio:
$ minikube start
😄 minikube v1.25.2 on Ubuntu 20.04
✨ Automatically selected the kvm2 driver. Other choices: virtualbox, ssh
👍 Starting control plane node minikube in cluster minikube
🔥 Creating kvm2 VM (CPUs=2, Memory=3900MB, Disk=20000MB) ...
🐳 Preparing Kubernetes v1.23.3 on Docker 20.10.12 ...
▪ kubelet.housekeeping-interval=5m
▪ Generating certificates and keys ...
▪ Booting up control plane ...
▪ Configuring RBAC rules ...
🔎 Verifying Kubernetes components...
▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟 Enabled addons: default-storageclass, storage-provisioner
🏄 Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
[ Cheat sheet: Get a list of Linux utilities and commands for managing servers and networks. ]
Para comprender cómo se comunican los contenedores en un pod, necesita un pod con varios contenedores. Este artículo usa un pod simple con dos contenedores: Nginx y BusyBox. El contenedor Nginx sirve la página web predeterminada y el contenedor BusyBox duerme indefinidamente:
$ cat nginx_busybox.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-busybox
spec:
containers:
- command:
- sleep
- infinity
image: busybox
name: busybox
- image: nginx
name: nginx
$ kubectl apply -f nginx_busybox.yaml
pod/nginx-busybox created
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-busybox 2/2 Running 0 17s
Una vez que el pod se ejecuta correctamente, puede conectarse a él e iniciar un shell para mirar alrededor. Primero, confirme que BusyBox puede comunicarse con Nginx a través de localhost:
$ kubectl exec -it -c busybox nginx-busybox -- /bin/sh
/ # wget localhost -O - 2>/dev/null
Welcome to nginx!
Welcome to nginx!
If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.
For online documentation and support please refer to
nginx.org.
Commercial support is available at
nginx.com.
Thank you for using nginx.
Se puede acceder a Nginx a través de localhost y sirve una página predeterminada.una examinacion netstat
La salida confirma que algo está escuchando en el puerto 80. Sin embargo, el contenedor BusyBox no puede ver el ID del proceso en ejecución:
/ # netstat -tnlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN -
tcp 0 0 :::80 :::* LISTEN -
El ID del proceso no está visible porque el contenedor BusyBox se ejecuta en un espacio de nombres de proceso diferente al del contenedor Nginx.Sin embargo, puede iniciar un shell en el contenedor de Nginx y ver el ID del proceso (después de la instalación). netstat
en un recipiente):
$ kubectl exec -it -c nginx nginx-busybox -- /bin/bash
root@nginx-busybox:/# netstat -tnlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1/nginx: master pro
tcp6 0 0 :::80 :::* LISTEN 1/nginx: master pro
Comprobar espacio de nombres
Hasta ahora, este artículo ha analizado varios aspectos de las redes desde una perspectiva de contenedor. Pero, ¿cómo se ve esto en el host? Para comprender la configuración del espacio de nombres desde la perspectiva del host, primero debe obtener la identificación del contenedor de cada contenedor dentro del pod:
$ kubectl get pod -o json nginx-busybox | jq .status.containerStatuses[].containerID
"docker://1d77670aebe59cdcc0f1f538e3e9e7a33b179abd1311c4230bbea69eea65eb02"
"docker://b34908dad17f3a139678520d367aa81786a2b8c74531a2b93b9c221a038b7a1e"
[ Download now: Advanced Linux commands cheat sheet. ]
Cada contenedor se puede verificar usando minikube ssh
Conéctese a una instancia de minikube en ejecución. Minikube usa el tiempo de ejecución de Docker de forma predeterminada y puede usar los comandos estándar de Docker para obtener el ID de proceso del contenedor.Estos ID de proceso se pueden pasar a lsns
Muestre los diferentes espacios de nombres en los que se ejecuta cada contenedor:
# Connect to minikube over SSH
$ minikube ssh
_ _
_ _ ( ) ( )
___ ___ (_) ___ (_)| |/') _ _ | |_ __
/' _ ` _ `\| |/' _ `\| || , < ( ) ( )| '_`\ /'__`\
| ( ) ( ) || || ( ) || || |\`\ | (_) || |_) )( ___/
(_) (_) (_)(_)(_) (_)(_)(_) (_)`\___/'(_,__/'`\____)
# Obtain the process ID of each container in the pod
$ docker inspect 1d77670aebe59cdcc0f1f538e3e9e7a33b179abd1311c4230bbea69eea65eb02 | jq .[].State.Pid
4590
$ docker inspect b34908dad17f3a139678520d367aa81786a2b8c74531a2b93b9c221a038b7a1e | jq .[].State.Pid
4685
# Obtain the namespaces for each process
$ sudo lsns -p 4590
NS TYPE NPROCS PID USER COMMAND
4026531835 cgroup 124 1 root /sbin/init noembed norestore
4026531837 user 124 1 root /sbin/init noembed norestore
4026532463 ipc 5 4513 65535 /pause
4026532466 net 5 4513 65535 /pause
4026532573 mnt 1 4590 root sleep infinity
4026532574 uts 1 4590 root sleep infinity
4026532575 pid 1 4590 root sleep infinity
$ sudo lsns -p 4685
NS TYPE NPROCS PID USER COMMAND
4026531835 cgroup 124 1 root /sbin/init noembed norestore
4026531837 user 124 1 root /sbin/init noembed norestore
4026532463 ipc 5 4513 65535 /pause
4026532466 net 5 4513 65535 /pause
4026532576 mnt 3 4685 root nginx: master process nginx -g daemon off;
4026532577 uts 3 4685 root nginx: master process nginx -g daemon off;
4026532578 pid 3 4685 root nginx: master process nginx -g daemon off;
Este resultado muestra la configuración desde la perspectiva del host.Los contenedores comparten un la red Espacios de nombres (4026532466
), pero funcionan de manera diferente proceso Espacios de nombres (4026532575
y 4026532578
). Esto explica por qué los contenedores dentro de un pod pueden comunicarse entre sí a través de localhost, pero no pueden ver los ID de proceso de los demás.
envolver
Un pod es la unidad de trabajo básica en un clúster de Kubernetes, y comprender el funcionamiento general de su pila de red es fundamental para comprender cómo se comunican las cargas de trabajo de Kubernetes.
Si bien un solo pod puede parecer una estructura muy simple, este artículo ha demostrado que se puede hacer mucho más en un pod en la parte inferior de la pila de redes de Linux. Además, la capacidad de los contenedores en un pod para comunicarse a través de direcciones de host local permite patrones como contenedores sidecar e init.
El próximo artículo de esta serie cubrirá cómo los Pods se comunican entre sí a través de múltiples nodos de Kubernetes.