Rumah >pembangunan bahagian belakang >Tutorial Python >Mengautomasikan Penggunaan Flask dan PostgreSQL pada KVM dengan Terraform dan Ansible

Mengautomasikan Penggunaan Flask dan PostgreSQL pada KVM dengan Terraform dan Ansible

DDD
DDDasal
2025-01-02 14:49:42955semak imbas

? Pengenalan

Hai, dalam siaran ini, kami akan menggunakan Libvirt dengan Terraform untuk menyediakan 2 KVM secara tempatan dan selepas itu, kami akan Menggunakan Flask App & PostgreSQL menggunakan Ansible.

kandungan

  • Seni Bina Projek
  • Keperluan
  • Buat KVM
  • Buat Playbook Ansible
    • Playbook untuk memasang Docker
    • Playbook untuk memasang dan mengkonfigurasi postgresql
    • Playbook untuk menggunakan Apl Flask
    • Jalankan Playbook dan ujian
  • Kesimpulan

? Seni Bina Projek

Jadi kami akan mencipta 2 VM menggunakan Terraform, kemudian gunakan projek Flask dan pangkalan data menggunakan Ansible.

Automating Deployment of Flask and PostgreSQL on KVM with Terraform and Ansible

? Keperluan

Saya menggunakan Ubuntu 22.04 LTS sebagai OS untuk projek ini. Jika anda menggunakan OS lain, sila buat pelarasan yang diperlukan semasa memasang kebergantungan yang diperlukan.

Pra-syarat utama untuk persediaan ini ialah hipervisor KVM. Jadi anda perlu memasang KVM dalam sistem anda. Jika anda menggunakan Ubuntu anda boleh mengikuti langkah ini:

sudo apt -y install bridge-utils cpu-checker libvirt-clients libvirt-daemon qemu qemu-kvm

Laksanakan arahan berikut untuk memastikan pemproses anda menyokong keupayaan virtualisasi:

$ kvm-ok

INFO: /dev/kvm exists
KVM acceleration can be used

Pasang Terraform

$ 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

Sahkan pemasangan:

$ terraform version

Terraform v1.9.8
on linux_amd64

Pasang Ansible

$ sudo apt update
$ sudo apt install software-properties-common
$ sudo add-apt-repository --yes --update ppa:ansible/ansible
$ sudo apt install ansible -y

Sahkan pemasangan:

$ ansible --version

ansible [core 2.15.1]
...

Buat KVM

kami akan menggunakan penyedia libvirt dengan Terraform untuk menggunakan Mesin Maya KVM.

Buat main.tf, hanya nyatakan pembekal dan versi yang anda mahu gunakan:

terraform {
  required_providers {
    libvirt = {
      source = "dmacvicar/libvirt"
      version = "0.8.1"
    }
  }
}

provider "libvirt" {
  uri = "qemu:///system"
}

Selepas itu, jalankan arahan terraform init untuk memulakan persekitaran:

$ 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.

Sekarang buat pembolehubah kami.tf. Fail variables.tf ini mentakrifkan input untuk laluan kumpulan cakera libvirt, URL imej Ubuntu 20.04 sebagai OS untuk VM dan senarai nama hos VM.

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"]
}

Jom kemas kini main.tf kami:

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
  }
}

skrip akan menyediakan berbilang VM KVM menggunakan penyedia Libvirt. Ia memuat turun imej asas Ubuntu 20.04, mengklonkannya untuk setiap VM, mengkonfigurasi awan-init untuk tetapan pengguna dan rangkaian, dan menggunakan VM dengan nama hos tertentu, memori 1GB dan grafik SPICE. Persediaan menyesuaikan diri secara dinamik berdasarkan bilangan nama hos yang disediakan dalam var.vm_hostnames.

Seperti yang saya nyatakan, saya menggunakan cloud-init, jadi mari sediakan konfigurasi rangkaian dan cloud init di bawah direktori konfigurasi:

mkdir config/

Kemudian buat config/cloud_init.yml kami, cuma pastikan anda mengkonfigurasi kunci ssh awam anda untuk akses ssh dalam konfigurasi:

#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...

Dan kemudian konfigurasi rangkaian, dalam config/network_config.yml:

version: 2
ethernets:
  ens3:
    dhcp4: true

Struktur projek kami sepatutnya kelihatan seperti ini:

sudo apt -y install bridge-utils cpu-checker libvirt-clients libvirt-daemon qemu qemu-kvm

Sekarang jalankan rancangan, untuk melihat perkara yang akan dilakukan:

$ kvm-ok

INFO: /dev/kvm exists
KVM acceleration can be used

Dan jalankan terraform terpakai untuk menjalankan penggunaan kami:

$ 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

