Istio 中的 Kubernetes 原生 Sidecar

使用 Istio 演示新的 SidecarContainers 功能。

2023年8月15日 | 作者:John Howard - Google

如果您听说过任何关于服务网格的信息,那就是它们使用 sidecar 模式工作:代理服务器与您的应用程序代码一起部署。sidecar 模式就是这样:一种模式。到目前为止,Kubernetes 完全没有正式支持 sidecar 容器。

这导致了许多问题:如果您有一个按设计终止的作业,但有一个不会终止的 sidecar 容器怎么办?这个确切的用例是Kubernetes 问题跟踪器上最受欢迎的用例

在 2019 年提出了在 Kubernetes 中添加 sidecar 支持的正式提案。经过一路上的多次启动和停止,以及去年对项目的重启,Kubernetes 1.28 中将正式发布对 sidecar 的 Alpha 支持。Istio 已经实现了对该功能的支持,并且在本篇文章中,您可以了解如何利用它。

Sidecar 难题

Sidecar 容器提供了强大的功能,但也存在一些问题。虽然 Pod 中的容器可以共享某些内容,但它们的生命周期是完全解耦的。对于 Kubernetes 来说,这两个容器在功能上是相同的。

但是,在 Istio 中它们并不相同 - Istio 容器是主应用程序容器运行所必需的,并且如果没有主应用程序容器则没有价值。

这种预期上的不匹配会导致各种问题

Istio 社区内外已经花费了无数小时来解决这些问题 - 但收效甚微。

解决根本原因

虽然 Istio 中越来越复杂的解决方法可以帮助减轻 Istio 用户的痛苦,但理想情况下,所有这些都应该正常工作 - 而且不仅仅是针对 Istio。幸运的是,Kubernetes 社区一直在努力直接在 Kubernetes 中解决这些问题。

在 Kubernetes 1.28 中,合并了一项添加对 sidecar 的原生支持的新功能,结束了 5 年多的持续工作。随着它的合并,我们所有的问题都可以在没有解决方法的情况下得到解决!

当我们身处“GitHub 问题名人堂”时,这两个问题占据了 Kubernetes 历时最久的问题的第 1 位和第 6 位 - 并且终于被关闭了!

特别感谢参与将此项目完成的众多个人。

试用

虽然 Kubernetes 1.28 刚刚发布,但新的 SidecarContainers 功能处于 Alpha 阶段(因此默认情况下处于关闭状态),并且 Istio 中对该功能的支持尚未发布,但我们今天仍然可以试用它 - 只是不要在生产环境中尝试!

首先,我们需要启动一个启用了 SidecarContainers 功能的 Kubernetes 1.28 集群

$ cat <<EOF | kind create cluster --name sidecars --image gcr.io/istio-testing/kind-node:v1.28.0 --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
featureGates:
  SidecarContainers: true
EOF

然后,我们可以下载最新的 Istio 1.19 预发布版(因为 1.19 尚未发布)。我在这里使用了 Linux。这是一个 Istio 的预发布版本,所以再次强调 - 不要在生产环境中尝试!当我们安装 Istio 时,我们将启用原生 sidecar 支持的功能标志并打开访问日志以帮助稍后演示。

$ TAG=1.19.0-beta.0
$ curl -L https://github.com/istio/istio/releases/download/$TAG/istio-$TAG-linux-amd64.tar.gz | tar xz
$ ./istioctl install --set values.pilot.env.ENABLE_NATIVE_SIDECARS=true -y --set meshConfig.accessLogFile=/dev/stdout

最后,我们可以部署工作负载

$ kubectl label namespace default istio-injection=enabled
$ kubectl apply -f samples/sleep/sleep.yaml

让我们看看 Pod

$ kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
sleep-7656cf8794-8fhdk   2/2     Running   0          51s

乍一看一切都很正常……如果我们深入了解,就可以看到其中的奥妙。

$ kubectl get pod -o "custom-columns="\
"NAME:.metadata.name,"\
"INIT:.spec.initContainers[*].name,"\
"CONTAINERS:.spec.containers[*].name"

NAME                     INIT                     CONTAINERS
sleep-7656cf8794-8fhdk   istio-init,istio-proxy   sleep

在这里,我们可以看到 Pod 中的所有 containersinitContainers

惊喜!istio-proxy 现在是 initContainer

更具体地说,它是一个 initContainer,并设置了 restartPolicy: Always(一个新字段,由 SidecarContainers 功能启用)。这告诉 Kubernetes 将其视为 sidecar。

这意味着列表中后面的 initContainers 和所有正常的 containers 都将在代理容器准备就绪后才开始启动。此外,即使代理容器仍在运行,Pod 也会终止。

Init 容器流量

为了对此进行测试,让我们让我们的 Pod 实际执行某些操作。在这里,我们部署了一个简单的 Pod,它在 initContainer 中发送请求。通常,这会失败。

apiVersion: v1
kind: Pod
metadata:
  name: sleep
spec:
  initContainers:
  - name: check-traffic
    image: istio/base
    command:
    - curl
    - httpbin.org/get
  containers:
  - name: sleep
    image: istio/base
    command: ["/bin/sleep", "infinity"]

检查代理容器,我们可以看到请求成功并通过了 Istio sidecar

$ kubectl logs sleep -c istio-proxy | tail -n1
[2023-07-25T22:00:45.703Z] "GET /get HTTP/1.1" 200 - via_upstream - "-" 0 1193 334 334 "-" "curl/7.81.0" "1854226d-41ec-445c-b542-9e43861b5331" "httpbin.org" ...

如果我们检查 Pod,我们可以看到我们的 sidecar 现在check-traffic initContainer 之前运行

$ kubectl get pod -o "custom-columns="\
"NAME:.metadata.name,"\
"INIT:.spec.initContainers[*].name,"\
"CONTAINERS:.spec.containers[*].name"

NAME    INIT                                  CONTAINERS
sleep   istio-init,istio-proxy,check-traffic   sleep

退出 Pod

前面,我们提到当应用程序退出(在 Jobs 中很常见)时,Pod 将永远存在。幸运的是,这也得到了解决!

首先,我们部署一个将在 1 秒后退出并且不会重新启动的 Pod

apiVersion: v1
kind: Pod
metadata:
  name: sleep
spec:
  restartPolicy: Never
  containers:
- name: sleep
  image: istio/base
  command: ["/bin/sleep", "1"]

我们可以观察它的进度

$ kubectl get pods -w
NAME    READY   STATUS     RESTARTS   AGE
sleep   0/2     Init:1/2   0          2s
sleep   0/2     PodInitializing   0          2s
sleep   1/2     PodInitializing   0          3s
sleep   2/2     Running           0          4s
sleep   1/2     Completed         0          5s
sleep   0/2     Completed         0          12s

在这里,我们可以看到应用程序容器退出了,并且 Istio 的 sidecar 容器也很快退出了。以前,Pod 会一直卡在 Running 状态,而现在它可以转换为 Completed 状态。不再有僵尸 Pod 了!

环境模式怎么样?

去年,Istio 宣布了环境模式 - Istio 的一种新的数据平面模式,它不依赖于 sidecar 容器。那么,随着环境模式的到来,这一切是否还有意义呢?

我会说一个响亮的“是”!

虽然当环境模式用于工作负载时,sidecar 的影响会减弱,但我预计几乎所有大型 Kubernetes 用户在其部署中都存在某种 sidecar。这可能是他们不想迁移到环境模式的 Istio 工作负载,是他们尚未迁移的工作负载,或者与 Istio 无关的事物。因此,虽然此问题相关的情况可能减少了,但对于使用 sidecar 的情况来说,它仍然是一个巨大的改进。

您可能会好奇相反的情况 - 如果我们所有的 sidecar 难题都得到了解决,我们为什么还需要环境模式呢?即使解决了这些 sidecar 限制,环境模式仍然带来各种好处。例如,这篇博文详细介绍了为什么将代理与工作负载解耦是有利的。

亲自试一试

我们鼓励喜欢冒险的读者在测试环境中亲自尝试!这些实验性和 Alpha 功能的反馈对于确保它们在提升之前是稳定并符合预期的至关重要。如果您试用了它,请在Istio Slack中告诉我们您的想法!

特别是,Kubernetes 团队希望了解更多关于以下方面的信息:

分享此文章