Kubernetes (znany również jako k8s) to otwartoźródłowy system orkiestracji. Umożliwia użytkownikom wdrażanie, skalowanie i zarządzanie skonteneryzowanymi aplikacjami przy minimalnym czasie przestoju. W tym samouczku dowiesz się, jak wdrożyć aplikację PHP w klastrze Kubernetes.
Nginx działa jako proxy dla PHP-FPM podczas uruchamiania aplikacji PHP. Zarządzanie tymi dwiema usługami w jednym kontenerze to trudny proces. Kubernetes pomaga nam zarządzać nimi w dwóch różnych kontenerach i zmniejsza kłopoty. Pozwala również użytkownikom na ponowne wykorzystanie kontenerów i brak konieczności martwienia się o budowanie obrazu kontenera dla każdej nowej wersji PHP/Nginx.
Uruchomisz swoją aplikację i usługę proxy w dwóch oddzielnych kontenerach. Samouczek dostarczy również informacji na temat tego, jak użyć lokalnej pamięci masowej do utworzenia Persistent Volume (PV) i Persistent Volume Claim (PVC). Następnie użyjesz tego PVC, aby zachować pliki konfiguracyjne i kod poza obrazami kontenerów. Po ukończeniu tego samouczka będziesz mógł ponownie wykorzystać swój obraz Nginx dla innych aplikacji wymagających serwera proxy. Możesz to osiągnąć poprzez przekazanie konfiguracji, zamiast ponownego budowania dla niej obrazu.
Wymagania wstępne
- Podstawowe zrozumienie platformy Kubernetes (k8s) i jej obiektów. Zapoznaj się z tym przewodnikiem, aby uzyskać szczegółowy przegląd ekosystemu Kubernetes.
- Działający klaster Kubernetes na systemie Ubuntu 18.04. Postępuj zgodnie z tym samouczkiem, aby utworzyć klaster Kubernetes za pomocą kubeadm.
- Dodatkowo musisz udostępnić kod swojej aplikacji pod publicznym adresem URL, na przykład na GitHub.
Krok 1: Tworzenie usług PHP-FPM i Nginx
Ten krok pomoże Ci utworzyć usługi PHP-FPM i Nginx. Każda usługa zapewnia dostęp do zestawu podów w klastrze. Wszystkie usługi obecne w klastrze mogą komunikować się ze sobą za pomocą swoich nazw, bez adresów IP. Usługa PHP-FPM i usługa Nginx zapewnią dostęp odpowiednio do podów PHP-FPM i Nginx.
Będziesz musiał wskazać usłudze PHP-FPM, jak znaleźć pody Nginx, ponieważ będzie ona działać jako proxy dla podów PHP-FPM. W tym celu skorzystasz z automatycznego wykrywania usług Kubernetes’ i użyjesz czytelnych dla człowieka nazw do kierowania żądań do odpowiedniej usługi.
Aby utworzyć dowolną usługę, musisz utworzyć plik YAML zawierający definicję obiektu. Ten plik YAML zawiera co najmniej następujące znaczniki:
apiVersion: Wersja API Kubernetes, do której należy definicja.kind: Rodzaj obiektu Kubernetes, który tworzy ten plik YAML. Na przykład:service,joblubpod.metadata: Nazwa obiektu oraz różnelabels(etykiety), które użytkownik może chcieć zastosować do tego obiektu, są zdefiniowane pod tym znacznikiem.spec: Ten znacznik zawiera specyfikację Twojego obiektu, taką jak zmienne środowiskowe (ENV), obraz kontenera, który ma zostać użyty, oraz porty, na których usługa kontenera będzie dostępna.
Tworzenie usługi PHP-FPM
Na początek należy utworzyć katalog do przechowywania definicji obiektów Kubernetes. Zaloguj się do swojego węzła nadrzędnego (master node) i utwórz katalog o nazwie “definitions:”
|
1 |
mkdir definitions |
Przejdź do katalogu definitions:
|
1 |
cd definitions |
Następnie utwórz plik usługi PHP-FPM jako plik php_service.yaml:
|
1 |
nano php_fpm_service.yaml |
Następnie ustaw apiVersion oraz kind w pliku php_fpm_service.yaml:
|
1 2 |
apiVersion: v1 kind: Service |
Nazwij swoją usługę jako php lub php-fpm ponieważ zapewni ona dostęp do Twojej aplikacji PHP-FPM:
|
1 2 3 |
… Metadata: name: php |
Oznacz swoją usługę php etykietą tier: backend ponieważ aplikacja PHP będzie działać za tą usługą:
|
1 2 3 |
… labels: tier: backend |
Usługa używa etykiet selector (selektora), aby określić, do których podów ma uzyskać dostęp. Każdy pod pasujący do tych etykiet, niezależnie od tego, kiedy został utworzony, jest obsługiwany. W dalszej części tego samouczka dowiesz się, jak dodawać etykiety do podów.
Dołącz tier: backend etykietę, która przypisuje Twój pod do warstwy backend, wraz z app: php-fpm etykietą wskazującą, że pod uruchamia aplikację PHP-FPM. Musisz dodać te etykiety po sekcji metadata :
|
1 2 3 4 5 |
… spec: selector: app: php-fpm tier: backend |
Następnie musisz zadeklarować port dostępu do tej usługi php-fpm w sekcji spec. Możesz dodać dowolny wybrany port, ale w tym samouczku użyjemy portu 9000 :
|
1 2 3 4 |
... ports: - protocol: TCP port: 9000 |
Po wykonaniu powyższych kroków Twój plik php_fpm_service.yaml będzie wyglądał następująco:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
apiVersion: v1 kind: Service metadata: name: php labels: tier: backend spec: selector: app: php tier: backend ports: - protocol: TCP port: 9000 |
Wprowadź Ctrl + O aby zapisać plik, a następnie wprowadź Ctrl + X aby wyjść z nano.
Stosowanie polecenia kubectl w celu utworzenia usługi PHP
Po utworzeniu definicji obiektu dla usługi uruchom polecenie kubectl apply z argumentem -f określając plik php_fpm_service.yaml :
|
1 |
kubectl apply -f php_fpm_service.yaml |
Wynik powyższego polecenia powinien być następujący:
|
1 |
service/php created |
Uruchom poniższe polecenie, aby zweryfikować, czy usługa php-fpm działa:
|
1 |
$ kubectl get svc |
Zobaczysz, że usługa php-fpm jest uruchomiona i działa:
|
1 2 3 |
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10m php ClusterIP 10.100.59.238 <none> 9000/TCP 5m |
Tworzenie usługi Nginx
Ponieważ usługa PHP-FPM jest już gotowa, nadszedł czas na utworzenie również usługi Nginx. Utwórz i otwórz w edytorze nowy plik YAML dla tej usługi o nazwie nginx_service.yaml :
|
1 |
$ nano nginx_service.yaml |
Nazwij tę usługę nginx, ponieważ będzie ona kierowana do podów Nginx. Ta usługa również należy do backendu, więc należy dodać do niej etykietę tier: backend :
|
1 2 3 4 5 6 |
apiVersion: v1 kind: Service metadata: name: nginx labels: tier: backend |
Podobnie jak w przypadku usługi php-fpm, dodaj etykiety selektora app: nginx oraz tier: backend, aby wskazać pody. Dodaj domyślny port HTTP 80, aby uzyskać dostęp do tej usługi:
|
1 2 3 4 5 6 7 8 |
... spec: selector: app: nginx tier: backend ports: - protocol: TCP port: 80 |
Usługa Nginx może być publicznie dostępna w Internecie pod publicznym adresem IP. Możesz dodać IP swojego węzła roboczego (worker node) jako your_public_ip. Dodaj poniższe linie pod sekcją spec.externalIPs:
|
1 2 3 4 5 |
... spec: externalIPs: - your_public_ip |
Twój plik nginx_service.yaml powinien wyglądać jak ten poniżej po wykonaniu wszystkich powyższych kroków:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
apiVersion: v1 kind: Service metadata: name: nginx labels: tier: backend spec: selector: app: nginx tier: backend ports: - protocol: TCP port: 80 externalIPs: - your_public_ip |
Zapisz i zamknij plik po dodaniu wszystkich wymaganych parametrów powyżej.
Stosowanie polecenia kubectl w celu utworzenia usługi Nginx
|
1 |
kubectl apply -f nginx_service.yaml |
|
1 |
service/nginx utworzono |
|
1 |
$ kubectl get svc |
|
1 2 3 4 |
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13m nginx ClusterIP 10.102.160.47 your_public_ip 80/TCP 50s php ClusterIP 10.100.59.238 <none> 9000/TCP 8m |
|
1 |
$ kubectl delete svc/service_name |
Step 2: Create Local Storage and Persistent Volume
Kubernetes udostępnia różne wtyczki pamięci masowej, które pomagają tworzyć przestrzeń dyskową dla Twojego środowiska. Ten krok poprowadzi Cię przez proces tworzenia lokalnej klasy StorageClass i pokaże, jak ta klasa Storage Class może być dalej użyta do utworzenia woluminu Persistent Volume.
Tworzenie lokalnej pamięci masowej
Utwórz plik, na przykład storageClass.yaml, w swoim edytorze:
|
1 |
$nano storageClass.yaml |
Dodaj kind jako "storageClass" oraz apiVersion jako "storage.k8s.io/v1" w następujący sposób:
|
1 2 |
kind: StorageClass apiVersion: storage.k8s.io/v1 |
Nazwij tę klasę StorageClass jako "my-local-storage" i dodaj provisioner oraz volumeBindingMode w następujący sposób:
|
1 2 3 4 5 |
… metadata: name: my-local-storage provisioner: kubernetes.io/no-provisioner volumeBindingMode: Immediate |
Zapisz i zamknij plik. Twój ostateczny plik storageClass.yaml powinien wyglądać następująco:
|
1 2 3 4 5 6 |
kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: my-local-storage provisioner: kubernetes.io/no-provisioner volumeBindingMode: WaitForFirstConsumer |
Teraz utwórz klasę StorageClass, uruchamiając polecenie kubectl create, jak poniżej:
|
1 |
$ kubectl create -f storageClass.yaml |
Po uruchomieniu powyższego polecenia powinieneś otrzymać następujące dane wyjściowe:
|
1 |
storageclass.storage.k8s.io/my-local-storage utworzono |
Tworzenie lokalnego woluminu Persistent Volume
Po utworzeniu lokalnej pamięci masowej możesz utworzyć lokalny wolumin Persistent Volume. Wolumin Persistent Volume, znany również jako PV, to pamięć blokowa o określonym rozmiarze, która jest niezależna od cyklu życia poda. Lokalny wolumin Persistent Volume to nic innego jak lokalny dysk lub katalog dostępny na węźle klastra Kubernetes. Ten lokalny wolumin Persistent Volume umożliwia użytkownikom dostęp do lokalnej pamięci masowej przy użyciu lokalnego żądania Persistent Volume Claim w bardzo prosty, a zarazem przenośny sposób. Możesz utworzyć ten lokalny wolumin Persistent Volume, korzystając z właśnie utworzonej klasy pamięci masowej. Otwórz plik, na przykład persistentVolume.yaml, w swoim edytorze:
|
1 |
$ nano persistentVolume.yaml |
Nadaj temu woluminowi persistent volume nazwę, na przykład "my-local-pv":
|
1 2 3 4 |
apiVersion: v1 kind: PersistentVolume metadata: name: my-local-pv |
Podczas tworzenia lokalnego woluminu Persistent Volume możesz dodać pojemność pamięci masowej zgodnie ze swoimi potrzebami. W tym samouczku użyjemy 5 Gi na pamięć masową:
|
1 2 3 4 |
… spec: capacity: storage: 5Gi |
Dodaj accessModes, persistentVolumeReclaimPolicy i podaj taką samą nazwę storageClassName, jak użyta w storageClass.yaml:
|
1 2 3 4 5 |
… accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: my-local-storage |
Dodaj local.path dla swojego Persistent Volume w następujący sposób:
|
1 2 3 |
… local: path: /mnt/disk/vol |
Po dodaniu wszystkich wymaganych pól Twój plik persistentVolume.yaml powinien wyglądać następująco:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
apiVersion: v1 kind: PersistentVolume metadata: name: my-local-pv spec: capacity: storage: 5Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: my-local-storage local: path: /mnt/disk/vol nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - worker |
Przygotowanie wolumenu lokalnego
Teraz musimy przygotować wolumen lokalny na węźle “worker”, tak jak dodaliśmy w pliku persistentVolume.yaml. Uruchom poniższe polecenia na węźle skonfigurowanym w persistentVolume. W tym przypadku jest to węzeł “worker”:
|
1 2 3 |
$ DIRNAME="vol" $ mkdir -p /mnt/disk/$DIRNAME $ chmod 777 /mnt/disk/$DIRNAME |
Uruchom poniższe polecenie na węźle nadrzędnym (master), na którym znajduje się Twój plik persistentVolume.yaml:
|
1 |
kubectl create -f persistentVolume.yaml |
Powinieneś otrzymać następujący wynik:
|
1 |
persistentvolume/my-local-pv created |
Po pomyślnym utworzeniu pamięci lokalnej i wolumenu Persistent Volume możesz teraz przejść do utworzenia żądania Persistent Volume Claim, które będzie przechowywać kod aplikacji i pliki konfiguracyjne.
Krok 3: Utwórz Persistent Volume
Kod Twojej aplikacji musi być bezpieczny podczas zarządzania podami lub ich aktualizacji. W tym celu użyjesz wolumenu Persistent Volume utworzonego w poprzednim kroku, do którego dostęp uzyskuje się za pomocą PersistentVolumeClaim (PVC). To PVC montuje PV w wymaganej ścieżce.
Otwórz plik, na przykład code_volume.yaml, w edytorze:
|
1 |
$ nano code_volume.yaml |
Nazwij swoje PVC jako code, dodając do pliku poniższe parametry i wartości:
|
1 2 3 4 |
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: code |
Sekcja spec w PVC zawiera następujące elementy:
- accessModes: Istnieją różne możliwe wartości dla tego pola, jak poniżej:
- ReadWriteOnce – montuje wolumen dla pojedynczego węzła z uprawnieniami zarówno do odczytu, jak i zapisu.
- ReadOnlyMany – montuje wolumen dla wielu węzłów tylko z uprawnieniem do odczytu.
- ReadWriteMany – montuje wolumen dla wielu węzłów z uprawnieniami zarówno do odczytu, jak i zapisu.
- resources: definiuje wymaganą przestrzeń dyskową.
Ponieważ pamięć lokalna jest montowana tylko do jednego węzła, konieczne będzie ustawienie accessMode na ReadWriteOnce. W tym samouczku dodasz tylko niewielki fragment kodu aplikacji, dlatego 1 GB pamięci będzie tutaj wystarczający. Jeśli jednak chcesz przechowywać większą ilość danych lub kodu, możesz zmodyfikować parametr storage zgodnie ze swoimi wymaganiami. Pamiętaj, że po utworzeniu woluminu będzie można zwiększyć rozmiar pamięci. Jednak jej zmniejszenie nie jest obsługiwane:
|
1 2 3 4 5 6 7 |
... spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi |
Teraz zadeklaruj klasę pamięci (storage class), której klaster Kubernetes użyje do przydzielenia woluminów. Użyj utworzonej w poprzednim kroku klasy pamięci my-local-storage jako wartości parametru storageClassName:
|
1 2 |
... storageClassName: my-local-storage |
Po wykonaniu powyższych kroków Twój plik code_volume.yaml powinien wyglądać następująco:
|
1 2 3 4 5 6 7 8 9 10 11 |
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: code spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: my-local-storage |
Teraz zapisz i zamknij plik.
Tworzenie PVC
Utwórz PVC code, uruchamiając polecenie kubectl apply:
|
1 |
$ kubectl apply -f code_volume.yaml |
Powinieneś otrzymać następujące dane wyjściowe, które wskazują, że obiekt został pomyślnie utworzony i jest gotowy do zamontowania Twojego PVC o rozmiarze 1 GB jako woluminu:
|
1 |
persistentvolumeclaim/code created |
Możesz uruchomić następujące polecenie, aby sprawdzić dostępny wolumin Persistent Volume (PV):
|
1 |
$ kubectl get pv |
Wynik powyższego polecenia powinien być następujący:
|
1 2 |
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-ca4df10f-ab8c-11e8-b89d-12331aa95b13 1Gi RWO Delete Bound default/code do-block-storage 2m |
Wszystkie powyższe pola, z wyjątkiem Reclaim Policy i Status, stanowią przegląd Twojego pliku konfiguracyjnego. Reclaim Policy definiuje, co dzieje się z PV po usunięciu uzyskującego do niego dostęp PVC. Wartość Delete usuwa PV zarówno z klastra Kubernetes, jak i z infrastruktury pamięci masowej. Możesz zapoznać się z dokumentacją Kubernetes PV, aby dokładnie zrozumieć działanie Reclaim Policy i Status.
Możesz teraz utworzyć swoje pody za pomocą wdrożenia (Deployment), ponieważ pomyślnie utworzyłeś wolumin Persistent Volume przy użyciu pamięci lokalnej.
Step 4: Create Deployment for your PHP-FPM Application
Ten krok pomoże Ci utworzyć pod PHP-FPM przy użyciu Deployment. Deployment używa ReplicaSets, aby zapewnić stabilny sposób tworzenia, aktualizowania i zarządzania podami. Deployment automatycznie przywraca pody do poprzedniego obrazu.
Klucz spec.selector we wdrożeniu (Deployment) zawiera listę wszystkich etykiet podów, którymi zarządza. Używa również klucza template do tworzenia wymaganych podów.
W tym kroku wprowadzimy również zastosowanie Init Containers. Kontenery Init (Init Containers) uruchamiają kilka poleceń przed zwykłymi kontenerami określonymi w szablonie poda. W tym przypadku kontener Init użyje usługi GitHub Gist (https://gist.github.com/) do pobrania przykładowego pliku index.php. Zawartość przykładowego pliku to:
|
1 2 |
<?php echo phpinfo(); |
Tworzenie wdrożenia PHP
Otwórz nowy plik o nazwie php_deployment.yaml w edytorze, aby utworzyć wdrożenie (Deployment):
|
1 |
$ nano php_deployment.yaml |
Teraz nazwij obiekt Deployment jako PHP, ponieważ ten Deployment będzie zarządzał Twoimi podami PHP-FPM. Dodaj etykietę tier: backend ponieważ pod będzie należał do warstwy backendu:
|
1 2 3 4 5 6 |
apiVersion: apps/v1 kind: Deployment metadata: name: php labels: tier: backend |
Używając parametru replica, określ liczbę kopii tego poda, które powinny zostać utworzone. Liczba replik może się różnić w zależności od Twoich wymagań i dostępnych zasobów. W tym samouczku utworzysz tylko jedną replikę swojego poda:
|
1 2 3 4 |
... spec: replicas: 1 |
Dodaj app: php oraz tier:backend etykiety pod kluczem selector, który oznacza, że ten Deployment będzie zarządzał podami pasującymi do tych dwóch etykiet:
|
1 2 3 4 5 |
... selector: matchLabels: app: php tier: backend |
Teraz definicja obiektu Twojego poda wymaga szablonu (template) w specyfikacji Deploymentu. Ten szablon definiuje specyfikację potrzebną do utworzenia poda. Na początek dodaj etykiety, które zostały określone dla selektora usługi php oraz matchLabels Deploymentu. Następnie dodaj app:php oraz tier:backend pod template.metadata.labels:
|
1 2 3 4 5 6 7 |
... template: metadata: labels: app: php tier: backend |
Najpierw musisz określić wszystkie wolumeny, do których Twoje kontenery będą miały dostęp. Nazwij ten wolumen code, ponieważ utworzyłeś PVC o nazwie code do przechowywania kodu aplikacji:
|
1 2 3 4 5 6 |
... spec: volumes: - name: code persistentVolumeClaim: claimName: code |
Następnie określ nazwę kontenera wraz z obrazem, który chcesz uruchomić wewnątrz poda. W sklepie Docker dostępnych jest wiele różnych obrazów (https://hub.docker.com/explore/), ale w tym samouczku użyjemy obrazu php:7-fpm :
|
1 2 3 4 |
... containers: - name: php image: php:7-fpm |
Teraz zamontuj wolumeny, do których kontener wymaga dostępu. Ponieważ ten kontener będzie uruchamiał Twój kod PHP, będzie potrzebował dostępu do wolumenu code utworzonego w poprzednim kroku. W tym kroku dowiesz się również, jak skopiować kod aplikacji za pomocą Init Containera.
Aby pobrać kod, ten samouczek pokaże Ci, jak użyć pojedynczego Init Containera z busybox. Busybox to mały kontener z narzędziem wget, którego użyjesz do tego celu.
Najpierw dodaj swój initContainer pod spec.template.spec i określ obraz busybox:
|
1 2 3 4 |
... initContainers: - name: install image: busybox |
Następnie, aby pobrać kod do wolumenu code, Twój Init Container będzie potrzebował do niego dostępu. Zamontuj wolumen code w ścieżce /code pod spec.template.spec.initContainers:
|
1 2 3 4 |
... volumeMounts: - name: code mountPath: /code |
Każdy Init Container wymaga uruchomienia polecenia. Ten Init Container użyje wget do pobrania code z Github do katalogu /code . Możesz przekazać opcję -O , aby nadać pobranemu plikowi nazwę, i możesz nazwać ten plik index.php.
Dodatkowo dodaj poniższe linie pod kontenerem install w spec.template.spec.initContainers:
|
1 2 3 4 5 6 |
... command: - wget - "-O" - "/code/index.php" - https://raw.githubusercontent.com/do-community/php-kubernetes/master/index.php |
Po wykonaniu wszystkich tych kroków Twój plik php_deployment.yaml powinien wyglądać następująco:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
apiVersion: apps/v1 kind: Deployment metadata: name: php labels: tier: backend spec: replicas: 1 selector: matchLabels: app: php tier: backend template: metadata: labels: app: php tier: backend spec: volumes: - name: code persistentVolumeClaim: claimName: code containers: - name: php image: php:7-fpm volumeMounts: - name: code mountPath: /code initContainers: - name: install image: busybox volumeMounts: - name: code mountPath: /code command: - wget - "-O" - "/code/index.php" - https://raw.githubusercontent.com/do-community/php-kubernetes/master/index.php |
Możesz teraz zapisać plik i wyjść. Następnie utwórz wdrożenie PHP-FPM za pomocą kubectl apply polecenia:
|
1 |
$ kubectl apply -f php_deployment.yaml |
Pomyślne utworzenie wdrożenia (Deployment) powinno dać poniższy wynik:
|
1 |
deployment.apps/php created |
To wdrożenie rozpoczyna się od pobrania określonych obrazów, następnie zażąda PersistentVolume z Twojego PersistentVolumeClaim, a następnie uruchomi initContainers. Po zakończeniu tego kroku kontenery zostaną uruchomione i zamontują woluminy w określonym punkcie montowania. Po wykonaniu wszystkich tych kroków Twój pod będzie działał.
Możesz uruchomić poniższe polecenie, aby wyświetlić swoje wdrożenie (Deployment):
|
1 |
$ kubectl get deployments |
Po uruchomieniu powyższego polecenia powinieneś otrzymać poniższy wynik:
|
1 2 |
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE php 1 1 1 0 19s |
Możesz zrozumieć bieżący stan wdrożenia za pomocą tego wyniku. Wdrożenie (Deployment) to kontroler, który utrzymuje pożądany stan. Pole DESIRED określa, że posiada ono 1 replikę poda o nazwie php. Pole CURRENT wskazuje, ile replik stanu DESIRED jest obecnie uruchomionych. Dla prawidłowo działającego poda powinno to być zgodne ze stanem DESIRED state. Więcej informacji o pozostałych polach można znaleźć w dokumentacji Kubernetes Deployments.
Następnie, aby sprawdzić status uruchomionego poda, możesz uruchomić poniższe polecenie:
|
1 |
$ kubectl get pods |
Wynik tego polecenia może się różnić w zależności od czasu, jaki upłynął od utworzenia wdrożenia (Deployment). Jeśli zostanie ono uruchomione krótko po utworzeniu wdrożenia, wynik będzie podobny do:
|
1 2 |
NAME READY STATUS RESTARTS AGE php-5d8f6bbf7f-56df2 0/1 Init:0/1 0 9s |
Wyjaśnienie:
Te kolumny reprezentują następujące informacje:
- Ready: Liczba bieżących/pożądanych replik uruchomionych w tym podzie.
- Status: Status Twojego poda. Init:0/1 oznacza, że kontenery Init są uruchomione i 0 z 1 kontenerów Init zakończyło działanie.
- Restarts: Wskazuje to liczbę ponownych uruchomień tego procesu w celu uruchomienia poda.
Zmiana statusu Twojego poda na podInitializing może zająć kilka minut, w zależności od złożoności skryptów startowych:
|
1 2 |
NAME READY STATUS RESTARTS AGE php-5d8f6bbf7f-56df2 0/1 podInitializing 0 39s |
Oznacza to, że kontenery Init zostały pomyślnie uruchomione i teraz następuje inicjalizacja kontenerów:
|
1 2 |
NAME READY STATUS RESTARTS AGE php-5d8f6bbf7f-56df2 1/1 Running 0 4m10s |
Jak widać, Twój pod jest teraz uruchomiony i działa. Jeśli jednak pod się nie uruchomi, możesz użyć poniższych poleceń w celach debugowania:
1. Aby wyświetlić szczegółowe informacje o podzie:
|
1 |
$ kubectl describe pods pod-name |
2. Aby wyświetlić logi poda:
|
1 |
$ kubectl logs pod-name |
3. Aby wyświetlić logi konkretnego kontenera w podzie:
|
1 |
$ kubectl logs pod-name container-name |
Gratulacje! Pomyślnie zamontowano kod aplikacji, a usługa PHP-FPM jest gotowa do obsługi połączeń. W podobny sposób możesz utworzyć wdrożenie Nginx.
Krok 5: Utwórz wdrożenie Nginx
Ten krok poprowadzi Cię przez konfigurację Nginx przy użyciu ConfigMap. ConfigMap przechowuje wszystkie wymagane konfiguracje w formacie klucz-wartość, które będą używane w innych definicjach obiektów Kubernetes. Dzięki temu podejściu masz elastyczność ponownego użycia lub zamiany obrazu Nginx na inną wersję w razie potrzeby. Możesz zaktualizować ConfigMap, a zmiany te zostaną automatycznie zreplikowane do każdego poda, który montuje ten ConfigMap.
Na początek otwórz plik nginx_configmap.yaml w swoim edytorze:
|
1 |
$ nano nginx_configMap.yaml |
Teraz nazwij ten ConfigMap jako nginx-config i dodaj go do tier: backend mikrousługi:
|
1 2 3 4 5 6 |
apiVersion: v1 kind: ConfigMap metadata: name: nginx-config labels: tier: backend |
Dodatkowo możesz dodać dane do ConfigMap. Dodaj klucz o nazwie config i dodaj całą zawartość pliku konfiguracyjnego Nginx jako wartość.
Ponieważ Kubernetes może kierować żądania do odpowiednich hostów dla danej usługi, możesz wpisać nazwę swojej usługi PHP-FPM w parametrze fastcgi_pass zamiast jej adresu IP. Dodaj następujące linie kodu do swojego pliku nginx_configMap.yaml :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
... data: config : | server { index index.php index.html; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; root /code; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass php:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } } |
Po zakończeniu Twój plik nginx_configMap.yaml będzie wyglądać następująco:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
apiVersion: v1 kind: ConfigMap metadata: name: nginx-config labels: tier: backend data: config : | server { index index.php index.html; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; root /code; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass php:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } } |
Możesz teraz zapisać i zamknąć edytor. Teraz wykonaj polecenie kubectl apply polecenie, aby utworzyć ConfigMap:
|
1 |
$ kubectl apply -f nginx_configMap.yaml |
Następnie na ekranie powinien pojawić się poniższy wynik:
|
1 |
configmap/nginx-config created |
Pomyślnie utworzono obiekt ConfigMap dla Nginx. Teraz możesz utworzyć wdrożenie (Deployment) Nginx.
Tworzenie wdrożenia Nginx
Na początek możesz utworzyć nowy plik o nazwie nginx_deployment.yaml w edytorze:
|
1 |
$ nano nginx_deployment.yaml |
Nazwij to wdrożenie (Deployment) nginx i dodaj do niego etykietę tier: backend:
|
1 2 3 4 5 6 7 |
apiVersion: apps/v1 kind: Deployment metadata: name: nginx labels: tier: backend |
Następnie określ liczbę replik, dodając pole replica w specyfikacji wdrożenia (Deployment spec) i dodaj do niego etykiety app: nginx oraz tier: backend:
|
1 2 3 4 5 6 7 |
... spec: replicas: 1 selector: matchLabels: app: nginx tier: backend |
Podobnie dodaj szablon poda. Upewnij się, że dodajesz te same etykiety, które zostały dodane w sekcji selector.matchLabels wdrożenia. Możesz dodać następujące elementy:
|
1 2 3 4 5 6 |
... template: metadata: labels: app: nginx tier: backend |
Zapewnij Nginx dostęp do utworzonego wcześniej PVC kodu, dodając następujące parametry w sekcji spec.template.spec.volumes:
|
1 2 3 4 5 6 |
... spec: volumes: - name: code persistentVolumeClaim: claimName: code |
|
1 2 3 4 5 6 7 |
... - name: config configMap: name: nginx-config items: - key: config path: site.conf |
Ostrzeżenie: Zawartość klucza zastąpi ścieżkę montowania (mountPath) wolumenu, jeśli plik nie zostanie określony. Innymi słowy, utracisz całą zawartość folderu docelowego, jeśli ścieżka nie zostanie wyraźnie określona.
Teraz określ nazwę, obraz i port, których chcesz użyć w swoim podzie. Tutaj użyjemy obrazu nginx:1.7.9 oraz portu 80. Dodaj je w sekcji spec.template.spec - sekcja:
|
1 2 3 4 5 6 |
... containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 |
Dodatkowo zamontuj wolumen kodu w /code, ponieważ zarówno Nginx, jak i PHP-FPM będą potrzebować dostępu do pliku pod tą samą ścieżką:
|
1 2 3 4 |
... volumeMounts: - name: code mountPath: /code |
Obraz nginx-1.7.9 automatycznie ładuje każdy plik konfiguracyjny z folderu /etc/nginx/conf.d. Jeśli teraz zamontujemy wolumen konfiguracyjny w tym katalogu, utworzy on /etc/nginx/conf.d/site.conf. Dodaj poniższe elementy pod sekcją volumeMount:
|
1 2 3 |
... - name: config mountPath: /etc/nginx/conf.d |
Po wykonaniu wszystkich powyższych kroków Twój plik nginx_deployment.yaml powinien wyglądać następująco:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
apiVersion: apps/v1 kind: Deployment metadata: name: nginx labels: tier: backend spec: replicas: 1 selector: matchLabels: app: nginx tier: backend template: metadata: labels: app: nginx tier: backend spec: volumes: - name: code persistentVolumeClaim: claimName: code - name: config configMap: name: nginx-config items: - key: config path: site.conf containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 volumeMounts: - name: code mountPath: /code - name: config mountPath: /etc/nginx/conf.d |
Możesz teraz zapisać i zamknąć plik, a następnie utworzyć wdrożenie (Deployment) Nginx, uruchamiając następujące polecenie:
|
1 |
$ kubectl apply -f nginx_deployment.yaml |
Po pomyślnym wykonaniu polecenia powinieneś zobaczyć następujący wynik:
|
1 |
deployment.apps/nginx created |
Możesz wyświetlić listę wszystkich swoich wdrożeń (Deployments), wykonując poniższe polecenia:
|
1 |
$ kubectl get deployments |
Powinieneś teraz zobaczyć wdrożenia (Deployments) zarówno Nginx, jak i PHP-FPM:
Ponadto możesz wykonać następujące polecenie, aby wyświetlić listę podów, które są zarządzane przez oba wymienione powyżej wdrożenia:
|
1 |
$ kubectl get pods |
Zobaczysz, że oba pody działają i są uruchomione w następujący sposób:
Ponieważ wszystkie obiekty Kubernetes są w tym momencie aktywne, możesz teraz uzyskać dostęp do usługi Nginx w swojej przeglądarce.
Uruchom następujące polecenie, aby wyświetlić listę usług:
|
1 |
$ kubectl get services -o wide |
Zanotuj zewnętrzny adres IP (External IP) swojej usługi Nginx:
Teraz, używając tego zewnętrznego adresu IP usługi Nginx, możesz odwiedzić swój serwer, wpisując http://your_public_ip w przeglądarce. Powinieneś zobaczyć wynik działania php_info(), który potwierdza, że Twoje usługi Kubernetes działają i są uruchomione.
Podsumowanie
W tym samouczku, aby niezależnie zarządzać usługami PHP-FPM i Nginx, skonteneryzowałeś obie te usługi. Dzięki temu nie tylko poprawisz skalowalność swojego projektu, ale także efektywnie wykorzystasz zasoby. Dowiedziałeś się również, jak utworzyć lokalną pamięć masową i wolumen trwały (Persistent Volume), aby przechowywać kod aplikacji na wolumenie i móc łatwo aktualizować swoje usługi w przyszłości. W ten sposób poprawiłeś użyteczność i łatwość utrzymania swojego kodu.
Ponadto zapoznaj się z naszymi innymi samouczkami dotyczącymi Dockera i Kubernetesa, które znajdziesz na naszym blogu:
- Wprowadzenie do Kubernetes
- Jak utworzyć klaster Kubernetes za pomocą Kubeadm na Ubuntu 18.04
- Czyszczenie zasobów Dockera – obrazy, kontenery i wolumeny
- Wdrażanie Laravel, Nginx i MySQL za pomocą Docker Compose
- Jak zainstalować & obsługiwać Docker na Ubuntu w chmurze publicznej
Udanego kodowania!


Komentarze
Brak komentarzy. Bądź pierwszy.