Sahkan penciptaan VM menggunakan arahan virsh:

$ terraform version

Terraform v1.9.8
on linux_amd64

Dapatkan alamat IP contoh:

$ sudo apt update
$ sudo apt install software-properties-common
$ sudo add-apt-repository --yes --update ppa:ansible/ansible
$ sudo apt install ansible -y

Cuba akses vm menggunakan pengguna ubuntu:

$ ansible --version

ansible [core 2.15.1]
...

Buat Playbook Ansible

Sekarang mari buat Playbook Ansible untuk menggunakan Flask & Postgresql pada Docker. Mula-mula anda perlu mencipta direktori ansible dan fail 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.

Kemudian buat fail inventori yang dipanggil hos:

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"]
}

menyemak VM kami menggunakan arahan ping ansible:

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
  }
}

Sekarang buat playbook.yml dan roles, playbook ini akan memasang dan mengkonfigurasi Docker, Flask dan PostgreSQL:

mkdir config/

Playbook untuk memasang Docker

Sekarang buat direktori baharu yang dipanggil roles/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...

Buat direktori baharu dalam docker dipanggil tasks, kemudian buat fail baharu main.yml. Fail ini akan memasang Docker & Docker Compose:

version: 2
ethernets:
  ens3:
    dhcp4: true
$ tree
.
├── config
│   ├── cloud_init.yml
│   └── network_config.yml
├── main.tf
└── variables.tf

Playbook untuk memasang dan mengkonfigurasi postgresql

Kemudian buat direktori baharu yang dipanggil psql, buat subdirektori yang dipanggil 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

Selepas itu, dalam vars, buat main.yml. Ini adalah pembolehubah yang digunakan untuk menetapkan nama pengguna, kata laluan, dll:

$ 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

Seterusnya, kami akan mencipta fail jinja yang dipanggil docker-compose.yml.j2. Dengan fail ini kami akan mencipta bekas postgresql:

$ virsh list

 Id   Name   State
----------------------
 1    vm1    running
 2    vm2    running

Seterusnya, buat main.yml untuk tugasan. Jadi kami akan menyalin docker-compose.yml.j2 dan jalankan menggunakan 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

Playbook untuk menggunakan Apl Flask

Mula-mula, anda perlu mencipta direktori yang dipanggil flask, kemudian buat sub-direktori sekali lagi:

$ 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:~$

Seterusnya, tambahkan main.yml pada vars. Fail ini merujuk kepada pembolehubah posgtresql sebelum ini, dengan tambahan alamat IP VM2(pangkalan data VM):

$ mkdir ansible && cd ansible

Seterusnya, buat config.py.j2 kepada templat. Fail ini akan menggantikan fail konfigurasi lama daripada projek Flask:

[defaults]
inventory = hosts
host_key_checking = True
deprecation_warnings = False
collections = ansible.posix, community.general, community.postgresql

Seterusnya, buat docker-compose.yml.j2 kepada templat. Dengan fail ini kami akan mencipta bekas menggunakan karang docker:

[vm1]
192.168.122.19 ansible_user=ubuntu

[vm2]
192.168.122.15 ansible_user=ubuntu

Seterusnya, buat main.yml dalam tugasan. Dengan fail ini kami akan mengklon projek kelalang, menambah fail karang, menggantikan config.py dan mencipta bekas baharu menggunakan karang docker:

$ 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"
}

Struktur projek kami sepatutnya kelihatan seperti ini:

---
- 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

Jalankan Playbook dan ujian

Akhir sekali, mari jalankan ansible-playbook untuk menggunakan PostgreSQL dan Flask:

$ mkdir roles
$ mkdir docker

Setelah selesai, cuma pastikan tiada ralat. Kemudian anda melihat terdapat dua yang dicipta. Dalam VM1 ialah Flask dan VM2 ialah Postgresql:

sudo apt -y install bridge-utils cpu-checker libvirt-clients libvirt-daemon qemu qemu-kvm

Cuba akses apl menggunakan penyemak imbas, hanya taip http://:

Automating Deployment of Flask and PostgreSQL on KVM with Terraform and Ansible

Cuba tambah tugas baharu dan kemudian data akan ditambahkan pada pangkalan data:

Automating Deployment of Flask and PostgreSQL on KVM with Terraform and Ansible

Kesimpulan

Akhir sekali, terima kasih kerana membaca artikel ini. Sila tinggalkan ulasan jika anda mempunyai sebarang soalan, cadangan atau maklum balas.

Nb: Repo Projek: danielcristo/that-i-write

Atas ialah kandungan terperinci Mengautomasikan Penggunaan Flask dan PostgreSQL pada KVM dengan Terraform dan Ansible. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn