解决ubuntu16.04中mongodb远程连接不上的问题

系统版本:

  • lsb_release -a
  • No LSB modules are available.
  • Distributor ID: Ubuntu
  • Description: Ubuntu 16.04.2 LTS
  • Release: 16.04
  • Codename: xenial

MongoDB版本:

> db.version()
2.6.10

ps:使用yum安装的mongodb

1、查看网络端口情况,发现mongodb服务绑定中本地ip上

netstat -tunlp
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.1.1:53            0.0.0.0:*               LISTEN      -               
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -               
tcp        0      0 127.0.0.1:27017         0.0.0.0:*               LISTEN      -               
tcp6       0      0 :::22                   :::*                    LISTEN      -               
udp        0      0 0.0.0.0:60855           0.0.0.0:*                           -               
udp        0      0 127.0.1.1:53            0.0.0.0:*                           -               
udp        0      0 0.0.0.0:68              0.0.0.0:*                           -               
udp        0      0 0.0.0.0:631             0.0.0.0:*                           -               
udp        0      0 0.0.0.0:5353            0.0.0.0:*                           -               
udp6       0      0 :::44164                :::*                                -               
udp6       0      0 :::5353                 :::*                                -   

2、修改/etc/mongodb.con文件中mongodb绑定端口的ip,绑定到任何ip上:

bind_ip = 0.0.0.0

3、查看系统网络端口情况,mongodb服务监听的端口绑定中所有ip上,这样能够被内网的主机能够访问到

netstat -tunlp
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.1.1:53            0.0.0.0:*               LISTEN      -               
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -               
tcp        0      0 0.0.0.0:27017           0.0.0.0:*               LISTEN      -               
tcp6       0      0 :::22                   :::*                    LISTEN      -               
udp        0      0 0.0.0.0:60855           0.0.0.0:*                           -               
udp        0      0 127.0.1.1:53            0.0.0.0:*                           -               
udp        0      0 0.0.0.0:68              0.0.0.0:*                           -               
udp        0      0 0.0.0.0:631             0.0.0.0:*                           -               
udp        0      0 0.0.0.0:5353            0.0.0.0:*                           -               
udp6       0      0 :::44164                :::*                                -               
udp6       0      0 :::5353                 :::*                                -  

4、使用内网的另外一台ubuntu系统机子:

输入 curl 192.168.31.172:27017 ,返回It looks like you are trying to access MongoDB over HTTP on the native driver port.

说明连接成功

或者中浏览器地址栏中输入http://192.168.31.172:27017/,enter后,回复上面相同的内容。

CentOS7.3搭建Apache+PHP7+web SVN+MariaDB Web服务器

注意:本教程使用干净的 CentOS 7进行安装,如果您已安装其他环境或软件,涉及到内核升级,请您妥善备份,可能导致您已安装的软件不兼容或出现其他问题。

免责声明:本教程仅以个人经验撰写,未必适合所有系统环境。如在使用本教程途中,出现无法挽救的损失(如数据丢失等),本人概不负责。

再次提醒:使用本教程前请妥善备份现有数据!使用本教程前请妥善备份现有数据!使用本教程前请妥善备份现有数据!

如果您使用本教程的方法过程中出现问题,您可留言,我将在能力范围内尽可能协助解决。

本文最终服务器环境配置:

Apache 2.7.27
subversion1.9.7
MariaDB10.2.28
php7.1.8

下面开始进入教程吧。

一. 升级内核和软件包

[root@instance-l79ltvo6 ~]# yum -y update
...    
Complete!

直到控制台输出Complete!说明升级完成,最好还是重启一下吧

[root@instance-l79ltvo6 ~]# reboot

二. 安装 apache 2.4.27

先安装一些基本依赖

[root@instance-l79ltvo6 ~]# yum install -y gcc gcc-c++ openssl-devel zlib-devel
//在root目录下创建一个soft文件夹,我们本次教程的软件将都放在该目录下
[root@instance-l79ltvo6 ~]# mkdir soft 
[root@instance-l79ltvo6 ~]# cd soft

然后开始安装apr、apr-util、pcre 3个依赖,最后再安装 apache

1、安装 apr

[root@instance-l79ltvo6 ~]# wget https://mirror.tuna.tsinghua.edu.cn/apache/apr/apr-1.6.2.tar.gz
[root@instance-l79ltvo6 ~]# tar zxf apr-1.6.2.tar.gz
[root@instance-l79ltvo6 ~]# cd apr-1.6.2/
[root@instance-l79ltvo6 ~]# ./configure --prefix=/usr/local/apr
[root@instance-l79ltvo6 ~]# make && make install
[root@instance-l79ltvo6 ~]# cd ..    //返回上级目录

因为我们使用了 apr 1.6.2 的依赖,所以下面我们必须要用 apr-util 1.6.0 版本,apr-util 1.6.0

不再捆绑安装 expat ,但又需要 expat 的支持,所以我们得手动先安装 expat。不然编译 apache 的时候会报错。

2、安装 expat

[root@instance-l79ltvo6 ~]# wget https://sourceforge.net/projects/expat/files/expat/2.2.3/expat-2.2.3.tar.bz2
[root@instance-l79ltvo6 ~]# tar jxf expat-2.2.3.tar.bz2
[root@instance-l79ltvo6 ~]# cd expat-2.2.3/
[root@instance-l79ltvo6 ~]# ./configure --prefix=/usr/local/expat
[root@instance-l79ltvo6 ~]# make && make install
[root@instance-l79ltvo6 ~]# cd ..    //返回上级目录

3、安装 apr-util

[root@instance-l79ltvo6 ~]# wget  https://mirror.tuna.tsinghua.edu.cn/apache/apr/apr-util-1.6.0.tar.gz
[root@instance-l79ltvo6 ~]# tar zxf apr-util-1.6.0.tar.gz
[root@instance-l79ltvo6 ~]# cd apr-util-1.6.0/
[root@instance-l79ltvo6 ~]# ./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr --with-expat=/usr/local/expat
[root@instance-l79ltvo6 ~]# make && make install
[root@instance-l79ltvo6 ~]# cd ..    //返回上级目录

4、安装 pcre

[root@instance-l79ltvo6 ~]# wget http://sourceforge.mirrorservice.org/p/pc/pcre/pcre/8.41/pcre-8.41.tar.gz
[root@instance-l79ltvo6 ~]# tar zxf pcre-8.41.tar.gz
[root@instance-l79ltvo6 ~]# cd pcre-8.41/
[root@instance-l79ltvo6 ~]# ./configure --prefix=/usr/local/pcre
[root@instance-l79ltvo6 ~]# make && make install
[root@instance-l79ltvo6 ~]# cd ..    //返回上级目录

5、安装 apache

