Giới thiệu và cách sử dụng Ansistrano

Như các bạn biết thì lâu nay việc triển khai code các bạn thường kết nối lên server rồi sau dó kéo code về, hoặc dùng ftp để tải lên, những cách này khá là thủ công, việc quản lý một dự án thì không sao chứ các chục dự án mà nhó các thông số ip server, thư mục của dự án… đều đó thật là làm lãng phí thời gian của ngưòi quản lý dự án đó, hoặc nếu như bạn nào đã từng triển khai các dự án web mà liên quan đến cân bằng tải(load balancer) thì việc deploy nó cũng khá là phiền phức.

Nếu bạn nào chưa rõ việc triển khai cân bằng tải thì có thể xem một bài viết Cấu hình Load Balancing cho WordPress chính vì vậy có nhiều tool auto deploy đã xuất hiện, như Capitrano, Deployer, Amazon commit, nhưng trong bài viết này chúng tôi sẽ chia sẽ kinh nghiệm sử dụng một công cụ mới đó là Ansistrano

Ngoài ra chúng tôi cũng có một bài viết giới thiệu cách dùng Capitrano, nếu bạn nào thích có thể xem thêm tại đây

Tại sao chúng tôi chọn Ansistrano

Trước khi dùng Ansistrano chúng tôi dùng khá là nhiều Capitrano, nhưng gần đây chúng tôi áp dụng việc triển khai cài đặt các server một cách tự động thông qua công cụ Ansible. Nó được viết bằng python , gsviec love python 🙂 trong khi đó capitrano lại bằng ruby(cá nhân tôi không thích ruby) việc tích hợp ruby rồi lại python và cùng một dự án khiến chúng tôi rất khó chịu, do đó chúng tôi kiếm một giải pháp thây thế cho nó, sau một hồi tìm kiếm google thì thấy ansistrano đáp ứng các tiêu chí chúng tôi mong đợi

  • Những gì làm được trên Capitrano thì Ansistrano đều làm được

  • Ansistrano viết bằng python được tích hợp với Ansible quá tuyệt vời

  • Capitrano phiên bản 2 không còn được hỗ trợ, trong khi phiên bản 3 không có đầy đủ tính năng

Những lý do này chúng tôi quyết định không dùng Capitrano nữa, nhưng nếu các bạn nào không muốn thây đổi thì cũng không sao Capitrano vẫn làm việc tốt.

Cài đặt Ansistrano

Để dùng Ansistrano máy bạn cần phải cài Ansible, nếu bạn chưa có thì hãy vào trang chủ nó chọn phiên bản tương ứng, có khá là nhiều cách cài đặt nhưng có lẽ phổ biến nhất là cài đặt thông qua pip, vì python quản lý các thư viện thông qua nó, giống như composer hay pecl trong php 🙂

[code lang=text]
sudo easy_install pip
sudo pip install ansible

[/code]

sau đó bạn chạy lệnh này để xác nhận có cài đặt thành công hay chưa

[code lang=text]
thientd at gsviec in ~/github/gsviec.video on master*
$ ansible –version
ansible 2.3.1.0
config file = /etc/ansible/ansible.cfg
configured module search path = Default w/o overrides
python version = 2.7.13 (default, May 10 2017, 20:04:36) [GCC 6.3.1 20161221 (Red Hat 6.3.1-1)]

[/code]

Nếu bạn nào đã từng dùng ansible thì sẽ biết là nó có một trang quản lý và chia sẽ các thư viện giữa các lập trình viên với nhau thông qua Ansible Galaxy, thì thằng Ansistrano nó chia sẽ thông qua Ansible Galaxy do đó bạn chỉ cần chạy lệnh bên dưới này để cài đặt:

[code lang=text]
#####
ansible-galaxy install carlosbuenosvinos.ansistrano-deploy carlosbuenosvinos.ansistrano-rollback

[/code]

