카테고리 보관물: infra

[Tomcat] 리눅스의 톰캣 로그에서 한글깨지는 문제 해결방법

리눅스의 톰캣 로그에서 한글이 깨져나오네요.

톰캣의 인코딩에 문제가 생겨서 그러겠죠?

[톰캣설치 폴더 > bin] 디렉토리로 가면 catalina.sh 파일이 있습니다.

그 파일을 편집기로 여시구요.

-Djava.io.tmpdir=”$CATALINA_TMPDIR” \
이 부분 찾아서 그 아래에 아래 소스를 모두 추가합니다.

-Djava.io.tmpdir=”$CATALINA_TMPDIR” \
-Dfile.encoding=”utf-8″\

수정한 파일을 저장하고, 톰캣을 재시작하면 아래처럼 로그에 한글이 잘 나옵니다.

kubeadm 이용 Ubuntu 20.04에 Kubernetes 클러스터 설치

Kubernetes는 온프레미스 서버 또는 하이브리드 클라우드 환경에서 대규모로 컨테이너화된 애플리케이션을 오케스트레이션 및 관리하기 위한 도구입니다. Kubeadm은 사용자가 모범 사례 시행을 통해 프로덕션 준비 Kubernetes 클러스터를 설치할 수 있도록 Kubernetes와 함께 제공되는 도구입니다. 이 튜토리얼은 kubeadm을 사용하여 Ubuntu 20.04에 Kubernetes 클러스터를 설치하는 방법을 보여줍니다.

Kubernetes 클러스터 배포에는 두 가지 서버 유형이 사용됩니다.

  • 마스터 : Kubernetes 마스터는 Kubernetes 클러스터의 포드, 복제 컨트롤러, 서비스, 노드 및 기타 구성 요소에 대한 제어 API 호출이 실행되는 곳입니다.
  • Node : Node는 컨테이너에 런타임 환경을 제공하는 시스템입니다. 컨테이너 포드 세트는 여러 노드에 걸쳐 있을 수 있습니다.

실행 가능한 설정을 위한 최소 요구 사항은 다음과 같습니다.

  • 메모리: 컴퓨터당 2GiB 이상의 RAM
  • CPU: 컨트롤 플레인 머신에 최소 2개의 CPU 가 있습니다.
  • 컨테이너 풀링을 위한 인터넷 연결 필요(개인 레지스트리도 사용할 수 있음)
  • 클러스터의 머신 간 전체 네트워크 연결 – 개인 또는 공용입니다.

Ubuntu 20.04에 Kubernetes 클러스터 설치

My Lab 설정에는 3개의 서버가 있습니다. 컨테이너화된 워크로드를 실행하는 데 사용할 하나의 컨트롤 플레인 머신과 두 개의 노드. 예를 들어 HA용 제어 평면 노드 3개 를 사용하여 원하는 사용 사례 및 부하에 맞게 노드를 더 추가할 수 있습니다 .

서버 유형 서버 호스트 이름 명세서
주인 k8s-master01.computingforgeeks.com 4GB 램, 2vcpus
노동자 k8s-worker01.computingforgeeks.com 4GB 램, 2vcpus
노동자 k8s-worker02.computingforgeeks.com 4GB 램, 2vcpus

1단계: Kubernetes 서버 설치

Ubuntu 20.04에서 Kubernetes 배포에 사용할 서버를 프로비저닝합니다. 설정 프로세스는 사용 중인 가상화 또는 클라우드 환경에 따라 다릅니다.

서버가 준비되면 업데이트하십시오.

sudo apt update
sudo apt -y upgrade && sudo systemctl reboot

2단계: kubelet, beadm 및 kubectl 설치

서버가 재부팅되면 Ubuntu 20.04용 Kubernetes 저장소를 모든 서버에 추가하십시오.

sudo apt update
sudo apt -y install curl apt-transport-https
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

그런 다음 필요한 패키지를 설치합니다.

sudo apt update
sudo apt -y install vim git curl wget kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

kubectl 버전을 확인하여 설치를 확인합니다.

$ kubectl version --client && kubeadm version
Client Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.2", GitCommit:"8b5a19147530eaac9476b0ab82980b4088bbc1b2", GitTreeState:"clean", BuildDate:"2021-09-15T21:38:50Z", GoVersion:"go1.16.8", Compiler:"gc", Platform:"linux/amd64"}
kubeadm version: &version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.2", GitCommit:"8b5a19147530eaac9476b0ab82980b4088bbc1b2", GitTreeState:"clean", BuildDate:"2021-09-15T21:37:34Z", GoVersion:"go1.16.8", Compiler:"gc", Platform:"linux/amd64"}

3단계: 스왑 비활성화

스왑과 방화벽을 끕니다.

sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
sudo swapoff -a
sudo ufw disable

crontab -e
@reboot sudo swapoff -a 

커널 모듈을 활성화하고 sysctl을 구성합니다.

# Enable kernel modules
sudo modprobe overlay
sudo modprobe br_netfilter

# Add some settings to sysctl
sudo tee /etc/sysctl.d/kubernetes.conf<<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

# Reload sysctl
sudo sysctl --system

4단계: 컨테이너 런타임 설치

Pod에서 컨테이너를 실행하기 위해 Kubernetes는 컨테이너 런타임을 사용합니다. 지원되는 컨테이너 런타임은 다음과 같습니다.

  • 도커
  • CRI-O
  • 컨테이너

참고 : 한 번에 하나의 런타임을 선택해야 합니다 .

도커 런타임 설치:

# Add repo and Install packages
sudo apt update
sudo apt install -y curl gnupg2 software-properties-common apt-transport-https ca-certificates

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

sudo apt update
sudo apt install -y containerd.io docker-ce docker-ce-cli

# Create required directories
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo mkdir -p /etc/docker

# Create daemon json config file
sudo tee /etc/docker/daemon.json <<EOF
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF

# Start and enable Services
sudo systemctl daemon-reload 
sudo systemctl restart docker
sudo systemctl enable docker

CRI-O 설치:

# Ensure you load modules
sudo modprobe overlay
sudo modprobe br_netfilter

# Set up required sysctl params
sudo tee /etc/sysctl.d/kubernetes.conf<<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

# Reload sysctl
sudo sysctl --system

# Add Cri-o repo
sudo su -
OS="xUbuntu_20.04"
VERSION=1.22
echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
echo "deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.list
curl -L https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:$VERSION/$OS/Release.key | apt-key add -
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/Release.key | apt-key add -

# Update CRI-O CIDR subnet
sudo sed -i 's/10.85.0.0/192.168.0.0/g' /etc/cni/net.d/100-crio-bridge.conf

# Install CRI-O
sudo apt update
sudo apt install cri-o cri-o-runc

# Start and enable Service
sudo systemctl daemon-reload
sudo systemctl restart crio
sudo systemctl enable crio
sudo systemctl status crio

컨테이너 설치:

# Configure persistent loading of modules
sudo tee /etc/modules-load.d/containerd.conf <<EOF
overlay
br_netfilter
EOF

# Load at runtime
sudo modprobe overlay
sudo modprobe br_netfilter

# Ensure sysctl params are set
sudo tee /etc/sysctl.d/kubernetes.conf<<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

# Reload configs
sudo sysctl --system

# Install required packages
sudo apt install -y curl gnupg2 software-properties-common apt-transport-https ca-certificates

# Add Docker repo
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

# Install containerd
sudo apt update
sudo apt install -y containerd.io

# Configure containerd and start service
sudo su -
mkdir -p /etc/containerd
containerd config default>/etc/containerd/config.toml

# restart containerd
sudo systemctl restart containerd
sudo systemctl enable containerd
systemctl status  containerd

 cgroup 드라이버 설치

systemd cgroup 드라이버를 사용하려면 에서 plugins.cri.systemd_cgroup = true 를 설정 /etc/containerd/config.toml하십시오. kubeadm을 사용할 때 kubelet 용 cgroup 드라이버를 수동으로 구성하십시오.

5단계: 마스터 노드 초기화

마스터로 사용할 서버에 로그인하고 br_netfilter 모듈이 로드되었는지 확인합니다.

$ lsmod | grep br_netfilter
br_netfilter           22256  0 
bridge                151336  2 br_netfilter,ebtable_broute

컨테이너 이미지 가져오기:

$ sudo kubeadm config images pull
[config/images] Pulled k8s.gcr.io/kube-apiserver:v1.22.2
[config/images] Pulled k8s.gcr.io/kube-controller-manager:v1.22.2
[config/images] Pulled k8s.gcr.io/kube-scheduler:v1.22.2
[config/images] Pulled k8s.gcr.io/kube-proxy:v1.22.2
[config/images] Pulled k8s.gcr.io/pause:3.5
[config/images] Pulled k8s.gcr.io/etcd:3.5.0-0
[config/images] Pulled k8s.gcr.io/coredns/coredns:v1.8.4

kubelet 서비스를 활성화합니다.

sudo systemctl enable kubelet

이제 etcd (클러스터 데이터베이스)와 API 서버를 포함하는 컨트롤 플레인 구성 요소를 실행할 시스템을 초기화하려고 합니다.

 

CRI 소켓이 여러 개인 경우 다음 --cri-socket중 하나를 선택 하는 데 사용하십시오.

# CRI-O
sudo kubeadm config images pull --cri-socket /var/run/crio/crio.sock

# Containerd
sudo kubeadm config images pull --cri-socket /run/containerd/containerd.sock

# Docker
sudo kubeadm config images pull --cri-socket /var/run/dockershim.sock

kubeadm init클러스터를 부트스트랩하는 데 사용되는 기본 옵션입니다.

--control-plane-endpoint : 모든 제어 평면 노드에 대한 공유 끝점을 설정합니다. DNS/IP일 수 있음
 --pod-network-cidr : 포드 네트워크 추가 기능을 설정하는 데 사용됨 CIDR
 --cri-socket : 런타임 소켓 경로를 설정하기 위해 컨테이너 런타임이 둘 이상인 경우 사용
 --apiserver-advertise-address : 이 특정 제어 평면 노드의 API 서버에 대한 광고 주소 설정

공유 엔드포인트가 없는 부트스트랩 (Worker 초기 설정 시 진행)

DNS 엔드포인트를 사용하지 않고 클러스터를 부트스트랩하려면 다음을 실행합니다.

sudo kubeadm init \
  --pod-network-cidr=192.168.0.0/16

공유 엔드포인트가 있는 부트스트랩(제어 평면 API의 DNS 이름)

클러스터 엔드포인트 DNS 이름을 설정하거나 /etc/hosts 파일에 레코드를 추가합니다.

$ sudo vim /etc/hosts
172.29.20.5 k8s-cluster.computingforgeeks.com

클러스터 생성: (Master Node 경우)

sudo kubeadm init \
  --pod-network-cidr=192.168.0.0/16 \
  --upload-certs \
  --control-plane-endpoint=k8s-cluster.computingforgeeks.com

참고 : 192.168.0.0/16 이 이미 네트워크 내에서 사용 중인 경우 위 명령에서 192.168.0.0/16을 대체하여 다른 포드 네트워크 CIDR을 선택해야 합니다.

컨테이너 런타임 소켓:

실행 시간 Unix 도메인 소켓 경로
도커 /var/run/docker.sock
용기에 담긴 /run/containerd/containerd.sock
만들기 /var/run/crio/crio.sock

선택적으로 런타임용 소켓 파일을 전달하고 설정에 따라 주소를 알릴 수 있습니다.

# CRI-O
sudo kubeadm init \
  --pod-network-cidr=192.168.0.0/16 \
  --cri-socket /var/run/crio/crio.sock \
  --upload-certs \
  --control-plane-endpoint=k8s-cluster.computingforgeeks.com

# Containerd
sudo kubeadm init \
  --pod-network-cidr=192.168.0.0/16 \
  --cri-socket /run/containerd/containerd.sock \
  --upload-certs \
  --control-plane-endpoint=k8s-cluster.computingforgeeks.com

# Docker
sudo kubeadm init \
  --pod-network-cidr=192.168.0.0/16 \
  --cri-socket /var/run/docker.sock \
  --upload-certs \
  --control-plane-endpoint=k8s-cluster.computingforgeeks.com

다음은 초기화 명령의 출력입니다.

....
[init] Using Kubernetes version: v1.22.2
[preflight] Running pre-flight checks
	[WARNING Firewalld]: firewalld is active, please ensure ports [6443 10250] are open or your cluster may not function correctly
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Using existing ca certificate authority
[certs] Using existing apiserver certificate and key on disk
[certs] Using existing apiserver-kubelet-client certificate and key on disk
[certs] Using existing front-proxy-ca certificate authority
[certs] Using existing front-proxy-client certificate and key on disk
[certs] Using existing etcd/ca certificate authority
[certs] Using existing etcd/server certificate and key on disk
[certs] Using existing etcd/peer certificate and key on disk
[certs] Using existing etcd/healthcheck-client certificate and key on disk
[certs] Using existing apiserver-etcd-client certificate and key on disk
[certs] Using the existing "sa" key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/admin.conf"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/kubelet.conf"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/controller-manager.conf"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/scheduler.conf"
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
W0611 22:34:23.276374    4726 manifests.go:225] the default kube-apiserver authorization-mode is "Node,RBAC"; using "Node,RBAC"
[control-plane] Creating static Pod manifest for "kube-scheduler"
W0611 22:34:23.278380    4726 manifests.go:225] the default kube-apiserver authorization-mode is "Node,RBAC"; using "Node,RBAC"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 8.008181 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.21" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Skipping phase. Please see --upload-certs
[mark-control-plane] Marking the node k8s-master01.computingforgeeks.com as control-plane by adding the label "node-role.kubernetes.io/master=''"
[mark-control-plane] Marking the node k8s-master01.computingforgeeks.com as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[bootstrap-token] Using token: zoy8cq.6v349sx9ass8dzyj
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:

  kubeadm join k8s-cluster.computingforgeeks.com:6443 --token sr4l2l.2kvot0pfalh5o4ik \
    --discovery-token-ca-cert-hash sha256:c692fb047e15883b575bd6710779dc2c5af8073f7cab460abd181fd3ddb29a18 \
    --control-plane 

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join k8s-cluster.computingforgeeks.com:6443 --token sr4l2l.2kvot0pfalh5o4ik \
    --discovery-token-ca-cert-hash sha256:c692fb047e15883b575bd6710779dc2c5af8073f7cab460abd181fd3ddb29a18

출력의 명령을 사용하여 kubectl을 구성합니다.

mkdir -p $HOME/.kube
sudo cp -f /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

echo 'export KUBECONFIG=$HOME/.kube/config' >> $HOME/.bashrc

클러스터 상태 확인:

$ kubectl cluster-info
Kubernetes master is running at https://k8s-cluster.computingforgeeks.com:6443
KubeDNS is running at https://k8s-cluster.computingforgeeks.com:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

설치 출력의 명령을 사용하여 마스터 노드를 추가할 수 있습니다.

kubeadm join k8s-cluster.computingforgeeks.com:6443 --token sr4l2l.2kvot0pfalh5o4ik \
    --discovery-token-ca-cert-hash sha256:c692fb047e15883b575bd6710779dc2c5af8073f7cab460abd181fd3ddb29a18 \
    --control-plane 

6단계: 마스터에 네트워크 플러그인 설치

이 가이드에서는 Calico 를 사용 합니다. 지원되는 다른 네트워크 플러그인 을 선택할 수 있습니다 .

kubectl create -f https://docs.projectcalico.org/manifests/tigera-operator.yaml 
kubectl create -f https://docs.projectcalico.org/manifests/custom-resources.yaml

다음 출력이 표시되어야 합니다.

customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgppeers.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/blockaffinities.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/clusterinformations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/felixconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/hostendpoints.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamblocks.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamconfigs.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamhandles.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ippools.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/kubecontrollersconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/apiservers.operator.tigera.io created
customresourcedefinition.apiextensions.k8s.io/imagesets.operator.tigera.io created
customresourcedefinition.apiextensions.k8s.io/installations.operator.tigera.io created
customresourcedefinition.apiextensions.k8s.io/tigerastatuses.operator.tigera.io created
namespace/tigera-operator created
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
podsecuritypolicy.policy/tigera-operator created
serviceaccount/tigera-operator created
clusterrole.rbac.authorization.k8s.io/tigera-operator created
clusterrolebinding.rbac.authorization.k8s.io/tigera-operator created
deployment.apps/tigera-operator created
.....
installation.operator.tigera.io/default created
apiserver.operator.tigera.io/default created

모든 포드가 실행 중인지 확인합니다.

$ watch kubectl get pods --all-namespaces
NAMESPACE     NAME                                                         READY   STATUS    RESTARTS   AGE
kube-system   calico-kube-controllers-76d4774d89-nfqrr                     1/1     Running   0          2m52s
kube-system   calico-node-kpprr                                            1/1     Running   0          2m52s
kube-system   coredns-66bff467f8-9bxgm                                     1/1     Running   0          7m43s
kube-system   coredns-66bff467f8-jgwln                                     1/1     Running   0          7m43s
kube-system   etcd-k8s-master01.computingforgeeks.com                      1/1     Running   0          7m58s
kube-system   kube-apiserver-k8s-master01.computingforgeeks.com            1/1     Running   0          7m58s
kube-system   kube-controller-manager-k8s-master01.computingforgeeks.com   1/1     Running   0          7m58s
kube-system   kube-proxy-bt7ff                                             1/1     Running   0          7m43s
kube-system   kube-scheduler-k8s-master01.computingforgeeks.com            1/1     Running   0          7m58s

마스터 노드가 준비되었는지 확인합니다.

# CRI-O
$ kubectl get nodes -o wide
NAME     STATUS   ROLES                  AGE   VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
ubuntu   Ready    control-plane,master   38s   v1.22.2   143.198.114.46   <none>        Ubuntu 20.04.3 LTS   5.4.0-88-generic   cri-o://1.22.0

# Containerd
$ kubectl get nodes -o wide
NAME     STATUS   ROLES                  AGE   VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
ubuntu   Ready    control-plane,master   15m   v1.22.2   143.198.114.46   <none>        Ubuntu 20.04.3 LTS   5.4.0-88-generic   containerd://1.4.11

# Docker
$ kubectl get nodes -o wide
NAME           STATUS   ROLES    AGE   VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE           KERNEL-VERSION     CONTAINER-RUNTIME
k8s-master01   Ready    master   64m   v1.22.2   135.181.28.113   <none>        Ubuntu 20.04 LTS   5.4.0-37-generic   docker://20.10.8

7단계: 작업자 노드 추가

제어 플레인이 준비되면 예약된 워크로드를 실행하기 위해 클러스터에 작업자 노드를 추가할 수 있습니다.

엔드포인트 주소가 DNS에 없으면 /etc/hosts 에 레코드를 추가 합니다 .

$ sudo vim /etc/hosts
172.29.20.5 k8s-cluster.computingforgeeks.com

주어진 조인 명령은 클러스터에 작업자 노드를 추가하는 데 사용됩니다.

kubeadm join k8s-cluster.computingforgeeks.com:6443 \
  --token sr4l2l.2kvot0pfalh5o4ik \
  --discovery-token-ca-cert-hash sha256:c692fb047e15883b575bd6710779dc2c5af8073f7cab460abd181fd3ddb29a18

산출:

[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
[kubelet-start] Downloading configuration for the kubelet from the "kubelet-config-1.21" ConfigMap in the kube-system namespace
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

제어 플레인에서 아래 명령을 실행하여 노드가 클러스터에 합류했는지 확인합니다.

$ kubectl get nodes
NAME                                 STATUS   ROLES    AGE   VERSION
k8s-master01.computingforgeeks.com   Ready    master   10m   v1.22.2
k8s-worker01.computingforgeeks.com   Ready    <none>   50s   v1.22.2
k8s-worker02.computingforgeeks.com   Ready    <none>   12s   v1.22.2

$ kubectl get nodes -o wide

조인 토큰이 만료된 경우 작업자 노드에 조인하는 방법에 대한 가이드를 참조하십시오.

8단계: 클러스터에 애플리케이션 배포

단일 노드 클러스터만 있는 경우 마스터 노드에서 컨테이너 포드를 실행하는 방법에 대한 가이드를 확인하세요.

애플리케이션을 배포하여 클러스터가 작동하는지 확인해야 합니다.

kubectl apply -f https://k8s.io/examples/pods/commands.yaml

포드가 시작되었는지 확인

$ kubectl get pods
NAME           READY   STATUS      RESTARTS   AGE
command-demo   0/1     Completed   0          16s

9단계: Kubernetes 대시보드 설치(선택 사항)

Kubernetes 대시보드는 컨테이너화된 애플리케이션을 Kubernetes 클러스터에 배포하고, 컨테이너화된 애플리케이션의 문제를 해결하고, 클러스터 리소스를 관리하는 데 사용할 수 있습니다.

설치 가이드를 참조하십시오: NodePort로 Kubernetes 대시보드를 설치하는 방법

10단계: Metrics Server 설치(Pod 및 노드 리소스 사용량 확인용)

Metrics Server  는 리소스 사용량 데이터의 클러스터 전체 집계 도구입니다.  각 노드에서 Kubelet 에 의해 노출된  요약 API 에서 메트릭을 수집  합니다. 아래 가이드를 사용하여 배포하세요.

11단계: Prometheus/Grafana 모니터링 배포

Prometheus는 Kubernetes 클러스터의 고급 메트릭 기능에 액세스할 수 있는 완전한 솔루션입니다. Grafana는 Prometheus 데이터베이스에 수집 및 저장되는 메트릭의 분석 및 대화형 시각화에 사용됩니다. Kubernetes 클러스터에서 전체 모니터링 스택을 설정하는 방법에 대한 완전한 가이드가 있습니다.

12단계: 영구 저장소 구성 아이디어(선택 사항)

Kubernetes용 영구 스토리지 솔루션도 찾고 있다면 다음을 확인하십시오.

13. Nginx 인그레스 컨트롤러 설치

Nginx가 Kubernetes 워크로드용으로 선호하는 Ingress 컨트롤러인 경우 설치 프로세스에 대한 가이드를 사용할 수 있습니다.

더 많은 가이드:

유사한 Kubernetes 배포 가이드:

VirtualBox에 VMware ESXi 설치 방법

중요:  IntelCPU를 소유하고 있는 경우VirtualBox에서실행되는 VM ESXi 호스트에서 새 VM 시스템을 시작할 수 없다는점에 유의하십시오. 

이것은 VirtualBox가 Intel CPU에 대한 중첩 가상화를 지원하지 않기 때문에 발생합니다. 

(VM 머신을 시작하려고 하면 “이 호스트는 Intel VT-x를 지원하지 않습니다.”라는 오류가 표시됩니다.) 따라서 Intel CPU를 소유하고 있다면VMware 플레이어에 ESXi설치하는것이 좋습니다.

VirtualBox에 ESXi vSphere Hypervisor를 설치하기 위한 하드웨어 요구 사항:

CPU: 호스트 시스템에는 최소 2개의 CPU 코어가 있어야 하고 CPU는 하드웨어 가상화 기능(Intel VT-x 또는 AMD RVI)을 지원해야 합니다. 시스템이 가상화를 지원하는지 확인하려면 CPUID CPU-Z 유틸리티를사용하십시오. *

* 참고:
1. 가상화 지원을 활성화하려면 BIOS 설정으로 이동 하여 Intel-VD(Intel VT-x) 또는 AMD VT 기술/기능을 활성화 합니다 .

RAM: ESXi에는 최소 2GB의 물리적 RAM이 필요합니다. VirtualBox에 ESXi를 설치하려면 최소 4GB(4096MB)의 RAM을 할당해야 합니다.

VirtualBox에 ESXi vSphere Hypervisor 6.7을 설치하기 위한 소프트웨어 요구 사항.

1. 이동 링크 및 작성 VM웨어 계정을 (당신이 이미 하나를 가지고 있지 않은 경우).
2. VMware vSphere Hypervisor(ESXi ISO) 이미지(VMware 도구 포함) 이미지를 다운로드 합니다 .

3. 평가판 라이센스(60일)를 무료(만료되지 않음)로 변환하려면 평가판 기간이 끝날 때 필요하므로 VMware vSphere Hypervisor 6 라이센스 키를 기록해 둡니다 . (기사의 끝을 참조하십시오).

4. VirtualBox에 ESXi VSphere Hypervisor를 설치하려면 여기 에서 Windows 호스트용 Virtualbox의 최신 릴리스를 다운로드하여 설치해야 합니다 .

영상

VirtualBox 호스트에 VMware vSphere Hypervisor(ESXi 서버)를 설치하는 방법.

1단계. ESXI용 가상 머신 생성 및 구성 *

1.   Oracle VM Virtual Box Manager를 시작하고 새로 만들기 를 클릭 합니다 .

vmware esxi 설치 virtualbox

2. 가상 머신의 이름(예: “eSXI vSphere”)을 지정하고 다음을 선택합니다.

유형: 리눅스

버전: Linux 2.6/3.x/4.x(64비트)

메모리 크기: 4096MB

하드 디스크: 지금 가상 디스크 만들기

3. 완료되면 만들기를 클릭 합니다.

VirtualBox에 VMware ESXi 6.7을 설치하는 방법.

4. 다음 화면에서 원하는 디스크 크기(예: 30GB)를 지정하고 ‘하드 디스크 파일 유형’: VDI(VirtualBox 디스크 이미지) 및 ‘실제 하드 디스크에 저장’: 동적 할당 의 기본 옵션을 그대로 두고 클릭합니다. 생성 .

VirtualBox에 ESXi 설치

5. 이제 새 가상 머신을 강조 표시하고 설정 을 클릭 합니다 .

영상

6a. 왼쪽에서 시스템 을 선택 하고 마더보드 탭에서 다음을 선택합니다.

  • 칩셋: ICH9
  • 포인팅 장치: PS/2 마우스

영상

6b. 그런 다음 프로세서 탭을 선택 하고…

  • 2개의   CPU를 할당합니다 .
  • PAE/NX 활성화 확인

영상

7. 그런 다음 스토리지를 선택 하고 광학 드라이브 추가  기호 를 클릭합니다 .

영상

8. 디스크 선택 을 선택한 다음 다운로드한 ‘vSphere Hypervisor(ESXi ISO)’ 파일을 선택합니다.

영상

9a. 마지막으로 네트워크 를 선택하고 호스트 전용 어댑터 를 선택한 다음 확인 을 클릭 합니다.

영상

9b. 마법사 기반 생성 프로세스 후에 가상화 기술을 실행할 수 있도록 생성된 VM을 수정해야 합니다.

이는 CLI(PowerShell/CMD)를 통해서만 가능합니다.

cd 'C:\Program Files\Oracle\VirtualBox\'
.\VBoxManage.exe modifyvm "VMwareESXi" --nested-hw-virt on

 

10. 시작 버튼을 클릭하고 아래로 진행하여 가상 머신에 ESXi vSphere Hypervisor를 설치합니다.

영상

2단계. VIRTUALBOX VM 머신에 VMWARE ESXI VSPHERE HYPERVISOR 6.7을 설치합니다.

* 참고: 물리적 시스템에 ESXi vSphere Hypervisor를 설치하는 경우 ESXi vSphere Hypervisor 설치 CD 미디어에서 시스템을 부팅하십시오.

1. 첫 화면에서 Enter 를 눌러 설치를 시작합니다.

VirtualBox 호스트에 ESXi vSphere Hypervisor를 설치하는 방법

2. VMware ESXI 설치 프로그램이 시작되어야 합니다…

영상

3. 시작 화면에서 Enter 키 를 누릅니다 .

영상

4. F11 키 를 눌러 사용권 계약에 동의합니다.

영상

5. 스토리지 옵션에서 Enter 키를 누릅니다 .

영상

6. 원하는 키보드 레이아웃을 선택하거나 기본값(미국)을 그대로 두고 Enter 키를 누릅니다 .

영상

7. 이제 원하는 비밀번호*를 두 번 입력 하고 Enter 키를 누릅니다 .

* 참고: 비밀번호는 최소 7자 이상이어야 하며 일반 및 대문자, 기호 및 숫자의 조합이어야 합니다.

영상

8. 마지막으로 F11 키 를 눌러 설치를 중단합니다. *

* VirtualBox 설치 참고 사항: ESXi 설치 시점에서 Intel 프로세서를 소유하고 있는 경우 화면에 다음 경고 메시지가 표시됩니다. “하드웨어 가상화 경고: 하드웨어 가상화는 이 CPU의 기능이 아니거나 BIOS에서 활성화되지 않았습니다.” 이 메시지를 무시하고 Enter 키를 눌러 계속하십시오. (이 기사의 시작 부분에서 말했듯이 VirtualBox는 Intel 프로세서에 대한 중첩 가상화를 지원하지 않기 때문에 이 메시지가 나타납니다.)

영상

9. 설치가 완료되면 설치 미디어를 제거하고 Enter 키 를 눌러 시스템을 재부팅합니다. *

영상

* 참고: VirtualBox에서 ESXi 설치 미디어(.ISO 파일)를 제거하려면 

  A.재부팅 후 VM 창을 닫고컴퓨터의 전원을 끕니다 .

영상

B. 그런 다음 VM 머신 스토리지 설정을 열고 ISO 파일을 제거한 다음 확인을 클릭 합니다.
C. 마지막으로 시작 버튼을 클릭하여 VMware ESXi 머신을 시작합니다.

영상

10. VMware ESXi 서버가 시작되면 DHCP에서 할당된 IP 주소를 “가져옵니다”. 아래 지침에 따라 ESXi 서버에 이 IP 주소를 사용하거나 새 고정 IP 주소를 설정할 수 있습니다.

영상

11. ESXi에서 IP 주소를 변경하려면 위 화면에서 F2 를 누른다 .
12. 루트 암호를 입력하고 Enter 키를 누릅니다.
13. 화살표 키를 사용하여 관리 네트워크 구성으로 이동 하고 Enter 키 를 누릅니다 .

image_thumb[1]_thumb[2]

14. IPv4 구성으로 이동 하고 Enter 키를 누릅니다 .

 image_thumb[3]_thumb[3]

(15) 로 이동 한 세트 정적 IPv4 주소 및 네트워크 구성 및 히트 공간 을 선택할 수 있습니다.
16. 고정 IP 주소, 서브넷 마스크 및 게이트웨이를 입력 하고 Enter 키를 누릅니다 .

image_thumb[5]_thumb[3]

17. 그런 다음 선택 DNS 구성 및 히트 입력합니다 .

image_thumb[7]_thumb[3]

18. 이동 정보는 다음의 제품에 다음 DNS 서버 주소 및 호스트 이름을 사용 하고 공격 공간 을 선택할 수 있습니다.
19. 유형 DNS 서버 주소 및 선택적으로 다른 호스트 이름을 지정합니다. 완료되면 Enter 키를 누릅니다 .

image_thumb[9]_thumb[1]

20. ESC 를 눌러 종료한 다음 Y 를 눌러 변경 사항을 적용하고 관리 네트워크를 다시 시작합니다.

image_thumb[11]_thumb[1]

(21) 이어서 프레스 ESC 로그 아웃 한 후 프레스 F12 및 종료 ESXi 서버.
22. VirtualBox Manager에서 새 가상 머신을 강조 표시하고 설정 을 클릭 합니다 .

영상

(23) 에서 네트워크 : 옵션에 첨부를 선택 브리지 어댑터를 클릭하고 OK

영상

24. VM ESXi 머신을 시작합니다.
25. ESXi 서버가 시작되면 웹 브라우저(호스트 컴퓨터에서)를 열고 ESXi 서버의 IP 주소로 이동하여 VMWare ESXi vShere 서버 관리를 시작합니다.

영상

추가 도움말: VMware ESXi Hypervisor 평가 라이센스를 무료로 변환하려면.

* 참고: 60일 동안(평가 기간 종료 시까지) ESXi의 모든 기능을 탐색하고 테스트할 수 있습니다. 따라서 평가 기간이 종료되기 전에 평가 라이센스를 무료로 변환하지 마십시오.

1. 관리 -> 라이선스로 이동 한 다음 라이선스 할당 을 클릭 합니다 .

image_thumb17_thumb[2]

2. vSphere Hypervisor 6 라이센스 키를 복사하여 붙여넣은 다음 라이센스 확인 을 클릭합니다.

image_thumb15_thumb

3. 마지막으로 라이선스 할당을 클릭 합니다.

image_thumb16_thumb[1]

4. 이제 ‘만료 날짜’ 상태가 “Never”인 화면이 표시되어야 합니다.

image_thumb18_thumb[2]

그게 다야!

시놀로지 NAS의 OpenVPN 서버 설정하기

Synology NAS의 PPTP VPN 서버 설정 방법을 이전 포스트에서 설명했는데 한가지 설명을 빠트렸었다. 무엇인고 하니 설명한 환경에서 NAS를 SuperDMZ 또는 DMZ(NAT) 기능을 이용해 집의 인터넷 공유기에 할당되는 공인IP를 통채로 NAS에 할당한 경우에만 가능한 방법이다.

그렇지 않고 통신사에 연결되는 인터넷 공유기에는 공인IP가 할당되고 NAS에는 192.X.X.X로 표시되는 사설IP가 할당될 경우에는 PPTP, IPSEC 등의 VPN은 정상동작시키기 쉽지 않다. 인터넷 공유기에서 포트포워딩을 해줘야할 포트도 여러개인데다 설정을 하더라도 제대로 동작하지 않는 경우가 많기 때문이다.

그래서 오늘은 하나의 포트만 포트포워딩 하면 사용할 수 있는 OpenVPN 서버의 설정방법을 포스팅한다.

1. 인터넷 공유기에서 OpenVPN에서 사용할 통신포트를 포트포워딩 하기

통신사에서 제공하는 인터넷 공유기의 경우 다음과 같이 “포트포워딩(Port Forwarding)” 기능을 제공하는 경우가 대부분이다.

2. 시놀로지 NAS에서 새 인증서 만들기

많은 시놀로지 사용자들이 OpenVPN 서버를 설정하면서 부닥치는 가장 큰 난관은 바로 인증서 설정과 관련된 부분이다. 일단 “인증서”가 뭔지 제대로 이해를 하지 못하고 있기 때문이다.

(기존의 기본 인증서로 설정해도 관계 없다. 생성하는 과정만 건너 뛰면 모든 작업은 동일하다.)

먼저 “제어판”에서 “보안” 메뉴를 선택하면 표시되는 “인증서” 탭을 선택한다.

 

synology nas의 Certificate tab
Synology NAS의 제어판-보안 메뉴의 인증서 탭

 

“추가” 버튼을 누르고 “인증서 생성” 창이 실행되면 “새 인증서 추가” 를 선택한 다음 “다음” 버튼을 누른다.

“설명” 에는 적당한 설명을 넣는다. 그리고 “자체 서명 인증서 생성”을 선택한다.

 

synology nas에서 self-sign certificate 만들기
자체 서명 인증서 생성

 

다음과 같이 루트(CA) 인증서 생성에 필요한 기본값을 입력한다. 대충 입력해도 된다.

 

시놀로지 NAS의 셀프사인 인증서 생성
루트 인증서(CA) 생성

 

루트(CA) 인증서를 만들 정보를 입력하고 나면 실제 통신 시 사용할 인증서를 만들게 된다. 입력하는 정보가 아주 조금 다른데… 대충~ 에러가 나지 않도록만 입력하면 된다.

 

시놀로지 NAS에 인증서 만들기

 

“적용” 버튼을 누르면 다음과 같이 인증서가 반들어진다. 그리고 인증서의 유효기간은 생성한 날로부터 1년이다.

 

Synology NAS에 만들어진 Self-sign Certificate
Synology NAS에 만들어진 자체 서명 인증서

 

3. VPN 서버가 새로 만든 인증서를 사용하도록 설정하기

“제어판” – “보안” – “인증서” 탭에서 “구성” 버튼을 누르면 인증서를 사용하는 서비스가 사용할 인증서를 선택할 수 있는 화면이 표시된다.

아래 화면처럼 “VPN Server”가 앞에서 새로 생성한 인증서를 사용하도록 선택해준다.

 

VPN Server가 사용할 인증서 선택하기

 

4. OpenVPN 서버 설정하기

이제 OpenVPN 서버를 설정해줘야 한다.  VPN Server를 설정하기 위해서 VPN Server를 실행하고 “OpenVPN” 메뉴를 선택한다.

그리고 “OpenVPN 서버 활성화”를 체크해준 뒤 다음과 같이 설정한다.

 

 Synology NAS의 OpenVPN Server
Synology NAS의 OpenVPN 서버

 

여기서 중요한 것은 “포트” 항목에 앞의 인터넷 공유기에서 NAS의 IP인 192.168.219.102의 포트포워딩 포트인 10472를 “포트” 항목에 입력하는 것이다.

그리고 나서 “적용” 버튼을 눌러 OpenVPN 서버를 실행한다.

 

OpenVPN 서버 실행

 

OpenVPN 서버를 실행하면 화면 아래에 보이는 “내보내기 구성” 버튼이 활성화된다.

이 버튼을 눌러 OpenVPN 클라이언트에서 OpenVPN 서버에 접속할 때 사용할 “설정 파일”을 저장한다.

 

OpenVPN 설정 내보내기

 

이 OpenVPN 접속 설정 파일을 적당한 이름으로 저장한다. 위에서는 synology-openvpn(10472).zip 파일로 저장했다. 그리고 하나의 파일을 더 저장해야 한다. 바로 인증서 파일이다.

5. 인증서를 파일로 저장하기

다시 인증서 화면으로 간 뒤 아래 화면처럼 새로 생성한 인증서 파일을 “인증서 내보내기” 버튼을 눌러 PC에 저장한다.

 

Synology NAS의 인증서 내보내기

 

인증서 파일은 기본적으로 archive.zip 파일로 저장된다.

지금가지 두개의 파일을 PC에 저장했다. OpenVPN 클라이언트에서 사용할 접속 설정 파일과 인증서 파일 두 개다. 이제 이 두개 파일의 압축을 해제한 뒤 편집해야 한다.

6. OpenVPN 클라이언트 구성 파일 편집

Synology에서 제공하는 VPN 서버의 버그인지… 아니면 원래 그런 것인지 모르겠지만 앞에서 다운로드 받은 OpenVPN 클라이언트 접속 용 구성 파일은 인증서 정보가 제대로 설정되어 다운로드 되지 않는다. 그래서 수동으로 인증서 내용을 편집해 넣어줘야 한다.

먼저 다음과 같이 인증서가 저장된 archive.zip과 OpenVPN 접속 설정파일인 synology-open….zip 파일의 압축을 해제한다.

 

인증서 파일과 OpenVPN 접속 구성파일 압축해제

 

인증서 압축파일을 해제하면 4개의 파일이 표시되는데 cert.pem 파일과 prikey.pem 파일의 내용을 OpenVPN 접속 구성 파일에 추가해줘야 한다.

 

인증서 압축파일 해제하면 표시되는 4개의 파일

 

OpenVPN 접속 구성 파일이 포함된 zip 파일을 압축해제하면 VPNConfig.ovpn 이라는 OpenVPN 접속 용 구성파일이 보인다. 이 파일을 Notepad 등으로 열어준다.

 

OpenVPN 접속 용 구성파일 열기

 

먼저 상단에 위치한 YOUR_SERVER_IP를 인터넷 공유기에 할당된 외부 공인IP로 수정한다. 만약 시놀로지의 DDNS를 이용해 xxx.synology.me 와 같은 도메인주소를 사용한다면 그 도메인주소를 입력해주면 된다.

 

ovpn파일 편집하기

 

다음은 새로운 Notepad을 열어 인증서 파일들 중 cert.pem 파일을 다음과 같이 연다.

 

cert.pem
cert.pem 파일

 

위의 cert.pem 파일의 내용 전체를 다음과 같이 VPNConfig.ovpn 파일을 열고 가장 아래부분의 </ca> 뒷 부분에 <cert> 태그를 추가하고 그 뒤에 붙여넣는다.

 

.ovpn 파일의 가장 뒤에 cert.pem 파일의 내용을 붙여 넣는다.

 

그리고 가장 뒷 부분에 </cert>을 추가한다.

마찬가지로 인증서 파일들 중 prikey.pem 파일의 내용을 모두 복사해 VPNConfig.ovpn 파일의 맨 뒷 부분에 <key> 태그를 추가한 뒤 붙여넣는다.

 

.ovpn 파일의 끝에 prikey.pem 파일의 내용을 추가한다.

 

그리고 맨 끝에 </key>를 추가해준 뒤 저장한다.

여기까지 진행하면 OpenVPN 클라이언트 프로그램이 OpenVPN 서버에 접속할 때 사용할 구성파일이 완성된다.

7. OpenVPN Client 설치하고 접속 구성 파일 복사하기

OpenVPN 서버에 접속하여 암호화 된 안전한 Private(사설) 네트워크를 만들기 위해서는 OpenVPN GUI라는 클라이언트 프로그램을 설치하여야 한다. 다운로드는 여기에서 받으면 된다.

기본 옵션으로 설치한 뒤 앞에서 편집한 VPNConfig.ovpn 파일을 아래와 같이 기본 config 경로에 복사한다.

 

.ovpn 파일 복사하기

 

이 때 관리자권한이 필요한데 관리자 권한을 부여하여 복사해 넣으면 된다.

8. OpenVPN 서버에 OpenVPN GUI로 접속하기

설치하고 나면 VPNConfig 라는 접속 구성이 보인다. 아래와 같이 “연결”을 눌러 OpenVPN 서버에 접속하면 된다.

 

OpenVPN GUI를 통해 접속하기

 

ID와 비밀번호를 묻는 창이 실행되면 시놀로지의 접소계정을 입력하면 된다. 다만 해당 계정은 시놀로지 DSM에서 OpenVPN 접속이 허용된 계정이어야 한다.

 

OpenVPN 서버에 접속하기
시롤로지 OpenVPN 서버에 접속하기

 

접속이 되면 다음과 같이 접속상태를 확인할 수 있고 “연결해제” 버튼을 눌러 VPN 네트워크를 파괴하여 접속을 끊을 수도 있다.

 

Synology NAS 오픈VPN 접속 상태

DNS TXT Record 로 Let’s Encrypt SSL 인증서 발급 받기

TXT 레코드 요청

  1. certbot 을 실행할 때 –manual 옵션과 –preferred-challenges dns 을 주어서 실행합니다.
    certbot certonly -d new.lesstif.com --manual --preferred-challenges dns
  2. IP 로깅을 허용하겠냐고 묻는 화면에서 Y 를 입력합니다.
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    NOTE: The IP of this machine will be publicly logged as having requested this
    certificate. If you're running certbot in manual mode on a machine that is not
    your server, please ensure you're okay with that.
    
    Are you OK with your IP being logged?
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    (Y)es/(N)o: Y
  3. TXT 에 등록할 내용이 출력되면 복사해 둡니다.
    Please deploy a DNS TXT record under the name
    _acme-challenge.new.lesstif.com with the following value:
    
    slqQSBrs4rToROM7LyEeBVvI92YXi3JJ-RK6S5OBKNc
    
    Before continuing, verify the record is deployed.
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Press Enter to Continue
  4.  DNS 서버에 TXT 레코드를 등록합니다. DNS 서비스 제공자에 따라 화면이 다를 수 있습니다.
  5. 새로운 터미널을 열고 정상적으로 등록됐는지 확인합니다.
    $ nslookup -q=TXT _acme-challenge.new.lesstif.com
    
    
    Server:         168.126.63.1
    Address:        168.126.63.1#53
    
    Non-authoritative answer:
    _acme-challenge.new.lesstif.com text = "slqQSBrs4rToROM7LyEeBVvI92YXi3JJ-RK6S5OBKNc"
    
    Authoritative answers can be found from:
  6. 기존 let’s encrypt 발급 터미널로 간 후에 엔터를 입력합니다.
  7. 정상 발급되었는지 확인하고 웹 서버를 설정합니다.
    Waiting for verification...
    Cleaning up challenges
    
    IMPORTANT NOTES:
     - Congratulations! Your certificate and chain have been saved at:
       /etc/letsencrypt/live/new.lesstif.com/fullchain.pem
       Your key file has been saved at:
       /etc/letsencrypt/live/new.lesstif.com/privkey.pem

Boot2Docker Volume Disk Resize

Boot2Docker에서 “장치에 남은 공간 없음” 오류가 발생합니까?

많은 수의 이미지와 함께 Boot2Docker를 사용하거나 작업 중인 이미지가 매우 큰 경우 Boot2Docker VM의 볼륨 공간이 부족하면 문제가 발생할 수 있습니다. 솔루션은 먼저 볼륨을 복제한 다음 디스크 파티셔닝 도구를 사용하여 크기를 조정하여 볼륨 크기를 늘리는 것입니다. (GParted)[ http://gparted.sourceforge.net/download.php/index.php ]는 무료 ISO이고 VirtualBox와 잘 작동하기 때문에 사용하겠습니다.

1. Boot2Docker의 VM을 중지합니다.

$ boot2docker stop 

Boot2Docker는 VirtualBox의 기본 도구로 크기를 조정할 수 없는 VMDK 이미지와 함께 제공됩니다. 대신 VDI 볼륨을 만들고 VMDK 볼륨을 여기에 복제합니다.

2. VirtualBox 명령줄 도구를 사용하여 VMDK 이미지를 VDI 이미지로 복제합니다.

$ vboxmanage clonehd /full/path/to/boot2docker-hd.vmdk /full/path/to/<newVDIimage>.vdi —format VDI —variant Standard

3. 필요에 적합한 크기를 선택하여 새 복제 볼륨의 크기를 조정합니다. 많은 컨테이너를 회전하거나 컨테이너가 특히 큰 경우 더 큰 것이 좋습니다.

$ vboxmanage modifyhd /full/path/to/<newVDIimage>.vdi —resize <size in MB>

4. (GParted)[ http://gparted.sourceforge.net/download.php/ ] 와 같은 디스크 파티션 도구 ISO를 다운로드합니다 . Boot2Docker VM의 IDE 버스에 ISO를 추가합니다. ISO를 추가하기 전에 버스를 생성해야 할 수도 있습니다.

5. VirtualBox의 Boot2Docker 이미지에 새 VDI 이미지를 추가합니다.

6. Boot2Docker VM에 대한 설정에서 CD/DVD가 부팅 순서 목록 의 맨 위에 있는지 확인 합니다.

7. VirtualBox에서 Boot2Docker VM을 시작하면 디스크 파티션 ISO가 시작됩니다. 

GParted를 사용하여 GParted Live(기본 설정) 옵션을 선택합니다. 기본 키보드, 언어 및 XWindows 설정을 선택하면 GParted 도구가 시작되고 생성한 새 VDI 볼륨이 표시됩니다. VDI를 마우스 오른쪽 버튼으로 클릭하고 크기 조정/이동 을 선택합니다 . 볼륨을 나타내는 슬라이더를 최대 크기로 끌어 크기 조정/이동 을 클릭 한 다음 적용 을 클릭 합니다. GParted를 종료하고 VM을 종료합니다. VirtualBox의 Boot2Docker VM용 IDE 컨트롤러에서 GParted ISO를 제거합니다.

8. VirtualBox에서 또는 명령줄( boot2docker start)을 사용하여 Boot2Docker VM을 시작하여 볼륨 변경 사항이 적용되었는지 확인합니다.

시놀로지 4TB디스크를 8TB디스크로 교체하기

DS918+와 4TB 하드디스크 한 개를 사용하고 있는데요. 8TB 하드디스크 네 개로 교체하고 싶어요.

  • 4TB 하드디스크의 공간이 가득 찼습니다. 8TB 하드디스크 4개 장착 후 raid5를 만들어서 24TB의 공간을 사용하고 싶습니다.
  • 나스는 24시간 계속 사용합니다. 8TB 하드디스크로 교체하는 동안에도 나스 접속이 끊기지 않아야 합니다.

8TB 하드디스크 4개를 raid5로 만듭니다.

DS920+는 핫스왑 기능을 제공하므로 나스를 계속 사용하면서 하드디스크를 교체할 수 있습니다. 8TB 하드디스크 4개를 사용하여 raid5가 완성되는 데는 5일 정도 소요 되었지만 실제로 작업한 시간(하드디스크 교체하기, 마우스 클릭하기 등)은 10분 정도밖에 되지 않습니다.

  • 현재는 1번 베이에 4TB 하드디스크가 장착되어 있고 나머지 베이는 비어 있습니다. 스토리지 풀은 shr방식입니다. 다음 과정을 거쳐서 8TB 하드디스크 4개로 raid5를 만듭니다.
  • 과정 1
    4TB 디스크 1개와 8TB 디스크 1개를 레이드1으로 만듭니다. 레이드1이 된 이후에는 볼륨의 크기가 4TB가 됩니다.
  • 과정 2
    4TB 디스크를 8TB 디스크로 교체 후 수리를 진행합니다. 수리가 끝나면 8TB 디스크 2개로 raid1이 되고 볼륨의 크기가 8TB가 됩니다.
  • 과정 3
    8TB 디스크 2개로 raid1 상태에서 8TB 디스크 2개를 추가하여 raid5로 변경합니다. raid5가 된 이후에는 볼륨의 크기가 24TB가 됩니다.

과정 1. 4TB와 8TB로 raid1 만들기.

  • 2번 베이에 8TB 디스크를 장착 후 “스토리지 풀 > 작업 > 드라이브 추가”를 클릭합니다. 드라이브 2를 선택합니다.
  • 스토리지 풀 화면에서 1번 베이의 4TB 디스크와 2번 베이의 8TB 디스크가 사용된 것을 볼 수 있습니다.
  • 스토리지 풀 확장하는 작업이 완료되면 스토리지 풀의 총 용량은 4TB, 볼륨의 총 용량도 4TB가 됩니다.
  • 스토리지 풀 확장이 완료되는데 13시간 정도 소요되었습니다.

과정 2. 4TB 교체 후, 8TB와 8TB로 raid1 만들기.

  • HDD/SSD 화면에서 4TB 하드디스크에 해당하는 드라이브(이번 사례에서는 드라이브 1)를 선택 후 “작업 > 비활성화”를 클릭합니다.
  • 드라이브 1 옆에 “비활성화됨”이 표시되면 4TB 하드디스크를 제거하고 새로운 8TB 디스크를 장착합니다. (기존 4TB 드라이브와 미러링 된 드라이브 외 새로운 드라이브 추가)
  • “스토리지 풀 > 작업 > 수리”를 클릭합니다. 드라이브 1을 선택합니다.
  • 2번 베이 하드디스크(Drive 2)의 내용을 1번 베이 하드디스크(Drive 1)로 복제하므로 Drive 2는 읽기작업이 발생하고 Drive 1은 쓰기작업이 발생하는 것을 리소스 모니터에서 확인할 수 있습니다.
  • 수리가 완료되는데 15시간 정도 소요되었습니다
  • 수리가 완료되면 스토리지 풀의 총 용량은 8TB로 늘어나지만, 사용한 용량은 여전히 4TB 그대로입니다. shr방식을 사용하는 경우에는 볼륨의 크기가 저절로 늘어나지 않기 때문입니다.        (DSM 6.2.3 부터는 자동으로 최대 크기로 늘어남)
  • 볼륨의 크기를 8TB로 늘립니다. “볼륨 > 작업 > 구성”을 클릭하고 “최대” 버튼을 클릭합니다. 그러면 “할당된 크기 수정(GB)” 칸의 숫자가 스토리지 풀이 사용할 수 있는 최대 용량으로 입력됩니다. “확인” 버튼을 클릭하면 10초 정도 후에 볼륨의 총 용량이 8TB로 변경됩니다.

과정 3. 8TB 디스크 2개 추가하기.

  • 3번 베이, 4번 베이에 8TB 디스크를 각각 장착한 다음 “스토리지 풀 > 작업 > 드라이브 추가”를 클릭합니다. 드라이브 3, 드라이브 4를 선택하고 다음을 클릭합니다. “설정 확인” 화면에서 총 용량이 21.82TB로 나오는지 확인합니다.
  • 스토리지 풀 확장이 완료되는데 90시간 정도 소요되었습니다.
  • 스토리지 풀 확장하는 작업이 완료되면 스토리지 풀의 총 용량은 24TB로 늘어나지만, 사용한 용량은 여전히 8TB 그대로입니다.  사용하지 않은 용량 16TB를 볼륨에 추가해야 합니다.
  • “볼륨 > 작업 > 구성”을 클릭하고 “최대” 버튼을 클릭합니다.
  • 최종적으로 볼륨의 크기가 24TB가 되었습니다.

8TB 디스크의 파티션 모습.

지금까지의 과정은 이벤트 로그와 알림에 기록되어 있습니다. 기록을 보면 “과정 3. 8TB 디스크 2개 추가하기”에서 동기화 작업이 네 번 나오는데요. 4TB 하드디스크로 스토리지 풀을 최초로 만들때 shr방식으로 설정했기 때문입니다. shr방식에서 더 큰 용량의 하드디스크로 교체하면 하드디스크의 파티션이 최초의 스토리지 풀 크기(4TB)와 나머지 크기(8TB에서 최초의 스토리지 풀 크기를 제외한 나머지)로  나누어집니다.  그래서 8TB디스크 4개 모두 두 개의 파티션으로 나누어져 있습니다. 또한 raid1에서 raid5로 변경하는 경우에 디스크 두 개를 한 번에 추가해도 변경작업(동기화 작업)은 한 개씩 이루어집니다. 그래서 다음과 같이 총 네 번의 동기화 작업이 진행됩니다.

  • 첫 번째 : 디스크 3개의 4TB  파티션을 동기화.
  • 두 번째 : 디스크 3개의 4TB  파티션을 제외한 부분 동기화.
  • 세 번째 : 디스크 4개의 4TB  파티션을 동기화.
  • 네 번째 : 디스크 4개의 4TB  파티션을 제외한 부분 동기화.

네 번의 동기화가 모두 끝나면 두 개의 raid5 장치가 생성됩니다. 하나는 4TB 크기 네 개로 raid5이므로 사용가능한 용량은 12TB가 되고, 다른 하나는 8TB에서 4TB를 제외한 크기(결국 4TB 크기) 네 개로 raid5이므로 마찬가지로 12TB가 됩니다. 그리고 두 개의 12TB 공간을 LVM을 사용하여 묶어서 총 24TB 크기의 스토리지 풀이 됩니다.

  • 지금까지의 과정을 “모든 알림”에서 볼 수 있습니다.
  • fdisk 명령어를 사용해서 파티션이 어떻게 나눠져 있는지 확인할 수 있습니다.
  • sda5, sdb5, sdc5, sdd5가 md2에 사용되고 sda6, sdb6, sdc6, sdd6이 md3에 사용되었습니다.

Elastic Search Index and Shade Split point

여러개의 샤드 vs 인덱스 쪼개기

다나와 서비스의 상품갯수는 급격하게 늘어나고 있습니다. 몇달전 4~5억건이었던 상품이 7억건에 육박하고 있는데요. 현재 사용하고 있는 패스트캣 검색엔진에서는 대량의 문서들을 여러개의 인덱스로 나누어 색인하고 있습니다.

검색할때는 나눈 인덱스들을 하나로 합쳐서 검색하고 있는데요. 엘라스틱서치에도 여러 인덱스를 하나로 합쳐서 한번에 검색하는 기능이 있어서 지금처럼 인덱스를 쪼개서 사용하는 것도 가능한 시나리오입니다. 참고로 얘기하면, 이렇게 데이터를 범위나 카테고리로 나누어 관리하는 기법을 파티셔닝이라고 합니다.

먼저 인덱스를 하나로 가져가든 여러개로 나누든, 샤드 하나의 크기는 비슷하게 설정해야 할텐데요, 적절한 샤드의 크기를 먼저 정해야 할 것 같습니다. 몇차례 구글링을 한결과 엘라스틱서치의 공식블로그에서 도움이 될만한 글를 찾을수 있었습니다.

TIP: 작은 샤드는 작은 세그먼트를 만들며 부하를 증가시킵니다. 평균 샤드 크기를 최소한 수 GB와 수십 GB 사이를 유지하세요. 시간 기반 데이터를 사용한 과거 사례를 보면, 20GB ~ 40GB 정도의 사이즈가 적당합니다.

샤드크기는 수GB에서 수십GB 사이가 적당하며, 경험상 시계열 데이터의 경우 20GB~40GB가 적당하다고 합니다. 그리고 아래에서 또다른 팁을 발견할수 있었습니다.

TIP: 하나의 노드에 저장할 수 있는 샤드의 개수는 가용한 힙의 크기와 비례하지만, Elasticsearch에서 그 크기를 제한하고 있지는 않습니다. 경험상 하나의 노드에 설정한 힙 1GB 당 20개 정도가 적당합니다. 따라서 30GB 힙을 가진 노드는 최대 600개 정도의 샤드를 가지는 것이 가능하지만, 이 보다는 적게 유지하는 것이 더 좋습니다.

힙메모리 30GB로 엘라스틱서치를 구동시 샤드는 최대 600개 정도라고 합니다. 이미 32GB 를 힙에 할당할 생각을 하고 있으므로, 활성화된 인덱스가 50개라고 한다면, 인덱스당 600샤드 / 50 인덱스 = 12 로 인덱스당 최대 12개의 샤드를 설정할수 있을 겁니다. 일단 샤드갯수의 최대치는 넉넉한것 같으므로, 많아서 문제가 될것같지는 않습니다.

하나의 샤드를 20GB~40GB로 설정한다면, 7억건의 상품은 몇개의 샤드로 나눠지게 될까요? 다나와 상품기준으로는 15개의 샤드로 나눠지게 됩니다. 물론 엘라스틱 서치 블로그에서는 시계열 데이터에 대한 팁이라서 상품과는 문서의 특성이 다릅니다. 대부분은 웹서버나 DB 로그데이터 일텐데요, 로그스태시의 파싱모듈을 확인해보면 한 로그내의 필드수가 10개 내외로 매우 적습니다. 반면에 상품의 필드는 수십개는 기본입니다.

이러한 문서특성의 차이로 검색과 색인시 한개 문서에 들어가는 리소스와 시간이 더 투여됩니다. 그러므로, 상품문서는 하나의 샤드를 20GB 보다는 조금 더 작게 나누면 여러 서버에 더 잘게 분산이 되어 전체적인 응답시간은 더 빨라질겁니다. 우리는 샤드당 약 5GB로 설정하고 테스트 했는데, 빠른 응답속도를 얻을 수 있었습니다.

그럼, 인덱스를 나누는것과 샤드를 나누는것 어떤것이 적합할까요? 어치피 샤드는 여러 서버에 분산되어 병렬 및 병행 (참고: https://soy.me/2015/01/03/concurrent/)으로 검색이 되므로, 인덱스가 같던 다르던 상관은 없습니다. 검색의 기본 단위는 샤드이기 때문이죠. 따라서 인덱스를 나누는 것은 운영의 편의성을 고려할때 선택하는 방법입니다. 장애없는 운영의 측면에서 생각해보면, 큰 덩어리 하나를 다루는 것은 부담스러워도, 작은 덩어리 여러개를 다루는 것이 번거롭긴해도 그만큼 장애 가능성을 낮추는 방법이 됩니다.

전체색인을 빠르게 하려면

전체색인을 할 경우 인덱스 하나가 7억건이라면 색인이 모두 끝날때까지 약 3-4시간이 소요될것이고, 검색에 노출되기 까지 이시간을 고스란히 기다려야 합니다. 더 문제가 되는것은 전체색인 도중에도 상품의 가격은 계속해서 변하게 되는데 이 변경분을 전체색인후에 일괄적용을 해야하며, 대기시간이 길수록 일괄적용시간도 늘어나게 됩니다. 그러므로, 최대한 전체색인을 빠르게 해야하는데, 이를 위해서는 문서를 입력하는 REST 클라이언트를 멀티스레드로 여러개 생성하여 동시입력량을 늘려야 합니다. 이때 Bulk Insert 를 쓰는것은 기본이구요.

하지만, 엘라스틱서치의 Write IO도 고려해야 합니다. 동시입력량을 늘리면, 서버의 CPU와 Disk IO중 둘중 하나는 최대치에 이를것이고, 더이상 색인속도는 늘어나지 않게 됩니다. 우리가 경험한 최대 색인속도는 500KB 상품문서 기준으로 16000건/초 였습니다. 이때 CPU는 32코어로 90%를 사용했으니 활용도는 매우 높다고 할수 있습니다. (참고: https://danawalab.github.io/elastic/2020/07/06/Elasticsearch-Index.html)

결국은 더 빠른 색인을 위해서는 하나의 인덱스를 여러개로 나눠야 합니다. 통으로 4시간이 걸리는 문서를 10개의 인덱스로 나누면 색인시간이 서버를 공유하므로 정확히 1/10이 될수는 없지만, 그대로 각각 40분정도로 병행완료가 됩니다.

상품DB의 특성상 우리는 카테고리군별로 인덱스를 나누고 있습니다. 카테고리별로 인덱스를 나눌때의 장점은 특정카테고리만 검색할때 해당 인덱스만 검색하면 되므로, 검색부하가 현저히 감소하게 됩니다. 우리는 인덱스도 나누고 샤드도 2-3개로 나누어 전체적인 검색응답시간을 최대한 단축하는 방향으로 설계했습니다.

레플리카 갯수는 몇개로?

고가용성을 추구할때 빼놓을 수 없는 것이 레플리카인데요, 레플리카는 레플리카 샤드를 줄여서 얘기하는 것으로, 프라이머리 샤드에 종속됩니다. 우리말로는 복제본 이라고도 하죠. 복제본은 분산 데이터 시스템에서는 동일한 역할을 담당하는데요, 하드웨어 장애를 극복하고 검색과 같은 읽기처리량을 향상시키는 것입니다.

그런데 읽기성능이 좋아진다는 것은 쓰기성능이 낮아진다는 얘기도 됩니다. 왜냐하면, 복제본을 여러개 만들기 위해서는 그만큼 문서색인시에 쓰기작업도 복제본 갯수만큼 발생하기 때문이죠. 하나의 서버만 본다면 1이지만, 전체클러스터 입장에서는 복제본이 열개면 10의 쓰기가 일어나는 것입니다. 문서가 색인될때 구지 모든 서버의 IO발생하게 만들 필요는 없을겁니다.

또한 복제본의 갯수는 동시에 장애가 발생할 노드를 몇개 까지 허용하는지에 달려있습니다. 복제본이 1개라면 하나의 노드가 죽어도 검색서비스는 유지됩니다. 하지만, 이제 복제본은 0개가 되므로, SA가 빨리 노드를 복구하지 않으면, 다른 또하나의 노드가 죽을때 검색서비스에는 장애가 생깁니다.

만약 회사내에 장애 복구시스템이 잘 갖춰져 있다고 하면, 복제본은 1개로도 가능합니다. 복제본이 2라면 서버가 연속 2개 죽어도 상관이 없으므로, 마음을 느긋하게 가질수 있습니다. 하지만 전체 클러스터에서 서버가 2개 빠지고도 부하를 충분히 견딜수 있게 서버를 배치해 놓아야 합니다. 우리는 카테고리별 인덱스의 읽기성능을 고려해서 부하가 높은 인덱스는 복제본 2를 나머지는 1을 설정할 계획입니다.

결론

nginx로그와 같은 로그성 문서는 색인을 하고 나면 수정이 필요없는 정적인 컨텐츠인 반면에, 상품문서는 색인이 끝나도 계속 갱신이 되어야 하는 살아있는 컨텐츠입니다. 그렇기 때문에, 동적색인이 원활하고 장애도 대비할수 있으며, 검색성능도 높은 설계가 필요합니다. 그리고 엘라스틱서치를 사용하여 검색시스템을 설계할때 운영자가 할수 있는 최선의 방법은 문서와 샤드를 잘 관리하는 것입니다. 따라서 견고한 검색시스템을 위해 인덱스와 샤드를 어떻게 설정해야 하는지에 대해 살펴봤습니다.

참고

https://www.elastic.co/kr/blog/how-many-shards-should-i-have-in-my-elasticsearch-cluster

https://medium.com/kariyertech/elasticsearch-cluster-sizing-and-performance-tuning-42c7dd54de3

https://www.elastic.co/guide/en/elasticsearch/reference/current/scalability.html

Kubernetes Virtual Storage (Ceph) Installation

설치에 필요한 도구로 Rook을 사용할 예정입니다. Rook은 오픈소스 클라우드 네이티브 스토리지 오케스트레이터로, 클라우드 네이티브 환경과 기본적으로 통합할 수 있는 다양한 스토리지 솔루션 세트에 대한 플랫폼, 프레임 워크 및 지원합니다. Rook을 통해 Ceph 가상스토리지를 구성하고 공유 파일 시스템을 적용하도록 하겠습니다.

Rook 구성도

Rook은 쿠버네티스 POD에서 실행되며, Ceph, EdgeFS등 가상솔루션을 POD로 배포하여 관리하는 도구입니다. agent를 통해 Ceph, EdgeFS등 가상솔루션을 관리하고, OSD를 통해 데이터를 영구저장합니다.

/images/2020-01-28-kubernetes-rook-ceph/Untitled.png

Ceph vs EdgeFS

Rook에서 제공하는 가상스토리지는 EgdeFS와 Ceph 외에도 다양하게 지원하지만 안정적인 버전은 아래 두가지만 지원합니다.

  • EdgeFS: 데이터베이스처럼 대용량 스토리지가 필요할때 사용됩니다.
  • Ceph: 공유 확장에 특화되어 있는 스토리지가 필요할때 사용됩니다.

공유나 확장에 특화되어 있는 Ceph를 설치하도록 하겠습니다.

Ceph 스토리지 유형

Ceph는 Block, Object, File 기반으로 데이터를 사용할 수 있습니다. 각 유형에 따라서 사용하는 기능에 차이가 있습니다.

  • Block Stroage: 단일 POD에 storage 제공합니다.
  • Object Storage: 애플리케이션이 쿠버네티스 클러스터 내부 또는 외부에서 액세스 할수있느 데이터를 IO 할수있고, S3 API를 스토리지 클러스터에 노출을 제공합니다.
  • Shared Stroage: 여러 POD에서 공유할 수있는 파일 시스템기반 스토리지입니다.

Shared Storage 구성도

이번에 설치해볼 Shared Storage 구성입니다. Ceph 클러스터에 데이터를 저장하고 Ceph를 통해 POD들과 데이터가 공유가 됩니다.

/images/2020-01-28-kubernetes-rook-ceph/Untitled%201.png

Ceph 설치

테스트 환경

쿠버네티스가 설치된 환경이 필요합니다. 설치방법은 쿠버네티스 고가용성 클러스터 구성 블로그를 통해 설치진행 바랍니다.

OS: ubuntu:18.04
Kubernetes: 1.16.4

Ceph 소스 다운로드 및 POD 배포

Rook은 별도의 설치가 없고 github으로 Ceph, EdgeFS 가상스토리지 솔루션을 쿠버네티스에 배포할 수 있도록 제공하고 있습니다.

$ git clone --single-branch --branch release-1.2 https://github.com/rook/rook.git

아래 경로에 보면 common.yaml, operator.yaml이 있습니다. kubectl 명령어를 통해 배포 합니다.

$ kubectl apply -f rook/cluster/examples/kubernetes/ceph/common.yaml
$ kubectl apply -f rook/cluster/examples/kubernetes/ceph/operator.ymal
$ kubectl apply -f rook/cluster/examples/kubernetes/ceph/cluster.yaml

cluster.yaml을 배포하게 되면 POD 중 OSD가 Running 상태인지 확인이 필요합니다. 변경되는 시간이 약 1 ~ 3 분 정도 소요됩니다.
테스트 환경에 따라 OSD 갯수가 차이가 있을 수 있습니다.

$ kubectl get pod -n rook-ceph

/images/2020-01-28-kubernetes-rook-ceph/Untitled%202.png

OSD Running 상태까지가 ceph 클러스터 구성이 완료되었고, Shared Storage 유형을 적용해보겠습니다.

Shared Storage 유형 적용

아래 명령어를 실행하게 되면 MDS POD가 배포가 됩니다. 약 1 ~ 3분 정도 소요됩니다. Shared Storage 옵션을 변경할 수 있는데 자세한 내용은 ceph-filesystem-crd 통해 확인바랍니다.

$ kubectl apply -f rook/cluster/examples/kubernetes/ceph/filesystem.yaml

StorageClass Driver 적용

StorageClass는 POD에서 Ceph 데이터 풀에 접근하기 위해 사용되는 드라이버입니다. kubectl 명령어를 통해 적용합니다.

$ kubectl apply -f rook/cluster/examples/kubernetes/ceph/csi/cephfs/storageclass.yaml

Shared Storage 확인

정상적으로 적용이 되었는지 확인하는 방법압니다. 아래 결과 처럼 myfs가 생성되어 있습니다.

$ kubectl get CephFileSystem -A

결과)

/images/2020-01-28-kubernetes-rook-ceph/Untitled%203.png

Shared Storage 테스트

kube-registry를 배포하면 PVC, docker-registry POD가 배포됩니다. 컨테이너 내부에 접근하여 /var/lib/registry 디렉터리에 dummy 파일을 생성 하여 다른 POD에서 공유되어 보여지는지 확인합니다.

$ kubectl apply -f rook/cluster/examples/kubernetes/ceph/csi/cephfs/kube-registry.yaml

정리

Rook이라는 도구를 이용해서 Ceph를 설치해보았습니다. Ceph를 관리하려면 러닝커브가 있지만 Rook이라는 도구를 이용해서 Ceph 관리와 쿠버네티스와 연동을 쉽게 할 수 있습니다.

Configuring Kubernetes High Availability Clusters

소개

쿠버네티스는 마스터 노드에 내부적으로 API-SERVER를 가지고 있어 마스터 노드를 통해 워커 노드로 통신이 전달됩니다. 대량에 통신량이 발생하게 되면 마스터 노드는 부하를 많이 받아 장애 발생 가능성이 커지게 됩니다. 마스터 노드를 고가용성 클러스터로 연결하게 되면 통신량을 분산시킬 수 있고, 일부가 마스터 노드에서 장애가 발생시 워커 노드의 운영 시스템에는 영향을 줄일 수 있습니다.

구성 환경

아래 사양으로 총 3대 서버를 준비합니다.

OS: CentOS 7
CPU: 2
RAM: 4
Storage: 100G

구성목표

  1. 마스터 노드 3개를 클러스터구성
  2. 가상 네트워크(weave) 적용
  3. ceph storage 적용

도커&쿠버네티스 설치

CentOS 패키지 업데이트와 방화벽을 정지 및 스왑을 종료합니다.

$ sudo yum update -y
$ sudo systemctl disable firewalld && sudo systemctl stop firewalld
$ sudo selinux disabled
$ sudo setenforce 0
$ sudo iptables piv4 forward
$ sudosudo bash -c 'echo 1 > /proc/sys/net/ipv4/ip_forward'
$ sudo swapoff -a
$ sudo sed -i '/swap/d' /etc/fstab

운영 환경에서는 아래 포트를 오픈하여 진행합니다.

노드 포트 TCP/UDP
마스터 6443, 2379-2380, 10250, 10251, 10252 TCP
마스터, 워커 6783 TCP
마스터, 워커 6783, 6784 UDP
워커 10250, 30000-32767 TCP
로드 밸런서 26443 TCP

호스트네임 설정

호스트네임은 서로 다르게 지정해야합니다.

$ sudo hostnamectl set-hostname node1

$ sudo hostnamectl set-hostname node2

$ sudo hostnamectl set-hostname node3

도커 설치

도커 레파지토리를 등록하여 yum 으로 설치 합니다.

$ sudo yum install -y yum-utils \
    device-mapper-persistent-data \
    lvm2

$ sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

$ sudo yum install docker-ce docker-ce-cli containerd.io

$ sudo systemctl start docker

설치 후 daemon.json을 추가하여 cgroupdriver를 systemd 옵션으로 사용할 수 있도록 합니다.

$ sudo cat <<EOF > /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}
EOF

$ sudo systemctl daemon-reload
$ sudo systemctl enable docker
$ sudo systemctl restart docker

쿠버네티스 설치

쿠버네티스의 레파지토리 저장소를 등록하여 yum 으로 kubelet, kubeadm, kubectl을 설치합니다.

  • kubeadm: 클러스터 관련 작업시 사용됩니다.
  • kubectl: 클러스터의 서비스 및 pod 관리시 사용됩니다.
  • kubelet: 클러스터 에이전트역할을 합니다.
$ sudo cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=0
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg [https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg](https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg)
EOF

$ sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

$ sudo systemctl enable kubelet
$ sudo systemctl restart kubelet

node1, node2, node3에 도커와 쿠버네티스가 설치를 하였다면 아래 명령어를 통해 확인해볼 수 있습니다.

$ sudo docker verison
$ kubectl version

로드밸런서 설치

공식문서에서 사용되고 있는 HAProxy를 사용하도록 하겠습니다.
테스트환경이기 때문에 keepalive및 failover 기능없이 진행하도록 하겠습니다.

노드1에만 haproxy 를 설치하도록 하겠습니다.

$ sudo yum install haproxy -y

haproxy 로드밸런싱 설정

node1 IP의 26443포트로 전달받은 데이터를 node1 ~ node3의 6443 포트로 포워드 시켜줍니다.
라운드로빈으로 순차적으로 접근하도록 하겠습니다.

$ sudo cat <<EOF >> /etc/haproxy/haproxy.cfg
frontend kubernetes-master-lb
bind 0.0.0.0:26443
option tcplog
mode tcp
default_backend kubernetes-master-nodes

backend kubernetes-master-nodes
mode tcp
balance roundrobin
option tcp-check
option tcplog
server node1 <node1 IP>:6443 check
server node2 <node2 IP>:6443 check
server node3 <node3 IP>:6443 check
EOF

$ sudo systemctl restart haproxy

haproxy 확인

해당 포트가 오픈되어 있는지 확인합니다.
포트가 오픈되어 있어도 접근이 안될때는 방화벽을 확인해야 합니다.

netstat -an|grep 26443

클러스터 생성

클러스터 생성할때 –upload-certs, –control-plane-endpoint 플래그를 추가해야 인증서가 자동 배포되고, 마스터 노드 조인 명령어가 출력됩니다.

$ sudo kubeadm init --control-plane-endpoint "<노드1 DNS/IP or LoadBalancer DNS/IP>:26443" \
                --upload-certs \
                --pod-network-cidr "10.244.0.0/16"

config 생성

kubectl 사용하기 위해서는 사용자 디렉토리 하위에 .kube/config 가 필요합니다. kubeadm init 명령어를 진행하고 마지막에 로그를 잘보면 config를 생성하는 명령어가 적혀있습니다.

$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config

클러스터 연결

노드1에서 클러스터 생성시 kubeadm join 명령어가 출력되는데 –control-plane –certificate-key 플래그 포함하여 명령어를 실행하면 마스터 노드로 연결이 되고, 플래그는 추가하지 않고 사용하게 되면 워커노드로 연결됩니다.

노드2 클러스터 연결

$ sudo kubeadm join 192.168.248.251:26443 --token 06glbc.s0yaqonyajs95ez3 \
    --discovery-token-ca-cert-hash sha256:379ff0daa2cffa3f6581ae25c96aa3d6e4a9af43df92b8d0ac5a4dbb4c7e5547 \
    --control-plane --certificate-key 8eb7fa9a38ca1579c3fb61e0a1106935c4e9dfd81cbad259121f223f0adf555f

config 생성

노드2의 사용자에서도 kubectl 명령어를 사용하기 위해선 config를 생성해야 합니다.

$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config

노드3 클러스터 연결

노드3에서도 노드2와 동일하게 연결을 진행합니다.

$ sudo kubeadm join 192.168.248.251:26443 --token 06glbc.s0yaqonyajs95ez3 \
    --discovery-token-ca-cert-hash sha256:379ff0daa2cffa3f6581ae25c96aa3d6e4a9af43df92b8d0ac5a4dbb4c7e5547 \
    --control-plane --certificate-key 8eb7fa9a38ca1579c3fb61e0a1106935c4e9dfd81cbad259121f223f0adf555f

config 생성

노드3에서도 동일하게 config를 생성해야합니다.

$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config

클러스터 구성 확인

노드가 연결이 되었다면 아래 명령어를 실행시 노드가 전부 보여야합니다.

$ kubectl get node

마스터 노드에는 기본설정으로 pod 배포가 안됩니다. taint명령어를 통해 pod 배포가 가능하도록 하겠습니다.

$ kubectl taint nodes --all node-role.kubernetes.io/master-

가상 네트워크(weave) 적용

Calico, Canal, Clilum, Flannel, weave 등 다양한 가상네트워크가 있지만 공식문서에서 제공하는 weave를 적용하도록 하겠습니다.

$ kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"

가상네트워크 적용 확인

최초 클러스터를 진행하게 되면 노드의 상태는 NotReady 입니다. 가상네트워크를 적용하게 되면 약 1 ~ 3분 소요되고 Ready 상태로 변경되게 됩니다. 이것으로 가상네트워크 적용이 완료 되었습니다.

$ kubectl get node

nginx 배포 해보기

nginx pod 3개를 배포하는 명령어입니다.

kubectl run --image=nginx --port 80 --replicas=3 nginx-app

아래 명령어를 통해 nginx-app 배포된 노드를 보면 node1 ~ 3 골고루 배포되어 있는걸 확인할 수 있습니다.

kubectl get pod -o wide

정리

이번에 쿠버네티스 고가용성 클러스터를 서버에 구축해보았습니다. 쿠버네티스 버전 1.6 이후 부터는 인증서배포 자동화, 클러스터 연결하는 방법이 간편하게 변경되었습니다. 이전 버전에서는 클러스터 구성하기위해선 복잡한 과정과 설정파일을 만들어야 했지만 이제는 간단하게 명령어 한줄만 입력하면 클러스터에 연결/해지를 하도록 변경되었습니다. 자유로운 노드 할당은 자원 낭비없이 효율적으로 관리하는데 장점이 될 것으로 보여집니다.

참고문서