Déployer des charges de travail

Cette page décrit la procédure à suivre pour déployer des charges de travail sur votre matériel Google Distributed Cloud, ainsi que les limites à respecter lors de la configuration de vos charges de travail.

Avant de suivre ces étapes, vous devez remplir les conditions d'installation de Distributed Cloud et commander le matériel Distributed Cloud.

Lorsque le matériel Google Distributed Cloud arrive à la destination de votre choix, il est préconfiguré avec le matériel, Google Cloudet certains paramètres réseau que vous avez spécifiés lors de la commande de Distributed Cloud.

Les installateurs Google effectuent l'installation physique, et votre administrateur système connecte Distributed Cloud à votre réseau local.

Une fois le matériel connecté à votre réseau local, il communique avec Google Cloud pour télécharger les mises à jour logicielles et se connecter à votre projetGoogle Cloud . Vous êtes alors prêt à provisionner des pools de nœuds et à déployer des charges de travail sur Distributed Cloud.

Présentation du déploiement

Pour déployer une charge de travail sur votre matériel Distributed Cloud, procédez comme suit :

  1. Facultatif : activez l'API Distributed Cloud Edge Network.

  2. Facultatif : Initialisez la configuration réseau de votre zone Distributed Cloud.

  3. Facultatif : Configurez la mise en réseau Distributed Cloud.

  4. Créez un cluster Distributed Cloud.

  5. Facultatif : Activez la prise en charge des clés de chiffrement gérées par le client (CMEK) pour le stockage local si vous souhaitez intégrer Cloud Key Management Service pour activer la prise en charge des CMEK pour les données de votre charge de travail. Pour savoir comment Distributed Cloud chiffre les données de charge de travail, consultez Sécurité du stockage local.

  6. Créez un pool de nœuds. Dans cette étape, vous attribuez des nœuds à un pool de nœuds et vous pouvez éventuellement configurer le pool de nœuds pour qu'il utilise Cloud KMS afin d'encapsuler et de désencapsuler la phrase secrète LUKS (Linux Unified Key Setup) pour chiffrer les données de charge de travail.

  7. Obtenez les identifiants d'un cluster pour le tester.

  8. Accordez aux utilisateurs l'accès au cluster en leur attribuant le rôle Lecteur Edge Container (roles/edgecontainer.viewer) ou Administrateur Edge Container (roles/edgecontainer.admin) sur le projet.

  9. Attribuez aux utilisateurs un accès précis basé sur les rôles aux ressources du cluster à l'aide de RoleBinding et ClusterRoleBinding.

  10. Facultatif : activez la prise en charge de l'environnement d'exécution de VM sur Google Distributed Cloud pour exécuter des charges de travail sur des machines virtuelles sur Distributed Cloud.

  11. Facultatif : Activez la prise en charge des GPU pour exécuter des charges de travail basées sur GPU sur Distributed Cloud.

  12. Facultatif : Connectez le cluster Distributed Cloud àGoogle Cloud :

    1. Créez une connexion VPN à votre projet Google Cloud .

    2. Vérifiez que la connexion VPN est opérationnelle.

  13. Facultatif : Configurez l'accès privé à Google pour permettre à vos pods d'accéder aux API et servicesGoogle Cloud à l'aide de Cloud VPN.

  14. Facultatif : Configurez Private Service Connect pour permettre à vos pods d'accéder aux API et servicesGoogle Cloud à l'aide de Cloud VPN.

Déployer l'équilibreur de charge NGINX en tant que service

