Estoy tratando de usar Spark en el clúster de Kubernetes (configuración existente: emr + yarn). Nuestro caso de uso es manejar demasiados trabajos, incluidos los de corta duración (entre unos segundos y 15 minutos). Además, tenemos horas pico en las que muchos trabajadores necesitan correr para manejar cientos de trabajos que se ejecutan simultáneamente.
Entonces, lo que quiero lograr, ejecutar al maestro y fijar pocos trabajadores (digamos 5) todo el tiempo y aumentar los trabajadores a 40-50 en el momento pico. Además, preferiré usar la asignación dinámica.
Lo estoy configurando como se muestra a continuación.
Imagen maestra (chispa maestra: X)
FROM <BASE spark 3.1 Image build using dev/make-distribution.sh -Pkubernetes in spark> ENTRYPOINT ["/opt/spark/sbin/start-master.sh", "-p", "8081", "<A long running server command that can accept get traffic on 8080 to submit jobs>"]Imagen de trabajador trabajador (spark-worker:X)
FROM <BASE spark 3.1 Image build using dev/make-distribution.sh -Pkubernetes in spark> ENTRYPOINT ["/opt/spark/sbin/start-worker.sh", "spark//spark-master:8081" ,"-p", "8081", "<A long running server command to keep up the worker>"]Implementos
apiVersion: apps/v1 kind: Deployment metadata: name: spark-master-server spec: replicas: 1 selector: matchLabels: component: spark-master-server template: metadata: labels: component: spark-master-server spec: containers: - name: spark-master-server image: spark-master:X imagePullPolicy: IfNotPresent ports: - containerPort: 8081 --- apiVersion: v1 kind: Service metadata: name: spark-master spec: type: ClusterIP ports: - port: 8081 targetPort: 8081 selector: component: spark-master-server --- apiVersion: apps/v1 kind: Deployment metadata: name: spark-worker-instance spec: replicas: 3 selector: matchLabels: component: spark-worker-instance template: metadata: labels: component: spark-worker-instance spec: containers: - name: spark-worker-server image: spark-worker:X imagePullPolicy: IfNotPresent ports: - containerPort: 8081Preguntas
La razón por la que intentamos no crear maestro y controlador dinámicamente por trabajo (como se indica en el ejemplo: http://spark.apache.org/docs/latest/running-on-kubernetes.html ) es que puede ser una sobrecarga para grandes no . de pequeños trabajos.
¿Se recomienda esta configuración?
No lo creas.
La asignación dinámica de recursos es una propiedad de una sola aplicación Spark "para ajustar dinámicamente los recursos que ocupa su aplicación en función de la carga de trabajo".
La asignación dinámica de recursos abarca sus requisitos de recursos independientemente de los nodos disponibles en un clúster. Siempre que haya recursos disponibles y un administrador de clústeres pueda asignarlos a una aplicación Spark, estos recursos son gratuitos.
Lo que parece estar tratando de configurar es cómo escalar el clúster hacia arriba y hacia abajo. En su caso, es Spark Standalone y, aunque técnicamente es posible con ReplicaSets (solo una suposición), nunca escuché ningún intento anterior. Estás solo, ya que Spark Standalone no es compatible desde el primer momento.
Eso creo que es una exageración ya que está creando un entorno de clúster de múltiples capas: usar un administrador de clúster (Kubernetes) para alojar otro administrador de clúster (Spark Standalone) para aplicaciones Spark. Dado que Spark en Kubernetes es compatible con la asignación dinámica desde el primer momento, la única preocupación que debe tener es simplemente cómo "agregar" más CPU y memoria a pedido mientras cambia el tamaño del clúster de Kubernetes. Debe confiar en las capacidades de Kubernetes para cambiar su tamaño hacia arriba y hacia abajo en lugar de Spark Standalone en Kubernetes.
El operador Spark on k8s puede proporcionar al menos un mecanismo para aprovisionar dinámicamente los recursos que necesita para realizar un escalado seguro de recursos en función de la demanda.
https://github.com/GoogleCloudPlatform/spark-on-k8s-operator
Mi opinión es que, en lugar de realizar un envío de chispa directo a un maestro en un clúster de chispa estático, podría hacer una llamada a la API k8s para aprovisionar la instancia requerida; o, de lo contrario, defínalos como un cronograma cron.
En el escenario de aprovisionamiento dinámico, una cosa a considerar es cómo se distribuyen sus cargas de trabajo en el clúster; no podemos usar reglas simples de HPA para esto, ya que puede no ser seguro derribar a un trabajador en los niveles de CPU/Mem; generar un clúster separado para cada carga de trabajo bajo demanda evita esto, pero puede no ser óptimo. Me interesaría saber cómo te va.