كتاب "Terraform: البنية التحتية على مستوى الكود"

صورةمرحبا ، هابروجيتلي! الكتاب مخصص لكل شخص مسؤول عن الرمز المكتوب بالفعل. ينطبق هذا على مسؤولي النظام ، ومتخصصي العمليات ، والإصدار ، والمهندسين SR ، و DevOps ، ومطوري البنية التحتية ، ومطوري الدورة الكاملة ، وقادة الفرق الهندسية ، والمديرين الفنيين. مهما كان موقفك ، إذا كنت مشتركًا في البنية التحتية ، ونشر التعليمات البرمجية ، وتكوين الخوادم ، وقياس التكتلات ، ونسخ البيانات احتياطيًا ، ومراقبة التطبيقات والرد على المكالمات في الساعة الثالثة صباحًا ، فهذا الكتاب لك.

يشار إلى هذه المسؤوليات معًا عادةً باسم الأنشطة التشغيلية (أو إدارة النظام). في السابق ، كان المطورين الذين يعرفون كيفية كتابة التعليمات البرمجية ولكنهم لم يفهموا إدارة النظام قد تم استيفائهم غالبًا ؛ غالبًا ما صادف مسؤولو النظام دون القدرة على كتابة التعليمات البرمجية. بمجرد أن كان هذا الفصل مقبولًا ، ولكن في العالم الحديث ، والذي لم يعد من الممكن تخيله بدون الحوسبة السحابية وحركة DevOps ، يحتاج أي مطور تقريبًا إلى مهارات إدارية ، ويجب أن يكون أي مسؤول نظام قادرًا على البرمجة.

لن تتعلم فقط كيفية إدارة البنية التحتية في شكل رمز باستخدام Terraform ، ولكن أيضًا ستتعلم كيف تتناسب مع المفهوم العام لـ DevOps. إليك بعض الأسئلة التي يمكنك الإجابة عنها بقراءة هذا الكتاب.

  • لماذا تستخدم IaC على الإطلاق؟
  • , , ?
  • Terraform, Chef, Ansible, Puppet, Salt, CloudFormation, Docker, Packer Kubernetes?
  • Terraform ?
  • Terraform, ?
  • Terraform, ?
  • Terraform?
  • Terraform ?
  • Terraform ?

2017 . 2019- , ! . , .

, , , Terraform, .

  • Terraform. , Terraform 0.8. Terraform 0.12. , . , !
  • . Terraform. , , , , , , , .
  • . Terraform . , , — , .
  • . 8 , Terraform . , , , : , .
  • HCL2. Terraform 0.12 HCL HCL2. ( ${…}!), , , null, for_each for, . HCL2, 5 6.
  • . Terraform 0.9 . Terraform . Terraform 0.9 , ; 0.10 . 3.
  • Terraform. Terraform 0.10 ( AWS, GCP, Azure . .). , . terraform init , . 2 7.
  • . 2016 Terraform (AWS, GCP Azure). 100, , , 1. (, Alicloud, Oracle Cloud Infrastructure, VMware vSphere .), , (GitHub, GitLab BitBucket), (MySQL, PostreSQL InfluxDB), ( DataDog, New Relic Grafana), Kubernetes, Helm, Heroku, Rundeck Rightscale . , : , AWS , , CloudFormation!
  • Terraform. 2017 HashiCorp Terraform (registry.terraform.io) — , Terraform, . 2018 . Terraform 0.11 . « » . 153.
  • . Terraform 0.9 : , , errored.tfstate. Terraform 0.12 . , , .
  • . , (. « » . 144), « » (, « Terraform» . 242), plan apply (. « » . 64), create_before_destroy, count, (. «» . 160), , provider .

. Terraform


(يتم إيلاء المزيد من الاهتمام لقضايا الاختبار التلقائي في الكتاب لاحقًا)

يمتلئ عالم DevOps بمخاوف مختلفة: يخشى الجميع السماح للأشياء بالعمل أو فقدان البيانات أو الاختراق. عند إجراء أي تغيير ، تسأل نفسك دائمًا عن العواقب التي ستترتب عليها. هل ستتصرف في جميع البيئات؟ هل سيتسبب في انقطاع آخر؟ وإذا حدث ذلك ، فكم ستبقى في العمل هذه المرة لإصلاحه؟ مع نمو الشركة ، هناك المزيد على المحك ، مما يجعل عملية النشر أسوأ وتزيد من خطر الأخطاء. تحاول العديد من الشركات تقليل هذا الخطر من خلال عمليات نشر أقل تكرارًا ، ولكن نتيجة لذلك ، يصبح كل عملية نشر فردية أكبر وأكثر عرضة للأخطاء.

إذا كنت تدير بنيتك الأساسية في شكل رمز ، فلديك طريقة أفضل لتقليل المخاطر: الاختبارات. هدفهم هو منحك ثقة كافية لإجراء التغييرات. الكلمة الأساسية هنا هي الثقة: لا يمكن لأي اختبارات أن تضمن عدم وجود أخطاء ، لذلك من المرجح أن تتعامل مع الاحتمالات. إذا كان بإمكانك تصوير جميع عمليات البنية الأساسية والنشر الخاصة بك ككود ، يمكنك اختبار هذا الرمز في بيئة اختبار. إذا نجحت ، فهناك احتمال كبير بأن يعمل الرمز نفسه في بيئة صناعية. في عالم من الخوف وعدم اليقين ، فإن الاحتمالية العالية والثقة باهظة الثمن.

في هذا الفصل ، سنتناول عملية اختبار كود البنية التحتية ، اليدوية والتلقائية ، مع التركيز على الأخير.

الاختبارات اليدوية:

  • أساسيات الاختبار اليدوي ؛
  • تنظيف الموارد بعد الاختبارات.

الاختبارات المؤتمتة:

  • اختبارات الوحدة
  • اختبارات التكامل ؛
  • اختبارات من طرف إلى طرف ؛
  • طرق الاختبار الأخرى.

الاختبارات اليدوية


عند التفكير في كيفية اختبار Terraform Code ، من المفيد رسم بعض أوجه التشابه مع رمز الاختبار المكتوب بلغات برمجة للأغراض العامة مثل Ruby. تخيل أنك تكتب خادم ويب روبي بسيط في ملف web-server.rb:

class WebServer < WEBrick::HTTPServlet::AbstractServlet
  def do_GET(request, response)
     case request.path
     when "/"
         response.status = 200
         response['Content-Type'] = 'text/plain'
         response.body = 'Hello, World'
     else
         response.status = 404
         response['Content-Type'] = 'text/plain'
         response.body = 'Not Found'
     end
  end
end

سيعيد هذا الرمز استجابة 200 OK مع نص Hello، World لعنوان URL /؛ بالنسبة لأي عنوان آخر ، ستكون الإجابة 404. كيف يمكنك اختبار هذا الرمز يدويًا؟ عادة ، يتم إضافة المزيد من التعليمات البرمجية لتشغيل خادم الويب محليًا:

#   ,      
#  ,       
if __FILE__ == $0
  #      8000
  server = WEBrick::HTTPServer.new :Port => 8000
  server.mount '/', WebServer

  #    Ctrl+C
  trap 'INT' do server.shutdown end

  #  
  server.start
end

إذا قمت بتشغيل هذا الملف في المحطة الطرفية ، فسيتم تحميل خادم الويب على المنفذ 8000:

$ ruby web-server.rb
[2019-05-25 14:11:52] INFO WEBrick 1.3.1
[2019-05-25 14:11:52] INFO ruby 2.3.7 (2018-03-28) [universal.x86_64-darwin17]
[2019-05-25 14:11:52] INFO WEBrick::HTTPServer#start: pid=19767 port=8000

للتحقق من تشغيل هذا الخادم ، يمكنك استخدام المتصفح أو curl:

$ curl localhost:8000/
Hello, World

$ curl localhost:8000/invalid-path
Not Found

تخيل الآن أننا قمنا بتغيير هذا الرمز عن طريق إضافة نقطة إدخال / api إليها والتي ترجع 201 Created ونصًا بتنسيق JSON:

class WebServer < WEBrick::HTTPServlet::AbstractServlet
  def do_GET(request, response)
     case request.path
     when "/"
         response.status = 200
         response['Content-Type'] = 'text/plain'
         response.body = 'Hello, World'
     when "/api"
         response.status = 201
         response['Content-Type'] = 'application/json'
         response.body = '{"foo":"bar"}'
     else
         response.status = 404
         response['Content-Type'] = 'text/plain'
         response.body = 'Not Found'
     end
  end
end

لاختبار هذا الرمز المحدث يدويًا ، اضغط على Ctrl + C وأعد تشغيل خادم الويب عن طريق تشغيل البرنامج النصي مرة أخرى:

$ ruby web-server.rb
[2019-05-25 14:11:52] INFO WEBrick 1.3.1
[2019-05-25 14:11:52] INFO ruby 2.3.7 (2018-03-28) [universal.x86_64-darwin17]
[2019-05-25 14:11:52] INFO WEBrick::HTTPServer#start: pid=19767 port=8000
^C
[2019-05-25 14:15:54] INFO going to shutdown ...
[2019-05-25 14:15:54] INFO WEBrick::HTTPServer#start done.

$ ruby web-server.rb
[2019-05-25 14:11:52] INFO WEBrick 1.3.1
[2019-05-25 14:11:52] INFO ruby 2.3.7 (2018-03-28) [universal.x86_64-darwin17]
[2019-05-25 14:11:52] INFO WEBrick::HTTPServer#start: pid=19767 port=8000

للتحقق من الإصدار الجديد ، يمكنك مرة أخرى استخدام الأمر curl:

$ curl localhost:8000/api
{"foo":"bar"}

أساسيات الاختبار اليدوي


كيف سيبدو هذا النوع من الاختبارات اليدوية في Terraform؟ على سبيل المثال ، من الفصول السابقة ، لا يزال لديك رمز لنشر ALB. فيما يلي مقتطف من ملف الوحدات / الشبكات / الألبوم / main.tf:

resource "aws_lb" "example" {
   name                     = var.alb_name
   load_balancer_type = "application"
   subnets                  = var.subnet_ids
   security_groups      = [aws_security_group.alb.id]
}

resource "aws_lb_listener" "http" {
   load_balancer_arn = aws_lb.example.arn
   port                      = local.http_port
   protocol                = "HTTP"

   #      404
   default_action {
      type = "fixed-response"

      fixed_response {
        content_type = "text/plain"
        message_body = "404: page not found"
        status_code = 404
      }
    }
}

resource "aws_security_group" "alb" {
   name = var.alb_name
}

# (...)

إذا قارنت هذه القائمة برمز روبي ، يمكنك أن ترى اختلافًا واحدًا واضحًا: AWS ALB ، والمجموعات المستهدفة ، والمستمعون ، ومجموعات الأمان ، ولا يمكن نشر أي موارد أخرى على جهاز الكمبيوتر الخاص بك.

فيما يلي الاستنتاج الرئيسي حول الاختبار رقم 1: لا يمكن إجراء اختبار رمز Terraform محليًا.

لا ينطبق هذا فقط على Terraform ، ولكن أيضًا على معظم أدوات IaC. الطريقة العملية الوحيدة لإجراء الاختبار اليدوي في Terraform هي نشر الكود في بيئة حقيقية (أي في AWS). وبعبارة أخرى ، فإن إطلاق تطبيق terraform بشكل مستقل وتدمير أوامر terraform التي عملت عليها أثناء قراءة الكتاب هو اختبار يدوي في Terraform.

هذا أحد الأسباب التي تجعل من المهم جدًا وجود أمثلة سهلة النشر في مجلد الأمثلة لكل وحدة (انظر الفصل 6). لاختبار وحدة الألبوم ، أسهل طريقة هي استخدام رمز العرض التوضيحي الذي قمت بإنشائه في الأمثلة / الألبوم:

provider "aws" {
   region = "us-east-2"

   #     AWS  2.x
   version = "~> 2.0"
}

module "alb" {
    source = "../../modules/networking/alb"

    alb_name = "terraform-up-and-running"
    subnet_ids = data.aws_subnet_ids.default.ids
}

لنشر هذا المثال ، تحتاج إلى تشغيل أمر تطبيق terraform ، كما فعلت بشكل متكرر:

$ terraform apply

(...)

Apply complete! Resources: 5 added, 0 changed, 0 destroyed.

Outputs:

alb_dns_name = hello-world-stage-477699288.us-east-2.elb.amazonaws.com

في نهاية النشر ، يمكنك استخدام أداة مثل curl ، على سبيل المثال ، للتأكد من أن ALB يُرجع 404 افتراضيًا:

$ curl \
   -s \
   -o /dev/null \
   -w "%{http_code}" \
hello-world-stage-477699288.us-east-2.elb.amazonaws.com

404

فحص البنية التحتية

, HTTP, , , curl HTTP-. . , MySQL, MySQL. VPN-, VPN. , , SSH - . . , , . , .

دعني أذكرك: ALB يُرجع 404 بسبب عدم وجود قواعد استماع أخرى في التكوين ، والإجراء الافتراضي في وحدة الألب يحتوي على استجابة 404:

resource "aws_lb_listener" "http" {
   load_balancer_arn = aws_lb.example.arn
   port                      = local.http_port
   protocol                = "HTTP"

   #      404
   default_action {
      type = "fixed-response"

      fixed_response {
       content_type = "text/plain"
       message_body = "404: page not found"
       status_code = 404
      }
   }
}

لذا ، فأنت تعرف بالفعل كيفية تشغيل واختبار الرمز الخاص بك. الآن يمكنك البدء في إجراء التغييرات. في كل مرة تقوم فيها بتغيير شيء ما (بحيث ، على سبيل المثال ، إرجاع الإجراء الافتراضي 401) ، تحتاج إلى استخدام الأمر terraform application لنشر الرمز الجديد:

$ terraform apply

(...)

Apply complete! Resources: 0 added, 1 changed, 0 destroyed.

Outputs:

alb_dns_name = hello-world-stage-477699288.us-east-2.elb.amazonaws.com

للتحقق من الإصدار الجديد ، يمكنك إعادة تشغيل curl:

$ curl \
   -s \
   -o /dev/null \
   -w "%{http_code}" \
   hello-world-stage-477699288.us-east-2.elb.amazonaws.com
401

عند الانتهاء ، قم بتشغيل الأمر terraform destruction لإزالة الموارد:

$ terraform destroy

(...)

Apply complete! Resources: 0 added, 0 changed, 5 destroyed.

بمعنى آخر ، عند العمل مع Terraform ، يحتاج كل مطور إلى عينات جيدة من التعليمات البرمجية للاختبار وبيئة تطوير حقيقية (مثل حساب AWS) ، والذي يعمل كمكافئ للكمبيوتر المحلي ويستخدم لإجراء الاختبارات. في عملية الاختبار اليدوي ، ستضطر على الأرجح إلى إنشاء وإزالة عدد كبير من مكونات البنية التحتية ، وقد يؤدي ذلك إلى العديد من الأخطاء. في هذا الصدد ، يجب عزل البيئة تمامًا عن البيئات الأكثر استقرارًا والمخصصة للاختبار النهائي ، وخاصة للتطبيقات الصناعية.

بالنظر إلى ما سبق ، أوصي بشدة أن يقوم كل فريق تطوير بإعداد بيئة معزولة يمكنك من خلالها إنشاء وإزالة أي بنية أساسية دون عواقب. لتقليل احتمالية حدوث تضارب بين المطورين المختلفين (تخيل أن مطورين يحاولان إنشاء موازن تحميل يحمل نفس الاسم) ، سيكون الحل المثالي هو إعطاء كل عضو في الفريق بيئة منفصلة ومعزولة تمامًا. على سبيل المثال ، إذا كنت تستخدم Terraform مع AWS ، فيجب أن يكون لكل مطور حسابه الخاص حيث يمكنه اختبار كل ما يريده.

تنظيف الموارد بعد الاختبارات


يعد وجود العديد من البيئات المعزولة أمرًا ضروريًا لتحقيق إنتاجية عالية للمطورين ، ولكن إذا لم تكن حذرًا ، يمكنك تجميع الكثير من الموارد الإضافية التي ستؤدي إلى فوضى في جميع بيئاتك وتكلفك مبلغًا إجماليًا.
للحفاظ على التكاليف تحت السيطرة ، قم بتنظيف الوسائط المعزولة بانتظام. هذا هو الاستنتاج الرئيسي حول الاختبار رقم 2 .

