Pengembangan berdiri tanpa antrian dan waktu henti

Tujuan artikel ini adalah untuk menunjukkan salah satu pendekatan yang mungkin untuk mengatur penyebaran fleksibel dari bangku dev / test. Tunjukkan keuntungan apa yang diberikan pendekatan IaC dalam kombinasi dengan alat modern.






Latar Belakang

Ada beberapa singkatan untuk developer - devs, test, production. Versi baru komponen produk muncul beberapa kali sehari. 





Alhasil, stand-stand yang ada sudah terisi, pengembang menganggur menunggu salah satu stand dikosongkan.





Pembuatan stan statis tambahan akan menyelesaikan masalah, tetapi akan menyebabkan kelebihan stan selama penurunan aktivitas pengembang dan, akibatnya, akan meningkatkan biaya infrastruktur perusahaan.





Sebuah tugas

Untuk memungkinkan pengembang menyebarkan dan menghapus stand mereka sendiri, berdasarkan kebutuhan saat ini.





Tumpukan

Gitlab CI, Terraform, Bash, semua awan pribadi / publik.





Kesulitan teknis: 





  1. File status terraform - di luar kotak kami tidak memiliki kemampuan untuk menggunakan variabel dalam nilai nama file negara. Anda perlu menemukan sesuatu atau menggunakan produk lain.





  2. Subnet - setiap lingkungan baru harus dibuat di subnet yang terisolasi. Anda perlu mengontrol subnet bebas / sibuk, semacam analog DHCP, tetapi untuk subnet.





Algoritma

  1. Gitlab CI menjalankan pipeline. Menyatukan semua komponen lainnya.





  2. Terraform .





  3. Configuration manager(CM) - .





  4. Bash .





development-infrastructure/
    deploy/
        env1/
            main.tf
            backend.tf
            ansible-vars.json 
            subnets.txt 
        env2/
        ...
    cm/
        ...
    modules/
        azure/
            main.tf
            variables.tf
    scripts/
        env.sh
        subnets.txt 
    .gitlab-ci.yml
      
      



  • deploy - - terraform CM, .





  • cm - , Ansible .





  • modules - terraform





  • scripts - bash





.gitlab-ci.yml:





stages: 
  - create environment 
  - terraform apply 
  - cm 
  - destroy environment 

.template: 
  variables: 
    ENV: $NAME_ENV 
  when: manual 
  tags: [cloudRunner01] 
  only: 
    refs: 
      - triggers 

Create environment: 
  stage: create environment 
  extends: .template 
  script: 
    - ./scripts/create_env.sh -e $ENV -a create 
  artifacts: 
    paths: 
      - deploy/${ENV}/backend.tf 
      - deploy/${ENV}/main.tf 
      - deploy/${ENV}/vars.json 

Create instances: 
  stage: terraform apply 
  extends: .template 
  script: 
    - cd ./deploy/$ENV 
    - terraform init -input=false 
    - terraform validate 
    - terraform plan -input=false -out=tf_plan_$ENV 
    - terraform apply -input=false tf_plan_$ENV 

Deploy applications: 
  stage: cm 
  extends: .template 
  script: 
    - #          CM 
    - #   ,    $ENV  , 
    - #      .. 
    - #       terraform 

Destroy instances and environment: 
  stage: destroy environment 
  extends: .template 
  script: 
    - cd ./deploy/$ENV 
    - terraform init -input=false 
    - terraform destroy -auto-approve 
    - ./scripts/delete_env.sh -e $ENV -a delete 
      
      



:





  • Create environment - , NAME_ENV, , git .





  • Create instances - ( ) , .





  • Deploy applications - Configuration Manager.





  • Destroy instances and environment - bash , . scripts/subnets.txt.





NAME_ENV, :





Git pipeline.





modules/base/main.tf:





#           
provider "azurerm" { 
  version = "=1.39.0" 
} 


#    ,   Azure.   ,         
resource "azurerm_resource_group" "product_group" { 
  name     = "${var.env_name}" 
  location = "East Europe" 
} 

#   
resource "azurerm_virtual_network" "vnet" { 
  name                = "product-vnet" 
  resource_group_name = azurerm_resource_group.product_group.name 
  location            = azurerm_resource_group.product_group.location 
  address_space       = [var.vnet_address] 
} 

#      bash  
resource "azurerm_subnet" "subnet" { 
  name                 = "product-subnet" 
  resource_group_name  = azurerm_resource_group.product_group.name 
  virtual_network_name = azurerm_virtual_network.vnet.name 
  address_prefix       = var.subnet_address 
} 

#     
resource "azurerm_virtual_machine" "product_vm" { 
  name                  = "main-instance" 
  location              = azurerm_resource_group.product_group.location 
  resource_group_name   = azurerm_resource_group.product_group.name 
  network_interface_ids = [azurerm_network_interface.main_nic.id] 
  … 
} 

#     ... 
      
      



, , , .





, , , .





scripts/env.sh:





#!/bin/bash 

set -eu 

