开篇

通过上一篇 Istio Sidecar注入原理 文章可以发现,在应用提交到kubernate部署时已经同时注入了Sidecar应用。

细心的话应该还可以发现,除了注入了istio-proxy应用外,另外还有注入一个istio-initInit Containers。接下来一起来看看在这两个注入的容器中分别都有做一些什么操作。

istio-init

istio-init init 容器用于设置 iptables 规则,以便将入站/出站流量通过 sidecar 代理。初始化容器与应用程序容器在以下方面有所不同:

  • 它在启动应用容器之前运行,并一直运行直至完成。
  • 如果有多个初始化容器,则每个容器都应在启动下一个容器之前成功完成

我们可以看下sleep对应的pod

  1. kubectl describe pod sleep-54f94cbff5-jmwtf
  2. Name: sleep-54f94cbff5-jmwtf
  3. Namespace: default
  4. Priority: 0
  5. Node: minikube/172.17.0.3
  6. Start Time: Wed, 27 May 2020 12:14:08 +0800
  7. Labels: app=sleep
  8. istio.io/rev=
  9. pod-template-hash=54f94cbff5
  10. security.istio.io/tlsMode=istio
  11. Annotations: sidecar.istio.io/interceptionMode: REDIRECT
  12. sidecar.istio.io/status:
  13. {"version":"d36ff46d2def0caba37f639f09514b17c4e80078f749a46aae84439790d2b560","initContainers":["istio-init"],"containers":["istio-proxy"]...
  14. traffic.sidecar.istio.io/excludeInboundPorts: 15020
  15. traffic.sidecar.istio.io/includeOutboundIPRanges: *
  16. Status: Running
  17. IP: 172.18.0.11
  18. IPs:
  19. IP: 172.18.0.11
  20. Controlled By: ReplicaSet/sleep-54f94cbff5
  21. Init Containers:
  22. istio-init:
  23. Container ID: docker://f5c88555b666c18e5aa343b3f452355f96d66dc4268fa306f93432e0f98c3950
  24. Image: docker.io/istio/proxyv2:1.6.0
  25. Image ID: docker-pullable://istio/proxyv2@sha256:821cc14ad9a29a2cafb9e351d42096455c868f3e628376f1d0e1763c3ce72ca6
  26. Port: <none>
  27. Host Port: <none>
  28. Args:
  29. istio-iptables
  30. -p
  31. 15001
  32. -z
  33. 15006
  34. -u
  35. 1337
  36. -m
  37. REDIRECT
  38. -i
  39. *
  40. -x
  41. -b
  42. *
  43. -d
  44. 15090,15021,15020
  45. State: Terminated
  46. Reason: Completed
  47. Exit Code: 0
  48. Started: Wed, 27 May 2020 12:14:12 +0800
  49. Finished: Wed, 27 May 2020 12:14:13 +0800
  50. Ready: True
  51. Restart Count: 0
  52. Limits:
  53. cpu: 100m
  54. memory: 50Mi
  55. Requests:
  56. cpu: 10m
  57. memory: 10Mi
  58. Environment:
  59. DNS_AGENT:
  60. Mounts:
  61. /var/run/secrets/kubernetes.io/serviceaccount from sleep-token-zq2wv (ro)
  62. Containers:
  63. sleep:
  64. Container ID: docker://a5437e12f6ea25d828531ba0dc4fab78374d5e9f746b6a199c4ed03b5d53c8f7
  65. Image: governmentpaas/curl-ssl
  66. Image ID: docker-pullable://governmentpaas/curl-ssl@sha256:b8d0e024380e2a02b557601e370be6ceb8b56b64e80c3ce1c2bcbd24f5469a23
  67. Port: <none>
  68. Host Port: <none>
  69. Command:
  70. /bin/sleep
  71. 3650d
  72. State: Running
  73. Started: Wed, 27 May 2020 12:14:14 +0800
  74. Ready: True
  75. Restart Count: 0
  76. Environment: <none>
  77. Mounts:
  78. /etc/sleep/tls from secret-volume (rw)
  79. /var/run/secrets/kubernetes.io/serviceaccount from sleep-token-zq2wv (ro)
  80. istio-proxy:
  81. Container ID: docker://d03a43d3f257c057b664cf7ab03bcd301799a9e849da35fe54fdb0c9ea5516a4
  82. Image: docker.io/istio/proxyv2:1.6.0
  83. Image ID: docker-pullable://istio/proxyv2@sha256:821cc14ad9a29a2cafb9e351d42096455c868f3e628376f1d0e1763c3ce72ca6
  84. Port: 15090/TCP
  85. Host Port: 0/TCP
  86. Args:
  87. proxy
  88. sidecar
  89. --domain
  90. $(POD_NAMESPACE).svc.cluster.local
  91. --serviceCluster
  92. sleep.$(POD_NAMESPACE)
  93. --proxyLogLevel=warning
  94. --proxyComponentLogLevel=misc:error
  95. --trust-domain=cluster.local
  96. --concurrency
  97. 2
  98. State: Running
  99. Started: Wed, 27 May 2020 12:14:17 +0800
  100. Ready: True
  101. Restart Count: 0

从输出中可以看出,istio-init 容器的 StateTerminated,而 ReasonCompleted。只有两个容器是运行的,主应用程序 curl-ssl 容器和 istio-proxyv2 容器。

让我们格式化istio-init 对应的 Args 参数,发现它执行了如下命令

  1. istio-iptables -p 15001 -z 15006 -u 1337 -m REDIRECT -i * -x -b * -d 15090,15021,15020

可以看到 istio-init 容器的入口是 istio-iptables 命令行, 它是一个go编译出来的二进制文件,该二进制文件会调用iptables命令创建了一些列iptables规则来劫持Pod中的流量。命令行工具源码入口在 tools/istio-iptables/main.go 中。接下来我们看看它具体操作的iptables规则有哪些。

本文运行在minikube上,因为istio-init容器在初始化完成后就会退出,所以是没办法直接登入该容器的。但是它应用的iptables的规则会在同一Pod内其他容器上看到,我们可以登录该Pod其他容器查看对应的规则,执行命令如下:

进入 minikube 并切换为 root 用户

  1. minikube ssh
  2. sudo -i

查看sleep应用相关的容器

  1. docker ps | grep sleep
  2. d03a43d3f257 istio/proxyv2 "/usr/local/bin/pilo…" 2 hours ago Up 2 hours k8s_istio-proxy_slee-54f94cbff5-jmwtf_default_70c72535-cbfb-4201-af07-feb0948cc0c6_0
  3. a5437e12f6ea 8c797666f87b "/bin/sleep 3650d" 2 hours ago Up 2 hours k8s_sleep_sleep-54f94cbff5-jmwtf_default_70c72535-cbfb-4201-af07-feb0948cc0c6_0
  4. efdbb69b77c0 k8s.gcr.io/pause:3.2 "/pause" 2 hours ago Up 2 hours k8s_POD_sleep-54f94cbff5-jmwtf_default_70c72535-cbfb-4201-af07-feb0948cc0c6_0

挑选上述容器中的其中一个,查看其进程ID,这里8533为其进程ID。这里如果直接进入其docker容器执行ssh是无法获取到其iptables规则的,因为其权限不足。

  1. iptables -t nat -L -v
  2. iptables v1.6.1: can't initialize iptables table `nat': Permission denied (you must be root)
  3. Perhaps iptables or your kernel needs to be upgraded.

需要通过nsenter提权查看其对应规则,nsenter命令详解

  1. docker inspect efdbb69b77c0 --format '{{ .State.Pid }}'
  2. 8533
  3. nsenter -t 8533 -n iptables -t nat -S
  4. -P PREROUTING ACCEPT
  5. -P INPUT ACCEPT
  6. -P OUTPUT ACCEPT
  7. -P POSTROUTING ACCEPT
  8. -N ISTIO_INBOUND
  9. -N ISTIO_IN_REDIRECT
  10. -N ISTIO_OUTPUT
  11. -N ISTIO_REDIRECT
  12. -A PREROUTING -p tcp -j ISTIO_INBOUND
  13. -A OUTPUT -p tcp -j ISTIO_OUTPUT
  14. -A ISTIO_INBOUND -p tcp -m tcp --dport 22 -j RETURN
  15. -A ISTIO_INBOUND -p tcp -m tcp --dport 15090 -j RETURN
  16. -A ISTIO_INBOUND -p tcp -m tcp --dport 15021 -j RETURN
  17. -A ISTIO_INBOUND -p tcp -m tcp --dport 15020 -j RETURN
  18. -A ISTIO_INBOUND -p tcp -j ISTIO_IN_REDIRECT
  19. -A ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-ports 15006
  20. -A ISTIO_OUTPUT -s 127.0.0.6/32 -o lo -j RETURN
  21. -A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -m owner --uid-owner 1337 -j ISTIO_IN_REDIRECT
  22. -A ISTIO_OUTPUT -o lo -m owner ! --uid-owner 1337 -j RETURN
  23. -A ISTIO_OUTPUT -m owner --uid-owner 1337 -j RETURN
  24. -A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -m owner --gid-owner 1337 -j ISTIO_IN_REDIRECT
  25. -A ISTIO_OUTPUT -o lo -m owner ! --gid-owner 1337 -j RETURN
  26. -A ISTIO_OUTPUT -m owner --gid-owner 1337 -j RETURN
  27. -A ISTIO_OUTPUT -d 127.0.0.1/32 -j RETURN
  28. -A ISTIO_OUTPUT -j ISTIO_REDIRECT
  29. -A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001

查看 NAT 表中规则配置的详细信息

  1. nsenter -t 8533 -n iptables -t nat -L -v
  2. Chain PREROUTING (policy ACCEPT 3435 packets, 206K bytes)
  3. pkts bytes target prot opt in out source destination
  4. 3435 206K ISTIO_INBOUND tcp -- any any anywhere anywhere
  5. Chain INPUT (policy ACCEPT 3435 packets, 206K bytes)
  6. pkts bytes target prot opt in out source destination
  7. Chain OUTPUT (policy ACCEPT 599 packets, 54757 bytes)
  8. pkts bytes target prot opt in out source destination
  9. 22 1320 ISTIO_OUTPUT tcp -- any any anywhere anywhere
  10. Chain POSTROUTING (policy ACCEPT 599 packets, 54757 bytes)
  11. pkts bytes target prot opt in out source destination
  12. Chain ISTIO_INBOUND (1 references)
  13. pkts bytes target prot opt in out source destination
  14. 0 0 RETURN tcp -- any any anywhere anywhere tcp dpt:22
  15. 1 60 RETURN tcp -- any any anywhere anywhere tcp dpt:15090
  16. 3434 206K RETURN tcp -- any any anywhere anywhere tcp dpt:15021
  17. 0 0 RETURN tcp -- any any anywhere anywhere tcp dpt:15020
  18. 0 0 ISTIO_IN_REDIRECT tcp -- any any anywhere anywhere
  19. Chain ISTIO_IN_REDIRECT (3 references)
  20. pkts bytes target prot opt in out source destination
  21. 0 0 REDIRECT tcp -- any any anywhere anywhere redir ports 15006
  22. Chain ISTIO_OUTPUT (1 references)
  23. pkts bytes target prot opt in out source destination
  24. 0 0 RETURN all -- any lo 127.0.0.6 anywhere
  25. 0 0 ISTIO_IN_REDIRECT all -- any lo anywhere !localhost owner UID match 1337
  26. 0 0 RETURN all -- any lo anywhere anywhere ! owner UID match 1337
  27. 22 1320 RETURN all -- any any anywhere anywhere owner UID match 1337
  28. 0 0 ISTIO_IN_REDIRECT all -- any lo anywhere !localhost owner GID match 1337
  29. 0 0 RETURN all -- any lo anywhere anywhere ! owner GID match 1337
  30. 0 0 RETURN all -- any any anywhere anywhere owner GID match 1337
  31. 0 0 RETURN all -- any any anywhere localhost
  32. 0 0 ISTIO_REDIRECT all -- any any anywhere anywhere
  33. Chain ISTIO_REDIRECT (1 references)
  34. pkts bytes target prot opt in out source destination
  35. 0 0 REDIRECT tcp -- any any anywhere anywhere redir ports 15001

关于 iptables 规则请参考 iptables 命令

回过头来看下对应go源码

tools/istio-iptables/pkg/constants/constants.go

  1. // Constants for iptables commands
  2. const (
  3. IPTABLES = "iptables"
  4. IPTABLESRESTORE = "iptables-restore"
  5. IPTABLESSAVE = "iptables-save"
  6. IP6TABLES = "ip6tables"
  7. IP6TABLESRESTORE = "ip6tables-restore"
  8. IP6TABLESSAVE = "ip6tables-save"
  9. IP = "ip"
  10. )
  11. // iptables tables
  12. const (
  13. MANGLE = "mangle"
  14. NAT = "nat"
  15. FILTER = "filter"
  16. )
  17. // Built-in iptables chains
  18. const (
  19. INPUT = "INPUT"
  20. OUTPUT = "OUTPUT"
  21. FORWARD = "FORWARD"
  22. PREROUTING = "PREROUTING"
  23. POSTROUTING = "POSTROUTING"
  24. )
  25. ......

tools/istio-iptables/pkg/cmd/root.go

  1. var rootCmd = &cobra.Command{
  2. Use: "istio-iptables",
  3. Short: "Set up iptables rules for Istio Sidecar",
  4. Long: "Script responsible for setting up port forwarding for Istio sidecar.",
  5. Run: func(cmd *cobra.Command, args []string) {
  6. cfg := constructConfig()
  7. var ext dep.Dependencies
  8. if cfg.DryRun {
  9. ext = &dep.StdoutStubDependencies{}
  10. } else {
  11. ext = &dep.RealDependencies{}
  12. }
  13. iptConfigurator := NewIptablesConfigurator(cfg, ext)
  14. if !cfg.SkipRuleApply {
  15. // 规则执行的入口
  16. iptConfigurator.run()
  17. }
  18. }
  19. }
  1. func (iptConfigurator *IptablesConfigurator) run() {
  2. iptConfigurator.logConfig()
  3. // ...此处省略1万字...
  4. // Create a new chain for redirecting outbound traffic to the common Envoy port.
  5. // In both chains, '-j RETURN' bypasses Envoy and '-j ISTIOREDIRECT'
  6. // redirects to Envoy.
  7. iptConfigurator.iptables.AppendRuleV4(
  8. constants.ISTIOREDIRECT, constants.NAT, "-p", constants.TCP, "-j", constants.REDIRECT, "--to-ports", iptConfigurator.cfg.ProxyPort)
  9. // Use this chain also for redirecting inbound traffic to the common Envoy port
  10. // when not using TPROXY.
  11. iptConfigurator.iptables.AppendRuleV4(constants.ISTIOINREDIRECT, constants.NAT, "-p", constants.TCP, "-j", constants.REDIRECT,
  12. "--to-ports", iptConfigurator.cfg.InboundCapturePort)
  13. iptConfigurator.handleInboundPortsInclude()
  14. // TODO: change the default behavior to not intercept any output - user may use http_proxy or another
  15. // iptablesOrFail wrapper (like ufw). Current default is similar with 0.1
  16. // Jump to the ISTIOOUTPUT chain from OUTPUT chain for all tcp traffic.
  17. iptConfigurator.iptables.AppendRuleV4(constants.OUTPUT, constants.NAT, "-p", constants.TCP, "-j", constants.ISTIOOUTPUT)
  18. // Apply port based exclusions. Must be applied before connections back to self are redirected.
  19. if iptConfigurator.cfg.OutboundPortsExclude != "" {
  20. for _, port := range split(iptConfigurator.cfg.OutboundPortsExclude) {
  21. iptConfigurator.iptables.AppendRuleV4(constants.ISTIOOUTPUT, constants.NAT, "-p", constants.TCP, "--dport", port, "-j", constants.RETURN)
  22. }
  23. }
  24. // 127.0.0.6 is bind connect from inbound passthrough cluster
  25. iptConfigurator.iptables.AppendRuleV4(constants.ISTIOOUTPUT, constants.NAT, "-o", "lo", "-s", "127.0.0.6/32", "-j", constants.RETURN)
  26. // Skip redirection for Envoy-aware applications and
  27. // container-to-container traffic both of which explicitly use
  28. // localhost.
  29. iptConfigurator.iptables.AppendRuleV4(constants.ISTIOOUTPUT, constants.NAT, "-d", "127.0.0.1/32", "-j", constants.RETURN)
  30. // Apply outbound IPv4 exclusions. Must be applied before inclusions.
  31. for _, cidr := range ipv4RangesExclude.IPNets {
  32. iptConfigurator.iptables.AppendRuleV4(constants.ISTIOOUTPUT, constants.NAT, "-d", cidr.String(), "-j", constants.RETURN)
  33. }
  34. // ...此处省略1万字...
  35. // 真正执行iptables的方法
  36. iptConfigurator.executeCommands()
  37. }

iptConfigurator.executeCommands() 方法执行最终可以跟踪到tools/istio-iptables/pkg/dependencies/implementation.go中,可以看到就是利用的go 的命令行执行工具exec.Command来执行的os系统命令。

  1. func (r *RealDependencies) execute(cmd string, redirectStdout bool, args ...string) error {
  2. //执行真正的iptables命令
  3. externalCommand := exec.Command(cmd, args...)
  4. externalCommand.Stdout = os.Stdout
  5. //TODO Check naming and redirection logic
  6. if !redirectStdout {
  7. externalCommand.Stderr = os.Stderr
  8. }
  9. return externalCommand.Run()
  10. }

执行此命令后,istio-init就完成了它的使命。

iptables 进行流量拦截的部分单独一篇文章来写。

istio-proxy

通过开篇我们可以看到还有istio-proxy这个容器

  1. Image: docker.io/istio/proxyv2:1.6.0
  2. Image ID: docker-pullable://istio/proxyv2@sha256:821cc14ad9a29a2cafb9e351d42096455c868f3e628376f1d0e1763c3ce72ca6
  3. Port: 15090/TCP
  4. Host Port: 0/TCP
  5. Args:
  6. proxy
  7. sidecar
  8. --domain
  9. $(POD_NAMESPACE).svc.cluster.local
  10. --serviceCluster
  11. sleep.$(POD_NAMESPACE)
  12. --proxyLogLevel=warning
  13. --proxyComponentLogLevel=misc:error
  14. --trust-domain=cluster.local
  15. --concurrency
  16. 2
  17. State: Running

我们可以通过dockerhub 查看改镜像的内容 https://hub.docker.com/r/istio/proxyv2/tags

这里我们一起看看对应镜像1.6.0版本对应的Dockerfile传送门 . 它在istio源码的位置在pilot/docker/Dockerfile.proxyv2

  1. ADD file:c3e6bb316dfa6b81dd4478aaa310df532883b1c0a14edeec3f63d641980c1789 in /
  2. /bin/sh -c [ -z "$(apt-get indextargets)" ]
  3. /bin/sh -c mkdir -p /run/systemd && echo 'docker' > /run/systemd/container
  4. CMD ["/bin/bash"]
  5. ENV DEBIAN_FRONTEND=noninteractive
  6. // ...此处省略1万字...
  7. COPY envoy /usr/local/bin/envoy
  8. COPY pilot-agent /usr/local/bin/pilot-agent
  9. ENTRYPOINT ["/usr/local/bin/pilot-agent"]

我们看到里面将envoy,pilot-agent程序添加进proxyv2容器,并执行pilot-agent作为启动命令,我们合并器执行参数,得出如下命令:

  1. pilot-agent proxy sidecar --domain default.svc.cluster.local --serviceCluster sleep.default --proxyLogLevel=warning --proxyComponentLogLevel=misc:error --trust-domain=cluster.local --concurrency 2

那么我们接着看看该命令执行后会做什么操作呢?参考上面的操作步骤

  1. minikube ssh
  2. sudo -i
  3. docker ps |grep sleep
  4. d03a43d3f257 istio/proxyv2 "/usr/local/bin/pilo…" 3 hours ago Up 3 hours k8s_istio-proxy_slee-54f94cbff5-jmwtf_default_70c72535-cbfb-4201-af07-feb0948cc0c6_0
  5. a5437e12f6ea 8c797666f87b "/bin/sleep 3650d" 3 hours ago Up 3 hours k8s_sleep_sleep-54f94cbff5-jmwtf_default_70c72535-cbfb-4201-af07-feb0948cc0c6_0
  6. efdbb69b77c0 k8s.gcr.io/pause:3.2 "/pause" 3 hours ago Up 3 hours k8s_POD_sleep-54f94cbff5-jmwtf_default_70c72535-cbfb-4201-af07-feb0948cc0c6_0

这次我们需要制定进入proxyv2容器d03a43d3f257并查看其内部运行的进程

  1. docker exec -it d03a43d3f257 /bin/bash
  2. ps -ef | grep sleep
  3. UID PID PPID C STIME TTY TIME CMD
  4. istio-p+ 1 0 0 04:14 ? 00:00:06 /usr/local/bin/pilot-agent proxy sidecar --domain default.svc.cluster.local --serviceCluster sleep.default --proxyLogLevel=warning --proxyComponentLogLevel=misc:error --trust-domain=cluster.local --concurrency 2
  5. istio-p+ 17 1 0 04:14 ? 00:00:26 /usr/local/bin/envoy -c etc/istio/proxy/envoy-rev0.json --restart-epoch 0 --drain-time-s 45 --parent-shutdown-time-s 60 --service-cluster sleep.default --service-node sidecar~172.18.0.11~sleep-54f94cbff5-jmwtf.default~default.svc.cluster.local --max-obj-name-len 189 --local-address-ip-version v4 --log-format %Y-%m-%dT%T.%fZ.%l.envoy %n.%v -l warning --component-log-level misc:error --concurrency 2

观察PID与PPID可以发现,pilot-agent执行后启动了envoy程序。

pilot-agent命令源码入口在pilot/cmd/pilot-agent/main.go,该命令的用法可以查阅pilot-agent命令

  1. proxyCmd = &cobra.Command{
  2. Use: "proxy",
  3. Short: "Envoy proxy agent",
  4. RunE: func(c *cobra.Command, args []string) error {
  5. // ...此处省略1万字...
  6. proxyConfig, err := constructProxyConfig()
  7. if out, err := gogoprotomarshal.ToYAML(&proxyConfig); err != nil {
  8. log.Infof("Failed to serialize to YAML: %v", err)
  9. // ...此处省略1万字...
  10. envoyProxy := envoy.NewProxy(envoy.ProxyConfig{
  11. Config: proxyConfig,
  12. Node: role.ServiceNode(),
  13. LogLevel: proxyLogLevel,
  14. ComponentLogLevel: proxyComponentLogLevel,
  15. PilotSubjectAltName: pilotSAN,
  16. MixerSubjectAltName: mixerSAN,
  17. NodeIPs: role.IPAddresses,
  18. PodName: podName,
  19. PodNamespace: podNamespace,
  20. PodIP: podIP,
  21. STSPort: stsPort,
  22. ControlPlaneAuth: proxyConfig.ControlPlaneAuthPolicy == meshconfig.AuthenticationPolicy_MUTUAL_TLS,
  23. DisableReportCalls: disableInternalTelemetry,
  24. OutlierLogPath: outlierLogPath,
  25. PilotCertProvider: pilotCertProvider,
  26. ProvCert: citadel.ProvCert,
  27. })
  28. agent := envoy.NewAgent(envoyProxy, features.TerminationDrainDuration())
  29. // 监控envoy启动直至启动成功,启动逻辑在`agent.Restart`中
  30. watcher := envoy.NewWatcher(tlsCerts, agent.Restart)
  31. go watcher.Run(ctx)
  32. return agent.Run(ctx)
  33. },
  34. }
  35. )

agent.Restart方法

  1. func (a *agent) Restart(config interface{}) {
  2. // 同一时刻只允许一个envoy agent执行启动
  3. a.restartMutex.Lock()
  4. defer a.restartMutex.Unlock()
  5. if reflect.DeepEqual(a.currentConfig, config) {
  6. // 如果配置文件没有发生变更那么什么都不用做,直接退出
  7. a.mutex.Unlock()
  8. return
  9. }
  10. // 如果监控到配置文件发生了变更,那么epoch版本号+1,创建新的envoy 实例
  11. epoch := a.currentEpoch + 1
  12. log.Infof("Received new config, creating new Envoy epoch %d", epoch)
  13. // 启动一个新的协程启动envoy
  14. go a.runWait(config, epoch, abortCh)
  15. }

go a.runWait(config, epoch, abortCh)方法

  1. func (a *agent) runWait(config interface{}, epoch int, abortCh <-chan error) {
  2. // 直接调用proxy实例启动,等待proxy启动完成
  3. err := a.proxy.Run(config, epoch, abortCh)
  4. a.proxy.Cleanup(epoch)
  5. a.statusCh <- exitStatus{epoch: epoch, err: err}
  6. }

proxy.Run 方法

  1. func (e *envoy) Run(config interface{}, epoch int, abort <-chan error) error {
  2. var fname string
  3. // 如果启动参数指定了自定义的配置文件那么使用自定义的配置文件,否则使用默认的配置
  4. if len(e.Config.CustomConfigFile) > 0 {
  5. fname = e.Config.CustomConfigFile
  6. } else {
  7. // 这里创建envoy 启动需要的/etc/istio/proxy/envoy-rev0.json 配置文件
  8. // 其中的0这个参数会随着重启的次数跟着+1变动,但仅仅是文件名发生变动,里面的配置内容还是一样
  9. out, err := bootstrap.New(bootstrap.Config{
  10. Node: e.Node,
  11. Proxy: &e.Config,
  12. PilotSubjectAltName: e.PilotSubjectAltName,
  13. MixerSubjectAltName: e.MixerSubjectAltName,
  14. LocalEnv: os.Environ(),
  15. NodeIPs: e.NodeIPs,
  16. PodName: e.PodName,
  17. PodNamespace: e.PodNamespace,
  18. PodIP: e.PodIP,
  19. STSPort: e.STSPort,
  20. ControlPlaneAuth: e.ControlPlaneAuth,
  21. DisableReportCalls: e.DisableReportCalls,
  22. OutlierLogPath: e.OutlierLogPath,
  23. PilotCertProvider: e.PilotCertProvider,
  24. ProvCert: e.ProvCert,
  25. }).CreateFileForEpoch(epoch)
  26. fname = out
  27. }
  28. // ...此处省略1万字...
  29. // envoy 启动需要的参数
  30. // 也就是 --restart-epoch 0 --drain-time-s 45 --parent-shutdown-time-s 60...这部分内容
  31. args := e.args(fname, epoch, istioBootstrapOverrideVar.Get())
  32. // 很熟悉的味道,调用系统命令启动envoy
  33. // e.Config.BinaryPath 参数值为 /usr/local/bin/envoy,
  34. // 相关默认常量值可以查阅 pkg/config/constants/constants.go 这个源文件
  35. cmd := exec.Command(e.Config.BinaryPath, args...)
  36. // ...此处省略1万字...
  37. }

整个启动过程其实挺复杂的,这里只是分析了最基础的启动envoy的流程。如果细看里面还包括

  1. SDS的启动

  2. polit 度量指标服务启动

  3. 监控配置更新后热启动envoy的流程

  4. 收到系统kill命令优雅退出envoy的流程

应用容器

至于应用容器的启动,该咋启动就咋启动,除了协议的限制外没有其他对Istio任何依赖,只要应用使用的是Istio支持的协议,都可以被Istio拦截并管理流量。这也就是Istio的强大之处。目前Istio支持为HTTP、gRPC、WebSocket 和 TCP 流量自动负载均衡。

参考文献

https://istio.io/zh/blog/2019/data-plane-setup/#traffic-flow-from-application-container-to-sidecar-proxy

https://jimmysong.io/blog/sidecar-injection-iptables-and-traffic-routing/

https://preliminary.istio.io/zh/docs/reference/commands/pilot-agent/

Istio Polit-agent & Envoy 启动流程的更多相关文章

  1. idou老师教你学Istio 29:Envoy启动流程

    1. 功能概述 Envoy启动时,会启动一个进程,并在这个进程中启动很多线程,这样,可以启动很多worker线程,一般worker线程数与核心数相同,每个worker线程处理所有已配置的listene ...

  2. Flume-ng源码解析之启动流程

    今天我们通过阅读Flume-NG的源码来看看Flume的整个启动流程,废话不多说,翠花,上源码!! 1 主类也是启动类 在这里我贴出Application中跟启动有关的方法,其他你们可以自己看源码,毕 ...

  3. ORACLE11G R2 RAC的进程启动流程

    简要说明ORACLE11GR2 RAC的进程启动流程: 1.启动流程概览图: 二.RAC启动流程的梳理: 第一层:OHASD 启动:(OHASD派生) 1.CSSDAGENT负责启动CSSD的AGEN ...

  4. Oracle RAC 服务启动流程

    启动流程步骤层次梳理:第一层:OHASD 启动: cssdagent - 负责启动 CSSD 的 Agent.orarootagent - 负责启动所有 root 用户下的 ohasd 资源 的Age ...

  5. MyCat源码分析系列之——配置信息和启动流程

    更多MyCat源码分析,请戳MyCat源码分析系列 MyCat配置信息 除了一些默认的配置参数,大多数的MyCat配置信息是通过读取若干.xml/.properties文件获取的,主要包括: 1)se ...

  6. Android进阶系列之源码分析Activity的启动流程

    美女镇楼,辟邪! 源码,是一个程序猿前进路上一个大的而又不得不去翻越障碍,我讨厌源码,看着一大堆.5000多行,要看完得啥时候去了啊.不过做安卓的总有这一天,自从踏上这条不归路,我就认命了.好吧,我慢 ...

  7. Spring Boot启动流程详解(一)

    环境 本文基于Spring Boot版本1.3.3, 使用了spring-boot-starter-web. 配置完成后,编写了代码如下: @SpringBootApplication public ...

  8. linux启动流程及自定义gurb

    linux 启动流程 POST BIOS(boot sequence) 所选择的启动设备次序的MBR中是否有引导程序, ----> MBR(bootloader) 提供内核列表 -------& ...

  9. linux启动流程

    看了深入理解linux内核一书的最后对linux启动流程的介绍,下面就把我能理解的写一下吧: bios(硬件加电自检POST,寻找第一个启动设备) the boot loader(可以从硬盘启动也可以 ...

随机推荐

  1. Radix_Sort

    public class Radix_sort { public static void sort(int[] arrays,int radix){ int n = 1; int length = a ...

  2. 数组输出黑科技----fwrite()

    fwrite(const void*buffer,size_t size,size_t count,FILE*stream); (1)buffer:是一个指针,对fwrite来说,是要输出数据的地址. ...

  3. CodeForces - 1047CEnlarge GCD(这题很难,快来看题解,超级详细,骗浏览量)

    C. Enlarge GCD time limit per test1 second memory limit per test256 megabytes inputstandard input ou ...

  4. JAVA大数几算--HDU 2054 A == B ?

    Problem Description Give you two numbers A and B, if A is equal to B, you should print "YES&quo ...

  5. Python爬虫---爬取抖音短视频

    目录 前言 抖音爬虫制作 选定网页 分析网页 提取id构造网址 拼接数据包链接 获取视频地址 下载视频 全部代码 实现结果 待解决的问题 前言 最近一直想要写一个抖音爬虫来批量下载抖音的短视频,但是经 ...

  6. 题解 CF545A 【Toy Cars】

    题目传送门 太弱了,只能写写A题的题解 题意 给你一个 $n·n$ 的矩阵,翻车分三种情况: 如果 $a_i,_j=1$ ,记录第 $i$ 辆车 如果 $a_i,_j=2$ ,记录第 $j$ 辆车 如 ...

  7. 初识CoAP协议

    前言 本文介绍什么是CoAP,以及如何在物联网设备上使用它.CoAP是一种物联网协议,具有一些专门为受约束的设备而设计的有趣功能.还有其他一些可用于构建物联网解决方案的IoT协议,例如MQTT等. 物 ...

  8. python:入门

    基础学习路线 解释器 什么是解释器? 下载解释器 下载链接 安装解释器 PyCharm 什么是PyCharm? 下载安装 下载链接 参考:1 注意:选择社区版 PyCharm的基本操作 1.创建项目 ...

  9. C. Helga Hufflepuff's Cup 树形dp 难

    C. Helga Hufflepuff's Cup 这个题目我感觉挺难的,想了好久也写了很久,还是没有写出来. dp[i][j][k] 代表以 i 为根的子树中共选择了 j 个特殊颜色,且当前节点 i ...

  10. Collection接口【集合】和Iterator迭代器类

    1.1集合的概述 前面基础学习并使用过集合ArrayList<E>,那么集合究竟是什么呢? 集合:集合是Java中提供的一种容器,可以用来存储多个数据. 那么意思就是说集合是容器,但是容器 ...