Jean-Luc’s Blog

An IT Blog.

Starting Marathon [En]

Let’s start our first Marathon service and then present some common pitfalls in the troubleshooting section.

Basic setup

One can download Marathon directly from the website https://mesosphere.github.io/marathon/.

Let’s deploy Marathon in ~/apps/marathon-0.6.0

Starting the services

Start the marathon server:

1
cd ~/apps/marathon-0.6.0 && MESOS_NATIVE_LIBRARY='/usr/local/lib/libmesos.dylib' ./bin/start --master localhost:5050 --zk zk://localhost:2181/marathon

Check the services are ok:

Repository

To deploy the same application in multiple nodes, an easy way is a shared repository. Each version of the app and its dependencies must be available in the Deployment Repository.

Here is a simple structure for a Simple Web Service called SWS :

1
2
3
4
5
6
7
└── SWS
    ├── v1-first_revision
    │   └── spray-test-assembly-0.1.jar
    ├── v2-bug_included
    │   └── my_app_v1.1.jar
    └── v3-bug_fixed
        └── my_app_v1.2.jar

The easy step to deploy this repository:

1
2
3
git clone (**TODO : create a git repository **)
cd dm_app_repository
python -m SimpleHTTPServer

Check the repository is available: 

1
2
3
4
5
6
7
8
$ curl http://127.0.0.1:8000/SWS/
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
<title>Directory listing for /SWS/</title>
[]
<li><a href="v1-first_revision/">v1-first_revision/</a>
<li><a href="v2-bug_included/">v2-bug_included/</a>
<li><a href="v3-bug_fixed/">v3-bug_fixed/</a>
[]

Test the application locally:

1
2
curl -o spray-test-assembly-0.1.jar http://127.0.0.1:8000/SWS/v1-first_revision/spray-test-assembly-0.1.jar
java -jar spray-test-assembly-0.1.jar 8091

Open a browser at http://127.0.0.1:8091/, you should see an hello message.

Deploy with Marathon

We ready to start playing with Marathon. Let’s deploy our first app server with Marathon:

1
curl -X POST -H "Content-Type: application/json" -d '{ "id": "sws1", "cmd": "java -jar spray-test-assembly-0.1.jar $PORT", "mem": 256.0, "instances": 1, "uris": [ "http://127.0.0.1:8000/SWS/v1-first_revision/spray-test-assembly-0.1.jar" ]}' http://127.0.0.1:8080/v2/apps

We can access directly the service from Marathon console.

If we need to deploy a second instance:

  • go to marathon console at http://127.0.0.1:8080/, the console is displayed Marathon Console
  • click the scale button, the scale window is displayed Scale Window
  • select 2 instances and press OK, the marathon console is updated with 2 instances Marathon Console with 2 instances

Troubleshooting

task identifier does not support uppercase

Let’s use an UPPERCASE identifier (SWS1), starting the task with:

1
2
$ curl -X POST -H "Content-Type: application/json" -d '{ "id": "SWS1", "cmd": "java -jar spray-test-assembly-0.1.jar $PORT", "mem": 256.0, "instances": 1, "uris": [ "http://127.0.0.1:8000/SWS/v1-first_revision/spray-test-assembly-0.1.jar" ]}' http://127.0.0.1:8080/v2/apps
{"errors":[{"attribute":"id","error":"must match \”^(([a-z0-9]|[a-z0-9][a-z0-9\\-]*[a-z0-9])\\.)*([a-z0-9]|[a-z0-9][a-z0-9\\-]*[a-z0-9])$\""}]}%

OK, we should have been used sws1 as task indentifier.

repository is down when starting a task

(we have killed the repository, or the python server process in this case).

Start the task with:

1
2
curl -X POST -H "Content-Type: application/json" -d '{ "id": "sws3", "cmd": "java -jar spray-test-assembly-0.1.jar $PORT", "mem": 256.0, "instances": 1, "uris": ["http://127.0.0.1:8000/SWS/v1-first_revision/spray-test-assembly-0.1.jar"] }' http://127.0.0.1:8080/v2/apps
null%

“null%”, so no error. everything looks good. Right ? Hmm. No. Why is the task not started in the Marathon console ?  Unstarted task

If we have a look at Marathon console logs, no details: 

1
2
3
4
[2014-11-04 11:43:47,195] INFO Assigned some ports for sws3: [0] -> [15603] (mesosphere.marathon.MarathonSchedulerService:78)
[2014-11-04 11:43:47,365] INFO Starting app sws3 (mesosphere.marathon.MarathonScheduler:223)
[2014-11-04 11:43:47,371] INFO Need to scale sws3 from 0 up to 1 instances (mesosphere.marathon.MarathonScheduler:338)
[2014-11-04 11:43:47,371] INFO Queueing 1 new tasks for sws3 (0 queued) (mesosphere.marathon.MarathonScheduler:344)

If we look at mesos console, we can see that the Framework is staging and repetedly failing: Staging task

But if we have a look at the Failed task error log, it’s clearer:

1
2
3
4
5
6
WARNING: Logging before InitGoogleLogging() is written to STDERR
I1104 16:52:49.402339 37630720 fetcher.cpp:76] Fetching URI 'http://127.0.0.1:8000/SWS/v1-first_revision/spray-test-assembly-0.1.jar'
I1104 16:52:49.403532 37630720 fetcher.cpp:126] Downloading 'http://127.0.0.1:8000/SWS/v1-first_revision/spray-test-assembly-0.1.jar' to '/tmp/mesos/slaves/20141104-103858-16777343-5050-9421-0/frameworks/20140902-013203-16777343-5050-4471-0000/executors/sws3.a09d4717-643a-11e4-bf70-e0f84706f8b6/runs/4209c508-40b7-4660-8c15-6b8a1a5dbe23/spray-test-assembly-0.1.jar'
E1104 16:52:49.404134 37630720 fetcher.cpp:129] Error downloading resource: Couldn't connect to server
Failed to fetch: http://127.0.0.1:8000/SWS/v1-first_revision/spray-test-assembly-0.1.jar
Failed to synchronize with slave (it's probably exited)

So enable the repository and we finally get a running task:  Running task

Not providing the uris correctly

Marathon is expecting the parameter “uris”: [ “http://127.0.0.1:8000/SWS/v1-first_revision/spray-test-assembly-0.1.jar” ]. What happen if we try to use the following command:

1
curl -X POST -H "Content-Type: application/json" -d '{ "id": "sws2", "cmd": "java -jar spray-test-assembly-0.1.jar $PORT", "mem": 256.0, "instances": 1, "uri": "http://127.0.0.1:8000/SWS/v1-first_revision/spray-test-assembly-0.1.jar" }' http://127.0.0.1:8080/v2/apps

Marathon console shows the task is switching between STAGING and FAILED states.

When we check the framework error log:

1
2
3
I1104 17:08:07.138018 125543168 exec.cpp:132] Version: 0.20.0
I1104 17:08:07.139219 184311808 exec.cpp:206] Executor registered on slave 20141104-103858-16777343-5050-9421-0
Error: Unable to access jarfile spray-test-assembly-0.1.jar

When we check the Framework STDOUT:

1
2
3
4
5
Registered executor on 172.16.0.17
Starting task sws2.c368adc6-643c-11e4-bf70-e0f84706f8b6
sh -c 'java -jar spray-test-assembly-0.1.jar $PORT'
Forked command at 17152
Command exited with status 1 (pid: 17152)

No file is downloaded nor installed. The task is starting fine, but the java process terminates with status = 1 as the jarfile is not downloaded.

An invalid command

Let’s use the (in)famous blah command:

1
curl -X POST -H "Content-Type: application/json" -d '{ "id": "err", "cmd": "blah", "mem": 256.0, "instances": 1 }' http://127.0.0.1:8080/v2/apps

In the Mesos console we get

1
2
3
I1107 10:40:25.843163 2021741312 exec.cpp:132] Version: 0.20.0
I1107 10:40:25.844281 217133056 exec.cpp:206] Executor registered on slave 20141107-103704-16777343-5050-4138-0
sh: blah: command not found

