使用Nginx 和Supervisor在Linux服务器上部署Tornado

Nginx 安装: sudo apt-get install nginx

Nginx 安装后用浏览器进入127.0.0.1就可以看到nginx的欢迎页了

nginx 常用命令

  1. sudo service nginx start 启动nginx
  2. sudo service nginx stop 停止nginx
  3. sudo service nginx restart 重启nginx
  4. sudo service nginx reload 重新加载配置文件

未分类

Supervisor 安装: sudo apt-get install supervisor

部署步骤:

  • Tornado项目路径 : /home/你的用户名/Tornado项目文件夹名称/main.py

  • 在/etc/nginx/下 创建nginx.conf配置文件
    这里我们使用8000-8003四个端口,进行端口转发 配置文件编写要注意main.py所在位置要写对,即下面配置文件中的中文

user root;
worker_processes auto;
pid /run/nginx.pid;

events {
    worker_connections 768;
    multi_accept on;
    use epoll;
}
http {
    # Enumerate all the Tornado servers here
    upstream frontends {
        server 127.0.0.1:8000;
        server 127.0.0.1:8001;
        server 127.0.0.1:8002;
        server 127.0.0.1:8003;
    }

    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    access_log /var/log/nginx/access.log;

    keepalive_timeout 65;
    proxy_read_timeout 200;
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    gzip on;
    gzip_min_length 1000;
    gzip_proxied any;
    gzip_types text/plain text/html text/css text/xml
               application/x-javascript application/xml
               application/atom+xml text/javascript;
    proxy_next_upstream error;

    server {
        listen 80;

        # Allow file uploads
        client_max_body_size 50M;

        location ^~ /static/ {
            root /home/用户名/项目文件夹名/;
            if ($query_string) {
                expires max;
            }
        }
        location = /favicon.ico {
            rewrite (.*) /static/favicon.ico;
        }
        location = /robots.txt {
            rewrite (.*) /static/robots.txt;
        }

        location / {
            proxy_pass_header Server;
            proxy_set_header Host $http_host;
            proxy_redirect off;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Scheme $scheme;
            proxy_pass http://frontends;
        }
    }
}
  • 编写supervisor配置文件

  • 进入supervisor配置文件夹 cd /etc/supervisor/conf.d/

  • 创建tornados.conf

[group:tornadoes]
programs=tornado-8000,tornado-8001,tornado-8002,tornado-8003

[program:tornado-8000]
command=python /home/用户名/项目文件夹名/main.py --port=8000
directory=/home/用户名/项目文件夹名
user=root
autorestart=true
redirect_stderr=true
stdout_logfile=/var/log/tornado.log
loglevel=info

[program:tornado-8001]
command=python /home/用户名/项目文件夹名/main.py --port=8001
directory=/home/用户名/项目文件夹名
user=root
autorestart=true
redirect_stderr=true
stdout_logfile=/var/log/tornado.log
loglevel=info

[program:tornado-8002]
command=python /home/用户名/项目文件夹名/main.py --port=8002
directory=/home/用户名/项目文件夹名
user=root
autorestart=true
redirect_stderr=true
stdout_logfile=/var/log/tornado.log
loglevel=info

[program:tornado-8003]
command=python /home/用户名/项目文件夹名/main.py --port=8003
directory=/home/用户名/项目文件夹名
user=root
autorestart=true
redirect_stderr=true
stdout_logfile=/var/log/tornado.log
loglevel=info
  • 其中/var/log/tornado.log为日志文件目录
    然后先重载nginx的配置文件 sudo service nginx reload
    重启 nginx : sudo service nginx restart
    supervisor开启所有进程: sudo supervisorctrl restart all

再次打开127.0.0.1后可以看到项目已经成功部署。

Linux下的守护进程工具-Supervisor

简介:没有

安装

sudo apt-get install supervisor

(其实我是用Mint的软件管理器安装的……)

配置

参考帖子:

详解supervisor使用教程 http://www.jb51.net/article/128676.htm

supervisor 从安装到使用 http://www.jianshu.com/p/3658c963d28b

使用 Supervisor 进行进程管理 http://www.jianshu.com/p/2a48b2c987e0

执行命令

sudo supervisord
sudo supervisorctl start/stop/restart RROGRAM_NAME
sudo supervisorctl reload
sudo supervisorctl status

配置文件模板

我的配置文件在/etc/supervisor/supervisord.conf
我的配置模板:

[program:ssr]
command = python local.py -c /home/jerry/opt/shadowsocksr-manyuser/shadowsocks/shadowsocksr.json
stdout_logfile=/tmp/ssr.log
stdout_logfile_backups=2 ;默认为10 
stdout_capture_maxbytes=1MB 

[program:drcom]
command = python2 /home/jerry/opt/DRCOM_PY/latest-wired.py
stdout_logfile=/tmp/drcom.log
stdout_logfile_backups=2 ;默认为10 
stdout_capture_maxbytes=1MB 
autostart= false

通用模板

;[program:theprogramname]
;command=/bin/cat              ; the program (relative uses PATH, can take args)
;process_name=%(program_name)s ; process_name expr (default %(program_name)s)
;numprocs=1                    ; number of processes copies to start (def 1)
;directory=/tmp                ; directory to cwd to before exec (def no cwd)
;umask=022                     ; umask for process (default None)
;priority=999                  ; the relative start priority (default 999)
;autostart=true                ; start at supervisord start (default: true)
;startsecs=1                   ; # of secs prog must stay up to be running (def. 1)
;startretries=3                ; max # of serial start failures when starting (default 3)
;autorestart=unexpected        ; when to restart if exited after running (def: unexpected)
;exitcodes=0,2                 ; 'expected' exit codes used with autorestart (default 0,2)
;stopsignal=QUIT               ; signal used to kill process (default TERM)
;stopwaitsecs=10               ; max num secs to wait b4 SIGKILL (default 10)
;stopasgroup=false             ; send stop signal to the UNIX process group (default false)
;killasgroup=false             ; SIGKILL the UNIX process group (def false)
;user=chrism                   ; setuid to this UNIX account to run the program
;redirect_stderr=true          ; redirect proc stderr to stdout (default false)
;stdout_logfile=/a/path        ; stdout log path, NONE for none; default AUTO
;stdout_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
;stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
;stdout_capture_maxbytes=1MB   ; number of bytes in 'capturemode' (default 0)
;stdout_events_enabled=false   ; emit events on stdout writes (default false)
;stderr_logfile=/a/path        ; stderr log path, NONE for none; default AUTO
;stderr_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
;stderr_logfile_backups=10     ; # of stderr logfile backups (default 10)
;stderr_capture_maxbytes=1MB   ; number of bytes in 'capturemode' (default 0)
;stderr_events_enabled=false   ; emit events on stderr writes (default false)
;environment=A="1",B="2"       ; process environment additions (def no adds)
;serverurl=AUTO                ; override serverurl computation (childutils)

