Partage de minutes fail

Hello,

allez, un petit pour la route, tout frais d’hier soir.

Je dois upgrader Harbor en dernière version, via chart Helm.

Après un helm diff upgrade, je remarque qu’il y a beaucoup de changements… modification des values pour corriger cela (cf harbor-helm/Upgrade.md at master · goharbor/harbor-helm · GitHub)

Maintenant tout semble OK, j’ai bien mes backups au cas où, l’upgrade s’est bien passée en environnement de pré-prod.

Vient le moment de l’upgrade:

  • Tout se passe “presque” bien…
  • Les pods redémarrent, la BDD migre, postgres démarre OK
  • Bizarrement les applis n’arrivent pas à contacter la BDD, les bases “registry” and co sont inexistantes !!

A priori, le volume persistant qui héberge la BDD est trop juste, mais pas suffisamment pour remonter un alerte avant l’upgrade. Donc harbor/pg a tenter l’upgrade de la BDD, s’est foiré, a perdu les data. Youpi \m/

Obligé alors de sortir la restauration velero (sur un autre cluster “juste” pour avoir le dump de la bdd).
Manque de bol, coupure réseau lors de la restauration, je suis un peu fatigué, je refais, entrées en double dans la BDD, au redémarrage les applis se foirent de partout !
Biensur, un kubectl copy ne fonctionne pas pour faire le dump en local car les conteneurs postgres n’ont pas tar. Obligé de monter le volume via un autre pod pour la copy/restauration.

Les alertes commencent à tomber, sur les cronjobs qui pull régulièrement les images docker, oh joie…

On se calme, il est tard, je fais qq manips, au bout du compte la restauration est OK, les pods redémarrent, je vais pouvoir me coucher, et les utilisateurs le lendemain n’auront vu que du feu !

Bilan de l’intervention:

  • toujours faire un backup de la BDD, mais ça tout le monde le sait (sauf ceux qui ont un peu trop confiance en eux)
  • vérifier l’état des volumes persistants, qu’ils soient pas “juste” en taille pour éventuellement permettre un dump.

Allez, on se décourage pas, ce soir j’enchaine avec GitLab :smiley:

Edit: upgrade GitLab est passée sans encombres !

2 « J'aime »

que la force soit avec toi !

Merci pour le partage et surtout d’avoir pris le temps de faire un bout de code qui reproduit le problème.

Pour ma part, j’ai mis environs 10 minutes à trouver le problème, et j’apprends quelque chose sur la syntaxe python.

C’est le moins qu’on puisse dire.

1 « J'aime »

@thierry.f.78, merci pour ce retour très cool.

1 « J'aime »

Alors comme tu le sais probablement je suis un énorme fan de Rust, donc j’ai tendance à être plutôt d’accord avec toi.

Ton commentaire m’a donné une idée, à partir de python 3.5, il y a les type hints pour définir du typage optionnel: PEP 484 – Type Hints | peps.python.org.
Bref qu’est ce que ça donne si j’ajoute du typage ?

Le code avec du typage (pas partout):

# bug.py
from datetime import datetime, timezone
import unittest
from typing import Dict, List, Any

class Share():
    instance_uuid = None
    share_id = None
    status = None
    tag = None
    export_location = None
    share_proto = None


def map_to_share_object(share: Share,
                        fields: List[str],
                        db_share: Dict[str, Any]):
    for field in fields:
        setattr(share, field, db_share[field])

def main()->None:
    NOW = datetime.now(timezone.utc)
    share = Share()

    fake_db_share = {
        'created_at': NOW,
        'updated_at': None,
        'deleted_at': None,
        'deleted': False,
        "id": 1,
        "instance_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",

        "share_id": "e8debdc0-447a-4376-a10a-4cd9122d7986",
        "status": "attaching",
        "tag": "e8debdc0-447a-4376-a10a-4cd9122d7986",
        "export_location": "10.0.0.50:/mnt/foo",
        "share_proto": "NFS",
    },

    fake_instance = {
        "instance_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
        "instance_flavor": "tiny"
    }

    map_to_share_object(share,
              [
                  "instance_uuid",
                  "share_id",
                  "status",
                  "tag",
                  "export_location",
                  "share_proto"
              ],
              fake_db_share)

    test = unittest.TestCase()
    test.assertEqual(share.instance_uuid,
                     'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa')
    test.assertEqual(share.share_id,
                     'e8debdc0-447a-4376-a10a-4cd9122d7986')
    test.assertEqual(share.status,
                     'attaching')
    test.assertEqual(share.tag,
                     'e8debdc0-447a-4376-a10a-4cd9122d7986')
    test.assertEqual(share.export_location,
                     '10.0.0.50:/mnt/foo')
    test.assertEqual(share.share_proto,
                     'NFS')


