PORCH Installation Manual

이 문서는 인프라 자동화 관리툴인 PORCH의 설치 매뉴얼입니다.

PORCH 소개

이 프로젝트의 핵심 기술을 “Immutable Infrastructure Automation” (IIA) and “Continuous Deployment PIpeline”(CDP) 굳이 번역하자면 “불변 인프라 자동화” 와 “연속 배치관(?)” 기술

각 용어의 정의

  • Immutable : 생성 후 변경되지 않는
  • Infrastructure: 물리/가상 자원(물리 자원, 가상 자원, 소프트웨어 스택 등)의 총체
  • Automation: 서비스에 필요한 물리/가상 자원의 생성, 설정을 자동화

필수 기능

  • 운영자의 간섭없는 시스템 설치, 설정 (non-interactive system install and configuration)
  • 각 요소 별 설정 메타데이터 형상관리 시스템 (version control system for configuration metadata of each component)
  • 구성요소 업그레이드는 기존 자원 업그레이드가 아닌 새 메타데이터 업데이트 후 새 자원으로 교체
  • 개발자의 코드가 형상관리시스템에 push되면 빌드, 시험 컨테이너가 바로 만들어져 개발 라이프사이클 자동화
  • 전통적 “Mutable and Manual” 인프라 관리기술의 문제점
  • 인프라 규모가 커짐에 따라 운영 관리 복잡성은 기하급수적으로 증가
  • 대규모 시스템 배치가 필요할 때 느리고 배치 중 오류 확률 증가
  • 보안 위협으로부터 보호하는 절차가 복잡하고 오류 확률이 높아짐

기대효과

  • 서버 시스템 완전 자동화 구현으로 운영 유지 관리 편의성 증대
  • 소스코드 형상관리와 같이 인프라 설정 형상관리를 통해 연속 통합(Continuous Integration), 연속 배치(Continuous Deployment) 구현
  • 시스템 오류와 보안 위협 감소 : 시스템 설정을 개별 서버에서 하게 되면, 업그레이드/패치 시 충돌로 인한 오류 발생 가능성 높음 ᅟ

PORCH 설치

ᅟporch 를 물리서버에 설치 할 수 있지만 가상머신에 설치하여 운영 할 수 있습니다. 해당 매뉴얼은 PORCH를 가상머신에 설치한 과정을 기술하였습니다. kvm, xen hypervisor 설치되어진 환경에서 가상머신 생성하는 과정부터 설치를 진행합니다.

서버 생성

PORCH 에 OS는 debian 입니다. debian jessie 가상머신을 생성하고 PORCH 를 설치합니다.

porch on kvm

ᅟvirt-install 을 이용하여 아래와 같이 가상머신을 구동하고 debian jessie를 설치합니다.

# mkdir -p /vm/{iso,img}
# curl -o /vm/iso/debian8.iso http://ftp.daumkakao.com/debian-cd/8.7.1/amd64/iso-cd/debian-8.7.1-amd64-netinst.iso
# vi /vm/porch.sh
#!/bin/sh

virt-install --virt-type kvm --name ᅟporch \
      --cdrom /vm/iso/debian8.iso --hvm \
      --os-variant debian8 \
      --disk path=/vm/img/ᅟporch,size=80,format=qcow2 \
      --vcpus 6 --memory 4096 \
      --network bridge=br0,model=virtio \
      --network bridge=br1,model=virtio \
      --boot cdrom,hd \
      --graphics vnc,listen=0.0.0.0,password=porchadmin

가상머신에 vnc 포트는 virsh vncdisplay 옵션으로 확인 할 수 있습니다. vnc 접속하여 설치를 진행합니다.

# virsh vncdisplay porch
:0

ᅟporch on pengxcloud

debiab jessie template이 존재한다면 pengxcli 를 이용하여 porch 가상머신을 생성합니다.

# pengxcli vm-add porch ec0edcbc-2dd0-40b4-a058-ec371fc30f6b 2 1 1024 1024 porch xenbr0 xenbr1

template이 없다면 config 파일을 만들어 신규 debian jessie를 설치합니다.

# mkdir -p /vm/{iso,img}
# curl -o /vm/iso/debian8.iso http://ftp.daumkakao.com/debian-cd/8.7.1/amd64/iso-cd/debian-8.7.1-amd64-netinst.iso
# qemu-img create -f qcow2 /vm/img/porch.qcow2 10G
# vi /vm/porch.cfg

name                    = "porch"
builder                  = "hvm"

maxmem                  = 1024
memory                  = 1024
maxvcpus                 = 4
vcpus                   = 1

boot                    = "c"
disk                    = ["format=qcow2,vdev=xvda,access=rw,target=/vms/img/porch.qcow2"]
vif                     = ["bridge=xenbr0,type=vif,model=e1000", "bridge=xenbr1,type=vif,model=e1000"]

vnc                     = 1
vnclisten               = "0.0.0.0"
vncunused               = 1
vncpasswd               = "porchadmin"

hap                     = 1
pae                     = 1
acpi                    = 1
apic                    = 1
nx                      = 1
hpet                    = 1
nestedhvm               = 0
localtime               = 1
xen_platform_pci        = 1
viridian                = 0
stdvga                  = 0
videoram                = 8

#usb                     = 1
#usbdevice               = "tablet"

bios                    = "seabios"
device_model_version    = "qemu-xen"
device_model_override   = "/usr/bin/qemu-system-i386"

on_poweroff             = "destroy"
on_reboot               = "restart"
on_crash                = "coredump-destroy"

# xl create /vm/porch.cfg

가상머신에 vnc 포트는 virsh vncdisplay 옵션으로 확인 할 수 있습니다.

# xenstore-ls /local/domain/{dom_id} | grep vnc
 vnc-pass = "porchadmin"
 vnc-listen = "0.0.0.0"
 vnc-port = "5905"

OS 설치 과정은 생략하도록 하겠습니다. 설치 중 일반 사용자 생성시 계정명은 porch 로 생성하였습니다.

기본 설정

가상머신에 접속하여 네트워크 설정을 진행합니다. 해당 문서는 배포망, 서비스망 2개에 네트워크로 구성된 환경으로 진행하였습니다. porch 의 네트워크 구성은 아래와 같이 배포망은 eth0, 서비스망 인터페이스는 eth1 로 구성하는 구조를 권장합니다.

  • 배포망(eth0) : 10.0.0.150
  • 서비스망(eth1) : 192.168.0.150

sudo 설치 및 설정

# apt update
# apt install sudo
# vi /etc/sudoers

...
ᅟporch ALL=(ALL:ALL) NOPASSWD:ALL

NTP 설치 및 설정

$ sudo apt install -y ntp
$ sudo systemctl start ntpd
$ sudo systemctl enable ntpd

docker 설치

$ sudo apt install -y apt-transport-https ca-certificates curl \
    software-properties-common
$ sudo curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -
$ sudo apt-key finger |grep 9DC8
    (key should be 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88)
$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/debian \
   $(lsb_release -cs) \
   stable"
$ sudo apt update
$ sudo apt install -y docker-ce
$ sudo gpasswd -a porch docker (udam 사용자에게 docker 그룹 권한을 부여)
$ sudo systemctl status docker (docker가 시작되었는 지 확인)

porch 사용자 계정으로 컨테이너를 구동하여 설치 검증을 합니다.

$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
78445dd45222: Pull complete
Digest: sha256:c5515758d4c5e1e838e9cd307f6c6a0d620b5e07e6f927b07d05f6d12a1ac8d7
Status: Downloaded newer image for hello-world:latest

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

시험한 컨테이너를 삭제합니다.

$ docker ps -a (컨테이너 이름 확인)
$ docker rm eloquent_austin
eloquent_austin
$ docker rmi hello-world
Untagged: hello-world:latest
Untagged: hello-world@sha256:c5515758d4c5e1e838e9cd307f6c6a0d620b5e07e6f927b07d05f6d12a1ac8d7
Deleted: sha256:48b5124b2768d2b917edcb640435044a97967015485e812545546cbed5cf0233
Deleted: sha256:98c944e98de8d35097100ff70a31083ec57704be0991a92c51700465e4544d08

etcd cluster 설치 및 설정

porch 에 etcd를 docker container로 구동합니다.

TLS certificate 생성

etcd git repo에 tls를 쉽게 생성할 수 있는 도구를 제공한다. 컨테이너를 구동하여 그 안에서 TLS 인증서를 생성한다.

