• Русский
  • Создание сервисов

    В 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.