K8S有状态静态Pod经典示例

研究K8S有一阵子了,这个东西很好用,但是也有很多坑,个人觉得很多地方还有待改进,K8S的静态Pod是一个利器,但也必须对它有全面的了解才能运作。
今天给大家示例一个从头到尾自己研究出来的项目,需要一定的基础,抛砖引玉,大家学会了可以自己去发挥。
K8S最大作用是面向集群业务型的和面向研发CI/CD,我这个例子偏向CI/CD。
步入正题:
环境:
1,首先,你得至少已经搭建了单节点的K8S平台;
2,会熟悉的部署Dockerfile;
3,   会K8S基本的命令操作;
4,对K8S基本运作有比较清晰的认识,不然排错是一个很大的障碍;

项目说明:
在上K8S之前各种计划任务,比如,定时备份,定时重启,定时检索日志发送邮件等等都是通过一台CentOS虚拟机的crontab来执行各种shell,python脚本来完成。

但是虚拟机也有因为停电,硬件故障导致系统崩溃的风险,所以,将这台虚拟机容器化并迁移至K8S内就健壮多了。
只要镜像在,并且K8S编排脚本在,那么一切都在,并且健康的运行,非常可靠。

最重要的,我需要将所有的管理脚本外置于外部NAS存储,并且挂载到K8S容器内,来达到数据持久化和代码集中化管理,

并且,我不需要登入容器,只需要在外部修改好crontab文件,删除掉当前pod,K8S会很乖的重新起一个容器,顺便加载了最新的crontab配置,巧妙利用K8S的特性来简化管理。

不废话,上干货,首先,需要把一切需要的东西封装到centos镜像中:
1,我需要在容器内执行python脚本,而且需要3以上的版本;
2,我需要shell执行远程ssh,那么需要安装sshpass;(当然你也可以选择其他方式)
3,我需要expect工具免交互脚本,那么需要安装expect;

4, 因为容器默认是没有安装crontab的,要做任务计划怎么能少了这个;

5,最重要的是安装supervisor进程守护管理工具,以免K8S的容器循环重启;(原理不作解释)


可能有一些不必要的插件,自己去优化吧,这里达到实验目的即可,没有做镜像大小优化,
贴上Dockerfile源码:

FROM      centos:centos7.6.1810
MAINTAINER gavin.guo<[email protected]>
ENV TZ "Asia/Shanghai"
ENV TERM xterm
ENV LANG en_US.utf8
ADD aliyun-mirror.repo /etc/yum.repos.d/CentOS-Base.repo
ADD aliyun-epel.repo /etc/yum.repos.d/epel.repo
RUN yum install -y zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap
-devel xz-devel && \
    yum install -y curl wget tar bzip2 unzip vim-enhanced passwd  yum-utils hostname net-tools rsync man && \
    yum install -y gcc gcc-c++ git make automake cmake patch logrotate python-devel libpng-devel libjpeg-devel && \
    yum clean all
ADD Python-3.6.2.tgz  /root
RUN cd /root/Python-3.6.2/  && \
    mkdir /usr/local/python3 ; ./configure --prefix=/usr/local/python3 && \
    make && make install && \
    ln -s /usr/local/python3/bin/python3 /usr/bin/python3 ; ln -s /usr/local/python3/bin/pip3 /usr/bin/pip3 && \
    cd /root ; rm -rf Python-3.6.2 && \
    yum -y install net-snmp-utils crontabs sshpass expect ; sed -i 's/required   pam_loginuid.so/sufficient   pam_loginuid.so/' /etc/pam.d/crond && \
    pip3 install supervisor && \
    mkdir -p /etc/supervisor.conf.d && \
    mkdir -p /var/log/supervisor
COPY supervisord.conf /etc/supervisord.conf
COPY supervisor_crontab.conf /etc/supervisor.conf.d/crontab.conf
EXPOSE 22
COPY start.sh /root/start.sh
RUN chmod +x /root/start.sh
ENTRYPOINT ["/root/start.sh"]

