Создание сервисов

В Kubernetes сервис — это способ открыть сетевое приложение, работающее в виде одного или нескольких Pod в вашем кластере.

Содержание

Зачем нужен сервис

  1. У Pod есть собственные IP, но:

    • IP Pod нестабильны (меняются при пересоздании Pod).

    • Прямой доступ к Pod становится ненадежным.

  2. Сервис решает эту проблему, предоставляя:

    • Стабильный IP и DNS-имя.

    • Автоматическое балансирование нагрузки на соответствующие Pod.

Пример сервиса типа ClusterIP:

# simple-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: ClusterIP
  selector:
    app.kubernetes.io/name: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  1. Доступные значения type и их поведение: ClusterIP, NodePort, LoadBalancer, ExternalName
  2. Набор Pod, на которые нацелен сервис, обычно определяется селектором, который вы задаёте.
  3. Порт сервиса.
  4. Привязка targetPort сервиса к containerPort Pod. Также можно ссылаться на port.name внутри контейнера Pod.

Headless-сервисы

Иногда не требуется балансировка нагрузки и единый IP сервиса. В таком случае можно создать так называемые headless-сервисы:

spec:
  clusterIP: None

Headless-сервисы полезны, когда:

  • Нужно обнаруживать отдельные IP Pod, а не только один IP сервиса.

  • Требуются прямые подключения к каждому Pod (например, для баз данных типа Cassandra или StatefulSets).

  • Используются StatefulSets, где каждый Pod должен иметь стабильное DNS-имя.

Создание сервиса через веб-консоль

  1. Перейдите в Container Platform.

  2. В левой панели навигации выберите Network > Services.

  3. Нажмите Create Service.

  4. Следуйте инструкциям для настройки соответствующих параметров.

    ПараметрОписание
    Virtual IP AddressЕсли включено, для сервиса будет выделен ClusterIP, который можно использовать для обнаружения сервиса внутри кластера.
    Если отключено, будет создан headless-сервис, который обычно используется для StatefulSet.
    Type
    • ClusterIP: Открывает сервис на внутреннем IP кластера. При выборе этого значения сервис доступен только внутри кластера.
    • NodePort: Открывает сервис на IP каждого узла на статическом порту (NodePort).
    • ExternalName: Отображает сервис на содержимое поля externalName (например, на hostname api.foo.bar.example).
    • LoadBalancer: Открывает сервис снаружи с помощью внешнего балансировщика нагрузки. Kubernetes напрямую не предоставляет компонент балансировки нагрузки; необходимо предоставить его самостоятельно или интегрировать кластер с облачным провайдером.
    Target Component
    • Workload: Сервис будет перенаправлять запросы на конкретную нагрузку, которая соответствует меткам, например project.cpaas.io/name: projectname и service.cpaas.io/name: deployment-name.

    • Virtualization: Сервис будет перенаправлять запросы на конкретную виртуальную машину или группу виртуальных машин.

    • Label Selector: Сервис будет перенаправлять запросы на определённый тип нагрузки с указанными метками, например environment: release.
    PortИспользуется для настройки сопоставления портов сервиса. В следующем примере другие Pod внутри кластера могут обращаться к сервису по виртуальному IP (если включено) и TCP-порту 80; запросы будут перенаправлены на внешний TCP-порт 6379 или redis Pod целевого компонента.
    • Protocol: Протокол, используемый сервисом, поддерживаются: TCP, UDP, HTTP, HTTP2, HTTPS, gRPC.
    • Service Port: Номер порта сервиса, открытого внутри кластера, то есть Port, например 80.
    • Container Port: Целевой номер порта (или имя), на который маппится порт сервиса, то есть targetPort, например 6379 или redis.
    • Service Port Name: Генерируется автоматически. Формат: <protocol>-<service port>-<container port>, например: tcp-80-6379 или tcp-80-redis.
    Session AffinityСессия с привязкой по IP-адресу источника (ClientIP). Если включено, все запросы с одного и того же IP будут направляться на один и тот же сервер при балансировке нагрузки, что гарантирует обработку запросов от одного клиента одним сервером.
  5. Нажмите Create.

Создание сервиса через CLI

kubectl apply -f simple-service.yaml

Создать сервис на основе существующего ресурса deployment my-app.

kubectl expose deployment my-app \
  --port=80 \
  --target-port=8080 \
  --name=test-service \
  --type=NodePort \
  -n p1-1

Пример: Доступ к приложению внутри кластера

# access-internal-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.25
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-clusterip
spec:
  type: ClusterIP
  selector:
    app: nginx
  ports:
    - port: 80
      targetPort: 80
  1. Примените этот YAML:

    kubectl apply -f access-internal-demo.yaml
  2. Запустите другой Pod:

    kubectl run test-pod --rm -it --image=busybox -- /bin/sh
  3. Доступ к сервису nginx-clusterip из Pod test-pod:

    wget -qO- http://nginx-clusterip
    # или используя DNS-записи, созданные автоматически Kubernetes: <service-name>.<namespace>.svc.cluster.local
    wget -qO- http://nginx-clusterip.default.svc.cluster.local

Вы должны увидеть HTML-ответ с текстом вроде "Welcome to nginx!".

Пример: Доступ к приложению вне кластера

# access-external-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.25
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-nodeport
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30080
  1. Примените этот YAML:

    kubectl apply -f access-external-demo.yaml
  2. Проверка Pod:

    kubectl get pods -l app=nginx -o wide
  3. curl к сервису:

    curl http://{NodeIP}:{nodePort}

Вы должны увидеть HTML-ответ с текстом вроде "Welcome to nginx!".

Разумеется, можно также получить доступ к приложению снаружи кластера, создав сервис типа LoadBalancer.

Примечание: Пожалуйста, настройте сервис LoadBalancer заранее.

# access-external-demo-with-loadbalancer.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.25
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-lb-service
spec:
  type: LoadBalancer
  selector:
    app: nginx
  ports:
    - port: 80
      targetPort: 80
  1. Примените этот YAML:

    kubectl apply -f access-external-demo-with-loadbalancer.yaml
  2. Получите внешний IP-адрес:

    kubectl get svc nginx-lb-service
    NAME            TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)        AGE
    nginx-service   LoadBalancer   10.0.2.57        34.122.45.100   80:30005/TCP   30s

    EXTERNAL-IP — это адрес, по которому вы можете получить доступ из браузера.

    curl http://34.122.45.100

Вы должны увидеть HTML-ответ с текстом вроде "Welcome to nginx!".

Если EXTERNAL-IP равен pending, значит сервис LoadBalancer в данный момент не развернут в кластере.

Пример: Сервис типа ExternalName

apiVersion: v1
kind: Service
metadata:
  name: my-external-service
  namespace: default
spec:
  type: ExternalName
  externalName: example.com
  1. Примените этот YAML:

    kubectl apply -f external-service.yaml
  2. Попробуйте разрешить имя внутри Pod в кластере:

    kubectl run test-pod --rm -it --image=busybox -- sh

    затем:

    nslookup my-external-service.default.svc.cluster.local

Вы увидите, что оно разрешается в example.com.

Аннотации для сервиса типа LoadBalancer

AWS EKS Cluster

Для подробного описания аннотаций сервиса LoadBalancer в EKS смотрите Annotation Usage Documentation .

КлючЗначениеОписание
service.beta.kubernetes.io/aws-load-balancer-typeexternal: Использовать официальный AWS LoadBalancer Controller.Определяет контроллер для типа LoadBalancer.

Примечание: Пожалуйста, заранее свяжитесь с администратором платформы для развертывания AWS LoadBalancer Controller.
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type
  • instance: Трафик будет направляться на Pod через NodePort.
  • ip: Трафик направляется напрямую на Pod (кластер должен использовать Amazon VPC CNI).
Определяет, как трафик достигает Pod.
service.beta.kubernetes.io/aws-load-balancer-scheme
  • internal: Частная сеть.
  • internet-facing: Публичная сеть.
Определяет, использовать ли частную или публичную сеть.
service.beta.kubernetes.io/aws-load-balancer-ip-address-type
  • IPv4
  • dualstack
Определяет поддерживаемый стек IP-адресов.

Huawei Cloud CCE Cluster

Для подробного описания аннотаций сервиса LoadBalancer в CCE смотрите Annotation Usage Documentation .

КлючЗначениеОписание
kubernetes.io/elb.idУкажите ID облачного балансировщика нагрузки, должен использоваться существующий облачный балансировщик.
kubernetes.io/elb.autocreateПример: {"type":"public","bandwidth_name":"cce-bandwidth-1551163379627","bandwidth_chargemode":"bandwidth","bandwidth_size":5,"bandwidth_sharetype":"PER","eip_type":"5_bgp","available_zone":["cn-north-4b"],"l4_flavor_name":"L4_flavor.elb.s1.small"}

Примечание: Пожалуйста, сначала ознакомьтесь с инструкцией по заполнению и при необходимости скорректируйте параметры примера.
Новый облачный балансировщик нагрузки для создания.
kubernetes.io/elb.subnet-idID подсети, в которой расположен кластер. При версии Kubernetes 1.11.7-r0 и ниже это поле обязательно при создании нового облачного балансировщика нагрузки.
kubernetes.io/elb.class
  • union: Общая балансировка нагрузки.
  • performance: Эксклюзивная балансировка нагрузки, поддерживается только в Kubernetes версии 1.17 и выше.
Определяет тип создаваемого облачного балансировщика нагрузки, см. Различия между эксклюзивной и общей балансировкой нагрузки.
kubernetes.io/elb.enterpriseIDОпределяет проект предприятия, к которому принадлежит создаваемый облачный балансировщик нагрузки.

Azure AKS Cluster

Для подробного описания аннотаций сервиса LoadBalancer в AKS смотрите Annotation Usage Documentation .

КлючЗначениеОписание
service.beta.kubernetes.io/azure-load-balancer-internal
  • true: Частная сеть.
  • false: Публичная сеть.
Определяет, использовать ли частную или публичную сеть.

Google GKE Cluster

Для подробного описания аннотаций сервиса LoadBalancer в GKE смотрите Annotation Usage Documentation .

КлючЗначениеОписание
networking.gke.io/load-balancer-typeInternalОпределяет использование частной сети.
loud.google.com/l4-rbsenabledПо умолчанию публичный. Если этот параметр настроен, трафик будет направляться напрямую на Pod.