istio: 无法提供内部访问外部服务
现象
能够内部无法访问外部服务。
- 在部署测试服务
kubectl apply -f samples/sleep/sleep.yaml
- 设置环境变量
export SOURCE_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
- 访问外网服务
$ kubectl exec -it $SOURCE_POD -c sleep -- curl http://www.baidu.com
$ kubectl exec -it $SOURCE_POD -c sleep -- curl -I https://www.baidu.com | grep "HTTP/"
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的代理配置,查看是否允许传递未知服务的请求。
$ kubectl get configmap istio -n istio-system -o yaml | grep -o "mode: ALLOW_ANY"
mode: ALLOW_ANY
mode: ALLOW_ANY
# 或者
$ kubectl get configmap istio -n istio-system -o yaml | grep -o "mode: REGISTRY_ONLY"
mode: REGISTRY_ONLY
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
$ kubectl get configmap istio -n istio-system -o yaml | sed 's/mode: REGISTRY_ONLY/mode: ALLOW_ANY/g' | kubectl replace -n istio-system -f -
configmap/istio replaced
验证配置
$ kubectl get configmap istio -n istio-system -o yaml | grep -o "mode: ALLOW_ANY"
mode: ALLOW_ANY
mode: ALLOW_ANY
重启部署
$ kubectl rollout restart deployment sleep
deployment.extensions/sleep restarted
访问外部服务
$ export SOURCE_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
$ kubectl exec -it $SOURCE_POD -c sleep -- curl http://www.baidu.com
......
京ICP证030173号