L'exemple suivant illustre le déploiement du serveur NGINX et son exposition en tant que service sur un cluster Distributed Cloud :

  1. Créez un fichier YAML nommé nginx-deployment.yaml avec le contenu suivant :

    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: nginx
    labels:
      app: nginx
    spec:
    replicas: 1
    selector:
      matchLabels:
         app: nginx
    template:
      metadata:
         labels:
         app: nginx
      spec:
         containers:
         - name: nginx
         image: nginx:latest
         ports:
         - containerPort: 80 
  2. Appliquez le fichier YAML au cluster à l'aide de la commande suivante :

    kubectl apply -f nginx-deployment.yaml
    
  3. Créez un fichier YAML nommé nginx-service.yaml avec le contenu suivant :

    apiVersion: v1
    kind: Service
    metadata:
    name: nginx-service
    spec:
    type: LoadBalancer
    selector:
      app: nginx
      ports:
         - protocol: TCP
           port: 8080
           targetPort: 80
  4. Appliquez le fichier YAML au cluster à l'aide de la commande suivante :

    kubectl apply -f nginx-deployment.yaml
    
  5. Obtenez l'adresse IP externe attribuée au service par l'équilibreur de charge MetalLB à l'aide de la commande suivante :

    kubectl get services
    

    La commande renvoie un résultat semblable à celui-ci :

    NAME            TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)          AGE
    nginx-service   LoadBalancer   10.51.195.25   10.100.68.104   8080:31966/TCP   11d
    

Déployer un conteneur avec des fonctions SR-IOV

L'exemple suivant montre comment déployer un pod qui utilise les fonctionnalités de l'opérateur de fonction réseau SR-IOV de Distributed Cloud.

Créer les composants réseau Distributed Cloud

Créez les composants réseau Distributed Cloud requis comme suit. Pour en savoir plus sur ces composants, consultez Fonctionnalités de mise en réseau Distributed Cloud.

  1. Créez un réseau :

    gcloud edge-cloud networking networks create NETWORK_NAME \
        --location=REGION \
        --zone=ZONE_NAME \
        --mtu=MTU_SIZE
    

    Remplacez les éléments suivants :

    • NETWORK_NAME : nom descriptif qui identifie de manière unique ce réseau.
    • REGION : région Google Cloud à laquelle appartient la zone Distributed Cloud cible.
    • ZONE_NAME : nom de la zone Distributed Cloud cible.
    • MTU_SIZE : taille de l'unité de transmission maximale (MTU) pour ce réseau. Les valeurs valides sont 1 500 et 9 000. Cette valeur doit correspondre à la taille de la MTU du réseau default et être identique pour tous les réseaux.
  2. Créez un sous-réseau :

    gcloud edge-cloud networking subnets create SUBNETWORK_NAME \
        --network=NETWORK_NAME \
        --ipv4-range=IPV4_RANGE \
        --vlan-id=VLAN_ID \
        --location=REGION \
        --zone=ZONE_NAME
    

    Remplacez les éléments suivants :

    • SUBNETWORK_NAME : nom descriptif qui identifie de manière unique ce sous-réseau.
    • NETWORK_NAME : réseau qui encapsule ce sous-réseau.
    • IPV4_RANGE : plage d'adresses IPv4 couverte par ce sous-réseau, au format adresse IP/préfixe.
    • VLAN_ID : ID de VLAN cible pour ce sous-réseau.
    • REGION : région Google Cloud à laquelle appartient la zone Distributed Cloud cible.
    • ZONE_NAME : nom de la zone Distributed Cloud cible.
  3. Surveillez l'état du sous-réseau jusqu'à ce qu'il ait été créé :

    watch -n 30 'gcloud edge-cloud networking subnets list \
        --location=REGION \
        --zone=ZONE_NAME
    

    Remplacez les éléments suivants :

    • REGION : région Google Cloud à laquelle appartient la zone Distributed Cloud cible.
    • ZONE_NAME : nom de la zone Distributed Cloud cible.

    L'état passe de PENDING à PROVISIONING, puis à RUNNING.

    Enregistrez l'ID de VLAN, le bloc CIDR du sous-réseau et l'adresse IP de la passerelle pour le bloc CIDR. Vous utiliserez ces valeurs plus tard dans cette procédure.

Configurer les ressources NodeSystemConfigUpdate

