Control Ingress Traffic(0.8)

在一个k8s环境中, Kubernetes Ingress Resource 被用于指定一个应被暴露在集群外的服务。在一个Istio服务网格中,一个更好的方法(在k8s和其他环境都可以工作)是使用一种不同的配置模型,称作 Istio Gateway. Gateway 允许Istio功能(例如监控和路由规则)应用于进入集群的流量。

这个task描述如何使用Istio Gateway 配置Istio在服务网格外暴露一个服务。

Before you begin

  • 安装Isito
  • 确认你的当前目录是istio 目录
  • 开启 httpbin 示例,它将被用作暴露在外部的目标服务。

如果你开启了自动注入sidecar,执行

kubectl apply -f samples/httpbin/httpbin.yaml

samples/httpbin/httpbin.yaml

否则,你需要在部署httpbin 应用前手动注入sidecar:

kubectl apply -f <(istioctl kube-inject -f samples/httpbin/httpbin.yaml)

samples/httpbin/httpbin.yaml

  • 为了测试,使用 OpenSSL 新建一个密钥和证书。
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /tmp/tls.key -out /tmp/tls.crt -subj "/CN=httpbin.example.com"
  • 确定ingress的IP和端口,看下节。
Determining the ingress IP and ports

执行如下命令来判断你的k8s集群运行环境是否支持外部负载均衡。

kubectl get svc istio-ingressgateway -n istio-system
NAME                   TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)                                      AGE
istio-ingressgateway   LoadBalancer   172.21.109.129   130.211.10.121  80:31380/TCP,443:31390/TCP,31400:31400/TCP   17h

如果EXTERNAL-IP 的值设置了,你的环境有一个外部负载均衡可用于ingress网关。如果EXTERNAL-IP 的值为 <none> (或一直为<pending>),你的环境没有为ingress网关提供一个外部负载均衡。这种情况下,你可以通过使用服务的 node port 进入网关。

Determining the ingress IP and ports for a load balancer ingress gateway
export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http")].port}')
export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].port}')
Determining the ingress IP and ports for a NodePort ingress gateway

确认端口:

export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http")].nodePort}')
export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')

确认ingress IP取决于集群供应商。
here.

Configuring ingress using an Istio Gateway

一个ingress 网关描述负载均衡,它位于接受进入的HTTP/TCP连接的网格边缘。它配置暴露端口,协议等,但不像 Kubernetes Ingress Resources, 它不包含任何流量路由配置。入口流量的流量路由使用Istio路由规则进行配置,与内部服务请求完全相同。

下面小节中,我们首先在端口80上配置一个网关,用于未加密的HTTP流量。然后我们为HTTPS流量添加一个安全端口443.

Configuring a gateway for HTTP

1.创建一个Istio Gateway

cat <<EOF | istioctl create -f -
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: httpbin-gateway
spec:
  selector:
    istio: ingressgateway # use Istio default gateway implementation
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "httpbin.example.com"
EOF

2.为通过 Gateway 输入的流量配置路由

cat <<EOF | istioctl create -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin
spec:
  hosts:
  - "httpbin.example.com"
  gateways:
  - httpbin-gateway
  http:
  - match:
    - uri:
        prefix: /status
    - uri:
        prefix: /delay
    route:
    - destination:
        port:
          number: 8000
        host: httpbin
EOF

在这里,我们为httpbin 服务创建了一个虚拟服务( virtual service )配置,其中包括两条允许路径 /status/delay的流量的路由规则。
gateways 列表指定只允许通过我们的 httpbin-gateway 的请求。所有其他外部请求将会被404响应拒绝。
注意,在此配置中,来自网格中其他服务的内部请求不受这些规则约束,而是简单地默认为循环路由。要将这些(或其他规则)应用于内部调用,我们可以将特殊值mesh 添加到gateways 列表中。

Verifying the gateway for HTTP

1.使用curl访问httpbin服务。注意curl--resolve 标志,允许任意域名访问IP地址。在我们的例子中,我们通过 “httpbin.example.com”来访问我们的入口网关,我们将其指定为我们的 Gateway 处理的host 。同时注意--HHost:httpbin.example.com 标志设置Host 的 HTTP Header 为“httpbin.example.com”。

curl --resolve httpbin.example.com:$INGRESS_PORT:$INGRESS_HOST -HHost:httpbin.example.com -I http://httpbin.example.com:$INGRESS_PORT/status/200
HTTP/1.1 200 OK
server: envoy
date: Mon, 29 Jan 2018 04:45:49 GMT
content-type: text/html; charset=utf-8
access-control-allow-origin: *
access-control-allow-credentials: true
content-length: 0
x-envoy-upstream-service-time: 48

2.访问其他没有明确暴露的URL。你会看到HTTP 404错误:

curl --resolve httpbin.example.com:$INGRESS_PORT:$INGRESS_HOST -HHost:httpbin.example.com -I http://httpbin.example.com:$INGRESS_PORT/headers
HTTP/1.1 404 Not Found
date: Mon, 29 Jan 2018 04:45:49 GMT
server: envoy
content-length: 0

Add a secure port (HTTPS) to our gateway

在这节中,我们为网关田间443端口以处理HTTPS流量。我们创建了一个带证书和私钥的密钥。之后,我们将之前的网关定义替换为在servers标签包含443端口的定义,以及之前定义的在servers标签包含端口80。

1.创建一个k8s Secret 保存密钥/证书
使用kubectl 在命名空间 istio-system 创建secret istio-ingressgateway-certs 。这个Istio网关将自动加载secret。

这个secret必须在命名空间istio-system 中被命名为 istio-ingressgateway-certs,否则它将不能被Istio gateway安装及使用。

kubectl create -n istio-system secret tls istio-ingressgateway-certs --key /tmp/tls.key --cert /tmp/tls.crt

注意,默认所有在命名空间 istio-system 的服务都可以访问这个ingress 密钥/证书,这可能会泄漏密钥/证书。你可以改变RBAC规则来保护它们。

2.在之前定义的Gateway 的server 小节中添加端口443.

本地的证书和私钥必须在/etc/istio/ingressgateway-certs, 否则网关无法加载

cat <<EOF | istioctl replace -f -
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: httpbin-gateway
spec:
  selector:
    istio: ingressgateway # use istio default ingress gateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "httpbin.example.com"
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
      mode: SIMPLE
      serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
      privateKey: /etc/istio/ingressgateway-certs/tls.key
    hosts:
    - "httpbin.example.com"
EOF
Verifying the gateway for HTTPS

1.确认我们的网关在80端口依然工作,并且像之前一样接受未加密HTTP流量。我们可以通过访问httpbin服务80端口来实现,就像Verifying the gateway for HTTP 那节那样。

2.通过HTTPS访问httpbin服务,通过curl发送一个HTTPS请求到 SECURE_INGRESS_PORT. 这里我们使用了curl的-k 选项通知curl不检查我们的证书(因为这仅仅是我们为了测试网关新建的假证书,curl不能察觉到它)。

curl --resolve httpbin.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST -HHost:httpbin.example.com -I -k https://httpbin.example.com:$SECURE_INGRESS_PORT/status/200
HTTP/2 200
server: envoy
date: Mon, 14 May 2018 13:54:53 GMT
content-type: text/html; charset=utf-8
access-control-allow-origin: *
access-control-allow-credentials: true
content-length: 0
x-envoy-upstream-service-time: 6

注意,新的网关定义可能需要时间传播,并且你可能受到如下错误:Failed to connect to httpbin.example.com port <your secure port>: Connection refused. 等几分钟,再次尝试curl 调用。

Disable the HTTP port

如果我们只想在服务网格中使用HTTPS流量,我们可以从我们的网关中移除HTTP端口。

1.重新定义不带HTTP端口的Gateway

cat <<EOF | istioctl replace -f -
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: httpbin-gateway
spec:
  selector:
    istio: ingressgateway # use istio default ingress gateway
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
      mode: SIMPLE
      serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
      privateKey: /etc/istio/ingressgateway-certs/tls.key
    hosts:
    - "httpbin.example.com"
EOF

2.访问HTTP端口,确定它不可用(会返回错误):

curl --resolve httpbin.example.com:$INGRESS_PORT:$INGRESS_HOST -HHost:httpbin.example.com -I http://httpbin.example.com:$INGRESS_PORT/status/200

Accessing Istio service mesh by a browser

目前,只有负载均衡ingress网关才支持通过浏览器访问网格,并且仅支持标准端口(80和443).指定网关的URL时,你必须省略端口。

对于NodePort ingress 网关,部分支持浏览器访问:仅用于VirtualService 中定义的* hosts。

Understanding what happened

Gateway 配置资源允许外部流量进入Istio服务网格,并使Istio的流量管理和策略功能可用于边缘服务。

在之前的步骤中,我们创建了一个Istio服务网格内部的服务,并展示如何将服务的HTTP和HTTPS端点公开给外部流量。

Cleanup

删除Gateway 的配置,VirtualService 以及secret,然后关闭httpbin服务:

istioctl delete gateway httpbin-gateway
istioctl delete virtualservice httpbin
kubectl delete --ignore-not-found=true -n istio-system secret istio-ingressgateway-certs
kubectl delete --ignore-not-found=true -f samples/httpbin/httpbin.yaml

samples/httpbin/httpbin.yaml

猜你喜欢

转载自blog.csdn.net/ybt_c_index/article/details/80737501