Jar*_*aws 5 kubernetes kubernetes-statefulset kubernetes-pod
我有一个 5 节点集群(1-master/4-worker)。是否可以配置一个 StatefulSet,在那里我可以让一个 pod(s) 在给定节点上运行,因为它知道它有足够的容量而不是 Kubernetes 调度程序做出这个决定?
假设,我的 StatefulSet 创建了 4 个 pod(副本:4)作为 myapp-0、myapp-1、myapp-2 和 myapp-3。现在我要找的是:
myapp-0 pod--被安排结束---> worker-1
myapp-1 pod--被调度结束---> worker-2
myapp-2 pod--被调度结束---> worker-3
myapp-3 pod--被调度结束---> worker-4
请让我知道它是否可以以某种方式实现?因为如果我向 StatefulSet 的 Pod 添加一个容忍度,它对所有 Pod 都是相同的,并且所有这些 Pod 都将在与污点匹配的单个节点上进行调度。
谢谢,J
您可以将调度任意 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
Run Code Online (Sandbox Code Playgroud)
然后只是在规范部分下的 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
Run Code Online (Sandbox Code Playgroud)
网络服务器 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
Run Code Online (Sandbox Code Playgroud)
如果我们创建上述两个部署,我们的三节点集群应该如下所示。
node-1 node-2 node-3
webserver-1 webserver-2 webserver-3
cache-1 cache-2 cache-3
Run Code Online (Sandbox Code Playgroud)
上面的例子使用 PodAntiAffinity 规则和 topologyKey:"kubernetes.io/hostname"来部署 redis 集群,以便没有两个实例位于同一主机上
您可以简单地定义特定 pod 的三个副本并定义特定的 pod 配置文件 egg.:有标签: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
Run Code Online (Sandbox Code Playgroud)
有关调度程序的更多信息:custom-scheduler。
看看这篇文章:assigining-pods-kubernetes。
您可以使用以下KubeMod ModRule:
apiVersion: api.kubemod.io/v1beta1
kind: ModRule
metadata:
name: statefulset-pod-node-affinity
spec:
type: Patch
match:
# Select pods named myapp-xxx.
- select: '$.kind'
matchValue: Pod
- select: '$.metadata.name'
matchRegex: myapp-.*
patch:
# Patch the selected pods such that their node affinity matches nodes that contain a label with the name of the pod.
- op: add
path: /spec/affinity/nodeAffinity/requiredDuringSchedulingIgnoredDuringExecution
value: |-
nodeSelectorTerms:
- matchExpressions:
- key: accept-pod/{{ .Target.metadata.name }}
operator: In
values:
- 'true'
Run Code Online (Sandbox Code Playgroud)
上面的 ModRule 将监视名为 pod 的创建,并在部署之前myapp-*将一个部分注入到其资源清单中。nodeAffinity这将指示调度程序将 pod 调度到标签设置为 的accept-pod/<pod-name>节点true。
然后,您可以通过向节点添加标签来将未来的 pod 分配给节点:
kubectl label node worker-1 accept-pod/myapp-0=true
kubectl label node worker-2 accept-pod/myapp-1=true
kubectl label node worker-3 accept-pod/myapp-2=true
...
Run Code Online (Sandbox Code Playgroud)
上述ModRule部署后,创建StatefulSet会触发其Pod的创建,这些Pod会被ModRule拦截。ModRule 将nodeAffinity使用 pod 的名称动态注入该部分。
如果稍后删除 StatefulSet,再次部署它会导致 pod 被调度到与之前相同的节点上。
请查看此指南https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
但是,您要查找的是nodeSelector应放置在 pod 规范中的指令。
| 归档时间: |
|
| 查看次数: |
4282 次 |
| 最近记录: |