> For the complete documentation index, see [llms.txt](https://kubernetes.youngwjung.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kubernetes.youngwjung.com/overview/basics-of-kubernetes/lab.md).

# 실습

해당 실습은 AWS 환경에서 t3.small 타입의 EC2 인스턴스에 Ubuntu Server 20.04 LTS 에서 실습을 진행하다고 가정하고 작성되었습니다.

## Minikube

EC2 인스턴스 1개를 생성하세요.

1. Docker 설치&#x20;

   ```
   sudo apt update && sudo apt install -y docker.io
   ```
2. Docker 권한 설정&#x20;

   ```
   sudo usermod -aG docker $USER
   sudo su - $USER
   ```
3. Minikube 설치&#x20;

   ```
   curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
   sudo install minikube-linux-amd64 /usr/local/bin/minikube
   ```
4. Minikube 실행&#x20;

   ```
   minikube start
   ```
5. 실행중인 Pod 확인&#x20;

   ```
   minikube kubectl -- get pod --all-namespaces
   ```
6. 데모 애플리케이션 배포

   ```
   minikube kubectl -- run nginx --image=nginx
   ```
7. 서비스 엔드포인트 생성&#x20;

   ```
   minikube kubectl -- expose pod nginx --port=80 --type=NodePort
   ```
8. 서비스 엔드포인트 및 포트 확인

   ```
   minikube service nginx
   ```
9. 서비스 엔드포인트로 접속되는지 확인&#x20;

   ```
   curl $(minikube service nginx --url)
   ```
10. EC2 인스턴스 삭제&#x20;

## Single Master Cluster

EC2 인스턴스 2개를 생성하세요.

### 마스터 노드 구성&#x20;

1. 마스터 노드로 사용할 EC2 인스턴스에 접속&#x20;
2. Root 유저로 전환&#x20;

   ```
   sudo -i
   ```
3. 시스템 구동에 필요한 라이브러리 설치

   ```
   apt update && apt install -y jq apt-transport-https ca-certificates libseccomp2  
   ```
4. CRI-O 구동에 필요한 overlay와 br\_netfilter 커널 모듈 불러오기&#x20;

   ```
   modprobe overlay
   modprobe br_netfilter
   ```
5. CRI-O 구동에 필요한 커널 파라미터 설정파일 생성&#x20;

   ```
   cat <<EOF> /etc/sysctl.d/99-kubernetes-cri.conf
   net.bridge.bridge-nf-call-iptables  = 1
   net.ipv4.ip_forward                 = 1
   net.bridge.bridge-nf-call-ip6tables = 1
   EOF
   ```
6. 위에서 생성한 설정파일 반영

   ```
   sysctl --system
   ```
7. CRI-O 설치

   ```
   {
       echo "deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.22/xUbuntu_18.04/ /" | sudo tee -a /etc/apt/sources.list.d/cri-0.list
       curl -L http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.22/xUbuntu_18.04/Release.key | sudo apt-key add -
       echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_18.04/ /" | sudo tee -a /etc/apt/sources.list.d/libcontainers.list

       apt update && apt install -y cri-o cri-o-runc
   }
   ```
8. CRI-O CNI 설정 확인

   ```
   cat /etc/cni/net.d/100-crio-bridge.conf
   ```
9. CRI-O CNI 설정 삭제

   ```
   rm -rf /etc/cni/net.d
   ```
10. CRI-O 서비스 재기동&#x20;

    ```
    {
        systemctl daemon-reload
        systemctl enable crio
        systemctl restart crio
    }
    ```
11. 쿠버네티스 설치 및 구동에 필요한 바이너리 설치&#x20;

    ```
    {
        curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
        echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
        apt update && apt install -y kubelet kubeadm kubectl
    }
    ```
12. 리눅스 호스트네임 설정&#x20;

    ```
    hostnamectl set-hostname master-1 && su
    ```
13. 컨트롤 플레인(마스터 노드) 구성&#x20;

    ```
    kubeadm init
    ```
14. kubeconfig 설정&#x20;

    ```
    mkdir -p $HOME/.kube
    cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    chown $(id -u):$(id -g) $HOME/.kube/config
    ```
15. kubeconfig 파일 확인&#x20;

    ```
    cat ~/.kube/config
    ```
16. 마스터 노드의 사설 IP 확인

    ```
    hostname -i
    ```
17. 노드 목록 확인&#x20;

    ```
    kubectl get node
    ```
18. 마스터 노드 상태 확인

    ```
    kubectl describe node master
    ```
19. 배포된 Pod 확인&#x20;

    ```
    kubectl get pod -A
    ```
20. Pending 상태의 Pod가 있다면 아래의 명령어를 통해서 그 이유를 확인

    ```
    kubectl -n kube-system describe pod \
    $(kubectl get pod -n kube-system -o=jsonpath='{.items[?(@.status.phase=="Pending")].metadata.name}')
    ```
21. CNI 플러그인 설치&#x20;

    ```
    kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
    ```
22. 마스터 노드 상태 확인&#x20;

    ```
    kubectl get node -w
    ```
23. 배포된 Pod 확인&#x20;

    ```
    kubectl get pod -A
    ```
24. 정적 Pod 생성 경로에 있는 파일 확인

    ```
    ls /etc/kubernetes/manifests/
    ```
25. Manifest 파일 생성&#x20;

    ```
    kubectl run nginx --image=nginx --dry-run=client -oyaml > nginx.yaml
    ```
26. 위에서 생성한 Manifest 파일을 정적 Pod 생성 경로로 복사

    ```
    mv nginx.yaml /etc/kubernetes/manifests/
    ```
27. 새로운 Pod가 생성되었는지 확인&#x20;

    ```
    kubectl get po
    ```
28. kubectl 명령어로 위에서 생성한 Pod 삭제

    ```
    kubectl delete pod nginx-master-1
    ```
29. Pod가 삭제되었는지 확인

    ```
    kubectl get pod
    ```
30. 정적 Pod 생성 경로에 있는 파일 삭제&#x20;

    ```
    rm /etc/kubernetes/manifests/nginx.yaml
    ```
31. Pod가 삭제되었는지 확인

    ```
    kubectl get pod
    ```
32. kubectl 명령어로 새로운 Pod 생성

    ```
    kubectl run nginx --image=nginx
    ```
33. 새로운 Pod가 생성되었는지 확인&#x20;

    ```
    kubectl get pod
    ```
34. Pod가 Pending 상태인 이유 확인

    ```
    kubectl describe pod \
    $(kubectl get pod -o=jsonpath='{.items[?(@.status.phase=="Pending")].metadata.name}')
    ```
35. 마스터 노드에 부여된 Taint 확인

    ```
    kubectl get node master-1 -o yaml -o=jsonpath='{.spec.taints}' | jq
    ```

### 워커 노드 구성&#x20;

1. 워커 노드로 사용할 EC2 인스턴스에 접속&#x20;
2. Root 유저로 전환&#x20;

   ```
   sudo -i
   ```
3. 시스템 구동에 필요한 라이브러리 설치

   ```
   apt update && apt install -y apt-transport-https ca-certificates libseccomp2  
   ```
4. CRI-O 구동에 필요한 overlay와 br\_netfilter 커널 모듈 불러오기&#x20;

   ```
   modprobe overlay
   modprobe br_netfilter
   ```
5. CRI-O 구동에 필요한 커널 파라미터 설정파일 생성&#x20;

   ```
   cat <<EOF> /etc/sysctl.d/99-kubernetes-cri.conf
   net.bridge.bridge-nf-call-iptables  = 1
   net.ipv4.ip_forward                 = 1
   net.bridge.bridge-nf-call-ip6tables = 1
   EOF
   ```
6. 위에서 생성한 설정파일 반영

   ```
   sysctl --system
   ```
7. CRI-O 설치

   ```
   {
       echo "deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.22/xUbuntu_18.04/ /" | sudo tee -a /etc/apt/sources.list.d/cri-0.list
       curl -L http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.22/xUbuntu_18.04/Release.key | sudo apt-key add -
       echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_18.04/ /" | sudo tee -a /etc/apt/sources.list.d/libcontainers.list

       apt update && apt install -y cri-o cri-o-runc
   }
   ```
8. CRI-O CNI 설정 삭제

   ```
   rm -rf /etc/cni/net.d
   ```
9. CRI-O 서비스 재기동&#x20;

   ```
   {
       systemctl daemon-reload
       systemctl enable crio
       systemctl restart crio
   }
   ```
10. 쿠버네티스 설치 및 구동에 필요한 바이너리 설치&#x20;

    ```
    {
        curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
        echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
        apt update && apt install -y kubelet kubeadm
    }
    ```
11. 리눅스 호스트네임 설정&#x20;

    ```
    hostnamectl set-hostname worker-1 && su
    ```
12. 마스터 노드에 연결된 터미널로 이동해서 워커 노드 조인 명령어 생성&#x20;

    ```
    kubeadm token create --print-join-command --ttl 0
    ```
13. 워커 노드에서 위의 명령어를 실행하고 나온 명령어를 실행

### 클러스터 구성 확인&#x20;

1. 마스터 노드 SSH 세션으로 이동&#x20;
2. 노드 상태 확인&#x20;

   ```
   kubectl get no
   ```
3. Pending 상태였던 Pod가 배포됐는지 확인&#x20;

   ```
   kubectl get po -o wide
   ```
4. Service 생성&#x20;

   ```
   kubectl expose pod nginx --port=80 --type=NodePort
   ```
5. 서비스 엔드포인트 및 포트 확인&#x20;

   ```
   kubectl get svc nginx
   ```
6. 웹브라우저에서 `ANY_NODE_IP:SERVICE_NODE_PORT` 로 접속되는지 확인 - 아래 명령어로 주소 확인 가능&#x20;

   ```
   echo "$(curl -s ifconfig.io):$(kubectl get svc nginx -o=jsonpath='{.spec.ports[0].nodePort}')"
   ```

실습에 사용한 인스턴스들을 삭제하세요.

## Multi Master Cluster

EC2 인스턴스 5개를 생성하세요.

### HAProxy 구성&#x20;

1. 로드밸런서로 사용할 EC2 인스턴스에 SSH 접속
2. 리눅스 호스트네임 설정&#x20;

   ```
   sudo hostnamectl set-hostname ha-proxy && sudo su $USER
   ```
3. HAProxy 설치&#x20;

   ```
   sudo apt-get update && sudo apt-get install -y haproxy
   ```
4. HAProxy 설정파일을 `/etc/haproxy/haproxy.cfg` 아래와 같이 수정&#x20;

   ```
   ...
   # 23번라인 근처를 아래와 같이 수정 
   defaults
   	log	global
   	mode	tcp
   	option	tcplog
   ...
   ...

   # 아래의 라인들을 추가 
   frontend proxynode
      bind *:80
      bind *:6443
      stats uri /proxystats
      default_backend k8sServers

   backend k8sServers
      balance roundrobin
      server master1 MASTER1_IP_ADDRESS:6443 check
      server master2 MASTER2_IP_ADDRESS:6443 check
      server master3 MASTER3_IP_ADDRESS:6443 check  

   listen stats
        bind :9999
        mode http
        stats enable
        stats hide-version
        stats uri /stats
   ```
5. HAProxy 데몬을 재시작하고 상태 확인&#x20;

   ```
   sudo systemctl restart haproxy
   sudo systemctl is-active haproxy
   ```
6. 웹 브라우저를 열고 `HAPROXY_IP:9999/stats` 주소로 접속 - 아래 명령어로 주소 확인 가능

   ```
   echo "$(curl -s ifconfig.io):9999/stats"
   ```

### 마스터 노드 구성&#x20;

#### 첫번째 마스터 노드 구성&#x20;

1. 마스터 노드로 사용한 인스턴스중에 하나로 SSH 접속
2. Root 유저로 전환&#x20;

   ```
   sudo -i
   ```
3. 시스템 구동에 필요한 라이브러리 설치

   ```
   apt update && apt install -y jq apt-transport-https ca-certificates libseccomp2  
   ```
4. CRI-O 구동에 필요한 overlay와 br\_netfilter 커널 모듈 불러오기&#x20;

   ```
   modprobe overlay
   modprobe br_netfilter
   ```
5. CRI-O 구동에 필요한 커널 파라미터 설정파일 생성&#x20;

   ```
   cat <<EOF> /etc/sysctl.d/99-kubernetes-cri.conf
   net.bridge.bridge-nf-call-iptables  = 1
   net.ipv4.ip_forward                 = 1
   net.bridge.bridge-nf-call-ip6tables = 1
   EOF
   ```
6. 위에서 생성한 설정파일 반영

   ```
   sysctl --system
   ```
7. CRI-O 설치

   ```
   {
       echo "deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.22/xUbuntu_18.04/ /" | sudo tee -a /etc/apt/sources.list.d/cri-0.list
       curl -L http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.22/xUbuntu_18.04/Release.key | sudo apt-key add -
       echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_18.04/ /" | sudo tee -a /etc/apt/sources.list.d/libcontainers.list

       apt update && apt install -y cri-o cri-o-runc
   }
   ```
8. CRI-O CNI 설정 삭제

   ```
   rm -rf /etc/cni/net.d
   ```
9. CRI-O 서비스 재기동&#x20;

   ```
   {
       systemctl daemon-reload
       systemctl enable crio
       systemctl restart crio
   }
   ```
10. 쿠버네티스 설치 및 구동에 필요한 바이너리 설치&#x20;

    ```
    {
        curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
        echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
        apt update && apt install -y kubelet kubeadm kubectl
    }
    ```
11. 리눅스 호스트네임 설정&#x20;

    ```
    hostnamectl set-hostname master-1 && su
    ```
12. 첫번째 컨트롤 플레인(마스터 노드) 구성

    ```
    kubeadm init --control-plane-endpoint "HA_PROXY_IP:6443" --upload-certs
    ```
13. 위의 명령어를 실행하고 나온 Outputs에서 컨트롤 플레인 노드 조인 명령어를 메모장에 복사&#x20;

    ```
    e.g.

    You can now join any number of the control-plane node running the following command on each as root:

    kubeadm join 123.123.123.123:6443 --token xu0c4j.vd0fi1yk4j95de30 \
    --discovery-token-ca-cert-hash sha256:1cfdaaa76a9316ac6e7fce7eb9577039857b565c14956c0f4b108108c02da6cb \
    --control-plane --certificate-key 09a6dba1b07280f75d121068a6feece19e0b6721baa555f418e55c783083177f
    ```
14. kubeconfig 설정&#x20;

    ```
    mkdir -p $HOME/.kube
    cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    chown $(id -u):$(id -g) $HOME/.kube/config
    ```
15. 마스터 노드 상태 확인&#x20;

    ```
    kubectl get node
    ```
16. CNI 플러그인 설치&#x20;

    ```
    kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
    ```
17. 마스터 노드 상태 확인&#x20;

    ```
    kubectl get node
    ```

#### 두번째 마스터 노드 구성&#x20;

1. 마스터 노드로 사용한 인스턴스중에 하나로 SSH 접속
2. Root 유저로 전환&#x20;

   ```
   sudo -i
   ```
3. 시스템 구동에 필요한 라이브러리 설치

   ```
   apt update && apt install -y apt-transport-https ca-certificates libseccomp2  
   ```
4. CRI-O 구동에 필요한 overlay와 br\_netfilter 커널 모듈 불러오기&#x20;

   ```
   modprobe overlay
   modprobe br_netfilter
   ```
5. CRI-O 구동에 필요한 커널 파라미터 설정파일 생성&#x20;

   ```
   cat <<EOF> /etc/sysctl.d/99-kubernetes-cri.conf
   net.bridge.bridge-nf-call-iptables  = 1
   net.ipv4.ip_forward                 = 1
   net.bridge.bridge-nf-call-ip6tables = 1
   EOF
   ```
6. 위에서 생성한 설정파일 반영

   ```
   sysctl --system
   ```
7. CRI-O 설치

   ```
   {
       echo "deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.22/xUbuntu_18.04/ /" | sudo tee -a /etc/apt/sources.list.d/cri-0.list
       curl -L http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.22/xUbuntu_18.04/Release.key | sudo apt-key add -
       echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_18.04/ /" | sudo tee -a /etc/apt/sources.list.d/libcontainers.list

       apt update && apt install -y cri-o cri-o-runc
   }
   ```
8. CRI-O CNI 설정 삭제

   ```
   rm -rf /etc/cni/net.d
   ```
9. CRI-O 서비스 재기동&#x20;

   ```
   {
       systemctl daemon-reload
       systemctl enable crio
       systemctl restart crio
   }
   ```
10. 쿠버네티스 설치 및 구동에 필요한 바이너리 설치&#x20;

    ```
    {
        curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
        echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
        apt update && apt install -y kubelet kubeadm kubectl
    }
    ```
11. 리눅스 호스트네임 설정&#x20;

    ```
    hostnamectl set-hostname master-2 && su
    ```
12. \[**첫번째 마스터 노드 구성**] 13번 단계에서 메모한 명령어를 실행&#x20;

#### 세번째 마스터 노드 구성&#x20;

1. 마스터 노드로 사용한 인스턴스중에 하나로 SSH 접속
2. Root 유저로 전환&#x20;

   ```
   sudo -i
   ```
3. 시스템 구동에 필요한 라이브러리 설치

   ```
   apt update && apt install -y apt-transport-https ca-certificates libseccomp2  
   ```
4. CRI-O 구동에 필요한 overlay와 br\_netfilter 커널 모듈 불러오기&#x20;

   ```
   modprobe overlay
   modprobe br_netfilter
   ```
5. CRI-O 구동에 필요한 커널 파라미터 설정파일 생성&#x20;

   ```
   cat <<EOF> /etc/sysctl.d/99-kubernetes-cri.conf
   net.bridge.bridge-nf-call-iptables  = 1
   net.ipv4.ip_forward                 = 1
   net.bridge.bridge-nf-call-ip6tables = 1
   EOF
   ```
6. 위에서 생성한 설정파일 반영

   ```
   sysctl --system
   ```
7. CRI-O 설치

   ```
   {
       echo "deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.22/xUbuntu_18.04/ /" | sudo tee -a /etc/apt/sources.list.d/cri-0.list
       curl -L http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.22/xUbuntu_18.04/Release.key | sudo apt-key add -
       echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_18.04/ /" | sudo tee -a /etc/apt/sources.list.d/libcontainers.list

       apt update && apt install -y cri-o cri-o-runc
   }
   ```
8. CRI-O CNI 설정 삭제

   ```
   rm -rf /etc/cni/net.d
   ```
9. CRI-O 서비스 재기동&#x20;

   ```
   {
       systemctl daemon-reload
       systemctl enable crio
       systemctl restart crio
   }
   ```
10. 쿠버네티스 설치 및 구동에 필요한 바이너리 설치&#x20;

    ```
    {
        curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
        echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
        apt update && apt install -y kubelet kubeadm kubectl
    }
    ```
11. 리눅스 호스트네임 설정&#x20;

    ```
    hostnamectl set-hostname master-3 && su
    ```
12. \[**첫번째 마스터 노드 구성**] 13번 단계에서 메모한 명령어를 실행&#x20;

### 워커 노드 구성&#x20;

1. 워커 노드로 사용할 EC2 인스턴스에 접속&#x20;
2. Root 유저로 전환&#x20;

   ```
   sudo -i
   ```
3. 시스템 구동에 필요한 라이브러리 설치

   ```
   apt update && apt install -y apt-transport-https ca-certificates libseccomp2  
   ```
4. CRI-O 구동에 필요한 overlay와 br\_netfilter 커널 모듈 불러오기&#x20;

   ```
   modprobe overlay
   modprobe br_netfilter
   ```
5. CRI-O 구동에 필요한 커널 파라미터 설정파일 생성&#x20;

   ```
   cat <<EOF> /etc/sysctl.d/99-kubernetes-cri.conf
   net.bridge.bridge-nf-call-iptables  = 1
   net.ipv4.ip_forward                 = 1
   net.bridge.bridge-nf-call-ip6tables = 1
   EOF
   ```
6. 위에서 생성한 설정파일 반영

   ```
   sysctl --system
   ```
7. CRI-O 설치

   ```
   {
       echo "deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.22/xUbuntu_18.04/ /" | sudo tee -a /etc/apt/sources.list.d/cri-0.list
       curl -L http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.22/xUbuntu_18.04/Release.key | sudo apt-key add -
       echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_18.04/ /" | sudo tee -a /etc/apt/sources.list.d/libcontainers.list

       apt update && apt install -y cri-o cri-o-runc
   }
   ```
8. CRI-O CNI 설정 삭제

   ```
   rm -rf /etc/cni/net.d
   ```
9. CRI-O 서비스 재기동&#x20;

   ```
   {
       systemctl daemon-reload
       systemctl enable crio
       systemctl restart crio
   }
   ```
10. 쿠버네티스 설치 및 구동에 필요한 바이너리 설치&#x20;

    ```
    {
        curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
        echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
        apt update && apt install -y kubelet kubeadm
    }
    ```
11. 리눅스 호스트네임 설정&#x20;

    ```
    hostnamectl set-hostname worker-1 && su
    ```
12. 첫번째 마스터 노드에 연결된 터미널로 이동해서 워커 노드 조인 명령어 생성&#x20;

    ```
    kubeadm token create --print-join-command --ttl 0
    ```
13. 워커 노드에서 위의 명령어를 실행하고 나온 명령어를 실행

### 클러스터 구성 확인&#x20;

1. 첫번째 마스터 노드에 연결된 터미널로 이동
2. 노드 상태 확인

   ```
   kubectl get node
   ```
3. 배포된 Pod 확인

   ```
   kubectl get po -A
   ```
4. HAProxy에 연결된 터미널로 이동
5. 웹 브라우저를 열고 `HAPROXY_IP:9999/stats` 주소로 접속 - 아래 명령어로 주소 확인 가능

   ```
   echo "$(curl -s ifconfig.io):9999/stats"
   ```

### 컨트롤 플레인 고가용성 테스트&#x20;

1. 첫번째 마스터 노드에 연결된 터미널로 이동
2. 실행중인 ETCD Pod 확인&#x20;

   ```
   kubectl get pod -n kube-system -l component=etcd 
   ```
3. ETCD Pod 로그 확인&#x20;

   ```
   kubectl -n kube-system logs etcd-master-2 | grep leader -A 5 -B 5
   ```
4. 실행중인 ETCD Pod의 IP 주소 확인&#x20;

   ```
   kubectl get pod -n kube-system -l component=etcd -o wide 
   ```
5. ETCD 클러스터 상태 확인&#x20;

   ```
   kubectl -n kube-system exec -it etcd-master-1 -- \
   etcdctl -w table \
   --endpoints \
   $(kubectl get pod etcd-master-1 -n kube-system -o=jsonpath='{.status.podIP}'):2379,\
   $(kubectl get pod etcd-master-2 -n kube-system -o=jsonpath='{.status.podIP}'):2379,\
   $(kubectl get pod etcd-master-3 -n kube-system -o=jsonpath='{.status.podIP}'):2379 \
   --cacert /etc/kubernetes/pki/etcd/ca.crt \
   --cert /etc/kubernetes/pki/etcd/server.crt \
   --key /etc/kubernetes/pki/etcd/server.key \
   endpoint status
   ```
6. ETCD 클러스터의 리더 Pod가 배포된 노드에 가서 컨테이너 런타임 정지 - 첫번째 마스터 노드의 ETCD가 가장 먼저 구성되었기 때문에 일반적으로 첫번째 마스터 노드에 배포된 ETCD가 리더

   ```
   {
       sudo systemctl stop kubelet
       sudo crictl stop $(sudo crictl ps -q)
       sudo systemctl stop crio.service
       sudo systemctl start kubelet
   }
   ```
7. 첫번째 마스터 노드에 연결된 터미널로 이동해서 ETCD Pod 로그 확인&#x20;

   ```
   kubectl -n kube-system logs etcd-master-2 | grep leader -A 5 -B 5
   ```
8. 웹 브라우저를 열고 `HAPROXY_IP_ADDRESS:9999/stats` 주소로 접속해서 위에서 노드들의 연결 상태 확인&#x20;
9. ETCD 클러스터 상태 확인 - 리더가 변경된 것을 확인&#x20;

   ```
   kubectl -n kube-system exec -it etcd-master-2 -- \
   etcdctl -w table \
   --endpoints \
   $(kubectl get pod etcd-master-1 -n kube-system -o=jsonpath='{.status.podIP}'):2379,\
   $(kubectl get pod etcd-master-2 -n kube-system -o=jsonpath='{.status.podIP}'):2379,\
   $(kubectl get pod etcd-master-3 -n kube-system -o=jsonpath='{.status.podIP}'):2379 \
   --cacert /etc/kubernetes/pki/etcd/ca.crt \
   --cert /etc/kubernetes/pki/etcd/server.crt \
   --key /etc/kubernetes/pki/etcd/server.key \
   endpoint status
   ```
10. 실행중인 ETCD Pod의 IP 주소 확인&#x20;

    ```
    kubectl get pod -n kube-system -l component=etcd -o wide 
    ```
11. ETCD 클러스터의 리더가 **아닌** Pod가 배포된 노드에 가서 컨테이너 런타임 정지

    ```
    {
        sudo systemctl stop kubelet
        sudo crictl stop $(sudo crictl ps -q)
        sudo systemctl stop crio.service
        sudo systemctl start kubelet
    }
    ```
12. HAProxy 상태 페이지에 들어가서 노드들의 연결 상태 확인
13. 첫번째 마스터 노드에 연결된 터미널로 이동해서 노드 상태 확인

    ```
    kubectl get node
    ```
14. 컨테이너 런타임을 정지한 노드들에서 컨테이너 런타임 실행 &#x20;

    ```
    sudo systemctl start crio.service
    ```
15. HAProxy 상태 페이지에 들어가서 노드들의 연결 상태 확인
16. 첫번째 마스터 노드에 연결된 터미널로 이동해서 노드 상태 확인

    ```
    kubectl get node
    ```
17. 모든 Pod가 정상적으로 실행되고 있는지 확인

    ```
    kubectl get pod -A
    ```
18. ETCD 클러스터 상태 확인

    ```
    kubectl -n kube-system exec -it etcd-master-2 -- \
    etcdctl -w table \
    --endpoints \
    $(kubectl get pod etcd-master-1 -n kube-system -o=jsonpath='{.status.podIP}'):2379,\
    $(kubectl get pod etcd-master-2 -n kube-system -o=jsonpath='{.status.podIP}'):2379,\
    $(kubectl get pod etcd-master-3 -n kube-system -o=jsonpath='{.status.podIP}'):2379 \
    --cacert /etc/kubernetes/pki/etcd/ca.crt \
    --cert /etc/kubernetes/pki/etcd/server.crt \
    --key /etc/kubernetes/pki/etcd/server.key \
    endpoint status
    ```

![](/files/-MangchaVis0J8urjaGM)

## ETCD

1. ETCD에 저장된 데이터 확인&#x20;

   ```
   kubectl exec -it etcd-master-1 -n kube-system -- \
   etcdctl --key /etc/kubernetes/pki/etcd/server.key --cert /etc/kubernetes/pki/etcd/server.crt --cacert /etc/kubernetes/pki/etcd/ca.crt get / --prefix --keys-only
   ```
2. Deployment 생성&#x20;

   ```
   kubectl create deployment nginx --image=nginx:latest --replicas=2
   ```
3. ETCD에 업데이트된 데이터 확인&#x20;

   ```
   kubectl exec -it etcd-master-1 -n kube-system -- \
   etcdctl --key /etc/kubernetes/pki/etcd/server.key --cert /etc/kubernetes/pki/etcd/server.crt --cacert /etc/kubernetes/pki/etcd/ca.crt get / --prefix --keys-only | grep deployment
   ```
4. 위에서 생성한 Deployment 객체의 데이터 확인

   ```
   kubectl exec -it etcd-master-1 -n kube-system -- \
   etcdctl --key /etc/kubernetes/pki/etcd/server.key --cert /etc/kubernetes/pki/etcd/server.crt --cacert /etc/kubernetes/pki/etcd/ca.crt get /registry/deployments/default/nginx
   ```
5. 컨테이너 이미지 변경&#x20;

   ```
   kubectl set image deployment/nginx nginx=nginx:alpine
   ```
6. 위에서 생성한 Deployment 객체 정보를 YAML 형식으로 확인

   ```
   kubectl get deployment nginx -o yaml
   ```
7. ETCD에 업데이트된 데이터 확인

   ```
   kubectl exec -it etcd-master-1 -n kube-system -- \
   etcdctl --key /etc/kubernetes/pki/etcd/server.key --cert /etc/kubernetes/pki/etcd/server.crt --cacert /etc/kubernetes/pki/etcd/ca.crt get /registry/deployments/default/nginx
   ```
8. 새로 생성된 ReplicaSet 확인&#x20;

   ```
   kubectl get rs
   ```

## EKS Cluster &#x20;

1. eksctl 설치&#x20;

   ```
   curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
   sudo mv /tmp/eksctl /usr/local/bin
   ```
2. eksctl 버전 확인&#x20;

   ```
   eksctl version
   ```
3. ClusterConfig 생성&#x20;

   ```
   cat <<EOF > mycluster.yaml
   apiVersion: eksctl.io/v1alpha5
   kind: ClusterConfig

   metadata:
     name: mycluster
     region: ap-northeast-2
     version: "1.29"

   availabilityZones: 
   - ap-northeast-2a 
   - ap-northeast-2b
   - ap-northeast-2c
   - ap-northeast-2d

   managedNodeGroups:
   - name: nodegroup
     instanceType: t3.small
     minSize: 2
     desiredCapacity: 2
     maxSize: 5
     volumeSize: 20
     iam:
       attachPolicyARNs:
       - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
       - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
       - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
       - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
   iam:
     withOIDC: true
   EOF
   ```
4. kubeconfig 삭제&#x20;

   ```
   rm -rf ~/.kube/config
   ```
5. 현재 로그인된 IAM 자격증명 확인

   ```
   aws sts get-caller-identity
   ```
6. IAM 자격증명 설정 - <https://kubernetes.youngwjung.com/preparation/cloud9#cloud9>
7. EKS 클러스터 생성&#x20;

   ```
   eksctl create cluster --config-file=mycluster.yaml
   ```
8. Deployment 생성&#x20;

   ```
   kubectl create deployment nginx --image=nginx --replicas=3
   ```
9. 생성된 Pod 확인&#x20;

   ```
   kubectl get po -o wide
   ```
10. Service 생성&#x20;

    ```
    kubectl expose deployment nginx --port 80 --type LoadBalancer
    ```
11. 생성된 Service 확인

    ```
    kubectl get svc nginx -l
    ```
12. 생성된 ELB 주소 확인

    ```
    kubectl get svc nginx \
    -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}{"\n"}'
    ```
13. 웹브라우저에서 위에서 확인한 URL로 접속
14. EKS 콘솔에서 Control Plane Logging 활성화&#x20;
15. CloudWatch에서 로그 확인&#x20;
16. 리소스 삭제

    ```
    kubectl delete deploy nginx
    kubectl delete svc nginx
    ```
17. EKS 클러스터 삭제 (다른 실습을 계속 진행할 경우에는 클러스터를 삭제하지 않습니다)

    ```
    eksctl delete cluster --config-file=mycluster.yaml
    ```
