Cơn ác mộng triển khai lúc 2 giờ sáng
Tất cả chúng ta đều đã từng trải qua tình huống này. Bạn đang đẩy một bản cập nhật định kỳ, mong đợi một thông báo thành công nhanh chóng, nhưng thay vào đó, terminal của bạn lại hiện ra một loạt chữ đỏ. Bạn đang cố gắng chạy một lệnh make install đơn giản hoặc một script, nhưng Ansible không thể tìm thấy thư mục mà nó cần làm việc. Đó là một trở ngại gây ức chế, đặc biệt là khi bạn chắc chắn rằng thư mục đó phải ở đó.
Lỗi thường trông như thế này:
fatal: [host]: FAILED! => {"changed": false, "cmd": "make install", "msg": "chdir /opt/app/build failed: [Errno 2] No such file or directory: '/opt/app/build'"}
Khi điều này xảy ra, Ansible đang báo cho bạn biết rằng tham số chdir trong module shell hoặc command của bạn trỏ đến một đường dẫn không tồn tại trên remote host. Đây không phải là lỗi trong thiết lập cục bộ của bạn. Đó là một trạng thái bị thiếu trên server đích—có lẽ một thư mục đã không được tạo, hoặc một bước trước đó đã thất bại mà không dừng playbook lại.
Tại sao thư mục lại bị thiếu?
Trước khi bạn bắt đầu can thiệp vào mã nguồn, bạn cần biết tại sao đường dẫn đó biến mất. Trong 90% trường hợp, nó rơi vào một trong ba nguyên nhân sau:
- Thất bại trong âm thầm: Một tác vụ
git clonehoặcunarchivetrước đó đã thất bại (có lẽ do lỗi 403 Forbidden hoặc vấn đề dung lượng đĩa) và không tạo ra thư mục. - Nhầm lẫn đường dẫn: Bạn đã sử dụng một đường dẫn tương đối như
chdir: build, và Ansible đã cố gắng tìm nó so với thư mục home của người dùng SSH (ví dụ:/home/ubuntu/build) thay vì đường dẫn hệ thống dự kiến. - Biến trống: Bạn đang sử dụng một biến như
chdir: "{{ app_path }}", nhưng biến đó chưa được định nghĩa hoặc vô tình bị đặt thành một chuỗi rỗng.
Debug nhanh: Kiểm tra trạng thái Remote
Đừng đoán mò. Hãy chạy một lệnh ad-hoc nhanh để xem server đang thấy gì:
ansible all -m shell -a "ls -ld /opt/app/build" -i inventory.ini
Nếu server trả về ls: cannot access..., thư mục đó thực sự bị thiếu. Nếu nó trả về chi tiết thư mục, có khả năng bạn đang gặp vấn đề về quyền truy cập hoặc lỗi đánh máy trong biến của playbook.
Các giải pháp
1. Ép buộc thư mục phải tồn tại
Cách khắc phục đáng tin cậy nhất là sử dụng module file ngay trước lệnh của bạn. Điều này đảm bảo thư mục tồn tại bất kể điều gì đã xảy ra trong các bước trước đó. Đây là một nguyên tắc cốt lõi của infrastructure as code: đừng giả định, hãy thực thi.
- name: Đảm bảo thư mục build đã sẵn sàng
ansible.builtin.file:
path: /opt/app/build
state: directory
mode: '0755'
- name: Chạy quá trình cài đặt
ansible.builtin.command: make install
args:
chdir: /opt/app/build
2. Chuyển sang đường dẫn tuyệt đối
Đường dẫn tương đối là nguồn cơn chính của các lỗi 'No such file'. Nếu playbook của bạn chạy với quyền root, chdir: project sẽ tìm trong /root/project. Nếu chạy với quyền ec2-user, nó sẽ tìm trong /home/ec2-user/project. Luôn sử dụng đường dẫn đầy đủ, như /var/www/my-app/build, để giữ cho playbook của bạn luôn ổn định và dễ đoán.
3. Sử dụng đối số 'Creates' để đảm bảo an toàn
Bạn có thể làm cho các tác vụ của mình thông minh hơn bằng cách sử dụng creates. Điều này nói với Ansible: "Chỉ chạy lệnh này nếu file cụ thể này còn thiếu." Đây là một cách tuyệt vời để ngăn ngừa lỗi và làm cho playbook của bạn có tính idempotent.
- name: Biên dịch ứng dụng
ansible.builtin.shell: ./configure && make
args:
chdir: /opt/app/src
creates: /opt/app/src/Makefile
4. Xử lý triển khai động
Nếu đường dẫn của bạn thay đổi dựa trên dấu thời gian hoặc mã hash của Git, hãy đảm bảo các biến của bạn được đăng ký chính xác. Ví dụ, nếu bạn đang triển khai vào một thư mục được đặt tên theo ngày hiện tại:
- name: Định nghĩa đường dẫn release
set_fact:
rel_path: "/opt/releases/{{ ansible_date_time.date }}"
- name: Tạo thư mục release
ansible.builtin.file:
path: "{{ rel_path }}"
state: directory
- name: Khởi tạo ứng dụng
ansible.builtin.shell: python3 manage.py migrate
args:
chdir: "{{ rel_path }}"
Xác minh việc khắc phục
Sau khi cập nhật playbook, hãy chạy nó với cờ -v (verbose). Hãy tìm đầu ra của module file. Nếu nó báo "changed": true, điều đó có nghĩa là thư mục thực sự đã bị thiếu và Ansible đã sửa nó cho bạn. Bạn cũng có thể chạy lệnh stat /opt/app/build trên remote server để kiểm tra thời gian tạo và quyền sở hữu (ví dụ: drwxr-xr-x).
Những lưu ý quan trọng
- Hãy rõ ràng: Đừng bao giờ tin rằng một tác vụ trước đó đã tạo ra thư mục. Hãy sử dụng module
fileđể chắc chắn. - Kiểm tra quyền hạn: Nếu thư mục tồn tại nhưng bạn vẫn gặp lỗi,
become_usercó thể không có quyền+xđể truy cập vào thư mục cha. - Tránh sử dụng dấu ngã (~): Không sử dụng
~/build. Hãy sử dụng/home/username/buildđể tránh sự mơ hồ giữa các người dùng SSH khác nhau.

