Apa yang diizinkan oleh Jupyter?

Kisah kami dimulai dengan tugas yang tampaknya sederhana. Itu perlu untuk menyiapkan alat analitis untuk spesialis ilmu data dan hanya analis data. Tugas ini ditujukan kepada kami oleh rekan-rekan dari divisi risiko ritel dan CRM, di mana konsentrasi spesialis ilmu data secara historis tinggi. Pelanggan memiliki keinginan sederhana - untuk menulis kode Python, mengimpor pustaka canggih (xgboost, pytorch, tensorflow, dll.) Dan menjalankan algoritma pada data yang diangkat dari cluster HDFS.



Segalanya tampak sederhana dan jelas. Tetapi ada begitu banyak jebakan sehingga kami memutuskan untuk menulis posting tentang itu dan memposting solusi siap pakai di GitHub.

Pertama, beberapa perincian tentang infrastruktur sumber:

  • Gudang Data HDFS (12 node Oracle Big Data Appliance, distribusi Cloudera). Secara total, gudang memiliki 130 TB data dari berbagai sistem internal bank, ada juga informasi heterogen dari sumber eksternal.
  • Dua server aplikasi tempat penggunaan alat analitik. Perlu disebutkan bahwa tidak hanya tugas analisis lanjutan "berputar" di server ini, jadi salah satu persyaratannya adalah penggunaan alat kontainerisasi (Docker) untuk mengelola sumber daya server, menggunakan berbagai lingkungan, dan mengonfigurasinya.

Sebagai lingkungan utama untuk pekerjaan analis, mereka memutuskan untuk memilih JupyterHub, yang secara de facto telah menjadi salah satu standar untuk bekerja dengan data dan mengembangkan model pembelajaran mesin. Baca lebih lanjut di sini . Di masa depan, kita sudah membayangkan JupyterLab.

Tampaknya semuanya sederhana: Anda perlu mengambil dan mengonfigurasi sekelompok Python + Anaconda + Spark. Instal Jupyter Hub di server aplikasi, integrasikan dengan LDAP, sambungkan Spark atau sambungkan ke data dalam HDFS dengan cara lain dan teruskan - buat model!
Jika Anda mempelajari semua sumber data dan persyaratan, maka berikut adalah daftar yang lebih terperinci:

  • Menjalankan JupyterHub di Docker (base OS - Oracle Linux 7)
  • Cloudera CDH cluster 5.15.1 + Spark 2.3.0 dengan otentikasi Kerberos dalam konfigurasi Direktori Aktif + MIT Kerberos khusus dalam cluster (lihat MIT KDC Cluster-Dedicated dengan Direktori Aktif ), Oracle Linux 6
  • Integrasi Direktori Aktif
  • Otentikasi transparan di Hadoop dan Spark
  • Dukungan Python 2 dan 3
  • Spark 1 dan 2 (dengan kemampuan untuk menggunakan sumber daya klaster untuk model pelatihan dan memparalelkan pemrosesan data menggunakan pyspark)
  • Kemampuan untuk membatasi sumber daya host
  • Kumpulan perpustakaan

Posting ini dirancang untuk para profesional TI yang dihadapkan dengan kebutuhan untuk menyelesaikan masalah seperti itu.

Deskripsi Solusi


Peluncuran di Docker + Cloudera Cluster Integration


Tidak ada yang aneh di sini. Klien produk JupyterHub dan Cloudera dipasang di wadah (seperti - lihat di bawah), dan file konfigurasi dipasang dari mesin host:

start-hub.sh

VOLUMES="-v/var/run/docker.sock:/var/run/docker.sock:Z -v/var/lib/pbis/.lsassd:/var/lib/pbis/.lsassd:Z -v/var/lib/pbis/.netlogond:/var/lib/pbis/.netlogond:Z -v/var/jupyterhub/home:/home/BANK/:Z -v/u00/:/u00/:Z -v/tmp:/host/tmp:Z -v${CONFIG_DIR}/krb5.conf:/etc/krb5.conf:ro -v${CONFIG_DIR}/hadoop/:/etc/hadoop/conf.cloudera.yarn/:ro -v${CONFIG_DIR}/spark/:/etc/spark/conf.cloudera.spark_on_yarn/:ro -v${CONFIG_DIR}/spark2/:/etc/spark2/conf.cloudera.spark2_on_yarn/:ro -v${CONFIG_DIR}/jupyterhub/:/etc/jupyterhub/:ro" docker run -p0.0.0.0:8000:8000/tcp ${VOLUMES} -e VOLUMES="${VOLUMES}" -e HOST_HOSTNAME=`hostname -f` dsai1.2 


