POSTGRESQL 远程链接的乌龙

安装了Postgresql 后,在 pg_hba.conf 中新增了远程链接的IP,远程链接依然抛出 “no pg_hba.conf entry for host “xxx.xx.xxx.xx”, user “xxx”, database “xxx”, SSL off”的错误信息,客户端无法链接

1、检查 postgresql.conflisten_addresses ,已经修改成 listen_addresses = ‘*’

2、检查防火墙,已关闭

但是错误信息依然存在,很是郁闷…

折腾了几个小时后,问题依然存在…到了晚上9点多,遗憾的关闭了电脑

第二天早上,在检查Postgresql的安装环境,顿悟,原来我安装Postgresql的过程中将 data 的文件路径设置在另外一个文件夹下了,而我一直修改的是Postgresql原生bin目录下的 pg_hba.conf ,此时,心中一万头新物种在狂奔!!!

容器之 CGroup

在 CentOS 7 中,已经通过 systemd 替换了之前的 cgroup-tools 工具,为了防止两者冲突,建议只使用 systemd ,只有对于一些不支持的,例如 net_prio ,才使用 cgroup-tools 工具。

在此,简单介绍其使用。

简介

在系统设计时,经常会遇到类似的需求,就是希望能限制某个或者某些进程的分配资源。

由此,就有了容器的概念,在容器中,有分配好的特定比例的 CPU、IO、内存、网络等资源,这就是 controller group ,简称为 cgroup ,最初由 Google 工程师提出,后来被整合进 Linux 内核中。

cgroup 本身提供了将进程进行分组化管理的功能和接口的基础结构。

使用简介

在 CentOS 7 中需要通过 yum install libcgroup libcgroup-tools 安装额外的 cgroup 工具,对系统来说,默认会挂载到 /sys/fs/cgroup/ 目录下。

----- 查看系统已经存在cgroup子系统及其挂载点
# lssubsys -am
----- 或者通过mount查看cgroup类型的挂载点
# mount -t cgroup

----- 可以命令行挂载和卸载子系统,此时再次执行上述命令将看不到memory挂载点
# umount /sys/fs/cgroup/memory/
----- 挂载cgroup的memory子系统,其中最后的cgroup参数是在/proc/mounts中显示的名称
# mount -t cgroup -o memory cgroup /sys/fs/cgroup/memory/
# mount -t cgroup -o memory none /sys/fs/cgroup/memory/

另外,在 CentOS 中有 /etc/cgconfig.conf 配置文件,该文件中可用来配置开机自动启动时挂载的条目:

mount {
    net_prio = /sys/fs/cgroup/net_prio;
}

然后,通过 systemctl restart cgconfig.service 重启服务即可,然后可以通过如下方式使用。

使用步骤

简单介绍如何通过 libcgroup-tools 创建分组并设置资源配置参数。

1. 创建控制组群

可以通过如下方式创建以及删除群组,创建后会在 cpu 挂载目录下 /sys/fs/cgroup/cpu/ 目录下看到一个新的目录 test,这个就是新创建的 cpu 子控制组群。

# cgcreate -g cpu:/test
# cgdelete -g cpu:/test

2. 设置组群参数

cpu.shares 是控制 CPU 的一个属性,更多的属性可以到 /sys/fs/cgroup/cpu 目录下查看,默认值是 1024,值越大,能获得更多的 CPU 时间。

# cgset -r cpu.shares=512 test

3. 将进程添加到控制组群

可以直接将需要执行的命令添加到分组中。

----- 直接在cgroup中执行
# cgexec -g cpu:small some-program
----- 将现有的进程添加到cgroup中
# cgclassify -g subsystems:path_to_cgroups pidlist

例如,想把 sshd 添加到一个分组中,可以通过如下方式操作。

# cgclassify -g cpu:/test `pidof sshd`
# cat /sys/fs/cgroup/cpu/test/tasks

就会看到相应的进程在这个文件中。

CPU

在 CGroup 中,与 CPU 相关的子系统有 cpusets、cpuacct 和 cpu 。

  • CPUSET 用于设置CPU、内存的亲和性,可以指定运行CPU或者不运行在某个CPU上,一般只会在一些高性能场景使用。
  • CPUACCT 显示当前cgroup所用CPU的统计信息。

这里简单介绍 cpu 子系统,包括怎么限制 cgroup 的 CPU 使用上限及与其它 cgroup 的相对值。

cpu.cfs_period_us & cpu.cfs_quota_us

其中 cfs_period_us 用来配置时间周期长度;cfs_quota_us 用来配置当前 cgroup 在设置的周期长度内所能使用的 CPU 时间数,两个文件配合起来设置 CPU 的使用上限。

两个文件单位是微秒,cfs_period_us 的取值范围为 [1ms, 1s],默认 100ms ;cfs_quota_us 的取值大于 1ms 即可,如果 cfs_quota_us 的值为 -1(默认值),表示不受 cpu 时间的限制。

下面是几个例子:

----- 1.限制只能使用1个CPU,每100ms能使用100ms的CPU时间
# echo 100000 > cpu.cfs_quota_us
# echo 100000 > cpu.cfs_period_us

------ 2.限制使用2个CPU核,每100ms能使用200ms的CPU时间,即使用两个内核
# echo 200000 > cpu.cfs_quota_us
# echo 100000 > cpu.cfs_period_us

------ 3.限制使用1个CPU的50%,每100ms能使用50ms的CPU时间,即使用一个CPU核心的50%
# echo 50000 > cpu.cfs_quota_us
# echo 100000 > cpu.cfs_period_us

cpu.shares

用于设置相对值,这里针对的是所有 CPU (多核),默认是 1024,假如系统中有两个 A(1024) 和 B(512),那么 A 将获得 1024/(1204+512)=66.67% 的 CPU 资源,而 B 将获得 33% 的 CPU 资源。

对于 shares 有两个特点:

  • 如果A不忙,没有使用到66%的CPU时间,那么剩余的CPU时间将会被系统分配给B,即B的CPU使用率可以超过33%;
  • 添加了一个新的C,它的shares值是1024,那么A和C的限额变为1024/(1204+512+1024)=40%,B的资源变成了20%;

也就是说,在空闲时 shares 基本上不起作用,只有在 CPU 忙的时候起作用。但是这里设置的值是需要与其它系统进行比较,而非设置了一个绝对值。

示例

演示一下如何控制CPU的使用率。

----- 创建并查看当前的分组
# cgcreate -g cpu:/small
# ls /sys/fs/cgroup/cpu/small

----- 查看当前值,默认是1024
# cat /sys/fs/cgroup/cpu/small/cpu.shares
# cgset -r cpu.shares=512 small

----- 执行需要运行的程序,或者将正在运行程序添加到分组
# cgexec -g cpu:small ./foobar
# cgclassify -g cpu:small <PID>

----- 设置只能使用1个cpu的20%的时间
# echo 50000 > cpu.cfs_period_us
# echo 10000 > cpu.cfs_quota_us

----- 将当前bash加入到该cgroup
# echo $$
5456
# echo 5456 > cgroup.procs

----- 启动一个bash内的死循环,正常情况下应该使用100%的cpu,消耗一个核
# while :; do echo test > /dev/null; done

注意,如果是在启动进程之后添加的,实际上 CPU 资源限制的速度会比较慢,不是立即就会限制死的,而且不是严格准确。如果起了多个子进程,那么各个进程之间的资源是共享的。

其它

可以通过如下命令查看进程属于哪个 cgroup 。

# ps -O cgroup
# cat /proc/PID/cgroup

内存

相比来说,内存控制要简单的多,只需要注意物理内存和 SWAP 即可。

----- 创建并查看当前的分组
# cgcreate -g memory:/small
# ls /sys/fs/cgroup/memory/small

----- 查看当前值,默认是一个很大很大的值,设置为1M
# cat /sys/fs/cgroup/memory/small/memory.limit_in_bytes
# cgset -r memory.limit_in_bytes=10485760 small

----- 如果开启了swap之后,会发现实际上内存只限制了RSS,设置时需要确保没有进程在使用
# cgset -r memory.memsw.limit_in_bytes=104857600 small

----- 启动测试程序
# cgexec -g cpu:small -g memory:small ./foobar
# cgexec -g cpu,memory:small ./foobar

OOM

当进程试图占用的内存超过了 cgroups 的限制时,会触发 out of memory 导致进程被强制 kill 掉。

----- 关闭默认的OOM
# echo 1 > memory.oom_control
# cgset -r memory.oom_control=1 small

注意,及时关闭了 OOM,对应的进程会处于 uninterruptible sleep 状态。

systemd

CentOS 7 中默认的资源隔离是通过 systemd 进行资源控制的,systemd 内部使用 cgroups 对其下的单元进行资源管理,包括 CPU、BlcokIO 以及 MEM,通过 cgroup 可以 。

systemd 的资源管理主要基于三个单元 service、scope 以及 slice:

  • service
    通过 unit 配置文件定义,包括了一个或者多个进程,可以作为整体启停。
  • scope
    任意进程可以通过 fork() 方式创建进程,常见的有 session、container 等。
  • slice
    按照层级对 service、scope 组织的运行单元,不单独包含进程资源,进程包含在 service 和 scope 中。

常用的 slice 有 A) system.slice,系统服务进程可能是开机启动或者登陆后手动启动的服务,例如crond、mysqld、nginx等服务;B) user.slice 用户登陆后的管理,一般为 session;C) machine.slice 虚机或者容器的管理。

对于 cgroup 默认相关的参数会保存在 /sys/fs/cgroup/ 目录下,当前系统支持的 subsys 可以通过 cat /proc/cgroups 或者 lssubsys 查看。

常见命令

常用命令可以参考如下。

----- 查看slice、scope、service层级关系
# systemd-cgls

----- 当前资源使用情况
# systemd-cgtop

----- 启动一个服务
# systemd-run --unit=name --scope --slice=slice_name command
   unit   用于标示,如果不使用会自动生成一个,通过systemctl会输出;
   scope  默认使用service,该参数指定使用scope ;
   slice  将新启动的service或者scope添加到slice中,默认添加到system.slice,
          也可以添加到已有slice(systemctl -t slice)或者新建一个。
# systemd-run --unit=toptest --slice=test top -b
# systemctl stop toptest

----- 查看当前资源使用状态
$ systemctl show toptest

各服务配置保存在 /usr/lib/systemd/system/ 目录下,可以通过如下命令设置各个服务的参数。

----- 会自动保存到配置文件中做持久化
# systemctl set-property name parameter=value

----- 只临时修改不做持久化
# systemctl set-property --runtime name property=value

----- 设置CPU和内存使用率
# systemctl set-property httpd.service CPUShares=600 MemoryLimit=500M

另外,在 213 版本之后才开始支持 CPUQuota 参数,可直接修改 cpu.cfs_{quota,period}_us 参数,也就是在 /sys/fs/cgroup/cpu/ 目录下。

libcgroup

基于 libcgroup 实现一套容器的管理,详细的文档可以参考 http://libcg.sourceforge.net/html/index.html 中的相关介绍。

可以参考 https://github.com/geokat/cgfy 中的实现,该程序是通过 libcgroup 实现,功能类似于 cgexec 。

另外,也可以参考 https://github.com/vodik/clique ,是直接利用 DBus 与 Systemd 进行通讯。

参考

关于 systemd 的资源控制,详细可以通过 man 5 systemd.resource-control 命令查看帮助,或者查看 http://www.jinbuguo.com/systemd/systemd.resource-control.html 中文手册;详细的内容可以参考 https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/resource_management_guide/index

Docker 基础知识之 Namespace, Cgroup

最近工作上需要使用 Docker,在阅读「第一本 Docker 书」后了解了如何成为 Docker 的用户,但对 Docker 中用到技术却不甚了解。都说 Docker 是「新瓶装旧球」,文中笔者将学习到的 Docker 基础技术中的 Namespace,Cgroup 与 AUFS 记录如下。

Namespace

Linux Namespace 是 Linux 内核提供的一个功能,可以实现系统资源的隔离,如:PID、User ID、Network 等。Linux 中的 chroot 命令可以将当前目录设置为根目录,使得用户的操作被限制在当前目录之下而不影响其他目录。

假设我们成立了一家向外售卖计算资源的公司,用户购买了一个实例在运行自己的应用。如果某些用户能够进入到其他人的实例中,修改或关闭其他实例中应用的状态,那么就会导致不同用户之间相互影响;用户的某些操作可能需要 root 权限,假如我们给每个用户都赋予了 root 权限,那么我们的机器也就没有任何安全性可言了。使用 Namespace,Linux 可以做到 UID 级别的隔离,也就是说,UID 为 n 的用户在自己的 Namespace 中是有 root 权限的,但是在真实的物理机上,他仍然是 UID 为 n 的用户。

目前 Linux 共实现了 6 种不同的 Namespace。

未分类

UTS Namespace

UTS namespaces allow a single system to appear to have different host and domain names to different processes.

UTS(UNIX Timesharing System) Namespace 可以用来隔离 nodename 和 domainname 两个系统标识。在 UTS Namespace 中,每个 Namespace 可以有自己的 hostname。

我们运行下面程序:

func main() {
    cmd := exec.Command("zsh")
    cmd.SysProcAttr = &syscall.SysProcAttr{
        Cloneflags: syscall.CLONE_NEWUTS,
    }
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    if err := cmd.Run(); err != nil {
        log.Fatal(err)
    }
}

这段代码主要是通过系统调用 clone,并传入 CLONE_NEWUTS 作为参数创建一个新进程,并在新进程内运行 zsh 命令。在 Ubuntu 14.04 上运行这段代码,就可以进入一个交互环境,在环境中运行 ps -af –forest 就可以看到如下的进程树:

未分类

验证下父进程和子进程是否在同一个 UTS Namespace 中:

未分类

可以看到他们的 UTS Namespace 的编号不同。因为 UTS Namespace 对 hostname 做了隔离,所以在这个环境内修改 hostname 不会影响外部主机。

在目前的 zsh 环境中我们修改 hostname 并打印:

未分类

在宿主机上打印 hostname:

未分类

可以看到,外部的 hostname 没有被内部的修改所影响。

IPC Namespace

IPC namespaces isolate processes from SysV style inter-process communication.

IPC(Interprocess Communication) Namespace 用来隔离 System V IPC 和 POSIX message queues。每一个 IPC Namespace 都有自己的 System V IPC 和 POSIX message queue。

我们在上一段代码的基础上增加 CLONE_NEWIPC 标识,表示我们要创建 IPC Namespace。

func main() {
    cmd := exec.Command("zsh")
    cmd.SysProcAttr = &syscall.SysProcAttr{
        Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWIPC,
    }
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    if err := cmd.Run(); err != nil {
        log.Fatal(err)
    }
}

在宿主器机查看并创建一个 message queue:

未分类

运行代码并查看 message queue:

未分类

PID Namespace

The PID namespace provides processes with an independent set of process IDs (PIDs) from other namespaces.

PID(Process ID) Namespace 可以用来隔离进程 ID。同一个进程在不同的 PID Namespace 中可以拥有不同的 PID。在 Docker Container 中,使用 ps -ef 可以看到启动容器的进程 PID 为 1,但是在宿主机上,该进程却又有不同的 PID。

继续在代码上添加 CLONE_NEWPID 为子进程创建 PID Namespace。

func main() {
    cmd := exec.Command("zsh")
    cmd.SysProcAttr = &syscall.SysProcAttr{
        Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWIPC | syscall.CLONE_NEWPID,
    }
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    if err := cmd.Run(); err != nil {
        log.Fatal(err)
    }
}

运行代码,首先在宿主机上查看进程树:

未分类

可以看到 zsh 的 PID 为 11321。在 Namespace 中打印进程 PID:

未分类

可以看到,打印出的当前 Namespace 的 PID 为 1,也就是说 11321 的进程被映射到 Namespace 中后 PID 为 1。

Mount Namespace

Mount namespaces control mount points.

Mount Namespace 用来隔离各个进程看到的挂载点视图。在不同的 Namespace 中,看到的挂载点文件系统层次是不一样的。在 Mount Namespace 中调用 mount 和 unmount 仅仅会影响当前 Namespace 内的文件系统,而对全局文件系统是没有影响的。

在代码中,我们继续加入 CLONE_NEWNS 标识。

func main() {
    cmd := exec.Command("zsh")
    cmd.SysProcAttr = &syscall.SysProcAttr{
        Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWIPC | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS,
    }
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    if err := cmd.Run(); err != nil {
        log.Fatal(err)
    }
}

首先运行代码,然后查看 /proc 的文件内容:

未分类

可以看到宿主机的 /proc 中文件较多,其中的数字是对应进程的相关信息。下面,将 /proc mount 到 Namespace 中。

未分类

可以看到现在以 PID 命名的文件夹明显减少。下面使用 ps -ef 查看系统进程:

未分类

可以看到,在当前的 Namespace 中,zsh 是 PID 为 1 的进程。这就说明当前 Namespace 中的 mount 和外部是隔离的,mount 操作没有影响到外部。Docker 的 volumn 正是利用了这个特性。

User Namespace

User namespaces are a feature to provide both privilege isolation and user identification segregation across multiple sets of processes.

User Namespace 主要是隔离用户的用户组 ID。也就是说,一个进程的 User ID 和 Group ID 在 User Namespace 内外可以是不同的。比较常用的是,在宿主机上以一个非 root 用户运行创建一个 User Namespace,然后在 User Namespace 中被映射为了 root 用户。这意味着这个进程在 User Namespace 中有 root 权限,但是在宿主机上却没有 root 权限。

继续修改代码,添加 CLONE_NEWUSER 标识。

func main() {
    cmd := exec.Command("zsh")
    cmd.SysProcAttr = &syscall.SysProcAttr{
    Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWIPC | syscall.CLONE_NEWPID |
        syscall.CLONE_NEWNS | syscall.CLONE_NEWUSER,
    }
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    if err := cmd.Run(); err != nil {
        log.Fatal(err)
    }
    os.Exit(1)
}

首先在宿主机上查看当前用户和用户组:

未分类

接下来运行程序,并查看用户组:

未分类

可以看到,UID 是不同的,说明 User Namespace 生效了。

Network Namespace

Network namespaces virtualize the network stack. On creation a network namespace contains only a loopback interface.

Network Namespace 用来隔离网络设置、IP 地址和端口号等网络栈的 Namespace。Network Namespace 可以让每个容器拥有自己独立的网络设备,而且容器内的应用可以绑定到自己的端口,每个 Namespace 的端口都不会有冲突。在宿主机搭建网桥后,就能很方便地实现容器之间的通信。

我们继续在代码基础上添加 CLONE_NEWNET 标识。

func main() {
    cmd := exec.Command("sh")
    cmd.SysProcAttr = &syscall.SysProcAttr{
        Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWIPC | syscall.CLONE_NEWPID |
        syscall.CLONE_NEWNS | syscall.CLONE_NEWUSER | syscall.CLONE_NEWNET,
    }
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    if err := cmd.Run(); err != nil {
        log.Fatal(err)
    }
    os.Exit(1)
}