[root@instance-l79ltvo6 ~]# wget http://mirrors.tuna.tsinghua.edu.cn/apache//httpd/httpd-2.4.27.tar.gz
[root@instance-l79ltvo6 ~]# tar zxf httpd-2.4.27.tar.gz
[root@instance-l79ltvo6 ~]# cd httpd-2.4.27/
[root@instance-l79ltvo6 ~]# ./configure 
--prefix=/usr/local/apache 
--with-apr=/usr/local/apr 
--with-apr-util=/usr/local/apr-util 
--with-pcre=/usr/local/pcre 
--with-ssl 
--with-zlib 
--with-mpm=worker 
--enable-rewrite 
--enable-so 
--enable-ssl 
--enable-cache 
--enable-disk-cache 
--enable-file-cache 
--enable-mem-cache 
--enable-headers 
--enable-expires 
--enable-deflate 
--enable-dav 
--enable-dav-fs 
--enable-cgi 
--enable-proxy 
--enable-proxy-fcgi
//这里请根据自身实际情况开启相关模块
[root@instance-l79ltvo6 ~]# make && make install
[root@instance-l79ltvo6 ~]# cd ..    //返回上级目录

6、修改 apache 配置文件

编辑/usr/local/apache/conf/httpd.conf

#LoadModule ssl_module modules/mod_ssl.so //去掉#开启 SSL
#LoadModule rewrite_module modules/mod_rewrite.so  //去掉#开启 rewrite
#ServerName www.example.com:80    //去掉#并把 www.example.com:80 修改为你的IP:80或者域名
#Include conf/extra/httpd-vhosts.conf     //去掉#,开启虚拟主机配置
//如果你需要安装svn服务,你需要开启
#LoadModule dav_module modules/mod_dav.so//去掉#

找到以下代码并更换

<Directory />
    AllowOverride none
    Require all denied
</Directory>
//修改为
<Directory />
    Options Indexes FollowSymLinks    //如不需要显示目录,把 Indexes 去掉
    AllowOverride ALL    //开启rewrite
    Require all granted
</Directory>

编辑/usr/local/apache/conf/extra/httpd-vhosts.conf,删除全部,
并添加下列代码

<VirtualHost *:80>
    DocumentRoot "/usr/local/apache/htdocs"
    ServerName your IP    //你的IP地址
    ErrorLog "logs/你的IP-error_log"
    CustomLog "logs/你的IP-access_log" common
</VirtualHost>

7、添加启动服务

[root@instance-l79ltvo6 ~]# cp /usr/local/apache/bin/apachectl  /etc/rc.d/init.d/
[root@instance-l79ltvo6 ~]# mv /etc/rc.d/init.d/apachectl /etc/rc.d/init.d/httpd
[root@instance-l79ltvo6 ~]# cd /etc/rc.d/init.d/

编辑 httpd ,在 #!/bin/sh 下面添加下面代码

# Comments to support chkconfig on RedHat Linux
# chkconfig: 2345 90 90
# description:http server

注册服务

[root@instance-l79ltvo6 ~]# chkconfig --add httpd
[root@instance-l79ltvo6 ~]# chkconfig httpd on

把 apache 加入系统环境变量

[root@instance-l79ltvo6 ~]# vim /etc/profile.d/httpd.sh
//写入
export PATH=$PATH:/usr/local/apache/bin
//保存后赋予执行权限
[root@instance-l79ltvo6 ~]# chmod 0777 /etc/profile.d/httpd.sh
[root@instance-l79ltvo6 ~]# source /etc/profile.d/httpd.sh

8、启动 apache

首先检查配置文件是否出错

[root@instance-l79ltvo6 ~]# /usr/local/apache/bin/apachectl -t
Syntax OK    //说明没问题,可以直接启动

启动 apache

[root@instance-l79ltvo6 ~]# systemctl start httpd.service

然后打开浏览器,输入你的IP地址,看到It works!,说明apache成功启动了

It works!

三. 安装 subversion 1.9.7

(如不需要svn服务请跳过)

1、安装 scons

[root@instance-l79ltvo6 ~]# cd /root/soft
[root@instance-l79ltvo6 ~]# wget http://sourceforge.mirrorservice.org/s/sc/scons/scons/2.5.1/scons-2.5.1.tar.gz
[root@instance-l79ltvo6 ~]# tar zxf scons-2.5.1.tar.gz
[root@instance-l79ltvo6 ~]# cd scons-2.5.1/
[root@instance-l79ltvo6 ~]# python setup.py install --prefix=/usr/local/scons
[root@instance-l79ltvo6 ~]# cd ..    //返回上级目录

2、安装 serf

[root@instance-l79ltvo6 ~]# wget https://mirrors.tuna.tsinghua.edu.cn/apache/serf/serf-1.3.9.tar.bz2
[root@instance-l79ltvo6 ~]# tar xf serf-1.3.9.tar.bz2
[root@instance-l79ltvo6 ~]# cd serf-1.3.9/
[root@instance-l79ltvo6 ~]# /usr/local/scons/bin/scons prefix=/usr/local/serf APR=/usr/local/apr APU=/usr/local/apr-util
[root@instance-l79ltvo6 ~]# /usr/local/scons/bin/scons install
[root@instance-l79ltvo6 ~]# cd ..    //返回上级目录

3、编译 subverion

[root@instance-l79ltvo6 ~]# wget http://www.sqlite.org/2017/sqlite-amalgamation-3190300.zip
[root@instance-l79ltvo6 ~]# wget https://mirrors.tuna.tsinghua.edu.cn/apache/subversion/subversion-1.9.7.tar.gz
[root@instance-l79ltvo6 ~]# tar zxf subversion-1.9.7.tar.gz
[root@instance-l79ltvo6 ~]# unzip sqlite-amalgamation-3190300.zip
[root@instance-l79ltvo6 ~]# mv /root/soft/sqlite-amalgamation-3190300 /root/soft/subversion-1.9.7/sqlite-amalgamation
[root@instance-l79ltvo6 ~]# cd subversion-1.9.7/
[root@instance-l79ltvo6 ~]# ./configure 
--prefix=/usr/local/svn 
--with-apr=/usr/local/apr 
--with-apr-util=/usr/local/apr-util 
--with-serf=/usr/local 
--enable-mod-activation 
--with-apache-libexecdir=/usr/local/apache/modules 
--with-apxs=/usr/local/apache/bin/apxs  
--without-berkeley-db
[root@instance-l79ltvo6 ~]# make && make install

给SVN创建一个名为svn的非登录用户

[root@instance-l79ltvo6 ~]# useradd svn -s /sbin/nologin

把svn加入到系统环境变量

[root@instance-l79ltvo6 ~]# vim /etc/profile.d/svn.sh
//添加
export PATH=$PATH:/usr/local/svn/bin
保存后赋予执行权限
[root@instance-l79ltvo6 ~]# chmod 0777 /etc/profile.d/svn.sh
[root@instance-l79ltvo6 ~]# source /etc/profile.d/svn.sh

在/etc/ld.so.conf.d/创建一个serf-1.3.9.conf,指定lib目录,不然svn启动会报错

[root@instance-l79ltvo6 ~]# vim /etc/ld.so.conf.d/serf-1.3.9.conf
//添加
/usr/local/lib
保存后刷新
[root@instance-l79ltvo6 ~]# /sbin/ldconfig -v

4、配置 subverion

下面我们先创建一个 test 项目

[root@instance-l79ltvo6 ~]# mkdir -p /data/svn
[root@instance-l79ltvo6 ~]# cd /data/svn
[root@instance-l79ltvo6 ~]# svnadmin create test

然后我们打开 /data/svn/test /就会发现里面自动创建了一些目录

conf
db
format
hooks
locks
README.txt

在conf里面的文件就是配置该项目的人员和权限,但如果多个项目,开发人员一样,那就要配置很多次了,这样很麻烦,所以我们要弄成配置一次权限就能直接应用到所有项目里面。

[root@instance-l79ltvo6 ~]# cp /data/svn/test/conf/authz  /data/svn/authz
[root@instance-l79ltvo6 ~]# cp /data/svn/test/conf/passwd  /data/svn/passwd
[root@instance-l79ltvo6 ~]# cp /data/svn/test/conf/svnserve.conf  /data/svn/svnserve.conf
//然后设置一个用户密码,这里以创建root用户为例,这里的演示是将密码加密而非明文存储
[root@instance-l79ltvo6 ~]# htpasswd -c /data/svn/passwd root
New password:       //输入密码
Re-type new password:    //再次输入密码

这样 root 用户就创建完成了,创建其他用户同理。 接下来我们需要修改配置文件

[root@instance-l79ltvo6 ~]# vim /data/svn/svnserve.conf
//删除所有内容,增加下面的代码
[general]
anon-access = read
auth-access = write
password-db = passwd
authz-db = authz
[sasl]
//保存
[root@instance-l79ltvo6 ~]# vim /data/svn/authz
//删除所有内容,增加下面的代码
[aliases]
# joe = /C=XZ/ST=Dessert/L=Snake City/O=Snake Oil, Ltd./OU=Research Institute/CN=Joe Average

[groups]
administrators = root

[/]
@administrators=rw

[test:/]
* = r
//保存

我们尝试启动下svn服务

[root@instance-l79ltvo6 ~]# svnserve --config-file /data/svn/svnserve.conf -d -r /data/svn

没有报错,说明启动成功了
把/data/svn/目录的拥有者更改为svn

[root@instance-l79ltvo6 ~]# chown -R svn:svn /data/svn

最后我们需要修改 apache 的相关配置文件
编辑/usr/local/apche/conf/httpd.conf

//找到
User daemon
Group daemon
//修改为
User svn
Group svn

编辑/usr/local/apache/conf/extra/httpd-vhost.conf,把刚刚那次编辑的内容更换为

<VirtualHost *:80>
    ServerName 你的IP
    ErrorLog "logs/你的IP-error_log"
    CustomLog "logs/你的IP-access_log" common
    <Location /svn>
      DAV svn
      #support more repositories
      SVNParentPath /data/svn

      #list all repositories
      #SVNListParentPath on
      AuthType Basic
      AuthName "Please input Username and Password"
      AuthUserFile /data/svn/passwd
      AuthzSVNAccessFile /data/svn/authz
      Require valid-user
    </Location>
</VirtualHost>

然后停止 apache 服务

[root@instance-l79ltvo6 ~]# systemctl stop httpd.service

检查 apache 配置文件是否出错

[root@instance-l79ltvo6 ~]# /usr/local/apache/bin/apachectl -t
Syntax OK    //说明没问题,可以直接启动

重新启动 apache

[root@instance-l79ltvo6 ~]# systemctl start httpd.service

打开浏览器访问http://你的ip/svn/test,提示输入账号密码 也可以使用TortoiseSVN进行操作
输入刚刚设置的账号密码后显示

test - Revision 0: /

说明配置成功,apache+svn服务启动成功

四. 安装 MariaDB 10.2.8

参考https://segmentfault.com/a/11…,把相关版本号更换为10.2.8即可

五. 安装 PHP 7.1.8

先安装基本依赖

[root@instance-l79ltvo6 ~]# yum -y install gcc gcc-c++ autoconf automake libtool re2c flex bison php-mcrypt libmcrypt libmcrypt-devel openssl-devel libxml2-devel libcurl-devel libjpeg-devel libpng-devel freetype-devel zlib-devel mcrypt bzip2-devel libicu-devel systemd-devel mhash postgresql-devel libxslt libxslt-devel

编译 PHP

[root@instance-l79ltvo6 ~]# cd /root/soft
[root@instance-l79ltvo6 ~]# wget http://cn.php.net/distributions/php-7.1.8.tar.gz
[root@instance-l79ltvo6 ~]# tar zxf php-7.1.8.tar.gz
[root@instance-l79ltvo6 ~]# cd php-7.1.8/
[root@instance-l79ltvo6 ~]# ./configure 
--prefix=/usr/local/php 
--with-apxs2=/usr/local/apache/bin/apxs 
--with-curl 
--with-freetype-dir 
--with-gd 
--with-gettext 
--with-iconv-dir 
--with-kerberos 
--with-libdir=lib64 
--with-libxml-dir 
--with-mysqli 
--with-openssl 
--with-pcre-regex 
--with-pdo-mysql 
--with-pdo-sqlite 
--with-pear 
--with-png-dir 
--with-xmlrpc 
--with-xsl 
--with-zlib 
--with-mhash 
--enable-fpm 
--enable-bcmath 
--enable-libxml 
--enable-inline-optimization 
--enable-gd-native-ttf 
--enable-mbregex 
--enable-mbstring 
--enable-opcache 
--enable-pcntl 
--enable-shmop 
--enable-soap 
--enable-sockets 
--enable-sysvsem 
--enable-xml 
--enable-zip 
--enable-mysqlnd
[root@instance-l79ltvo6 ~]# make && make install
...    //漫长的等待

编译成功

[PEAR] Archive_Tar    - installed: 1.4.3
[PEAR] Console_Getopt - installed: 1.4.1
[PEAR] Structures_Graph- installed: 1.1.1
[PEAR] XML_Util       - installed: 1.4.2
[PEAR] PEAR           - installed: 1.10.5
Wrote PEAR system config file at: /usr/local/php/etc/pear.conf
You may want to add: /usr/local/php/lib/php to your php.ini include_path
/root/soft/php-7.1.8/build/shtool install -c ext/phar/phar.phar /usr/local/php/bin
ln -s -f phar.phar /usr/local/php/bin/phar
Installing PDO headers:           /usr/local/php/include/php/ext/pdo/

这里提示让我们从源码包复制一份 php.ini 到 /usr/local/php/lib/

[root@instance-l79ltvo6 ~]# cp php.ini-development /usr/local/php/lib/php.ini

修改 apache ,让 apache 支持 php
编辑/usr/local/apache/conf/httpd.conf

LoadModule php7_module        modules/libphp7.so    //默认是开启php7.so
//找到 <IfModule mime_module>,在</IfModule>前面增加
    AddType application/x-httpd-php .php .php3 .phtml .inc
    AddType application/x-httpd-php-source .phps
//找到 DirectoryIndex index.html,增加index.php
DirectoryIndex index.html index.shtml index.cgi index.php index.phtml index.php3

保存后看看httpd.conf有没有出错

[root@instance-l79ltvo6 ~]# /usr/local/apache/bin/apachectl -t
Syntax OK    //说明没问题,可以直接启动

把PHP加入环境变量

[root@instance-l79ltvo6 ~]# vim /etc/profile.d/php.sh
//加入
export PATH=$PATH:/usr/local/php/bin
//保存后赋予执行权限
[root@instance-l79ltvo6 ~]# chmod 0777 /etc/profile.d/php.sh
[root@instance-l79ltvo6 ~]# source /etc/profile.d/php.sh

