Maison >développement back-end >Tutoriel Python >Automatisation du déploiement de Flask et PostgreSQL sur KVM avec Terraform et Ansible
Bonjour, dans cet article, nous utiliserons Libvirt avec Terraform pour provisionner 2 KVM localement et après cela, nous déploierons Flask App et PostgreSQL à l'aide d'Ansible.
Nous allons donc créer 2 VM à l'aide de Terraform, puis déployer un projet Flask et la base de données à l'aide d'Ansible.
J'ai utilisé Ubuntu 22.04 LTS comme système d'exploitation pour ce projet. Si vous utilisez un autre système d'exploitation, veuillez effectuer les ajustements nécessaires lors de l'installation des dépendances requises.
Le pré-requis majeur pour cette configuration est l'hyperviseur KVM. Vous devez donc installer KVM sur votre système. Si vous utilisez Ubuntu, vous pouvez suivre cette étape :
sudo apt -y install bridge-utils cpu-checker libvirt-clients libvirt-daemon qemu qemu-kvm
Exécutez la commande suivante pour vous assurer que votre processeur prend en charge les capacités de virtualisation :
$ kvm-ok INFO: /dev/kvm exists KVM acceleration can be used
$ wget -O - https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg $ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list $ sudo apt update && sudo apt install terraform -y
Vérifier l'installation :
$ terraform version Terraform v1.9.8 on linux_amd64
$ sudo apt update $ sudo apt install software-properties-common $ sudo add-apt-repository --yes --update ppa:ansible/ansible $ sudo apt install ansible -y
Vérifier l'installation :
$ ansible --version ansible [core 2.15.1] ...
nous utiliserons le fournisseur libvirt avec Terraform pour déployer une machine virtuelle KVM.
Créez main.tf, précisez simplement le fournisseur et la version que vous souhaitez utiliser :
terraform { required_providers { libvirt = { source = "dmacvicar/libvirt" version = "0.8.1" } } } provider "libvirt" { uri = "qemu:///system" }
Ensuite, exécutez la commande terraform init pour initialiser l'environnement :
$ terraform init Initializing the backend... Initializing provider plugins... - Reusing previous version of hashicorp/template from the dependency lock file - Reusing previous version of dmacvicar/libvirt from the dependency lock file - Reusing previous version of hashicorp/null from the dependency lock file - Using previously-installed hashicorp/template v2.2.0 - Using previously-installed dmacvicar/libvirt v0.8.1 - Using previously-installed hashicorp/null v3.2.3 Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure. All Terraform commands should now work. If you ever set or change modules or backend configuration for Terraform, rerun this command to reinitialize your working directory. If you forget, other commands will detect it and remind you to do so if necessary.
Créez maintenant notre variables.tf. Ce fichier variables.tf définit les entrées pour le chemin du pool de disques libvirt, l'URL de l'image Ubuntu 20.04 en tant que système d'exploitation pour les machines virtuelles et une liste de noms d'hôtes de machines virtuelles.
variable "libvirt_disk_path" { description = "path for libvirt pool" default = "default" } variable "ubuntu_20_img_url" { description = "ubuntu 20.04 image" default = "https://cloud-images.ubuntu.com/releases/focal/release/ubuntu-20.04-server-cloudimg-amd64.img" } variable "vm_hostnames" { description = "List of VM hostnames" default = ["vm1", "vm2"] }
Mettons à jour notre main.tf :
resource "null_resource" "cache_image" { provisioner "local-exec" { command = "wget -O /tmp/ubuntu-20.04.qcow2 ${var.ubuntu_20_img_url}" } } resource "libvirt_volume" "base" { name = "base.qcow2" source = "/tmp/ubuntu-20.04.qcow2" pool = var.libvirt_disk_path format = "qcow2" depends_on = [null_resource.cache_image] } # Volume for VM with size 10GB resource "libvirt_volume" "ubuntu20-qcow2" { count = length(var.vm_hostnames) name = "ubuntu20-${count.index}.qcow2" base_volume_id = libvirt_volume.base.id pool = var.libvirt_disk_path size = 10737418240 # 10GB } data "template_file" "user_data" { count = length(var.vm_hostnames) template = file("${path.module}/config/cloud_init.yml") } data "template_file" "network_config" { count = length(var.vm_hostnames) template = file("${path.module}/config/network_config.yml") } resource "libvirt_cloudinit_disk" "commoninit" { count = length(var.vm_hostnames) name = "commoninit-${count.index}.iso" user_data = data.template_file.user_data[count.index].rendered network_config = data.template_file.network_config[count.index].rendered pool = var.libvirt_disk_path } resource "libvirt_domain" "domain-ubuntu" { count = length(var.vm_hostnames) name = var.vm_hostnames[count.index] memory = "1024" # VM memory vcpu = 1 # VM CPU cloudinit = libvirt_cloudinit_disk.commoninit[count.index].id network_interface { network_name = "default" wait_for_lease = true hostname = var.vm_hostnames[count.index] } console { type = "pty" target_port = "0" target_type = "serial" } console { type = "pty" target_type = "virtio" target_port = "1" } disk { volume_id = libvirt_volume.ubuntu20-qcow2[count.index].id } graphics { type = "spice" listen_type = "address" autoport = true } }
le script provisionnera plusieurs machines virtuelles KVM à l'aide du fournisseur Libvirt. Il télécharge une image de base Ubuntu 20.04, la clone pour chaque VM, configure cloud-init pour les paramètres utilisateur et réseau et déploie des VM avec des noms d'hôte spécifiés, 1 Go de mémoire et des graphiques SPICE. La configuration s'adapte dynamiquement en fonction du nombre de noms d'hôte fournis dans var.vm_hostnames.
Comme je l'ai mentionné, j'utilise cloud-init, alors configurons la configuration réseau et cloud init dans le répertoire de configuration :
mkdir config/
Créez ensuite notre config/cloud_init.yml, assurez-vous simplement de configurer votre clé publique ssh pour l'accès ssh dans la configuration :
#cloud-config runcmd: - sed -i '/PermitRootLogin/d' /etc/ssh/sshd_config - echo "PermitRootLogin yes" >> /etc/ssh/sshd_config - systemctl restart sshd ssh_pwauth: true disable_root: false chpasswd: list: | root:cloudy24 expire: false users: - name: ubuntu gecos: ubuntu groups: - sudo sudo: - ALL=(ALL) NOPASSWD:ALL home: /home/ubuntu shell: /bin/bash lock_passwd: false ssh_authorized_keys: - ssh-rsa AAAA...
Et puis config réseau, dans config/network_config.yml :
version: 2 ethernets: ens3: dhcp4: true
La structure de notre projet devrait ressembler à ceci :
sudo apt -y install bridge-utils cpu-checker libvirt-clients libvirt-daemon qemu qemu-kvm
Maintenant, exécutez un plan, pour voir ce qui sera fait :
$ kvm-ok INFO: /dev/kvm exists KVM acceleration can be used
Et exécutez terraform apply pour exécuter notre déploiement :
$ wget -O - https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg $ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list $ sudo apt update && sudo apt install terraform -y
Vérifiez la création de la VM à l'aide de la commande virsh :
$ terraform version Terraform v1.9.8 on linux_amd64
Obtenir l'adresse IP des instances :
$ sudo apt update $ sudo apt install software-properties-common $ sudo add-apt-repository --yes --update ppa:ansible/ansible $ sudo apt install ansible -y
Essayez d'accéder à la machine virtuelle en utilisant l'utilisateur Ubuntu :
$ ansible --version ansible [core 2.15.1] ...
Créons maintenant le Playbook Ansible pour déployer Flask et Postgresql sur Docker. Vous devez d'abord créer un répertoire ansible et un fichier ansible.cfg :
terraform { required_providers { libvirt = { source = "dmacvicar/libvirt" version = "0.8.1" } } } provider "libvirt" { uri = "qemu:///system" }
$ terraform init Initializing the backend... Initializing provider plugins... - Reusing previous version of hashicorp/template from the dependency lock file - Reusing previous version of dmacvicar/libvirt from the dependency lock file - Reusing previous version of hashicorp/null from the dependency lock file - Using previously-installed hashicorp/template v2.2.0 - Using previously-installed dmacvicar/libvirt v0.8.1 - Using previously-installed hashicorp/null v3.2.3 Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure. All Terraform commands should now work. If you ever set or change modules or backend configuration for Terraform, rerun this command to reinitialize your working directory. If you forget, other commands will detect it and remind you to do so if necessary.
Créez ensuite un fichier d'inventaire appelé hosts :
variable "libvirt_disk_path" { description = "path for libvirt pool" default = "default" } variable "ubuntu_20_img_url" { description = "ubuntu 20.04 image" default = "https://cloud-images.ubuntu.com/releases/focal/release/ubuntu-20.04-server-cloudimg-amd64.img" } variable "vm_hostnames" { description = "List of VM hostnames" default = ["vm1", "vm2"] }
vérifier nos VM à l'aide de la commande ansible ping :
resource "null_resource" "cache_image" { provisioner "local-exec" { command = "wget -O /tmp/ubuntu-20.04.qcow2 ${var.ubuntu_20_img_url}" } } resource "libvirt_volume" "base" { name = "base.qcow2" source = "/tmp/ubuntu-20.04.qcow2" pool = var.libvirt_disk_path format = "qcow2" depends_on = [null_resource.cache_image] } # Volume for VM with size 10GB resource "libvirt_volume" "ubuntu20-qcow2" { count = length(var.vm_hostnames) name = "ubuntu20-${count.index}.qcow2" base_volume_id = libvirt_volume.base.id pool = var.libvirt_disk_path size = 10737418240 # 10GB } data "template_file" "user_data" { count = length(var.vm_hostnames) template = file("${path.module}/config/cloud_init.yml") } data "template_file" "network_config" { count = length(var.vm_hostnames) template = file("${path.module}/config/network_config.yml") } resource "libvirt_cloudinit_disk" "commoninit" { count = length(var.vm_hostnames) name = "commoninit-${count.index}.iso" user_data = data.template_file.user_data[count.index].rendered network_config = data.template_file.network_config[count.index].rendered pool = var.libvirt_disk_path } resource "libvirt_domain" "domain-ubuntu" { count = length(var.vm_hostnames) name = var.vm_hostnames[count.index] memory = "1024" # VM memory vcpu = 1 # VM CPU cloudinit = libvirt_cloudinit_disk.commoninit[count.index].id network_interface { network_name = "default" wait_for_lease = true hostname = var.vm_hostnames[count.index] } console { type = "pty" target_port = "0" target_type = "serial" } console { type = "pty" target_type = "virtio" target_port = "1" } disk { volume_id = libvirt_volume.ubuntu20-qcow2[count.index].id } graphics { type = "spice" listen_type = "address" autoport = true } }
Créez maintenant playbook.yml et les rôles, ce playbook installera et configurera Docker, Flask et PostgreSQL :
mkdir config/
Créez maintenant un nouveau répertoire appelé rôles/docker :
#cloud-config runcmd: - sed -i '/PermitRootLogin/d' /etc/ssh/sshd_config - echo "PermitRootLogin yes" >> /etc/ssh/sshd_config - systemctl restart sshd ssh_pwauth: true disable_root: false chpasswd: list: | root:cloudy24 expire: false users: - name: ubuntu gecos: ubuntu groups: - sudo sudo: - ALL=(ALL) NOPASSWD:ALL home: /home/ubuntu shell: /bin/bash lock_passwd: false ssh_authorized_keys: - ssh-rsa AAAA...
Créez un nouveau répertoire dans le docker appelé tâches, puis créez un nouveau fichier main.yml. Ce fichier installera Docker & Docker Compose :
version: 2 ethernets: ens3: dhcp4: true
$ tree . ├── config │ ├── cloud_init.yml │ └── network_config.yml ├── main.tf └── variables.tf
Créez ensuite un nouveau répertoire appelé psql, créez un sous-répertoire appelé vars, tempalates & Tasks :
$ terraform plan data.template_file.user_data[1]: Reading... data.template_file.user_data[0]: Reading... data.template_file.network_config[1]: Reading... data.template_file.network_config[0]: Reading... ... Plan: 8 to add, 0 to change, 0 to destroy
Après cela, dans vars, créez main.yml. Ce sont des variables utilisées pour définir le nom d'utilisateur, les mots de passe, etc :
$ terraform apply ... null_resource.cache_image: Creation complete after 10m36s [id=4239391010009470471] libvirt_volume.base: Creating... libvirt_volume.base: Creation complete after 3s [id=/var/lib/libvirt/images/base.qcow2] libvirt_volume.ubuntu20-qcow2[1]: Creating... libvirt_volume.ubuntu20-qcow2[0]: Creating... libvirt_volume.ubuntu20-qcow2[1]: Creation complete after 0s [id=/var/lib/libvirt/images/ubuntu20-1.qcow2] libvirt_volume.ubuntu20-qcow2[0]: Creation complete after 0s [id=/var/lib/libvirt/images/ubuntu20-0.qcow2] libvirt_domain.domain-ubuntu[1]: Creating... ... libvirt_domain.domain-ubuntu[1]: Creation complete after 51s [id=6221f782-48b7-49a4-9eb9-fc92970f06a2] Apply complete! Resources: 8 added, 0 changed, 0 destroyed
Ensuite, nous allons créer un fichier jinja appelé docker-compose.yml.j2. Avec ce fichier nous allons créer un conteneur postgresql :
$ virsh list Id Name State ---------------------- 1 vm1 running 2 vm2 running
Ensuite, créez main.yml pour les tâches. Nous allons donc copier docker-compose.yml.j2 et exécuter en utilisant docker compose :
$ virsh net-dhcp-leases --network default Expiry Time MAC address Protocol IP address Hostname Client ID or DUID ----------------------------------------------------------------------------------------------------------------------------------------------- 2024-12-09 19:50:00 52:54:00:2e:0e:86 ipv4 192.168.122.19/24 vm1 ff:b5:5e:67:ff:00:02:00:00:ab:11:b0:43:6a:d8:bc:16:30:0d 2024-12-09 19:50:00 52:54:00:86:d4:ca ipv4 192.168.122.15/24 vm2 ff:b5:5e:67:ff:00:02:00:00:ab:11:39:24:8c:4a:7e:6a:dd:78
Tout d'abord, vous devez créer un répertoire appelé flask, puis créer à nouveau un sous-répertoire :
$ ssh ubuntu@192.168.122.15 The authenticity of host '192.168.122.15 (192.168.122.15)' can't be established. ED25519 key fingerprint is SHA256:Y20zaCcrlOZvPTP+/qLLHc7vJIOca7QjTinsz9Bj6sk. This key is not known by any other names Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '192.168.122.15' (ED25519) to the list of known hosts. Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-200-generic x86_64) ... ubuntu@ubuntu:~$
Ensuite, ajoutez main.yml à vars. Ce fichier fait référence à la variable posgtresql auparavant, avec en plus l'adresse IP de la VM2 (base de données VM) :
$ mkdir ansible && cd ansible
Ensuite, créez config.py.j2 dans les modèles. Ce fichier remplacera l'ancien fichier de configuration du projet Flask :
[defaults] inventory = hosts host_key_checking = True deprecation_warnings = False collections = ansible.posix, community.general, community.postgresql
Ensuite, créez docker-compose.yml.j2 dans les modèles. Avec ce fichier nous allons créer un conteneur en utilisant docker compose :
[vm1] 192.168.122.19 ansible_user=ubuntu [vm2] 192.168.122.15 ansible_user=ubuntu
Ensuite, créez main.yml dans les tâches. Avec ce fichier, nous allons cloner le projet flask, ajouter le fichier composer, remplacer config.py et créer un nouveau conteneur à l'aide de docker compose :
$ ansible -m ping all 192.168.122.15 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python3" }, "changed": false, "ping": "pong" } 192.168.122.19 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python3" }, "changed": false, "ping": "pong" }
La structure de notre projet devrait ressembler à ceci :
--- - name: Deploy Flask hosts: vm1 become: true remote_user: ubuntu roles: - flask - config - name: Deploy Postgresql hosts: vm2 become: true remote_user: ubuntu roles: - psql - config
Enfin, exécutons ansible-playbook pour déployer PostgreSQL et Flask :
$ mkdir roles $ mkdir docker
Une fois terminé, assurez-vous simplement qu'il n'y a pas d'erreur. Ensuite, vous voyez qu'il y en a deux créés. Dans VM1 se trouve Flask et VM2 est Postgresql :
sudo apt -y install bridge-utils cpu-checker libvirt-clients libvirt-daemon qemu qemu-kvm
Essayez d'accéder à l'application à l'aide des navigateurs, tapez simplement http://
Essayez d'ajouter une nouvelle tâche et les données seront ensuite ajoutées à la base de données :
Enfin, merci d’avoir lu cet article. N'hésitez pas à laisser un commentaire si vous avez des questions, des suggestions ou des commentaires.
Nb : Project Repo : danielcristho/that-i-write
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!