文档备案控制台
免费开始使用

Service Mesh 服务网格一:Sidecar模式

人的一生是短的,但如果卑劣地过这一生,就太长了。——莎士比亚

文前预览

1. 什么是sidecar模式

2. sidecar的注入和流量劫持

4. k8s实现sidecar自动注入

  1. 什么是sidecar模式

上篇文章我们已经了解了服务网格大致做什么,同时我们也提到了 sidecariptables ,那么这边文章着重聊下 sidecar模式iptables技术

picture.image

sidecar 模式通俗地讲就是将控制和逻辑分离,控制负责服务注册,服务发现以及服务限流等功能,逻辑主要是负责业务功能模块的实现,如上图那样,应用服务(车主)你只管开好你的车,打仗的事情就交给 sidecar (副手)就好。这与分布式微服务架构完美契合,真正的实现了控制和逻辑的分离与解耦。

  1. sidecar注入和流量劫持

k8s中每个pod在初始化应用服务之前,需要先初始化一个init容器,这个init容器负责运行包含一些应用服务镜像中不存在的实用工具或安装脚本。

2.1 sidecar注入

一个Pod中可以指定多个Init容器,如果指定了多个,那么Init容器将会按顺序依次运行。只有当前面的Init容器必须运行成功后,才可以运行下一个Init容器。当所有的Init容器运行完成后,Kubernetes 才初始化Pod和运行应用容器。

注入sidecar:命令行展示如下

  
istioctl kube-inject -f yaml/istio-bookinfo/bookinfo.yaml  
  
//bookinfo.yaml参考:https://github.com/rootsongjc/kubernetes-vagrant-centos-cluster/blob/master/yaml/istio-bookinfo/bookinfo.yaml

我们看下注入sidecar之后bookinfo的service和deploment yaml配置

service :

  
  
apiVersion: v1  
kind: Service  
metadata:  
 name: productpage  
 labels:  
 app: productpage  
spec:  
 ports:  
 - port: 9080  
 name: http  
 selector:  
 app: productpage

deploment

  
apiVersion: extensions/v1beta1  
kind: Deployment  
metadata:  
 creationTimestamp: null  
 name: productpage-v1  
spec:  
 replicas: 1  
 strategy: {}  
 template:  
 metadata:  
 annotations:  
 sidecar.istio.io/status: '{"version":"fde14299e2ae804b95be08e0f2d171d466f47983391c00519bbf01392d9ad6bb","initContainers":["istio-init"],"containers":["istio-proxy"],"volumes":["istio-envoy","istio-certs"],"imagePullSecrets":null}'  
 creationTimestamp: null  
 labels:  
 app: productpage  
 version: v1  
 spec:  
 containers:  
 - image: istio/examples-bookinfo-productpage-v1:1.8.0  
 imagePullPolicy: IfNotPresent  
 name: productpage  
 ports:  
 - containerPort: 9080  
 resources: {}  
 - args:  
 - proxy  
 - sidecar  
 - --configPath  
 - /etc/istio/proxy  
 - --binaryPath  
 - /usr/local/bin/envoy  
 - --serviceCluster  
 - productpage  
 - --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: jimmysong/istio-release-proxyv2:1.0.0  
 imagePullPolicy: IfNotPresent  
 name: istio-proxy  
 resources:  
 requests:  
 cpu: 10m  
 securityContext:  
 privileged: false  
 readOnlyRootFilesystem: true  
 runAsUser: 1337  
 volumeMounts:  
 - mountPath: /etc/istio/proxy  
 name: istio-envoy  
 - mountPath: /etc/certs/  
 name: istio-certs  
 readOnly: true  
 initContainers: //init容器的iptables参数  
 - args:  
 - -p  
 - "15001"  
 - -u  
 - "1337"  
 - -m  
 - REDIRECT  
 - -i  
 - '*'  
 - -x  
 - ""  
 - -b  
 - 9080,  
 - -d  
 - ""  
 image: jimmysong/istio-release-proxy_init:1.0.0  
 imagePullPolicy: IfNotPresent  
 name: istio-init  
 resources: {}  
 securityContext:  
 capabilities:  
 add:  
 - NET_ADMIN  
 privileged: true  
 volumes:  
 - emptyDir:  
 medium: Memory  
 name: istio-envoy  
 - name: istio-certs  
 secret:  
 optional: true  
 secretName: istio.default  
status: {}

我们着重看下deployment配置,Istio给应用Pod注入的配置主要包括:

  • Init容器istio-init:用于给sidecar容器做初始化,设置iptables端口转发
  • sidecar容器istio-proxy:运行Envoy代理(后面说这个玩意儿是啥 暂且忽略)

我们一起看下init容器的dockfile:

  
FROM ubuntu:xenial  
RUN apt-get update && apt-get install -y \  
 iproute2 \  
 iptables \  
 && rm -rf /var/lib/apt/lists/*  
ADD istio-iptables.sh /usr/local/bin/  
ENTRYPOINT ["/usr/local/bin/istio-iptables.sh"]

们看到istio-init容器的入口是/usr/local/bin/istio-iptables.sh 脚本。这个脚本会将deploment中的initContainer中的参数组装成iptables的参数进行调用,iptables可以根据NAT技术实现流量转发和控制。

组装完整的iptables命令如下:

  
$ /usr/local/bin/istio-iptables.sh -p 15001 -u 1337 -m REDIRECT -i '*' -x "" -b 9080 -d ""

这条启动命令的作用是:

  1. 将应用容器的所有流量都转发到Envoy的15001端口。
  2. 使用istio-proxy用户身份运行, UID为1337,即Envoy所处的用户空间,这也是istio-proxy容器默认使用的用户。
  3. 使用默认的REDIRECT模式来重定向流量。
  4. 将所有出站流量都重定向到Envoy代理。
  5. 将所有访问9080端口(即应用容器bookinfo的端口的流量重定向到Envoy代理。

因为init容器初始化完毕后就会自动终止,因为我们无法登陆到容器中查看iptables信息,但是init容器初始化结果会保留到应用容器和Sidecar容器中,我们可以登录Sidecar中查看iptables的nat规则列表。

该容器存在的意义就是让Envoy代理可以拦截所有的进出Pod的流量,即将入站流量重定向到Sidecar,再拦截应用容器的出站流量经过Sidecar处理后再出站。

2.2 iptables技术

流量劫持是通过iptables技术来实现的,它是Linux内核中的防火墙软件netfilter的管理工具,位于用户空间,同时也是netfilter的一部分。Netfilter位于内核空间,不仅有网络地址转换的功能,也具备数据包内容修改、以及数据包过滤等防火墙功能。

具体大家下来自行去查看研究,这不是本文重点。

  1. k8s实现sidecar自动注入

所谓自动sidecar注入就是将生成Pod配置从应用yml文件期间转移到mutable webhook中,这样当k8s api server启动的时候默认会走一些准入控制器,这样我们就会把sidecar自动注入到pod中,让其伴在应用服务容器旁边提供控制服务。

  1. 参考

  1. bookinfo.yaml https://github.com/rootsongjc/kubernetes-vagrant-centos-cluster/blob/master/yaml/istio-bookinfo/bookinfo.yaml
  2. init容器 https://jimmysong.io/kubernetes-handbook/concepts/init-containers.html
  3. iptables技术 https://www.zsythink.net/archives/1517
  4. mutable webhook https://jimmysong.io/kubernetes-handbook/concepts/admission-controller.html

5 关注公众号

微信公众号: 堆栈future

picture.image

扫我关注

0
0
0
0
评论
未登录
暂无评论