停止 apache,然后重新启动 apache

[root@instance-l79ltvo6 ~]# systemctl stop httpd.service
[root@instance-l79ltvo6 ~]# systemctl start httpd.service

测试PHP

[root@instance-l79ltvo6 ~]# vim /usr/local/apache/htdocs/phpinfo.php
//加入
<?php
  phpinfo();
?>

保存后访问http://你的IP/phpinfo.php
如果成功访问到PHP的相关信息,那么PHP环境配置成功。

教程结束

本次教程本人在 CentOS 7.3 下搭建成功。

如果出现编译失败也不要灰心,一般都是缺少相关依赖,善于利用搜索引擎。如果实在不知道怎么解决,给我留言,我会在能力范围尽可能的协助解决。

使用Vagrant进行LVS/DR的实验

未分类

LVS/DR模式,数据流来的时候走VS,回去的时候调度到RS上,然后用VIP的作为源地址返回回去。

实验采用Vagrant配置网络和主机信息。Vagrant的用法可参考 Vagrant–快速搭建实验环境利器(http://www.yulongjun.com/linux/20170811-vagrant/)。

Vagrantfile配置文件:

Vagrant.configure("2") do |config|
  # config为全局配置文件
  config.vm.box = "longdream/centos7"     # 这里是我自定义的centos7模板
  config.hostmanager.enabled = true       # 启用hostmanager插件
  config.hostmanager.manage_guest = true  # 允许更新虚拟机上的hosts文件
  config.hostmanager.manage_host = true   # 允许更新主机上的hosts文件
  # 定义Client
  config.vm.define "client" do |client|
    client.vm.network "private_network", ip: "172.16.111.123"
    client.vm.hostname = "client"
    client.vm.provision "shell", inline: "sudo bash /vagrant/client.sh"
  end
  # 定义Router
  config.vm.define "router" do |router|
    router.vm.network "private_network", ip: "172.16.111.222"
    router.vm.network "private_network", ip: "192.168.111.222"
    router.vm.hostname = "router"
    router.vm.provision "shell", inline: "sudo bash /vagrant/router.sh"
  end
  # 定义VS
  config.vm.define "vs" do |vs|
    vs.vm.network "private_network", ip: "192.168.111.100"
    vs.vm.hostname = "vs"
    vs.vm.provision "shell", inline: "sudo bash /vagrant/vs.sh"
  end
  # 定义RS1
  config.vm.define "rs1" do |rs1|
    rs1.vm.network "private_network", ip: "192.168.111.101"
    rs1.vm.hostname = "rs1"
    rs1.vm.provision "shell", inline: "sudo bash /vagrant/rs1.sh"
  end
  # 定义RS2
  config.vm.define "rs2" do |rs2|
    rs2.vm.network "private_network", ip: "192.168.111.102"
    rs2.vm.hostname = "rs2"
    rs2.vm.provision "shell", inline: "sudo bash /vagrant/rs2.sh"
  end
end

Vagrantfile里每一台机器都运行了相应的脚本。

Client:

client.sh

#!/bin/bash
echo "GATEWAY=172.16.111.222" >> /etc/sysconfig/network-scripts/ifcfg-eth1
ifdown eth1 && ifup eth1

Router:

router.sh

#!/bin/bash
echo "net.ipv4.ip_forward=1" >>/etc/sysctl.conf
echo 1 > /proc/sys/net/ipv4/ip_forward

VS:

vs.sh

#!/bin/bash
echo "GATEWAY=192.168.111.222" >> /etc/sysconfig/network-scripts/ifcfg-eth1
ifdown eth1 && ifup eth1
yum install -y ipvsadm
bash /vagrant/vs-dr-wlc.sh start

vs.sh引用的vs-dr-wlc.sh来启动VS。

vs-dr-wlc.sh:

#!/bin/bash
vip=192.168.111.200
mode=g  # m为NAT模式,g为DR模式,i为tun模式
schdule=wlc
rip1=192.168.111.101
rip2=192.168.111.102
dev=lo:1
case $1 in
start)
    ifconfig $dev $vip netmask 255.255.255.255 broadcast $vip up
    ipvsadm -A -t $vip:80 -s $schdule
    ipvsadm -a -t $vip:80 -r $rip1 -$mode -w 3
    ipvsadm -a -t $vip:80 -r $rip2 -$mode -w 1
    ;;
stop)
    ipvsadm -C
    ifconfig $dev down
    ;;
*)
    echo "Usage: `basename $0` start|stop"
    exit 1
    ;;
esac

RS1

rs1.sh:

#!/bin/bash
echo "GATEWAY=192.168.111.222" >> /etc/sysconfig/network-scripts/ifcfg-eth1
ifdown eth1 && ifup eth1
yum install -y httpd
cat >/var/www/html/index.html<<EOF
Real Server 1
EOF
systemctl enable httpd
systemctl start httpd
bash /vagrant/rs-config.sh start

RS2

rs2.sh:

#!/bin/bash
echo "GATEWAY=192.168.111.222" >> /etc/sysconfig/network-scripts/ifcfg-eth1
ifdown eth1 && ifup eth1
yum install -y httpd
cat >/var/www/html/index.html<<EOF
Real Server 2
EOF
systemctl enable httpd
systemctl start httpd
bash /vagrant/rs-config.sh start

两个RS都调用的一个脚本

rs-config.sh

#!/bin/bash
vip=192.168.111.200
dev=lo:1
case $1 in
start)
    echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
    echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
    echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
    echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
    ifconfig $dev $vip netmask 255.255.255.255 broadcast $vip up
    echo "VS Server is Ready!"
    ;;
stop)
    ifconfig $dev down
    echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
    echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
    echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
    echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce
    echo "VS Server is Cancel!"
    ;;
*)
    echo "Usage `basename $0` start|stop"
    exit 1
    ;;
esac

vagrant up启动所有机器后,在Virtualbox里关掉所有虚机的eth0(vagrant创建虚机时候,默认的一个NAT网络,默认在eth0上,关闭它以防止对实验造成影响):

ifdown eth0

然后从Client虚机里运行:

bash /vagrant/client-test.sh进行测试:

#!/bin.bash
# 测试LVS
vip=192.168.111.200
for i in `seq 100`;do
    curl --connect-timeout 1 $vip
    sleep 1
done

RAID及LVM的实现

RAID介绍及创建

1、mdadm工具

mdadm [mode] <raid device> [options] <任意块设备>
   [mode] 
         -C : 创建
         -A : 装配
         -F : 监控
         管理模式
             -f : 标记指定磁盘为损坏
             -a : 添加磁盘
             -r : 移除磁盘
     -C : 创建模式
         -n# : 使用#个设备来创建此RAID
         -l# : 指明要创建的RAID级别
         -a [yes | no] : 是否自动创建设备文件
         -c : 指明块大小
         -x# : 指明空闲盘个数
         -D : 显示RAID的详细信息

先介绍一下一些常见RAID阵列

     RAID 0
             利用率为100%
             无容错能力
             最小磁盘数 2
     RAID 1  
             利用率为50%
             有冗余能力
             最少磁盘数 2
     RAID 5  
             利用率为(n-1)/n ,有一块作为备用
             有容错能力
             最少磁盘数 3
     RAID 10
             利用率为50%
             有容错能力,但每组镜像只能坏一块
             最少磁盘 4

