Category: [บันทึกกันลืม]

  • [บันทึกกันลืม] 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

  • วิธีหา processing speed จาก log file ด้วย shell script

    [บันทึกกันลืม] ห่างหายไปนาน

    กำลังทำระบบ ETL ซึ่งเป็นลักษณะของ Concurrent processing โจทย์คือ ต้องเอาข้อมูล 40 ล้าน items เข้าไปใน Apache Cassandra cluster ที่ประกอบด้วย 5 nodes เป้าหมายคือ 1000 items /second

    วิธีทำ concurrent ด้วย python เดี๋ยวมาเล่าให้ฟัง (รอ Link ตรงนี้)

    โดยย่อ การนำเข้าข้อมูล ทำด้วย Python script แล้วจะเขียน log file หน้าตาประมาณนี้ ให้สนใจแค่ว่าคอลัมน์แรก เป็น timestamp

    ประมาณว่า บรรทัดแรก เขียนข้อมูลเมื่อ 2022-11-30 07:34:13

    แล้วบรรทัดล่าสุด หน้าตาประมาณนี้

    ประมาณว่า บรรทัดสุดท้าย เขียนข้อมูลเมื่อ 2022-11-30 11:12:19

    ทำไปแล้วกี่ items ใช้คำสั่ง wc -l นับบรรทัด เก็บในตัวแปร it

    wc -l kx.log

    ได้มาประมาณ 17,030,016 items

    แล้วเราจะหา จำนวนวินาที จากเริ่มต้น ถึงปัจจุบันอย่างไร ???

    อันนี้คือ shell script เดี๋ยวอธิบายต่อไป

    t1=$(head -1 kx.log|cut -d, -f1); ts1=$(date -d "$t1" +%s); t2=$(tail -1 kx.log|cut -d, -f1); ts2=$(date -d "$t2" +%s); it=$(wc -l kx.log|cut -d' ' -f1); retrys=$(wc -l retryf.txt| cut -d' ' -f1); ss=$(expr $ts2 - $ts1) ; timelag=$(date -d@$ss -u +%H:%M:%S); speed=$(expr \( $it - $retrys \) / \( $ts2 - $ts1 \)); echo "process $it items, take $timelag,  $speed it/s"

    เมื่อ run แล้ว ได้ผลลัพธ์ประมาณนี้

    process 17030016 items, 1334 it/s

    มาดูรายละเอียดกัน

    t1=$(head -1 kx.log|cut -d, -f1)

    เป็นการสร้างตัวแปร ชื่อ t1 ซึ่ง $(…) เป็นการสั่งให้คำสั่ง ภายในวงเล็บ นั้นทำงาน

    head -1 kx.log

    คำสั่ง head -1 คือ เอาบรรทัดแรก

    cut -d, -f1

    เป็นการ แยกข้อความ ด้วย , และเอา ฟิลด์ (field) ที่ 1 ออกมา

    ผลรวมของคำสั่งนี้ คือ จะได้ timestamp เก็บในตัวแปร t1

    2022-11-30 07:34:13

    เช่นเดียวกับเวลาของบรรทัดสุดท้าย เปลี่ยนจาก head เป็น tail ก็จะได้ ตัวแปร t2

    2022-11-30 11:12:19

    คราวนี้ เราจะรู้ได้ไง ว่า ระหว่าง 2022-11-30 07:34:13 กับ 2022-11-30 11:12:19 ห่างกันกี่วินาที ?

    เราสามารถใช้คำสั่ง (เก็บในตัวแปร ts2)

    date -d '2022-11-30 11:12:19' +%s

    เพื่อได้วินาทีของวันเวลา คือค่า

    1669781539

    เช่นดัวกับ เวลาเริ่มต้น (เก็บในตัวแปร ts1)

    date -d '2022-11-30 07:34:13' +%s

    จะได้ค่า

    1669768453

    มาถึงตรงนี้ เราก็จะได้ตัวแปร ts1, ts2, it เราจะหาความเร็วก็ต้องใช้สูตร

    speed = it / (ts2 - ts1)

    ใน shell script เราเขียนตรง ๆ อย่างนั้นไม่ได้ ต้องใช้ผ่านคำสั่ง expr (เก็บในตัวแปร speed)

    expr $it / \( $ts2 - $ts1 \)

    คราวนี้ เราต้องการรู้ด้วยว่า ใช้เวลาทำไปแล้ว กี่ชั่วโมง นาที วินาที คำสั่งนี้ ใช้ date -d แล้วใช้ @ ตามด้วยจำนวนวินาที

    date -d@60  -u +%H:%M:%S

    ใช้คำสั่งนี้ หา จำนวนวินาที เก็บในตัวแปร ss

    expr $ts2 - $ts1

    แล้วใช้คำสั่งนี้ แปลงเป็น ชั่วโมง นาที วินาที เก็บในตัวแปร timelag

    date -d@$ss -u +%H:%M:%S

    สุดท้าย เอามารวมกันทั้งหมด แล้ว echo ออกไป

    echo "process $it items, take $timelag,  $speed it/s"

    ผลที่ได้คือ

    process 17030016 items, take 04:29:03, 1334 it/s

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