Este documento explica como configurar pods no Google Kubernetes Engine (GKE) com várias interfaces de rede através do Multus CNI, do plug-in IPVLAN CNI e do plug-in Whereabouts IPAM.
O plug-in CNI IPVLAN oferece conetividade da camada 2 para interfaces de pods adicionais e o plug-in IPAM Whereabouts atribui-lhes dinamicamente endereços IP.
Esta configuração permite configurações de rede avançadas, como a separação do tráfego do plano de controlo e do plano de dados para um isolamento e uma segmentação da rede melhorados.
Este documento destina-se a arquitetos da nuvem e especialistas em redes que concebem e arquitetam a rede para a respetiva organização. Para saber mais acerca das funções comuns e das tarefas de exemplo que referimos no Google Cloud conteúdo, consulte o artigo Funções e tarefas comuns de utilizadores do GKE.
Antes de ler este documento, certifique-se de que conhece os seguintes conceitos:
- Redes do GKE.
- Redes do Kubernetes.
- Interface de rede de contentores (CNI).
- IPVLAN.
- Gestão de endereços IP (IPAM).
Vantagens da utilização do Multus com o IPVLAN
A configuração dos seus pods com várias interfaces de rede através desta solução oferece várias vantagens importantes. Os principais exemplos de utilização para configurar o Multus com o IPVLAN no modo de camada 2 destinam-se à segmentação de rede que requer adjacência da camada 2:
- Isolamento do tráfego: isole diferentes tipos de tráfego para melhorar a segurança e o desempenho. Por exemplo, pode separar o tráfego de gestão sensível do tráfego de dados de aplicações.
- Separação do plano de controlo e do plano de dados: dedique a interface de rede principal ao tráfego do plano de controlo enquanto direciona o tráfego do plano de dados de elevado débito através de uma interface IPVLAN secundária.
- Adjacência da camada 2: cumpre os requisitos para aplicações que precisam de conetividade direta da camada 2 entre os pods na mesma rede secundária.
Limitações
Os pods configurados com interfaces Multus não podem usar simultaneamente as capacidades de várias redes incorporadas do GKE. A configuração de rede de um pod tem de usar o Multus ou a capacidade de várias redes integrada do cluster.
Como o Multus funciona com o IPVLAN e o Whereabouts
O Multus é um metaplugin CNI que permite que os pods se associem a várias redes. O Multus atua como um distribuidor, chamando outros plugins CNI para configurar interfaces de rede com base em recursos NetworkAttachmentDefinition. Define cada rede adicional através de um NetworkAttachmentDefinition, que especifica que plug-in CNI (como IPVLAN) e plug-in IPAM (como Whereabouts) usar para essa rede.
O diagrama seguinte ilustra a arquitetura Multus com plug-ins IPVLAN e Whereabouts.O plug-in Whereabouts funciona com o Multus e o IPVLAN para gerir o endereço IP (IPAM) das interfaces de rede adicionais dos pods.
Este diagrama mostra dois nós que têm cada um um Pod. Cada Pod tem uma interface principal e uma interface adicional. As duas interfaces principais ligam-se a uma placa de rede partilhada e as duas interfaces adicionais ligam-se a uma placa de rede partilhada diferente.
Quando usa o Multus com o IPVLAN e o Whereabouts no GKE, os pods têm normalmente a seguinte configuração de interface:
- Interface principal (
eth0): o GKE Dataplane V2 gere esta interface, oferecendo conectividade de cluster predefinida. - Interfaces adicionais (
net1, etc.): O Multus gere estas interfaces. O Multus invoca o plug-in CNI IPVLAN no modo de camada 2 para cadaNetworkAttachmentDefinitionque especificar nas anotações de um pod. Esta configuração fornece conetividade da camada 2 a uma rede VPC secundária. - Gestão de endereços IP (IPAM): configura o plug-in IPAM do Whereabouts
no
NetworkAttachmentDefinition. O plug-in IPAM Whereabouts atribui dinamicamente endereços IP às interfaces IPVLAN adicionais a partir de um intervalo predefinido.
Agendamento de pods com várias redes
Quando cria um agrupamento e especifica um NetworkAttachmentDefinition nas respetivas anotações, o programador do GKE coloca o agrupamento apenas num nó que possa satisfazer os requisitos de rede. O programador identifica os nós num conjunto de nós que têm a interface de rede secundária necessária configurada. Este processo de identificação de nós garante que o programador agenda o pod num nó que se pode ligar à rede adicional e receber um endereço IP do intervalo especificado.
As secções seguintes explicam como configurar o Multus com os plug-ins IPVLAN e Whereabouts no seu cluster do GKE.
Antes de começar
Antes de começar, certifique-se de que realizou as seguintes tarefas:
- Ative a API Google Kubernetes Engine. Ative a API Google Kubernetes Engine
- Se quiser usar a CLI gcloud para esta tarefa,
instale-a e, em seguida,
inicialize a
CLI gcloud. Se instalou anteriormente a CLI gcloud, execute o comando
gcloud components updatepara obter a versão mais recente. As versões anteriores da CLI gcloud podem não suportar a execução dos comandos neste documento.
- Instale a ferramenta de linha de comandos
kubectl. - Configure um cluster do GKE com a versão 1.28 ou posterior com o Dataplane V2, o alias de IP e a rede múltipla ativados. Para saber como, consulte o artigo Configure o suporte de várias redes para os Pods. A ativação da multirrede também ativa as funcionalidades de política de HA de sub-rede de vários IPs e IP persistente, que eliminam a necessidade de configuração manual da conetividade entre nós.
- Use uma versão validada pelo GKE do Multus CNI (como a v4.2.1) para garantir a compatibilidade.
Configure a VPC
Para configurar a nuvem privada virtual (VPC) para utilização com o Multus, incluindo a criação de uma sub-rede para a rede de nós e intervalos secundários para a rede de pods, conclua os seguintes passos:
Crie uma nova VPC ou use uma existente:
gcloud compute networks create VPC_NAME \ --subnet-mode=customSubstitua
VPC_NAMEpelo nome da VPC.Crie uma nova sub-rede nesta VPC:
gcloud compute networks subnets create SUBNET_NAME \ --range=PRIMARY_RANGE \ --network=VPC_NAME \ --region=REGION \ --secondary-range=SECONDARY_RANGE_NAME=SECONDARY_RANGE_CIDRSubstitua o seguinte:
SUBNET_NAME: o nome da nova sub-rede.PRIMARY_RANGE: o intervalo CIDR principal para a sub-rede, como10.0.1.0/24. Este comando usa este 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 agrupamentos na sub-rede.SECONDARY_RANGE_CIDR: o intervalo CIDR secundário para pods, como172.16.1.0/24. As interfaces adicionais nos pods usam este intervalo.
Este 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.
Crie um cluster padrão do GKE
Crie um cluster padrão do GKE 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 o seguinte:
CLUSTER_NAME: o nome do novo cluster.CLUSTER_VERSION: a versão do seu cluster do GKE. Tem de usar a versão 1.28 ou posterior.
A ativação da rede múltipla permite-lhe criar node pools com várias interfaces de rede, o que o CNI Multus requer.
Crie um node pool padrão do GKE
Crie um pool de nós padrão do GKE ligado a redes VPC adicionais:
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 o seguinte:
NODEPOOL_NAME: o nome do novo node pool.CLUSTER_NAME: o nome do seu cluster.ZONE: a zona do node pool, 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ários para agrupamentos na sub-rede.
Este comando cria um node pool onde os nós têm uma interface de rede adicional em SUBNET_NAME e os pods nestes nós podem usar endereços IP de SECONDARY_RANGE_NAME.
Para mais informações sobre a criação de clusters do GKE com capacidades de várias redes, consulte o artigo Configure o suporte de várias redes para pods.
Aplique a implementação do Multus
Para ativar várias interfaces de rede para os seus pods, instale o plug-in Multus CNI. Guarde o seguinte manifesto, que inclui o DaemonSet necessário e a definição de recursos personalizados (CRD), 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
Crie um manifesto NetworkAttachmentDefinition
Para permitir que os Pods se liguem a redes adicionais, crie um
NetworkAttachmentDefinition manifesto. Este manifesto define como os pods se ligam a uma rede e especifica o intervalo de endereços IP que um plug-in IPAM, como o Whereabouts, atribui. Este intervalo tem de fazer parte da sub-rede que liga as interfaces de rede adicionais dos seus nós.
Guarde este manifesto como
nad.yaml. Este 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 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 começam normalmente cometh1e são denominadas sequencialmente. Para confirmar o nome da interface, estabeleça ligação a um nó através de SSH e execute o comandoip addr.range: o intervalo de endereços IP para interfaces de pods, que é igual ao intervalo IPv4 secundário que criou para os pods (SECONDARY_RANGE_NAME). Por exemplo,172.16.1.0/24.
Aplique o manifesto ao cluster:
kubectl apply -f nad.yaml
Anexe Pods a redes adicionais
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, indique uma lista de nomes de NetworkAttachmentDefinition separados por vírgulas no seguinte formato:
<namespace>/<nad-name>.
O exemplo seguinte mostra um manifesto de podcast que está anexado ao elemento
NetworkAttachmentDefinition com o nome NAD_NAME no espaço de nomes
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 criou.
Quando aplica este manifesto, o Kubernetes cria o pod com uma interface de rede adicional (net1) ligada à rede especificada por NetworkAttachmentDefinition.
Valide o endereço IP adicional do Pod
Para verificar se o Pod recebe um endereço IP adicional depois de o anexar a uma rede adicional, inspecione as interfaces de rede no Pod:
Para inspecionar o
samplepode validar o endereço IP adicional, use o seguinte comando:$kubectl describe pod PODNAMESubstitua
PODNAMEpelo nome do seu Pod, comosamplepod.Examine o resultado. 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 é semelhante ao 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 emeth0e10.200.1.1é o endereço IP adicional emnet1.
O que se segue?
- Saiba mais sobre o Multus CNI.
- Saiba mais sobre o IPVLAN CNI.
- Saiba mais acerca do Whereabouts IPAM.