如何实现无 Pod 的 Kubernetes 和 Istio 部署

探索如何将 Kubernetes 和 Istio 的完整功能嵌入到单一二进制文件中,实现无 Pod 的极简部署方案。

本文为译文,阅读原文请转到:https://jimmysong.io/trans/podless-kubernetes-istio/

Kubernetes 经常被批评(有些不公平)操作起来过于复杂,促使大多数人依赖托管服务。然而,k3s[1] 某种程度上颠覆了这一点,将完整的 Kubernetes 发行版打包成一个二进制文件。这非常方便,特别是在物联网等小型环境中运行时;虽然隔离组件对非常大规模、先进的部署有好处,但对较小的环境来说,操作微服务可能只是一种负担——这正是 Istio 多年前选择重构为更单体架构的原因[2]

然而,它还是没有那么“精简”。在一个空集群中运行 k3d cluster create test 后,我们会在集群中看到各种 pod:

$ kubectl get pods --all-namespaces
NAMESPACE     NAME                                      READY   STATUS     RESTARTS  AGE
kube-system   local-path-provisioner-6c86858495-gc9jq   1/1Running02m18s
kube-system   coredns-6799fbcd5-pdf4b                   1/1Running02m18s
kube-system   helm-install-traefik-crd-cp9s2            0/1Completed02m18s
kube-system   helm-install-traefik-pch7c                0/1Completed12m18s
kube-system   traefik-f4564c4f4-q4lkj                   1/1Running02m8s
kube-system   metrics-server-54fd9b65b-d69w6            1/1Running02m18s
kube-system   svclb-traefik-58c5bb65-sq54b              2/2Running0         2m8s

k3d[3] 是一个方便的工具,可以在 Docker 内部部署 k3s,便于测试。

这是怎么回事?我们的“单二进制 Kubernetes”怎么变成了 6 个不同的容器?

虽然 k3s 将许多组件(kube-proxyflannelcontainerdkubelet 等)嵌入到一个二进制文件中,但其他组件则作为标准 pod 在集群中运行。

此外,一旦我们部署了我们最喜欢的 服务网格[4],我们将会有更多的 pod,使我们离没有 pod 的目标更远。

没有 pod 的 Kubernetes?

那么问题是——我们能否通过进一步推进 k3s 的理念,将完整的集群功能嵌入到一个二进制文件中,来获得一个功能齐全的 Kubernetes 和 Istio 部署?

警告:这些是实验性概念;绝不要在生产环境中尝试!

首先,我们可以直接去除一些不必要的组件,如 servicelb(负载均衡服务需要)、traefik(Ingress 需要)、local-storage(PVC 需要)和 metrics-serverkubectl top 需要)。

这就剩下 coredns 和 Istio。

如果我们追求极简,我们肯定会希望使用 Istio 的 ambient mode[5],它完全不需要 sidecar。幸运的是,它开箱即用并且有完整的 DNS 支持[6]。这让我们可以去掉 coredns

这样一来,如果我们能运行 Istio ambient,就可以去掉 kube-system 中的所有内容。这相对简单;难点在于不为 Istio 添加更多的 pod。

嵌入 Istio

通过 k3s 的一个分支,我修改了它,使 Istio 本身嵌入到 k3s 中。k3s 可以作为服务器和/或代理运行。通常你会有 1 个服务器,每个其他节点作为代理运行。

在 server 上,我们希望运行 Istiod(Istio 的控制平面)。在代理上,我们希望运行 istio-cni(每个节点的控制平面)和 ztunnel(每个节点的数据平面)。

这三个组件都可以直接嵌入到 k3s 中,只需一些工作!

使用这个自定义构建,我们可以通过一些自定义配置启动一个新的 k3d 集群,禁用我们不再需要的组件:

apiVersion: k3d.io/v1alpha5
kind:Simple
metadata:
name:podless
servers:1
agents:1
options:
k3d:
wait:true
timeout:"60s"
disableLoadbalancer:true
disableRollback:true
k3s:
extraArgs:
-arg:--disable-cloud-controller
nodeFilters:
-server:*
-arg:--disable-kube-proxy
nodeFilters:
-server:*
-arg:--disable-network-policy
nodeFilters:
-server:*
-arg:--disable-helm-controller
nodeFilters:
-server:*
-arg:--disable=coredns,servicelb,traefik,local-storage,metrics-server
nodeFilters:
- server:*

这里我们禁用了上面看到的所有 pod,包括一些额外的。

一个显著的例子是 kube-proxy。像其他一些项目一样(如 Cilium[7]),Istio 的 ztunnel 可以有效地替代大多数用例中的 kube-proxy

无 pod 的服务网格

所有配置就绪后,我们的集群是什么样子?

$ kubectl get pods --all-namespaces
No resources found

到目前为止一切顺利....当然,什么都不运行很容易;真正的挑战是保持集群的功能。

让我们部署一些应用程序 pod。再次强调,这些是集群中的唯一 pod:

$ kubectl get pods --all-namespaces
NAMESPACE   NAME                     READY   STATUS    RESTARTS   AGE
default     shell-5fff89ccf5-98kgg   1/1     Running   0          19s
default     echo-66d88ff694-9qprp    1/1     Running   0          14s

然后我们可以发送流量:

$ kubectl exec deploy/shell -- curl -s echo
RequestHeader=Accept:*/*
RequestHeader=User-Agent:curl/8.5.0
Hostname=echo-66d88ff694-9qprp

流量完全正常,包括服务流量(以前由 kube-proxy 处理)和 DNS(以前由 coredns 处理)。现在这些全部由 ztunnel 处理,并且所有内容都通过安全的 mTLS 传输。

除了 mTLS 加密,我们还可以基于 mTLS 身份应用策略。同样,这些都由 ztunnel 执行。

apiVersion: security.istio.io/v1
kind:AuthorizationPolicy
metadata:
name:allow-default
spec:
action:ALLOW
selector:
matchLabels:
app:echo
rules:
-from:
-source:
namespace:["cluster.local/ns/default/sa/shell"]

现在 default 命名空间的流量被允许,但其他流量不被允许。我们可以通过从 shell 发送流量以及我在 other 命名空间中部署的新测试工作负载来验证这一点:

$ kubectl exec deploy/shell -- curl -s echo
RequestHeader=Accept:*/*
RequestHeader=User-Agent:curl/8.5.0
Hostname=echo-66d88ff694-9qprp
$ kubectl exec deploy/shell -n other -- curl -s echo
command terminated with exit code 56

正如预期的那样,我们的其他应用程序被拒绝了!

此外,如果我们愿意,我们可以将流量升级通过完整的 HTTP 代理("waypoint"[8]):

$ istioctl x waypoint apply --enroll-namespace
waypoint default/waypoint applied

$ kubectl get pods
NAME                        READY   STATUS    RESTARTS   AGE
echo-66d88ff694-czd65       1/1Running

093m
shell-56bd5dbdbf-f4gh9      1/1Running093m
waypoint-7cd4dc789f-2s7z21/1Running041s

$ kubectl exec deploy/shell -- curl -s echo
RequestHeader=Accept:*/*
RequestHeader=User-Agent:curl/8.5.0
RequestHeader=X-Request-Id:18d72190-9caa-4162-8bc5-4c11518d7568
Hostname=echo-66d88ff694-czd65

现在我们的 waypoint 已经部署,所有到命名空间的流量会自动转发到它,在那里可以执行完整的 HTTP 策略。这里,我们可以看到 X-Request-Id 被添加到我们的请求中,但我们还可以获得 自动配置的其他功能[9],以及更多 我们可以配置的内容[10]

总结

最终,我们能够部署一个完整的 Kubernetes 集群和服务网格,所有基础设施组件嵌入到一个隐藏的节点二进制文件中——集群功能不需要 pod。

这实际操作起来是否实用?不太实用。然而,这确实表明 Kubernetes/Istio 被认为过于臃肿和复杂的看法并不完全准确。

它真的比典型的集群更简单吗?某种程度上是的……我们确实替换了两个组件(kube-proxy 和 coredns),但其余的我们基本上只是隐藏和打包。这显然不如完全替换有意义,但也不错。话虽如此,隐藏东西对 社交媒体参与度[11] 有好处,而 k3s 通过有效地隐藏和打包取得了巨大成功,因此显然提供了一些实实在在的好处。


引用链接

[1] k3shttps://k3s.io/
[2] Istio 多年前选择重构为更单体架构的原因: https://blog.christianposta.com/microservices/istio-as-an-example-of-when-not-to-do-microservices/
[3] k3dhttps://github.com/k3d-io/k3d/
[4] 服务网格: https://istio.io/
[5] ambient mode: https://istio.io/latest/docs/ops/ambient/getting-started/
[6] DNS 支持: https://istio.io/latest/docs/ops/configuration/traffic-management/dns-proxy/
[7] Cilium: https://docs.cilium.io/en/stable/network/kubernetes/kubeproxy-free/
[8] "waypoint": https://istio.io/latest/docs/ops/ambient/architecture/
[9] 自动配置的其他功能: https://istio.io/latest/blog/2021/zero-config-istio/
[10] 我们可以配置的内容: https://istio.io/latest/docs/tasks/
[11] 社交媒体参与度: https://twitter.com/wm/status/1577081662848241664

获取更多云原生社区资讯,加入微信群,请加入云原生社区,点击阅读原文了解更多。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值