Giap Hiep

I'm Giap Hiep

I'm a web developer, a gymer. I enjoy share something i know that help people's work!
Giap Hiep

Kubernetes Application Deployment with AWS EKS and ECR

Đặt vấn đề

Gần đây rất nhiều người hay nói đến Docker, Kubernetes (K8s) làm cho một thằng chỉ code backend như mình để ý. Sau một thời gian tìm hiểu và mất tiền cho AWS, cuối cùng cũng cho ra được bài viết dưới đây.

Trong bài viết này mình sẽ nói về việc tự động deploy một ứng dụng lên AWS EKS (Elastic Kubernetes Service) sử dụng Gitlab-CI, docker images sẽ lưu trữ tại ECR( Amazon Elastic Container Registry ).

Với những bạn mới thao tác với AWS thì cũng cần lưu ý về giá cả các dịch vụ. Tuy AWS có gói Free Tier 1 năm nhưng không phải tất cả đều free. Nhớ đọc kỹ để tránh mất tiền oan.

Nội dung gồm các phần:

  • Setup Kubernetes cluster
  • Dockerize
  • Push image to ERC
  • Kubernetes deployments
  • Auto deploy via Gitlab-CI
  • Clean up

Các bước mình triển khai: tạo k8s cluster => dockerize => push image lên ERC => deploy app bằng EKS => Gitlab auto deploy.


Setup Kubernetes cluster

Có nhiều cách để tạo một K8s cluster, bạn có thể vào AWS console để tạo thông qua giao diện trực quan. Còn với mình, mình sẽ tạo thông qua eksctl, đây là một CLI do AWS cung cấp.

Lưu ý một chút là do mình dùng macOS nên các câu lệnh dưới đây là cho macOS. Các bạn có thể truy cập AWS guide để cài đặt cho hệ điều hành mình đang dùng.

Install the AWS CLI

curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg" sudo installer -pkg AWSCLIV2.pkg -target /

Configure your AWS CLI credentials

Để sử dụng được CLI này bạn cần Access keys của AWS bao gồm access key ID và secret access key. Truy cập IAM của AWS để generate nhé.
Tiếp đó dùng lệnh:

aws configure

sau đó nhập thông tin Access keys đã lấy từ AWS.

Ví dụ:

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

Install eksctl

Mình cài bằng brew

brew install weaveworks/tap/eksctl

Kiểm tra xem cài đặt thành công chưa bằng lệnh:

eksctl version
# 0.25.0

Create Kubernetes cluster

Câu lệnh tạo một cluster như sau:

eksctl create cluster --name=app-demo --nodes=1 --node-type t2.small

Trên đây mình tạo một cluster tên là app-demo, có 1 node, note type là t2.small theo bảng giá hiện tại của AWS là $0.0292 một giờ. Chọn node type nhỏ sẽ phù hợp với những bạn mới tìm hiểu. Nếu không có flag --node-type thì eksctl sẽ mặc định là m5.large với chi phí là $0.12 một giờ.
Nghe thì tưởng chừng ít nhưng bạn thử để vài ngày xem, nó sẽ là:

Thời gian tạo cluster thường mất từ 15-20 phút.
Sau khi xong, chạy lệnh:

kubectl get nodes

để kiểm tra. Nếu có vấn đề gì về credentials, bạn nên kiểm tra lại config aws bằng lệnh bên trên aws configure.

Dockerize

Bước tiếp theo, ta cần dockerize ứng dụng. Tuỳ ứng dụng của bạn mà bạn viết Dockerfile cho phù hợp. Nếu bạn nào chưa có thì dùng app của mình. App viết bằng Vuejs, clone tại link.

# Dockerfile
FROM node:lts-alpine
RUN npm install -g http-server
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
EXPOSE 8080
CMD [ "http-server", "dist" ]

Build docker images bằng lệnh:

docker build -t demo-app .

Output của việc dockerize là bạn phải chạy được app qua docker. Ta chạy app bằng lệnh:

docker run -p 8080:8080 demo-app

Truy cập localhost:8080 nếu app hiển thị bình thường là ta đã thành công.

Push image to ERC

Bước tiếp theo ta sẽ push images lên ERC
Đầu tiên cần login:

aws ecr get-login-password --region region | docker login --username AWS --password-stdin aws_account_id.dkr.ecr.region.amazonaws.com

Thay thế region, aws_account_id bằng thông tin tài khoản AWS của bạn.

Tiếp đến tạo một responsitory

aws ecr create-repository \
    --repository-name demo-app \
    --image-scanning-configuration scanOnPush=true \
    --region region

Bạn cũng có thể tạo responsitory qua giao diện tại ERC responsitory

Cuối cùng ta add tag và push image lên ERC via:

docker tag demo-app aws_account_id.dkr.ecr.region.amazonaws.com/demo-app:latest
docker push aws_account_id.dkr.ecr.region.amazonaws.com/demo-app:latest

Lưu ý rằng gói Free Tier sẽ free cho bạn 500Mb khi lưu trên ERC, Nếu tổng file images của bạn > 500Mb thì nên cân nhắc xoá bớt đi.

Kubernetes deployments

Giờ là thời điểm để deploy app vào cluster ta đã tạo trước đó.
Tạo một file tên là deployment.yaml có nội dung như sau:

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: server-demo
  namespace: default
spec:
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: demo-app
          image: aws_account_id.dkr.ecr.region.amazonaws.com/demo-app
          ports:
            - containerPort: 8080
  • Ta gắn label cho app là app:web
  • Image được lấy từ aws_account_id.dkr.ecr.region.amazonaws.com/demo-app.
  • Số lượng replicas là 2.

Tiếp đến chạy lệnh:

kubectl apply -f deployment.yaml

Kiểm tra bằng lệnh:

kubectl get deployments

Tiếp đến ta cần expose một External IP để truy cập vào app từ internet. Sử dụng một ELB( Elastic Load Balancer)

kubectl expose deployment demo-app --type=LoadBalancer --name=demo-elb

Kiểm tra thông tin ELB bằng lệnh:

 kubectl get services demo-elb

Kiểm tra tại EXTERNAL-IP ta sẽ có một domain. Truy cập domain:8080 để kiểm tra xem app đã được deploy chưa.

Auto deploy via Gitlab-CI

Các bước ở trên chỉ là đệm cho bước cuối cùng này. Kết quả ta cần đạt được đó là tự động deploy app mỗi khi có một commit mới.

Trước tiên, truy cập Gitlab.com => Settings => CI-CD => Variables rồi thêm vào các biến sau:

Tạo mới file .gitlab-ci.yml

mage: docker:latest
variables:
  REPOSITORY_URL: aws_account_id.dkr.ecr.region.amazonaws.com/demo-app
  REGION: region
services:
- docker:dind
stages:
  - build
  - deploy
build:
  stage: build
  script:
    - apk add --no-cache curl jq python3 py3-pip
    - pip install awscli
    - aws ecr get-login-password --region ap-southeast-1 | docker login --username AWS --password-stdin 230470490156.dkr.ecr.ap-southeast-1.amazonaws.com
    - docker build -t demo-app -f ./Dockerfile .
    - docker tag demo-app $REPOSITORY_URL.${CI_BUILD_REF}
    - docker push $REPOSITORY_URL.${CI_BUILD_REF}
deploy:
  stage: deploy
  script:
    - kubectl set image deployment/server-demo demo-app=$REPOSITORY_URL --record
  only:
    - master

Các câu lệnh trong file .gitlab-ci.yml ta đã thực hiện ở trên. Có một số điểm khác đó là:

  • Sử dụng biến ${CI_BUILD_REF} để deploy chính xác image được build khi commit.
  • Lệnh kubectl set image để cập nhật lại image và deploy.

Commit code lên respository của bạn và tận hưởng thành quả.

Cleaning Up

Sau khi đạt được thành quả, bạn có thể ngắm nhìn một lúc, take a screenshot nhưng đừng quên xoá nó đi nếu không có ý định sử dụng lâu dài.

eksctl delete cluster --name=demo-app

Kết luận

Bài viết trên đây là một hành trình đến Docker, k8s, AWS với học phí 21.53$ của mình. Các bạn có thắc mắc gì thì comment nhé.
Tài liệu tham khảo: