Category: Cloud

  • Triển khai angular web với AWS CDK

    Triển khai angular web với AWS CDK

    Ở phần đầu của series, mình đã giới thiệu AWS CDK là gì. Nay để hiểu rõ nó hơn mình sẽ giới thiệu cách triển khai 1 web angular với AWS CDK.

    Chuẩn bị

    • Chuẩn bị sẵn account AWS
    • Cài đặt NodeJS
    • Cài đặt Typescript: npm i -g typescript
    • Cài đặt AWS CLI
    • Cấu hình AWS client: aws configure. Bạn sẽ cần nhập thông tin access key ID, secret access key và aws region. Chi tiết cấu hình bạn có tìm ở đây
    • Cài đẳt AWS CDK: npm install -g aws-cdk

    Thực hiện

    • Tạo một thư mục static_web_cdk.

    • Trong thư mục này tạo 2 thư mục con, 1 cái angular-sample-web cho website và 1 cái infrastructure cho phần infra.

    Build source code Angular

    • Di chuyển đến thư mục ngular-sample-web. Trong thư mục này mình sẽ download sample từ trên trang chủ Angular về để sử dung Xem chi tiết ở đây.

    web1

    • Di chuyển đến thư mục infrastructure

    • Khơi tạo source code infrastructure: cdk init app --language typescript. Lệnh này sẽ gen ra sample code cho chúng ta.

    web2

    • Mở file bin/infrastructure.ts, thêm stackName và uncomment phần env. Phần env này chúng sẽ sử dụng mặc định như bên dưới.
    #!/usr/bin/env node
    import 'source-map-support/register';
    import * as cdk from '@aws-cdk/core';
    import { InfrastructureStack } from '../lib/infrastructure-stack';
    
    const app = new cdk.App();
    new InfrastructureStack(app, 'InfrastructureStack', {
      /* If you don't specify 'env', this stack will be environment-agnostic.
       * Account/Region-dependent features and context lookups will not work,
       * but a single synthesized template can be deployed anywhere. */
      stackName: 'web-static-stack',
      /* Uncomment the next line to specialize this stack for the AWS Account
       * and Region that are implied by the current CLI configuration. */
      env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION },
    
      /* For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html */
    });
    
    • Bây giờ mở file /lib/infrastructure-stack.ts nơi chúng ta sẽ khai báo các dịch vụ của stack.

    Khai báo các thành phần của Stack

    Để triển khai Angular web static mình sử dụng các dịch vụ CloudFront và S3. CloudFront sẽ access vào private S3 thông qua OAI (Origin Access Identity). Vậy thì Stack cần phải code những gì mọi người theo dõi bên dưới nhé.

    • Cài đặt thư viện @aws-cdk/aws-s3 để sử dụng được dịch vụ s3.
    • Cài đặt thư viện @aws-cdk/aws-cloudfront để sử dụng dịch vụ cloudfront.
    • Cài đặt thư viện @aws-cdk/aws-iam để sử dụng khai báo Policy cho S3
    • Trong file lib/infrastructure-stack.ts, chúng ta sẽ cần import các thư viện phía trên vào. Sau đó ở sau ta sẽ cần khai báo các dịch vụ bên duới dòng comment //The code that defines your stack goes here:
    import * as cdk from '@aws-cdk/core';
    import { BlockPublicAccess, Bucket, BucketEncryption } from '@aws-cdk/aws-s3';
    import { CloudFrontWebDistribution, OriginAccessIdentity } from '@aws-cdk/aws-cloudfront';
    import { PolicyStatement } from '@aws-cdk/aws-iam';
    
    export class InfrastructureStack extends cdk.Stack {
      constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);
    
        // The code that defines your stack goes here
        // Khai báo S3
        const myBucket = new Bucket(this, "static-website-bucket", {
          bucketName: 'static-web-sample-s3',
          versioned: true,
          encryption: BucketEncryption.S3_MANAGED,
          blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
          websiteIndexDocument: "index.html"
        });
    
        // Khai báo OAI
        const oia = new OriginAccessIdentity(this, 'OIA', {
          comment: "Created by CDK"
        });
    
        // Khai báo Policy cho S3
        const policyStatement = new PolicyStatement();
        policyStatement.addActions('s3:GetObject');
        policyStatement.addResources(`${myBucket.bucketArn}/*`);
        policyStatement.addCanonicalUserPrincipal(oia.cloudFrontOriginAccessIdentityS3CanonicalUserId);
        myBucket.addToResourcePolicy(policyStatement);
    
        // Khai báo CloudFront
        new CloudFrontWebDistribution(this, 'static-website-cf', {
          originConfigs: [
            {
              s3OriginSource: {
                s3BucketSource: myBucket,
                originAccessIdentity: oia
              },
              behaviors: [
                { isDefaultBehavior: true }
              ]
            }
          ]
        });
    
        // Output giá trị DNS của CloudFront
        new CfnOutput(this, 'CloudFrontDNS', {
          value: cfWebStatic.distributionDomainName
        })
      }
    }
    
    
    • Tiêp theo chúng ta sẽ phần khai báo deploy. Bạn sẽ cần cài thư viện @aws-cdk/aws-s3-deployment và thêm import * as s3Deployment from '@aws-cdk/aws-s3-deployment' vào file stack và khai báo deploy như bên dưới:
    const deployment = new s3Deployment.BucketDeployment(this, "deployStaticWebsite", {
          sources: [s3Deployment.Source.asset("../angular-sample-web/dist")],
          destinationBucket: myBucket,
        });
    
    • Thuộc tính s3Deployment.Source.asset("../angular-sample-web/dist") là nơi mọi người sẽ cần update tới đúng vị trị source code mình đang dùng.

    Triển khai

    Bây giờ chúng ta sẽ cần triển khai stack này tới AWS:

    • Di chuyển đến thư mục angular-sample-web

    • Cài đặt các thư viện npm i

    • Build Angular app ng build --prod. Lúc này bundle source code sẽ được gen ra trong thư mục dist

    • Sau khi build xong Angular app thì di chuyển đến thư mục infrastructure

    • Trên cửa sổ command gõ lệnh: cdk boostrap. Thư mục cdk.out sẽ được tạo ra. Nó sẽ bao gồm code phần website và infrastructure template.

    The first time you deploy an AWS CDK app into an environment (account/region), you’ll need to install a “bootstrap stack”. This stack includes resources that are needed for the toolkit’s operation. For example, the stack includes an S3 bucket that is used to store templates and assets during the deployment process.

    • Chạy lệnh cdk synth. Nó sẽ tổng hợp lại CloudFormation template cho stack.
    • Chạy lệnh cdk deploy
    • Nhập y để tiếp tục triển khai
    • Sau khi đã hoàn thành, chúng ta tới console của dịch vụ CloudFormation. Chúng ta sẽ thấy có 2 stack được tạo ra là CDKToolkit và web-static-stack

    web4

    • Bây giờ vào tiếp stack web-static-stack để lấy link web.

    web4

    • Click vào link CloudFrontDNS trên tab Output của màn hình stack. Bạn sẽ thấy kết quả như bên dưới.

    web5

    NOTE:

    • Khi bạn không dùng nữa thì có thể chạy lệnh cdk destroy để xoá stack.

    • Ví dụ bên trên là dùng cài đặt AWS client với giá trị default. Khi bạn đã thiết lập profile cho AWS thì tham khảo các câu lệnh để chạy cdk bên dưới đây nhé.

      cdk boostrap --profile profile_name
      cdk synth --profile profile_name
      cdk deploy --profile profile_name
      cdk destroy --profile profile_name
      

    Bạn có thể tham khao code ở Github

    Tôi hy vọng nó sẽ có ích. Bạn cũng có thể thay thế Angular với ReactJS hoặc VueJS. Xin vui lòng cho tôi biết phản hồi của bạn.

  • AWS CDK là gì ?

    AWS CDK là gì ?

    Infrastructure as Code

    Khái niệm này đã có rất nhiều bài viết nói về. Nên mình chỉ trích dẫn nội dung chính như bên dưới.

    Infrastructure as code (IaC) is the process of managing and provisioning computer data centers through machine-readable definition files, rather than physical hardware configuration or interactive configuration tools. The IT infrastructure managed by this process comprises both physical equipment, such as bare-metal servers, as well as virtual machines, and associated configuration resources. The definitions may be in a version control system. It can use either scripts or declarative definitions, rather than manual processes, but the term is more often used to promote declarative approaches.

    Để hiểu rõ hơn về IaC, mọi người đọc link bên dưới nhé. https://magz.techover.io/2021/08/19/infrastructure-as-code/

    AWS CDK

    • AWS (AWS CDK) là một framework phát triển phần mềm mã nguồn mở để xác định cơ sở hạ tầng đám mây trong mã và cung cấp nó thông qua AWS CloudFormation.

    • Nó cung cấp tính trừu tượng hướng đối tượng mức cao để xác định tài nguyên AWS một cách phân cấp bằng cách sử dụng sức mạnh của các ngôn ngữ lập trình hiện đại. Sử dụng thư viện cấu trúc cơ sở hạ tầng của CDK, bạn có thể dễ dàng đóng gói các phương pháp hay nhất của AWS vào định nghĩa cơ sở hạ tầng của mình và chia sẻ nó mà không cần lo lắng về logic bản soạn sẵn.

    • AWS CDK có hỗ trợ hạng nhất cho TypeScript, JavaScript, Python, Java và C #.

    cdk

    Tại sao nên sử dụng AWS CDK ?

    • AWS CDK cho phép phát triển hạ tầng với code và triển khai nó lên AWS qua CloudFormation. Bạn sẽ nhận được toàn bộ lợi ích của CloudFormation.

    • Sử dụng các ngôn ngữ lập trình, công cụ và quy trình làm việc quen thuộc – AWS CDK cho phép bạn phát triển cơ sở hạ tầng bằng TypeScript, Python, Java và .NET.

    • Triển khai cơ sở hạ tầng và runtime code cùng nhau – AWS CDK cho phép bạn tham chiếu các runtime code của mình trong cùng một dự án với cùng một ngôn ngữ lập trình

    • Sử dụng logic (câu lệnh if, vòng lặp for, v.v.) khi xác định cơ sở hạ tầng của bạn

    • Sử dụng các kỹ thuật hướng đối tượng để tạo mô hình hệ thống của bạn

    • Xác định các nội dung tóm tắt ở cấp độ cao, chia sẻ và xuất bản chúng cho nhóm, công ty hoặc cộng đồng của bạn

    • Tổ chức dự án của bạn thành các mô-đun hợp lý

    • Chia sẻ và sử dụng lại cơ sở hạ tầng của bạn làm thư viện

    • Kiểm tra mã cơ sở hạ tầng của bạn bằng các giao thức tiêu chuẩn ngành

    cdk

    Cấu trúc CDK Code

    Apps

    • Chạy chương trình
    • Render and triển khai cfn templates

    Stacks

    • Đơn vị triển khai
    • Gồm thông tin region và account id

    Constructs

    • Đại diện các tài nguyên AWS
    • Có thể hình thành cấu trúc cây phân cấp

    cdk

    • Chúng là các tệp bao gồm mọi thứ cần thiết để triển khai ứng dụng của bạn lên môi trường đám mây.

    • Đơn vị triển khai trong AWS CDK được gọi là stack. Tất cả các tài nguyên AWS được xác định trong phạm vi của một stack, trực tiếp hoặc gián tiếp, đều được cung cấp như một đơn vị duy nhất. Vì AWS CDK stack được triển khai thông qua AWS CloudFormation stack nên chúng có những hạn chế giống như trong AWS CloudFormation.

    • Construct là các khối xây dựng cơ bản của ứng dụng AWS CDK. Một cấu trúc đại diện cho một "thành phần đám mây" và đóng gói mọi thứ AWS CloudFormation cần để tạo thành phần đó.

    CDK Lifecycle

    • CDK (với sự trợ giúp của AWS CLI) biên dịch App của nó (App sẽ chạy chương trình có chứa các StackConstruct)
    • CDK tổng hợp mã để chuyển nó thành mẫu CloudFormation. Khi bạn chạy cdk, hãy triển khai mã mà chúng tôi đã đặt trong lib / <code_name> .ts được phân tích cú pháp bởi CDK Framework, sau đó tạo một mẫu CloudFormation nằm trong thư mục cdk.out và cuối cùng triển khai nó vào CloudFormation.
    • Mẫu CloudFormation được triển khai trong tài khoản AWS và chạy để tạo tất cả các thành phần AWS

    cdk

    AWS workflow

    cdk

    Đây chỉ là phần giới thiệu về AWS CDK trong chuỗi bài viết về AWS CDK, mình sẽ làm demo ở bài viết sau nhé. Mong mọi người ủng hộ.

    Tham khảo: https://dev.to/aws-builders/everything-about-aws-cdk-489m

  • AWS Certificate Manager là gì ?

    AWS Certificate Manager là gì ?

    Chứng chỉ SSL miễn phí

    Khi nói đến chứng chỉ SSL miễn phí, chắc hẳn bạn sẽ nghĩ ngay đến Let’s Encrypt. Nhưng thật ra thì, AWS Certificate Manager cũng cung cấp chứng chỉ SSL miễn phí. Bản chất ACM là một dịch vụ sẵn có miễn phí, cung cấp chức năng quản lý chứng chỉ SSL. Bạn không cần phải trả thêm gì khác ngoài chi phí cho các tài nguyên AWS mà bạn tạo ra để chạy ứng dụng.

    AWS Certificate Manager

    Với AWS Certificate Manager, bạn có thể nhanh chóng yêu cầu một chứng chỉ và triển khai chứng chỉ đó trên các tài nguyên AWS được tích hợp ACM( chẳng hạn như các dịch vụ Elastic Load Balancer, Amazon CloudFront và API Gateway,…) đồng thời cho phép AWS Certificate Manager xử lý các yêu cầu gia hạn chứng chỉ. Dịch vụ này còn cho phép bạn tạo các chứng chỉ riêng cho các tài nguyên nội bộ trong hệ thống mạng của mình và quản lý vòng đời của chứng chỉ một cách tập trung.

    acm

    Cách cấu hình

    Ở phần này mình sẽ không nói cách cấu hình như nào vì các bạn có thể tham khảo trên tài liệu của AWS đã có hướng dẫn rất đầy đủ. Mình sẽ tập trung nói về các điểm lợi điểm hại của các cách cấu hình.Với ACM chúng ta sẽ có 3 cách cấu hình chính:

    Cách 1: Import certificate

    Cách này chỉ dùng khi chúng ta đăng kí domain từ bên thứ 3 khác không phải là AWS. Với domain mà bạn tự mua thì có thể dễ dàng sẽ lấy được certificate và key chain. Nhưng nếu domain của khách hàng của bạn thì họ sẽ rất khó để cung cấp chúng cho bạn. Đôi khi họ cũng chỉ là nguời mới không lưu trữ cái đó chả hạn. Đặc biệt khi domain hết hạn cần gia hạn lại thì họ cũng phải cung cấp lại các thông tin certificate mới của domain để mình import lại. Nó sẽ làm tốn thêm công sức nhiều. Cho nên cách này mình không khuyến cáo sử dụng.

    case1

    • Certificate body: Certificate issued for a particular domain name
    • Certificate private key: Unencrypted (created without a password) private key.
    • Certificate chain: CA bundle of the issuing Certificate Authority

    Cách cấu hình: https://docs.aws.amazon.com/acm/latest/userguide/import-certificate-api-cli.html

    Cách 2: Request a certificate with email

    Cách này chúng ta sẽ cần điền thông tin email mà mình hoặc khách hàng đã dùng để đăng kí domain từ bên thứ 3 khác. Đôi khi khách hàng họ sẽ quên mất email đăng kí domain là email nào. Hoặc đơn giản họ chỉ là người mới tiếp quản công việc không thể nào biết được. Đặc biệt cách này cũng cần xử lý khi domain hết hạn mà gia hạn lại. Cho nên cách này mình không khuyến cáo sử dụng.

    case1

    Cách cấu hình: https://docs.aws.amazon.com/acm/latest/userguide/gs-acm-request-public.html

    Cách 3: Request a certificate with DNS validation

    Sau khi đã hoàn thành các bước thì chúng ta sẽ cần export DNS từ phần đăng ký ACM. Chúng ta cần thêm thông tin này trên trang quản trị domain. Với cách này sẽ đảm bảo khách hàng dễ xử lý với việc thêm nó và an toàn cho thông tin certificate domain của khách hàng.

    case1

    Ví dụ: Hệ thống khách hàng xây dựng trên AWS, nhưng lại đăng kí domain với Godday. Chúng ta có thể vào GoDaddy thêm 1 record với type là CNAME. Sau đó lấy các thông tin export từ ACM để điền vào. Hoàn thành bước này thì chúng ta đã đảm bảo phần có thể active được ACM. Ngoài ra với cách này chúng ta sẽ không cần lo lắng về việc khi domain hết hạn và gia hạn lại. Mình sẽ không phải làm gì thêm từ phía ACM. Mình khuyến khích nên sử dụng cách này. Nó sẽ vừa dễ dàng cho mình và cho khách có thể xử lý được mà không bị phụ thuộc certificate của domain hoặc email đã đăng kí.

    godady

    Cách cấu hình: https://docs.aws.amazon.com/acm/latest/userguide/dns-validation.html

  • Sử dụng Nginx để truy cập tới một Private S3 Bucket

    Sử dụng Nginx để truy cập tới một Private S3 Bucket

    Bài toán

    Mình được giao nhiệm vụ phát triển một ứng dụng quản lý chi tiêu cho khách hàng. Thông tin các hoá đơn và ảnh trong ứng dụng sẽ được lưu trên S3. Khách hàng có yêu cầu có thể xem được ảnh lưu trên S3 bằng domain của họ thay vì bằng đường link trực tiếp từ S3. Hệ thống Backend của họ đang sử dụng Nginx với Python Flask và mong muốn không sử dụng đến dịch vụ CloudFront.

    Giải pháp

    Sau hồi nguyên cứu mình đã tìm ra giải pháp là có thể dùng Nginx để truy cập tới một private S3 bucket.

    Để có thể demo được giải pháp nên mình sẽ lược bỏ hệ thống cho nó đơn giản hơn so với hệ thống của khách hàng. Đầu tiên giả sử hệ thống trên AWS đã được cấu hình như bên dưới:

    • VPC(10.0.0.0/16) với public subnet và private subnet
    • VPC Endpoint cho s3
    • A static web on ECS Fargate with Nginx
    • 1 trang web tĩnh được triển khai trên dịch vụ ECS Fargate với việc dùng Nginx
    • 1 private S3 bucket để lưu ảnh của trang web.

    Alt Text

    Kết quả sau khi cấu hình xong chúng ta sẽ có 1 trang web như bên dưới. Nhưng hình ảnh mọi nguời thấy là hình ảnh được tải từ trên mạng. Alt Text

    Bây giờ mình sẽ cần thay thể ảnh trên mạng này với ảnh trên S3. Để làm được điều đó các bạn theo dõi tiếp bên dưới nhé. Alt Text

    Thiết lập Nginx và S3

    1. Thay đổi S3 bucket policy để chỉ cho phép lấy dữ liệu từ VPC Endpoint.

    {
        "Version": "2008-10-17",
        "Id": "PolicyForCloudFrontPrivateContent",
        "Statement": [
            {
                "Sid": "Access-to-specific-VPCE-only",
                "Effect": "Allow",
                "Principal": "*",
                "Action": "s3:GetObject",
                "Resource": "arn:aws:s3:::demo-static-s3/*",
                "Condition": {
                    "StringEquals": {
                        "aws:sourceVpce": "vpce-0d92e50f230bc8070"
                    }
                }
            }
        ]
    }
    

    2. Tiếp theo là việc quan trọng nhất, chúng ta sẽ cần cấu hình Nginx để có thể tải ảnh từ private S3

    location ~^/image/(.+)$ {
            resolver 10.0.0.2;
            proxy_pass http://s3-ap-southeast-1.amazonaws.com/demo-static-s3/image/$1; 
    }
    
    • resolver: Địa chỉ IP của DNS server trong VPC mà mình đã tạo.

      Ví dụ, VPC của mình tạo có CIRD là 10.0.0.0/16. AWS sẽ dùng 5 IPs bên dưới cho các mục đích bên của họ và mình sẽ không thể sử dụng các IP đó.

      • 10.0.0.0: Network address.
      • 10.0.0.1: Reserved by AWS for the VPC router.
      • 10.0.0.2: Reserved by AWS. The IP address of the DNS server is the base of the VPC network range plus two. For VPCs with multiple CIDR blocks, the IP address of the DNS server is located in the primary CIDR. We also reserve the base of each subnet range plus two for all CIDR blocks in the VPC. For more information, see Amazon DNS server.
      • 10.0.0.3: Reserved by AWS for future use.
      • 10.0.0.255: Network broadcast address. We do not support broadcast in a VPC, therefore we reserve this address.

      => Resolver sẽ có giá trị là 10.0.0.2

      Tham khảo: https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Subnets.html

    • proxy_pass: s3 link

      Định dạng: http://s3-ap-southeast-1.amazonaws.com/[main_bucket]/[sub_bucket]/$1

    3. Thay đổi dường dẫn của tải ảnh của trang web

    <div class="container">
        <h1>Hey there</h1>
        <img src="https://cleandevs.com/image/668c1d479e27bb8750823655c83a6c9bd90263f9_hq.jpg"/>
      </div>
    

    4. Cuối cùng mình sẽ deploy lại trang web lên dịch vụ ECS Fargate. Kết quả sẽ như hình bên dưới. Trang web đã hiển thị ảnh được tải từ private S3 bucket

    Alt Text

  • Infrastructure as Code

    Infrastructure as Code

    Lời nói đầu

    Với sự phát triển manh mẽ của Cloud Computing, các ứng dụng mà đơn vị GST đang phát triển được xây dựng trên cloud như AWS ngày càng nhiều. Việc quản lý resource trên cloud cũng là một vấn đề cực kì quan trọng. Hôm nay mình sẽ giới thiệu về Infrastructure as Code(IaC) và Terraform, những công cụ giúp chúng ta quản lý resource cloud dễ dàng hơn.

    Nội dung

    Vấn đề

    Như đã nói ở phía trên, vấn đề chúng ta bàn đến chính là quản lý resouce cloud(AWS, Azure, GPC..). Tại sao lại phải quản lý? Lý do là mỗi dự án sử dụng khoảng 10-15 services, mỗi service có khoảng 1-10 resources, mỗi resource lại có nhiều config khác nhau. Vì vậy nếu không quản lý tốt, sẽ rất dễ bị miss resource, hoặc config giữa các resource khác nhau giữa các môi trường, lúc tạo môi trường mới mất nhiều thời gian để config, compare các môi trường với nhau, rủi ro khi xử lý manual là rất lớn. Vì vậy việc sử dụng tool để quản lý resource là cần thiết và vô cùng quan trọng. Infrastructure as Code đã được sinh ra để giải quyết các vấn đề đó.

    Infrastructure as Code

    Định nghĩa IaC thì mỗi ông định nghĩa 1 kiểu, sau đây mình sẽ trích dẫn định nghĩa mà mình cho là khá dễ hiểu:

    Infrastructure as code (IaC) is the process of managing and provisioning computer data centers through machine-readable definition files, rather than physical hardware configuration or interactive configuration tools. The IT infrastructure managed by this process comprises both physical equipment, such as bare-metal servers, as well as virtual machines, and associated configuration resources. The definitions may be in a version control system. It can use either scripts or declarative definitions, rather than manual processes, but the term is more often used to promote declarative approaches.

    Refer: https://docs.microsoft.com/en-us/devops/deliver/what-is-infrastructure-as-code

    Hiểu một cách đơn giản hơn thì IaC có nghĩa là chúng ta sử dụng các đoạn code theo format có sẵn(giống như 1 ngôn ngữ lập trình hoặc 1 dạng template: yaml, json..) để quản lý các resource của hệ thống. Khi cần thêm, sửa, xoá 1 resource thì update vào code và apply để thay đổi infra.

    Cụ thể IaC giải quyết vấn đề gì?

    • Giải quyết vấn đề đồng bộ giữa các môi trường, không có chuyện môi trường staging 1 kiểu, môi trường prd config lại khác, vì resource cùng sinh ra từ 1 đoạn code
    • Giảm thiểu chi phí xây dựng môi trường. Ban đầu sẽ hơi mất thời gian 1 chút để tạo các resource bằng code, tuy nhiên sau khi dựng xong 1 môi trường hoàn chỉnh, tạo các môi trường khác thì chỉ cần sử dụng lại code đã tạo cho môi trường đầu tiên. Nếu có 1,2 môi trường thì lợi ích có thể ít, nhưng mình đã làm 1 dự án có 9 môi trường, việc này tiết kiệm rất nhiều thời gian
    • Khả năng tái sử dụng: Ví dụ Project A sử dụng VPC, Subnet, EC2 server, Project B cũng sử dụng các resource như vậy, chúng ta có thể tái sử dụng lại source code infra của A, optimize lại 1 chút để sử dụng luôn cho project B
    • Automation: Việc tự động tạo, update, xoá các resource khiến cho việc thục hiện manual được ít đi rất nhiều, giảm thiểu rủi ro do ngứa tay

    Một số Iac tool phổ biến:

    Terraform

    Để dễ hình dung hơn về IaC, mình sẽ giới thiệu về Terraform, một IaC tool khá phổ biến.
    Terraform là gì?

    Terraform là một IaC tool mã nguồn mở, công cụ phần mềm mã cung cấp quy trình làm việc CLI nhất quán để quản lý hàng trăm dịch vụ đám mây. Terraform mã hóa các API đám mây thành các file khai báo cấu hình.

    Một số điểm đáng chú ý:

    • Phát triển bằng Go
    • Phát triển bời HashiCorp, công ty với mục tiêu cách mạng hóa việc quản lý trung tâm dữ liệu: phát triển, phân phối và bảo trì ứng dụng
    • Multi cloud: Support tạo resource cho nhiều cloud provider khác nhau: AWS, Azure, GPC, Oracle..
    • Cung cấp cơ sở hạ tầng trên hơn 300 đám mây và dịch vụ public bằng cách sử dụng một quy trình làm việc duy nhất

    Terraform hoạt động thế nào?

    Terraform cho phép cơ sở hạ tầng được thể hiện dưới dạng mã bằng một ngôn ngữ đơn giản, con người có thể đọc được gọi là HCL (HashiCorp Configuration Language). Nó đọc các file cấu hình và cung cấp một kế hoạch thực hiện các thay đổi, có thể được xem xét để đảm bảo an toàn, sau đó mới áp dụng các thay đổi.

    Các nhà cung cấp có thể mở rộng cho phép Terraform quản lý nhiều loại tài nguyên, bao gồm IaaS, PaaS, SaaS và các dịch vụ phần cứng.

    Ví dụ Terraform và 1 số câu lệnh đơn giản

    Syntax cơ bản của Terraform

    Khi muốn apply code lên Infra của mình, thực hiện câu lệnh

    terraform apply

    Khi muốn xem sự thay đổi của code hiện tại với trạng thái trước khi thay đổi

    terraform plan

    Kết quả sau khi apply thành công

    Export file terraform thành dạng graph sử dụng lệnh

    terraform graph | dot -Tsvg > graph.svg

    Kết quả sẽ là file svg có tên là graph.svg, dùng extension để view file, ta có kết quả như sau

    CICD với terraform

    Terraform là code, thực hiện quản lý, thay đổi tác động đến Infra của hệ thống. Vậy đã là code thì hoàn toàn có thể apply deploy tự động.

    Cơ bản CICD với Terraform cũng giống như IaC với ngôn ngữ khác, thay vì các lệnh build thì chúng ta thay bằng các command của terraform.

    Kết luận

    Bài viết này mình đã giới thiệu về Infrastructure as Code, tại sao lại cần đến nó, lợi ích khi sử dụng. Mình cũng đã giới thiệu ngắn gọn về một IaC tool khá phổ biến là Terraform. Mong rằng bài viết sẽ cho mọi người thấy được tầm quan trọng của IaC và có thể nghiên cứu apply vào dự án của mình.

  • Case study ứng dụng serverless trên AWS phục vụ Olympic Tokyo

    Case study ứng dụng serverless trên AWS phục vụ Olympic Tokyo

    Lời nói đầu

    Ở đâu đó có thể các bạn đã nghe thấy khái niệm serverless hay chạy ứng dụng không mà không cần sử dụng một server nào (non-server). Hiện nay với sự phát triển mạnh mẽ của các nền tảng public cloud như AWS, Azure, Alibaba.., khái niệm serverless đang dần trở nên thân thuộc hơn với những lập trình viên. Tuy nhiên bạn đã bao giờ tự tay xây dựng một hệ thống API mà không phải sử dụng server bao giờ chưa? Theo mình thấy thì hiện tại sự trải nghiệm của các dev với serverless thực sự chưa nhiều, một phần có lẽ do người ta vẫn tin tưởng ở server truyền thống hơn(Cái gì sờ thấy được cũng chắc chắn hơn). Ở loạt bài này, mình sẽ trình bày về một dự án team mình xây dựngAPI 100% sử dụng serverless . Mình sẽ tập trung vào kiến trúc hệ thống, giải thích các thành phần và framework hỗ trợ deploy serverless nhé!

    Nội dung

    Bối cảnh

    Khách hàng của mình đã xây dựng hệ thống trên môi trường AWS, sử dụng EC2 làm server, ngôn ngữ là Java và sử dụng framework là Struts . Hệ thống hiện tại chi phí đang quá lớn (Bao gồm cả chi phí AWS cũng như các chi phí liên quan khác), thời gian sử dụng và chạy job trong ngày là không cố định(do nghiệp vụ), nhiều khi không có người sử dụng cũng như không có job nào chạy nhưng cũng phải trả tiền cho 1 server API và 1 server Job. Khách hàng đã yêu cầu chuyển hệ thống cũ sang serverless và phát triển thêm tính năng dựa trên kiến trúc mới này. Hệ thống này mình xây dựng hoàn toàn trên Amazon Web Service, nên các dịch vụ cứ mặc định là của AWS nhé!

    Mô hình hệ thống Serverless

    Có lẽ nhiều người cũng đã nhìn qua kiến trúc serverless như thế này:



    Đúng, nó là 1 kiến trúc chung thường thấy của 1 serverless system triển khai trên AWS. Flow sẽ là:

    • App call API qua API Gateway
    • API Gateway trigger lambda
    • Lambda query data từ DB, trả về kết quả
    • API Gateway response data cho client

    Bla…Bla..

    Tuy nhiên, để ứng dụng nó vào 1 dự án cụ thể cần nhiều hơn thế này, theo dõi phần tiếp theo nhé!

    Hệ thống Serverless trong thực tế

    Mỗi hệ thống sẽ có những điểm giống và khác nhau tuỳ thuộc vào bài toán cần giải quyết. Không loằng ngoằng mình sẽ đưa ra kiến trúc mình đã xây dựng luôn (Đã lược bỏ một số chi tiết, tập trung chính vào phần serverless)

    Overview hệ thống này nhé:

    • Phần màu đỏ là hosting cho Frontend(được viết bằng Angular xxx). Phần FrontEnd sẽ bao gồm một S3 Bucket được setting làm static web, 1 Cloudfront Distribution để cache lại các resource tĩnh GLOBAL.
    • Phần màu xanh là hệ thống API serverless. Chúng ta sẽ quan tâm đến phần này nhiều hơn vì nó là trọng tâm của bài viết này. Nó bao gồm những dịch vụ gì, đi lần lượt nhé:
      • WAF: Web Application Firewall – Đây được coi là bức tường lửa đầu tiên để bảo vệ web. Nhiêm vụ của nó là bảo vệ app qua rule do người dùng thiết lập, ví dụ Whitelist IP, Blacklist IP… Quan trọng hơn là nó có thể phát hiện và chặn những request có dấu hiệu tấn công như XSS, SQL Injection….
      • API Gateway: Điểm nhận tất cả các request từ phía client. AWS cho phép route từng path của request đến những handler tương ứng.
      • Cognito: Dịch vụ này cung cấp phương thức xác thực, phân quyền và quản lý người dùng.
      • Lambda (Authenticate): Vì app của mình có tính năng authen hơi đặc biệt, do vậy mình phải dùng lambda function này để add thêm 1 số feature mà Cognito không đáp ứng đủ. Lambda function này sẽ được đính trực tiếp vào API Gateway, đóng vai trò tương tự như 1 middleware, cũng đặt trong private subnet nhé, nhưng vẽ như thế để tránh rối
      • VPC, Public subnet và private subnet: Cái này nếu ai đã làm qua với AWS và network của nó thì có thể nắm được rồi. Public subnet thì có thể internet facing, private subet là nơi đặt các server EC2, RDS, Lambda là private. Không thể truy cập trực tiếp từ internet vào các dịch vụ được đặt trong private subnet.
      • InternetGateway cho phép VPC có thể truy cập Internet, VPC Endpoint cho phép kết nối đến các dịch vụ khác của AWS mà ko qua đường truyền internet
      • Squid Proxy Server: Đóng vai trò là proxy cho phép các resource từ private subet kết nối ra ngoài Internet(Nhiều người sẽ dùng NAT Gateway hoặc NAT Instance).
      • Lambda (Đặt trong private subnet): Đây chính là linh hồn của Serverless, đóng vai trò tương tự 1 server. Mỗi path của API Gateway sẽ được xử lý bởi 1 lambda function. Lambda sẽ nhận request từ API Gateway, xử lý, trả response về API Gateway -> Response về Client
      • S3: Nếu ko có server thì file được lưu trữ ở đâu, up/down thế nào? Thông thường nếu hệ thống sử dụng autoscale thì cũng cần 1 nơi lưu trữ file chung (EFS hoặc S3 ….). Với Lambda cũng vậy, mình chọn S3 để lưu trữ file. Nhưng làm thế nào để upload và download file qua lambda nhỉ. Câu trả lời là sẽ không up/download file qua lambda, lambda chỉ là trung gian, generate Pre-signed URL để client thực hiện upload và download trực tiếp với S3.
      • DynamoDB: Đây là 1 database dạng NoSQL do AWS phát triển. Lưu data dạng Key-Value. Nếu cần thiết phải sử dụng CSDL quan hệ, mình khuyến khích dùng AWS Aurora serverless(MySQL hoặc PostgreSQL), hỗ trợ tốt nếu sử dụng serverless
      • CloudWatch: Phần này có 1 số dịch vụ nhỏ hơn. Tuy nhiên có 2 service chính là Logs và Rules. Logs là nơi xem, truy vấn log mà Lambda function đã ghi ra trong quá trình chạy, Rules được sử dụng để lập lịch cho 1 số job chạy cố định hàng ngày, khi đến thời gian nó sẽ gọi lambda function tương ứng.
      • SQS: Queue được dùng cho sử dụng cho những job muốn chạy ngay lập tức. SQS trigger đến Lambda function(Job) mỗi khi có message mới được đẩy vào queue.
      • X-Ray: Service này khá hay, nó giúp monitor ứng dụng một cách chi tiết hơn, visualize nó lên trên dashboard AWS, giúp gỡ lỗi ứng dụng, phán đoán lỗi cũng như cải tiến ứng dụng tốt hơn. Ví dụ: Thời gian query data từ DynamoDb, thời gian upload file S3…….
      • SNS: Gửi notification.

    Serverless framework

    Nếu đã từng làm việc với lambda, mọi người sẽ biết được rằng mỗi Lambda function là độc lập với nhau, source code vì vậy cũng hoàn toàn riêng biệt. Vậy với 1 project lớn bao gồm hàng trăm API, làm thế nào chúng ta quản lý source code và deploy, không thể build và upload bản build cho từng lambda function được. Vì vậy team đã quyết định sử dụng framework là serverless(https://www.serverless.com)

    Serverless framework là fw hỗ trợ nhiều cloud provider phổ biến như AWS, Azure, GPC, Alibaba… Nó cung cấp cho chúntg ta 1 công cụ để quản lý full life cycle cho ứng dụng serverless. Serverless framework cũng hỗ trợ nhiều ngôn ngữ như Java, Nodejs, Go, Python …

    Cấu hình serverless:
    Tư tưởng của framework hiểu đơn giản là chúng ta cần mapping Path của API Gateway với class, file xử lý logic cho function tương ứng.

    Đây là 1 file cấu hình sample của project serverless. Một số thành phần quan trọng bao gồm:

    • provider
      • name: Tên cloud provider(aws, gpc, azure)
      • runtime: Môi trường thực thi(java8, java11, nodejs12..)
    • package:
      • artifact: Đường dẫn trỏ đến file build
    • functions: List API của project
      • Tên lambda function:
        • handler: class xử lý logic cho API
        • events:
          • http: (nếu là HTTP thì lambda function này sẽ được trigger từ API Gateway)
            • path: Đường dẫn API
            • method: HTTP method(get, post …)

    Mình chỉ giới thiệu qua cấu hình cơ bản của serverless. Lợi ích của nó là giúp chúng ta dễ dàng quản lý life cycle của project serverless, sử dụng các architype có sẵn khi tạo project.

    Tổng kết lại

    Túm lại, để nói về 1 serverless system thì 1 bài viết là không đủ. Ở phần này mình chỉ overview hệ thống, các dịch vụ và vai trò của nó . Mong rằng qua bài viết này các bạn có thể nắm được cơ bản về kiến trúc 1 hệ thống không sử dụng server truyền thống nó như thế nào, đánh giá xem có thể apply trực tiếp vào dự án tiếp theo được không. Mong rằng sẽ có nhiều hơn dự án sử dụng serverless trong đơn vị để mọi người có thêm những trải nghiệm mới.

  • Cost-effective, High Availability Cassandra with AWS EKS and EC2 Spot instance.

    Cost-effective, High Availability Cassandra with AWS EKS and EC2 Spot instance.

    Mở đầu

    Cassandra hay Apache Cassandra, là một hệ thống quản lý cơ sở dữ liệu NoSQL, mã nguồn mở, miễn phí, phân tán dựa trên mạng ngang hàng P2P, hiện tại thường dùng dễ lưu trữ dữ liệu dưới dạng timeseries.

    Bản thân Cassandra đã có khả năng High availability với thiết kế no single point of failure và bản thân Cassandra cũng hỗ trợ việc mở rộng node một cách dễ dàng, vậy tại sao không mang sức mạnh của EC2 Spot Instance (chi phí rẻ cho khả năng tính toán lớn).

    Chúng ta lợi dụng một số tính năng sau của Cassandra để xử lý:

    • Data Center

      image

      • Trong đó data center sẽ đóng vai trò như một cụm node, Cassandra có thể live backups giữa các data center, data sẽ tự động copy async sang DC khác, khi một DC down các DC khác vẫn hoạt động bình thường
    • Seed nodes: Seed nodes sẽ là nơi các node mới connect và thông báo về việc chúng join cluster Seed node hoạt động như các điểm chung chuyển, các node sẽ trao đổi với các node seeds hơn các node khác, và các node này thường sẽ có các thông tin mới nhất và đầy đủ nhất, nhưng chúng sẽ gặp vấn đề overhead nên đừng sử dụng mọi node làm seeds.

    • Data replication: Cassandra lưu trữ dữ liệu trên nhiều node để đảm bảo tính toàn vẹn và fault tolerance (mình khá không thích dịch tiếng việt tự này, có thể dịch là khả năng chịu lỗi). Có 2 strategy: Simple và NetworkTopology, vì chúng ta dự định sử dụng data center nên hãy chọn NetworkTopology

    Như vậy về mặt lý thuyết chúng ta có thể xử lý được toàn bộ vấn đề, hãy mapping chúng với, K8S và AWS thậm chí hoàn toàn có thể xử lý được với trường hợp sử dụng Spot Instance.

    image

    Chúng ta sẽ sử dụng luôn khái niệm Availability Zone của AWS cho tương ứng với data center. Như vậy sẽ có 1 Statefulset cài đặt Cassandra, 1 Service để expose với mỗi DC.

    Cài đặt nào

    Thực ra script đã được chuẩn bị ở đây rồi.

    Mình sẽ giải thích một vài điểm cần chú ý

    Chúng ta add label cho các pod, việc này để các service có thể chọn được các pod của cassandra

      template:
        metadata:
          labels:
            app: cassandra
            interface: cassandraa
    

    Chọn node để cài đặt cassandra, chúng ta có thể dùng các key khác nhưng để cho tiện thì mình dùng tạm key này, việc này đảm bảo node của DC được cài đặt theo AZ của AWS đúng tinh thần High availability

          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: topology.kubernetes.io/zone
                    operator: In
                    values:
                    - ap-southeast-1a
    

    Cassandra seeds node, node đầu tiên của các statefulset được chọn làm seed, ở đây mình xử lý dùng 1 service cassandra thay vì dùng 3 service cho 3 AZ (một điểm nho nhỏ khác biệt), việc này không ảnh hưởng lắm.

      - name: CASSANDRA_SEEDS
        value: cassandraa-0.cassandra.thingsboard.svc.cluster.local,cassandrab-0.cassandra.thingsboard.svc.cluster.local,cassandrac-0.cassandra.thingsboard.svc.cluster.local
    

    Chúng ta không cần tất cả các seed cùng một lúc, nên ngay cả khi seed down thì node vẫn hoạt động bình thường.

    Ở các pod sử dụng cassandra này thì cần chỉ rõ DC nào của Cassandra để kết nối đến, ở đây mình đang cài đặt Thingsboard nên sẽ thêm environment variable sau, tất nhiên sẽ phải xử lý tách application của bạn ra 3 statefulset hoặc deployment khác nhau:

      - name: CASSANDRA_LOCAL_DATACENTER
        value: ap-southeast-1a
    

    Tada

    2021-08-17 18:08:36
    2021-08-17 11:08:36,628 [main] INFO  o.s.o.j.LocalContainerEntityManagerFactoryBean - Initialized JPA EntityManagerFactory for persistence unit 'default'
    2021-08-17 18:08:52
    2021-08-17 11:08:52,732 [main] INFO  c.d.o.d.internal.core.ContactPoints - Contact point cassandra:9042 resolves to multiple addresses, will use them all ([cassandra/10.0.1.112, cassandra/10.0.2.149, cassandra/10.0.1.150])
    2021-08-17 18:08:53
    2021-08-17 11:08:53,734 [main] INFO  c.d.o.d.i.c.DefaultMavenCoordinates - DataStax Java driver for Apache Cassandra(R) (com.datastax.oss:java-driver-core) version 4.10.0
    2021-08-17 18:08:54
    2021-08-17 11:08:54,956 [Thingsboard Cluster-admin-0] INFO  c.d.o.d.internal.core.time.Clock - Could not access native clock (see debug logs for details), falling back to Java system clock
    2021-08-17 18:08:56
    2021-08-17 11:08:56,621 [Thingsboard Cluster-admin-0] WARN  c.d.o.d.i.c.l.h.OptionalLocalDcHelper - [Thingsboard Cluster|default] You specified ap-southeast-1b as the local DC, but some contact points are from a different DC: Node(endPoint=cassandra/10.0.1.112:9042, hostId=a56560a6-1274-43f9-b72e-d8b1e7b33bf8, hashCode=6a745db0)=ap-southeast-1a, Node(endPoint=cassandra/10.0.1.150:9042, hostId=c7f9bc1c-c066-40d6-9def-7fbe58af90bb, hashCode=2c4f4fec)=ap-southeast-1a; please provide the correct local DC, or check your contact points
    

    Nếu dòng log cuối gây confuse thì hãy sử dụng các sevice riêng biệt nhé

    Happy Coding

  • Kiểm soát chi phí sử dụng AWS thông qua việc tạo AWS Budget

    Kiểm soát chi phí sử dụng AWS thông qua việc tạo AWS Budget

    Bạn đã trải nghiệm với các dịch vụ trên AWS, nhưng không may bạn nhận được một bất ngờ không mong muốn trên hóa đơn AWS vào cuối tháng?

    Hoặc có lẽ ai đó trong tổ chức của bạn đã hỏi bạn về việc chi phí AWS tăng cao, có cách nào nhận thông báo chi phí đã sử dụng trên AWS theo hằng ngày được không.

    Đây là việc mà có lẽ hầu hết các kĩ sư cloud đã trải qua.

    AWS Budget sẽ giúp các bạn giải quyết các vấn đề đó. Theo dõi các bước bên dưới để thiết lập nó nhé.


    (1) Đăng nhập vào tài khoản AWS của bạn. Nhập AWS Budgets ở ô tìm kiếm. Sau khi hiển thị kết quả chọn AWS Budgets.

    budget1

    (2) Ở màn hình giao diện Budgets, chọn Create budget.

    budget2

    (3) Ở Step 1, chọn Budget types là Cost budget, sau đó ấn Next step.

    budget3

    (4) Ở Step2, nhập các thông tin budget như hình. Ở chỗ nhập Enter your budgeted amount nên nhập giá trị nhỏ, để Budget sẽ dễ dàng kiểm tra và thông báo cho bạn được thường xuyên. Mình hay để chỗ này tầm 5 hoặc 10$.

    budget4

    (5) Ở Step3, chọn Add an alert threadhold để cài đặt alert.

    budget5

    Trên giao diện Alert, mình sẽ cần nhập thông tin như bên dưới:

    • Threshold: Phần trăm cost sử dụng so với giá trị budget đã set ở Step2 để trigger thông báo. Mình hay để chỗ này tầm 50 hoặc 60.
    • Email recipients: Nhập các email bạn mong muốn để nhận thông báo cost. Các email sẽ cách nhau bởi dấu (,)

    budget6 Sau khi đã nhập xong thì mình chuyển sang step tiếp theo.

    (6) Ở Step4, mình sẽ để default không thay đổi gì cả và chuyển sang step tiếp theo. budget7

    (7) Ở Step5, mình sẽ nhìn lại các cài đặt ở các bước lúc trước. Nếu không có vấn đề gì thì mình chọn Create budget. budget8

    (8) Bạn sẽ nhận email có nội dung như bên dưới. budget9

  • Docker thường thức – Phần 1: Giới thiệu về Containers, Virtual machines và Docker

    Docker thường thức – Phần 1: Giới thiệu về Containers, Virtual machines và Docker

    Docker thường thức – Phần 1: Giới thiệu về Containers, Virtual machines và Docker

    Dù bạn là một Kỹ sư phần mềm hay một nhà Khoa học dữ liệu, dù bạn đang lập trình Web hay đang lập trình Mobile,… thì ít nhiều đã nghe nói về Docker. Theo một thống kê của Stack Overflow trong năm 2020; Docker xếp hạng thứ 2 trong số các nền tảng được yêu thích nhất, đồng thời dẫn đầu trong số các nền tảng mà các developers muốn tìm hiểu nhất. Như vậy có thể thấy, Docker đang dần trở thành xu thế tất yếu mà bất kỳ ai tham gia vào ngành công nghiệp công nghệ thông tin cũng nên tìm hiểu, để biết cách sử dụng nó, áp dụng nó, và biến nó trở thành công cụ hữu ích cho các dự án.

    Chuỗi bài viết về chủ đề Docker của tôi nhằm mang lại cho người đọc mới bắt đầu tìm hiểu về docker có những cái nhìn tổng quan, cơ bản nhất xung quanh công nghệ đang là hot trend này, từ đó họ có thể dễ dàng chuyển sang các chủ đề chuyên sâu hơn mà phù hợp với dự án của mỗi người.

    Trong phần 1, mục đích của bài viết này nhằm mang lại cho bạn đọc các khái niệm cơ bản liên quan đến Docker, chúng sẽ là những thứ mà bạn nhất định phải biết nếu muốn đi sâu vào công nghệ này, ngoài những giải thích bằng lời, tôi cũng cung cấp các hình ảnh trực quan cùng với các ví dụ dễ hiểu.

    Công nghệ đến rồi công nghệ đi, nhưng cái nhìn sâu sắc là ở lại trong ta mãi mãi!

    Danh mục nội dung

    Tại sao lại cần Docker?

    Trước khi đi vào các khái niệm cụ thể, tôi muốn đưa bạn qua một ví dụ để bạn có thể hình dung ra Docker hữu ích như thế nào. Giả sử như bạn đang xây dựng một hệ thống end-to-end với tech stack bao gồm: web server sử dụng NodeJs, database sử dụng MongoDB, messaging system sử dụng Redis, và một orchestration tool.

    Cách tiếp cận truyền thống

    Với các cách tiếp cận truyền thống (mà không sử dụng Docker), chúng ta sẽ gặp phải nhiều vấn đề với tech stack nói trên – chúng là các components/services khác nhau trong hệ thống cần xây dựng.

    • Đầu tiên là khả năng tương thích (compatibility) với hệ điều hành nền tảng (underlying os), chúng ta phải đảm bảo rằng tất cả các services khác nhau nói trên tương thích với OS mà chúng ta đang sử dụng. Trong trường hợp tồn tại một service trong tech stack đó có version mà chúng ta định sử dụng không tương thích với OS, thì chúng ta lại phải tìm kiếm OS khác tương thích với tất cả các services để phù hợp với nhu cầu của hệ thống ta muốn xây dựng.

    • Thứ 2 là chúng ta phải kiểm tra khả năng tương thích giữa các services khác nhau này với các libraries và các dependencies trên OS. Sẽ có vấn đề nếu như một service yêu cầu một phiên bản của dependent library, trong khi đó một service khác lại yêu cầu một phiên bản khác của dependent library đó.

    Kiến trúc của hệ thống sẽ thay đổi qua thời gian, chúng ta sẽ phải upgrade lên các phiên bản mới hơn của các thành phần này. Và mỗi lần có một thứ gì đó cần thay đổi, chúng ta lại phải kiểm tra khả năng tương thích của nó với underlying infrastructure (OS, libraries, dependencies,…). Hơn nữa, mỗi khi có một developer mới onboard, chúng ta sẽ gặp khó khăn khi set up môi trường làm việc cho developer đó.

    The Matrix from Hell !!

    Tất cả những vấn đề nói trên dẫn đến việc developing, building và shipping hệ thống gặp nhiều khó khăn.

    Cách tiệp cận sử dụng Docker

    Như vậy, chúng ta cần một cái gì đó có thể giúp chúng ta giải quyết vấn đề về tính tương thích giữa các thành phần này với OS, chúng ta cũng cần một thứ gì đó có thể giúp chúng ta sửa đổi hoặc thay đổi các thành phần này mà không ảnh hưởng đến các thành phần khác trong hệ thống. Docker đã giải quyết tốt cho chúng ta.

    The services with containers

    Với Docker, ta có thể chạy mỗi component trong một container riêng biệt với các dependencies và các libraries của riêng nó, tất cả trên một VM (Virtual machine) và một OS nhưng tách biệt môi trường. Chúng ta chỉ phải build cấu hình Docker một lần và các developer có thể bắt đầu với một lệnh docker run đơn giản, không phân biệt underlying operating system mà chúng ta đang chạy. Tất cả những cái chúng ta cần là có Docker đã được cài đặt.

    Containers vs Virtual Machines

    Cả Containers và Virtual Machines (VMs) đều giống nhau ở mục tiêu, đó là: cô lập môt ứng dụng và các dependencies của nó thành một đơn vị khép kín (self-contained unit) mà có thể chạy ở bất cứ đâu, bất cứ môi trường nào.

    Hơn nữa, các Containers và VMs loại bỏ nhu cầu về phần cứng vật lý, cho phép sử dụng hiệu quả hơn các tài nguyên máy tính, cả về tiêu thụ năng lượng và hiệu quả chi phí.

    Sự khác biệt chính giữa Containers và VMs là ở cách tiếp cận kiến trúc của chúng.

    Virtual machines

    VMs về cơ bản là một sự mô phỏng của một máy tính thực, thực thi các chương trình giống như một máy tính thực.

    VMs chạy trên một máy vật lý sử dụng cái gọi là hypervisor. Một hypervisor chạy trên một host machine hoặc trên một bare-metal.

    • Một hypervisor là một phần của software, firmware hoặc hardware mà VMs chạy trên đó. Bản thân các hypervisors chạy trên một máy tính vật lý, được gọi là host machine. Host machine cung cấp các tài nguyên cho VMs bao gồm RAM và CPU. Các tài nguyên này được phân chia giữa các VMs và có thể được phân phối khi bạn cảm thấy phù hợp. Vì vậy, nếu một VM đang chạy một ứng dụng cần nhiều tài nguyên hơn thì bạn có thể phân bổ nhiều tài nguyên hơn cho VM đó so với các VM khác đang chạy trên cùng một host machine.

    • VM đang chạy trên một host machine thường được gọi là guest machine. Guest machine này chứa ứng dụng và cả những thứ khác nó cần để chạy ứng dụng đó. Nó chiếm hữu toàn bộ phần cứng được ảo hóa của riêng nó, bao gồm virtualized network adapters, storage, và CPU,… và nó cũng có một guest operating system của riêng nó. Nhìn từ bên trong, guest machine hoạt động riêng biệt với các tài nguyên chuyên dụng dành cho nó. Nhìn từ bên ngoài, nó là một máy ảo – chia sẻ tài nguyên được cung cấp bởi host machine.

    Như đã đề cập ở trên, một guest machine có thể chạy trên một hosted hypervisor hoặc trên một bare-metal hypervisor. Có một vài khác biệt quan trọng giữa chúng:

    • Đầu tiên, một hosted hypervisor chạy trên OS của một host machine. Lấy ví dụ, một máy tính đang chạy OSX có thể có một VM được cài đặt trên OS đó. VM không có quyền truy cập trực tiếp vào hardware, nó phải thông qua OS của host machine. Lợi ích của hosted hypervisor đó là underlying hardware đóng vai trò ít quan trọng. OS của máy chủ chịu trách nhiệm về các hardware drivers thay vì chính hypervisor, và do đó có khả năng tương thích phần cứng tốt. Mặc khác, tầng trung gian này (OS của máy chủ) giữa hardware và hypervisor tạo ra nhiều tài nguyên hơn, làm giảm performance của VM.

    • Một bare-metal hypervisor giải quyết vấn đề hiệu năng nói trên bằng cách cài đặt và chạy ngay trên hardware của host machine. Vì nó giao tiếp trực tiếp với phần cứng nên nó không cần OS của máy chủ để chạy. Trong trường hợp này, thứ đầu tiên được cài đặt trên máy chủ đó là hypervisor. Không giống như hosted hypervisor, một bare-metal hypervisor có device drivers của riêng nó và tương tác trực tiếp với từng thành phần cho bất kỳ tác vụ cụ thể nào. Điều này dẫn đến performance, scalability, và stability tốt hơn. Sự đánh đổi ở đây là khả năng tương thích phần cứng bị hạn chế bởi vì hypervisor chỉ có thể có rất nhiều device drivers được tích hợp trong đó.

    Sau tất cả những gì đã nói về hypervisor, bạn có thể sẽ hỏi rằng tại sao chúng ta lại cần thêm một layer "hypervisor" giữa VM và host machine ? Câu trả lời đó là vì VM có một virtual OS của riêng nó, hypervisor đóng vai trò thiết yếu trong việc cung cấp cho VMs một platform để quản lý để thực thi hệ điều hành khách này. Nó cho phép các host computers chia sẻ tài nguyên của chúng tới các VMs đang chạy với tư cách là guest trên chúng.

    Virtual machines

    Như bạn có thể thấy trên diagram, hypervisor đóng gói virtual hardware, kernel và user space cho mỗi VM mới.

    Containers

    Containers có một lịch sử lâu đời trong lĩnh vực điện toán. Không giống như hypervisor virtualization, nơi mà có một hoặc nhiều VMs độc lập chạy ảo trên physical hardware qua một layer trung gian; thay vào đó, containers chạy trong user space ở trên kernel của OS. Do đó, container virtualization thường được gọi là ảo hóa cấp OS. Công nghệ container cho phép nhiều phiên bản user space độc lập được chạy trên một máy chủ duy nhất.

    Do trạng thái của chúng là guest của OS, nên các containers đôi khi được xem là kém linh hoạt hơn: chúng thường chỉ có thể chạy cùng hệ điều hành hoặc hệ điều hành khách tương tự trên máy chủ. Lấy ví dụ: bạn có thể chạy Redhat Enterprise Linux trên một máy chủ Ubuntu, nhưng bạn không thể chạy Microsoft Windows trên máy chủ Ubuntu. Containers cũng được coi là kém an toàn hơn so với sự cô lập hoàn toàn của hypervisor virtualization.

    Bất chấp những hạn chế này, các containers đã được triển khai dưới nhiều user cases khác nhau. Chúng phổ biến cho việc triển khai hyperscale của các dịch vụ multi-tenant, cho lightweight sandboxing,… bất chấp những lo ngại về bảo mật của chúng.

    Các công nghệ container gần đây bao gồm OpenVZ, Solaris Zones và Linux containers như lxc. Sử dụng các công nghệ mới này, containers giờ đây có thể được xem như là một máy chủ hoàn chỉnh theo đúng nghĩa của chúng thay vì chỉ là môi trường thực thi. Trong trường hợp của Docker, vì có các features hiện đại của Linux kernel, như là control group và namespaces –> các containers có sự độc lập mạnh mẽ, network và storage stacks của riêng chúng, cũng như khả năng quản lý tài nguyên để cho phép sự tồn tại thân thiện của nhiều containers trên cùng một máy chủ.

    Mặc dù các containers trước đây đã không đạt được large-scale adoption. Một phần lớn của vấn đề này có thể nằm ở độ phức tạp của chúng: các containers có thể phức tạp, khó để set up, khó để quản lý và tự động hóa. Docker nhằm mục đích thay đổi điều đó.

    Containers

    Tóm lại, một khác biệt lớn giữa containers và VMs đó là các containers share kernel của máy chủ với các containers khác.

    Containers vs VMs

    Dưới đây là một sự so sánh những điểm khác biệt chính giữa VMs và Containers.

    Containers vs VMs

    Ở bên phải hình trên, trong trường hợp của Docker, ta có underlying hardware infrastructure, OS ở phía trên và Docker được cài đặt trên OS, Docker sau đó quản lý các containers – chúng hoạt động cùng với các libraries và dependencies.

    Trong trường hợp của VMs, ở phía bên trái, ta có Hypervisor ở trên hardware và sau đó là VMs ở trên chúng. Và như bạn nhìn thấy, mỗi VMs có OS riêng bên trong nó, sau đó là các libs và deps rồi đến Application –> việc sử dụng các tài nguyên phần cứng trở nên lớn hơn khi có nhiều virtual operating systems đang chạy. VMs cũng tiêu thụ không gian đĩa lớn hơn vì mỗi VM khá nặng – thường lên đến hàng GB, trong khi đó docker containers nhẹ hơn – thường chỉ đến hàng MB –> điều này cho phép Docker container khởi động nhanh hơn – thường chỉ trong vài giây, trong khi đó các VMs sẽ mất khoảng vài phút để khởi động vì nó cần khởi động toàn bộ cả Operating System.

    Một điều quan trọng cần lưu ý là Docker có ít sự cô lập (isolation) hơn vì có nhiều tài nguyên được chia sẻ giữa các containers, như Kernel. Trong khi đó, VMs có sự cô lập hoàn toàn với nhau vì chúng không dựa trên underlying os hay kernel.

    Mặc dù có sự khác biệt nhất định giữa Container và VM, nhưng sự kết hợp giữa chúng có thể mang lại sự hữu ích nếu biết cách phối hợp chúng hợp lý.

    Containers and VMs

    Khi bạn có môi trường lớn với hàng ngàn containers chạy trên hàng ngàn docker host, bạn sẽ thường thấy các containers được cung cấp trên các virtual docker host. Bằng cách này, chúng ta có thể tận dụng được ưu điểm của cả 2 công nghệ, chúng ta có thể sử dụng virtualization để dễ dàng kiểm soát các docker host theo nhu cầu, đồng thời tận dụng Docker để dễ dàng kiểm soát các ứng dụng và scale chúng theo nhu cầu.

    Giới thiệu về Docker

    Đến đây thì chắc hẳn nhiều bạn đọc đặt câu hỏi, vậy tóm lại Docker là gì? Tôi sẽ trả lời câu hỏi này ngay sau đây.

    Docker là một open-source engine, tự động hóa việc triển khai các ứng dụng vào các containers. Nó được viết bởi một team tại Docker, Inc và được họ phát hành theo giấy phép Apache 2.0.

    Vậy Docker có gì đặc biệt? Docker thêm một công cụ triển khai ứng dụng trên môi trường thực thi container đươc ảo hóa. Nó được thiết kế để cung cấp môi trường nhẹ và nhanh chóng để chạy code của bạn, cũng như workflow hiệu quả để đưa code từ laptop –> môi trường test –> môi trường production.

    Docker cực kỳ đơn giản. Thật vậy, bạn có thể bắt đầu với Docker trên một máy chủ minimal không chạy gì ngoài một Linux kernel tương thích và một Docker binary. Nhiệm vụ của Docker là cung cấp:

    Một cách dễ dàng và nhẹ nhàng để mô hình hóa thực tế:

    Docker rất nhanh, bạn có thể Dockerize ứng dụng của mình trong vài phút. Docker dựa trên mô hình copy-on-write nên việc thực hiện các thay đổi đối với ứng dụng của bạn cũng cực kỳ nhanh chóng.

    Sự phân chia logic giữa các tác vụ:

    Với Docker, các Developers quan tâm về các ứng dụng của họ chạy trong các containers và các Operations quan tâm đến việc quản lý các containers. Docker được thiết kế để tăng cường tính nhất quán bằng cách đảm bảo môi trường mà các developers viết code khớp với môi trường mà các ứng dụng được triển khai thực tế. Điều này làm giảm rủi ro: "worked in dev, now an ops problem".

    Vòng đời phát triển nhanh và hiệu quả:

    Docker nhằm mục đích giảm thời gian trong chu kỳ giữa code được viết, code được kiểm tra, code được triển khai và được sử dụng. Nó cũng làm cho các ứng dụng của bạn trở nên khả chuyển, dễ để build, và dễ cộng tác.

    Khuyến khích kiến trúc hướng dịch vụ (SOA):

    Docker cũng khuyến khích các kiến trúc service-oriented và microservices. Docker recommends rằng mỗi container nên chạy một process hoặc một application duy nhất. Điều này thúc đẩy mô hình ứng dụng phân tán, trong đó một ứng dụng hoặc dịch vụ được đại diện bởi một loạt các containers được kết nối với nhau. Điều này giúp dễ dàng distribute, scale, debug và introspect các ứng dụng.

    Các khái niệm cơ bản

    Tôi sẽ không nhắc lại khái niệm về VMs và Containers nữa; mà thay vào đó, tôi sẽ đề cập đến 3 khái niệm quan trọng khác mà bạn sẽ gặp thường xuyên khi làm việc với Docker.

    Docker image:

    Docker image giống như các blueprints, chúng là cá immutable master image được sử dụng để tạo ra các containers hoàn toàn giống nhau.

    Một docker image chứa Dockerfile, các libraries, và mã nguồn ứng dụng bạn cần chạy, tất cả chúng được bundled lại với nhau.

    Dockerfile:

    Dockerfile là một tệp chứa các lệnh chỉ dẫn cách Docker nên build image của bạn.

    Dockerfile đề cập đến một base image, đươc sử dụng để xây dựng initial image layer. Các base images phổ biến như python, ubuntu, redis…

    Các layers bổ sung sau đó có thể được xếp chồng lên các base image layers, theo các lệnh chỉ dẫn trong Dockerfile. Ví dụ, một Dockerfile cho một ứng dụng học máy có thể yêu cầu Docker thêm Numpy, Pandas, và Scikit-learn trong một layer trung gian.

    Cuối cùng, một thin layer có thể được xếp chồng lên trên các layers khác theo Dockerfile code.

    Container Registry:

    Nếu bạn muốn người khác có thể tạo các containers từ image của bạn tạo ra, bạn cần gửi image đó tới một container registry. Docker hub là registry lớn nhất và là mặc định.

    Một phép ẩn dụ

    Để khép lại phần 1, tôi đưa ra một phép ẩn dụ để minh họa các khái niệm vừa nói ở trên, bằng cách sử dụng hoạt động Nấu ăn, cụ thể là việc làm một chiếc bánh Pizza.

    Khi nấu một món ăn, ta cần có công thức cho món ăn đó, công thức giống như một Dockerfile. Nó cho bạn biết cần phải làm gì để đạt được mục tiêu. Các thành phần của món ăn giống như các layersa, bạn đã có vỏ bánh, nước sốt và pho-mát cho chiếc bánh pizza này.

    Hãy nghĩ về công thức và các thành phần được kết hợp lại thành một công cụ làm bánh pizza. Nó giống như Docker image.

    Công thức (Dockerfile) cho chúng ta biết những gì chúng ta sẽ làm. Dưới đây là kế hoạch:

    • Lớp vỏ được định dạng sẵn và immutable. Nó giống như một basic ubuntu parent image. Đây là bottom layer và được xây dựng đầu tiên.

    • Sau đó bạn sẽ thêm một ít pho mát. Thêm second layer này vào bánh pizza giống như cài đặt thêm một thư viện bên ngoài – ví dụ Numpy.

    • Sau đó bạn rắc thêm một ít húng quế. Nó giống như mã trong một tệp bạn viết để chạy ứng dụng.

    Được rồi, chúng ta hãy bắt đầu nấu ăn:

    • Lò nướng bánh pizza giống như Docker platform. Bạn đã lắp đặt lò nướng vào nhà khi chuyển đến để có thể chế biến mọi thứ với nó. Tương tự như vậy, bạn đã cài đặt Docker vào máy tính của mình để có thể "nấu" các containers.

    • Bạn khởi động lò nướng bằng cách xoay núm. Lệnh Docker run image_name giống như núm của bạn – nó tạo và khởi động container của bạn.

    • Bánh pizza đã chín giống như một Docker container đang chạy.

    • Ăn pizza giống như việc sử dụng ứng dụng.

    Giống như làm bánh pizza, tạo một ứng dụng trong một Docker container mất một số công việc, nhưng cuối cùng bạn đã có một thứ tuyệt vời!

    Lời kết: Bài viết đến đây cũng khá dài. Trong Phần 2, tôi sẽ đi sâu vào kiến trúc, các thành phần của Docker, và không phải chờ đợi lâu, ngay trong phần 2 tôi cũng sẽ giúp bạn đọc bắt đầu viết các lệnh đầu tiên với Docker.

    Tài liệu tham khảo

    [1]: James Turnbull, The Docker Book (2018)

    [2]: Preethi Kasireddy, A Beginner-Friendly Introduction to Containers, VMs and Docker (2016)

    [3]: Jeff Hale, Learn Enough Docker to be Useful (2019)

    [4]: Mumshad Mannambeth, Docker for the Absolute Beginner – Hands On – DevOps, Section 1 – Docker overview.

    Author

    Hà Hữu Linh

    [email protected]

  • Triển khai CD cho dự án phát triển Website với Gitlab-CI và AWS S3

    Triển khai CD cho dự án phát triển Website với Gitlab-CI và AWS S3

    Article overview

    Giả sử chúng ta phát triển một sản phẩm Website với ReactJS và sử dụng Static Website Hosting của AWS S3. Mỗi lần deploy đều cần thực hiện build source và upload manual.
    Mục tiêu là triển khai CD để thay thế cho các công việc manual không cần thiết và giảm thiểu các sai sót ngoài ý muốn.

    Tổng quan về các công nghệ sử dụng:

    • ReactJS Website
    • Gitlab-CI
    • AWS S3, AWS CLI
    • Môi trường MacOS

    Table of contents

    Chúng ta cần một số bước sau:

    • Liên kết và khởi tạo Runner với Gitlab repository
    • [Cài đặt và cấu hình môi trường tại thiết bị chạy service runner](## Cài đặt và cấu hình môi trường tại thiết bị chạy service runner)
    • [Cấu hình các job CI/CD với .gitlab-ci.xml và Gitlab-CI](## Cấu hình các job CI/CD với gitlab-ci.xml và Gitlab-CI)

    Cài đặt và cấu hình môi trường tại thiết bị chạy service runner

    Giả định ở thiết bị MacOS chạy service runner đã build được Website ReactJS, chúng ta sẽ skip qua phần cài đặt cho ReactJS. Đầu tiên, chúng ta cần cài đặt AWS CLI.
    Sau khi cài đặt xong, ta thực hiện config với thông tin của AWS User có quyền deploy lên AWS S3 với câu lệnh sau:

    $ aws configure
    AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
    AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
    Default region name [None]: us-west-2
    Default output format [None]: json

    Cấu hình các job CI/CD với gitlab-ci.xml và Gitlab-CI

    Đầu tiên, thay vì upload bằng tay các file trong thư mục build/ chúng ta sẽ sử dụng command aws s3 sync như sau:
    aws s3 sync build/ s3://ww95 với ww95 là tên của Bucket đang Host Website.
    Sau đó, chúng ta sẽ cài đặt command package.json như sau:

      "scripts": {
        "build": "react-scripts build", // Build source code để deploy
        "deploy": "aws s3 sync build/ s3://ww95" // Thực hiện deploy lên S3
      },

    Tiếp đó, ta sẽ cấu hình .gitlab-ci.yml để hệ thống tự động deploy khi có thay đổi trên nhánh master.

    stages:
      - Deployment
    deploy:
      stage: Deployment
      before_script: []
      only:
          - master
      allow_failure: true
      script:
        - yarn install
        - yarn build
        - yarn deploy

    Tuy nhiên, khi chạy thực tế trên Gitlab-CI ta sẽ gặp lỗi sau:

    Treating warnings as errors because process.env.CI = true.
    Most CI servers set it automatically. 
    Failed to compile.

    Để giải quyết vấn đề này ta phải setting lại process.env.CI = false bằng hai cách sau:

    • Thay đổi cấu hình .gitlab-ci.yml từ yarn build -> CI=false yarn build.
    • Cài đặt biến môi trường trong Gitlab-CI như ảnh sau

    Sau đó merge code vào master, và hưởng thành quả. Từ giờ các bạn không cần phải deploy bằng tay nữa rồi, chúc các bạn may mắn.

    Authors

    MinhNN44