Configurez une ressource d'opérateur de fonction réseau NodeSystemConfigUpdate pour chaque nœud du cluster comme suit.

  1. Répertoriez les nœuds exécutés dans le pool de nœuds du cluster cible à l'aide de la commande suivante :

    kubectl get nodes | grep -v master
    

    La commande renvoie un résultat semblable à celui-ci :

    NAME                                 STATUS   ROLES       AGE     VERSION
    pool-example-node-1-01-b2d82cc7      Ready    <none>      2d      v1.22.8-gke.200
    pool-example-node-1-02-52ddvfc9      Ready    <none>      2d      v1.22.8-gke.200
    

    Enregistrez les noms des nœuds renvoyés et dérivez leurs noms courts. Par exemple, pour le nœud pool-example-node-1-01-b2d82cc7, son nom court est node101.

  2. Pour chaque nœud que vous avez enregistré à l'étape précédente, créez un fichier de ressources NodeSystemConfigUpdate dédié avec le contenu suivant :

    apiVersion: networking.gke.io/v1
    kind: NodeSystemConfigUpdate
    metadata:
    name: nodesystemconfigupdate-NODE_SHORT_NAME
    namespace: nf-operator
    spec:
    kubeletConfig:
      cpuManagerPolicy: Static
      topologyManagerPolicy: SingleNumaNode
    nodeName: NODE_NAME
    osConfig:
      hugePagesConfig:
         ONE_GB: 2
         TWO_MB: 0
      isolatedCpusPerSocket:
         "0": 40
         "1": 40
    sysctls:
      nodeLevel:
         net.core.rmem_max: "8388608"
         net.core.wmem_max: "8388608"

    Remplacez les éléments suivants :

    • NODE_NAME : nom complet du nœud cible. Exemple : pool-example-node-1-01-b2d82cc7.
    • NODE_SHORT_NAME : nom abrégé du nœud cible dérivé de son nom complet. Exemple :node101

    Nommez chaque fichier node-system-config-update-NODE_SHORT_NAME.yaml.

  3. Appliquez chacun des fichiers de ressources NodeSystemConfigUpdate au cluster à l'aide de la commande suivante :

    kubectl apply -f node-system-config-update-NODE_SHORT_NAME.yaml
    

    Remplacez NODE_SHORT_NAME par le nom abrégé du nœud cible correspondant.

    Lorsque vous appliquez les ressources au cluster, chaque nœud concerné redémarre, ce qui peut prendre jusqu'à 30 minutes.

    1. Surveillez l'état des nœuds concernés jusqu'à ce qu'ils aient tous redémarré correctement :
    kubectl get nodes | grep -v master
    

    L'état de chaque nœud passe de not-ready à ready une fois le redémarrage terminé.

Configurer les commutateurs ToR pour les fonctions réseau SR-IOV

Suivez les étapes de cette section pour configurer les interfaces réseau de chaque commutateur ToR Distributed Cloud dans le rack Distributed Cloud pour le fonctionnement des fonctions réseau SR-IOV.

  1. Créez un fichier nommé mlnc6-pcie1-tor1-sriov.yaml avec le contenu suivant : Ce fichier configure la première interface réseau sur le premier commutateur ToR.

      apiVersion: sriovnetwork.k8s.cni.cncf.io/v1
      kind: SriovNetworkNodePolicy
      metadata:
      name: mlnx6-pcie1-tor1-sriov
      namespace: sriov-network-operator
      spec:
      deviceType: netdevice
      isRdma: false
      linkType: eth
      mtu: 9000
      nicSelector:
         pfNames:
         - enp59s0f0np0
      nodeSelector:
         edgecontainer.googleapis.com/network-sriov.capable: "true"
      numVfs: 31
      priority: 99
      resourceName: mlnx6_pcie1_tor1_sriov
  2. Créez un fichier nommé mlnc6-pcie1-tor2-sriov.yaml avec le contenu suivant : Ce fichier configure la deuxième interface réseau sur le premier commutateur ToR.

      apiVersion: sriovnetwork.k8s.cni.cncf.io/v1
      kind: SriovNetworkNodePolicy
      metadata:
      name: mlnx6-pcie1-tor2-sriov
      namespace: sriov-network-operator
      spec:
      deviceType: netdevice
      isRdma: false
      linkType: eth
      mtu: 9000
      nicSelector:
         pfNames:
         - enp59s0f1np1
      nodeSelector:
         edgecontainer.googleapis.com/network-sriov.capable: "true"
      numVfs: 31
      priority: 99
      resourceName: mlnx6_pcie1_tor2_sriov
  3. Créez un fichier nommé mlnc6-pcie2-tor1-sriov.yaml avec le contenu suivant : Ce fichier configure la première interface réseau sur le deuxième commutateur ToR.

      apiVersion: sriovnetwork.k8s.cni.cncf.io/v1
      kind: SriovNetworkNodePolicy
      metadata:
      name: mlnx6-pcie2-tor1-sriov
      namespace: sriov-network-operator
      spec:
      deviceType: netdevice
      isRdma: false
      linkType: eth
      mtu: 9000
      nicSelector:
         pfNames:
         - enp216s0f0np0
      nodeSelector:
         edgecontainer.googleapis.com/network-sriov.capable: "true"
      numVfs: 31
      priority: 99
      resourceName: mlnx6_pcie2_tor1_sriov
  4. Créez un fichier nommé mlnc6-pcie2-tor2-sriov.yaml avec le contenu suivant : Ce fichier configure la deuxième interface réseau sur le deuxième commutateur ToR.

      apiVersion: sriovnetwork.k8s.cni.cncf.io/v1
      kind: SriovNetworkNodePolicy
      metadata:
      name: mlnx6-pcie2-tor2-sriov
      namespace: sriov-network-operator
      spec:
      deviceType: netdevice
      isRdma: false
      linkType: eth
      mtu: 9000
      nicSelector:
         pfNames:
         - enp216s0f1np1
      nodeSelector:
         edgecontainer.googleapis.com/network-sriov.capable: "true"
      numVfs: 31
      priority: 99
      resourceName: mlnx6_pcie2_tor2_sriov
  5. Appliquez les fichiers de configuration ToR au cluster à l'aide des commandes suivantes :

    kubectl apply -f mlnc6-pcie1-tor1-sriov.yaml
    kubectl apply -f mlnc6-pcie1-tor2-sriov.yaml
    kubectl apply -f mlnc6-pcie2-tor1-sriov.yaml
    kubectl apply -f mlnc6-pcie2-tor2-sriov.yaml
    

    Les nœuds concernés sont marqués comme non programmables, drainés et redémarrés.

  6. Surveillez l'état des nœuds à l'aide de la commande suivante :

    watch -n 5 'kubectl get sriovnetworknodestates -o yaml -A | \ 
    grep "syncStatus\|pool-"|sed "N;s/\n/ /"'
    

    Lorsque tous les nœuds concernés affichent syncStatus: Succeeded, appuyez sur Ctrl+C pour quitter la boucle de commande de surveillance.

    La commande renvoie un résultat semblable à celui-ci, indiquant que les fonctionnalités de la fonction réseau SR-IOV ont été activées sur les commutateurs ToR :

    Allocated resources:
    (Total limits may be over 100 percent, i.e., overcommitted.)
    Resource                       Requests     Limits
    --------                       --------     ------
    cpu                            2520m (3%)   7310m (9%)
    memory                         3044Mi (1%)  9774Mi (3%)
    ephemeral-storage              0 (0%)       0 (0%)
    hugepages-1Gi                  0 (0%)       0 (0%)
    hugepages-2Mi                  0 (0%)       0 (0%)
    devices.kubevirt.io/kvm        0            0
    devices.kubevirt.io/tun        0            0
    devices.kubevirt.io/vhost-net  0            0
    gke.io/mlnx6_pcie1_tor1_sriov  3            3
    gke.io/mlnx6_pcie1_tor2_sriov  0            0
    gke.io/mlnx6_pcie2_tor1_sriov  0            0
    gke.io/mlnx6_pcie2_tor2_sriov  0            0
    

Configurer une ressource NetworkAttachmentDefinition

