# 실습

해당 실습은 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
    ```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://kubernetes.youngwjung.com/overview/basics-of-kubernetes/lab.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
