diff --git a/README.md b/README.md index 95e08f1..5ced1c7 100644 --- a/README.md +++ b/README.md @@ -1,609 +1,611 @@ - 本次实验源代码来自:https://github.com/greyli/albumy - demo网站:http://59.110.70.81:5000 - (主机的带宽最好大一点,我的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 https://github.com/greyli/albumy.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,同上) - - ![](http://106.75.225.141/guoteng/albumy/raw/develop/readme_image/压测albumy.png) - -不重启主机,对测试主机配置后开始测试: - 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即可 - -```python -我们首先要将上面的run.py中的 -app.run()改为app.run(host='0.0.0.0',port=3389) -``` - -部署时先下载docker - -```bash -curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun -``` - -若报错则先执行 - -```bash -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服务 - -```bash -service docker start -``` - -写入我们的Dockerfile - -```bash -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; - } -} - -``` - -之后在本地建立镜像 - -```bash -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到远端 - -首先对镜像打标签 - -```bash -docker tag image1 lh123/albumy_nginx_mysql_image:v2 -``` - -之后将镜像推送到仓库 - -```bash -docker push lh123/albumy_nginx_mysql_image:v2 -``` - -以后需要创建应用时只需要从docker中拉取镜像运行即可。 - -![](http://106.75.225.141/guoteng/albumy/raw/develop/readme_image/docker_image.png) - -新建云主机,安装docker之后将上述镜像pull到本地,之后执行 - -``` -docker run -d -p 3389:3389 --name test1 lh123/albumy_nginx_mysql_image:v2 -``` - -打开http:云主机ip:3389即可访问网页。 - - - -### 二、采用负载均衡 - -之后在ucloud中使用负载均衡ULB,创建负载均衡ULB。 - -接着在建立三台云主机,使用原来申请的有外网的云主机,分别通过内网连接三台新建的云主机。 - -在云主机上pull下来刚才上传的docker镜像 - -```bash -docker pull lh123/albumy_nginx_mysql_image:v2 -``` - -在云主机上启动镜像 - -```bash -docker run -d -p 3389:3389 --name test1 albumy_nginx_mysql_image:v2 -``` - -将我们启动好的三台云主机啊加到我们的负载均衡当中 - -![](http://106.75.225.141/guoteng/albumy/raw/develop/readme_image/负载均衡.png) - -使用负载均衡之后的压测效果更好 - -![](http://106.75.225.141/guoteng/albumy/raw/develop/readme_image/压测albumy.png) - -### 三、连接云数据库 - -为了保证负载均衡的服务器的数据一致性,我们将数据库挂在到云数据库mysql上 - -我们将项目的.flask.env文件中的设置改为 - -```bash -FLASK_APP=albumy -FLASK_ENV=development -``` - -再将setting.py中的设置改为 - -```bash -class ProductionConfig(BaseConfig): - SQLALCHEMY_DATABASE_URI = 'mysql://root:lianghui123@10.23.56.255:3306/flask_test' -``` - -再打包到docker并运行我们的项目 - -发现报错No module named MYSQLdb发现是因为 - -```bash -按照 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(记得先启动虚拟环境) - -```absh -pip install pymsql -``` - -并在__init__.py中加入 - -```python -import pymysql -pymysql.install_as_MySQLdb() -``` - -再将setting.py中的设置改为 - -```bash -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 - -```bash - -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.yaml** 和 **service.yaml**, - -**deployment.yaml**中: - -```bash -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 -``` - - - -之后运行一下命令部署项目 - -```bash -kubectl create -f deployment.yaml - -kubectl create -f service.yaml -``` - -查看pod是否处于ready状态,若pod不处于ready状态且一直是containercreating状态则 - -![](http://106.75.225.141/guoteng/albumy/raw/develop/readme_image/错误1.png) - -查看创建日志,发现是容器创建失败,谷歌不能访问,uhub-edu.service.ucloud.cn/google_containers/pause-amd64:3.0"镜像无法获取,这应该是ucloud端的问题。(我们采用平时实验作业第八次的部署方法部署实验2里的静态网页也还是报这个错误,真的是很无语)。 - -(即使用 - -```bash -kubectl create deployment webapp --image=lh123/albumy_nginx_mysql_image:v2 -``` - -我们发现这样子pod的状态还是一直处于containercreating的状态,而且也是报下图的错误,我觉得者应该是ucloud端的问题,被墙了。我怀疑是ucloud的教育云出问题了之前第八次实验的时候还可以用,现在就不可以用了。 - -) - -![](http://106.75.225.141/guoteng/albumy/raw/develop/readme_image/错误2.png) - -解决方法如下,从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 -``` - -之后新建连接,登录云主机执行 - -```bash -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个 - -```bash -kubectl scale deployments/albumy-node-deployment --replicas=10 -``` - -将我们的网页暴露给公网,并加上负载均衡 - -创建一个负载均衡 - -```bash -kubectl expose deployment albumy-node-deployment --type=LoadBalancer --port=80 -``` - -查看service,可以看到负载均衡服务的外网ip地址 - -```bash -kubectl get services -``` - -之后访问http:localhost:负载均衡ip就可以看到网页 - - - - - -本次作业镜像: - -账号:1491337293@qq.com - -密码:18830095812zxc - -docker账户 - -账号:lh123 - -密码:18830095812zxc - -docker镜像:lh123/albumy_nginx_mysql_image:v2 - -![](http://106.75.225.141/guoteng/albumy/raw/develop/readme_image/docker镜像.png) - -ucloud上docker部署镜像名:docker_nginx_mysql - -![](http://106.75.225.141/guoteng/albumy/raw/develop/readme_image/镜像.png) - -集群部署有点问题被墙了。 - + 本次实验源代码来自: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 https://github.com/greyli/albumy.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,同上) + + ![](http://106.75.225.141/guoteng/albumy/raw/develop/readme_image/压测albumy.png) + +不重启主机,对测试主机配置后开始测试: + 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即可 + +```python +我们首先要将上面的run.py中的 +app.run()改为app.run(host='0.0.0.0',port=3389) +``` + +部署时先下载docker + +```bash +curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun +``` + +若报错则先执行 + +```bash +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服务 + +```bash +service docker start +``` + +写入我们的Dockerfile + +```bash +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; + } +} + +``` + +之后在本地建立镜像 + +```bash +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到远端 + +首先对镜像打标签 + +```bash +docker tag image1 lh123/albumy_nginx_mysql_image:v2 +``` + +之后将镜像推送到仓库 + +```bash +docker push lh123/albumy_nginx_mysql_image:v2 +``` + +以后需要创建应用时只需要从docker中拉取镜像运行即可。 + +![](http://106.75.225.141/guoteng/albumy/raw/develop/readme_image/docker_image.png) + +新建云主机,安装docker之后将上述镜像pull到本地,之后执行 + +``` +docker run -d -p 3389:3389 --name test1 lh123/albumy_nginx_mysql_image:v2 +``` + +打开http:云主机ip:3389即可访问网页。 + + + +### 二、采用负载均衡 + +之后在ucloud中使用负载均衡ULB,创建负载均衡ULB。 + +接着在建立三台云主机,使用原来申请的有外网的云主机,分别通过内网连接三台新建的云主机。 + +在云主机上pull下来刚才上传的docker镜像 + +```bash +docker pull lh123/albumy_nginx_mysql_image:v2 +``` + +在云主机上启动镜像 + +```bash +docker run -d -p 3389:3389 --name test1 albumy_nginx_mysql_image:v2 +``` + +将我们启动好的三台云主机啊加到我们的负载均衡当中 + +![](http://106.75.225.141/guoteng/albumy/raw/develop/readme_image/负载均衡.png) + +使用负载均衡之后的压测效果更好 + +![](http://106.75.225.141/guoteng/albumy/raw/develop/readme_image/压测albumy.png) + +### 三、连接云数据库 + +为了保证负载均衡的服务器的数据一致性,我们将数据库挂在到云数据库mysql上 + +我们将项目的.flask.env文件中的设置改为 + +```bash +FLASK_APP=albumy +FLASK_ENV=development +``` + +再将setting.py中的设置改为 + +```bash +class ProductionConfig(BaseConfig): + SQLALCHEMY_DATABASE_URI = 'mysql://root:lianghui123@10.23.56.255:3306/flask_test' +``` + +再打包到docker并运行我们的项目 + +发现报错No module named MYSQLdb发现是因为 + +```bash +按照 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(记得先启动虚拟环境) + +```absh +pip install pymsql +``` + +并在__init__.py中加入 + +```python +import pymysql +pymysql.install_as_MySQLdb() +``` + +再将setting.py中的设置改为 + +```bash +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 + +```bash + +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.yaml** 和 **service.yaml**, + +**deployment.yaml**中: + +```bash +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 +``` + + + +之后运行一下命令部署项目 + +```bash +kubectl create -f deployment.yaml + +kubectl create -f service.yaml +``` + +查看pod是否处于ready状态,若pod不处于ready状态且一直是containercreating状态则 + +![](http://106.75.225.141/guoteng/albumy/raw/develop/readme_image/错误1.png) + +查看创建日志,发现是容器创建失败,谷歌不能访问,uhub-edu.service.ucloud.cn/google_containers/pause-amd64:3.0"镜像无法获取,这应该是ucloud端的问题。(我们采用平时实验作业第八次的部署方法部署实验2里的静态网页也还是报这个错误,真的是很无语)。 + +(即使用 + +```bash +kubectl create deployment webapp --image=lh123/albumy_nginx_mysql_image:v2 +``` + +我们发现这样子pod的状态还是一直处于containercreating的状态,而且也是报下图的错误,我觉得者应该是ucloud端的问题,被墙了。我怀疑是ucloud的教育云出问题了之前第八次实验的时候还可以用,现在就不可以用了。 + +) + +![](http://106.75.225.141/guoteng/albumy/raw/develop/readme_image/错误2.png) + +解决方法如下,从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 +``` + +之后新建连接,登录云主机执行 + +```bash +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个 + +```bash +kubectl scale deployments/albumy-node-deployment --replicas=10 +``` + +将我们的网页暴露给公网,并加上负载均衡 + +创建一个负载均衡 + +```bash +kubectl expose deployment albumy-node-deployment --type=LoadBalancer --port=80 +``` + +查看service,可以看到负载均衡服务的外网ip地址 + +```bash +kubectl get services +``` + +之后访问http:localhost:负载均衡ip就可以看到网页 + + + + + +本次作业镜像: + +账号:1491337293@qq.com + +密码:18830095812zxc + +docker账户 + +账号:lh123 + +密码:18830095812zxc + +docker镜像:lh123/albumy_nginx_mysql_image:v2 + +![](http://106.75.225.141/guoteng/albumy/raw/develop/readme_image/docker镜像.png) + +ucloud上docker部署镜像名:docker_nginx_mysql + +![](http://106.75.225.141/guoteng/albumy/raw/develop/readme_image/镜像.png) + +集群部署有点问题被墙了。 +