Khám Phá Sức Mạnh CI/CD: Hành Trình với GitHub Self-Hosted Runners
Chào mọi người! 👋 Hôm nay đánh dấu Ngày thứ 7 của Daily DevOps SRE Challenge - Mùa 2, và thực sự hôm nay là một ngày tuyệt vời! Nhiệm vụ của chúng ta: thiết lập GitHub Self-Hosted Runners và triển khai một trò chơi Rắn cổ điển dựa trên web. Thách thức này đã mang đến cho tôi một cái nhìn sâu sắc về cách tùy chỉnh các pipeline CI/CD, và tôi rất hào hứng chia sẻ trải nghiệm của mình.
Lời Cảm Ơn Đặc Biệt
Trước tiên, tôi muốn gửi lời cảm ơn đến người hướng dẫn tuyệt vời của chúng tôi, Sagar Utekar. 🙏 Những thách thức có cấu trúc và sự hướng dẫn sâu sắc của anh ấy thực sự đã tạo ra sự khác biệt trong hành trình DevOps của tôi. Nhiệm vụ cụ thể này đã giúp tôi nối liền khoảng cách giữa kiến thức lý thuyết và ứng dụng thực tế trong thế giới thực.
Nhiệm Vụ: Vượt Qua CI/CD Cơ Bản
Nội dung chính của thách thức hôm nay là triển khai một trò chơi Rắn đơn giản dựa trên Flask. Mặc dù các runner tiêu chuẩn của GitHub rất tuyệt vời, nhưng bài học thật sự đến từ việc sử dụng một self-hosted runner.
Tại Sao Chọn Self-Hosted?
Đây là một câu hỏi mà cả những người học mới và những nhà tuyển dụng có kinh nghiệm có thể thắc mắc, và nó làm nổi bật một khái niệm quan trọng trong DevOps. Đối với tôi, điều này liên quan đến:
- Tùy Chỉnh: Kiểm soát hoàn toàn môi trường xây dựng (HĐH, phiên bản phần mềm, công cụ cụ thể).
- Tối Ưu Tài Nguyên: Có thể tiết kiệm chi phí hơn cho các khối lượng công việc lớn, ổn định so với việc trả tiền cho thời gian chạy của GitHub.
- Bảo Mật & Tuân Thủ: Đáp ứng các chính sách bảo mật doanh nghiệp cụ thể bằng cách giữ các bản xây dựng trên hạ tầng riêng.
- Truy Cập Mạng Riêng: Cho phép các workflow tương tác với tài nguyên phía sau tường lửa mà các runner công khai của GitHub không thể tiếp cận.
Hiểu được "tại sao" này rất quan trọng cho bất kỳ kỹ sư SRE hoặc DevOps nào đang mong muốn phát triển sự nghiệp. Nó cho thấy bạn đang suy nghĩ không chỉ về việc hoàn thành công việc mà còn thực hiện nó theo cách hiệu quả và an toàn nhất có thể.
Hành Trình Triển Khai Self-Hosted Runner của Tôi
Dưới đây là cách tôi giải quyết thách thức, mô tả từng giai đoạn cho bất kỳ ai đọc bài viết này, cho dù bạn mới bắt đầu hay đang xem xét khả năng của tôi!
1. Thiết Lập Host: Phiên Bản AWS EC2 của Tôi
Bước đầu tiên là chuẩn bị hạ tầng cho self-hosted runner của tôi.
- Phiên Bản Cloud: Tôi đã khởi tạo một AWS EC2 instance (Ubuntu 22.04). Đây là một lựa chọn phổ biến và mạnh mẽ để lưu trữ các ứng dụng và dịch vụ trên đám mây.
- Truy Cập Mạng: Quan trọng là tôi đã cấu hình nhóm bảo mật của EC2 để cho phép lưu lượng truy cập vào Cổng 22 (cho truy cập SSH) và Cổng 80 (để trò chơi Rắn có thể truy cập).
- Kết Nối SSH: Khi phiên bản đã chạy, tôi đã sử dụng SSH để kết nối và bắt đầu cấu hình.
2. Đăng Ký GitHub Self-Hosted Runner
Đây là lúc phiên bản EC2 trở thành một phần của hệ sinh thái GitHub Actions của tôi.
- Tôi đã điều hướng đến
Cài Đặt > Hành Động > Runner
của kho lưu trữ GitHub của mình. - GitHub cung cấp hướng dẫn rõ ràng và các lệnh để tải xuống, giải nén và cấu hình ứng dụng runner trên phiên bản EC2 của tôi.
- Sau khi chạy
./config.sh
, tôi đã khởi động runner với./run.sh
. Bước quan trọng này đã khiến phiên bản EC2 của tôi hoạt động "nghe" các công việc workflow từ kho lưu trữ của tôi. Nhìn thấy nó hiển thị là "Online" trong GitHub là một khoảnh khắc rất thỏa mãn!
3. Docker Hóa Trò Chơi Rắn (và Rào Cản Đầu Tiên của Tôi! 🚧)
Dự án trò chơi Rắn sử dụng Python Flask, và để đảm bảo triển khai nhất quán, Dockerization là rất quan trọng. Đây là lúc thách thức thực sự đầu tiên xuất hiện, và đó là một trải nghiệm học tập tuyệt vời!
- Thiếu Dockerfile: Dự án không đi kèm với
Dockerfile
. Điều này có nghĩa là tôi phải tạo một cái từ đầu. Đối với một người mới, đây là một bài tập hoàn hảo để hiểu cách container hóa một ứng dụng. Đối với một nhà tuyển dụng, điều này cho thấy sự chủ động và khả năng điều chỉnh một dự án cho triển khai dựa trên container.
dockerfile
# Dockerfile đơn giản cho trò chơi Rắn
FROM python:3.8-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 80
CMD ["python", "app.py"]
-
Quyền Truy Cập Docker Daemon: Sau khi tạo Dockerfile, tôi gặp phải lỗi
permission denied
khi cố gắng chạydocker build
. Đây là một vấn đề rất phổ biến: người dùngubuntu
của tôi không nằm trong nhómdocker
!- Cách Khắc Phục: Tôi chỉ cần chạy
sudo usermod -aG docker $USER
và sau đó đăng xuất/đăng nhập lại (hoặcnewgrp docker
). Điều này đã cấp quyền cần thiết cho người dùng của tôi để tương tác với Docker daemon mà không cầnsudo
. Một sửa lỗi nhỏ, nhưng là một bài học quan trọng trong quản lý người dùng Linux!
- Cách Khắc Phục: Tôi chỉ cần chạy
Với Dockerfile đã sẵn sàng và quyền truy cập đã được giải quyết, tôi có thể chạy:
docker build -t snake-game .
docker run -d -p 80:80 snake-game
4. Xây Dựng Workflow GitHub Actions: Pipeline Tự Động Hóa của Tôi
Đây là phần tự động hóa cốt lõi. Tôi đã tạo một tệp .github/workflows/deploy.yml
để tổ chức mọi thứ.
name: Triển Khai Trò Chơi Rắn lên EC2
on:
push:
branches: [main] # Kích hoạt khi có đẩy lên nhánh chính
workflow_dispatch: # Cho phép kích hoạt thủ công
jobs:
build-and-deploy:
runs-on: self-hosted # <-- Điều kỳ diệu! Chỉ định GitHub sử dụng runner EC2 của tôi!
steps:
- name: Kiểm tra kho lưu trữ
uses: actions/checkout@v4
- name: Thiết lập đăng nhập Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} # Sử dụng GitHub Secrets để bảo mật!
- name: Xây dựng và đẩy hình ảnh Docker
run: |
docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/snake-game:latest .
docker push ${{ secrets.DOCKERHUB_USERNAME }}/snake-game:latest
- name: Triển khai ứng dụng
run: |
docker stop snake-game || true # Dừng container hiện tại một cách nhẹ nhàng
docker rm snake-game || true # Xóa nó
docker run -d --name snake-game -p 80:80 ${{ secrets.DOCKERHUB_USERNAME }}/snake-game:latest # Chạy cái mới!
Những điểm chính từ workflow:
runs-on: self-hosted
: Dòng này chỉ dẫn công việc đến phiên bản EC2 tùy chỉnh của tôi. Đây là một tính năng mạnh mẽ để tích hợp hạ tầng của bạn vào CI/CD của GitHub.- GitHub Secrets: Tôi đã sử dụng GitHub Secrets (
DOCKERHUB_USERNAME
,DOCKERHUB_TOKEN
,EMAIL_RECIPIENT
) để lưu trữ thông tin nhạy cảm một cách an toàn. Đây là một thực hành tốt không thể thiếu cho bất kỳ pipeline sẵn sàng cho sản xuất nào. - Logic Triển Khai Chắc Chắn: Các lệnh
docker stop || true
vàdocker rm || true
đảm bảo rằng các triển khai là idempotent – có nghĩa là chúng có thể được chạy nhiều lần mà không gây ra vấn đề. - Kiểm Tra là Chìa Khóa: Vòng lặp
curl
để xác thực sức khỏe của ứng dụng là rất quan trọng. Workflow của tôi ban đầu đã thất bại ở đây với mã thoátcurl
56 (không nhận được dữ liệu).- Cách Khắc Phục: Điều này đã dẫn tôi đến việc gỡ lỗi container đang chạy trực tiếp trên phiên bản EC2 bằng cách sử dụng
docker ps -a
vàdocker logs <container_id>
. Hóa ra có một vấn đề nhỏ khiến ứng dụng Flask thoát ngay sau khi khởi động. Việc sửa mã ứng dụng bên trong container đã giải quyết được vấn đề. Quá trình gỡ lỗi lặp đi lặp lại này rất phổ biến trong DevOps!
- Cách Khắc Phục: Điều này đã dẫn tôi đến việc gỡ lỗi container đang chạy trực tiếp trên phiên bản EC2 bằng cách sử dụng
- Thông Báo: Tích hợp bước thông báo qua email đảm bảo rằng các thành viên trong nhóm liên quan luôn biết đến kết quả triển khai.
Kết Quả Cuối Cùng!
Sau khi vượt qua những thách thức này, tôi đã xây dựng thành công một pipeline CI/CD end-to-end mà:
- Lắng nghe các thay đổi mã.
- Sử dụng một runner tùy chỉnh, tự lưu trữ trên AWS EC2.
- Container hóa ứng dụng với Docker.
- Triển khai ứng dụng đã container hóa.
- Xác thực sức khỏe của nó và gửi thông báo.
Và tất nhiên, chứng minh là ở trong món ăn:
Một ảnh chụp màn hình của Workflow GitHub Actions chạy trên runner tự lưu trữ
của tôi:
Một ảnh chụp màn hình của trò chơi Rắn chạy trực tiếp trong trình duyệt trên IP công khai của EC2 của tôi:
Một ảnh chụp màn hình chi tiết phiên bản AWS EC2 của tôi:
Điều Gì Tiếp Theo & Tham Gia Cộng Đồng!
Thách thức này đã tăng cường sự tự tin của tôi trong việc quản lý hạ tầng CI/CD tùy chỉnh. Tôi đã sẵn sàng cho việc khám phá các nhiệm vụ bổ sung như tự động mở rộng runners và triển khai Nginx để cân bằng tải!
Một lần nữa, tôi xin cảm ơn Sagar vì những bài học vô giá này!
Câu Hỏi Thường Gặp (FAQ)
1. Self-hosted runner là gì?
Self-hosted runner là máy chủ riêng của bạn được sử dụng để chạy các workflow của GitHub Actions, giúp bạn kiểm soát hoàn toàn môi trường.
2. Tại sao lại sử dụng Docker cho triển khai?
Docker giúp bạn đảm bảo môi trường triển khai nhất quán và dễ dàng hơn trong việc quản lý ứng dụng.
3. Làm thế nào để khắc phục lỗi quyền truy cập trong Docker?
Bạn có thể thêm người dùng của mình vào nhóm docker để có quyền truy cập mà không cần sử dụng sudo.