FreeSWITCH中文网,电话机器人开发网 ,微信订阅号:

FreeSWITCH及VOIP,Openser,电话机器人等产品中文技术资讯、交流、沟通、培训、咨询、服务一体化网络。QQ群:293697898

在Docker上搭建PostGreSQL流复制


tags:王鹏冲 Docker PostgreSQL 创建时间:2017-03-19 14:43:38

转自于: http://mp.weixin.qq.com/s/riwYwYn0VUUBDX56qCVyyQ

Not why but how to run DataBase in Docker 之 在Docker上搭建PostGreSQL流复制

微信首发:数据库技术圈

2017年春节后,几篇关于Docker和数据库的文章在朋友圈流传较广。

话说一位老外首先发表了他的意见 《为什么数据库不适合跑在容器里面》 https://myopsblog.wordpress.com/2017/02/06/why-databases-is-not-for-containers/ 里面列举了他认为容器技术不适合运行数据库的7个原因。

后来午夜咖啡的blog发表了一篇博文: 《2016年容器技术思考:Docker, Kubernetes, Mesos 将走向何方》http://jolestar.com/container-ecosystem/ 这篇文章较为全面地阐述了他对容器的技术生态圈的发展前景所做的思考,非常值得细细咀嚼。其中有一句话很鲜明地告诉那些还将docker与虚拟机相提并论的同学二者的本质差别: 传统虚拟机封装的目标是操作系统,为操作系统提供虚拟化硬件环境,而容器封装的目标是应用进程,其中内嵌的操作系统只是应用的依赖而已。

我想午夜咖啡在发表上述博文时,应该还没有看《why-databases-is-not-for-containers》这篇文章。

所以后来他又专门发表了一篇博文《论数据库容器化的目标和价值》 http://jolestar.com/the-containerized-value-of-database/

大家不妨将这三篇博文参照来看,仁者见仁智者见智,可能你也不会认同所有观点。但我个人觉得一些论据还是比较充分的,比如说老外说的数据丢失、网络问题,难道他不知道docker可以支持volume映射、host网络吗?

我的朋友圈里面的DBA们,有传统金融公司的,也有互联网行业的,也有物流、制造行业的,大家在转发评价时或者在群里讨论时,总是感觉对数据库要不要跑在docker里面,docker给我们能带来什么价值和好处,或者跑在docker上对数据库架构的高可用、高可靠带来什么不利因素都有自己的看法。

我个人的看法是,纸上得来终觉浅,绝知此事要躬行,是骡子是马拉出来遛遛。

我们要以开放的心态来对待新的技术和架构,况且docker已经不算新了。 我们可以先在开发测试环境实施基于容器技术的数据库架构,坑踩过了,觉得稳定了,觉得确实在你的企业环境内比传统架构更容易扩展、易部署、易做到devops,再逐步推广到生产环境非关键系统,再到关键系统,这样一个渐进的演进过程。

所以,今天这个文章我们就来在docker上面溜溜看PostgreSQL的流复制怎么搭建。

环境:

Host1 192.168.11.1

Host2 192.168.11.2

操作系统:CoreOS Container Linux

题外话:

CoreOS可以说是趁着容器技术的春风火起来的一个操作系统,它的设计非常有独创,尤其是两个分区滚动patch升级OS的方案,可以解决系统管理员长期以来要不定期实施停机OS patch维护的痛处(当然CoreOS割接时也要重启一下,不过仅仅是需要重启一下)。不过现在它和Docker公司决裂了,CoreOS也在发展自己的技术生态圈。

有兴趣的同学可以看看这个: http://danielcompton.net/2014/12/02/modular-integrated-docker-coreos#rd

我在hub.docker上查到的官方的PostgreSQL的image是基于debain Jessie这个OS的,我们需要的是ubuntu OS,而且还有一些客户化的配置需求,所以要自己先build一个PostgreSQL的image。

一、 创建客户化的PostgreSQL镜像:

1,以下在宿主机器(pg的主库所在机器host1)操作:
建立PG的bulid image的环境,

docker pull ubuntu 
---简单吧,一条命令你在CoreOS上面就有了一个ubuntu的OS可以用了。  
mkdir -p /backup/postgresql    
mkdir -p /storage/docker/postgresql



docker run -it 
--name build_pg_img \
-v /storage/docker/postgresql:/var/lib/postgresql \
-v /backup/postgresql:/backup \
ubuntu \
/bin/bash

---这样我们就跑起来了一个操作系统为ubuntu的容器,并且将宿主机的两个本地目录mount到了容器内部。

2,如下操作均为容器内部的操作:

连接到刚才创建的容器:

Docker exec –it build_pg_img /bin/bash

在ubuntu容器里面执行安装软件包:

apt-get update    
apt-get install vim    
apt-get install postgresql-9.5

---So easy,安装完毕PG 9.5

查看pg已经安装完毕

root@3fd84ba76393:~# dpkg -l |grep post    
      postgresql-9.5 
      postgresql-client-9.5   
      postgresql-client-common
      postgresql-common 
      postgresql-contrib-9.5
    root@3fd84ba76393:~#

3,切换到postgres用户

root@3fd84ba76393:~# more /etc/passwd |grep post    
postgres:x:105:109:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash    
root@3fd84ba76393:~# su - postgres    
postgres@3fd84ba76393:~$

4,编辑postgres用户的profile
vi .bash_profile

#!/bin/bash    
PGHOME=/usr/lib/postgresql/9.5    
export PGHOME    
export PGPORT=5432    
export PGDATA=/var/lib/postgresql/data    
PATH=$PGHOME/bin:$PATH:$HOME/bin    
export PATH    
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PGHOME/lib    
export LD_LIBRARY_PATH

5,初始化PG数据库目录

cd /var/lib/postgresql/    
mv 9.5 9.5_bak   ------我们不使用安装时的PG库 
mkdir data    
initdb -D /var/lib/postgresql/data     
cd /var/lib/postgresql/data    
mkdir pg_log pg_archlog

6,配置postgresql.conf参数

vi $PGDATA/postgresql.conf
此处省略具体的参数配置,无甚区别。

7,配置pg_hba.conf

vi $PGDATA/pg_hba.conf    
host  all    all    192.168.0.0/16    md5    
host replication  repuser   192.168.0.0/16    md5

8,启动数据库

pg_ctl start -D /var/lib/postgresql/data

9,创建扩展

create extension pg_stat_statements;

10,停止数据库,退出容器

pg_ctl stop -D /var/lib/postgresql/data -m fast    
exit    
exit

---为什么敲2个exit呢,第一个exit退出postgres,第二个exit退出root(登录到容器时的初始用户,也就是退出了容器)

11,以下在宿主机器host1操作:
查看刚才跑的容器的信息:

docker ps -a |grep build_pg_img

12,创建基础镜像:

docker commit build_pg_img pg9.5_template

------此命令基于我们刚才跑的name为“build_pg_img”的container,创建了一个name为“pg9.5_template”的image。此后docker images命令即可以看到该新创建的image。 但是这个镜像还缺少ENTRYPOINT,无法直接在start container时就让PG运行起来,还需要先启动容器,再在容器内部start PG库。而这明显达不到我们的需求。

13,编辑dockerfile

vi Dockerfile    
FROM  pg9.5_template    
USER postgres    
ENV PGHOME /usr/lib/postgresql/9.5    
ENV PGPORT 5432    
ENV PGDATA /var/lib/postgresql/data    
ENV PATH $PGHOME/bin:$PATH    
ENV LD_LIBRARY_PATH=$PGHOME/lib:$LD_LIBRARY_PATH    
EXPOSE 5432    
CMD ["/usr/lib/postgresql/9.5/bin/postgres", "-D", "/var/lib/postgresql/data"]

更多Dockerfile语法参考: https://docs.docker.com/engine/reference/builder/

14,创建新镜像

docker build -t eg_postgresql .

15,基于新镜像eg_postgresql来启动新的pg容器:

docker run 
--name pg_pri \
-v /storage/docker/postgresql:/var/lib/postgresql \
-v /backup/postgresql:/backup \
-p 5436:5432 \
-d eg_postgresql

说明:我们这里使用了docker默认的bridge网络,并指定了端口映射,这样其它机器上的应用就可以通过该宿主机的IP+5436端口来访问容器内的5432端口的PG库。

host1 # docker ps  |grep pg_pri    
6ccecb527eaa        eg_postgresql       "/usr/lib/postgresql/"   9 seconds ago       Up 9 seconds   5432/tcp            pg_pri    
host1 #

16,进入容器,进入之后默认就是postres用户

host1 # docker exec -it pg_pri /bin/bash
此时使用psql即可连接到pg库内部。

