Kubernetes Services для вихідного трафіку

Kubernetes-сервіси ExternalName та Kubernetes-сервіси з Endpoints дозволяють створити локальний DNS псевдонім для зовнішнього сервісу. Цей DNS-псевдонім має такий же формат, як і DNS-записи для локальних сервісів, а саме <імʼя сервісу>.<імʼя простору імен>.svc.cluster.local. DNS-псевдоніми забезпечують прозорість розташування для ваших робочих навантажень: робочі навантаження можуть викликати як локальні, так і зовнішні сервіси однаковим чином. Якщо в певний момент ви вирішите розгорнути зовнішній сервіс всередині свого кластера, ви можете просто оновити його Kubernetes-сервіс для посилання на локальну версію. Робочі навантаження продовжать працювати без будь-яких змін.

Це завдання показує, що ці механізми Kubernetes для доступу до зовнішніх сервісів продовжують працювати з Istio. Єдиний крок конфігурації, який потрібно виконати, це використати TLS-режим, відмінний від взаємного TLS Istio. Зовнішні сервіси не є частиною сервісної мережі Istio, тому вони не можуть виконувати взаємний TLS Istio. Ви повинні встановити TLS-режим відповідно до вимог TLS зовнішнього сервісу та способу, яким ваші робочі навантаження звертаються до зовнішнього сервісу. Якщо ваші робочі навантаження виконують прості HTTP-запити, а зовнішній сервіс вимагає TLS, можливо, вам варто виконати ініціалізацію TLS через Istio. Якщо ваші робочі навантаження вже використовують TLS, трафік вже зашифрований, то ви можете просто вимкнути взаємний TLS Istio.

Хоча в прикладах цього завдання використовуються HTTP-протоколи, Kubernetes-сервіси для вихідного трафіку працюють також з іншими протоколами.

Перш ніж розпочати

  • Налаштуйте Istio, дотримуючися інструкцій у посібнику з встановлення.

  • Розгорніть демонстраційний застосунок curl для використання як джерело тестових запитів. Якщо у вас увімкнено автоматичне додавання sidecar, виконайте наступну команду для розгортання демонстраційного застосунку:

    Zip
    $ kubectl apply -f @samples/curl/curl.yaml@

    Інакше, вручну додайте sidecar перед розгортанням застосунку curl за допомогою наступної команди:

    Zip
    $ kubectl apply -f <(istioctl kube-inject -f @samples/curl/curl.yaml@)
  • Встановіть змінну середовища SOURCE_POD на імʼя вашого podʼа:

    $ export SOURCE_POD=$(kubectl get pod -l app=curl -o jsonpath={.items..metadata.name})
  • Створіть простір імен для вихідного pod без керування Istio:

    $ kubectl create namespace without-istio
  • Запустіть зразок curl у просторі імен without-istio.

    Zip
    $ kubectl apply -f @samples/curl/curl.yaml@ -n without-istio
  • Для надсилання запитів створіть змінну оточення SOURCE_POD_WITHOUT_ISTIO для зберігання назви джерела podʼа:

    $ export SOURCE_POD_WITHOUT_ISTIO="$(kubectl get pod -n without-istio -l app=curl -o jsonpath={.items..metadata.name})"
  • Переконайтеся, що sidecar Istio не була додано, тобто pod має один контейнер:

    $ kubectl get pod "$SOURCE_POD_WITHOUT_ISTIO" -n without-istio
    NAME                     READY   STATUS    RESTARTS   AGE
    curl-66c8d79ff5-8tqrl    1/1     Running   0          32s

Сервіс Kubernetes ExternalName для доступу до зовнішніх сервісів

  1. Створіть сервіс Kubernetes ExternalName для httpbin.org у просторі імен default:

    $ kubectl apply -f - <<EOF
    kind: Service
    apiVersion: v1
    metadata:
      name: my-httpbin
    spec:
      type: ExternalName
      externalName: httpbin.org
      ports:
      - name: http
        protocol: TCP
        port: 80
    EOF
  2. Поспостерігайте за своїм сервісом. Зверніть увагу, що він не має кластерного IP.

    $ kubectl get svc my-httpbin
    NAME         TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
    my-httpbin   ExternalName   <none>       httpbin.org   80/TCP    4s
  3. Отримайте доступ до httpbin.org через імʼя хосту сервісу Kubernetes з вихідного podʼа без Istio sidecar. Зверніть увагу, що команда curl нижче використовує формат DNS Kubernetes для сервісів: <назва сервісу>.<простір імен>.svc.cluster.local.

    $ kubectl exec "$SOURCE_POD_WITHOUT_ISTIO" -n without-istio -c curl -- curl -sS my-httpbin.default.svc.cluster.local/headers
    {
      "headers": {
        "Accept": "*/*",
        "Host": "my-httpbin.default.svc.cluster.local",
        "User-Agent": "curl/7.55.0"
      }
    }
  4. У цьому прикладі незашифровані HTTP-запити надсилаються на httpbin.org. Лише для прикладу, ви відключаєте режим TLS і дозволити незашифрований трафік до зовнішнього сервісу. У реальних сценаріях ми рекомендуємо виконати Створення TLS для вихідного трафіку за допомогою Istio.

    $ kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1
    kind: DestinationRule
    metadata:
      name: my-httpbin
    spec:
      host: my-httpbin.default.svc.cluster.local
      trafficPolicy:
        tls:
          mode: DISABLE
    EOF
  5. Отримайте доступ до httpbin.org через імʼя хоста Kubernetes-сервісу з вихідного podʼа з Istio sidecar. Зверніть увагу на заголовки, додані Istio sidecar, наприклад, X-Envoy-Peer-Metadata. Також зауважте, що заголовок Host дорівнює імені хосту вашого сервісу.

    $ kubectl exec "$SOURCE_POD" -c curl -- curl -sS my-httpbin.default.svc.cluster.local/headers
    {
      "headers": {
        "Accept": "*/*",
        "Content-Length": "0",
        "Host": "my-httpbin.default.svc.cluster.local",
        "User-Agent": "curl/7.64.0",
        "X-B3-Sampled": "0",
        "X-B3-Spanid": "5795fab599dca0b8",
        "X-B3-Traceid": "5079ad3a4af418915795fab599dca0b8",
        "X-Envoy-Peer-Metadata": "...",
        "X-Envoy-Peer-Metadata-Id": "sidecar~10.28.1.74~curl-6bdb595bcb-drr45.default~default.svc.cluster.local"
      }
    }

