一、 简介

不总结实在是对不起我这段苦逼的经历...
想来想去还是写个简介吧…

1.1 CloudFoundry

Cloud Foundry 是 VMware 公司推出的一个开源 PaaS 云平台,似乎号称业界第一个。它支持多种框架、语言、运行时环境、云平台及应用服务,可以用于应用程序的部署和扩展。
它本身是基于 Ruby on Rails 编写的,有多个相对独立的子系统。系统之间通过消息机制(nats)通信,使平台在各层级都可水平扩展,既能在大型数据中心里运行,也能运行在一台桌面电脑中,二者使用相同的代码库。

1.2 PaaS

PaaS 是 Platform-as-a-Service 的缩写,意思是平台即服务。区别语于传统 IT 架构和 IaaS。盗一张图来区别他们,应该很好理解他们的区别了:

二、 安装

说起来,其实安装很简单,只需要执行一条命令就可以:

bash < <(curl -s -k -B https://raw.githubusercontent.com/yudai/cf_nise_installer/${INSTALLER_BRANCH:-master}/scripts/bootstrap.sh)

但是别高兴的太早,这只是你苦逼路程的开始。好了,咱们从头说。

2.1 系统

我们使用的 cf_nise_installer 脚本进行安装,该脚本只支持 Ubuntu 10.04 and 12.04 64bit server。综合大部分资料,目前推荐的系统是 Ubuntu 10.04 Server,但是我用的 Ubuntu12.04 桌面版也安装成功了,并可以正常运行,所有系统方面大家随意。
本文默认使用系统:Ubuntu12.04 桌面版

2.2 cf_nise_installer

本文的安装使用的是 cf_nise_installer 的脚本进行安装,正常情况下,该脚本是全自动与运行的。CloudFoundry 所安装过程中涉及的所有安装及环境需要的包他都会下载安装并配置好。
参考:https://github.com/yudai/cf_nise_installer

一定要科学上网,一定要科学上网,一定要科学上网,重要的事情要说三遍,然而并没有卵用......

整个过程中只需要执行两句命令:

sudo apt-get install curl
bash < <(curl -s -k -B https://raw.githubusercontent.com/yudai/cf_nise_installer/${INSTALLER_BRANCH:-master}/scripts/bootstrap.sh)

过程中会各种断,尤其是下载 buildpack 包的时候,每个包都好几百兆,断了只能从头下载,尤其是 buildpack_ruby 接近 1G 的大小,下载过程中自求多福吧,个中辛苦谁下谁知道。
既然说到了 cf_nise_installer,就简单分析一下他的脚本,跟句命令来看,我们执行的是工程下 scripts 文件夹下的 bootstrap.sh 脚本,其中的内容是:

#!/bin/bash -ex

if [ ! -f /etc/lsb-release ] || \
   [ `uname -m` != "x86_64" ]; then
    echo "This installer supports only Ubuntu 10.04 and 12.04 64bit server"
    exit 1;
fi

# Git bootstrap
if ! (which git); then
    sudo apt-get update
    sudo apt-get install -y git-core
fi

INSTALLER_URL=${INSTALLER_URL:-https://github.com/yudai/cf_nise_installer.git}
INSTALLER_BRANCH=${INSTALLER_BRANCH:-master}

if [ ! -d cf_nise_installer ]; then
    git clone ${INSTALLER_URL} cf_nise_installer
fi

(
    cd cf_nise_installer
    git checkout ${INSTALLER_BRANCH}
    ./scripts/install.sh
)

脚本中可以看出,cf_nise_installer 只支持 Ubuntu 10.04 and 12.04 64bit server,所以使用过程中请注意。接下来下载了 cf_nise_installer 工程之后调用了 install.sh 脚本,继续查看 install.sh 脚本:

#!/bin/bash -ex

# Detect RVM
if (rvm >/dev/null 2>&1); then
    echo "Found RVM is installed! RVM is not supported by this installer. Remove it and rerun this script."
    exit 1
fi

sudo apt-get update

./scripts/install_ruby.sh
source ~/.profile

./scripts/clone_nise_bosh.sh
./scripts/clone_cf_release.sh

./scripts/install_environemnt.sh
./scripts/install_cf_release.sh

set +x
echo "Done!"
echo "You can launch Cloud Foundry with './scripts/start.sh'"
echo "Restart your server before starting processes if you are using Ubuntu 10.04"

看到这脚本估计你会很高兴,因为主要你看到了一下几行字就代表你安装完成了:

set +x
echo "Done!"
echo "You can launch Cloud Foundry with './scripts/start.sh'"
echo "Restart your server before starting processes if you are using Ubuntu 10.04"

然而别高兴的太早,你的安装过程一定对的起苦逼二字的。
言归正传,继续看脚本,脚本先对 RVM 进行了判断,cf_nise_installer 使用的是 rbenv 这个 ruby 安装工具,没有选择使用 rvm。这个脚本照样没做啥正事,判断了一下 rvm,然后又是调用了一堆脚本:

./scripts/install_ruby.sh
source ~/.profile

./scripts/clone_nise_bosh.sh
./scripts/clone_cf_release.sh

./scripts/install_environemnt.sh
./scripts/install_cf_release.sh

别着急,一个一个的看,./scripts/install_ruby.sh:

#!/bin/bash -ex

if [ ! -d ~/.rbenv ]; then
    sudo apt-get -y install build-essential libreadline-dev libssl-dev zlib1g-dev git-core
    git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
    git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
    echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.profile
    echo 'eval "$(rbenv init -)"' >> ~/.profile
fi
source ~/.profile
if ! (rbenv versions | grep -q 1.9.3-p484); then
    rbenv install 1.9.3-p484
fi
rbenv local 1.9.3-p484

gem install bundler --no-rdoc --no-ri
rbenv rehash

很简单,这个脚本就是在装 ruby 及相关的包,继续看 clone_nise_bosh.sh

#!/bin/bash -ex

if [ ! "$(ls -A nise_bosh)" ]; then
    git submodule update --init --recursive nise_bosh


    (
        cd nise_bosh

        if [ "" != "$NISE_BOSH_REV" ]; then
            git checkout $NISE_BOSH_REV
        fi

        echo "Using Nise BOSH revision: `git rev-list --max-count=1 HEAD`"
    )
else
    echo "'nise_bosh' directory is not empty. Skipping cloning..."
fi

就像名字所说,下载 nise_bosh 项目。其实 cf_nise_installer 本来就是基于 nise_bosh 的一个脚本,真正执行安装的就是 nise_bosh 这个项目。nise_bosh 本身是一个基于 bosh 的项目,把 bosh 关于 IaaS 层的内容去除,保留了虚拟机上组建安装的内容。所以使用 nisebosh 无需 IaaS 层的 API 支持,只需要虚拟机即可安装。继续看下边的脚本,clone_cf_release.sh:

#!/bin/bash -ex

CF_RELEASE_USE_HEAD=${CF_RELEASE_USE_HEAD:-no}

ruby_version=`rbenv version | cut -f1 -d" "` # to overwrite .ruby-version

if [ ! "$(ls -A cf-release)" ]; then
    if [ -z "${CF_RELEASE_URL}" ]; then
        git submodule update --init cf-release
    else
        rmdir cf-release
        git clone ${CF_RELEASE_URL} cf-release
    fi

    (
        cd cf-release

        if [ -n "${CF_RELEASE_BRANCH}" ]; then
            git checkout -f ${CF_RELEASE_BRANCH}
        fi

        if [ $CF_RELEASE_USE_HEAD != "no" ]; then
            # required to compile a gem native extension of CCNG
            sudo apt-get -y install git-core libmysqlclient-dev libpq-dev libsqlite3-dev libxml2-dev libxslt-dev
            gem install rake -v 0.9.2.2 --no-rdoc --no-ri # hack for collector

            git submodule update --init --recursive
            RBENV_VERSION=$ruby_version bundle install
            RBENV_VERSION=$ruby_version bundle exec bosh -n create release --force
        fi
    )
else
    echo "'cf-release' directory is not empty. Skipping cloning..."
fi

下载 cf_release,如果存在则升级。cf_release 是 cf 源码经过编译后的内容。源码下载下来之后,执行 git submodule update --init --recursive 把子模块 submodule 下载下来,再执行 bosh create release 命令,就可以得到一个完整的 cf_release。。在内网可以下载肉备好了,下边就开始调作料了,install_environemnt.sh:

#!/bin/bash -ex

(
    cd nise_bosh
    sudo ./bin/init
    sudo apt-get install -y libmysqlclient-dev libpq-dev
)

这个脚本里又调用了一个新的脚本,nise_bosh/bin 里的 init 脚本:

#!/bin/bash -ex

bosh_app_dir=/var/vcap
bosh_dir=${bosh_app_dir}/bosh

apt-get update

# emulating stemcell_builder/stages/image_install_grub/apply.sh
if [ `lsb_release -cs` ==  "trusty" ]; then
    if (sed -i -e 's/GRUB_CMDLINE_LINUX=""/GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"/' /etc/default/grub); then
        update-grub
    else
        echo Your /etc/default/grub is modified from the default
        exit 1
    fi
fi

# stemcell_builder/stages/base_apt/apply.sh
DEBIAN_FRONTEND=noninteractive apt-get install -o Dpkg::Options::="--force-confnew" -f -y \
--force-yes --no-install-recommends \
build-essential libssl-dev lsof \
strace bind9-host dnsutils tcpdump iputils-arping \
curl wget libcurl3 libcurl3-dev bison libreadline6-dev \
libxml2 libxml2-dev libxslt1.1 libxslt1-dev zip unzip \
nfs-common flex psmisc apparmor-utils iptables sysstat \
rsync openssh-server traceroute libncurses5-dev quota \
libaio1 gdb tripwire libcap2-bin libyaml-dev

# stemcell_builder/stages/bosh_monit/apply.sh
DEBIAN_FRONTEND=noninteractive apt-get install -o Dpkg::Options::="--force-confnew" -f -y \
--force-yes --no-install-recommends runit

# installed somewhere else
DEBIAN_FRONTEND=noninteractive apt-get install -o Dpkg::Options::="--force-confnew" -f -y \
--force-yes --no-install-recommends gettext

# bosh_agent/lib/bosh_agent/platform/ubuntu/templates/logrotate.erb
cat <<EOF > /etc/logrotate.d/nise_bosh
/var/vcap/sys/log/*.log /var/vcap/sys/log/*/*.log /var/vcap/sys/log/*/*/*.log {
  missingok
  rotate 7
  compress
  delaycompress
  copytruncate
  size=100M
}
EOF

# stemcell_builder/stages/bosh_users/apply.sh
if [ `cat /etc/passwd | cut -f1 -d ":" | grep "^vcap$" -c` -eq 0 ]; then
    addgroup --system admin
    adduser --disabled-password --gecos Ubuntu vcap

    for grp in admin adm audio cdrom dialout floppy video plugdev dip
    do
        adduser vcap $grp
    done
else
    echo "User vcap exists already, skippking adduser..."
fi

# stemcell_builder/stages/system_kernel/apply.sh
if [ -d /boot/grub ]; then
    if [ `lsb_release -cs` ==  "lucid" ]; then
        variant="lts-backport-oneiric"

        # Headers are needed for open-vm-tools
        DEBIAN_FRONTEND=noninteractive apt-get install -o Dpkg::Options::="--force-confnew" -y -f \
            linux-image-virtual-${variant} linux-headers-virtual-${variant}
    else
        DEBIAN_FRONTEND=noninteractive apt-get install -o Dpkg::Options::="--force-confnew" -y -f \
            linux-image-virtual linux-image-extra-virtual
    fi
fi
# stemcell_builder/stages/bosh_monit/apply.sh
monit_basename=monit-5.2.4
(
    cd /tmp
    wget "http://mmonit.com/monit/dist/${monit_basename}.tar.gz" -O ${monit_basename}.tar.gz
    tar xvzf ${monit_basename}.tar.gz
    cd ${monit_basename}
    ./configure --prefix=$bosh_dir --without-ssl
    make -j4 && make install
)
mkdir -p $bosh_dir/etc
cat <<EOF > /$bosh_dir/etc/monitrc
set daemon 10
set logfile /var/vcap/monit/monit.log

set httpd port 2822 and use address 127.0.0.1
  allow cleartext /var/vcap/monit/monit.user

include /var/vcap/monit/*.monitrc
include /var/vcap/monit/job/*.monitrc
EOF
chmod 0700 $bosh_dir/etc/monitrc
mkdir -p $bosh_app_dir/monit
touch $bosh_app_dir/monit/empty.monitrc

echo Done.

if [ ! -d /sys/fs/cgroup ]; then
    echo "Restart may be required"
fi

下载了茫茫多的东西…作料撒上了,接着开始炖了 install_cf_release.sh:

#!/bin/bash -ex

NISE_IP_ADDRESS=${NISE_IP_ADDRESS:-`ip addr | grep 'inet .*global' | cut -f 6 -d ' ' | cut -f1 -d '/' | head -n 1`}

./scripts/generate_deploy_manifest.sh

(
    cd nise_bosh
    bundle install

    # Old spec format
    sudo env PATH=$PATH bundle exec ./bin/nise-bosh -y ../cf-release ../manifests/deploy.yml micro -n ${NISE_IP_ADDRESS}
    # New spec format, keeping the  monit files installed in the previous run
    sudo env PATH=$PATH bundle exec ./bin/nise-bosh --keep-monit-files -y ../cf-release ../manifests/deploy.yml micro_ng -n ${NISE_IP_ADDRESS}
)

这里边又出现了一个脚本 generate_deploy_manifest.sh:

#!/bin/bash -ex

NISE_IP_ADDRESS=${NISE_IP_ADDRESS:-`ip addr | grep 'inet .*global' | cut -f 6 -d ' ' | cut -f1 -d '/' | head -n 1`}

sed "s/192.168.10.10/${NISE_IP_ADDRESS}/g" manifests/template.yml > manifests/deploy.yml

if [ "${NISE_DOMAIN}" != "" ]; then
    if (! sed --version 1>/dev/null 2>&1); then
        # not a GNU sed
        sed -i '' "s/${NISE_IP_ADDRESS}.xip.io/${NISE_DOMAIN}/g" manifests/deploy.yml
    else
        sed -i "s/${NISE_IP_ADDRESS}.xip.io/${NISE_DOMAIN}/g" manifests/deploy.yml
    fi
fi

if [ "${NISE_PASSWORD}" != "" ]; then
    if (! sed --version 1>/dev/null 2>&1); then
        # not a GNU sed
        sed -i '' "s/c1oudc0w/${NISE_PASSWORD}/g" manifests/deploy.yml
    else
        sed -i "s/c1oudc0w/${NISE_PASSWORD}/g" manifests/deploy.yml
    fi
fi

这个脚本的主要作用就是新建一个 deploy.yml 并修改 ip 等一些东西。
所有脚本执行完毕,安装也完毕了,重启机器。后,执行~/cf_nise_installer/script/start 即可启动服务。

2.3 启动

重启后,在~/cf_nise_installer/script 下执行./start.sh,程序会自动启动。

#!/bin/bash -ex

path=`dirname $0`
cd "$path"/../

sudo /var/vcap/bosh/bin/monit
sleep 5

for process in \
    postgres \
    nats
do
    sudo /var/vcap/bosh/bin/monit start $process
    sleep 30
done;

sudo /var/vcap/bosh/bin/monit start all


echo "Waiting for all processes to start"
for ((i=0; i < 120; i++)); do
    if ! (sudo /var/vcap/bosh/bin/monit summary | tail -n +3 | grep -v -E "running$"); then
        break
    fi
    sleep 10
done

if (sudo /var/vcap/bosh/bin/monit summary | tail -n +3 | grep -v -E "running$"); then
    echo "Found process failed to start"
    exit 1
fi

set +x
echo "All processes have been started!"
api_url=`grep srv_api_uri: ./manifests/deploy.yml | awk '{ print $2 }'`
password=`grep ' - admin' ./manifests/deploy.yml | cut -f 2 -d '|'  `
echo "Login : 'cf login -a ${api_url} -u admin -p ${password} --skip-ssl-validation'"
echo "Download CF CLI from https://github.com/cloudfoundry/cli"

其实就是使用/var/vcap/bosh/bin/monit 进行启动,手动执行效果也是一样的。
可能会出现 warden 无法启动的情况,如果无法启动,执行下边三条命令:

$umount /home/yourname/.gvfs
$find . -inum 554009 -exec rm{} \;
$rm -rf .gvfs

删除后执行

sudo /var/vcap/bosh/bin/monit restart warden 

重启 warden 服务。同时也可以使用

sudo /var/vcap/bosh/bin/monit summary

来监控服务状态。
全部启动如下图:


↙↙↙阅读原文可查看相关链接,并与作者交流