if __name__ == '__main__':
    main()

Ensuite je lance mypy pour faire l’analyse statique:

 🦉 rribaud  ~  workspace  bug  mypy bug.py 
bug.py:54: error: Argument 3 to "map_to_share_object" has incompatible type "Tuple[Dict[str, Union[str, int, bool, datetime, None]]]"; expected "Dict[str, Any]"
Found 1 error in 1 file (checked 1 source file)

AMHA, c’est quand même mieux.

  1. Déja on trouve le problème pas au runtime. A contrario sans le typage, si le code n’est pas éxécuté, on ne voit pas le problème. (d’ou l’importance encore plus grande des tests et de la couverture)
  2. Ca donne une information plus précise sur l’origine du problème. On sait que le soucis vient de l’argument 3.
  3. Ca “autodocumente” le code grace à la signature de la fonction.
1 « J'aime »

@remi, faut venir nous parler de ça lors d’une prochaine session de la libre antenne sur le sujet. :wink:
En + comme c’est du K8s, je suis sur que ça va intéresser plein de personnes.

1 « J'aime »

Je comprends par cette phrase que le typage de python doit être vérifié par un programme qui n’est pas python, mais qui est mypy ?

A l’occase faudra que je passe, la vie est remplie d’échecs :stuck_out_tongue:

1 « J'aime »

@thierry.f.78, oui c’est ça.

  • Python àpartir de 3.5 va accepter la syntaxe pour définir les types.
  • Par ailleurs tu vois qu’il faut un module typing pour définir les types plus complexes que string, int, etc…
  • Et effectivement un programme externe mypy qui fait la vérification. Il y a pleins d’integrations pour les éditeurs/IDEs histoire de voir les résultats dans l’éditeur/IDE et que se soit “transparent”.
1 « J'aime »

Le typing python est une vrai transformation du langage et là où les tests étaient ton seul salut, désormais le typing vient faire le job.

Oui le typing aide. Après ne laisse pas croire qu’il ne faut plus faire de tests. :stuck_out_tongue_winking_eye:

Non bien sur!
Mais certain tests deviennent redondant avec le typing, et c’est plus simple de déclarer des type que de créer un cas de test

a discuter dans le prochain numéro : Atlassian a effacé les environnements cloud de 400 clients par erreur

1 « J'aime »

Sans spoiler ça va arriver, @erwan va nous parler de ce sujet. :wink:

2 « J'aime »

Attention je ne suis pas le responsable pour atlassian :sweat_smile:

2 « J'aime »

Un potentiel sujet chez Heroku?

1 « J'aime »

Vanta (service qui aide à passer les audits de sécurité comme SOC2) a temporairement mélangé des données entre ces comptes clients (uniquement des noms de channels Slack).
En soit ce n’est pas trop critique comme fuite mais c’est assez trivial de devoir déclarer un incident de sécurité dans l’outils de suivi d’incident de sécurité.

Today Vanta became aware of a bug that caused channel names from some Slack workspaces to be temporarily available to another customer in the autocomplete dropdown of their notification settings page.

We deployed a fix 1 hour and 10 minutes after being made aware of the issue. After a comprehensive review of our logs, we believe your account was affected.

du coup d’accord 1h 10 ça va, top réactivité mais à la fin de l’email qui est hyper long … ça parle du bug et du cache résiduel We do not store this list long term, but we do cache the list for 30 seconds in Redis. bon là encore 30 seconds d’accord. Puis arrive la partie Forensics

With an understanding of the bug, we were able to review our logs from the time this bug was introduced on February 24, 2022 until the time it was fixed on April 27, 2022 for any instances where it’s possible that a customer was shown the incorrectly cached results from another Vanta account.

Ah oui quand même, donc en fait 2 mois donc :slight_smile: Et le message continue avec Response Timeline qui reprend uniquement les 1h10 du fix :slight_smile:

Mais en soit ça respecte la SLA qui se déclenche au moment où c’est découvert, reste à savoir si ils ont communiqué quand ils l’ont trouvé ou bien quand le planning permettait un fix rapide…

Oui sauf que Python ne check pas les types, c’est juste un indication:

Note
The Python runtime does not enforce function and variable type annotations. They can be used by third party tools such as type checkers, IDEs, linters, etc.

Au même titre que les tests… si tu ne lancent pas ils ne sont pas utiles :wink: