• les dernières technologies innovantes en cours de développement ou en phase de lancement sur le marché.
  • les critiques de produits technologiques populaires, tels que les téléphones intelligents, les ordinateurs portables, les tablettes, les écouteurs, les caméras, etc.
  • des conseils sur la façon de rester en sécurité en ligne, notamment en ce qui concerne la protection de la vie privée, la sécurité des données et la prévention des escroqueries en ligne.
  • les dernières nouvelles et mises à jour dans le monde de la technologie, y compris les fusions et acquisitions, les partenariats, les changements de direction, etc.

lundi 20 mai 2024

Streamlining MLflow Deployment on Kubernetes with Local Storage


Configuring Persistent Storage

In the realm of MLOps, the combination of Kubeflow and MLflow stands out as a powerful duo, empowering data scientists and engineers with a comprehensive platform for managing machine learning workflows. To enhance this synergy, let's delve into deploying MLflow on Kubernetes with a focus on utilizing local storage for enhanced efficiency and reliability.

Persistent Storage Configuration


apiVersion: v1
kind: PersistentVolume
metadata:
  name: mlflow-pv
  namespace: mlflow
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: mlflow-storage
  hostPath:
    path: /mnt/data/mlflow

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mlflow-pvc
  namespace: mlflow
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: mlflow-storage
  resources:
    requests:
      storage: 10Gi
    

Deploying MLflow Service

With storage in place, we proceed to deploy the MLflow service. Our deployment configuration ensures seamless integration with Kubernetes, utilizing the defined PVC for data storage.

MLflow Service Deployment Configuration


apiVersion: apps/v1
kind: Deployment
metadata:
  name: mlflow-deployment
  namespace: mlflow
  labels:
    app: mlflow
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mlflow
  template:
    metadata:
      labels:
        app: mlflow
    spec:
      automountServiceAccountToken: false
      serviceAccountName: mlflow-sa
      containers:
        - name: mlflow
          image: ghcr.io/mlflow/mlflow:v2.2.1
          imagePullPolicy: Always
          command: ["/bin/bash", "-c", "mlflow server --host 0.0.0.0"]
          ports:
            - containerPort: 5000
          resources:
            requests:
              memory: "512Mi"
              cpu: "100m"
            limits:
              memory: "1Gi"
              cpu: "1"
          volumeMounts:
            - name: mlflow-storage
              mountPath: /mnt/mlflow
      volumes:
        - name: mlflow-storage
          persistentVolumeClaim:
            claimName: mlflow-pvc
    

Integrating with Kubeflow's Central Dashboard

To seamlessly integrate MLflow into Kubeflow's ecosystem, we configure a VirtualService and update the central dashboard to include an MLflow tab. This enables users to access MLflow's features directly from Kubeflow's centralized interface.

VirtualService Configuration


apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: mlflow
  namespace: mlflow
spec:
  gateways:
    - kubeflow/kubeflow-gateway
  hosts:
    - "*"
  http:
    - match:
        - uri:
            prefix: /mlflow/
      rewrite:
        uri: /
      route:
        - destination:
            host: mlflow-service.mlflow.svc.cluster.local
            port:
              number: 5000
    

Modifying Kubeflow Central Dashboard ConfigMap

Additionally, we need to modify the configmap of centraldashboard for Kubeflow to include the MLflow tab. This ensures that users have easy access to MLflow's functionalities from within Kubeflow's central dashboard.


kubectl edit cm centraldashboard-config -n kubeflow
# add this under the other menu items
{
  "type": "item",
  "link": "/mlflow/",
  "text": "MlFlow",
  "icon": "icons:cached"
}

With these configurations in place, MLflow seamlessly integrates into Kubeflow's ecosystem, enriching the platform with robust experiment tracking and management capabilities. This holistic approach ensures smooth collaboration and enhanced productivity for MLOps practitioners leveraging Kubernetes and MLflow.

jeudi 16 mai 2024

Les Nouveautés de Java 21


Java 21 est enfin disponible ! En plus d'être une version LTS (Long Term Support), elle regorge d'innovations. Vous êtes un peu perdu ? Explorons ces nouveautés ensemble.

