Вы можете делегировать ответственность за планирование произвольных подмножеств модулей в свой собственный (-ые) планировщик (-и), который (-ые) выполняет (-ы) рядом с планировщиком Kubernetes по умолчанию или вместо него.
Вы можете написать свой собственный планировщик. Пользовательский планировщик может быть написан на любом языке и может быть настолько простым или сложным, насколько вам нужно. Ниже приведен очень простой пример пользовательского планировщика, записанного в Bash, который назначает узел случайным образом. Обратите внимание, что вам нужно запустить его вместе с прокси-сервером kubectl, чтобы он работал.
SERVER='localhost:8001'
while true;
do
for PODNAME in $(kubectl --server $SERVER get pods -o json | jq '.items[] | select(.spec.schedulerName == "my-scheduler") | select(.spec.nodeName == null) | .metadata.name' | tr -d '"')
;
do
NODES=($(kubectl --server $SERVER get nodes -o json | jq '.items[].metadata.name' | tr -d '"'))
NUMNODES=${#NODES[@]}
CHOSEN=${NODES[$[$RANDOM % $NUMNODES]]}
curl --header "Content-Type:application/json" --request POST --data '{"apiVersion":"v1", "kind": "Binding", "metadata": {"name": "'$PODNAME'"}, "target": {"apiVersion": "v1", "kind"
: "Node", "name": "'$CHOSEN'"}}' http://$SERVER/api/v1/namespaces/default/pods/$PODNAME/binding/
echo "Assigned $PODNAME to $CHOSEN"
done
sleep 1
done
Тогда просто в вашем файле конфигурации StatefulSet в разделе спецификации вы должны добавить строку schedulerName: your-scheduler
.
Вы также можете использовать сходство pod: .
Пример:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis-cache
spec:
selector:
matchLabels:
app: store
replicas: 3
template:
metadata:
labels:
app: store
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- store
topologyKey: "kubernetes.io/hostname"
containers:
- name: redis-server
image: redis:3.2-alpine
В приведенном ниже фрагменте yaml состояния statefuset веб-сервера настроены podAntiAffinity и podAffinity. , Это сообщает планировщику, что все его реплики должны быть расположены вместе с модулями с меткой селектора app = store . Это также гарантирует, что каждая реплика веб-сервера не будет размещаться на одном узле.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web-server
spec:
selector:
matchLabels:
app: web-store
replicas: 3
template:
metadata:
labels:
app: web-store
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web-store
topologyKey: "kubernetes.io/hostname"
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- store
topologyKey: "kubernetes.io/hostname"
containers:
- name: web-app
image: nginx:1.12-alpine
Если мы создадим два вышеупомянутых развертывания, наш кластер из трех узлов должен выглядеть следующим образом.
node-1 node-2 node-3
webserver-1 webserver-2 webserver-3
cache-1 cache-2 cache-3
В приведенном выше примере используется правило PodAntiAffinity с topologyKey: "kubernetes.io/hostname"
для развертывания кластера redis, чтобы на одном хосте не было двух экземпляров
Вы можете просто определить три реплики с указанием c pod и определите конкретный файл конфигурации pod, egg .: есть метка: nodeName , которая является самой простой формой ограничения выбора узла, но из-за его ограничений она обычно не используется. nodeName - это поле PodSpe c. Если он не пустой, планировщик игнорирует модуль, и кублет, запущенный на указанном узле, пытается запустить модуль. Таким образом, если имя узла указано в PodSpe c, оно имеет приоритет над вышеуказанными методами для выбора узла.
Вот пример файла конфигурации модуля, использующего поле nodeName:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
nodeName: kube-worker-1
Дополнительная информация о планировщике: настраиваемый планировщик .
Посмотрите эту статью: assigining-pods-kubernetes .