首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否可以为Kubernetes集群的特定节点分配一个pod的StatefulSet?

是否可以为Kubernetes集群的特定节点分配一个pod的StatefulSet?
EN

Stack Overflow用户
提问于 2020-02-16 03:24:34
回答 5查看 5.4K关注 0票数 7

我有一个5节点集群(1-master/4-worker)。有没有可能配置一个StatefulSet,我可以让一个pod在给定的节点上运行,知道它有足够的容量,而不是Kubernetes Scheduler来做这个决定?

假设我的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

EN

回答 5

Stack Overflow用户

发布于 2020-02-17 21:46:30

您可以将调度任意pod子集的责任委托给您自己的自定义调度器,这些调度器与默认的Kubernetes调度器一起运行,或者代替默认的Kubernetes调度器运行。

您可以编写自己的自定义调度程序。自定义调度程序可以用任何语言编写,可以根据您的需要而简单或复杂。下面是一个用Bash编写的自定义调度器的非常简单的示例,它随机分配一个节点。请注意,您需要将其与kubectl代理一起运行,才能使其工作。

代码语言:javascript
复制
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 affinity:

示例:

代码语言:javascript
复制
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

下面的The服务器statefuset的yaml片段配置了podAntiAffinity和podAffinity。这会通知调度程序,它的所有副本都将与具有选择器标签app=store的pod放在同一位置。这还将确保每个web服务器副本不会共存于单个节点上。

代码语言:javascript
复制
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

如果我们创建上述两个部署,我们的三节点集群应该如下所示。

代码语言:javascript
复制
node-1              node-2           node-3
webserver-1     webserver-2          webserver-3
cache-1             cache-2          cache-3

上面的示例使用带有topologyKey:"kubernetes.io/hostname"的PodAntiAffinity规则来部署redis集群,这样就不会有两个实例位于同一主机上

您可以简单地定义特定pod的三个副本,并定义特定pod配置文件egg。注意:有label:nodeName,这是节点选择约束的最简单形式,但由于其限制,通常不使用它。nodeName是PodSpec的一个字段。如果它不为空,则调度程序将忽略pod,并且在指定节点上运行的kubelet将尝试运行pod。因此,如果PodSpec中提供了nodeName,则它优先于上面的节点选择方法。

以下是使用nodeName字段的pod配置文件的示例:

代码语言:javascript
复制
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
  nodeName: kube-worker-1

有关调度程序的更多信息:custom-scheduler

看看这篇文章:assigining-pods-kubernetes

票数 6
EN

Stack Overflow用户

发布于 2020-02-16 10:10:43

你可以使用nodeSelectornode affinity来做这件事(看看这个指南https://kubernetes.io/docs/concepts/configuration/assign-pod-node/),任何人都可以用来在特定的节点上运行pod。但是如果节点有污染(限制),那么您需要为这些节点添加容差(更多信息可以在https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/中找到)。使用这种方法,您可以指定用于pod调度的节点列表,问题是如果您指定for ex。3个节点,你有5个pod,那么你无法控制在每个节点上运行多少pod。它们按照kube-schedular进行分发。另一个相关用例:如果您想在每个指定节点上运行一个pod,您可以创建一个守护进程并使用nodeSelector选择节点。

票数 1
EN

Stack Overflow用户

发布于 2020-02-16 16:19:30

您可以使用podAntiAffinity将副本分发到不同的节点。

代码语言:javascript
复制
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 4
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: k8s.gcr.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - nginx
            topologyKey: "kubernetes.io/hostname"

这将在worker1中部署web-0,在worker2中部署web-1,在worker3中部署web-2,在worker4中部署web-3。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60242339

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档