สร้าง K8S Cluster ด้วย Proxmox+Talos

What is Talos Linux ?

  • Linux for distributed systems for Container > Kubernetes = เกิดมาเพื่อเป็น Container และทำมาสำหรับ K8S
  • secure by default
    - eliminates console / shell / SSH access ตัดออกหมดเลย เหลือแต่หน้า Dashboard เท่านั้น คหสต เวลาพังดูยาก เปิด Log จาก Console ของ Proxmox อารมณ์ไปดูหน้าเครื่อง หรือ Query จาก talosctl
    - Network Card ยังสุ่มเลย ขึ้นแต่ละรอบไม่เหมือนกัน
  • Managed by API
    - พอตัดหมด จัดการผ่าน CLI ที่จะยิง Request ผ่าน API เท่านั้น ปรับอะไรต้องสร้าง Yaml ของ Machine และ Apply เอา
    - มีพวก Mutual TLS / RBAC และตัว Pod Security | Talos Linux
  • Minimalism
  • Open source

จริงๆมันมีตัวที่ทำให้ใช้งานขึ้น A Better Way to Run Kubernetes - Sidero Labs

ภาพรวมของ Infra ชุดนี้

สำหรับ Blog นี้ ผมจะอิงตามคู่มือใน Proxmox | Talos Linux (จริงมีลงใน Stack อื่นๆด้วย) และมาเติมรายละเอียดเพิ่มเติมเข้าไปครับ

ต่อไปเรามา Setup Cluster กัน โดยมี Base จาก Proxmox 8.1 (Blog Setup เขียนแยกอีกอัน 555 แปะ Step ไว้ใน Blog แหละ เผื่อมันพัง)

สำหรับตัว Infra มี ดังรูปเลย

VMK8S RolevCPUMemoryDiskHostnameIP
talos-pve-controlpane0Control Pane (Master)22GB15GBtalos-controlpane-0192.168.1.220
talos-pve-worker0Worker Node (Slave)22GB32GBtalos-worker-0192.168.1.221
จริงๆ Hostname ใช้ . แทน - แต่ Cap รูปไปหมดแล้ว 555

Note:

  • Spec For Test เท่านั้น ถ้าของจริงต้องคิดอีกเยอะ ตั้งแต่
    - Proxmox (Security / Disk / Hardening / HA / etc... )
    - Talos - Scale เข้าใจว่า ถ้าต้องการเพิ่ม Worker Node เอา Yaml ไปรันเพิ่มนะ / HA ด้วยไหม
  • ถ้ามี Worker เพิ่ม VM แล้วเอา YAML ของ Worker ไป talosctl apply
  • HW เป็น NUC เก่าๆ มือ2 น่าจะ 5 ปีแล้ว Intel Gen 6 / RAM 8 GB / HDD 250 GB
  • Component ของ Talos คล้ายกับของ K8S ลองเข้าไปดูเพิ่มเติมได้ >> Components | Talos Linux
  • จริงมัน preload k8s component เข้ามาเลย แต่ต้องไปดูใน Release Releases · siderolabs/talos (github.com)

Create VM

- Download VM

ตัว Proxmox จะ Upload ISO หรือ ให้ตัว Proxmox Download from URL มาให้ มีขั้นตอน ดังนี้

Note: ถ้าเป็นการ Download from URL เอา Link Git แปะได้เลย

  • Pattern
https://github.com/siderolabs/talos/releases/download/<version>/metal-<arch>.iso
  • Sample
https://github.com/siderolabs/talos/releases/download/v1.6.1/metal-amd64.iso
- Create VM Control Pane
  • สร้าง VM ใน Proxmox โดยทีข้อมูลตามนี้
