[LINUX] Comment créer un agent de ressources compatible OCF

Je souhaite gérer ma propre application dans un cluster avec Pacemaker

Vous pouvez facilement le créer en lisant le Guide du développeur de l'agent de ressources OCF, mais comme la quantité de texte est importante, "quelque chose qui fonctionne pour le moment" Pour les personnes qui veulent réussir.

Notions de base OCF

OCF est une abréviation pour OpenCluster Framework, qui définit l'interface pour les applications de clustering. Les gestionnaires de cluster tels que Pacemaker, qui gère les clusters, gèrent les applications gérées et les adresses IP virtuelles en tant que «ressources». Pacemaker commande aux ressources de démarrer, d'arrêter, de migrer, de promouvoir en maître, de rétrograder en esclave, etc. Vous pouvez mettre en cluster vos propres applications à l'aide de Pacemaker en créant un programme compatible OCF avec un logiciel de gestion de cluster tel que Pacemaker et l'interface entre les ressources. Le but de cette fois est de créer moi-même cet agent de ressources.

Plus précisément, le logiciel de gestion de cluster compatible OCF lance l'agent de ressources en mettant une action à entreprendre dans la variable d'environnement $ __ OCF_ACTION. Les actions incluent le démarrage / l'arrêt / la migration / la promotion vers le maître / la rétrogradation vers l'esclave, et certaines actions nécessitent une définition et d'autres pas (facultatif). Les fichiers d'exécution sont lancés lors du contrôle des ressources. Ce fichier exécutable est appelé un agent de ressources et gère en fait le fonctionnement des ressources. L'agent de ressources examine la variable d'environnement $ __ OCF_ACTION et agit pour effectuer réellement cette action. Si des paramètres sont requis pour chaque action, ils sont passés dans une variable d'environnement préfixée par $ OCF_RESKEY. Tant que le format du fichier d'exécution répond aux exigences de l'API d'OCF, il n'y a aucune restriction sur le langage, etc., mais il semble qu'il soit généralement implémenté par un script shell.

L'agent de ressources le plus simple

Le code conforme OCF le plus simple

sample-resource


#!/bin/sh

#Initialize
: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/resource.d/heartbeat}
. ${OCF_FUNCTIONS_DIR}/.ocf-shellfuncs

RUNNING_FILE=/tmp/.running

sample_meta_data() {
    cat << EOF
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="sample-resource" version="0.1">
    <version>0.1</version>
    <longdesc lang="en">sample resource</longdesc>
    <shortdesc lang="en">sample resource</shortdesc>
    <parameters>
    </parameters>
    <actions>
        <action name="meta-data" timeout="5" />
        <action name="start" timeout="5" />
        <action name="stop" timeout="5" />
        <action name="monitor" timeout="5" />
        <action name="validate-all" timeout="5" />
    </actions>
</resource-agent>
EOF
    return $OCF_SUCCESS
}

sample_validate(){
    return $OCF_SUCCESS
}

sample_start(){
    touch ${RUNNING_FILE}
    return $OCF_SUCCESS
}

sample_stop(){
    rm -f ${RUNNING_FILE}
    return $OCF_SUCCESS
}

sample_monitor(){
    if [ -f ${RUNNING_FILE} ];
    then
        return $OCF_SUCCESS
    fi
    return $OCF_NOT_RUNNING
}

sample_usage(){
    echo "Test Resource."
    return $OCF_SUCCESS
}

# Translate each action into the appropriate function call
case $__OCF_ACTION in
meta-data)      sample_meta_data
                exit $OCF_SUCCESS
                ;;
start)          sample_start;;
stop)           sample_stop;;
monitor)        sample_monitor;;
validate-all)   sample_validate;;
*)              sample_usage
                exit $OCF_ERR_UNIMPLEMENTED
                ;;
esac

Initialisation

C'est une magie qui est également décrite dans le Guide du développeur de l'agent de ressources OCF.

#Initialize
: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/resource.d/heartbeat}
. ${OCF_FUNCTIONS_DIR}/.ocf-shellfuncs

Mettre en œuvre les actions requises

Voici les actions qui doivent être mises en œuvre. En dehors de cela, il est traité comme une option, définissons donc les actions suivantes pour le moment.

Des valeurs de retour appropriées doivent être renvoyées lorsque chaque action est effectuée. La valeur de retour est définie dans OCF.

Variables d'environnement utilisées dans l'agent de ressources

Décrit les variables d'environnement à utiliser avant d'entrer dans la définition concrète de chaque action requise.

Variable $ __ OCF_ACTION

Contient le traitement demandé à l'agent de ressources et est défini lorsque l'agent de ressources est appelé. L'agent de ressources lit d'abord cette variable d'environnement et distribue chaque action.

Exemple d'implémentation Guide du développeur de l'agent de ressources OCF

case $__OCF_ACTION in
meta-data)      sample_meta_data
                exit $OCF_SUCCESS
                ;;
start)          sample_start;;
stop)           sample_stop;;
monitor)        sample_monitor;;
validate-all)   sample_validate;;
*)              sample_usage
                exit $OCF_ERR_UNIMPLEMENTED
                ;;
esac
Nom du paramètre $ OCF_RESKEY_

Une variable qui contient les paramètres définis lors de la création de la ressource. Il n'est pas utilisé dans cet exemple, mais il est utilisé lors de la mise en cluster du démon de serveur TCP décrit plus loin.

meta-data Les métadonnées fournissent des informations de base sur l'agent de ressources, telles que le nom de l'agent de ressources, les actions qu'il fournit et les paramètres qu'il peut recevoir. Écrit en XML, l'agent de ressources renvoie les métadonnées dans la sortie standard sur demande.

start Implémentez le processus de démarrage des ressources. Plus précisément, écrivez le script de démarrage du démon. Cette fois, le démon réel ne sera pas démarré et seul un certain fichier sera créé. Si le démarrage réussit, il renvoie $ OCF_SUCCESS.

stop Mettre en œuvre l'arrêt des ressources. Décrit l'arrêt du démon. Cette fois, nous supprimerons le fichier créé par start.

S'il n'y a pas de problème avec l'arrêt du traitement, $ OCF_SUCCESS est renvoyé. (Notez que ce n'est pas $ OCF_NOT_RUNNING)

Notez que l'action d'arrêt signifie "arrêt forcé" de la ressource. Même si la ressource ne peut pas être arrêtée en toute sécurité, c'est une action pour l'arrêter quand même. Si l'action d'arrêt échoue, elle peut entraîner des problèmes fatals et le gestionnaire de cluster peut effectuer une séparation des nœuds (isolation, telle qu'un arrêt forcé). L'action d'arrêt doit utiliser tous les moyens possibles pour arrêter une ressource et ne renvoyer un code d'erreur que si l'arrêt échoue toujours.

monitor Implémentez le processus pour obtenir l'état de la ressource. S'il est en cours d'exécution, il renvoie $ OCF_SUCCESS, et s'il n'est pas en cours d'exécution, il renvoie $ OCF_NOT_RUNNING. S'il y a une erreur, la constante d'erreur appropriée commençant par $ OCF_ERR_ est renvoyée en fonction du contenu de l'erreur.

validate-all Validez les paramètres des ressources. Vérifiez que les paramètres sont correctement définis, que les autorisations des fichiers utilisés par la ressource sont appropriées, etc. La valeur de retour doit être l'une des suivantes:

Valeur de retour sens
$OCF_SUCCESS aucun problème
$OCF_ERR_CONFIGURED Il y a un problème avec les paramètres
$OCF_ERR_INSTALLED Les composants requis n'existent pas (par exemple, le démon à démarrer n'est pas installé)
$OCF_ERR_PERM Il y a un problème avec les autorisations d'accès aux fichiers requis pour la gestion des ressources

(Cette fois c'est facile, donc il renvoie toujours $ OCF_SUCCESS.)

Essayez de tester

Vous pouvez tester avec ocf-tester.

#ocf-tester -n [Nom de la ressource] [Chemin de l'agence de ressources]

salacia@ha1:~/ocf-scr$ sudo ocf-tester -n sample-resource ./sample-resource
Beginning tests for ./sample-resource...
* Your agent does not support the notify action (optional)
* Your agent does not support the demote action (optional)
* Your agent does not support the promote action (optional)
* Your agent does not support master/slave (optional)
* Your agent does not support the reload action (optional)
./sample-resource passed all tests

Commencez en fait avec Pacemaker

Déployer un agent de ressources

L'emplacement de l'agent de ressources de Pacemaker est sous / usr / lib / ocf / resource.d /. Créez ici un répertoire avec le nom du fournisseur et placez-y l'agent de ressources créé.

Puisque mon pseudo est Kamaboko, le nom du fournisseur est kamaboko et l'exemple de ressource ci-dessus est placé. (Les agents de ressources doivent être placés sur tous les nœuds du cluster)

salacia@ha1:~/ocf-scr$ ls -al /usr/lib/ocf/resource.d/kamaboko/
total 16
drwxrwxr-x 2 root root 4096 Aug 11 14:07 .
drwxr-xr-x 6 root root 4096 Jun 21 03:36 ..
-rwxr-xr-x 1 root root 1547 Aug 11 14:07 sample-resource
-rwxrwxr-x 1 root root 2103 Jun 21 03:36 sample-tcp-server

Maintenant que l'agent de ressources est disponible depuis Pacemaker, créons une ressource à partir de la commande pcs.

salacia@ha1:~/ocf-scr$ sudo pcs resource create SAMPLE ocf:kamaboko:sample-resource

salacia@ha1:~$ sudo pcs status
Cluster name: c1
Stack: corosync
Current DC: ha2 (version 1.1.18-2b07d5c5a9) - partition with quorum
Last updated: Tue Aug 11 14:15:47 2020
Last change: Tue Aug 11 14:15:45 2020 by root via cibadmin on ha1

2 nodes configured
1 resource configured

Online: [ ha1 ha2 ]

Full list of resources:

 SAMPLE (ocf::kamaboko:sample-resource):        Started ha1

Daemon Status:
  corosync: active/enabled
  pacemaker: active/enabled
  pcsd: active/enabled

J'ai pu exécuter mon propre agent de ressources sur Pacemaker.

Un exemple un peu plus pratique

Voici l exemple de code. OCF Resource Agent Samle

Pour le moment, seul le paquet .deb est pris en charge, donc je pense qu'il peut fonctionner sur Debian, Ubuntu, etc. (L'environnement de développement est Ubuntu 18.04) Un stimulateur cardiaque est une condition préalable à l'installation.

Applications à regrouper

Je viens de créer un démon approprié, j'ai donc créé une application qui me salue lorsque je me connecte avec TCP. (Ne mentionnez pas le code lui-même car ce n'est qu'un exemple ...) Lorsque vous démarrez l'application et que vous vous connectez à telnet, etc., le texte de bienvenue défini dans la variable d'environnement et votre propre nom de nœud sont renvoyés.

daemon/tcp-server.py.py


#!/usr/bin/python3
import os
import socket
import threading
import time
import signal
import sys

PORT = 5678
PID_FILE_DIR = "/var/run/sample-tcp-server"
PID_FILE_NAME = "tcp-server.pid"
PID_FILE = "%s/%s" % (PID_FILE_DIR, PID_FILE_NAME)
EXIT = False
GREET = os.environ.get("GREET", "Hello!")

def signal_handler(signum, stack):
    EXIT = True

