Este documento explica como configurar pods no Google Kubernetes Engine (GKE) com várias interfaces de rede usando o Multus CNI, o plug-in IPVLAN CNI e o plug-in Whereabouts IPAM.
O plug-in IPVLAN CNI fornece conectividade de camada 2 para outras interfaces de pod, e o plug-in Whereabouts IPAM atribui endereços IP a elas de forma dinâmica.
Essa configuração permite configurações de rede avançadas, como a separação do tráfego do plano de controle e do plano de dados para melhorar o isolamento e a segmentação da rede.
Este documento é destinado a arquitetos de nuvem e especialistas em redes que projetam e arquitetam a rede para a organização. Para saber mais sobre funções comuns e exemplos de tarefas que referenciamos no Google Cloud conteúdo, consulte Funções e tarefas comuns do usuário do GKE.
Antes de ler este documento, verifique se você está familiarizado com os seguintes conceitos:
- Rede do GKE.
- Rede do Kubernetes.
- Interface de rede de contêineres (CNI, na sigla em inglês).
- IPVLAN.
- Gerenciamento de endereços IP (IPAM, na sigla em inglês).
Benefícios de usar o Multus com IPVLAN
A configuração dos pods com várias interfaces de rede usando essa solução oferece várias vantagens importantes. Os principais casos de uso para configurar o Multus com IPVLAN no modo de camada 2 são para segmentação de rede que exige adjacência de camada 2:
- Isolamento de tráfego:isole diferentes tipos de tráfego para melhorar a segurança e o desempenho. Por exemplo, é possível separar o tráfego de gerenciamento sensível do tráfego de dados do aplicativo.
- Separação do plano de controle e de dados:dedique a interface de rede principal ao tráfego do plano de controle enquanto direciona o tráfego de dados de alta capacidade pelo plano de dados por uma interface IPVLAN secundária.
- Adjacência de camada 2:atenda aos requisitos de aplicativos que precisam de conectividade direta de camada 2 entre pods na mesma rede secundária.
Limitações
O Multus com IPVLAN e Whereabouts tem as seguintes limitações:
- Os pods configurados com interfaces Multus não podem usar simultaneamente os recursos de várias redes integrados do GKE. A configuração de rede de um pod precisa usar o Multus ou várias redes integradas do cluster.
- O Multus com IPVLAN e Whereabouts exige a resolução de ARP de camada 2 no pod para funcionar corretamente.
- Por padrão, as sub-redes VPC não permitem a resolução de ARP em interfaces secundárias de VMs do Compute Engine. Para permitir essa resolução de ARP, inscreva-se na visualização particular do recurso
resolve-subnet-maskabrindo um caso de suporte.
Como o Multus funciona com IPVLAN e Whereabouts
O Multus é um metaplug-in CNI que permite que os pods se conectem a várias redes. O Multus atua como um dispatcher, chamando outros plug-ins CNI para configurar interfaces de rede com base em recursos NetworkAttachmentDefinition. Você define cada rede adicional usando um NetworkAttachmentDefinition, que especifica qual plug-in CNI (como IPVLAN) e plug-in IPAM (como Whereabouts) usar para essa rede.
O diagrama a seguir ilustra a arquitetura do Multus com plug-ins IPVLAN e Whereabouts.O plug-in Whereabouts funciona com o Multus e o IPVLAN para processar o gerenciamento de endereços IP (IPAM) para as interfaces de rede adicionais dos pods.
Este diagrama mostra dois nós, cada um com um pod. Cada pod tem uma interface principal e uma interface adicional. As duas interfaces principais se conectam a uma placa de rede compartilhada, e as duas interfaces adicionais se conectam a uma placa de rede compartilhada diferente.
Ao usar o Multus com IPVLAN e Whereabouts no GKE, os pods normalmente têm a seguinte configuração de interface:
- Interface principal (
eth0): o GKE Dataplane V2 gerencia essa interface, fornecendo conectividade de cluster padrão. - Interfaces adicionais (
net1etc.): O Multus gerencia essas interfaces. O Multus invoca o plug-in IPVLAN CNI no modo de camada 2 para cadaNetworkAttachmentDefinitionespecificado nas anotações de um pod. Essa configuração fornece conectividade de camada 2 a uma rede VPC secundária. - Gerenciamento de endereços IP (IPAM): configure o plug-in Whereabouts IPAM
no
NetworkAttachmentDefinition. O plug-in Whereabouts IPAM atribui endereços IP de forma dinâmica às interfaces IPVLAN adicionais de um intervalo predefinido.
Programação de pods com várias redes
Quando você cria um pod e especifica um NetworkAttachmentDefinition nas anotações dele, o programador do GKE coloca o pod apenas em um nó que pode atender aos requisitos de rede. O programador identifica nós em um pool de nós que têm a interface de rede secundária necessária configurada. Esse processo de identificação de nós ajuda a garantir que o programador programe o pod em um nó que possa se conectar à rede adicional e receber um endereço IP do intervalo especificado.
As seções a seguir orientam você na configuração do Multus com plug-ins IPVLAN e Whereabouts no cluster do GKE.
Antes de começar
Antes de começar, verifique se você realizou as tarefas a seguir:
- Ative a API Kubernetes Engine do Google. Ativar a API Google Kubernetes Engine
- Se você quiser usar a Google Cloud CLI para essa tarefa,
instale e, em seguida,
inicialize a
CLI gcloud. Se você já instalou a CLI gcloud, faça o download da versão mais recente
executando o comando
gcloud components update. As versões anteriores da CLI gcloud podem não oferecer suporte à execução dos comandos neste documento.
- Instale a ferramenta de linha de comando
kubectl. - Configure um cluster do GKE que execute a versão 1.28 ou mais recente com o Dataplane V2, o alias de IP e várias redes ativadas. Para saber como, consulte Configurar o suporte a várias redes para pods. A ativação de várias redes também ativa os recursos de política de alta disponibilidade de sub-rede de vários IPs e IP persistente, que eliminam a necessidade de configuração manual de conectividade entre nós.
- Use uma versão validada pelo GKE do Multus CNI (como a v4.2.1) para compatibilidade.
Configurar a VPC
Para configurar a nuvem privada virtual (VPC) para uso com o Multus, incluindo a criação de uma sub-rede para rede de nós e intervalos secundários para rede de pods, siga estas etapas:
Crie uma VPC ou use uma já existente:
gcloud compute networks create VPC_NAME \ --subnet-mode=customSubstitua
VPC_NAMEpelo nome da VPC.Crie uma sub-rede nessa VPC:
gcloud compute networks subnets create SUBNET_NAME \ --range=PRIMARY_RANGE \ --network=VPC_NAME \ --region=REGION \ --secondary-range=SECONDARY_RANGE_NAME=SECONDARY_RANGE_CIDRSubstitua:
SUBNET_NAME: o nome da nova sub-rede;PRIMARY_RANGE: o intervalo CIDR principal da sub-rede, como10.0.1.0/24. Esse comando usa esse intervalo para interfaces de nós.VPC_NAME: o nome da VPC.REGION: a região da sub-rede, comous-central1.SECONDARY_RANGE_NAME: o nome do intervalo de endereços IP secundário para pods na sub-rede.SECONDARY_RANGE_CIDR: o intervalo CIDR secundário para pods, como172.16.1.0/24. Outras interfaces em pods usam esse intervalo.
Esse comando cria uma sub-rede com um intervalo CIDR principal para uma interface de nó adicional e um intervalo secundário para as interfaces de pod adicionais.
Criar um cluster do GKE Standard
Crie um cluster do GKE Standard com várias redes ativadas:
gcloud container clusters create CLUSTER_NAME \
--cluster-version=CLUSTER_VERSION \
--enable-dataplane-v2 \
--enable-ip-alias \
--enable-multi-networking
Substitua:
CLUSTER_NAME: o nome do novo cluster;CLUSTER_VERSION: a versão do cluster do GKE. É necessário usar a versão 1.28 ou mais recente.
A ativação de várias redes permite criar pools de nós com várias interfaces de rede, o que é exigido pelo Multus CNI.
Criar um pool de nós do GKE Standard
Crie um pool de nós do GKE Standard conectado a outras redes VPC:
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
Substitua:
NODEPOOL_NAME: o nome do novo pool de nós.CLUSTER_NAME: o nome do cluster.ZONE: a zona do pool de nós, comous-central1-c.VPC_NAME: o nome da VPC adicional.SUBNET_NAME: o nome da sub-rede.SECONDARY_RANGE_NAME: o nome do intervalo de endereços IP secundário para pods na sub-rede.
Esse comando cria um pool de nós em que os nós têm uma interface de rede adicional em SUBNET_NAME, e os pods nesses nós podem usar endereços IP de SECONDARY_RANGE_NAME.
Para mais informações sobre como criar clusters do GKE com recursos de várias redes, consulte Configurar o suporte a várias redes para pods.
Aplicar a implantação do Multus
Para ativar várias interfaces de rede para seus pods, instale o plug-in Multus CNI. Salve o manifesto a seguir, que inclui o DaemonSet e a definição de recurso personalizado (CRD, na sigla em inglês) necessários, 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
Em seguida, aplique o manifesto ao cluster:
kubectl apply -f multus-manifest.yaml
Criar um manifesto NetworkAttachmentDefinition
Para permitir que os pods se conectem a outras redes, crie um manifesto NetworkAttachmentDefinition. Esse manifesto define como os pods se conectam a uma rede e especifica o intervalo de endereços IP que um plug-in IPAM, como o Whereabouts, atribui. Esse intervalo precisa fazer parte da sub-rede que conecta as interfaces de rede adicionais dos nós.
Salve este manifesto como
nad.yaml. Esse manifesto usa plug-ins IPVLAN e 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 } } ] }'O manifesto inclui os seguintes campos:
NAD_NAME: o nome doNetworkAttachmentDefinition.master: o nome da interface de rede secundária do nó, que atua como a interfacemasterpara IPVLAN. No GKE, as interfaces de rede secundárias normalmente começam cometh1e são nomeadas sequencialmente. Para confirmar o nome da interface, conecte-se a um nó usando SSH e execute o comandoip addr.range: o intervalo de endereços IP para interfaces de pod, que é o mesmo intervalo IPv4 secundário criado para os pods (SECONDARY_RANGE_NAME). Por exemplo,172.16.1.0/24.
Aplique o manifesto ao cluster:
kubectl apply -f nad.yaml
Anexar pods a outras redes
Para anexar um pod a uma rede adicional, adicione a anotação k8s.v1.cni.cncf.io/networks ao manifesto do pod. Para várias redes, forneça uma
lista de nomes NetworkAttachmentDefinition separada por vírgulas no seguinte formato:
<namespace>/<nad-name>.
O exemplo a seguir mostra um manifesto de pod que se conecta ao NetworkAttachmentDefinition chamado NAD_NAME no namespace 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
Substitua NAD_NAME pelo nome do NetworkAttachmentDefinition criado.
Quando você aplica esse manifesto, o Kubernetes cria o pod com uma interface de rede adicional (net1) conectada à rede especificada pelo NetworkAttachmentDefinition.
Verificar o endereço IP adicional do pod
Para verificar se o pod recebe um endereço IP adicional depois de anexá-lo a uma rede adicional, inspecione as interfaces de rede no pod:
Para inspecionar o
samplepode verificar o endereço IP adicional, use o seguinte comando:$kubectl describe pod PODNAMESubstitua o
PODNAMEpelo nome do pod, comosamplepod.Examine a saída. A interface
eth0tem o endereço IP principal do pod. O plug-in Whereabouts atribui o endereço IP adicional a outra interface, comonet1.O resultado será assim:
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-nadNeste exemplo,
10.104.5.19é o endereço IP principal emeth0, e10.200.1.1é o endereço IP adicional emnet1.
A seguir
- Saiba mais sobre o Multus CNI.
- Saiba mais sobre o IPVLAN CNI.
- Saiba mais sobre Whereabouts IPAM.