; The below sample eventlistener section shows all possible
; eventlistener subsection values, create one or more 'real'
; eventlistener: sections to be able to handle event notifications
; sent by supervisor.

进程管理工具Supervisor(二)Events

supervisor可以当做一个简单的进程启动、重启、控制工具使用,也可以作为一个进程监控框架使用,作为后者,需要使用supervisor的Events机制。

Event Listeners

supervisor对子程序的监控通过叫做event listener的程序实现。supervisor控制的子程序状态发生变化时,就会产生一些事件通知,event listener可以对这些事件通知进行订阅。

event listener本身也是作为supervisor的子程序运行的。事件通知协议的实现基于event listener子程序的stdin和stdout。supervisor发送特定格式的信息到event listener的stdin,然后从event listener的stdout获得特定格式的输出,从而形成一个请求/应答循环。

配置

event listener的配置放置于配置文件中的[eventlistener:x]块中。

[eventlistener:mylistener]
command=my_custom_listener.py
events=PROCESS_STATE,TICK_60

x是listener的名称,command是执行listener脚本的命令,events是要监控的事件类型。

event listener本身是作为supervisor的子程序运行的,所以与配置子程序[program:x]块类似,官网例子:

[eventlistener:theeventlistenername]
command=/bin/eventlistener
process_name=%(program_name)s_%(process_num)02d
numprocs=5
events=PROCESS_STATE
buffer_size=10
directory=/tmp
umask=022
priority=-1
autostart=true
autorestart=unexpected
startsecs=1
startretries=3
exitcodes=0,2
stopsignal=QUIT
stopwaitsecs=10
stopasgroup=false
killasgroup=false
user=chrism
redirect_stderr=false
stdout_logfile=/a/path
stdout_logfile_maxbytes=1MB
stdout_logfile_backups=10
stdout_events_enabled=false
stderr_logfile=/a/path
stderr_logfile_maxbytes=1MB
stderr_logfile_backups=10
stderr_events_enabled=false
environment=A="1",B="2"
serverurl=AUTO

事件通知协议

一个event listener可以处于三种状态,ACKNOWLEDGED、READY、BUSY,只有在READY状态下才可以接收事件通知。

event listener启动时处于ACKNOWLEDGED状态,直到event listener向stdout中输出“READYn”字符串为止。

event listener向stdout中输出“READYn”之后就处于READY状态,supervisor会向处于READY状态的listener发送listener订阅的事件通知。

listener接收事件通知之后就处于BUSY状态,期间listener对接收到的事件通知进行处理,处理结束后向stdout输出“RESULT 2nOK”或者“RESULT 4nFAIL”,前者代表处理成功,后者代表处理失败。

supervisor收到OK或者FAIL输出后,就将event listener的状态置于ACKNOWLEDGED。FAIL的事件通知会被缓存然后再次发送。

event listener的状态处于ACKNOWLEDGED后可以退出执行,也可以继续执行,继续执行就可以向stdout输出“READYn”形成一个循环。

supervisor向listener发送的事件通知由两部分组成,header和body,由”n”换行符分开。

一个header例子:

ver:3.0 server:supervisor serial:21 pool:listener poolserial:10 eventname:PROCESS_COMMUNICATION_STDOUT len:54

ver:协议版本

server:supervisor的标识符,由[supervisord]块中的identifier选项设置。

serial:event的序列号

pool:listener的pool的名字。

poolserial:event在pool中的的序列号

eventname:event类型名称

len:header后面的body长度。

一个body例子:

processname:foo groupname:bar pid:123
This is the data that was sent between the tags

processname:事件所属的子进程名字

groupname:子进程所属组名

pid:子进程pid

一个简单的listener脚本,listener.py:

import sys

def write_stdout(s):
    # only eventlistener protocol messages may be sent to stdout
    sys.stdout.write(s)
    sys.stdout.flush()

def write_stderr(s):
    sys.stderr.write(s)
    sys.stderr.flush()

def main():
    while True:
        # 进入READY状态
    ┆   write_stdout('READYn')
    ┆   # 读取事件通知的header
    ┆   line = sys.stdin.readline()
    ┆   write_stderr(line)
        # 获取body长度,读取body
    ┆   headers=dict([x.split(':') for x in line.split() ])
    ┆   data = sys.stdin.read(int(headers['len']))
    ┆   write_stderr(data+'n')
        # 发送OK进入ACKNOWLEDGED状态
    ┆   write_stdout('RESULT 2nOK')
if __name__ == '__main__':
    main()

在conf.d目录中建立一个listener配置文件mylistener.conf:

[eventlistener:mylistener]
command=python listener.py
directory=/thedirectoroflistener.py
user=user
events=PROCESS_STATE,TICK_5
stdout_logfile=/path/to/mylistener_stdout.log
stderr_logfile=/path/to/mylistener_stderr.log

启动:

ubuntu:$ sudo supervisorctl start all
mylistener: started
celerybeat: started
ubuntu:$ sudo supervisorctl status
celerybeat                       RUNNING   pid 87729, uptime 0:00:20
mylistener                       RUNNING   pid 87728, uptime 0:00:20

监控就开始了,可以到日志中查看事件通知的内容:

ver:3.0 server:supervisor serial:15361 pool:mylistener poolserial:15361 eventname:PROCESS_STATE_RUNNING len:73
processname:mylistener groupname:mylistener from_state:STARTING pid:87728
ver:3.0 server:supervisor serial:15362 pool:mylistener poolserial:15362 eventname:TICK_5 len:15
when:1514313560
ver:3.0 server:supervisor serial:15364 pool:mylistener poolserial:15364 eventname:PROCESS_STATE_RUNNING len:73
processname:celerybeat groupname:celerybeat from_state:STARTING pid:87729