def server():
    os.makedirs(PID_FILE_DIR, exist_ok=True)
    if os.path.isfile(PID_FILE):
        raise Exception("Already running")
    
    with open(PID_FILE, "w") as f:
        f.write(str(os.getpid()))
    
    print("Create Socket")
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(('', PORT))
    s.listen(5)

    try:
        while True:
            if EXIT:
                raise Exception("Stop daemon due to receive signal")
            
            (con, addr) = s.accept()
            t = threading.Thread(
                target=handler,
                args=(con, addr),
                daemon=False
            )
            t.start()
    except Exception as e:
        sys.stderr.write("%s\n" % e)
    finally:
        print("Close Socket")
        s.close()
        os.remove(PID_FILE)
        return

def handler(con, addr):
    con.send(("%s This is %s!\n" % (GREET, socket.gethostname())).encode())
    con.close()

if __name__ == '__main__':
    signal.signal(signal.SIGINT, handler)
    signal.signal(signal.SIGTERM, handler)
    server()
    

Comme il a été réalisé uniquement avec des modules standard, il n'est pas nécessaire d'installer des bibliothèques. J'essaye de générer un fichier PID pour confirmer le début du processus. Étant donné que le fichier PID est supprimé lorsque l'application est fermée, vous pouvez vérifier le démarrage de l'application par l'existence du fichier PID, mais s'il est déposé par SIGKILL etc., il ne sera pas supprimé, donc je pense que ce n'est pas très bon. (Cette fois c'est juste un test, donc je fais ça pour simplifier)

Commencez

GREET=Hii! python3 tcp-server.py

Essayez de vous connecter avec telnet

salacia@ha1:~$ telnet localhost 5678
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hi!, This is ha1!
Connection closed by foreign host.

L'exemple de code comprend un fichier de service pour permettre à systemd de démarrer et d'arrêter cette application. Cette fois, exécutons cette application dans un cluster haute disponibilité pour la rendre redondante.

Installation

Vous pouvez télécharger et créer un package avec make, donc tout ce que vous avez à faire est de l'installer depuis dpkg. (Doit être installé sur tous les nœuds du cluster)

git clone https://github.com/kamaboko123/OCF_resource_agent_sample.git
cd OCF_resource_agent_sample
make
sudo dpkg -i dist/sampletcpserver_1.0_amd64.deb

Contrôle de fonctionnement

Pour le moment, définissez VIP (VRRP) entre les deux nœuds et provoquer un basculement en cas de panne.

#Inscrivez-vous VIP en tant que service
sudo pcs resource create VIP ocf:heartbeat:IPaddr2 ip=172.16.0.50 cidr_netmask=24 op monitor interval=10s on-fail="standby"

#Enregistrer un exemple d'application en tant que service
sudo pcs resource create TCP-SERVER ocf:kamaboko:sample-tcp-server greet=Hi!

#Définissez des contraintes afin que les nœuds VIP et ACTIVE de l'exemple d'application soient identiques
sudo pcs constraint colocation add TCP-SERVER with VIP INFINITY

Connectez-vous à l'adresse IP virtuelle par telnet à partir d'un nœud externe.

salacia@Vega:~$ telnet 172.16.0.50 5678
Trying 172.16.0.50...
Connected to 172.16.0.50.
Escape character is '^]'.
Hi!, This is ha1!
Connection closed by foreign host.

Arrêtez le nœud connecté pour le basculer et vérifiez que le service est toujours disponible.

#Actuellement VIP et TCP-Nœud sur lequel la ressource SERVER s'exécute(ha1)Laissez tomber
salacia@ha1:~$ sudo pcs status
[sudo] password for salacia:
Cluster name: c1
Stack: corosync
Current DC: ha2 (version 1.1.18-2b07d5c5a9) - partition with quorum
Last updated: Tue Aug 11 14:31:30 2020
Last change: Tue Aug 11 14:17:26 2020 by root via cibadmin on ha1

2 nodes configured
2 resources configured

Online: [ ha1 ha2 ]

Full list of resources:

 VIP    (ocf::heartbeat:IPaddr2):       Started ha1
 TCP-SERVER     (ocf::kamaboko:sample-tcp-server):      Started ha1

Daemon Status:
  corosync: active/enabled
  pacemaker: active/enabled
  pcsd: active/enabled

salacia@ha1:~$ sudo shutdown -h now
Connection to 172.16.0.51 closed by remote host.
Connection to 172.16.0.51 closed.



#Vérifiez si le service continue à être fourni du nœud externe au VIP
salacia@Vega:~$ telnet 172.16.0.50 5678
Trying 172.16.0.50...
Connected to 172.16.0.50.
Escape character is '^]'.
Hi!, This is ha2!
Connection closed by foreign host.

#Nœud de destination de basculement(ha2)Vérifiez l'état avec
salacia@ha2:~$ sudo pcs status
[sudo] password for salacia:
Cluster name: c1
Stack: corosync
Current DC: ha2 (version 1.1.18-2b07d5c5a9) - partition with quorum
Last updated: Tue Aug 11 14:35:51 2020
Last change: Tue Aug 11 14:17:26 2020 by root via cibadmin on ha1

2 nodes configured
2 resources configured

Online: [ ha2 ]
OFFLINE: [ ha1 ]

Full list of resources:

 VIP    (ocf::heartbeat:IPaddr2):       Started ha2
 TCP-SERVER     (ocf::kamaboko:sample-tcp-server):      Started ha2

Daemon Status:
  corosync: active/enabled
  pacemaker: active/enabled
  pcsd: active/enabled

À propos, lors du test d'ocf-tester, c'est OK si vous spécifiez le chemin complet.

sudo ocf-tester -n sample-tcp-server /usr/lib/ocf/resource.d/kamaboko/sample-tcp-server

Commentaire

Comme expliqué précédemment, l'agent de ressources est écrit dans un script shell.

/usr/lib/ocf/resource.d/kamaboko/sample-tcp-server


#!/bin/sh

#Initialize
: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/resource.d/heartbeat}
. ${OCF_FUNCTIONS_DIR}/.ocf-shellfuncs

#default value
OCF_RESKEY_greet_default="Hello!"
: ${OCF_RESKEY_greet=${OCF_RESKEY_greet_default}}

#environment variables for systemd
DAEMON_PID_FILE=/var/run/sample-tcp-server/tcp-server.pid

sample_meta_data() {
    cat << EOF
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="sample-tcp-server" version="0.1">
    <version>0.1</version>
    <longdesc lang="en">sample tcp server</longdesc>
    <shortdesc lang="en">sample tcp server</shortdesc>
    <parameters>
        <parameter name="greet" unique="0" required="0">
            <longdesc lang="en">greet message</longdesc>
            <shortdesc lang="en">greet message</shortdesc>
            <content type="string"/>
        </parameter>
    </parameters>
    <actions>
        <action name="meta-data" timeout="5" />
        <action name="start" timeout="5" />
        <action name="stop" timeout="5" />
        <action name="monitor" timeout="5" />
        <action name="validate-all" timeout="5" />
    </actions>
</resource-agent>
EOF
    return $OCF_SUCCESS
}

sample_validate(){
    return $OCF_SUCCESS
}

sample_start(){
    mkdir -p /var/run/sample-tcp-server
    echo "GREET=${OCF_RESKEY_greet}" > /var/run/sample-tcp-server/env
    systemctl start sample-tcp-server
    sleep 1
    return $OCF_SUCCESS
}

sample_stop(){
    systemctl stop sample-tcp-server
    return $OCF_SUCCESS
}

sample_monitor(){
    if [ -f ${DAEMON_PID_FILE} ];
    then
        return $OCF_SUCCESS
    fi
    return $OCF_NOT_RUNNING
}

sample_usage(){
    echo "Test Resource."
    return $OCF_SUCCESS
}

# Translate each action into the appropriate function call
case $__OCF_ACTION in
meta-data)      sample_meta_data
                exit $OCF_SUCCESS
                ;;
