+10

Xây dựng môi trường phát triển ứng dụng trên Kubernetes với DevSpace

Giới thiệu

Chào các bạn 👋👋👋. Dạo gần đây mình có được nghe đến và tiếp xúc với DevSpace - một K8s tool giúp build và deploy ứng dụng một cách nhanh chóng. Đặt vấn đề một chút là các dự án/ ứng dụng minh đang làm việc thì đều được triển khai lên Kubernetes bất kể môi trường là staging hay production. Tuy nhiên khi phát triển ứng dụng thì mọi người vẫn đang chỉ đơn giản là cài docker và viết một file docker-compose cấu hình các image sử dụng để chạy ứng dụng và viết code => Môi trường dev đang không có sự đồng nhất với staging và production. Và ngoài ra thì DevSpace còn có rất nhiều tính năng khác giúp đơn giản hóa và nâng cao trải nghiệm khi phát triển ứng dụng trên Kubernetes. Nên trong bài viết này mình sẽ giúp các bạn có được cái nhìn khái quát về DevSpace và giúp các bạn xây dựng được môi trường phát triển ứng dụng trên Kubernetes. Trong bài viết này mình sẽ mặc định là các bạn đều đã có sẵn kiến thức về container và Kubernetes nên những bạn nào chưa có kiến thức về phần này thì các bạn có thể tìm hiểu về nó trước nhé. Còn nếu các bạn đã sẵn sàng rồi thì cũng bắt đầu thôi!!!

DevSpace là gì?

devspace-logo-primary.png

DevSpace là một Kubernetes tool cho client giúp việc phát triển ứng trên Kubernetes một cách dễ dàng hơn. Nó cung cấp tính năng giúp tối ưu hóa quy trình phát triển sản phẩm từ lúc phát triển, triển khai đến lúc vận hành ứng dụng cụ thể:

  • Xây dựng, kiểm thử và gỡ lỗi ngay trong Kubernetes
  • Phát triển ứng dụng với hot reloading: khi có sự thay đổi code sẽ áp dụng thay đổi đó vào running container luôn mà không cần build lại image hay restart container.
  • Đồng bộ quy trình triển khai trong team và qua các môi trường dev, staging, production.
  • Tự động hóa các tác vụ lặp đi lặp lại như build image hay deploy

Tại sao lại là DevSpace

DevSpace là một công cụ giúp phát triển ứng dụng cloud-native nhanh chóng thể hiện qua các tính năng.

Declarative Workflows

DevSpace cho phép chúng ta lưu trư tất cả workflow trong một file config devspace.yaml:

  • Mã hóa kiến thức quy trình về build image, deploy ứng dụng và các dependency của nó.
  • Versioning cho workflow (ta hoàn toàn có thể lấy bất kỳ version nào và chạy nó chỉ với 1 command)
  • Chia sẻ workflow với mọi người trong team

Made For Teams

DevSpace giúp đội ngũ phát triển quy chuẩn hóa deployment và workflow deployment mà không yêu cầu tất cả mọi người trong team đều cần phải là Kubernetes expert (chuyên gia về Kubernetes).

  • DevOps và Kubernetes expert trong team có thể cấu hình DevSpace với file devspace.yaml và đẩy nó lên git.
  • Với những người khác trong team kiểm tra trong project chỉ cần chạy devspace deploy để deploy ứng dụng và họ sẽ có ngay một phiên bản đang chạy của project.
  • Cấu hình của DevSpace rất linh hoạt, ta có thể cấu hình mọi thứ bằng cách sử dụng biến giúp cho mỗi người developer sẽ có câu hình config của project mà mình muốn.

Hot Reloading

Thay vì phải build lại image và triển khai lại ứng dụng với image mới vừa build, DevSpace cho phép chúng ta cập nhật những thay đổi trong code ngay lập tức vào những container đang running.

  • Khi dùng DevSpace ta chỉ cần đơn giản sửa lại code trong IDE thì những thay đổi đó sẽ được áp dụng vào những container đang chạy.
  • Ta có thể xem logs, kết nối với trình debugger hoặc mở terminal container trực tiếp từ IDE với một dòng lệnh.

Automation

Việc triển khai và gỡ lỗi dịch vụ bằng Kubernetes đòi hỏi rất nhiều kiếc thức và ta cần phải gõ đi gõ các command như kubectl get pod và sao chép pod id qua lại. DevSpace sẽ giúp bạn không lãng phí thời gian vào những việc như thế bằng cách tự động hóa:

  • DevSpace cho phép ta build nhiều image song song, thêm tag cho các image một cách tự động và triển khai toàn bộ ứng dụng với chỉ một command.
  • DevSpace sẽ tự động bắt đầu port-forwarding và logs streaming nên chúng ta sẽ không cần phải copy và paste pod id một cách thủ công để có thể lấy ra được những thông tin cần thiết.

Compatibility

DevSpace đã được kiểm thử trên nhiều Kubernetes distributions bao gồm:

  • Local Kubernetes clusters như minikube, k3s, MikroK8s, kind
  • Managed Kubernetes clusters trên GKE (Google), EKS (AWS), AKS (Azure), DOKS (Digital Ocean)
  • Self-managed Kubernetes clusters (ví dụ như Rancher)

Xây dụng môi trường phát triển với DevSpace

Cài đặt

Cách cài đặt trên docs của DevSpace đã có khá đầy đủ các bạn có thể xem tại đây. Trong bài viết này mình sẽ cài đặt với Mac.

# AMD64 / Intel
curl -L -o devspace "https://github.com/loft-sh/devspace/releases/latest/download/devspace-darwin-amd64" && sudo install -c -m 0755 devspace /usr/local/bin

Sau khi download xong bạn hay kiểm tra máy mình cài đặt thành công hay chưa bằng lệnh.

devspace version

// Hiện ra dòng chữ như này là đã thành công
DevSpace version : 6.3.7

Khởi tạo project

Trong bài viết này mình sẽ tiến hành tạo một project Go để demo cho các bạn xem thử. Vì là chưa có dự án Go nào nên mình sẽ dùng luôn dự án demo bên phía DevSpace cho trực quan.

git clone https://github.com/loft-sh/devspace-quickstart-golang
cd devspace-quickstart-golang

Repo sẽ có cấu trúc bao gồm Dockerfile(build image), main.go function main handle http như hình bên dưới.

Ảnh màn hình 2023-12-31 lúc 21.54.17.png

Sau khi đã clone được repo về rồi thì bạn mở terminal trong repo đó là gõ lệnh.

devspace init



     %########%      
     %###########%       ____                 _____                      
         %#########%    |  _ \   ___ __   __ / ___/  ____    ____   ____ ___ 
         %#########%    | | | | / _ \\ \ / / \___ \ |  _ \  / _  | / __// _ \
     %#############%    | |_| |(  __/ \ V /  ____) )| |_) )( (_| |( (__(  __/
     %#############%    |____/  \___|  \_/   \____/ |  __/  \__,_| \___\\___|
 %###############%                                  |_|
 %###########%


info Detecting programming language...

Sau khi gõ command init thì devspace sẽ hỏi bạn vài câu hỏi trên terminal để tiến hành thêm config cho project tùy theo requirement project mà bạn chọn các option phù hợp.

? Select the programming language of this project  [Use arrows to move, type to filter]
  c# (dotnet)
> go
  java-gradle
  java-maven
  javascript
  php
  python

Do project mình vừa clone về sử dụng Go nên mình chọn Go.

? How do you want to deploy this project?  [Use arrows to move, type to filter]
> helm
  kubectl
  kustomize

Ở đây mình sẽ dùng helm để deploy project nên mình chọn helm.

? Is this a DevSpace Quickstart project?  [Use arrows to move, type to filter]
> Yes
  No

Vì mình clone quicks-start của DevSpacec nên mình chọn Yes.