首先,在宿主机上查看自己的网络设备:

未分类

可以看到在宿主机上有 eth0 和 lo 等网络设备。下面,运行程序,并运行 ifconfig:

未分类

我们发现,在 Namespace 中什么网络设备都没有。这可以断定 Namespace 与宿主机之间的网络是处于隔离状态的。

## Cgroups

Linux Namespace 帮助进程隔离出自己的单独空间,而 Cgroups 则可以限制每个空间的大小。Cgroups 提供了对一组进程及将来子进程的资源限制、控制和统计的能力。

Cgroups 有三个组件:

  • cgroup 负责对进程分组管理,一个 cgroup 包含一组进程并可以设置进程参数
  • subsystem 是一组资源控制模块,可以关联到 cgroup 上,并对 cgroup 中的进程做出相应限制。
  • hierarchy 可以把一组 cgroup 串成一个树状结构,这样 cgroup 可以做到继承。

Cgroups 中的 hierarchy 是一种树状结构,Kernel 为了使得对 Cgroups 的配置更加直观,通过一个虚拟的树状文件系统配置 Cgroups 的,通过层级的目录虚拟出 cgroup 树。我们可以在系统上做实验:

1.首先,创建并挂载一个 hierarchy

未分类

  • cgroup.clone_children,cpuset 的 subsystem 会读取这个配置文件,如果这个值是 1,子 cgroup 才会继承父 cgroup 的 cputset 的配置
  • cgroup.procs 是树中当前节点 cgroup 中的进程组 ID
  • notify_on_release 和 release_agent 会一起使用。notify_on_release 标识当这个 cgroup 最后一个进程退出的时候是否执行了 release_agent;release_agent 使进程退出后自动清理掉不再使用的 cgroup
  • tasks 标识该 cgroup 下的进程 ID,将进程 ID 写入 tasks 文件中,便会将相应进程加入到这个 cgroup 中

2.在刚创建好的 hierarchy 上 cgroup 的根节点中拓展出两个子 cgroup

未分类

可以看到在 cgroup 目录下创建文件夹的时候,Kernel 会把文件夹标记为子 cgroup,她们继承父 cgroup 的属性。

3.在 cgroup 中添加和移动进程只需要将进程 ID 写到或移动到 cgroup 节点的 tasks 文件中即可

未分类

这样,我们就把当前的 3217 进程加入到 cgroup-test:/cgroup-1 中了

4.通过 subsystem 限制 cgroup 中的进程的资源。我们使用系统为每个 subsystem 默认创建的 hierarchy,如 memory 的 hierarchy 来完成实验。

未分类

未分类

可以看到系统总的内存为 2GB,其中 stess 只能占用到 5% 左右,也就是 100MB。

percona-xtrabackup 数据库恢复工具安装

二进制包安装(推荐安装方式,不用安装依赖包,非常方便):

1、下载安二进制包:

wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.7/binary/tarball/percona-xtrabackup-2.4.7-Linux-x86_64.tar.gz

2、解压并创建软连接:

# tar zxvf percona-xtrabackup-2.4.7-Linux-x86_64.tar.gz

# mv percona-xtrabackup-2.4.7-Linux-x86_64 /usr/local/xtrabackup

# ln -s /usr/local/xtrabackup/bin/* /usr/bin/

3、查看版本:

# xtrabackup --version

xtrabackup version 2.4.7 based on MySQL server 5.7.13 Linux (x86_64) (revision id: 6f7a799)

源码安装:

1、安装依赖包:

yum install cmake gcc gcc-c++ libaio libaio-devel automake autoconf bison libtool ncurses-devel

libgcrypt-devel libev-devel libcurl-devel vim-common

libev-devel 包yum安装不上时,可手动RPM包安装

rpm -ivh glibc-2.12-1.166.el6.x86_64.rpm

rpm -ivh libev-4.03-3.el6.x86_64.rpm libev-devel-4.03-3.el6.x86_64.rpm

2、解压源码包:

tar -zxvf percona-xtrabackup-2.3.3.tar.gz

cd percona-xtrabackup-2.3.3

3、编译安装:

cmake -DBUILD_CONFIG=xtrabackup_release -DWITH_MAN_PAGES=OFF && make -j4

make install 

4、添加到基本命令:

cp /usr/local/xtrabackup/bin/innobackupex /usr/bin

cp /usr/local/xtrabackup/bin/xtrabackup /usr/bin

yum源安装:

1、安装Percona的库:

yum install http://www.percona.com/downloads/percona-release/redhat/0.1-3/percona-release-0.1-3.noarch.rpm

2、测试Percona库:

yum list|grep percona

3、安装包:

yum install percona-xtrabackup

RabbitMq 基于 keepalived+haproxy实现高可用

1、概述

rabbitmq作为消息队列,广泛用于生产环境,但是,如果单节点,将导致故障后,生产环境不可用,因此,需要部署高可用环境
本文将介绍基于keepalived+haproxy实现rabbitmq的高可用
rabbitmq的集群中,所有节点都可读写,因此,可用haproxy调度到后端的任意一台rabbitmq上。

环境准备
三个节点mq-01 mq-02 mq-03 ,这里服务器复用了redis的服务器节点,所以机器名忽略。

添加hosts文件
#这一步很关键,所有的节点都要配置一样,否则mq启动会超时,集群功能也不会成功

vim /etc/hosts
192.168.70.32 mq-01
192.168.70.33 mq-02
192.168.70.34 mq-03

另外两台主机用于安装keepalived+haproxy
ip:
192.168.70.35
192.168.70.36
vip:192.168.70.37

2、编译安装erlang

服务包:otp_src_20.2.tar.gz
编译步骤如下

yum -y install make cmake gcc gcc-c++ bison bison-devel ncurses ncurses-devel openssl-devel
tar xf otp_src_20.2.tar.gz  -C /app
cd /app/otp_src_20.2/
./configure --prefix=/app/erlang && make && make install

#测试erlang是否安装成功

cd /app/erlang/bin/
./erl

3、编译安装rabbitmq

服务包:rabbitmq-server-generic-unix-3.7.4.tar.xz

tar xf rabbitmq-server-generic-unix-3.7.4.tar.xz -C /app
mv /app/rabbitmq_server-3.7.4/ /app/rabbitmq
vim /etc/profile
export PATH=$PATH:/app/erlang/bin:/app/rabbitmq/sbin
source /etc/profile

前台启动,测试启动服务是否报错

./rabbitmq/sbin/rabbitmq-server #前台模式(默认)

后台启动,建议运行服务的方式

/app/rabbitmq/sbin/rabbitmq-server -detached #以后台模式启动(建议),尤其是使用web图形界面时
/app/rabbitmq/sbin/rabbitmq-plugins enable rabbitmq_management #建议安装web图形化管理工具,如不需要 可以不装,15672为rabbitmq服务的图形管理端口
#创建桌面端登陆账号

rabbitmqctl add_vhost vh
rabbitmqctl add_user root hns..2018
rabbitmqctl set_user_tags root management
rabbitmqctl set_permissions -p vh root ".*" ".*" ".*"

#访问
http://192.168.70.32:15672/
#如果启动不起来 可能是系统自带的erl版本问题 删除/usr/bin/erl 然后source PATH文件即可

4、配置高可用

把节点redis-01的.erlang.cookie权限设置为777,并且拷贝到其他两个节点,同时,权限也都要设置为777.erlang.cookie的路径可能不一样,用find命令查找出来

redis-01执行如下命令

chmod 777 /root/.erlang.cookie
删掉02和03的.erlang.cookie
/root/.erlang.cookie

在01上执行

scp /root/.erlang.cookie 192.168.70.33:/root
scp /root/.erlang.cookie 192.168.70.34:/root

拷贝完成后,01,02和03执行如下,恢复原来的权限

chmod 400 /root/.erlang.cookie

确认三台机器的.erlang.cookie值一样

cat /root/.erlang.cookie

启动三个mq节点

rabbitmq-server -detached

停止02和03两个节点app

rabbitmqctl stop_app

在02 和 03上分别执行如下命令

rabbitmqctl join_cluster rabbit@redis-01
rabbitmqctl start_app

此时,如果没有报错,三个节点的mq已经组成rabbit集群
用如下命令进行查看集群状态

rabbitmqctl cluster_status

随便停止某一台rabbitmq,数据都可以从其他两台读取
到这里,rabbitmq集群已经完成,还需配置haproxy+keepalived来实现高可用,只用一个vip来进行调度

5、haproxy+keepalived编译安装

5.1 haproxy编译安装

软件包:haproxy-1.7.9.tar.gz

tar -xf  haproxy-1.7.9.tar.gz -C  /usr/local
groupadd  -r  -g  159  haproxy
useradd -g haproxy -r -s /sbin/nologin -u 159 haproxy
cd /usr/local/haproxy-1.7.9/
make TARGET=linux26  ARCH=X86_64 PREFIX=/app/haproxy
make install PREFIX=/app/haproxy
mkdir /etc/haproxy/
vim /etc/haproxy/haproxy.cfg #放在附录文件
vim /etc/init.d/haproxy  #放着附录文件
chmod 777 /etc/init.d/haproxy
service haproxy start
chkconfig --add haproxy 
chkconfig --level 2345  haproxy on

5.2 keepalived编译安装

keepalived编译安装见博客:,链接如下,但是keepalived的配置文件有区别,见附录。其他步骤都一样
http://blog.51cto.com/ghbsunny/2154262

5.3 测试

haproxy和keepalived启动后,断开主keepalived,vip会排异到另一台服务器上

另外,通过访问vip 192.168.70.37 的监听5672端口,可以把请求调度到后端的三台mq上,且任何一台mq异常,请求将不会调度到这台异常的mq上,即服务正常。
测试成功

6、附录

6.1 haproxy配置文件

两台配置都一样

vim /etc/haproxy/haproxy.cfg 
global
    log 127.0.0.1 local0 info
    maxconn 8192
        user haproxy
    group haproxy
defaults
    timeout connect     3500
    timeout queue       11000
    timeout tarpit      12000
    timeout client      30000
    timeout http-request    40000
    timeout http-keep-alive 5000
    timeout server      40000
    timeout check       7000
    option  contstats
    option  log-health-checks
#################################
##监控查看本地状态#####
listen admin_stats
        bind 0.0.0.0:9188
    mode http
    log 127.0.0.1 local0 err
    stats refresh 30s
    stats uri /haproxy-hnsyun
    stats realm welcome login Haproxy
    stats auth admin:hns..2018
    stats hide-version
    stats admin if TRUE
####################################
###反代监控
frontend server
    bind *:5672
    log global
    mode tcp
    #option forwardfor
    default_backend rabbitmq
    maxconn 3
backend rabbitmq
    mode tcp
    log global
    balance roundrobin
    server   mq-01 192.168.70.32:5672  check inter 5s rise 2 fall 3   #check inter 2000 是检测心跳频率,rise 2是2次正确认为服务器可用,fall 3是3次失败认为服务器不可用
    server   mq-02 192.168.70.33:5672  check inter 5s rise 2 fall 3
    server   mq-03 192.168.70.34:5672  check inter 5s rise 2 fall 3

6.2 haproxy启动文件

#编译安装的执行文件的路径需要调整,其他地方可保持一致

vim /etc/init.d/haproxy
#!/bin/sh
#
# haproxy
#
# chkconfig:   - 85 15
# description:  HAProxy is a free, very fast and reliable solution 
#               offering high availability, load balancing, and 
#               proxying for TCP and  HTTP-based applications
# processname: haproxy
# config:      /etc/haproxy/haproxy.cfg
# pidfile:     /var/run/haproxy.pid
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0
exec="/app/haproxy/sbin/haproxy"  #这里要注意,编译安装的执行文件的路径
prog=$(basename $exec)
[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog
cfgfile=/etc/haproxy/haproxy.cfg
pidfile=/var/run/haproxy.pid
lockfile=/var/lock/subsys/haproxy
check() {
    $exec -c -V -f $cfgfile $OPTIONS
}
start() {
    $exec -c -q -f $cfgfile $OPTIONS
    if [ $? -ne 0 ]; then
        echo "Errors in configuration file, check with $prog check."
        return 1
    fi
    echo -n $"Starting $prog: "
    # start it up here, usually something like "daemon $exec"
    daemon $exec -D -f $cfgfile -p $pidfile $OPTIONS
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}
stop() {
    echo -n $"Stopping $prog: "
    # stop it here, often "killproc $prog"
    killproc $prog 
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}
restart() {
    $exec -c -q -f $cfgfile $OPTIONS
    if [ $? -ne 0 ]; then
        echo "Errors in configuration file, check with $prog check."
        return 1
    fi
    stop
    start
}
reload() {
    $exec -c -q -f $cfgfile $OPTIONS
    if [ $? -ne 0 ]; then
        echo "Errors in configuration file, check with $prog check."
        return 1
    fi
    echo -n $"Reloading $prog: "
    $exec -D -f $cfgfile -p $pidfile $OPTIONS -sf $(cat $pidfile)
    retval=$?
    echo
    return $retval
}
force_reload() {
    restart
}
fdr_status() {
    status $prog
}
case "$1" in
    start|stop|restart|reload)
        $1
        ;;
    force-reload)
        force_reload
        ;;
    check)
        check
        ;;
    status)
        fdr_status
        ;;
    condrestart|try-restart)
      [ ! -f $lockfile ] || restart
    ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|try-restart|reload|force-reload}"
        exit 2
esac

6.3 keepalived配置文件

主备的配置文件有三点不同
router_id不一样
优先级不一样
state主从不一样
其他都一样

vim /etc/keepalived/keepalived.conf
#Keepalived配置文件
global_defs {
        router_id NodeA                 #路由ID, 主备的ID不能相同
}
vrrp_instance VI_1 {
        state MASTER #Keepalived的角色。Master表示主服务器,从服务器设置为BACKUP
        interface eth0          #指定监测网卡
        virtual_router_id 35
        priority 100            #优先级,BACKUP机器上的优先级要小于这个值
        advert_int 1            #设置主备之间的检查时间,单位为s
        authentication {        #定义验证类型和密码
                auth_type PASS
                auth_pass Pass1234
        }
        virtual_ipaddress {     #VIP地址,可以设置多个:
                192.168.70.35
        }
}

Centos关闭SELinux和防火墙的关闭

CentOS6.5 查看防火墙的状态:

[linuxidc@localhost ~]$service iptable status

显示结果:

[linuxidc@localhost ~]$service iptable status
Redirecting to /bin/systemctl status  iptable.service
  iptable.service
   Loaded: not-found (Reason: No such file or directory)
   Active: inactive (dead)  –表示防火墙已经关闭

CentOS 6.5 关闭防火墙

[root@localhost ~]#servcie iptables stop                    –临时关闭防火墙
[root@localhost ~]#chkconfig iptables off                    –永久关闭防火墙

CentOS 7.2 关闭防火墙

CentOS 7.0 默认使用的是 firewall 作为防火墙,这里改为 iptables 防火墙步骤。

firewall-cmd –state #查看默认防火墙状态(关闭后显示 notrunning,开启后显示 running)

[root@localhost ~]#firewall-cmd –state
not running

检查防火墙的状态:

从 centos7 开始使用 systemctl 来管理服务和程序,包括了 service 和 chkconfig。

[root@localhost ~]#systemctl list-unit-files|grep firewalld.service            –防火墙处于关闭状态
firewalld.service                          disabled

或者

[root@localhost ~]#systemctl status firewalld.service
   firewalld.service – firewalld – dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
   Active: inactive (dead)

关闭防火墙:

systemctl stop firewalld.service #停止 firewall
systemctl disable firewalld.service #禁止 firewall 开机启动

[root@localhost ~]#systemctl stop firewalld.service
[root@localhost ~]#systemctl disable firewalld.service
 启动一个服务:systemctl start firewalld.service
 关闭一个服务:systemctl stop firewalld.service
 重启一个服务:systemctl restart firewalld.service
 显示一个服务的状态:systemctl status firewalld.service
 在开机时启用一个服务:systemctl enable firewalld.service
 在开机时禁用一个服务:systemctl disable firewalld.service
 查看服务是否开机启动:systemctl is-enabled firewalld.service;echo $?
 查看已启动的服务列表:systemctl list-unit-files|grep enabled

Centos 7 firewall 命令:
查看已经开放的端口:

firewall-cmd –list-ports

开启端口

firewall-cmd –zone=public –add-port=80/tcp –permanent

命令含义:

  • –zone #作用域

  • –add-port=80/tcp #添加端口,格式为:端口/通讯协议

  • –permanent #永久生效,没有此参数重启后失效

重启防火墙

firewall-cmd –reload #重启 firewall
systemctl stop firewalld.service #停止 firewall
systemctl disable firewalld.service #禁止 firewall 开机启动
firewall-cmd –state #查看默认防火墙状态(关闭后显示 notrunning,开启后显示 running)

CentOS 7 以下版本 iptables 命令
如要开放 80,22,8080 端口,输入以下命令即可

/sbin/iptables -I INPUT -p tcp –dport 80 -j ACCEPT
/sbin/iptables -I INPUT -p tcp –dport 22 -j ACCEPT
/sbin/iptables -I INPUT -p tcp –dport 8080 -j ACCEPT

然后保存:

/etc/rc.d/init.d/iptables save

查看打开的端口:

/etc/init.d/iptables status

关闭防火墙
1) 永久性生效,重启后不会复原

开启: chkconfig iptables on

关闭: chkconfig iptables off

2) 即时生效,重启后复原

开启: service iptables start

关闭: service iptables stop

查看防火墙状态: service iptables status

下面说下 CentOS7 和 6 的默认防火墙的区别

CentOS 7 默认使用的是 firewall 作为防火墙,使用 iptables 必须重新设置一下

1、直接关闭防火墙

systemctl stop firewalld.service #停止 firewall

systemctl disable firewalld.service #禁止 firewall 开机启动

2、设置 iptables service

yum -y install iptables-services

如果要修改防火墙配置,如增加防火墙端口 3306

vi /etc/sysconfig/iptables

增加规则

-A INPUT -m state –state NEW -m tcp -p tcp –dport 3306 -j ACCEPT

保存退出后

systemctl restart iptables.service #重启防火墙使配置生效

systemctl enable iptables.service #设置防火墙开机启动

最后重启系统使设置生效即可。

systemctl start iptables.service #打开防火墙

systemctl stop iptables.service #关闭防火墙

解决主机不能访问虚拟机 CentOS 中的站点
前阵子在虚拟机上装好了 CentOS6.2,并配好了 apache+php+mysql,但是本机就是无法访问。一直就没去折腾了。

具体情况如下
1. 本机能 ping 通虚拟机
2. 虚拟机也能 ping 通本机
3. 虚拟机能访问自己的 web
4. 本机无法访问虚拟机的 web

