Назад | Перейти на главную страницу

Внутренняя маршрутизация кластера Kubernetes не работает (служба NodePort)

Я пока работаю над настройкой кластера Kubernetes. Моя установка состоит из двух узлов и одного мастера. Все три машины работают в кластере Proxmox и имеют 2 виртуальных сетевых интерфейса. Один из интерфейсов (перечисленных ниже) находится в мостовой сети с другими машинами. Другой открыт для внутренней сети.

Настройка сети для мостовых интерфейсов выглядит следующим образом:

Network: 10.10.0.0  
Broadcast: 10.10.255.255  
Netmask: 255.255.0.0  

kubernetes-master IP: 10.10.0.1
kubernetes-worker01 IP: 10.10.0.2
kubernetes-worker02 IP: 10.10.0.3

Все серверы могут без проблем разговаривать друг с другом. Я еще не настраивал брандмауэр.

root@kubernetes-master:~/manifests# kubectl get nodes
NAME        STATUS    AGE
10.10.0.2   Ready     5d
10.10.0.3   Ready     5d

У меня есть приложение hello world nodeJS, которое предоставляет HTTP-сервер на порт 8080 и отображает «Hello world» при запросе. Это настроено так:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: hello-node-deployment
spec:
  replicas: 4
  template:
    metadata:
      labels:
        app: hello-node
    spec:
      containers:
      - name: hello-node
        image: kubernetes-master:5000/hello-node:v1
        ports:
        - containerPort: 8080

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

apiVersion: v1
kind: Service
metadata:
  name: hello-node-service
  labels:
    app: hello-node
spec:
  ports:
  - port: 8080
    protocol: TCP
  selector:
    app: hello-node
  type: NodePort

После запуска службы и развертывания:

root@kubernetes-master:~/manifests# kubectl describe service hello-node-service
Name:           hello-node-service
Namespace:      default
Labels:         app=hello-node
Selector:       app=hello-node
Type:           NodePort
IP:         10.100.0.88
Port:           <unset> 8080/TCP
NodePort:       <unset> 30862/TCP
Endpoints:      192.168.0.22:8080,192.168.0.23:8080,192.168.0.89:8080 + 1 more...
Session Affinity:   None
No events.

root@kubernetes-master:~/manifests# kubectl get pods --selector="app=hello-node" --output=wide
NAME                                    READY     STATUS    RESTARTS   AGE       IP             NODE
hello-node-deployment-815057587-0w896   1/1       Running   0          24m       192.168.0.89   10.10.0.2
hello-node-deployment-815057587-62d2b   1/1       Running   0          24m       192.168.0.23   10.10.0.3
hello-node-deployment-815057587-d6t4z   1/1       Running   0          24m       192.168.0.90   10.10.0.2
hello-node-deployment-815057587-k7qcx   1/1       Running   0          24m       192.168.0.22   10.10.0.3

После этого мастер не может связаться ни с одним из узлов на предоставленном порту узла (10.10.0.2:30862, 10.10.0.2:30862). Соединение зависает и не удается.

Если я подключаюсь к узлу через ssh, я могу успешно запросить службу, напрямую поговорив с модулем:

root@kubernetes-worker02:~# curl http://192.168.0.22:8080
Hello World!

Я что-то упустил? Это ожидаемое поведение или мои настройки нарушены?

Kubernetes требует больше, чем просто возможность общения узлов друг с другом. Также требуется сеть (или таблица маршрутизации), чтобы модули могли общаться друг с другом. По сути, это другая сеть только для модулей (часто называемая сетью наложения / основы), которая позволяет модулю на nodeA взаимодействовать с модулями на nodeB.

Судя по всему, у вас не настроена сеть модулей. Вы можете реализовать наложение сети множеством способов (что является одной из причин, по которой это так сбивает с толку). Узнать больше о сетевых требованиях Вот.

Имея всего 2 узла, я бы порекомендовал вам настроить то, что я называю «no SDN Kubernetes», и просто вручную добавлять маршруты модулей к каждому узлу. Это потребует от вас сделать 2 вещи.

  1. Укажите подсеть для модулей на каждом узле
  2. Вручную запустите команду для создания маршрута

У меня есть подробности, как это сделать на моем сообщение в блоге, которое я написал на эту тему.

К сожалению, настройка сети модулей поможет вам добиться этого только наполовину. Чтобы реализовать автоматические службы NodePort, вам также необходимо установить kube-proxy. Задача kube-proxy - следить за тем, на каком порту запускается служба, и затем направлять этот порт в нужную службу / модуль внутри кластера. Это делается через IP-таблицы и в основном происходит автоматически.

Мне не удалось найти очень хороший пример развертывания kube-proxy вручную (обычно это выполняется с помощью вашего инструмента развертывания). Вот пример DaemonSet в Кубеадм Инструмент должен автоматически создать для запуска kube-proxy на каждом узле кластера.

apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  generation: 1
  labels:
    component: kube-proxy
    k8s-app: kube-proxy
    kubernetes.io/cluster-service: "true"
    name: kube-proxy
    tier: node
  name: kube-proxy
  namespace: kube-system
spec:
  selector:
    matchLabels:
      component: kube-proxy
      k8s-app: kube-proxy
      kubernetes.io/cluster-service: "true"
      name: kube-proxy
      tier: node
  template:
    metadata:
      labels:
        component: kube-proxy
        k8s-app: kube-proxy
        kubernetes.io/cluster-service: "true"
        name: kube-proxy
        tier: node
    spec:
      containers:
      - command:
        - kube-proxy
        - --kubeconfig=/run/kubeconfig
        image: gcr.io/google_containers/kube-proxy-amd64:v1.5.2
        imagePullPolicy: IfNotPresent
        name: kube-proxy
        securityContext:
          privileged: true
        terminationMessagePath: /dev/termination-log
        volumeMounts:
        - mountPath: /var/run/dbus
          name: dbus
        - mountPath: /run/kubeconfig
          name: kubeconfig
      dnsPolicy: ClusterFirst
      hostNetwork: true
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
      volumes:
      - hostPath:
          path: /etc/kubernetes/kubelet.conf
        name: kubeconfig
      - hostPath:
          path: /var/run/dbus
        name: dbus

Еще один ресурс, который может оказаться полезным: Kubernetes: трудный путь. Это напрямую не применимо к запуску в виртуальных машинах на proxmox (предполагается, что GCE или AWS), но показывает минимальные шаги и ресурсы, необходимые для запуска работающего кластера Kubernetes.