Cài đặt PySpark và nối với Jupyter bằng hai bàn tay trắng
Spark
5
PySpark
1
Jupyter
1
Python
57
White

Phan Chuong viết ngày 14/03/2019

Bài này được dịch từ bản gốc của mình ở đây

Tại sao lại có bài này?

Gần đây, mình có một dự án riêng phải làm về phân tích dữ liệu. Khối lượng dữ liệu (đã nén) vào khoảng 40Gb. Vậy thì sao?

  • Các đầu việc phân tích dữ liệu mình thường làm trên công ty. Nhưng lần này mình không thể sử dụng hạ tầng của công ty được (Hadoop, Yarn, Spark, ...), việc cá nhân mà.
  • Máy của mình lúc nào cũng cài sẵn Jupyter notebook, nhưng khổ thân con máy lúc nào cũng chỉ dư nhiều lắm là 100Mb bộ nhớ không thể gánh nổi lượng dữ liệu kia dù không quá lớn.
  • Mình muốn sử dụng PySpark DataFrame chứ không dùng Pandas DataFrame vì mình quen với API và tài liệu của PySpark hơn. Cách viết bên Pandas quá rối rắm mình không nắm được.

Giả sử:

  • Bạn đã có sẵn một con server Ubuntu 16.04 (Xenial Xerus) mới tinh: Thực ra thì không cần mới tinh, cũng không nhất thiết phải là Ubuntu 16.04. Tuy nhiên việc cài cắm trên một con server mới với phiên bản chính xác như thế sẽ dễ dàng hơn rất nhiều. Bạn có thể không tin, nhưng vọc vạch với một con server cũ với một đống gói (packages) đã được cài sẵn với các thể loại phiên bản khác nhau chỉ làm mọi việc ngày càng rối rắm, cướp vài ngày của bạn như chơi.
  • Con server này cần có địa chỉ IP riêng, ở đây ta tạm cho nó là 11.22.33.44 : Ghi chú, nếu bạn chỉ có ý định chạy trên mạng nội bộ hoặc trên máy của chính mình thì không cần. Địa chỉ IP trên mạng LAN hoặc thậm chí localhost là thừa rồi.
  • Con server này cần phải mở ít nhất là 2 cổng 888818080: Tương tự như trên, nếu đây là môi trường nội bộ thì bạn hoàn toàn có thể bỏ qua yêu cầu này.

Cài đặt

Swap Space

Trong bài này mình sử dụng một server EC2 miễn phí của AWS, và nó có mỗi 1Gb RAM, không đủ để chạy một hệ thống nặng như Spark. Hơn nữa có thêm swap space cũng tốt, để đề phòng trường hợp RAM bất thình lình bị chiếm hết.

Ở đây mình chỉ sử dụng 2Gb ổ cứng để làm swap space (trên tổng số 30Gb). Bạn có thể thay đổi tuỳ ý nếu cần thêm.

sudo dd if=/dev/zero of=/var/swapfile bs=1M count=2048
sudo chmod 600 /var/swapfile
sudo mkswap /var/swapfile
echo /var/swapfile none swap defaults 0 0 | sudo tee -a /etc/fstab
sudo swapon -a

Các ứng dụng cần thiết

Có một vài ứng dụng ta sẽ cần dùng về sau, nên thôi cứ cài luôn từ giờ:

  • unzip: Giải nén
  • python-pip: Python và chương trình quản lý package của Python (2.7.12)
  • default-jdk: JDK (8)
sudo apt-get update
sudo apt-get install -y unzip python-pip default-jdk

SBT

Spark sử dụng SBT (và Maven) để quản lý code và công cụ để build.

echo "deb https://dl.bintray.com/sbt/debian /" | sudo tee -a /etc/apt/sources.list.d/sbt.list
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823
sudo apt-get update
sudo apt-get install sbt

sbt about # để xác nhận đã cài đặt thành công

Spark

Giờ chúng ta sẽ build toàn bộ Spark từ mã nguồn của nó. Nghe thì to nhưng dễ vô cùng. Dù sao code chính của Spark vẫn là Scala (Java), nên build dễ hơn nhiều so với mã nguồn C (phụ thuộc rất nhiều vào hệ điều hành).

Quá trình build sbt package khá lâu (khoảng 30-45 phút), nên bạn có thể đi mua cốc trà sữa về, giải quyết nhu cầu rồi quay lại bàn còn hơn là dí mắt vào màn hình xem logs.

git clone https://github.com/apache/spark.git
cd ~/spark
git checkout v2.1.1
sbt package # chú này lâu này

Sau khi build xong, có các bản build cần thiết rồi, thì phải thêm vào đường dẫn chính (PATH)

tee -a ~/.bash_aliases <<EOF
export PATH=\$PATH:/home/ubuntu/spark/sbin:/home/ubuntu/spark/bin
export SPARK_HOME=/home/ubuntu/spark/
EOF
source ~/.bashrc

pyspark --version # để xác nhận đã cài đặt thành công

Spark History Server

Server này cần một chỗ để lưu các file tạm cho các Spark job. Vị trí mặc định là thư mục /tmp/spark-events. Vậy nên tạo thư mục này rồi bật server thôi.

mkdir /tmp/spark-events
bash ~/spark/sbin/start-history-server.sh

Giờ bạn có thể truy cập vào đây http://11.22.33.44:18080/ và sẽ thấy đại khái như này:
spark-server-history

Jupyter

Giờ là lúc cài đặt Jupyter, cần câu cơm chính của chúng ta.

sudo python -m pip install --upgrade pip
sudo python -m pip install jupyter

jupyter notebook list #  để xác nhận đã cài đặt thành công

Giờ nối nó với PySpark thôi. Để tránh việc chỉ vì cài Jupyter mà "chết" cả Spark, PySpark (không hẳn là chết, mà là không kết nối được kể cả không cần Jupyter, mình gặp nhiều rồi), ta tạo riêng hẳn một file shell script mới cho Jupyter để sử dụng về sau.

tee jupyter.sh <<EOF
export PYSPARK_DRIVER_PYTHON="jupyter"
export PYSPARK_DRIVER_PYTHON_OPTS="notebook --ip=0.0.0.0 --no-browser"
pyspark --conf spark.eventLog.enabled=true --conf spark.eventLog.dir=file:/tmp/spark-events "\$@"
EOF

Từ giờ ta chỉ cần bash jupyter.sh để bật Jupyter, và truy cập ở đây http://11.22.33.44:8888/. Nhưng làm sao để biết chắc Jupyter đã kết nối thành công với PySpark? Dùng cái này nhé sc.applicationId, bạn sẽ thấy ngay:

jupyter-application-id

Đồng thời nếu quay lại Spark History Server, bạn sẽ thấy application ID khớp với nhau:

history-application-id

Thêm cái này cho vui

Việc này hoàn toàn không bắt buộc, nhưng nếu bạn có sẵn một domain nào đó thì sao không tạo thêm một hay cái subdomain cho Jupyter với Spark UI thay vì gõ IP như trên? Cá nhân mình ghét gõ IP vô cùng. Mình sử dụng Nginx proxy. Giả sử bạn đã có sẵn domain.com, bạn có thể cấu hình DNS để trỏ 2 subdomain jupyter.domain.comsparkui.domain.com vào 11.22.33.44, và:

Cái này để cài Nginx

sudo apt-get install -y nginx

Cái này cho Jupyter

upstream notebook {
  server localhost:8888;
}

server{
  listen 80;
  server_name jupyter.domain.com;

  location / {
    proxy_pass            http://notebook;
    proxy_set_header      Host $host;
  }

  location ~ /api/kernels/ {
    proxy_pass            http://notebook;
    proxy_set_header      Host $host;
    # websocket support
    proxy_http_version    1.1;
    proxy_set_header      Upgrade "websocket";
    proxy_set_header      Connection "Upgrade";
    proxy_read_timeout    86400;
  }

  location ~ /terminals/ {
    proxy_pass            http://notebook;
    proxy_set_header      Host $host;
    # websocket support
    proxy_http_version    1.1;
    proxy_set_header      Upgrade "websocket";
    proxy_set_header      Connection "Upgrade";
    proxy_read_timeout    86400;
  }

}

Cái này cho Spark History Server

server {
  listen 80;
  server_name sparkui.domain.com;

  location / {
    proxy_pass            http://localhost:18080;
  }
}
Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Phan Chuong

2 bài viết.
1 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
7 7
Nhiều thống kê trên internet cho thấy rất nhiều người dùng chủ quan và "lười" khi sử dụng chung một mật khẩu cho nhiều tài khoản khác nhau trên mạn...
Phan Chuong viết 1 năm trước
7 7
Bài viết liên quan
White
2 0
Mở đầu Như đã nói ở bài trước, mình đang nghiên cứu về Spark nên cần log lại một số thứ để dành sau này dùng đến :smile: Đối tượng hướng đến vẫn ...
Phạm Quốc Thắng viết hơn 3 năm trước
2 0
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
2 bài viết.
1 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!