Instruktaż/Tutorial Kubernetes k3s (out of the box)

3Qn

Ave UBI!
Q's Professional
11 Czerwiec 2016
398
3
161
113
QNAP
TS-x73A
Ethernet
1 GbE
Długo myślałem (nie jestem pewien czy można nazwać to tutorialem ;)) a raczej wydaje mi się że można to traktować jako przygotowanie do pracy z klastrem minikube/k3s/k8s podstawowe komendy klienta kubernetes (kubectl) oraz menadzera pakietów (helm).

Uruchomienie w budowanego (single-node) klastra Kubernetes k3s na Qnap'ie ogranicza się do aktywacji K3s w ContainerStation.

Zrzut ekranu_20221115_205300.png


Zarządzenie dostępny jest panelu z przeglądarki, tu się nie wypowiem bo nie korzystam w pracy ani prywatnie i osobiście nie znam osoby która by cokolwiek wyklikiwała.

Jako standardowe narzędzie do obsługi klastra (k3s/k8s/minikube) wykorzystamy kubectl. Proces instalacji opisany jest tu: kubectl w duecie z zsh (pluginem oh my bash) oraz auto uzupełnianiem dzięki któremu praca z cli jest ultra przyjemna działa auto-uzupełnianie komend podzbiorów.

Pobieramy plik kubeconfig.yaml (⚠️ pobrany plik będzie nazywał się k3s.yaml ⚠️)
Zawartość pliku k3s.yaml dopisujemy w odpowiednie sekcje user, cluster, context do pliku jeżeli istnieje
Kod:
./kube/config
jeżeli nie kopiujemy cały plik k3s.yaml i zmieniamy jego nazwę na config.
Od tej pory możemy pracować z naszym klastrem aby wyświetlić wszystkie dostępne klastry (lista zależna od aktualnie zdefiniowanych w pliku ./kubec/config)
Bash:
(base) ➜  ~ kubectl config get-clusters
NAME
minikube
kubernetes-dom-nas
kubernetes-biuro-nas
kubernetes-ovh
kubernetes-piwnica

Wszystkie wykonywane komendy kubectl wykonywane są w aktywnego kontekstu, aby sprawdzić dostępne wywołujemy komendę:
Bash:
(base) ➜  ~ kubectl config get-contexts
CURRENT   NAME                               CLUSTER               AUTHINFO        NAMESPACE
*         dom-admin@kubernetes-dom-nas       kubernetes-dom-nas    dom-admin
          biuro-admin@kubernetes-biuro-nas   kubernetes-biuro-nas  biuro-admin
          ovh-admin@kubernetes-ovh           kubernetes-ovh        ovh-admin
          piwnica-admin@kubernetes-piwnica   kubernetes-piwnica    piwnica-admin
          minikube                           minikube              minikube        default

Klaster domyślnie zawiera przestrzenie "namespace", systemowe krórych nie powinniśmy modyfikować u mnie są widoczne ponieważ zaznaczyłem to przy aktywacji K3s (w ContainerStation) totalnie bez sensu no ale są ;)
Bash:
(bash) ➜  ~ kubectl get ns
NAME                   STATUS   AGE
default                Active   4d22h
kube-system            Active   4d22h
kube-public            Active   4d22h
kube-node-lease        Active   4d22h
kubernetes-dashboard   Active   4d22h

Domyślnym roboczą przestrzenią jest "default" aby wyświetlić aktualne pody (instancje aplikacji sądzę że tam można to nazwać) możemy jest listować:
Bash:
(base) ➜  ~ kubectl get pods
No resources found in default namespace.
Wywołanie tej komendy jest rownoznaczne z:
Bash:
(base) ➜  ~ kubectl -n default get pods
No resources found in default namespace.

Pragnę wyczulić i wydaje mi się być dobrym nawykiem jest wskazywanie namespace-u "-n".

Zmiana kontekstu/klastra:

Bash:
(base) ➜  ~ kubectl config use biuro-admin@kubernetes-biuro-nas
Switched to context "biuro-admin@kubernetes-biuro-nas".

Pora na instalację menadżera pakietów kubernetes instalacja helm'a jest trywialnym, helm do pracy wymaga kubectl działa na aktywny kontekscie kubectl.
Poszukując gotowców proponuję szykać "helm chart ****"

Przykład najbardziej optymistyczny wyszykujemy interesujący nas aplikację w towarzystwie fraz "helm chart"
1) Tworzymy przetrzeń "smart-home":
Bash:
(base) ➜  ~ kubectl create namespace smart-home
namespace/smart-home created
2) Instalacja home-assitance:
- Dodanie repozytorium home-assistance
Bash:
(base) ➜  ~ helm repo add k8s-at-home https://k8s-at-home.com/charts/
"k8s-at-home" has been added to your repositories
- instalacja home-assistance: zaawansowana konfiguracja: home-assistant 13.4.2 · k8s-at-home/k8s-at-home
Bash:
(base) ➜  ~ helm -n smart-home install home-assistant k8s-at-home/home-assistant
NAME: home-assistant
LAST DEPLOYED: Wed Nov 16 21:49:37 2022
NAMESPACE: smart-home
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace smart-home -l "app.kubernetes.io/name=home-assistant,app.kubernetes.io/instance=home-assistant" -o jsonpath="{.items[0].metadata.name}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl port-forward $POD_NAME 8080:8123
Listowanie pod'ów:
Bash:
(base) ➜  ~ kubectl -n smart-home get pods
NAME                             READY   STATUS    RESTARTS   AGE
home-assistant-9db975878-mchnj   1/1     Running   0          2m42s
Śledzenie logów poda:
Bash:
(base) ➜  ~ kubectl -n smart-home logs -f home-assistant-9db975878-mchnj
[s6-init] making user provided files available at /var/run/s6/etc...exited 0.
[s6-init] ensuring user provided files have correct perms...exited 0.
[fix-attrs.d] applying ownership & permissions fixes...
[fix-attrs.d] done.
[cont-init.d] executing container initialization scripts...
[cont-init.d] done.
[services.d] starting services
[services.d] done.
No i interactywana konsola poda:
Bash:
(base) ➜  ~ kubectl -n smart-home exec -it home-assistant-9db975878-mchnj bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
bash-5.1#
Opis aktualny stan poda:
Bash:
(base) ➜  ~ kubectl -n smart-home describe pod home-assistant-9db975878-mchnj
Name:             home-assistant-9db975878-mchnj
Namespace:        smart-home
Priority:         0
Service Account:  default
Node:             qnap-k3s-q218b14086m/10.0.3.2
Start Time:       Wed, 16 Nov 2022 21:49:36 +0100
Labels:           app.kubernetes.io/instance=home-assistant
                  app.kubernetes.io/name=home-assistant
                  pod-template-hash=9db975878
Annotations:      <none>
Status:           Running
IP:               10.42.0.13
IPs:
  IP:           10.42.0.13
Controlled By:  ReplicaSet/home-assistant-9db975878
Containers:
  home-assistant:
    Container ID:   containerd://fbb586b44fc5f3ede0ede17565df3137014541c8221c5c4ede8d0d30c64c83ec
    Image:          ghcr.io/home-assistant/home-assistant:2022.5.4
    Image ID:       ghcr.io/home-assistant/home-assistant@sha256:ec6d67fbedfacc943977e89a993abc479be7ce2be5dd6bcf58d6b08161624ff8
    Port:           8123/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Wed, 16 Nov 2022 21:51:54 +0100
    Ready:          True
    Restart Count:  0
    Liveness:       tcp-socket :8123 delay=0s timeout=1s period=10s #success=1 #failure=3
    Readiness:      tcp-socket :8123 delay=0s timeout=1s period=10s #success=1 #failure=3
    Startup:        tcp-socket :8123 delay=0s timeout=1s period=5s #success=1 #failure=30
    Environment:
      TZ:  UTC
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-ddhv4 (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  kube-api-access-ddhv4:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type     Reason     Age    From               Message
  ----     ------     ----   ----               -------
  Normal   Scheduled  5m20s  default-scheduler  Successfully assigned smart-home/home-assistant-9db975878-mchnj to qnap-k3s-q218b14086m
  Normal   Pulling    5m20s  kubelet            Pulling image "ghcr.io/home-assistant/home-assistant:2022.5.4"
  Normal   Pulled     3m4s   kubelet            Successfully pulled image "ghcr.io/home-assistant/home-assistant:2022.5.4" in 2m15.854586749s
  Normal   Created    3m3s   kubelet            Created container home-assistant
  Normal   Started    3m3s   kubelet            Started container home-assistant
  Warning  Unhealthy  3m1s   kubelet            Startup probe failed: dial tcp 10.42.0.13:8123: connect: connection refused
Przekierowań bezpośrednio do serwisów, dziłają do czasu zmnięcia komenty przydatne jeżeli serwis, który domyślnie nie powinien być dostępny na zewnątrz chcemy by był chwilowo dostępny.
Bash:
(base) ➜  ~  kubectl -n smart-home port-forward pods/home-assistant-9db975878-mchnj 8123:8123
Forwarding from 127.0.0.1:8123 -> 8123
Forwarding from [::1]:8123 -> 8123
Handling connection for 8123
1668633136988.png


To teraz czas na bardziej ambitny projekt pełen stack homeassistant z brokerem mqtt (dla zigbee), influxem oraz grafaną taki mamy plan.

Zaczniemy od czyszczenia starego namespace:
Kod:
(base) ➜ ✗ kubectl delete ns smart-home
namespace "smart-home" deleted

Alternatywne podejście do deployów w kubernetesie realizowane mogą być poprzez tak zwane helm chart'y, które mają pewną analogie z plikami docker-compose.
Helm chart'y możemy isntalować predefiniowane repozytoria lub też tworzyć własne wariację bazujące na już istniejących repozytoriach helm'a, obrazach dockerowych.
My stworzymy słasne.
Towrzymy katalog np. "smart-home" w nim pliki "Chart.yaml" zawartość tego pliku to :
YAML:
apiVersion: v2
name: smart-stack
description: A Helm chart for Kubernetes

type: application
version: 1.0.0
appVersion: "1.0.0"

dependencies:
  - name: influxdb
    version: ^5.4.10
    repository: https://charts.bitnami.com/bitnami
  - name: grafana
    version: ^6.44.2
    repository: https://grafana.github.io/helm-charts
  - name: mosquitto
    version: ^4.8.2
    repository: https://k8s-at-home.com/charts/
  - name: home-assistant
    version: ^13.4.2
    repository: https://k8s-at-home.com/charts/
Oraz plik "values.yaml" który stanowi nasze indywidualne parametry dla wszystkich serwisów
YAML:
ingress:
  main:
    enabled: true
    annotations:
      nginx.org/websocket-services: home-assistant
    hosts:
      - host: home-assistant.nas
        paths:
          - path: /

volume:
  storageClassName: "standard"
  createPersistentVolume: true

# Pod settings
home-assistant:
  fullnameOverride: "home-assistant"
  env:
    TZ: "UTC+1"
  ingress:
    main:
      enabled: true
  # influxdb
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: home-assistant

influxdb:
  fullnameOverride: "db"
  auth.enabled: false
  influxdb.service.ports.http: 8888

grafana:
  fullnameOverride: "statistics"

mosquitto:
  fullnameOverride: "broker"

Instalacja naszego deyploymentu pierwszym krokie będzie przygotowanie wszystkich źródeł zależności:
Bash:
(base) ➜  smart-home git:(feature/full-stack) ✗ helm dependency build .
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "mojo2600" chart repository
...Successfully got an update from the "authelia" chart repository
...Successfully got an update from the "k8s-at-home" chart repository
...Successfully got an update from the "grafana" chart repository
...Successfully got an update from the "my-repo" chart repository
Update Complete. ⎈Happy Helming!⎈
Saving 4 charts
Downloading influxdb from repo https://charts.bitnami.com/bitnami
Downloading grafana from repo https://grafana.github.io/helm-charts
Downloading mosquitto from repo https://k8s-at-home.com/charts/
Downloading home-assistant from repo https://k8s-at-home.com/charts/
Deleting outdated charts
Następnie instalacją projektu:
Bash:
(base) ➜  smart-home git:(feature/full-stack) ✗ helm -n smart-home install -f values.yaml smart-stack .
W1119 19:52:36.584878   15085 warnings.go:70] policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
W1119 19:52:36.659251   15085 warnings.go:70] policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
NAME: smart-stack
LAST DEPLOYED: Sat Nov 19 19:52:35 2022
NAMESPACE: smart-home
STATUS: deployed
REVISION: 1
Proces instlacji weryfikujemy listując pody w naszym projekcie:
Bash:
(base) ➜  smart-home git:(feature/full-stack) ✗ kubectl -n smart-home get pods
NAME                              READY   STATUS              RESTARTS   AGE
db-79d4c767-k6k6b                 0/1     Pending             0          17s
broker-7676967445-bg47c           0/1     ContainerCreating   0          17s
statistics-7b88fc5cd5-855ld       0/1     ContainerCreating   0          17s
home-assistant-5db498c678-7jcg2   0/1     Running

Problem polega na udostepnienieu naszego serwisu na zewnątrz permanentne nie tylko przez użycie komendy port-forward.
 
Czesc,

swietnie przygotowany artykul - dzieki za podzielenie sie wiedza.

Czy mozesz przyblizyc jeszcze temat mozliwosci polaczenia sie z klastrem z zewnatrz?

How to use Container Station 3?
Networking
  • LoadBalancer services are supported on firmware 5.0.1 and later.
  • Ingress is unsupported.

Z tego co widze Ingress nie jest wspierany, ale zastanawiam sie jakie sa mozliwosci wystawienia uslug tak aby byly widoczne z sieci lokalniej.
Za pomoca docker-compose udalo mi sie rozwiazac ten temat tworzac wirtualny przelacznik i sec widoczna w lan. Przyklad:

YAML:
qnet-network:
    driver_opts:
      iface: eth0
    driver: qnet
    ipam:
      driver: qnet
      options:
        iface: eth0
      config:
        - subnet: 192.168.88.0/24
          gateway: 192.168.123.10