Các Tính Năng Của Ansistrano

  • Triển khai ứng dụng web một cách chính xác cho bất kỳ số lượng máy chủ nào ta chỉ định theo tiến trình của hàng đợi do ta định nghĩa cho nó.

  • Tự động hóa lưu trữ logs của bất kỳ máy nào khi tương tác với nó chẵn hạn như kiểm tra số lần login, liệt kê bản cập nhật, fix các lỗi bảo mật.

  • Chạy các kịch bản script thông qua giao thức SSH

  • Thực hiện tự động hóa các task

  • Hỗ trợ các infrastructure(cơ sở hạ tầng) Chef-solo, Ánsible…

  • Hiển thị cũng như định dạng các dữ liệu đầu ra (progress, pretty, html, etc).

  • Dễ dàng tích hợp vói công cụ quản lý source như git

  • Hỗ trợ nhiều một trường phát triển

  • Hỗ trợ deploy lên bất ký máy chủ nào trong cùng một cụm máy chủ(subset)

  • Gửi thông tin sau khi deploy qua Slack hay Hipchat

Ansistrano là một công cụ kich bản rất mềm dẽo, nó có thể tích hợp bất kỳ phần mềm nào viết bằng Python do đó bạn có thể tái sử dụng nó trong các dự án python của bạn, nhưng bạn cũng có thể sử dụng cho bất kỳ dự án nào viết bằng java, php, etc

Cấu Trúc

Ansistrano sử dụng một hệ thống phân cấp thư mục được định nghĩa chặt chẽ trên mỗi máy chủ từ xa để tổ chức mã nguồn và dữ liệu triển khai liên quan khác. Các đường dẫn gốc của cấu trúc này có thể được định nghĩa với các biến cầu hình như ansistrano_deploy_from, ansistrano_deploy_to, bạn có thể tham khảo các biến dưới đây:

 

[bash]
vars:
ansistrano_deploy_from: "{{ playbook_dir }}" # Where my local project is (relative or absolute path)
ansistrano_deploy_to: "/var/www/my-app" # Base path to deploy to.
ansistrano_version_dir: "releases" # Releases folder name
ansistrano_current_dir: "current" # Softlink name. You should rarely changed it.
ansistrano_current_via: "symlink" # Deployment strategy who code should be deployed to current path. Options are symlink or rsync
ansistrano_keep_releases: 0 # Releases to keep after a new deployment. See "Pruning old releases".

# Arrays of directories and files to be shared.
# The following arrays of directories and files will be symlinked to the current release directory after the ‘update-code’ step and its callbacks
# Notes:
# * Paths are relative to the /shared directory (no starting /)
# * If your items are in a subdirectory, write the entire path to each shared directory
#
# Example:
# ansistrano_shared_paths:
# – path/to/first-dir
# – path/next-dir
# ansistrano_shared_files:
# – my-file.txt
# – path/to/file.txt
ansistrano_shared_paths: []
ansistrano_shared_files: []

# Shared paths and basedir shared files creation.
# By default the shared paths directories and base directories for shared files are created automatically if not exists. But in some scenarios those paths could be symlinks to another directories in the filesystem, and the deployment process would fails. With these variables you can disable the involved tasks. If you have two or three shared paths, and don’t need creation only for some of them, you always could disable the automatic creation and add a custom task in a hook.
ansistrano_ensure_shared_paths_exist: yes
ansistrano_ensure_basedirs_shared_files_exist: yes

ansistrano_deploy_via: "rsync" # Method used to deliver the code to the server. Options are copy, rsync, git, svn, s3 or download. Copy, download and s3 have an optional step to unarchive the downloaded file which can be used by adding _unarchive. You can check all the options inside tasks/update-code folder!
ansistrano_allow_anonymous_stats: yes