Integrasi Direktori Aktif


Untuk integrasi dengan Active Directory / besi Kerberos dan bukan sangat host, standar di perusahaan kami adalah produk PBIS Open . Secara teknis, produk ini adalah serangkaian layanan yang berkomunikasi dengan Active Directory, yang pada gilirannya, klien bekerja melalui soket domain unix. Produk ini terintegrasi dengan Linux PAM dan NSS.

Kami menggunakan metode Docker standar - soket layanan host domain unix dipasang di sebuah wadah (soket ditemukan secara empiris oleh manipulasi sederhana dengan perintah lsof):

start-hub.sh

 VOLUMES="-v/var/run/docker.sock:/var/run/docker.sock:Z -v/var/lib/pbis/.lsassd:/var/lib/pbis/.lsassd:Z <b>-v/var/lib/pbis/.netlogond:/var/lib/pbis/.netlogond:Z -v/var/jupyterhub/home:/home/BANK/:Z -v/u00/:/u00/:Z -v/tmp:/host/tmp:Z -v${CONFIG_DIR}/krb5.conf:/etc/krb5.conf:ro </b> -v${CONFIG_DIR}/hadoop/:/etc/hadoop/conf.cloudera.yarn/:ro -v${CONFIG_DIR}/spark/:/etc/spark/conf.cloudera.spark_on_yarn/:ro -v${CONFIG_DIR}/spark2/:/etc/spark2/conf.cloudera.spark2_on_yarn/:ro -v${CONFIG_DIR}/jupyterhub/:/etc/jupyterhub/:ro" docker run -p0.0.0.0:8000:8000/tcp ${VOLUMES} -e VOLUMES="${VOLUMES}" -e HOST_HOSTNAME=`hostname -f` dsai1.2 

Pada gilirannya, paket-paket PBIS dipasang di dalam wadah, tetapi tanpa menjalankan bagian postinstall. Jadi kami hanya menempatkan file dan pustaka yang dapat dieksekusi, tetapi jangan memulai layanan di dalam wadah - ini berlebihan bagi kami. Perintah integrasi PAM dan NSS Linux dijalankan secara manual.

Dockerfile:

 # Install PAM itself and standard PAM configuration packages. RUN yum install -y pam util-linux \ # Here we just download PBIS RPM packages then install them omitting scripts. # We don't need scripts since they start PBIS services, which are not used - we connect to the host services instead. && find /var/yum/localrepo/ -type f -name 'pbis-open*.rpm' | xargs rpm -ivh --noscripts \ # Enable PBIS PAM integration. && domainjoin-cli configure --enable pam \ # Make pam_loginuid.so module optional (Docker requirement) and add pam_mkhomedir.so to have home directories created automatically. && mv /etc/pam.d/login /tmp \ && awk '{ if ($1 == "session" && $2 == "required" && $3 == "pam_loginuid.so") { print "session optional pam_loginuid.so"; print "session required pam_mkhomedir.so skel=/etc/skel/ umask=0022";} else { print $0; } }' /tmp/login > /etc/pam.d/login \ && rm /tmp/login \ # Enable PBIS nss integration. && domainjoin-cli configure --enable nsswitch 

Ternyata klien wadah PBIS berkomunikasi dengan layanan host PBIS. JupyterHub menggunakan PAM authenticator, dan dengan PBIS yang dikonfigurasi dengan benar pada host, semuanya berjalan di luar kotak.

Untuk mencegah semua pengguna dari AD memasuki JupyterHub, Anda dapat menggunakan pengaturan yang membatasi pengguna untuk grup AD tertentu.

config-example / jupyterhub / jupyterhub_config.py

 c.DSAIAuthenticator.group_whitelist = ['COMPANY\\domain^users'] 

Otentikasi transparan di Hadoop dan Spark


Saat masuk ke JupyterHub, PBIS cache tiket Kerberos pengguna dalam file tertentu di direktori / tmp. Untuk otentikasi transparan dengan cara ini, cukup dengan me-mount direktori / tmp dari host di wadah dan mengatur variabel KRB5CCNAME ke nilai yang diinginkan (ini dilakukan di kelas authenticator kami).

start-hub.sh

 VOLUMES="-v/var/run/docker.sock:/var/run/docker.sock:Z -v/var/lib/pbis/.lsassd:/var/lib/pbis/.lsassd:Z -v/var/lib/pbis/.netlogond:/var/lib/pbis/.netlogond:Z -v/var/jupyterhub/home:/home/BANK/:Z -v/u00/:/u00/:Z -v/tmp:/host/tmp:Z -v${CONFIG_DIR}/krb5.conf:/etc/krb5.conf:ro -v${CONFIG_DIR}/hadoop/:/etc/hadoop/conf.cloudera.yarn/:ro -v${CONFIG_DIR}/spark/:/etc/spark/conf.cloudera.spark_on_yarn/:ro -v${CONFIG_DIR}/spark2/:/etc/spark2/conf.cloudera.spark2_on_yarn/:ro -v${CONFIG_DIR}/jupyterhub/:/etc/jupyterhub/:ro" docker run -p0.0.0.0:8000:8000/tcp ${VOLUMES} -e VOLUMES="${VOLUMES}" -e HOST_HOSTNAME=`hostname -f` dsai1.2 

aset / jupyterhub / dsai.py

 env['KRB5CCNAME'] = '/host/tmp/krb5cc_%d' % pwd.getpwnam(self.user.name).pw_uid 

Berkat kode di atas, pengguna JupyterHub dapat menjalankan perintah hdfs dari terminal Jupyter dan menjalankan pekerjaan Spark tanpa langkah otentikasi tambahan. Memasang seluruh direktori / tmp dari host ke dalam wadah tidak aman - kami mengetahui masalah ini, tetapi solusinya masih dalam pengembangan.

Versi Python 2 dan 3


Di sini, tampaknya, semuanya sederhana: Anda perlu menginstal versi Python yang diperlukan dan mengintegrasikannya dengan Jupyter, menciptakan Kernel yang diperlukan. Masalah ini sudah dibahas di banyak tempat. Conda digunakan untuk mengelola lingkungan Python. Mengapa semua kesederhanaan hanya terlihat akan menjadi jelas dari bagian selanjutnya. Contoh kernel untuk Python 3.6 (file ini tidak di git - semua file kernel dihasilkan oleh kode):

/opt/cloudera/parcels/Anaconda-5.3.1-dsai1.0/envs/python3.6.6/share/jupyter/kernels/python3.6.6/kernel.json

 {   "argv": [      "/opt/cloudera/parcels/Anaconda-5.3.1-dsai1.0/envs/python3.6.6/bin/python",       "-m",       "ipykernel_launcher",       "-f",      "{connection_file}"   ],   "display_name": "Python 3",   "language": "python" } 

Percikan 1 dan 2


Untuk berintegrasi dengan klien SPARK, Anda juga perlu membuat kernel. Contoh kernel untuk Python 3.6 dan SPARK 2.

/opt/cloudera/parcels/Anaconda-5.3.1-dsai1.0/envs/python3.6.6/share/jupyter/kernels/python3.6.6-pyspark2/kernel.json

 {   "argv": [       "/opt/cloudera/parcels/Anaconda-5.3.1-dsai1.0/envs/python3.6.6/bin/python",       "-m",       "ipykernel_launcher",       "-f",      "{connection_file}"   ],   "display_name": "Python 3 + PySpark 2",   "language": "python",   "env": {       "JAVA_HOME": "/usr/java/default/",       "SPARK_HOME": "/opt/cloudera/parcels/SPARK2/lib/spark2/",       "PYTHONSTARTUP": "/opt/cloudera/parcels/SPARK2/lib/spark2/python/pyspark/shell.py",       "PYTHONPATH": "/opt/cloudera/parcels/SPARK2/lib/spark2/python/:/opt/cloudera/parcels/SPARK2/lib/spark2/python/lib/py4j-0.10.7-src.zip",       "PYSPARK_PYTHON": "/opt/cloudera/parcels/Anaconda-5.3.1-dsai1.0/envs/python3.6.6/bin/python"   } } 

Harap perhatikan bahwa persyaratan untuk memiliki dukungan Spark 1 telah berkembang secara historis. Namun, ada kemungkinan bahwa seseorang akan menghadapi batasan yang sama - Anda tidak dapat, misalnya, menginstal Spark 2 dalam sebuah cluster. Oleh karena itu, kami menggambarkan di sini perangkap yang kami temui dalam perjalanan ke implementasi.
Pertama, Spark 1.6.1 tidak berfungsi dengan Python 3.6. Menariknya, dalam CDH 5.12.1 ini diperbaiki, tetapi dalam 5.15.1 - untuk beberapa alasan tidak). Pada awalnya, kami ingin menyelesaikan masalah ini dengan hanya menerapkan tambalan yang sesuai. Namun, di masa depan, ide ini harus ditinggalkan, karena pendekatan ini membutuhkan pemasangan Spark yang dimodifikasi dalam sebuah cluster, yang tidak dapat kami terima. Solusinya ditemukan dalam menciptakan lingkungan Conda terpisah dengan Python 3.5.

Masalah kedua mencegah Spark 1 dari bekerja di dalam Docker. Driver Spark membuka port tertentu di mana Pekerja terhubung ke driver - untuk ini driver mengirimkannya alamat IP-nya. Dalam kasus Docker Worker, ia mencoba untuk terhubung ke driver melalui IP kontainer, dan ketika menggunakan jaringan = jembatan itu tidak bekerja secara alami.

Solusi yang jelas adalah mengirim bukan IP wadah, tetapi IP tuan rumah, yang diterapkan di Spark 2 dengan menambahkan pengaturan konfigurasi yang sesuai. Patch ini dirancang ulang secara kreatif dan diterapkan pada Spark 1. Spark yang dimodifikasi dengan cara ini tidak perlu ditempatkan pada host cluster, jadi tidak ada masalah yang mirip dengan ketidakcocokan dengan Python 3.6.

Terlepas dari versi Spark, untuk fungsinya perlu untuk memiliki versi Python yang sama di dalam cluster seperti dalam wadah. Untuk menginstal Anaconda secara langsung melewati Cloudera Manager, kami harus belajar melakukan dua hal:

  • bangun paket Anda dengan Anaconda dan semua lingkungan yang tepat
  • pasang di Docker (untuk konsistensi)

Paket perakitan Anaconda


Ini ternyata menjadi tugas yang cukup sederhana. Yang Anda butuhkan adalah:

  1. Siapkan konten parcel dengan menginstal versi yang diperlukan dari lingkungan Anaconda dan Python
  2. Buat file metadata dan letakkan di direktori meta
  3. Buat paket dengan tar sederhana
  4. Validasi utilitas paket dari Cloudera

Prosesnya dijelaskan secara lebih rinci tentang GitHub , ada juga kode validator di sana. Kami meminjam metadata dalam paket Anaconda resmi untuk Cloudera, mengolahnya secara kreatif.

Instal paket di Docker


Praktek ini telah terbukti bermanfaat karena dua alasan:

  • memastikan Spark operabilitas - tidak mungkin menempatkan Anaconda ke dalam cluster tanpa paket
  • Spark 2 didistribusikan hanya dalam bentuk paket - Anda tentu saja dapat menginstalnya dalam wadah hanya dalam bentuk file jar, tetapi pendekatan ini ditolak

Sebagai bonus, sebagai hasil dari penyelesaian masalah di atas, kami menerima:

  • kemudahan pengaturan klien Hadoop dan Spark - saat memasang paket yang sama di Docker dan di cluster, jalur di cluster dan di wadah adalah sama
  • kemudahan mempertahankan lingkungan yang seragam di dalam wadah dan di dalam kluster - saat memperbarui kluster, gambar Docker dibangun kembali dengan paket yang sama dengan yang dipasang di kluster.

Untuk menginstal paket di Docker, Cloudera Manager pertama kali diinstal dari paket RPM. Untuk pemasangan parcel yang sebenarnya, kode Java digunakan. Klien di Java tahu apa yang tidak bisa dilakukan klien dengan Python, jadi saya harus menggunakan Java dan kehilangan beberapa keseragaman), yang memanggil API.

aset / instal-parcel / src / InstallParcels.java

 ParcelsResourceV5 parcels = clusters.getParcelsResource(clusterName); for (int i = 1; i < args.length; i += 2) {   result = installParcel(api, parcels, args[i], args[i + 1], pause);   if (!result) {       System.exit(1);   } } 

Batasan sumber daya host


Untuk mengelola sumber daya mesin host, kombinasi DockerSpawner digunakan - komponen yang menjalankan pengguna akhir Jupyter dalam wadah Docker yang terpisah - dan cgroup - mekanisme manajemen sumber daya di Linux. DockerSpawner menggunakan Docker API, yang memungkinkan Anda untuk mengatur cgroup induk untuk wadah. Tidak ada kemungkinan seperti itu di DockerSpawner biasa, jadi kami menulis kode sederhana yang memungkinkan kami untuk mengatur korespondensi antara entitas AD dan cgroup induk dalam konfigurasi.

aset / jupyterhub / dsai.py

 def set_extra_host_config(self):       extra_host_config = {}       if self.user.name in self.user_cgroup_parent:           cgroup_parent = self.user_cgroup_parent[self.user.name]       else:           pw_name = pwd.getpwnam(self.user.name).pw_name           group_found = False           for g in grp.getgrall():               if pw_name in g.gr_mem and g.gr_name in self.group_cgroup_parent:                   cgroup_parent = self.group_cgroup_parent[g.gr_name]                   group_found = True                   break           if not group_found:               cgroup_parent = self.cgroup_parent extra_host_config['cgroup_parent'] = cgroup_parent 

Sebuah modifikasi kecil juga telah diperkenalkan yang meluncurkan Jupyter dari gambar yang sama dari mana JupyterHub diluncurkan. Karena itu, tidak perlu menggunakan lebih dari satu gambar.

aset / jupyterhub / dsai.py

 current_container = None host_name = socket.gethostname() for container in self.client.containers():   if container['Id'][0:12] == host_name:       current_container = container       break self.image = current_container['Image'] 

Apa sebenarnya yang harus dijalankan dalam wadah, Jupyter atau JupyterHub, ditentukan dalam skrip startup oleh variabel lingkungan:

aset / jupyterhub / dsai.py

 #!/bin/bash ANACONDA_PATH="/opt/cloudera/parcels/Anaconda/" DEFAULT_ENV=`cat ${ANACONDA_PATH}/envs/default` source activate ${DEFAULT_ENV} if [ -z "${JUPYTERHUB_CLIENT_ID}" ]; then   while true; do       jupyterhub -f /etc/jupyterhub/jupyterhub_config.py   done else   HOME=`su ${JUPYTERHUB_USER} -c 'echo ~'`   cd ~   su ${JUPYTERHUB_USER} -p -c "jupyterhub-singleuser --KernelSpecManager.ensure_native_kernel=False --ip=0.0.0.0" fi 

Kemampuan untuk memulai wadah Docker Jupyter dari wadah Docker JupyterHub dicapai dengan memasang soket daemon Docker di wadah JupyterHub.

start-hub.sh

 VOLUMES="-<b>v/var/run/docker.sock:/var/run/docker.sock:Z -v/var/lib/pbis/.lsassd:/var/lib/pbis/.lsassd:Z</b> -v/var/lib/pbis/.netlogond:/var/lib/pbis/.netlogond:Z -v/var/jupyterhub/home:/home/BANK/:Z -v/u00/:/u00/:Z -v/tmp:/host/tmp:Z -v${CONFIG_DIR}/krb5.conf:/etc/krb5.conf:ro -v${CONFIG_DIR}/hadoop/:/etc/hadoop/conf.cloudera.yarn/:ro -v${CONFIG_DIR}/spark/:/etc/spark/conf.cloudera.spark_on_yarn/:ro -v${CONFIG_DIR}/spark2/:/etc/spark2/conf.cloudera.spark2_on_yarn/:ro -v${CONFIG_DIR}/jupyterhub/:/etc/jupyterhub/:ro" docker run -p0.0.0.0:8000:8000/tcp ${VOLUMES} -e VOLUMES="${VOLUMES}" -e HOST_HOSTNAME=`hostname -f` dsai1.2 

Di masa depan, direncanakan untuk meninggalkan keputusan ini demi, misalnya, ssh.

Saat menggunakan DockerSpawner bersama dengan Spark, masalah lain muncul: driver Spark membuka port acak, di mana Pekerja kemudian membuat koneksi eksternal. Kami dapat mengontrol rentang nomor port yang dipilih secara acak dengan mengatur rentang ini dalam konfigurasi Spark. Namun, rentang ini harus berbeda untuk pengguna yang berbeda, karena kami tidak dapat menjalankan wadah Jupyter dengan port yang diterbitkan sama. Untuk mengatasi masalah ini, kode ditulis yang hanya menghasilkan rentang port oleh id pengguna dari basis data JupyterHub dan meluncurkan wadah Docker dan Spark dengan konfigurasi yang sesuai:

aset / jupyterhub / dsai.py

 def set_extra_create_kwargs(self):       user_spark_driver_port, user_spark_blockmanager_port, user_spark_ui_port, user_spark_max_retries = self.get_spark_ports()       if user_spark_driver_port == 0 or user_spark_blockmanager_port == 0 or user_spark_ui_port == 0 or user_spark_max_retries == 0:           return       ports = {}       for p in range(user_spark_driver_port, user_spark_driver_port + user_spark_max_retries):           ports['%d/tcp' % p] = None       for p in range(user_spark_blockmanager_port, user_spark_blockmanager_port + user_spark_max_retries):           ports['%d/tcp' % p] = None       for p in range(user_spark_ui_port, user_spark_ui_port + user_spark_max_retries):           ports['%d/tcp' % p] = None self.extra_create_kwargs = { 'ports' : ports } 

Kerugian dari solusi ini adalah bahwa ketika Anda me-restart wadah dengan JupyterHub, semuanya berhenti berfungsi karena kehilangan basis data. Karena itu, ketika Anda me-restart JupyterHub untuk, misalnya, perubahan konfigurasi, kami tidak menyentuh wadah itu sendiri, tetapi hanya me-restart proses JupyterHub di dalamnya.

restart-hub.sh

 #!/bin/bash docker ps | fgrep 'dsai1.2' | fgrep -v 'jupyter-' | awk '{ print $1; }' | while read ID; do docker exec $ID /bin/bash -c "kill \$( cat /root/jupyterhub.pid )"; done 

Cgroups sendiri dibuat oleh alat Linux standar, korespondensi antara entitas AD dan cgroups dalam konfigurasi terlihat seperti ini.

 <b>config-example/jupyterhub/jupyterhub_config.py</b> c.DSAISpawner.user_cgroup_parent = {   'bank\\user1'    : '/jupyter-cgroup-1', # user 1   'bank\\user2'    : '/jupyter-cgroup-1', # user 2   'bank\\user3'    : '/jupyter-cgroup-2', # user 3 } c.DSAISpawner.cgroup_parent = '/jupyter-cgroup-3' 

Kode git


Solusi kami tersedia untuk umum di GitHub: https://github.com/DS-AI/dsai/ (DSAI - Ilmu Data dan Kecerdasan Buatan). Semua kode diatur dalam direktori dengan nomor seri - kode dari setiap direktori selanjutnya dapat menggunakan artefak dari yang sebelumnya. Hasil kode dari direktori terakhir adalah gambar Docker.

Setiap direktori berisi file:

  • assets.sh - pembuatan artefak yang diperlukan untuk perakitan (mengunduh dari Internet atau menyalin dari direktori langkah sebelumnya)
  • build.sh - build
  • clean.sh - artefak pembersih yang diperlukan untuk perakitan

Untuk benar-benar membangun kembali gambar Docker, perlu untuk menjalankan clean.sh, assets.sh, build.sh dari direktori sesuai dengan nomor seri mereka.

Untuk perakitan, kami menggunakan mesin dengan Linux RedHat 7.4, Docker 17.05.0-ce. Mesin ini memiliki 8 core, 32GB RAM dan 250GB ruang disk. Sangat disarankan agar Anda tidak menggunakan host dengan pengaturan RAM dan HDD terburuk untuk membangunnya.

Ini adalah bantuan untuk nama-nama yang digunakan:

  • 01-spark-patched - RPM Spark 1.6.1 dengan dua patch diterapkan SPARK-4563 dan SPARK-19019.
  • 02-validator - validator parsel
  • 03-anaconda-dsai-parcel-1.0 - parcel Anaconda dengan Python yang tepat (2, 3.5 dan 3.6)
  • 04-cloudera-manager-api - Perpustakaan Cloudera Manager API
  • 05-dsai1.2-offline - gambar akhir

Sayangnya, rakitan mungkin macet karena alasan yang tidak dapat kami perbaiki (misalnya, tar dijatuhkan saat perakitan parsel. Dalam kasus ini, Anda hanya perlu me-restart perakitan, tetapi ini tidak selalu membantu (misalnya, bilah percikan bergantung pada sumber daya eksternal) Cloudera, yang mungkin tidak lagi tersedia, dll.).

Kelemahan lainnya adalah rakitan paket tidak dapat direproduksi. Karena perpustakaan terus diperbarui, pengulangan perakitan dapat memberikan hasil yang berbeda dari yang sebelumnya.

Final akbar


Sekarang pengguna berhasil menggunakan alat, jumlah mereka telah melampaui beberapa lusin dan terus bertambah. Di masa depan, kami berencana untuk mencoba JupyterLab dan berpikir untuk menghubungkan GPU ke cluster, karena sekarang sumber daya komputasi dari dua server aplikasi yang cukup kuat tidak lagi cukup.

Source: https://habr.com/ru/post/id443294/


All Articles