Wracajac do k3s, to probowalem stworzyc load balancer (teoterycznie dostepne od 5.0.1) za pomoca ponizszego yaml'a. Niestety przy odpytywaniu o status serwisu caly czas widze EXTERNAL_IP: <pending>

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
demo-service LoadBalancer 10.43.39.100 <pending> 80:61151/TCP 43m

Czy ma ktos moze jakies porady jak temu zaradzic badz jakies linki do dokumentacji qnap? Probowalem szukac wiedzy w kontekscie k8s i qnap i jedyna sensowna wiedze jaka znalazlem byla opisana w Twoim artykule.


Z gory dzieki za pomoc i pozdrawiam,
Milosz
 
ingress -> traefik (bardzo dobrze współpracuje z k3s kolega z forum używa caddy który wydaje mi się jest również "native cloud")

zarządzanie:
-> kubectl (baza trzeba znać)
-> k9s fajne takie konsolowe "mc"
-> openlenss (GUI free)
-> sądzę że plugin pod każde ide znajdziesz
 
Dzieki Mistrzu za podpowiedz.

Z tego co zauwazylem to trefik jest juz zainstalowany na QNAP.
Probuje zrobic jakis przykladowy setup i dziala mi pod warunkiem, ze robie port forward.
YAML:
apiVersion: v1
kind: Namespace
metadata:
  name: nginx-deployment
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.14.2
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80


---

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress-test

spec:
  rules:
    - http:
        paths:
          - path: /
            pathType: Exact
            backend:
              service:
                name: nginx-service
                port:
                  number: 80
Po wykonaniu describe na pod traefik widze, ze wystawia on dashboard na porcie 9000 a web jest dostepne na 8000.
Bash:
 k describe pod traefik-97b44b794-f97jz -n kube-system
Port forward na 9000 udostepnia mi dashboard a na 8000 jestem w stanie polaczyc sie z moim serwisem.
Bash:
k port-forward pod/traefik-97b44b794-f97jz 9001:9000 -n kube-system
k port-forward pod/traefik-97b44b794-f97jz 8001:8000 -n kube-system

Do tego momentu wszystko dziala jak nalezy. Niestety mam problem z polaczeniem sie do tego z LAN.

Na dashboard QNAP dotyczacym sieci widze, ze jest utworzona wirtualna siec i wirtualny adapter. Adres adapter zgadza sie z EXTERNAL-IP service'u traefik.
Kod:
kube-system            traefik                     LoadBalancer   10.43.4.166     10.0.3.2      80:61305/TCP,443:61434/TCP   17d    app.kubernetes.io/instance=traefik,app.kubernetes.io/name=traefik

Niestety kiedy odpytuje po ip 10.0.3.2 (lub domeny wskazujace na to ip) na portach 80,443,61305,9000,8000, etc. (wiem, ze bez sensu czesc z nich, ale warto bylo sie upewnic) dostaje ERR_CONNECTION_TIMED_OUT.

Zastanawiam sie co pominalem. Mam wrazenie, ze nie powiazalem serwisu treafik z wpisami ingress ale nigdzie nie moge znalezc informacji, ze nalezy to zrobic i jak. Czy mozna prosic o jakas wskazowke?
 
Czy kojarzysz moze czy powinienem ponownie zainstalowac albo zmodyfikowac traefik za pomoca Helm Chartow? Zastanawiam sie, czy gdzies nie musze ustawic w jakis sposob routingu badz odblokowac firewalla.
Z rzeczy ktore jeszcze probowalem przetestowac to w jaki sposob sie polaczyc do klastra w podobny sposob jak robilem to w docker-compose. Czyli zdefiniowanie sieci external i przypisanie do niej obrazu - dzieki czemu w QNAP powstanie wirtualny adapter z przypisanym zewnetrznym IP.
Probowalem wykonac kroki z Exposing an External IP Address to Access an Application in a Cluster oraz wczesniej z dokumentacji dotyczace epose --external-ip (kod ponizej) ab

Bash:
kubectl run my-pod --image=nginx
kubectl expose pod my-pod --port=80 --target-port=80 --external-ip=10.0.3.102

W obu przypadkach uslugi sie dodaly i przypisaly external_ip. Niestety polaczenie caly czas zawodzi.
Bash:
curl http://10.0.3.2:8080
curl: (28) Failed to connect to 10.0.3.2 port 8080 after 21034 ms: Couldn't connect to server

Rowniez wirtualne adaptery nie dodaly sie w QNAP.
 

Użytkownicy znaleźli tą stronę używając tych słów:

  1. kubernetes
  2. docker x64
  3. restart serwisu
  4. mqtt
  5. helm
  6. proces node
  7. homeassistant
  8. https://forum.qnap.net.pl/threads/kubernetes-k3s-out-of-the-box.39829/
  9. repositories
  10. Docker
  11. lista wszystkich NAS