docker - 如何正确创建边车容器以在 kubernetes pod 中创建 SSH 隧道
问题描述
我在 AWS 中有一个需要从 Kubernetes 连接的数据库,但该数据库中的安全设置阻止了这种情况。我的解决方案是从 Kubernetes pod 内通过 SSH 隧道连接到代理,并通过它连接到 AWS 中的数据库。
但是,我不太确定如何在 Kubernetes 中真正实现这一点,因为边车容器会抛出“CrashLoopBackOff”错误。
我的 Dockerfile 很薄。它是一个高山容器,除了复制一个处理隧道的 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
隧道.sh
#!/bin/bash
ssh -i /keys/sql_proxy.private -L 3306:10.0.0.229:6033 centos@proxysql-sshtunnel.domain.com -N
它们的 SSH 密钥从 Kubernetes 中的秘密卷安装到 pod。我的部署如下所示:
部署.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 在本地运行容器docker run sql-proxy:latest /tunnel.sh
,则会收到一个不同的错误,抱怨密钥不存在(这正是我期望看到的)。
不知道这个问题出在哪里。
编辑:尝试在本地重建容器并手动包含密钥。我能够成功启动容器。所以看起来这绝对是一个 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 需要特定的密钥权限才能连接。Kubernetes 使用基于十进制的文件权限,所以这里的正确值应该是384,这将在 Linux 中以正确的权限 0600 挂载密钥。
因为权限错误,每次脚本尝试执行都会失败退出,触发Kubernetes尝试重启。
仍然不确定为什么从未生成这些日志,但我通过在我的部署清单中任意更改command
and来发现这一点,args
而不是连续 ping localhost,这样容器至少会启动:
...
- image: gcr.io/xxxxxxxxx/sql-proxy:latest
command: ["ping"]
args: ["127.0.0.1"]
...
然后我连接到正在运行的 pod,并尝试手动运行 tunnel.sh 命令。现在我可以真正了解它失败的原因,我可以修复它。
推荐阅读
- python - 通过 Gmail API 将 CSV 文件转换为 Pandas df
- c++ - 在谈论 ADT 时,表示和实现之间是否有区别?表示如何与“接口”相关联?
- properties - Xquery 从 .properties 文件中提取属性值
- matlab - Matlab 3D按H然后S然后V排序
- java - 如何指定 ToolProvider.getSystemJavaCompiler() 的工作目录以允许 -classpath 选项中的相对路径?
- r - 创建 R 包时,如何包含安装时显示的警告?有方便的 roxygen2 标签吗?
- bash - 不能在 grep 上使用过滤器来搜索包括字符串在内的所有路径
- numpy - Numpy:如何生成特定的数组(迭代器会更好)
- docker - Hyperledger Fabric 的创建和加入频道错误 WARN 001 Failed Loading ClientOU 证书
- android - 在 CarouselView 自定义渲染器中添加什么来摆脱 Xamarin Forms 中的键盘问题