Este documento explica como configurar pods no Google Kubernetes Engine (GKE) com várias interfaces de rede usando a CNI do Multus, o plug-in CNI do IPVLAN e o plug-in IPAM do Whereabouts.
O plug-in CNI IPVLAN oferece conectividade da camada 2 para interfaces de pod adicionais, e o plug-in IPAM Whereabouts atribui endereços IP dinamicamente a elas.
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 papéis comuns e tarefas de exemplo referenciados no conteúdo do Google Cloud , consulte Tarefas e funções de usuário comuns do GKE.
Antes de ler este documento, confira se você conhece os seguintes conceitos:
- Rede do GKE.
- Rede do Kubernetes.
- Interface de rede de contêineres (CNI).
- IPVLAN.
- Gerenciamento de endereços IP (IPAM).
Benefícios de usar o Multus com IPVLAN
Configurar seus 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 da Camada 2 são para segmentação de rede que exige adjacência da Camada 2:
- Isolamento de tráfego:isole diferentes tipos de tráfego para aumentar 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 e direcione o tráfego do plano de dados de alta capacidade por uma interface IPVLAN secundária.
- Adjacência da camada 2:atende aos requisitos de aplicativos que precisam de conectividade direta da camada 2 entre pods na mesma rede secundária.
Limitações
Os pods configurados com interfaces Multus não podem usar simultaneamente os recursos multirrede integrados do GKE. A configuração de rede de um pod precisa usar o Multus ou a multirrede integrada do cluster.
Como o Multus funciona com IPVLAN e Whereabouts
O Multus é um metaplugin 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 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) das interfaces de rede adicionais dos pods.
Este diagrama mostra dois nós, cada um com um pod. Cada pod tem uma interface principal e outra 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 padrão do cluster. - Outras interfaces (
net1etc.): O Multus gerencia essas interfaces. O Multus invoca o plug-in CNI IPVLAN no modo da camada 2 para cadaNetworkAttachmentDefinitionespecificado nas anotações de um pod. Essa configuração fornece conectividade da Camada 2 a uma rede VPC secundária. - Gerenciamento de endereços IP (IPAM): configure o plug-in IPAM do Whereabouts
no
NetworkAttachmentDefinition. O plug-in Whereabouts IPAM atribui dinamicamente endereços IP à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 os 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ó garante que o programador agende 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:
- Ativar a API Google Kubernetes Engine. Ativar a API Google Kubernetes Engine
- Se você quiser usar a CLI do Google Cloud para essa tarefa,
instale e inicialize a
gcloud CLI. Se você instalou a gcloud CLI anteriormente, instale a versão
mais recente executando o comando
gcloud components update. Talvez as versões anteriores da gcloud CLI não sejam compatíveis com a execução dos comandos neste documento.
- Instale a ferramenta de linha de comando
kubectl. - Configure um cluster do GKE executando a versão 1.28 ou mais recente com Dataplane V2, 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 várias sub-redes de IP e IP persistente, o que elimina a necessidade de configuração manual da conectividade entre nós.
- Use uma versão do Multus CNI validada pelo GKE (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, conclua as seguintes etapas:
Crie uma VPC ou use uma existente:
gcloud compute networks create VPC_NAME \ --subnet-mode=customSubstitua
VPC_NAMEpelo nome da VPC.Crie uma sub-rede na 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. Use a versão 1.28 ou posterior.
Ao ativar várias redes, é possível criar pools de nós com várias interfaces de rede, o que é necessário para a CNI do Multus.
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 seguinte manifesto, que inclui o DaemonSet e a
definição de recurso personalizada (CRD) 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
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 plugins 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 do seuNetworkAttachmentDefinition.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 geralmente começam cometh1e são nomeadas em sequência. 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 outra rede, adicione a anotação k8s.v1.cni.cncf.io/networks
ao manifesto do pod. Para várias redes, forneça uma lista separada por vírgulas de nomes NetworkAttachmentDefinition 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
que você criou.
Quando você aplica esse manifesto, o Kubernetes cria o pod com uma interface de rede adicional (net1) conectada à rede especificada por NetworkAttachmentDefinition.
Verificar o endereço IP adicional do pod
Para verificar se o pod recebe um endereço IP adicional depois de ser anexado a uma rede extra, 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
PODNAMEpelo nome do pod, comosamplepod.Analise 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á o seguinte:
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 a CNI do Multus.
- Saiba mais sobre o IPVLAN CNI.
- Saiba mais sobre o IPAM do Whereabouts.