VMK8S RolevCPUMemoryDiskHostnameIP
talos-pve-controlpane0Control Pane (Master)22GB15GBtalos-controlpane-0192.168.1.220
  • ตอนนี้เราจะได้ VM ที่มันจะแจ้งว่าใน Maintenace Mode
  • กด F3 ตอนนี้เราต้อง Fixed IP ก่อน ว่าจะให้มันเป็น IP 192.168.1.220 โดยตั้งค่าตามในส่วน Configure (Ctrl+Q) แล้วกด tab ไปตั้งค่า และบาง Field ต้องเลือก Combo ก่อน มันถึงจะโผล่มา
    และจำ LinkName ดีๆนะครับ เดวเอาไปใช้ใน machine config ต่อ

NOTE: ตัว Network Interface เดิม ถ้าใครลอง Image Ver ต่ำกว่า 1.5.xxx จะเป็น eth0 หลังจากนั้นมันจะ Random ชื่อตาม Predictable Network Interface Names นั่งงมหลายวันตามคู่มือหลายที่ว่าทำไม Set eth0 แล้ว IP ไม่เปลี่ยน 5555

  • IP เปลี่ยน และ
- Create VM Worker
  • ขั้นตอนคล้ายกัน Control Pane แต่อันนี้ผมจะเพิ่ม Disk นิดนึงของ Control Pane 15 GB ตัว Woker 32 GB ครับ
VMK8S RolevCPUMemoryDiskHostnameIP
talos-pve-worker0Worker Node (Slave)22GB32GBtalos-worker-0192.168.1.221
  • ตอนนี้เราจะได้ VM ที่มันจะแจ้งว่าใน Maintenace Mode ทำเหมือนกันตัว VM Control Pane ครับ แก้ IP ตามที่เรากำหนดไว้

Install talos cli

  • Linux / Mac
curl -sL https://talos.dev/install | sh
  • Windows
    - เข้าไป Download เอง จาก release ไฟล์ talosctl-windows-amd64.exe (ของ V1.6.1) ถ้าอยากได้ตัวใหม่กว่านี้ดูจาก https://github.com/siderolabs/talos/releases/tag/<<latest-version>>
    - เอา exe ที่ได้ไปวางใน Environment Variable ตัวแปร Path

Setup K8S Cluster

1. Generate Machine Config

ทำไมต้องใช้ Machine Config เพราะตัว Talos มันเชื่อการตั้งค่าจากตัวนี้ โดยที่ตัว Machine Config เป็น Yaml คล้ายๆกับที่ตัว Deployment ใน K8S แต่เยอะกว่ามาก
Note: ถ้าไปส่ง Param ใน Kernel ตอน Start ใน Machine Config มันลบทิ้งอออกหมดนะ (Ref: Network Configuration - Kernel Command Line | Talos Linux)

  • ก่อนอื่นต้องลง talos cli
  • Run คำสั่ง เพื่อให้ระบบมัน Gen YAML ให้
export CONTROL_PLANE_IP=192.168.1.220
talosctl gen config talos-proxmox-cluster https://$CONTROL_PLANE_IP:6443 --output-dir _out

//Powershell Style
$env:CONTROL_PLANE_IP= '192.168.1.220'
talosctl gen config talos-proxmox-cluster https://"$env:CONTROL_PLANE_IP":6443 --output-dir _out

Note: ถ้าต้องการให้ Secure ขึ้น Generate Secret ตามคำสั่งดังนี้แทน

talosctl gen secrets -o secrets.yaml

talosctl gen config --with-secrets secrets.yaml <cluster-name> <cluster-endpoint>
  • ตอนนี้ระบบจะได้มา 3 ไฟล์
    - controlplane.yaml
    - worker.yaml
    - talosconfig
  • แก้ไขไฟล์ controlplane.yaml เพื่อ Fixed IP และทำ DNS ที่ extraHostEntries