There is another variant when we execute the task in another node : Marathon try to start the task with the same user as the current user having started the Marathon process. If it does not exist in the slave node, we get something like :

1
E0904 00:25:34.097573 147271680 slave.cpp:2484] Container 'c6d1a64f-1fd9-48e6-9fea-32bc794b508c' for executor 'webtest2.38a08eb7-33b9-11e4-b27e-e0f84706f8b6' of framework '20140902-013203-16777343-5050-4471-0000' failed to start: Failed to redirect stdout: Failed to chown: Failed to get user information for 'jlcanela': Undefined error: 0

Important:

  • Be sure you know how access the mesos logs : without them, you’re lost
  • Make sure you repository is accessible from all the nodes
  • Always use a “uris” : [ “url1” ] syntax.  
  • Always ensure the *nix accounts are created on all the slave nodes

Your First Mesos Command [En]

First setup the basic thing in local, and then run our first mesos command.

Basic setup

If you’re an OS X user, you can install according to the documentation http://mesosphere.com/docs/getting-started/developer/brew-install/ which is very didactic. http://mesosphere.com/docs/guides/ contains a lot of useful information.

So once it’s installed :

  • Zookeeper is installed and started

Starting the services

First, let’s check that Zookeeper is started:

1
jps | grep QuorumPeerMain

if no process is listed, please check your Zookeeper setup.

Start the mesos master:

1
/usr/local/sbin/mesos-master --registry=in_memory --ip=127.0.0.1

Start the mesos slave:

1
sudo /usr/local/sbin/mesos-slave --master=127.0.0.1:5050

Check the services are ok:

Start a simple mesos command

Let’s execute a simple ls command

1
mesos execute --master=127.0.0.1:5050 --name=Command --command="ls"

Where to find logs

Then go to the Mesos console and click on Framework.

The Framework view is displayed: Mesos Framework View

Then click in the Terminated framework link like …5050-9877-0000.

The Framework detail is displayed: Mesos Framework Detail

Then click the sandbox link. The sandbox window is opened: Sandbox window

Click the stdout link, the following log is displayed:

1
2
3
4
5
6
7
8
9
10
11
12
13
Registered executor on 172.16.0.17
Starting task Command
sh -c 'ls'
Forked command at 10500
stderr
stdout
Command exited with status 0 (pid: 10500)
Shutting down
Sending SIGTERM to process tree at pid 10500
Killing the following process trees:
[

]

Important : the mesos console is your best friend, when something is wrong, always try to puzzle out the error logs accessible through the mesos framework view.

Web Service Deployment in 2014 [En]

Here are some thoughts about deploying a web service or a web application today, in 2014.

Let’s consider some expectations for the following roles:

  • client : he expects the service to be reliable
  • provider : he requires ease of deployment, ease of testing & maintenance

Reliability

The 3 top issues are : 

  • service is not available (network) : we have to continuously check the service is available and fix the issue immediately. It can be a permanent or temporary network availability issue.
  • service is slow or is returning errors : errors must be automatically detected, sysadmin must be notified immediately to take action
  • service is returning incorrect result : current version of the service must have been validated by a QA team

Ease of deployment

For the service to be easy to deploy:

  • deployment is done via a single deploy command
  • deployment can made partially
  • constant checking is done during deployment
  • it’s always possible to come back
  • deploy a server farm is as simple as deploying a single server

Ease of testing and no-longer-painful maintenance

Let’s imagine that:

  • service execution data are collected and processed in realtime
  • execution data is automatically analysed
  • servers are automatically switched when necessary
  • it’s easy to add new servers when service load is increasing

I’m preparing a serie of article about Mesos / Marathon. This platform, maybe, is a good opportunity to move in this direction.

Quel Avenir Pour Scala ? N’est Pas La Question. [FR]

J’ai été tenté d’écrire un article sur les incroyables capacités et potentiel du langage scala et de son écosystème. Quel que soit l’article vantant les mérites de telle ou telle technologie, que ce soit de la lessive, une voiture, le C++ et maintenant scala, on retrouve à peu prés les mêmes éléments marketing :« Performant » « Puissant » « Efficace » « Bla bla bla ».

