[rank_math_breadcrumb]

Konteneryzacja Aplikacji: Wprowadzenie do Docker i Kubernetes

Sebastian Kruk, CEO & CTO

Konteneryzacja Aplikacji: Wprowadzenie do Docker i Kubernetes

Co to jest konteneryzacja?

Konteneryzacja jest technologią, która umożliwia uruchamianie i izolowanie aplikacji w sposób niezależny od infrastruktury sprzętowej. W praktyce oznacza to, że aplikacje mogą być uruchamiane na różnych środowiskach: od komputerów deweloperskich, przez serwery testowe, aż po produkcyjne chmury obliczeniowe, bez konieczności wprowadzania istotnych zmian w ich kodzie.

Konteneryzacja wykorzystuje tzw. kontenery, które zawierają wszystko, co jest potrzebne do uruchomienia aplikacji, w tym kod, biblioteki, narzędzia i pliki konfiguracyjne. Główną zaletą konteneryzacji jest jej zdolność do izolowania aplikacji, co pozwala na ich bezproblemowe uruchamianie w różnych środowiskach i minimalizowanie konfliktów zależności.

Główne zalety konteneryzacji:

  • **Izolacja** – Każda aplikacja działa w swoim własnym, odizolowanym środowisku, co minimalizuje ryzyko konfliktów.
  • **Spójność** – Kontenery zachowują się identycznie w różnych środowiskach, co oznacza, że to, co działa u dewelopera, będzie działać również na produkcji.
  • **Szybkość** – Kontenery są lekkie i mogą być uruchamiane znacznie szybciej niż tradycyjne maszyny wirtualne.
  • **Skalowalność** – Dzięki narzędziom takim jak Docker Compose i Kubernetes, można łatwo zarządzać dużą liczbą kontenerów w skali.

Docker: Podstawy Konteneryzacji

Docker jest jednym z najpopularniejszych narzędzi do konteneryzacji aplikacji. Zapewnia on prosty sposób na tworzenie, wdrażanie i uruchamianie aplikacji w kontenerach. Docker pozwala na definiowanie środowiska aplikacji w pliku Dockerfile, co umożliwia łatwe odtwarzanie i udostępnianie tego środowiska.

Tworzenie pierwszego kontenera:

  1. **Instalacja Docker**: Aby zacząć, musisz zainstalować Docker na swoim systemie operacyjnym.
  2. **Tworzenie Dockerfile**: Tworzy się plik nazwany Dockerfile, który zawiera instrukcje dotyczące budowy obrazu kontenera.
  3. **Budowanie obrazu**: Za pomocą polecenia docker build tworzysz obraz zdefiniowany w Dockerfile.
  4. **Uruchamianie kontenera**: Obraz można uruchomić jako kontener za pomocą polecenia docker run.

Przykładowy Dockerfile:

Oto przykładowy Dockerfile dla aplikacji Node.js:


# Pobranie obrazu bazowego
FROM node:14

# Ustawienie katalogu roboczego
WORKDIR /app

# Kopiowanie plików aplikacji
COPY . .

# Instalacja zależności
RUN npm install

# Uruchamianie aplikacji
CMD ["node", "app.js"]

Uruchomienie powyższych komend w katalogu zawierającym powyższy Dockerfile i pliki aplikacji Node.js utworzy kontener, który będzie działać z tą aplikacją.

Kubernetes: Orkiestracja Kontenerów

Kubernetes to open-source’owy system do zarządzania kontenerami na dużą skalę. Podczas gdy Docker jest świetny do tworzenia i uruchamiania pojedynczych kontenerów, Kubernetes zarządza całymi klastrami kontenerów, automatyzując ich rozkład, skalowanie i zarządzanie cyklem życia.

Podstawowe elementy Kubernetes:

  • **Klaster**: Podstawowa jednostka Kubernetes, składająca się z węzłów (nodes).
  • **Pod**: Najmniejsza jednostka obliczeniowa w Kubernetes, która może zawierać jeden lub więcej kontenerów.
  • **ReplicaSet**: Zapewnia, że określona liczba replik poda jest zawsze uruchomiona.
  • **Deployment**: Ułatwia zarządzanie aplikacjami poprzez obsługę skalowania, aktualizacji i rollback’u.
  • **Service**: Tworzy trwały endpoint sieciowy, aby umożliwić komunikację między podami.

Tworzenie prostego klastru Kubernetes:

  1. **Instalacja Minikube**: Umożliwia uruchomienie lokalnego klastru Kubernetes na komputerze.
  2. **Uruchomienie Minikube**: Polecenie minikube start uruchamia lokalny klaster.
  3. **Konfiguracja aplikacji**: Stwórz pliki YAML, które definiują pody, serwisy i inne zasoby Kubernetes.
  4. **Wdrożenie aplikacji**: Użyj kubectl apply do wdrożenia zasobów z plików YAML w klastrze.

