Implementa Gemma con Ollama y Open-WebUI

Con las GPUs de NVIDIA de nivel empresarial incluidas en el SKU optimizado para IA de la zona de pruebas de GDC, puedes desarrollar y probar aplicaciones exigentes de entrenamiento e inferencia de IA, como la IA generativa.

Gemma es un modelo de lenguaje grande ligero basado en la tecnología de Gemini. En esta guía del instructivo, se muestra cómo implementar Gemma con Ollama y Open-WebUI en GDC Sandbox, y se incluyen los siguientes objetivos.

  • Implementa Ollama con el modelo Gemma en un entorno de pruebas de GDC optimizado para IA con GPUs.
  • Envía instrucciones al servicio de Ollama en su extremo privado a través de la interfaz de Open-WebUI.

Antes de comenzar

Las GPUs en GDC Sandbox se incluyen en el clúster de infraestructura de la organización.

  • Para ejecutar comandos en el clúster de infraestructura de la organización, asegúrate de tener el kubeconfig del clúster org-1-infra, como se describe en Trabaja con clústeres:

    • Configura y autentica la línea de comandos de gdcloud.
    • Genera el archivo kubeconfig para el clúster de infraestructura de la organización y asigna su ruta de acceso a la variable de entorno KUBECONFIG.
  • Asegúrate de que el usuario tenga el rol sandbox-gpu-admin asignado para el proyecto sandbox-gpu-project. De forma predeterminada, el rol se asigna al usuario platform-admin. Puedes asignar el rol a otros usuarios accediendo como platform-admin y ejecutando el siguiente comando:

    kubectl --kubeconfig ${KUBECONFIG} create rolebinding ${NAME} --role=sandbox-gpu-admin \
    --user=${USER} --namespace=sandbox-gpu-project
    
  • Asegúrate de configurar el repositorio de Artifact Registry como se describe en Uso de Artifact Registry y accede para poder enviar y extraer imágenes del registro de artefactos.

Implementa el modelo de Gemma con Ollama y Open-WebUI