? Do you want to develop this project with DevSpace or just deploy it?  [Use arrows to move, type to filter]  [Use arrows to move, type to filter]
> I want to develop this project and my current working dir contains the source code
  I just want to deploy this project

Mình sẽ dùng sử dụng DevSpace cho cả dev lẫn deploy nên chọn option 1.

? How should DevSpace build the container image for this project?  [Use arrows to move, type to filter]
> Use this existing Dockerfile: ./Dockerfile
  Use a different Dockerfile (e.g. ./backend/Dockerfile)
  Use alternative build tool (e.g. jib, bazel)
  Skip / I don't know

Repo được clone có sẵn Dockerfile ở root nên chọn option 1.

? If you were to push any images, which container registry would you want to push to?  [Use arrows to move, type to filter]
> Skip Registry
  Use hub.docker.com
  Use GitHub image registry
  Use other registry

Trong bài viết này mình sẽ build image local nên sẽ chọn Skip Registry.

Sau khi đã config hết xong ta sẽ có thông báo.

done Project successfully initialized
info Configuration saved in devspace.yaml - you can make adjustments as needed
         
You can now run:
1. devspace use namespace - to pick which Kubernetes namespace to work in
2. devspace dev - to start developing your project in Kubernetes

Run `devspace -h` or `devspace [command] -h` to see a list of available commands and flags

Khi nhìn vào thư mục của project bạn sẽ thấy có thêm 3 file nữa đó là .gitignore, devspace_start.sh, devspace.yaml.

  • devspace.yaml: các hoạt động/workflow như develope, build, deploy sẽ được cấu hình trong file này.
  • devspace_start.sh: sử dụng để hiển thị ra thông tin cho developer khi terminal của các dev container được mở.
  • .gitignore: ignore thư mục ./devspace sử dụng để DevSpace lưu trữ một số thông tin local như cache, ...

File devspace.yaml sẽ tương tự như sau.

version: v2beta1
name: devspace-quickstart-golang

# This is a list of `pipelines` that DevSpace can execute (you can define your own)
pipelines:
  # This is the pipeline for the main command: `devspace dev` (or `devspace run-pipeline dev`)
  dev:
    run: |-
      run_dependencies --all       # 1. Deploy any projects this project needs (see "dependencies")
      ensure_pull_secrets --all    # 2. Ensure pull secrets
      create_deployments --all     # 3. Deploy Helm charts and manifests specfied as "deployments"
      start_dev app                # 4. Start dev mode "app" (see "dev" section)
  # You can run this pipeline via `devspace deploy` (or `devspace run-pipeline deploy`)
  deploy:
    run: |-
      run_dependencies --all                            # 1. Deploy any projects this project needs (see "dependencies")
      ensure_pull_secrets --all                         # 2. Ensure pull secrets
      build_images --all -t $(git describe --always)    # 3. Build, tag (git commit hash) and push all images (see "images")
      create_deployments --all                          # 4. Deploy Helm charts and manifests specfied as "deployments"

# This is a list of `images` that DevSpace can build for this project
# We recommend to skip image building during development (devspace dev) as much as possible
images:
  app:
    image: my-image-registry.tld/username/app
    dockerfile: ./Dockerfile

# This is a list of `deployments` that DevSpace can create for this project
deployments:
  app:
    # This deployment uses `helm` but you can also define `kubectl` deployments or kustomizations
    helm:
      # We are deploying this project with the Helm chart you provided
      chart:
        name: component-chart
        repo: https://charts.devspace.sh
      # Under `values` we can define the values for this Helm chart used during `helm install/upgrade`
      # You may also use `valuesFiles` to load values from files, e.g. valuesFiles: ["values.yaml"]
      values:
        containers:
          - image: my-image-registry.tld/username/app
        service:
          ports:
            - port: 8080

# This is a list of `dev` containers that are based on the containers created by your deployments
dev:
  app:
    # Search for the container that runs this image
    imageSelector: my-image-registry.tld/username/app
    # Replace the container image with this dev-optimized image (allows to skip image building during development)
    devImage: ghcr.io/loft-sh/devspace-containers/go:1.18-alpine
    # Sync files between the local filesystem and the development container
    sync:
      - path: ./
        uploadExcludeFile: .dockerignore
    # Open a terminal and use the following command to start it
    terminal:
      command: ./devspace_start.sh
    # Inject a lightweight SSH server into the container (so your IDE can connect to the remote dev env)
    ssh:
      enabled: true
    # Make the following commands from my local machine available inside the dev container
    proxyCommands:
      - command: devspace
      - command: kubectl
      - command: helm
      - gitCredentials: true
    # Forward the following ports to be able access your application via localhost
    ports:
      - port: "2345"
      - port: "8080"
    # Open the following URLs once they return an HTTP status code other than 502 or 503
    open:
      - url: http://localhost:8080

# Use the `commands` section to define repeatable dev workflows for this project 
commands:
  migrate-db:
    command: |-
      echo 'This is a cross-platform, shared command that can be used to codify any kind of dev task.'
      echo 'Anyone using this project can invoke it via "devspace run migrate-db"'

# Define dependencies to other projects with a devspace.yaml
# dependencies:
#   api:
#     git: https://...  # Git-based dependencies
#     tag: v1.0.0
#   ui:
#     path: ./ui        # Path-based dependencies (for monorepos)

DevSpace đã thêm commend cho config để giúp bạn hiểu hơn về cấu hình của nó.

Development mode

Trước khi chạy container của ứng dụng lên bạn cần setup một cluster K8s bất kỳ nên bạn chưa có setup cluster dưới máy các bạn cần tiền hành cài trước nhé. Ở đây mình sẽ sử dụng k3s.

Set cluster và namespace

Trước khởi chạy development mode ta cần setup cluster và namespace cho DevSpace.

devspace use context
? Which context do you want to use?  [Use arrows to move, type to filter]
> k3d-k3s-demo

Vì ở đây mình chỉ có duy nhất một cluster nên mình tiến hành chọn luôn. Nếu máy bạn có nhiều hơn một thì bạn cần chọn đúng cluster nhé.

kubectl create ns dev-space
devspace use namespace dev-space

info The default namespace of your current kube-context 'k3d-k3s-demo' has been updated to 'dev-space'
         To revert this operation, run: devspace use namespace 

done Successfully set default namespace to 'dev-space'

Trước khi chọn namespace cho DevSpace mình sẽ tiến hành tạo một namespace mới tên là dev-space trên cluster trước sau đó mới sử dụng namespace vừa tạo.

Chạy container

Chạy command sau để deploy project và bắt đầu dev container.

devspace dev

info Using namespace 'dev-space'
info Using kube context 'k3d-k3s-demo'
deploy:app Deploying chart /Users/macbook/.devspace/component-chart/component-chart-0.9.1.tgz (app) with helm...
deploy:app Downloading helm...
deploy:app Deployed helm chart (Release revision: 1)
deploy:app Successfully deployed app with helm
dev:app Waiting for pod to become ready...
dev:app DevSpace is waiting, because Pod app-devspace-795bf85697-z874s has status: ContainerCreating
dev:app DevSpace is waiting, because Pod app-devspace-795bf85697-z874s has status: ContainerCreating
dev:app DevSpace is waiting, because Pod app-devspace-795bf85697-z874s has status: ContainerCreating
dev:app DevSpace is waiting, because Pod app-devspace-795bf85697-z874s has status: ContainerCreating
dev:app DevSpace is waiting, because Pod app-devspace-795bf85697-z874s has status: ContainerCreating
dev:app DevSpace is waiting, because Pod app-devspace-795bf85697-z874s has status: ContainerCreating
dev:app DevSpace is waiting, because Pod app-devspace-795bf85697-z874s has status: ContainerCreating

     %########%      
     %###########%       ____                 _____                      
         %#########%    |  _ \   ___ __   __ / ___/  ____    ____   ____ ___ 
         %#########%    | | | | / _ \\ \ / / \___ \ |  _ \  / _  | / __// _ \
     %#############%    | |_| |(  __/ \ V /  ____) )| |_) )( (_| |( (__(  __/
     %#############%    |____/  \___|  \_/   \____/ |  __/  \__,_| \___\\___|
 %###############%                                  |_|
 %###########%


Welcome to your development container!

This is how you can work with it:
- Files will be synchronized between your local machine and this container
- Some ports will be forwarded, so you can access this container via localhost
- Run `go run main.go` to start the application

Như bạn có thể thấy DevSpace sẽ tiến hành deploy ứng dụng lên và update lại trang thái container, sau đó khi container đã được tạo thì sẽ được inject vào chính container đó luôn. Sau khi đã chạy thành công ta sẽ gõ tiếp command go run main.go để chạy ứng dụng. Truy cập vào localhost:8080 ta sẽ thấy như sau.

Ảnh màn hình 2023-12-31 lúc 22.41.43.png

Vậy là ứng dụng của chúng ta đã được deploy và start thành công.

Development

Sau khi ứng dụng dev ở local đã lên ta sẽ tiến hành vọc vẹch một chút.

kubectl get pod

NAME                            READY   STATUS    RESTARTS   AGE
app-devspace-795bf85697-z874s   1/1     Running   0          9m1s

Khi kiểm tra thử danh sách các pod trong namespace thì ta đã thấy pod của devspace đã được thêm lên trên cluster.

helm list
NAME	NAMESPACE	REVISION	UPDATED                             	STATUS  	CHART                	APP VERSION
app 	dev-space	1       	2023-12-31 22:36:12.854021 +0700 +07	deployed	component-chart-0.9.1	           
---
helm history
REVISION	UPDATED                 	STATUS  	CHART                	APP VERSION	DESCRIPTION     
1       	Sun Dec 31 22:36:12 2023	deployed	component-chart-0.9.1	           	Install complete

Sử dụng command helm listhelm history để xem các release và release history.

Giờ ta sẽ tiến hành sửa code trong IDE và xem nó có update lại không nhé. Trong file main.go mình sẽ update lại content của thẻ h2 từ Now it's time to code: thành Now it's time to say Hello World và tiến hành chạy lại go run main.go.

Ảnh màn hình 2023-12-31 lúc 22.58.35.png

Như các bạn đã thấy nội dung đã được update mà không cần lặp lại quá trình build image và deploy lại image vừa build lên cluster mà DevSpace đã update lại cho chúng ta nhờ config sync trong file devspace.yaml.

Để trực quan và thân thiện với mọi người dùng khi running devspace dev, DevSpace còn một localhost UI giúp chúng ta dễ dàng quản lý và các thông tin được hiển thị một cách trực quan hơn trong quá trình development. Ta có thể truy cập vào UI này thông qua localhost:8090.

Ảnh màn hình 2023-12-31 lúc 23.03.48.png

Tổng kết

Qua bài viết này mình đã giới thiệu DevSpace và setup một môi trường dev đơn giản cho ngôn ngữ Go. Những kiến thức trên cũng chỉ là do mình tự tìm hiểu và học từ nhiều nguồn khác nhau nếu có sai sót gì mong mọi người có thể góp ý để bài viết hoàn thiện hơn. Hy vọng qua bài viết này các bạn có được cái nhìn tổng quan nhất về DevSpace và có thể dễ dàng setup được môi trường dev các ứng dụng đơn giản, những ứng dụng phức tạp hơn như api được viết bằng Laravel, web được viết với Nuxt, ngoài ra còn có cầu hình khác như Minio, Redis, ... thì các bạn có thể sửa lại file config hoặc hẹn gặp các bạn ở các bài viết khác. Cảm ơn các bạn đã theo dõi đến hết bài viết ❤️.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí