Archives mensuelles : septembre 2018


[Ansible] : comment installer un client et un serveur ntp ?

Cet article fait suite à mon fil rouge sur ansible. L’idée c’est de vous relater quelques moments de mon autoformation dans ce domaine. Pour moi c’est aussi le moment de me pencher différement sur ce que je fais et de constituer mon bloc-note.

Avant de commencer, je ne vais pas revenir dessus dans le détail mais j’utilise un script sympa (enfin je trouve). Il permet de me créer un ensemble de conteneurs façon VM (debian et redhat depuis la dernière évolution). Ainsi j’ai une plateforme de développement et je peux simuler des lancements de playbook sur un parc de machines. Pour en savoir plus rendez-vous sur cet article qui présente le script et les grandes lignes.

Donc j’ai lancé deux fois le script et je possède pour l’exemple 4 machines (2 debian stretch et 2 centos7).

Et voilà. Maintenant comment je peux faire pour avoir 1 serveur ntp et 3 serveurs clients ? L’idée c’est de faire en sorte qu’un seul serveur soit exposé et soit utilisé pour contacter les ntp externes.

ansible-ntp

Ainsi on veut avoir le schéma :

ntp_externes >> ntp_serveur >> ntp_clients

1. Les principes des clients et du serveur (sans ansible)

Là encore on va aller à l’essentiel de la configuration. Vous trouverez facilement des articles clairs et courts comme celui-ci qui vous donnera ce qu’il faut pour installer un ntp.

D’un côté, sur le serveur ntp est installé ntp. Il doit au niveau de sa conf taper vers les serveurs externes et surtout accepter les requêtes des autres serveurs. Pour cela il faut supprimer simplement dans /etc/ntp.conf la ligne :

restrict default nomodify notrap nopeer noquery

Et ajouter la localisation ntp :

ntp_area: 'fr'

De l’autre côté pour les serveurs clients, il faut juste modifier les serveurs vers lesquels on fait la synchro dans /etc/ntp.conf. Les serveurs par défaut deviennent par exemple :

server 172.17.0.2 ibusrt

Pour vérifier le bon fonctionnement, il suffira de faire un ntpq -p et voir où les machines vont se synchroniser.

2. NTP avec ansible c’est facile

Bien sûr que c’est facile car ntp est un utilitaire de base des serveurs web ou autres. Ansible Galaxy vous propose donc de très bon rôles. Et j’aurais tendance à dire comme d’habitude c’est geerlingguy qui va vous le proposer avec geerlingguy.ntp.

Alors pour le mettre en place dans votre répertoire de rôles il suffit de faire :

ansible-galaxy install -p roles geerlingguy.ntp

et dedans on a ceci mais on ne va toucher à rien :

.
├── defaults
│   └── main.yml
├── handlers
│   └── main.yml
├── LICENSE
├── meta
│   └── main.yml
├── README.md
├── tasks
│   ├── clock-rhel-6.yml
│   └── main.yml
├── templates
│   ├── clock.j2
│   └── ntp.conf.j2
├── tests
│   ├── README.md
│   └── test.yml
└── vars
├── Archlinux.yml
├── Debian.yml
├── FreeBSD.yml
├── RedHat.yml
└── Suse.yml

Nous avons donc un rôle ntp qui ne demande qu’à tourner. Pour cela mettons à jour notre liste de hosts.yml de notre inventory :

all:
  children:
    ntp-client:
      hosts:
        172.17.0.3:
        172.17.0.4:
        172.17.0.5:
    ntp-server:
      hosts:
        172.17.0.2:

Vous voyez que j’ai entré les ip de mes conteneurs docker. Elles sont classées en 2 groupes ntp-server et ntp-client.

Maintenant je vais créer 2 group_vars (deux répertoires avec un fichier yaml chacun) :

.
├── group_vars
│   ├── ntp-client
│   │   └── ntp-client.yml
│   └── ntp-server
│       └── ntp-server.yml

Puis je complète les fichiers de la manière suivante (en prenant en compte ce que nous avons abordé dans le paragraphe 1.).

ntp-client.yml

ntp_manage_config: True
ntp_servers:
- "172.17.0.2 ibusrt"

ntp-server.yml

ntp_manage_config: True
ntp_restrict:
- "127.0.0.1" 
- "::1" 
- "-4 default kod notrap nomodify nopeer noquery" 
- "-6 default kod notrap nomodify nopeer noquery"

Et là c’est terrible car je vous dis « nous avons fait le plus dur » ! Car maintenant on lance le playbook :

ansible-playbook -i hosts.yml --user=oki playbook-ntp.yml

Et la bingo

PLAY RECAP ************************************************************************************
172.17.0.2 : ok=7 changed=0 unreachable=0 failed=0 
172.17.0.3 : ok=8 changed=0 unreachable=0 failed=0 
172.17.0.4 : ok=8 changed=0 unreachable=0 failed=0 
172.17.0.5 : ok=8 changed=0 unreachable=0 failed=0

Comme vous le voyez moi je n’ai pas de changement car j’ai fait tourner le playbook deux fois.

Maintenant rendez vous sur le serveur ntp :

[root@7dcab8fb52ed ~]# ntpq -p
remote refid st t when poll reach delay offset jitter
================================================================
dev.rudloff.pro 209.176.15.122 3 u 53 64 1 35.024 -29.279 8.299
clients0.arcani 131.188.3.223 2 u 53 64 1 41.120 -23.491 9.220
myminers.net 10.21.137.1 2 u 53 64 1 28.079 -27.255 13.304
*master.servme.f 213.251.128.249 2 u 53 64 1 22.207 -30.641 11.5

et sur le client :

[root@6c6c89bc23ac ~]# ntpq -p
remote refid st t when poll reach delay offset jitter
================================================
172.17.0.2 178.33.111.48 3 u 1 64 1 0.079 0.018 0.000

Nos avons donc bien installé un serveur ntp qui se met à jour sur des serveurs externes et des clients ntp qui se mettent à jour sur notre serveur maitre.

Si cet article vous a plus partagez-le et n’hésitez pas à vous abonner pour ne pas manquer les prochains articles.


[Oracle] : comment réaliser un explain plan ?

L’explain plan chez oracle c’est une possiblité de découvrir comment le moteur traite vos requêtes. Ainsi, vous voyez le cheminement réalisé par le moteur pour vous apporter le résultat.

Explain plan est donc le prinicipal outil pour optimiser vos requêtes et vos bases. Mais attention, le plus dur n’est pas de réaliser l’explain plan mais sa lecture et son interprétation (et ça il faut des années pour devenir un champion des l’optimisation).

Comment lancer un Explain Plan d’une requête ?

Si nécessaire, mettez en place le module utlxplan.sql

@$ORACLE_HOME/rdbms/admin/utlxplan.sql

Ensuite, définissez le nom de votre plan :

RENAME PLAN_TABLE TO monplan;

Ensuite lancez la requête qui va construire votre explain plan.

EXPLAIN PLAN FOR
SELECT champs1, champs2, champs3 FROM matable;

Maintenant, vous pouvez consulter le résultat en utilisant le DBMS_XPLAN.

SELECT PLAN_TABLE_OUTPUT
FROM TABLE(DBMS_XPLAN.DISPLAY());

Si vous souhaitez voir quelques exemple sur comment paser un explain, vous pouvez consulter la page du site oracle.

Comment l’analyser ?

Clairement, ce n’est pas dans cet article que vous allez apprendre à optimiser vos requêtes et bases.

Sur le blog de Markus Winand, vous trouverez cette page qui va vous permettre de trouver les principaux termes que vous retrouverez dans les résultats d’un explain plan. En effet, le plan repose principalement sur l’exploitations de jointures et d’index pour vous apporter le résultat le plus vite possible.

Un résultat resemble à ceci :

| Id| Operation                   | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
| 0 | SELECT STATEMENT            |               |     4 | 16208 |     3   (0)| 00:00:01 |
| 1 |  TABLE ACCESS BY INDEX ROWID| CONSULTANT    |     4 | 16208 |     3   (0)| 00:00:01 |
|*2 |   INDEX RANGE SCAN          | CONSULTANT_PK |     4 |       |     2   (0)| 00:00:01 |

Source : SOAT

Dedans on peuty découvrir :

  • le type d’opération
  • le nombre de lignes parcourues
  • le volume utilisé
  • le coût
  • le temps

Mais le principal c’est l’ordre. Un plan se lit de bas en haut. Le moteur commence par les actions du bas et remonte progressivement. Donc dans l’exemple, il accède à un index CONSULTANT_PK puis à la table CONSULTANT.

En apprendre plus par les experts oracle

Pour cela il existe une très bonne vidéo d’une interventionde Maria Colgan.

Et si vous voulez en voir une un peu plus courte mais déjà bien complète, commencez par celle de Jeff Smith.

Je vous invite à lire le document : xplan_webinar.pdf


[Ansible] : commençons simplement : copie de fichiers, modification/écriture avec copy et lineinfile

Précédemment, je vous avais fait part de ma volonté de me lancer dans ansible et de vous partager cette expérience d’apprentissage.

Un précédent article vous présentait un script qui me permet de mettre en place un « centre serveur de poche » à partir de conteneurs (attention ce ne sont que des conteneurs pas de VM donc pas des serveurs… pas la peine de lancer des discussions à ce sujet). Bref, l’idée de cet article était de vous expliquer mon script pour mettre en place une infrastructure légère permettant de me faire la main sur ansible.

Et le bilan c’est que ça marche très bien et que c’est bien plus léger que tout ce qui est à partir de VM. C’est extrèmement pratique pour bosser sur son portable car on peut faire et réinitialiser les serveurs très vites.

Maintenant, il faut se former.

Le fichier inventory, la liste des serveurs

L’inventory est le fichier contenant la liste de référence de vos machines. Dans mon cas j’ai lancé deux conteneurs (machine) 172.17.0.2 et172.17.0.3. En avoir plusieurs c’est vraiment bien pour créer des variations au niveau des hosts et ainsi approfondir le fonctionnement de ansible.

Mon fichier se nomme hosts (comme souvent sur ansible) :

└─ $ ▶ cat hosts
[web]
172.17.0.2
172.17.0.3

J’ai choisi le format init et non le yaml car je suis tombé avec un bug en lien avec python 3.5 (ansible ne lisait pas le yaml de l’inventory).

Pour tester votre inventory, vous pouvez lancer :

ansible -i hosts all --list-hosts

Ensuite, vous pouvez tester une commande linux sur votre parc, par exemple « uptime » :

00:07:33 - oki @ doki ~/autoform_ansible 
└─ $ ▶ ansible -i hosts all -u oki -m shell -a "uptime"
172.17.0.3 | SUCCESS | rc=0 >>
22:07:35 up 1:26, 1 user, load average: 1.00, 0.75, 0.66

172.17.0.2 | SUCCESS | rc=0 >>
22:07:35 up 1:26, 1 user, load average: 1.00, 0.75, 0.66

L’arborescence

Extrèmement importante cette arborescence dans un outil d’orchestration comme ansible. En effet, cela peut vite tourner au boxon tellement vous aller générer de fichiers.

De base si on ne rentre pas dans les roles :

.
├── group_vars
│   └── web
├── hosts
├── host_vars
│   ├── 172.17.0.2
│   └── 172.17.0.3
├── playbook-manip.yml

  • group_vars : contient les variables des groupes (regroupement de serveur) par exemple « web » dans mon cas
  • hosts : c’ets l’inventory de nos machines classées par groupe
  • host_vars : contient les variables des machines (pour spécifier à la machine une variable)
  • playbook.yml : les actions à réaliser

Les deux éléments centraux sont donc : la liste des machines et les actions à réaliser dessus.

Le playbook

On l’a dit le playbook contient les actions à réaliser (et par qui et sur qui). L’entête sert principalement à définir par qui et sur qui de cette manière :

---
- name: Lancement des actions
  hosts: web
  remote_user: oki
  become: yes
  tasks:
  • hosts : pour dire sur quelles machines ou quel groupe on travaille (en l’occurence web dans mon exemple)
  • remote_user : qui va exécuter les actions
  • become : permet d’élever les privilèges si nécessaire pour faire les actions
  • tasks : indique la liste des actions à venir

Le « – name: » est extrèment important. Il permet sera défini de nombreuse fois tout au long de notre code et permet au lancement du playbook de savoir où nous en sommes. C’est donc indispensable pour débugger.

La première action que nous allons réaliser c’est de copier un fichier présent au même niveau que notre playbook (c’est moche je sais mais c’est simple avant tout).

 - name: Transfert de monfichier.txt
   copy:
     src: ./monfichier.txt
     dest: /tmp/monfichier.txt

Nous définissons donc le nom de l’action que nous allons lancer par « – name: ». Puis utilisons le module copy de ansible. Pour copier/coller un fichier il prend deux éléments :

  • src: le fichier source
  • dest: le fichier de destination

Dans une deuxième action nous allons modifier le contenu de mon fichier qui ne contient que « bonjour Xavier » pour le faire contenir « Remplacement salut Xavier ». Et pour cela nous allons utiliser le module lineinfile :

 - name: Modification de monfichier.txt
   lineinfile:
     path: /tmp/monfichier.txt
     regexp: "^bonjour(.*)"
     line: 'Remplacement salut'
     backrefs: yes

Dans cette utilisation de lineinfile je transmets les éléments :

  • path : la localisation de mon fichier à modifier
  • regexp : un élément permettant de retrouver la ligne et capturer un motif (dans mon cas je capture « Xavier » par exemple
  • line : la nouvelle ligne contenant mon texte et « \1 » c’est à dire le motif capturé
  • backrefs : pour utiliser la capture à partir du backslash

Mon playbook au final contient ceci (attention l’indentation doit être stricte, c’est un yaml) :

---
- name: Lancement des actions
  hosts: all
  remote_user: oki
  become: yes
  tasks:

    - name: Transfert de monfichier.txt
      copy:
        src: ./monfichier.txt
        dest: /tmp/monfichier.txt

    - name: Modification de monfichier.txt
      lineinfile:
        path: /tmp/monfichier.txt
        regexp: "^bonjour(.*)"
        line: 'Remplacement salut'
        backrefs: yes

Pour lancer votre playbook sur votre inventory passez :

ansible-playbook -i hosts --user=oki -D playbook-fichier.yml

Et en sortie le résultat du log ansible donne :

PLAY [Lancement des actions] ********************************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************************************************
ok: [172.17.0.2]
ok: [172.17.0.3]

TASK [Transfert de monfichier.txt] **************************************************************************************************************************************************************
--- before: /tmp/monfichier.txt
+++ after: /home/oki/autoform_ansible/monfichier.txt
@@ -12,4 +12,4 @@
###############################################################


-Remplacement salut Xavier
+bonjour Xavier

changed: [172.17.0.3]
--- before: /tmp/monfichier.txt
+++ after: /home/oki/autoform_ansible/monfichier.txt
@@ -12,4 +12,4 @@
###############################################################


-Remplacement salut Xavier
+bonjour Xavier

changed: [172.17.0.2]

TASK [Modification de monfichier.txt] ******************************************
--- before: /tmp/monfichier.txt (content)
+++ after: /tmp/monfichier.txt (content)
@@ -12,4 +12,4 @@
###############################################################


-bonjour Xavier
+Remplacement salut Xavier

changed: [172.17.0.3]
--- before: /tmp/monfichier.txt (content)
+++ after: /tmp/monfichier.txt (content)
@@ -12,4 +12,4 @@
###############################################################


-bonjour Xavier
+Remplacement salut Xavier

changed: [172.17.0.2]

PLAY RECAP ***************************************************
172.17.0.2 : ok=3 changed=2 unreachable=0 failed=0 
172.17.0.3 : ok=3 changed=2 unreachable=0 failed=0

[Docker] : comment créer une image à partir d’un conteneur et la pousser ?

Comme dirait l’autre ça va finir par rentrer, nom d’une pipe. Mais cela fait plusieurs fois que je fais cette manip et comme écrire un article m’aide à retenir les choses je vais vous faire partager une manip docker.

Le but aujourd’hui c’est de savoir comment créer une image à partir d’un conteneur existant que vous avez ajustez à votre guise. Dans mon cas c’est un conteneur qui permet d’avoir une debian stretch avec systemd, openssh, sudo et vim. La grosse subtilité c’est d’avoir systemd mais je ne vais pas vous détailler cela aujourd’hui.

docker-image-conteneur

Démo en vidéo :

La première chose à faire c’est de connaître l’id de son conteneur avec un bon docker ps :

└─ $ ▶ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bbb5c547002c debian-systemd "/lib/systemd/systemd" 31 minutes ago Up 31 minutes competent_vaughan

Ensuite il faut commiter tout ceci dans une nouvelle image avec un docker commit (à partir de l’ID de l’image) :

└─ $ ▶ docker commit -m "image stretch + systemd + openssh" bbb5c547002c priximmo/stretch-systemd-ssh

Sivous faite un docker image ls, vous pouvez déjà voir votre image sur votre pc en local.

Puis si vous le souhaitez vous pouvez pousser ceci sur dockerhub ou un autre repository.

docker login
docker push priximmo/stretch-systemd-ssh

Et voilà vous disposez de votre image en local et sur votre dépôt.

Retrouvez l’image en question sur docker hub.