본문 바로가기

Docker 시작하기 - RestAPI편

4) Kubernetes 로 Docker 배포하기

반응형

이전까지 docker를 run 하고 run 된 docker의 log 를 어떤식으로 통합해서 관리하는지에 대해 공부했다.

 

이제는 docker에 대한 배포 관리를 어떻게 할지 공부해 본다. 

 

프로젝트를 진행하면 굉장히 많은 docker images들이 생길것이다. 

 

인증API 부터 여러 기능의 API들과 front End 부분의 nginx들도 있을것이고 

 

이런 docker images들의 배포 와 실행을 효율적인 관리가 필요해져 생겨난것이 쿠버네티스 이다.

 

쿠버네티스 Doc 참조 : https://kubernetes.io/ko/docs/concepts/overview/what-is-kubernetes/

 

쿠버네티스란 무엇인가?

쿠버네티스는 컨테이너화된 워크로드와 서비스를 관리하기 위한 이식할 수 있고, 확장 가능한 오픈소스 플랫폼으로, 선언적 구성과 자동화를 모두 지원한다. 쿠버네티스는 크고 빠르게 성장하

kubernetes.io

 

이제 쿠버네티스를 설치해보고 배포까지 해보도록하자.

 

먼저 쿠버네티스 설치를 위해 GCP 인스턴스를 두개를 만들도록 한다. 하나는 쿠버네티스 Master node로 하나는 Worker node로 사용할 것이다.

 

master-node : Ubuntu 18.04 CPU 2core mem 4g

worker-node : Ubuntu 18.04 CPU 2core mem 4g

이렇게 두개를 만들었다. 

 

이제 두 인스턴스에 공통으로 설치되야하는 부분을 설치해보도록 하자.

 

먼저 Docker를  설치한다.

sudo apt update
sudo apt-get update

# Docker CE 설치
## 리포지터리 설정
### apt가 HTTPS 리포지터리를 사용할 수 있도록 해주는 패키지 설치
sudo apt-get install -y \
  apt-transport-https ca-certificates curl software-properties-common gnupg2

### Docker의 공식 GPG 키 추가
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

### Docker apt 리포지터리 추가.
sudo add-apt-repository \
  "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) \
  stable"

## Docker CE 설치.
sudo apt-get update && sudo apt-get install -y \
  containerd.io=1.2.13-1 \
  docker-ce=5:19.03.8~3-0~ubuntu-$(lsb_release -cs) \
  docker-ce-cli=5:19.03.8~3-0~ubuntu-$(lsb_release -cs)

# 데몬 설정.
sudo su -
cat > /etc/docker/daemon.json <<EOF
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF
exit

sudo mkdir -p /etc/systemd/system/docker.service.d

# Docker 재시작.
sudo systemctl daemon-reload
sudo systemctl restart docker

 

이제 쿠버네티스에 필요한 kubeadm, kubelet, kubectl 를 설치 한다.

 

sudo apt-get update
sudo apt-get upgrade

sudo apt-get install -y apt-transport-https curl
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl

# 자동업데이트 방지
sudo apt-mark hold kubelet kubeadm kubectl

kubeadm version
kubelet --version
kubectl version

 

이제 mater node에서 아래 명령어를 실행한다.

sudo kubeadm init --pod-network-cidr=10.244.0.0/16 \
  --apiserver-advertise-address=<GCP 인스턴스 내부아이피>

위 명령를 실행하면 아래와 같은 메세지가 나오는데 

  o 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

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

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/

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

kubeadm join 10.178.0.10:6443 --token b3127i.2zzufx7o47jpl6s4 \
    --discovery-token-ca-cert-hash sha256:d1f0978b8950b5009a5376ed2bde4826d87b4973902c7b6b3fe7bf2a9b0d9c55 

 

위 메세지 부분에서  kubectl 명령어를 root 계정없이 사용하기 위해 아래를 실행

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

 

그리고 제일 마지막 부분의 kubeadm... 부분을 copy 해서 worker node에서 실행시켜주면된다.

kubeadm join 10.178.0.10:6443 --token b3127i.2zzufx7o47jpl6s4 \
    --discovery-token-ca-cert-hash sha256:d1f0978b8950b5009a5376ed2bde4826d87b4973902c7b6b3fe7bf2a9b0d9c55 

 

master node에 네트워크 add on을 설치한다. 쿠버네티스 클러스터 네트워킹의 동작을 위한 플러그인이라고 한다.

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/2140ac876ef134e0ed5af15c65e414cf26827915/Documentation/kube-flannel.yml

 

