여러 가지 VM 및 Linux OS가 존재하고, 딱히 뭘 활용해도 큰 관계는 없다
VirtualBox 설치 : https://www.virtualbox.org/wiki/Downloads
CentOS 설치 : http://isoredirect.centos.org/centos/7/isos/x86_64/
꼭 필요한 과정은 아니다.
단지 Virtual Box가 불편한 점이 몇 개 존재한다
(복사 붙여넣기가 잘 안된다는 점이라던가 마우스 포인터가 잘 안된다는 점이라던가...)
그리서 원격접속 툴이 있으면 편하게 활용 가능하다
원격접속 툴이므로 "내가 원하는 IP 주소"를 입력해야 해당 IP 주소를 통해 접근 가능할 것이다.
Server의 고정 IP 주소는 아래와 같이 설정했다.
이름 : 구분만 가능하면 됨
종류 : 사용할 OS. Linux 기반으로 만들 것이므로 Linux 선택
버전 : CentOS는 Other Linux에 포함됨
이후 계속 확인 선택
시스템 프로세서 CPU 2개
저장소 선택
네트워크 선택 후 어댑터에 브리지 선택
Test this media & install CentOS 7 선택
Language : 한국어
Disk 설정 [시스템 > 설치 대상]
네트워크 설정 [시스템 > 네트워크 및 호스트명 설정]
설치 시작 & [설정 > 사용자 설정] ROOT 암호 설정
설치 완료 후 [재부팅]
쿠버네티스가 Pod Network에 필요한 호스트 파일 시스템에 액세스 가능하도록 하기 위해 하는 설정들이다.
특정 서비스들이 Selinux라는 보안을 강화해주는 보안 강화 커널 때문에 오류가 발생하는 경우가 존재하는데, 이런 경우를 없애기 위한 과정이다
SELinux를 permissive로 변경하는 설정 과정으로, SELinux를 끄는 과정이다.
참고로 여기서부터 XShell에서 수행시키면 더욱 편하다
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
SELinux는 보안 커널이기 때문에 재부팅하면 다시 SELinux가 켜진다. 쿠버네티스를 활용할 때 SELinux를 계속 껐다 켰다 하기엔 귀찮기 때문에, 리부팅을 시켜도 SELinux가 꺼져있게 하기 위하여 영구적으로 SELinux를 끄도록 설정하는 명령어이다.
/etc/selinux/config
, 즉 SELinux에 대한 설정값들이 들어있는 파일에서 SELINUX의 Default Setting을 enforcing에서 permissive로 변경한다는 의미이다
sestatus
Current Mode:permissive
로 나온다면 성공!나중에 우리는 calico.yaml 파일을 활용하는데, 여기에서 열어줘야 하는 포트가 몇 개 존재한다.
6443은 Kubernetes API Server를 위한 Port, 10250은 kubelet API를 위한 Port 등등이다.
나중에 실제 서비스를 제공할 때는 이런 Port 번호만 열여주는 형식으로 방화벽을 해제하겠으나, 지금은 어디까지나 "활용"해보는 단계이므로 그냥 모든 방화벽을 내려서 모든 Port를 활용 가능하게 만들어버리자
systemctl stop firewalld && systemctl disable firewalld
systemctl stop NetworkManager && systemctl disable NetworkManager
Swap이 쿠버네티스에 필요한가를 알기 위해서는 먼저 Swap이 무엇인지부터 알 필요가 있다.
Swap은 RAM 용량이 부족할 때 하드 디스크 일부를 메모리처럼 활용하는 것이다.
RAM에 100개의 프로세스가 적재될 수 있는 경우, 101번째 프로세스가 들어온다고 가정하자.
Swap out은 100개의 적재된 프로세스 중 특정 프로세스가 Swap Partition으로 이동하는 Case, Swap in은 Swap Partition에 있는 프로세스에 이벤트가 와서 다시 메모리 영역으로 돌아오는 Case를 말한다.
먼저, 처음에 쿠버네티스에서 Swap을 고려하지 않았던 이유를 생각해보자.
쿠버네티스는 Pod를 생성할 때 "필요한 만큼의 리소스"를 할당 받을 수 있도록 설계되었다.
Swap 기능은 본래 허락된 메모리보다 더 큰 메모리 할당을 가능하게 하기 위한 기능이다.
하지만 쿠버네티스 자체가 "자원을 100% 활용하자!"라는 목표로 나왔고, 당연히 Pod는 "필요한 만큼의 리소스"를 받을 수 있다는 가정이 깔려있다. Swap 기능을 사용하는 순간 필요한 만큼의 리소스를 받지 못한다는 가정이 깔리기 때문에, 쿠버네티스의 목적에 맞지 않다고 생각하여 처음 kubelet은 이런 상황을 아예 고려하지 않도록 만들어졌다.
하지만, 위 사이트(Github Issues)에는 Swap에 대한 다양한 의견이 존재했다.
물론, 쿠버네티스는 자원을 모두 활용하는 것이 좋기 때문에 Swap이 발생하지 않는 것이 가장 좋다.
하지만, 위 사이트 중 "Deavid" 의견을 인용하자면, Host OS 자체 메모리가 작을 경우 Host 시스템의 안정성을 위해 Swap이 필요할 수도 있다고 주장한다.
즉, 쿠버네티스의 "자원을 최대한 활용하자"라는 목표에는 안 맞을 수도 있지만, "어떤 환경에서도 동작 가능하도록 만들자"라는 목표를 맞추기 위해서는 Swap 기능이 필요하다는 것이다.
Host OS 메모리가 작은데 이 Memory보다 큰 App을 실행시켜야 할 경우, 당연히 Host쪽에서는 OOM이 발생할 것이다.
Swap 기능이 존재한다면 이를 활용하여 최대한 OOM 문제를 피할 수 있겠으나, 존재하지 않는 쿠버네티스의 경우 OOM을 발생시킬 것이며, 이 OOM은 Host OS에 Critical한 문제(예를 들어 서버 다운)을 발생시킨다는 것이다.
이런 배포 환경에 대한 다양성을 고려하기 위해서 어느 정도 Swap 기능이 필요하다는 의견이였다.
이런 의견과 토론을 쿠버네티스측에서 보았는지 쿠버네티스 쪽에서도 Swap 기능을 활용할 수 있도록 Update를 진행한 것 같다.
하지만, 이런 제한적인 상황에서 활용되는 기능을 Main으로는 고려하지 않았는지 중요한 Update로 생각하지도 않은 것 같다.(일단 기능을 Update시키고 나중에 Docs를 배포하는 것을 보고 그렇게 생각이 들었다)
우리는 이런 제한적인 상황을 고려하지 않을 것이므로, Swap 설정을 끄자!
(사실 현업에서도 절대로 고려하지 않을 문제일거 같은게, 1개의 App Size가 크다면 Server가 될 컴퓨터 사양을 키워서 최소 1개 App은 돌아가도록 만들지 Swap 기능을 굳이 활용해서 꾸역꾸역 돌아가도록 만들지는 않을 것 같다)
swapoff -a && sed -i '/ swap / s/^/#/' /etc/fstab
RHEL이나 CentOS7을 사용할 때 iptables가 무시되어 트래픽이 잘못 Routing되는 문제가 발생된다고 한다.
이를 해결하기 위한 설정 방법이다.
cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
k8s.conf
라는 파일을 생성하는 명령어원래
net.bridge.bridge-nf-call-iptables
값의 Default가 0이라고 한다.
이는 Bridge 네트워크를 통해 송수신되는 패킷이 iptables 설정을 우회한다는 의미라고 한다.
Container의 네트워크 패킷이 Host OS의 iptables 설정에 따라 제어되는 것이 바람직한 상황이다.
따라서,net.bridge.bridge-nf-call-iptables
값을 1로 설정하여 Bridge 네트워크를 통해 송수신되는 패킷도 iptables를 따르게 하고, 이는 IPv6 버전에서 활용되는 iptable인 ip6tables에도 똑같이 적용되도록 설정하는 것이다
sysctl --system
Applying /etc/sysctl.d/k8s.conf
가 존재하면 성공적으로 설정 된 것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
EOF
/etc/yum.repos.d/kubernetes.repo
파일에 대한 설정을 해주는 과정yum update -y
cat << EOF >> /etc/hosts
192.168.0.30 k8s-master
192.168.0.31 k8s-node1
192.168.0.32 k8s-node2
EOF
/etc/hosts
: 현 컴퓨터의 호스트 이름 및 FQDN이 들어 있는 파일yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum update -y && yum install -y docker-ce-18.06.2.ce
mkdir /etc/docker
cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "60m"
},
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}
EOF
/etc/docker
디렉토리 생성/etc/docker/daemon.json
파일 생성 & 내용 추가mkdir -p /etc/systemd/system/docker.service.d
yum install -y --disableexcludes=kubernetes kubeadm-1.15.5-0.x86_64 kubectl-1.15.5-0.x86_64 kubelet-1.15.5-0.x86_64
shutdown now
Master를 복사하기 위해서는 먼저 Master가 꺼져 있어야 함
이후 VirtualBox Master 마우스 오른쪽 클릭 [복제] 버튼 클릭
root
로 되었을 것이며, 비밀번호는 아까 위에서 설정했던 root 비밀번호 값
그대로 입력하면 된다vi /etc/sysconfig/network-scripts/ifcfg-enp0s3
이후 IPADDR=
부분을 해당 Node의 IP로 변경해준다.
(ex) Node1을 변경할 경우, Node1은 192.168.0.31
로 설정해야한다.
즉, IPADDR="192.168.0.31"
로 변경한다
마지막으로, 네트워크를 재시작하여 변경한 설정값을 적용시킨다.
systemctl restart network
192.168.0.30
으로 설정되어 있으므로 XShell이 접속하지 못한다hostnamectl set-hostname k8s-node1
k8s-node1 대신 다른 이름으로 hosts를 설정하였을 경우, 설정한 값으로 입력해준다
이후 XShell에서 접근 가능해진다
systemctl daemon-reload
systemctl enable --now docker
docker run hello-world
Hello from Docker!
문구가 나오면 설치가 잘 된 것이다systemctl enable --now kubelet
kubeadm init --pod-network-cidr=20.96.0.0/12 --apiserver-advertise-address=192.168.0.30
--pod-network-cidr
: Pod Network IP
--apiserver-advertise-address
: Master IP
실행 이후 가장 아래에 kubeadm join ~
이라는 문구가 뜰 텐데, 이 문구를 항상 잘 저장해 놓아야 한다
root 계정을 이용하여 kubectl을 실행하기 위한 환경 변수를 설정하는 것이다
mkdir -p $HOME/.kube
$HOME/.kube
디렉토리 생성sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
/etc/kubernetes/admin.conf
에 쿠버네티스의 Master로써 실행시킬 수 있는 kubectl에 관한 설정이 들어있는데 이를 복사하여 $HOME/.kube/config
에 옮겨줌으로써 root 계정에서도 kubectl을 실행시킬 수 있게 해주는 것이다sudo chown $(id -u):$(id -g) $HOME/.kube/config
kubectl 이후 [tab]을 이용해서 다음에 올 명령어 리스트를 조회할 수 있게 하는 것
필수 기능은 아님
명령 실행 후 Server를 재시작해야 활용 가능
yum install bash-completion -y
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc
systemctl daemon-reload
systemctl enable --now docker
systemctl enable --now kubelet
Master Init 했을 때 복사한 값 붙여 넣기
kubeadm join 192.168.0.30:6443 --token acmwi3.dhvx1d8h2hm9tmu8 --discovery-token-ca-cert-hash sha256:2114bb74a3594caa37b0f8d380b1e69b5db3c23c45be82b45db2c035513c22b0
kubectl get nodes
curl -O https://docs.projectcalico.org/v3.9/manifests/calico.yaml
sed s/192.168.0.0\\/16/20.96.0.0\\/12/g -i calico.yaml
kubectl apply -f calico.yaml
kubectl get pods --all-namespaces
kubectl apply -f https://kubetm.github.io/documents/appendix/kubetm-dashboard-v1.10.1.yaml
nohup kubectl proxy --port=8001 --address=192.168.0.30 --accept-hosts='^*$' >/dev/null 2>&1 &
http://192.168.0.30:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/