Author: kanakorn.h

  • [บันทึกกันลืม] วิธีป้องกันไม่ให้ผู้ใช้ดาวน์โหลดสิ่งใด ๆ ออกไปจาก Jupyter Notebook/Lab ได้

    ปัญหา

    การใช้ Jupyter Notebook/Lab (aka. Jupyter) นั้นมีข้อดีคือ เราสามารถจำกัดการเข้าถึงข้อมูลที่ละเอียดอ่อนได้ อย่างเช่นเราสามารถตั้งค่าการ access ของ database user ได้จาก private ip ของ Jupyter ได้ แต่ก็ยังมีช่องโหว่คือ ผู้ใช้สามารถ Export file แล้ว download ออกไปได้

    ** Caution: บันทึกนี้ไม่สามารถป้องการการ scp และ API call เพื่อ upload ไปยัง Google Drive, Owncloud ได้ **

    ในที่นี้ ใช้ Jupyter ผ่าน Docker/Kubernetes

    แนวทางการแก้ไข

    Credit:

    เปิด Terminal แล้วพิมพ์คำสั่งต่อไปนี้ เพื่อปิด เมนู

    # disable downloads from File > Download
    jupyter labextension disable @jupyterlab/docmanager-extension:download
    # disable downloads from the context menu in the file browser
    jupyter labextension disable @jupyterlab/filebrowser-extension:download

    แต่ก็ยังมีทางให้เรียกผ่าน URL ได้อยู่ดี จึงต้อง disable การเรียกผ่าน HTTP protocol ได้ จึงต้องปิดด้วยการปิดการเรียก File handler อีกชั้น โดยประกอบด้วย 2 ขั้นตอน

    1. การแก้ไขไฟล์ $HOME/.jupyter/jupyter_notebook_config.py

    import os, sys
    sys.path.append('$HOME/.jupyter/')
    c.ContentsManager.files_handler_class = 'handlers.ForbidFilesHandler'
    c.ContentsManager.files_handler_params = {}

    2. สร้างไฟล์ $HOME/.jupyter/handlers.py

    # Creating ForbidFilesHandler class, overriding the default files_handler_class
    cat <<END >$HOME/.jupyter/handlers.py
    from tornado import web
    from notebook.base.handlers import IPythonHandler
    
    class ForbidFilesHandler(IPythonHandler):
      @web.authenticated
      def head(self, path):
        self.log.info("HEAD: File download forbidden.")
        raise web.HTTPError(403)
    
      @web.authenticated
      def get(self, path, include_body=True):
        self.log.info("GET: File download forbidden.")
        raise web.HTTPError(403)
    
    END

    จากนั้น restart jupyter container

    ผลคือ

    หวังว่าจะเป็นประโยชน์ครับ

  • [บันทึกกันลืม] kubernetes certificate expired

    ถ้าท่านที่รัน Kubernetes นานพอ ก็จะได้เจอปัญหานี้ พอดี cluster ผมใช้งานมาครบ 365 วันนี้พอดี เราก็มือใหม่ซะด้วยสิ ทีนี้ ว้าวุ่นเลย อิอิ

    ปัญหา

    เมื่อใช้คำสั่งต่าง ๆ บน control plane แล้วได้ error ประมาณนี้

    Unable to connect to the server: x509: certificate has expired or is not yet valid:

    สาเหตุ

    Certificate ของ kubernetes cluster มีวันหมดอายุ และวันนี้มันหมดอายุไปแล้ว

    วิธีตรวจสอบ

    kubeadm certs check-expiration

    วิธีแก้ไข

    kubeadm certs renew all
    sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    sudo chown $(id -u):$(id -g) $HOME/.kube/config

    จาก Managing Expired Certificates in Kubernetes Clusters บอกว่า ให้ restart container ที่เกี่ยวข้องกับ

    kube-apiserver, kube-scheduler, kube-controller-manager, and etcd

    โดยใช้คำสั่ง

    for i in $(crictl ps 2>/dev/null | egrep 'etcd|api|sch|control'| cut -d' ' -f 1) ; do crictl stop $i ;done

    ตรวจสอบผล

    kubeadm certs check-expiration

    หวังว่าจะเป็นประโยชน์

  • [บันทึกกันลืม] แก้ปัญหา kube-flannel เกิด CrashLoopBackOff

    Problem reproduce

    kubectl describe pod/airflow-postgresql-0 -n airflow

    result:

    Warning  FailedCreatePodSandBox  26m                   kubelet            Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox "ad25da9611dd6ae39e9124ccbd497783db28b2e2de333128f18ee148e01952d7": plugin type="flannel" failed (add): loadFlannelSubnetEnv failed: open /run/flannel/subnet.env: no such file or directory

    Resolution

    edit file /run/flannel/subnet.env and paste the content *ON EVERY NODES*:

    FLANNEL_NETWORK=10.244.0.0/16
    FLANNEL_SUBNET=10.244.0.1/24
    FLANNEL_MTU=1450
    FLANNEL_IPMASQ=true

    Hope this help

  • [บันทึกกันลืม] วิธีกำหนดให้ pod สร้างเฉพาะบน node ที่ต้องการ

    Kubernetes cluster สามารถกระจายตัวไปในหลาย ๆ ดาต้าเซนเตอร์ได้ แต่ในบางงาน เช่น การใช้ Airflow ในการเข้าถึงข้อมูลบนระบบฐานข้อมูล ซึ่งจำกัดการเข้าถึงได้เฉพาะจากบาง IP range เท่านั้น สามารถทำได้โดยการกำหนด ‘label’ ให้ nodes ที่ต้องการ และ nodeSelector ของ pods หรือ resources

    วิธีกำหนด label ให้ node

    ใช้คำสั่งต่อไปนี้ เพื่อ label ว่า ‘database-access=true’ ให้ node ชื่อ ‘dc1node1’ ซึ่งเป็น node ที่สามารถเข้าถึงฐานข้อมูลได้

    kubectl label node/dc1node1 database-access=true

    วิธีระบุ Pod/Resource ให้เลือก node ที่ต้องการ

    ใช้คำสั่งเพื่อ edit เช่น

    kubectl edit statefulset.apps/airflow-worker -n airflow

    จากนั้นเลื่อนไปที่

    spec: containers: initContainers: nodeSelector:

    ตั้งค่า

    database-access: "true"

    เมื่อทำมีการ reschedule ก็จะไปใช้ node ที่มี label ตามที่กำหนด

    หวังว่าจะมีประโยชน์ครับ

  • [บันทึกกันลืม] วิธีเพิ่ม Node (Ubuntu 22.04) เข้า Kubernetes cluster (version 1.25.0)

    Adding a new node running Ubuntu 22.04 to Kubernetes version 1.25.0 cluster.

    swapoff -a
    sed -i 's/\/swap.img/#\/swap.img/g' /etc/fstab
    echo 1 > /proc/sys/net/ipv4/ip_forward
    modprobe overlay
    modprobe br_netfilter
    sysctl --system
    apt install -y curl gnupg2 software-properties-common apt-transport-https ca-certificates
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
    add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
    apt update -y
    apt install -y containerd
    mkdir /etc/containerd
    containerd config default > /etc/containerd/config.toml
    sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml
    systemctl restart containerd
    systemctl enable containerd
    apt -y install curl vim git wget apt-transport-https gpg
    mkdir /etc/apt/keyrings
    curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.25/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
    echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.25/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
    apt update -y
    apt install -y  kubelet=1.25.16-1.1 kubeadm=1.25.16-1.1
    apt-mark hold kubelet kubeadm kubectl
    systemctl enable kubelet
    kubeadm join <IP>:6443 --token <TOKEN> --discovery-token-ca-cert-hash sha256:<SHA256>

    Hope this help.

  • [บันทึกกันลืม] ย้าย docker ไปไว้ที่ partition อื่น

    ปัญหา

    ถ้าติดตั้ง docker บน Linux โดยค่าเริ่มต้นจะสร้างที่เก็บพวก image, container และ volumns ต่าง ๆ ไว้ที่ /var/lib/docker เมื่อใช้งานไปเรื่อย ๆ จะทำให้ / เต็ม

    วิธีการแก้ไข

    ควร mount disk partition ใหม่นอก / เข้ามา เช่น ‘/otherpartition’ จาก disk อีกลูก แล้วสร้างไดเรคทอรี่ ‘docker’ แล้ว copy ข้อมูลทั้งหมดจาก /var/lib/docker ไปยัง /otherpartition/docker

    rsync  -apv /var/lib/docker /otherpartition/docker

    จากนั้นสร้างไฟล์

    /etc/docker/daemon.json
    { 
       "data-root": "/otherpartition/docker" 
    }

    จากนั้น restart docker

    systemctl restart docker

    หวังว่าเป็นประโยชน์

  • [บันทึกันลืม] Shell script เพื่อทำงาน parallel ด้วย screen

    Parellel processing

    เมื่อเราเขียน shell script เพื่อทำหลาย ๆ งานพร้อมกัน เช่น มีข้อมูล 1,000,000 รายการ ถ้าวิธีแบบ Sequential ก็เริ่มจาก 1, 2, 3, …, 1,000,000 ซึ่งก็จะเสียเวลามาก เพราะต้องรอให้ งานที่ 1 เสร็จก่อน แล้วถึงไปทำงานที่ 2, 3 ถ้าแต่ละงานให้เวลา 1 วินาที ก็ต้องใช้เวลา 1,000,000 วินาที กว่าจะเสร็จ

    แต่ถ้าเราแบ่ง เป็น 100 process ย่อย ๆ แต่ละ process จัดการ 10,000 รายการ ก็จะใช้เวลาลดลง (เมื่อ resources เหลือเฟือ) ทั้งนี้ก็ขึ้นกับประสิทธิภาพเครื่องคอมพิวเตอร์ด้วย

    เช่น เรามี process.py หน้าตาประมาณนี้

    import time
    import sys
    def processing(start_position, steps):
        # something blah
        for i in range(start_position, start_position+steps):
            print(f'processing {i}')
            time.sleep(1)
    
    def main():
        start_position=sys.argv[1]
        steps=sys.argv[2]
        processing(start_position, steps)
    
    if __name__ == "__main__":
        main()
    

    เดิมเราก็จะใช้เครื่องหมาย & เพื่อทำให้ไปอยู่ background

    !/bin/bash
    for i in $(seq 1 100); do
        python3 process.py $i 10000 &amp;
    done
    

    ปัญหาคือ เราจะไม่สามารถดูได้ว่า ตอนนี้ แต่ละ process ไปถึงไหนแล้ว

    screen

    screen เป็น Utility ที่ทำให้เราสามารถส่งคำสั่งไปทำงาน แล้วค่อยสลับเข้าไปดูได้ เทคนิคการใช้งานคำสั่ง screen บน Linux

    เราก็เปลี่ยนจากการใช้ & ต่อท้าย เป็น screen แทนดังนี้

    !/bin/bash
    for i in $(seq 1 100); do
        screen -S p$i -dm python3 process.py $i 10000
    done
    
    

    วิธีนี้ ทำให้สามารถใช้คำสั่ง

    screen -ls
    

    และ

    screen -r p1
    

    เพื่อเข้าไปดูว่า ตอนนี้ process p1 ทำงานถึงไหนแล้ว

    หวังว่าจะเป็นประโยชน์ครับ

  • [บันทึกกันลืม] วิธีติดตั้ง mariadb package สำหรับ python บน Ubuntu

    เรามักเข้าใจว่าแค่ใข้คำสั่ง

    pip install mariadb

    แล้วจะก็จะเรียกใช้งานได้ แต่จริง ๆ แล้ว ไม่ใช่ เพราะจะต้องติดตั้ง package บน OS (ในที่นี้จะเป็น Ubuntu 20.04 – focal)

    sudo apt install libmariadb3 libmariadb-dev

    แต่จะติดตั้ง package นี้ได้ จะต้องติดตั้ง MariaDB Connector/C Community Server package repository (CS)

    ซึ่งขั้นตอนต้นฉบับของ mariadb นั้น ก็ช่าง …. ซับซ้อน ลิงค์ไปมา

    https://mariadb.com/docs/server/connect/programming-languages/python/install/#Prerequisites_for_Source_Distributions

    https://mariadb.com/docs/server/connect/programming-languages/c/install/

    ซึ่งจุดใหญ่ใจความคือ การติดตั้ง repository ให้ได้ แล้วก็จะติดตั้ง package ได้

    เลยบันทึกกันลืมไว้ที่นี่ copy วางได้เลย

    sudo apt install wget -y
    wget https://downloads.mariadb.com/MariaDB/mariadb_repo_setup
    echo "367a80b01083c34899958cdd62525104a3de6069161d309039e84048d89ee98b  mariadb_repo_setup" \
        | sha256sum -c -
    chmod +x mariadb_repo_setup
    sudo ./mariadb_repo_setup \
       --os-type='ubuntu' \
       --os-version='focal' \
       --mariadb-server-version="mariadb-10.6"
    sudo apt update -y
    sudo apt install libmariadb3 libmariadb-dev -y
    pip3 install mariadb
    

    เท่านี้แหล่ะ

    Update สำหรับ Ubuntu 22.04

    ไม่รู้ว่าเกี่ยวกับการเป็น Ubuntu pro หรือไม่ แต่ libssl1.1 ไม่สามารถลงตรง ๆ ได้ ต้องทำดังนี้

    wget http://archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2_amd64.deb
    sudo dpkg -i libssl1.1_1.1.1f-1ubuntu2_amd64.deb
    sudo apt install libmariadbclient-dev
  • บันทึกลับ vim

    Update: 2022-12-16

    สารบัญ

    • แสดง Line Number
    • ลบบรรทัดแรกถึงบรรทัดสุดท้าย
    • Comment ทีละหลาย ๆ บรรทัด

    แสดง Line Number

    Esc :set number

    ลบบรรทัดแรกถึงบรรทัดสุดท้าย

    Esc :1,$d

    Before

    After

    Comment ทีละหลาย ๆ บรรทัด

    Ctrl+v Shift+i #

    Before

    Ctrl+v แล้วเลื่อนลูกศรลงมาเรื่อย ๆ

    Shift+i แล้วใส่ #

    แล้วกดปุ่ม Esc