machine:
  network:
    hostname: talos-controlpane-0
    interfaces:
      - interface: enxbc24113fdb31 # The interface name - System Generate ตอน Start VM
        addresses:
          - 192.168.1.220/24
        routes:
          - network: 0.0.0.0/0 # The route's network.
            gateway: 192.168.0.1 # The route's gateway.
        dhcp: true

    nameservers:
      - 192.168.0.1
      - 8.8.4.4
      - 8.8.8.8
      - 1.1.1.1

    extraHostEntries:
    - ip: 192.168.1.220 # The IP of the host.
      # The host alias.
      aliases:
      - talos-controlpane-0
    - ip: 192.168.1.221 # The IP of the host.
      # The host alias.
      aliases:
      - talos-worker-0

Note พวก disk จะ default ที่  /dev/sda ต้องมาแก้ให้เรียบร้อยก่อน Apply ครับ

2. Create Control Pane
  • Apply Change ตอนนี้
talosctl apply-config --insecure --nodes $CONTROL_PLANE_IP --file _out/controlplane.yaml

//Powershell Style
talosctl apply-config --insecure --nodes $env:CONTROL_PLANE_IP --file _out/controlplane.yaml
3. Create Worker Node
  • แก้ไขไฟล์ worker.yaml เพื่อ Fixed IP และทำ DNS ที่ extraHostEntries
 network:
    # `interfaces` is used to define the network interface configuration.
      hostname: talos-controlpane-0
      interfaces:
      - interface: enxbc24113fdb31  # The interface name.
        # Assigns static IP addresses to the interface.
        addresses:
          - 192.168.1.220/24
          # A list of routes associated with the interface.
        routes:
        - network: 0.0.0.0/0 # The route's network (destination).
          gateway: 192.168.1.1 # The route's gateway (if empty, creates link scope route).
          metric: 1024 # The optional metric for the route.
        mtu: 1500 # The interface's MTU.

      #Used to statically set the nameservers for the machine.
      nameservers:
      - 8.8.8.8
      - 1.1.1.1
      - 192.168.1.1
      - 8.8.4.4

      # Allows for extra entries to be added to the `/etc/hosts` file
      extraHostEntries:
        - ip: 192.168.1.220 # The IP of the host.
          # The host alias.
          aliases:
            - talos-controlpane-0
        - ip: 192.168.1.221 # The IP of the host.
          # The host alias.
          aliases:
            - talos-worker-0
  • Apply Change ตอนนี้
export WORKER_IP =192.168.1.221
talosctl apply-config --insecure --nodes $WORKER_IP --file _out/worker.yaml

//Powershell Style
$env:WORKER_IP = '192.168.1.221'
talosctl apply-config --insecure --nodes $env:WORKER_IP --file _out/worker.yaml
  • ตรงนี้ Apply Yaml เรียบร้อยแล้ว สังเกตุว่า Cluster Name ไม่ขึ้น ถ้าลองไปดู Yaml ControlPane / Worker ต่างกันที่ไม่มี Cluster Name อันนี้ระบบมัน Generate เราจะปล่อยข้ามไปก่อน
4. Config Cluster

กำหนด Config ทำได้ 2 แบบ

  • กำหนดผ่าน Environment Variable จากนั้นกำหนด endpoint / node
export TALOSCONFIG="_out/talosconfig"
talosctl config endpoint $CONTROL_PLANE_IP
talosctl config node $CONTROL_PLANE_IP

//Powershell Style
$env:TALOSCONFIG= "_out/talosconfig"
talosctl config endpoint $env:CONTROL_PLANE_IP
talosctl config node $env:CONTROL_PLANE_IP
  • หรือ ส่ง talosconfig ไปเป็น Param เลย
=========================================================================
//อีกแบบไม่ต้อง Set Env เข้าไป
talosctl --talosconfig _out/talosconfig config endpoint $CONTROL_PLANE_IP
talosctl --talosconfig _out/talosconfig config node $CONTROL_PLANE_IP

//Powershell Style
talosctl --talosconfig _out/talosconfig config endpoint $env:CONTROL_PLANE_IP
talosctl --talosconfig _out/talosconfig config node $env:CONTROL_PLANE_IP

Initial K8S Cluster ทำที่ตัว Control pane ดู endpoint / node ดีๆ ต้องเป็น 192.168.1.220

