{"id":1367,"date":"2021-06-20T23:33:13","date_gmt":"2021-06-20T21:33:13","guid":{"rendered":"https:\/\/wchmurze.cloud\/?p=1367"},"modified":"2021-06-22T22:27:38","modified_gmt":"2021-06-22T20:27:38","slug":"certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5","status":"publish","type":"post","link":"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/","title":{"rendered":"Certified Kubernetes Administrator (CKA) krok po kroku &#8211; cz\u0119\u015b\u0107 5"},"content":{"rendered":"<h3>W jaki spos\u00f3b mo\u017cna w \u015brodowisku skonteneryzowanym utrzymywa\u0107 dane i stan ?<\/h3>\n<p>&nbsp;<\/p>\n<p>Jak wiadomo ka\u017cdy kontener ma sw\u00f3j system plik\u00f3w dost\u0119pny tylko dla niego. Ten system jest ulotny (efemeryczny). Oznacza to, ze wszelki dane jakie zapiszemy w kontenerze podczas jego pracy po ponownym uruchomienia b\u0119d\u0105 utracone.Je\u017celi mamy do czynienia z aplikacja, kt\u00f3ra dzia\u0142a samodzielnie i nie musi zapisywa\u0107 swojego stanu nie mamy problemu, ale co zrobi\u0107 w sytuacji, gdy aplikacja sk\u0142ada si\u0119 z wielu kontener\u00f3w i musi wymienia\u0107 sw\u00f3j stan i utrzymywa\u0107 go mi\u0119dzy restartami?<\/p>\n<p>&nbsp;<\/p>\n<p>O tym jest dzisiejsza opowie\u015b\u0107:<\/p>\n<p>&nbsp;<\/p>\n<h3>Wolumeny danych<\/h3>\n<p>&nbsp;<\/p>\n<p>Na pocz\u0105tku pracy z Kubernetes pewn\u0105 trudno\u015b\u0107 sprawia\u0142a mi budowa manifest\u00f3w, kt\u00f3re wykorzystuj\u0105 wolumeny. Nie uczmy si\u0119 na pami\u0119\u0107, wykorzystajmy zar\u00f3wno system pomocy jak i wbudowane narz\u0119dzia, niekoniecznie zgodnie z intencj\u0105 ich tw\u00f3rc\u00f3w.\u00a0 Jak mo\u017cna\u00a0 sprawnie budowa\u0107 takie manifesty?<\/p>\n<p>Na pocz\u0105tku zacznijmy od prostego \u0107wiczenia<\/p>\n<p>Czym r\u00f3\u017cni\u0105 si\u0119 dwa tryby <strong>kubectl &#8211;dry-run<\/strong> ? (<strong>client<\/strong>, <strong>server<\/strong>)<\/p>\n<p>W przypadku opcji <strong>client<\/strong> polecenie kubectl wy\u015bwietli tylko obiekt ( dla opcji -o yaml) , jaki zostanie wys\u0142any do klastra, a w przypadku opcji <strong>server<\/strong> obiekt zostanie wys\u0142any na klaster, zostan\u0105 dopisane r\u00f3\u017cne domy\u015blne warto\u015bci, ale bez ko\u0144cowego zapisu obiektu.<\/p>\n<p>Przyk\u0142adowe polecenie generuj\u0105ce manifest obiektu pod.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">kubectl run test --image=nginx.alpine -o yaml --dry-run=client<\/pre>\n<p>Zwrotny manifest wygl\u0105da w taki spos\u00f3b<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">apiVersion: v1\r\nkind: Pod\r\nmetadata:\r\n  creationTimestamp: null\r\n  labels:\r\n    run: test\r\n  name: test\r\nspec:\r\n  containers:\r\n  - image: nginx.alpine\r\n    name: test\r\n    resources: {}\r\n  dnsPolicy: ClusterFirst\r\n  restartPolicy: Always\r\nstatus: {}<\/pre>\n<p>&nbsp;<\/p>\n<p>W\u00a0 wersji &#8220;serwerowej&#8221; wygl\u0105da to nieco inaczej.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">kubectl run test --image=nginx:alpine -o yaml --dry-run=server \r\n<\/pre>\n<p>Manifest zawiera w sobie o wiele wi\u0119cej danych. Zwr\u00f3\u0107my uwag\u0119 na jeden aspekt jakim jest pod\u0142\u0105czenie za pomoc\u0105 obiektu secret tokena pochodz\u0105cego od konta serwisowego (<strong>serviceaccount<\/strong>) o nazwie default. Ka\u017cda przestrze\u0144 nazw ma utworzon\u0105 par\u0119 obiekt\u00f3w konto serwisowe\u00a0 (serviceaccount) o nazwie <strong>default<\/strong> i skojarzony z tym kontem token zawarty w obiekcie secret <strong>default-token-HASH<\/strong>.<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">apiVersion: v1\r\nkind: Pod\r\nmetadata:\r\n  creationTimestamp: \"2021-06-17T20:03:21Z\"\r\n  labels:\r\n    run: test\r\n # managedfields ommited (...)\r\n  name: test\r\n  namespace: default\r\n  selfLink: \/api\/v1\/namespaces\/default\/pods\/test\r\n  uid: 2049eb41-0974-4017-b5b6-1eddc29fbd9a\r\nspec:\r\n  containers:\r\n  - image: nginx:alpine\r\n    imagePullPolicy: IfNotPresent\r\n    name: test\r\n    resources: {}\r\n    terminationMessagePath: \/dev\/termination-log\r\n    terminationMessagePolicy: File\r\n    volumeMounts:\r\n    - mountPath: \/var\/run\/secrets\/kubernetes.io\/serviceaccount\r\n      name: default-token-hzgn6\r\n      readOnly: true\r\n  dnsPolicy: ClusterFirst\r\n  enableServiceLinks: true\r\n  preemptionPolicy: PreemptLowerPriority\r\n  priority: 0\r\n  restartPolicy: Always\r\n  schedulerName: default-scheduler\r\n  securityContext: {}\r\n  serviceAccount: default\r\n  serviceAccountName: default\r\n  terminationGracePeriodSeconds: 30\r\n  tolerations:\r\n  - effect: NoExecute\r\n    key: node.kubernetes.io\/not-ready\r\n    operator: Exists\r\n    tolerationSeconds: 300\r\n  - effect: NoExecute\r\n    key: node.kubernetes.io\/unreachable\r\n    operator: Exists\r\n    tolerationSeconds: 300\r\n  volumes:\r\n  - name: default-token-hzgn6\r\n    secret:\r\n      defaultMode: 420\r\n      secretName: default-token-hzgn6\r\nstatus:\r\n  phase: Pending\r\n  qosClass: BestEffort<\/pre>\n<p>&nbsp;<\/p>\n<p>Zobaczmy jak to wygl\u0105da w naszym przypadku. Wylistujmy wszystkie obiekty kont serwisowych i obiekty secret w przestrzeni nazw default<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">kubectl get sa,secret -n default\r\n<\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">NAME SECRETS AGE\r\nserviceaccount\/default 1 8m17s\r\n\r\nNAME TYPE DATA AGE\r\nsecret\/default-token-hzgn6 kubernetes.io\/service-account-token 3 8m17s<\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">kubectl get sa default -o yaml -n default\r\n<\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">apiVersion: v1\r\nkind: ServiceAccount\r\nmetadata:\r\n  creationTimestamp: \"2021-06-17T19:57:18Z\"\r\n  name: default\r\n  namespace: default\r\n  resourceVersion: \"380\"\r\n  selfLink: \/api\/v1\/namespaces\/default\/serviceaccounts\/default\r\n  uid: 9e41fc13-3d63-4b10-ac6c-f1cd32d2a643\r\nsecrets:\r\n- name: default-token-hzgn6<\/pre>\n<p>&nbsp;<\/p>\n<p>Nazwa obiektu secret dla konta serwisowego jest zawarta w mapie <strong>secrets<\/strong>.<\/p>\n<p>&nbsp;<\/p>\n<p>Wracaj\u0105c do tematu pod\u0142\u0105czania do kontenera wolumenu, to warto zauwa\u017cy\u0107, \u017ce lista volumen\u00f3w jest na poziomie <strong>spec.<\/strong> ca\u0142ego obiektu pod, natomiast pod\u0142\u0105czenie tego wolumenu jest ju\u017c na poziomie kontenera w obiekcie pod, czyli <strong>spec.containers[*]<\/strong>.<\/p>\n<p>Przypominam, i\u017c pod jest obiektem grupuj\u0105cym <strong>wiele<\/strong> kontener\u00f3w i te kontenery umieszczone s\u0105 w tym samej linuksowej przestrzeni nazw, komunikuj\u0105 si\u0119 przez localhost i mog\u0105 dzieli\u0107 ten sam wolumen. Wolumeny maj\u0105 w ramach obiektu pod unikalne nazwy.<\/p>\n<p>Poni\u017cej umie\u015bci\u0142em cz\u0119\u015b\u0107 manifestu na poziomie listy wolumen\u00f3w<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">spec:\r\n# (...)\r\n  volumes:\r\n  - name: default-token-hzgn6\r\n    secret:\r\n      defaultMode: 420\r\n      secretName: default-token-hzgn6\r\n<\/pre>\n<p>Mamy tu do czynienia z jednym elementem listy\u00a0 na poziomie <strong>pod.spec.volumes<\/strong>, gdzie unikaln\u0105 warto\u015bci\u0105 jest name. Dodatkowo widzimy informacj\u0119, o tym, \u017ce \u017ar\u00f3d\u0142em wolumenu jest obiekt secret. Lista takich \u017ar\u00f3de\u0142 jest dosy\u0107 d\u0142uga i zale\u017cy od dostawcy us\u0142ugi magazynowej (storage).<\/p>\n<p>Patrz\u0105c na cz\u0119\u015b\u0107 manifestu na poziomie miejsca pod\u0142\u0105czenia (<strong>volumeMounts<\/strong>)<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">spec:\r\n  containers:\r\n# (...)\r\n    volumeMounts:\r\n    - mountPath: \/var\/run\/secrets\/kubernetes.io\/serviceaccount\r\n      name: default-token-hzgn6\r\n      readOnly: true\r\n<\/pre>\n<p>W tym przypadku na poziomie <strong>pod.spec.containers[*].volumeMounts<\/strong> widzimy t\u0119 sam\u0105 warto\u015b\u0107 <strong>name<\/strong> co wcze\u015bniej i mamy dodany punkt pod\u0142\u0105czenia (<strong>mountPath<\/strong>) w kontenerze. W naszym przypadku jest to katalog wewn\u0105trz kontenera o \u015bcie\u017cce<strong> \/var\/run\/secrets\/kubernetes.io\/serviceaccount<\/strong> z ustawionym dodatkowo znacznikiem trybu tylko do odczytu (<strong>readOnly: true<\/strong>).<\/p>\n<p>&nbsp;<\/p>\n<p>Cz\u0119\u015b\u0107 manifestu obrazuj\u0105cego oba poziomy dotycz\u0105ce wolumen\u00f3w.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">apiVersion: v1\r\nkind: Pod\r\nmetadata:\r\n  labels:\r\n    run: pod\r\n  #  managedfields ommited (...)\r\n  name: pod\r\nspec:\r\n  containers:\r\n# (...)\r\n    volumeMounts:\r\n    - mountPath: \/var\/run\/secrets\/kubernetes.io\/serviceaccount\r\n      name: default-token-hzgn6\r\n      readOnly: true\r\n#  (...)\r\n  volumes:\r\n  - name: default-token-hzgn6\r\n    secret:\r\n      defaultMode: 420\r\n      secretName: default-token-hzgn6\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Jak wygl\u0105da nasz obiekt secret <strong>default-token-hzgn6<\/strong> ?<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">kubectl get secret default-token-hzgn6<\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">NAME                  TYPE                                  DATA   AGE\r\ndefault-token-hzgn6   kubernetes.io\/service-account-token   3      12m<\/pre>\n<p>&nbsp;<\/p>\n<p>Jak wida\u0107 obiekt secret zawiera trzy pary klucz:warto\u015b\u0107<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">kubectl get secret default-token-hzgn6 -o yaml<\/pre>\n<p>Obrobiony manifest wygl\u0105da tak:<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">apiVersion: v1\r\ndata:\r\n  ca.crt: REDACTED\r\n  namespace: ZGVmYXVsdA==\r\n  token: REDACTED\r\n  annotations:\r\n    kubernetes.io\/service-account.name: default\r\n    kubernetes.io\/service-account.uid: 9e41fc13-3d63-4b10-ac6c-f1cd32d2a643\r\n  creationTimestamp: \"2021-06-17T19:57:18Z\"\r\n  # managedFields ommitted \r\n    manager: kube-controller-manager\r\n    operation: Update\r\n    time: \"2021-06-17T19:57:18Z\"\r\n  name: default-token-hzgn6\r\n  namespace: default\r\n  resourceVersion: \"379\"\r\n  selfLink: \/api\/v1\/namespaces\/default\/secrets\/default-token-hzgn6\r\n  uid: 8ed2d192-b058-4147-b811-6e43a7bc2824\r\ntype: kubernetes.io\/service-account-token<\/pre>\n<p>&nbsp;<\/p>\n<p>Dane , kt\u00f3re\u00a0 mo\u017cna przekaza\u0107 do kontenera s\u0105 na poziomie <strong>data.<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">data: \r\n  ca.crt: REDACTED\r\n  namespace: ZGVmYXVsdA==\r\n  token: REDACTED<\/pre>\n<p>&nbsp;<\/p>\n<p>Wdr\u00f3\u017cmy nasz obiekt na klaster<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">kubectl run test --image=nginx:alpine<\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">pod\/test created<\/pre>\n<p>&nbsp;<\/p>\n<p>Spr\u00f3bujmy wej\u015b\u0107 do \u015brodka kontenera w obiekcie o nazwie test. Wykorzystamy do tego polecenie <strong>kubectl exec<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">kubectl exec test -it -- sh<\/pre>\n<p>To co widzimy w \u015brodku naszego kontenera<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\"># zmieniamy katalog\r\n\r\n\/ cd \/var\/run\/secrets\/kubernetes.io\r\n\r\n# listujemy pliki ktore w nim s\u0105\r\n\r\n\/run\/secrets\/kubernetes.io # ls -la\r\ntotal 8\r\ndrwxr-xr-x 3 root root 4096 Jun 17 20:13 .\r\ndrwxr-xr-x 3 root root 4096 Jun 17 20:13 ..\r\ndrwxrwxrwt 3 root root 140 Jun 17 20:12 serviceaccount\r\n\r\n# wyswietlamy zawartosc podkatalogu serviceaccount\r\n\/run\/secrets\/kubernetes.io # ls -la serviceaccount\/\r\ntotal 4\r\ndrwxrwxrwt 3 root root 140 Jun 17 20:12 .\r\ndrwxr-xr-x 3 root root 4096 Jun 17 20:13 ..\r\ndrwxr-xr-x 2 root root 100 Jun 17 20:12 ..2021_06_17_20_12_55.229534384\r\nlrwxrwxrwx 1 root root 31 Jun 17 20:12 ..data -&gt; ..2021_06_17_20_12_55.229534384\r\nlrwxrwxrwx 1 root root 13 Jun 17 20:12 ca.crt -&gt; ..data\/ca.crt\r\nlrwxrwxrwx 1 root root 16 Jun 17 20:12 namespace -&gt; ..data\/namespace\r\nlrwxrwxrwx 1 root root 12 Jun 17 20:12 token -&gt; ..data\/token\r\n\r\n# wyswietlamy zawarto\u015b\u0107 pliku namespace\r\n\r\n\/run\/secrets\/kubernetes.io # cat serviceaccount\/namespace \r\n\r\ndefault<\/pre>\n<p>Mamy plik manifestu w obiekcie typu secret zawieraj\u0105cy trzy pary klucz:warto\u015b\u0107. W prosty spos\u00f3b mo\u017cemy pod\u0142\u0105czy\u0107 te dane jako trzy osobne pliki. Takie pliki traktowane s\u0105 przez system plikowy kontenera w trybie do odczytu. Co wi\u0119cej zmiana obiektu secret powoduje automatyczn\u0105 zmian\u0119 pod\u0142\u0105czonego pliku (dla danej pary klucz: warto\u015b\u0107) bez restartu obiektu pod.<\/p>\n<p>Uwa\u017cna osoba zada na pewno pytanie, po co montujemy niejako w tle takie rzeczy. Ot\u00f3\u017c obiekt pod uruchomiony na klastrze Kubernetes ma dost\u0119p do Kubernetes API. Uprawnienia z jakimi ma do tego API dost\u0119p wynikaj\u0105 z uprawnie\u0144 jakie ma\u00a0 konto serwisowe (w naszym przypadku o nazwie default)\u00a0 w zadanej przestrzeni nazw.\u00a0 Nie jest to zagadnienie zakresu egzaminacyjnego, ale warto wiedzie\u0107, \u017ce je\u015bli nie potrzebujemy dost\u0119pu do API Kubernetes, to mo\u017cemy zablokowa\u0107 pod\u0142\u0105czenie danych zwi\u0105zanych z obiektem secret stowarzyszonym z danym kontem serwisowym (<strong>serviceaccount<\/strong>). Warto dok\u0142adniej poczyta\u0107 o <strong>RBAC<\/strong>.<\/p>\n<p><a href=\"https:\/\/kubernetes.io\/docs\/reference\/access-authn-authz\/rbac\/\" target=\"_blank\" rel=\"noopener\">https:\/\/kubernetes.io\/docs\/reference\/access-authn-authz\/rbac\/<\/a><\/p>\n<p>&nbsp;<\/p>\n<p>Mamy do dyspozycji dwie metody, kt\u00f3re zablokuj\u0105 dost\u0119p do API Kubernetes:<\/p>\n<p>&nbsp;<\/p>\n<p>Mo\u017cna\u00a0 wy\u0142\u0105czy\u0107 dla danego konta mo\u017cliwo\u015b\u0107 korzystania z API Kubernetes dodaj\u0105c do manifestu\u00a0 <strong>automountServiceAccountToken: false<\/strong><\/p>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">apiVersion: v1\r\nkind: ServiceAccount\r\nmetadata:\r\n  name: no-token-please\r\n  namespace: default\r\nautomountServiceAccountToken: false<\/pre>\n<p>&nbsp;<\/p>\n<p>Mo\u017cna te\u017c w definicji np. obiektu typu pod przy definicji konta serwisowego poprosi\u0107 o niepod\u0142\u0105czanie do API dodaj\u0105c <strong>automountServiceAccountToken: false<\/strong><\/p>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">apiVersion: v1\r\nkind: Pod\r\nmetadata:\r\n  name: my-pod\r\nspec:\r\n  serviceAccountName: yes-token-please\r\n  automountServiceAccountToken: false<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p><em>Zniecierpliwiona osoba, zacznie si\u0119 pyta\u0107, po co tyle opowie\u015bci o korzystaniu z API i pod\u0142\u0105czaniu plik\u00f3w do kontenera. Niniejszy wpis nie jest cz\u0119\u015bci\u0105 jakiego\u015b kursu Kubernetes, kt\u00f3rych jest ju\u017c du\u017co i w kt\u00f3rych mo\u017cna znale\u017a\u0107 wi\u0119cej informacji. Jest to pr\u00f3ba pomocy dla os\u00f3b, kt\u00f3re przygotowuj\u0105 si\u0119 do certyfikacji CKA, ale jednocze\u015bnie nie chcia\u0142bym, aby by\u0142 to jedynie spis gotowych rozwi\u0105za\u0144, kt\u00f3re co prawda pozwol\u0105 wyrobi\u0107 sobie manualn\u0105 sprawno\u015b\u0107, ale niewiele wi\u0119cej.<\/em><\/p>\n<p>&nbsp;<\/p>\n<p>W jaki spos\u00f3b Kubernetes jest w stanie zapewni\u0107 nam przechowanie danych pomimo restartu kontenera ?<\/p>\n<p>Dotarli\u015bmy do pocz\u0105tku naszej opowie\u015bci.\u00a0 Przypomn\u0119 obrazek z jednej z poprzednich cz\u0119\u015bci<\/p>\n<p>&nbsp;<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-full wp-image-1471\" src=\"https:\/\/wchmurze.cloud\/wp-content\/uploads\/2021\/05\/kubernetes-secret-configmap.png\" alt=\"\" width=\"1360\" height=\"346\" srcset=\"https:\/\/wchmurze.cloud\/wp-content\/uploads\/2021\/05\/kubernetes-secret-configmap.png 1360w, https:\/\/wchmurze.cloud\/wp-content\/uploads\/2021\/05\/kubernetes-secret-configmap-300x76.png 300w, https:\/\/wchmurze.cloud\/wp-content\/uploads\/2021\/05\/kubernetes-secret-configmap-1024x261.png 1024w, https:\/\/wchmurze.cloud\/wp-content\/uploads\/2021\/05\/kubernetes-secret-configmap-768x195.png 768w\" sizes=\"(max-width: 1360px) 100vw, 1360px\" \/><\/p>\n<p>Tym razem zajmiemy si\u0119 cz\u0119\u015bci\u0105 praw\u0105 (zielon\u0105) zar\u00f3wno dla obiektu <strong>configmap<\/strong> jak i dla obiektu <strong>secret, <\/strong>z tym, \u017ce dla obiektu <strong>secret<\/strong> zamiast <strong>mapy configMap<\/strong> b\u0119dzie mapa <strong>secret. <\/strong><\/p>\n<div><\/div>\n<div>Kubernetes obs\u0142uguje ponad 20 typ\u00f3w wolumen\u00f3w, nie ma sensu uczy\u0107 si\u0119 ich na pami\u0119\u0107.<\/div>\n<div><\/div>\n<div>\n<p><a href=\"https:\/\/kubernetes.io\/docs\/concepts\/storage\/volumes\/\">Kubernetes Volume Types<\/a><\/p>\n<p>&nbsp;<\/p>\n<\/div>\n<h4><\/h4>\n<h4>Wolumeny ulotne<\/h4>\n<p>&nbsp;<\/p>\n<div>\n<h5>EmptyDir<\/h5>\n<p>Wolumen typu <strong>emptyDir<\/strong> jest tworzony w momencie, gdy na danym w\u0119\u017ale pojawia si\u0119 obiekt pod po raz pierwszy. Wolumen ten istnieje tak d\u0142ugo jak obiekt pod na danym w\u0119\u017ale. Zgodnie z nazw\u0105 pocz\u0105tkowy stan jest pusty. Wszystkie kontenery w danym obiekcie pod mog\u0105 czyta\u0107 i pisa\u0107 do tego samego wolumenu. Kiedy pod jest zrestartowany lub usuni\u0119ty dane w tego typu wolumenie s\u0105 tracone.<\/p>\n<p>Jakie\u00a0 jest g\u0142\u00f3wne zastosowanie?<\/p>\n<\/div>\n<ul>\n<li>cache<\/li>\n<li>d\u0142ugotrwa\u0142e obliczenia, kt\u00f3re musz\u0105 by\u0107 wykonane w pami\u0119ci<\/li>\n<li>dane tymczasowe na przyk\u0142ad podczas sortowania<\/li>\n<\/ul>\n<div>Przyk\u0142adowy manifest wykorzystuj\u0105cy <strong>emptyDir<\/strong><\/div>\n<div>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">apiVersion: v1\r\nkind: Pod\r\nmetadata:\r\n  name: my-pod\r\nspec:\r\n  containers:\r\n  - image: my-app-image\r\n    name: my-app\r\n    volumeMounts:\r\n    - mountPath: \/cache\r\n      name: cache-volume\r\n  volumes:\r\n    - name: cache-volume\r\n      emptyDir: {}\r\n<\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\"><\/div>\n<\/div>\n<\/div>\n<div class=\"highlight js-code-highlight\">\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">Uwaga: Tego typu wolumen\u00f3w nie nale\u017cy u\u017cywa\u0107 do zapisu trwa\u0142ych zmian.<\/div>\n<\/div>\n<\/div>\n<p>&nbsp;<\/p>\n<h5>HostPath<\/h5>\n<p>Wolumen typu <strong>hostPath<\/strong> pozwala na pod\u0142\u0105czenie pliku lub katalogu znajduj\u0105cego si\u0119 na w\u0119\u017ale, na kt\u00f3rym zosta\u0142 uruchomiony pod. Mo\u017cna ustali\u0107, czy plik lub katalog musi wcze\u015bniej istnie\u0107, czy te\u017c ma by\u0107 utworzony podczas startu obiektu pod.<\/p>\n<div class=\"highlight js-code-highlight\">\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\"><\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<p><code>type: Directory<\/code> oznacza, \u017ce katalog o tej nazwie musi istnie\u0107 na w\u0119\u017ale. Nale\u017cy go utworzy\u0107 wcze\u015bniej,<\/p>\n<p><code>type: DirectoryOrCreate<\/code> oznacza, \u017ce katalog o tej\u00a0 nazwie zostanie utworzony je\u015bli nie istnieje na w\u0119\u017ale,<\/p>\n<p><code>type: File<\/code> oznacza, \u017ce plik o tej nazwie musi istnie\u0107 na w\u0119\u017ale. Nale\u017cy go utworzy\u0107 wcze\u015bniej,<\/p>\n<p><code>type: FileOrCreate<\/code> oznacza, \u017ce plik o tej\u00a0 nazwie zostanie utworzony je\u015bli nie istnieje na w\u0119\u017ale,<\/p>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Jakie\u00a0 jest g\u0142\u00f3wne zastosowanie?<\/p>\n<p>Uruchamianie kontener\u00f3w, kt\u00f3re wymagaj\u0105 dost\u0119pu do wewn\u0119trznych mechanizm\u00f3w Docker. Mo\u017cna wykorzysta\u0107 \u015bcie\u017ck\u0119 hostPath <code>\/var\/lib\/docker<\/code><\/p>\n<p>Uruchamianie wewn\u0105trz kontenera cAdvisor Mo\u017cna wykorzysta\u0107 \u015bcie\u017ck\u0119 hostPath <code>\/sys<\/code><\/p>\n<div>\n<p>Wady tego typu rozwi\u0105zania:<\/p>\n<ul>\n<li>Obiekty pod utworzone z tego samego szablonu mog\u0105 si\u0119 r\u00f3\u017cnie zachowywa\u0107 na r\u00f3\u017cnych w\u0119z\u0142ach w zale\u017cno\u015bci od zawarto\u015bci scie\u017cki hostPath<\/li>\n<li>Pliki i katalogi tworzone z hostPath na poziomie w\u0119z\u0142a s\u0105 zapisywalne tylko z uprawnieniami u\u017cytkownika root. Czyli albo musimy uruchamia\u0107 takie obiekty z uprawnieniami root, albo modyfikowa\u0107 uprawnienia do plik\u00f3w\/katalog\u00f3w na poziomie hosta. Oba przypadki prowadz\u0105 do problem\u00f3w z bezpiecze\u0144stwem i powinny by\u0107 stosowane w bardzo uzasadnionych przypadkach.<\/li>\n<li>Je\u017celi obiekt pod jest cz\u0119\u015bci\u0105 obiektu StatefulSet nie mo\u017ce korzysta\u0107 z hostPath.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<\/div>\n<p>Przyk\u0142adowy manifest wykorzystuj\u0105cy <strong>hostPath<\/strong><\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">apiVersion: v1\r\nkind: Pod\r\nmetadata:\r\n  name: my-pod\r\nspec:\r\n  containers:\r\n  - image: my-app-image\r\n    name: my-app\r\n    volumeMounts:\r\n      - mountPath: \/test-pd\r\n        name: test-volume\r\n  volumes:\r\n  - name: test-volume \r\n    hostPath:\r\n    path: \/data  #directory on host\r\n    type: Directory #optional<\/pre>\n<\/div>\n<h4><\/h4>\n<h4>Wolumeny trwa\u0142e<\/h4>\n<p>&nbsp;<\/p>\n<p>Najpopularniejsze typy wolumen\u00f3w, z kt\u00f3rymi mo\u017cna si\u0119 spotka\u0107<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li><strong>configMap:<\/strong>\u00a0 Mo\u017cliwo\u015b\u0107 pod\u0142\u0105czenia plik\u00f3w zawieraj\u0105cych dane niewra\u017cliwe na podstawie zawarto\u015bci obiektu typu <strong>configMap<\/strong><\/li>\n<li><strong>secret: <\/strong>Mo\u017cliwo\u015b\u0107 pod\u0142\u0105czenia plik\u00f3w zawieraj\u0105cych dane wra\u017cliwe na podstawie zawarto\u015bci obiektu typu <strong>secret<\/strong><\/li>\n<li><strong>persistentVolumeClaim: <\/strong>Mo\u017cliwo\u015b\u0107 pod\u0142\u0105czenia obiektu typu <strong>persistentVolume<\/strong> do obiektu typu pod za pomoc\u0105 obiektu\u00a0 <strong>persistentVolumeClaim<\/strong><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>Um\u00f3wmy ten ostatni typu wolumenu.<\/p>\n<p>&nbsp;<\/p>\n<h5><\/h5>\n<h5><span style=\"color: #000000;\"><b><span style=\"font-size: x-large;\">Persistent Volumes<\/span><\/b><\/span><\/h5>\n<div>\n<p>&nbsp;<\/p>\n<p>Obiekty <strong>PersistentVolume (PV)<\/strong> mog\u0105 powstawa\u0107 statycznie na podstawie manifest\u00f3w wdra\u017canym na klaster przez jego administratora lub dynamicznie na podstawie wskazania obiektu StorageClass. Obiekty <strong>StorageClass (SC)<\/strong> zawiera predefiniowan\u0105 konfiguracj\u0119 dostarczyciela (provider) i parametry, na podstawie kt\u00f3rych ma powsta\u0107 obiekt PersistentVolume. Obiekty te maja zasi\u0119g w ca\u0142ym klastrze i nie s\u0105 umieszczane w przestrzeni nazw.<\/p>\n<p>&nbsp;<\/p>\n<\/div>\n<p>Obiekt <strong>PersistemVolumeClaim<\/strong> (PVC) jest \u017c\u0105daniem pod\u0142\u0105czenia dysku przez uzytkownika, kt\u00f3ry prosi o obiekt typu <strong>PersistentVolume<\/strong> na podstawie wielko\u015bci, trybu dost\u0119pu do danych, itp. Je\u017celi znajdzie si\u0119 wolny wolumen PV to zostanie on dowi\u0105zany (<strong>bound<\/strong>) do obiektu PVC. Obiekt PV nie jest bezpo\u015brednio powi\u0105zany z obiektem typu pod, ale wykorzystuje jako po\u015brednika obiekty typu PVC. Obiekty PVC w przeciwie\u0144stwie do VP s\u0105 umieszczane w przestrzeni nazw.<\/p>\n<div>\n<div>\n<p>&nbsp;<\/p>\n<p><strong>PersistentVolume<\/strong> mo\u017ce mie\u0107 nast\u0119puj\u0105ce tryby dost\u0119pu do danych (access mode) :<\/p>\n<\/div>\n<\/div>\n<div>\n<ul>\n<li>ReadWriteOnce \u2013\u00a0 wolumen mo\u017ce by\u0107 pod\u0142\u0105czony w trybie zapisu (read-write) tylko przez jeden obiekt<\/li>\n<li>ReadOnlyMany \u2013\u00a0 wolumen mo\u017ce by\u0107 pod\u0142\u0105czony w trybie odczytu (read-only) przez wiele obiekt\u00f3w<\/li>\n<li>ReadWriteMany \u2013 wolumen mo\u017ce by\u0107 pod\u0142\u0105czony w trybie zapisu (read-write) przez wiele obiekt\u00f3w<\/li>\n<\/ul>\n<p>Tryby te s\u0105 podczas korzystania z <strong>kubectl<\/strong> skracane do<\/p>\n<ul>\n<li><strong>RWO<\/strong> &#8211; ReadWriteOnce<\/li>\n<li><strong>ROX<\/strong> &#8211; ReadOnlyMany<\/li>\n<li><strong>RWX<\/strong> &#8211; ReadWriteMany<\/li>\n<\/ul>\n<\/div>\n<div><\/div>\n<div><\/div>\n<div><\/div>\n<div><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-88667 defer-loaded\" src=\"https:\/\/phoenixnap.com\/kb\/wp-content\/uploads\/2021\/04\/graphic-of-persistent-volume-bond.png\" alt=\"A graphic showing how pods connect to persistent volumes and external physical storage.\" width=\"703\" height=\"265\" data-src=\"https:\/\/phoenixnap.com\/kb\/wp-content\/uploads\/2021\/04\/graphic-of-persistent-volume-bond.png\" \/><\/div>\n<div>Powy\u017cszy obraz pokazuje w uproszczony spos\u00f3b powi\u0105zanie obiekt\u00f3w typu pod, persistentVolumeClaim i PersistentVolume.<\/div>\n<div><\/div>\n<div><\/div>\n<div><\/div>\n<div>Zabierzmy si\u0119 za \u0107wiczenia.<\/div>\n<div><\/div>\n<div><\/div>\n<div><\/div>\n<h3>\u0106wiczenia<\/h3>\n<p>&nbsp;<\/p>\n<h4>Zadanie pierwsze<\/h4>\n<p>&nbsp;<\/p>\n<p>Utw\u00f3rz obiekt typu pod o nazwie\u00a0 <strong>secret-test<\/strong> zawieraj\u0105cy obraz <strong>nginx:latest<\/strong> pracuj\u0105cy na porcie <strong>80<\/strong> .<\/p>\n<p>W kontenerze nale\u017cy pod\u0142\u0105czy\u0107 obiekt secret o nazwie <strong>test-secret<\/strong> w katalogu <strong>\/etc\/secret-volume<\/strong>. Nazwa wolumenu to <strong>secret-volume<\/strong><\/p>\n<p>Umie\u015b\u0107 go w przestrzeni nazw <strong>delta. <\/strong>Je\u017celi przestrze\u0144 nazw nie istnieje nale\u017cy j\u0105 utworzy\u0107.<\/p>\n<p>&nbsp;<\/p>\n<p>Manifest tworz\u0105cy obiekt secret wygl\u0105da tak:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">apiVersion: v1\r\nkind: Secret\r\nmetadata:\r\n  name: test-secret\r\n  namespace: delta\r\ndata:\r\n  username: bXktYXBw\r\n  password: Mzk1MjgkdmRnN0pi\r\n<\/pre>\n<p>Obiekt\u00a0 mo\u017cna wdro\u017cy\u0107 na klaster m.in w ten spos\u00f3b:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">cat\u00a0&lt;&lt;EOF\u00a0|\u00a0kubectl\u00a0apply\u00a0-f\u00a0-\r\napiVersion: v1\r\nkind: Secret\r\nmetadata:\r\n  name: test-secret\r\n  namespace: delta\r\ndata:\r\n  username: bXktYXBw\r\n  password: Mzk1MjgkdmRnN0pi\r\nEOF\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>To od czego powinni\u015bmy zacz\u0105\u0107 to przygotowanie manifestu obiektu pod. Robili\u015bmy to ju\u017c wiele razy<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">kubectl run secret-test --image=nginx:latest --port=80 --dry-run=client -o yaml &gt; 01.pod.secret-test.yaml\r\n\r\n<\/pre>\n<p>W pliku dodajemy brakuj\u0105c\u0105 przestrze\u0144 nazwa delta i usuwamy zb\u0119dne dane. Manifest powinien wygl\u0105da\u0107 tak:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">apiVersion: v1\r\nkind: Pod\r\nmetadata:\r\n  labels:\r\n    run: secret-test\r\n  name: secret-test\r\n  namespace: delta\r\nspec:\r\n  containers:\r\n  - image: nginx:latest\r\n    name: secret-test\r\n    ports:\r\n    - containerPort: 80\r\n  dnsPolicy: ClusterFirst\r\n  restartPolicy: Always\r\n<\/pre>\n<p>Teraz zabieramy si\u0119 za brakuj\u0105cy wolumen<\/p>\n<p>Dodajemy go w dw\u00f3ch miejscach:<\/p>\n<ul>\n<li>na poziomie specyfikacji ca\u0142ego obiektu pod<\/li>\n<\/ul>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">apiVersion: v1\r\nkind: Pod\r\nmetadata:\r\n  name: secret-test\r\n  namespace: delta\r\nspec:\r\n # (...)\r\n  volumes:\r\n  - name: secret-volume\r\n    secret:\r\n      secretName: test-secre<\/pre>\n<p>Tutaj zawsze b\u0119dziemy mieli do czynienia z list\u0105 wewn\u0105trz <strong>volumes<\/strong>.<\/p>\n<ol>\n<li><strong>name<\/strong> (nazwa jest unikalna w obr\u0119bie obiektu pod)<\/li>\n<li>typ wolumenu (w naszym przypadku jest to <strong>secret<\/strong>), a potem w zale\u017cno\u015bci od typu wolumenu wewn\u0119trzne mapy. W naszym przypadku jest to <strong>secretName<\/strong> wskazuj\u0105cy na nazw\u0119 obiektu <strong>secret<\/strong>.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<ul>\n<li>na poziomie specyfikacji kontenera w obiekcie pod<\/li>\n<\/ul>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">apiVersion: v1\r\nkind: Pod\r\nmetadata:\r\n  name: secret-test\r\n  namespace: delta\r\nspec:\r\n  containers:\r\n    - name: test-container\r\n   # (...)\r\n      volumeMounts:\r\n      - name: secret-volume\r\n        mountPath: \/etc\/secret-volume\r\n<\/pre>\n<p>Tutaj zawsze b\u0119dziemy mie\u0107 do czynienia z list\u0105 wewn\u0105trz <strong>volumeMounts<\/strong>:<\/p>\n<ol>\n<li><strong>name<\/strong> (nazwa jest unikalna w obr\u0119bie obiektu pod), kt\u00f3ry musi by\u0107 wyszczegolniony na poziomie <strong>spec.volumes<\/strong>. Wi\u0105zane wolumenu z punktem pod\u0142\u0105czenia jest na podstawie nazwy tego wolumenu.<\/li>\n<li><strong>mountPath<\/strong> ( wskazuje miejsce, w kt\u00f3rym zostanie pod\u0142\u0105czony nasz wokumen w kontenerze)<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<p>Po uwzgl\u0119dnieniu obu cz\u0119\u015bci nasz manifest powinien wygl\u0105da\u0107 tak:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">apiVersion: v1\r\nkind: Pod\r\nmetadata:\r\n  name: secret-test\r\n  namespace: delta\r\nspec:\r\n  containers:\r\n    - name: test-container\r\n      image: nginx:latest\r\n      ports: \r\n      - containerPort: 80\r\n      volumeMounts:\r\n      - name: secret-volume\r\n        mountPath: \/etc\/secret-volume\r\n  volumes:\r\n  - name: secret-volume\r\n    secret:\r\n      secretName: test-secret<\/pre>\n<p>&nbsp;<\/p>\n<p>Wdra\u017camy obiekt na klaster<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">kubectl apply -f 01.pod.secret-test.yaml \r\n<\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">pod\/secret-test created<\/pre>\n<p>&nbsp;<\/p>\n<h4>Zadanie drugie<\/h4>\n<p>&nbsp;<\/p>\n<p>Utw\u00f3rz obiekt typu pod o nazwie\u00a0 <strong>configmap-test<\/strong> zawieraj\u0105cy obraz <strong>nginx:latest<\/strong> pracuj\u0105cy na porcie <strong>80<\/strong> .<\/p>\n<p>W kontenerze nale\u017cy pod\u0142\u0105czy\u0107 obiekt configmap o nazwie <strong>test-configmap<\/strong> w katalogu <strong>\/etc\/configmap<\/strong>. Nazwa wolumenu to <strong>configmap-volume<\/strong><\/p>\n<p>Umie\u015b\u0107 go w przestrzeni nazw <strong>delta. <\/strong>Je\u017celi przestrze\u0144 nazw nie istnieje nale\u017cy j\u0105 utworzy\u0107.<\/p>\n<p>&nbsp;<\/p>\n<p>Manifest tworz\u0105cy obiekt configmap wygl\u0105da tak:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">apiVersion: v1\r\nkind: ConfigMap\r\nmetadata:\r\n  name: test-configmap\r\n  namespace: delta\r\ndata:\r\n  SPECIAL_LEVEL: very\r\n  SPECIAL_TYPE: charm\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Tak jak poprzednio obiekt mo\u017cna wdro\u017cy\u0107 na klaster za pomoc\u0105 <strong>kubectl apply -f &#8211;<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">cat\u00a0&lt;&lt;EOF\u00a0|\u00a0kubectl\u00a0apply\u00a0-f\u00a0-\r\napiVersion: v1\r\nkind: ConfigMap\r\nmetadata:\r\n  name: test-configmap\r\n  namespace: delta\r\ndata:\r\n  SPECIAL_LEVEL: very\r\n  SPECIAL_TYPE: charm\r\nEOF<\/pre>\n<p>Standardowo zaczynamy od wygenerowania bazowego obiektu pod<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">kubectl run configmap-test --image=nginx:latest --port=80 --dry-run=client -o yaml &gt; 02.pod.configmap-test.yaml<\/pre>\n<p>&nbsp;<\/p>\n<p>Po podaniu cz\u0119\u015bci zwi\u0105zanych z wolumenem pochodz\u0105cym z obiektu configmap manifest powinien wygl\u0105da\u0107 tak:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">apiVersion: v1\r\nkind: Pod\r\nmetadata:\r\n  labels:\r\n    run: configmap-test\r\n  name: configmap-test\r\n  namespace: delta\r\nspec:\r\n  containers:\r\n  - image: nginx:latest\r\n    name: configmap-test\r\n    ports:\r\n    - containerPort: 80\r\n    volumeMounts:\r\n    - name: configmap-volume\r\n      mountPath: \/etc\/configmap\r\n  volumes:\r\n  - name: configmap-volume \r\n    configMap: \r\n      name: test-configmap<\/pre>\n<p>&nbsp;<\/p>\n<p>Wdra\u017camy obiekt na klaster<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">kubectl apply -f 02.pod.configmap-test.yaml\r\n<\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">pod\/configmap-test created<\/pre>\n<p>Zobaczmy co mo\u017cemy zobaczy\u0107 w \u015brodku kontenera za pomoc\u0105 polecenia <strong>kubectl exec<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">kubectl exec configmap-test -n delta -it -- bash\r\n<\/pre>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">root@configmap-test:\/# ls -la \/etc\/configmap\/\r\ntotal 12\r\ndrwxrwxrwx 3 root root 4096 Jun 20 11:59 .\r\ndrwxr-xr-x 1 root root 4096 Jun 20 11:59 ..\r\ndrwxr-xr-x 2 root root 4096 Jun 20 11:59 ..2021_06_20_11_59_16.816891944\r\nlrwxrwxrwx 1 root root   31 Jun 20 11:59 ..data -&gt; ..2021_06_20_11_59_16.816891944\r\nlrwxrwxrwx 1 root root   20 Jun 20 11:59 SPECIAL_LEVEL -&gt; ..data\/SPECIAL_LEVEL\r\nlrwxrwxrwx 1 root root   19 Jun 20 11:59 SPECIAL_TYPE -&gt; ..data\/SPECIAL_TYPE\r\nroot@configmap-test:\/# cat \/etc\/configmap\/SPECIAL_LEVEL \r\nvery\r\n\r\nroot@configmap-test:\/# cat \/etc\/configmap\/SPECIAL_TYPE\r\ncharm<\/pre>\n<p>&nbsp;<\/p>\n<p>Po wykonaniu polecenia\u00a0 <code>ls \/etc\/configmap\/<\/code><\/p>\n<p>Otrzymamy w\u00f3wczas list\u0119 plik\u00f3w<\/p>\n<div class=\"highlight\">\n<pre><code class=\"language-shell\" data-lang=\"shell\">SPECIAL_LEVEL SPECIAL_TYPE\r\n<\/code><\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Jak wida\u0107 s\u0105 to nazwy kluczy\u00a0 z obiektu configmap o nazwie test-configmap. A zawarto\u015bci\u0105 ka\u017cdego z tych plik\u00f3w jest warto\u015b\u0107 zwi\u0105zana z danym kluczem.<\/p>\n<p>&nbsp;<\/p>\n<p>Uwa\u017cna osoba zauwa\u017cy pewn\u0105 niekonsekwencj\u0119 nazewnictwa p\u00f3l.<\/p>\n<p>W jednym przypadku u\u017cyli\u015bmy <strong>name<\/strong> (dla obiektu <strong>configMap<\/strong>) a w drugim <strong>secretName<\/strong> (dla obiektu <strong>secret<\/strong>).<\/p>\n<p>W razie w\u0105tpliwo\u015bci mo\u017cna skorzysta\u0107 z wbudowanej pomocy<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">kubectl explain pod.spec.volumes.secret --recursive<\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">KIND:     Pod\r\nVERSION:  v1\r\n\r\nRESOURCE: secret &lt;Object&gt;\r\n\r\nDESCRIPTION:\r\n     Secret represents a secret that should populate this volume. More info:\r\n     https:\/\/kubernetes.io\/docs\/concepts\/storage\/volumes#secret\r\n\r\n     Adapts a Secret into a volume. The contents of the target Secret's Data\r\n     field will be presented in a volume as files using the keys in the Data\r\n     field as the file names. Secret volumes support ownership management and\r\n     SELinux relabeling.\r\n\r\nFIELDS:\r\n   defaultMode  &lt;integer&gt;\r\n   items        &lt;[]Object&gt;\r\n      key       &lt;string&gt;\r\n      mode      &lt;integer&gt;\r\n      path      &lt;string&gt;\r\n   optional     &lt;boolean&gt;\r\n   secretName   &lt;string&gt;<\/pre>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">kubectl explain pod.spec.volumes.configMap --recursive<\/pre>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">KIND:     Pod\r\nVERSION:  v1\r\n\r\nRESOURCE: configMap &lt;Object&gt;\r\n\r\nDESCRIPTION:\r\n     ConfigMap represents a configMap that should populate this volume\r\n\r\n     Adapts a ConfigMap into a volume. The contents of the target ConfigMap's\r\n     Data field will be presented in a volume as files using the keys in the\r\n     Data field as the file names, unless the items element is populated with\r\n     specific mappings of keys to paths. ConfigMap volumes support ownership\r\n     management and SELinux relabeling.\r\n\r\nFIELDS:\r\n   defaultMode  &lt;integer&gt;\r\n   items        &lt;[]Object&gt;\r\n      key       &lt;string&gt;\r\n      mode      &lt;integer&gt;\r\n      path      &lt;string&gt;\r\n   name &lt;string&gt;\r\n   optional     &lt;boolean&gt;<\/pre>\n<p>&nbsp;<\/p>\n<p>Nie uczymy si\u0119 na pami\u0119\u0107. Wbudowana w narz\u0119dzie kubectl pomoc mo\u017ce nam znacznie u\u0142atwi\u0107 prac\u0119.<\/p>\n<p>&nbsp;<\/p>\n<h4>Zadanie trzecie<\/h4>\n<p>&nbsp;<\/p>\n<p>Utw\u00f3rz obiekt typu pod o nazwie\u00a0 <strong>configmap-test-key<\/strong> zawieraj\u0105cy obraz <strong>nginx:latest<\/strong> pracuj\u0105cy na porcie <strong>80<\/strong> .<\/p>\n<p>W kontenerze nale\u017cy pod\u0142\u0105czy\u0107 obiekt configmap o nazwie <strong>test-configmap<\/strong> w katalogu <strong>\/etc\/configmap<\/strong>, z tego obiektu nale\u017cy wykorzysta\u0107 jedynie klucz <strong>SPECIAL_LEVEL, kt\u00f3ry powinien by\u0107 umiezczony w\u00a0<\/strong> Nazwa wolumenu to <strong>configmap-volume-key<\/strong><\/p>\n<p>Umie\u015b\u0107 go w przestrzeni nazw <strong>delta. <\/strong>Je\u017celi przestrze\u0144 nazw nie istnieje nale\u017cy j\u0105 utworzy\u0107.<\/p>\n<p>&nbsp;<\/p>\n<p>Zadanie wygl\u0105da na bardzo podobne do poprzedniego. Zacznijmy od skopiowania manifestu<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">cp 02.pod.configmap-test.yaml 03.pod.configmap-test-key.yaml<\/pre>\n<p>&nbsp;<\/p>\n<p>Podczas edycji pliku nale\u017cy zmieni\u0107 nazw\u0119 obiektu pod, nazw\u0119 wskazanego obiektu configmap.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">apiVersion: v1\r\nkind: Pod\r\nmetadata:\r\n  labels:\u00a0\r\n    run: configmap-test-key \r\n  name: configmap-test-key\r\n  namespace: delta\r\nspec:\r\n  containers:\r\n    - name: configmap-test-key\r\n      image: nginx:latest\r\n      volumeMounts:\r\n      - name: configmap-volume-key\r\n        mountPath: \/etc\/configmap\r\n  volumes:\r\n    - name: configmap-volume-key\r\n      configMap:\r\n        name: test-configmap\r\n        items:\r\n        - key: SPECIAL_LEVEL\r\n          path: keys\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Podczas edycji pliku nale\u017cy zmieni\u0107 nazw\u0119 obiektu pod, nazw\u0119 wskazanego obiektu configmap.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">spec:\r\n # (...)\r\n  volumes:\r\n    - name: configmap-volume-key\r\n      configMap:\r\n        name: test-configmap\r\n        items:\r\n        - key: SPECIAL_LEVEL\r\n          path: keys<\/pre>\n<p>Poniewa\u017c nie chcemy korzysta\u0107 z ca\u0142o\u015bci danych zawartych w obiekcie configmap w naszej definicji wolumenu pojawi\u0142y si\u0119 dodatkowe elementy listy.\u00a0 Dane warto\u015bci klucza o nazwie <strong>SPECIAL_KEY<\/strong> zostan\u0105 umieszczone w pliku o nazwie keys, kt\u00f3ry zostanie umieszczony w katalogu\u00a0 mountPath: \/etc\/configmap.<\/p>\n<p><a href=\"https:\/\/kubernetes.io\/docs\/tasks\/configure-pod-container\/configure-pod-configmap\/\" target=\"_blank\" rel=\"noopener\">https:\/\/kubernetes.io\/docs\/tasks\/configure-pod-container\/configure-pod-configmap\/<\/a><\/p>\n<p>&nbsp;<\/p>\n<p>Wdra\u017camy obiekt na klaster<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">kubectl apply -f 01.pod.secret-test.yaml \r\n<\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">pod\/secret-test created<code><\/code><\/pre>\n<p>Zobaczmy co mo\u017cemy zobaczy\u0107 wean\u0105trz kontenera:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">kubectl exec configmap-test-key -n delta -it -- sh<\/pre>\n<p>W \u015brodku kontenera proponuj\u0119 wykona\u0107 polecenie <code>cat \/etc\/configmap\/keys<\/code><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">ls -la \/etc\/configmap\/\r\ntotal 12\r\ndrwxrwxrwx 3 root root 4096 Jun 20 11:53 .\r\ndrwxr-xr-x 1 root root 4096 Jun 20 11:53 ..\r\ndrwxr-xr-x 2 root root 4096 Jun 20 11:53 ..2021_06_20_11_53_34.366829492\r\nlrwxrwxrwx 1 root root   31 Jun 20 11:53 ..data -&gt; ..2021_06_20_11_53_34.366829492\r\nlrwxrwxrwx 1 root root   11 Jun 20 11:53 keys -&gt; ..data\/keys\r\n\r\nroot@configmap-test-key:\/# cat \/etc\/configmap\/keys \r\nvery<\/pre>\n<p>otrzymamy w\u00f3wczas zawarto\u015b\u0107 tego pliku:<\/p>\n<div class=\"highlight\">\n<pre><code class=\"language-shell\" data-lang=\"shell\">very\r\n<\/code><\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Jak wida\u0107, w \u015brodku wskazanej do podmontowania \u015bcie\u017cki pojawi\u0142 si\u0119 plik o nazwie <strong>keys<\/strong> zawieraj\u0105cy warto\u015b\u0107 klucza <strong>SPECIAL_KEY<\/strong>.<\/p>\n<p>&nbsp;<\/p>\n<p>Nast\u0119pne zadanie jest na rozgrzewk\u0119.<\/p>\n<p>&nbsp;<\/p>\n<h4>Zadanie\u00a0 czwarte<\/h4>\n<p>&nbsp;<\/p>\n<p>Utw\u00f3rz obiekt typu pod o nazwie\u00a0 <strong>pod-webapp<\/strong> zawieraj\u0105cy obraz <strong>nginx:latest<\/strong> pracuj\u0105cy na porcie <strong>80<\/strong> . Umie\u015b\u0107 go w przestrzeni nazw <strong>delta. <\/strong>Je\u017celi przestrze\u0144 nazw nie istnieje nale\u017cy j\u0105 utworzy\u0107.<\/p>\n<div><\/div>\n<div><\/div>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">kubectl run webapp --image=nginx --port=80 --dry-run=client -o yaml &gt; 04.pod.pod-webapp.yaml<\/pre>\n<\/div>\n<p>Masz manifest powinien wygl\u0105da\u0107 mniej wiecej tak. Pami\u0119tajmy o dodawaniu przestrzeni nazw, w tym przypadku <strong>delta<\/strong>.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">apiVersion: v1\r\nkind: Pod\r\nmetadata:\r\n  labels:\r\n    run: pod-webapp\r\n  name: pod-webapp\r\n  namespace: gamma\r\nspec:\r\n  containers:\r\n  - image: nginx\r\n    name: webapp\r\n    ports:\r\n    - containerPort: 80\r\n  dnsPolicy: ClusterFirst\r\n  restartPolicy: Always\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Wdra\u017camy nasz obiekt na klaster<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">kubectl apply -f 04.pod.pod-webapp.yaml<\/pre>\n<h4><\/h4>\n<h4>Zadanie pi\u0105te<\/h4>\n<p>&nbsp;<\/p>\n<p>Utw\u00f3rz obiekt typu pod o nazwie\u00a0 <strong>pod-webapp-volume<\/strong> zawieraj\u0105cy obraz <strong>nginx:latest<\/strong> pracuj\u0105cy na porcie <strong>80<\/strong> . Umie\u015b\u0107 go w przestrzeni nazw <strong>delta. <\/strong><\/p>\n<p>Do kontenera nale\u017cy pod\u0142\u0105czy\u0107 wolumen o nazwie <strong>nginx-volume<\/strong> typu <strong>emptyDir<\/strong>, kt\u00f3ry b\u0119dzie pod\u0142\u0105czony w kontenerze nginx pod \u015bcie\u017ck\u0105 <strong>\/opt\/data\/<\/strong>.<\/p>\n<p>Je\u017celi przestrze\u0144 nazw nie istnieje nale\u017cy j\u0105 utworzy\u0107.<\/p>\n<p>&nbsp;<\/p>\n<p>Wszystkie kluczowe parametry s\u0105 poni\u017cej<\/p>\n<p>&nbsp;<\/p>\n<div>Pod name:\u00a0 pod-webapp-volume<\/div>\n<div>Volume\u00a0Name:\u00a0nginx-volume<\/div>\n<div>Image\u00a0Name:\u00a0nginx:latest<\/div>\n<div>Container\u00a0port:\u00a080<\/div>\n<div>Volume Type: emptyDir()<\/div>\n<div>Volume\u00a0Mount:\u00a0\/opt\/data\/<\/div>\n<p>&nbsp;<\/p>\n<p>Naj\u0142atwiej b\u0119dzie wykorzysta\u0107 istniej\u0105cy juz plik manifestu z poprzedniego zadania<\/p>\n<div><\/div>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">cp 04.pod.pod-webapp.yaml 05.pod.pod-webapp-volume.yaml<\/pre>\n<p>&nbsp;<\/p>\n<\/div>\n<div>Zmieniamy nazw\u0119 obiektu pod z pod-webapp na pod-webapp-volume i dodajemy wolumen o nazwie nginx-volume.<\/div>\n<div><\/div>\n<p>Nasz manifest powinien wygl\u0105da\u0107 tak:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">apiVersion: v1\r\nkind: Pod\r\nmetadata:\r\n\u00a0\u00a0labels:\r\n\u00a0\u00a0\u00a0\u00a0run: pod-webapp-volume\r\n\u00a0\u00a0name: pod-webapp-volume\r\n\u00a0\u00a0namespace: delta\r\nspec:\r\n\u00a0\u00a0containers:\r\n\u00a0\u00a0- image: nginx:latest\r\n\u00a0\u00a0\u00a0\u00a0name: webapp-volume\r\n\u00a0\u00a0\u00a0\u00a0ports:\r\n\u00a0\u00a0\u00a0\u00a0- containerPort: 80\r\n\u00a0\u00a0\u00a0\u00a0resources: {}\r\n\u00a0\u00a0\u00a0\u00a0volumeMounts:\r\n\u00a0\u00a0\u00a0\u00a0- name: nginx-volume\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0mountPath: \/opt\/data\r\n\u00a0\u00a0dnsPolicy: ClusterFirst\r\n\u00a0\u00a0restartPolicy: Always\r\n\u00a0\u00a0volumes:\r\n\u00a0\u00a0- name: nginx-volume\r\n\u00a0\u00a0\u00a0\u00a0emptyDir: {}<\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">spec:\r\n\u00a0\u00a0# (...)\r\n\u00a0\u00a0volumes:\r\n\u00a0\u00a0- name: nginx-volume\r\n\u00a0\u00a0\u00a0\u00a0emptyDir: {}<\/pre>\n<p>Czym to si\u0119 w\u0142a\u015bciwie r\u00f3\u017cni od wolumen\u00f3w z poprzednich zada\u0144 ?<\/p>\n<p>Zawsze b\u0119dziemy mieli do czynienia z list\u0105 wewn\u0105trz <strong>volumes<\/strong>.<\/p>\n<ol>\n<li><strong>name<\/strong> (nazwa jest unikalna w obr\u0119bie obiektu pod)<\/li>\n<li>typ wolumenu (w naszym przypadku jest to <strong>emptyDir<\/strong>), a potem w zale\u017cno\u015bci od typu wolumenu wewn\u0119trzne mapy. W naszym przypadku jest to warto\u015b\u0107 pusta, czyli <strong>{}<\/strong><\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<p>Wdra\u017camy nasz obiekt na klaster<\/p>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">kubectl apply -f 05.pod.pod-webapp-volume.yaml<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<h4>Zadanie sz\u00f3ste<\/h4>\n<p>&nbsp;<\/p>\n<p>Utw\u00f3rz obiekt typu pod o nazwie\u00a0<strong> pod-webapp-volume-host<\/strong> zawieraj\u0105cy obraz <strong>nginx:latest<\/strong> pracuj\u0105cy na porcie <strong>80<\/strong> . Umie\u015b\u0107 go w przestrzeni nazw <strong>delta. <\/strong><\/p>\n<p>Do kontenera nale\u017cy pod\u0142\u0105czy\u0107 wolumen o nazwie\u00a0<strong>webapp-host<\/strong> typu <strong>hostPath<\/strong> wskazuj\u0105cy na \u015bcie\u017ck\u0119<strong>\/var\/log\/nginx\/<\/strong>, kt\u00f3ry b\u0119dzie pod\u0142\u0105czony w kontenerze nginx pod \u015bcie\u017ck\u0105\u00a0<strong>\/var\/log\/nginx\/ <\/strong>Je\u017celi przestrze\u0144 nazw nie istnieje nale\u017cy j\u0105 utworzy\u0107.<\/p>\n<p>&nbsp;<\/p>\n<p>Wszystkie kluczowe parametry s\u0105 poni\u017cej<\/p>\n<div><\/div>\n<div>Pod name: pod-webapp-volume-host<\/div>\n<div>Volume\u00a0Name:\u00a0webapp-host<\/div>\n<div>Image\u00a0Name:\u00a0nginx:latest<\/div>\n<div>Container\u00a0port:\u00a080<\/div>\n<div>Volume Type: HostPath \/var\/log\/nginx\/<\/div>\n<div>Volume\u00a0Mount:\u00a0\/var\/log\/nginx\/<\/div>\n<p>&nbsp;<\/p>\n<p>Po raz kolejny wykorzystamy istniej\u0105cy juz plik manifestu z poprzedniego zadania<\/p>\n<div><\/div>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">cp 05.pod.pod-webapp-volume.yaml 06.pod.pod-webapp-volume-host.yaml<\/pre>\n<\/div>\n<div><\/div>\n<p>Zmieniamy nazw\u0119 obiektu pod i nazw\u0119 wolumenu (w dw\u00f3ch miejscach)<\/p>\n<p>Masz plik manifestu powinien wygl\u0105da\u0107 tak:<\/p>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">apiVersion: v1\r\nkind: Pod\r\nmetadata:\r\n\u00a0\u00a0labels:\r\n\u00a0\u00a0\u00a0\u00a0run: pod-webapp-volume-host\r\n\u00a0\u00a0name: pod-webapp-volume-host\r\n\u00a0\u00a0namespace: delta\r\nspec:\r\n\u00a0\u00a0containers:\r\n\u00a0\u00a0- image: nginx:latest\r\n\u00a0\u00a0\u00a0\u00a0name: webapp-volume-host\r\n\u00a0\u00a0\u00a0\u00a0ports:\r\n\u00a0\u00a0\u00a0\u00a0- containerPort: 80\r\n\u00a0\u00a0\u00a0\u00a0resources: {}\r\n\u00a0\u00a0\u00a0\u00a0volumeMounts:\r\n\u00a0\u00a0\u00a0\u00a0- name: webapp-host\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0mountPath: \/var\/log\/nginx\/\r\n\u00a0\u00a0dnsPolicy: ClusterFirst\r\n\u00a0\u00a0restartPolicy: Always\r\n\u00a0\u00a0volumes:\r\n\u00a0\u00a0- name: webapp-host\r\n\u00a0\u00a0\u00a0\u00a0hostPath:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0path: \/var\/log\/nginx\/<\/pre>\n<p>Sprawdzmy czym si\u0119 to r\u00f3\u017cni w por\u00f3wnaniu z manifestem poprzedniego zadania (pod z volumenem typu emptyDir).<\/p>\n<p>&nbsp;<\/p>\n<\/div>\n<p>Masz plik manifestu powinien wygl\u0105da\u0107 tak:<\/p>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">spec:\r\n # (...)\r\n\u00a0\u00a0volumes:\r\n\u00a0\u00a0- name: webapp-host\r\n\u00a0\u00a0\u00a0\u00a0hostPath:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0path: \/var\/log\/nginx\/<\/pre>\n<\/div>\n<p>Zawsze b\u0119dziemy mieli do czynienia z list\u0105 wewn\u0105trz <strong>volumes<\/strong>.<\/p>\n<ol>\n<li><strong>name<\/strong> (nazwa jest unikalna w obr\u0119bie obiektu pod)<\/li>\n<li>typ wolumenu (w naszym przypadku jest to <strong>hostPath<\/strong>), a potem w zale\u017cno\u015bci od typu wolumenu wewn\u0119trzne mapy. W naszym przypadku jest to mapa <strong>path: \/var\/log\/nginx\/<\/strong><\/li>\n<\/ol>\n<p>Wdra\u017camy nasz obiekt na klaster<\/p>\n<div><\/div>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">kubectl apply -f 06.pod.pod-webapp-volume-host.yaml<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<div><\/div>\n<h4>Zadanie si\u00f3dme<\/h4>\n<p>&nbsp;<\/p>\n<p>Utw\u00f3rz obiekt typu persistentVolume o nazwie <strong>pv-data<\/strong>, kt\u00f3ry potrafi przechowa\u0107 <strong>50Mi<\/strong> danych w trybie <strong>ReadWriteMany<\/strong>. Volumem ma korzysta\u0107 z hostPath<strong> \/var\/log\/data<\/strong><\/p>\n<p>&nbsp;<\/p>\n<p>Wszystkie kluczowe parametry s\u0105 poni\u017cej<\/p>\n<div><\/div>\n<div>\u00a0\u00a0\u00a0\u00a0Volume\u00a0Name:\u00a0pv-data<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0Storage:\u00a050Mi<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0Access\u00a0modes:\u00a0ReadWriteMany<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0Host\u00a0Path:\u00a0\/var\/log\/data<\/div>\n<div><\/div>\n<p>&nbsp;<\/p>\n<p>Tu po raz pierwszy nie mo\u017cemy zastosowa\u0107 generatora w kubectl. Mamy dwie mo\u017cliwo\u015bci .<\/p>\n<p>a) Skorzysta\u0107 z systemu pomocy kubectl explain pv<\/p>\n<p>b) Si\u0119gn\u0105\u0107 do przyk\u0142adowych manifest\u00f3w z dokumentacji.<\/p>\n<p>&nbsp;<\/p>\n<p>Jak wygl\u0105da informacja zwrotna dla polecenia<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">kubectl explain persistentvolume.spec --recursive<\/pre>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">KIND:     PersistentVolume\r\nVERSION:  v1\r\n\r\nRESOURCE: spec &lt;Object&gt;\r\n\r\nDESCRIPTION:\r\n     Spec defines a specification of a persistent volume owned by the cluster.\r\n     Provisioned by an administrator. More info:\r\n     https:\/\/kubernetes.io\/docs\/concepts\/storage\/persistent-volumes#persistent-volumes\r\n\r\n     PersistentVolumeSpec is the specification of a persistent volume.\r\n\r\nFIELDS:\r\n   accessModes  &lt;[]string&gt;\r\n   awsElasticBlockStore &lt;Object&gt;\r\n      fsType    &lt;string&gt;\r\n      partition &lt;integer&gt;\r\n      readOnly  &lt;boolean&gt;\r\n      volumeID  &lt;string&gt;\r\n   azureDisk    &lt;Object&gt;\r\n      cachingMode       &lt;string&gt;\r\n      diskName  &lt;string&gt;\r\n      diskURI   &lt;string&gt;\r\n      fsType    &lt;string&gt;\r\n      kind      &lt;string&gt;\r\n      readOnly  &lt;boolean&gt;\r\n   azureFile    &lt;Object&gt;\r\n      readOnly  &lt;boolean&gt;\r\n      secretName        &lt;string&gt;\r\n      secretNamespace   &lt;string&gt;\r\n      shareName &lt;string&gt;\r\n   capacity     &lt;map[string]string&gt;\r\n   cephfs       &lt;Object&gt;\r\n      monitors  &lt;[]string&gt;\r\n      path      &lt;string&gt;\r\n      readOnly  &lt;boolean&gt;\r\n      secretFile        &lt;string&gt;\r\n      secretRef &lt;Object&gt;\r\n         name   &lt;string&gt;\r\n         namespace      &lt;string&gt;\r\n      user      &lt;string&gt;\r\n   cinder       &lt;Object&gt;\r\n      fsType    &lt;string&gt;\r\n      readOnly  &lt;boolean&gt;\r\n      secretRef &lt;Object&gt;\r\n         name   &lt;string&gt;\r\n         namespace      &lt;string&gt;\r\n      volumeID  &lt;string&gt;\r\n   claimRef     &lt;Object&gt;\r\n      apiVersion        &lt;string&gt;\r\n      fieldPath &lt;string&gt;\r\n      kind      &lt;string&gt;\r\n      name      &lt;string&gt;\r\n      namespace &lt;string&gt;\r\n      resourceVersion   &lt;string&gt;\r\n      uid       &lt;string&gt;\r\n   csi  &lt;Object&gt;\r\n      controllerExpandSecretRef &lt;Object&gt;\r\n         name   &lt;string&gt;\r\n         namespace      &lt;string&gt;\r\n      controllerPublishSecretRef        &lt;Object&gt;\r\n         name   &lt;string&gt;\r\n         namespace      &lt;string&gt;\r\n      driver    &lt;string&gt;\r\n      fsType    &lt;string&gt;\r\n      nodePublishSecretRef      &lt;Object&gt;\r\n         name   &lt;string&gt;\r\n         namespace      &lt;string&gt;\r\n      nodeStageSecretRef        &lt;Object&gt;\r\n         name   &lt;string&gt;\r\n         namespace      &lt;string&gt;\r\n      readOnly  &lt;boolean&gt;\r\n      volumeAttributes  &lt;map[string]string&gt;\r\n      volumeHandle      &lt;string&gt;\r\n   fc   &lt;Object&gt;\r\n      fsType    &lt;string&gt;\r\n      lun       &lt;integer&gt;\r\n      readOnly  &lt;boolean&gt;\r\n      targetWWNs        &lt;[]string&gt;\r\n      wwids     &lt;[]string&gt;\r\n   flexVolume   &lt;Object&gt;\r\n      driver    &lt;string&gt;\r\n      fsType    &lt;string&gt;\r\n      options   &lt;map[string]string&gt;\r\n      readOnly  &lt;boolean&gt;\r\n      secretRef &lt;Object&gt;\r\n         name   &lt;string&gt;\r\n         namespace      &lt;string&gt;\r\n   flocker      &lt;Object&gt;\r\n      datasetName       &lt;string&gt;\r\n      datasetUUID       &lt;string&gt;\r\n   gcePersistentDisk    &lt;Object&gt;\r\n      fsType    &lt;string&gt;\r\n      partition &lt;integer&gt;\r\n      pdName    &lt;string&gt;\r\n      readOnly  &lt;boolean&gt;\r\n   glusterfs    &lt;Object&gt;\r\n      endpoints &lt;string&gt;\r\n      endpointsNamespace        &lt;string&gt;\r\n      path      &lt;string&gt;\r\n      readOnly  &lt;boolean&gt;\r\n   hostPath     &lt;Object&gt;\r\n      path      &lt;string&gt;\r\n      type      &lt;string&gt;\r\n   iscsi        &lt;Object&gt;\r\n      chapAuthDiscovery &lt;boolean&gt;\r\n      chapAuthSession   &lt;boolean&gt;\r\n      fsType    &lt;string&gt;\r\n      initiatorName     &lt;string&gt;\r\n      iqn       &lt;string&gt;\r\n      iscsiInterface    &lt;string&gt;\r\n      lun       &lt;integer&gt;\r\n      portals   &lt;[]string&gt;\r\n      readOnly  &lt;boolean&gt;\r\n      secretRef &lt;Object&gt;\r\n         name   &lt;string&gt;\r\n         namespace      &lt;string&gt;\r\n      targetPortal      &lt;string&gt;\r\n   local        &lt;Object&gt;\r\n      fsType    &lt;string&gt;\r\n      path      &lt;string&gt;\r\n   mountOptions &lt;[]string&gt;\r\n   nfs  &lt;Object&gt;\r\n      path      &lt;string&gt;\r\n      readOnly  &lt;boolean&gt;\r\n      server    &lt;string&gt;\r\n   nodeAffinity &lt;Object&gt;\r\n      required  &lt;Object&gt;\r\n         nodeSelectorTerms      &lt;[]Object&gt;\r\n            matchExpressions    &lt;[]Object&gt;\r\n               key      &lt;string&gt;\r\n               operator &lt;string&gt;\r\n               values   &lt;[]string&gt;\r\n            matchFields &lt;[]Object&gt;\r\n               key      &lt;string&gt;\r\n               operator &lt;string&gt;\r\n               values   &lt;[]string&gt;\r\n   persistentVolumeReclaimPolicy        &lt;string&gt;\r\n   photonPersistentDisk &lt;Object&gt;\r\n      fsType    &lt;string&gt;\r\n      pdID      &lt;string&gt;\r\n   portworxVolume       &lt;Object&gt;\r\n      fsType    &lt;string&gt;\r\n      readOnly  &lt;boolean&gt;\r\n      volumeID  &lt;string&gt;\r\n   quobyte      &lt;Object&gt;\r\n      group     &lt;string&gt;\r\n      readOnly  &lt;boolean&gt;\r\n      registry  &lt;string&gt;\r\n      tenant    &lt;string&gt;\r\n      user      &lt;string&gt;\r\n      volume    &lt;string&gt;\r\n   rbd  &lt;Object&gt;\r\n      fsType    &lt;string&gt;\r\n      image     &lt;string&gt;\r\n      keyring   &lt;string&gt;\r\n      monitors  &lt;[]string&gt;\r\n      pool      &lt;string&gt;\r\n      readOnly  &lt;boolean&gt;\r\n      secretRef &lt;Object&gt;\r\n         name   &lt;string&gt;\r\n         namespace      &lt;string&gt;\r\n      user      &lt;string&gt;\r\n   scaleIO      &lt;Object&gt;\r\n      fsType    &lt;string&gt;\r\n      gateway   &lt;string&gt;\r\n      protectionDomain  &lt;string&gt;\r\n      readOnly  &lt;boolean&gt;\r\n      secretRef &lt;Object&gt;\r\n         name   &lt;string&gt;\r\n         namespace      &lt;string&gt;\r\n      sslEnabled        &lt;boolean&gt;\r\n      storageMode       &lt;string&gt;\r\n      storagePool       &lt;string&gt;\r\n      system    &lt;string&gt;\r\n      volumeName        &lt;string&gt;\r\n   storageClassName     &lt;string&gt;\r\n   storageos    &lt;Object&gt;\r\n      fsType    &lt;string&gt;\r\n      readOnly  &lt;boolean&gt;\r\n      secretRef &lt;Object&gt;\r\n         apiVersion     &lt;string&gt;\r\n         fieldPath      &lt;string&gt;\r\n         kind   &lt;string&gt;\r\n         name   &lt;string&gt;\r\n         namespace      &lt;string&gt;\r\n         resourceVersion        &lt;string&gt;\r\n         uid    &lt;string&gt;\r\n      volumeName        &lt;string&gt;\r\n      volumeNamespace   &lt;string&gt;\r\n   volumeMode   &lt;string&gt;\r\n   vsphereVolume        &lt;Object&gt;\r\n      fsType    &lt;string&gt;\r\n      storagePolicyID   &lt;string&gt;\r\n      storagePolicyName &lt;string&gt;\r\n      volumePath        &lt;string&gt;<\/pre>\n<p>&nbsp;<\/p>\n<p>Na pocz\u0105tek troch\u0119 za du\u017co informacji, ale wiemy ju\u017c, \u017ce manifest obiektu tego typu powinien zaczyna\u0107 si\u0119 tak<\/p>\n<div><\/div>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">apiVersion: v1\r\nkind: PersistentVolume\r\nmetadata:\r\n\u00a0\u00a0name: pv-data\r\nspec:\r\n<\/pre>\n<p>Dodatkowo dla typu hostPath mamy wewn\u0105trz<strong> spec.<\/strong><\/p>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">hostPath &lt;Object&gt; \r\npath &lt;string&gt; type &lt;string&gt;<\/pre>\n<p>&nbsp;<\/p>\n<p>W tym przypadku szybciej b\u0119dzie skorzystanie z dokumentacji <a href=\"https:\/\/kubernetes.io\/docs\/concepts\/storage\/persistent-volumes\/#persistent-volumes\" target=\"_blank\" rel=\"noopener\">persistent-volumes <\/a>na stronie produktu, gdzie ju\u017c pierwszy manifest od g\u00f3ry jest przydatny<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">apiVersion: v1\r\nkind: PersistentVolume\r\nmetadata:\r\n  name: pv0003\r\nspec:\r\n  capacity:\r\n    storage: 5Gi\r\n  volumeMode: Filesystem\r\n  accessModes:\r\n    - ReadWriteOnce\r\n  persistentVolumeReclaimPolicy: Recycle\r\n  storageClassName: slow\r\n  mountOptions:\r\n    - hard\r\n    - nfsvers=4.1\r\n  nfs:\r\n    path: \/tmp\r\n    server: 172.17.0.2<\/pre>\n<div><\/div>\n<p>Po usuni\u0119ciu zb\u0119dnych informacji nasz plik zgodnie z wymaganiami zadania powninien wygl\u0105da\u0107 tak:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">apiVersion:\u00a0v1\r\nkind:\u00a0PersistentVolume\r\nmetadata:\r\n\u00a0\u00a0name:\u00a0pv-data\r\nspec:\r\n\u00a0\u00a0capacity:\r\n\u00a0\u00a0\u00a0\u00a0storage:\u00a050Mi\r\n\u00a0\u00a0accessModes:\r\n\u00a0\u00a0\u00a0\u00a0-\u00a0ReadWriteMany\r\n\u00a0\u00a0hostPath:\r\n\u00a0\u00a0\u00a0\u00a0path:\u00a0\/var\/log\/data<\/pre>\n<p>&nbsp;<\/p>\n<div>Wdra\u017camy nasz obiekt na klaster<\/div>\n<div><\/div>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">kubectl apply -f 07.pv.pv-data.yaml<\/pre>\n<\/div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">persistentvolume\/pv-data created<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h4>Zadanie \u00f3sme<\/h4>\n<p>&nbsp;<\/p>\n<p>Utw\u00f3rz obiekt typu <strong>persistentVolumeClaim<\/strong> o nazwie <strong>pvc-log<\/strong>, kt\u00f3ry ma potrafi\u0107 przechowa\u0107 <strong>30Mi<\/strong> danych w trybie <strong>ReadWriteOnce<\/strong>.<\/p>\n<p>Umie\u015b\u0107 go w przestrzeni nazw <strong>delta.\u00a0 <\/strong>Je\u017celi przestrze\u0144 nazw nie istnieje nale\u017cy j\u0105 utworzy\u0107.<\/p>\n<p>&nbsp;<\/p>\n<p>Wszystkie kluczowe parametry s\u0105 poni\u017cej<\/p>\n<div><\/div>\n<div>\u00a0\u00a0\u00a0\u00a0Volume\u00a0Name:\u00a0pvc-log<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0Storage:\u00a030Mi<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0Access\u00a0modes:\u00a0ReadWriteOnce<\/div>\n<div><\/div>\n<div>W przypadku tego typu obiekt\u00f3w r\u00f3wnie\u017c nie ma gotowych generator\u00f3w, proponuje wycieczk\u0119 na stron\u0119<\/div>\n<div><\/div>\n<div><a href=\"https:\/\/kubernetes.io\/docs\/concepts\/storage\/persistent-volumes\/#persistentvolumeclaims\" target=\"_blank\" rel=\"noopener\">https:\/\/kubernetes.io\/docs\/concepts\/storage\/persistent-volumes\/#persistentvolumeclaims<\/a><\/div>\n<div><\/div>\n<div>Pierwszy od g\u00f3ry manifest wygl\u0105da tak<\/div>\n<div><\/div>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">apiVersion: v1\r\nkind: PersistentVolumeClaim\r\nmetadata:\r\n  name: myclaim\r\nspec:\r\n  accessModes:\r\n    - ReadWriteOnce\r\n  volumeMode: Filesystem\r\n  resources:\r\n    requests:\r\n      storage: 8Gi\r\n  storageClassName: slow\r\n  selector:\r\n    matchLabels:\r\n      release: \"stable\"\r\n    matchExpressions:\r\n      - {key: environment, operator: In, values: [dev]}<\/pre>\n<\/div>\n<div>Po niewielkiej korekcie powinni\u015bmy otrzyma\u0107 plik o poni\u017cszej zawarto\u015bci<\/div>\n<div><\/div>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">apiVersion:\u00a0v1\r\nkind:\u00a0PersistentVolumeClaim\r\nmetadata:\r\n\u00a0\u00a0name:\u00a0pvc-log\r\n  namespace: delta\r\nspec:\r\n\u00a0\u00a0accessModes:\r\n\u00a0\u00a0\u00a0\u00a0-\u00a0ReadWriteOnce\r\n\u00a0\u00a0resources:\r\n\u00a0\u00a0\u00a0\u00a0requests:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0storage:\u00a030Mi<\/pre>\n<p>&nbsp;<\/p>\n<\/div>\n<p>Wdra\u017camy nasz obiekt na klaster<\/p>\n<div><\/div>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">kubectl apply -f 08.pvc.pvc-log.yaml<\/pre>\n<\/div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">persistentvolumeclaim\/pvc-log created<\/pre>\n<p>&nbsp;<\/p>\n<p>W tym momencie warto obejrze\u0107 jak wygl\u0105daj\u0105 nasze obiekty PV oraz PVC.<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">kubectl get pv,pvc -n delta\r\n<\/pre>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">NAME                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE\r\npersistentvolume\/pv-data   50Mi       RWX            Retain           Available                                   2m13s\r\n\r\nNAME                            STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE\r\npersistentvolumeclaim\/pvc-log   Pending                                                     42s<\/pre>\n<p>&nbsp;<\/p>\n<p>Jak wida\u0107 mamy obiekt PV o nazwie PV-data, kt\u00f3ry ma ustawiony status na Available i obiekt typu PVC o nazwie pvc-log, kt\u00f3ry ma ustawiony status Pending. Jak wida\u0107 nie dosz\u0142o do powi\u0105zania tych dw\u00f3ch obiekt\u00f3w ? Dlatego, \u017ce oba z nich nie maj\u0105 wsp\u00f3lnej warto\u015bcia dla trybu dost\u0119pu (accessModes).<\/p>\n<p>&nbsp;<\/p>\n<p>Spr\u00f3bujmy to naprawi\u0107 w nast\u0119pnym zadaniu.<\/p>\n<p>&nbsp;<\/p>\n<h4>Zadanie dziewi\u0105te<\/h4>\n<p>&nbsp;<\/p>\n<p>Utw\u00f3rz obiekt typu persistentVolumeClaim o nazwie <strong>pvc-log-fix<\/strong>, kt\u00f3ry ma potrafi\u0107 przechowa\u0107 <strong>30Mi<\/strong> danych w trybie <strong>ReadWriteMany<\/strong>.<\/p>\n<p>Umie\u015b\u0107 go w przestrzeni nazw <strong>delta.\u00a0 <\/strong>Je\u017celi przestrze\u0144 nazw nie istnieje nale\u017cy j\u0105 utworzy\u0107.<\/p>\n<p>&nbsp;<\/p>\n<p>Wszystkie kluczowe parametry s\u0105 poni\u017cej<\/p>\n<div><\/div>\n<div>\u00a0\u00a0\u00a0\u00a0Volume Name: pvc-log-fix<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0Storage:\u00a030Mi<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0Access modes: ReadWritemany<\/div>\n<div><\/div>\n<div><\/div>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">apiVersion: v1\r\nkind: PersistentVolumeClaim\r\nmetadata:\r\n\u00a0\u00a0name: pvc-log-fix\r\n  namespace: delta\r\nspec:\r\n\u00a0\u00a0accessModes:\r\n\u00a0\u00a0\u00a0\u00a0- ReadWriteMany\r\n\u00a0\u00a0resources:\r\n\u00a0\u00a0\u00a0\u00a0requests:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0storage: 30Mi<\/pre>\n<p>&nbsp;<\/p>\n<\/div>\n<p>Wdra\u017camy nasz obiekt na klaster<\/p>\n<div><\/div>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">kubectl apply -f 09.pvc.pvc-log-fix.yaml<\/pre>\n<\/div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">persistentvolumeclaim\/pvc-log-fix created<\/pre>\n<p>&nbsp;<\/p>\n<p>Warto obejrze\u0107 jak wygl\u0105daj\u0105 nasze obiekty PV oraz PVC.<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">kubectl get pv,pvc -n delta\r\n<\/pre>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">NAME                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS   REASON   AGE\r\npersistentvolume\/pv-data   50Mi       RWX            Retain           Bound    delta\/pvc-log-fix                           8m47s\r\n\r\nNAME                                STATUS    VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE\r\npersistentvolumeclaim\/pvc-log       Pending                                                      7m16s\r\npersistentvolumeclaim\/pvc-log-fix   Bound     pv-data   50Mi       RWX                           70s<\/pre>\n<p>&nbsp;<\/p>\n<p>Jak wida\u0107 mamy teraz obiekt PV o nazwie pv-data , kt\u00f3ry ma ustawiony status na <strong>Bound<\/strong> ze wskazaniem na PVC o nazwie <strong>delta\/pvc-log-fix<\/strong>\u00a0 i i dwa obiekty typu PVC o nazwach pvc-log i pvc-log-fix , z kt\u00f3rych pierwszy ma ustawiony status <strong>Pending<\/strong> a drugi status <strong>Bound<\/strong> ze wskazaniem na obiekt PV o nazwie pv-data.<\/p>\n<p>Poprawa trybu dost\u0119pu na RWX (czyli <span class=\"enlighter-text\">ReadWriteMany<\/span>) pomog\u0142a w powi\u0105zaniu obiekt\u00f3w PV i PVC.<\/p>\n<div>\n<p>&nbsp;<\/p>\n<\/div>\n<p>&nbsp;<\/p>\n<h4>Zadanie dziesi\u0105te<\/h4>\n<p>&nbsp;<\/p>\n<p>Utw\u00f3rz obiekt typu pod o nazwie\u00a0 <strong>pod-webapp-volume-pvc<\/strong> zawieraj\u0105cy obraz <strong>nginx:latest<\/strong> pracuj\u0105cy na porcie <strong>80<\/strong> . Umie\u015b\u0107 go w przestrzeni nazw <strong>delta. <\/strong><\/p>\n<p>Do kontenera nale\u017cy pod\u0142\u0105czy\u0107 wolumen o nazwie\u00a0<strong>pvc-log-fix<\/strong> typu <strong>PersistentVolumeClaim<\/strong> , kt\u00f3ry b\u0119dzie pod\u0142\u0105czony w kontenerze nginx pod \u015bcie\u017ck\u0105 <strong>\/var\/log\/nginx\/ <\/strong>Je\u017celi przestrze\u0144 nazw nie istnieje nale\u017cy j\u0105 utworzy\u0107.<\/p>\n<p>&nbsp;<\/p>\n<p>Wszystkie kluczowe parametry s\u0105 poni\u017cej<\/p>\n<p>&nbsp;<\/p>\n<p>Name: pod-webapp-volume-pvc<\/p>\n<div>\n<div>Image\u00a0Name:\u00a0nginx:latest<\/div>\n<div>Volume:\u00a0PersistentVolumeClaim=pvc-log<\/div>\n<div>Volume\u00a0Mount:\u00a0\/var\/log\/nginx\/<\/div>\n<div>Volume Name: pvc-log-fix<\/div>\n<div><\/div>\n<\/div>\n<div><\/div>\n<div>Tutaj mo\u017cemy skorzysta\u0107 z manifestu z zadania sz\u00f3stego<\/div>\n<div><\/div>\n<div>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">cp 06.pod-webapp-volume-host 10.pod.pod-webapp-volume-pvc.yaml\r\n<\/pre>\n<\/div>\n<div>Nale\u017cy poprawi\u0107 nazw\u0119 obiektu pod i dodatkowo zmodyfikowa\u0107 typ wolumenu z jakim mamy do czynienia<\/div>\n<div><\/div>\n<div>Czyli zamiast<\/div>\n<div><\/div>\n<div>\n<div><\/div>\n<div>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">spec:\r\n\r\n\u00a0\u00a0volumes:\r\n\u00a0\u00a0- name: webapp-host\r\n\u00a0\u00a0\u00a0\u00a0hostPath:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0path: \/var\/log\/nginx\/<\/pre>\n<\/div>\n<\/div>\n<div><\/div>\n<div>Powinno by\u0107<\/div>\n<div>\n<div><\/div>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">spec:\r\n\u00a0# (...)\r\n\u00a0\u00a0volumes:\r\n\u00a0\u00a0- name: pvc-log\r\n\u00a0\u00a0\u00a0\u00a0persistentVolumeClaim:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0claimName: pvc-log-fix<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div><\/div>\n<div>Przy okazji przypominam o systemie pomocy<\/div>\n<div><\/div>\n<div><\/div>\n<div><\/div>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">kubectl explain pod.spec.volumes.persistentVolumeClaim --recursive\r\n<\/pre>\n<\/div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">KIND:     Pod\r\nVERSION:  v1\r\n\r\nRESOURCE: persistentVolumeClaim &lt;Object&gt;\r\n\r\nDESCRIPTION:\r\n     PersistentVolumeClaimVolumeSource represents a reference to a\r\n     PersistentVolumeClaim in the same namespace. More info:\r\n     https:\/\/kubernetes.io\/docs\/concepts\/storage\/persistent-volumes#persistentvolumeclaims\r\n\r\n     PersistentVolumeClaimVolumeSource references the user's PVC in the same\r\n     namespace. This volume finds the bound PV and mounts that volume for the\r\n     pod. A PersistentVolumeClaimVolumeSource is, essentially, a wrapper around\r\n     another type of volume that is owned by someone else (the system).\r\n\r\nFIELDS:\r\n   claimName    &lt;string&gt;\r\n   readOnly     &lt;boolean&gt;<\/pre>\n<div><\/div>\n<div><\/div>\n<div>Nasz plik manifestu powinien wygl\u0105da\u0107 tak<\/div>\n<div><\/div>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\">apiVersion: v1\r\nkind: Pod\r\nmetadata:\r\n\u00a0\u00a0labels:\r\n\u00a0\u00a0\u00a0\u00a0run: pod-webapp-volume-pvc\r\n\u00a0\u00a0name: pod-webapp-volume-pvc\r\n\u00a0\u00a0namespace: delta\r\nspec:\r\n\u00a0\u00a0containers:\r\n\u00a0\u00a0- image: nginx:latest\r\n\u00a0\u00a0\u00a0\u00a0name: webapp-volume-pvc\r\n\u00a0\u00a0\u00a0\u00a0ports:\r\n\u00a0\u00a0\u00a0\u00a0- containerPort: 80\r\n\u00a0\u00a0\u00a0\u00a0resources: {}\r\n\u00a0\u00a0\u00a0\u00a0volumeMounts:\r\n\u00a0\u00a0\u00a0\u00a0- name: pvc-log\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0mountPath: \/var\/log\/nginx\/\r\n\u00a0\u00a0dnsPolicy: ClusterFirst\r\n\u00a0\u00a0restartPolicy: Always\r\n\u00a0\u00a0volumes:\r\n\u00a0\u00a0- name: pvc-log\r\n\u00a0\u00a0\u00a0\u00a0persistentVolumeClaim:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0claimName: pvc-log-fix<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Wdra\u017camy obiekt na klaster<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">kubectl apply -f 10.pod.pod-webapp-volume-pvc.yaml \r\n<\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">pod\/pod-webapp-volume-pvc created<\/pre>\n<p>&nbsp;<\/p>\n<p>Sprawd\u017amy czy nasz wolumen zosta\u0142 pod\u0142\u0105czony do obiektu pod. Naj\u0142atwiej jest to zrobi\u0107 za pomoc\u0105 <strong>kubectl describe pod<\/strong><\/p>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">kubectl describe pod pod-webapp-volume-pvc -n delta<\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">Volumes:\r\n  pvc-log:\r\n    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)\r\n    ClaimName:  pvc-log-fix\r\n    ReadOnly:   false\r\n  default-token-g5fdr:\r\n    Type:        Secret (a volume populated by a Secret)\r\n    SecretName:  default-token-g5fdr\r\n    Optional:    false\r\nQoS Class:       BestEffort\r\nNode-Selectors:  &lt;none&gt;\r\nTolerations:     node.kubernetes.io\/not-ready:NoExecute for 300s\r\n                 node.kubernetes.io\/unreachable:NoExecute for 300s\r\nEvents:\r\n  Type    Reason     Age   From               Message\r\n  ----    ------     ----  ----               -------\r\n  Normal  Scheduled  9s    default-scheduler  Successfully assigned delta\/pod-webapp-volume-pvc to node01\r\n  Normal  Pulling    9s    kubelet, node01    Pulling image \"nginx:latest\"\r\n  Normal  Pulled     8s    kubelet, node01    Successfully pulled image \"nginx:latest\" in 746.348637ms\r\n  Normal  Created    8s    kubelet, node01    Created container webapp-volume-pvc\r\n  Normal  Started    8s    kubelet, node01    Started container webapp-volume-pvc<\/pre>\n<p>&nbsp;<\/p>\n<p>Jak wyda\u0107 opr\u00f3cz zadeklarowanego w manifescie wolumenu pojawi\u0142 si\u0119 ten zwi\u0105zany z obiektem secret umo\u017cliwiaj\u0105cy dost\u0119p do API Kubernetes, o czy wspomina\u0142em na samym pocz\u0105tku tego wpisu.<\/p>\n<p>&nbsp;<\/p>\n<p>Nie zosta\u0142o opisanych jeszcze wiele aspekt\u00f3w pracy z wolumenami danych, nic nie wspomnia\u0142em o <strong>reclaimPolicy<\/strong> i nie ma \u017cadnych przyk\u0142ad\u00f3w dotycz\u0105cych <strong>storageClass<\/strong>, temat jest obszerny i nie chcia\u0142em dodatkowo rozszerza\u0107 liczby minut do przeczytania i prze\u0107wiczenia. Mam nadziej\u0119, \u017ce ch\u0119tni si\u0119gn\u0105 do dokumentacji.<\/p>\n<p>&nbsp;<\/p>\n<p>Na tym ko\u0144czymy dzisiejsz\u0105 audycj\u0119, do us\u0142yszenia wkr\u00f3tce.<\/p>\n<p>&nbsp;<\/p>\n<p>Poprzednie cz\u0119\u015bci<\/p>\n<p>&nbsp;<\/p>\n<p><a href=\"https:\/\/wchmurze.cloud\/index.php\/2021\/05\/07\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-1\/\" target=\"_blank\" rel=\"noopener\">Certified Kubernetes Administrator (CKA) krok po kroku \u2013 cz\u0119\u015b\u0107 1<\/a><\/p>\n<p><a href=\"https:\/\/wchmurze.cloud\/index.php\/2021\/05\/24\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-2\/\" target=\"_blank\" rel=\"noopener\">Certified Kubernetes Administrator (CKA) krok po kroku &amp;#8211; cz\u0119\u015b\u0107 2<\/a><\/p>\n<p><a href=\"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/07\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-3\/\" target=\"_blank\" rel=\"noopener\">Certified Kubernetes Administrator (CKA) krok po kroku \u2013 cz\u0119\u015b\u0107 3<\/a><\/p>\n<p><a href=\"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/13\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-4\/\" target=\"_blank\" rel=\"noopener\">Certified Kubernetes Administrator (CKA) krok po kroku &amp;#8211; cz\u0119\u015b\u0107 4<\/a><\/p>\n<p>&nbsp;<\/p>\n<p>Nast\u0119pne cz\u0119\u015bci:<\/p>\n<p>&nbsp;<\/p>\n<p>TODO<\/p>\n<p>&nbsp;<\/p>\n<h4>Literatura:<\/h4>\n<p>&nbsp;<\/p>\n<p><a href=\"https:\/\/kubernetes.io\/docs\/tasks\/configure-pod-container\/configure-service-account\/\" target=\"_blank\" rel=\"noopener\">https:\/\/kubernetes.io\/docs\/tasks\/configure-pod-container\/configure-service-account\/<\/a><\/p>\n<p><a href=\"https:\/\/kubernetes.io\/docs\/reference\/generated\/kubectl\/kubectl-commands\" target=\"_blank\" rel=\"noopener\">https:\/\/kubernetes.io\/docs\/reference\/generated\/kubectl\/kubectl-commands<\/a><\/p>\n<p><a href=\"https:\/\/dev.to\/techworld_with_nana\/difference-between-emptydir-and-hostpath-volume-types-in-kubernetes-286g\" target=\"_blank\" rel=\"noopener\">https:\/\/dev.to\/techworld_with_nana\/difference-between-emptydir-and-hostpath-volume-types-in-kubernetes-286g<\/a><\/p>\n<p><a href=\"https:\/\/kubernetes.io\/docs\/concepts\/configuration\/secret\/\" target=\"_blank\" rel=\"noopener\">https:\/\/kubernetes.io\/docs\/concepts\/configuration\/secret\/<\/a><\/p>\n<p><a href=\"https:\/\/kubernetes.io\/docs\/concepts\/storage\/persistent-volumes\/#persistent-volumes\" target=\"_blank\" rel=\"noopener\">https:\/\/kubernetes.io\/docs\/concepts\/storage\/persistent-volumes\/#persistent-volumes<\/a><\/p>\n<p><a href=\"https:\/\/kubernetes.io\/docs\/tasks\/configure-pod-container\/configure-pod-configmap\/\" target=\"_blank\" rel=\"noopener\">https:\/\/kubernetes.io\/docs\/tasks\/configure-pod-container\/configure-pod-configmap\/<\/a><\/p>\n<p>&nbsp;<\/p>\n<div class=\"entry-content-asset videofit\">\n<blockquote class=\"wp-embedded-content\" data-secret=\"PfxfQ17LpF\"><p><a href=\"https:\/\/vocon-it.com\/2018\/12\/10\/kubernetes-4-persistent-volumes-hello-world\/\">Kubernetes (4): Persistent Volumes &#8211; Hello World<\/a><\/p><\/blockquote>\n<p><iframe class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" style=\"position: absolute; clip: rect(1px, 1px, 1px, 1px);\" title=\"&#8222;Kubernetes (4): Persistent Volumes &#8211; Hello World&#8220; &#8212; \" src=\"https:\/\/vocon-it.com\/2018\/12\/10\/kubernetes-4-persistent-volumes-hello-world\/embed\/#?secret=PfxfQ17LpF\" data-secret=\"PfxfQ17LpF\" width=\"600\" height=\"338\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe><\/div>\n<p>&nbsp;<\/p>\n<div class=\"entry-content-asset videofit\">\n<blockquote class=\"wp-embedded-content\" data-secret=\"pYhnMATSU7\"><p><a href=\"https:\/\/vocon-it.com\/2018\/12\/20\/kubernetes-local-persistent-volumes\/\">Kubernetes (5) Local Persistent Volumes &#8211; A Step-by-Step Tutorial<\/a><\/p><\/blockquote>\n<p><iframe class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" style=\"position: absolute; clip: rect(1px, 1px, 1px, 1px);\" title=\"&#8222;Kubernetes (5) Local Persistent Volumes &#8211; A Step-by-Step Tutorial&#8220; &#8212; \" src=\"https:\/\/vocon-it.com\/2018\/12\/20\/kubernetes-local-persistent-volumes\/embed\/#?secret=pYhnMATSU7\" data-secret=\"pYhnMATSU7\" width=\"600\" height=\"338\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe><\/div>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>W jaki spos\u00f3b mo\u017cna w \u015brodowisku skonteneryzowanym utrzymywa\u0107 dane i stan ? &nbsp; Jak wiadomo ka\u017cdy kontener ma sw\u00f3j system plik\u00f3w dost\u0119pny tylko dla niego. Ten system jest ulotny (efemeryczny). Oznacza to, ze wszelki dane jakie zapiszemy w kontenerze podczas &hellip; <a href=\"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/\">Continued<\/a><\/p>\n","protected":false},"author":1,"featured_media":1060,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[22,27,23,26],"tags":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v19.13 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Certified Kubernetes Administrator (CKA) krok po kroku - cz\u0119\u015b\u0107 5 - W chmurze o chmurze i nie tylko<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/\" \/>\n<meta property=\"og:locale\" content=\"pl_PL\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Certified Kubernetes Administrator (CKA) krok po kroku - cz\u0119\u015b\u0107 5 - W chmurze o chmurze i nie tylko\" \/>\n<meta property=\"og:description\" content=\"W jaki spos\u00f3b mo\u017cna w \u015brodowisku skonteneryzowanym utrzymywa\u0107 dane i stan ? &nbsp; Jak wiadomo ka\u017cdy kontener ma sw\u00f3j system plik\u00f3w dost\u0119pny tylko dla niego. Ten system jest ulotny (efemeryczny). Oznacza to, ze wszelki dane jakie zapiszemy w kontenerze podczas &hellip; Continued\" \/>\n<meta property=\"og:url\" content=\"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/\" \/>\n<meta property=\"og:site_name\" content=\"W chmurze o chmurze i nie tylko\" \/>\n<meta property=\"article:published_time\" content=\"2021-06-20T21:33:13+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-06-22T20:27:38+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/wchmurze.cloud\/wp-content\/uploads\/2019\/08\/Kubernetes_New.png\" \/>\n\t<meta property=\"og:image:width\" content=\"730\" \/>\n\t<meta property=\"og:image:height\" content=\"389\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"djkormo\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Napisane przez\" \/>\n\t<meta name=\"twitter:data1\" content=\"djkormo\" \/>\n\t<meta name=\"twitter:label2\" content=\"Szacowany czas czytania\" \/>\n\t<meta name=\"twitter:data2\" content=\"23 minuty\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/\"},\"author\":{\"name\":\"djkormo\",\"@id\":\"https:\/\/wchmurze.cloud\/#\/schema\/person\/9832cc6f86f99f541d983d2b8d60f323\"},\"headline\":\"Certified Kubernetes Administrator (CKA) krok po kroku &#8211; cz\u0119\u015b\u0107 5\",\"datePublished\":\"2021-06-20T21:33:13+00:00\",\"dateModified\":\"2021-06-22T20:27:38+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/\"},\"wordCount\":3797,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/wchmurze.cloud\/#\/schema\/person\/9832cc6f86f99f541d983d2b8d60f323\"},\"articleSection\":[\"Certyfikacja\",\"CKA\",\"konteneryzacja\",\"Kubernetes\"],\"inLanguage\":\"pl-PL\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/\",\"url\":\"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/\",\"name\":\"Certified Kubernetes Administrator (CKA) krok po kroku - cz\u0119\u015b\u0107 5 - W chmurze o chmurze i nie tylko\",\"isPartOf\":{\"@id\":\"https:\/\/wchmurze.cloud\/#website\"},\"datePublished\":\"2021-06-20T21:33:13+00:00\",\"dateModified\":\"2021-06-22T20:27:38+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/#breadcrumb\"},\"inLanguage\":\"pl-PL\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Strona g\u0142\u00f3wna\",\"item\":\"https:\/\/wchmurze.cloud\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Certified Kubernetes Administrator (CKA) krok po kroku &#8211; cz\u0119\u015b\u0107 5\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/wchmurze.cloud\/#website\",\"url\":\"https:\/\/wchmurze.cloud\/\",\"name\":\"W chmurze o chmurze i nie tylko\",\"description\":\"W chmurze o chmurze i nie tylko\",\"publisher\":{\"@id\":\"https:\/\/wchmurze.cloud\/#\/schema\/person\/9832cc6f86f99f541d983d2b8d60f323\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/wchmurze.cloud\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"pl-PL\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/wchmurze.cloud\/#\/schema\/person\/9832cc6f86f99f541d983d2b8d60f323\",\"name\":\"djkormo\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pl-PL\",\"@id\":\"https:\/\/wchmurze.cloud\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/14a901b808871fa98086ae259c45d646?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/14a901b808871fa98086ae259c45d646?s=96&d=mm&r=g\",\"caption\":\"djkormo\"},\"logo\":{\"@id\":\"https:\/\/wchmurze.cloud\/#\/schema\/person\/image\/\"},\"url\":\"https:\/\/wchmurze.cloud\/index.php\/author\/djkormo\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Certified Kubernetes Administrator (CKA) krok po kroku - cz\u0119\u015b\u0107 5 - W chmurze o chmurze i nie tylko","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/","og_locale":"pl_PL","og_type":"article","og_title":"Certified Kubernetes Administrator (CKA) krok po kroku - cz\u0119\u015b\u0107 5 - W chmurze o chmurze i nie tylko","og_description":"W jaki spos\u00f3b mo\u017cna w \u015brodowisku skonteneryzowanym utrzymywa\u0107 dane i stan ? &nbsp; Jak wiadomo ka\u017cdy kontener ma sw\u00f3j system plik\u00f3w dost\u0119pny tylko dla niego. Ten system jest ulotny (efemeryczny). Oznacza to, ze wszelki dane jakie zapiszemy w kontenerze podczas &hellip; Continued","og_url":"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/","og_site_name":"W chmurze o chmurze i nie tylko","article_published_time":"2021-06-20T21:33:13+00:00","article_modified_time":"2021-06-22T20:27:38+00:00","og_image":[{"width":730,"height":389,"url":"https:\/\/wchmurze.cloud\/wp-content\/uploads\/2019\/08\/Kubernetes_New.png","type":"image\/png"}],"author":"djkormo","twitter_card":"summary_large_image","twitter_misc":{"Napisane przez":"djkormo","Szacowany czas czytania":"23 minuty"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/#article","isPartOf":{"@id":"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/"},"author":{"name":"djkormo","@id":"https:\/\/wchmurze.cloud\/#\/schema\/person\/9832cc6f86f99f541d983d2b8d60f323"},"headline":"Certified Kubernetes Administrator (CKA) krok po kroku &#8211; cz\u0119\u015b\u0107 5","datePublished":"2021-06-20T21:33:13+00:00","dateModified":"2021-06-22T20:27:38+00:00","mainEntityOfPage":{"@id":"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/"},"wordCount":3797,"commentCount":0,"publisher":{"@id":"https:\/\/wchmurze.cloud\/#\/schema\/person\/9832cc6f86f99f541d983d2b8d60f323"},"articleSection":["Certyfikacja","CKA","konteneryzacja","Kubernetes"],"inLanguage":"pl-PL","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/","url":"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/","name":"Certified Kubernetes Administrator (CKA) krok po kroku - cz\u0119\u015b\u0107 5 - W chmurze o chmurze i nie tylko","isPartOf":{"@id":"https:\/\/wchmurze.cloud\/#website"},"datePublished":"2021-06-20T21:33:13+00:00","dateModified":"2021-06-22T20:27:38+00:00","breadcrumb":{"@id":"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/#breadcrumb"},"inLanguage":"pl-PL","potentialAction":[{"@type":"ReadAction","target":["https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/wchmurze.cloud\/index.php\/2021\/06\/20\/certified-kubernetes-administrator-cka-krok-po-kroku-czesc-5\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Strona g\u0142\u00f3wna","item":"https:\/\/wchmurze.cloud\/"},{"@type":"ListItem","position":2,"name":"Certified Kubernetes Administrator (CKA) krok po kroku &#8211; cz\u0119\u015b\u0107 5"}]},{"@type":"WebSite","@id":"https:\/\/wchmurze.cloud\/#website","url":"https:\/\/wchmurze.cloud\/","name":"W chmurze o chmurze i nie tylko","description":"W chmurze o chmurze i nie tylko","publisher":{"@id":"https:\/\/wchmurze.cloud\/#\/schema\/person\/9832cc6f86f99f541d983d2b8d60f323"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/wchmurze.cloud\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"pl-PL"},{"@type":["Person","Organization"],"@id":"https:\/\/wchmurze.cloud\/#\/schema\/person\/9832cc6f86f99f541d983d2b8d60f323","name":"djkormo","image":{"@type":"ImageObject","inLanguage":"pl-PL","@id":"https:\/\/wchmurze.cloud\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/14a901b808871fa98086ae259c45d646?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/14a901b808871fa98086ae259c45d646?s=96&d=mm&r=g","caption":"djkormo"},"logo":{"@id":"https:\/\/wchmurze.cloud\/#\/schema\/person\/image\/"},"url":"https:\/\/wchmurze.cloud\/index.php\/author\/djkormo\/"}]}},"_links":{"self":[{"href":"https:\/\/wchmurze.cloud\/index.php\/wp-json\/wp\/v2\/posts\/1367"}],"collection":[{"href":"https:\/\/wchmurze.cloud\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wchmurze.cloud\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wchmurze.cloud\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wchmurze.cloud\/index.php\/wp-json\/wp\/v2\/comments?post=1367"}],"version-history":[{"count":40,"href":"https:\/\/wchmurze.cloud\/index.php\/wp-json\/wp\/v2\/posts\/1367\/revisions"}],"predecessor-version":[{"id":1565,"href":"https:\/\/wchmurze.cloud\/index.php\/wp-json\/wp\/v2\/posts\/1367\/revisions\/1565"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wchmurze.cloud\/index.php\/wp-json\/wp\/v2\/media\/1060"}],"wp:attachment":[{"href":"https:\/\/wchmurze.cloud\/index.php\/wp-json\/wp\/v2\/media?parent=1367"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wchmurze.cloud\/index.php\/wp-json\/wp\/v2\/categories?post=1367"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wchmurze.cloud\/index.php\/wp-json\/wp\/v2\/tags?post=1367"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}