Nouveautés de l'API

Ces fonctionnalités sont immédiatement utilisables dans Java 21.

Collections Séquencées (JEP 431)

Un rafraîchissement bienvenu de l'API Collection ! La gestion des collections ordonnées est enfin là. Trois nouvelles interfaces sont ajoutées :

  • SequencedCollection
  • SequencedSet
  • SequencedMap

Ces interfaces fournissent des méthodes cohérentes pour manipuler ou ajouter des éléments en début ou en fin de collection.

Illustration des Collections Séquencées

Notez que ArrayList, qui implémentait déjà List, est maintenant aussi une SequencedCollection.

Pattern pour les Records (JEP 440)

Initialement en preview, cette fonctionnalité est maintenant officielle, permettant de déconstruire un record pour accéder directement à ses composants. Par exemple :

record Point(int x, int y) {}

if (o instanceof Point(int a, int b)) {
    int sum = a + b;
}

Cela fonctionne aussi dans les instructions switch :

int sum = switch (o) {
    case Point(int a, int b) -> a + b;
    default -> 0;
};

Threads Virtuels (JEP 444)

Très attendue, cette fonctionnalité est enfin stable ! Pour plus de détails, vous pouvez consulter mon article précédent.

Autres ajouts

Quelques autres nouveautés intéressantes :

  • Gestion des emojis avec Character.isEmoji()
  • StringBuilder.repeat() pour répéter une chaîne de caractères
  • HttpClient implémente AutoCloseable et peut être utilisé dans un bloc try-with-resources

Nouveautés en Preview

Ces fonctionnalités ne sont pas activées par défaut. Pour les utiliser, ajoutez les options de compilation :

--release 21 --enable-preview

et pour l'exécution :

--enable-preview

Modèles de Chaînes (JEP 430)

Permet d'intégrer des expressions dans les chaînes de caractères avec interpolation. Par exemple :

String str = "World";
String result = STR."Hello \{str}";

Utilisez la notation \{expression} et un Processor comme STR pour traiter l'interpolation. Le JDK inclut trois Processors par défaut :

  • RAW : Pas d'interpolation
  • STR : Concatène les chaînes
  • FMT : Formatte les chaînes en utilisant un formateur

Vous pouvez également créer votre propre Processor en implémentant l'interface StringTemplate.Processor.

Variables et Patterns Anonymes (JEP 443)

Parfois, il est nécessaire de déclarer une variable sans l'utiliser. Cette fonctionnalité permet d'utiliser le caractère '_' (underscore) pour ces cas. Par exemple :

for (Element _ : elements) {
    // Bloc qui n'utilise pas les éléments
}

var _ = mySet.remove(myObject);

try {
    int i = Integer.parseInt(str);
} catch (NumberFormatException _) {
    logger.warn("Not a number");
}

Map> employees = new HashMap<>();
employees.computeIfAbsent(id, _ -> new ArrayList<>());

Cela fonctionne aussi avec le pattern matching :

if (object instanceof Point(int _, int y)) {
    // ...
}

int result = switch (obj) {
    case Point(int x, int _) -> x;
};

Classes et Méthodes Main Sans Nom (JEP 445)

Pour simplifier l'apprentissage de Java, cette fonctionnalité permet de créer des classes sans nom avec une méthode main simplifiée. Par exemple, au lieu de :

public class HelloWorld { 
    public static void main(String[] args) { 
        System.out.println("Hello World!");
    }
}

On peut écrire :

class HelloWorld { 
    void main() { 
        System.out.println("Hello World!");
    }
}

Ou même :

void main() { 
    System.out.println("Hello World!");
}

Les classes sans nom simplifient l'écriture de la méthode main, facilitant l'apprentissage de Java.

Conclusion

Java 21 apporte une série d'améliorations et de nouvelles fonctionnalités visant à rendre le langage plus moderne, performant et facile à utiliser. Avec le pattern matching, les records améliorés, la nouvelle API FFM, les threads virtuels et les valeurs à portée, cette version offre des outils puissants pour les développeurs cherchant à écrire du code plus propre, plus efficace et plus sûr. Les améliorations continues de la sécurité et des performances font de Java 21 une mise à jour incontournable pour les développeurs et les entreprises utilisant cette plate-forme pour leurs applications critiques.

