0、导
众所周知,pod本身可能会因为各种原因被重启,重启之后手动执行的修改就会被重置。比如,重启之后,手动使用influx命令修改的数据保留策略将会被重置为永久保存。
也就是说,如果我希望influxdb pod的数据保留策略一直是一个特定的时间(比如三个月),那就需要pod在每次启动前设置一次数据保留策略,也就是启动前执行特定命令。
1、操作尝试
1.1 报错permission denied
shell + configmap + command
首先将要执行的命令写成shell脚本的形式,将shell脚本作为configmap挂载到pod中,使用pod的command参数来执行该脚本
kind: ConfigMap
apiVersion: v1
metadata:
name: influxdb-alter-retention-sh
namespace: influxdb
labels:
app: influxdb
data:
alter_retention_policy.sh: |
#!/bin/sh
influx -username "telegraf" -password "XXXXXXXXX" -execute 'alter retention policy "autogen" on "telegraf" duration 90d replication 1 default'
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: influxdb-deployment
namespace: influxdb
labels:
app: influxdb
spec:
replicas: 1
selector:
matchLabels:
app: influxdb
template:
metadata:
labels:
app: influxdb
spec:
containers:
- name: influxdb
image: influxdb:1.8.3
imagePullPolicy: IfNotPresent
ports:
- containerPort: 60000
name: metrics
- containerPort: 8086
name: http-api
- containerPort: 8088
name: backup
command: ["./conf/alter_retention_policy.sh"]
volumeMounts:
- name: influxdb-data-pvc
mountPath: /var/lib/influxdb/
- name: influxconf
mountPath: /etc/influxdb/
- name: influxdb-alter-retention-sh
mountPath: /conf/alter_retention_policy.sh
subPath: alter_retention_policy.sh
volumes:
- name: influxdb-data-pvc
persistentVolumeClaim:
claimName: influxdb-data-pvc
- name: influxconf
configMap:
name: influxdb-config
- name: influxdb-alter-retention-sh
configMap:
name: influxdb-alter-retention-sh
结果,apply资源清单之后报错
permission denied
,如下,看报错我们也知道原因是脚本没有执行权限导致报错。
Error: failed to start container "influxdb": Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: "./conf/alter_retention_policy.sh":permission denied
": unknown
所以需要给configmap加上
defaultMode
属性:
volumes:
configMap:
# 因为我是用的是 1.15.2 版本的k8s,所以defaultMode的值范围是0-0777
defaultMode: 0755
name: influxdb-alter-retention-sh
└─╼ $kubectl explain deployments.spec.template.spec.volumes.configMap.defaultMode
KIND: Deployment
VERSION: extensions/v1beta1
FIELD: defaultMode <integer>
DESCRIPTION:
Optional: mode bits to use on created files by default. Must be a value
between 0 and 0777. Defaults to 0644. Directories within the path are not
affected by this setting. This might be in conflict with other options that
affect the file mode, like fsGroup, and the result can be other mode bits
set.
1.2 报错127.0.0.1:8086: connect: connection refused
待configmap脚本的属性修改完成之后,重新apply资源清单,得到报错
Failed to connect to http://localhost:8086: Get http://localhost:8086/ping: dial tcp 127.0.0.1:8086: connect: connection refused Please check your connection settings and ensure 'influxd' is running.
因为pod使用的是influxdb的镜像,influxd
没找到,意思就是守护进程没启动喽。这是啥情况?
kubernetes.io文档说明,
如果在配置文件中指定了容器启动时要执行的命令以及参数,那么容器镜像中自带的命令与参数将会被覆盖掉而不再执行
。以上解释说明了报错的原因,因为通过资源清单的command字段指定了容器启动时要执行的命令,所以就覆盖掉了容器镜像本身的启动命令(也就是Dockerfile的CMD/ENTRYPOINT指令)。所以influxdb的守护进程没有被启动,自然也就没有地方去执行influx命令了。
1.3 解决问题
既然覆盖掉了Dockerfile的启动命令,我第一反应是定制化一个镜像,通过官方的Dockerfile修改CMD指令,将我们想要执行的命令在Dockerfile指定,这样不就不会产生谁覆盖谁的问题了嘛?
可是当我把这个问题推迟了一会儿之后我又发现,都是执行多条命令,我为啥还要再去定制化镜像一遍,何不直接通过k8s资源清单的command来执行被覆盖掉的Dockerfile启动命令呢?emmmm,好像是个解决办法!整!
有了解决,那就去扒一下influxdb的Dockerfile启动命令是啥吧。喏,地址在这里了。
FROM buildpack-deps:stretch-curl
RUN set -ex && \
mkdir ~/.gnupg; \
echo "disable-ipv6" >> ~/.gnupg/dirmngr.conf; \
for key in \
05CE15085FC09D18E99EFB22684A14CF2582E0C5 ; \
do \
gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys "$key" ; \
done
ENV INFLUXDB_VERSION 1.8.10
RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" && \
case "${dpkgArch##*-}" in \
amd64) ARCH='amd64';; \
arm64) ARCH='arm64';; \
armhf) ARCH='armhf';; \
armel) ARCH='armel';; \
*) echo "Unsupported architecture: ${dpkgArch}"; exit 1;; \
esac && \
wget --no-verbose https://dl.influxdata.com/influxdb/releases/influxdb_${INFLUXDB_VERSION}_${ARCH}.deb.asc && \
wget --no-verbose https://dl.influxdata.com/influxdb/releases/influxdb_${INFLUXDB_VERSION}_${ARCH}.deb && \
gpg --batch --verify influxdb_${INFLUXDB_VERSION}_${ARCH}.deb.asc influxdb_${INFLUXDB_VERSION}_${ARCH}.deb && \
dpkg -i influxdb_${INFLUXDB_VERSION}_${ARCH}.deb && \
rm -f influxdb_${INFLUXDB_VERSION}_${ARCH}.deb*
COPY influxdb.conf /etc/influxdb/influxdb.conf
EXPOSE 8086
VOLUME /var/lib/influxdb
COPY entrypoint.sh /entrypoint.sh
COPY init-influxdb.sh /init-influxdb.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["influxd"]
从 Dockerfile 中可以看到,既有ENTRYPOINT又有CMD指令
。Dockerfile的CMD和ENTRYPOINT什么区别呢?可以看下这篇文章就能弄懂。这里不再赘述它们的区别了,直接上结论:该 influxdb 的 Dockefile 同时使用了 CMD 和 ENTRYPOINT,此时ENTRYPOINT是 exec 模式,CMD 指定的内容则会被追加为 ENTRYPOINT 指定命令的参数。也就是说该镜像的启动命令是 /entrypoint.sh influxd
。如果你再细看一下上边 Dockerfile 官方地址的目录结构,翻看一下entrypoint.sh的内容就知道它会检测influxd
是否被作为了$1参数
(shell语法,位置参数
),如果跟了就会去执行另外一个脚本init-influxdb.sh
Tips:
"${@:2}" 也是shell的用法,如下示例
#!/bin/bash
echo ${@:2}
variable=${@:3}
echo $variable
-------------------------------
示例运行:
./ex.bash 1 2 3 4 5
2 3 4 5
3 4 5
所以,基于以上判断。那我们使用k8s的command参数覆盖Dockerfile参数的时候,需要执行该
/entrypoint.sh influxd
命令,如下:
# 仅贴出来重要的部分
kind: ConfigMap
apiVersion: v1
metadata:
name: influxdb-alter-retention-sh
namespace: influxdb
labels:
app: influxdb
data:
# -------------------------------- #
# 重点一 是这里的shell脚本,执行influx命令修改数据保留策略
# -------------------------------- #
alter_retention_policy.sh: |
#!/bin/sh
influx -username "telegraf" -password "xxxxxxxx" -execute 'alter retention policy "autogen" on "telegraf" duration 90d replication 1 default'
---
......
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: influxdb-deployment
namespace: influxdb
labels:
app: influxdb
spec:
replicas: 1
selector:
matchLabels:
app: influxdb
template:
metadata:
labels:
app: influxdb
spec:
containers:
- name: influxdb
image: influxdb:1.8.3
imagePullPolicy: IfNotPresent
ports:
- containerPort: 60000
name: metrics
- containerPort: 8086
name: http-api
- containerPort: 8088
name: backup
# -------------------------------- #
# 重点二 是这里的 command 和 args 字段,需要将被覆盖的Dockerfile启动命令在这里执行
# -------------------------------- #
command: ["/bin/sh","-c"]
args: ["/entrypoint.sh influxd; ./conf/alter_retention_policy.sh"]
volumeMounts:
- name: influxdb-data-pvc
mountPath: /var/lib/influxdb/
- name: influxconf
mountPath: /etc/influxdb/
- name: influxdb-alter-retention-sh
mountPath: /conf/alter_retention_policy.sh
subPath: alter_retention_policy.sh
volumes:
- name: influxdb-data-pvc
persistentVolumeClaim:
claimName: influxdb-data-pvc
- name: influxconf
configMap:
name: influxdb-config
- name: influxdb-alter-retention-sh
configMap:
defaultMode: 0755
name: influxdb-alter-retention-sh
在上边的资源清单中,command 和 args 指令指定了两条pod启动命令,分别是
/entrypoint.sh influxd
和./conf/alter_retention_policy.sh
使用 command 和 args 字段指定多条命令的exec模式写法如下:
command: ["/bin/sh","-c"]
args: ["command one; command two && command three"]
1.4 验证环节
经过 1.3 的解决问题环节,这里验证一下是否成功实现了
influxdb pod启动时修改数据备份策略
的目的
由图已经看到influxdb pod在启动时,数据备份策略已经被修改为了3个月的时间,成功实现
2、总结
通过本次实现 Influxdb Pod 启动修改默认数据保留策略为90天的过程,有这么几个小知识点和错误总结一下。
2.1
挂载到 Pod 内的文件如果需要可执行,需要修改 defaultMode 字段为相应值,比如我这里 1.15.2 版本的 0755。
2.2
Dockerfile 的 ENTRYPOINT 和 CMD有exec模式和shell模式,exec模式写法是中括号[]
,比如ENTRYPOINT ["COMMAND 1"]
,关于 Dockerfile 中 CMD 和 ENTRYPOINT 的复杂覆盖情况可见官方下图,一览各种情况
2.3
如果在 Pod 配置文件()中指定了容器启动时要执行的命令以及参数,那么容器镜像中(Dockerfile CMD ENTRYPOINT)自带的命令与参数将会被覆盖掉而不再执行
2.5
shell位置参数回顾