Dockefile 同目录下,需要放置python3.6的二进制源码安装包,防止版本漂移和加快构建速度,和启动脚本start.sh

#! /bin/bash
cp /root/script/root -f  /var/spool/cron/
/usr/local/python3/bin/supervisord -n -c /etc/supervisord.conf

这个小小的脚本一行都不能少,少了第一行,那么K8S在启动Pod的时候会报错,因为找不到shell的执行路径;

第二行用来每次启动新的Pod的时候加载最新的crontab文件,而不需要操作pod容器;

第三行,启动supervisord,保证pod健康运行而不退出;

crontab的supervisord的启动配置文件贴一下:

[program:crond]
directory=/
command=/usr/sbin/crond -n
user=root
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/%(program_name)s.log
stderr_logfile=/var/log/supervisor/%(program_name)s.log

使用命令开始封装镜像:

docker build -t  gavin/mycron:v1 .

封装完成后,开始编写K8S编排文件:

创建一个mycron.yaml文件:

apiVersion: v1
kind: Pod
metadata:
  name: mycron
spec:
  containers:
  - name: mycron
    image: gavin/mycron:v1
    ports:
    - containerPort: 22
    volumeMounts:
    - name: script
      mountPath: /root/script
  volumes:
  - name: script
    hostPath:
      path: /root/K8S_PV/script
      type: DirectoryOrCreate

代码很简单,但我们重点看主机磁盘卷的挂载,这里虽然用的是hostPath,但是/root/K8S_PV/Script并不是普通的本地路径,而是我挂载到本地的NAS共享文件夹:

注意:

使用命令将配置好的NAS共享文件挂载到K8S宿主机内,并用hostPath的方式将其映射到master节点的Pod内,这个是官方教程和权威指南里面都没有说过的,不是亲身实验是无从得知的,但理论和实际上都是可行的;

讲操作:

挂载NAS共享文件夹:

mount -o username=XXX,password=XXX //NAS服务器的IP/K8S_PV   /root/K8S_PV

K8S允许挂载NFS的PV,但是遇上NAS是有权限验证的,有权限验证的NFS如何引入PV,  官方和网上都没有资料,这也是我说它为什么需要改进的,不能都要求用户去单独搭一个NFS服务器吧!

而且对于小型存储需求来讲,PV和PVI这一套显得繁琐,没有本地直接挂载然后hostPath简单粗暴好用。

挂载完毕后,然后在K8S_PV里面新建一个目录script,将所有脚本丢进去即可;


将mycron.yaml文件复制到目录/etc/kubernetes/manifests/, K8S会自动启动静态Pod;

图片.png

那么我们进入容器内看看是否一切正常:

kubectl exec -it mycron-master  /bin/bash
运行crontab -e

发现定时任务配置已经顺利同步:

图片.png

并且脚本路径顺利加载至pod:

图片.png

以后我们需要修改定时任务或者脚本,只需要在NAS服务器上修改下文件,删除一下Pod即可,非常快捷方便,并且做到高可用,高可靠,集中化管理。


个人认为非常经典的一个实验,实践了以下内容:

1,静态Pod的创建;

2,hostPath存储的挂载,外部NAS存储的巧妙引用;

3,测试了静态Pod的特性;

4,Docker镜像的封装, 关键点还在于入口脚本的设置,

     一般来说,通畅Dockerfile的最后一行为:

 ENTRYPOINT ["/usr/local/python3/bin/supervisord" ,"-n","-c" "/etc/supervisord.conf"]

 这个是supervisord的启动进程命令,但是很多时候并不是这么简单,可能在容器启动的时候有很多初始化的复杂操作,那么全部放入一个start脚本里面去执行,并且保证supervisord在最后执行即可;

就像本例,我需要在启动进程前将挂载存储路径里面的配置文件更新到相应的目录,来达到重起容器即更新配置的目的,那么非脚本不可。


学会了吗?试试看,打造你的私有镜像并且使用启动脚本来更新容器,可能更有妙用。

猜你喜欢

转载自blog.51cto.com/kingda/2435923