现象

能够内部无法访问外部服务。

  1. 在部署测试服务
  1. kubectl apply -f samples/sleep/sleep.yaml
  1. 设置环境变量
  1. export SOURCE_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
  1. 访问外网服务
  1. $ kubectl exec -it $SOURCE_POD -c sleep -- curl http://www.baidu.com
  2. $ kubectl exec -it $SOURCE_POD -c sleep -- curl -I https://www.baidu.com | grep "HTTP/"
  3. command terminated with exit code 35

进入sleep容器,执行curl http://www.baidu.com,无数据返回;执行curl -I https://www.baidu.com也访问失败。这种现象就是内部无法访问外部服务。

原因

由于某些情况下,来自Istio-enable Pod的所有出站流量都会重定向到其Sidecar代理,外部外部URL的可访问性替代代理的配置。在其他情况下,Istio将使Envoy代理配置为允许传递未知服务的请求。但这不是Istio推荐的做法,因此,商服务或者其他安装配置可能会修改默认设置为不允许传递未知服务的请求。

当遇到遇到内部无法访问外部服务时,可运行以下命令检查Sidecar的代理配置,查看是否允许传递未知服务的请求。

  1. $ kubectl get configmap istio -n istio-system -o yaml | grep -o "mode: ALLOW_ANY"
  2. mode: ALLOW_ANY
  3. mode: ALLOW_ANY
  4. # 或者
  5. $ kubectl get configmap istio -n istio-system -o yaml | grep -o "mode: REGISTRY_ONLY"
  6. mode: REGISTRY_ONLY
  7. mode: REGISTRY_ONLY

如果命令输出有mode: ALLOW_ANY表示Istio代理允许调用未知的服务;如果命令输出有mode: REGISTRY_ONLY那么Istio代理会阻止任何没有在网格中定义的HTTP服务或service entry的主机

方法

如果是因为Istio的配置项为mode: REGISTRY_ONLY而导致内部无法访问外部服务。可有以下三种访问外部服务的方法:

  • 方法一:修改配置为mode: ALLOW_ANY以允许Sidecar将请求传递到未在网格内部配置过的服务。
  • 方法二:配置ServiceEntry以提供对外部服务的预期访问。
  • 方法三:对于特定范围的IP,完全绕过Envoy代理。

方法一

运行以下命令,修改配置为 mode: ALLOW_ANY

  1. $ kubectl get configmap istio -n istio-system -o yaml | sed 's/mode: REGISTRY_ONLY/mode: ALLOW_ANY/g' | kubectl replace -n istio-system -f -
  2. configmap/istio replaced

验证配置

  1. $ kubectl get configmap istio -n istio-system -o yaml | grep -o "mode: ALLOW_ANY"
  2. mode: ALLOW_ANY
  3. mode: ALLOW_ANY

重启部署

  1. $ kubectl rollout restart deployment sleep
  2. deployment.extensions/sleep restarted

访问外部服务

  1. $ export SOURCE_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
  2. $ kubectl exec -it $SOURCE_POD -c sleep -- curl http://www.baidu.com
  3. <!DOCTYPE html>
  4. ......
  5. ICP030173号&nbsp; <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>
  6. $ kubectl exec -it $SOURCE_POD -c sleep -- curl -I https://www.baidu.com | grep "HTTP/"
  7. HTTP/1.1 200 OK

注:这种访问外部服务的简单方法有一个缺点,即丢失了对外部服务流量的Istio监控和控制

方法二

在开始方法二之前,需要先修改Istio的配置项为mode: REGISTRY_ONLY

  1. $ kubectl get configmap istio -n istio-system -o yaml | sed 's/mode: ALLOW_ANY/mode: REGISTRY_ONLY/g' | kubectl replace -n istio-system -f -
  2. configmap "istio" replaced