2、创建并定义RAID设备

这里以创建RAID 5为例

开始工作: 准备系统磁盘,这里小编已经先做好了,并将系统ID改为RAID类型

如下:

Device Boot         Start         End      Blocks   Id  System
/dev/sdb1               1         262     2104483+  fd  Linux raid autodetect
/dev/sdb2             263         524     2104515   fd  Linux raid autodetect
/dev/sdb3             525         786     2104515   fd  Linux raid autodetect
/dev/sdb4             787        1048     2104515   fd  Linux raid autodetect

(1)、 在/dev下创建RAID5命名为md0,且设为开机自动创建,模式为RAID 5 使用3个设备创建此RAID,/dev/sdb4作为备用

mdadm -C /dev/md0 -a yes -l5 -n3 -x1 /dev/sdb{1,2,3,4}

(2)、 对创建的md0设备进行格式化

mke2fs -j /dev/md0

(3)、 将/dev/md0进行挂载,就可以进行使用了

到此RAID 5 很简单的就创建完毕

(4)、 可以通过命令来查看RAID的设备状况

         mdadm -D /dev/md0

        [root@Centos6 ~]#mdadm -D /dev/md0
        /dev/md0 :
         Version : 1.2
   Creation Time : Mon Aug 14 12:44:33 2017
      Raid Level : raid5                        # RAID 5模式
      Array Size : 4204544 (4.01 GiB 4.31 GB)     
   Used Dev Size : 2102272 (2.00 GiB 2.15 GB)    # 使用的设备大小
    Raid Devices : 3                            # RAID 设备数
   Total Devices : 4                            # RAID 总设备数
     Persistence : Superblock is persistent

     Update Time : Mon Aug 14 12:44:56 2017
           State : clean                        # 是否被破坏
  Active Devices : 3                            # 活动设备
 Working Devices : 4                            # 工作设备
  Failed Devices : 0                            # 损坏设备
   Spare Devices : 1                            # 空闲设备

          Layout : left-symmetric
      Chunk Size : 512K                            # chunk(块)大小

            Name : Centos6.9ymd:0  (local to host Centos6.9ymd)
            UUID : 7d8465ed:f8b2c03b:8e7e2a82:0af865ee
          Events : 18

     Number   Major   Minor   RaidDevice State
        0       8       17        0      active sync   /dev/sdb1  # 活动设备
        1       8       18        1      active sync   /dev/sdb2  # 活动设备
        4       8       19        2      active sync   /dev/sdb3  # 活动设备

        3       8       20        -      spare   /dev/sdb4        # 空闲设备

(5)、 如若在最开始创建的时候并没有备用的设备,我们可以在设备中增添新成员,增加容错能力

mdadm  -G  /dev/md0  -n4 -a /dev/add

(6)、 生成配置文件,以备我们将其停止后能够重新启动它

mdadm -Ds >> /etc/mdadm.conf 

(7)、 停止RAID设备

mdadm -S /dev/md0 

(8)、重新启动RAID设备

mdadm -As /dev/md0

3、那么创建好后,怎样删除它呢?

(1)、 首先我们需要将其卸载

umount /dev/md0

(2)、 停止RAID设备

mdadm -S /dev/md0 

(3)、 删除配置文件

rm -rf /etc/mdadm.conf

(4)、 删除RAID,清除其成员的元信息

mdadm --zero-superblock /dev/sdb{1,2,3,4}

(5)、如果在/etc/fstab文件中增加了开机自动加载的信息则还要将其删除

LVM的实现

1、基本命令

  • 创建及删除物理卷LV
pvcreate  device 
pvremove  device 
  • 创建卷组VG
vgcreate vgname device
    vgname : 为自己指定的vg名称
    -s # : 可指定PE的大小,默认为4M 
  • 管理卷组
vgextend  vgname  device  在vg内添加pv
vgreduce  vgname  device  在vg内移除pv
vgchange                  配置vg是否启动
vgremove  device          删除一个vg
vgs | vgdisplay           查看vg信息
  • 创建逻辑卷LV
lvcreate  [options] [lvname] device 
    [options]
        -L # [+][G,g,T,t,M,m] 改变LV容量
        -l #% VG              以百分比形式改变容量
        -n name               设置LV名字
lvextend          增加LV容量
lvreduce          削减LV容量
lvremove          删除一个LV
lvresize          调整lv容量大小
lvs | lvdisplay   查看lv信息
  • 挂载使用逻辑卷

2、接下来我们开始逻辑卷的创建

将自己创建的过程及相关命令列出

如下:

  • 创建pv
[root@Centos6 ~]#pvcreate /dev/sdb{1..4}
Physical volume "/dev/sdb1" successfully created
Physical volume "/dev/sdb2" successfully created
Physical volume "/dev/sdb3" successfully created
Physical volume "/dev/sdb4" successfully created

[root@Centos6 ~]#pvs
PV         VG   Fmt  Attr PSize PFree 
/dev/sdb1  vg0  lvm2 a--u 2.00g     0 
/dev/sdb2  vg0  lvm2 a--u 2.00g     0 
/dev/sdb3  vg0  lvm2 a--u 2.00g     0 
/dev/sdb4  vg0  lvm2 a--u 2.00g 16.00m
  • 创建vg
[root@Centos6 ~]#vgcreate vg0 /dev/sdb{1..4}
Volume group "vg0" successfully created

[root@Centos6 ~]#vgs
VG   #PV #LV #SN Attr   VSize VFree
vg0    4   1   0 wz--n- 8.02g 16.00m
  • 创建lv
[root@Centos6 ~]#lvcreate -L +8G -n lv0 vg0
Logical volume "lv0" created.

[root@Centos6 ~]#lvdisplay 
--- Logical volume ---
LV Path                /dev/vg0/lv0
LV Name                lv0
VG Name                vg0
LV UUID                NfI3VT-QXop-Ju9V-qdzT-jZOj-Okmz-lcDAAf
LV Write Access        read/write
LV Creation host, time Centos6.9ymd, 2017-08-17 06:11:37 +0800
LV Status              available
# open                 0
LV Size                8.00 GiB
Current LE             2048
Segments               4
Allocation             inherit
Read ahead sectors     auto
- currently set to     256
Block device           253:0

3、LV扩容及缩减

(1)、扩容LV

  • 创建系统ID是LVM的分区

这里以/dev/sdc1为例

  • 将/dev/sdc1变成物理卷
pvcreate /dev/sdc1
  • 将其加入卷组中
vgcreate vg0 /dev/sdc1
  • 扩容LV
lvextend  -L +#G  /dev/vg0/lv0
  • 同步文件系统(当在磁盘上看不到增加的容量时可用)
resize2fs  /dev/vg0/lv0 #G 

也可将4、5合并成以下命令来代替

lvextend -r -L +#G  /dev/vg0/lv0

(2)、缩减LV

  • 卸载已经挂载的lv
umount
  • 强制进行磁盘检测
e2fsck -f /dev/vg0/lv0
  • 同步文件系统
resize2fs  /dev/vg0/lv0  #G
  • 缩减LV
lvreduce  -L #G  /dev/vg0/lv0 
  • 挂载重新使用
mount