可以根据自己的需要设定监控的事件类型,然后根据不同的事件类型和内容做出不同的应变,具体的事件类型可以官网查看。

python的supervisor.childutils模块对header和body的处理进行了包装:

def get_headers(line):
    return dict([ x.split(':') for x in line.split() ])

def eventdata(payload):
    headerinfo, data = payload.split('n', 1)
    headers = get_headers(headerinfo)
    return headers, data

def get_asctime(now=None):
    if now is None: # for testing
        now = time.time() # pragma: no cover
    msecs = (now - long(now)) * 1000
    part1 = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(now))
    asctime = '%s,%03d' % (part1, msecs)
    return asctime

class ProcessCommunicationsProtocol:
    def send(self, msg, fp=sys.stdout):
        fp.write(ProcessCommunicationEvent.BEGIN_TOKEN)
        fp.write(msg)
        fp.write(ProcessCommunicationEvent.END_TOKEN)

    def stdout(self, msg):
        return self.send(msg, sys.stdout)

    def stderr(self, msg):
        return self.send(msg, sys.stderr)

pcomm = ProcessCommunicationsProtocol()

class EventListenerProtocol:
    def wait(self, stdin=sys.stdin, stdout=sys.stdout):
        self.ready(stdout)
        line = stdin.readline()
        headers = get_headers(line)
        payload = stdin.read(int(headers['len']))
        return headers, payload

    def ready(self, stdout=sys.stdout):
        stdout.write(PEventListenerDispatcher.READY_FOR_EVENTS_TOKEN)
        stdout.flush()

    def ok(self, stdout=sys.stdout):
        self.send('OK', stdout)

    def fail(self, stdout=sys.stdout):
        self.send('FAIL', stdout)

    def send(self, data, stdout=sys.stdout):
        resultlen = len(data)
        result = '%s%sn%s' % (PEventListenerDispatcher.RESULT_TOKEN_START,
                               str(resultlen),
                               data)
        stdout.write(result)
        stdout.flush()

listener = EventListenerProtocol()

listener脚本可以方便的写做:

import sys

from supervisor import childutils

def write_stdout(s):
    # only eventlistener protocol messages may be sent to stdout
    sys.stdout.write(s)
    sys.stdout.flush()

def write_stderr(s):
    sys.stderr.write(s)
    sys.stderr.flush()

def main():
    while True:
    ┆   headers, payload = childutils.listener.wait()
    ┆   write_stderr(payload+'n')
    ┆   childutils.listener.ok(sys.stdout)

if __name__ == '__main__':
    main()

进程管理工具Supervisor(一)简介与使用

Supervisor是用Python开发的一套client/server架构的进程管理程序,能做到开机启动,以daemon进程的方式运行程序,并可以监控进程状态等等。

linux进程管理方式有传统的rc.d、新兴的upstart、systemd等,与这些相比,Supervisor有着自己的特点。

便利性

使用rc.d管理进程的时候,一是要写耗时耗力的脚本,二是管理的进程挂掉的话不会自动重启。

而supervisor要启动子进程,只需要将子进程的启动命令写入配置文件即可,配置自动重启子进程也很方便。

精确

supervisor作为父进程监控子进程,得到的子进程状态是很准确的。

授权

一般要管理linux进程的话,特别是在一些“low” tcp端口,比如1024以下端口中运行的程序,都需要root权限。

而以root权限启动supervisord后,一般的用户可以在一个简单的shell或者web界面中获取supervisord控制的子进程运行状态,并通过stop、start、restart的命令控制子进程的运行。

进程组

supervisor可以对子进程以start all或者restart all命令的方式进行统一管理。

中央集中式管理

supervisor可以在同一个地方启动、停止或者监视管理的进程。既可以单独的控制一个进程,也可以一起控制一组进程。

管理的时候,既可以本地管理,又可以远程连接,提供命令行接口与web页面接口。

高效性

supervisor是通过fork/exec的方式启动子进程的,子进程挂掉的话,操作系统会立即通知supervisor。

兼容性

除了windows,其他操作系统平台都可运行supervisor。supervisor使用python编写,不需要c编译器。

组件

supervisord

supervisor的服务器端,负责启动子程序,响应客户端发来的命令,重启子程序,记录子程序stdout和stderr的日志,处理Event。

配置文件一般是名为/etc/supervisord.conf的ini文件。

supervisorctl

supervisor的命令行客户端,提供一个类shell接口,用户可以使用supervisorctl连接不同的supervisord进程,查看子进程状态,start、stop子进程,获取控制的子进程列表。

客户端可以使用unix socket或者tcp socket与服务端进行通讯,通过配置文件中的[supervisorctl]段进行配置。

Web Server

使用tcp socket启动supervisord的时候,提供的一个访问supervisor的web接口。

url地址通过配置文件中的[inet_http_server]进行设置。

XML-RPC Interface

一个XML-RPC接口

下载

可以使用setuptools或者pip下载:

easy_install supervisor
or
pip install supervisor

ubuntu中使用apt下载:

apt-get install supervisor

配置文件

运行echo_supervisord_conf命令可以在shell中显示一份supervisor配置文件样本。配置一般是放在文件/etc/supervisord.conf的,所以可以将配置输入到配置文件中:

echo_supervisord_conf > /etc/supervisord.conf

上述命令需要root权限,如果没有权限或者想另置配置文件地址,可以在当前目录生成:

echo_supervisord_conf > supervisord.conf

然后启动时使用-c选项指定配置文件即可:

supervisord -c supervisord.conf

启动

首先配置要启动的子进程,可以在supervisord.conf中配置,也可以单独配置,supervisord.conf中的include配置:

[include]
files = /etc/supervisor/conf.d/*.conf

所以可以在/etc/supervisor/conf.d/目录下,以.conf作为扩展名为子进程建立单独的配置文件,比如建立一个foo.conf文件:

[program:foo]
command=/bin/cat

上述是最简单的配置了,foo为子进程名称,command是子进程运行命令。

重启supervisor使配置生效:

service supervisor restart

或者直接执行启动supervisord:

$BINDIR/supervisord

启动foo子进程:

supervisorctl start foo

一个实际例子,启动celery beat服务,建立celerybeat.conf文件:

; ================================
;  celery beat supervisor example
; ================================

[program:celerybeat]
; Set full path to celery program if using virtualenv
command=celery beat -A myapp --schedule /var/lib/celery/beat.db --loglevel=INFO

; remove the -A myapp argument if you aren't using an app instance

directory=/path/to/project
user=nobody
numprocs=1
stdout_logfile=/var/log/celery/beat.log
stderr_logfile=/var/log/celery/beat.log
autostart=true
autorestart=true
startsecs=10

; Causes supervisor to send the termination signal (SIGTERM) to the whole process group.
stopasgroup=true

; if rabbitmq is supervised, set its priority higher
; so it starts first
priority=999

启动:

$ supervisorctl start celerybeat
celerybeat: started

celery beat服务开始运行了:

[2017-12-22 07:13:47,904: WARNING/ForkPoolWorker-1] 32
[2017-12-22 07:13:47,908: INFO/ForkPoolWorker-1] Task tests.tasks.add[77706e41-83c1-4545-922b-b77a57205ef5] succeeded in 0.00359446300718s: None
[2017-12-22 07:13:57,903: INFO/MainProcess] Received task: tests.tasks.add[3f9c7c88-61aa-44cc-a517-14f32305ad64] 
[2017-12-22 07:13:57,907: WARNING/ForkPoolWorker-1] 32
[2017-12-22 07:13:57,910: INFO/ForkPoolWorker-1] Task tests.tasks.add[3f9c7c88-61aa-44cc-a517-14f32305ad64] succeeded in 0.00268728499941s: None
[2017-12-22 07:14:07,903: INFO/MainProcess] Received task: tests.tasks.add[90e4277b-7041-4c3a-905c-1a5e16272d31] 
[2017-12-22 07:14:07,907: WARNING/ForkPoolWorker-1] 32
[2017-12-22 07:14:07,910: INFO/ForkPoolWorker-1] Task tests.tasks.add[90e4277b-7041-4c3a-905c-1a5e16272d31] succeeded in 0.0029478570068s: None

配置不正确的话,会报supervisor ERROR (spawn error)错误,可以使用tail命令看下错误日志:

supervisorctl tail celerybeat stdout

查看管理的子进程运行状态:

$ supervisorctl status
celerybeat                       RUNNING   pid 66802, uptime 0:12:59

关闭子进程:

supervisorctl stop celerybeat

不加参数的直接运行supervisorctl命令,会进入supervisor客户端的交互终端进行操作。

要通过web页面访问supervisor,可以添加以下配置:

[inet_http_server]
port = 127.0.0.1:9001
username = username
password = yourpwd

浏览器访问127.0.0.1:9001,输入配置的用户名、密码,进入页面:

未分类

Docker资源管理

每个Docker容器在运行时都需要CPU, 内存以及IO资源,而运行Docker容器的主机的资源是有限的,因此如何有效的管理和使用资源就非常的重要了,因此Docker也提供了一下机制可以限制容器使用的资源。

CPU

在使用 docker run 启动容器时,提供了参数-c int或者–cpu-shares int可以帮助我们限制容器对CPU的使用。参数值是一个整数类型,用于设置当前Docker容器使用cpu的权重值(默认为1024)。这是一个相对值,每个容器能够使用的cpu, 取决于它的cpu shares 占所有容器cpu share的比例: 例如:

docker run --name "container1" -c 1024 image
docker run --name "container2" -c 512 image

在上述情况下,如果二者都需要内存,那么 container1 分配到两倍于 container2 的CPU资源。

另外需要注意,这种按权重分配 CPU 只会发生在 CPU 资源紧张的情况下。当CPU还有足够的空闲资源时,是没有此限制的。

内存

我们知道内存包括 实际的物理内存 和 交换内存(swap), 因此 Docker也分别提供了参数来控制内存的使用。

物理内存

在使用 docker run 启动容器时,提供参数-m bytes或者–memory bytes可以帮助我们限制容器对内存的使用。

这里的 bytes 指的是以字节为单位的最大使用限额,指的是明确的限额,而不是一个相对值。

例如:

docker run -m 200M image

此时该容器在运行时可以使用的最大的内存值为 200M, 此时 swap 最大值是物理内存的两倍。

交换内存

在使用 docker run 启动容器时,提供参数–memory-swap bytes可以帮助我们限制容器对swap的使用。

与 -m 参数的使用方式相同,并且二者可以同时使用:

docker run -m 200M --memory-swap=300M image

创建的新镜像可以使用最多 200M 物理内存和 300M swap。

IO

IO资源同样也是操作系统的一种非常重要的资源,通常包含了对硬盘的读写,网络数据的交换等等,这里指关注对 Docker host的硬盘的读写(即block IO)。

控制容器读写硬盘的方法有以下几种:

  1. 设置容器读写硬盘资源的权重
  2. 限制bps和iops

设置权重

在使用 docker run 启动容器时,提供参数–blkio-weight int可以帮助我们控制容器读写磁盘(block IO)的优先级。

这个参数类似于使用 -c 对 cpu资源 的控制方式, 设置的是相对值,而不是绝对值。其含义和分配方式均与 -c 类似,这里就不细说了。

限制 bps 和 iops

  • bps: byte per second,每秒读写的字节数(即读写速率)
  • iops: io per second,每秒 IO 的次数

在使用 docker run 启动容器时, 提供了以下参数来加以控制:

  1. –device-read-bps,限制读某个设备时的 bps。
  2. –device-write-bps,限制写某个设备时的 bps。
  3. –device-read-iops,限制读某个设备时的 iops。
  4. –device-write-iops,限制写某个设备时的 iops。

这里的设置指的就是硬盘,磁盘等等,通过这些参数,可以严格的限制当前容器对某个存储设备的读写速度。

  • –device-read-bps和–device-write-bps参数值的格式为: :[]。device-path 指的就是设备的路径名,number是一个正整数,unit是单位,可以是kb, mb 或者gb

  • –device-read-iops和–device-write-iops参数值的格式为: :。注意这里是没有单位的,因为它表示的就是次数。

例如:

docker run -it --device-write-bps /dev/sda:30MB --device-write-iops /dev/sdb:10000 image

上述命令,限制了新容器对磁盘设备/dev/sda的每秒钟后读写的字节数(bps)为30MB, 以及对 /dev/sdb设备的读写最大次数为10000次.

docker搭建统一开发环境

背景说明:由于公司项目众多,nginx重写复杂,各种缓存等原因导致开发环境搭建很麻烦,开发效率低下。
无需本地安装docker环境。

软件清单

  • docker 服务器
  • rancher 容器管理平台
  • syncthing 文件同步

1. 准备docker环境

用一台配置还不错的服务器,安装好docker环境。

docker安装说明:https://docs.docker.com/engine/installation/

2. 安装rancher

使用rancher主要为了方便管理容器,可视化的界面可以让不会docker的人也能使用。

rancher安装说明:http://rancher.com/docs/rancher/v1.6/zh/

sudo docker run -d --restart=unless-stopped -p 8080:8080 rancher/server:stable

安装好rancher后 访问 http://:8080

3. 添加负载均衡服务

在应用添加负载均衡服务,主要为外部域名访问到不同容器。

4. 添加syncthing

刚开始本来用Samba, 但担心服务器挂掉后代码无法查看,所以才选用syncthing,就算磁盘坏掉都不用担心代码丢失。
在rancher页面上添加或直接run容器,注意需要将数据目录挂载出来

docker run --network=host 
    -v /wherever/st-cfg:/var/syncthing/config 
    -v /wherever/st-sync:/var/syncthing 
    syncthing/syncthing:latest

启动后,访问 http://:8384
使用说明:https://docs.syncthing.net/index.html

5. 本地安装syncthing

syncthing跨所有平台,下载自己系统相应的版本 https://syncthing.net/

下载实时同步插件 Syncthing-inotify https://github.com/syncthing/syncthing-inotify

启动syncthing客户端,web访问 http://127.0.0.1:8384

启动Syncthing-inotify,这样修改文件会实时同步。

添加远程设备,设置远程设备ID(操作->显示ID),服务器端和本地都需要相互添加。

6. 设置需要同步的代码

本地syncthing,添加文件夹,设名称和路径,并共享给服务端,保存。

注意:在同步文件路径根目录添加 .stignore 文件,忽略掉不需要同步的文件或文件夹。例如:

.svn
.git
.idea
down/
phperrorlog/
*.zip
testUnit/
temp/
FonDoc/
tests/
test/

客户端保存后,服务端syncthing,会自动提示有客户端共享文件,修改好服务端保存路径。

7. rancher添加web容器

启动web容器,注意代码挂载路径。也可将php和nginx配置文件挂载出来,便于实时修改。

version: '2'
services:
    dongxu-php56:
        image: dzer/php-meilele-dev:v1
        environment:
          DOCUMENT_ROOT: /app
        stdin_open: true
        volumes:
        - /data/syncthing/dongxu/meilele:/app:rw
        - /data/syncthing/meilele_nginx_conf:/usr/local/nginx/conf:rw
        - /data/syncthing/meilele_php_conf:/usr/local/php/etc:rw
        tty: true
        extra_hosts:
        - common.meilele.com:127.0.0.1
        - memcache.meilele.com:192.168.0.250
        - clubmemcache.meilele.com:192.168.0.250
        - codememc.meilele.com:192.168.0.250
        - zxmemcache.meilele.com:192.168.0.250
        - adminmemcache.meilele.com:192.168.0.250
        - wapmemc.meilele.com:192.168.0.250
        - rule.meilele.com:192.168.0.22
        - ip.meilele.com:192.169.0.250
        - ipadmemcache.meilele.com:192.168.0.250
        - imgmemcache.meilele.com:192.168.0.250
        - dcmemcache.meilele.com:192.168.0.250
        - factory.meilele.com:192.168.0.250
        - zxback.meilele.com:127.0.0.1
        - slave.meilele.com:192.168.0.23

8. rancher lb-service添加域名

在rancher lb中添加需要访问的域名,并指向相应的容器。

9. 修改本地hosts

将需要访问的域名和服务器ip 添加到 本地hosts

CentOS 7上安装Docker

脚本安装

1、使用root权限登陆系统。

2、更新系统包到最新。

yum -y update

3、执行Docker安装脚本

curl -sSL https://get.docker.com/ | sh
yum install -y docker-selinux

4、启动 Docker

systemctl start docker.service

5、验证 docker 已经正常安装

docker run hello-world

yum 安装

1、添加 yum 仓库

cat >/etc/yum.repos.d/docker.repo <<-EOF
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/centos/7
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg
EOF

2、安装 Docker 包

yum install -y docker-engine

开机自启动

systemctl enable docker.service

Ubuntu 17.04 x64 安装 Docker CE

Docker 是个划时代的开源项目,它彻底释放了计算虚拟化的威力,极大提高了应用的运行效率,降低了云计算资源供应的成本!使用 Docker,可以让应用的部署、测试和分发都变得前所未有的高效和轻松!

无论是应用开发者、运维人员、还是其他信息技术从业人员,都有必要认识和掌握 Docker,节约有限的时间。

一、系统要求

要安装Docker CE,您需要这些Ubuntu版本的64位版本:

  • Artful 17.10(Docker CE 17.11 Edge及更高版本)
  • ZESTY 17.04
  • Xenial 16.04(LTS)
  • Trusty 14.04(LTS)

Ubuntu x86_64,Linux armhf,s390x(IBM Z)和ppc64le(IBM Power)架构上支持Docker CE 。

二、卸载旧版本

老版本的Docker被称为docker或docker-engine。如果安装了这些,请将其卸载:

$ apt-get remove docker docker-engine docker.io

三、使用存储库进行安装

首次在新的主机上安装Docker CE之前,需要设置Docker存储库。之后,您可以从存储库安装和更新Docker。

  • 设置存储库

1. 更新软件包

更新apt软件包索引:

$ apt-get update

2. 设置存储库

安装软件包以允许apt通过HTTPS使用存储库:

$ apt-get install 
    apt-transport-https 
    ca-certificates 
    curl 
    software-properties-common

3. 添加GPG密钥

添加Docker的官方GPG密钥:

鉴于国内网络问题,强烈建议使用国内源,官方源请在注释中查看。

$ curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -

# 官方源
# $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

4. 设置镜像源

添加 Docker 软件源

鉴于国内网络问题,强烈建议使用国内源,官方源请在注释中查看。

然后,我们需要向 source.list 中添加 Docker 软件源

$ sudo add-apt-repository 
    "deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu 
    $(lsb_release -cs) 
    stable"


# 官方源
# $ sudo add-apt-repository 
#    "deb [arch=amd64] https://download.docker.com/linux/ubuntu 
#    $(lsb_release -cs) 
#    stable"

以上命令会添加稳定版本的 Docker CE APT 镜像源,如果需要最新或者测试版本的 Docker CE 请将 stable 改为 edge 或者 test。从 Docker 17.06 开始,edge test 版本的 APT 镜像源也会包含稳定版本的 Docker。

四、安装Docker CE

1. 更新软件包

更新apt软件包索引。

$ apt-get update

2. 安装Docker CE

安装最新版本的Docker CE,或者转到下一步安装特定版本。任何现有的Docker安装都将被替换。

$ apt-get install docker-ce

3. 列出版本

在生产系统上,您应该安装特定版本的Docker CE,而不是始终使用最新版本。此输出被截断。列出可用的版本。

$ apt-cache madison docker-ce

docker-ce | 17.12.0~ce-0~ubuntu | https://download.docker.com/linux/ubuntu zesty/stable amd64 Packages
docker-ce | 17.09.1~ce-0~ubuntu | https://download.docker.com/linux/ubuntu zesty/stable amd64 Packages
docker-ce | 17.09.0~ce-0~ubuntu | https://download.docker.com/linux/ubuntu zesty/stable amd64 Packages
docker-ce | 17.06.2~ce-0~ubuntu | https://download.docker.com/linux/ubuntu zesty/stable amd64 Packages
docker-ce | 17.06.1~ce-0~ubuntu | https://download.docker.com/linux/ubuntu zesty/stable amd64 Packages
docker-ce | 17.06.0~ce-0~ubuntu | https://download.docker.com/linux/ubuntu zesty/stable amd64 Packages

列表的内容取决于启用了哪个存储库。选择一个特定的版本进行安装。第二列是版本字符串。第三列是存储库名称,它指出了软件包来自哪个存储库,并通过扩展其稳定性级别。要安装特定版本,请将版本字符串附加到包名称,并用等号(=)将它们分开:

$ sudo apt-get install docker-ce=<VERSION>

4. 运行镜像

通过运行hello-world 映像验证是否正确安装了Docker CE 。

$ docker run hello-world

这个命令下载一个测试图像并在容器中运行。容器运行时,会打印一条信息消息并退出。

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
ca4f61b1923c: Pull complete 
Digest: sha256:445b2fe9afea8b4aa0b2f27fe49dd6ad130dfe7a8fd0832be5de99625dad47cd
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://cloud.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/engine/userguide/

五、以非root用户身份管理Docker

默认情况下,docker 命令会使用 Unix socket 与 Docker 引擎通讯。而只有 root 用户和 docker 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 root 用户。因此,更好地做法是将需要使用 docker 的用户加入 docker 用户组。

要创建docker组并添加您的用户:

1. 创建用户组

创建docker组。

$ sudo groupadd docker

2. 添加用户组

将您的用户添加到docker组中。

$ sudo usermod -aG docker $USER

3. 注销系统

注销并重新登录,如果在虚拟机上进行测试,则可能需要重新启动虚拟机才能使更改生效。

4. 运行镜像

验证您可以不运行docker命令sudo。

$ docker run hello-world

六、卸载Docker CE

1. 卸载

卸载Docker CE软件包:

$ sudo apt-get purge docker-ce

2. 删除

主机上的图像,容器,卷或自定义配置文件不会自动删除。删除所有图像,容器和卷:

$ sudo rm -rf /var/lib/docker

七、利用 commit 理解镜像构成

这条命令会用nginx 镜像启动一个容器,命名为 myweb,并且映射了 80 端口,这样我们可以用浏览器去访问这个 nginx 服务器。

$ docker run --name myweb -d -p 80:80 nginx

直接访问:http://localhost;如果使用的是 Docker Toolbox,或者是在虚拟机、云服务器上安装的 Docker,则需要将 localhost 换为虚拟机地址或者实际云服务器地址。

未分类

参考:Docker 官网 Get Docker CE for Ubuntu

https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu/#install-using-the-convenience-script

使用minikube在本机搭建kubernetes集群

Kubernetes(k8s)是自动化容器操作的开源平台,基于这个平台,你可以进行容器部署,资源调度和集群扩容等操作。如果你曾经用过Docker部署容器,那么可以将Docker看成Kubernetes底层使用的组件,Kubernetes是Docker的上层封装,通过它可以很方便的进行Docker集群的管理。今天我们使用minikube在单机上进行Kubernetes集群的部署,目的是让我们对k8s有个初步的认识。

安装docker

首先安装docker环境,不详细说明了,网上资料一大堆,可以参考官方安装文档

Mac: https://docs.docker.com/docker-for-mac/install/

Ubuntu: https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu/

CentOS: https://docs.docker.com/engine/installation/linux/docker-ce/centos/

当然,如果上面所有方法你都失败了,也可以尝试直接下载binary可执行文件,然后启动docker即可 https://docs.docker.com/engine/installation/linux/docker-ce/binaries/

安装Minikube

Mac

# 如未安装cask,自行搜索 brew安装cask
brew cask install minikube

minikube -h

Linux

# 下载v0.24.1版本
curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.24.1/minikube-linux-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/

# 也可以下载最新版,但可能和本文执行环境不一致,会有坑
curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/

minikube -h

安装Kubectl

kubectl即kubernetes的客户端,通过他可以进行类似docker run等容器管理操作

curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/

kubectl -h

启动程序

启动minikube

sudo minikube start

首次启动会下载localkube,下载过程可能会失败,会有如下提示,重试几次即可

Starting local Kubernetes v1.8.0 cluster...
Starting VM...
Downloading Minikube ISO
 64.70 MB / 140.01 MB [====================>-----------------------]  46.21% 14s
E0105 14:06:03.884826   10434 start.go:150] Error starting host: Error attempting to cache minikube ISO from URL: Error downloading Minikube ISO: failed to download: failed to download to temp file: failed to copy contents: read tcp 10.0.2.15:47048->172.217.24.16:443: read: connection reset by peer.

================================================================================
An error has occurred. Would you like to opt in to sending anonymized crash
information to minikube to help prevent future errors?
To opt out of these messages, run the command:
    minikube config set WantReportErrorPrompt false
================================================================================
Please enter your response [Y/n]:

如果下载成功,但是报了诸如VBoxManage not found这样的错误,如下

Starting local Kubernetes v1.8.0 cluster...
Starting VM...
Downloading Minikube ISO
 140.01 MB / 140.01 MB [============================================] 100.00% 0s
E0105 14:10:00.035369   10474 start.go:150] Error starting host: Error creating host: Error executing step: Running precreate checks.
: VBoxManage not found. Make sure VirtualBox is installed and VBoxManage is in the path.

 Retrying.
E0105 14:10:00.035780   10474 start.go:156] Error starting host:  Error creating host: Error executing step: Running precreate checks.
: VBoxManage not found. Make sure VirtualBox is installed and VBoxManage is in the path
================================================================================
An error has occurred. Would you like to opt in to sending anonymized crash
information to minikube to help prevent future errors?
To opt out of these messages, run the command:
    minikube config set WantReportErrorPrompt false
================================================================================
Please enter your response [Y/n]:

解决办法是安装 VirtualBox【对于windows或者mac】 再重新启动;当然如果你是Linux,也可以执行如下命令启动minikube,此时就不需要安装VirtualBox了。

因为minikube默认需要虚拟机来初始化kunernetes环境,但Linux是个例外,可以追加–vm-driver=none参数来使用自己的环境,说明见https://github.com/kubernetes/minikube#quickstart

# linux 下独有,不依赖虚拟机启动
sudo minikube start --vm-driver=none

# 如果是Mac or Windows,安装VirtualBox后再重新start即可
sudo minikube start

如果安装了虚拟机,或者使用了–vm-driver=none参数,并且下载完毕,会有如下提示运行成功

Starting local Kubernetes v1.8.0 cluster...
Starting VM...
Getting VM IP address...
Moving files into cluster...
Downloading localkube binary
 148.25 MB / 148.25 MB [============================================] 100.00% 0s
 0 B / 65 B [----------------------------------------------------------]   0.00%
 65 B / 65 B [======================================================] 100.00% 0sSetting up certs...
Connecting to cluster...
Setting up kubeconfig...
Starting cluster components...
Kubectl is now configured to use the cluster.
===================
WARNING: IT IS RECOMMENDED NOT TO RUN THE NONE DRIVER ON PERSONAL WORKSTATIONS
    The 'none' driver will run an insecure kubernetes apiserver as root that may leave the host vulnerable to CSRF attacks

When using the none driver, the kubectl config and credentials generated will be root owned and will appear in the root home directory.
You will need to move the files to the appropriate location and then set the correct permissions.  An example of this is below:

    sudo mv /root/.kube $HOME/.kube # this will write over any previous configuration
    sudo chown -R $USER $HOME/.kube
    sudo chgrp -R $USER $HOME/.kube

    sudo mv /root/.minikube $HOME/.minikube # this will write over any previous configuration
    sudo chown -R $USER $HOME/.minikube
    sudo chgrp -R $USER $HOME/.minikube

This can also be done automatically by setting the env var CHANGE_MINIKUBE_NONE_USER=true
Loading cached images from config file.

启动一个容器服务

# kube-nginx999 是要定义的容器名称 nginx:latest表明要用nginx镜像 --port=80表明容器对外暴露80端口
sudo kubectl run kube-nginx999 --image=nginx:latest --port=80

> deployment "kube-nginx999" created

查看状态

sudo kubectl get pods

NAME                             READY     STATUS              RESTARTS   AGE
nginx999-55f47cb99-46nm8         1/1       containerCreating   0          38s

稍等一分钟左右,如果你的服务一直是containerCreating状态,没有变化,那就是创建实例出现问题,如下方法查看log

sudo minikube logs

日志中出现 failed pulling image… 则是因为镜像拉取失败导致服务创建失败,原因?GFW嘛!服务在拉取自身需要的gcr.io/google_containers/pause-amd64:3.0镜像时失败了,如下报错。

Jan 05 03:52:58 minikube localkube[3624]: E0105 03:52:58.952990    3624 kuberuntime_manager.go:632] createPodSandbox for pod "nginx666-864b85987c-kvdpb_default(b0cc687d-f1cb-11e7-ba05-080027e170dd)" failed: rpc error: code = Unknown desc = failed pulling image "gcr.io/google_containers/pause-amd64:3.0": Error response from daemon: Get https://gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)

解决方法:用本地镜像替代

原理就是使用阿里云的镜像下载到本地,然后命名为minikube使用的gcr.io的同名镜像,替代远端镜像即可

# 下载阿里云镜像
docker pull registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0

# 本地命名为 gcr.io/google_containers/pause-amd64:3.0
docker tag registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0 gcr.io/google_containers/pause-amd64:3.0

重新启动服务

增加 –image-pull-policy=IfNotPresent 参数,表明优先使用本地镜像,不从远端拉取

sudo kubectl run kube-nginx999 --image=nginx:latest --port=80 --image-pull-policy=IfNotPresent

如果提示已经存在,换个名字重新执行即可。这时候查看服务状态应该是如下Running状态代表创建成功,但此时还不能访问容器

sudo kubectl get pods

NAMESPACE     NAME                             READY     STATUS             RESTARTS   AGE
default       kube-nginx999-77867567f5-48czx   1/1       Running            2          16h

发布服务

sudo kubectl expose deployment kube-nginx999 --type=NodePort

> service "kube-nginx999" exposed

查看服务地址

sudo minikube service kube-nginx999 --url

> http://127.0.0.1:30690

上面命令展示的地址即启动的nginx容器服务地址,访问 http://127.0.0.1:30690 即可出现nginx首页,服务成功启动!

PS: 访问http://localhost:30690是不可以的。

dashboard 管理后台

dashboard是kubernetes提供的容器服务管理后台,可视化界面,用来进行机器负载,集群管理,镜像扩容,配置数据等相关操作

启动dashboard

# 会打印出管理后台地址
sudo minikube dashboard --url

# 或者用下面写法,会自动打开默认浏览器,但我的一直失败,没有打开默认浏览器,没关系,执行后自己打开也行
sudo minikube dashboard

但初次会报下面的两种错误之一

# 1
Could not find finalized endpoint being pointed to by kubernetes-dashboard: Error validating service: Error getting service kubernetes-dashboard: services "kubernetes-dashboard" not found

# 2
Waiting, endpoint for service is not ready yet...
Waiting, endpoint for service is not ready yet...

如果查看log的话,会找到和pause一样的错误,即在镜像拉取的时候失败,解决方法如下,将所有kubernetes需要的镜像全部用阿里源下载到本地,然后命名为gcr.io…,来让minikube不从远端下载

如果不确定应该将tag重命名为什么的话,可以执行sudo grep ‘image:’ -R /etc/kubernetes看到默认情况下需要的镜像名以及版本号,对应去 https://dev.aliyun.com/search.html 搜索下载,然后命名为上面配置中定义的tag即可,当然,你可以在阿里云下载1.1然后重命名为1.2也没关系,差几个小版本不会有太大影响。

docker pull registry.cn-hangzhou.aliyuncs.com/google-containers/kubernetes-dashboard-amd64:v1.7.1
docker tag registry.cn-hangzhou.aliyuncs.com/google-containers/kubernetes-dashboard-amd64:v1.7.1 gcr.io/google_containers/kubernetes-dashboard-amd64:v1.8.0

docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-addon-manager:v6.4-beta.2
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/kube-addon-manager:v6.4-beta.2 gcr.io/google-containers/kube-addon-manager:v6.4-beta.2

docker pull registry.cn-shenzhen.aliyuncs.com/gcrio/k8s-dns-kube-dns-amd64:latest
docker tag registry.cn-shenzhen.aliyuncs.com/gcrio/k8s-dns-kube-dns-amd64:latest gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.14.5

docker pull registry.cn-hangzhou.aliyuncs.com/google-containers/k8s-dns-dnsmasq-nanny-amd64:1.14.5
docker tag registry.cn-hangzhou.aliyuncs.com/google-containers/k8s-dns-dnsmasq-nanny-amd64:1.14.5 gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64:1.14.5

docker pull registry.cn-hangzhou.aliyuncs.com/google-containers/k8s-dns-sidecar-amd64:1.14.5
docker tag registry.cn-hangzhou.aliyuncs.com/google-containers/k8s-dns-sidecar-amd64:1.14.5 gcr.io/google_containers/k8s-dns-sidecar-amd64:1.14.5

docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/storage-provisioner:v1.8.1
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/storage-provisioner:v1.8.1 gcr.io/k8s-minikube/storage-provisioner:v1.8.1

然后重启minikube

sudo minikube stop
sudo minikube start [--vm-driver=none] # linux没装virtualbox的情况下需要加上后面的参数

再次执行

sudo minikube dashboard --url

> http://127.0.0.1:30000/

访问 http://127.0.0.1:30000/ 即可看到操作后台

未分类

写在最后

如果你下载工具时提示下载错误,基本上就是因为GFW,所以如果你有本地ss能够科学上网的话,可以在终端里执行下面命令,让 curl wget等命令也会走代理,加快下载

export http_proxy='socks5:127.0.0.1:1080'

有个坑,执行完以后访问 127.0.0.1 也是会走代理,这时候当然要换一个tab访问即可。

使用Jenkins部署应用到Kubernetes

【编者的话】这篇文章基于去年5月进行的一次Kubernetes使用情况调查,阐述了使用Jenkins作为持续集成工具部署应用程序到Kubernetes的现状,对于大家如何进行CI/CD工具的选型有参考意义。

新的技术栈正不断交付Kubernetes开源容器编排引擎的内容。 本周我们将报告如何将应用程序实际部署到Kubernetes。 当在容器编排、持续交付流水线或配置管理工具之间进行选择时,我们2017年5月进行的Kubernetes调查的受访者经常表示他们使用编排框架来部署应用程序。 虽然有些人曾经把Kubernetes想象成可以做任何事情的瑞士军刀,但实际上他们对应用程序部署中的Kubernetes的角色有着更细致的了解。

当更直接地问到他们是否使用Jenkins将应用程序部署到Kubernetes时,45%的人表示赞成,另有36%的Kubernetes用户使用其它的持续部署(CD)流水线将应用程序部署到Kubernetes,其中GitLab CI和CircleCI是被提及最多的。请注意,调查问题的性质意味着这些信息不能用来决定市场份额,其他工具的整体采用率可能高于下图所示。

未分类

这就是说,Jenkins仍然是最常用的持续集成(CI)工具。 未来的研究将不会问是否使用Jenkins,而是会问在组织流水线中的核心地位。 在许多情况下,同一公司内的不同团队将使用竞争产品。 在其他情况下,Jenkins是更大工作流程中的一个小组件,另一个供应商的工具会是CD流水线图中的焦点。

深入挖掘一下,我们发现小公司(两到一百名员工)相对于平均情况使用Jenkins的可能性较小(38%比45%),可能是因为他们以前没有需要部署工作流的大型组织。 这与我们上周写到的一个趋势是一致的,即不同规模的团队倾向于使用不同的CI/CD工具。

受访者认为,应用程序的自动化部署是使用成熟的Kubernetes一个关键优势。 许多受访者描述了交付流水线如何与Kubernetes所带来的更大的组织变革相关联。 有人说:“在我们的早期阶段,改进开发人员的工作流程,使开发人员能够思考他们的代码是如何在生产环境中运行的,这是我们想要用Kubernetes实现的最重要的事情。”

我们知道有65%的生产环境用户在Kubernetes上运行应用程序开发工具。 在这方面,Kubernetes对于持续部署和提供“基础设施即代码”至关重要。