Istio 尾行记
Istio 一直没有什么像样的更新,Conduit 也迟迟不出来怼,眼看 2017 就要过去,安装试用也不新鲜了,补一篇 Istio 的笔记,算做个收尾了。
Istio 最大的亮点之一,就是使用 Pilot 将集群控制语言翻译成为 Envoy 配置,利用 Sidecar 的方式对服务通信进行控制,下面就是对这一过程的跟踪尝试。
kubectl apply -f install/kubernetes/istio.yaml
cat istio.yaml| grep ^kind
会看到,这里生成了相当多的内容,除去 Deployment、Service 和 ConfigMap 老几样之外,还有当前集群必须的 RBAC 几要素:Service Account、ClusterRole 以及 ClusterRoleBinding。然后就是 Kubernetes 世界里强力扩展的标志:各种 CRD(CustomResourceDefinition) 了。
kubectl apply -f install/kubernetes/addons/
这里会生成一系列的监控用具,包括了 Prometheus、Grafana、ZipKin 以及 ServiceGraph,原则上这些并非必须组件。不过为了监控方便,一般还是会加上。
另外这里的 Prometheus 以及 Grafana 的监控、仪表盘配置都可以保存下来,方便同现有设施进行融合。
istioctl kube-inject -f ...
运行这个命令之前,务必注意几个对 Workload 的要求:
- 目前,Pod 对应单一服务的情况才能得到支持。
- 服务端口必须命名,[协议]-[后缀] 的方式,后缀部分可以忽略,写一部分可以使用 http, http2, grpc, mongo 以及 redis。如果不进行合理的命名,又没有显示声明这一端口是 UDP 端口,那么就会被当做普通 TCP 端口处理。
- Deployment 需要有 App 标签,注意看示例应用的标签方法。
- 目前的缺省安装不支持
cluster.local
之外的 Kubernetes 域名。
在安装好 Istio 之后,一般会使用这一命令对服务进行注入(同样也有自动注入的能力),使之称为被 istio 加持的 Service Mesh 成员服务。注入之后的 YAML 会变得比较丰腴:
- 一组注解
- 两个 Init
- 一个同 Pod 容器
- 两个卷
下面分别讲解一下多出来的这些部分:
Annotation
为 Deployment 和 Pod 加入了同样的注解:
sidecar.istio.io/status: injected-version...
,目前理解是,标注了这一部署和 Pod 是否已经被注入,被什么版本注入。
Init 1
使用 Alpine 镜像,设置内核 Dump 模板,以及 ulimit。
Init 2
使用 docker.io/istio/proxy_init:0.4.0
进行初始化,参数为 -p 15001 -u 1337
Sidecar
镜像为: docker.io/istio/proxy_debug:0.4.0
其中定义了大量的服务关系,包括:
- Istio Pilot
- Zipkin
- Mixer
- 管理端口
卷
- 内存卷用于存储配置;
- Secret 卷用于后面的 TLS。
运行
利用 kubectlapply -f
,将注入后的 yaml 文件运行起来,接下来就可以使用各个 Pod 来查看刚才注入的内容的行迹了。
列出 Pod:
NAME READY STATUS RESTARTS AGE
httpbin-7965799df7-ll75q 2/2 Running 0 53m
通过前面的 yaml 定义,我们知道这个 Pod 的两个容器分别是 httpbin
和 istio-proxy
,Istio 强调的是 Sidecar 模式的无侵入管理,因此我们可以认为 httpbin
是没有变化的,Service Mesh 的 Sidecar 功能会体现在 istio-proxy
这一容器中。
初始化
上一节中提到了,使用 proxy_init
进行的初始化(Alpine 部分修改内核参数,就不用多说了),我们可以进入源码,查查他的初始化做了什么。
Dockerfile 中我们看到,这一容器的入口命令为 istio-start.sh
,找出这个文件,会看到其中使用这两个参数对 iptables 的 nat 部分做了配置,另外还可以看到,其中加入了 iptables 命令,这里我们可以进行验证:kubectl exec httpbin-7965799df7-ll75q -c istio-proxy sudo iptables-save
,输出内容可以这样解读:
- 跳过和 Proxy 进程用户一致的用户进程的流量处理;
- 跳过 Loopback 流量处理;
- 所有流量转发到 15001 端口。
和脚本初始化内容一致。
istio-proxy
启动之后,我们可以使用 kubectl exec -it [httpbin] -c istio-proxy sh
进入 Proxy 容器,执行命令 ps -ef
,会发现有两个正在运行的进程:
- /usr/local/bin/pilot-agent
- /usr/local/bin/envoy
并且 Envoy 的父进程就是这个 pilot-agent。其运行参数和我们前面注入到 YAML 中的参数一致。
另外还可以查看 /etc/istio/proxy/
下面的配置文件,可以看出:
- Envoy 通过 pilot-agent 传递的参数运行
- 服务发现是通过 Pilot 完成的
- Envoy 开放了 15000 端口进行管理
验证路由规则
执行 kubectl exec [Pod] -c istio-proxy curl localhost:15000/routes
可以看到 httpbin 的路由如下:
{
"version_info": "hash_35afd004f717e588",
"route_config_name": "8000",
"cluster_name": "rds",
"route_table_dump": {"name":"8000","virtual_hosts":[{"name":"httpbin.default.svc.cluster.local|http","domains":["httpbi
n:8000","httpbin","httpbin.default:8000","httpbin.default","httpbin.default.svc:8000","httpbin.default.svc","httpbin.defaul
t.svc.cluster:8000","httpbin.default.svc.cluster","httpbin.default.svc.cluster.local:8000","httpbin.default.svc.cluster.loc
al","10.0.34.255:8000","10.0.34.255"],"routes":[{"match":{"prefix":"/"},"route":{"cluster":"out.httpbin.default.svc.cluster
.local|http","timeout":"0s"},"decorator":{"operation":"default-route"}}]}]}
}
新建缺省路由:
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
name: rule-all-http
spec:
destination:
name: httpbin
precedence: 1
route:
- labels:
app: httpbin
weight: 100
再次查询路由,可以看到其中发生了变化:
{
"version_info": "hash_146c02ed176ff12b",
"route_config_name": "8000",
"cluster_name": "rds",
"route_table_dump": {"name":"8000","virtual_hosts":[{"name":"httpbin.default.svc.cluster.local|http","domains":["httpbi
n:8000","httpbin","httpbin.default:8000","httpbin.default","httpbin.default.svc:8000","httpbin.default.svc","httpbin.defaul
t.svc.cluster:8000","httpbin.default.svc.cluster","httpbin.default.svc.cluster.local:8000","httpbin.default.svc.cluster.loc
al","10.0.34.255:8000","10.0.34.255"],"routes":[{"match":{"prefix":"/"},"route":{"cluster":"out.httpbin.default.svc.cluster
.local|http|app=httpbin","timeout":"0s"},"decorator":{"operation":"rule-all-http"}}]}]}
}
cluster
kubectl exec [pod] -c istio-proxy curl localhost:15000/routes
可以看到所有对应的服务信息,以及可能存在的断路器信息。