Skip to main content

Helmchart

kkrolikowskiAbout 4 minGuidekubernetes

Na potrzeby uruchamiania różnych aplikacji na klastrze kubernetes przygotowałem helmchart, który dostępny jest w repozytorium https://github.com/HomeDevopsLab/appchartopen in new window. Helmchart automatyzuje i co za tym idzie upraszcza tworzenie obiektów kubernetes. Na podstawie jednego obiektu HelmRelease generowanych jest wiele resource'ów kubenetes.

W tej dokumentacji będzie opis poszczególnych sekcji pliku HelmRelease.

Specyfikacja

W specyfikacji zdefiniowany jest interwał. To okres czasu, który mówi co ile flux ma przeprowadzać proces rekonsyliacji helm release. Poza nim zdefiniowane jest repozytorium git w którym znajduje się definicja helmcharta.

spec:
  interval: 1m
  chart:
    spec:
      chart: ./chart
      sourceRef:
        kind: GitRepository
        name: homelab-app-chart-multiple-ingresses
        namespace: default
      interval: 1m

Values

nodeSelector

Za pomocą nodeSelectora określam na której grupie nodów ma zostać uruchomiony pod z aplikacją. W moim środowisku używam rozgraniczenia na podstawie architektury procesora. Dzięki temu mogę sobie wybrać czy coś mi się uruchomi na raspberry pi, czy na vm-ce z proxmoxa.

nodeSelector:
  kubernetes.io/arch: amd64

Możliwe do skonfigurowania opcje

kubernetes.io/archamd64arm64
PlatformaVM-ProxmoxRaspberry Pi

startupProbes

StartupProbes odpowiedzialne są za sprawdzanie, czy aplikacja działająca w podzie już działa. W tym helmcharcie check jest bardzo prosty. Wykonuje http get na wskazany port.

startupProbes:
  enabled: true
  port: 3000

Jeśli nie chcemy uruchamiać startupProbes stosujemy konnfigurację poniżej:

startupProbes:
  enabled: false

replicaCount

ReplicaCount jest bardzo prostym parametrem. Za jego pomocą na sztywno można określić na ilu podach ma zostać uruchomiona aplikacja. W środowisku domowym zazwyczaj będzie to wartość: 1 aby zaoszczędzić zasoby. W środowiskach produkcyjnych można użyć większej liczby aby zapewnić aplikacji większą moc obliczeniową i HA.

replicaCount: 1

database

Opcja database służy do uruchomienia hooków, które mają za zadanie stworzyć bazę danych mysql oraz wygenerować secret dla aplikacji. Uruchamiane są podczas instalacji aplikacji z helmcharta.

database:
  enabled: true

Jeśli nie chcemy używać tych pre-hooków ustawiamy enabled: false.

Deprecation warning

Obsługa database zostanie usunięta w kolejnych wersjach helmcharta. Utrzymanie tego modelu wymaga zbyt dużo pracy związanej z aktualizacją infrastruktury.

image

Opcja image służy do wskazania kontenera, który ma zostać uruchomiony.

image:
  registrySecret: regcred
  imagePolicy: true
  repository: private.registry.address/homelab/documentation
  tag: 2.4.0 # {"$imagepolicy": "flux-system:homelab-doc:tag"}
OpcjaWymaganeOpis
registrySecretNieOpcji używamy w przypadku rejestru prywatnego, który wymaga zalogowania się do niego. Opcja wskazuje nazwę secretu
imagePolicytakfalse image policy off, true image policy on
repositorytakWskazanie registry z kontenerami dockera
tagtakwskazanie na wersję aplikacji. W przypadku imagepolicy, trzeba podać specjalny string dla fluxa po znaku komentarza

Image Policy

Image policy to specjalny typ resource'u (CRD), który jest dostarczany przez Fluxa. Odpowiada on za wdrożenie najnowszego dostępnego taga/ W homelabie posługuję się patternem semveropen in new window.

policy:
  semver:
    range: ">=0.0.1"

Aby można było śledzić wersje w deploymencie, trzeba dodać do linijki tag specjalny komentarz: # {"$imagepolicy": "flux-system:homelab-doc:tag"}. Wskazuje on namespace oraz nazwę resource'a ImagePolicy, który ma zostać utworzony.

resources

Całe resources jest wczytywane bezpośrednio do deploymentu. Jest to standardowa konfiguracja kubernetes. Pozwala ustawić limity na użycie procesora i ramu w aplikacji.

services

Opcja services odpowiedzialna jest za stworzenie obiektu (lub obiektów) typu service w klastrze kubernetes. Jest to yamlowa tablica obiektów.

services:
  - name: gitlab
    type: ClusterIP
    protocol: 'TCP'
    servicePort: 80
    targetPort: 80
    ....
OpcjaOpis
nameDo nazwy dokładany jest prefix z nazwą HelmRelease'a. Np: na podstawie name: ssh zostanie utworzony serwis: gitlab-ssh
typeClusterIP - służy do komunikacji wewnętrznej: service - kontener. Używam go do komunikacji z serwerami www działającymi w podach. LoadBalancer - mapuje servicePort do IPków wystawianych przez load balancer
protocolTCP lub UDP
servicePortPort, który wystaia serwis. Korzysta z niego Ingress (w przypadku ClusterIP) lub jest on wystawiony do LoadBalancera (type: LoadBalancer), dzięki czemu możemy np. na porcie: 2222 połączyć się do ssh działającego w podzie.
targetPortPort wystawiony przez kontener z aplikacją

