Позволяя только одному стручку эластичного поиска подойти к узлу в Кубернетесе - PullRequest
0 голосов
/ 26 декабря 2018

У нас есть многоузловая настройка нашего продукта, в которой нам необходимо развернуть несколько модулей Elasticsearch.Поскольку все они являются узлами данных и имеют монтируемые тома для постоянного хранения, мы не хотим устанавливать два модуля на одном узле.Я пытаюсь использовать анти-аффинность в Kubernetes, но безрезультатно.

Развертывание кластера осуществляется через Rancher.У нас есть 5 узлов в кластере, и три узла (скажем, node-1, node-2 and node-3) имеют метку test.service.es-master: "true".Поэтому, когда я развертываю таблицу управления и масштабирую ее до 3-х, модули Elasticsearch запускаются и работают на всех этих трех узлах.но если я масштабирую его до 4, 4-й узел данных входит в один из вышеупомянутых узлов.Это правильное поведение?Насколько я понимаю, навязывание строгой антиаффинности должно препятствовать появлению стручков на одном узле.Я ссылался на несколько блогов и форумов (например, this и this ), и они предлагают изменения, подобные моим.Я прилагаю соответствующий раздел рулевой диаграммы.

Требование заключается в том, что нам нужно вызывать ES только на тех узлах, которые помечены определенной парой ключ-значение, как упомянуто выше, и каждый из этих узлов должен содержать только один модуль.Любые отзывы приветствуются.

apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    test.service.es-master: "true"
  name: {{ .Values.service.name }}
  namespace: default
spec:
  clusterIP: None
  ports:
  ...
  selector:
    test.service.es-master: "true"
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    test.service.es-master: "true"
  name: {{ .Values.service.name }}
  namespace: default
spec:
  selector:
    matchLabels:
      test.service.es-master: "true"
  serviceName: {{ .Values.service.name }}
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: test.service.es-master
            operator: In
            values:
            - "true"
        topologyKey: kubernetes.io/hostname
  replicas: {{ .Values.replicaCount }}
  template:
    metadata:
      creationTimestamp: null
      labels:
        test.service.es-master: "true"
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: test.service.es-master
                operator: In
                values:
                  - "true"
              topologyKey: kubernetes.io/hostname
      securityContext:
             ...
      volumes:
        ...
      ...
status: {}

Обновление-1

В соответствии с предложениями в комментариях и ответах, я добавил раздел анти-сродства в шаблоне.spec.Но, к сожалению, проблема все еще остается.Обновленный yaml выглядит следующим образом:

apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    test.service.es-master: "true"
  name: {{ .Values.service.name }}
  namespace: default
spec:
  clusterIP: None
  ports:
  - name: {{ .Values.service.httpport | quote }}
    port: {{ .Values.service.httpport }}
    targetPort: {{ .Values.service.httpport }}
  - name: {{ .Values.service.tcpport | quote }}
    port: {{ .Values.service.tcpport }}
    targetPort: {{ .Values.service.tcpport }}
  selector:
    test.service.es-master: "true"
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    test.service.es-master: "true"
  name: {{ .Values.service.name }}
  namespace: default
spec:
  selector:
    matchLabels:
      test.service.es-master: "true"
  serviceName: {{ .Values.service.name }}
  replicas: {{ .Values.replicaCount }}
  template:
    metadata:
      creationTimestamp: null
      labels:
        test.service.es-master: "true"
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
            matchExpressions:
            - key: test.service.es-master
              operator: In
              values:
              - "true"
            topologyKey: kubernetes.io/hostname
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: test.service.es-master
                operator: In
                values:
                  - "true"
              topologyKey: kubernetes.io/hostname
      securityContext:
             readOnlyRootFilesystem: false
      volumes:
       - name: elasticsearch-data-volume
         hostPath:
            path: /opt/ca/elasticsearch/data
      initContainers:
         - name: elasticsearch-data-volume
           image: busybox
           securityContext:
                  privileged: true
           command: ["sh", "-c", "chown -R 1010:1010 /var/data/elasticsearch/nodes"]
           volumeMounts:
              - name: elasticsearch-data-volume
                mountPath: /var/data/elasticsearch/nodes
      containers:
      - env:
        {{- range $key, $val := .Values.data }}
        - name: {{ $key }} 
          value: {{ $val | quote }}
        {{- end}}
        image: {{ .Values.image.registry }}/analytics/{{ .Values.image.repository }}:{{ .Values.image.tag }}
        name: {{ .Values.service.name }}
        ports:
        - containerPort: {{ .Values.service.httpport }}
        - containerPort: {{ .Values.service.tcpport }}
        volumeMounts:
              - name: elasticsearch-data-volume
                mountPath: /var/data/elasticsearch/nodes    
        resources:
          limits:
            memory: {{ .Values.resources.limits.memory }}
          requests:
            memory: {{ .Values.resources.requests.memory }}
        restartPolicy: Always
status: {}

Ответы [ 3 ]

0 голосов
/ 14 января 2019

Это работает для меня с Kubernetes 1.11.5:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      test.service.es-master: "true"
  template:
    metadata:
      labels:
        test.service.es-master: "true"
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: test.service.es-master
                operator: In
                values:
                - "true"
            topologyKey: kubernetes.io/hostname
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: test.service.es-master
                operator: In
                values:
                  - "true"
      containers:
      - image: nginx:1.7.10
        name: nginx

Я не знаю, почему вы выбрали тот же ключ / значение для метки селектора развертывания модуля, что и для селектора узла.Они как минимум сбивают с толку ...

0 голосов
/ 15 января 2019

Во-первых, и в исходном манифесте, и даже в обновленном манифесте вы используете topologyKey для nodeAffinity, что приведет к ошибке при попытке развернуть манифест с использованием kubectl create или kubectl apply, так как нетAPI-ключ с именем topologyKey для nodeAffinity Ref doc

Во-вторых, вы используете ключ с именем test.service.es-master для вашего узла. Вы уверены, что ваш «узел» имеет эти метки?Пожалуйста, подтвердите с помощью этой команды kubectl get nodes --show-labels

Наконец, добавив к ответу @ Laszlo и свой комментарий @ bitswazsky , чтобы упростить его, вы можете использовать следующий код:

Здесь я использовал метку узла (как ключ) с именем role, чтобы идентифицировать узел, вы можете добавить его к узлу ваших существующих кластеров, выполнив эту команду kubectl label nodes <node-name> role=platform

selector:
    matchLabels:
      component: nginx
  template:
    metadata:
      labels:
        component: nginx
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: role
                operator: In
                values:
                - platform
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: component
                operator: In
                values:
                - nginx
            topologyKey: kubernetes.io/hostname
0 голосов
/ 26 декабря 2018

Как предположил Егор, вам нужно podAntiAffinity:

apiVersion: apps/v1
kind: Deployment
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"

Источник: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#always-co-located-in-the-same-node

Итак, с вашей текущей меткой это может выглядеть так:

spec:
  affinity:
    nodeAffinity:
    # node affinity stuff here
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: "test.service.es-master"
            operator: In
            values:
            - "true"
        topologyKey: "kubernetes.io/hostname"

Убедитесь, что вы поместили это в правильное место в своем yaml, иначе это не будет работать.

...