Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 
 

18 KiB

本次实验源代码来自:https://github.com/greyli/albumy
demo网站:http://59.110.70.81:5000 或者http://106.75.223.107:5000
gitlab项目地址(注意是develop分支下的代码)
http://106.75.225.141/guoteng/albumy/tree/develop
(主机的带宽最好大一点,我的1M小水管打开网站测试极慢)
tomcat需要8080端口,nginx需要5000,80端口。
不必要的端口不要开,提前提示,谨慎reboot,update,upgrade,高并发优化不是必要的,谨慎使用。
系统:Centos 8

先创建一个有root权限的用户(这里用Rivenatte)
切换到Rivenatte:
su Rivenatte
更新:
sudo yum update
sudo yum upgrade
检查有没有gcc:
gcc -v
没有就:
sudo yum install gcc
有时需安装git:
sudo yum install git

拉取项目(这里用原项目的):
git clone http://gitea.shuishan.net.cn/10185501411/cloud_computing_1.git
cd albumy
配置虚拟环境:
python -m venv env(or python3 -m venv env)
source env/bin/activate
pip install -r requirements.txt
python -m pip install --upgrade pip
生成测试数据并测试:
flask forge
flask run --host 0.0.0.0 --port 5000
用浏览器打开http://云主机ip:5000
测试的用户账号:
username:admin@helloflask.com
password:helloflask

下面的pip可以换成pip3,如果你在创建虚拟环境时用python3的话
然而flask自带的wsgi容器性能较差,我采用另一个服务器,gunicorn。
先将我git上的python文件放在albumy中,
同时还需在项目目录下:
mkdir log
cd log
touch debug.log
touch gunicorn.pid
cd ..
这里的albumy指项目目录,不是albumy模块。

gunicorn需要在虚拟环境下安装:
(没进虚拟环境的先:
source env/bin/activate)
pip install gunicorn
同时还需安装gevent:
pip install gevent
推荐参考这个格式,指定源:
pip install 包名 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
可以解决大多问题。

然后:
cd albumy
修改__init__.py的create_app中的
app = Flask('albumy')
改为
app = Flask(__name__)
输入
gunicorn -c albumy项目的绝对路径/gconfig.py run:app
像上面一样,打开浏览器测试