CIDR="24" 
DEPLOY_DIR="./deploy" 
SCRIPT_DIR=$(dirname "$0") 

usage() { 
     echo "Usage: $0 -e [ENV_NAME] -a [create/delete]" 
     echo "  -e: Environment name" 
     echo "  -a: Create or delete" 
     echo "  -h: Help message" 
     echo "Examples:" 
     echo "  $0 -e dev-stand-1 -a create" 
     echo "  $0 -e issue-1533 -a delete" 
} 

while getopts 'he:a:' opt; do 
    case "${opt}" in 
        e) ENV_NAME=$OPTARG ;; 
        a) ACTION=$OPTARG ;; 
        h) usage; exit 0 ;; 
        *) echo "Unknown parameter"; usage; exit 1;; 
    esac 
done 

if [ -z "${ENV_NAME:-}" ] && [ -z "${ACTION:-}" ]; then 
    usage 
    exit 1 
fi 

#       
ENV_NAME="${ENV_NAME,,}" 

git_push() { 
    git add ../"${ENV_NAME}" 
    case ${1:-} in 
        create) 
            git commit -am "${ENV_NAME} environment was created" 
            git push origin HEAD:"$CI_COMMIT_REF_NAME" -o ci.skip 
            echo "Environment ${ENV_NAME} was created.";; 
        delete) 
            git commit -am "${ENV_NAME} environment was deleted" 
            git push origin HEAD:"$CI_COMMIT_REF_NAME" -o ci.skip 
            echo "Environment ${ENV_NAME} was deleted.";; 
    esac 
} 

create_env() { 
    #      
    if [ -d "${DEPLOY_DIR}/${ENV_NAME}" ]; then 
        echo "Environment ${ENV_NAME} exists..." 
        exit 0 
    else 
        mkdir -p ${DEPLOY_DIR}/"${ENV_NAME}" 
    fi 

    #    
    NET=$(sed -e 'a$!d' "${SCRIPT_DIR}"/subnets.txt) 
    sed -i /"$NET"/d "${SCRIPT_DIR}"/subnets.txt 
    echo "$NET" > ${DEPLOY_DIR}/"${ENV_NAME}"/subnets.txt 
    if [ -n "$NET" ] && [ "$NET" != "" ]; then 
        echo "Subnet: $NET" 
        SUBNET="${NET}/${CIDR}" 
    else 
        echo "There are no free subnets..." 
        rm -r "./${DEPLOY_DIR}/${ENV_NAME}" 
        exit 1 
    fi 

    pushd "${DEPLOY_DIR}/${ENV_NAME}" || exit 1 

    #  main.tf terraform        
cat > main.tf << END 
module "base" { 
source = "../../modules/azure" 
env_name = "${ENV_NAME}" 
vnet_address = "${SUBNET}" 
subnet_address = "${SUBNET}" 
} 
END 

    # C backend.tf terraform  ,      state  
cat > backend.tf << END 
terraform { 
    backend "azurerm" { 
        storage_account_name = "terraform-user" 
        container_name = "environments" 
        key = "${ENV_NAME}.tfstate" 
    } 
} 
END 
} 

delete_env() { 
    #       
    if [ -d "${DEPLOY_DIR}/${ENV_NAME}" ]; then 
        NET=$(sed -e '$!d' ./${DEPLOY_DIR}/"${ENV_NAME}"/subnets.txt) 
        echo "Release subnet: ${NET}" 
        echo "$NET" >> ./"${SCRIPT_DIR}"/subnets.txt 
        pushd ./${DEPLOY_DIR}/"${ENV_NAME}" || exit 1 
        popd || exit 1 
        rm -r ./${DEPLOY_DIR}/"${ENV_NAME}" 
    else 
        echo "Environment ${ENV_NAME} does not exist..." 
        exit 1 
    fi 
} 

case "${ACTION}" in 
    create) 
        create_env 
        git_push "${ACTION}" 
        ;; 
    delete) 
        delete_env 

        git_push "${ACTION}" 
        ;; 
    *) 
        usage; exit 1;; 
esac 

      
      



  1. env.sh



    - (\).





  2. :





  3. DEPLOY_DIR



    .





  4. scripts/subnets.txt .





  5. Terraform.





  6. git .





  7. scripts/subnets.txt







scripts/subnets.txt:





172.28.50.0
172.28.51.0
172.28.52.0
...
      
      



. CIDR  scripts/create_env.sh







  1. Kami mendapatkan fondasi yang memungkinkan kami menerapkan stand baru dengan menjalankan pipline di Gitlab CI.





  2. Mengurangi biaya infrastruktur perusahaan kami.





  3. Pengembang tidak menganggur dan dapat membuat serta menghapus stand saat mereka membutuhkannya.





  4. Kami juga mendapat kemampuan untuk membuat mesin virtual di cloud apa pun dengan menulis modul Terraform baru dan sedikit memodifikasi skrip untuk membuat / menghapus lingkungan





  5. Kita dapat bermain dengan pemicu Gitlab  dan menerapkan stand baru dari pipeline tim pengembangan dengan mentransfer versi layanan.








All Articles