La technologie

Lorsque l’on compare les différents langages, les différentes technologies, l’efficacité / performance varie souvent d’un facteur 3. En effet, l’accompagnement au changement, comme par exemple la formation, la migration logicielle, les changements dans les process de développement, etc, sont couteux et font que ce type de solution est difficilement maitrisable.

Ce n’est qu’en cas de saut technologique que ce facteur peut être largement supérieur - je ne parle pas des dépliants publicitaires bien sûr -.

Sommes nous bloqués là ?

Quel est l’objectif réel lorsqu’on choisit une nouvelle technologie ? La raison est souvent : « déveloper plus vite ». Et pourquoi déveloper plus vite ? Pour livrer plus vite.

L’équipe

Livrer plus vite. Une solution est d’utiliser une équipe plus compétente ou mieux formée:

  • la recette idéale entre le meilleur ratio développeurs-seniors (+cher) et développeurs-juniors (moins-chers) est toujours en préparation;
  • le consensus est plutôt de bien maitriser la croissance de l’équipe et le « team building »;
  • la citation « neuf femmes ne font pas un bébé en un mois » est toujours d’actualité.

En fonction de l’expérience, les développeurs vont choisir des solutions plus ou moins adaptées. La variabilité constatée est d’au moins entre 1 et 10, voire plus …

Livrer plus vite c’est bien, mais livrer quoi, telle est la question … ?

Livrer, c’est quoi ?

Il faut faire la différence entre:

  • ce qui est livré : « la fonctionalité »;
  • celui qui l’utilise : l’utilisateur;
  • celui qui paye : l’acheteur.

L’acheteur paye pour livrer la fonctionnalité à l’utilisateur.

Voici ce qui peut arriver:

  • peu de livraisons ou peu d’utilisateur = faible nombre de transactions
  • valeur ajoutée fournie par la fonctionalité trop faible = transactions de faible montant
  • pas d’acheteur = pas de paiement

La valeur ajoutée est déterminée en fonction du service rendu, et non pas en fonction du coût de production. Celle-ci pourrait concerner par exemple l’augmentation des revenus, la projection de la marque ou la rétention des clients.

L’organisation

Imaginons une organisation dont le contexte est le suivant:

  • 1.000.000 de clients, en constant renouvellement;
  • le coût du service est de 30€ / mois

Considérons une fonctionalité de rétention des clients:

  • rétention de 5.000 clients / mois;
  • bénéfice attendu = 150 k€ / mois
  • coût de développement négligeable = 10j de développeur
  • délai de livraison = 1 mois

L’organisation dispose de plusieurs paramètres pour optimiser son développement. Les voici ordonnée par impact financier:

  • sélection de la bonne fonctionnalité
  • réduction du délai de livraison - hypothèse de « déploiement continu » -
  • réduction du coût de développement

On saisit rapidement l’impact des projets organisés autour de l’optimisation de la livraison de valeur ajoutée. La stratégie est tout simplement de commencer la livraison de la valeur ajoutée la plus élevée en premier.

On peut évaluer, au minimum, une différence de productivité (financiaire) de 1 à 100 entre les organisations qui tirent profit de ce type d’optimisations et les autres.

Et scala dans tout ça ?

Développer, en scala ou dans quelque langage que ce soit, ne me parait être en aucune façon une garantie de succès. L’impact de l’organisation sur le succès ou l’échec d’un projet me parait bien supérieur:

Impact de l’organisation : 1 à 100; Impact des équipes : 1 à 10; Impact des technologies : 1 à 3. Si pour vous « retrospective meeting » ne rime pas avec itération, les méthodes agiles peuvent vous apporter un vrai plus dans votre productivité quotidienne.

Si pour vous un « retrospective meeting » est indispensable après chaque itération; je vous fais totalement confiance car au final vous avez obtenu votre organisation avec les bonnes personnes, les bons profils, et les bonnes technologies. D’ailleurs, vous avez déjà décidé sur le fait d’utiliser Scala ou non, n’est-ce pas ?

CQFD : « Quel avenir pour Scala ? » n’est pas la question.