Service

Jedna aplikacja może mieć kilka usług, które potrzebują komunikacji ze światem. Najlepszym przykładem jest gitlab, który posiada serwer www, serwer ssh oraz dodatkowo registry kontenerów dockera.

ingress

Ingress jest odpowiedzialny za serwowanie aplikacji webowej pod wybranym adresem domenowym. Ostatnia wersja helmcharta umożliwia utworzenie więcej niż jednego ingressu dla aplikacji. Przykładem jest Gitlab, który wymaga wystawienia GUI gitlaba oraz registry doockerowego.

ingress:
  enabled: true
  ssl: true
  hosts:
    - name: gitlab.example.com
      servicePort: 80
    - name: registry.example.com
      servicePort: 5050
OpcjaOpis
enabledtrue: ingress zainstalowany, false: ingress nie zainstalowany
ssltrue: certyfikat Let's Encrypt podłączony, ustawione przekierowanie lub false: brak certyfikatu ssl
hoststablica vhostów. Każdy vhost to jeden ingress
servicePortNumer portu musi być zgodny z servicePort w kluczu service

volumes

Klucz volumes służy do pomontowywania przestrzeni dyskowej do aplikacji, jeśli jest to wymagane.

volumes:
  enabled: true
  mountPath:
    - config:/etc/gitlab
    - logs:/var/log/gitlab
    - data:/var/opt/gitlab
  ownership: 0:0
  type:
    nfs:
      server: srv-nfs.lan
      path: /storage
OpcjaOpis
mountPathTablica mapowań katalogu na współdzielonym storage, do katalogu w kontenerze
ownershipKto ma być właścicielem utworzonych katalogów
typeObecnie jest to tylko NFS

Po ustawieniu trybu enabled: true uruchamiany jest w pre-install hooku skrypt, który tworzy na udziale storage odpowiednią strukturę katalogów. W przedstawionym przykładzie tworzona jest następująca struktura katalogów:

gitlab
├── config
├── data
└── logs

W parametrze nfs ustawiony jest adres serwera nfs oraz wyeksportowany z niego katalog.

Templates

Opis działania poszczególnych elementów helmcharta. Definicje obiektów znajdują się w katalogu appchart/chart/templatesopen in new window w repozytorium.

dbsecrets.yaml

Opcja database odpowiada za stworzenie ssecretu do bazy MySQL w kubernetes oraz za uruchomienie skryptu tworzącego bazę danych i konto użytkownika na podstawie stworzonego secretu. Akcje związane z tworzeniem bazy uruchamiają się w pre-install hooku, zanim aplikacja zostanie uruchomiona.

apiVersion: v1
kind: Secret
metadata:
  name: {{ .Release.Name }}-db
  annotations:
    "helm.sh/hook": pre-install
    "helm.sh/hook-weight": "-5"
    "helm.sh/hook-delete-policy": before-hook-creation
type: Opaque
data:
  login: {{ .Release.Name | trimSuffix "-www" | b64enc | quote }}
  password: {{ randAlphaNum 32 | b64enc | quote }}

Do wygenerowania hasła wykorzyystywana jest funckcja helma: randAlphaNum.

Secret

Jeśli secret o tej nazwie już istnieje, zostanie on wygenerowany od nowa. Może to doprowadzić do problemów z działaniem aplikacji, jeśli dane konta w bazie się nie zmienią.

mysqlDBhelper.yaml

Jest to pre-hook odpowiedzialny za utworzenie bazy danych oraz konta użytkownika na sewerze mysql. Źródłem danych, na których on operuje jest stworzony w innym pre-hooku secret kubernetes. Prehook uruchamia skrypt w bashu, który jest obudowany kontenerem dockera: mysql-initdb:0.0.1.

mysql-initdb

run.sh

#!/bin/bash

MYSQL="/usr/bin/mysql"

function mysql_cmd() {
    $MYSQL -u ${DB_ADMIN_LOGIN} -p${DB_ADMIN_PASS} -h ${DB_HOST} -Nsre "$1"
}

function userExists() {
    result=$(mysql_cmd "SELECT count(User) FROM mysql.user WHERE User='${APPDB_LOGIN}'")
    echo $result
}

if [ $(userExists) == "1" ]; then
    mysql_cmd "ALTER USER '${APPDB_LOGIN}'@'%' IDENTIFIED BY '${APPDB_PASS}'"
    mysql_cmd "FLUSH PRIVILEGES"
else
    mysql_cmd "CREATE DATABASE ${APPDB_NAME}"
    mysql_cmd "CREATE USER '${APPDB_LOGIN}'@'%' IDENTIFIED BY '${APPDB_PASS}'"
    mysql_cmd "GRANT ALL ON ${APPDB_NAME}.* TO '${APPDB_LOGIN}'@'%'"
fi

Dockerfile

FROM gitea.angrybits.pl/kkrolikowski/toolbox:0.0.1
WORKDIR /usr/local/bin
COPY run.sh .
RUN chmod +x run.sh
ENTRYPOINT [ "/bin/bash", "./run.sh" ]