继续用nginx来做反向代理。
先安装nginx:
sudo yum install nginx
接下来的配置,不同的linux发行版修改的文件可能不同,但大体类似。
实在不行就用whereis nginx找。
centos就先:
cd /etc/nginx
ls -a
发现conf.d这个文件夹,这个是放配置文件的
先对nginx.conf修改。
一般第二个https的设置是被注释的,不用管。
看http的设置,在http部分的最下面加入:
include conf.d/*.conf;(;不能少了)
这样我们就可以通过在conf.d文件夹里修改文件来进行配置
配置文件必须是.conf格式
比如 albumy.conf
server {
    listen 80;   
    root albumy项目的绝对路径;
    server_name 公网ip;
    location / {
        proxy_set_header x-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_pass http://localhost:5000/; # gunicorn绑定的端口号
    }
    # 配置static的静态文件:
    location ~ ^\/static\/.*$ {
        root 项目的绝对路径;
    }
}
添加后
sudo nginx -c /etc/nginx/nginx.conf
sudo nginx -t
sudo nginx -s reload
用浏览器打开80,5000端口,看下有没有成功。
80端口的仅仅是静态页面,比较简陋。

接着我们需要用nohup守护进程:
进入项目文件夹的虚拟环境:
cd xxx/albumy/
source env/bin/activate
nohup gunicorn -c gconfig.py run:app &
然后看下有没有成功:
ps -e | grep gunicorn

nohub不能让主机重启后自动运行进程,我们需要设置开机启动:
sudo vim /etc/rc.local
在最下面添加命令行,这样就可以在重启后自动执行命令行了。
最后别忘了加:
chmod +x /etc/rc.d/rc.local

然后可以重启检查下。

接下来进行高并发优化
我们需要安装ab压测工具
这个在任何服务器上部署都可以,只要在最后把ip改下就行。
这里申请一台centos8主机,部署ab。
同样不使用root用户。
先提醒下,deb系的安装与以下有点区别。

先更新:
sudo yum update
sudo yum upgrade

安装依赖:
sudo yum install apr-util
sudo yum install yum-utils
sudo mkdir -p /appdata/apache/ab && cd /appdata/apache/ab

安装ab:
sudo yum install yum-utils.noarch
sudo yumdownloader httpd-tools*
下一步需要root用户:
su root
rpm2cpio httpd-tools*.rpm | cpio -idmv
su Rivenatte
sudo cp /appdata/apache/ab/usr/bin/ab /usr/bin

执行ab:
ab -n 1000 -c 200 http://ip:5000/
如果不与项目在同一主机,写公网ip
在就localhost
1000指共访问了1000次,200指同时200并发
进行了5次
出现apr_pollset_poll: The timeout specified has expired (70007)
就改为ab -n 1000 -c 200 -k http://ip:5000/
看主机配置,量力而行。

先测试下,与优化后比较。

回到部署nginx的主机。
先获取cpu核心数:
grep processor /proc/cpuinfo | wc -l
一般在申请时就知道了
修改配置文件中的http模块:
sudo vim /etc/nginx/nginx.conf
具体参数参考以下文章:
https://www.jianshu.com/p/0fa77899913a
单核2g的主机可以参考以下配置:
worker_rlimit_nofile 10000;
events {
    worker_connections 10000;
}
keepalive_timeout 0;(高并发的网站需要设置的参数)

su root
(不用root用户无法进行下列命令)
对系统配置:
ulimit -n 一个较大的数字
echo 50000 > /proc/sys/net/core/somaxconn
more /proc/sys/net/core/somaxconn
有50000则正常
下列同理:
echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle(注意,现在的centos取消了这个参数,没有可以不管)
cat /proc/sys/net/ipv4/tcp_tw_recycle
echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse
cat /proc/sys/net/ipv4/tcp_tw_reuse
echo 0 > /proc/sys/net/ipv4/tcp_syncookies
cat /proc/sys/net/ipv4/tcp_syncookies
dmesg|tail
(可能需vim /etc/sysctl.conf 
设置:
net.ipv4.tcp_syncookies = 0)
对测试主机也需:
echo 50000 > /proc/sys/net/core/somaxconn
ulimit -n 一个较大的数字
(可能需设置net.ipv4.tcp_syncookies = 0,同上)

不重启主机,对测试主机配置后开始测试: sudo vim /etc/sysctl.conf 加入: net.nf_conntrack_max = 655360 net.netfilter.nf_conntrack_tcp_timeout_established = 1200)

ab -c 100000 -n 100000 -r http://主机ip:5000/

(可以适当改下,但还是要看主机配置,我这台是2gRam 1核)

之后可以将以上系统设置加入自启动项(服务器重启可能会回到修改前设置)

下面添加邮箱:
先去注册个邮箱,并以stmp服务器发送。(这个需要网上查下如何开放邮箱stmp,不同邮箱的可能不同)

像之前一样,修改启动项:
source env/bin/activate
export MAIL_SERVER='smtp.163.com'  //示例
export MAIL_USERNAME='XXXXXX@163.com'  //填邮箱XXXXXX
export MAIL_PASSWORD='XXXXXX'   //密码,注意是邮箱开启第三方smtp的认证码
别忘了chmod +x /etc/rc.d/rc.local
最后reboot。
(注:这里需要邮箱发送验证邮件,才可以输入验证码注册)

采用docker部署与k8s集群负载均衡

一、docker部署上传镜像

配置docker容器并push到远端,重新在别的服务器上部署时只需将镜像pull下来即可。 写好Dockerfile,在本地build好镜像后,将容器push到远端。

在服务器上部署时只需将远端的容器pull到服务器上,再run即可

我们首先要将上面的run.py中的
app.run()改为app.run(host='0.0.0.0',port=3389)

部署时先下载docker

curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

若报错则先执行

yum install -y https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.6-3.3.el7.x86_64.rpm

接着启动docker服务

service docker start

写入我们的Dockerfile

vim Dockerfile
FROM python:3.6
RUN apt-get update
RUN apt install -y nginx

WORKDIR /Project/demo

COPY requirements.txt ./
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

COPY . .

RUN rm /etc/nginx/sites-enabled/default
COPY nginx_flask.conf /etc/nginx/sites-available/
RUN ln -s /etc/nginx/sites-available/nginx_flask.conf /etc/nginx/sites-enabled/nginx_flask.conf
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
CMD ["nginx","-c","/etc/nginx/nginx.conf"]
CMD ["nginx","-t"]
CMD ["nginx","-s","reload"]
CMD ["gunicorn", "run:app", "-c", "./gconfig.py"]

其中需要我们之前部署时写的gconfig.py文件和我们的nginx配置文件

除此以外我们需要在根目录创建一个新文件nginx_flask.conf

server {
    listen      80;

    location / {
        proxy_pass http://localhost:5000/;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location ^~ /static/ {
        root /Project/demo;
    }
}

之后在本地建立镜像

docker build -t image1 .

建立成功后可以尝试启动docker容器

docker run -d -p 3389:3389 --name test1 image1

打开http://云主机ip:3389查看是否显示界面

之后将我们的镜像push到远端

没有注册docker账号的话先注册一个docker账号

https://registry.hub.docker.com/

接着登录docker账号

docker login
输入账号
输入密码

显示login successful就成功了,之后push到远端

首先对镜像打标签

docker tag image1 lh123/albumy_nginx_mysql_image:v2

之后将镜像推送到仓库

docker push lh123/albumy_nginx_mysql_image:v2

以后需要创建应用时只需要从docker中拉取镜像运行即可。

新建云主机,安装docker之后将上述镜像pull到本地,之后执行

docker run -d -p 3389:3389 --name test1 lh123/albumy_nginx_mysql_image:v2

打开http:云主机ip:3389即可访问网页。

二、采用负载均衡

之后在ucloud中使用负载均衡ULB,创建负载均衡ULB。

接着在建立三台云主机,使用原来申请的有外网的云主机,分别通过内网连接三台新建的云主机。

在云主机上pull下来刚才上传的docker镜像

docker pull lh123/albumy_nginx_mysql_image:v2

在云主机上启动镜像

docker run -d -p 3389:3389 --name test1 albumy_nginx_mysql_image:v2

将我们启动好的三台云主机啊加到我们的负载均衡当中

使用负载均衡之后的压测效果更好

三、连接云数据库

为了保证负载均衡的服务器的数据一致性,我们将数据库挂在到云数据库mysql上

我们将项目的.flask.env文件中的设置改为

FLASK_APP=albumy
FLASK_ENV=development

再将setting.py中的设置改为

class ProductionConfig(BaseConfig):
    SQLALCHEMY_DATABASE_URI = 'mysql://root:lianghui123@10.23.56.255:3306/flask_test'

再打包到docker并运行我们的项目

发现报错No module named MYSQLdb发现是因为

按照 Flask-SQLAlchemy 文档的说明,配置好 SQLALCHEMY_DATABASE_URI = 'mysql://username:password@server/db' 后操作 MySQL 报错 ImportError: No module named 'MySQLdb'。既然缺少 MySQLdb 这个模块,按照常规方法缺啥补啥吧,执行 pip install MySQL-python 却报错 ImportError: No module named 'ConfigParser'。查了一下,这是由于 MySQL-python 不支持 Python 3(MySQL-3.23 through 5.5 and Python-2.4 through 2.7 are currently supported)。

将MySQLdb换为pymsql,安装pymsql(记得先启动虚拟环境)

pip install pymsql

并在__init__.py中加入

import pymysql
pymysql.install_as_MySQLdb()

再将setting.py中的设置改为

class ProductionConfig(BaseConfig):
    SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:lianghui123@10.23.56.255:3306/flask_test'

即可访问我们的云主机数据库。

最后将完成的项目打包好镜像push到远端仓库。

四、k8s集群部署(有点问题)

建立好docker容器之后就可以使用k8s集群部署网页,采用k8s部署可以实现容器集群的自动化部署、自动扩缩容、维护等功能。

首先在ucloud中创建一个UK8S,之后申请一个云主机,

登录云主机安装docker拉取镜像

docker pull lh123/albumy_nginx_mysql_image:v2

安装k8s


wget https://storage.googleapis.com/kubernetes-release/release/v1.19.0/bin/linux/amd64/kubectl
chmod +x kubectl
sudo mv kubectl /usr/local/bin/   (root用户:mv kubectl /usr/bin/)
kubectl version -o json

将K8S的集群凭证添加到kubectl配置文件中,从而能够操控集群。

打开K8S的外网集凭证复制,在云主机中创建~/.kube文件夹,并在其中创建config文件,将外网集凭证复制到config文件中。

为了能在k8s上部署我们的docker镜像,我们还需要在项目文件中添加两个文件Deployment.yamlservice.yaml

deployment.yaml中:

apiVersion: extensions/v1beta1
 kind: Deployment
 metadata:
   name: albumy-node-deployment
 spec:
   replicas: 1
   selector:
     matchLabels:
       app: albumynode
   template:
     metadata:
       labels:
         app: albumynode
     spec:
       containers:
       - name: albumynode
         image: lh123/albumy_nginx_mysql_image:v2
         imagePullPolicy: Always
         ports:
         - containerPort: 3389

service.yaml中:

apiVersion: v1
 kind: Service
 metadata:
   name: albumy-node-deployment
 spec:
   ports:
   - port: 3389
     targetPort: 3389
   selector:
     app: albumynode

之后运行一下命令部署项目

kubectl create -f deployment.yaml

kubectl create -f service.yaml

查看pod是否处于ready状态,若pod不处于ready状态且一直是containercreating状态则

查看创建日志,发现是容器创建失败,谷歌不能访问,uhub-edu.service.ucloud.cn/google_containers/pause-amd64:3.0"镜像无法获取,这应该是ucloud端的问题。(我们采用平时实验作业第八次的部署方法部署实验2里的静态网页也还是报这个错误,真的是很无语)。

(即使用

kubectl create deployment webapp --image=lh123/albumy_nginx_mysql_image:v2

我们发现这样子pod的状态还是一直处于containercreating的状态,而且也是报下图的错误,我觉得者应该是ucloud端的问题,被墙了。我怀疑是ucloud的教育云出问题了之前第八次实验的时候还可以用,现在就不可以用了。

解决方法如下,从docker.io把pause-amd64镜像取下来,然后做个标签。这样就可以解决问题。

docker pull googlecontainer/pause-amd64:3.0
docker tag googlecontainer/pause-amd64:3.0 uhub-edu.service.ucloud.cn/google_containers/pause-amd64:3.0

之后新建连接,登录云主机执行

echo -e "\n\e[92mStarting Proxy. After starting it will not output a response. Please click the first Terminal Tab\n"; kubectl proxy

之后访问我们的应用

kubectl get pods#获取我们pod的名称
export POD_NAME=$刚才得到的pod名称
curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/

查看我们创建的POD的详细信息

kubectl get pods -o wide

之后将副本scale到10个

kubectl scale deployments/albumy-node-deployment --replicas=10

将我们的网页暴露给公网,并加上负载均衡

创建一个负载均衡

kubectl expose deployment albumy-node-deployment --type=LoadBalancer --port=80

查看service,可以看到负载均衡服务的外网ip地址

kubectl get services

之后访问http:localhost:负载均衡ip就可以看到网页

本次作业镜像:

账号:1491337293@qq.com

密码:18830095812zxc

docker账户

账号:lh123

密码:18830095812zxc

docker镜像:lh123/albumy_nginx_mysql_image:v2

ucloud上docker部署镜像名:docker_nginx_mysql

集群部署有点问题被墙了。

五、总结与反思

通过本次大作业,我们学习网站前后端的知识,学习了云计算的一些基本知识,亲自部署了云上的应用,学习了docker、k8s等云计算工具的使用,更好的理解了的docker和k8s的用途,和它们在真实云计算环境下对项目部署的帮助。但我们的部署和开发并不完善,一些应用的细节问题没有解决,关于docker、k8s和其他云计算工具的许多知识还需要学习 分工:项目部署、README书写、版本控制、前后端修改:郭腾、梁辉 前后端开发修改、版本控制、项目部署:沈小奇