W kolejnej części przewodnika po praktykach, które pomagają zdobyć certyfikat CKA , chciałbym skoncentrować się na metodach sprawnego generowania manifestów obiektów Kubernetes w postaci plików YAML.
Podstawy
Ogólna postać polecenia
kubectl [command] [TYPE] [NAME] [flags]
TYPE: Określa typ zasobu . W typach zasobów nie jest rozróżniana wielkość liter i można określić formę pojedynczą, mnogą lub skróconą.
Możemy pytać się o to samo na kilka sposobów. Dla przykładu typ obiektu node (węzeł). Forma skrocóna no, forma pojedyńcza node, forma mnoga nodes.
kubectl get no
NAME STATUS ROLES AGE VERSION
controlplane Ready master 88s v1.19.0
node01 Ready 59s v1.19.0
kubectl get node
NAME STATUS ROLES AGE VERSION
controlplane Ready master 114s v1.19.0
node01 Ready 85s v1.19.0
kubectl get nodes
NAME STATUS ROLES AGE VERSION
controlplane Ready master 2m10s v1.19.0
node01 Ready 101s v1.19.0
NAME: Określa nazwę zasobu. W nazwach jest rozróżniana wielkość liter. W przypadku pominięcia nazwy wyświetlane są na przykład szczegóły dotyczące wszystkich zasobów kubectl get pods.
kubectl get node node01
NAME STATUS ROLES AGE VERSION
node01 Ready 4m6s v1.19.0
kubectl get node Node01
Error from server (NotFound): nodes "Node01" not found
Warto o tym pamiętać (!)
flags: Określa opcjonalne flagi
Generatory
Na początku spróbujmy skorzystać z funkcjonalności dostępnych w narzędziu kubectl. To jest główne polecenie typu cli (command line interface), z którym się trzeba zapoznać, powiem więcej, które przynajmniej musisz polubić
Zacznijmy od małego śledztwa
kubectl create --help
W odpowiedzi otrzymamy listę obiektów, które możemy utworzyć w sposób imperatywny
Create a resource from a file or from stdin. JSON and YAML formats are accepted. Examples: # Create a pod using the data in pod.json. kubectl create -f ./pod.json # Create a pod based on the JSON passed into stdin. cat pod.json | kubectl create -f - # Edit the data in docker-registry.yaml in JSON then create the resource using the edited data. kubectl create -f docker-registry.yaml --edit -o json Available Commands: clusterrole Create a ClusterRole. clusterrolebinding Create a ClusterRoleBinding for a particular ClusterRole configmap Create a configmap from a local file, directory or literal value cronjob Create a cronjob with the specified name. deployment Create a deployment with the specified name. job Create a job with the specified name. namespace Create a namespace with the specified name poddisruptionbudget Create a pod disruption budget with the specified name. priorityclass Create a priorityclass with the specified name. quota Create a quota with the specified name. role Create a role with single rule. rolebinding Create a RoleBinding for a particular Role or ClusterRole secret Create a secret using specified subcommand service Create a service using specified subcommand. serviceaccount Create a service account with the specified name
Odfiltruję, te obiekty, które nas interesują w zakresie certyfikacji
configmap Create a configmap from a local file, directory or literal value cronjob Create a cronjob with the specified name. deployment Create a deployment with the specified name. job Create a job with the specified name. namespace Create a namespace with the specified name quota Create a quota with the specified name. secret Create a secret using specified subcommand service Create a service using specified subcommand.
Uważni zwrócą uwagę, iż brakuje możliwości utworzenia obiektu typu pod. Z historycznych powodów zamiast polecenia kubectl create należy zastosować polecenie kubectl run.
Zobaczmy jak to wygląda:
kubectl run --help
W odpowiedzi otrzymujemy bogatą informacje, którą pozwoliłem sobie nieco skrócić (…) … (…)
Create and run a particular image in a pod. Examples: # Start a nginx pod. kubectl run nginx --image=nginx # Start a hazelcast pod and let the container expose port 5701. kubectl run hazelcast --image=hazelcast/hazelcast --port=5701 # Start a hazelcast pod and set environment variables "DNS_DOMAIN=cluster" and "POD_NAMESPACE=default" in the container. kubectl run hazelcast --image=hazelcast/hazelcast --env="DNS_DOMAIN=cluster" --env="POD_NAMESPACE=default" # Start a hazelcast pod and set labels "app=hazelcast" and "env=prod" in the container. kubectl run hazelcast --image=hazelcast/hazelcast --labels="app=hazelcast,env=prod" # Dry run. Print the corresponding API objects without creating them. kubectl run nginx --image=nginx --dry-run=client # Start a nginx pod, but overload the spec with a partial set of values parsed from JSON. kubectl run nginx --image=nginx --overrides='{ "apiVersion": "v1", "spec": { ... } }' # Start a busybox pod and keep it in the foreground, don't restart it if it exits. kubectl run -i -t busybox --image=busybox --restart=Never # Start the nginx pod using the default command, but use custom arguments (arg1 .. argN) for that command. kubectl run nginx --image=nginx -- <arg1> <arg2> ... <argN> # Start the nginx pod using a different command and custom arguments. kubectl run nginx --image=nginx --command -- <cmd> <arg1> ... <argN> Options: (...) ... (...) Usage: kubectl run NAME --image=image [--env="key=value"] [--port=port] [--dry-run=server|client] [--overrides=inline-json] [--command] -- [COMMAND] [args...] [options]
Lista możliwych parametrów jest dosyć długa, co ciekawe sporo z tych parametrów nie może być stosowanych w obiekcie kontrolującym pod jakim jest deployment. Na to też jest sposób.
Co z pozostałymi obiektami ?
Mamy dwie albo nawet trzy możliwości
- Skorzystanie z przykładowych manifestów, które znajdują się w oficjalnej dokumentacji
- Przekształcenie jednego typu obiektu w drugi (pokażę, to na kilku przykładach)
- Wykorzystanie generatora kubectl run do wklejenia tych cech obiektu, które nie są możliwe z poziomu kubectl create
- Użycie polecenia kube explain
Zadanie pierwsze
- Utwórz obiekt pod o nazwie web w przestrzeni nazw alpha wykorzystujący obraz nginx:1.11.9-alpine, kontener ma pracować na portach 80 i 443. Uzupełnij klaster o brakującą przestrzeń nazw alpha.
Wykorzystajmy kubectl run:
kubectl run web --image=nginx:1.11.9-alpine --port 80 -o yaml --dry-run=client > 01.pod.web.yaml
W tym miejscu zaczynamy stosować nasz schemat postępowania:
- 1. imperatywnie tworzymy plik manifestu
- 2. poprawiamy zawartość tego pliku
- 3. wdrażamy obiekt na klaster Kubernetes
- 4. po weryfikacji stanu obiektu na klastrze, wracamy do punktu 2 jeśli jest taka potrzeba
- 5. Zabieramy się za kolejne zadanie
Zobaczmy, co się znajduje w naszym pliku
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: web
name: web
spec:
containers:
- image: nginx:1.11.9-alpine
name: web
ports:
- containerPort: 80
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
Edytujemy plik
vim 01.pod.web.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: web
name: web
namespace: alpha
spec:
containers:
- image: nginx:1.11.9-alpine
name: web
ports:
- containerPort: 80
- containerPort: 443
dnsPolicy: ClusterFirst
restartPolicy: Always
Skąd wiadomo, że tak się dodaje kolejny port ?
Można szukać przykładów w obszernej dokumentacji Kubernetes, ale kubectl dostarcza nam polecenie explain
kubectl explain pod.spec.containers.ports
KIND: Pod VERSION: v1 RESOURCE: ports <[]Object> DESCRIPTION: List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default "0.0.0.0" address inside a container will be accessible from the network. Cannot be updated. ContainerPort represents a network port in a single container. FIELDS: containerPort -required- Number of port to expose on the pod's IP address. This must be a valid port number, 0 < x > 65536.
Zgodnie z dokumentację mamy do czynienia z listą.
Bez utworzenia obiektu namespace o nazwie alpha nasze wdrożenie kończy się tak:
kubectl apply -f 01.pod.web.yaml
Error from server (NotFound): error when creating "01.pod.web.yaml": namespaces "alpha" not found
Tu pojawia się pokusa, by wykorzystać imperatywnie utworzenie przestrzeni nazw za pomocą
kubectl create ns alpha
Polecam jednak utworzyć ten obiekt stosując nasz schemat opisany powyżej.
kubectl create ns alpha -o yaml --dry-run=client > 01.ns.alpha.yaml
cat 01.ns.alpha.yaml
apiVersion: v1
kind: Namespace
metadata:
creationTimestamp: null
name: alpha
spec: {}
status: {}
kubectl apply -f 01.ns.alpha.yaml
namespace/alpha created
Zadanie drugie
kubectl expose pod/web --name=webservice -n alpha -o yaml --dry-run=client > 02.svc.webservice.yaml
Jak wygląda nasz plik ?
cat 02.svc.webservice.yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
run: web
name: webservice
namespace: alpha
spec:
ports:
- name: port-1
port: 80
protocol: TCP
targetPort: 80
- name: port-2
port: 443
protocol: TCP
targetPort: 443
selector:
run: web
status:
loadBalancer: {}
kubectl apply -f 02.svc.webservice.yaml
Zadanie trzecie
kubectl run postgresql --image=postgres:12.4 --port 5432 -o yaml --dry-run=client > 03.pod.postgresql.yaml
Doprowadźmy nasz manifest do odpowiedniej postaci dopisując namespace. Warto też usunąć końcowy status: {}
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: postgresql
name: postgresql
namespace: alpha
spec:
containers:
- image: postgres:12.4
name: postgresql
ports:
- containerPort: 5432
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
kubectl apply -f 03.pod.postgresql.yaml
Wnikliwy obserwator zauważy, iż obiekt pod nie jest w statusie Running
kubectl get pod postgresql -n alpha
NAME READY STATUS RESTARTS AGE postgresql 0/1 CrashLoopBackOff 1 17s
Spróbujmy dokonać prostej diagnozy naszego obiektu. W tym celu można skorzystać z polecenia kubectl describe, które zmienia postać obiektu na klastrze na bardziej zrozumiały opis ( ale to też jest kwestia dyskusyjna), bez formatu JSON czy YAML.
kubectl describe pod postgresql -n alpha
Name: postgresql Namespace: alpha Priority: 0 Node: node01/172.17.0.58 Start Time: Mon, 10 May 2021 18:17:34 +0000 Labels: run=postgresql Annotations: Status: Running IP: 10.244.1.6 IPs: IP: 10.244.1.6 Containers: postgresql: Container ID: docker://893dc06e02cdad8cf6998203b08a911a4e46e37919579f213c8422d8a9ee2e61 Image: postgres:12.4 Image ID: docker-pullable://postgres@sha256:a1e04460fdd3c338d6b65a2ab66b5aa2748eb18da3e55bcdc9ef17831ed3ad46 Port: 5432/TCP Host Port: 0/TCP State: Waiting Reason: CrashLoopBackOff
Last State: Terminated Reason: Error Exit Code: 1
Started: Mon, 10 May 2021 18:20:49 +0000 Finished: Mon, 10 May 2021 18:20:49 +0000 Ready: False Restart Count: 5 Environment: Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-57qw5 (ro) Conditions: Type Status Initialized True Ready False ContainersReady False PodScheduled True Volumes: default-token-57qw5: Type: Secret (a volume populated by a Secret) SecretName: default-token-57qw5 Optional: false QoS Class: BestEffort Node-Selectors: 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 3m55s default-scheduler Successfully assigned alpha/postgresql to node01 Normal Pulling 3m54s kubelet, node01 Pulling image "postgres:12.4" Normal Pulled 3m53s kubelet, node01 Successfully pulled image "postgres:12.4" in 1.428701345s Normal Started 3m4s (x4 over 3m53s) kubelet, node01 Started container postgresql Warning BackOff 2m26s (x10 over 3m51s) kubelet, node01 Back-off restarting failed container Normal Created 2m12s (x5 over 3m53s) kubelet, node01 Created container postgresql Normal Pulled 2m12s (x4 over 3m52s) kubelet, node01 Container image "postgres:12.4" already present on machine
Widać, że mamy w manifeście poprawny adres obrazu z repozytorium (Successfully pulled image “postgres:12.4”) , ale z jakiegoś powolu zwrócony jest Exit Code o wartości 1, a obiekt jest restartowany. gdyż restartPolicy ustawione jest na wartość Always (taka jest domyślna wartość dla tej cechy)
Co możemy z tym dalej zrobić ?
Spróbujmy obejrzeć logi kontenera w obiekcie pod, tym razem korzystając z polecenia kubectl logs.
kubectl logs postgresql -n alpha
Error: Database is uninitialized and superuser password is not specified. You must specify POSTGRES_PASSWORD to a non-empty value for the superuser. For example, "-e POSTGRES_PASSWORD=password" on "docker run". You may also use "POSTGRES_HOST_AUTH_METHOD=trust" to allow all connections without a password. This is *not* recommended. See PostgreSQL documentation about "trust": https://www.postgresql.org/docs/current/auth-trust.html
I teraz jest już wszystko jasne. Nasz kontener z bazą postgresql wymaga wstrzyknięcia zmiennych środowiskowych. Tym zajmiemy się w kolejnym zadaniu.
Przy okazji zrobiliśmy mały wstęp do zadań z zakresu naprawy obiektów na klastrze. Zostawmy ten obiekt tak jak jest. Został przygotowany zgodnie ze warunkami zadania.
Zadanie czwarte
Spróbujmy wykorzystać pomoc dostępną w kubectl i odfiltrować jego bogatą treść:
kubectl run --help| grep -i env
# Start a hazelcast pod and set environment variables "DNS_DOMAIN=cluster" and "POD_NAMESPACE=default" in the container. kubectl run hazelcast --image=hazelcast/hazelcast --env="DNS_DOMAIN=cluster" --env="POD_NAMESPACE=default" # Start a hazelcast pod and set labels "app=hazelcast" and "env=prod" in the container. kubectl run hazelcast --image=hazelcast/hazelcast --labels="app=hazelcast,env=prod" --env=[]: Environment variables to set in the container.
Mamy przykładowe wywołanie, które możemy wykorzystać.
Wystarczy do linii poleceń dopisać wielokrotnie –env=”KEY=VALUE”
kubectl run postgresql-env --image=postgres:12.4 --port 5432 --env="POSTGRES_DB=postgresdb"
--env="POSTGRES_USER=postgresadmin" --env="POSTGRES_PASSWORD=admin123"
-o yaml --dry-run=client > 04.pod.postgresql-env.yaml
Zobaczmy jak wygląda nasz plik
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: postgresql-env
name: postgresql-env
spec:
containers:
- env:
- name: POSTGRES_DB
value: postgresdb
- name: POSTGRES_USER
value: postgresadmin
- name: POSTGRES_PASSWORD
value: admin123
image: postgres:12.4
name: postgresql-env
ports:
- containerPort: 5432
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
Doprowadźmy nasz manifest do odpowiedniej postaci dopisując namespace i usuwając resources: {}, status: {}. Można też pozbyć się rownież linii creationTimestamp: null w sekcji metadata. Starajmy się w plikach trzymać jedynie niezbędne informacje.
Wdrażamy obiekt na klaster
kubectl apply -f 04.pod.postgresql-env.yaml
Dla zainteresowanych kontrolą zasobów kontenera proponuję wykonać
kubectl run --help |grep limit
kubectl run --help |grep request
kubectl run test --image=nginx --port 80 -o yaml --dry-run=client --limits='cpu=500m,memory=512Mi' --requests='cpu=200m,memory=256Mi'
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: test
name: test
spec:
containers:
- image: nginx
name: test
ports:
- containerPort: 80
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 200m
memory: 256Mi
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
Na razie zakończymy zabawę z obiektami pod (w tej części) i spróbujemy przenieść się na poziom wyżej. Czyli będziemy tworzyć jeden z tych obiektów, które kontrolują obiekty pod. Obiektem tym jest deployment
Zadanie piąte
Utwórz obiekt deployment o nazwie nginx-deployment, który jest oparty o obraz nginx:1.18.0 z wystawionym portem 80. Umieść go w przestrzeni nazw alpha.
kubectl create deployment nginx-deployment --image=nginx:1.18.0 -n alpha -o yaml --dry-run=client > 05.deployment.nginx-deployment.yaml
vim 05.deployment.nginx-deployment.yaml
Ponieważ create deployment nie pozwala na dodanie z marszu numeru portu, należy uzupełnić go ręcznie.
Czy musimy w ten sposób działać ? Niekoniecznie.
Można sprobować wygenerować manifest samego obiektu typu pod z wygenerowanym portem (tak jak w zadaniu pierwszym) i potem wkleić jego zawartość do obiektu deployment w miejscu spec.template.spec.containers, gdzie kropką odzieliłem kolejne zagnieżdzenie.
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: nginx-deployment
name: nginx-deployment
namespace: alpha
spec:
replicas: 1
selector:
matchLabels:
app: nginx-deployment
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: nginx-deployment
spec:
containers:
- image: nginx:1.18.0
name: nginx
ports:
- containerPort: 80
resources: {}
Można też skorzystać z wbudowanej pomocy i sprawdzić jak ma wyglądać nasza składnia
kubectl explain deployment.spec.template.spec.containers --recursive
Skrócona odpowiedź (…)
KIND: Deployment
VERSION: apps/v1
RESOURCE: containers <[]Object>
DESCRIPTION:
List of containers belonging to the pod. Containers cannot currently be
added or removed. There must be at least one container in a Pod. Cannot be
updated.
A single application container that you want to run within a pod.
FIELDS:
(...)
Wdrażamy nasz obiekt na klaster
kubectl apply -f 05.deployment.nginx-deployment.yaml -n alpha --record
Zadanie szóste
kubectl expose deploy nginx-deployment -n alpha -o yaml --port 80 --name=nginx-service -dry-run=client > 06.service.nginx-service.yaml
Tak wygląda nasz manifest
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: nginx-deployment
name: nginx-service
namespace: alpha
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx-deployment
status:
loadBalancer: {}
Po poprawieniu manifestu wdrażamy go na klaster.
Zawsze warto w przypadku środowiska egzaminacyjunego pamiętać o dodaniu dla obiektów wdrażanych w przestrzemni nazw (pod, deployment,service i inne) nazwy tej przestrzeni. Pozwala nam to na ominięcie w linii poleceeń
-n nazwa_przestrzeni Jeśli natomiast użyjemy innej nazwy przestrzeni w opcjach polecenia kubectl, a inna będzie w deklaracji manifestu wdrożenie nie uda się. W ten sposób zabezpieczamy się przed pomyłkami.
kubectl apply -f 06.service.nginx-service.yaml -n alpha
Zadanie siódme
kubectl set image deploy nginx-deployment -n alpha nginx=nginx:1.19.2 -o yaml --dry-run=client > 07.deploy.nginx-deployment.yaml
W tym momencie mamy juz przygotowany manifest obiektu deployment z nowym obrazem.
Pozostaje nam tylko wdrożenie go na klaster, ale należy pamietać o rejestracji tej zmiany. Do tego służy flaga –record
kubectl apply -f 07.deploy.nginx-deployment.yaml -n alpha --record
Zobaczmy jak wygląda historia
kubectl rollout history deploy/nginx-deployment -n alpha
Cofnijmy ostatnią zmianę
kubectl rollout undo deployment nginx-deployment -n alpha
Ponownie możemy zobaczyć historię obiekty deployment
kubectl rollout history deploy/nginx-deployment -n alpha
Na końcu sprobujmy wyskalować obiekt deployment zwiększając listę replik do pięciu. Tu mamy kolejne dedykowane polecenie kubectl scale. Warto je zapamiętać, a przykłady łatwo znaleźć za pomocą kubectl scale –help.
kubectl scale deploy nginx-deployment -n alpha --replicas=5
To ostatnie jest zrobione w trybie imperatywnym, proponuję też sprobować zmienić odpowiedni manifest yaml (pole replicas: x) i wdrożyc w trybie deklaratywnym. Nigdy za mało praktyki, przekonacie sie o tym podczas kontroli czasu na egzaminie.
Jakie obiekty tworzy na klastrze wdrożenie typu deployment? Oprócz kilku replik obiektu pod, powstanie obiekt replicaset, Nazwa tego obiektu to nazwa deploymentname_hashreplicaset, a nazwy obiektów pod to deploymentname_hashreplicaset_hashpod. Po pewnej wprawie łatwo będzie się można zorientować, który obiekt jest rodzicem, a który dzieckiem.
Zadanie ósme
Utwórz obiekt typu replicaset o nazwie replicaset-nginx zawierający obraz redis:alpine. Liczba instancji powinna wynosić cztery (4). Obiekt należy umieścić w przestrzeni nazw alpha. To zadanie można zrobić na dwa sposoby.
Pierwszy to sięgnąć do dokumentacji Kubernetes
https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/ i znaleźć tam gotowy przykład. Wkleić kod takiego manifestu, obrobić w edytorze tekstu i ogłosić sukces.
Drugi sposób to spreparować obiekt replicaset z obiektu deployment. Spróbujmy to zrobić
Na początku tworzymy plik o nazwie zgodnej z przyjęta konwencją.
kubectl create deployment replicaset-nginx --image=redis:alpine -n alpha -o yaml --dry-run=client > 08.replicaset.replicaset-nginx.yaml
Zobaczmy jak wygląda jego zawartość
cat 08.replicaset.replicaset-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: replicaset-nginx
name: replicaset-nginx
namespace: alpha
spec:
replicas: 1
selector:
matchLabels:
app: replicaset-nginx
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: replicaset-nginx
spec:
containers:
- image: redis:alpine
name: redis
resources: {}
status: {}
To co musimy zrobić to zmienić typ obiektu z kind: Deployment na kind: ReplicaSet
Sprawdzmy jak jaka powinna być wersja
kubectl explain replicaset
KIND: ReplicaSet VERSION: apps/v1
usuńmy strategy{} i ustawmy liczbę replik na cztery
Nasz plik powinien wyglądać tak
apiVersion: apps/v1
kind: ReplicaSet
metadata:
creationTimestamp: null
labels:
app: replicaset-nginx
name: replicaset-nginx
namespace: alpha
spec:
replicas: 4
selector:
matchLabels:
app: replicaset-nginx
template:
metadata:
creationTimestamp: null
labels:
app: replicaset-nginx
spec:
containers:
- image: redis:alpine
name: redis
resources: {}
Obiekt taki można następnie wdrożyć na klaster
kubectl apply -f 08.replicaset.replicaset-nginx.yaml
kubectl get all -n alpha
NAME READY STATUS RESTARTS AGEpod/replicaset-nginx-6ddrz 1/1 Running 0 98 spod/replicaset-nginx-95krm 1/1 Running 0 98s pod/replicaset-nginx-chs8b 1/1 Running 0 98s pod/replicaset-nginx-rqdf2 1/1 Running 0 98s NAME DESIRED CURRENT READY AGE replicaset.apps/replicaset-nginx 4 4 4 98s
Strategia jest jest cechą obiektu deployment i pozwala na łatwe wdrażanie kolejnych wersji obrazu. W przypadku obiektu replicaset jest to wartość niemutowalna i wymaga usunięcia obiektu z klastra i utworzenia raz jeszcze. W praktyce samodzielne tworzenie tego typu zasobów nie jest popularne.
Zadanie dziewiąte
Utwórz obiekt typu daemonset o nazwie daemonset-filebeat zawierający obraz filebat. Obiekt należy umieścić w przestrzeni nazw alpha.
W aktualnej wersji (1.20) nie ma możliwości utworzenia obiektu tego typu za pomocą kubectl create daemonset. Wykorzystajmy znany nam obiekt deployment.
kubectl create deployment daemonset-filebeat --image=filebeat -n alpha -o yaml --dry-run=client > 09.daemonset.daemonset-filebeat.yaml
Zobaczmy jak wygląda nasz manifest
cat 09.daemonset.daemonset-filebeat.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: daemonset-filebeat
name: daemonset-filebeat
namespace: alpha
spec:
replicas: 1
selector:
matchLabels:
app: daemonset-filebeat
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: daemonset-filebeat
spec:
containers:
- image: filebeat
name: filebeat
resources: {}
status: {}
Sprawdzmy wersje API dla obiektu daemonset. Wersja jest ta sama i nie musimy jej zmieniać, ale warto to sprawdzić, nie uczmy sie na pamięć.
kubectl explain daemonset
KIND: DaemonSet
VERSION: apps/v1
Po drobnych zmianach nasz plik powinien wyglądać mniej więcej tak.
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
app: daemonset-filebeat
name: daemonset-filebeat
namespace: alpha
spec:
selector:
matchLabels:
app: daemonset-filebeat
template:
metadata:
labels:
app: daemonset-filebeat
spec:
containers:
- image: filebeat
name: filebeat
resources: {}
Jakie to zmiany ? Najważniejsza to usunięcie liczby replik z manifestu. Daemonset to typu obiektu, który pozwala na wdrożenie po jednej instancji obiektu pod per węzeł (node). Jest z reguły stosowany do instalacji na klastrze kontenerów technicznych. Można też ograniczyć liczbę węzłów, na których ma się pojawić korzystająć na przykład z selektorów dla węzła.
Wdrażamy nasz obiekt na klaster i mamy poczucie dobrze zrobionego zadania.
Dotarliśmy do końca dzisiejszyej audycji i powinniśmy mieć wrażenie, że to jest tylko zadrapanie powierzchni z bogatego zakresu zagadnień egzaminacyjnych.
Dla tych, którzy chcą sobie poćwiczyć dodatkowo proponuję poniższą listę zadań.
https://dev.to/subodev/50-questions-for-ckad-and-cka-exam-3bjm
W poprzedniej części:
Certified Kubernetes Administrator (CKA) krok po kroku – część 1
W następnych częściach
Certified Kubernetes Administrator (CKA) krok po kroku – część 3
marcin
cd równie bardzo dobry