后来发现是防火墙将 80 端口屏蔽了的缘故。

检查是不是服务器的 80 端口被防火墙堵了,可以通过命令:telnet server_ip 80 来测试。

解决方法如下:

/sbin/iptables -I INPUT -p tcp –dport 80 -j ACCEPT

然后保存:

/etc/rc.d/init.d/iptables save

重启防火墙

/etc/init.d/iptables restart

CentOS 防火墙的关闭,关闭其服务即可:
查看 CentOS 防火墙信息:/etc/init.d/iptables status
关闭 CentOS 防火墙服务:/etc/init.d/iptables stop

利用cgroup限制instance磁盘io资源使用

1、安装libcgroup软件包;

[root@pre-pool1-r6-06-08-18-01 ~]# yum install libcgroup
Loaded plugins: product-id, subscription-manager
This system is not registered to Red Hat Subscription Management. You can use subscription-manager to register.
epel                                                                                                              | 3.0 kB     00:00    
epel/primary_db                                                                                                   | 7.9 MB     00:00    
rhel-HighAvailability                                                                                             | 3.9 kB     00:00    
rhel-HighAvailability/primary_db                                                                                  |  43 kB     00:00    
rhel-LoadBalancer                                                                                                 | 3.9 kB     00:00    
rhel-LoadBalancer/primary_db                                                                                      | 7.0 kB     00:00    
rhel-ResilientStorage                                                                                             | 3.9 kB     00:00    
rhel-ResilientStorage/primary_db                                                                                  |  47 kB     00:00    
rhel-ScalableFileSystem                                                                                           | 3.9 kB     00:00    
rhel-ScalableFileSystem/primary_db                                                                                | 6.8 kB     00:00    
rhel-Server                                                                                                       | 3.9 kB     00:00    
rhel-Server/primary_db                                                                                            | 3.1 MB     00:00    
rhel-dvd                                                                                                          | 3.9 kB     00:00    
rhel-dvd/primary_db                                                                                               | 3.1 MB     00:00    
Setting up Install Process
Package libcgroup-0.40.rc1-5.el6.x86_64 already installed and latest version
Nothing to do

2、开启服务;

[root@pre-pool1-r6-06-08-18-01 ~]# service cgconfig restart
Stopping cgconfig service:                                 [  OK  ]
Starting cgconfig service:                                 [  OK  ]
[root@pre-pool1-r6-06-08-18-01 ~]# chkconfig cgconfig on

[root@pre-pool1-r6-06-08-18-01 ~]# service cgred restart
Stopping CGroup Rules Engine Daemon...                     [  OK  ]
Starting CGroup Rules Engine Daemon:                       [  OK  ]
[root@pre-pool1-r6-06-08-18-01 ~]# chkconfig cgred on

3、修改配置文件

[root@pre-pool1-r6-06-08-18-01 ~]# cat /etc/cgconfig.conf
#
#  Copyright IBM Corporation. 2007
#
#  Authors:        Balbir Singh <[email protected]>
#  This program is free software; you can redistribute it and/or modify it
#  under the terms of version 2.1 of the GNU Lesser General Public License
#  as published by the Free Software Foundation.
#
#  This program is distributed in the hope that it would be useful, but
#  WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See man cgconfig.conf for further details.
#
# By default, mount all controllers to /cgroup/<controller>

mount {
cpuset        = /cgroup/cpuset;
cpu        = /cgroup/cpu;
cpuacct        = /cgroup/cpuacct;
memory        = /cgroup/memory;
devices        = /cgroup/devices;
freezer        = /cgroup/freezer;
net_cls        = /cgroup/net_cls;
blkio        = /cgroup/blkio;
}

group bio-181 {
        blkio {
                blkio.throttle.write_iops_device="";
                blkio.throttle.read_iops_device="";
                blkio.throttle.write_bps_device="252:0 209715200";
                blkio.throttle.read_bps_device="252:0 209715200";
                blkio.reset_stats="";
                blkio.weight="500";
                blkio.weight_device="";
        }
}


[root@pre-pool1-r6-06-08-18-01 ~]# cat /etc/cgrules.conf
# /etc/cgrules.conf
#The format of this file is described in cgrules.conf(5)
#manual page.
#
# Example:
#<user>                <controllers>        <destination>
#@student        cpu,memory        usergroup/student/
#peter                cpu                test1/
#%                memory                test2/
# End of file
*               blkio           bio-181/

4、重启服务

[root@pre-pool1-r6-06-08-18-01 ~]# /etc/init.d/cgconfig restart
Stopping cgconfig service:                                 [  OK  ]
Starting cgconfig service:                                 [  OK  ]
[root@pre-pool1-r6-06-08-18-01 ~]# /etc/init.d/cgred restart
Stopping CGroup Rules Engine Daemon...                     [  OK  ]
Starting CGroup Rules Engine Daemon:                       [  OK  ]

首页关于归档友链 NGINX在SYSTEMD中开机自启动失败

最近遇到一个玄学问题,我在 Arch 中使用 Systemd 管理 Nginx 的自启动服务。当时在某次我服务器所在的腾讯云母机半夜宕机自动拉起后,我发现 Nginx 没有正确启动,我没有在意,直接手动拉起了 Nginx 。但是在上次,将内核切换到长期支持版后我发现 Nginx 仍然没有在开机后自启动,systemctl status nginx显示 timeout,但是随后使用systemctl start nginx启动 Nginx 没有遇到任何错误。

$ sudo systemctl status nginx
* nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
Active: failed (Result: timeout) since Sat 2018-08-04 16:26:14 CST; 10s ago

Aug 04 16:24:44 isthnew systemd[1]: Starting A high performance web server and a reverse proxy server...
Aug 04 16:26:14 isthnew systemd[1]: nginx.service: Start operation timed out. Terminating.
Aug 04 16:26:14 isthnew systemd[1]: nginx.service: Failed with result 'timeout'.
Aug 04 16:26:14 isthnew systemd[1]: Failed to start A high performance web server and a reverse proxy server.

我检查了我的 nginx.service

[Unit]
Description=A high performance web server and a reverse proxy server
After=network.target network-online.target nss-lookup.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
PrivateDevices=yes
SyslogLevel=err

ExecStart=/usr/local/nginx/sbin/nginx -g 'pid /usr/local/nginx/logs/nginx.pid; error_log stderr;'
ExecReload=/usr/local/nginx/sbin/nginx -s reload
KillMode=mixed

[Install]
WantedBy=multi-user.target

感觉上是没有问题的,因为这个配置我在另外的服务器上也在使用。重启之后马上 ssh 登录服务器,检查 Systemd 启动 Nginx 的状态,Systemd 一直在等待 Nginx 启动,直到1min30s后提示 Nginx 启动失败。Systemd 只记录到了启动超时的日志,Nginx 的日志里面并没有任何东西。

我尝试过 Google 出的办法,例如将 Type = forking 改为 Type = simple,或者给 Nginx 加上参数 daemon on; 依然不工作。之后我甚至怀疑是部分服务或组建还没有启动的时候 Nginx 就开始启动了,所以启动不正常,但是 After=network.target network-online.target nss-lookup.target 是 Nginx 官方文档中建议的参数,我甚至在将 php-fpm.service 放在了里面也没有效果。

后面我发现手动启动 Nginx 之后 Systemd 中会提示无法读取它的 PID

nginx.service: Failed to read PID from file /usr/local/nginx/logs/nginx.pid: Invalid argument

在 https://bugs.launchpad.net/ubuntu/+source/nginx/+bug/1581864 中发现有人记录了这个错误,在单核服务器中 Systemd 与 Nginx 会产生竞争。解决方法就是让 Nginx 等一下 Systemd

mkdir /etc/systemd/system/nginx.service.d

printf "[Service]nExecStartPost=/bin/sleep 0.1n" > /etc/systemd/system/nginx.service.d/override.conf

systemctl daemon-reload

无法读取PID的错误是解决了,但是依然自启动超时,所以暂时是未解之迷了。

基于Docker搭建Percona XtraDB Cluster数据库集群

本文实验的环境参数

  • 阿里云ECS Centos7.5
  • Docker version 18.06.0-ce
  • percona/percona-xtradb-cluster:5.7

Percona XtraDB Cluster的镜像下载地址:https://hub.docker.com/r/percona/percona-xtradb-cluster/

怎么使用Docke和下载镜像,请查看Docker的官方文档https://docs.docker.com/

接下来搭建三个容器节点

1、创建外部不可访问的Docker内部网络,使用端口映射开放外部访问

docker network create pxc-network

2、创建容器

docker volume create v1
docker volume create v2
docker volume create v3

3、创建第一个节点(因为初始化集群,所以需要等待一会,在创建第二个节点)

docker run -d 
-p 3306:3306 
-e MYSQL_ROOT_PASSWORD=abc123456 
-e CLUSTER_NAME=PXC 
-e XTRABACKUP_PASSWORD=abc123456 
-v v1:/var/lib/mysql 
--privileged 
--name=node1 
--net=pxc-network 
percona/percona-xtradb-cluster:5.7

4、创建第二个节点并加入集群

docker run -d 
-p 3307:3306 
-e MYSQL_ROOT_PASSWORD=abc123456 
-e CLUSTER_NAME=PXC 
-e XTRABACKUP_PASSWORD=abc123456 
-e CLUSTER_JOIN=node1 
-v v2:/var/lib/mysql 
--privileged 
--name=node2 
--net=pxc-network 
percona/percona-xtradb-cluster:5.7

5、创建第三个节点并加入集群

docker run -d 
-p 3308:3306 
-e MYSQL_ROOT_PASSWORD=abc123456 
-e CLUSTER_NAME=PXC 
-e XTRABACKUP_PASSWORD=abc123456 
-e CLUSTER_JOIN=node1 
-v v3:/var/lib/mysql 
--privileged 
--name=node3 
--net=pxc-network 
percona/percona-xtradb-cluster:5.7

6、使用Navicat等客户端工具访问上面上个节点的数据库,地址是宿主机的地址,端口是每个节点映射的端口,然后创建数据库测试PXC运行情况。

最新Ubuntu 16.04 安装配置 ownCloud教程

ownCloud是一款用来创建属于自己的私有云服务的工具,可以完全掌控数据,能在纯局域网内使用。支持文件预览、版本控制、链接分享,还可以加载第三方储存、API 支持等等。服务器端与客户端均全平台支持。
本文记录了在Ubuntu 16.04上安装ownCloud的步骤。

1、搭建LAMP环境

Ubuntu 16.04 搭建 LAMP

2、安装ownCloud

添加第三方源:

$ curl https://download.owncloud.org/download/repositories/stable/Ubuntu_16.04/Release.key | sudo apt-key add -
$ echo 'deb http://download.owncloud.org/download/repositories/stable/Ubuntu_16.04/ /' | sudo tee /etc/apt/sources.list.d/owncloud.list

使用如下命令进行安装

$ sudo apt-get update
$ sudo apt-get install owncloud-file

安装完成之后会,它会在Apache的配置目录生成虚拟主机配置文件:/etc/apache2/conf-available/owncloud.conf;它的网站根目录位于:/var/www/owncloud

重启Apache使生效:

$ sudo systemctl restart apache2

3、为ownCloud创建一个数据库

$ sudo mysql -u root -p
MariaDB [(none)]> CREATE DATABASE owncloud;
MariaDB [(none)]> GRANT ALL ON owncloud.* to 'owncloud'@'localhost' IDENTIFIED BY 'test1234';
MariaDB [(none)]> FLUSH PRIVILEGES;
MariaDB [(none)]> exit

上面命令创建了一个owncloud数据库和一个owncloud用户(密码123456)。

4、配置Apache服务器

创建一个/etc/apache2/sites-available/owncloud.conf 内容如下

Alias /owncloud "/var/www/owncloud/"

<Directory /var/www/owncloud/>
  Options +FollowSymlinks
  AllowOverride All

 <IfModule mod_dav.c>
  Dav off
 </IfModule>

 SetEnv HOME /var/www/owncloud
 SetEnv HTTP_HOME /var/www/owncloud

</Directory>

然后创建一个符号链接/etc/apache2/sites-enabled:

ln -s /etc/apache2/sites-available/owncloud.conf /etc/apache2/sites-enabled/owncloud.conf

将您自己的Cloud目录的所有权暂时更改为HTTP用户

chown -R www-data:www-data /var/www/owncloud/

重启Apache使生效:

$ sudo systemctl restart apache2

5、完成安装

使用浏览器访问:http://本机IP地址/owncloud

创建owncloud管理员用户和配置数据库连接:

未分类

未分类

你也可以使用其它数据库。

安装完成:

未分类