您可以将调度任意 pod 子集的责任委托给您自己的自定义调度程序,该调度程序与默认 Kubernetes 调度程序一起运行,或者代替默认 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
以下 webserver statefuset 的 yaml 片段配置了 podAntiAffinity 和 podAffinity。这会通知调度程序,它的所有副本都将与具有选择器标签app=store的 pod 位于同一位置。这还将确保每个 Web 服务器副本不会位于单个节点上。
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 集群,使得没有两个实例位于同一主机上
您可以简单地定义特定 pod 的三个副本,并定义特定的 pod 配置文件 egg.: 有 label: nodeName是最简单的节点选择约束形式,但由于其局限性,通常不使用。nodeName 是 PodSpec 的一个字段。如果它非空,则调度程序会忽略该 pod,并且在命名节点上运行的 kubelet 会尝试运行该 pod。因此,如果 PodSpec 中提供了 nodeName,则它优先于上述节点选择方法。
下面是一个使用 nodeName 字段的 pod 配置文件示例:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
nodeName: kube-worker-1
有关调度程序的更多信息:custom-scheduler。
看看这篇文章:assigining-pods-kubernetes。