Talos Linux 알아보기

Talos OS 이란?

  • 클라우드 네이티브 환경에서 Kubernetes 클러스터를 실행하는 데 최적화된 컨테이너 기반 리눅스 배포판
  • 관리와 보안을 중점으로 설계된 Talos OS는 Kubernetes의 컨트롤 플레인과 워커 노드를 효율적으로 운영할 수 있도록 간소화된 방식을 제공하며, 자동화와 관리의 복잡성을 최소화한 운영체제이다.

주요 특징

No Bash. No SSH. No Systemd.
  • 초경량 운영체제
    • Talos OS는 Kubernetes를 실행하기 위한 기본적인 요구 사항에 초점을 맞춰 최소한의 기능만 포함됨
    • OS 내 Package Manager, Shell(터미널), SSH 서버 등을 지원하지 않으며, 완전한 API 기반으로 관리됨
  • API 중심 관리
    • 기존 명령어 기반 관리가 아닌 모든 운영은 API로 관리되어 자동화, 확장성, 간소화가 쉬움
    • talosctl 전용 도구를 사용하여 클러스터 설정 및 디버깅 가능
  • 보안 강화
    • 읽기 전용 루트 파일 시스템으로 동작해 안정성과 보안을 제공
    • 자동화된 업데이트와 재부팅 없이도 클러스터의 안정성을 유지.
  • Kubernetes 네이티브 통합
    • Kubernetes의 관리 작업을 단순화하며, 클러스터를 빠르게 설정하고 유지할 수 있도록 최적화.
    • 다양한 클라우드 및 온프레미스 환경에서 Kubernetes를 실행 가능.
  • 운영 편리성
    • 운영체제의 설정을 선언적 방식(immutable)으로 정의
      • YAML 파일로 Machine의 설정을 정의
    • DevOps 및 GitOps Workflow와 호환 및 통합이 쉬움
  • 빠른 배포
    • 클러스터 생성, 업그레이드, 재배포가 몇 분 만에 완료됨. 
    • Kubernetes 환경을 신속하게 배포 가능
  • 단순성과 안정성
    • Package Manager, SSH, Patch 작업 등 별도의 설정 관리 도구가 필요 없으며, 이로 인해 오류와 중단 가능성을 크게 줄임
  • 단점
    • Secure Shell(이하 SSH)가 없으므로 전통적인 디버깅 방식이 제한됨
    • 일반적인 리눅스 운영체제로 사용하기 어렵고 Kubernetes 이외의 작업에는 부적합
지원 시스템

플랫폼 구분

이름

비고

Bare Metal 

Equinix Metal

Creating Talos clusters with Equinix Metal.

ISO

Booting Talos on bare-metal with ISO.

Matchbox

In this guide we will create an HA Kubernetes cluster with 3 worker nodes using an existing load balancer and matchbox deployment.

Network Configuration

In this guide we will describe how network can be configured on bare-metal platforms.

PXE

Booting Talos over the network on bare-metal with PXE.

SecureBoot

Booting Talos in SecureBoot mode on UEFI platforms.

Virtualized

Hyper-V

Creating a Talos Kubernetes cluster using Hyper-V.

KVM

OpenNebula

Proxmox

Creating Talos Kubernetes cluster using Proxmox.

Vagrant & Libvirt

VMware

Creating Talos Kubernetes cluster using VMware.

Xen

Cloud

Akamai

Creating a cluster via the CLI on Akamai Cloud (Linode).

AWS

Creating a cluster via the AWS CLI.

Azure

Creating a cluster via the CLI on Azure.

CloudStack

Creating a cluster via the CLI (cmk) on Apache CloudStack.

DigitalOcean

Creating a cluster via the CLI on DigitalOcean.

Exoscale

Creating a cluster via the CLI using http://exoscale.com

GCP

Creating a cluster via the CLI on Google Cloud Platform.

Hetzner

Creating a cluster via the CLI (hcloud) on Hetzner.

Kubernetes

Running Talos Linux as a pod in Kubernetes.

Nocloud

Creating a cluster via the CLI using qemu.

OpenStack

Creating a cluster via the CLI on OpenStack.

Oracle

