====== Kubernetes: Services ======
Поды – это не постоянные сущности кластера. В любой момент времени вы можете добавить новый под или удалить не нужный. При перемещении пода между нодами кластера, под создается на новой ноде и удаляется на старой. При этом у пода меняется IP адрес. Именно поэтому не стоит обращаться к поду по ip адресу.
В Kubernetes, для доступа к поду (наборам подов) используются сервисы (service). Сервис – это абстракция, определяющая набор подов и политику доступа к ним.
Предположим, что в системе есть приложение, производящее обработку запросов. Приложение работает без сохранения состояния и поэтому может легко горизонтально масштабироваться. Для обработки потока запросов нам потребовалось несколько экземпляров приложения (подов) и нам необходимо распределить нагрузку между ними.
Если бы мы не использовали Kubernetes, нам бы пришлось ставить перед приложениями какую-то программу, занимающуюся распределением запросов. Например nginx. И каждый раз при изменении количества приложений, при переезде приложения с одного сервера на другой перенастраивать nginx.
В Kubernetes заботу о распределении нагрузки или доступа к группе приложений ложится на сервис. При определении сервиса обычно достаточно указать селектор, определяющий выбор подов, на которые будут пересылаться запросы. //Так же существует возможность определения сервисов без селекторов, но об этом мы поговорим позднее.//
===== ClusterIP =====
Утилита kubectl может создать сервис используя аргументы командной строки. Но мы будем пользоваться старыми добрыми yaml файлами.
---
apiVersion: v1
kind: Service
metadata:
name: service-name
spec:
selector:
app: pod-selector
ports:
- protocol: TCP
port: 80
targetPort: 8080
В приведённом выше примере создаётся сервис с именем service-name. Kubernetes присваивает сервису ip адрес и добавляет его данные в DNS сервер. После этого вы можете обратиться к сервису по его имени. В нашем случае сервис принимает запросы на 80-м порту и, если мы находимся в том же неймспейсе, мы можем обратиться к нему [[http://service-name|http://service-name]]. Если в другом, то с указанием неймспейса: [[http://service-name.namespace.svc|http://service-name.namespace.svc]]. //Подробно о работе DNS в Kubernetes можно почитать тут: [[:devops:k8s:k8s_dns|https://fatalex.cifro.netdoku.php/devops/k8s/k8s_dns]]//
Приходящие запросы сервис будет пересылать на порт 8080 подам с метками (label) app: selector. Если в системе будет несколько подов с таким селектором, сервис будет перераспределять запросы между ними. По умолчанию по алгоритму round robbin.
В качестве значения targetPort можно использовать имена портов. Конечно, если вы его описали при определении пода. Это удобно, если вы ссылаетесь на поды, у которых определены разные номера портов, но под одним именем.
Рассмотрим пример. Deployment для сервера Tomcat.
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: tomcat
labels:
app: tomcat
spec:
replicas: 2
revisionHistoryLimit: 3
selector:
matchLabels:
app: tomcat
template:
metadata:
labels:
app: tomcat
spec:
containers:
- name: tomcat
image: tomcat:10-jdk15
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: "0.2"
memory: "200Mi"
limits:
cpu: "0.5"
memory: "500Mi"
ports:
- containerPort: 8080
name: tomcat
protocol: TCP
**//Файл 01-// ****//deployment// ****//.// ****//yaml// ****//.// **
В deployment указано наличие двух реплик (подов) приложения. Объявляется порт приложения 8080, с названием tomcat. Приложению присваивается метка: app: tomcat.
Сервис, предоставляющий доступы к этим подам можно объявить следующим образом:
---
apiVersion: v1
kind: Service
metadata:
name: tomcat-main
spec:
selector:
app: tomcat
ports:
- protocol: TCP
port: 80
targetPort: tomcat
**//Файл 02-// ****//service// ****//.// ****//yaml// **
В разделе selector мы указываем метку приложения, на которые мы будем ссылаться. В разделе ports говорим, что к сервису нужно обращаться на 80-й порт. Запрос будет переслан приложению на порт, имеющий имя tomcat.
Применим файлы манифеста.
kubectl apply -f 01-deployment.yaml
kubectl apply -f 02-service.yaml
//Примечание. Кластер kuberntes устанавливался со следующими параметрами сети://
networking:
dnsDomain: cluster.local
podSubnet: 10.234.0.0/18
serviceSubnet: 10.233.0.0/18
Посмотрим информацию о запущенных подах. Вывод программы немного обрезан.
# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP
tomcat-56db4566fd-8ffjg 1/1 Running 0 2m40s 10.234.9.2
tomcat-56db4566fd-xdctz 1/1 Running 0 2m40s 10.234.8.196
Если обратиться к любому поду напрямую, мы увидим ответ сервера tomcat.
# curl 10.234.9.2:8080
Тут было много символов
Apache Tomcat/10.0.0-M10