Czas usiąść za ster

Kubernetes paź 05, 2020

W życiu każdej osoby przychodzi taki moment, że trzeba wziąć sprawy w swoje ręce i zostać kowalem własnego losu. Natomiast ja, zamiast tego zostanę "sternikiem", na tym wzburzonym morzu, jakim jest Kubernetes :)

Proxmox a Kubernetes

Kubernetes to narzędzie do zarządzania i skalowania aplikacji zamieszczonych w kontenerach, które są przez jednych wychwalane, a przez innych znienawidzone. Ja nie jestem w stanie jeszcze stwierdzić, po której stronie mocy stoję, bo nie mam z nimi takiego doświadczenia.

Jeżeli czytałeś ostatni post, to zamieściłem tam informację, że HomeLab będzie budowany na Proxmox - niestety musiałem zrezygnować z tego pomysłu z jednego powodu. Proxmox nie jest po prostu aplikacją - jest to bootowany system tam samo jak Windows i Linux.

Jako, że póki co wszystko się dzieje na moim lokalnym PC, nie jest to rozwiązanie dla mnie - przecież czasami trzeba zagrać w jakąś gierkę czy obejrzeć serial na Netflixie :) Postawienie Proxmoxa na VM niestety nie zdało egzaminu, gdyż zauważyłem problemy z wydajnością. Dopiero, gdy będę miał już swój mini-serwer, wtedy chętnie wypróbuję tam Proxmoxa, a póki co mój wybór padł na Kubernetes i postawienie aplikacji w kontenerach. Myślę, że to idealna okazja, żeby z K8s się zaznajomić :)

Pierwsze wrażenie

Pierwszy kontakt był taki sam jak z każdym narzędziem, czyli doczytałem jakie tak naprawdę problemy rozwiązuje K8s, a następnie w jaki sposób go zainstalować na środowisku. Tutaj nie napotkałem żadnych niespodzianek, wszystko przebiegło gładko. O ile skalowania aplikacji za bardzo nie użyję w moim przypadku, gdyż wszystko będzie działać lokalnie i będzie użytkowane przez maksymalnie kilka osób, to zapewnienie jak najwyższego uptime aplikacji jest dla mnie priorytetem.

StatefulSet, PV, PVC, Ingress, NodePort - mój boże, co to jest?! Taka była na początku moja reakcja, gdy zobaczyłem ile tak naprawdę usług składa się na K8s. Z legend, które zasłyszałem, nikt nie wspominał, że jest tak wiele komponentów, o których trzeba mieć chociaż jakiekolwiek pojęcie.

No nic... Trzeba się dobrze skupić i dowiedzieć się co w trawie piszczy. Jeżeli czytałeś poprzedni post, to wiesz jakie aplikacje chcę w swoim HomeLab postawić, natomiast zapomniałem tam uwzględnić silników bazodanowych...

Komponenty K8s

Dlatego na pierwszy ogień poszedł PostgresSQL, który będzie wykorzystany m.in do aplikacji Bitwarden. Wyczytałem, że potrzebuje kilku komponentów K8s, aby taki silnik bazodanowy miał rację bytu. Na pierwszy ogień poszedł PV oraz PVC, czyli Persistent Volume i Persistent Volume Claim.

Ten pierwszy możemy określić jako przestrzeń dyskowa, na której będą przetrzymywane dane konkretnej aplikacji. Natomiast PVC to żądanie użytkownika, aby aplikacja otrzymała dany storage. Poniżej kod yaml, który definiuje te dwie usługi w moim przypadku.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: postgres-pv-volume
  labels:
    type: local
    app: postgres
spec:
  capacity:
    storage: 1Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage
  local:
    path: "/mnt/C0E67961E679591C/Kubernetes/Postgres"
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - minikube
    
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: postgres-pv-claim
  labels:
    app: postgres
spec:
  storageClassName: local-storage
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi

Mogłoby się wydawać, że pierwsze dwa komponenty sprawią mi najmniej problemu... Przecież to tylko przydzielenie przestrzeni dyskowej dla aplikacji - yhym jasne... Dalej dowiesz się co i jak, natomiast teraz omówię resztę usług.