mercredi 8 mai 2024

Intégration de l'architecture hexagonale dans un projet Quarkus avec des exemples Java



L'architecture hexagonale, également connue sous le nom de portes et adaptateurs ou architecture en oignon, est un modèle de conception logicielle qui favorise la séparation des préoccupations et la facilité de testabilité. En mettant l'accent sur la dépendance inverse, elle permet de créer des systèmes hautement modulaires et évolutifs. Dans cet article, nous explorerons comment intégrer l'architecture hexagonale dans un projet Quarkus en utilisant des exemples concrets en Java.

Comprendre l'architecture hexagonale

L'architecture hexagonale repose sur le principe de séparation des préoccupations en divisant l'application en trois couches principales : le domaine, les adaptateurs et l'infrastructure.

  • Le domaine représente le cœur métier de l'application, il contient les entités, les règles métier et les services.
  • Les adaptateurs, également appelés ports, sont les points d'entrée et de sortie de l'application. Ils permettent d'interagir avec le domaine en fournissant des interfaces pour les entrées (ports primaires) et les sorties (ports secondaires).
  • L'infrastructure est responsable de la mise en œuvre des adaptateurs. Elle comprend les bases de données, les API externes, les frameworks, etc.

Intégration de l'architecture hexagonale dans Quarkus

Quarkus est un framework Java open source conçu pour créer des applications cloud natives. Il offre une prise en charge de premier ordre pour les conteneurs, la réactivité et le développement rapide. Intégrer l'architecture hexagonale dans un projet Quarkus peut être réalisé en suivant quelques principes de conception simples.

Création du domaine

Commençons par définir le domaine de notre application. Supposons que nous construisons une application de gestion de tâches. Nous pouvons avoir des entités telles que Task, User, et des services comme TaskService qui implémentent la logique métier.


public class Task {
    private String id;
    private String title;
    private boolean completed;
    // Getters and setters
}

public interface TaskService {
    Task createTask(String title);
    Task markTaskAsCompleted(String taskId);
    List<Task> getAllTasks();
    // Other business methods
}
    

Implémentation des adaptateurs

Les adaptateurs fournissent des interfaces pour interagir avec le domaine. Dans notre exemple, nous pourrions avoir des adaptateurs pour interagir avec une base de données, une API REST, ou toute autre source de données.


@ApplicationScoped
public class TaskRepository implements TaskService {
    @Transactional
    public Task createTask(String title) {
        // Logic to persist task in database
    }

    @Transactional
    public Task markTaskAsCompleted(String taskId) {
        // Logic to mark task as completed in database
    }

    @Transactional
    public List<Task> getAllTasks() {
        // Logic to retrieve all tasks from database
    }
    // Other database interactions
}
    

Configuration de l'infrastructure

Dans Quarkus, la configuration de l'infrastructure peut être réalisée en utilisant les fonctionnalités natives de Quarkus pour la persistance des données, les appels REST, etc.


@QuarkusTest
public class TaskResourceTest {

    @Inject
    TaskService taskService;

    @Test
    public void testCreateTask() {
        // Test logic to create task via REST API
    }

    @Test
    public void testMarkTaskAsCompleted() {
        // Test logic to mark task as completed via REST API
    }

    @Test
    public void testGetAllTasks() {
        // Test logic to get all tasks via REST API
    }
}
    

Conclusion

En utilisant l'architecture hexagonale dans un projet Quarkus, nous pouvons créer des applications bien structurées, modulaires et faciles à tester. En séparant clairement le domaine des adaptateurs et de l'infrastructure, nous obtenons une meilleure maintenabilité et évolutivité de notre code. En combinant la flexibilité de Quarkus avec les principes de conception solides de l'architecture hexagonale, nous pouvons construire des applications Java robustes pour répondre aux besoins métier les plus exigeants.