W kolejnych częściach tego artykułu przyjrzymy się bardziej szczegółowo funkcjonowaniu Docker oraz Kubernetes i zrozumiemy, jak możemy skorzystać z tych technologii w praktyce.

Szczegółowe Funkcje Docker

W poprzedniej części omówiliśmy podstawowe pojęcia związane z konteneryzacją oraz podstawy użycia Docker. Teraz zgłębimy bardziej zaawansowane funkcje Docker, które pozwalają na jeszcze efektywniejsze zarządzanie aplikacjami i środowiskami deweloperskimi.

Warstwy i Obrazy

Obrazy Docker są zbudowane z warstw, gdzie każda warstwa reprezentuje różnicę względem poprzedniej. Warstwy są wersjonowane, co oznacza, że są dzielone między obrazy, które mają te same warstwy początkowe. To podejście obniża koszty przechowywania i poprawia wydajność, ponieważ te same warstwy są przechowywane tylko raz.

Na przykład, jeżeli dwa obrazy używają tej samej wersji Node.js jako warstwy bazowej, ta wersja będzie przechowywana tylko raz, niezależnie od liczby obrazów używających tej wersji.

Docker Compose

Docker Compose jest narzędziem umożliwiającym definiowanie i uruchamianie wielokontenerowych aplikacji Docker. Dzięki plikowi docker-compose.yml można zdefiniować usługi, sieci i wolumeny potrzebne dla aplikacji. Docker Compose automatyzuje proces budowania, uruchamiania i zarządzania kontenerami, co jest szczególnie użyteczne w środowiskach deweloperskich.

Przykładowy plik docker-compose.yml:


version: '3.8'

services:
  web:
    build: .
    ports:
      - "5000:5000"
    volumes:
      - .:/app
    environment:
      FLASK_ENV: development

  redis:
    image: "redis:alpine"

Powyższy plik definiuje dwie usługi: aplikację webową uruchomioną z bieżącego katalogu i usługę Redis uruchomioną z obrazu “redis:alpine”.

Sieciowanie w Docker

Sieci w Docker umożliwiają kontenerom komunikację ze sobą oraz z zewnętrznymi serwisami. Docker pozwala na tworzenie różnych typów sieci:

  • **Bridge** – Domyślna sieć izolowana dla kontenerów na tym samym hoście.
  • **Host** – Używa sieci hosta, co oznacza, że kontener dzieli sieć z hostem.
  • **Overlay** – Umożliwia komunikację między kontenerami na różnych hostach, używana w klastrach zarządzanych przez Docker Swarm lub Kubernetes.
  • **Macvlan** – Pozwala na przypisanie wirtualnej karty sieciowej do kontenera.

Tworzenie własnej sieci Docker:


docker network create --driver bridge my_custom_network

Po utworzeniu sieci, można uruchamiać kontenery dołączając je do tej sieci:


docker run --network my_custom_network my_image

Zaawansowane Funkcje Kubernetes

Kubernetes oferuje zaawansowane funkcje zarządzania kontenerami na dużą skalę. Przyjrzyjmy się kilku kluczowym możliwościom, które pozwalają na efektywne zarządzanie klastrami Kubernetes.

Namespaces

Namespaces w Kubernetes pozwalają na logiczne segmentowanie klastrów. Dzięki namespaces można zarządzać zasobami różnych projektów lub zespołów w jednym klastrze, co pozwala na lepszą organizację i izolację zasobów.

Aby utworzyć namespace, można użyć następującego polecenia:


kubectl create namespace my-namespace

Następnie można wdrażać zasoby w utworzonym namespace:


kubectl apply -f my-deployment.yaml -n my-namespace

Persistent Volumes i Persistent Volume Claims

Kubernetes zarządza przechowywaniem danych poprzez Persistent Volumes (PV) i Persistent Volume Claims (PVC). PV reprezentują zasoby pamięci dostępne w klastrze, a PVC są żądaniami dostępu do tych zasobów od aplikacji uruchomionych w kontenerach.

Przykładowe pliki PV i PVC:


apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

ConfigMaps i Secrets

ConfigMaps i Secrets są używane do przechowywania danych konfiguracyjnych potrzebnych aplikacjom uruchomionym w klastrze Kubernetes. ConfigMaps przechowują nieszyfrowane dane konfiguracyjne, takie jak zmienne środowiskowe, natomiast Secrets są używane do przechowywania wrażliwych danych, takich jak hasła i klucze.

