docker - 如何正确创建 sidecar 容器以在 kubernetes pod 中创建 SSH 隧道

标签 docker kubernetes ssh openssh

我在 AWS 中有一个数据库,需要从 Kubernetes 连接到该数据库,但该数据库中的安全设置阻止了这种情况。我的解决方案是从 Kubernetes pod 内通过 SSH 隧道连接到代理,并通过该隧道连接到 AWS 中的数据库。

但是,我不太确定如何在 Kubernetes 中实际实现这一点,因为 sidecar 容器会抛出“CrashLoopBackOff”错误。

我的 Dockerfile 非常薄。它是一个 Alpine 容器,除了复制处理隧道的 shell 脚本之外,实际上什么也不做。

Dockerfile

FROM alpine:3.14.0

COPY tunnel.sh /

RUN apk update && apk add curl \
    wget \
    nano \
    bash \
    ca-certificates \
    openssh-client

RUN chmod +x /tunnel.sh
RUN mkdir ~/.ssh

RUN ssh-keyscan -Ht ecdsa proxysql-sshtunnel.domain.com > ~/.ssh/known_hosts

CMD /bin/bash

tunnel.sh

#!/bin/bash
ssh -i /keys/sql_proxy.private -L 3306:10.0.0.229:6033 <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="fb989e958f9488bb8b89948382888a97d68888938f8e95959e97d59f94969a9295d5989496" rel="noreferrer noopener nofollow">[email protected]</a> -N

它们的 SSH key 从 Kubernetes 中的 secret 卷安装到 pod。我的部署如下所示:

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: accounts-deployment
  namespace: default
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: api-accounts
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    spec:
      containers:
      - image: gcr.io/xxxxxxxx/accounts:VERSION-2.0.6
        imagePullPolicy: Always
        name: accounts
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /tmp
          name: accounts-keys
          readOnly: true
        - mountPath: /var/www/html/var/spool
          name: mail-spool
      - image: gcr.io/xxxxxxxx/sql-proxy:latest
        imagePullPolicy: IfNotPresent
        name: sql-proxy
        args:
          - -c
          - /tunnel.sh
        command:
          - /bin/bash
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /keys
          name: keys-sql-proxy
          readOnly: true
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
      volumes:
      - name: accounts-keys
        secret:
          defaultMode: 420
          secretName: accounts-keys
      - name: spoonity-sql-proxy
        secret:
          defaultMode: 420
          secretName: spoonity-sql-proxy
      - emptyDir: {}
        name: mail-spool
status:

<--------相关部分在这里-------->

...
- image: gcr.io/xxxxxxxx/sql-proxy:latest
  imagePullPolicy: IfNotPresent
  name: sql-proxy
  args:
    - -c
    - /tunnel.sh
  command:
    - /bin/bash
  resources: {}
  terminationMessagePath: /dev/termination-log
  terminationMessagePolicy: File
  volumeMounts:
    - mountPath: /keys
      name: keys-sql-proxy
      readOnly: true
...

我从 Kubernetes 获得的唯一日志是:“/bin/bash: line 1:/tunnel.sh: No such file or directory

如果我尝试使用 docker run sql-proxy:latest/tunnel.sh 在 docker 本地运行容器,则会收到一个不同的错误,提示 key 不存在(即这正是我所期望看到的)。

不确定这个问题出在哪里。

编辑:尝试在本地重建容器并手动包含 key 。我能够成功启动容器。所以看起来这肯定是 Kubernetes 问题,但我真的不确定为什么。

最佳答案

所以问题就在这里:

volumes:
      - name: accounts-keys
        secret:
          defaultMode: 420
          secretName: accounts-keys
      - name: spoonity-sql-proxy
        secret:
          defaultMode: 420 #<----------- this is wrong
          secretName: spoonity-sql-proxy

SSH 需要特定的 key 权限才能连接。 Kubernetes 使用基于十进制的文件权限,因此此处的正确值应该是 384,这将在 Linux 中以正确的权限 0600 挂载 key 。

由于权限错误,每次脚本尝试执行都会失败并退出,触发 Kubernetes 尝试重启。

仍然不确定为什么这些日志从未生成,但我通过任意更改部署 list 中的 commandargs 来发现这一点,而不是连续 ping localhost,这样容器至少会启动:

...
 - image: gcr.io/xxxxxxxxx/sql-proxy:latest
   command: ["ping"]
   args: ["127.0.0.1"]
...

然后,我连接到正在运行的 pod,并尝试手动运行tunnel.sh 命令。现在我实际上可以了解它失败的原因,我可以修复它。

关于docker - 如何正确创建 sidecar 容器以在 kubernetes pod 中创建 SSH 隧道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68472696/

相关文章:

docker - Docker 镜像及其存储库何时会具有不同的名称?

r - 在rocker/shiny docker中部署 Shiny 的应用程序

r - 使用 Shiny Server 和 Docker 将应用程序日志输出到标准输出

mysql - Eclipse Che 中的 MySQL 运行时拒绝连接

kubernetes - 容器中的容器如何通过名称相互引用?

docker - 我们可以更新docker默认配置吗?

perl - 使用ssh时如何自动输入密码?

kubernetes - Ingress 是否与 ClusterIP 服务一起使用?

Git:如何设置 SSH key 以从第二台计算机访问我的远程存储库?

git - Bitbucket 权限被拒绝(公钥)。但适用于 ssh