Creating a cluster via the CLI (oci) on http://OracleCloud.com .

Scaleway

Creating a cluster via the CLI (scw) on http://scaleway.com .

UpCloud

Creating a cluster via the CLI (upctl) on http://UpCloud.com .

Vultr

Creating a cluster via the CLI (vultr-cli) on http://Vultr.com .

Local

Docker

Creating Talos Kubernetes cluster using Docker.

QEMU

Creating Talos Kubernetes cluster using QEMU VMs.

VirtualBox

Creating Talos Kubernetes cluster using VurtualBox VMs.

Single Board

https://www.talos.dev/v1.8/talos-guides/install/single-board-computers/

아키텍처

Architecture
Learn the system architecture of Talos Linux itself.

이름

설명

비고

EFI

EFI boot 데이터를 저장

BIOS

GRUB의 두 번째 단계 부팅에 사용

BOOT

부트 로더에 사용, initramfs 및 커널 데이터를 저장

META

node id's와 같은 탈로스 노드에 대한 메타데이터 저장

STATE

클러스터 검색을 위한 node identity data, machine configuration 등 KubeSpan 정보를 저장

EPHEMERAL

ephemeral 상태 정보를 저장, mounted at /var

라이센스

Talos OS는 Apache 2.0 라이선스이다. 이는 오픈소스 라이선스로, 개인, 비즈니스, 상업적 목적을 포함한 다양한 용도로 자유롭게 사용할 수 있음을 나타낸다.

  • 상업적 사용 가능
    • Talos OS를 상업적 제품이나 서비스에 포함하여 사용할 수 있음
  • 수정 및 배포 허용
    • 소스 코드를 수정하고 재배포할 수 있음
    • 수정한 내용은 명시적으로 언급해야 함(변경사항을 알릴 의무)
  • 라이선스 명시 요구
    • Talos OS를 사용하는 소프트웨어에 Apache 2.0 라이선스 사용 사실을 명시해야 함
  • 책임 면제
    • Talos OS의 사용으로 발생하는 문제에 대해 개발자는 책임을 지지 않음
  • 주의점
    • 상표 사용: Apache 2.0 라이선스는 Talos OS 이름이나 로고를 상업적으로 사용할 권리를 포함하지 않으며, 상표 사용 시 별도의 허가가 필요할 수 있음
Talos OS는 비즈니스에서 자유롭게 사용할 수 있으며, 라이선스 조건을 준수하면 상업적 활용에도 문제가 없다.

Talos OS 설정

필요 조건

  • 작업 컴퓨터
    • talosctl
    • kubectl
  • 서버
    • Control Plane
    • Worker

talosctl

curl -sL https://talos.dev/install | sh
talosctl version

kubectl

export OS="$(uname -s | tr A-Z a-z)" ARCH=$(test "$(uname -m)" = 'x86_64' && echo 'amd64' || echo 'arm64')
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/${OS}/${ARCH}/kubectl"
sudo install -m 0755 ./kubectl /usr/local/bin/kubectl
kubectl version

설치

이미지 준비
서버 구성

hostname

type

private_ip_address

mac_address

spec

talos-cp-01

control plane

192.168.0.106

BC:24:11:E3:03:3E

  • 2 (1sockets, 2cores) [x86-64-v2-AES]

  • 4GB RAM

  • 50GB SSD

  • talos-v1.8.1-metal-amd64.iso

talos-worker-01

worker

192.168.0.107

BC:24:11:42:0B:D4

talos-worker-02

worker

192.168.0.108

BC:24:11:2A:F5:CA

Talos OS 사용

disk 확인

참고: 기본적으로 Talos 구성은 /dev/sda에 설치되며, 설정에 따라 가상 디스크가 다르게 마운트될 수 있음 (ex. /dev/vda)

가상 디스크 경로가 다를 경우, controlplane.yaml, worker.yaml내 디스크 경로를 수정해야함

$ CP_IP=192.168.0.106
$ talosctl disks --insecure \
    --nodes $CP_IP
    
DEV          MODEL           SERIAL   TYPE      UUID   WWID   MODALIAS      NAME   SIZE     BUS_PATH                                                                  SUBSYSTEM          READ_ONLY   SYSTEM_DISK
/dev/loop0   -               -        UNKNOWN   -      -      -             -      4.1 kB   /virtual                                                                  /sys/class/block   *           
/dev/loop1   -               -        UNKNOWN   -      -      -             -      684 kB   /virtual                                                                  /sys/class/block   *           
/dev/loop2   -               -        UNKNOWN   -      -      -             -      77 MB    /virtual                                                                  /sys/class/block   *           
/dev/sda     QEMU HARDDISK   -        HDD       -      -      scsi:t-0x00   -      54 GB    /pci0000:00/0000:00:05.0/0000:01:01.0/virtio2/host2/target2:0:0/2:0:0:0   /sys/class/block               
/dev/sr0     QEMU DVD-ROM    -        CD        -      -      scsi:t-0x05   -      108 MB   /pci0000:00/0000:00:01.1/ata2/host1/target1:0:0/1:0:0:0                   /sys/class/block               

Kubernetes 구성 및 설치

  • 공통 환경 변수 설정
export TALOS_CUSTOM=$HOME/talos_conf
export TALOSCONFIG=$TALOS_CUSTOM/config/talosconfig

export CONTROLPLANE_IP=192.168.0.106
export CONTROLPLANE_IPS=("192.168.0.106")
export WORKER_IPS=("192.168.0.107" "192.168.0.108")
  • talos 콘픽 폴더 생성
mkdir -p $TALOS_CUSTOM/config
mkdir -p $TALOS_CUSTOM/patches
mkdir -p $TALOS_CUSTOM/results
  • secrets.yaml 생성
talosctl gen secrets -o $TALOS_CUSTOM/config/secrets.yaml
  • Kubernetes Cluster Configurations 생성
    • patch
      • allow-controlplane-workloads.yaml : Control Plane 에서 Workloads 작업 허용
How to enable workers on your control plane nodes
How to enable workers on your control plane nodes.
    • ipvs-strict-arp-enabled.yaml : metalLB 사용 시, Strict ARP 설정
    • none-network-cni.yaml : Cilium CNI 사용을 위해 기본 Network CNI None 처리
Deploying Cilium CNI
In this guide you will learn how to set up Cilium CNI on Talos.
    • disable-kube-proxy.yaml : Cilium CNI 에서 kube-proxy 대체
Kube-proxy Replacement
Enhanced networking speed and efficiency for your Kubernetes clusters
    • control-plane-patch.yaml
    • worker-patch.yaml
cat << EOF > $TALOS_CUSTOM/patches/allow-controlplane-workloads.yaml
# patches/allow-controlplane-workloads.yaml
cluster:
  allowSchedulingOnControlPlanes: true
EOF

cat << EOF > $TALOS_CUSTOM/patches/ipvs-strict-arp-enabled.yaml
# patches/ipvs-strict-arp-enabled.yaml
- op: add
  path: /cluster/proxy
  value:
    disabled: false
    mode: ipvs
    extraArgs:
      ipvs-strict-arp: true
EOF

cat << EOF > $TALOS_CUSTOM/patches/none-network-cni.yaml
# patches/none-network-cni.yaml
- op: add
  path: /cluster/network/cni
  value:
    name: none
EOF

cat << EOF > $TALOS_CUSTOM/patches/disable-kube-proxy.yaml
# patches/disable-kube-proxy.yaml
- op: add
  path: /cluster/proxy
  value:
    disabled: true
EOF

cat << EOF > $TALOS_CUSTOM/patches/control-plane-patch.yaml
# patches/control-plane-patch.yaml
- op: replace
  path: /machine/network
  value:
    interfaces:
      - interface: eth0
- op: replace
  path: /machine/network/interfaces/0
  value:
    interface: eth0
    dhcp: true
    mtu: 1500
EOF

cat << EOF > $TALOS_CUSTOM/patches/worker-patch.yaml
# patches/worker-patch.yaml
- op: replace
  path: /machine/network
  value:
    interfaces:
      - interface: eth0
- op: replace
  path: /machine/network/interfaces/0
  value:
    interface: eth0
    dhcp: true
    mtu: 1500
EOF

  • config
    • output
      • config은 $TALOS_CUSTOM 폴더에 생성된다.
        • $TALOS_CUSTOM/config/controlplane.yaml
        • $TALOS_CUSTOM/config/worker.yaml
        • $TALOS_CUSTOM/talosconfig
talosctl gen config my-talos-cluster https://$CONTROLPLANE_IP:6443 \
  --install-disk /dev/sda \
  --with-secrets $TALOS_CUSTOM/config/secrets.yaml \
  --kubernetes-version 1.31.2 \
  --config-patch @$TALOS_CUSTOM/patches/disable-kube-proxy.yaml \
  --config-patch @$TALOS_CUSTOM/patches/none-network-cni.yaml \
  --config-patch-control-plane @$TALOS_CUSTOM/patches/control-plane-patch.yaml \
  --config-patch-worker @$TALOS_CUSTOM/patches/worker-patch.yaml \
  --output-dir $TALOS_CUSTOM/config
  • $TALOS_CUSTOM/talosconfig 내 endpoint를 지정해준다. 
talosctl config endpoint $CONTROLPLANE_IPS
  • hostname 변경
CONTROLPLANE_IPS=("192.168.0.106")
WORKER_IPS=("192.168.0.107" "192.168.0.108")

index=1
for CONTROLPLANE_IP in "${CONTROLPLANE_IPS[@]}"; do
  talosctl machineconfig patch $TALOS_CUSTOM/config/controlplane.yaml \
    --nodes "$CONTROLPLANE_IP" \
    --patch '[{"op": "add", "path": "/machine/network/hostname", "value": "talos-cp-'$(printf '%02d' $index)'"}]' \
    --output $TALOS_CUSTOM/results/talos-cp-$(printf '%02d' $index).yaml
  index=$((index + 1))
done

index=1
for WORKER_IP in "${WORKER_IPS[@]}"; do
  talosctl machineconfig patch $TALOS_CUSTOM/config/worker.yaml \
    --nodes "$WORKER_IP" \
    --patch '[{"op": "add", "path": "/machine/network/hostname", "value": "talos-worker-'$(printf '%02d' $index)'"}]' \
    --output $TALOS_CUSTOM/results/talos-worker-$(printf '%02d' $index).yaml
  index=$((index + 1))
done

control plane & worker 노드 콘픽 적용

Editing Machine Configuration
How to edit and patch Talos machine configuration, with reboot, immediately, or stage update on reboot.
  • talosctl apply-config
  • talosctl edit machineconfig
  • talosctl patch machineconfig
  • apply-config 재부팅 옵션
    • 재부팅 적용 (--mode=reboot): 변경 사항을 적용하고 노드를 재부팅하여 업데이트
    • 즉시 적용 (--mode=no-reboot): 재부팅 없이 즉시 적용. 재부팅이 필요한 변경 사항은 실패
    • 다음 재부팅 시 적용 (--mode=staged): 변경 사항을 저장해 두고, 다음 재부팅 시 적용
    • 자동 되돌리기 적용 (--mode=try): 즉시 변경 적용. 실패 시 1분 후 자동 되돌리기
    • 대화형 모드 (--mode=interactive): TUI 기반 관리자를 통해 대화형으로 구성 변경
index=1
for CP_IP in "${CONTROLPLANE_IPS[@]}"; do
  talosctl apply-config \
    --insecure \
    --nodes "$CP_IP" \
    --file $TALOS_CUSTOM/results/talos-cp-$(printf '%02d' $index).yaml
  index=$((index + 1))
done
index=1
for WOR_IP in "${WORKER_IPS[@]}"; do
  talosctl apply-config \
    --insecure \
    --nodes "$WOR_IP" \
    --file $TALOS_CUSTOM/results/talos-worker-$(printf '%02d' $index).yaml
  index=$((index + 1))
done
  • 메인 Control Plane 클러스터 구성
    • Kubernetes 클러스터 구축
talosctl --nodes $CONTROLPLANE_IP bootstrap
    • Kubernetes 구성 확인
talosctl kubeconfig -n $CONTROLPLANE_IP $TALOS_CUSTOM/results