Configurez une ressource NetworkAttachmentDefinition pour le cluster comme suit :

  1. Créez un fichier nommé network-attachment-definition.yaml avec le contenu suivant :

    apiVersion: "k8s.cni.cncf.io/v1"
    kind: NetworkAttachmentDefinition
    metadata:
    name: sriov-net1
    annotations:
      k8s.v1.cni.cncf.io/resourceName: gke.io/mlnx6_pcie1_tor1_sriov
    spec:
    config: '{
    "type": "sriov",
    "cniVersion": "0.3.1",
    "vlan": VLAN_ID,
    "name": "sriov-network",
    "ipam": {
      "type": "host-local",
      "subnet": "SUBNETWORK_CIDR",
      "routes": [{
         "dst": "0.0.0.0/0"
      }],
      "gateway": "GATEWAY_ADDRESS"
    }
    }'

Remplacez les éléments suivants :

  • VLAN_ID : ID de VLAN du sous-réseau que vous avez créé précédemment dans ce guide.
  • SUBNETWORK_CIDR : bloc CIDR du sous-réseau.
  • GATEWAY_ADDRESS : adresse IP de la passerelle pour le sous-réseau.
  1. Appliquez la ressource au cluster à l'aide de la commande suivante :

    kubectl apply -f network-attachment-definition.yaml
    

Déployer un pod avec des fonctions réseau SR-IOV

Suivez les étapes de cette section pour déployer un pod avec des fonctions réseau SR-IOV sur le cluster. Le champ annotations du fichier de configuration du pod spécifie le nom de la ressource NetworkAttachmentDefinition que vous avez créée précédemment dans ce guide et l'espace de noms dans lequel elle a été déployée (default dans cet exemple).

  1. Créez un fichier de spécification de pod nommé sriovpod.yaml avec le contenu suivant :

         apiVersion: v1
         kind: Pod
         metadata:
         name: sriovpod
         annotations:
            k8s.v1.cni.cncf.io/networks: default/sriov-net1
         spec:
         containers:
         - name: sleeppodsriov
            command: ["sh", "-c", "trap : TERM INT; sleep infinity & wait"]
            image: busybox
            securityContext:
               capabilities:
               add:
                  - NET_ADMIN
  2. Appliquez le fichier de spécification du pod au cluster à l'aide de la commande suivante :

    kubectl apply -f sriovpod.yaml
    
  3. Vérifiez que le pod a bien démarré à l'aide de la commande suivante :

    kubectl get pods
    
  4. Établissez un shell de ligne de commande pour le pod à l'aide de la commande suivante :

    kubectl exec -it sriovpod -- sh
    
  5. Vérifiez que le pod communique avec les commutateurs ToR à l'aide de la fonctionnalité d'opérateur de fonction réseau SR-IOV en exécutant la commande suivante dans le shell du pod :

    ip addr
    

    La commande renvoie un résultat semblable à celui-ci :

    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
       link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
       inet 127.0.0.1/8 scope host lo
          valid_lft forever preferred_lft forever
       inet6 ::1/128 scope host 
          valid_lft forever preferred_lft forever
    51: net1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 9000 qdisc mq qlen 1000
       link/ether 2a:af:96:a5:42:ab brd ff:ff:ff:ff:ff:ff
       inet 192.168.100.11/25 brd 192.168.100.127 scope global net1
          valid_lft forever preferred_lft forever
    228: eth0@if229: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue qlen 1000
       link/ether 46:c9:1d:4c:bf:32 brd ff:ff:ff:ff:ff:ff
       inet 10.10.3.159/32 scope global eth0
          valid_lft forever preferred_lft forever
       inet6 fe80::44c9:1dff:fe4c:bf32/64 scope link 
          valid_lft forever preferred_lft forever
    

    Les informations renvoyées pour l'interface net1 indiquent que la connectivité réseau entre les commutateurs ToR et le pod a été établie.

Limites pour les charges de travail Distributed Cloud

Lorsque vous configurez vos charges de travail Distributed Cloud, vous devez respecter les limites décrites dans cette section. Ces limites sont appliquées par Distributed Cloud à toutes les charges de travail que vous déployez sur votre matériel Distributed Cloud.

Limites des charges de travail Linux

