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 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.
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.
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 list
và helm 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ư 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
.
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