kubectl get nodes --kubeconfig $TALOS_CUSTOM/results/kubeconfig

  • network CNI
    • cilium
Deploying Cilium CNI
In this guide you will learn how to set up Cilium CNI on Talos.
export KUBECONFIG=$TALOS_CUSTOM/results/kubeconfig

helm repo add cilium https://helm.cilium.io/
helm repo update cilium 

helm install \
    cilium \
    cilium/cilium \
    --version 1.16.3 \
    --namespace kube-system \
    --set ipam.mode=kubernetes \
    --set kubeProxyReplacement=true \
    --set securityContext.capabilities.ciliumAgent="{CHOWN,KILL,NET_ADMIN,NET_RAW,IPC_LOCK,SYS_ADMIN,SYS_RESOURCE,DAC_OVERRIDE,FOWNER,SETGID,SETUID}" \
    --set securityContext.capabilities.cleanCiliumState="{NET_ADMIN,SYS_ADMIN,SYS_RESOURCE}" \
    --set cgroup.autoMount.enabled=false \
    --set cgroup.hostRoot=/sys/fs/cgroup \
    --set k8sServiceHost=localhost \
    --set k8sServicePort=7445 \
    --set hubble.relay.enabled=true \
    --set hubble.ui.enabled=true
    • calico (Not tested) 
helm repo add projectcalico https://docs.projectcalico.org/charts/
helm repo update projectcalico

helm install my-tigera-operator projectcalico/tigera-operator \
  --version 3.29.0 \
  --create-namespace \
  --namespace tigera-operator

기타 명령어

  • 대시보드
talosctl -n <NODEIP> dashboard
  • 서비스 목록
talosctl -n <NODEIP> service
  • 프로세스 목록
talosctl -n <NODEIP> processes
  • 쿠버네티스 버전 업그레이드
talosctl --nodes $CONTROLPLANE_IP upgrade-k8s \
  --to "1.31.2"
  • 이미지 업그레이드
talosctl upgrade --nodes $CONTROLPLANE_IP --image factory.talos.dev/installer/4a0d65c669d46663f377e7161e50cfd570c401f26fd9e7bda34a0216b6f1922b:v1.8.3 -m powercycle -f

확장

extensions/network/tailscale/README.md at main · siderolabs/extensions
Talos Linux System Extensions. Contribute to siderolabs/extensions development by creating an account on GitHub.
---
apiVersion: v1alpha1
kind: ExtensionServiceConfig
name: tailscale
environment:
  - TS_AUTHKEY=<your auth key>

tailscale.patch.yaml

talosctl patch mc \
  -n $CONTROLPLANE_IP \
  -p @$TALOS_CUSTOM/patches/tailscale.patch.yaml

machine patch

talosctl apply-config \
  --nodes $CONTROLPLANE_IP \
  --file $TALOS_CUSTOM/results/talos-cp-01.yaml
  --config-patch @$TALOS_CUSTOM/patches/tailscale.patch.yaml

apply-config patch

Trouble Shoot

kubectl get pods \
  -n kube-system \
  --field-selector=status.phase=Failed \
  -o name | xargs kubectl delete -n kube-system --force --grace-period=0 

root@proxmox:~/talos_conf# mkdir config2
root@proxmox:~/talos_conf# talosctl gen config my-talos-cluster https://$CONTROLPLANE_IP:6443 \
  --install-disk /dev/sda \
  --with-secrets $TALOS_CUSTOM/config/secrets.yaml \
  --kubernetes-version 1.31.2 \
  --config-patch @$TALOS_CUSTOM/patches/disable-kube-proxy.yaml \
  --config-patch @$TALOS_CUSTOM/patches/none-network-cni.yaml \
  --config-patch-control-plane @$TALOS_CUSTOM/patches/control-plane-patch.yaml \
  --config-patch-worker @$TALOS_CUSTOM/patches/worker-patch.yaml \
  --output-dir $TALOS_CUSTOM/config2