postgres@6ccecb527eaa:/$ ps -ef|grep post                                                         
postgres     1     0  0 07:42 ?        00:00:00 /usr/lib/postgresql/9.5/bin/postgres -D /var/lib/postgresql/data    
postgres     6     1  0 07:42 ?        00:00:00 postgres: logger process       
postgres     8     1  0 07:42 ?        00:00:00 postgres: checkpointer process       
postgres     9     1  0 07:42 ?        00:00:00 postgres: writer process       
postgres    10     1  0 07:42 ?        00:00:00 postgres: wal writer process       
postgres    11     1  0 07:42 ?        00:00:00 postgres: autovacuum launcher process       
postgres    12     1  0 07:42 ?        00:00:00 postgres: archiver process       
postgres    13     1  0 07:42 ?        00:00:00 postgres: stats collector process       
postgres    14     0  0 07:43 ?        00:00:00 /bin/bash    
postgres    22    14  0 07:43 ?        00:00:00 ps -ef    
postgres    23    14  0 07:43 ?        00:00:00 /bin/bash    
postgres@6ccecb527eaa:/$     
postgres@6ccecb527eaa:/$ psql
psql (9.5.6)
Type "help" for help.
postgres=#

17,怎么以root用户进入容器? 因为我们的dockerfile里面指定过user是postgres,所以默认进入容器就是postgres用户,如果想要以root用户进入容器的方式,不能在容器内部直接su – root,会报错,要这样做:

docker exec -u root -it pg_pri /bin/bash

18,将镜像打包

docker save -o eg_postgresql.tar eg_postgresql

19,传输到pg从库所在的机器上

scp eg_postgresql.tar core@192.168.11.2:/tmp/.

20,在pg从库机器(host2)上load image

docker load -i eg_postgresql.tar

这样在host2上我们就可以使用此image来run新的container了。

二、以下搭建主从流复制:

在pg主库机器host1上操作 1, 进入主库容器

host1 # docker exec -it pg_pri /bin/bash

2,主库创建流复制用户

CREATE USER repuser replication LOGIN CONNECTION LIMIT 3 ENCRYPTED PASSWORD 'repuser';

3, 主库打开备份:

select pg_start_backup('Replition work');

4,退出容器,在宿主机器上操作数据文件的备份:

cd /storage/docker/postgresql
tar cvf data.tar data
scp data.tar core@192.168.11.2:/tmp/.

5,进入容器,主库结束备份

select pg_stop_backup(), current_timestamp;

6,在pg从库机器host2上操作:

mkdir -p /backup/postgresql
mkdir -p /storage/docker/postgresql
cp /tmp/data.tar /storage/docker/postgresql/.
tar xvf data.tar
cd /storage/docker/postgresql/data
删除slave端(从master端拷过来的)的pid文件    
rm -f $PGDATA/postmaster.pid

7,编辑从库recovery.conf文件

cd /storage/docker/postgresql/data
vi recovery.conf
standby_mode = 'on'
primary_conninfo = 'host=192.168.17.61 port=5436 user=repuser password=repuser keepalives_idle=60'
trigger_file = '/var/lib/postgresql/primary_down'

8, 启动从库容器

docker run 
--name pg_slv \
-v /storage/docker/postgresql:/var/lib/postgresql \
-v /backup/postgresql:/backup \
-p 5436:5432 \
-d eg_postgresql

host2# docker ps |grep pg_slv
    830b2ea66753        eg_postgresql       "/usr/lib/postgresql/"   About a minute ago   Up About a minute   0.0.0.0:5436->5432/tcp   pg_slv

9,进入从库容器

host2# docker exec -it pg_slv /bin/bash

 postgres@830b2ea66753:/$ ps -ef|grep post                                                        postgres     1     0  0 09:18 ?        00:00:00 /usr/lib/postgresql/9.5/bin/postgres -D /var/lib/postgresql/data
    postgres     7     1  0 09:18 ?        00:00:00 postgres: logger process   
    postgres     8     1  0 09:18 ?        00:00:00 postgres: startup process   recovering 000000010000000000000009
    postgres     9     1  0 09:18 ?        00:00:00 postgres: checkpointer process   
    postgres    10     1  0 09:18 ?        00:00:00 postgres: writer process   
    postgres    11     1  0 09:18 ?        00:00:00 postgres: wal receiver process   streaming 0/9000060
    postgres    12     1  0 09:18 ?        00:00:00 postgres: stats collector process   
    postgres    38     0  0 09:19 ?        00:00:00 /bin/bash
    postgres    46    38  0 09:19 ?        00:00:00 ps -ef
    postgres    47    38  0 09:19 ?        00:00:00 grep post
    postgres@830b2ea66753:/$ psql
    psql (9.5.6)
    Type "help" for help.

    postgres=#

万事大吉,已经可以正常看到wal receiver process了,现在,你可以在主库建表,测试是否会正常同步到从库了。

那么,如何在Docker的环境内配置PostgreSQL的HA、监控、备份呢? 敬请期待下文。



上海老李,QQ:1354608370,FreeSWITCH QQ群: