Отже у нас вже є готовий налаштований кластер і, озброївшись необхідним теоретичним мінімумом, ми можемо переходити до подальшого вивчення Kubernetes. Цього разу ми поговоримо детальніше про основні примітиви (objects) Kubernetes, як вони взаємодіють між собою та як реалізовані.
Забігаючи наперед, основні команд для отримання даних про роботу об'єктів є наступні:
ПОД (POD). Створимо под, що буде складатись з одного docker-контейнера і буде доступний на порту 9876. Для цього використаємо образ з dockerhub mhausenblas/simpleservice:0.5.0:
$ kubectl run first-pod --image=mhausenblas/simpleservice:0.5.0 --port=9876
Забігаючи наперед, основні команд для отримання даних про роботу об'єктів є наступні:
- kubectl get object_type - перерахунок всіх об'єктів даного типу, котрі знаходяться в межах одного неймспейсу
- kubectl describe object_type - детальна інформація про всі об'єкт даного типу, що також знаходяться в одному неймспейсі
ПОД (POD). Створимо под, що буде складатись з одного docker-контейнера і буде доступний на порту 9876. Для цього використаємо образ з dockerhub mhausenblas/simpleservice:0.5.0:
$ kubectl run first-pod --image=mhausenblas/simpleservice:0.5.0 --port=9876
deployment "first-pod" created
Перевіримо чи новий под працює:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
first-pod-2257828502-l6z96 1/1 Running 0 23s
$ kubectl describe pod first-pod-2257828502-l6z96 | grep IP:
IP: 10.34.0.25
Отже, в межах кластеру под працює за адресою 10.34.0.25. Із будь-якого вузла кластеру пересвідчимось в цьому, зробивши запит до додатку:
[cluster]$ curl 10.34.0.25:9876/info
{"host": "10.34.0.25:9876", "version": "0.5.0", "from": "10.32.0.1"}
Звісно зручніше створювати поди використовуючи yaml-опис ресурсу:
$ vim second-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: second-pod
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
resources:
limits:
memory: "64Mi"
cpu: "500m"
- name: shell
image: centos:7
command:
- "bin/bash"
- "-c"
- "sleep 10000"
$ kubectl apply -f second-pod.yaml
Отже, в межах кластеру под працює за адресою 10.34.0.25. Із будь-якого вузла кластеру пересвідчимось в цьому, зробивши запит до додатку:
[cluster]$ curl 10.34.0.25:9876/info
{"host": "10.34.0.25:9876", "version": "0.5.0", "from": "10.32.0.1"}
Звісно зручніше створювати поди використовуючи yaml-опис ресурсу:
$ vim second-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: second-pod
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
resources:
limits:
memory: "64Mi"
cpu: "500m"
- name: shell
image: centos:7
command:
- "bin/bash"
- "-c"
- "sleep 10000"
$ kubectl apply -f second-pod.yaml
pod "second-pod" created
$ kubectl get pods
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
second-pod 2/2 Running 0 16s
Як видно з опису, под складається з 2 контейнерів: із іменем sise та shell. Перший контейнер також має встановлені ліміти використання пам’яті та центрального процесору (64MB RAM та 0.5 CPUs). Знаючи ім’я поду та контейнера, можна отримати термінальний доступ до нього:
$ kubectl exec second-pod -c sise -i -t -- bash
second-pod 2/2 Running 0 16s
Як видно з опису, под складається з 2 контейнерів: із іменем sise та shell. Перший контейнер також має встановлені ліміти використання пам’яті та центрального процесору (64MB RAM та 0.5 CPUs). Знаючи ім’я поду та контейнера, можна отримати термінальний доступ до нього:
$ kubectl exec second-pod -c sise -i -t -- bash
[root@second-pod /]# curl localhost:9876/info
{"host": "localhost:9876", "version": "0.5.0", "from": "127.0.0.1"}
Синтаксис майже аналогічний тому, що використовується для доступу до контейнерів Docker.
Більше сервісних даних можна отримати за допомогою наступної команди:
$ kubectl describe pod second-pod
{"host": "localhost:9876", "version": "0.5.0", "from": "127.0.0.1"}
Синтаксис майже аналогічний тому, що використовується для доступу до контейнерів Docker.
Більше сервісних даних можна отримати за допомогою наступної команди:
$ kubectl describe pod second-pod
Name: second-pod
Namespace: default
Node: k8s-s3/192.168.60.113
Start Time: Sun, 01 Oct 2017 17:25:08 -0400
Labels: <none>
Annotations: ...
Status: Running
IP: 10.34.0.38
Containers:
sise:
Container ID: ...
Image: mhausenblas/simpleservice:0.5.0
Image ID: ...
Port: 9876/TCP
State: Running
Started: Sun, 01 Oct 2017 17:25:08 -0400
Ready: True
Restart Count: 0
Limits:
cpu: 500m
memory: 64Mi
Requests:
cpu: 500m
memory: 64Mi
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-k016d (ro)
shell:
Container ID: ...
Image: centos:7
Image ID: ...
Port: <none>
Command:
bin/bash
-c
sleep 10000
State: Running
Started: Sun, 01 Oct 2017 17:25:08 -0400
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-k016d (ro)
Conditions:
Type Status
Initialized True
Ready True
PodScheduled True
Volumes:
default-token-k016d:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-k016d
Optional: false
QoS Class: Burstable
Node-Selectors: <none>
Tolerations: node.alpha.kubernetes.io/notReady:NoExecute for 300s
node.alpha.kubernetes.io/unreachable:NoExecute for 300s
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
...
4m 4m 1 kubelet, k8s-s3 spec.containers{shell} Normal Started Started container
Є можливість вручну вказувати вузол, на котрому необхідно запустити под. Це робиться наступним чином:
$ kubectl label nodes k8s-s1 shouldrun=here
Namespace: default
Node: k8s-s3/192.168.60.113
Start Time: Sun, 01 Oct 2017 17:25:08 -0400
Labels: <none>
Annotations: ...
Status: Running
IP: 10.34.0.38
Containers:
sise:
Container ID: ...
Image: mhausenblas/simpleservice:0.5.0
Image ID: ...
Port: 9876/TCP
State: Running
Started: Sun, 01 Oct 2017 17:25:08 -0400
Ready: True
Restart Count: 0
Limits:
cpu: 500m
memory: 64Mi
Requests:
cpu: 500m
memory: 64Mi
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-k016d (ro)
shell:
Container ID: ...
Image: centos:7
Image ID: ...
Port: <none>
Command:
bin/bash
-c
sleep 10000
State: Running
Started: Sun, 01 Oct 2017 17:25:08 -0400
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-k016d (ro)
Conditions:
Type Status
Initialized True
Ready True
PodScheduled True
Volumes:
default-token-k016d:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-k016d
Optional: false
QoS Class: Burstable
Node-Selectors: <none>
Tolerations: node.alpha.kubernetes.io/notReady:NoExecute for 300s
node.alpha.kubernetes.io/unreachable:NoExecute for 300s
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
...
4m 4m 1 kubelet, k8s-s3 spec.containers{shell} Normal Started Started container
Є можливість вручну вказувати вузол, на котрому необхідно запустити под. Це робиться наступним чином:
$ kubectl label nodes k8s-s1 shouldrun=here
node "k8s-s1" labeled
Ми призначили мітку shouldrun=here вузлу k8s-s1. Після чого опишемо і запустимо под, котрий буде запущено цьому вузлі:
$ vim specific-pod-node.yaml
apiVersion: v1
kind: Pod
metadata:
name: specific-pod-node
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
nodeSelector:
shouldrun: here
$ kubectl apply -f specific-pod-node.yaml
$ kubectl get pods --output=wide
Ми призначили мітку shouldrun=here вузлу k8s-s1. Після чого опишемо і запустимо под, котрий буде запущено цьому вузлі:
$ vim specific-pod-node.yaml
apiVersion: v1
kind: Pod
metadata:
name: specific-pod-node
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
nodeSelector:
shouldrun: here
$ kubectl apply -f specific-pod-node.yaml
$ kubectl get pods --output=wide
NAME READY STATUS RESTARTS AGE IP NODE
specific-pod-node 1/1 Running 0 1m 10.40.0.34 k8s-s1
Для контейнерів в поді є механізм перевірки роботи додатків (health checks). Probes, як їх називають в Kubernetes, виконуються процесом kubelet для того, щоб визначити чи потрібно його перестворити (livenessProbe) у разі проблем з роботою; чи ініціюються сервісом (об'єкт Kubernetes), щоб зрозуміти чи має под отримувати трафік (readinessProbe) і т.п. Піднімемо наступний под для демонстрації підключення хелсчеків:
$ vim pod-healthcheck1.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-healthcheck1
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
livenessProbe:
initialDelaySeconds: 2
periodSeconds: 5
httpGet:
path: /health
port: 9876
$ kubectl apply -f pod-healthcheck1.yaml
$ kubectl get pods
specific-pod-node 1/1 Running 0 1m 10.40.0.34 k8s-s1
Для контейнерів в поді є механізм перевірки роботи додатків (health checks). Probes, як їх називають в Kubernetes, виконуються процесом kubelet для того, щоб визначити чи потрібно його перестворити (livenessProbe) у разі проблем з роботою; чи ініціюються сервісом (об'єкт Kubernetes), щоб зрозуміти чи має под отримувати трафік (readinessProbe) і т.п. Піднімемо наступний под для демонстрації підключення хелсчеків:
$ vim pod-healthcheck1.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-healthcheck1
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
livenessProbe:
initialDelaySeconds: 2
periodSeconds: 5
httpGet:
path: /health
port: 9876
$ kubectl apply -f pod-healthcheck1.yaml
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
pod-healthcheck1 1/1 Running 0 7s
Тут потрібно звернути увагу на секцію livenessProbe, де вказано, що через 2 секунди після старту контейнера sise, кожні 5 секунд на порт 9876 буде надсилатись GET-запит по шляху /health. У разі повернення не 200 коду контейнер буде перестворено автоматично. Звісно, що для роботи цього механізму додаток має бути написаний відповідним чином, тобто на запит на 9876 порт та вищезгаданий шлях програма має віддавати коректний статус код.
Перевірка readinessProbe оголошується майже аналогічно:
$ vim pod-healthcheck2.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-healthcheck2
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
readinessProbe:
initialDelaySeconds: 10
httpGet:
path: /health
port: 9876
$ kubectl apply -f pod-healthcheck2.yaml
У цьому ж разі под pod-healthcheck2 буде ввімкнений в сервіс (тобто на нього буде спрямовано трафік) лише у разі повернення коду 200 від додатку. Запуск першої перевірки відбудеться через 10 секунд після старту поду (на випадок якщо необхідно завантажити якісь дані з 3-го сервісу чи щось на зразок цього). Більше про хелсчеки можна почитати за посиланням https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/.
Для того, щоб відправити довільну змінну середовища, до опису поду має бути додана секція env:
$ vim pod-env.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-env
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
env:
- name: SIMPLE_SERVICE_VERSION
value: "1.0"
$ kubectl apply -f pod-env.yaml
$ kubectl exec pod-env -- printenv
pod-healthcheck1 1/1 Running 0 7s
Тут потрібно звернути увагу на секцію livenessProbe, де вказано, що через 2 секунди після старту контейнера sise, кожні 5 секунд на порт 9876 буде надсилатись GET-запит по шляху /health. У разі повернення не 200 коду контейнер буде перестворено автоматично. Звісно, що для роботи цього механізму додаток має бути написаний відповідним чином, тобто на запит на 9876 порт та вищезгаданий шлях програма має віддавати коректний статус код.
Перевірка readinessProbe оголошується майже аналогічно:
$ vim pod-healthcheck2.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-healthcheck2
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
readinessProbe:
initialDelaySeconds: 10
httpGet:
path: /health
port: 9876
$ kubectl apply -f pod-healthcheck2.yaml
У цьому ж разі под pod-healthcheck2 буде ввімкнений в сервіс (тобто на нього буде спрямовано трафік) лише у разі повернення коду 200 від додатку. Запуск першої перевірки відбудеться через 10 секунд після старту поду (на випадок якщо необхідно завантажити якісь дані з 3-го сервісу чи щось на зразок цього). Більше про хелсчеки можна почитати за посиланням https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/.
Для того, щоб відправити довільну змінну середовища, до опису поду має бути додана секція env:
$ vim pod-env.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-env
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
env:
- name: SIMPLE_SERVICE_VERSION
value: "1.0"
$ kubectl apply -f pod-env.yaml
$ kubectl exec pod-env -- printenv
PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=pod-env
SIMPLE_SERVICE_VERSION=1.0
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
LANG=C.UTF-8
GPG_KEY=C01E1CAD5EA2C4F0B8E3571504C367C218ADD4FF
PYTHON_VERSION=2.7.13
PYTHON_PIP_VERSION=9.0.1
REFRESHED_AT=2017-04-24T13:50
HOME=/root
Проте виливати поди напряму не найкраща ідея, адже в такому разі не буде доступне їх перестворення у разі падіння, масштабування, зручний деплой/ролбек коду, зміни їх параметрів і т.п. Тому варто створювати поди в контексті deployment примітиву.
МІТКА ТА СЕЛЕКТОР (LEBEL, SELECTOR). Мітки до об’єктів Kubernetes можуть призначатись виходячи з дуже різноманітної логіки. Наприклад, мітка може вказувати на те, хто є відповідальним за роботу поду чи до якого середовища він відноситься (dev, prod). Окрім того, виходячи з назви мітки, до об’єктів можуть бути прив’язані інші об’єкти за допомогою опції selector. Наприклад, до подів з міткою app: sise може бути прив’язаний сервіс з таким же селектором.
Для прикладу створимо под з міткою env=development:
$ vim pod-label.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-label
labels:
env: development
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
$ kubectl apply -f pod-label.yaml
Перевіримо чи була встановлена мітка:
$ kubectl get pods --show-labels
HOSTNAME=pod-env
SIMPLE_SERVICE_VERSION=1.0
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
LANG=C.UTF-8
GPG_KEY=C01E1CAD5EA2C4F0B8E3571504C367C218ADD4FF
PYTHON_VERSION=2.7.13
PYTHON_PIP_VERSION=9.0.1
REFRESHED_AT=2017-04-24T13:50
HOME=/root
Проте виливати поди напряму не найкраща ідея, адже в такому разі не буде доступне їх перестворення у разі падіння, масштабування, зручний деплой/ролбек коду, зміни їх параметрів і т.п. Тому варто створювати поди в контексті deployment примітиву.
МІТКА ТА СЕЛЕКТОР (LEBEL, SELECTOR). Мітки до об’єктів Kubernetes можуть призначатись виходячи з дуже різноманітної логіки. Наприклад, мітка може вказувати на те, хто є відповідальним за роботу поду чи до якого середовища він відноситься (dev, prod). Окрім того, виходячи з назви мітки, до об’єктів можуть бути прив’язані інші об’єкти за допомогою опції selector. Наприклад, до подів з міткою app: sise може бути прив’язаний сервіс з таким же селектором.
Для прикладу створимо под з міткою env=development:
$ vim pod-label.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-label
labels:
env: development
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
$ kubectl apply -f pod-label.yaml
Перевіримо чи була встановлена мітка:
$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
pod-label 1/1 Running 0 32s env=development
Мітки можуть бути додані до вже створених подів:
$ kubectl label pods pod-label owner=ipeacocks
pod-label 1/1 Running 0 32s env=development
Мітки можуть бути додані до вже створених подів:
$ kubectl label pods pod-label owner=ipeacocks
pod "pod-label" labeled
$ kubectl get pods --show-labels
$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
pod-label 1/1 Running 0 6m env=development,owner=ipeacocks
Виходячи з доступних міток можна робити вибірки:
$ kubectl get pods --selector owner=ipeacocks
NAME READY STATUS RESTARTS AGE
pod-label 1/1 Running 0 7m
Ці вибірки в тому числі можуть бути комплексні. На зразок наступної операції OR:
$ kubectl get pods -l 'env in (production, development)'
-l - скорочений варіант опції --selector.
НАБІР/МНОЖИНА РЕПЛІК (REPICA SETS). Рівень абстракції над подами, котрий можна створити наступним чином:
$ vim replicaset-x.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: replicaset-x
spec:
replicas: 3
selector:
matchLabels:
app: replicaset-x
template:
metadata:
name: replicaset-x
labels:
app: replicaset-x
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
$ kubectl apply -f replicaset-x.yaml
Отже, було створено набір реплік replicaset-x, котрий має складатись із 3 однакових подів зі встановленою міткою app: replicaset-x, на що вказує опція matchLabels. Перевіримо це:
$ kubectl get rs
pod-label 1/1 Running 0 7m
Ці вибірки в тому числі можуть бути комплексні. На зразок наступної операції OR:
$ kubectl get pods -l 'env in (production, development)'
-l - скорочений варіант опції --selector.
НАБІР/МНОЖИНА РЕПЛІК (REPICA SETS). Рівень абстракції над подами, котрий можна створити наступним чином:
$ vim replicaset-x.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: replicaset-x
spec:
replicas: 3
selector:
matchLabels:
app: replicaset-x
template:
metadata:
name: replicaset-x
labels:
app: replicaset-x
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
$ kubectl apply -f replicaset-x.yaml
Отже, було створено набір реплік replicaset-x, котрий має складатись із 3 однакових подів зі встановленою міткою app: replicaset-x, на що вказує опція matchLabels. Перевіримо це:
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
replicaset-x 3 3 3 37s
$ kubectl get pods --show-labels
replicaset-x 3 3 3 37s
$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
replicaset-x-39t0n 1/1 Running 0 2m app=replicaset-x
replicaset-x-dm96t 1/1 Running 0 2m app=replicaset-x
replicaset-x-mqdll 1/1 Running 0 2m app=replicaset-x
Звісно, що можна як збільшувати кількість подів у репліках, так і зменшувати:
$ kubectl scale --replicas=1 rs replicaset-x
replicaset-x-39t0n 1/1 Running 0 2m app=replicaset-x
replicaset-x-dm96t 1/1 Running 0 2m app=replicaset-x
replicaset-x-mqdll 1/1 Running 0 2m app=replicaset-x
Звісно, що можна як збільшувати кількість подів у репліках, так і зменшувати:
$ kubectl scale --replicas=1 rs replicaset-x
replicaset "replicaset-x" scaled
$ kubectl get pods -l app=replicaset-x
$ kubectl get pods -l app=replicaset-x
NAME READY STATUS RESTARTS AGE
replicaset-x-39t0n 1/1 Running 0 4m
replicaset-x-dm96t 1/1 Terminating 0 4m
replicaset-x-mqdll 1/1 Terminating 0 4m
Знову ж виливати поди напряму через ReplicaSet не рекомендується. ReplicaSet вже входить в контекст об’єкту Deployment, який наглядає за історією подів (rolling-update команда) та кількістю їх інстансів.
ДЕПЛОЙМЕНТ (DEPLOYMENT). Створюється наступним чином:
$ vim deployment-09.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-09
spec:
replicas: 2
selector:
matchLabels:
app: sise
template:
metadata:
labels:
app: sise
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
env:
- name: SIMPLE_SERVICE_VERSION
value: "0.9"
$ kubectl apply -f deployment-09.yaml
deployment "deployment-09" created
Цей деплоймент одразу призведе до виливки реплікасету та подів в ньому:
$ kubectl get deploy
replicaset-x-39t0n 1/1 Running 0 4m
replicaset-x-dm96t 1/1 Terminating 0 4m
replicaset-x-mqdll 1/1 Terminating 0 4m
Знову ж виливати поди напряму через ReplicaSet не рекомендується. ReplicaSet вже входить в контекст об’єкту Deployment, який наглядає за історією подів (rolling-update команда) та кількістю їх інстансів.
ДЕПЛОЙМЕНТ (DEPLOYMENT). Створюється наступним чином:
$ vim deployment-09.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-09
spec:
replicas: 2
selector:
matchLabels:
app: sise
template:
metadata:
labels:
app: sise
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
env:
- name: SIMPLE_SERVICE_VERSION
value: "0.9"
$ kubectl apply -f deployment-09.yaml
deployment "deployment-09" created
Цей деплоймент одразу призведе до виливки реплікасету та подів в ньому:
$ kubectl get deploy
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deployment-09 2 2 2 2 17s
$ kubectl get rs
deployment-09 2 2 2 2 17s
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
deployment-09-4084969740 2 2 2 30s
$ kubectl get pods
deployment-09-4084969740 2 2 2 30s
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
deployment-09-4084969740-g4756 1/1 Running 0 34s
deployment-09-4084969740-gw4df 1/1 Running 0 34s
Через змінну середовища (env) було передано версію сервісу, що працює в контейнері поду. Перевіримо чи вищезгаданий сервіс справді повертає це значення:
$ kubectl describe pod deployment-09-4084969740-g4756
deployment-09-4084969740-g4756 1/1 Running 0 34s
deployment-09-4084969740-gw4df 1/1 Running 0 34s
Через змінну середовища (env) було передано версію сервісу, що працює в контейнері поду. Перевіримо чи вищезгаданий сервіс справді повертає це значення:
$ kubectl describe pod deployment-09-4084969740-g4756
Name: deployment-09-4084969740-g4756
Namespace: default
Node: k8s-s2/192.168.60.112
Start Time: Sun, 01 Oct 2017 19:42:59 -0400
Labels: app=sise
pod-template-hash=4084969740
...
Status: Running
IP: 10.38.0.35
Created By: ReplicaSet/deployment-09-4084969740
Controlled By: ReplicaSet/deployment-09-4084969740
Containers:
sise:
...
Environment:
SIMPLE_SERVICE_VERSION: 0.9
...
[cluster] $ curl 10.38.0.35:9876/info
{"host": "10.38.0.35:9876", "version": "0.9", "from": "10.32.0.1"}
Відредагуємо змінну SIMPLE_SERVICE_VERSION і встановимо її в значення 1.0:
$ vim deployment-09.yaml
Після чого застосуємо зміни, на попередній деплоймент:
$ kubectl apply -f deployment-09.yaml
Namespace: default
Node: k8s-s2/192.168.60.112
Start Time: Sun, 01 Oct 2017 19:42:59 -0400
Labels: app=sise
pod-template-hash=4084969740
...
Status: Running
IP: 10.38.0.35
Created By: ReplicaSet/deployment-09-4084969740
Controlled By: ReplicaSet/deployment-09-4084969740
Containers:
sise:
...
Environment:
SIMPLE_SERVICE_VERSION: 0.9
...
[cluster] $ curl 10.38.0.35:9876/info
{"host": "10.38.0.35:9876", "version": "0.9", "from": "10.32.0.1"}
Відредагуємо змінну SIMPLE_SERVICE_VERSION і встановимо її в значення 1.0:
$ vim deployment-09.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-09
spec:
replicas: 2
selector:
matchLabels:
app: sise
template:
metadata:
labels:
app: sise
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
env:
- name: SIMPLE_SERVICE_VERSION
value: "1.0"
Після чого застосуємо зміни, на попередній деплоймент:
$ kubectl apply -f deployment-09.yaml
ReplicaSet-и та прості поди не дозволено оновлювати після змін параметрів. Єдиний варіант - це перезалити їх заново.
Окрім оновлення yaml-у виливки можна було напряму відредагувати деплоймент за допомогою наступної команди:
$ kubectl edit deployment deployment-09
У процесі оновлення буде помітно як створюються нові поди та реплікасет:
$ kubectl get pods
Окрім оновлення yaml-у виливки можна було напряму відредагувати деплоймент за допомогою наступної команди:
$ kubectl edit deployment deployment-09
У процесі оновлення буде помітно як створюються нові поди та реплікасет:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
deployment-09-2996259344-m887q 1/1 Running 0 24s
deployment-09-2996259344-qwd0f 1/1 Running 0 24s
deployment-09-4084969740-g4756 1/1 Terminating 0 3h
deployment-09-4084969740-gw4df 1/1 Terminating 0 3h
$ kubectl get rs
deployment-09-2996259344-m887q 1/1 Running 0 24s
deployment-09-2996259344-qwd0f 1/1 Running 0 24s
deployment-09-4084969740-g4756 1/1 Terminating 0 3h
deployment-09-4084969740-gw4df 1/1 Terminating 0 3h
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
sise-deploy-2958877261 2 2 2 28s
sise-deploy-3513442901 0 0 0 3h
Попередні поди будуть зупинені, а нові будуть запущені з новою змінною середовища SIMPLE_SERVICE_VERSION.
Впродовж виливки нового деплойменту за прогресом цього процесу можна спостерігати наступною командою:
$ kubectl rollout status deployment deployment-09
sise-deploy-2958877261 2 2 2 28s
sise-deploy-3513442901 0 0 0 3h
Попередні поди будуть зупинені, а нові будуть запущені з новою змінною середовища SIMPLE_SERVICE_VERSION.
Впродовж виливки нового деплойменту за прогресом цього процесу можна спостерігати наступною командою:
$ kubectl rollout status deployment deployment-09
Waiting for rollout to finish: 1 out of 2 new replicas have been updated...
deployment "deployment-09" successfully rolled out
Як і в попередньому випадку, за допомогою 'kubectl describe pod' дізнаємось про нову адресу поду, щоб пересвідчитись на практиці, що зміни в додатку відбулись:
$ kubectl describe pod deployment-09-2996259344-m887q | grep IP:
deployment "deployment-09" successfully rolled out
Як і в попередньому випадку, за допомогою 'kubectl describe pod' дізнаємось про нову адресу поду, щоб пересвідчитись на практиці, що зміни в додатку відбулись:
$ kubectl describe pod deployment-09-2996259344-m887q | grep IP:
IP: 10.34.0.38
[cluster] $ curl 10.34.0.38:9876/info
{"host": "10.34.0.38:9876", "version": "1.0", "from": "10.32.0.1"}
Kubernetes веде історію всіх оновлень деплойментів:
$ kubectl rollout history deployment deployment-09
[cluster] $ curl 10.34.0.38:9876/info
{"host": "10.34.0.38:9876", "version": "1.0", "from": "10.32.0.1"}
Kubernetes веде історію всіх оновлень деплойментів:
$ kubectl rollout history deployment deployment-09
deployments "deployment-09"
REVISION CHANGE-CAUSE
1 <none>
2 <none>
У разі проблем з виливкою змін Kubernetes самостійно поверне останню стабільну версію, але ж і ніхто не забороняє зробити це самостійно:
$ kubectl rollout undo deployment deployment-09 --to-revision=1
REVISION CHANGE-CAUSE
1 <none>
2 <none>
У разі проблем з виливкою змін Kubernetes самостійно поверне останню стабільну версію, але ж і ніхто не забороняє зробити це самостійно:
$ kubectl rollout undo deployment deployment-09 --to-revision=1
deployment "deployment-09" rolled back
$ kubectl rollout history deployment deployment-09
$ kubectl rollout history deployment deployment-09
deployments "deployment-09"
REVISION CHANGE-CAUSE
2 <none>
3 <none>
$ kubectl get pods
REVISION CHANGE-CAUSE
2 <none>
3 <none>
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
deployment-09-3513442901-ng8fz 1/1 Running 0 1m
deployment-09-3513442901-s8q4s 1/1 Running 0 1m
Як і реплікасети, деплойменти можуть легко масштабуватись горизонтально:
$ kubectl scale --replicas=3 deployment deployment-09
deployment-09-3513442901-ng8fz 1/1 Running 0 1m
deployment-09-3513442901-s8q4s 1/1 Running 0 1m
Як і реплікасети, деплойменти можуть легко масштабуватись горизонтально:
$ kubectl scale --replicas=3 deployment deployment-09
deployment "deployment-09" scaled
Для того щоб видалити всі поди та набір реплік у цьому разі варто лише видалити deployment:
$ kubectl delete deployment deployment-09
Для того щоб видалити всі поди та набір реплік у цьому разі варто лише видалити deployment:
$ kubectl delete deployment deployment-09
deployment "deployment-09" deleted
СЕРВІС (SERVICE). Сервіс прив'язується до вже працюючих подів із відповідними мітками. Справа в тому, що кожна наступна виливка тих же подів зазвичай призводить до того, що їхні адреси в оверлейній мережі змінюються. Сервіс же слідкує за цим і завдяки процесу kube-proxy динамічно перебудовує iptables-правила доступу до кінцевих подів.
Розглянемо на прикладі як це відбувається. Створимо деплоймент із іменем deployment-for-service:
$ vim deployment-for-service.yaml
$ kubectl apply -f deployment-for-service.yaml
Та сервіс із іменем service-for-pods:
$ vim service-for-pods.yaml
$ kubectl apply -f service-for-pods.yaml
service "service-for-pods" created
Після перевіримо поди, які мають бути створені в результаті цього:
$ kubectl get pods -l app=sise
СЕРВІС (SERVICE). Сервіс прив'язується до вже працюючих подів із відповідними мітками. Справа в тому, що кожна наступна виливка тих же подів зазвичай призводить до того, що їхні адреси в оверлейній мережі змінюються. Сервіс же слідкує за цим і завдяки процесу kube-proxy динамічно перебудовує iptables-правила доступу до кінцевих подів.
Розглянемо на прикладі як це відбувається. Створимо деплоймент із іменем deployment-for-service:
$ vim deployment-for-service.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-for-service
spec:
replicas: 1
selector:
matchLabels:
app: sise
template:
metadata:
labels:
app: sise
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
$ kubectl apply -f deployment-for-service.yaml
Та сервіс із іменем service-for-pods:
$ vim service-for-pods.yaml
apiVersion: v1
kind: Service
metadata:
name: service-for-pods
spec:
selector:
app: sise
ports:
- port: 80
targetPort: 9876
$ kubectl apply -f service-for-pods.yaml
service "service-for-pods" created
Після перевіримо поди, які мають бути створені в результаті цього:
$ kubectl get pods -l app=sise
NAME READY STATUS RESTARTS AGE
deployment-for-service-3136624256-q49fv 1/1 Running 0 15m
$ kubectl describe pod deployment-for-service-3136624256-q49fv
deployment-for-service-3136624256-q49fv 1/1 Running 0 15m
$ kubectl describe pod deployment-for-service-3136624256-q49fv
Name: deployment-for-service-3136624256-q49fv
Namespace: default
Node: k8s-s3/192.168.60.113
Start Time: Mon, 02 Oct 2017 07:30:50 +0300
Labels: app=sise
pod-template-hash=3136624256
...
Status: Running
IP: 10.34.0.25
Created By: ReplicaSet/deployment-for-service-3136624256
Controlled By: ReplicaSet/deployment-for-service-3136624256
Containers:
...
З виводу останньої команди бачимо пряму адресу контейнера в оверлейній мережі 10.34.0.25. Перевіримо чи працює сервіс в поді:
[cluster] $ curl 10.34.0.25:9876/info
{"host": "10.34.0.25:9876", "version": "0.5.0", "from": "10.32.0.1"}
Ця адреса буде актуальною лише в межах життєвого циклу поду, котрий може обірватись його перестворенням через деплой нової версії коду, можливі помилки роботи додатку і т.п. Перевіримо адресу щойно створеного сервісу simpleservice:
$ kubectl get svc service-for-pods
Namespace: default
Node: k8s-s3/192.168.60.113
Start Time: Mon, 02 Oct 2017 07:30:50 +0300
Labels: app=sise
pod-template-hash=3136624256
...
Status: Running
IP: 10.34.0.25
Created By: ReplicaSet/deployment-for-service-3136624256
Controlled By: ReplicaSet/deployment-for-service-3136624256
Containers:
...
З виводу останньої команди бачимо пряму адресу контейнера в оверлейній мережі 10.34.0.25. Перевіримо чи працює сервіс в поді:
[cluster] $ curl 10.34.0.25:9876/info
{"host": "10.34.0.25:9876", "version": "0.5.0", "from": "10.32.0.1"}
Ця адреса буде актуальною лише в межах життєвого циклу поду, котрий може обірватись його перестворенням через деплой нової версії коду, можливі помилки роботи додатку і т.п. Перевіримо адресу щойно створеного сервісу simpleservice:
$ kubectl get svc service-for-pods
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service-for-pods 10.103.222.198 <none> 80/TCP 23m
$ kubectl describe svc service-for-pods
service-for-pods 10.103.222.198 <none> 80/TCP 23m
$ kubectl describe svc service-for-pods
Name: service-for-pods
Namespace: default
Labels: <none>
...
Selector: app=sise
Type: ClusterIP
IP: 10.103.222.198
Port: <unset> 80/TCP
Endpoints: 10.34.0.25:9876
Session Affinity: None
Events: <none>
Отже наразі поди, що мають мітку app=sise будуть доступні за адресою 10.103.222.198:
[cluster] $ curl 10.103.222.198:80/info
{"host": "10.103.222.198", "version": "0.5.0", "from": "10.32.0.1"}
Адреса 10.103.222.198 віртуальна, тобто не прив'язана до жодного інтерфейсу. Вона маршрутизується до адрес подів завдяки правилам iptables, котрі створює kube-proxy, і надалі слідкує за ними. Ці правила зручно переглядати завдяки коментарям, в котрих міститься ім'я сервісу, що призвів до їх створення:
[cluster] $ sudo iptables-save | grep service-for-pods
-A KUBE-SEP-XT3CJYIQSQHZ6QSZ -s 10.34.0.25/32 -m comment --comment "default/service-for-pods:" -j KUBE-MARK-MASQ
-A KUBE-SEP-XT3CJYIQSQHZ6QSZ -p tcp -m comment --comment "default/service-for-pods:" -m tcp -j DNAT --to-destination 10.34.0.25:9876
-A KUBE-SERVICES -d 10.103.222.198/32 -p tcp -m comment --comment "default/service-for-pods: cluster IP" -m tcp --dport 80 -j KUBE-SVC-2LEWRE2R3GXDG7LY
-A KUBE-SVC-2LEWRE2R3GXDG7LY -m comment --comment "default/service-for-pods:" -j KUBE-SEP-XT3CJYIQSQHZ6QSZ
Тож, виходячи з цих правил, TCP трафік до адреси 10.103.222.198:80 буде перенаправлятись до 10.34.0.25:9876, що і є нашим подом.
Масштабуємо попередній деплоймент до двох одиниць:
$ kubectl scale --replicas=2 deployment deployment-for-service
Namespace: default
Labels: <none>
...
Selector: app=sise
Type: ClusterIP
IP: 10.103.222.198
Port: <unset> 80/TCP
Endpoints: 10.34.0.25:9876
Session Affinity: None
Events: <none>
Отже наразі поди, що мають мітку app=sise будуть доступні за адресою 10.103.222.198:
[cluster] $ curl 10.103.222.198:80/info
{"host": "10.103.222.198", "version": "0.5.0", "from": "10.32.0.1"}
Адреса 10.103.222.198 віртуальна, тобто не прив'язана до жодного інтерфейсу. Вона маршрутизується до адрес подів завдяки правилам iptables, котрі створює kube-proxy, і надалі слідкує за ними. Ці правила зручно переглядати завдяки коментарям, в котрих міститься ім'я сервісу, що призвів до їх створення:
[cluster] $ sudo iptables-save | grep service-for-pods
-A KUBE-SEP-XT3CJYIQSQHZ6QSZ -s 10.34.0.25/32 -m comment --comment "default/service-for-pods:" -j KUBE-MARK-MASQ
-A KUBE-SEP-XT3CJYIQSQHZ6QSZ -p tcp -m comment --comment "default/service-for-pods:" -m tcp -j DNAT --to-destination 10.34.0.25:9876
-A KUBE-SERVICES -d 10.103.222.198/32 -p tcp -m comment --comment "default/service-for-pods: cluster IP" -m tcp --dport 80 -j KUBE-SVC-2LEWRE2R3GXDG7LY
-A KUBE-SVC-2LEWRE2R3GXDG7LY -m comment --comment "default/service-for-pods:" -j KUBE-SEP-XT3CJYIQSQHZ6QSZ
Тож, виходячи з цих правил, TCP трафік до адреси 10.103.222.198:80 буде перенаправлятись до 10.34.0.25:9876, що і є нашим подом.
Масштабуємо попередній деплоймент до двох одиниць:
$ kubectl scale --replicas=2 deployment deployment-for-service
deployment "deployment-for-service" scaled
$ kubectl get pods -l app=sise -o wide
$ kubectl get pods -l app=sise -o wide
NAME READY STATUS RESTARTS AGE IP NODE
deployment-for-service-3136624256-q49fv 1/1 Running 0 1h 10.34.0.25 k8s-s3
deployment-for-service-3136624256-tt4sh 1/1 Running 0 9m 10.38.0.35 k8s-s2
Після чого знову перевіримо правила iptables:
[cluster] $ sudo iptables-save | grep service-for-pods
-A KUBE-SEP-XT3CJYIQSQHZ6QSZ -s 10.34.0.25/32 -m comment --comment "default/service-for-pods:" -j KUBE-MARK-MASQ
-A KUBE-SEP-XT3CJYIQSQHZ6QSZ -p tcp -m comment --comment "default/service-for-pods:" -m tcp -j DNAT --to-destination 10.34.0.25:9876
-A KUBE-SEP-Z7AWXXEVLG2GJLHC -s 10.38.0.35/32 -m comment --comment "default/service-for-pods:" -j KUBE-MARK-MASQ
-A KUBE-SEP-Z7AWXXEVLG2GJLHC -p tcp -m comment --comment "default/service-for-pods:" -m tcp -j DNAT --to-destination 10.38.0.35:9876
-A KUBE-SERVICES -d 10.103.222.198/32 -p tcp -m comment --comment "default/service-for-pods: cluster IP" -m tcp --dport 80 -j KUBE-SVC-2LEWRE2R3GXDG7LY
-A KUBE-SVC-2LEWRE2R3GXDG7LY -m comment --comment "default/service-for-pods:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-XT3CJYIQSQHZ6QSZ
-A KUBE-SVC-2LEWRE2R3GXDG7LY -m comment --comment "default/service-for-pods:" -j KUBE-SEP-Z7AWXXEVLG2GJLHC
З виводу видно нове правило, окрім ще одного доданого поду з адресою 10.38.0.35:
-A KUBE-SVC-EZC6WLOVQADP4IAW -m comment --comment "default/simpleservice:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-4SQFZS32ZVMTQEZV
Це правило вказує, що трафік буде розподілятись між двома подами порівну (--probability 0.50000000000), що стало можливим завдяки модулю iptables statistics. Звісно це не Round-robin в класичному розумінні. Почитати про це більше можна тут і тут.
Але це ще не все. Завдяки додатку kube-dns, що представлений у вигляді групи подів в системному неймспейсі, сервіси можуть взаємодіяти між собою по автоматично згенерованим доменним іменам. Продемонструю це на наступному прикладі. Створимо сервіс service-disc та деплоймент deploy-disc:
$ vim deploy-disc.yaml
$ vim service-disc.yaml
apiVersion: v1
kind: Service
metadata:
name: service-disc
spec:
ports:
- port: 80
targetPort: 9876
selector:
app: sise
$ kubectl apply -f deploy-disc.yaml
deployment-for-service-3136624256-q49fv 1/1 Running 0 1h 10.34.0.25 k8s-s3
deployment-for-service-3136624256-tt4sh 1/1 Running 0 9m 10.38.0.35 k8s-s2
Після чого знову перевіримо правила iptables:
[cluster] $ sudo iptables-save | grep service-for-pods
-A KUBE-SEP-XT3CJYIQSQHZ6QSZ -s 10.34.0.25/32 -m comment --comment "default/service-for-pods:" -j KUBE-MARK-MASQ
-A KUBE-SEP-XT3CJYIQSQHZ6QSZ -p tcp -m comment --comment "default/service-for-pods:" -m tcp -j DNAT --to-destination 10.34.0.25:9876
-A KUBE-SEP-Z7AWXXEVLG2GJLHC -s 10.38.0.35/32 -m comment --comment "default/service-for-pods:" -j KUBE-MARK-MASQ
-A KUBE-SEP-Z7AWXXEVLG2GJLHC -p tcp -m comment --comment "default/service-for-pods:" -m tcp -j DNAT --to-destination 10.38.0.35:9876
-A KUBE-SERVICES -d 10.103.222.198/32 -p tcp -m comment --comment "default/service-for-pods: cluster IP" -m tcp --dport 80 -j KUBE-SVC-2LEWRE2R3GXDG7LY
-A KUBE-SVC-2LEWRE2R3GXDG7LY -m comment --comment "default/service-for-pods:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-XT3CJYIQSQHZ6QSZ
-A KUBE-SVC-2LEWRE2R3GXDG7LY -m comment --comment "default/service-for-pods:" -j KUBE-SEP-Z7AWXXEVLG2GJLHC
З виводу видно нове правило, окрім ще одного доданого поду з адресою 10.38.0.35:
-A KUBE-SVC-EZC6WLOVQADP4IAW -m comment --comment "default/simpleservice:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-4SQFZS32ZVMTQEZV
Це правило вказує, що трафік буде розподілятись між двома подами порівну (--probability 0.50000000000), що стало можливим завдяки модулю iptables statistics. Звісно це не Round-robin в класичному розумінні. Почитати про це більше можна тут і тут.
Але це ще не все. Завдяки додатку kube-dns, що представлений у вигляді групи подів в системному неймспейсі, сервіси можуть взаємодіяти між собою по автоматично згенерованим доменним іменам. Продемонструю це на наступному прикладі. Створимо сервіс service-disc та деплоймент deploy-disc:
$ vim deploy-disc.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy-disc
spec:
replicas: 1
selector:
matchLabels:
app: sise
template:
metadata:
labels:
app: sise
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
$ vim service-disc.yaml
apiVersion: v1
kind: Service
metadata:
name: service-disc
spec:
ports:
- port: 80
targetPort: 9876
selector:
app: sise
$ kubectl apply -f deploy-disc.yaml
$ kubectl apply -f service-disc.yaml
Припустимо тепер, що ми хочемо підключитись до сервісу service-disc з іншого поду кластера. Для того щоб продемонструвати це, створимо под в цьому ж неймспейсі (по-замовчуванню це default, адже ми його не вказуємо під час виконання команд):
$ vim jumpod.yaml
apiVersion: v1
kind: Pod
metadata:
name: jumpod
spec:
containers:
- name: shell
image: centos:7
command:
- "bin/bash"
- "-c"
- "sleep 10000"
$ kubectl apply -f jumpod.yaml
Завдяки вищезгаданому плагіну сервіс service-disc буде доступним по FQDN service-disc.default.svc.cluster.local (або по трохи коротшому service-disc.default) для всіх подів кластеру і по короткому імені service-disc в межах одного неймспейсу:
$ kubectl exec jumpod -c shell -i -t -- ping service-disc.default.svc.cluster.local
$ vim jumpod.yaml
apiVersion: v1
kind: Pod
metadata:
name: jumpod
spec:
containers:
- name: shell
image: centos:7
command:
- "bin/bash"
- "-c"
- "sleep 10000"
$ kubectl apply -f jumpod.yaml
Завдяки вищезгаданому плагіну сервіс service-disc буде доступним по FQDN service-disc.default.svc.cluster.local (або по трохи коротшому service-disc.default) для всіх подів кластеру і по короткому імені service-disc в межах одного неймспейсу:
$ kubectl exec jumpod -c shell -i -t -- ping service-disc.default.svc.cluster.local
PING service-disc.default.svc.cluster.local (10.110.53.67) 56(84) bytes of data.
...
[cluster] $ kubectl exec jumpod -c shell -i -t -- curl http://service-disc/info
{"host": "service-disc", "version": "0.5.0", "from": "10.38.0.35"}
Де 10.38.0.35 - адреса внутрішньої оверлейної мережі кластера Kubernetes. Отже, якщо розібрати ім'я домену service-disc.default.svc.cluster.local на складові, то service-disc - це ім'я сервісу, а default - неймспейс, в якому цей сервіс створено.
ТОМ (VOLUME). Це директорія, що доступна для всіх контейнерів одного поду. По-замовчуванню кожен контейнер володіє окремим дисковим простором, структура якого оголошується в docker-образі, котрий у разі передеплою чи падіння буде затертий і створений заново. Volume же дозволяє зберегти увесь зміст томів навіть після перестворення контейнерів у поді у разі падінь, але лише до моменту поки под не буде видалений власноруч. Типів томів існує велика множина, тому я продемонструю роботу лише одного типу - emptyDir. Для цього створимо под pod-volume із двох контейнерів:
$ vim pod-volume.yaml
...
[cluster] $ kubectl exec jumpod -c shell -i -t -- curl http://service-disc/info
{"host": "service-disc", "version": "0.5.0", "from": "10.38.0.35"}
Де 10.38.0.35 - адреса внутрішньої оверлейної мережі кластера Kubernetes. Отже, якщо розібрати ім'я домену service-disc.default.svc.cluster.local на складові, то service-disc - це ім'я сервісу, а default - неймспейс, в якому цей сервіс створено.
ТОМ (VOLUME). Це директорія, що доступна для всіх контейнерів одного поду. По-замовчуванню кожен контейнер володіє окремим дисковим простором, структура якого оголошується в docker-образі, котрий у разі передеплою чи падіння буде затертий і створений заново. Volume же дозволяє зберегти увесь зміст томів навіть після перестворення контейнерів у поді у разі падінь, але лише до моменту поки под не буде видалений власноруч. Типів томів існує велика множина, тому я продемонструю роботу лише одного типу - emptyDir. Для цього створимо под pod-volume із двох контейнерів:
$ vim pod-volume.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-volume
spec:
containers:
- name: c1
image: centos:7
command:
- "bin/bash"
- "-c"
- "sleep 10000"
volumeMounts:
- name: xchange
mountPath: "/tmp/xchange"
- name: c2
image: centos:7
command:
- "bin/bash"
- "-c"
- "sleep 10000"
volumeMounts:
- name: xchange
mountPath: "/tmp/data"
volumes:
- name: xchange
emptyDir: {}
$ kubectl apply -f pod-volume.yaml
$ kubectl describe pod pod-volume
Name: pod-volume
Namespace: default
...
Volumes:
xchange:
Type: EmptyDir (a temporary directory that shares a pod's lifetime)
Medium:
У кожному із контейнерів c1 та с2 буде примонтовано один диск по шляху /tmp/xchange та /tmp/data відповідно. Щоб перевірити, що це насправді так, зайдемо в перший контейнер, перевіримо чи примонтований диск та створимо текстовий файл на ньому:
$ kubectl exec pod-volume -c c1 -i -t -- bash
Namespace: default
...
Volumes:
xchange:
Type: EmptyDir (a temporary directory that shares a pod's lifetime)
Medium:
У кожному із контейнерів c1 та с2 буде примонтовано один диск по шляху /tmp/xchange та /tmp/data відповідно. Щоб перевірити, що це насправді так, зайдемо в перший контейнер, перевіримо чи примонтований диск та створимо текстовий файл на ньому:
$ kubectl exec pod-volume -c c1 -i -t -- bash
[root@pod-volume /]# mount | grep xchange
/dev/sda1 on /tmp/xchange type ext4 (rw,relatime,errors=remount-ro,data=ordered)
[root@pod-volume /]# echo 'some data' > /tmp/xchange/data
Із другого спробуємо переглядати зміст цього ж файлу:
$ kubectl exec pod-volume -c c2 -i -t -- bash
/dev/sda1 on /tmp/xchange type ext4 (rw,relatime,errors=remount-ro,data=ordered)
[root@pod-volume /]# echo 'some data' > /tmp/xchange/data
Із другого спробуємо переглядати зміст цього ж файлу:
$ kubectl exec pod-volume -c c2 -i -t -- bash
[root@pod-volume /]# mount | grep /tmp/data
/dev/sda1 on /tmp/data type ext4 (rw,relatime,errors=remount-ro,data=ordered)
[root@pod-volume /]# cat /tmp/data/data
some data
Як бачимо, практика відповідає теорії.
ПРОСТІР ІМЕН (NAMESPACE). Створюється так:
$ vim ns-test.yaml
$ kubectl apply -f ns-test.yaml
$ kubectl get ns
/dev/sda1 on /tmp/data type ext4 (rw,relatime,errors=remount-ro,data=ordered)
[root@pod-volume /]# cat /tmp/data/data
some data
Як бачимо, практика відповідає теорії.
ПРОСТІР ІМЕН (NAMESPACE). Створюється так:
$ vim ns-test.yaml
apiVersion: v1
kind: Namespace
metadata:
name: test
$ kubectl apply -f ns-test.yaml
$ kubectl get ns
NAME STATUS AGE
default Active 71d
ingress Active 30d
kube-public Active 71d
kube-system Active 71d
test Active 8s
$ kubectl describe ns default
ingress Active 30d
kube-public Active 71d
kube-system Active 71d
test Active 8s
$ kubectl describe ns default
Name: default
Labels: <none>
Annotations: <none>
Status: Active
No resource quota.
No resource limits.
Звісно нові об'єкти Kubernetes можна додавати до вже створеного неймспейсу за допомогою ключа --namespace:
$ vim podintest.yaml
$ kubectl apply --namespace=test -f podintest.yaml
Разом з тим бажаний неймспейс для об'єкту можна вказувати в тілі його yaml-опису:
$ vim podintest.yaml
apiVersion: v1
kind: Pod
metadata:
name: podintest
namespace: test
Щоб переглянути, наприклад, поди одного неймспейсу необхідно знову ж використати ключ --namespace:
$ kubectl get pods --namespace=test
Labels: <none>
Annotations: <none>
Status: Active
No resource quota.
No resource limits.
Звісно нові об'єкти Kubernetes можна додавати до вже створеного неймспейсу за допомогою ключа --namespace:
$ vim podintest.yaml
apiVersion: v1
kind: Pod
metadata:
name: podintest
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
$ kubectl apply --namespace=test -f podintest.yaml
Разом з тим бажаний неймспейс для об'єкту можна вказувати в тілі його yaml-опису:
$ vim podintest.yaml
apiVersion: v1
kind: Pod
metadata:
name: podintest
namespace: test
Щоб переглянути, наприклад, поди одного неймспейсу необхідно знову ж використати ключ --namespace:
$ kubectl get pods --namespace=test
NAME READY STATUS RESTARTS AGE
podintest 1/1 Running 0 16s
У цій статті ми користуємось неймспейсом default, тому ми, в основному, не вказуємо його імені. Видалення неймспейсу потягне за собою видалення всіх об'єктів, що працюють в його межах:
$ kubectl delete namespace test
podintest 1/1 Running 0 16s
У цій статті ми користуємось неймспейсом default, тому ми, в основному, не вказуємо його імені. Видалення неймспейсу потягне за собою видалення всіх об'єктів, що працюють в його межах:
$ kubectl delete namespace test
namespace "test" deleted
ЗАВДАННЯ (JOB). Створимо одноразове завдання, задачу, що рахуватиме з 9 до 1:
$ vim job.yaml
$ kubectl apply -f job.yaml
Перевіримо статус її створення:
$ kubectl get jobs
ЗАВДАННЯ (JOB). Створимо одноразове завдання, задачу, що рахуватиме з 9 до 1:
$ vim job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: countdown
spec:
template:
metadata:
name: countdown
spec:
containers:
- name: counter
image: centos:7
command:
- "bin/bash"
- "-c"
- "for i in 9 8 7 6 5 4 3 2 1 ; do echo $i ; done"
restartPolicy: Never
$ kubectl apply -f job.yaml
Перевіримо статус її створення:
$ kubectl get jobs
NAME DESIRED SUCCESSFUL AGE
countdown 1 1 6s
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
countdown-lc80g 0/1 Completed 0 16s
Після виконання завдання відповідний под зупиниться. Щоб дізнатись більше про даний под можна також виконати наступну команду:
$ kubectl describe jobs countdown
Name: countdown
Namespace: default
Selector: controller-uid=35701d78-a73f-11e7-8ef0-080027d6708d
Labels: controller-uid=35701d78-a73f-11e7-8ef0-080027d6708d
job-name=countdown
Annotations: ...
Parallelism: 1
Completions: 1
Start Time: Mon, 02 Oct 2017 02:59:17 -0400
Pods Statuses: 0 Running / 1 Succeeded / 0 Failed
Pod Template:
Labels: controller-uid=35701d78-a73f-11e7-8ef0-080027d6708d
job-name=countdown
Containers:
counter:
Image: centos:7
Port: <none>
Command:
bin/bash
-c
for i in 9 8 7 6 5 4 3 2 1 ; do echo $i ; done
Environment: <none>
Mounts: <none>
Volumes: <none>
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 1m 1 job-controller Normal SuccessfulCreate Created pod: countdown-qwbgd
Чи переглянути журнал поду:
$ kubectl logs countdown-qwbgd
Namespace: default
Selector: controller-uid=35701d78-a73f-11e7-8ef0-080027d6708d
Labels: controller-uid=35701d78-a73f-11e7-8ef0-080027d6708d
job-name=countdown
Annotations: ...
Parallelism: 1
Completions: 1
Start Time: Mon, 02 Oct 2017 02:59:17 -0400
Pods Statuses: 0 Running / 1 Succeeded / 0 Failed
Pod Template:
Labels: controller-uid=35701d78-a73f-11e7-8ef0-080027d6708d
job-name=countdown
Containers:
counter:
Image: centos:7
Port: <none>
Command:
bin/bash
-c
for i in 9 8 7 6 5 4 3 2 1 ; do echo $i ; done
Environment: <none>
Mounts: <none>
Volumes: <none>
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 1m 1 job-controller Normal SuccessfulCreate Created pod: countdown-qwbgd
Чи переглянути журнал поду:
$ kubectl logs countdown-qwbgd
9
8
7
6
5
4
3
2
1
Видалення для задачі, як і для всіх інших об'єктів, відбувається наступним чином:
$ kubectl delete job countdown
job "countdown" deleted
Цей об'єкт Kubernetes корисний у випадках одноразових операцій на кшталт міграції баз, запуску одноразових перевірок і т.п. Також існують багаторазові завдання, з якими детальніше можна ознайомитись за посиланням https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/
INGRESS. Примітив Kubernetes, котрий відповідає за переадресацію запитів на сервіси (примітиви Kubernetes) по певним правилам (в залежності від імені хосту і/або URL-ів). Контроллер для нього необхідно виливати окремо і вже після цього можна користуватись новим об'єктом kind: Ingress. Тобто, можна сказати, що це і плагін і об'єкт одночасно. Як його активувати, та як ним користуватись я вже описав тут https://blog.ipeacocks.info/2018/01/kubernetes-part-v-configure-and-use.html
Наступні пункти не являються об'єктами Kubernetes, але про них також хотілося б згадати.
Журнал (Logs). Трішки ще хотілося б додати про логи. Створимо тестовий под pod-logme, контейнер в якому виконує команди для генерації виводу stdout та stderr:
$ vim pod-logme.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-logme
spec:
containers:
- name: gen
image: centos:7
command:
- "bin/bash"
- "-c"
- "while true; do echo $(date) | tee /dev/stderr; sleep 1; done"
$ kubectl apply -f pod-logme.yaml
Переглянемо логи контейнеру gen в цьому поді:
$ kubectl logs --tail=5 pod-logme -c gen
Mon Oct 2 21:30:36 UTC 2017
Mon Oct 2 21:30:37 UTC 2017
Mon Oct 2 21:30:37 UTC 2017
Mon Oct 2 21:30:38 UTC 2017
Mon Oct 2 21:30:38 UTC 2017
Окрім цього можна спостерігати за потоком всіх повідомлень (щось на зразок tail -f), що з'являються з часом:
$ kubectl logs -f --since=10s pod-logme -c gen
Mon Oct 2 21:30:37 UTC 2017
Mon Oct 2 21:30:37 UTC 2017
Mon Oct 2 21:30:38 UTC 2017
Mon Oct 2 21:30:38 UTC 2017
Окрім цього можна спостерігати за потоком всіх повідомлень (щось на зразок tail -f), що з'являються з часом:
$ kubectl logs -f --since=10s pod-logme -c gen
...
Mon Oct 2 21:31:35 UTC 2017
Mon Oct 2 21:31:36 UTC 2017
Mon Oct 2 21:31:36 UTC 2017
Mon Oct 2 21:31:37 UTC 2017
Mon Oct 2 21:31:37 UTC 2017
^C
Параметр --since=10s вказує на те, що повідомлення почнуть виводитись лише за останні 10 секунд. Інакше ж на початку будуть виведені всі можливі логи доступні в stdout контейнера. Можна також вивести лише 5 останніх повідомлень:
$ kubectl logs --tail=5 pod-logme -c gen
Mon Oct 2 21:31:35 UTC 2017
Mon Oct 2 21:31:36 UTC 2017
Mon Oct 2 21:31:36 UTC 2017
Mon Oct 2 21:31:37 UTC 2017
Mon Oct 2 21:31:37 UTC 2017
^C
Параметр --since=10s вказує на те, що повідомлення почнуть виводитись лише за останні 10 секунд. Інакше ж на початку будуть виведені всі можливі логи доступні в stdout контейнера. Можна також вивести лише 5 останніх повідомлень:
$ kubectl logs --tail=5 pod-logme -c gen
Mon Oct 2 22:07:26 UTC 2017
Mon Oct 2 22:07:27 UTC 2017
Mon Oct 2 22:07:27 UTC 2017
Mon Oct 2 22:07:28 UTC 2017
Mon Oct 2 22:07:28 UTC 2017
Логи можна виводити навіть для контейнерів, котрі вже закінчили свій життєвий цикл:
$ vim pod-oneshot.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-oneshot
spec:
containers:
- name: gen
image: centos:7
command:
- "bin/bash"
- "-c"
- "for i in 9 8 7 6 5 4 3 2 1 ; do echo $i ; done"
$ kubectl apply -f pod-oneshot.yaml
Контейнер цього поду лише виведе цифри від 9 до 1 і вже потім закінчить свою роботу:
$ kubectl logs pod-oneshot -c gen
Mon Oct 2 22:07:27 UTC 2017
Mon Oct 2 22:07:27 UTC 2017
Mon Oct 2 22:07:28 UTC 2017
Mon Oct 2 22:07:28 UTC 2017
Логи можна виводити навіть для контейнерів, котрі вже закінчили свій життєвий цикл:
$ vim pod-oneshot.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-oneshot
spec:
containers:
- name: gen
image: centos:7
command:
- "bin/bash"
- "-c"
- "for i in 9 8 7 6 5 4 3 2 1 ; do echo $i ; done"
$ kubectl apply -f pod-oneshot.yaml
Контейнер цього поду лише виведе цифри від 9 до 1 і вже потім закінчить свою роботу:
$ kubectl logs pod-oneshot -c gen
9
8
7
6
5
4
3
2
1
Secrets. Окрім цього Kubernetes володіє функціоналом збереження секретних даних на кшталт паролів, API-ключів і т.п. Проте перед використанням цього механізму варто прийняти до уваги наступні властивості:
$ echo -n "A19fh68B001j" > ./apikey.txt
8
7
6
5
4
3
2
1
Secrets. Окрім цього Kubernetes володіє функціоналом збереження секретних даних на кшталт паролів, API-ключів і т.п. Проте перед використанням цього механізму варто прийняти до уваги наступні властивості:
- Секрети доступні всім об'єктам у межах неймспейсу, в якому вони були створені
- Доступ до них відбувається через змінні середовища чи том (volume) контейнера в поді
- Секрети на вузлах зберігаються на tmpfs томах
- На кожен секрет виділяється не більше 1МБ
- API сервер Kubernetes зберігає секрети як незашифрований текст в etcd
$ echo -n "A19fh68B001j" > ./apikey.txt
$ kubectl create secret generic apikey --from-file=./apikey.txt
secret "apikey" created
$ kubectl get secrets
$ kubectl get secrets
NAME TYPE DATA AGE
apikey Opaque 1 22s
default-token-k016d kubernetes.io/service-account-token 3 71d
$ kubectl describe secret apikey
Name: apikey
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
apikey.txt: 12 bytes
Тепер створимо под з томом, на котрому буде знаходитись секрет apikey.txt:
$ vim pod-secret.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-secret
spec:
containers:
- name: shell
image: centos:7
command:
- "bin/bash"
- "-c"
- "sleep 10000"
volumeMounts:
- name: apikeyvol
mountPath: "/tmp/apikey"
readOnly: true
volumes:
- name: apikeyvol
secret:
secretName: apikey
$ kubectl apply -f pod-secret.yaml
Перевіримо чи справді секрет знаходиться в контейнері поду:
$ kubectl exec pod-secret -c shell -i -t -- bash
apikey Opaque 1 22s
default-token-k016d kubernetes.io/service-account-token 3 71d
$ kubectl describe secret apikey
Name: apikey
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
apikey.txt: 12 bytes
Тепер створимо под з томом, на котрому буде знаходитись секрет apikey.txt:
$ vim pod-secret.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-secret
spec:
containers:
- name: shell
image: centos:7
command:
- "bin/bash"
- "-c"
- "sleep 10000"
volumeMounts:
- name: apikeyvol
mountPath: "/tmp/apikey"
readOnly: true
volumes:
- name: apikeyvol
secret:
secretName: apikey
$ kubectl apply -f pod-secret.yaml
Перевіримо чи справді секрет знаходиться в контейнері поду:
$ kubectl exec pod-secret -c shell -i -t -- bash
[root@pod-secret /]# mount | grep apikey
tmpfs on /tmp/apikey type tmpfs (ro,relatime)
[root@pod-secret /]# cat /tmp/apikey/apikey.txt
A19fh68B001j
Проте, виходячи з останньої особливості збереження секретів в Kubernetes, доступ до etcd варто надавати лише вузькому колу людей.
Вузол (node). Вузли, на кшталт об'єктів Kubernetes, можуть бути опитані на предмет стану роботи та опцій з якими вони працюють. Як і у всіх попередніх випадках за це відповідають функції get та describe:
$ kubectl get nodes
tmpfs on /tmp/apikey type tmpfs (ro,relatime)
[root@pod-secret /]# cat /tmp/apikey/apikey.txt
A19fh68B001j
Проте, виходячи з останньої особливості збереження секретів в Kubernetes, доступ до etcd варто надавати лише вузькому колу людей.
Вузол (node). Вузли, на кшталт об'єктів Kubernetes, можуть бути опитані на предмет стану роботи та опцій з якими вони працюють. Як і у всіх попередніх випадках за це відповідають функції get та describe:
$ kubectl get nodes
NAME STATUS AGE VERSION
k8s-m1 Ready 71d v1.7.1
k8s-s1 Ready 71d v1.7.1
k8s-s2 Ready 71d v1.7.1
k8s-s3 Ready 71d v1.7.1
$ kubectl describe node k8s-s1
k8s-m1 Ready 71d v1.7.1
k8s-s1 Ready 71d v1.7.1
k8s-s2 Ready 71d v1.7.1
k8s-s3 Ready 71d v1.7.1
$ kubectl describe node k8s-s1
Name: k8s-s1
Role:
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/os=linux
kubernetes.io/hostname=k8s-s1
shouldrun=here
Annotations: node.alpha.kubernetes.io/ttl=0
volumes.kubernetes.io/controller-managed-attach-detach=true
Taints: <none>
CreationTimestamp: Sat, 22 Jul 2017 15:31:29 -0400
Conditions:
Type Status LastHeartbeatTime LastTransitionTime Reason Message
---- ------ ----------------- ------------------ ------ -------
OutOfDisk False Mon, 02 Oct 2017 19:02:36 -0400 Mon, 04 Sep 2017 16:13:03 -0400 KubeletHasSufficientDisk kubelet has sufficient disk space available
...
Ready True Mon, 02 Oct 2017 19:02:36 -0400 Mon, 02 Oct 2017 17:03:27 -0400 KubeletReady kubelet is posting ready status. AppArmor enabled
Addresses:
InternalIP: 192.168.60.111
Hostname: k8s-s1
Capacity:
cpu: 1
memory: 1495332Ki
pods: 110
Allocatable:
cpu: 1
memory: 1392932Ki
pods: 110
System Info:
Machine ID: b8240bf4076b4a2f88f491b9bd176fd9
System UUID: 20EA61E7-5746-42F3-B1AC-174DC0EF4DD4
Boot ID: de304d90-37fd-4589-9eed-1cae280f6db2
Kernel Version: 4.4.0-83-generic
OS Image: Ubuntu 16.04.2 LTS
Operating System: linux
Architecture: amd64
Container Runtime Version: docker://1.12.0
Kubelet Version: v1.7.1
Kube-Proxy Version: v1.7.1
ExternalID: k8s-s1
Non-terminated Pods: (8 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits
--------- ---- ------------ ---------- --------------- -------------
ingress default-backend-2856460360-wktts 10m (1%)10m (1%) 20Mi (1%) 20Mi (1%)
...
kube-system weave-scope-agent-b6zhk 0 (0%) 0 (0%) 0 (0%) 0 (0%)
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
CPU Requests CPU Limits Memory Requests Memory Limits
------------ ---------- --------------- -------------
290m (28%) 10m (1%) 130Mi (9%) 190Mi (13%)
Events: <none>
Як бачимо, тут є купа корисної сервісної інформації на кшталт версій підсистем, завантаженості вузла контейнерами і т.п.
Посилання:
http://kubernetesbyexample.com/
https://kubernetesbootcamp.github.io/kubernetes-bootcamp/
https://kubernetes.io/docs/concepts/configuration/overview/
https://habrahabr.ru/company/flant/blog/332990/
https://habrahabr.ru/company/flant/blog/333956/
https://www.xenonstack.com/blog/deploying-python-application-on-docker-kubernetes
https://blog.yadutaf.fr/2017/07/28/tracing-a-packet-journey-using-linux-tracepoints-perf-ebpf/
https://kubernetes.io/docs/concepts/configuration/overview/
Role:
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/os=linux
kubernetes.io/hostname=k8s-s1
shouldrun=here
Annotations: node.alpha.kubernetes.io/ttl=0
volumes.kubernetes.io/controller-managed-attach-detach=true
Taints: <none>
CreationTimestamp: Sat, 22 Jul 2017 15:31:29 -0400
Conditions:
Type Status LastHeartbeatTime LastTransitionTime Reason Message
---- ------ ----------------- ------------------ ------ -------
OutOfDisk False Mon, 02 Oct 2017 19:02:36 -0400 Mon, 04 Sep 2017 16:13:03 -0400 KubeletHasSufficientDisk kubelet has sufficient disk space available
...
Ready True Mon, 02 Oct 2017 19:02:36 -0400 Mon, 02 Oct 2017 17:03:27 -0400 KubeletReady kubelet is posting ready status. AppArmor enabled
Addresses:
InternalIP: 192.168.60.111
Hostname: k8s-s1
Capacity:
cpu: 1
memory: 1495332Ki
pods: 110
Allocatable:
cpu: 1
memory: 1392932Ki
pods: 110
System Info:
Machine ID: b8240bf4076b4a2f88f491b9bd176fd9
System UUID: 20EA61E7-5746-42F3-B1AC-174DC0EF4DD4
Boot ID: de304d90-37fd-4589-9eed-1cae280f6db2
Kernel Version: 4.4.0-83-generic
OS Image: Ubuntu 16.04.2 LTS
Operating System: linux
Architecture: amd64
Container Runtime Version: docker://1.12.0
Kubelet Version: v1.7.1
Kube-Proxy Version: v1.7.1
ExternalID: k8s-s1
Non-terminated Pods: (8 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits
--------- ---- ------------ ---------- --------------- -------------
ingress default-backend-2856460360-wktts 10m (1%)10m (1%) 20Mi (1%) 20Mi (1%)
...
kube-system weave-scope-agent-b6zhk 0 (0%) 0 (0%) 0 (0%) 0 (0%)
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
CPU Requests CPU Limits Memory Requests Memory Limits
------------ ---------- --------------- -------------
290m (28%) 10m (1%) 130Mi (9%) 190Mi (13%)
Events: <none>
Як бачимо, тут є купа корисної сервісної інформації на кшталт версій підсистем, завантаженості вузла контейнерами і т.п.
Посилання:
http://kubernetesbyexample.com/
https://kubernetesbootcamp.github.io/kubernetes-bootcamp/
https://kubernetes.io/docs/concepts/configuration/overview/
https://habrahabr.ru/company/flant/blog/332990/
https://habrahabr.ru/company/flant/blog/333956/
https://www.xenonstack.com/blog/deploying-python-application-on-docker-kubernetes
https://blog.yadutaf.fr/2017/07/28/tracing-a-packet-journey-using-linux-tracepoints-perf-ebpf/
https://kubernetes.io/docs/concepts/configuration/overview/
Немає коментарів:
Дописати коментар