En este documento, se explica cómo configurar Pods en Google Kubernetes Engine (GKE) con varias interfaces de red mediante Multus CNI, el complemento IPVLAN CNI y el complemento Whereabouts IPAM.
El complemento IPVLAN CNI proporciona conectividad de capa 2 para interfaces de Pod adicionales, y el complemento Whereabouts IPAM les asigna direcciones IP de forma dinámica.
Esta configuración permite configuraciones de red avanzadas, como la separación del tráfico del plano de control y del plano de datos para mejorar el aislamiento y la segmentación de la red.
Este documento está dirigido a arquitectos de nube y especialistas en herramientas de redes que diseñan la red para su organización. Para obtener más información sobre los roles comunes y las tareas de ejemplo a las que hacemos referencia en el Google Cloud contenido de, consulta Roles y tareas comunes del usuario de GKE.
Antes de leer este documento, asegúrate de estar familiarizado con los siguientes conceptos:
- Herramientas de redes de GKE.
- Herramientas de redes de Kubernetes.
- Interfaz de red de contenedor (CNI).
- IPVLAN
- Administración de direcciones IP (IPAM).
Beneficios de usar Multus con IPVLAN
Configurar tus Pods con varias interfaces de red mediante esta solución proporciona varias ventajas clave. Los principales casos de uso para configurar Multus con IPVLAN en modo de capa 2 son para la segmentación de red que requiere adyacencia de capa 2:
- Aislamiento del tráfico: Aísla diferentes tipos de tráfico para mejorar la seguridad y el rendimiento. Por ejemplo, puedes separar el tráfico de administración sensible del tráfico de datos de la aplicación.
- Separación del plano de control y del plano de datos: Dedica la interfaz de red principal al tráfico del plano de control mientras diriges el tráfico del plano de datos de alto rendimiento a través de una interfaz IPVLAN secundaria.
- Adyacencia de capa 2: Cumple con los requisitos de las aplicaciones que necesitan conectividad directa de capa 2 entre los Pods en la misma red secundaria.
Limitaciones
Multus con IPVLAN y Whereabouts tiene las siguientes limitaciones:
- Los Pods configurados con interfaces de Multus no pueden usar las capacidades de varias redes integradas de GKE de forma simultánea. La configuración de red de un Pod debe usar Multus o las varias redes integradas del clúster.
- Multus con IPVLAN y Whereabouts requiere la resolución ARP de capa 2 dentro del Pod para funcionar correctamente.
- De forma predeterminada, las subredes de VPC no permiten la resolución ARP en las interfaces secundarias de las VMs de Compute Engine. Para permitir esta resolución ARP, puedes inscribirte en la versión preliminar privada de la función
resolve-subnet-masksi abres un caso de asistencia.
Cómo funciona Multus con IPVLAN y Whereabouts
Multus es un metaplugin de CNI que permite que los Pods se conecten a varias redes. Multus actúa como un despachador y llama a otros complementos de CNI para configurar interfaces de red basadas en recursos NetworkAttachmentDefinition. Defines cada red adicional con un NetworkAttachmentDefinition, que especifica qué complemento de CNI (como IPVLAN) y qué complemento de IPAM (como Whereabouts) usar para esa red.
En el siguiente diagrama, se ilustra la arquitectura de Multus con los complementos IPVLAN y Whereabouts.El complemento Whereabouts funciona con Multus y IPVLAN para controlar la administración de direcciones IP (IPAM) para las interfaces de red adicionales de los Pods.
En este diagrama, se muestran dos nodos que tienen un Pod cada uno. Cada Pod tiene una interfaz principal y una interfaz adicional. Las dos interfaces principales se conectan a una tarjeta de interfaz de red compartida, y las dos interfaces adicionales se conectan a una tarjeta de interfaz de red compartida diferente.
Cuando se usa Multus con IPVLAN y Whereabouts en GKE, los Pods suelen tener la siguiente configuración de interfaz:
- Interfaz principal (
eth0): GKE Dataplane V2 administra esta interfaz y proporciona conectividad predeterminada del clúster. - Interfaces adicionales (
net1, etc.): Multus administra estas interfaces. Multus invoca el complemento IPVLAN CNI en modo de capa 2 para cadaNetworkAttachmentDefinitionque especifiques en las anotaciones de un Pod. Esta configuración proporciona conectividad de capa 2 a una red de VPC secundaria. - Administración de direcciones IP (IPAM): Configuras el complemento Whereabouts IPAM
dentro de
NetworkAttachmentDefinition. El complemento Whereabouts IPAM asigna direcciones IP de forma dinámica a las interfaces IPVLAN adicionales desde un rango predefinido.
Programación de Pods con varias redes
Cuando creas un Pod y especificas un NetworkAttachmentDefinition en sus anotaciones, el programador de GKE coloca el Pod solo en un nodo que puede satisfacer los requisitos de red. El programador identifica los nodos dentro de un grupo de nodos que tienen configurada la interfaz de red secundaria necesaria. Este proceso de identificación de nodos ayuda a garantizar que el programador programe el Pod en un nodo que pueda conectarse a la red adicional y recibir una dirección IP del rango especificado.
En las siguientes secciones, se explica cómo configurar Multus con los complementos IPVLAN y Whereabouts en tu clúster de GKE.
Antes de comenzar
Antes de comenzar, asegúrate de haber realizado las siguientes tareas:
- Habilita la API de Google Kubernetes Engine. Habilitar la API de Google Kubernetes Engine
- Si deseas usar Google Cloud CLI para esta tarea,
instala y, luego,
inicializa gcloud CLI. Si instalaste gcloud CLI anteriormente, ejecuta el comando
gcloud components updatepara obtener la versión más reciente. Es posible que las versiones anteriores de gcloud CLI no admitan la ejecución de los comandos de este documento.
- Instala la herramienta de línea de comandos de
kubectl. - Configura un clúster de GKE que ejecute la versión 1.28 o posterior con Dataplane V2, alias de IP y varias redes habilitadas. Para obtener información, consulta Configura la compatibilidad con varias redes para Pods. Habilitar varias redes también habilita las funciones de Multi-IP-Subnet y Persistent-IP HA Policy, lo que elimina la necesidad de configuración manual de conectividad entre nodos.
- Usa una versión validada por GKE de Multus CNI (como v4.2.1) para la compatibilidad.
Configura la VPC
Para configurar la nube privada virtual (VPC) para usar con Multus, incluida la creación de una subred para la red de nodos y rangos secundarios para la red de Pods, completa los siguientes pasos:
Crea una VPC nueva o usa una existente:
gcloud compute networks create VPC_NAME \ --subnet-mode=customReemplaza
VPC_NAMEpor el nombre de la VPC.Crea una subred nueva dentro de esta VPC:
gcloud compute networks subnets create SUBNET_NAME \ --range=PRIMARY_RANGE \ --network=VPC_NAME \ --region=REGION \ --secondary-range=SECONDARY_RANGE_NAME=SECONDARY_RANGE_CIDRReemplaza lo siguiente:
SUBNET_NAME: es el nombre de la subred nueva.PRIMARY_RANGE: es el rango CIDR principal de la subred, como10.0.1.0/24. Este comando usa este rango para las interfaces de nodos.VPC_NAME: El nombre de la VPC.REGION: la región de la subred, comous-central1.SECONDARY_RANGE_NAME: el nombre del rango de direcciones IP secundario para los Pods en la subred.SECONDARY_RANGE_CIDR: el rango CIDR secundario para los Pods, como172.16.1.0/24. Las interfaces adicionales en los Pods usan este rango.
Este comando crea una subred con un rango CIDR principal para una interfaz de nodo adicional y un rango secundario para las interfaces de Pod adicionales.
Crea un clúster de GKE Standard
Crea un clúster de GKE Standard con varias redes habilitadas:
gcloud container clusters create CLUSTER_NAME \
--cluster-version=CLUSTER_VERSION \
--enable-dataplane-v2 \
--enable-ip-alias \
--enable-multi-networking
Reemplaza lo siguiente:
CLUSTER_NAME: es el nombre del clúster nuevo.CLUSTER_VERSION: es la versión de tu clúster de GKE. Debes usar la versión 1.28 o una posterior.
Habilitar varias redes te permite crear grupos de nodos con varias interfaces de red, lo que requiere Multus CNI.
Crea un grupo de nodos de GKE Standard
Crea un grupo de nodos de GKE Standard conectado a redes de VPC adicionales:
gcloud container node-pools create NODEPOOL_NAME \
--cluster CLUSTER_NAME \
--zone "ZONE" \
--additional-node-network network=VPC_NAME,subnetwork=SUBNET_NAME \
--additional-pod-network subnetwork=SUBNET_NAME,pod-ipv4-range=SECONDARY_RANGE_NAME,max-pods-per-node=8
Reemplaza lo siguiente:
NODEPOOL_NAME: el nombre del grupo de nodos nuevoCLUSTER_NAME: El nombre de tu clúster.ZONE: la zona del grupo de nodos, comous-central1-c.VPC_NAME: el nombre de la VPC adicional.SUBNET_NAME: Es el nombre de la subred.SECONDARY_RANGE_NAME: el nombre del rango de direcciones IP secundario para los Pods en la subred.
Este comando crea un grupo de nodos en el que los nodos tienen una interfaz de red adicional en SUBNET_NAME, y los Pods en estos nodos pueden usar direcciones IP de SECONDARY_RANGE_NAME.
Para obtener más información sobre cómo crear clústeres de GKE con capacidades de varias redes, consulta Configura la compatibilidad con varias redes para Pods.
Aplica la implementación de Multus
Para habilitar varias interfaces de red para tus Pods, instala el complemento Multus CNI. Guarda el siguiente manifiesto, que incluye el DaemonSet y la definición de recursos personalizados (CRD) requeridos, como multus-manifest.yaml:
apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: ippools.whereabouts.cni.cncf.io spec: group: whereabouts.cni.cncf.io names: kind: IPPool listKind: IPPoolList plural: ippools singular: ippool scope: Namespaced versions: - name: v1alpha1 schema: openAPIV3Schema: description: IPPool is the Schema for the ippools API properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' type: string metadata: type: object spec: description: IPPoolSpec defines the desired state of IPPool properties: allocations: additionalProperties: description: IPAllocation represents metadata about the pod/container owner of a specific IP properties: id: type: string podref: type: string required: - id type: object description: Allocations is the set of allocated IPs for the given range. Its indices are a direct mapping to the IP with the same index/offset for the pools range. type: object range: description: Range is a RFC 4632/4291-style string that represents an IP address and prefix length in CIDR notation type: string required: - allocations - range type: object type: object served: true storage: true status: acceptedNames: kind: "" plural: "" conditions: [] storedVersions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.4.1 name: overlappingrangeipreservations.whereabouts.cni.cncf.io spec: group: whereabouts.cni.cncf.io names: kind: OverlappingRangeIPReservation listKind: OverlappingRangeIPReservationList plural: overlappingrangeipreservations singular: overlappingrangeipreservation scope: Namespaced versions: - name: v1alpha1 schema: openAPIV3Schema: description: OverlappingRangeIPReservation is the Schema for the OverlappingRangeIPReservations API properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object spec: description: OverlappingRangeIPReservationSpec defines the desired state of OverlappingRangeIPReservation properties: containerid: type: string podref: type: string required: - containerid type: object required: - spec type: object served: true storage: true status: acceptedNames: kind: "" plural: "" conditions: [] storedVersions: [] --- kind: ConfigMap apiVersion: v1 metadata: name: multus-cni-config namespace: kube-system labels: app: gke-multinet data: cni-conf.json: | { "name": "multus-cni-network", "type": "multus", "confDir": "/etc/cni/net.d", "namespaceIsolation": true, "logLevel": "verbose", "logFile": "/var/log/multus.log", "kubeconfig": "/var/lib/kubelet/kubeconfig", "clusterNetwork": "gke-pod-network" } --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: network-attachment-definitions.k8s.cni.cncf.io spec: group: k8s.cni.cncf.io scope: Namespaced names: plural: network-attachment-definitions singular: network-attachment-definition kind: NetworkAttachmentDefinition shortNames: - net-attach-def versions: - name: v1 served: true storage: true schema: openAPIV3Schema: description: 'NetworkAttachmentDefinition is a CRD schema specified by the Network Plumbing Working Group to express the intent for attaching pods to one or more logical or physical networks. More information available at: https://github.com/k8snetworkplumbingwg/multi-net-spec' type: object properties: apiVersion: description: 'APIVersion defines the versioned schema of this represen tation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object spec: description: 'NetworkAttachmentDefinition spec defines the desired state of a network attachment' type: object properties: config: description: 'NetworkAttachmentDefinition config is a JSON-formatted CNI configuration' type: string --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: multus-role rules: - apiGroups: ["k8s.cni.cncf.io"] resources: - '*' verbs: - '*' --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: whereabouts rules: - apiGroups: - whereabouts.cni.cncf.io resources: - ippools - overlappingrangeipreservations verbs: - get - list - watch - create - update - patch - delete - apiGroups: - coordination.k8s.io resources: - leases verbs: - create - apiGroups: - coordination.k8s.io resources: - leases resourceNames: - whereabouts verbs: - '*' - apiGroups: [""] resources: - pods verbs: - list - get --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: multus-role-binding subjects: - kind: Group name: system:nodes roleRef: kind: ClusterRole name: multus-role apiGroup: rbac.authorization.k8s.io --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: whereabouts-role-binding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: whereabouts subjects: - kind: ServiceAccount name: whereabouts-sa namespace: kube-system --- apiVersion: v1 kind: ServiceAccount metadata: name: whereabouts-sa namespace: kube-system --- apiVersion: apps/v1 kind: DaemonSet metadata: name: gke-multinet namespace: kube-system labels: app: gke-multinet spec: selector: matchLabels: app: gke-multinet template: metadata: labels: app: gke-multinet spec: priorityClassName: system-node-critical hostNetwork: true tolerations: - operator: Exists serviceAccountName: whereabouts-sa containers: - name: whereabouts-gc command: [/ip-control-loop] args: - "--log-level=debug" - "--enable-pod-watch=false" - "--cron-schedule=* * * * *" image: gcr.io/gke-release/whereabouts:v0.7.0-gke.3@sha256:2bb8450a99d86c73b262f5ccd8c433d3e3abf17d36ee5c3bf1056a1fe479e8c2 env: - name: NODENAME valueFrom: fieldRef: apiVersion: v1 fieldPath: spec.nodeName - name: WHEREABOUTS_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace resources: requests: cpu: "100m" memory: "50Mi" limits: cpu: "100m" memory: "50Mi" initContainers: - name: install-multus-config image: gcr.io/gke-release/multus-cni:v4.2.1-gke.6@sha256:25b48b8dbbf6c78a10452836f52dee456514783565b70633a168a39e6d322310 args: - "--cni-conf-dir=/host/etc/cni/net.d" - "--multus-conf-file=/tmp/multus-conf/00-multus.conf" - "--multus-log-level=verbose" - "--multus-kubeconfig-file-host=/var/lib/kubelet/kubeconfig" - "--skip-multus-binary-copy=true" - "--skip-config-watch=true" resources: requests: cpu: "100m" memory: "50Mi" limits: cpu: "100m" memory: "50Mi" securityContext: privileged: true volumeMounts: - name: cni mountPath: /host/etc/cni/net.d - name: multus-cfg mountPath: /tmp/multus-conf - name: install-whereabouts command: ["/bin/sh"] args: - -c - > SLEEP=false /install-cni.sh image: gcr.io/gke-release/whereabouts:v0.7.0-gke.3@sha256:2bb8450a99d86c73b262f5ccd8c433d3e3abf17d36ee5c3bf1056a1fe479e8c2 env: - name: NODENAME valueFrom: fieldRef: apiVersion: v1 fieldPath: spec.nodeName - name: WHEREABOUTS_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace resources: requests: cpu: "100m" memory: "50Mi" limits: cpu: "100m" memory: "50Mi" securityContext: privileged: true volumeMounts: - name: cni mountPath: /host/etc/cni/net.d - name: cnibin mountPath: /host/opt/cni/bin - name: install-binary image: gcr.io/gke-release/multus-cni:v4.2.1-gke.6@sha256:25b48b8dbbf6c78a10452836f52dee456514783565b70633a168a39e6d322310 command: ["/gkecmd"] args: - "-operation=copy" - "-cni-bin-dir=/host/opt/cni/bin" resources: requests: cpu: "10m" memory: "100Mi" limits: cpu: "10m" memory: "100Mi" securityContext: privileged: true volumeMounts: - name: cnibin mountPath: /host/opt/cni/bin volumes: - hostPath: path: /var/lib/kubelet/kubeconfig type: File name: kubelet-credentials - name: cni hostPath: path: /etc/cni/net.d type: DirectoryOrCreate - name: cnibin hostPath: path: /home/kubernetes/bin type: DirectoryOrCreate - name: multus-cfg configMap: name: multus-cni-config items: - key: cni-conf.json path: 00-multus.conf updateStrategy: rollingUpdate: maxUnavailable: 2 type: RollingUpdate
Luego, aplica el manifiesto al clúster:
kubectl apply -f multus-manifest.yaml
Crea un manifiesto NetworkAttachmentDefinition
Para permitir que los Pods se conecten a redes adicionales, crea un manifiesto NetworkAttachmentDefinition. Este manifiesto define cómo se conectan los Pods a una red y especifica el rango de direcciones IP que asigna un complemento de IPAM, como Whereabouts. Este rango debe formar parte de la subred que conecta las interfaces de red adicionales de tus nodos.
Guarda este manifiesto como
nad.yaml. Este manifiesto usa los complementos IPVLAN y Whereabouts.apiVersion: "k8s.cni.cncf.io/v1" kind: NetworkAttachmentDefinition metadata: name: NAD_NAME spec: config: '{ "cniVersion": "0.3.1", "plugins": [ { "type": "ipvlan", "master": "eth1", "mode": "l2", "ipam": { "type": "whereabouts", "range": SECONDARY_RANGE_NAME } } ] }'El manifiesto incluye los siguientes campos:
NAD_NAME: el nombre de tuNetworkAttachmentDefinition.master: el nombre de la interfaz de red secundaria del nodo, que actúa como la interfazmasterpara IPVLAN. En GKE, las interfaces de red secundarias suelen comenzar coneth1y se nombran de forma secuencial. Para confirmar el nombre de la interfaz, conéctate a un nodo con SSH y ejecuta el comandoip addr.range: el rango de direcciones IP para las interfaces de Pod, que es el mismo que el rango IPv4 secundario que creaste para los Pods (SECONDARY_RANGE_NAME). Por ejemplo,172.16.1.0/24.
Aplica el manifiesto al clúster:
kubectl apply -f nad.yaml
Conecta Pods a redes adicionales
Para conectar un Pod a una red adicional, agrega la anotación k8s.v1.cni.cncf.io/networks al manifiesto del Pod. Para varias redes, proporciona una
lista de nombres NetworkAttachmentDefinition separada por comas en el siguiente formato:
<namespace>/<nad-name>.
En el siguiente ejemplo, se muestra un manifiesto de Pod que se conecta al NetworkAttachmentDefinition llamado NAD_NAME en el espacio de nombres default:
apiVersion: v1
kind: Pod
metadata:
name: samplepod
annotations:
k8s.v1.cni.cncf.io/networks: default/NAD_NAME
spec:
containers:
- name: sample-container
image: nginx
Reemplaza NAD_NAME por el nombre del NetworkAttachmentDefinition que creaste.
Cuando aplicas este manifiesto, Kubernetes crea el Pod con una interfaz de red adicional (net1) conectada a la red que especifica NetworkAttachmentDefinition.
Verifica la dirección IP adicional del Pod
Para verificar que el Pod reciba una dirección IP adicional después de conectarlo a una red adicional, inspecciona las interfaces de red dentro del Pod:
Para inspeccionar el
samplepody verificar la dirección IP adicional, usa el siguiente comando:$kubectl describe pod PODNAMEReemplaza
PODNAMEpor el nombre de tu Pod, comosamplepod.Examina el resultado. La interfaz
eth0tiene la dirección IP principal del Pod. El complemento Whereabouts asigna la dirección IP adicional a otra interfaz, comonet1.El resultado es similar a este:
k8s.v1.cni.cncf.io/network-status: [{ "name": "gke-pod-network", "interface": "eth0", "ips": [ "10.104.3.4" ], "mac": "ea:e2:f6:ce:18:b5", "default": true, "dns": {}, "gateway": [ "\u003cnil\u003e" ] },{ "name": "default/my-nad", "interface": "net1", "ips": [ "10.200.1.1" ], "mac": "42:01:64:c8:c8:07", "dns": {} }] k8s.v1.cni.cncf.io/networks: default/my-nadEn este ejemplo,
10.104.5.19es la dirección IP principal eneth0, y10.200.1.1es la dirección IP adicional ennet1.
¿Qué sigue?
- Obtén más información sobre Multus CNI.
- Obtén más información sobre IPVLAN CNI.
- Obtén más información sobre Whereabouts IPAM.