Przykładowy plik ConfigMap:


apiVersion: v1
kind: ConfigMap
metadata:
  name: my-config
data:
  APP_ENV: "development"
  APP_DEBUG: "true"

Przykładowy plik Secret:


apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
data:
  password: c2VjcmV0

Użycie ConfigMaps i Secrets w aplikacjach:


apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: my-container
      image: my-image
      env:
        - name: APP_ENV
          valueFrom:
            configMapKeyRef:
              name: my-config
              key: APP_ENV
        - name: APP_PASSWORD
          valueFrom:
            secretKeyRef:
              name: my-secret
              key: password

Pod Autoscaling

Kubernetes umożliwia automatyczne skalowanie aplikacji w oparciu o metryki takie jak zużycie CPU. Aby skonfigurować autoscaling, używa się zasobu HorizontalPodAutoscaler.

Przykład konfiguracji HorizontalPodAutoscaler:


apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: my-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-deployment
  minReplicas: 2
  maxReplicas: 10
  targetCPUUtilizationPercentage: 80

Autoscaler monitoruje aplikację i dostosowuje liczbę podów w odpowiedzi na zmieniające się zużycie zasobów.

W trzeciej części artykułu omówimy bardziej zaawansowane scenariusze użycia Docker i Kubernetes oraz przyjrzymy się najlepszym praktykom i narzędziom wspomagającym zarządzanie tymi technologiami.

Zaawansowane Scenariusze Użycia Docker i Kubernetes

W poprzednich częściach omówiliśmy podstawowe i zaawansowane funkcje Docker i Kubernetes. W tej sekcji przyjrzymy się bardziej zaawansowanym scenariuszom użycia oraz najlepszym praktykom, które pomogą w skutecznym zarządzaniu projektami opartymi na tych technologiach.

CI/CD z Docker i Kubernetes

Integracja ciągła (CI) i dostarczanie ciągłe (CD) są kluczowymi elementami nowoczesnych procesów deweloperskich. Docker i Kubernetes odgrywają w nich ważną rolę.

CI/CD Pipeline z Docker:

  1. **Budowanie obrazu Docker**: Pipeline zaczyna się od budowania obrazu Docker z kodem aplikacji.
  2. **Testowanie**: Uruchamianie kontenera z built-in testami w izolowanym środowisku.
  3. **Push to Registry**: Jeśli testy przejdą pomyślnie, obraz jest wysyłany do rejestru obrazów (np. DockerHub, Google Container Registry).
  4. **Deployment**: Pipeline kończy się wdrożeniem nowego obrazu w środowisku staging lub produkcyjnym za pomocą Docker lub Kubernetes.

Przykładowy fragment pliku Jenkinsfile do CI/CD:


pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                script {
                    docker.build('my-app:latest')
                }
            }
        }
        stage('Test') {
            steps {
                script {
                    docker.image('my-app:latest').inside {
                        sh 'npm test'
                    }
                }
            }
        }
        stage('Push') {
            steps {
                script {
                    docker.withRegistry('https://my-registry', 'registry-credentials') {
                        docker.image('my-app:latest').push()
                    }
                }
            }
        }
        stage('Deploy') {
            steps {
                script {
                    kubernetesDeploy(
                        configs: 'k8s/deployment.yaml',
                        kubeconfigId: 'kubeconfig',
                    )
                }
            }
        }
    }
}

Zarządzanie Sekretami i Konfiguracjami

W zarządzaniu dużymi aplikacjami kluczowe jest zapewnienie bezpiecznego przechowywania konfiguracji i sekretów. Kubernetes oferuje wbudowane mechanizmy do zarządzania tymi elementami.

Bezpieczne Sekrety:

Chociaż Kubernetes domyślnie nie szyfruje sekretów, istnieją sposoby, aby to zmienić:

  • Encryption at Rest – Konfiguracja klastrów Kubernetes do szyfrowania danych w spoczynku.
  • External Secret Management – Integracja z systemami zarządzania sekretami, takimi jak HashiCorp Vault.

Przykładowa konfiguracja Encryption at Rest w Kubernetes:


apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: c2VjcmV0MQ==
      - identity: {}

Plik ten musi być następnie wskazany w parametrach uruchomienia kube-apiserver.

Monitoring i Logging

Efektywne monitorowanie i logowanie są kluczowe w zarządzaniu aplikacjami w Kubernetes. Popularne narzędzia to Prometheus, Grafana i EFK Stack (Elasticsearch, Fluentd, Kibana).

Prometheus i Grafana:

