Kubernetes – это мощная платформа оркестрации контейнеров, но для раскрытия ее полного потенциала важно понимать ее основные компоненты, при этом роли фундаментальных компонентов играют поды и сервисы. В этой статье мы рассмотрим, что они представляют из себя и как взаимодействуют для предоставления доступа и управления приложениями, работающими внутри кластера Kubernetes.
Что такое Под?
Поды – это наименьшие управляемые вычислительные единицы, которые можно создавать и управлять в Kubernetes.
Прежде чем создать под, давайте проверим доступные ресурсы API в вашем кластере Kubernetes; вы можете использовать команду kubectl api-resources
. Эта команда перечисляет ресурсы API, поддерживаемые сервером API Kubernetes, включая их сокращенные имена, группы API и информацию о том, являются ли они именованными пространствами или нет. Это полезно для понимания возможностей вашего кластера, особенно при работе с пользовательскими ресурсами или изучении новых функций Kubernetes. Команда kubectl explain
дополняет это, предоставляя подробную информацию о отдельных ресурсах.
Давайте создадим базовый файл конфигурации пода для запуска простого контейнера Nginx.
Создайте файл с именем nginx-pod.yaml
:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Вот краткое объяснение используемых терминов:
- apiVersion: v1: Указывает версию API.
- kind: Pod: Указывает, что эта конфигурация предназначена для пода.
- metadata:name: Имя пода.
- метаданные: метки: Пары ключ-значение, которые могут использоваться для организации и выбора пода.
- спецификация:контейнеры: Список контейнеров, которые будут запущены в поде.
- спецификация:контейнеры:имя: Имя контейнера.
- спецификация:контейнеры:образ: Образ контейнера для использования (в данном случае, последний образ Nginx).
- спецификация:контейнеры:порты: Порты для выставления из контейнера.
Используйте kubectl
, чтобы применить файл конфигурации и создать под:
kubectl apply -f nginx-pod.yaml
Проверьте статус пода, чтобы убедиться, что он был создан и работает:
kubectl get pods
Вы должны увидеть вывод, аналогичный этому:
NAME READY STATUS RESTARTS AGE
nginx-pod 1/1 Running 0 10s
Затем удалите под:
kubectl delete pod nginx-pod
Вывод должен выглядеть примерно так:
kubectl get pod
No resources found in default namespace.
Что такое Сервис?
Создание сервиса для пода Nginx в Kubernetes позволяет вам выставить приложение Nginx и сделать его доступным внутри или за пределами кластера. Вот пошаговое руководство по созданию Сервиса для пода Nginx.
Чтобы убедиться, что у вас работает под Nginx, если у вас его еще нет, создайте файл YAML с именем nginx-pod.yaml
:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Примените конфигурацию Пода:
kubectl apply -f nginx-pod.yaml
Создайте файл YAML с именем nginx-service.yaml
для определения Сервиса:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
Вот несколько важных моментов:
- selector: Селектор меток для сопоставления с подом Nginx.
- app: nginx: Он должен совпадать с меткой в поде Nginx.
- type: ClusterIP: Тип Сервиса. ClusterIP делает Сервис доступным только в пределах кластера. Вы также можете использовать NodePort или LoadBalancer, чтобы предоставить доступ к Сервису снаружи.
Примените конфигурацию Сервиса с помощью kubectl
:
kubectl apply -f nginx-service.yaml
kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-service ClusterIP 10.96.0.1 <none> 80/TCP 10s
Поскольку тип Сервиса – ClusterIP, он доступен только в пределах кластера. Чтобы получить к нему доступ извне кластера, можно изменить тип Сервиса на NodePort или LoadBalancer.
Для предоставления доступа к Сервису снаружи с использованием NodePort
, измените файл nginx-service.yaml
:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30007 # Specify a node port in the range 30000-32767 (optional)
type: NodePort
Примените обновленную конфигурацию Сервиса:
kubectl apply -f nginx-service.yaml
Теперь вы можете получить доступ к приложению Nginx, используя IP-адрес узла и порт узла (например, http://<node-ip>:30007).
Мультиконтейнерные поды
Использование одного контейнера на каждый под обеспечивает максимальную детализацию и разделение. Однако существуют сценарии, когда развертывание нескольких контейнеров, иногда называемых композитными контейнерами, в одном поде является выгодным. Эти вторичные контейнеры могут выполнять различные роли: обработка журналирования или улучшение работы основного контейнера (концепция sidecar), действие в качестве прокси к внешним системам (концепция ambassador) или изменение данных для соответствия внешнему формату (концепция adapter). Эти вторичные контейнеры дополняют основной контейнер, выполняя задачи, которые он не обрабатывает.
Ниже приведен пример конфигурации пода Kubernetes, который включает основной контейнер, запускающий сервер Nginx, и вторичный контейнер, действующий в качестве sidecar для обработки журналирования. Вторичный контейнер sidecar использует простой контейнер для журналирования, например BusyBox, чтобы продемонстрировать, как он может просматривать журналы доступа Nginx.
apiVersion: v1
kind: Pod
metadata:
name: nginx-with-logging-sidecar
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: shared-logs
mountPath: /var/log/nginx
- name: log-sidecar
image: busybox:latest
command: ["sh", "-c", "tail -f /var/log/nginx/access.log"]
volumeMounts:
- name: shared-logs
mountPath: /var/log/nginx
volumes:
- name: shared-logs
emptyDir: {}
Затем вы выполните следующее:
- Сохраните конфигурацию YAML в файл, например,
nginx-with-logging-sidecar.yaml
. - Примените конфигурацию с помощью
kubectl: kubectl apply -f nginx-with-logging-sidecar.yaml
. - Проверьте, что под запущен:
kubectl get pods
. - Проверьте журналы вторичного контейнера, чтобы увидеть журналы доступа Nginx:
kubectl logs -f <имя-пода> -c log-sidecar
.
Следуя этим шагам, вы удалите существующий Pod и примените новую конфигурацию, настроив Pod с контейнером Nginx и вспомогательным контейнером для ведения журналов. Это обеспечит активность и работоспособность новой конфигурации в вашем кластере Kubernetes.
Многоконтейнерные поды в Kubernetes предлагают несколько преимуществ, обеспечивая более гибкое и эффективное развертывание и управление приложениями.
Шаблоны многоконтейнерных подов
Шаблон Sidecar
Вспомогательные контейнеры могут улучшить основное приложение, предоставляя вспомогательные функции, такие как ведение журналов, управление конфигурацией или проксирование. Этот шаблон помогает расширить функциональность без модификации основного контейнера. Вспомогательный контейнер может обрабатывать ведение журналов, собирая и пересылая журналы из основного контейнера приложения.
Шаблон посла
Контейнеры-послы действуют как прокси, управляя коммуникацией между основным приложением и внешними сервисами. Это может упростить интеграцию и конфигурацию. Контейнер-посол может обрабатывать завершение SSL или функции шлюза API.
Шаблон Посла включает использование вспомогательного контейнера для управления коммуникацией между основным приложением и внешними сервисами. Этот шаблон может обрабатывать задачи, такие как проксирование, балансировка нагрузки или управление безопасными соединениями, тем самым абстрагируя сложность от основного контейнера приложения.
- Основной контейнер приложения: Простой веб-сервер, делающий HTTP-запросы
- Вспомогательный контейнер Посла: Прокси Envoy настроенный для управления запросами к внешнему API
apiVersion: v1
kind: Pod
metadata:
name: app-with-ambassador
spec:
containers:
- name: web-app
image: python:3.8-slim
command: ["python", "-m", "http.server", "8000"]
volumeMounts:
- name: config-volume
mountPath: /etc/envoy
- name: envoy-proxy
image: envoyproxy/envoy:v1.18.3
args: ["-c", "/etc/envoy/envoy.yaml"]
ports:
- containerPort: 8080
volumeMounts:
- name: config-volume
mountPath: /etc/envoy
volumes:
- name: config-volume
configMap:
name: envoy-config
---
apiVersion: v1
kind: ConfigMap
metadata:
name: envoy-config
data:
envoy.yaml: |
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 8080
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: external_service
http_filters:
- name: envoy.filters.http.router
clusters:
- name: external_service
connect_timeout: 0.25s
type: LOGICAL_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: external_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: api.example.com
port_value: 80
Этот пример демонстрирует шаблон посредника (Ambassador pattern) в Kubernetes, где прокси-сервер Envoy действует в качестве посредника для управления внешними коммуникациями для основного контейнера приложения. Этот шаблон помогает абстрагировать сложности коммуникаций и улучшает модульность и поддерживаемость.
Шаблон Адаптер (Adapter Pattern)
Контейнеры-адаптеры могут изменять или преобразовывать данные между основным приложением и внешними системами, обеспечивая совместимость и интеграцию. Например, контейнер-адаптер может переформатировать данные журналов, чтобы соответствовать требованиям внешнего сервиса регистрации.
Шаблон адаптера в Kubernetes включает использование контейнера-прицепа (sidecar container) для преобразования данных между основным контейнером приложения и внешними системами. Это может быть полезно, когда основному приложению требуются данные в определенном формате, отличающемся от формата, предоставленного или требуемого внешними системами.
Предположим, у вас есть основной контейнер приложения, который генерирует журналы в пользовательском формате. Вам необходимо отправить эти журналы во внешний сервис регистрации, который требует журналы в определенном стандартизированном формате. Контейнер-адаптер может использоваться для преобразования данных журналов в требуемый формат перед их отправкой во внешний сервис.
- Основной контейнер приложения: Простое приложение, которое записывает журналы в пользовательском формате.
- Контейнер-адаптер: Контейнер, который считывает пользовательские журналы, преобразует их в формат JSON и отправляет их во внешний сервис регистрации.
apiVersion: v1
kind: Pod
metadata:
name: app-with-adapter
spec:
containers:
- name: log-writer
image: busybox
command: ["sh", "-c", "while true; do echo \"$(date) - Custom log entry\" >> /var/log/custom/app.log; sleep 5; done"]
volumeMounts:
- name: shared-logs
mountPath: /var/log/custom
- name: log-adapter
image: busybox
command: ["sh", "-c", "tail -f /var/log/custom/app.log | while read line; do echo \"$(echo $line | sed 's/ - / - {\"timestamp\": \"/;s/$/\"}/')\" >> /var/log/json/app.json; done"]
volumeMounts:
- name: shared-logs
mountPath: /var/log/custom
- name: json-logs
mountPath: /var/log/json
- name: log-sender
image: busybox
command: ["sh", "-c", "while true; do cat /var/log/json/app.json | grep -v '^$' | while read line; do echo \"Sending log to external service: $line\"; done; sleep 10; done"]
volumeMounts:
- name: json-logs
mountPath: /var/log/json
volumes:
- name: shared-logs
emptyDir: {}
- name: json-logs
emptyDir: {}
Этот пример демонстрирует шаблон адаптера в Kubernetes, где контейнер-адаптер преобразует данные из контейнера основного приложения в необходимый формат перед отправкой их во внешнюю систему. Этот шаблон помогает интегрировать приложения с внешними службами, обрабатывая преобразования формата данных в контейнере-сопровождающем.
Сводка
В общем, поды:
- Являются наименьшими развертываемыми единицами в Kubernetes.
- Представляют собой один экземпляр работающего процесса.
- Могут содержать один или несколько контейнеров.
Службы:
- Обеспечивают стабильный IP-адрес и DNS-имя для доступа к подам.
- Позволяют балансировать нагрузку между набором подов.
- Облегчают обнаружение служб внутри кластера.
Source:
https://dzone.com/articles/the-ultimate-guide-to-kubernetes-pods-and-services