talosctl bootstrap

รอไปสักพักนึง เราจะพบว่า หลังจากที่มัน Initial etcd แล้ว และจัดการอย่างอื่น ตอนนี้ทั้ง Control Pane / Worker สถานะ Ready แล้วครับ

  • Control Pane
  • Worker

ถ้าต้องการเพิ่ม Node เอาไฟล์ worker.yaml มาแก้ไข Config แล้ว Apply ได้เลย

Command อื่นๆ
  • Retrieve kernel logs
talosctl dmesg
  • List talos container
talosctl containers -k  //k8s.io containerd namespace

talosctl containers
  • ถ้าต้องการแก้ Config ของตัว Talos เนื่องจากมันปลอดภัยมาก ไม่มี Shell ดูได้จาก talosctl ถ้าจะแก้ไข ต้องมาแก้ YAML ของ Machine
    ** กำหนด Endpoint / Node และ Key (talosconfig) ให้เรียบร้อย
talosctl edit machineconfig

Retrieve the kubeconfig

talosctl kubeconfig .  

//อีกแบบไม่ต้อง Set Env เข้าไป
talosctl --talosconfig _out/talosconfig kubeconfig .

=================================================================
//default filename >> kubeconfig
//if you want to custom
 talosctl kubeconfig talos_pve_local     //config file name talos_pve_local

Testing

- kubectl

Install kubectl ตามนี้เลย Install Tools | Kubernetes จากนั้นเอาไฟล์ที่ได้จาก Step Retrieve the kubeconfig Copy ไปแปะใน $HOME/.kube

  • Linux
//If .kube not exist run this command
mkdir -p $HOME/.kube   

//Copy Config
sudo cp -i kubeconfig $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
  • Windows - Copy มือได้

จากนั้นลองดูก่อนว่าเราจิ้มที่เครื่องไหน

kubectl config get-contexts
  • ของผมจิ้มที่ Cluster ที่เพิ่งสร้างพอดีครับ ถ้าไปดูใน Step ตอนสร้าง Control Pane ผมกำหนดชื่อไว้เป็น talos-proxmox-cluster
  • ลองดู node / pod
kubectl get nodes -o wide

kubectl get pods -A
- Sample Image

ลอง Get Node ปกติแล้ว มาเอา Image มาลอง Deploy ครับ test_talos_nginx.yaml

apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: null
  name: test-talos
spec: {}
status: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: test-talos
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2 
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
  • Apply - เจอ Warning เหมือนตัว Talos จะเปิด Pod Security Graduates มาให้เลย
kubectl apply -f testnginx.yaml
===========================
namespace/test-talos created
Warning: would violate PodSecurity "restricted:latest": allowPrivilegeEscalation != false (container "nginx" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (container "nginx" must set securityContext.capabilities.drop=["ALL"]), runAsNonRoot != true (pod or container "nginx" must set securityContext.runAsNonRoot=true), seccompProfile (pod or container "nginx" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")
deployment.apps/nginx-deployment created

ตรวจสอบ

  • Get Pod
kubectl get pod -n test-talos
===========================
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-7c79c4bf97-c6fx6   1/1     Running   0          46s
nginx-deployment-7c79c4bf97-gs9sj   1/1     Running   0          46s
  • Expose
kubectl expose deployment nginx-deployment -n test-talos --type=NodePort --port=80
===========================
service/nginx-deployment exposed
kubectl get svc -n test-talos
===========================
NAME               TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
nginx-deployment   NodePort   10.104.142.124   <none>        80:32740/TCP   43s
  • View URL http://NodeIP:ExposePort
    ดู nodeip จาก kubectl get nodes -o wide column INTERNAL-IP
    ในที่นี้ Worker Node = 192.168.1.221
    ดังนั้น url ที่ access http://192.168.1.221:32740

Reference


Discover more from naiwaen@DebuggingSoft

Subscribe to get the latest posts to your email.