# Variables used in the rsync deployment strategy
ansistrano_rsync_extra_params: "" # Extra parameters to use when deploying with rsync in a single string. Although Ansible allows an array this can cause problems if we try to add multiple –include args as it was reported in https://github.com/ansistrano/deploy/commit/e98942dc969d4e620313f00f003a7ea2eab67e86
ansistrano_rsync_set_remote_user: yes # See [ansible synchronize module](http://docs.ansible.com/ansible/synchronize_module.html). Options are yes, no.
ansistrano_rsync_path: "" # See [ansible synchronize module](http://docs.ansible.com/ansible/synchronize_module.html). By default is "sudo rsync", it can be overwriten with (example): "sudo -u user rsync".

# Variables used in the Git deployment strategy
ansistrano_git_repo: [email protected]:USERNAME/REPO.git # Location of the git repository
ansistrano_git_branch: master # What version of the repository to check out. This can be the full 40-character SHA-1 hash, the literal string HEAD, a branch name, or a tag name
ansistrano_git_repo_tree: "" # If specified the subtree of the repository to deploy
ansistrano_git_identity_key_path: "" # If specified this file is copied over and used as the identity key for the git commands, path is relative to the playbook in which it is used
ansistrano_git_identity_key_remote_path: "" # If specified this file on the remote server is used as the identity key for the git commands, remote path is absolute
# Optional variables, omitted by default
ansistrano_git_refspec: ADDITIONAL_GIT_REFSPEC # Additional refspec to be used by the ‘git’ module. Uses the same syntax as the ‘git fetch’ command.
ansistrano_git_ssh_opts: "-o StrictHostKeyChecking=no" # Additional ssh options to be used in Git

# Variables used in the SVN deployment strategy
# Please note there was a bug in the subversion module in Ansible 1.8.x series (https://github.com/ansible/ansible-modules-core/issues/370) so it is only supported from Ansible 1.9
ansistrano_svn_repo: "https://svn.company.com/project" # Location of the svn repository
ansistrano_svn_branch: "trunk" # What branch from the repository to check out.
ansistrano_svn_revision: "HEAD" # What revision from the repository to check out.
ansistrano_svn_username: "user" # SVN authentication username
ansistrano_svn_password: "Pa$$word" # SVN authentication password
ansistrano_svn_environment: {} # Dict with environment variables for svn tasks (https://docs.ansible.com/ansible/playbooks_environment.html)

# Variables used in the HG deployment strategy
ansistrano_hg_repo: "https://[email protected]/USERNAME/REPO" # Location of the hg repo
ansistrano_hg_branch: "default" # Any branch identifier that works with hg -r, so named branch, bookmark, commit hash…

# Variables used in the download deployment strategy
ansistrano_get_url: https://github.com/someproject/somearchive.tar.gz
ansistrano_download_force_basic_auth: false # no default as this is only supported from Ansible 2.0
ansistrano_download_headers: "" # no default as this is only supported from Ansible 2.0

# Variables used in the S3 deployment strategy
ansistrano_s3_bucket: s3bucket
ansistrano_s3_object: s3object.tgz # Add the _unarchive suffix to the ansistrano_deploy_via if your object is a package (ie: s3_unarchive)
ansistrano_s3_region: eu-west-1
ansistrano_s3_rgw: false # must be Ansible >= 2.2. use Ceph RGW (when set true, ignore ansistrano_s3_region)
ansistrano_s3_url: http://rgw.example.com # when use Ceph RGW, set url
# Optional variables, omitted by default
ansistrano_s3_aws_access_key: YOUR_AWS_ACCESS_KEY
ansistrano_s3_aws_secret_key: YOUR_AWS_SECRET_KEY

# Hooks: custom tasks if you need them
ansistrano_before_setup_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-before-setup-tasks.yml"
ansistrano_after_setup_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-after-setup-tasks.yml"
ansistrano_before_update_code_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-before-update-code-tasks.yml"
ansistrano_after_update_code_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-after-update-code-tasks.yml"
ansistrano_before_symlink_shared_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-before-symlink-shared-tasks.yml"
ansistrano_after_symlink_shared_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-after-symlink-shared-tasks.yml"
ansistrano_before_symlink_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-before-symlink-tasks.yml"
ansistrano_after_symlink_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-after-symlink-tasks.yml"
ansistrano_before_cleanup_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-before-cleanup-tasks.yml"
ansistrano_after_cleanup_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-after-cleanup-tasks.yml"