允许访问外部HTTP服务

  1. 添加ServiceEntry,允许访问httpbin的HTTP服务
  1. kubectl apply -f - <<EOF
  2. apiVersion: networking.istio.io/v1alpha3
  3. kind: ServiceEntry
  4. metadata:
  5. name: httpbin-ext
  6. spec:
  7. hosts:
  8. - httpbin.org
  9. ports:
  10. - number: 80
  11. name: http
  12. protocol: HTTP
  13. resolution: DNS
  14. location: MESH_EXTERNAL
  15. EOF
  1. 从sleep向外部发送httpbin的HTTP服务请求
  1. $ kubectl exec -it $SOURCE_POD -c sleep -- curl http://httpbin.org/headers
  2. {
  3. "headers": {
  4. "Accept": "*/*",
  5. "Content-Length": "0",
  6. "Host": "httpbin.org",
  7. "User-Agent": "curl/7.64.0",
  8. "X-Amzn-Trace-Id": "Root=1-5e89e3ba-e22faf007e305d9897cddf1e",
  9. "X-B3-Sampled": "1",
  10. "X-B3-Spanid": "338f3faa38eb194e",
  11. "X-B3-Traceid": "d0ff4841f30240b2338f3faa38eb194e",
  12. "X-Envoy-Decorator-Operation": "httpbin.org:80/*",
  13. "X-Envoy-Peer-Metadata": "ChwKDElOU1RBTkNFX0lQUxIMGgoxMC4xLjAuMjQ1CsMBCgZMQUJFTFMSuAEqtQEKDgoDYXBwEgcaBXNsZWVwCiAKEXBvZC10ZW1wbGF0ZS1oYXNoEgsaCWM2OWQ5NmM5YwokChlzZWN1cml0eS5pc3Rpby5pby90bHNNb2RlEgcaBWlzdGlvCioKH3NlcnZpY2UuaXN0aW8uaW8vY2Fub25pY2FsLW5hbWUSBxoFc2xlZXAKLwojc2VydmljZS5pc3Rpby5pby9jYW5vbmljYWwtcmV2aXNpb24SCBoGbGF0ZXN0ChoKB01FU0hfSUQSDxoNY2x1c3Rlci5sb2NhbAofCgROQU1FEhcaFXNsZWVwLWM2OWQ5NmM5Yy0yZnh6ZAoWCglOQU1FU1BBQ0USCRoHZGVmYXVsdApJCgVPV05FUhJAGj5rdWJlcm5ldGVzOi8vYXBpcy9hcHBzL3YxL25hbWVzcGFjZXMvZGVmYXVsdC9kZXBsb3ltZW50cy9zbGVlcAoaCg9TRVJWSUNFX0FDQ09VTlQSBxoFc2xlZXAKGAoNV09SS0xPQURfTkFNRRIHGgVzbGVlcA==",
  14. "X-Envoy-Peer-Metadata-Id": "sidecar~10.1.0.245~sleep-c69d96c9c-2fxzd.default~default.svc.cluster.local"
  15. }
  16. }

注:返回数据中可以看到Istio sidecar代理添加的标题:X-Envoy-Decorator-Operation,表示访问外部的流量经过了sidecar

  1. 检查睡眠的边车
  1. 1
  2. 2
  3. $ kubectl logs $SOURCE_POD -c istio-proxy | tail
  4. [2020-04-05T13:57:13.948Z] "GET /headers HTTP/1.1" 200 - "-" "-" 0 1117 629 628 "-" "curl/7.64.0" "d94cc283-11ef-949c-8ba0-d948ad5785ab" "httpbin.org" "52.202.2.199:80" outbound|80||httpbin.org 10.1.0.245:48116 34.230.193.231:80 10.1.0.245:56246 - default

允许访问外部HTTPS服务

  1. 添加ServiceEntry,允许访问httpbin的HTTPS服务
  1. kubectl apply -f - <<EOF
  2. apiVersion: networking.istio.io/v1alpha3
  3. kind: ServiceEntry
  4. metadata:
  5. name: httpbin-https-ext
  6. spec:
  7. hosts:
  8. - httpbin.org
  9. ports:
  10. - number: 443
  11. name: https
  12. protocol: HTTPS
  13. resolution: DNS
  14. location: MESH_EXTERNAL
  15. EOF
  1. 从sleep向外部发送httpbin的HTTPS服务请求
  1. $ kubectl exec -it $SOURCE_POD -c sleep -- curl -I https://httpbin.org/headers
  2. HTTP/2 200
  3. date: Sun, 05 Apr 2020 14:10:25 GMT
  4. content-type: application/json
  5. content-length: 173
  6. server: gunicorn/19.9.0
  7. access-control-allow-origin: *
  8. access-control-allow-credentials: true
  1. 检查睡眠的边车
  1. $ kubectl logs $SOURCE_POD -c istio-proxy | tail
  2. [2020-04-05T14:10:23.939Z] "- - -" 0 - "-" "-" 941 5597 1695 - "-" "-" "-" "-" "3.232.168.170:443" outbound|443||httpbin.org 10.1.0.245:36844 3.232.168.170:443 10.1.0.245:36838 httpbin.org -

管理到外部服务的流量

通过ServiceEntry配置访问的外部服务,可以向内部的请求相同的设置Istio路由规则。下面以httpbin作为替代,设置对服务访问的超时规则。

  1. 向外部服务httpbin.org的/ delay端点发出curl请求:
  1. $ kubectl exec -it $SOURCE_POD -c sleep sh
  2. / # time curl -o /dev/null -s -w "%{http_code}\n" http://httpbin.org/delay/5
  3. 200
  4. real 0m 6.12s
  5. user 0m 0.00s
  6. sys 0m 0.00s
  7. / #
  1. 这个请求大约在5秒内返回200(OK)。

  2. 使用kubectl设置调用外部服务httpbin.org的超时时间为3秒。

  1. $ kubectl apply -f - <<EOF
  2. apiVersion: networking.istio.io/v1alpha3
  3. kind: VirtualService
  4. metadata:
  5. name: httpbin-ext
  6. spec:
  7. hosts:
  8. - httpbin.org
  9. http:
  10. - timeout: 3s
  11. route:
  12. - destination:
  13. host: httpbin.org
  14. weight: 100
  15. EOF
  1. 几秒后,重新发出curl请求:
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. $ kubectl exec -it $SOURCE_POD -c sleep sh
  8. / # time curl -o /dev/null -s -w "%{http_code}\n" http://httpbin.org/delay/5
  9. 504
  10. real 0m 3.28s
  11. user 0m 0.00s
  12. sys 0m 0.00s

这一次,在3秒后出现了504(Gateway Timeout)。Istio在3秒后切断了响应时间为5秒的httpbin.org服务。

方法三

在开始方法三之前,需要先清理对外部服务的预先访问

  1. $ kubectl delete serviceentry baidu-ext httpbin-ext httpbin-https-ext
  2. serviceentry.networking.istio.io "baidu-ext" deleted
  3. serviceentry.networking.istio.io "httpbin-ext" deleted
  4. serviceentry.networking.istio.io "httpbin-https-ext" deleted
  5. $ kubectl delete virtualservice httpbin-ext --ignore-not-found=true
  6. virtualservice.networking.istio.io "httpbin-ext" deleted

直接访问外部服务

如果要让特定范围的IP完全绕过Istio,则可以配置Envoy sidecars以防止其拦截外部请求。要设置绕过Istio,请更改global.proxy.includeIPRangesglobal.proxy.excludeIPRanges配置选项,并使用kubectl apply命令更新istio-sidecar-injector的配置。istio-sidecar-injector配置的更新,影响的是新部署应用的pod

注:与方法一使用mode: ALLOW_ANY流量策略来让Istio sidecar代理将调用传递给未知服务不同。更改global.proxy.includeIPRangesglobal.proxy.excludeIPRanges配置选项的方法,完全绕过了sidecar,从而替换了指定IP的所有Istio功能。您不能mode: ALLOW_ANY方法为那样的特定目标增量添加服务项。因此,仅当出于性能或其他原因无法使用三轮配置外部访问时,才建议使用此配置方法

排除所有外部IP重置到Sidecar代理的一种简单方法是将global.proxy.includeIPRanges配置选项设置为内部可用服务使用的IP范围。这些IP范围值可以取代所在的平台

确定平台内部的IP范围
阿里云(AKS)

注:这里先提下阿里云,因为其设置与其他平台不同

  1. 查看更多信息,获取Pod网络CIDR和Service CIDR,如172.20.0.0/16和172.21.0.0/20

  2. 点击Istio管理,单击更新,找到includeIPRanges并设置为Pod网络CIDR和Service CIDR

IBM Cloud Private
  1. 从IBM Cloud Private的配置文件cluster / config.yaml中获取您的service_cluster_ip_range:
  1. $ cat cluster/config.yaml | grep service_cluster_ip_range
  2. service_cluster_ip_range: 10.0.0.1/24 //这里以 10.0.0.1/24 为例
  1. 使用 --set global.proxy.includeIPRanges="10.0.0.1/24"
IBM Cloud Kubernetes服务

使用 --set global.proxy.includeIPRanges="172.30.0.0/16\,172.21.0.0/16\,10.10.10.0/24"

Google容器引擎(GKE)

范围是不固定的,你需要运行gcloud容器集群描述了命令来确定要使用的范围。举个例子:

  1. $ gcloud container clusters describe XXXXXXX --zone=XXXXXX | grep -e clusterIpv4Cidr -e servicesIpv4Cidr
  2. clusterIpv4Cidr: 10.4.0.0/14
  3. servicesIpv4Cidr: 10.7.240.0/20

使用 --set global.proxy.includeIPRanges="10.4.0.0/14\,10.7.240.0/20"

Azure容器服务(ACS)

使用 --set global.proxy.includeIPRanges="10.244.0.0/16\,10.240.0.0/16

Minikube,用于桌面的Docker,裸机

默认值10.96.0.0/12,但不是固定的。使用以下命令确定您的实际值:

  1. $ kubectl describe pod kube-apiserver -n kube-system | grep 'service-cluster-ip-range'
  2. --service-cluster-ip-range=10.96.0.0/12

使用–set global.proxy.includeIPRanges =“ 10.96.0.0/12”

配置代理绕行

使用平台的IP范围更新istio-sidecar-injector的配置。例如,如果IP范围是10.0.0.1/24,则使用一下命令:

  1. istioctl manifest apply <the flags you used to install Istio> --set values.global.proxy.includeIPRanges="10.0.0.1/24"

安装Istio命令的基础上增加--set values.global.proxy.includeIPRanges="10.0.0.1/24"

注:若你是按照本专栏开发环境搭建教程构建环境的话,则使用istioctl manifest apply --set profile=demo --set values.global.proxy.includeIPRanges="10.96.0.0/12"命令配置代理绕行即可。

访问外部服务

由于绕行配置仅影响新的部署,因此需要重新部署sleep程序。

  1. $ kubectl delete deployment sleep
  2. deployment.extensions "sleep" deleted
  3. $ kubectl apply -f samples/sleep/sleep.yaml
  4. serviceaccount/sleep unchanged
  5. service/sleep unchanged
  6. deployment.apps/sleep created

在更新istio-sidecar-injector configmap和重新部署sleep程序后,Istio sidecar将仅拦截并管理其内部的内部请求。任何外部请求都会绕过Sidecar,并直接到达其预期的目的地。举个例子:

  1. $ export SOURCE_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
  2. $ kubectl exec -it $SOURCE_POD -c sleep curl http://httpbin.org/headers
  3. {
  4. "headers": {
  5. "Accept": "*/*",
  6. "Host": "httpbin.org",
  7. "User-Agent": "curl/7.64.0",
  8. "X-Amzn-Trace-Id": "Root=1-5e89f4e2-524fd7a41c99025a43c403ce"
  9. }
  10. }

与通过HTTP和HTTPS访问外部服务不同,你不会看到任何与Istio sidecar有关的请求头,并且发送到外部服务的请求不会出现在Sidecar的日志中。对外部服务的访问。

总结

本文先介绍了允许内部无法访问外部服务的现象,然后扩展了该现象的原因,最后提供了三个方法供大家替换。

方法一通过修改Istio sidecar代理配置为mode: ALLOW_ANY以允许访问外部服务。使用这种方法时,您将无法监控对外部服务的访问无法利用Istio的流量控制功能

方法二通过添加ServiceEntry,以允许访问外部服务。可以让你使用Istio服务网格所有的功能去调用内部或转换外部的服务,这是官方推荐的方法

三方法直接绕过了Istio边门代理,使你的服务可以直接访问任意的外部服务。但是,这种以配置方式代理需要了解集群提供商相关知识状语从句:配置。与方法一类似,也。你将失去对外部服务访问的监控,并且无法将Istio功能添加到外部服务

方法二的做法对准“白名单”,不但能达到访问外部服务的目的,并且可以像内置内部服务一样对待(可使用Istio的流量控制功能)。另外,甚至服务遭到入侵,由于“白名单”的设置入侵者也无法(或较难)将流量回传到入侵机器,进一步保证了服务的安全性。因此,强烈推荐大家使用方法二

最后,特别提醒一下大家。某些教程,如Istio服务无法访问外网,开放外网权限includeOutboundIPRanges设置为空是有问题的,这相当于将所有的服务都配置代理绕行,那sidecar就没起作用了,没了sidecar的Istio就没有灵魂了。。

参考

istio: 无法提供内部访问外部服务的更多相关文章

  1. kubernetes 集群内部访问外部的数据库endpoint

    k8s访问集群外独立的服务最好的方式是采用Endpoint方式,以mysql服务为例: 创建mysql-service.yaml apiVersion: v1 kind: Service metada ...

  2. openstack集群访问外部服务出现访问失败

    场景描述: openstack私有云中的容器服务A(部署在openshift上)需要通过http访问阿里云中的B服务,中间需要经过openstack的nat网关,以及阿里云的lb.但在访问时发现访问失 ...

  3. kubernetes集群内通过endpoint访问外部服务

    kubernetes内的服务访问集群外独立的服务最好通过endpoint方式,例如MySQL 1.创建mysql-service.yaml apiVersion: v1 kind: Service m ...

  4. Istio ServiceEntry 引入外部服务

    概念及示例 使用服务入口Service Entry来添加一个入口到 Istio 内部维护的服务注册中心.添加了服务入口后,Envoy 代理可以向服务发送流量,就好像它是网格内部的服务一样.配置服务入口 ...

  5. [置顶] kubernetes将外部服务映射为内部服务

    在实际应用中,一般不会把mysql这种重IO.有状态的应用直接放入k8s中,而是使用专用的服务器来独立部署.而像web这种无状态应用依然会运行在k8s当中,这时web服务器要连接k8s管理之外的数据库 ...

  6. springmvc:BeanNameViewResolver访问内部资源视图对象和访问外部资源视图对象

    <!-- 处理器映射器 --> <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerM ...

  7. bladex下载前端代码后,运行服务时报错【'vue-cli-service' 不是内部或外部命令,也不是可运行的程序或批处理文件。】的解决方法

    问题:E:\BladeXDB\Saber>yarn run serveyarn run v1.13.0$ vue-cli-service serve'vue-cli-service' 不是内部或 ...

  8. Istio Service Mash管理微服务

    Istio Service Mash管理微服务 今天的文章通过Istio开源项目展示如何为Kubernetes管理的微服务提供可见性,弹性,安全性和控制. 服务是现代软件体系结构的核心.比起复杂庞大的 ...

  9. Spring提供的用于访问Rest服务的客户端:RestTemplate实践

    什么是RestTemplate? RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效 ...

随机推荐

  1. CSS3 & Flex Layout All In One

    CSS3 & Flex Layout All In One demos https://www.cnblogs.com/xgqfrms/p/10769302.html .flex-contai ...

  2. http cache & 浏览器缓存,存储位置的优先级,条件?

    http cache & 浏览器缓存,存储位置的优先级,条件? memory cache disk cache 浏览器缓存,存储位置的优先级,条件, 机制,原理是什么? from memory ...

  3. Google IO & 2019

    Google IO & 2019 Google IO Recap \ https://www.techradar.com/news/google-io-2019-keynote https:/ ...

  4. COOP & COEP

    COOP & COEP Cross-Origin Opener Policy (COOP) and Cross-Origin Embedder Policy (COEP) https://de ...

  5. NGK乘势而上打造生态所,建立全方位的区块链生态系统

    当金融理财变成了生活的一部分,购买金融衍生品的眼光成为了影响生活质量重要组成部分.这是一个不缺少黄金的年代,一夜间实现财务自由的故事每天都在上演,但是由于太多人缺少发现黄金的眼睛,只能被财富和机遇拒之 ...

  6. redis5.* 手动构建集群

    1.集群的概念 集群是一组相互独立的.通过高速网络互联的计算机,它们构成了一个组,并以单一系统的模式加以管理.一个客户与集群相互作用时,集群像是一个独立的服务器.集群配置是用于提高可用性和可缩放性.当 ...

  7. ElasticSearch 聚合分析

    公号:码农充电站pro 主页:https://codeshellme.github.io ES 中的聚合分析(Aggregations)是对数据的统计分析功能,它的优点是实时性较高,相比于 Hadoo ...

  8. 【死磕JVM】JVM快速入门之前戏篇

    简介 Java是一门可以跨平台的语言,但是Java本身是不可以实现跨平台的,需要JVM实现跨平台.javac编译好后的class文件,在Windows.Linux.Mac等系统上,只要该系统安装对应的 ...

  9. Jquery获取链接请求的参数

    比如有一个链接:https://www.baidu.com/s?cl=3&tn=baidutop10&fr=top1000,先定义方法: //获取url中的参数 function ge ...

  10. 破解MySQL库user表hash密码

    目录 得到用户名和密码 hash 带*和不带*的区别 破解hash 在线工具 Hashcat 实验环境 select version(); 得到用户名和密码 hash mysql安装好就会默认生成图中 ...