0%

背景

VPN(virtual private network)虚拟专用网络,目前主要能接触到的协议包括PPTP(点对点隧道协议)和L2TP(2层隧道协议)

  • PPTP(2层VPN) 由微软和3Com等公司组成的PPTP论坛开发的点对点隧道协议,基于PPP协议使用PAP或CHAP之类的加密算法。
  • L2TP(2层VPN) 是IETF基于L2F (Cisco的第二层转发协议)开发的PPTP的后续版本,是一种工业标准 Internet 隧道协议,其可以为跨越面向数据包的媒体发送点到点协议 (PPP) 框架提供封装。
    PPTP和L2TP都使用PPP协议对数据进行封装,然后添加附加包头用于数据在互联网络上的传输。PPTP只能在两端点间建立单一隧道。 L2TP支持在两端点间使用多隧道,用户可以针对不同的服务质量创建不同的隧道。L2TP可以提供隧道验证,而PPTP则不支持隧道验证。但是当L2TP 或PPTP与IPSEC共同使用时,可以由IPSEC提供隧道验证,不需要在第2层协议上验证隧道使用L2TP。PPTP要求互联网络为IP网络。L2TP只要求隧道媒介提供面向数据包的点对点的连接,L2TP可以在IP(使用UDP),桢中继永久虚拟电路 (PVCs),X.25虚拟电路(VCs)或ATM VCs网络上使用。

IPSec(3层VPN),隧道模式隧道是封装、路由与解封装的整个过程。隧道将原始数据包隐藏(或封装)在新的数据包内部。该新的数据包可能会有新的寻址与路由信息,从而使其能够通过网络传输。隧道与数据保密性结合使用时,在网络上窃听通讯的人将无法获取原始数据包数据(以及原始的源和目标)。封装的数据包到达目的地后,会删除封装,原始数据包头用于将数据包路由到最终目的地。

搭建环境

  • OS, raspbian jessie
  • 硬件,Raspbarry Pi 3B
  • ppp,2.4.6
  • pptpd,1.4.0
  • openswan,2.6.38
  • xl2tp,1.3.6

PPTP部署

软件安装

安装ppppptpd

1
2
sudo apt-get install ppp
sudo apt-get install pptpd

配置pptpd

在配置文件/etc/pptpd.conf中,增加如下内容:

1
2
localip 192.168.1.101       # 本地ip
remoteip 192.168.1.110-120 # 设置ip分配范围

*** 注:ip地址不要有冲突 ***

配置ppp

在配置文件/etc/ppp/chap-secrets中,增加用户名密码
格式: {用户名}<tab>*<tab>{密码}<tab>*

在配置文件/etc/ppp/options中,设置MTU

1
2
-mru        # 关闭MRU协商
mru 1496 # 设置MTU值为1496

ip转发配置

如果需要通过VPN访问宿主机本地网络,需要开通ip转发功能,在/etc/sysctl.conf中设置net.ipv4.ip_forward=1。并执行sudo sysctl -p使修改生效。

重启pptpd服务

sudo systemctl restart pptpd

IPsec over L2TP部署

软件安装

安装pppxl2tpdopenswan

1
2
3
sudo apt-get install ppp
sudo apt-get install xl2tpd
sudo apt-get install openswan

IPsec配置及测试

配置

/etc/ipsec.conf中,增加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
onn L2TP-PSK-NAT
rightsubnet=vhost:%priv
also=L2TP-PSK-noNAT

conn L2TP-PSK-noNAT
authby=secret
pfs=no
auto=add
keyingtries=3
rekey=no
ikelifetime=8h
keylife=1h
type=transport
left=192.168.3.100 # 本机ip
leftprotoport=17/1701
right=%any
rightprotoport=17/%any

/etc/ipsec.secrets中增加预共享密钥{本地IP}<tab>%any: PSK<tab>"{密码}"
eg: 192.168.3.100 %any: PSK "lsjflsdkfj"

关闭内核ICMP重定向

1
2
3
4
5
for abspath in /proc/sys/net/ipv4/conf/*
do
echo 0 > $abspath/accept_redirects
echo 0 > $abspath/send_redirects
done

修改/etc/sysctl.conf中的配置

1
2
3
4
5
6
7
8
9
10
net.ipv4.ip_forward = 1
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.log_martians = 0
net.ipv4.conf.default.log_martians = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.icmp_ignore_bogus_error_responses = 1

执行sudo sysctl -p立即生效

测试

使用ipsec verify验证ipsec配置。在验证前,请先重启ipsec服务sudo systemctl restart ipsec

L2TP配置

/etc/xl2tpd/xl2tpd.conf中增加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[global]

listen-addr = 192.168.3.100
ipsec saref = yes

[lns default]
ip range = 192.168.3.120-192.168.3.123
local ip = 192.168.3.100
refuse chap = yes
refuse pap = yes
require authentication = yes
name = l2tp
ppp debug = yes

pppoptfile = /etc/ppp/options.xl2tpd

length bit = yes

PPP配置

options配置

新建xl2tpd专用options,并增加内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ipcp-accept-local
ipcp-accept-remote

#ms-dns 192.168.3.1
ms-dns 8.8.8.8
ms-dns 8.8.4.4

noccp
auth
crtscts
debug
hide-password
modem
lock
proxyarp

账户配置

可复用PPTP部署中的PPP配置的账户

重启L2TP服务

sudo systemctl restart xl2tpd

参考&鸣谢

linux的ip命令和ifconfig类似,ifconfig属于net-tools套件中,ip命令属于iproute2套件中。由于net-tools中的部分命令已经长时间没有更新维护了,所以iproute2的套件大有取代net-tools套件的趋势。

NET-TOOLS IPROUTE2对比

net-tools iproute2
arp -na ip neigh
ifconfig ip link
ifconfig -a ip addr show
ifconfig –help ip help
ifconfig -s ip -s link
ifconfig eth0 up ip link set eth0 up
ipmaddr ip maddr
iptunnel ip tunnel
netstat ss
netstat -i ip -s link
netstat -g ip maddr
netstat -l ss -l
netstat -r ip route
route add ip route add
route del ip route del
route -n ip route show
vconfig ip link

参考&鸣谢

背景

docker容器的创建依赖于镜像,镜像的创建依赖于目录树,不同的linux发行版,有自己的目录树。本文主要介绍debian族发行版与fedora族发行版base image的创建。如果您想从零创建一个linux发行版base image,请参考LFS(linux from scratch)。

测试环境

  • OS Version, RHEL7.2
  • docker Version, 1.12.5

debian

debian类的操作系统包括debian、ubuntu,这一类操作系统的目录树都是用debootstrap来生成的。其中de取debian之意。

安装

可直接使用yum安装yum install debootstrap

使用

debian默认的mirror为https://deb.debian.org/debian/

debootstrap格式:
debootstrap [OPTION...] <版本> <目录树存放位置目录> [<镜像(mirror)位置>]

eg: sudo debootstrap jessie my_jessie

fedora

fedora类的操作系统包括fedora、RHEL、CentOS,这一类操作系统的目录树都是用febootstrap来生成的。其中fe取fedora之意。

安装

febootstrap并没有存在于RHEL7.2(或CentOS7.2)Repo中,目前可以直接安装6.8 repo中的febootstrap-3.21-4

febootstrap-3.21-4依赖包如下所示:

  • fakechroot-2.9-24.5.el6_1.1.x86_64
  • fakechroot-libs-2.9-24.5.el6_1.1.x86_64
  • fakeroot-1.12.2-22.2.el6.x86_64
  • fakeroot-libs-1.12.2-22.2.el6.x86_64
  • febootstrap-supermin-helper-3.21-4.el6.x86_64

使用

febootstrap格式:
febootstrap [OPTION...] <版本> <目录树存放位置目录> [镜像(mirror)位置]

eg: febootstrap -i bash 6.8 my_centos6.8 http://mirrors.163.com/centos/6.8/os/x86_64/

LFS

Todo…

镜像导入

Tar导入方式创建镜像

无论是debootstrap还是febootstrap生成的目录,其导入docker image的方法是一样的。

格式:
tar -C <目录树目录> -c . | docker import - <docker image 名称>

eg: tar -C ./my_jessie -c . | docker import - my_jessie_base

空镜像创建

格式:
tar cv --files-from /dev/null | docker import - <docker image 名称>

eg: tar cv --files-from /dev/null | docker import - empty_image

参考&鸣谢

介绍

Raspberrypi3自带wifi模块,用户可以通过配置用户名密码就可以建立wifi连接。

版本

  • 硬件,RaspberryPi3
  • OS,raspbian jessie

配置

使用wpa_passphrase <SSID> <用户名> <密码>生成wifi连接需要的用户信息
然后,将wpa_passphrase生成的信息,追加到/etc/wpa_supplicant/wpa_supplicant.conf
最后重启系统。

参考&鸣谢

介绍

Raspberrypi原产至英国,其语言及键盘布局都是GB版的。而我们目前接触到的都是US版的。所以这里需要对键盘布局进行切换一下。

版本

  • 硬件,RaspberryPi3
  • OS,raspbian jessie

键盘配置

在命令行中输入sudo raspi-config,进入Internationaliation Options,选择Change Keyboard Layout,弹出键盘配置界面。

然后选择Generic 101-key PC,在layout中选择Other,然后在Country of origin for the keyboard中选择English (US),再在Keyboard Layout页面中选择English (US, alternative international)

参考&鸣谢

介绍

Dockerfile是docker image构建脚本,是用于生成image。Dockerfile忽略大小写,使用‘#’注释,每行只执行一条指令。Dockerfile指令分为两种,构建指令和设置指令。

  • 构建指令,用于构建image,不会在image的容器上执行
  • 设置指令,用于设置image属性,会在image的容器上执行

Dockerfile指令

FROM

构建指令,用于指定基础image。该指令必须指定在Dockerfile其它指令的前面,后面的Dockerfile指令都依赖于该指令指定的image。FROM指令指定的基础image可以是官方docker hub仓库中的,也可以是位于本地仓库中的。

指令格式:FROM <image>[:<tag>]
若不指定:<tag>,默认使用:latest

MAINTAINER

构建指令,用于将image的制作者相关信息写入到image中。

指令格式:MAINTAINER <name>

RUN

构建指令,可以运行任何被基础image支持的命令。

指令格式:RUN <command>RUN ["executable","param 1","param n"]
一般用于软件安装

CMD

设置指令,用于container启动时指定的操作。该操作可以是执行自定义脚本,也可以是执行系统命令。该指令只能在文件中存在一次,如果有多个,则只执行最后一条。

指令格式:CMD <executable> <param 1> <param n>CMD ["executable", "param 1", "param n"]

ENTRYPOINT

设置指令,指定容器启动时执行的命令,可以多次设置,但是只有最后一个有效。

指令格式:ENTRYPOINT ["executable", "param 1", "param n"]ENTRYPOINT <executable> <param 1> <param n>
CMD指令和ENTRYPOINT会互相覆盖只有最后一个CMD或者ENTRYPOINT有效。

和CMD指令配合使用来指定ENTRYPOINT的默认参数,这时CMD指令不是一个完整的可执行命令,仅仅是参数部分。ENTRYPOINT指令只能使用JSON方式指定执行命令,而不能指定参数。

1
2
3
FROM centos7
CMD ["-l"]
ENTRYPOINT ["/usr/bin/ls"]

USER

设置指令,设置启动容器的用户,默认是root用户

指令格式:USER <user name>

EXPOSE

设置指令,该指令会将容器中的端口映射成宿主机器中的某个端口。需要访问容器的时候,可以不是用容器的IP地址而是使用宿主机器的IP地址和映射后的端口。首先在Dockerfile使用EXPOSE设置需要映射的容器端口,然后在运行容器的时候指定-p选项加上EXPOSE设置的端口,这样EXPOSE设置的端口号会被随机映射成宿主机器中的一个端口号。也可以指定需要映射到宿主机器的那个端口,这时要确保宿主机器上的端口号没有被使用。EXPOSE指令可以一次设置多个端口号,相应的运行容器的时候,可以配套的多次使用-p选项。

指令格式:EXPOSE <port> [<port>...]

ENV

构建指令,在image中设置一个环境变量

指令格式:ENV <key> <value>
设置了后,后续的RUN命令都可以使用,container启动后,可以通过docker inspect查看这个环境变量,也可以通过在docker run –env key=value时设置或修改环境变量。

ADD

构建指令,从src复制文件到container的dest路径。

指令格式:ADD <src> <dest>

  • <src>是相对被构建的源目录的相对路径,可以是文件或目录的路径,也可以是一个远程的文件url
  • <dest>是container中的绝对路径
    所有拷贝到container中的文件和文件夹权限为0755,uid和gid为0;如果是一个目录,那么会将该目录下的所有文件添加到container中,不包括目录;如果文件是可识别的压缩格式,则docker会帮忙解压缩(注意压缩格式);如果<src>是文件且<dest>中不使用斜杠结束,则会将<dest>视为文件,<src>的内容会写入<dest>;如果<src>是文件且<dest>中使用斜杠结束,则会<src>文件拷贝到<dest>目录下。

VOLUME

设置指令,指定挂载点。使容器中的一个目录具有持久化存储数据的功能,该目录可以被容器本身使用,也可以共享给其他容器使用。我们知道容器使用的是AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失。当容器中的应用有持久化数据的需求时可以在Dockerfile中使用该指令。

指令格式:VOLUME ["<mount point path>"]

WORKDIR

设置指令,切换目录,可多次切换(相当于cd命令),对RUNCMDENTRYPOINT生效

指令格式:WORKDIR <path>

ONBUILD

设置指令,在子镜像中执行,在构建镜像时并不执行,而是在它的子镜像中执行

指令格式:ONBUILD <Dockerfile指令>

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 第一条有效指令必须指出基础镜像
FROM my_ubuntu_03:latest

# 作者
MAINTAINER zhou bo

# 环境变量
ENV BASE_IMAGE="ubuntu:16"
ENV CURRENT_IMAGE="Simple Image"

# 安装 ssh server 端程序
RUN apt-get update
RUN apt-get install -y openssh-server

# 映射端口22
EXPOSE 22

# 启动 ssh 守护进程
CMD ["-D"]
ENTRYPOINT ["/usr/sbin/sshd"]

# 在 / 目录下挂在一个 DataFolder 目录
VOLUME ["/DataFolder"]

# 在子镜像中执行的指令
ONBUILD ENV SON_IAMGE="你永远是我儿子"

参考&鸣谢

docker-vs-vms

Deploy

Linux部署

(由于Linux发行版众多,本文以RHEL7.2为例)

单机版环境docker部署

通过yum源安装docker,yum install docker

安装完成后,使用docker version查看docker客户端和服务端版本号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ docker version
Client:
Version: 1.12.5
API version: 1.24
Go version: go1.6.4
Git commit: 7392c3b
Built: Fri Dec 16 02:23:59 2016
OS/Arch: linux/amd64

Server:
Version: 1.12.5
API version: 1.24
Go version: go1.6.4
Git commit: 7392c3b
Built: Fri Dec 16 02:23:59 2016
OS/Arch: linux/amd64

分布式环境docker部署

详细请见:docker官网关于linux环境安装部分

MacOS部署

从Docker官网上下载Docker.dmg(下载地址:https://www.docker.com/products/docker#/mac),并安装。

安装完成后,使用docker version查看docker客户端和服务端版本号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ docker version
Client:
Version: 1.12.5
API version: 1.24
Go version: go1.6.4
Git commit: 7392c3b
Built: Fri Dec 16 06:14:34 2016
OS/Arch: darwin/amd64

Server:
Version: 1.12.5
API version: 1.24
Go version: go1.6.4
Git commit: 7392c3b
Built: Fri Dec 16 06:14:34 2016
OS/Arch: linux/amd64

Container

容器创建&删除

docker create

使用docker create {选项} {镜像ID/镜像名称} {COMMAND}创建容器,返回容器ID

1
2
$ docker create -i -t --name=ubu my_ubuntu_03 /bin/bash
1af8ed9b04f8b16d264418038e1f4004b1f5512f229059646a5c9b1d20ed8404

docker run

使用docker run {选项} {镜像ID/镜像名称} {COMMMAND}创建并运行容器,run = create + start。

1
docker run -i -t ubuntu /bin/bash

docker rm

使用docker rm {容器ID/容器名称}删除已经停止的容器,使用-f参数,可删除正在运行中的容器。

容器查询

docker ps

使用docker ps列出所有运行中的容器,带-a参数,可列出所有容器(包括非运行状态的容器)

1
2
3
4
5
6
7
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1af8ed9b04f8 my_ubuntu_03 "/bin/bash" 2 minutes ago Up 3 seconds ubu
ebe0ce381aaf my_ubuntu_03 "/usr/sbin/sshd -D" 42 hours ago Up 42 hours 0.0.0.0:50022->22/tcp ubu_03_sshd
e69e9d4cdfa3 my_ubuntu_01 "/bin/bash" 43 hours ago Exited (0) 42 hours ago ubu_01
0fa200a32e8e ceph/daemon "/entrypoint.sh osd" 47 hours ago Up 47 hours ceph-osd
be0583fade06 ceph/daemon "/entrypoint.sh mon" 4 days ago Up 47 hours ceph-mon

docker inspect

使用docker inspect {容器ID/容器名称}查看容器详细信息(容器详细信息以JSON格式返回)

1
2
3
4
5
6
7
8
9
10
11
$ docker inspect ubu_03_sshd
[
{
"Id": "ebe0ce381aafa73ec679ec0dc38e8d54291378693146a65d3655dd574c76ec01",
"Created": "2016-12-26T08:00:56.73955094Z",
"Path": "/usr/sbin/sshd",
"Args": [
"-D"
],
......
]

容器启停

使用docker start/stop {容器ID/容器名称}启动或停止容器运行。

容器访问

在容器内执行命令

1
2
3
4
$ docker exec ubu ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 07:01 ? 00:00:00 /bin/bash
root 10 0 0 07:02 ? 00:00:00 ps -ef

Attach/Detach容器

1
2
$ docker attach ubu
root@1af8ed9b04f8:/#

Detach容器时,只要在command line中输入exit即可,但detach时,会导致容器停止运行。所以若不想导致容器停止运行可以使用docker exec -it ubu /bin/bash

Image

镜像创建

创建新镜像(Dockerfile)

使用Dockerfile创建镜像,首先需要选择基础镜像,然后撰写dockerfile,最后使用docker build -t {new image name}:{new image tag} [-f {dockerfile}] .创建Image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ docker build -t new_image_ubu03:v1 -f ./dockerfile/tmp.docker .
Sending build context to Docker daemon 317.7 MB
Step 1 : FROM my_ubuntu_03
---> 28b69113a240
Step 2 : MAINTAINER xxx xx "x.xxx@xxxx.com"
---> Running in ae3004ef2bd2
---> 68ab9a056fbf
Removing intermediate container ae3004ef2bd2
Successfully built 68ab9a056fbf

$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
new_image_ubu03 v1 68ab9a056fbf 14 seconds ago 304.4 MB
my_ubuntu_01 v1 e1aace2f9532 46 hours ago 304.4 MB
my_ubu base 31184d4c3c2c 47 hours ago 317.7 MB
my_ubuntu_03 latest 28b69113a240 3 days ago 304.4 MB
my_ubuntu_01 latest 800c37009cde 3 days ago 270 MB
ubuntu latest 104bec311bcd 2 weeks ago 128.9 MB
ceph/daemon latest c06ccf521c4e 6 weeks ago 1.078 GB

关于dockerfile的撰写请见《Dockerfile》

基于已有镜像创建新镜像

使用docker commit {容器名称/容器ID} {RESPOSITORY}<TAG>用已有容器创建镜像。

1
2
$ docker commit ubu_01 my_ubuntu_01:v1
sha256:e1aace2f953280326b96f31708ddf8f9f02289845e997736fcb1d0342777c72f

从docker hub上下载新镜像

在docker hub上有很多镜像,供使用者下载,用户可以使用docker search查询要下载的镜像,然后使用docker pull下载镜像。

1
2
3
4
5
$ docker pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world
Digest: sha256:0256e8a36e2070f7bf2d0b0763dbabdd67798512411de4cdcf9431a1feb60fd9
Status: Image is up to date for hello-world:latest

镜像查询

查询本地镜像

1
2
3
4
5
6
7
8
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my_ubu base 31184d4c3c2c 7 seconds ago 317.7 MB
my_ubuntu_03 latest 28b69113a240 47 hours ago 304.4 MB
my_ubuntu_01 latest 800c37009cde 2 days ago 270 MB
ubuntu latest 104bec311bcd 12 days ago 128.9 MB
ceph/daemon latest c06ccf521c4e 5 weeks ago 1.078 GB
hello-world latest c54a2cc56cbb 5 months ago 1.848 kB

查询镜像详细信息

使用docker inspect {IMAGE ID/REPOSITORY}<:{TAG}>查询镜像库的详细信息,TAG默认为“latest”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ docker inspect my_ubu:base
[
{
"Id": "sha256:31184d4c3c2cbbc56e087dfff68cad2d2d89d628a260f6789baf108345cd6c9b",
"RepoTags": [
"my_ubu:base"
],
"RepoDigests": [],
"Parent": "",
"Comment": "Imported from -",
"Created": "2016-12-28T07:30:31.500350508Z",
"Container": "",
"ContainerConfig": {
......
]

查询hub上的镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ docker search ceph
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
ceph/daemon Image containing all the Ceph daemons 29 [OK]
ceph/demo 10 [OK]
ceph/osd Ceph OSD (object storage daemon) 6 [OK]
ceph/base Ceph base image 5 [OK]
ceph/radosgw Ceph RADOSGW (S3/Swift-like service for Ceph) 4 [OK]
cdxvirt/ceph-daemon All-in-one container for cdxvirt ceph core... 2 [OK]
ceph/config Ceph bootstrap (configuration) 2 [OK]
ceph/rbd Ceph rbd (RADOS block device) CLI tool 2 [OK]
ceph/mds Ceph MDS (metadata server) 2 [OK]
ulexus/ceph-osd DEPRECATED: development is now at ceph/osd 2 [OK]
ceph/mon Ceph MON (monitor daemon) 1 [OK]
h0tbird/ceph Containerized Ceph distributed file system 1 [OK]
ceph/rados Ceph rados (reliable autonomic distributed... 1 [OK]
cdxvirt/ceph-base Ceph base container image 1 [OK]
qnib/ceph-base QNIBTerminal ceph base image 0 [OK]
qnib/ceph-mono Monolithic approach of an CEPH cluster + r... 0 [OK]
fernandosanchez/ceph-dash ceph-dash 0 [OK]
ceph/install-utils Install wrappers for common Ceph utility p... 0 [OK]
qnib/ceph-mon QNIBTerminal CEPH monitoring Image 0 [OK]
cephbuilder/ceph Docker image for building custom Ceph daem... 0 [OK]
qnib/d-ceph-fuse QNIBTerminal image (debian) mounting /ceph... 0 [OK]
ulexus/ceph-mon DEPRECATED: development is now at ceph/mon 0 [OK]
fmeppo/ceph-daemon Main container for Ceph in Docker. 0 [OK]
fmeppo/ceph-base Base container for Ceph in Docker. 0 [OK]
xenopathic/ceph-keystone Automated full-stack Ceph environment with... 0 [OK]

镜像删除

使用docker rmi {REPOSITORY/IMAGE ID}删除镜像。

1
2
3
4
5
$ docker rmi hello-world
Untagged: hello-world:latest
Untagged: hello-world@sha256:0256e8a36e2070f7bf2d0b0763dbabdd67798512411de4cdcf9431a1feb60fd9
Deleted: sha256:c54a2cc56cbb2f04003c1cd4507e118af7c0d340fe7e2720f70976c4b75237dc
Deleted: sha256:a02596fdd012f22b03af6ad7d11fa590c57507558357b079c3e8cebceb4262d7

镜像导出导入

save & load

只用于镜像(image)的导入导出文件

export & import

  • export用于容易导出成文件
  • import用于文件导入成镜像(image)

关系图

import_export

Volume

数据卷创建、删除、查询、权限

创建&权限

*** docker在创建容器时,可以创建数据卷;一旦容器运行后,就不能动态添加数据卷。若想添加需要重新创建容器。***

私有数据卷创建

docker run/create时,使用-v {容器内路径}参数在容器内创建指定的目录,并映射到其宿主机/var/lib/docker/volumes/{ID}/_data的路径下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 数据卷创建
$ docker run -it --name=ubu2 -v=/home/zhoub/docker/data ubuntu /bin/bash
# 数据卷查询
$ dccker inspect ubu2
...
"Mounts": [
{
"Name": "95868b7e6fd47927cfb7f54b35057545f4302d69ed92aa73425dffc289527b6b",
"Source": "/var/lib/docker/volumes/95868b7e6fd47927cfb7f54b35057545f4302d69ed92aa73425dffc289527b6b/_data",
"Destination": "/home/zhoub/docker/data",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
...

共享数据卷创建

docker run/create时,使用-v {宿主机路径:容器内路径:访问权限(ro/rw,默认是RW)}参数挂载数据目录或文件到容器内,宿主机与容器共享该目录,无论宿主机还是容器修改该目录后,另一方也能看到改变。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 数据卷创建
$ docker run -it --name=ubu -v=/home/zhoub/docker/data:/data ubuntu /bin/bash
# 数据卷查询
$ docker inspect ubu
...
"Mounts": [
{
"Source": "/home/zhoub/docker/data",
"Destination": "/data",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
...

数据卷删除

  • 仅使用docker rm删除容器,会导致数据卷无法删除,仍占用硬盘空间
  • 使用docker rm -v删除容器和数据卷

数据卷容器

创建数据卷容器

1
$ docker run -v /vol --name voldata ubuntu echo "Data Container"

1
$ docker create -v /vol --name voldata ubuntu echo "Data Container"

注:

  • 数据卷容器不需要运行,运行会白浪费系统资源
  • 不要下载微小镜像创建数据卷容器,只使用本机所带的镜像即可,不需要咱用额外的存储空间。

使用数据卷容器

docker run中使用--volumes-from参数为新建的容器挂载voldata数据卷容器中的/vol目录

1
$ docker run --volumes-from voldata -it --name testContainer ubuntu /bin/bash

数据卷备份

将数据卷容器中数据卷里的数据备份到指定目录中

步骤:

  1. 创建备份目录
  2. 创建容器映射备份目录到容器内,并挂载数据卷容器
  3. 在容器中将数据卷容器中的数据copy到映射的备份目录内
1
2
3
$ mkdir /tmp/backup

$ docker run --rm --volumes-from voldata -v /tmp/backup:/backup ubuntu tar cvf /backup/voldata.tar /vol

看到此处估计你已经要骂娘了,什么破Docker,连个卷管理接口都没有!以上是老版本中docker对卷的管理方法。接下来说一下新版本中docker对卷的管理。
** 一条华丽的分割线… **

新的数据卷管理

  • 卷创建
    docker volume create {options},创建卷,可指定卷名称和访问卷所使用的驱动。目前docker volume plugin支持的驱动包括:blockbridge、convoy、flocker、glusterfs、horcrux、ipfs、netshare、openstorage、quobyte
  • 卷查询
    docker volume ls,显示卷列表
    docker volume inspect {volume name},显示指定卷的详细信息
  • 卷删除
    docker rm {volume name},删除指定卷,若卷已经被容器所加载,无论容器是否出于运行状态,删除都会失败。

*** 很可惜docker新版本中还是不支持动态加载卸载数据卷 ***

Network

docker 有三种网络bridge、host、none。

  • bridge 桥接网络
  • host 复制宿主机网络
  • none 无网络,容器只有一个回环地址

网络管理

网络创建

bridge

可通过docker network create --subnet {CIDR} {network name}创建bridge网络

host

默认docker会提供一个host网络,用户不能再手动创建该网络Error response from daemon: only one instance of "host" network is allowed

none

该网络不可自创建

网络删除

可使用docker network rm {network name}删除指定网络

网络查询

使用docker network ls查看网络列表

1
2
3
4
5
6
$ docker network ls
ETWORK ID NAME DRIVER SCOPE
852c90cb4a48 bridge bridge local
bebda2efe6dc host host local
6a69c0cd935e my_net bridge local
09cf35b0a2fe none null local

使用docker network inspect {network name}查看指定网络信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$ docker network inspect my_net
[
{
"Name": "my_net",
"Id": "6a69c0cd935ef315d143f1253634b8cce2b20e8e330ce791d53d26a6a08c387f",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.100.0/24",
"Gateway": "192.168.100.1"
}
]
},
"Internal": false,
"Containers": {},
"Options": {
"com.docker.network.bridge.name": "my_net"
},
"Labels": {}
}
]

网络使用

with ‘–network’

docker create/run时,指定--network {network name}参数,默认网络使用bridge

1
$ docker run -it --name net_1 --network my_net my_ubuntu_03 /bin/bash

container复制

使用--network container:{容器名称/容器ID}将指定容器的网络及主机名复制到新容器内。

创建‘net_4’容器,并复制‘net_1’的network

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ docker run -it --name net_4 --network container:net_1 my_ubuntu_03 /bin/bash
root@5eb98cff1ec6:/# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:c0:a8:64:02
inet addr:192.168.100.2 Bcast:0.0.0.0 Mask:255.255.255.0
inet6 addr: fe80::42:c0ff:fea8:6402/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:648 (648.0 B) TX bytes:648 (648.0 B)

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

容器‘net_1’的网卡信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ docker exec -it net_1 /bin/bash
root@5eb98cff1ec6:/# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:c0:a8:64:02
inet addr:192.168.100.2 Bcast:0.0.0.0 Mask:255.255.255.0
inet6 addr: fe80::42:c0ff:fea8:6402/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:16 errors:0 dropped:0 overruns:0 frame:0
TX packets:16 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1395 (1.3 KB) TX bytes:1284 (1.2 KB)

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:4 errors:0 dropped:0 overruns:0 frame:0
TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:375 (375.0 B) TX bytes:375 (375.0 B)
  • 复制主机名
  • 复制MAC地址
  • 复制IP地址

Docker Remote API

开启Remote API

以RHEL7.2为例,开启Docker Remote API服务

  1. 修改systemd中的docker.server
    找到ExecStart项,增加-H tcp://0.0.0.0:2375允许任意客户端访问;增加-H unix:///var/run/docker.sock保证docker命令能正常使用。
    若需要使用HTTPS证书,可以增加--tls=true --tlscert=cert.pem --tlskey=key.pem详细请见
  2. 增加防火墙规则/关闭防火墙
    RHEL7.2中防火墙服务为firewalld
    eg: sudo systemctl stop firewalld
  3. 重启docker服务
    重载配置sudo systemctl daemon-reload
    重启服务sudo systemctl restart docker

API使用说明

详细请见:《Docker Remote API v1.24》

参考&鸣谢

Class

Python中也有类的概念,类中的成员函数不支持重载(overloading method),但支持重写(overiding method)。Python Class中还有很多隐含的成员函数,这些函数的首尾都是“__”开头结尾的。

隐藏的用法

构造与析构

new

创建对象时调用,返回当前对象的一个实例。

1
__new__(cls, *args, **kwargs)

init

对象建立后,第一个被调用的函数,相当于c++中的构造函数

1
__init__(self, *args, **kwargs)

del

对象销毁前,最后调用的函数,相当于c++中的析构函数

1
__del__(self, *args, **kwargs)

call

重写__call__方法后,对象当函数来使用,相当于重载了括号运算符

1
__call__(self, *args, **kwargs)

属性操作

getattr

获取属性

1
__getattr__(self, key)

setattr

创建或设置属性

1
__setattr__(self, key, value)

delattr

删除属性

1
__delattr__(self, key)

str

对象转换字符串函数

1
__str__(self)

repr

str()出来的是给人看的,repr()出来的是给Python看的,可以通过eval()重新变回一个Python对象。

1
__repr__(self)

参考&鸣谢

背景

在 *nix 环境下,若要对http server提供的RESTful接口进行测试,往往需要安装一些HTTP Client工具,然后在输入URL、参数、Method等,组成HTTP协议后发送测试。这种HTTP Client工具大都以浏览器插件形式提供。今天介绍一些curl使用方法,来替代HTTP Client。此处只是一个应用举例,关于curl更多操作请参考man手册

curl简介

curl命令是一个功能强大的网络工具,它能够通过http、ftp等方式下载文件,也能够上传文件。curl命令使用了libcurl库来实现,libcurl库常用在C程序中用来处理HTTP请求,curlpp是libcurl的一个C++封装,这几个东西可以用在抓取网页、网络监控等方面的开发,而curl命令可以帮助来解决开发过程中遇到的问题。

环境

Mac环境

  • OS : os x 10.11.6
  • curl : url 7.43.0 (x86_64-apple-darwin15.0) libcurl/7.43.0 SecureTransport zlib/1.2.5
  • openssl : OpenSSL 0.9.8zh 14 Jan 2016

Linux环境

  • OS : Red Hat Enterprise Linux Server release 7.2 (Maipo)
  • curl : curl 7.29.0 (x86_64-redhat-linux-gnu) libcurl/7.29.0 NSS/3.16.2.3 Basic ECC zlib/1.2.7 libidn/1.28 libssh2/1.4.3
  • openssl : OpenSSL 1.0.1e-fips 11 Feb 2013

Usage

HTTP请求命令格式

HTTP命令

** curl {URL}?{参数} -X {Http Method} -H “{Header信息}” -d “{body信息}” -v **

eg:

1
curl http://127.0.0.1:80/test?param=help -X PUT -H "Connection:keep-alive" -d "Hello world" -v

HTTPS请求命令格式

导入HTTPS需要的证书

*** 此处以pkcs12证书为例 ***

Mac

双击证书文件,按提示步骤导入证书文件

Linux

Linux下证书存在于/etc/pki/nssdb中,可使用certutil -d sql:/etc/pki/nssdb -L命令查询数据库中的证书,使用certutil -d sql:/etc/pki/nssdb -D -n <证书名>删除证书,使用certuil -d sql:/etc/pki/nssdb -A -t "C,," -n <证书名> -i <cer证书文件路径>添加cer证书,如果是p12证书其添加方法为p12util -d sql:/etc/pki/nssdb -i <p12证书文件>
本文中用到的证书正是p12证书,所以可用p12util去添加证书。

HTTPS命令

Mac

** curl {URL}?{参数} -k –cert {证书.p12}:{证书密码} -X {Http Method} -H “{Header信息}” -d “{body信息}” -v **
eg:

1
curl https://127.0.0.1:8787/test?param=help -k --cert cert.p12:pasword -X PUT -H "Connection:keep-alive" -d "Hello world" -v

Linux

** curl {URL}?{参数} -k -X {Http Method} -H “{Header信息}” -d “{body信息}” -v **
eg:

1
curl https://127.0.0.1:8787/test?param=help -k -X PUT -H "Connection:keep-alive" -d "Hello world" -v

参考&鸣谢

背景

  • XenServer7
  • Ceph Jewel
  • RBDSR

集成原理

rbdsr-xenserver7-integration

应用层客户端i/o通过XenServer将i/o传递给fuse或nbd内核模块,nbd通过文件socket,将i/o请求传递给rbd-nbd。rbd-nbd通过ceph-common(包括librbd和librados)将读写请求发送给Ceph集群。(fuse内部通信方式及协议目前不清楚,待后续调研清楚再更新)

安装配置步骤

依赖库安装

snappy leveldb gdisk gperftools-libs fuse fuse-libs安装

rpm列表:

  • snappy-1.1.0-3.el7.x86_64.rpm
  • leveldb-1.12.0-11.el7.x86_64.rpm
  • gdisk-0.8.6-5.el7.x86_64.rpm
  • gperftools-libs-2.4-5.el7.x86_64.rpm
  • fuse-2.9.2-6.el7.x86_64.rpm
  • fuse-libs-2.9.2-6.el7.x86_64.rpm

安装:

1
yum -y localinstall *.rpm

python-argparse 安装

python-argparse依赖rpm列表:

  • libunwind-1.1-5.el7.x86_64.rpm
  • python-backports-ssl_match_hostname-3.4.0.2-4.el7.noarch.rpm
  • python-backports-1.0-8.el7.x86_64.rpm
  • python-setuptools-0.9.8-4.el7.noarch.rpm

安装:

1
yum -y localinstall *.rpm

tar列表:
argparse-1.4.0.tar.gz
python-argparse安装:

1
2
3
tar -xzvf ./argparse-1.4.0.tar.gz
cd argparse-1.4.0
python setup.py install

ceph-common rbd-fuse rbd-nbd安装

rpm列表:

  • boost-iostreams-1.53.0-25.el7.x86_64.rpm
  • ceph-common-10.2.3-0.el7.x86_64.rpm
  • librados2-10.2.3-0.el7.x86_64.rpm
  • lttng-ust-2.4.1-1.el7.x86_64.rpm
  • python-rbd-10.2.3-0.el7.x86_64.rpm
  • rbd-fuse-10.2.3-0.el7.x86_64.rpm
  • rbd-nbd-10.2.3-0.el7.x86_64.rpm
  • python-requests-2.6.0-1.el7_1.noarch.rpm
  • python-cephfs-10.2.3-0.el7.x86_64.rpm
  • libradosstriper1-10.2.3-0.el7.x86_64.rpm
  • fcgi-2.4.0-25.el7.x86_64.rpm
  • boost-program-options-1.53.0-25.el7.x86_64.rpm
  • boost-random-1.53.0-25.el7.x86_64.rpm
  • libbabeltrace-1.2.4-3.el7.x86_64.rpm
  • librbd1-10.2.3-0.el7.x86_64.rpm
  • python-chardet-2.2.1-1.el7_1.noarch.rpm
  • python-six-1.9.0-2.el7.noarch.rpm
  • userspace-rcu-0.7.16-1.el7.x86_64.rpm
  • python-urllib3-1.10.2-2.el7_1.noarch.rpm
  • python-rados-10.2.3-0.el7.x86_64.rpm
  • librgw2-10.2.3-0.el7.x86_64.rpm
  • libcephfs1-10.2.3-0.el7.x86_64.rpm
  • boost-regex-1.53.0-25.el7.x86_64.rpm

安装:

1
yum -y localinstall *.rpm

RBDSR安装

获取RBDSR

可通过git获取或svn获取
Git事例:

1
git clone https://github.com/zhoubofsy/RBDSR-1.git

安装RBDSR

1
./install

Ceph配置

copy Ceph集群里的配置文件(/etc/ceph/ceph.conf)和 Keyring文件(/etc/ceph/ceph.client.admin.keyring)到XenServer节点的/etc/ceph/目录下
完成copy工作后,可通过ceph -s命令来确认ceph访问能力是否正常

重启XAPI

1
xe-toolstack-restart

主节点挂载

*** 注:在XenServer Master节点上需要按下述步骤挂载Ceph存储,其他非Master节点只需要执行45步 ***

1. 在ceph集群上创建链接XenServer需要的存储池

首先使用uuidgen生成uuid,然后创建存储池,存储池命名规则为“RBD_XenStorage-”前缀加uuid的方式。
eg:ceph osd pool create RBD_XenStorage-ffc44a2c-7de2-49e7-a621-8ecabdb357f4 128 128 replicated

2. 创建SR

eg:

1
# xe sr-introduce name-label="CEPH RBD Storage" type=rbd uuid=ffc44a2c-7de2-49e7-a621-8ecabdb357f4 shared=true content-type=user
  • name-label,可根据需要随意填写
  • uuid,为创建ceph存储池时使用的uuid

3. 获取host uuid

1
2
3
4
5
6
7
8
9
# xe host-list
uuid ( RO) : 267cb56e-983f-48fb-a50a-7bcb7bbbee85
name-label ( RW): xenserver-88
name-description ( RW): Default install


uuid ( RO) : 11e7e849-fd19-470e-9cb8-0c6c6781531f
name-label ( RW): xenserver90
name-description ( RW): Default install

取本机的uuid做为host uuid

4. 创建PBD

使用xe pbd-create创建PBD,默认创建方式为rbd-nbd方式,若想以rbd-fuse方式创建PBD,需要在rbd-mode参数中指定fuse。创建成功则返回PBD uuid
rbd-nbd eg:

1
2
# xe pbd-create sr-uuid=ffc44a2c-7de2-49e7-a621-8ecabdb357f4 host-uuid=11e7e849-fd19-470e-9cb8-0c6c6781531f
c51c8000-ad5f-190e-5a6c-dc12cc8f8733

rbd-fuse eg:

1
2
# xe pbd-create sr-uuid=ffc44a2c-7de2-49e7-a621-8ecabdb357f4 host-uuid=11e7e849-fd19-470e-9cb8-0c6c6781531f device-config:rbd-mode=fuse
c51c8000-ad5f-190e-5a6c-dc12cc8f8733

5. 挂载PBD

使用xe pbd-plug挂载PBD,需要指定PBD uuid。
eg:

1
# xe pbd-plug uuid=c51c8000-ad5f-190e-5a6c-dc12cc8f8733

参考&鸣谢