La implementación se coordina a través de un conjunto de archivos de configuración de Kubernetes (manifiestos YAML), cada uno de los cuales define un componente o servicio específico.

  1. Crea un Dockerfile con Gemma descargada previamente.

     FROM ubuntu
    
     # Install Ollama
     # This uses Ollamas official installation script, which adds Ollama to /usr/local/bin
     RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates
     RUN curl -fsSL https://ollama.com/install.sh -o install.sh
     RUN chmod +x install.sh
     RUN ./install.sh && \
         rm -rf /var/lib/apt/lists/*
    
     # Set environment variables for Ollama (optional, but good practice)
     ENV OLLAMA_HOST="0.0.0.0"
     # ENV OLLAMA_MODELS="/usr/local/ollama/models" # Default is /root/.ollama
     # If you want to customize the model storage path within the container, set OLLAMA_MODELS
     # and then ensure you create and populate that directory. Default is usually fine for pre-downloaded.
    
     # --- Predownload Gemma Model ---
     # This step starts Ollama server in the background, pulls the model,
     # and then kills the server to allow the Docker build to continue.
     # This approach works around Docker''s RUN command limitations for services.
    
     RUN ollama serve & \
         sleep 5 && \
         # Give the Ollama server a moment to start up
         # Use --retry and --retry-connrefused to handle startup delays
         curl --retry 10 --retry-connrefused -s http://localhost:11434 || true && \
         echo "Attempting to pull gemma:7b..." && \
         ollama pull gemma:7b && \
         echo "Model pull complete. Cleaning up background Ollama process." && \
         pkill ollama || true # Gracefully kill the ollama serve process
    
     # Expose Ollama's default port
     EXPOSE 11434
    
     # Command to run Ollama server when the container starts
     CMD ["ollama", "serve"]
    
    
  1. Compila la imagen de Docker y súbela al repositorio de Artifact Registry.

    docker build -t ollama-gemma .
    docker tag ollama-gemma REGISTRY_REPOSITORY_URL/ollama-gemma:latest
    docker push REGISTRY_REPOSITORY_URL/ollama-gemma:latest
    

    Reemplaza lo siguiente:

    • REGISTRY_REPOSITORY_URL con la URL del repositorio
  2. Crea un secreto para guardar las credenciales de Docker.

    
    export SECRET=DOCKER_REGISTRY_SECRET
    export DOCKER_TEST_CONFIG=~/.docker/config.json 
    kubectl --kubeconfig ${KUBECONFIG}$ create secret docker-registry ${SECRET} --from-file=.dockerconfigjson=${DOCKER_TEST_CONFIG} -n sandbox-gpu-project
    

    Reemplaza lo siguiente:

    • Nombre del Secret DOCKER_REGISTRY_SECRET.
  3. Crea un archivo ollama-deployment.yaml para definir la implementación del motor de IA de Ollama:

    La implementación del servidor de Ollama solicita una GPU.

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        annotations:
          deployment.kubernetes.io/revision: "9"
        name: ollama
        namespace: sandbox-gpu-project
      spec:
        progressDeadlineSeconds: 600
        replicas: 1
        revisionHistoryLimit: 10
        selector:
          matchLabels:
            app: ollama
        strategy:
          rollingUpdate:
            maxSurge: 25%
            maxUnavailable: 25%
          type: RollingUpdate
        template:
          metadata:
            creationTimestamp: null
            labels:
              app: ollama
              egress.networking.gke.io/enabled: "true"
          spec:
            containers:
              - name: ollama
                image: REGISTRY_REPOSITORY_URL/ollama-gemma:latest
                imagePullPolicy: Always
                ports:
                  - containerPort: 11434
                    protocol: TCP
                resources:
                  limits:
                    nvidia.com/gpu-pod-NVIDIA_H100_80GB_HBM3: "1"
                  requests:
                    nvidia.com/gpu-pod-NVIDIA_H100_80GB_HBM3: "1"
                env:
                  - name: OLLAMA_HOST
                    value: 0.0.0.0
                  - name: OLLAMA_ORIGINS
                    value: http://localhost:8080,http://ollama-webui.ollama-llm.svc.cluster.local:8080,http://ollama-webui:8080
                securityContext:
                  seLinuxOptions:
                    type: unconfined_t
                terminationMessagePath: /dev/termination-log
                terminationMessagePolicy: File
            imagePullSecrets:
            - name: DOCKER_REGISTRY_SECRET
            dnsConfig:
              nameservers:
                - 8.8.8.8
            dnsPolicy: ClusterFirst
            restartPolicy: Always
            schedulerName: default-scheduler
            terminationGracePeriodSeconds: 30
    
    

    Reemplaza lo siguiente:

    • REGISTRY_REPOSITORY_URL: Es la URL del repositorio.
    • DOCKER_REGISTRY_SECRET: Nombre del secreto.
  4. Crea el archivo ollama-service.yaml para exponer el servidor de Ollama de forma interna.

    apiVersion: v1
    kind: Service
    metadata:
      name: ollama
      namespace: sandbox-gpu-project
      annotations:
        metallb.universe.tf/ip-allocated-from-pool: lb-address-pool-0-ptleg
    spec:
      type: LoadBalancer
      selector:
        app: ollama
      ports:
        - port: 11434
          nodePort: 30450
      ipFamilyPolicy: SingleStack
      ipFamilies:
        - IPv4
      clusterIPs:
        - 10.1.122.216
      clusterIP: 10.1.122.216
    
  5. Aplica los manifiestos

    kubectl --kubeconfig ${KUBECONFIG} apply -f ollama-deployment.yaml
    kubectl --kubeconfig ${KUBECONFIG} apply -f ollama-service.yaml
    
  6. Asegúrate de que los pods de Ollama se estén ejecutando.

    kubectl --kubeconfig ${KUBECONFIG} get deployments -n sandbox-gpu-project
    kubectl --kubeconfig ${KUBECONFIG} get service -n sandbox-gpu-project
    
  7. Toma nota de la IP externa del servicio de Ollama OLLAMA_BASE_END_POINT del resultado.

    kubectl --kubeconfig ${KUBECONFIG} get service ollama \
          -n sandbox-gpu-project -o jsonpath='{.status.loadBalancer.ingress[*].ip}'
    
  8. Crea el archivo openweb-ui-deployment.yaml para implementar la interfaz de Open-WebUI.

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: ollama-webui
        namespace: sandbox-gpu-project
        labels:
          app: ollama-webui
        annotations:
          deployment.kubernetes.io/revision: "5"
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: ollama-webui
        strategy:
          type: RollingUpdate
          rollingUpdate:
            maxSurge: 25%
            maxUnavailable: 25%
        progressDeadlineSeconds: 600
        revisionHistoryLimit: 10
        template:
          metadata:
            labels:
              app: ollama-webui
            creationTimestamp: null
          spec:
            containers:
              - name: ollama-webui
                image: ghcr.io/open-webui/open-webui:main
                imagePullPolicy: IfNotPresent
                ports:
                  - name: http
                    containerPort: 8080
                    protocol: TCP
                env:
                  - name: OLLAMA_BASE_URL
                    value: OLLAMA_BASE_END_POINT
                  - name: PORT
                    value: "8080"
                terminationMessagePath: /dev/termination-log
                terminationMessagePolicy: File
            restartPolicy: Always
            dnsPolicy: ClusterFirst
            schedulerName: default-scheduler
            terminationGracePeriodSeconds: 30
    

    Reemplaza lo siguiente:

    • OLLAMA_BASE_END_POINT: Es la dirección IP externa del servicio de Ollama.
  9. Crea un archivo ollama-webui-service.yaml para exponer externamente la interfaz webui abierta.

    apiVersion: v1
    kind: Service
    metadata:
      name: ollama-webui
      namespace: sandbox-gpu-project
      annotations:
        metallb.universe.tf/ip-allocated-from-pool: lb-address-pool-0-ptleg
    spec:
      type: LoadBalancer
      ipFamilyPolicy: SingleStack
      ipFamilies:
      - IPv4
      clusterIPs:
      - 10.1.104.52
      clusterIP: 10.1.104.52
      ports:
      - port: 80
        targetPort: 8080
        nodePort: 32351
      selector:
        app: ollama-webui
    
  10. Aplica los manifiestos openweb-ui-deployment.yaml y ollama-webui-service.yaml al clúster.

        kubectl --kubeconfig ${KUBECONFIG} apply -f openweb-ui-deployment.yaml
        kubectl --kubeconfig ${KUBECONFIG} apply -f ollama-webui-service.yaml
    
  11. Crea una política de red del proyecto para permitir el tráfico entrante desde direcciones IP externas.

    kubectl --kubeconfig ${KUBECONFIG} apply -f - <<EOF
    apiVersion: networking.global.gdc.goog/v1
    kind: ProjectNetworkPolicy
    metadata:
      namespace: sandbox-gpu-project
      name: allow-inbound-traffic-from-external
    spec:
      policyType: Ingress
      subject:
        subjectType: UserWorkload
      ingress:
      - from:
        - ipBlock:
            cidr: 0.0.0.0/0
    EOF
    
  12. Ejecuta el siguiente comando para identificar la IP externa del servicio de Ollama. Toma nota de él para usarlo en pasos posteriores, en los que sustituirás este valor por OPEN_WEB_UI_ENDPOINT.

    kubectl --kubeconfig ${KUBECONFIG} get service -n sandbox-gpu-project
    
  13. Abre Google Chrome y, luego, ingresa la URL con la dirección IP externa que encontraste en el paso anterior. Ahora puedes interactuar con el modelo de Gemma a través de la interfaz de la IU web abierta.

    http://OPEN_WEB_UI_ENDPOINT/