Kolejny w procesie konfiguracji był StatefulSet, czyli usługa, która postawi mi daną aplikację w podzie. Na jej konfigurację składa się kilka czynników, m.in to jaką ilość instancji aplikacji ma ona zapewnić - konfigurowane jest to adnotacją replicaset. Dodatkowo, w tym miejscu można określić z jakich PV oraz PVC ma aplikacja korzystać.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres-stateful
  labels:
    app: postgres
spec:
  serviceName: "postgres"
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - name: postgres
        image: postgres:13.0
        envFrom:
        - configMapRef:
           name: postgres-config
        ports:
        - containerPort: 5432
          name: postgresdb
        volumeMounts:
        - name: pv-data
          mountPath: /var/lib/postgresql/data
      volumes:
      - name: pv-data
        persistentVolumeClaim:
          claimName: postgres-pv-claim

Kolejną usługą jakiej potrzebuje, jest NodePort, dzięki której będę mógł dobić się do aplikacji z zewnątrz klastra. Polega ona na tym, że aplikacja jest wystawiana na danym porcie (możemy go podać ręcznie lub zostanie nadany automatycznie) i za pomocą tego portu oraz cluster-ip możemy się tam dostać.

Pierwsze 2 godziny straciłem na tym, że za żadne skarby nie mogłem się dobić do aplikacji po cluster-ip który został nadany usłudze NodePort oraz porcie. Okazało się, że zamiast cluster-ip usługi, powinienem skorzystać z IP mojego minikube. W dokumentacji wyczytałem co innego, ale być może źle coś zrozumiałem. Będę to jeszcze wyjaśniać, bo muszę poznać przyczynę dlaczego dla usługi NodePort jest nadawany adres IP, skoro nie służy on do połączenia z tą usługą.

apiVersion: v1
kind: Service
metadata:
  name: postgres-service
  labels:
    app: postgres
spec:
  type: NodePort
  ports:
   - port: 5432
  selector:
   app: postgres

Ostatnim elementem układanki jest ConfigMap, która służy do przekazywania zmiennych do kontenera. Przykładowo, ConfigMap do PostgreSQL może zawierać takie informacje jak login, hasło usera domyślnego, zakładanego przy instalacji oraz domyślną bazę.

apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-config
  labels:
    app: postgres
data:
  POSTGRES_DB: postgresdb
  POSTGRES_USER: postgresadmin
  POSTGRES_PASSWORD: admin123

Tyle pytań, a odpowiedzi brak...

Wróćmy teraz do kwestii PV i PVC. Niestety z tym mam największy problem i w sumie do tej pory nie mam odpowiedzi, także czeka mnie dokumentacja do przestudiowania. Chodzi o to, że jeżeli aplikacja ma nadany PV i PVC to faktycznie przechowuje dane. Gdy dodam nową bazę danych, usunę pod z aplikacją, to nowa aplikacja z kolejnego poda, również widzi i ma dostęp do tej bazy.

Kwestia jest tylko taka, że w PV podaje lokalizację storage mojego lokalnego dysku, gdzie teoretycznie te dane powinny być zapisane (nie wiem, tak się domyślam)? Faktycznie folder ten jest pusty, dlatego zastanawia mnie, gdzie ten wydzielony storage faktycznie przetrzymuje nowe dane, które są chronione przed utratą, gdy ubijamy poda. Skoro nie bezpośrednio w ścieżce, która podałem w PV, to po co w ogóle jest ta ścieżka? Tyle pytań, ale póki co brak odpowiedzi :D

Nie będę ukrywał, ostatnie kilka dni spędzone z Kubernetes i kontenerami dały mi trochę w kość. Rozbudowana architektura usług i serwisów Kubernetes może przytłoczyć przy pierwszym kontakcie. Nie uważam jednak, aby to były dni zmarnowane. Udało mi się poznać choć trochę technologię, która ostatniego czasu jest dość popularna, gdy przeglądam oferty pracy widzę tam właśnie K8s.

Mam nadzieję, że już w kolejnym poście, uda mi się opisać w jaki sposób dopiąłem kwestię PostgreSQL oraz uda mi się postawić pierwszą aplikację, która będzie korzystała z bazy danych. A także, że ubicie pod'a nie będzie skutkowało utratą konfiguracji czy też danych. Do następnego!

Tagi

Bartłomiej Komendarczuk

Newbie DevOps :)

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.