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, виконайте наступну команду для розгортання демонстраційного застосунку:
$ kubectl apply -f @samples/curl/curl.yaml@
Інакше, вручну додайте sidecar перед розгортанням застосунку
curl
за допомогою наступної команди:$ 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
.$ 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 для доступу до зовнішніх сервісів
Створіть сервіс 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
Поспостерігайте за своїм сервісом. Зверніть увагу, що він не має кластерного IP.
$ kubectl get svc my-httpbin NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE my-httpbin ExternalName <none> httpbin.org 80/TCP 4s
Отримайте доступ до
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" } }
У цьому прикладі незашифровані 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
Отримайте доступ до
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 з точками доступу до зовнішнього сервісу
Створіть сервіс Kubernetes без селектора для Вікіпедії:
$ kubectl apply -f - <<EOF kind: Service apiVersion: v1 metadata: name: my-wikipedia spec: ports: - protocol: TCP port: 443 name: tls EOF
Створіть точки доступу для вашого сервісу. Виберіть кілька 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
Поспостерігайте за своїм сервісом. Зверніть увагу, що він має кластерний 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
Надсилайте 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>
У цьому випадку робоче навантаження надсилає 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
Отримайте доступ до
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>
Переконайтеся, що доступ дійсно виконується з 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
Очищення
Вимкніть сервіс curl:
$ kubectl delete -f @samples/curl/curl.yaml@
Вимкніть сервіс curl у просторі імен
without-istio
:$ kubectl delete -f @samples/curl/curl.yaml@ -n without-istio
Видаліть простір імен
without-istio
:$ kubectl delete namespace without-istio
Скиньте змінні оточення:
$ unset SOURCE_POD SOURCE_POD_WITHOUT_ISTIO