Services de Kubernetes para Tráfico de Salida

Los services ExternalName de Kubernetes y los services de Kubernetes con Endpoints le permiten crear un alias DNS local para un service externo. Este alias DNS tiene la misma forma que las entradas DNS para services locales, a saber, <nombre del service>.<nombre del namespace>.svc.cluster.local. Los alias DNS proporcionan transparencia de ubicación para sus workloads: los workloads pueden llamar a services locales y externos de la misma manera. Si en algún momento decide desplegar el service externo dentro de su cluster, puede simplemente actualizar su service de Kubernetes para que haga referencia a la versión local. Los workloads seguirán funcionando sin ningún cambio.

Esta tarea muestra que estos mecanismos de Kubernetes para acceder a services externos siguen funcionando con Istio. El único paso de configuración que debe realizar es usar un modo TLS diferente al mTLS de Istio. Los services externos no forman parte de una service mesh de Istio, por lo que no pueden realizar el mTLS de Istio. Debe configurar el modo TLS de acuerdo con los requisitos TLS del service externo y de acuerdo con la forma en que su workload accede al service externo. Si su workload emite solicitudes HTTP planas y el service externo requiere TLS, es posible que desee realizar la TLS origination por Istio. Si su workload ya utiliza TLS, el tráfico ya está cifrado y simplemente puede deshabilitar el mTLS de Istio.

Aunque los ejemplos de esta tarea utilizan protocolos HTTP, los Services de Kubernetes para tráfico de salida también funcionan con otros protocolos.

Antes de empezar

  • Configura Istio siguiendo las instrucciones de la Guía de instalación.

  • Despliega la aplicación de ejemplo curl para usarla como fuente de prueba para enviar solicitudes. Si tienes habilitada la inyección automática de sidecar , ejecuta el siguiente comando para desplegar la aplicación de ejemplo:

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

    De lo contrario, inyecta manualmente el sidecar antes de desplegar la aplicación curl con el siguiente comando:

    Zip
    $ kubectl apply -f <(istioctl kube-inject -f @samples/curl/curl.yaml@)
  • Establece la variable de entorno SOURCE_POD con el nombre de tu pod de origen:

    $ export SOURCE_POD=$(kubectl get pod -l app=curl -o jsonpath={.items..metadata.name})
  • Cree un namespace para un pod de origen sin control de Istio:

    $ kubectl create namespace without-istio
  • Inicie la muestra curl en el namespace without-istio.

    Zip
    $ kubectl apply -f @samples/curl/curl.yaml@ -n without-istio
  • Para enviar solicitudes, cree la variable de entorno SOURCE_POD_WITHOUT_ISTIO para almacenar el nombre del pod de origen:

    $ export SOURCE_POD_WITHOUT_ISTIO="$(kubectl get pod -n without-istio -l app=curl -o jsonpath={.items..metadata.name})"
  • Verifique que el sidecar de Istio no fue inyectado, es decir, que el pod tiene un solo contenedor:

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

Service ExternalName de Kubernetes para acceder a un service externo

  1. Cree un service ExternalName de Kubernetes para httpbin.org en el namespace predeterminado:

    $ 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. Observe su service. Tenga en cuenta que no tiene una IP de cluster.

    $ kubectl get svc my-httpbin
    NAME         TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
    my-httpbin   ExternalName   <none>       httpbin.org   80/TCP    4s
  3. Acceda a httpbin.org a través del hostname del service de Kubernetes desde el pod de origen sin sidecar de Istio. Tenga en cuenta que el comando curl a continuación utiliza el formato DNS de Kubernetes para services: <nombre del service>.<namespace>.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. En este ejemplo, se envían solicitudes HTTP sin cifrar a httpbin.org. Solo para el ejemplo, deshabilita el modo TLS y permite el tráfico sin cifrar al service externo. En escenarios reales, recomendamos realizar la TLS origination de salida por 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. Acceda a httpbin.org a través del hostname del service de Kubernetes desde el pod de origen con sidecar de Istio. Observe las cabeceras agregadas por el sidecar de Istio, por ejemplo X-Envoy-Peer-Metadata. También tenga en cuenta que la cabecera Host es igual al hostname de su service.

    $ 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"
      }
    }

Limpieza del service ExternalName de Kubernetes

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

Usar un service de Kubernetes con endpoints para acceder a un service externo

  1. Cree un service de Kubernetes sin selector para Wikipedia:

    $ kubectl apply -f - <<EOF
    kind: Service
    apiVersion: v1
    metadata:
      name: my-wikipedia
    spec:
      ports:
      - protocol: TCP
        port: 443
        name: tls
    EOF
  2. Cree endpoints para su service. Elija un par de IPs de la lista de rangos de Wikipedia.

    $ 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. Observe su service. Tenga en cuenta que tiene una IP de cluster que puede usar para acceder a 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. Envíe solicitudes HTTPS a wikipedia.org por la IP del cluster de su service de Kubernetes desde el pod de origen sin sidecar de Istio. Use la opción --resolve de curl para acceder a wikipedia.org por la IP del cluster:

    $ 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, la enciclopedia libre</title>
  5. En este caso, el workload envía solicitudes HTTPS (abre conexión TLS) a wikipedia.org. El tráfico ya está cifrado por el workload, por lo que puede deshabilitar de forma segura el mTLS de 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. Acceda a wikipedia.org por la IP del cluster de su service de Kubernetes desde el pod de origen con sidecar de 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, la enciclopedia libre</title>
  7. Verifique que el acceso se realiza realmente por la IP del cluster. Observe la frase Connected to en.wikipedia.org (172.21.156.230) en la salida de curl -v, menciona la IP que se imprimió en la salida de su service como la IP del cluster.

    $ 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)
    ...

Limpieza del service de Kubernetes con endpoints

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

Limpieza

  1. Apague el service curl:

    Zip
    $ kubectl delete -f @samples/curl/curl.yaml@
  2. Apague el service curl en el namespace without-istio:

    Zip
    $ kubectl delete -f @samples/curl/curl.yaml@ -n without-istio
  3. Elimine el namespace without-istio:

    $ kubectl delete namespace without-istio
  4. Desestablezca las variables de entorno:

    $ unset SOURCE_POD SOURCE_POD_WITHOUT_ISTIO
¿Fue útil esta información?
¿Tienes alguna sugerencia para mejorar?

¡Gracias por tus comentarios!