كحد أدنى ، يجب عليك إنشاء مثل هذه الثقافة في الفريق عندما يقوم المطورون ، بعد الاختبار ، بحذف كل شيء قاموا بنشره باستخدام أمر تدمير terraform. قد يكون من الممكن العثور على أدوات لتنظيف الموارد الزائدة أو القديمة التي يمكن تشغيلها على أساس منتظم (على سبيل المثال ، استخدام cron). فيما يلي بعض الأمثلة لبيئات النشر المختلفة.

  • cloud-nuke (http://bit.ly/2OIgM9r). , . AWS ( Amazon EC2 Instances, ASG, ELB . .). (Google Cloud, Azure) . — , . , cloud-nuke cron, . , , , :

    $ cloud-nuke aws --older-than 48h
  • Janitor Monkey (http://bit.ly/2M4GoLB). , AWS , ( — ). , , , . Netflix Simian Army, Chaos Monkey . , Simian Army , : , Janitor Monkey Swabbie (http://bit.ly/2OLrOLb).
  • aws-nuke (http://bit.ly/2ZB8lOe). هذه أداة مفتوحة المصدر لحذف جميع محتويات حساب AWS. يتم تحديد الحسابات والموارد المراد حذفها في ملف التكوين بتنسيق YAML:

    #   
    regions:
    - us-east-2
    
    #    
    accounts:
       "111111111111": {}
    
    #    
    resource-types:
       targets:
       - S3Object
       - S3Bucket
       - IAMRole

    يبدأ Aws-nuke على النحو التالي:

    $ aws-nuke -5c config.yml

الاختبارات المؤتمتة


مفهوم الاختبار التلقائي هو أن الاختبارات مكتوبة لاختبار سلوك الكود الحقيقي. في الفصل 8 ، ستتعلم أنه باستخدام خادم CI ، يمكن تشغيل هذه الاختبارات بعد تنفيذ كل فرد. إذا لم يكتمل التثبيت ، يمكن التراجع عنه أو تصحيحه على الفور. وبالتالي ، سيتم تشغيل التعليمات البرمجية الخاصة بك دائمًا.

هناك ثلاثة أنواع من الاختبارات الآلية.

  • . — . , . (, , - ) mock-. (, mock- , ) , .
  • . . , . mock-: , , , , , , , mock-.
  • . (, , , ) . : , Selenium . - mock-, ( , ).

كل نوع من أنواع الاختبارات له غرضه الخاص ، وبمساعدته يمكنك تحديد جميع أنواع الأخطاء ، لذلك يجب استخدامها معًا. اختبارات الوحدة سريعة وتسمح لك بالحصول على الفور على فكرة عن التغييرات التي تم إجراؤها والتحقق من مجموعة متنوعة من المجموعات. يمنحك هذا الثقة في أن المكونات الأولية للشفرة (وحدات فردية) تتصرف كما كنت تتوقع. ومع ذلك ، فإن حقيقة أن الوحدات تعمل بشكل صحيح بشكل منفصل لا يعني على الإطلاق أنها يمكن أن تعمل معًا ، لذلك ، للتأكد من أن المكونات الأولية الخاصة بك متوافقة ، هناك حاجة إلى اختبارات التكامل. من ناحية أخرى ، لا يضمن السلوك الصحيح لأجزاء مختلفة من النظام أن يعمل هذا النظام كما يجب أن يعمل بعد نشره في بيئة صناعية ، لذلك من خلال الاختبارات مطلوبة لاختبار التعليمات البرمجية الخاصة بك في ظروف قريبة من الظروف الحقيقية.

»المزيد من المعلومات حول الكتاب يمكن الاطلاع على الموقع الإلكتروني للناشر
» المحتويات
» مقتطفات

لKhabrozhiteley 25٪ خصم القسيمة - Terraform

عند دفع النسخة الورقية من الكتاب، يتم إرسال الكتاب الالكتروني عن طريق البريد الإلكتروني.

All Articles