Network

В кластере kubernetes можно выделить три типа сетей:

  • Сеть нод(узлов) - данная сеть обеспечивает связь между узлами кластера.

  • Сеть подов - каждый под в кластере имеет свой уникальны IP адрес в этой сети, данная сеть связывает поды как на одной ноде так и на разных.

  • Сеть сервисов - виртуальная сеть, позволяющая обращаться к группе подов, распределяя трафик между ними.

Для обеспечения связности внутри кластера используются различные CNI плагины, которые обеспечивают подключение пода в подовую сеть на ноде, а также обеспечивают взаимодействие подов на разных нодах, например, создавая оверлейную сеть. Для управления сетью сервисов существует стандартный компонент kube-proxy, обеспечивающий распределение трафика от IP адреса сервиса к IP адресам подов.

Концепции

  • Service: это абстракция, которая предоставляет устойчивый IP-адрес и DNS-имя для группы связанных подов. Service может использоваться для балансировки нагрузки между несколькими экземплярами приложения или между различными приложениями в кластере.

  • Ingress: это объект, который управляет внешним доступом к сервисам в кластере. Ingress может маршрутизировать трафик на основе различных критериев, таких как путь URL и заголовки HTTP.

  • Network Policy: это объект, который определяет правила безопасности для сети Kubernetes. С помощью Network Policy можно ограничить трафик между различными сервисами и подами в кластере.

  • DNS: это сервис, который предоставляет разрешение имен для объектов Kubernetes. DNS-имена могут использоваться для связи между различными сервисами и подами в кластере.

Service/Endpoints

В Kubernetes сервис (Service) - это абстракция, которая представляет собой логическое имя и IP-адрес, которые используются для обеспечения доступа к группе подов.

apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  ports:
  - name: web
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: nginx
  type: ClusterIP

Выбор подов как и в других ресурсах производится с помощью селектора по лейблам spec.selector.

Поле spec.type определяет тип сервиса, существует следующие типы:

  • ClusterIP: это тип сервиса, который назначает виртуальный IP-адрес сервису. Этот IP-адрес доступен только внутри кластера и используется для связи между подами в кластере.

  • NodePort: это тип сервиса, который открывает порт на каждой ноде кластера и перенаправляет трафик на соответствующий порт в подах, связанных с этим сервисом. Такой сервис доступен снаружи кластера через IP-адрес ноды и порт NodePort.

  • LoadBalancer: это тип сервиса, который создает внешний балансировщик нагрузки и назначает ему виртуальный IP-адрес. Балансировщик нагрузки перенаправляет трафик на соответствующие поды, связанные с этим сервисом. Такой сервис доступен снаружи кластера через IP-адрес балансировщика нагрузки.

  • ExternalName: в отличии от других типов не имеет селектор, он создает CNAME запись во внутреннем DNS, ссылающуюся на внешний ресурс.

Поле spec.ports определяет в какие порты пода будет производиться перенаправление трафика:

  • name (опционально) - имя порта, которое можно использовать для ссылки на порт в других частях манифеста сервиса.

  • port - номер порта на сервисе.

  • targetPort - номер порта на поде, который сервис должен направлять входящие соединения.

  • protocol (опционально) - протокол порта (TCP или UDP). По умолчанию используется TCP.

  • nodePort (опционально) - номер порта на каждой ноде кластера, который будет проксировать входящие соединения на порт сервиса

Сервисы также могут использоваться для реализации масштабирования приложений, когда новые поды могут быть добавлены и удалены из группы подов, связанной с сервисом, без изменения IP-адреса и имени сервиса.

Каждый раз, когда создается новый сервис, Kubernetes создает объект Endpoints, который содержит список IP-адресов и портов, соответствующих конечным точкам, связанным с сервисом. Этот список конечных точек автоматически обновляется Kubernetes в соответствии с изменениями количества запущенных подов в кластере. Endpoints обеспечивает прямое взаимодействие между сервисами и подами.

apiVersion: v1
kind: Endpoints
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: default
subsets:
- addresses:
  - ip: 10.244.1.5
    nodeName: kind-worker2
    targetRef:
      kind: Pod
      name: nginx-deployment-76d6c9b8c-n6c4f
      namespace: default
      uid: 7ec844ca-36d9-4082-a7ea-e0cd8e95d390
  - ip: 10.244.2.25
    nodeName: kind-worker
    targetRef:
      kind: Pod
      name: nginx-deployment-76d6c9b8c-9h2fn
      namespace: default
      uid: a93b7fd4-43b1-4c85-897b-3d150a8ec3dd
  - ip: 10.244.2.26
    nodeName: kind-worker
    targetRef:
      kind: Pod
      name: nginx-deployment-76d6c9b8c-r9vll
      namespace: default
      uid: d31680a6-1aad-439c-84a2-aee8c5d1930e
  ports:
  - name: web
    port: 8080
    protocol: TCP

Endpointslices - это новый объект Kubernetes, который был введен в версии Kubernetes 1.19. Endpointslice является более эффективной и масштабируемой заменой Endpoints. Endpointslices разделяются на куски, которые содержат небольшое количество конечных точек и могут динамически обновляться.

apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
  name: nginx-k7j7n
addressType: IPv4
endpoints:
- addresses:
  - 10.244.1.5
  conditions:
    ready: true
    serving: true
    terminating: false
  nodeName: kind-worker2
  targetRef:
    kind: Pod
    name: nginx-deployment-76d6c9b8c-n6c4f
    namespace: default
    uid: 7ec844ca-36d9-4082-a7ea-e0cd8e95d390
- addresses:
  - 10.244.2.25
  conditions:
    ready: true
    serving: true
    terminating: false
  nodeName: kind-worker
  targetRef:
    kind: Pod
    name: nginx-deployment-76d6c9b8c-9h2fn
    namespace: default
    uid: a93b7fd4-43b1-4c85-897b-3d150a8ec3dd
- addresses:
  - 10.244.2.26
  conditions:
    ready: true
    serving: true
    terminating: false
  nodeName: kind-worker
  targetRef:
    kind: Pod
    name: nginx-deployment-76d6c9b8c-r9vll
    namespace: default
    uid: d31680a6-1aad-439c-84a2-aee8c5d1930e
ports:
- name: web
  port: 80
  protocol: TCP

Ingress/Ingress controller

Ingress Controller - это компонент Kubernetes, который обрабатывает входящие HTTP/HTTPS-запросы в кластер и маршрутизирует их к соответствующим сервисам на основе правил, заданных в объекте Ingress.

Одним из самых популярных Ingress-контроллеров является Nginx Ingress Controller, который может быть настроен для обработки различных правил маршрутизации на основе Ingress. Он может выполнять функции балансировки нагрузки, управления маршрутизацией трафика, обеспечения безопасности и дополнительных функций.

Ingress - это объект Kubernetes, который определяет правила маршрутизации входящих запросов на основе их хост- и путь-сопоставления. Ingress можно использовать для настройки балансировки нагрузки, HTTPS-шифрования, аутентификации и авторизации входящих запросов.

Ingress определяет правила маршрутизации трафика, которые состоят из нескольких частей:

  • Правила (rules) - определяют, какие входящие запросы должны быть направлены на какой сервис. Каждое правило содержит один или несколько хостов, которые будут использоваться для маршрутизации, а также определяет, какой сервис должен быть использован для обработки запросов.

  • Правила маршрутизации (paths) - определяют, какой путь в URL-адресе запроса должен быть направлен на какой сервис. Маршруты определяются с помощью регулярных выражений и могут быть использованы для маршрутизации запросов, направленных на различные пути в приложении.

  • Сервисы (services) - определяются в качестве конечных точек для входящих запросов. Каждый сервис определяет, какой порт должен быть использован для обработки запросов.

Пример манифеста Ingress для приложения, которое использует два сервиса (frontend и backend), и доступно по двум хостам (app.example.com и api.example.com):

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
spec:
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: frontend
            port:
              name: http
  - host: api.example.com
    http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: backend
            port:
              name: http

В этом примере Ingress определяет два правила маршрутизации - одно для хоста app.example.com, которое направляет запросы на сервис frontend, и одно для хоста api.example.com, которое направляет запросы на сервис backend.

Network Policies

Network Policy - это механизм в Kubernetes, который позволяет определить правила доступа к сетевым ресурсам в кластере. С помощью Network Policy можно настроить сегментацию сети и ограничить доступ к сервисам в кластере на уровне сети.

Сущности, с которыми определяются правила доступа, могут быть:

  • Pods

  • Namespaces

  • IP Blocks

По умолчанию в Kubernetes отсутствует политика, которая ограничивает сетевой трафик между подами. Это означает, что если не задана явная политика для пода или неймспейса, то он может свободно общаться со всеми другими подами в кластере.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: netpol
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - ipBlock:
            cidr: 172.17.0.0/16
            except:
              - 172.17.1.0/24
        - namespaceSelector:
            matchLabels:
              project: myproject
        - podSelector:
            matchLabels:
              role: frontend
      ports:
        - protocol: TCP
          port: 6379
  egress:
    - to:
        - ipBlock:
            cidr: 10.0.0.0/24
      ports:
        - protocol: TCP
          port: 5978

Примечание

Network Policies реализуются сетевыми плагинами кластера, таким образом нужно убедиться что используемый в кластере сетевой плагин поддерживает их.

DNS

В кластере Kubernetes имеется свой DNS сервер(по умолчанию используется coredns), который создает записи для ресурсов Pod и Service.

Service

Для обычных сервисов(не headless) создается запись вида svc-name.namespace.svc.cluster.local, которая разрешается в ClusterIP сервиса.

Для headless сервисов(которые не имеют ClusterIP) также создается данная запись, но разрешается в IP адреса всех подов, которые отслеживает сервис через селектор.

Pod

Для подов создается запись вида pod-ip-address.namespace.pod.cluster.local, например 172-17-0-3.default.pod.cluster.local. Также для каждого пода за сервисом создается запись вида pod-ip-address.svc-name.namespace.svc.cluster.local.