start)          sample_start;;
stop)           sample_stop;;
monitor)        sample_monitor;;
validate-all)   sample_validate;;
*)              sample_usage
                exit $OCF_ERR_UNIMPLEMENTED
                ;;
esac

méta-données et valeurs par défaut

Dans les méta-données, les paramètres sont définis en plus des éléments requis. Le paramètre est une valeur qui est définie lors de la création de la ressource, et peut être obtenue avec la variable ʻOCF_RESKEY_parameter namedans l'agent de ressource. Cette fois, le texte du message d'accueil est défini par le nom de paramètre «saluer». Dans le cas d'un paramètre obligatoire, l'attribut «required» est mis à 1, mais cette fois il vaut 0, il est donc traité comme une option. Par conséquent, il inclut également une définition de la valeur par défaut si elle n'est pas spécifiée. (Si elle n'est pas spécifiée, cette valeur par défautHello!Sera dans$ OCF_RESKEY_greet`.)

#default value
OCF_RESKEY_greet_default="Hello!"
: ${OCF_RESKEY_greet=${OCF_RESKEY_greet_default}}

sample_meta_data() {
    cat << EOF
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="sample-tcp-server" version="0.1">
    <version>0.1</version>
    <longdesc lang="en">sample tcp server</longdesc>
    <shortdesc lang="en">sample tcp server</shortdesc>
    <parameters>
        <parameter name="greet" unique="0" required="0">
            <longdesc lang="en">greet message</longdesc>
            <shortdesc lang="en">greet message</shortdesc>
            <content type="string"/>
        </parameter>
    </parameters>
    <actions>
        <action name="meta-data" timeout="5" />
        <action name="start" timeout="5" />
        <action name="stop" timeout="5" />
        <action name="monitor" timeout="5" />
        <action name="validate-all" timeout="5" />
    </actions>
</resource-agent>
EOF
    return $OCF_SUCCESS
}

start Je lance juste un service avec systemd. Le fichier de service sera expliqué plus tard. Puisque les paramètres d'OCF sont passés en tant que variables d'environnement au démarrage du service, $ {OCF_RESKEY_greet} est écrit dans le fichier.

sample_start(){
    mkdir -p /var/run/sample-tcp-server
    echo "GREET=${OCF_RESKEY_greet}" > /var/run/sample-tcp-server/env
    systemctl start sample-tcp-server
    sleep 1
    return $OCF_SUCCESS
}

stop Il n'y a pas d'explication particulière et le service est arrêté.

sample_stop(){
    systemctl stop sample-tcp-server
    return $OCF_SUCCESS
}

monitor Cette fois, je regarde le fichier PID.

sample_monitor(){
    if [ -f ${DAEMON_PID_FILE} ];
    then
        return $OCF_SUCCESS
    fi
    return $OCF_NOT_RUNNING
}

J'ai fait cela pour simplifier, mais je ne pense pas que ce soit vraiment une bonne implémentation. Il est implémenté pour supprimer le fichier PID à la fin du processus, mais s'il est tué par SIGKILL, le fichier PID ne sera pas supprimé. En fonction de la création du fichier de service, l'action d'arrêt est considérée comme arrêtant la ressource par tous les moyens, si bien que SIGKILL peut être émis à la fin. Dans ce cas, le fichier PID continuera à rester même s'il est arrêté, et il est possible que l'état réel diffère de l'état confirmé par l'action du moniteur. (Puisque j'utilise systemd pour la gestion des services, j'aurais dû le faire via systemd)

validate-all Je ne fais rien de particulier.

sample_validate(){
    return $OCF_SUCCESS
}

fichier de service

Rien de spécial n'est fait, il suffit de démarrer le démon tout en lisant les variables d'environnement à partir du fichier de variables d'environnement créé lors de la définition de la ressource.

/lib/systemd/system/sample-tcp-server.service


[Unit]
Description=Sample TCP Server

[Service]
Type=simple
ExecStartPre=/bin/touch /var/run/sample-tcp-server/env
EnvironmentFile=/var/run/sample-tcp-server/env
ExecStart=/usr/bin/tcp-server.py
ExecStop=/usr/bin/pkill -F /var/run/sample-tcp-server/tcp-server.pid

[Install]
WantedBy=multi-user.target

Résumé

Les agents de ressources OCF sont étonnamment faciles à créer. Cette fois, en guise d'entrée, nous avons d'abord créé un agent de ressources qui ne fonctionne qu'avec les actions requises, mais il y a quelques points détaillés à noter lors de sa création. Il y a plusieurs astuces dans le Guide du développeur de l'agent de ressources OCF, donc je pense que ce sera utile.

De côté

LPIC304 Quand j'étudiais, je ne comprenais pas vraiment ce que faisait Pacemaker, et en recherchant diverses choses, j'ai réalisé que je pouvais créer mon propre agent de ressources, alors cet article est né.

Recommended Posts

Comment créer un agent de ressources compatible OCF
Comment créer un environnement NVIDIA Docker
Comment créer un article à partir de la ligne de commande
Comment créer un téléchargeur d'image avec Bottle (Python)
[Python Kivy] Comment créer un fichier exe avec pyinstaller
Comment créer un fichier ISO (image CD) sous Linux
Comment créer un package Conda
Comment créer un pont virtuel
Comment créer / supprimer des liens symboliques
Comment créer un Dockerfile (basique)
Comment créer un fichier de configuration
Comment créer un dossier git clone
python3 Comment installer un module externe
Comment convertir Python en fichier exe
Comment créer un référentiel à partir d'un média
Comment créer des exemples de données CSV avec hypothèse
Comment créer un pilote de périphérique Linux intégré (11)
Comment créer des fichiers volumineux à haute vitesse
Comment créer un pilote de périphérique Linux intégré (8)
Comment créer un pilote de périphérique Linux intégré (1)
Comment créer un pilote de périphérique Linux intégré (4)
Comment créer un objet fonction à partir d'une chaîne
Comment créer des variables explicatives et des fonctions objectives
Comment créer un fichier JSON en Python
Comment créer un pilote de périphérique Linux intégré (7)
Comment créer un pilote de périphérique Linux intégré (2)
Comment recadrer une image avec Python + OpenCV
Comment obtenir de l'aide dans un shell interactif
Comment créer un pilote de périphérique Linux intégré (3)
Comment lire un tableau avec ConfigParser de Python
Comment créer des données à mettre dans CNN (Chainer)
Créer une instance de GPU AWS pour entraîner StyleNet
[Note] Comment créer un environnement de développement Ruby
Comment créer un pilote de périphérique Linux intégré (6)
Comment créer une boîte de saisie Kivy 1 ligne
Procédure de création d'application multi-plateforme avec kivy
Essayez de créer un serveur HTTP en utilisant Node.js
Comment créer une API Rest dans Django
Comment créer un pilote de périphérique Linux intégré (5)
Comment créer un pilote de périphérique Linux intégré (10)
Comment créer un pilote de périphérique Linux intégré (9)
[Note] Comment créer un environnement de développement Mac
Comment créer des nombres aléatoires avec le module aléatoire de NumPy
Comment utiliser NUITKA-Utilities hinted-compilation pour créer facilement un fichier exécutable à partir d'un script Python
Lire la source Python-Markdown: Comment créer un analyseur
Comment créer un sous-menu avec le plug-in [Blender]
[Go] Comment créer une erreur personnalisée pour Sentry
Backtrader Comment importer un indicateur depuis un autre fichier
Un moyen simple de créer un module d'importation avec jupyter
Comment créer un outil CLI interactif avec Golang
Comment transformer un fichier .py en fichier .exe
Comment créer un serveur HTTPS avec Go / Gin
Comment créer un référentiel local pour le système d'exploitation Linux
[Python] Comment créer une matrice de corrélation et une carte thermique