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

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

Содержание

Зачем нужен Service

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

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

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

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

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

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

Пример Service типа 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, на которые нацелен Service, обычно определяется селектором, который вы задаёте.
  3. Порт Service.
  4. Привязка targetPort Service к containerPort Pod. Также можно ссылаться на port.name в контейнере Pod.

Headless Services

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

spec:
  clusterIP: None

Headless Services полезны, когда:

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

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

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

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

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

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

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

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

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

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

    • Label Selector: Service будет перенаправлять запросы на определённый тип workload с указанными метками, например, environment: release.
    PortИспользуется для настройки сопоставления портов для этого Service. В следующем примере другие Pod внутри кластера могут обращаться к этому Service через виртуальный IP (если включён) и TCP порт 80; запросы будут перенаправлены на внешний TCP порт 6379 или redis Pod целевого компонента.
    • Protocol: Протокол, используемый Service, поддерживаются: TCP, UDP, HTTP, HTTP2, HTTPS, gRPC.
    • Service Port: Номер порта, который Service экспонирует внутри кластера, то есть Port, например, 80.
    • Container Port: Целевой порт (или имя), на который маппится service 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 к Service:

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

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

Разумеется, можно также получить доступ к приложению из вне кластера, создав Service типа 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 в данный момент не развернут в кластере.

Пример: Service типа 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.

Аннотации для Service типа LoadBalancer

AWS EKS Cluster

Для подробного описания аннотаций LoadBalancer Service в 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 Service в 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 Service в AKS, пожалуйста, обратитесь к Annotation Usage Documentation .

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

Google GKE Cluster

Для подробного описания аннотаций LoadBalancer Service в GKE, пожалуйста, обратитесь к Annotation Usage Documentation .

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