目标:部署mysql服务容器并使用docker构建包含python爬虫脚本的容器采集数据到mysql数据库。
环境:Centos7、已配置Kubernetes集群及docker。
环境配置请参考以下文章:
CentOS7搭建Kubernetes集群
Kubernetes集群信息如下(虚拟机主机名和IP地址):
主机名 | IP地址 |
---|---|
master | 192.168.138.110 |
slave1 | 192.168.138.111 |
slave2 | 192.168.138.112 |
1. 安装MySQL数据库
1.1 创建 namespace
创建namespace,用于部署mysql,使其与其他应用程序隔离
kubectl create namespace dev
1.2 创建持久卷 PV
1)创建PV(持久数据卷),用于存储mysql数据文件
mdir -p /nfs/data/01
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
3)创建PV对象
kubectl create -f mysql-pv.yaml
4)查看创建结果
kubectl get pv
kubectl describe pv pv-1gi
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
2)创建此PVC对象
kubectl create -f mysql-pvc.yaml
3)查看创建结果
kubectl get pvc -n dev
可以看到,mysql-pvc对象已经和pv-1gi对象绑定。
1.4 创建Secret对象以保存mysql的root用户密码
1)执行创建命令,并将密码设置为 123456
kubectl create secret generic mysql-root-password --from-literal=password=123456 -n dev
2)查看创建结果
kubectl get secret -n dev
kubectl get secret mysql-root-password -n dev -o yaml
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
2)创建mysql-svc
kubectl create -f mysql-svc.yqml
3)查看创建结果
kubectl get pod, svc -n dev
2. 设置mysql数据库远程连接
2.1 进入容器设置远程连接
1)进入容器
kubectl exec -it mysql /bin/bash -n dev
2)登录mysql
mysql -u root -p
123456
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)
4)创建mydb库并授权给root用户
mysql> create database mydb;
mysql> grant all privileges on mydb.* to 'root'@'%';
flush privileges;
5)使用可视化软件进行远程连接
查看mysql
部署在集群的哪个节点上
kubectl get service -n dev -o wide
在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));
2)查看表
show tables;
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)
注:
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
如果脚本执行出现异常则将异常信息追加到
/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
此处包含了两层调度,crond
命令定时调度script.sh
脚本,script.sh
脚本又调度了python爬虫
脚本。
注:这三个文件要放在同一级目录下,方便后续的镜像构建。
3.2 创建镜像
利用Dockerfile构建镜像
docker build -t docker-crond .
创建完成后如下:
3.3 执行脚本
1)进入容器内部
创建docker-crond
容器并进入容器内部
docker run -it docker-crond /bin/bash
2)配置定时任务
设定时程表
crond
crontab -e
添加内容如下:
*/5 * * * * /script.sh >> /var/log/cron.log 2>&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;
4. docker commit构建镜像并推送到镜像仓库
1)查看容器
docker ps
2)将指定容器构建成为镜像
docker commit dreamy_sammet registry.cn-hangzhou.aliyuncs.com/hadooptian/docker-crond:v1
注:要根据特定格式打标签即
registry.cn-hangzhou.aliyuncs.com/用户名/镜像名称:版本号
3)查看构建完成的镜像
docker images
4)登录阿里云镜像仓库
docker login --username=hadooptian registry.cn-hangzhou.aliyuncs.com
5)推送镜像
docker push registry.cn-hangzhou.aliyuncs.com/hadooptian/docker-crond:v1
6)到阿里云仓库查看
可以看到,构建的镜像已经被推送到阿里云镜像仓库中了。
至此,基于容器和集群技术的数据自动化采集设计和实现项目完成。