$ docker run -ti --rm -v /tmp:/out golang /bin/bash
root@ae3ff554c914:/go# git clone https://github.com/coreos/etcd
root@ae3ff554c914:/go# cd etcd/hack/tls-setup
root@ae3ff554c914:/go/etcd/hack/tls-setup# mkdir /out/etcd-cert
root@ae3ff554c914:/go/etcd/hack/tls-setup# apt update
root@ae3ff554c914:/go/etcd/hack/tls-setup# apt install -y vim
root@ae3ff554c914:/go/etcd/hack/tls-setup# vi config/ca-config.json
{
  "signing": {
    "default": {
        "usages": [
          "signing",
          "key encipherment",
          "server auth",
          "client auth"
        ],
        "expiry": "87600h"
    }
  }
}

87600h == 10 years (should be enough.)

root@ae3ff554c914:/go/etcd/hack/tls-setup# vi config/ca-csr.json
{
  "CN": "ETCD CA",
  "key": {
    "algo": "ecdsa",
    "size": 384
  },
  "names": [
    {
      "O": "iOrchard",
      "OU": "Service Technology Team",
      "L": "Gangnam-gu",
      "ST": "Seoul",
      "C": "KR"
    }
  ]
}
root@ae3ff554c914:/go/etcd/hack/tls-setup# vi config/etcd0.json
{
  "CN": "etcd0",
  "hosts": [
    "10.0.0.150",
    "porch",
    "127.0.0.1",
    "localhost"
  ],
  "key": {
    "algo": "ecdsa",
    "size": 384
  },
  "names": [
    {
      "O": "iOrchard",
      "OU": "Service Technology Team",
      "L": "Gangnam-gu"
    }
  ]
}

클라이언트 인증서를 설정합니다.
root@ae3ff554c914:/go/etcd/hack/tls-setup# vi config/client.json
{
  "CN": "etcd-client",
  "hosts": [
    "127.0.0.1",
    "localhost"
  ],
  "key": {
    "algo": "ecdsa",
    "size": 384
  },
  "names": [
    {
      "O": "iOrchard",
      "OU": "Service Technology Team",
      "L": "Gangnam-gu"
    }
  ]
}

root@ae3ff554c914:/go/etcd/hack/tls-setup# vi Makefile
: set paste
...
req:
    $(CFSSL) gencert \
      -ca certs/ca.pem \
      -ca-key certs/ca-key.pem \
      -config config/ca-config.json \
      config/etcd0.json | $(JSON) -bare certs/etcd0
    $(CFSSL) gencert \
      -ca certs/ca.pem \
      -ca-key certs/ca-key.pem \
      -config config/ca-config.json \
      config/client.json | $(JSON) -bare certs/client
...

Makefile의 req 부분에서 etcd0, client 생성을 위와 같이 설정합니다. 위 req 부분에서 etcd0과 client 부분만 변경하고 나머지 엔트리들을 삭제합니다.
Makefile은 indentation으로 TAB을 사용하므로 에러가 발생하기에 위 내용을 copy & paste 할 경우 vi 에 pate mode로 전환하여 붙여넣습니다.

TLS certs 를 생성합니다.

cfssl 바이너리를 가져와 `/go/bin/`에 저장합니다.
root@ae3ff554c914:/go/etcd/hack/tls-setup# make cfssl
go get -u -tags nopkcs11 github.com/cloudflare/cfssl/cmd/cfssl
go get -u github.com/cloudflare/cfssl/cmd/cfssljson
go get -u github.com/mattn/goreman

CA 인증서를 생성합니다.
root@ae3ff554c914:/go/etcd/hack/tls-setup# make ca
mkdir -p certs
2017/06/07 17:16:07 [INFO] generating a new CA key and certificate from CSR
2017/06/07 17:16:07 [INFO] generate received request
2017/06/07 17:16:07 [INFO] received CSR
2017/06/07 17:16:07 [INFO] generating key: ecdsa-384
2017/06/07 17:16:07 [INFO] encoded CSR
2017/06/07 17:16:07 [INFO] signed certificate with serial number 125782362072859064781008653288266758237889669094


생성된 CA 인증서로 각 etcd 서버/클라이언트 인증서를 생성합니다.
root@ae3ff554c914:/go/etcd/hack/tls-setup# make req
2017/06/07 17:21:19 [INFO] generate received request
2017/06/07 17:21:19 [INFO] received CSR
2017/06/07 17:21:19 [INFO] generating key: ecdsa-384
2017/06/07 17:21:19 [INFO] encoded CSR
2017/06/07 17:21:19 [INFO] signed certificate with serial number 715595833875702950179628632233744324477815970137
2017/06/07 17:21:19 [INFO] generate received request
2017/06/07 17:21:19 [INFO] received CSR
2017/06/07 17:21:19 [INFO] generating key: ecdsa-384
2017/06/07 17:21:19 [INFO] encoded CSR
2017/06/07 17:21:19 [INFO] signed certificate with serial number 169717375321772320384205510672357633574611121108


certs 파일에 있는 모든 인증서를 /out/etcd-cert/ 로 복사합니다.
root@ae3ff554c914:/go/etcd/hack/tls-setup# cp certs/* /out/etcd-cert/

이제 porch 서버에 /tmp/etcd-cert/ 경로를 확인해보면 위 복사한 인증서를 확인 할 수 있습니다.

해당 인증서를 이용하여 etcd 컨테이너를 구동합니다. /tmp/etcd-cert/ 로부터 /etc/ssl/etcd/ 로 파일들을 복사합니다.

$ sudo mkdir /etc/ssl/etcd
$ sudo cp /tmp/etcd-cert/{ca*.pem,etcd0*.pem} /etc/ssl/etcd/

클라이언트 인증서를 /etc/ssl/etcd/ 에 놓고 porch 사용자가 key 파일을 읽을 수 있도록 권한을 변경합니다.

$ sudo cp /tmp/etcd-cert/client{-key,}.pem  /etc/ssl/etcd/
$ sudo chmod 644 /etc/ssl/etcd/client-key.pem

인증서 내용을 확인하려면 아래 명령으로 확인 할 수 있습니다.

$ openssl x509 -noout -text -in /etc/ssl/etcd/etcd0.pem

아래 etcd.sh 스크립트 파일을 생성합니다.

$ vi etcd.sh

HostIP=$(ip addr show dev eth0 |grep 'inet ' |awk '{print $2}' |cut -d'/' -f1)

docker run -d \
 -v /etc/ssl/etcd:/etc/ssl/certs \
 -v /var/lib/etcd:/etcd0.etcd \
 -p 4001:4001 -p 2380:2380 -p 2379:2379 \
 --name etcd0 quay.io/coreos/etcd \
 etcd \
 -name etcd0 \
 -trusted-ca-file=/etc/ssl/certs/ca.pem \
 -cert-file=/etc/ssl/certs/etcd0.pem \
 -key-file=/etc/ssl/certs/etcd0-key.pem \
 -client-cert-auth=1 \
 -peer-trusted-ca-file=/etc/ssl/certs/ca.pem \
 -peer-cert-file=/etc/ssl/certs/etcd0.pem \
 -peer-key-file=/etc/ssl/certs/etcd0-key.pem \
 -peer-client-cert-auth=1 \
 -advertise-client-urls https://${HostIP}:2379,https://${HostIP}:4001 \
 -listen-client-urls https://0.0.0.0:2379,https://0.0.0.0:4001 \
 -initial-advertise-peer-urls https://${HostIP}:2380 \
 -listen-peer-urls https://0.0.0.0:2380 \
 -initial-cluster-token etcd-cluster \
 -initial-cluster etcd0=https://${HostIP}:2380 \
 -initial-cluster-state new

etcd 를 구동한 뒤 구동상태를 확인합니다.

$ sh etcd.sh
$ docker ps
CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                                                      NAMES
8b096a81df06        quay.io/coreos/etcd   "etcd -name etcd0 ..."   9 minutes ago       Up 9 minutes        0.0.0.0:2379-2380->2379-2380/tcp, 0.0.0.0:4001->4001/tcp   etcd0

위 컨테이너로부터 etcdctl 바이너리를 PORCH 서버로 복사합니다.

$ docker cp etcd0:/usr/local/bin/etcdctl .

이제 클라이언트에서 클라이언트 인증서를 이용하여 접속을 시도합니다. PORCH 에 배포망 ip를 hosts 파일에 등록합니다.

$ sudo echo "10.0.0.150    etcd0" >> /etc/hosts
$ ./etcdctl --endpoints https://etcd0:2379 \
    --cert-file /etc/ssl/etcd/client.pem \
    --key-file /etc/ssl/etcd/client-key.pem \
    --ca-file /etc/ssl/etcd/ca.pem member list
4ec2422565450a13: name=etcd0 peerURLs=https://10.0.0.150:2380 clientURLs=https://10.0.0.150:2379,https://10.0.0.150:4001 isLeader=true

소프트웨어 설치 및 설정

porch 사용자 계정으로 porch 소프트웨어를 설치합니다.

python3 관련 필수 패키지 설치

  • python3-venv (for virtual env.)
  • gcc (for cryptography compile)
  • python3-dev (for cryptography compile)
  • libssl-dev (for cryptography compile)
$ sudo apt install -y python3-venv gcc python3-dev libssl-dev

python 가상환경 설정

$ mkdir .envs
$ pyvenv .envs/porch
$ vi .bashrc
...
# porch virtualenv
source .envs/porch/bin/activate

$ source .envs/porch/bin/activate
(porch) $

flask webframework 설치 및 설정

porch 는 Web backend API 서버로 Flask를 사용합니다.

(porch) $ pip install -U pip
(porch) $ pip install
          flask-restplus        (rest api)
          python-etcd           (etcd python client)
          requests              (http python client)
          flask-jwt-extended    (json web token)
          bcrypt                (salt-key based hash password generator)
          flask-cors            (cross origin resource sharing support)
          cryptography          (ssh pub/private key generator)
          GitPython             (git python library)
          ansible==2.2.1.0      (automation tool)

ansible 2.3.0은 python 3.4와 호환되지 않습니다. 참조 :
https://github.com/ansible/ansible/issues/24180

cliff cli framework 설치 및 설정

Cliff는 CLI framework 로 ud 명령어를 사용하기 위해 설치합니다.

(porch) $ pip install -U setuptools
(porch) $ pip install cliff

nfs 서비스 중지

porch 는 nfs를 사용하지 않으므로 nfs 서비스를 사용 중이라면 다음과 같이 nfs 서비스를 중지합니다.

(porch) $ sudo systemctl stop nfs-kernel-server nfs-common rpcbind
(porch) $ sudo systemctl mask nfs-kernel-server nfs-common rpcbind

porch 소스 파일 가져오기

(ᅟporch) $ git clone https://git.iorchard.co.kr/jijisa/porch.git

fai 설치 및 설정

(porch) $ sudo su
# wget -O - http://fai-project.org/download/074BCDE4.asc | apt-key add -
# echo "deb http://fai-project.org/download jessie koeln" > \
    /etc/apt/sources.list.d/fai.list
# apt update
# apt install -y fai-quickstart pxelinux rinse aptitude xz-utils \
        ipmitool freeipmi-tools

# sed -i -e 's/^#deb/deb/' /etc/fai/apt/sources.list
# sed -i -e 's/#LOGUSER/LOGUSER/' /etc/fai/fai.conf

# fai-setup -v
(It takes a long time)
...
FAI setup finished.
Log file written to /var/log/fai/fai-setup.log

copy porch/srv/tftp/fai/* /srv/tftp/fai/

(ᅟporch) $ sudo chown -R porch:porchard /srv/tftp/fai
(ᅟporch) $ cp -a porch/srv/tftp/fai/* /srv/tftp/fai/

copy fai config files

(ᅟporch) $ sudo chown -R porch:porch /srv/fai
(ᅟporch) $ cp -a porch/srv/fai/config/* /srv/fai/config/
(ᅟporch) $ mkdir /srv/fai/{pub,pri}keys
$ mkdir /srv/fai/config/pubkeys

copy /usr/lib/PXELINUX/lpxelinux.0 to /srv/tftp/fai

(ᅟporch) $ cp /usr/lib/PXELINUX/lpxelinux.0 /srv/tftp/fai

create and copy public/private keys to /srv/fai/{pub,pri}keys/

(ᅟporch) $ ssh-keygen -N ''
(ᅟporch) $ cp .ssh/id_rsa.pub /srv/fai/config/pubkeys/authorized_keys
(ᅟporch) $ cp .ssh/id_rsa /srv/fai/prikeys/prikey

copy and edit boot.ipxe (IP address)

IP 주소를 porch에 배포망 IP 주소로 바꾼다.

(ᅟporch) $ cd /srv/tftp/fai
(ᅟporch) $ cp boot.ipxe.dev boot.ipxe
(ᅟporch) $ vi boot.ipxe

#!ipxe

echo ${net1/mac}
chain http://10.0.0.150/api/fai/pxe/${net1/mac}

get undionly.kpxe

$ wget -O /srv/tftp/fai/undionly.kpxe http://boot.ipxe.org/undionly.kpxe

create squash image

$ sudo fai-cd -d "" -SMeJ /srv/tftp/fai/squash.img

create basefiles

$ cd /srv/fai/config/basefiles
$ sudo ./mk-basefile CENTOS7_64
$ sudo ./mk-basefile JESSIE64
$ sudo ln -s /usr/share/debootstrap/scripts/gutsy \
              /usr/share/debootstrap/scripts/xenial
$ sudo ./mk-basefile XENIAL64
$ xz CENTOS7_64.tar
$ xz JESSIE64.tar
$ xz XENIAL64.tar
$ cd /srv/fai/config
$ mkdir pubkeys saltkey
$ sh config_tarball.sh
$ mv fai-*.tar /srv/tftp/fai/

configuration package

ᅟ추가 설치가 필요한 패키지가 있다면 package_config/{class} 설정 파일에 패키지명을 추가합니다. ᅟ 패키지 명령은 PACKAGES 단어 다음에 ᅟ수행할 명령 이름으로 정의합니다. 명령 이름은 apt-get, aptitude 또는 yum 과 같은 패키지 도구에 매핑됩니다.

추가로 명령 이름의 목록을 install_packages 를 사용하여 확인 할 수 있습니다.

$ sudo install_packages -H
List of known commands for package_config files
Short list:
apt
aptitude
aptitude-r
cupt
cupt-r
dnfgroup
dnfi
dnfr
dselect-upgrade
hold
install
install-norec
remove
rpmr
smarti
smartr
taskinst
taskrm
unpack
urpme
urpmi
y2i
y2r
yast
yumgroup
yumi
yumr
zypper
zypper-rm

Long list:
            apt    apt -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confnew install
       aptitude    aptitude -R -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confnew install
     aptitude-r    aptitude -r -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confnew install
           cupt    cupt -R -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confnew install
         cupt-r    cupt -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confnew install
       dnfgroup    dnf -y group install
           dnfi    dnf -y install
           dnfr    dnf -y remove
dselect-upgrade    apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confnew dselect-upgrade
           hold    dpkg --set-selections
        install    apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confnew --fix-missing install
  install-norec    apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confnew --fix-missing install --no-install-recommends
         remove    apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confnew --purge remove
           rpmr    rpm -e
         smarti    smart install -y
         smartr    smart remove -y
       taskinst    tasksel install
         taskrm    tasksel remove
         unpack    cd /var/cache/apt/archives/partial/; aptitude download
          urpme    urpme --auto --foce --allow-force --keep
          urpmi    urpmi --auto --foce --allow-force --keep
            y2i    y2pmsh isc
            y2r    y2pmsh remove
           yast    yast -i
       yumgroup    yum -y groupinstall
           yumi    yum -y install
           yumr    yum -y remove
         zypper    zypper -n install
      zypper-rm    zypper -n remove

예로 debian class 에 dig, nslookup 을 사용하기 위하여 dnsutils 패키지를 추가하였습니다. install 명령 이름은 install 뒤에 지정된 모든 패키지를 설치합니다. 패키지 이름에 ᅟ하이픈이 추가되면 패키지를 제고하고 설치하지 않습니다.

아래와 같이 package_config 디렉토리로 이동하여 DEBIAN class package 설정 파일을 열어 dnsutils 패키지명을 추가하였습니다.

$ cd /srv/fai/config/package_config
$ vi DEBIAN
...
PACKAGES install I386
linux-image-686-pae initramfs-tools
memtest86+

PACKAGES install CHROOT
linux-image-686-pae-
linux-image-amd64-

PACKAGES install AMD64
linux-image-amd64 initramfs-tools
memtest86+

PACKAGES install DHCPC
isc-dhcp-client

PACKAGES install GRUB_PC
grub-pc grub-legacy- lilo-

PACKAGES install LVM
lvm2

PACKAGES install PORCH
nano-
curl

PACKAGES install
dnsutils

수정이 완료되었다면 위 create basefiles 작업에서 수행하였던 config tarball 을 다시 생성하고 이동하는 작업을 다시 진행합니다.

$ cd /srv/fai/config
$ sh config_tarball.sh
$ mv fai-*.tar /srv/tftp/fai/

porch 포털 페이지에서 os 자동 배포할 서버를 Provisioned 준비 상태로 변경 후 os 를 배포하여 정상적으로 패키지가 설치되었는지 점검합니다.

dhcp 설정

$ sudo cp porch/conf/dhcpd.conf.dev /etc/dhcp/dhcpd.conf
$ sudo vi /etc/dhcp/dhcpd.conf

    subnet 10.0.0.0 netmask 255.255.0.0 {
        option routers 10.0.0.23;
    ...
        filename "http://10.0.0.150/api/fai/boot/";
    ...

$ sudo systemctl restart isc-dhcp-server

ᅟpxeboot 를 위한 설정

porch 로 자동설치하는 머신들은 porch 에 배포망 IP를 gateway로 설정하여 인터넷 연결이 되어야 합니다. 따라서 porch 에 IP Masquerade 설정을 합니다. 해당 매뉴얼과 같이 porch 가 가상머신으로 구동 중이라면, porch 가 구동 중인 물리머신에 배포망 IP를 gateway 로 설정합니다.

아래는 porch(debian) 에서의 설정 방법입니다.

$ sudo iptables-save > /etc/iptables.up.rules
$ vi /etc/iptables.up.rules
...
:POSTROUTING ACCEPT [6311:437650]
-A POSTROUTING -o eth0 -j MASQUERADE
...

CLI에서 수동 입력시 아래 명령으로 수행합니다.

$ sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
$ sudo vi /etc/sysctl.conf
...
net.ipv4.ip_forward=1
...

$ sudo sysctl -p

flask backend 설정

$ cp porch/porch/config.py.dev porch/porch/config.py
$ cp porch/porch/settings.py.dev porch/porch/settings.py

초기 관리자 salt/password를 먼저 생성한다.

$ python porch/scripts/create_adminpw.py

출력된 salt과 adminpw 를 config.py에 기입한다.

$ python porch/scripts/create_jwt_key.py

출력된 jwt key 를 config.py에 기입한다. Do not Edit Below!! 라인 전까지 udam 서버에 맞게 설정을 수정한다.

$ vi porch/porch/config.py

...
## URL
PORCH_URL = 'http://10.0.0.150/api/fai'  # Put PORCH's pxe network ip address.

# ADMIN_* is used when there is no admin entry in etcd.
# ADMIN_SALT = bcrypt.gensalt()
# ADMIN_PW = bcrypt.hashpw(b"plaintext_password", ADMIN_SALT)
ADMIN_ID = 'admin'
ADMIN_SALT = '$2b$12$cQBcbldPwh.o5uH52J1TGO'
ADMIN_PW = '$2b$12$cQBcbldPwh.o5uH52J1TGOkc5FRxfHwfZ2oPktk4L/fDNUNOfHaue'

# JWT secret key
# Create random key: binascii.hexlify(os.urandom(24)).decode()
JWT_SECRET_KEY = '8e2edbd163909f711be60ec7ca07d0e1f8a2b540b6fef2cc'
JWT_ACCESS_TOKEN_EXPIRES = timedelta(minutes=60)
#JWT_ACCESS_TOKEN_EXPIRES is 15 minutes default.
#JWT_REFRESH_TOKEN_EXPIRES is 1 month default.

# ipmi
IPMIUSER = 'root'
IPMIPASS = 'xxxx'

# Terminal
PORCH_USER = 'porch'
PORCHSHELL = 'myshell'
TERM_PORT_BEGIN = 40000
TERM_PORT_END = 41000
MY_IP = '192.168.0.150'

# PROXY
PROXY_URL = '10.0.0.150'
PROXY_PORT = 3128
...

settings.py도 udam 서버에 맞게 설정을 수정합니다. etcd cert 경로를 지정합니다.

$ vi porch/porch/settings.py

...
# Flask settings
FLASK_HOST = '0.0.0.0'
FLASK_PORT = 8000
FLASK_DEBUG = True  # Do not use debug mode in production

# Flask-Restplus settings
RESTPLUS_SWAGGER_UI_DOC_EXPANSION = 'list'
RESTPLUS_VALIDATE = True
RESTPLUS_MASK_SWAGGER = False
RESTPLUS_ERROR_404_HELP = False

# ETCD settings
ETCD_HOST = '10.0.0.150'
ETCD_PORT = 2379
ETCD_PROTO = 'https'  # 'http' or 'https'
ETCD_PREFIX = '/porch'
ETCD_CERT = ('/etc/ssl/etcd/client.pem',
             '/etc/ssl/etcd/client-key.pem')
ETCD_CA_CERT = '/etc/ssl/etcd/ca.pem'

기본 docker image 저장

porch에서 사용하는 기본 docker 이미지로는 myshell 이 있습니다. 해당 이미지를 이용하여 파일 배포 관리 콘솔을 사용합니다.

$ mkdir docker
$ cd docker
$ vi Dockerfile

FROM debian:jessie
MAINTAINER Heechul Kim <jijisa@iorchard.net>
LABEL version="1.0"
LABEL description="This is an image for common shell."
USER root
RUN apt-get update && \
    apt-get upgrade -y && \
    apt-get install -y openssh-client vim dnsutils && \
    apt-get clean && \
    rm -fr /var/lib/apt/lists/*

$ docker build -t myshell .

이미지가 정상적으로 생성되었는지 확인합니다.

$ docker images
myshell               latest              a9aea684cc9f        38 seconds ago

shellinabox 설치

$ cd ~
$ sudo apt install -y git libssl-dev libpam0g-dev zlib1g-dev dh-autoreconf
$ git clone https://github.com/shellinabox/shellinabox.git
$ cd shellinabox
$ autoreconf -i
$ ./configure && make
$ sudo cp shellinaboxd /usr/local/bin/
$ cd ..
$ rm -fr shellinabox

필수 디렉토리 생성

$ mkdir porch/porch/{git,log,play}
$ mkdir porch/porch/log/{os,app,file}

uwsgi 설치 및 설정

$ sudo apt install -y uwsgi uwsgi-plugin-python3
$ sudo cp porch/conf/uwsgi.ini /etc/uwsgi/apps-available/porch.ini
$ sudo ln -s /etc/uwsgi/apps-available/porch.ini /etc/uwsgi/apps-enabled/porch.ini
$ sudo cp /usr/share/uwsgi/conf/default.ini /etc/default/uwsgi_default.ini
$ sudo vi /etc/default/uwsgi_default.ini

    chmod-socket = 666 (nginx는 www-data, 그러므로 666필요)
    uid = porch
    gid = porch


$ sudo vi /etc/default/uwsgi

    INHERITED_CONFIG=/etc/default/uwsgi_default.ini

$ sudo systemctl restart uwsgi

nginx 설치 및 설정

$ sudo apt install -y nginx
$ sudo cp porch/conf/nginx_porch /etc/nginx/sites-available/porch
$ sudo vi /etc/nginx/sites-available/porch

    -    root /home/jijisa/porch/web;
    +    root /home/porch/porch/web;

    -        uwsgi_pass unix:/home/jijisa/porch/porch.sock;
    +        uwsgi_pass unix:/run/uwsgi/app/porch/socket;

$ sudo ln -sf /etc/nginx/sites-available/porch /etc/nginx/sites-enabled/default
$ sudo systemctl restart nginx

nodeenv 설치 및 설정

(porch) $ pip install nodeenv
(porch) $ nodeenv -p

quasar 설치 및 설정

(porch) $ cd porch/quasar
(porch) $ npm install -g quasar-cli
(porch) $ quasar init porch
(porch) $ cp -a src porch/
(porch) $ cp config.js porch/src/
(porch) $ cd porch
(porch) $ npm install
(porch) $ npm install vue-cookie vue-resource vuelidate vuex --save
(porch) $ vi src/config.js

    export const API_URL = 'http://192.168.0.150/api'

위 IP를 porch 에 서비스 IP로 수정합니다.

(porch) $ quasar build
(porch) $ cp -a dist ~/porch/web

cli 설치 및 설정

(porch) $ cd porch/cliff
(porch) $ python setup.py build
(porch) $ cp po/config.py.dev po/config.py
(porch) $ vi po/config.py

    API_ENDPOINT = 'http://localhost:80/api'

이제 웹브라우저를 열고 http://{서비스망 IP} 에 접속하여 페이지를 확인하고 관리자 계정(admin)으로 로그인 합니다. 로그인이 성공하였다면 PORCH 관리자 매뉴얼을 참조하여 인프라 자동화 서비스를 시작하도록 하겠습니다.