• 基于容器和集群技术的数据自动化采集设计和实现


    目标:部署mysql服务容器并使用docker构建包含python爬虫脚本的容器采集数据到mysql数据库。

    环境:Centos7、已配置Kubernetes集群及docker。

    环境配置请参考以下文章:
    CentOS7搭建Kubernetes集群

    Kubernetes集群信息如下(虚拟机主机名和IP地址):

    主机名IP地址
    master192.168.138.110
    slave1192.168.138.111
    slave2192.168.138.112

    1. 安装MySQL数据库

    1.1 创建 namespace

    创建namespace,用于部署mysql,使其与其他应用程序隔离

    kubectl create namespace dev
    
    • 1

    1.2 创建持久卷 PV

    1)创建PV(持久数据卷),用于存储mysql数据文件

    mkdir -p /nfs/data/01
    
    • 1

    2)编写msql-pv.yaml文件,内容如下:

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv-1gi
    spec:
      capacity:
        storage: 1Gi
      accessModes:
        - ReadWriteMany
      storageClassName: nfs
      nfs:
        path: /nfs/data/01
        server: 192.168.138.110
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3)创建PV对象

    kubectl create -f mysql-pv.yaml
    
    • 1

    4)查看创建结果

    kubectl get pv
    kubectl describe pv pv-1gi
    
    • 1
    • 2

    在这里插入图片描述

    1.3 创建持久卷声明 PVC

    1)编写mysql-pvc.yaml文件,文件内容如下:

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: mysql-pvc
      namespace: dev
    spec:
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 1Gi
      storageClassName: nfs
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2)创建此PVC对象

    kubectl create -f mysql-pvc.yaml
    
    • 1

    3)查看创建结果

    kubectl get pvc -n dev
    
    • 1

    在这里插入图片描述

    可以看到,mysql-pvc对象已经和pv-1gi对象绑定。

    1.4 创建Secret对象以保存mysql的root用户密码

    1)执行创建命令,并将密码设置为 123456

    kubectl create secret generic mysql-root-password --from-literal=password=123456 -n dev
    
    • 1

    2)查看创建结果

    kubectl get secret -n dev
    kubectl get secret mysql-root-password -n dev -o yaml
    
    • 1
    • 2

    在这里插入图片描述

    1.5 创建Service

    1)编辑mysql-svc.yaml文件,内容如下:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: mysql
      name: mysql
      namespace: dev
        spec:
          containers:
          - image: mysql:8.0
            name: mysql
            env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-root-password
                  key: password
            ports:
            - containerPort: 3306
    ---
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        app: svc-mysql
      name: svc-mysql
      namespace: dev
    spec:
      selector:
        app: mysql
      type: NodePort
      ports:
      - port: 3306
        protocol: TCP
        targetPort: 3306
        nodePort: 31233
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    2)创建mysql-svc

    kubectl create -f mysql-svc.yqml
    
    • 1

    3)查看创建结果

    kubectl get pod, svc -n dev
    
    • 1

    在这里插入图片描述

    2. 设置mysql数据库远程连接

    2.1 进入容器设置远程连接

    1)进入容器

    kubectl exec -it mysql /bin/bash -n dev
    
    • 1

    2)登录mysql

    mysql -u root -p
    	123456
    
    • 1
    • 2

    在这里插入图片描述

    3)配置root用户可远程连接

    mysql> ALTER USER root@localhost IDENTIFIED WITH mysql_native_password BY '123456';
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> ALTER USER root@'%' IDENTIFIED WITH mysql_native_password BY '123456';
    Query OK, 0 rows affected (0.01 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4)创建mydb库并授权给root用户

    mysql> create database mydb;
    
    mysql> grant all privileges on mydb.* to 'root'@'%';
    flush privileges;
    
    • 1
    • 2
    • 3
    • 4

    5)使用可视化软件进行远程连接

    查看mysql部署在集群的哪个节点上

    kubectl get service -n dev -o wide
    
    • 1

    在这里插入图片描述

    在navicat新键连接,使用slave2的IP地址和映射端口即192.168.138.112:31233

    在这里插入图片描述

    测试连接

    在这里插入图片描述

    注:若是连接失败,使用命令kubectl get pods -n kube-system获取pod名称查看coredns的状态,若为CrashLoopBackOff(这是因为每次挂机再启动之后,/etc/resolv.conf主机下的nameserver都被修改为8.8.8.8和114.114.114.114),则需要进行如下修改:

    将nameserver 修改为master主机的ip(三台主机都修改)

    vim /etc/resolv.conf

    在这里插入图片描述

    在这里插入图片描述

    修改成功后,再删除异常coredns的两个pod即可,通过 kubectl get pods -n kube-system获取pod名称。

    删除成功之后k8s会自动创建两个coredns。

    再通过 kubectl get pods -n kube-system查看coredns的状态,状态是running的时候,java-web和k8s配置的数据库就可以访问了。

    在这里插入图片描述

    2.2 建表

    1)在数据库mydb中建product_info

    # 切换数据库
    use mydb	
    # 建product_info表
    CREATE TABLE product_info(	
    product_name varchar (1000)
    , supplier varchar (1000)
    , supplier_web varchar (1000)
    , product_desc varchar (1000)
    ,product_img varchar (1000)
    , product_price varchar (1000)
    , addr varchar (1000)
    , mailing_ins varchar (1000));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    2)查看表

    show tables;
    
    • 1

    在这里插入图片描述

    3. 采集数据存入数据库

    3.1 创建定时任务Dockerfile及脚本

    1)创建爬虫脚本

    vim mysql.sh

    #!/usr/bin/env python
    # coding: utf-8
    
    # In[1]:
    
    
    
    import urllib.request
    from time import sleep
    from bs4 import BeautifulSoup as bs
    from urllib.parse import urljoin
    import pymysql
    
    
    # In[2]:
    
    
    headers = {
        'User-Agent': 'Mozilla/6.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'
    }
    
    
    # In[3]:
    
    
    def get_info(page):
        url='https://www.cnhnb.com/p/mianfen-0-0-0-0-{}/'.format(page)
        req = urllib.request.Request(url, headers=headers)
        html = urllib.request.urlopen(req)
        soup = bs(html.read(), 'html.parser')
        lu = soup.find_all('div',class_='show-ctn')
        product_all=[]
        for i in lu:
            product_name=i.find('h2').get_text()#产品名称
            supplier=i.find("a").get_text()#供应商
            supplier_web=i.find("a").attrs['href']#供应商网址
            product_desc=i.find('div',class_='shop-image').img.attrs['alt']#产品介绍
            product_img=i.find('div',class_='shop-image').img.attrs['src']#产品图片
            product_price=str(i.find('div',class_='shops-price').get_text()).strip().replace('\n','').replace(' ','')#产品价格
            addr=str(i.find('div',class_='r-shop-btm').get_text())#发货地
            mailing_ins=str(i.find('div',class_='cw-tags').get_text()).strip().replace('\n','').replace(' ','')#邮寄说明
            product=[product_name,supplier,supplier_web,product_desc,product_img,product_price,addr,mailing_ins]
            product_all.append(product)
        return product_all
    
    
    # In[12]:
    
    
    def save_mysql(all_data):
        conn = pymysql.connect(host='192.168.138.112', user='root', port=31233, password='123456', db='mydb', charset='utf8')
        curson = conn.cursor()
        # 创建表sql语句
        #ctablesql = 'CREATE TABLE product_info(product_name varchar (1000), supplier varchar (1000), supplier_web varchar (1000), product_desc varchar (1000),product_img varchar (1000), product_price varchar (1000), addr varchar (1000), mailing_ins varchar (1000))'
        #curson.execute(ctablesql)
        # 插入数据SQL语句
        insertsql = 'insert into product_info(product_name,supplier,supplier_web,product_desc,product_img,product_price,addr,mailing_ins) value (%s,%s,%s,%s,%s,%s,%s,%s)'
        for data in all_data:
            data = tuple(data)
            curson.execute(insertsql, data)
        conn.commit()
    
    
    # In[13]:
    
    
    if __name__ == '__main__':
        for i in range(1,89):
            all_data=get_info(i)
            save_mysql(all_data)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    注:save_mysql函数conn = pymysql.connect(host='192.168.138.112', user='root', port=31233, password='123456', db='mydb', charset='utf8')语句中的host要更改为自己mysql服务容器部署的那个节点。

    2)创建执行脚本

    vim script.sh

    python3 /mysql.py >> /var/log/cron.log 2>&1
    
    • 1

    如果脚本执行出现异常则将异常信息追加到/var/log/cron.log文件中。

    3)创建定时任务脚本

    vim Dockerfile

    内容如下:

    FROM centos:7
    RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
    RUN curl -o /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo
    RUN yum makecache fast;
    RUN yum -y update && \
        yum -y install cronie.x86_64
    
    RUN yum install python3-devel python3-pip -y
    RUN pip3 install -i https://pypi.douban.com/simple pymysql
    RUN pip3 install -i https://pypi.douban.com/simple Beautifulsoup4
    
    
    COPY ./script.sh /script.sh
    COPY ./mysql.py /mysql.py
    RUN chmod +x /script.sh
    RUN chmod +x /mysql.py
    
    CMD crond
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    此处包含了两层调度,crond命令定时调度script.sh脚本,script.sh脚本又调度了python爬虫脚本。

    注:这三个文件要放在同一级目录下,方便后续的镜像构建。

    3.2 创建镜像

    利用Dockerfile构建镜像

    docker build -t docker-crond .
    
    • 1

    创建完成后如下:

    在这里插入图片描述

    3.3 执行脚本

    1)进入容器内部

    创建docker-crond容器并进入容器内部

    docker run -it docker-crond /bin/bash
    
    • 1

    2)配置定时任务

    设定时程表

    crond
    
    • 1
    crontab -e
    
    • 1

    添加内容如下:

    */5 * * * * /script.sh >> /var/log/cron.log 2>&1
    
    • 1

    在这里插入图片描述

    注:2>&1是一个重定向操作符,用于将标准错误(文件描述符2)重定向到标准输出(文件描述符1)。

    之后保存退出,脚本就会自动执行。

    在这里插入图片描述

    crond是linux下用来周期性的执行某种任务或等待处理某些事件的一个守护进程,与windows下的计划任务类似,当安装完成操作系统后,默认会安装此服务工具,并且会自动启动crond进程,crond进程每分钟会定期检查是否有要执行的任务,如果有要执行的任务,则自动执行该任务。

    crontab 是用来让使用者在固定时间或固定间隔执行程序之用,换句话说,也就是类似使用者的时程表。

    3.4 查看结果

    因为脚本设定是每5分钟执行一次,一共执行两次,所以10分钟后查看。

    在这里插入图片描述

    可以看到据容器运行已经11分钟,进入到navicat查看表内容

    select count(1) from product_info;
    
    select * from product_info;
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    在这里插入图片描述

    4. docker commit构建镜像并推送到镜像仓库

    1)查看容器

    docker ps 
    
    • 1

    在这里插入图片描述

    2)将指定容器构建成为镜像

    docker commit dreamy_sammet registry.cn-hangzhou.aliyuncs.com/hadooptian/docker-crond:v1
    
    • 1

    注:要根据特定格式打标签即registry.cn-hangzhou.aliyuncs.com/用户名/镜像名称:版本号

    在这里插入图片描述

    3)查看构建完成的镜像

    docker images
    
    • 1

    在这里插入图片描述

    4)登录阿里云镜像仓库

    docker login --username=hadooptian registry.cn-hangzhou.aliyuncs.com
    
    • 1

    在这里插入图片描述

    5)推送镜像

    docker push registry.cn-hangzhou.aliyuncs.com/hadooptian/docker-crond:v1
    
    • 1

    在这里插入图片描述

    6)到阿里云仓库查看

    在这里插入图片描述

    可以看到,构建的镜像已经被推送到阿里云镜像仓库中了。

    至此,基于容器和集群技术的数据自动化采集设计和实现项目完成。

  • 相关阅读:
    2023年【河北省安全员B证】新版试题及河北省安全员B证试题及解析
    Spring的创建和使用
    JVM面试题总结
    软件架构模式
    【云原生之Docker实战】使用docker部署ubuntu系统测试环境
    Linux--网络编程-字节序
    全量知识系统问题及SmartChat给出的答复 之18 生存拓扑控制+因子分析实现自然语言处理中的特征提取及语义关联
    STM32基于hal库的adc以DMA的多通道采样以及所遇问题解决
    2.1 Redis中SDS的定义
    一文带你吃透阻塞队列
  • 原文地址:https://blog.csdn.net/weixin_61307261/article/details/136285021