前言
在上一篇文章介绍的kubernetes环境的示例中,istio以边车模式部署在pod中,它接管了业务容器所有出入站流量,从而灵活控制网络。本文关键讨论如何接管。
kubernetes Init Containers
在开始之前,先介绍kubernetes的 Init Containers。比如如下示例
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox
command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
- name: init-mydb
image: busybox
command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
initContainers有几个特点:
- 从开始到结束,只运行一次
- 每一个initContainer都必须成功执行后才会执行下一个
- 在容器启动之前执行
- 如果执行失败,pod会重启(restartPolicy为Never除外)
因为pod共享命名空间、网络和volumes,可以通过它在普通容器启动前初始化网络环境。
istio-proxy
一个普通nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.0-alpine
ports:
- containerPort: 80
使用istioctl部署如下
kubectl apply -f <(istioctl kube-inject -f nginx-deployment.yaml)
我们关注istioctl kube-inject -f nginx-deployment.yaml
生成的内容。
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: nginx
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx
strategy: {}
template:
metadata:
annotations:
sidecar.istio.io/status: '{"version":"c560152609b91ff8d7c47257873095fffb2bddad37acf20013cc9362e6b389de","initContainers":["istio-init"],"containers":["istio-proxy"],"volumes":["istio-envoy","istio-certs"],"imagePullSecrets":null}'
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: nginx:1.14.0-alpine
name: nginx
ports:
- containerPort: 80
resources: {}
- args:
- proxy
- sidecar
- --configPath
- /etc/istio/proxy
- --binaryPath
- /usr/local/bin/envoy
- --serviceCluster
- nginx
- --drainDuration
- 45s
- --parentShutdownDuration
- 1m0s
- --discoveryAddress
- istio-pilot.istio-system:15007
- --discoveryRefreshDelay
- 1s
- --zipkinAddress
- zipkin.istio-system:9411
- --connectTimeout
- 10s
- --statsdUdpAddress
- istio-statsd-prom-bridge.istio-system:9125
- --proxyAdminPort
- "15000"
- --controlPlaneAuthPolicy
- NONE
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: INSTANCE_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: ISTIO_META_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: ISTIO_META_INTERCEPTION_MODE
value: REDIRECT
image: registry.cn-hangzhou.aliyuncs.com/my-istio-release/proxyv2:1.0.2
imagePullPolicy: IfNotPresent
name: istio-proxy
resources:
requests:
cpu: 10m
securityContext:
readOnlyRootFilesystem: true
runAsUser: 1337
volumeMounts:
- mountPath: /etc/istio/proxy
name: istio-envoy
- mountPath: /etc/certs/
name: istio-certs
readOnly: true
initContainers:
- args:
- -p
- "15001"
- -u
- "1337"
- -m
- REDIRECT
- -i
- '*'
- -x
- ""
- -b
- 80,
- -d
- ""
image: registry.cn-hangzhou.aliyuncs.com/my-istio-release/proxy_init:1.0.2
imagePullPolicy: IfNotPresent
name: istio-init
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
volumes:
- emptyDir:
medium: Memory
name: istio-envoy
- name: istio-certs
secret:
optional: true
secretName: istio.default
status: {}
- 在原理pod基础增加了容器istio-proxy
- 在原理pod基础增加了初始化容器istio-init
istio-init
正是上文提到的k8s initContainers。使用proxy_init镜像,通过docker inspect
命令可以查看此镜像的Entrypoint:
{
"Entrypoint": ["/usr/local/bin/istio-iptables.sh"]
}
这个初始化容器主要工作就是执行这样一个脚本istio-iptables.sh参数args是:
istio-iptables.sh -p "15001" -u "1337" -m REDIRECT -i '*' -x "" -b 80, -d ""
他的作用是把所有80端口的出入站流量重定向 UID为1337、端口为15001的istio_proxy(Envoy)。通过iptable完成了网络流量的拦截转发都到Envoy代理,这就是sidecar接管流量的关键。iptables的详细介绍见理解iptables
流量到envoy后,它的路由、服务发现等动态配置从哪里获取的?
从istioctl kube-inject -f
生成的内容还有这样一段:
proxy
sidecar
--configPath
/etc/istio/proxy
--binaryPath
/usr/local/bin/envoy
--serviceCluster
nginx
--drainDuration
45s
--parentShutdownDuration
1m0s
--discoveryAddress
istio-pilot.istio-system:15007
--discoveryRefreshDelay
1s
--zipkinAddress
zipkin.istio-system:9411
--connectTimeout
10s
--statsdUdpAddress
istio-statsd-prom-bridge.istio-system:9125
--proxyAdminPort
"15000"
--controlPlaneAuthPolicy
NONE
这是proxy的初始化参数,告诉envoy,discoveryAddress地址istio-pilot.istio-system:15007
--discoveryAddress istio-pilot.istio-system:15007
--discoveryRefreshDelay 1s
总结
- 通过k8s初始化容器执行iptables指令,把流量交给proxy
- proxy通过pilot获取配置
下文我们讨论,pilot 和 envoy是怎么结合的。