Prometheus zbiera metryki z aplikacji i infrastruktury, a Grafana umożliwia wizualizację tych danych.

Przykład instalacji Prometheus i Grafana za pomocą Helm:


helm install prometheus stable/prometheus
helm install grafana stable/grafana

EFK Stack:

EFK Stack umożliwia zbieranie, przechowywanie i wizualizację logów z klastrów Kubernetes.

Przykład instalacji Elasticsearch, Fluentd i Kibana:


kubectl apply -f https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/fluentd-elasticsearch/elasticsearch-deployment.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/fluentd-elasticsearch/fluentd-es-configmap.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/fluentd-elasticsearch/fluentd-es-ds.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/fluentd-elasticsearch/kibana-deployment.yaml

Najlepsze Praktyki w Kubernetes

Aby efektywnie zarządzać klastrami Kubernetes, warto stosować się do pewnych najlepszych praktyk:

  • **Zastosowanie namespaces**: Używanie namespaces do segmentacji zasobów.
  • **Automatyzacja skali**: Korzystanie z HorizontalPodAutoscaler oraz Cluster Autoscaler.
  • **Zarządzanie zasobami**: Konfiguracja limitów zasobów dla podów.
  • **Bezpieczeństwo**: Minimalizacja uprawnień podów i użycie RBAC (Role-Based Access Control).
  • **Monitoring i logging**: Konfiguracja pełnej observability, aby monitorować stan aplikacji i infrastruktury.
  • **Ciągła integracja i dostarczanie**: Implementacja CI/CD pipeline dla szybkich i bezpiecznych wdrożeń.

Przykład konfiguracji limitów zasobów:


apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: my-container
      image: my-image
      resources:
        requests:
          memory: "64Mi"
          cpu: "250m"
        limits:
          memory: "128Mi"
          cpu: "500m"

Zaawansowane narzędzia wspomagające zarządzanie

Istnieje wiele narzędzi, które pomagają w zarządzaniu infrastrukturą kontenerową:

Helm

Helm to menedżer pakietów dla Kubernetes, który umożliwia definiowanie, instalowanie i zarządzanie aplikacjami za pomocą tzw. chartów.

Przykład instalacji aplikacji za pomocą Helm:


helm install my-release stable/my-chart

Istio

Istio to sieć serwisów (service mesh), która pomaga w zarządzaniu ruchem sieciowym, bezpieczeństwem i monitorowaniem aplikacji w Kubernetes.

Przykład instalacji Istio za pomocą Istioctl:


istioctl install --set profile=demo

Kustomize

Kustomize pozwala na modyfikowanie plików konfiguracyjnych Kubernetes w sposób deklaratywny. Jest zintegrowane z kubectl, co ułatwia jego użycie.

Przykład użycia Kustomize:


kubectl apply -k ./kustomize-dir

Podsumowanie

Docker i Kubernetes stanowią fundament nowoczesnej konteneryzacji i zarządzania aplikacjami. Zrozumienie podstaw i zaawansowanych funkcji tych narzędzi pozwala na efektywne zarządzanie aplikacjami w różnych środowiskach oraz na wdrażanie skalowalnych i niezawodnych systemów. Wykorzystując najlepsze praktyki oraz zaawansowane narzędzia wspomagające, można w pełni wykorzystać potencjał tych technologii w projektach deweloperskich i produkcyjnych.

Chcesz wiedzieć jak zacząć? Skontaktuj się z nami – kontakt.

Sebastian Kruk

Sebastian Kruk

CEO & CTO

Założyciel Giraffe Studio. Absolwent informatyki na Polsko-Japońskiej Akademii Technik Komputerowych w Warszawie. Programista mobilny i backendowy z dużym doświadczeniem. Typ wizjonera, który zawsze znajdzie rozwiązanie, nawet jeśli inni uważają, że jest to niemożliwe. Z pasją tworzy architekturę rozbudowanych projektów, inicjując i planując pracę zespołu, koordynując i łącząc działania deweloperów. Gdyby nie został programistą, z pewnością spędzałby czas pod maską samochodu lub motocykla, bo motoryzacja to jego wielka pasja. Miłośnik podróży kamperem, w których towarzyszą mu żona, mały synek i pies, nieustannie odkrywa nowe miejsca na kuli ziemskiej, wychodząc z założenia, że ciekawych ludzi i fascynujące miejsca można znaleźć wszędzie. Potrafi grać na pianinie, gitarze, akordeonie i harmonijce ustnej, a także obsługiwać maszynę do szycia. Ukończył szkołę aktorską. Nigdy nie odmawia pizzy, czekolady i kawy.

Alrighty, let’s do this

Get a quote
Alrighty, let’s do this