Giaosucan's blog - Chia sẻ kiến thức theo cách bá đạo

Ticker

20/recent/ticker-posts

Giải pháp build AMI để đạt zero downtime deployment

zero-downtime-500 - Digitally Infinite: Cloud Partner

ABC là một công ty nổi tiếng ở US chuyên cung cấp các giải pháp ERP cho các công ty thương mại điện tử trên toàn thế giới.

Sản phẩm của công ty được deploy trên Cloud infra (AWS và Google Cloud), gồm 2 layer, application layer (frontend & backend) và service layer (elastic search, Hadoop, mongodb)…

2 layer này được deploy trên một hoặc nhiều EC2 được chạy tự động bằng Jenkins jobs. Mỗi khi có khách hàng mới, DevOps engineer sẽ provision một infra mới (VPC, EC2, Route53…) và deploy app lên infra này. 

Việc provision infra cũng được thực hiện tự động bằng python code (Infra as Code), leverage AWS API. 

Do nhu cầu của khách hàng, application được nâng cấp version và deploy daily bằng các job tự động. Do số lượng server ec2 có thể lên tới hàng nghìn, nên công cụ Configuration Management là SaltStack được sử dụng để thực hiện việc deploy app 

SaltStack hoạt động theo mô hình Master/Minion, từ Salt-master có thể thực hiện các command deployment trên nhiều server cùng một lúc (ví dụ như install các service, application, tạo các folder, copy file từ salt-master tới minion)

SaltStack - Architecture - Tutorialspoint

Các command deploy sẽ được viết thành các state file sls 

Ví dụ state file ở dưới sẽ install httpd-service lên nhiều minion

httpd-service:
pkg.installed:
- names:
- httpd
- httpd-devel
service.running:
- name: httpd
- enable: True

Tuy nhiên mỗi khi deploy version mới, các saltstate mất khá nhiều thời gian để thực hiện bao gồm việc re-install lại các service sau đó là re-install lại application new version. Dẫn tới hệ thống bị down-time trong vòng 1 -2 tiếng.

Bài toán đặt ra làm thế nào có thể giảm thời gian down-time này xuống. thậm chí thực hiện được Zero-DownTime

Sau nhiều nghiên cứu và thảo luận, nhận thấy layer service như Hadoop, elastic-search không thay đổi, việc nâng cấp version chỉ xảy ra ở layer app. Nên thay vì deploy toàn bộ 2 layer lên cùng 1 EC2, sẽ deploy tách biệt ra thành 2 cụm server riêng biệt.

Application server và Service server. Service layer sẽ được deploy một lần duy nhất, việc deploy app sẽ được thực hiện trên application server. Salt-master sẽ bị loại bỏ thay vào đó là sử dụng kiến trúc salt-masterless. Tức là một server sẽ kiêm cả master lẫn minion

Application và Service được build thành AMI sử dụng tool Packer. Các EC2 sẽ được provision từ những AMI này

Packer là một công cụ để tạo ra các images trên nhiều platform khác nhau, bao gồm AWS, GCP, Azure, Digital Ocean,.. hay thậm chí là cả VMWare và Docker. Các AMI được viết dưới dạng Packer template json để thực hiện việc build AMI

Ví dụ về một packer template

{
"variables": {
"aws_access_key": "",
"aws_secret_key": ""
},
"builders": [
{
"type": "amazon-ebs",
"access_key": "{{user `aws_access_key`}}",
"secret_key": "{{user `aws_secret_key`}}",
"region": "us-east-1",
"source_ami_filter": {
"filters": {
"virtualization-type": "hvm",
"name": "ubuntu/images/*ubuntu-xenial-16.04-amd64-server-*",
"root-device-type": "ebs"
},
"owners": ["099720109477"],
"most_recent": true
},
"instance_type": "t2.micro",
"ssh_username": "ubuntu",
"ami_name": "packer-example {{timestamp}}"
}
],
"provisioners": [
{
"type": "shell",
"inline": ["echo foo"]
}
]
}

Phương pháp provision infra cũng được thay đổi, thay vì sử dụng AWS API viết bằng python như trước. Một công cụ là OPS CLI được sử dụng

ops-cli is a python wrapper for TerraformAnsible and SSH for cloud automation.

Cách provision infra truyền thống sử dụng Terraform có nhiều nhược điểm khi provision infra trên nhiều môi trường dev, qa, prod do code bị trùng lặp. Do đó Adobe đã phát triển công cụ ops-cli để giải quyết nhược điểm trên.

Trong Ops-cli, code terraform được viết dưới dạng Jinja template, developer sẽ define infra dưới dạng YAML template kiểu như

terraform:
boto_profile: my-aws-profile
paths:
aws-eks: compositions/generic/aws-eks
helm-init: compositions/generic/helm-init
helm: compositions/generic/helm
state:
type: local # store terraform state files on local disk
# type: s3 # store terraform state files on S3 bucket
# kms_arn: 'arn:aws:kms:us-east-1:111111222222:key/ddddddddd-3333-4444-aaaa-bbbbbbbbbbbb' # ARN of KMS key used for S3 encryption
vars:
terraform_var1: ''
kubernetes:
version: 1.11
cluster_id: mykubernetescluster # change the cluster name here
environment: stage
aws:
profile: my-aws-profile # enter the right aws profile
region: us-east-1
account_id: 11111111111 # enter your AWS account id here. This is used for the cluster-autoscaler helm chart.
short_region: va6
availability_zones: '["us-east-1a", "us-east-1b", "us-east-1c", "us-east-1d"]'
allow_my_ip: "192.168.0.1/32" # enter your public ip (eg. by using http://ipv4.icanhazip.com)
tags:
Cluster: mykubernetescluster
worker_nodes:
instance_type: m5.large
ami_id: ami-0b4eb1d8782fc3aea
max_size: 2
min_size: 2
helm:
tiller_version: 2.12.3

Ops cli sẽ tự động render ra terraform code base on jinja và template này để loại bỏ việc duplicate code

Như vậy mỗi khi deploy version mới của app, ops cli sẽ launch ra một application server mới dựa trên AMI đã có sẵn, run script salt-stack trực tiếp trong server đó để install app version. Sau khi server mới chạy ổn định, load balancer sẽ route request sang server mới và terminate server cũ đi.

Đăng nhận xét

0 Nhận xét