关于后端:硬核干货丨借助多容器Pod轻松扩展K8S中的应用

Kubernetes提供了微小的灵活性和运行各种利用的能力。如果你的利用是云原生微服务或12因素(12-factor)利用,那么在Kubernetes中运行它们有可能会绝对简略。

然而,运行那些没有明确设计为在容器化环境中运行的应用程序呢?Kubernetes也能够解决这些问题,然而设置起来可能会比拟麻烦。

Kubernetes提供的最弱小的工具之一是多容器pod(只管多容器pod在各种状况下对云原生利用也很有用)。为什么要在一个 pod 中运行多个容器?因为多容器pod能够让你在不扭转其代码的状况下更改应用程序的行为。

这在各种状况下都很有用,特地是对于那些最后没有被设计成在容器中运行的应用程序来说,这很不便。咱们来看看一个例子。

确保HTTP服务的平安

Elasticsearch是在容器风行之前诞生的(当然当初在Kubernetes中运行也非常简略),它能够看成在虚拟机中运行的传统Java利用的代替。

咱们将Elasticsearch作为示例应用程序,而后应用多容器pods来加强它。

以下是非常根本的(非生产环境就绪)Elasticsearch Deployment和服务:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: elasticsearch
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: elasticsearch
  template:
    metadata:
      labels:
        app.kubernetes.io/name: elasticsearch
    spec:
      containers:
        - name: elasticsearch
          image: elasticsearch:7.9.3
          env:
            - name: discovery.type
              value: single-node
          ports:
            - name: http
              containerPort: 9200
---
apiVersion: v1
kind: Service
metadata:
  name: elasticsearch
spec:
  selector:
    app.kubernetes.io/name: elasticsearch
  ports:
    - port: 9200
      targetPort: 9200

discovery.type环境变量是让它以单个正本运行的必要条件。

Elasticsearch默认通过HTTP端口9200进行监听。你能够通过在集群中运行另一个Pod并curlelasticsearch服务来确认pod工作。