Distributed Cloud n'est compatible qu'avec les fonctionnalités Linux suivantes pour les charges de travail :

  • AUDIT_READ
  • AUDIT_WRITE
  • CHOWN
  • DAC_OVERRIDE
  • FOWNER
  • FSETID
  • IPC_LOCK
  • IPC_OWNER
  • KILL
  • MKNOD
  • NET_ADMIN
  • NET_BIND_SERVICE
  • NET_RAW
  • SETFCAP
  • SETGID
  • SETPCAP
  • SETUID
  • SYS_CHROOT
  • SYS_NICE
  • SYS_PACCT
  • SYS_RESOURCE
  • SYS_TIME

Restrictions concernant les espaces de noms

Distributed Cloud n'est pas compatible avec les espaces de noms suivants :

  • hostPID
  • hostIPC
  • hostNetwork

Restrictions concernant les types de ressources

Distributed Cloud n'est pas compatible avec le type de ressource CertificateSigningRequest, qui permet à un client de demander l'émission d'un certificat X.509 en fonction d'une demande de signature.

Restrictions du contexte de sécurité

Distributed Cloud n'est pas compatible avec le contexte de sécurité en mode privilégié.

Restrictions liées à l'association de pods

Distributed Cloud n'est pas compatible avec l'association de pods aux ports hôtes dans l'espace de noms HostNetwork. De plus, l'espace de noms HostNetwork n'est pas disponible.

hostPath restrictions de volume

Distributed Cloud n'autorise que les volumes hostPath suivants avec accès en lecture/écriture :

  • /dev/hugepages
  • /dev/infiniband
  • /dev/vfio
  • /dev/char
  • /sys/devices

Restrictions de type de ressource PersistentVolumeClaim

Distributed Cloud n'autorise que les types de ressources PersistentVolumeClaim suivants :

  • csi
  • nfs
  • local

Restrictions concernant les types de volumes

Distributed Cloud n'autorise que les types de volumes suivants :

  • configMap
  • csi
  • downwardAPI
  • emptyDir
  • hostPath
  • nfs
  • persistentVolumeClaim
  • projected
  • secret

Restrictions de tolérance des pods

Distributed Cloud n'autorise pas les pods créés par l'utilisateur sur les nœuds du plan de contrôle. Plus précisément, Distributed Cloud n'autorise pas la planification des pods qui comportent les clés de tolérance suivantes :

  • ""
  • node-role.kubernetes.io/master
  • node-role.kubernetes.io/control-plane

Restrictions concernant l'usurpation d'identité

Distributed Cloud n'est pas compatible avec l'usurpation d'identité d'utilisateurs ou de groupes.

Restrictions concernant l'espace de noms de gestion

Distributed Cloud n'autorise pas l'accès aux espaces de noms suivants :

  • ai-system
  • ai-speech-system
  • ai-ocr-system
  • ai-translation-system
  • anthos-identity-service
  • cert-manager
  • dataproc-system
  • dataproc-PROJECT_ID
  • dns-system
  • g-istio-system
  • gke-connect
  • gke-managed-metrics-server
  • gke-operators
  • g-ospf-servicecontrol-system
  • g-ospf-system
  • gke-system
  • gpc-backup-system
  • iam-system
  • kube-node-lease
  • kube-public
  • kube-system, à l'exception de la suppression de ippools.whereabouts.cni.cncf.io
  • metallb-system, à l'exception de la modification des ressources configMap pour définir les plages d'adresses IP d'équilibrage de charge
  • nf-operator
  • oclcm-system
  • prediction
  • rm-system
  • robinio
  • saas-system
  • sriov-fec-system
  • sriov-network-operator
  • vm-system

PROJECT_ID désigne l'ID du projet Google Cloud cible.

Évitez d'utiliser un espace de noms dont le nom commence par le préfixe g-. Ces espaces de noms sont généralement des espaces de noms réservés utilisés par Distributed Cloud.

Restrictions concernant les webhooks

Distributed Cloud limite les webhooks comme suit :

  • Tout webhook de mutation que vous créez exclut automatiquement l'espace de noms kube-system.
  • Les webhooks de mutation sont désactivés pour les types de ressources suivants :
    • nodes
    • persistentvolumes
    • certificatesigningrequests
    • tokenreviews

Étapes suivantes