[/bash]

Trong đó {{ playbook_dir }} là đường dẫn hiện tại của dự án bạn, nếu bạn dùng git để triển khai thì ở ansistrano_git_repo bạn điền repo của dự án bạn vào, nếu sau khi bạn triển khai thành công thì cấu trúc nó có dạng như sau:

 

[bash]
[centos@ip-172-31-78-33 gsviec.video]$ ls -la
total 8
drwxr-xr-x 5 root root 87 Jan 17 07:17 .
drwxr-xr-x. 6 root root 110 Jan 17 03:41 ..
lrwxrwxrwx 1 root root 26 Jan 17 07:17 current -> ./releases/20180117071619Z
-r——– 1 root root 4096 Jan 17 07:17 git_identity_key
drwxr-xr-x 4 root root 52 Jan 17 07:17 releases
drwxr-xr-x 11 root root 4096 Jan 17 04:19 repo
drwxr-xr-x 4 root root 34 Jan 17 03:50 shared
[centos@ip-172-31-78-33 gsviec.video]$

[/bash]

  • current là một symlink chỉ tới phát hành mới nhất. Symlink này được cập nhật vào một triển khai thành công cuối cùng. Nếu triển khai không thành công trong bất kỳ bước nào các current symlink vẫn chỉ tới phát hành trước đó gần nhất.

  • releases chứa tất cả các triển khai trong một thư mục được đặt tên theo kiểu timestamped. Các current symlink sẽ trỏ tới những thư mục này.

  • repo chứa các phiên bản kiểm soát cấu hình hệ thống.

  • shared chứa linked_files và linked_dirs được symlinked vào mỗi bản phát hành. Những thông tin này vẫn tồn tại qua việc triển khai và phát hành. Nó nên được sử dụng cho các tập tin tĩnh và cấu hình database…

Các giai đoạn thực thi của Ansistrano có thể diễn đạt ngắn gọn qua hình ảnh sau:

Ứng dụng vào thực tế

Để cho bạn có cái nhìn rõ hơn chúng ta hãy lấy một bài toán, mà cụ thể ở đây là website gsviec, bạn có thể tải mã nguồn trên github https://github.com/gsviec/video, thì gsiec viết bằng ngôn ngữ php, mà cụ thể là framewok phalconphp nên chúng ta sẽ cài cấu hình tương ứng như cài đặt thư viện trong tập tin composer như thế nào, tạo thư mục cache volt cho phalcon như thế nào,…

Dưới đây là tập tin deploy.yml của gsviec

 

[bash]

– hosts: web
become: true
vars:
ansistrano_deploy_from: "{{ playbook_dir }}/../"
ansistrano_deploy_to: "/srv/www/gsviec.video"
release_var_path: "{{ ansistrano_release_path.stdout }}/var"

# release_upload_path:
ansistrano_current_dir: "current"
ansistrano_current_via: "symlink"
ansistrano_version_dir: "releases" # Releases folder name
ansistrano_keep_releases: 2
ansistrano_deploy_via: git
# Variables used in the Git deployment strategy
ansistrano_git_repo: [email protected]:gsviec/video.git # Location of the git repository
ansistrano_git_branch: "{{ branch_deploy | default(‘master’) }}" # What version of the repository to check out. This can be the full 40-character SHA-1 hash, the literal string HEAD, a branch name, or a tag name
ansistrano_git_repo_tree: "" # If specified the subtree of the repository to deploy
ansistrano_git_identity_key_path: "~/.ssh/id_rsa_macos"

remote path is absolute
ansistrano_after_symlink_tasks_file: "{{ playbook_dir }}/deploy/after-symlink.yml"
ansistrano_after_symlink_shared_tasks_file: "{{ playbook_dir }}/deploy/after-symlink-shared.yml"
roles:
– { role: carlosbuenosvinos.ansistrano-deploy }

[/bash]

như tập tin chúng tôi định nghĩa thư mục web sẽ deploy là /srv/www/gsviec.video, và thự mục /srv/www/gsviec.video/current sẽ là thự mục sẽ được nginx hay apache trỏ vào, mặc định nếu bạn không truyền tham số branch_deploy thì nó sẽ lấy nhánh master làm nhánh mặc định khi triển khai code lên server của bạn, ansistrano_git_repo và ansistrano_git_identity_key_path chính là repo git và key ssh dùng để xác thực khi kết nối repo git của bạn.

Ngoài ra như bạn biết sau khi triển khai code xong bạn cần phải cài đặt các thư viện vendor trong php, thì bạn có thể định nghĩa trong tập tin after-symlink-shared.yml

[bash]
– name: Install Composer dependencies
composer:
command: install
working_dir: ‘{{ ansistrano_release_path.stdout }}’

[/bash]

Như chúng tôi đã nói ansistrano là một thư viện của ansible do đó, sau khi bạn cấu hình xong thì chỉ cần chạy lệnh duới đây để triển khai code lên server staging của bạn:

[code lang=text]
#Deploy to staging
cd opsfiles/ansible
ansible-playbook -i hosts/staging/inventory deploy.yml

[/code]

Nếu bạn muốn triển khai lên môi trường production thì chỉ cần chạy lệnh dưới đây

[code lang=text]
#Deploy to prd
cd opsfiles/ansible
ansible-playbook -i hosts/production/inventory deploy.yml

[/code]

Nếu bạn muốn triển khai cho nhánh khác của repo bạn thì bạn thêm tham số -e, ví dụ triển khai cho nhánh develop

[code lang=text]
ansible-playbook -i hosts/staging/inventory deploy.yml -e branch_deploy=develop

[/code]

Chúc mừng bạn như vậy là bạn đã thành công triển khai ứng dụng lên server của bạn. Công việc còn lại là của bạn để cấu hình cho ứng dụng có thể chạy được trên server như cấu hình nginx hay apache, tất nhiên cái này có thể thực hiện được thông qua ansible nhưng trong khuôn khỗ bài viết này chúng tôi tạm thời dừng tại đây.

Mở rộng

Một trong những khó khăn của việc dùng ansible hay ansistrano đó là cài đặt trên window, tất nhiên chúng ta vẫn có thể cài đặt được nhưng trong thực tế tại các công ty thì người ta sẽ setup một con CI/CD như jenkin chẳng hạn để giúp cho các developer hoặc các designer mà muốn triển khai tính năng mà họ đã phát triển trên git của họ một cách nhanh chóng, họ không cần phải cài đặt ansible hay ansistrano gì cả, trong bài viết thứ 2 chúng tôi sẽ giúp các bạn làm chuyên đó, ngay lúc này hãy xem vài hình ảnh demo về nó

Cấu hình jenkin cho môi trường production:

Giao diện triển khai code lên server của gsviec trên jenkin, bạn chỉ cần nhập tên nhánh cần triển khai sau đó bấm bút build thế là xong, quá dễ phải không nào:)

Giao diện hiển thị trên jenkin khi bạn triển khai code xong, nếu thành công hay thất bại nó sẽ hiển thị cho bạn biết

Kết Luận

Ansistrano là một công cụ khá hay và dễ sử dụng cũng như cấu hình những gì bạn muốn mà không cần phải lên server, nó giúp bạn dễ dàng triển khai một hoặc nhiều ứng dụng của bạn lên remote server.

Ansistrano giúp bạn tiết kiệm nhiều thời gian cho quá trình triển khai ứng dụng. Toàn bộ mã nguồn demo ansistrano chúng tôi để nó trên github bạn có thể lấy tại đây, bạn đã chuẩn bị triển khai cho dự án kế tiếp với Ansitrano chưa, hãy chia sẽ những suy nghĩ của bạn về nó dưới đây:)

 

 

Leave a Comment

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

Scroll to Top