En este documento, se explica cómo configurar Pods en Google Kubernetes Engine (GKE) con varias interfaces de red mediante el CNI de Multus, el complemento de CNI de IPVLAN y el complemento de IPAM de Whereabouts.
El complemento de CNI de IPVLAN proporciona conectividad de capa 2 para interfaces de Pod adicionales, y el complemento de IPAM de Whereabouts les asigna direcciones IP de forma dinámica.
Esta configuración permite establecer configuraciones de red avanzadas, como la separación del tráfico del plano de control y el 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 contenido de Google Cloud , consulta Roles y tareas comunes de los usuarios 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 a través de esta solución proporciona varias ventajas clave. Los casos de uso principales para configurar Multus con IPVLAN en el modo de capa 2 son para la segmentación de redes 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 el plano de datos: Dedica la interfaz de red principal al tráfico del plano de control y dirige el tráfico del plano de datos de alta capacidad de procesamiento 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 Pods en la misma red secundaria.
Limitaciones
Los Pods configurados con interfaces de Multus no pueden usar simultáneamente las capacidades integradas de varias redes de GKE. La configuración de red de un Pod debe usar Multus o la función integrada de varias redes del clúster.
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 distribuidor, ya que llama a otros complementos de CNI para configurar interfaces de red según los recursos de NetworkAttachmentDefinition. Defines cada red adicional con un NetworkAttachmentDefinition, que especifica qué complemento de CNI (como IPVLAN) y qué complemento de IPAM (como Whereabouts) se deben 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) de las interfaces de red adicionales de los Pods.
En este diagrama, se muestran dos nodos, cada uno con un Pod. 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étera): Multus administra estas interfaces. Multus invoca el complemento de CNI de IPVLAN 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 IPAM de Whereabouts dentro de
NetworkAttachmentDefinition. El complemento Whereabouts IPAM asigna de forma dinámica direcciones IP 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 garantiza 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 te guiará para 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 ya instalaste gcloud CLI, 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 que se describen en 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 redes múltiples habilitados. Para obtener más información, consulta Configura la compatibilidad con varias redes para Pods. Habilitar las redes múltiples también habilita las funciones de política de alta disponibilidad de subred de varias IPs y de IP persistente, lo que elimina la necesidad de configurar manualmente la conectividad entre nodos.
- Usa una versión validada por GKE de Multus CNI (como la v4.2.1) para garantizar la compatibilidad.
Configura la VPC
Para configurar la nube privada virtual (VPC) para usarla con Multus, lo que incluye 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 de 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: Es la región de la subred, comous-central1.SECONDARY_RANGE_NAME: Es el nombre del rango de direcciones IP secundario para los Pods en la subred.SECONDARY_RANGE_CIDR: Es el rango de CIDR secundario para 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_NAMEes el nombre del clúster nuevo.CLUSTER_VERSION: Es la versión del 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 estándar de GKE 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: Es la zona del grupo de nodos, comous-central1-c.VPC_NAME: Es el nombre de la VPC adicional.SUBNET_NAME: Es el nombre de la subred.SECONDARY_RANGE_NAME: Es 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 de CNI de Multus. Guarda el siguiente manifiesto, que incluye el DaemonSet y la definición de recurso personalizado (CRD) obligatorios, 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 los Pods se conectan a una red y especifica el rango de direcciones IP que asigna un complemento de IPAM, como Whereabouts. Este rango debe ser 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: Es 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: Es el rango de direcciones IP para las interfaces de Pod, que es el mismo que el rango de 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
Cómo conectar los Pods a redes adicionales
Para adjuntar 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 separada por comas de los nombres de NetworkAttachmentDefinition en el siguiente formato: <namespace>/<nad-name>.
En el siguiente ejemplo, se muestra un manifiesto de Pod que se adjunta 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 recibe una dirección IP adicional después de que lo adjuntas a una red adicional, inspecciona las interfaces de red dentro del Pod:
Para inspeccionar
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 lo siguiente:
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 eneth0y10.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 el CNI de IPVLAN.
- Obtén más información sobre Whereabouts IPAM.