4、如何跨主机迁移卷组到新系统

首先要确定被迁移的卷组是否与新卷组名称冲突,如果冲突则先要更改名字

vgrename  vg0   newvg0name
  • 先卸载被挂载的逻辑卷
umount
  • 禁用卷组中的所有逻辑卷
vgchange -an vg0
  • 让卷组处于导出状态
vgexport  vg0
  • 关机拆除硬盘,出入新的系统

  • 导入转移的vg0

vgimport vg0
  • 激活逻辑卷
vgchange -ny vg0 
  • 挂载使用

5、逻辑卷快照

快照,顾名思义,保存当前的状态,以备以后能够还原到当前的状态,其原理这里不再赘述

  • 为现有的LV创建快照
lvcreate  -s  -l 60  -n /dev/vg0/data  -p r /dev/vg0/lv0 
    -s : 创建快照
    -l : 使用PE数量,作为快照区使用
    -n : 快照区设备名称
    -p r : 设定快照为只读属性
  • 挂载快照
mount -o ro /dev/vg0/data  /mnt/snap 
  • 恢复快照
lvconvert --merge  /dev/vg0/data

kvm直接拷贝qcow2虚机文件到另一个虚机启动的问题

场景是这样的:

  • 实体机是kvm,上面跑了A和B两台虚机。

  • A 机 IP 是 192.168.85.40,然后胡乱鼓捣,里面乱作一团,然后想恢复。

  • B 机 IP 是 192.168.85.47,全新安装。

  • 想直接把 B 机的qcow2文件翻版覆盖A机,然后启动改个 ip 即可。

结果是不行,用 virsh console A 上去查看,发现 eth0 没了,多了一个 eth1 。

于是明白,网卡冲突了,解决方法如下:

vi /etc/udev/rules.d/70-persistent-net.rules  
# This file was automatically generated by the /lib/udev/write_net_rules
# program, run by the persistent-net-generator.rules rules file.
#
# You can modify it, as long as you keep each rule on a single
# line, and change only the value of the NAME= key.

# PCI device 0x1af4:0x1000 (virtio-pci)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="f0:00:c0:a8:55:2f", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"

# PCI device 0x1af4:0x1000 (virtio-pci)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="f0:00:c0:a8:55:28", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"  

看到了吧,eth1 的地址是 f0:00:c0:a8:55:28 ,把这行删掉,把上面 eth0 的地址改成 f0:00:c0:a8:55:28即可。

顺手改了ifcfg-eth0和network,重启一切搞定。

KVM使用virsh命令行调整虚拟机的cpu和内存

1、virsh edit centos73 (更改前要将virsh shutdown centos73 )
找到“memory”和“vcpu”标签,将

<name>centos73</name>
  <uuid>2220a6d1-a36a-4fbb-8523-e078b3dfe795</uuid>
  <memory unit='KiB'>2097152</memory>
  <currentMemory unit='KiB'>2097152</currentMemory>
  <vcpu placement='static'>1</vcpu>

改为:

<name>centos73</name>
  <uuid>2220a6d1-a36a-4fbb-8523-e078b3dfe795</uuid>
  <memory unit='KiB'>3145728</memory>
  <currentMemory unit='KiB'>3145728</currentMemory>
  <vcpu placement='static'>2</vcpu>

virsh define /etc/libvirt/qemu/centos73.xml 重定义使配置生效

重启虚拟机

virsh start centos73 --console

查看原配置信息

[root@localhost kvm]# virsh dominfo centos734
Id:             -
Name:           centos73
UUID:           2220a6d1-a36a-4fbb-8523-e078b3dfe795
OS Type:        hvm
State:          shut off
CPU(s):         1
Max memory:     2097152 KiB
Used memory:    2097152 KiB
Persistent:     yes
Autostart:      disable
Managed save:   no
Security model: none
Security DOI:   0

调整后信息:

[root@localhost kvm]# virsh dominfo centos73
Id:             -
Name:           centos73
UUID:           2220a6d1-a36a-4fbb-8523-e078b3dfe795
OS Type:        hvm
State:          shut off
CPU(s):         2
Max memory:     3145728 KiB
Used memory:    3145728 KiB
Persistent:     yes
Autostart:      disable
Managed save:   no
Security model: none
Security DOI:   0

centos7上kvm的安装与使用

一般都是虚拟机上使用的,请先将虚拟机的虚拟化打开

安装准备好需要的工具

xshell 和 xmanager(windows上安装的远程管理工具)

xshell下载地址:http://sw.bos.baidu.com/sw-search-sp/software/2e288f0f946d9/Xshell5_5.0.1326.exe

xmanager下载地址:http://sw.bos.baidu.com/sw-search-sp/software/7c666e01b0271/xmgr5_5.0.1049_wm.exe

请先都安装好在进行后面的操作

打开xshell –》文件 –》属性 –》隧道 设置成这样

未分类

使cpu支持虚拟化

更改的时候请关闭虚拟机,不然是无法修改的

未分类

inter的cpu

grep 'vmx' /proc/cpuinfoBashCopy

amd的cpu

grep 'svm' /proc/cpuinfoBashCopy

只要有内容就表示支持

安装依赖及kvm

yum  -y  install epel-release
yum -y install qemu-kvm libvirt virt-manager 
yum -y install dejavu-lgc-sans-fonts   #这个是解决xmanager乱码的问题BashCopy

运行下面的命令,有如下返回值表示成功

[root@localhost ~]# lsmod | grep kvm
kvm_intel             170181  0 
kvm                   554609  1 kvm_intel
irqbypass              13503  1 kvmBashCopy

启动服务

systemctl start libvirtd
systemctl enable libvirtdBashCopy

启动创建虚拟机窗口

virt-managerBashCopy

未分类

先不急,上传镜像上去,我很懒,直接上传到/root/下面了

[root@localhost ~]# ls
anaconda-ks.cfg  CentOS-7-x86_64-Minimal-1611.isoBashCopy

使用xmanager的图形来创建centos 7

未分类

直接点前进

未分类

选择镜像

未分类

未分类

找到后直接打开

未分类

继续

未分类

提示可能没权限,不管,直接yes

未分类

后面是配额,我们继续前进

未分类

磁盘大小

未分类

可以继续前进

这一步很关键,不选择好的话,后面无法使用键盘,我们勾上,选择在安装前先进行配置,下面还有个网卡选择,因为需要花点时间测试,网卡的部分将在下一文章讲解

未分类

然后点击finish

出来下面的,记得选择跟下图一样的配置,点击apply

未分类

然后就会看到下面的安装画面

未分类

基础教程安装完成。

Kubernetes的Cron Job定时任务小试

Kubernetes集群使用Cron Job管理基于时间的作业,可以在指定的时间点执行一次或在指定时间点执行多次任务。 一个Cron Job就好像Linux crontab中的一行,可以按照Cron定时运行任务。

定时任务对我们并不陌生,例如Linux的crontab,各种编程语言都内置了定时任务支持,这在我们应用开发中比较常见,但这种定时任务在分布式系统中使用会有限制,因此需要分布式计划任务。 Kubernetes的CronJob可以理解为Kubernetes对分布式计划任务的支持。

在使用Cron Job之前需要确认Kubernetes集群的版本>=1.5,因为它还处于alpha,所以还需要对kube-apiserver加入启动参数–runtime-config=batch/v2alpha1=true,开启batch/v2alpha1。 下面我们来试验一下,试验的Kubernetes集群的版本为1.6.8。

在加入启动参数–runtime-config=batch/v2alpha1=true后,要重启kube-apiserver, kube-controller-manager, kube-scheduler,创建crontab才会被调度

创建Cron Job

创建一个简单的CronJob,每隔1分钟打印当前的时间并”say Hello”,cronjob.yaml:

apiVersion: batch/v2alpha1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: alpine
            args:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure

下面创建这个CronJob:

kubectl create -f cronjob.yaml
cronjob "hello" created

查看这个CronJob的状态:

kubectl get cronjob hello
NAME      SCHEDULE      SUSPEND   ACTIVE    LAST-SCHEDULE
hello     */1 * * * *   False     0         <none>

从上面的输出看这个cronjob还没有被调度,等大约1分钟再次查看:

kubectl get jobs --watch
NAME               DESIRED   SUCCESSFUL   AGE
hello-1503321060   1         1            2m
hello-1503321120   1         1         1m
hello-1503321180   1         1         36s


kubectl get cronjob
NAME      SCHEDULE      SUSPEND   ACTIVE    LAST-SCHEDULE
hello     */1 * * * *   False     0         Mon, 21 Aug 2017 21:14:00 +0800

删除Cron Job

 kubectl delete cronjob hello
cronjob "hello" deleted

kubectl delete -f cronjob.yaml

删除命令会停止已经创建出来的作业,当时正在运行的作业不会被被停止,同时Job和Pod不会被删除:

kubectl get jobs
NAME               DESIRED   SUCCESSFUL   AGE
hello-1503321060   1         1            7m
hello-1503321120   1         1            6m
hello-1503321180   1         1            5m
hello-1503321240   1         1            4m
hello-1503321300   1         1            3m
hello-1503321360   1         1            2m
hello-1503321420   1         1            1m

需要手动删除上面的job,job被删除,它创建出来的Pod也会被删除掉。

使用kubectl delete jobs –all可以删除当前namespaces下所有的job

当前Cron Job的限制

当前一个CronJob在执行期间“大约”创建一个Job,之所以说“大约”是因为在特殊的情况下可能会创建两个或没有Job被创建。Kubernetes官方正在试图使这种情况尽量少发生,但目前还不能保证完全杜绝。 因此如果我们现在使用它,那么Job应该被我们设计成幂等的。

GitHub是如何无缝迁移到Kubernetes的?

【编者的话】全球最大的代码托管和编程社交网络GitHub,近期已经在开发、SRE等团队的配合下将服务切换到Kubernetes,因为其坐拥千万用户和亿级代码仓库,这可不是一个小工程,文章介绍了GitHub迁移到Kubernetes的整个过程。

在过去的一年中,GitHub逐步发展了运行Ruby On Rails应用的基础设施,该应用负责github.com和api.github.com。目前所有的WEB和API请求都由运行在GitHub Metal Cloud上的Kubernetes容器集群中。

将关键应用迁移到Kubernetes是一个非常有意思的挑战,今天就给大家分享下:

为什么尝试改变——释放SRE工程师

在此之前,主要的Ruby On Rails应用(github/github)还类似于8年前:“Unicorn processes”由Ruby进程管理器调用运行在Puppet-managed的“God”。同样的,部署ChatOps如同第一次引入时所作:Capistrano在每个前端服务器上建立SSH连接,然后更新代码,重新启动应用,当峰值请求负载超过可用的前端CPU容量时,GitHub站点的SRE会释放额外的容量,并将其添加到活动前端服务器池当中。

未分类

在近几年中,虽然基本生产方法没有太大的变化,不过GitHub本身有了很多改变如:新的功能、更大的社区、更多的员工、以及更多的需求。所以这也就产生了很多新的问题,许多团队想将其负责的功能从某个大的应用中提取出来,形成一个可以独立运行和部署的小型服务。伴随着运行服务数量的增加,SRE团队开始为数十个其他应用提供类似的配置,从而增加了在服务器维护、配置和其他工作上花费的时间,但这些工作又和改进整个GitHub的工作流程没有直接关联。

新服务因为它们的复杂性和SRE团队的时间问题,需要几天、几周或者几个月的时间来进行部署,随着时间的推移,一些问题逐渐显现:这种方法并没有为工程师提供他们需要的灵活性,以继续构建世界级的服务。

工程师们需要一个自助平台,可以在上面试验、部署和扩展新的服务,还需要同样的平台来满足Ruby On Rails应用的需求,这样工程师或机器人就能以秒、天或更长的时间来分配额外的计算机资源去响应需求的变化。

为了满足这些需求,SRE、平台和开发者体验团队开始了一个联合项目:每天数十次地将github.com和api.github.com的代码部署到Kubernetes集群。

为什么是Kubernetes?

为了评估“平台即服务”的工具,GitHub仔细研究了Kubernetes,它是Google的一个项目,用于自动化部署、扩展和管理容器化应用的开源系统,通过以下几点为Kubernetes特性做了评估:该项目获得了火热的开源社区支持,首次运行实践(允许部署小型集群和应用在最初的几个小时),大量关于设计的经验。

因此迅速地扩大了实验力度和范围:立了一个小的项目去构建Kubernetes集群和部署工具,用来支持即将到来的Hack Week从而获得一些实际场景中的经验,GitHub内部对这个项目反映非常积极。

为什么从github/github开始?

在项目最初阶段,GitHub做了一个深思熟虑的决定,关键性工作负载的:github/github迁移,许多因素促成了这一决定,比较重要的几点是:

  • 深入了解GitHub中运行的这个应用软件在迁移过程中很有用
  • 需要自助扩展工具来处理持续的增长
  • 希望确保开发习惯和模式适用于大型应用和较小的服务
  • 可以更好地将应用与开发、Staging、生产、Enterprise、和其他环境隔离
  • 迁移一个关键的、高知名度的工作负载可以激发信心,鼓励GitHub进一步采用Kubernetes

考虑到我们计划迁移的工作负载极为关键,我们需要在利用其交付实际生产流量之前建立起充分的运营信心。

通过引入审查实验室以实现快速迭代并建立信心

作为迁移的一部分,进行了一些设计以及原型,并验证了前端服务器使用Kubernetes的基础服务如:Pod、部署和服务。通过在容器中运行gitub/github现有的测试套件,可以对这种新设计进行一些验证,但仍需观察这个容器是如何成为更大的Kubernetes资源一部分的,很快就清楚地认识到,在验证阶段,对Kubernetes和打算运行的服务进行探索性测试环境是必备的。

与此同时,项目成员观察到,现有的github/github抓取请求的模式已经开始显示出增长十分困难的迹象,部署速度和工程师的数量成正比,使用几个额外的部署环境作为验证拉取请求到github/github的部分过程也是如此,在工作高峰时,功能齐全的部署环境数量往往是固定的,这就降低了部署拉取请求的过程,工程师门经常要求在“Branch Lab”中测试更多的子系统,同时允许多名工程师同时进行部署,但每个工程师只能启动一个“Unicorn Process”,所以只在测试API和UI变更时有用,因为这些需求重叠很多,所以可以将这些项目结合起来,并开始在github/github上开发一个新的基于Kubernetes/github的部署环境,被称之为:Review Lab。

在构建Review Lab的过程中,还发布了几个子项目:

  • 在AWS VPC上运行的Kubernetes集群管理使用了Terraform & Kops
  • 一组Bash集成测试使用短暂的Kubernetes集群,后来在项目开始时大量使用,增强对Kuberbetes的信心。
  • 一个github Dockerfile/github
  • 对内部CI平台的增强,用来支持构建和将容器发布到容器注册中心
  • YAML表示50+Kubernetes资源,签入github/github
  • 对内部部署应用的增强,支持将Kubernetes的资源从一个存储库部署到Kubernetes的命名空间,以及从内部存储库中创建Kubernetes
  • 该服务结合了Haproxy和Consul-Template,将Unicorn Pods路由到现有的服务,发布服务信息。
  • 一种读取Kubernetes事件的服务,并将异常事件发送给内部服务跟踪系统
  • 一种名为kube-me且与Rpc兼容的服务,通过聊天向用户公开一组有限的kubectl命令。

最终的结果是一个基于聊天的界面,用于为任何拉取请求创建GitHub的独立部署,一旦请求通过了所有需要的CI任务,用户即可部署他们的请求:

未分类

如同之前的“Branch Lab”一样,实验室在最后一次部署后就被清理掉,由于每个实验室都是在其Kubernetes名称空间中创建的,清理工作就像删除名称空间一样简单,部署系统会在需要时自动执行。

Review Lab是一个成功的项目,积累了许多经验和成果,在为工程师提供这种环境之前,还为Kubernetes集群设计提供了必要的验证基础和原型环境,以及Kubernetes资源的设计和配置,这些资源现在用以描述github/github的工作负载,在发布后,它帮助工程师建立了信心,GitHub非常满意这个环境赋予工程师实验和通过自助的方式去解决问题。

未分类

Metal Cloud上的Kubernetes

随着Review Lab的发布后,注意力就转移到了github.com上,为了满足关键服务的性能的可靠性需求(依赖于低延迟访问其他数据服务),需要构建Kubernetes的基础设施,去支持在物理数据中心和POP中运行的云计算,同样,有十几个子项目:

  • 关于容器网络,因为一个及时且详尽的帖子,GitHub选择了Calico,其提供了需要在IPIP模式下快速发送一个集群的功能,与此同时也提供了可以在以后的网络基础设施中进行探索的灵活性。
  • 通过多次阅读Kelesyhightower写的《Kubernetes the hard way》,GitHub将一些手动操作的服务器组装到了一个临时的Kubernetes集群中,此集群通过了相关测试。
  • 还构建了一些小工具,为每个集群生成所需的CA和配置,格式可以由Puppet和Secret Systems 使用。
  • 对两个实例配置进行了处理:Kubernetes节点和Kubernetes Apiservers,这种方式允许用户提供已经配置的集群名称,以便在规定的时间内引入。
  • 构建了一个小型的Go服务,用于消耗容器日志,将Key/Value格式的元数据附加到每一行,并将它们发送到主机的本地Syslog端点。
  • 加强内部负载均衡服务,用来支持Kubernetes Node Port。

这些工作并没有白费,都通过了内部验收测试的集群,因此,GitHub的信心十足,同样的一组Inputs(由Review Lab使用的Kubernetes资源),相同的数据集(网络服务Review Lab连接到VPN上),同样的工具都会产生类似的结果,不到一周,虽然大部分的时间都花费在了内部通信和排序上,但对迁移产生了非常重大的影响:可以将整个工作负载从运行在AWS上的Kubernetes集群迁移到一个运行在GitHub数据中的集群。

提升信心

Kubernetes集群在Github Metal Cloud上的成功和可复制性,所以是时候对“Unicorn”进行部署来替代当前前端服务器池了,在GitHub,工程师及其团队通过创建一个Flipper特性去验证新功能是很常见的做法,若可行即选择它,然后加强部署系统再去部署一套新的Kubernetes资源,github-produciton名称空间和现有的生产服务器,提高GLB支持员工请求路由到不同的后端:基于Flipper-infuenced的cookie,允许员工在任务控制栏的一个按钮上选择实验Kubernetes后端。

未分类

来自内部用户的负载可以帮助发现问题、修复BUG,并开始适应Kubernetes的生产,在此期间,通过模拟未来想要执行的应用、编写运行手册和执行Failure Tests来增强信心,还将少量的生产流量路由到这个集群,去确认对于负载下性能和可靠性的设定,从每秒100个请求开始,然后扩展到github.com和api.github.com请求的10%,在几个模拟试验中曾短暂地停止用来重新评估完全迁移的风险。

未分类

Cluster Groups

因为一些Failure Tests导致了意料之外的结果,特别是模拟单个Apiserver节点故障的测试破坏了集群,这种方式对运行工作负载的可用性造成了负面影响,根据调查显示,这些测试没有取得决定性的效果,但帮助识别出相关的破坏可能是一个相互作用的各种客户连接到Kubernetes Apiserver(像Calico-Agent Kubelet Kube-Proxy,Kube-Controller-Manager)和内部负载均衡器的行为在一个Apiserver节点中的失败,因为检测到Kuberntes集群降级可能会破坏服务,所以开始关注了每个站点上运行的关键应用,并自动化地将请求从一个不健康的集群迁移到其他健康的集群。

类似的工作已经放在GitHub的流程图中,支持此应用部署到多个独立运营的网站,和其他积极的方式进行取舍。最终选定的设计是:使用部署系统支持多个“分区”增强它通过一个定制的支持提供集群乏味内配置Kubernetes资源注释,放弃现有的联合解决方案,允许使用业务逻辑已经出现在GitHub的部署系统。

从10%到100%

有了集群组,GitHub逐渐将前端服务器转换为Kubernetes节点,并增加了路由到Kubernetes的流量,与其他一些工程师团队一起,在一个多月的时间内完成了前端的转换,同时,在这此期间保持了预计的性能和可接受的错误率。

未分类

在迁移过程中,遇到了一直持续至今的问题:在高负载/或高利用率的容器中,一些Kubernetes节点会出现内核错误并会重启,虽然GitHub对这种情况不是很满意,而且进行了最高优先级的排查,但还是很高兴地看到Kubernetes能够自动地绕过这些故障,并继续在错误范围内服务流量。

GitHub进行了一些Failure Tests,模拟了与echo c/proc/sysrq触发相似的内核错误,这是一个很有用的补充。

未来

本文的灵感来自于将此应用迁移到Kubernetes的经验,并且期待着更多的迁移,虽然在第一次迁移的范围被有意限制在无状态的工作负载中,但对在Kubernetes上尝试运行有状态的服务模式抱有很大兴趣。

在项目的最后阶段,GitHub还发布了一个工作流,用于将新的应用和服务部署到类似的Kubernetes集群中。工程师们几个月以来已经在此集群中部署了数十个应用,每一个都需要SRE的配置管理和支持,有了自助式的应用供应工作流,SRE可以将更多的时间花在向工程团队的其他成员交付基础设施产品上去支持最佳实践,为每个人构建更快,更有弹性的GitHub体验。