kubectl run -it --rm --image=curlimages/curl curl \
  -- curl http://elasticsearch:9200
{
  "name" : "elasticsearch-77d857c8cf-mk2dv",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "z98oL-w-SLKJBhh5KVG4kg",
  "version" : {
    "number" : "7.9.3",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "c4138e51121ef06a6404866cddc601906fe5c868",
    "build_date" : "2020-10-16T10:36:16.141335Z",
    "build_snapshot" : false,
    "lucene_version" : "8.6.2",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

当初,假如你正在向零信赖平安模式倒退,你须要对网络上的所有流量进行加密。如果应用程序没有原生的TLS反对,你会如何去做?

近期版本的Elasticsearch反对TLS,但它在之前很长一段时间内是一个付费性能。

咱们首先想到的可能是用nginx ingress做TLS终止,因为ingress是集群中路由内部流量的组件。但这并不能满足要求,因为ingress pod和Elasticsearch pod之间的流量可能会在未加密的状况下通过网络。


内部流量被路由到Ingress,而后路由到Pod

如果你在Ingress终止TLS,剩下的流量将不会加密。

一个能满足要求的解决方案是在pod上加一个nginx代理容器,通过TLS进行监听。从用户到Pod的一路流量都是加密的。

如果在pod中蕴含一个代理容器,你能够在Nginx pod中终止TLS。

当你比拟以后的设置时,你能够留神到,在Elasticsearch容器之前,流量始终是加密的。

以下是部署的状况:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: elasticsearch
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: elasticsearch
  template:
    metadata:
      labels:
        app.kubernetes.io/name: elasticsearch
    spec:
      containers:
        - name: elasticsearch
          image: elasticsearch:7.9.3
          env:
            - name: discovery.type
              value: single-node
            - name: network.host
              value: 127.0.0.1
            - name: http.port
              value: '9201'
        - name: nginx-proxy
          image: nginx:1.19.5
          volumeMounts:
            - name: nginx-config
              mountPath: /etc/nginx/conf.d
              readOnly: true
            - name: certs
              mountPath: /certs
              readOnly: true
          ports:
            - name: https
              containerPort: 9200
      volumes:
        - name: nginx-config
          configMap:
            name: elasticsearch-nginx
        - name: certs
          secret:
            secretName: elasticsearch-tls
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: elasticsearch-nginx
data:
  elasticsearch.conf: |
    server {
        listen 9200 ssl;
        server_name elasticsearch;
        ssl_certificate /certs/tls.crt;
        ssl_certificate_key /certs/tls.key;

        location / {
            proxy_pass http://localhost:9201;
        }
    }

让咱们来解读一下:

  • Elasticsearch在端口9201上监听localhost,而不是默认的0.0.0.0:9200(那是network.host和http.port环境变量的作用)。
  • 新的nginx-proxy容器通过HTTPS在9200端口监听,并在9201端口代理申请到Elasticsearch。(elasticsearch-tls
    secret蕴含TLS证书和密钥,例如能够用cert-manager生成)。

所以来自pod内部的申请会通过HTTPS进入9200端口的Nginx,而后转发到9201端口的Elasticsearch。

你能够通过在集群内收回HTTPS申请来确认它是否能够失常工作。

kubectl run -it --rm --image=curlimages/curl curl \
  -- curl -k https://elasticsearch:9200
{
  "name" : "elasticsearch-5469857795-nddbn",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "XPW9Z8XGTxa7snoUYzeqgg",
  "version" : {
    "number" : "7.9.3",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "c4138e51121ef06a6404866cddc601906fe5c868",
    "build_date" : "2020-10-16T10:36:16.141335Z",
    "build_snapshot" : false,
    "lucene_version" : "8.6.2",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

对于自签名的TLS证书,-k版本是必要的。在生产环境中,你须要应用可信的证书。

疾速查看日志,显示该申请通过了Nginx代理:

kubectl logs elasticsearch-5469857795-nddbn nginx-proxy | grep curl
10.88.4.127 – – [26/Nov/2020:02:37:07 +0000] “GET / HTTP/1.1” 200 559 “-” “curl/7.73.0-DEV” “-“

你也能够查看你是否无奈通过未加密的连贯连贯到Elasticsearch:

kubectl run -it --rm --image=curlimages/curl curl \
  -- curl http://elasticsearch:9200
<html>
<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<center>The plain HTTP request was sent to HTTPS port</center>
<hr><center>nginx/1.19.5</center>
</body>
</html>

你曾经强制执行了TLS,而无需接触Elasticsearch代码或容器镜像。

代理容器是一种常见的模式

在pod中增加代理容器的做法很常见,以至于它有一个名字:Ambassador模式。

这篇文章中的所有模式在谷歌的一篇优秀论文中都有详细描述。公众号后盾回复【论文】,获取论文下载地址。

增加根本的TLS反对只是一个开始。这里有一些其余的事件你能够用Ambassador模式来做:

  • 如果你想让集群中的所有流量都用TLS证书加密,你可能会在集群中的每个pod中装置一个nginx(或其余)代理。你甚至能够更进一步,应用互相TLS来确保所有的申请都是通过认证以及加密的。(这是Istio和Linkerd等服务网格应用的次要办法)。
  • 你能够应用代理来确保集中的OAuth受权通过验证jwts来认证所有申请。例如,gcp-iap-auth,它能够验证申请是否被GCP
    Identity-Aware Proxy认证。
  • 你能够通过平安隧道连贯到内部数据库。这对于那些没有内置TLS反对的数据库来说尤其不便(比方旧版本的Redis)。

多容器pod的工作原理

咱们先来理解Kubernetes上pod和容器之间的区别,以便更好地理解其底层是如何工作的。

一个传统的容器(例如由docker run启动的容器)提供了几种模式的隔离:

  • 资源隔离(如,内存限度)
  • 过程隔离
  • Filesystem和挂载隔离
  • 网络隔离

Docker还有其余一些设置,但这些是最次要的。

底层应用的工具是Linux命名空间和控制组(cgroups)。

控制组是一种用来限度资源的便捷办法,比方一个特定过程能够应用的CPU或内存。例如,你能够说你的过程应该只应用2GB的内存和4个CPU外围中的一个。

命名空间则负责隔离过程以及限度该过程能看到的货色。例如,过程只能看到与它间接相干的网络数据包,它无奈看到流经网络适配器的所有网络数据包。或者你能够隔离filesystem,让过程置信它能够拜访所有的filesystem。

从内核5.6版本开始,有八种命名空间,挂载命名空间是其中之一

有了挂载命名空间,你能够让过程认为它能够拜访主机上的所有目录,而事实上它并没有

挂载命名空间被设计为隔离资源——在本例中是filesystem。

每个过程都能够看到同一个filesystem,同时还能够与其余过程隔离

如果你须要温习一下cgroups和namespaces,这里有一篇很好的博客文章,深入探讨了一些技术细节:

https://jvns.ca/blog/2016/10/…

在Kubernetes上,容器提供了所有模式的隔离,除了网络隔离。网络隔离产生在pod层面。换句话说,一个pod中的每个容器都会有本人的filesystem、过程表等,但它们都会共享同一个网络命名空间。

让咱们来看看一个简略pod容器,以更好地理解它是如何工作的。

apiVersion: v1
kind: Pod
metadata:
  name: podtest
spec:
  containers:
    - name: c1
      image: busybox
      command: ['sleep', '5000']
      volumeMounts:
        - name: shared
          mountPath: /shared
    - name: c2
      image: busybox
      command: ['sleep', '5000']
      volumeMounts:
        - name: shared
          mountPath: /shared
  volumes:
    - name: shared
      emptyDir: {}

咱们将下面的代码段拆解一下:

  • 有两个容器,这两个容器都会沉睡一段时间。
  • 有一个emptyDir卷,它实质上是一个长期的本地卷,在pod的生命周期内继续存在。
  • emptyDir卷装置在每个pod中的/shared目录下。

你能够应用kubectl exec看到卷被挂载在第一个容器上:

kubectl exec -it podtest --container c1 -- sh

该命令将终端会话连贯到podtest pod中的容器c1。

kubectl exec的–container选项通常缩写为-c。

mount | grep shared
/dev/vda1 on /shared type ext4 (rw,relatime)

如你所见,一个卷挂载在/shared上——这就是咱们之前创立的shared卷。当初咱们来创立一些文件:

echo "foo" > /tmp/foo
echo "bar" > /shared/bar

咱们从第二个容器中查看雷同的文件。首先连贯到它:

kubectl exec -it podtest --container c2 -- sh
cat /shared/bar
bar
cat /tmp/foo
cat: can't open '/tmp/foo': No such file or directory

如你所见,在shared目录中创立的文件在两个容器上都是可用的,但/tmp中的文件却不可用。这是因为除了卷之外,容器的filesysytem之间是齐全隔离的。

当初咱们来看看网络和过程隔离。一个很好的办法是应用命令ip link来查看网络是如何设置的,它能够显示Linux零碎的网络设备。让咱们在第一个容器中执行这个命令:

kubectl exec -it podtest -c c1 -- ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
178: eth0@if179: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue
    link/ether 46:4c:58:6c:da:37 brd ff:ff:ff:ff:ff:ff

在另一个容器中执行同样的命令:

kubectl exec -it podtest -c c2 -- ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
178: eth0@if179: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue
    link/ether 46:4c:58:6c:da:37 brd ff:ff:ff:ff:ff:ff

你能够看到两个容器都有:

  • 雷同的设施eth0
  • 雷同MAC地址:46:4c:58:6c:da:37

因为MAC地址应该是全局惟一的,因而雷同的地址分明地表明,这些Pod共享同一个设施。

当初让咱们来看看网络共享的操作吧!咱们先连贯到第一个容器:

ubectl exec -it podtest -c c1 -- sh

借助nc启动一个简略的网络监听器:

nc -lk -p 5000 127.0.0.1 -e 'date'

该命令在端口5000的localhost上启动一个监听器,并向任何连贯的TCP客户端输出date命令。

那么第二个容器能够连贯到它吗?

应用以下命令在第二个容器中关上终端:

kubectl exec -it podtest -c c2 -- sh

当初你能够验证第二个容器能够连贯到该网络监听器,但不能看到nc过程:

telnet localhost 5000
Connected to localhost
Sun Nov 29 00:57:37 UTC 2020
Connection closed by foreign host

ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 sleep 5000
   73 root      0:00 sh
   81 root      0:00 ps aux

通过telnet连贯,能够看到date的输入,证实nc监听器在工作,然而ps aux(显示容器上的所有过程)基本没有显示nc。这是因为pod内的容器有过程隔离,但没有网络隔离。这就解释了Ambassador模式的工作原理:

  • 因为所有的容器都共享同一个网络命名空间,所以一个容器能够监听所有的连贯——甚至是内部的连贯。
  • 其余的容器只承受来自localhost的连贯——回绝任何内部连贯。

接管内部流量的容器就是Ambassador,因而该模式也被称为Ambassador模式。

不过有一点很要害,要记住:因为网络命名空间是共享的,所以一个pod中的多个容器不能在同一个端口监听。

让咱们来看看多容器pod的一些其余用例。

应用标准接口裸露指标

假如你曾经标准化地应用Prometheus来监控Kubernetes集群中的所有服务,但你应用的一些应用程序并没有原生导出Prometheus指标(如,Elasticsearch)。

你能在不扭转你的利用程序代码的状况下,将Prometheus指标增加到你的pod中吗?事实上,你能够,应用Adapter模式。

对于Elasticsearch的例子,让咱们在pod中增加一个 “exporter”容器,以Prometheus格局裸露各种Elasticsearch指标。

这并不艰难,因为有一个Elasticsearch的开源exporter(你还须要将相干端口增加到服务中):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: elasticsearch
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: elasticsearch
  template:
    metadata:
      labels:
        app.kubernetes.io/name: elasticsearch
    spec:
      containers:
        - name: elasticsearch
          image: elasticsearch:7.9.3
          env:
            - name: discovery.type
              value: single-node
          ports:
            - name: http
              containerPort: 9200
        - name: prometheus-exporter
          image: justwatch/elasticsearch_exporter:1.1.0
          args:
            - '--es.uri=http://localhost:9200'
          ports:
            - name: http-prometheus
              containerPort: 9114
---
apiVersion: v1
kind: Service
metadata:
  name: elasticsearch
spec:
  selector:
    app.kubernetes.io/name: elasticsearch
  ports:
    - name: http
      port: 9200
      targetPort: http
    - name: http-prometheus
      port: 9114
      targetPort: http-prometheus

一旦利用了这个性能,你就能够在9114端口找到裸露的指标:

kubectl run -it --rm --image=curlimages/curl curl \
  -- curl -s elasticsearch:9114/metrics | head
# HELP elasticsearch_breakers_estimated_size_bytes Estimated size in bytes of breaker
# TYPE elasticsearch_breakers_estimated_size_bytes gauge
elasticsearch_breakers_estimated_size_bytes{breaker="accounting",name="elasticsearch-ss86j"} 0
elasticsearch_breakers_estimated_size_bytes{breaker="fielddata",name="elasticsearch-ss86j"} 0
elasticsearch_breakers_estimated_size_bytes{breaker="in_flight_requests",name="elasticsearch-ss86j"} 0
elasticsearch_breakers_estimated_size_bytes{breaker="model_inference",name="elasticsearch-ss86j"} 0
elasticsearch_breakers_estimated_size_bytes{breaker="parent",name="elasticsearch-ss86j"} 1.61106136e+08
elasticsearch_breakers_estimated_size_bytes{breaker="request",name="elasticsearch-ss86j"} 16440
# HELP elasticsearch_breakers_limit_size_bytes Limit size in bytes for breaker
# TYPE elasticsearch_breakers_limit_size_bytes gauge

再次,你曾经可能扭转你的应用程序的行为,而无需理论扭转你的代码或容器镜像。你曾经裸露了标准化的Prometheus指标,这些指标能够被集群范畴内的工具(如Prometheus Operator应用),从而实现了应用程序和底层基础设施之间的良好拆散。

Tailing logs

接下来,咱们来看看Sidecar模式,在这一模式下你能够将容器增加到Pod,该pod能够以某些形式加强应用程序。

Sidecar模式非常通用,能够利用到不同类型的用例中。咱们接下来摸索以下sidecar的经典用例:log tailing sidecar。

在容器化环境中,最佳实际是始终将日志记录到规范输入,这样能够集中收集和汇总日志。但许多旧的应用程序被设计成日志输入到文件,而扭转这一形式并非易事。而增加一个log tailing sidecar意味着你不须要更改原有的形式也能够实现日志的集中收集和汇总。

咱们持续以Elasticsearch为例,这可能会有点顺当,因为Elasticsearch容器默认是将日志记录到规范输入的(而且让它记录到文件也不是件容易的事)。

以下是部署状况:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: elasticsearch
  labels:
    app.kubernetes.io/name: elasticsearch
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: elasticsearch
  template:
    metadata:
      labels:
        app.kubernetes.io/name: elasticsearch
    spec:
      containers:
        - name: elasticsearch
          image: elasticsearch:7.9.3
          env:
            - name: discovery.type
              value: single-node
            - name: path.logs
              value: /var/log/elasticsearch
          volumeMounts:
            - name: logs
              mountPath: /var/log/elasticsearch
            - name: logging-config
              mountPath: /usr/share/elasticsearch/config/log4j2.properties
              subPath: log4j2.properties
              readOnly: true
          ports:
            - name: http
              containerPort: 9200
        - name: logs
          image: alpine:3.12
          command:
            - tail
            - -f
            - /logs/docker-cluster_server.json
          volumeMounts:
            - name: logs
              mountPath: /logs
              readOnly: true
      volumes:
        - name: logging-config
          configMap:
            name: elasticsearch-logging
        - name: logs
          emptyDir: {}

日志配置文件是一个独自的ConfigMap,因为它太长了所以这里没有包含它。

两个容器共享雷同的volume,名为logs。Elasticsearch容器将日志写入该卷,而日志容器只是从相应的文件中读取并输入到规范输入。你能够用kubectl logs指定相应的容器来检索日志流:

kubectl logs elasticsearch-6f88d74475-jxdhl logs | head
{
  "type": "server",
  "timestamp": "2020-11-29T23:01:42,849Z",
  "level": "INFO",
  "component": "o.e.n.Node",
  "cluster.name": "docker-cluster",
  "node.name": "elasticsearch-6f88d74475-jxdhl",
  "message": "version[7.9.3], pid[7], OS[Linux/5.4.0-52-generic/amd64], JVM"
}
{
  "type": "server",
  "timestamp": "2020-11-29T23:01:42,855Z",
  "level": "INFO",
  "component": "o.e.n.Node",
  "cluster.name": "docker-cluster",
  "node.name": "elasticsearch-6f88d74475-jxdhl",
  "message": "JVM home [/usr/share/elasticsearch/jdk]"
}
{
  "type": "server",
  "timestamp": "2020-11-29T23:01:42,856Z",
  "level": "INFO",
  "component": "o.e.n.Node",
  "cluster.name": "docker-cluster",
  "node.name": "elasticsearch-6f88d74475-jxdhl",
  "message": "JVM arguments […]"
}

应用sidecar的益处是,流式传输到规范输入并不是惟一的抉择。

如果你须要切换到一个自定义的日志聚合服务,你能够只扭转sidecar容器,而无需扭转你的应用程序中任何其余货色。

其余sidecar用例

Sidecar有许多用例,日志容器只是其中一个比较简单的用例。

以下是你在其余方面可能用到的一些其余用例:

  • 实时从新加载ConfigMaps,而不须要重新启动pod
  • 将 Hashicorp Vault 中的secret注入到应用程序中
  • 将本地 Redis 实例增加到你的应用程序中,以实现低提早的内存缓存

筹备运行pod

到目前为止,本篇文章所介绍的所有多容器pod的例子都波及到多个容器同时运行。Kubernetes还提供了运行Init Containers的能力,Init Containers是在 “惯例 “容器启动之前运行实现的容器。

这容许你在你的pod正式启动之前运行一个初始化脚本。为什么你心愿你的筹备工作在一个独自的容器中运行,而不是在你的容器的entrypoint脚本中增加一些初始化?

让咱们来看看Elasticsearch的一个理论例子。Elasticsearch文档举荐在生产就绪部署中设置vm.max_map_count的sysctl设置。这在容器化环境中是有问题的,因为没有容器级的sysctl隔离,任何更改都必须产生在节点级。

在不能自定义Kubernetes节点的状况下,如何解决这个问题?

一种办法是在特权容器中运行Elasticsearch,这将使Elasticsearch可能扭转其主机节点上的零碎设置,并扭转entrypoint脚本以增加sysctls。但从平安角度来看,这将是十分危险的!如果Elasticsearch服务被入侵,攻击者将领有对其主机节点的root权限。你能够应用init container来肯定水平上升高这个危险:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: elasticsearch
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: elasticsearch
  template:
    metadata:
      labels:
        app.kubernetes.io/name: elasticsearch
    spec:
      initContainers:
        - name: update-sysctl
          image: alpine:3.12
          command: ['/bin/sh']
          args:
            - -c
            - |
              sysctl -w vm.max_map_count=262144
          securityContext:
            privileged: true
      containers:
        - name: elasticsearch
          image: elasticsearch:7.9.3
          env:
            - name: discovery.type
              value: single-node
          ports:
            - name: http
              containerPort: 9200

pod在特权init container中设置了sysctl,之后Elasticsearch容器按预期启动。

你依然在应用一个特权容器,这并不是现实状态,但至多它持续时间很短,所以攻击面要低得多。

这是Elastic Cloud Operator举荐的办法:
https://www.elastic.co/guide/…

应用特权init container为运行pod的节点做筹备是一种相当常见的模式。例如,Istio应用init container来设置每次pod运行时的iptables规定。

应用init container的另一个起因是以某种形式筹备 pod 的filesystem。一个常见的用例是secrets治理。

其余的init container用例

如果你应用相似HashicCorp Vault这样的工具来治理secrets,而不是Kubernetes secrets,你能够在一个init container中检索secrets,并将它们长久化到一个共享的emptyDir卷。

如下所示:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  labels:
    app.kubernetes.io/name: myapp
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: myapp
  template:
    metadata:
      labels:
        app.kubernetes.io/name: myapp
    spec:
      initContainers:
        - name: get-secret
          image: vault
          volumeMounts:
            - name: secrets
              mountPath: /secrets
          command: ['/bin/sh']
          args:
            - -c
            - |
              vault read secret/my-secret > /secrets/my-secret
      containers:
        - name: myapp
          image: myapp
          volumeMounts:
            - name: secrets
              mountPath: /secrets
      volumes:
        - name: secrets
          emptyDir: {}

当初secret/my-secret secret将在myapp容器的filesystem中可用。

这就是Vault Agent Sidecar Injector等零碎工作的基本思路。然而,它们在实践中相当简单(联合mutating webhooks、init container和sidecars来暗藏大部分的复杂性)。

此外,还有一些其余你可能想要应用init container的起因:

  • 你心愿数据库迁徙脚本在你的应用程序之前运行(这通常能够在一个entrypoint脚本中实现,但有时应用专用容器更容易做到这一点)。
  • 你想从S3或GCS中检索一个你的利用所依赖的大文件(为此应用一个init container有助于防止利用容器的臃肿)。

总 结

这篇文章涵盖了相当多的内容,所以这里有一个表格,列出了一些多容器模式,以及你什么时候可能要应用它们:

图片

如果你想深入研究这个问题,请务必浏览官网文档和原始容器设计模式文件:

https://kubernetes.io/docs/co…

https://static.googleusercont…


原文链接:
https://learnk8s.io/sidecar-c…

【腾讯云】轻量 2核2G4M,首年65元

阿里云限时活动-云数据库 RDS MySQL  1核2G配置 1.88/月 速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

您可能还喜欢...

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据