여기까지하고 master node에서  kubectl get pods 를 실행해보면 아래 처럼 나오는것을 확인 할 수 있다.

 

이제 테스트를 위해 docker hub에서 hello world images를 쿠버네티스에 deploy 시켜 pod를 할당해 보자.

 

kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1

위 명령어를 실행하면 만들어 놓은 worker-node에 pod가 할당되는것을 확인 할 수 있다.

 

kubectl get pods -o wide

pod에 할당받은 IP로 실행한 이미지가 가 잘 작동하는지 테스트 해 보자 

 

curl을 날려 해당 container가 잘 작동하는것을 확인 할 수 있다.

 

이제 쿠버네티스가 잘 설치 되었다는것을 확인 했으니 앞에서 만들어 놓은 rest api images를 배포해 보자.

 

먼저 만들어 놓은 이미지를 docker hub에 psush 한다. 

 

docker hub에 이미지를 올리고 아래 처럼 쿠버네티스 deployment yml파일 작성하고 deployment를 생성한다.

 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-react-app
spec:
  replicas: 3
  minReadySeconds: 5
  selector:
    matchLabels:
      app: my-react-app
  template:
    metadata:
      name: my-react-app-pod
      labels:
        app: my-react-app
    spec:
      containers:
      - name: my-react-app
        image: kangzu8743/apitest:v1
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
kubectl create -f my-react-app-deployment.yml

depl,oyment를 실행하면 해당 deploymeny yml에 설정된 내용으로 pod가 만들어 진다. 

 

기본으로 replica 3으로 설정되어 3개의 pod가 만들어 진다.

각각의 3개의 pod에 curl을 날려서 확인해 보자 . 

 

 

 

의 그림과 같이 결과가 나오는것을 확인 할 수 있다. 이제 여기에 각각의 pod를 앞에 LoadBalancer 를  설정해 보자 .

 

쿠버네티스에서는 간단히 Component가 있다. 아래 yml 파일을 보면서 이해해 보자.

 

apiVersion: v1
kind: Service
metadata:
  name: my-react-app-service
spec:
  selector:
    app: my-react-app
  ports:
    - port: 8080
      protocol: TCP
      targetPort: 8080
  type: LoadBalancer

 

Service type이고 selector 부분을 보면 pod name이 my-react-app 인것들을 연결하고 

포트는 8080 port 이고 my-react-app의 내부port 도 8080 이고 이 service의 type은  LoadBalancer 라고 되어 있다.

 

이렇게  설정된 값으로 service를 생성해 보자.

kubectl create -f lb-service.yml

결과를 확인해 보면 

 

kubectl get services

 

와 같이 LB가 생성된 것을 확인 할 수 있다. 이제 curl로 확인을 해보면 

 

 

여기서 문제는 EXTERNAL_IP가 pending 이 되어 있다. exnternal_ip가 할당 되지 않아서 그런지 CLUSTER-IP로는 정상적으로 데이터가 호출이 되는데  GCE 외부IP로 호출하게 되면 접속이 안된다. 

 

확인해 보니 현재 instance에 8080으로 LISTEN 하고 프로세스가 없는것을 확인. 이로 미로어 볼때 쿠버네티스 클러스터에서 8080이 할당되어 있고 클러스터 외부에서는 8080을 Listen 하지 않는다는것인데 ... 

 

여러내용을 찾아본 결과 서비스 생성 yml을 아래와같이 수정해 주면 해결!

 

apiVersion: v1
kind: Service
metadata:
  name: my-react-app-service
spec:
  selector:
    app: my-react-app
  ports:
    - port: 8080
      protocol: TCP
      targetPort: 8080
  externalIPs:
    - 10.178.0.10
  type: LoadBalancer

externalIPs:
    - 10.178.0.10 ==> 이부분이 GCE의 내부IP(master node) 로 추가하면 외부에서 GCE 외부 IP로 접속해서 service 호출이 가능해 진다. 

 

여기까지 쿠버네티스를 설치하고 배포하고 배포된 pod에 대한 LB 까지 테스트 해 봤다. 

 

다음은 간단히 쿠버네티스의 무중단 배포에 대해 알아보도록 하자. 무중단 배포에 간단한 원리와 쿠버네티스에서는 어떤식으로 무중단 배포를 지원하는지를 공부해보자.