Видалення сервісу Kubernetes ExternalName

$ kubectl delete destinationrule my-httpbin
$ kubectl delete service my-httpbin

Використовуйте сервіс Kubernetes з точками доступу до зовнішнього сервісу

  1. Створіть сервіс Kubernetes без селектора для Вікіпедії:

    $ kubectl apply -f - <<EOF
    kind: Service
    apiVersion: v1
    metadata:
      name: my-wikipedia
    spec:
      ports:
      - protocol: TCP
        port: 443
        name: tls
    EOF
  2. Створіть точки доступу для вашого сервісу. Виберіть кілька IP-адрес зі списку діапазонів Вікіпедії (https://www.mediawiki.org/wiki/Wikipedia_Zero/IP_Addresses).

    $ kubectl apply -f - <<EOF
    kind: Endpoints
    apiVersion: v1
    metadata:
      name: my-wikipedia
    subsets:
      - addresses:
          - ip: 198.35.26.96
          - ip: 208.80.153.224
        ports:
          - port: 443
            name: tls
    EOF
  3. Поспостерігайте за своїм сервісом. Зверніть увагу, що він має кластерний IP, який ви можете використовувати для доступу до wikipedia.org.

    $ kubectl get svc my-wikipedia
    NAME           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
    my-wikipedia   ClusterIP   172.21.156.230   <none>        443/TCP   21h
  4. Надсилайте HTTPS-запити до wikipedia.org за IP кластера вашого сервісу Kubernetes з вихідного podʼа без Istio sidecar. Використовуйте параметр --resolve у команді curl для доступу до wikipedia.org за кластерною IP-адресою:

    $ kubectl exec "$SOURCE_POD_WITHOUT_ISTIO" -n without-istio -c curl -- curl -sS --resolve en.wikipedia.org:443:"$(kubectl get service my-wikipedia -o jsonpath='{.spec.clusterIP}')" https://en.wikipedia.org/wiki/Main_Page | grep -o "<title>.*</title>"
    <title>Wikipedia, the free encyclopedia</title>
  5. У цьому випадку робоче навантаження надсилає HTTPS-запити (відкрите TLS-зʼєднання) до wikipedia.org. Трафік вже зашифрований робочим навантаженням зашифрований робочим навантаженням, тому ви можете безпечно відключити взаємний TLS в Istio:

    $ kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1
    kind: DestinationRule
    metadata:
      name: my-wikipedia
    spec:
      host: my-wikipedia.default.svc.cluster.local
      trafficPolicy:
        tls:
          mode: DISABLE
    EOF
  6. Отримайте доступ до wikipedia.org за IP-адресою кластера вашого сервісу Kubernetes з вихідного podʼа за допомогою sidecar Istio:

    $ kubectl exec "$SOURCE_POD" -c curl -- curl -sS --resolve en.wikipedia.org:443:"$(kubectl get service my-wikipedia -o jsonpath='{.spec.clusterIP}')" https://en.wikipedia.org/wiki/Main_Page | grep -o "<title>.*</title>"
    <title>Wikipedia, the free encyclopedia</title>
  7. Переконайтеся, що доступ дійсно виконується з IP кластера. Зверніть увагу на речення Connected to en.wikipedia.org (172.21.156.230) у виводі curl -v, в ньому згадується IP, який було надруковано у виводі вашого сервісу як IP кластера.

    $ kubectl exec "$SOURCE_POD" -c curl -- curl -sS -v --resolve en.wikipedia.org:443:"$(kubectl get service my-wikipedia -o jsonpath='{.spec.clusterIP}')" https://en.wikipedia.org/wiki/Main_Page -o /dev/null
    * Added en.wikipedia.org:443:172.21.156.230 to DNS cache
    * Hostname en.wikipedia.org was found in DNS cache
    *   Trying 172.21.156.230...
    * TCP_NODELAY set
    * Connected to en.wikipedia.org (172.21.156.230) port 443 (#0)
    ...

Видалення сервісу Kubernetes з точками доступу

$ kubectl delete destinationrule my-wikipedia
$ kubectl delete endpoints my-wikipedia
$ kubectl delete service my-wikipedia

Очищення

  1. Вимкніть сервіс curl:

    Zip
    $ kubectl delete -f @samples/curl/curl.yaml@
  2. Вимкніть сервіс curl у просторі імен without-istio:

    Zip
    $ kubectl delete -f @samples/curl/curl.yaml@ -n without-istio
  3. Видаліть простір імен without-istio:

    $ kubectl delete namespace without-istio
  4. Скиньте змінні оточення:

    $ unset SOURCE_POD SOURCE_POD_WITHOUT_ISTIO
Чи була ця інформація корисною?
Чи є у вас пропозиції щодо покращення?

Дякуємо за ваш відгук!