generating PKI and tokens
Created /root/talos_conf/config2/controlplane.yaml
Created /root/talos_conf/config2/worker.yaml
Created /root/talos_conf/config2/talosconfig
root@proxmox:~/talos_conf# ls
config  config2  examples  patches  results
root@proxmox:~/talos_conf# diff config/controlplane.yaml config2/controlplane.yaml 
506,593d505
<     # A list of inline Kubernetes manifests.
<     inlineManifests:
<         - name: cilium-install # Name of the manifest.
<           contents: | # Manifest contents as a string.
<             ---
<             apiVersion: rbac.authorization.k8s.io/v1
<             kind: ClusterRoleBinding
<             metadata:
<               name: cilium-install
<             roleRef:
<               apiGroup: rbac.authorization.k8s.io
<               kind: ClusterRole
<               name: cluster-admin
<             subjects:
<             - kind: ServiceAccount
<               name: cilium-install
<               namespace: kube-system
<             ---
<             apiVersion: v1
<             kind: ServiceAccount
<             metadata:
<               name: cilium-install
<               namespace: kube-system
<             ---
<             apiVersion: batch/v1
<             kind: Job
<             metadata:
<               name: cilium-install
<               namespace: kube-system
<             spec:
<               backoffLimit: 10
<               template:
<                 metadata:
<                   labels:
<                     app: cilium-install
<                 spec:
<                   restartPolicy: OnFailure
<                   tolerations:
<                     - operator: Exists
<                     - effect: NoSchedule
<                       operator: Exists
<                     - effect: NoExecute
<                       operator: Exists
<                     - effect: PreferNoSchedule
<                       operator: Exists
<                     - key: node-role.kubernetes.io/control-plane
<                       operator: Exists
<                       effect: NoSchedule
<                     - key: node-role.kubernetes.io/control-plane
<                       operator: Exists
<                       effect: NoExecute
<                     - key: node-role.kubernetes.io/control-plane
<                       operator: Exists
<                       effect: PreferNoSchedule
<                   affinity:
<                     nodeAffinity:
<                       requiredDuringSchedulingIgnoredDuringExecution:
<                         nodeSelectorTerms:
<                           - matchExpressions:
<                               - key: node-role.kubernetes.io/control-plane
<                                 operator: Exists
<                   serviceAccount: cilium-install
<                   serviceAccountName: cilium-install
<                   hostNetwork: true
<                   containers:
<                   - name: cilium-install
<                     image: quay.io/cilium/cilium-cli-ci:latest
<                     env:
<                     - name: KUBERNETES_SERVICE_HOST
<                       valueFrom:
<                         fieldRef:
<                           apiVersion: v1
<                           fieldPath: status.podIP
<                     - name: KUBERNETES_SERVICE_PORT
<                       value: "6443"
<                     command:
<                       - cilium
<                       - install
<                       - --set ipam.mode=kubernetes
<                       - --set kubeProxyReplacement=true
<                       - --set hubble.relay.enabled=true
<                       - --set hubble.ui.enabled=true
<                       - --set securityContext.capabilities.ciliumAgent="{CHOWN,KILL,NET_ADMIN,NET_RAW,IPC_LOCK,SYS_ADMIN,SYS_RESOURCE,DAC_OVERRIDE,FOWNER,SETGID,SETUID}"
<                       - --set securityContext.capabilities.cleanCiliumState="{NET_ADMIN,SYS_ADMIN,SYS_RESOURCE}"
<                       - --set cgroup.autoMount.enabled=false
<                       - --set cgroup.hostRoot=/sys/fs/cgroup
<                       - --set k8sServiceHost=localhost
<                       - --set k8sServicePort=7445
620a533,541
> 
>     # # A list of inline Kubernetes manifests.
>     # inlineManifests:
>     #     - name: namespace-ci # Name of the manifest.
>     #       contents: |- # Manifest contents as a string.
>     #         apiVersion: v1
>     #         kind: Namespace
>     #         metadata:
>     #                 name: ci
You've successfully subscribed to taking
Great! Next, complete checkout to get full access to all premium content.
Error! Could not sign up. invalid link.
Welcome back! You've successfully signed in.
Error! Could not sign in. Please try again.
Success! Your account is fully activated, you now have access to all content.
Error! Stripe checkout failed.
Success! Your billing info is updated.
Error! Billing info update failed.