# Kubernetes

### Minikube

1. EBS 볼륨 사이즈 변경&#x20;

   ```
   curl -s https://raw.githubusercontent.com/youngwjung/aws-tools/main/resize.sh \
   | bash /dev/stdin 30
   ```
2. Minikube 설치&#x20;

   ```
   {
       curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
       sudo install minikube-linux-amd64 /usr/local/bin/minikube
   }
   ```
3. 클러스터 생성&#x20;

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

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

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

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

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

   ```
   curl $(minikube service nginx --url)
   ```
9. 클러스터 삭제&#x20;

   ```
   minikube delete
   ```

### 쿠버네티스 클러스터 생성

1. 실습 환경 생성&#x20;

   ```
   {
       cd ~/environment/container-labs
       git pull
       terraform init
       terraform apply --target=module.kubernetes --auto-approve
   }
   ```
2. 인스턴스 정보 확인

   ```
   terraform show -json |\
   jq -r '.values.root_module.child_modules | .[].resources | .[] | select(.address | contains("module.kubernetes.aws_instance")) | .name + ": " + .values.public_ip'
   ```
3. SSH 비밀번호 확인&#x20;

   ```
   terraform show -json |\
   jq -r '.values.root_module.child_modules | .[].resources | .[] | select(.address == "module.kubernetes.random_password.this").values.result'
   ```
4. 새로운 터미널을 열고 첫번째 컨트롤 플레인 노드로 사용할 인스턴스로 SSH 연결

   ```
   ssh root@CP_IP_ADDRESS
   ```
5. 시스템 구동에 필요한 라이브러리 설치

   ```
   sudo apt update && sudo apt install -y \
   curl apt-transport-https vim git wget gnupg2 net-tools \
   software-properties-common lsb-release ca-certificates uidmap 
   ```
6. 컨테이너 런타임 구동에 필요한 overlay와 br\_netfilter 커널 모듈 불러오기&#x20;

   ```
   {
       cat <<EOF | sudo tee /etc/modules-load.d/kubernetes.conf
   overlay
   br_netfilter
   EOF

       sudo modprobe overlay
       sudo modprobe br_netfilter
   }
   ```
7. 컨테이너 런타임 구동에 필요한 커널 파라미터 설정

   ```
   {
       cat <<EOF | sudo tee /etc/sysctl.d/kubernetes.conf
   net.bridge.bridge-nf-call-iptables  = 1
   net.bridge.bridge-nf-call-ip6tables = 1
   net.ipv4.ip_forward                 = 1
   EOF

       sudo sysctl --system
   }
   ```
8. containerd 설치

   ```
   {
       sudo mkdir -p /etc/apt/keyrings
       curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
       echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
       sudo apt update && apt install -y containerd.io
       sudo containerd config default | tee /etc/containerd/config.toml
       sudo sed -e 's/SystemdCgroup = false/SystemdCgroup = true/g' -i /etc/containerd/config.toml
       sudo systemctl restart containerd
   }
   ```
9. 쿠버네티스 설치 및 구동에 필요한 바이너리 설치&#x20;

   ```
   {
       curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
       echo "deb  http://apt.kubernetes.io/  kubernetes-xenial  main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
       sudo apt update && sudo apt install -y kubelet=1.28.1-00 kubeadm=1.28.1-00 kubectl=1.28.1-00
   }
   ```
10. `/etc/hosts` 파일에 아래와 같은 라인 추가 - CP\_IP\_ADDRESS는 CP 노드 IP주소 &#x20;

    ```
    CP_IP_ADDRESS k8scp
    ```

    예를들어 CP의 IP주소가 123.45.67.89라면 아래처럼 입력

    ```
    123.45.67.89 k8scp
    ```
11. 클러스터 설정 파일 생성&#x20;

    ```
    cat << EOF | tee kubeadm-config.yaml
    apiVersion: kubeadm.k8s.io/v1beta3
    kind: ClusterConfiguration
    kubernetesVersion: 1.28.1
    controlPlaneEndpoint: "k8scp:6443"
    networking:
      podSubnet: 192.168.0.0/16
    EOF
    ```
12. 컨트롤 플레인 노드 구성&#x20;

    ```
    kubeadm init --config=kubeadm-config.yaml --upload-certs | tee kubeadm-init.out
    ```
13. kubeconfig 파일 복사

    ```
    {
        mkdir -p $HOME/.kube
        sudo cp /etc/kubernetes/admin.conf $HOME/.kube/config
    }
    ```
14. kubeconfig 파일 확인&#x20;

    ```
    cat ~/.kube/config
    ```
15. 실행중인 Pod 확인 &#x20;

    ```
    kubectl get pod --all-namespaces
    ```
16. Pending 상태의 Pod의 상세내용 확인

    ```
    kubectl describe pod \
    $(kubectl get pod -A --field-selector=status.phase=Pending -o=jsonpath='{.items[0].metadata.name}') \
    -n $(kubectl get pod -A --field-selector=status.phase=Pending -o=jsonpath='{.items[0].metadata.namespace}')
    ```
17. 노드 목록 확인

    ```
    kubectl get node
    ```
18. CP 노드 상태 확인

    ```
    kubectl describe node cp
    ```
19. kubelet 로그 확인

    ```
    sudo journalctl -u kubelet -n 10 --no-pager
    ```
20. CNI 플러그인 설치&#x20;

    ```
    kubectl apply -f \
    https://raw.githubusercontent.com/youngwjung/lf-training/main/LFS458/v1.28.1/SOLUTIONS/s_03/cilium-cni.yaml
    ```
21. 실행중인 Pod 확인 &#x20;

    ```
    kubectl get pod -A
    ```
22. CP 노드 상태 확인

    ```
    kubectl describe node cp
    ```
23. kubectl 명령어에 대한 bash completion 설정&#x20;

    ```
    {
        echo 'source <(kubectl completion bash)' >>~/.bashrc
        source <(kubectl completion bash)
    }
    ```
24. 새로운 터미널을 열고 워커 노드로 사용할 인스턴스로 SSH 연결&#x20;

    ```
    ssh root@WORKER_IP_ADDRESS
    ```
25. 시스템 구동에 필요한 라이브러리 설치&#x20;

    ```
    sudo apt update && sudo apt install -y \
    curl apt-transport-https vim git wget gnupg2 net-tools \
    software-properties-common lsb-release ca-certificates uidmap 
    ```
26. 컨테이너 런타임 구동에 필요한 overlay와 br\_netfilter 커널 모듈 불러오기&#x20;

    ```
    {
        cat <<EOF | sudo tee /etc/modules-load.d/kubernetes.conf
    overlay
    br_netfilter
    EOF

        sudo modprobe overlay
        sudo modprobe br_netfilter
    }
    ```
27. 컨테이너 런타임 구동에 필요한 커널 파라미터 설정

    ```
    {
        cat <<EOF | sudo tee /etc/sysctl.d/kubernetes.conf
    net.bridge.bridge-nf-call-iptables  = 1
    net.bridge.bridge-nf-call-ip6tables = 1
    net.ipv4.ip_forward                 = 1
    EOF

        sudo sysctl --system
    }
    ```
28. containerd 설치

    ```
    {
        sudo mkdir -p /etc/apt/keyrings
        curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
        echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
        sudo apt update && apt install -y containerd.io
        sudo containerd config default | tee /etc/containerd/config.toml
        sudo sed -e 's/SystemdCgroup = false/SystemdCgroup = true/g' -i /etc/containerd/config.toml
        sudo systemctl restart containerd
    }
    ```
29. 쿠버네티스 설치 및 구동에 필요한 바이너리 설치&#x20;

    ```
    {
        curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
        echo "deb  http://apt.kubernetes.io/  kubernetes-xenial  main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
        sudo apt update && sudo apt install -y kubelet=1.28.1-00 kubeadm=1.28.1-00 kubectl=1.28.1-00
    }
    ```
30. `/etc/hosts` 파일에 아래와 같은 라인 추가 - CP\_IP\_ADDRESS는 CP 노드 IP주소 &#x20;

    ```
    CP_IP_ADDRESS k8scp
    ```
31. 컨트롤 플레인 노드에 연결된 터미널로 이동&#x20;
32. Worker 노드 조인 명령어 생성&#x20;

    ```
    kubeadm token create --print-join-command --ttl 0
    ```
33. Worker 노드에 연결된 터미널로 이동해서  위의 명령어를 실행하고 나온 명령어를 실행
34. 컨트롤 플레인 노드에 연결된 터미널로 이동&#x20;
35. 노드 상태 확인&#x20;

    ```
    kubectl get no
    ```

### 샘플 애플리케이션 배포

1. Deployment 생성&#x20;

   ```
   kubectl create deployment nginx --image=nginx
   ```
2. Deployment 상태 확인&#x20;

   ```
   kubectl get deploy
   ```
3. Pod가 생성되었는지 확인

   ```
   kubectl get pod
   ```
4. 생성된 NGINX Deployment 상태 상세 확인&#x20;

   ```
   kubectl describe deployment nginx 
   ```
5. 클러스터에 발생한 이벤트 확인&#x20;

   ```
   kubectl get events  --sort-by='.metadata.creationTimestamp'
   ```
6. Deployment에 속하는 Pod 삭제

   ```
   kubectl delete pod -l app=nginx
   ```
7. Pod가 존재하는지 확인&#x20;

   ```
   kubectl get pod
   ```
8. Service 생성&#x20;

   ```
   kubectl expose deploy nginx --port 80
   ```
9. NGINX 서비스 확인 &#x20;

   ```
   kubectl get svc nginx
   ```
10. NGINX 서비스에 연결된 Endpoints 확인&#x20;

    ```
    kubectl get ep nginx
    ```
11. 실행중인 Pod의 IP 주소 확인 &#x20;

    ```
    kubectl get pod -l app=nginx -o wide
    ```
12. 서비스 엔드포인트 및 포트 확인&#x20;

    ```
    kubectl get svc nginx
    ```
13. NGINX 서비스의 ClusterIP에 HTTP 요청&#x20;

    ```
    curl $(kubectl get svc nginx -o=jsonpath='{.spec.clusterIP}')
    ```
14. NGINX 서비스에 연결된 Endpoints 주소로 HTTP 요청&#x20;

    ```
    curl $(kubectl get ep nginx -o=jsonpath='{.subsets[0].addresses[0].ip}:{.subsets[0].ports[0].port}')
    ```
15. NGINX Deployment의 Replica 갯수를 3개로 변경&#x20;

    ```
    kubectl scale deployment nginx --replicas=3
    ```
16. Pod가 추가로 생성됐는지 확인 &#x20;

    ```
    kubectl get pod -l app=nginx -o wide
    ```
17. NGINX 서비스에 연결된 Endpoints 확인  &#x20;

    ```
    kubectl get ep nginx
    ```
18. NGNIX 서비스를 NodePort 타입으로 변경&#x20;

    ```
    kubectl patch svc nginx --type='json' -p '[{"op":"replace","path":"/spec/type","value":"NodePort"}]'
    ```
19. NGINX Service 엔드포인트 및 포트 확인&#x20;

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

    ```
    echo "$(curl -s ifconfig.io):$(kubectl get svc nginx -o=jsonpath='{.spec.ports[0].nodePort}')"
    ```
21. NGINX Deployment의 Replica 갯수를 0개로 변경 &#x20;

    ```
    kubectl scale deployment nginx --replicas=0
    ```
22. 웹브라우저에서 `ANY_NODE_IP:SERVICE_PORT` 로 접속되는지 확인
23. NGINX Deployment의 Replica 갯수를 2개로 변경 &#x20;

    ```
    kubectl scale deployment nginx --replicas=2
    ```
24. 웹브라우저에서 `ANY_NODE_IP:SERVICE_PORT` 로 접속되는지 확인&#x20;
25. 리소스 삭제   &#x20;

    ```
    {
        kubectl delete deployment nginx
        kubectl delete svc nginx
    }
    ```

### 고가용성 쿠버네티스 클러스터 구성

1. HAProxy로 SSH 접속&#x20;

   ```
   ssh root@HAPROXY_IP_ADDRESS
   ```
2. HAProxy 설치&#x20;

   ```
   sudo apt update && sudo apt install -y haproxy
   ```
3. HAProxy 설정파일 `/etc/haproxy/haproxy.cfg` 에 아래의 라인들을 추가 - CP\_IP\_ADDRESS에 CP 노드의 IP 주소를 넣으세요.&#x20;

   ```
   frontend kubernetes-cp
      mode	tcp
      option tcplog
      bind *:6443
      default_backend kubernetes-cp-nodes

   backend kubernetes-cp-nodes
      mode tcp
      balance roundrobin
      server cp1 CP_IP_ADDRESS:6443 check  

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

   ```
   {
       sudo systemctl restart haproxy
       sudo systemctl status haproxy --no-pager
   }
   ```
5. CP 노드에 연결된 터미널로 이동
6. `/etc/hosts` 파일에서 k8scp에 지정된 IP주소를 HAProxy IP 주소로 변경&#x20;

   ```
   HAPROXY_IP_ADDRESS k8scp
   ```
7. Worker 노드에 연결된 터미널로 이동
8. `/etc/hosts` 파일에서 k8scp에 지정된 IP주소를 HAProxy IP 주소로 변경&#x20;

   ```
   HAPROXY_IP_ADDRESS k8scp
   ```
9. 웹 브라우저를 열고 HAPROXY\_IP\_ADDRESS:9999/stats 주소로 접속&#x20;
10. CP 노드에 연결된 터미널로 이동
11. kubectl 명령어로 API 호출&#x20;

    ```
    {
        kubectl get node
        kubectl get pod -A
    }
    ```
12. HAProxy 통계 페이지를 리프레시해서 트래픽 정보가 업데이트 되는지 확인&#x20;
13. SecondCP로 SSH 접속&#x20;

    ```
    ssh root@SECOND_CP_IP_ADDRESS
    ```
14. 시스템 구동에 필요한 라이브러리 설치

    ```
    sudo apt update && sudo apt install -y \
    curl apt-transport-https vim git wget gnupg2 net-tools \
    software-properties-common lsb-release ca-certificates uidmap
    ```
15. 컨테이너 런타임 설치&#x20;

    ```
    {
        cat <<EOF | sudo tee /etc/modules-load.d/kubernetes.conf
    overlay
    br_netfilter
    EOF

        sudp modprobe overlay
        sudo modprobe br_netfilter

        cat <<EOF | sudo tee /etc/sysctl.d/kubernetes.conf
    net.bridge.bridge-nf-call-iptables  = 1
    net.bridge.bridge-nf-call-ip6tables = 1
    net.ipv4.ip_forward                 = 1
    EOF

        sudo sysctl --system
        
        sudo mkdir -p /etc/apt/keyrings
        curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
        echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
        sudo apt update && apt install -y containerd.io
        sudo containerd config default | tee /etc/containerd/config.toml
        sudo sed -e 's/SystemdCgroup = false/SystemdCgroup = true/g' -i /etc/containerd/config.toml
        sudo systemctl restart containerd
    }
    ```
16. 쿠버네티스 설치

    ```
    {
        curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
        echo "deb  http://apt.kubernetes.io/  kubernetes-xenial  main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
        sudo apt update && apt install -y kubelet=1.28.1-00 kubeadm=1.28.1-00 kubectl=1.28.1-00
    }
    ```
17. `/etc/hosts` 파일에 아래와 같은 라인 추가 &#x20;

    ```
    HAPROXY_IP_ADDRESS k8scp
    ```
18. ThirdCP로 SSH 접속&#x20;

    ```
    ssh root@THIRD_CP_IP_ADDRESS
    ```
19. 14번부터 17번 단계를 실행&#x20;
20. CP 노드에 연결된 터미널로 이동
21. 컨트롤 플레인 조인 명령어 생성&#x20;

    ```
    echo "sudo kubeadm join k8scp:6443 --control-plane \
    --token $(sudo kubeadm token create) \
    --discovery-token-ca-cert-hash sha256:$(openssl x509 -pubkey \
    -in /etc/kubernetes/pki/ca.crt | openssl rsa \
    -pubin -outform der 2>/dev/null | openssl dgst \
    -sha256 -hex | grep -oE '[A-z0-9]+$') \
    --certificate-key $(sudo kubeadm init phase upload-certs --upload-certs| tail -1)" 
    ```
22. 위에서 생성한 명령어를 SecondCP 노드 및 ThirdCP 노드에 실행&#x20;
23. HAProxy 노드에 연결된 터미널로 이동&#x20;
24. HAProxy 설정파일 `/etc/haproxy/haproxy.cfg` 을 아래와 같이 수정&#x20;

    ```
    ...
    ...
    backend kubernetes-cp-nodes
       mode tcp
       balance roundrobin
       server cp1 CP_IP_ADDRESS:6443 check
       server cp2 SECOND_CP_IP_ADDRESS:6443 check
       server cp3 THIRD_CP_IP_ADDRESS:6443 check
    ```
25. HAProxy 데몬을 재시작하고 상태 확인&#x20;

    ```
    {
        sudo systemctl restart haproxy
        sudo systemctl status haproxy --no-pager
    }
    ```
26. 웹 브라우저를 열고 HAPROXY\_IP\_ADDRESS:9999/stats 주소로 접속해서 위에서 추가한 노드들의 연결 상태 확인&#x20;
27. CP 노드에 연결된 터미널로 이동&#x20;
28. Node 목록 확인&#x20;

    ```
    kubectl get node
    ```
29. kubectl 명령어로 몇가지 API 호출을 실행하고 HAProxy 통계사이트에서 로드가 분산되는지 확인&#x20;

    ```
    for i in {1..10}; do kubectl get pod; done
    ```

### 고가용성 테스트&#x20;

1. 실행중인 ETCD Pod 확인&#x20;

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

   ```
   kubectl -n kube-system logs etcd-secondcp | grep leader
   ```
3. 실행중인 ETCD Pod의 IP 주소 확인&#x20;

   ```
   kubectl get pod -n kube-system -l component=etcd -o wide 
   ```
4. ETCD 클러스터의 멤버 목록 확인&#x20;

   ```
   kubectl -n kube-system exec -it etcd-cp -- \
   etcdctl -w table \
   --endpoints localhost:2379 \
   --cacert /etc/kubernetes/pki/etcd/ca.crt \
   --cert /etc/kubernetes/pki/etcd/server.crt \
   --key /etc/kubernetes/pki/etcd/server.key \
   member list
   ```
5. ETCD 클러스터 멤버 목록을 환경변수로 지정&#x20;

   <pre><code><strong>{
   </strong><strong>    export ETCD_ENDPOINTS=$(kubectl -n kube-system exec -it etcd-cp -- \
   </strong>    etcdctl -w json \
       --endpoints localhost:2379 \
       --cacert /etc/kubernetes/pki/etcd/ca.crt \
       --cert /etc/kubernetes/pki/etcd/server.crt \
       --key /etc/kubernetes/pki/etcd/server.key \
       member list \
       | jq -r '.members | map(.clientURLs[]) | join(",")')
       echo $ETCD_ENDPOINTS
   }
   </code></pre>
6. ETCD 클러스터의 리더 확인&#x20;

   ```
   kubectl -n kube-system exec -it etcd-cp -- \
   etcdctl -w table \
   --endpoints $ETCD_ENDPOINTS \
   --cacert /etc/kubernetes/pki/etcd/ca.crt \
   --cert /etc/kubernetes/pki/etcd/server.crt \
   --key /etc/kubernetes/pki/etcd/server.key \
   endpoint status
   ```
7. ETCD 클러스터의 각 멤버별 상태 확인&#x20;

   ```
   kubectl -n kube-system exec -it etcd-cp -- \
   etcdctl -w table \
   --endpoints $ETCD_ENDPOINTS \
   --cacert /etc/kubernetes/pki/etcd/ca.crt \
   --cert /etc/kubernetes/pki/etcd/server.crt \
   --key /etc/kubernetes/pki/etcd/server.key \
   endpoint health
   ```
8. ETCD 클러스터의 리더 Pod가 배포된 노드에 가서 kubelet 및 컨테이너 런타임 정지- CP 노드의 ETCD가 가장 먼저 구성되었기 때문에 일반적으로 CP 노드에 배포된 ETCD가 리더

   ```
   {
       sudo systemctl stop kubelet
       sudo crictl --runtime-endpoint=unix:///run/containerd/containerd.sock \
       stop $(sudo crictl --runtime-endpoint=unix:///run/containerd/containerd.sock ps -q)
       sudo systemctl stop containerd.service
   }
   ```
9. ETCD Pod 로그 확인&#x20;

   ```
   kubectl -n kube-system logs etcd-secondcp | grep leader
   ```
10. 웹 브라우저를 열고 HAPROXY\_IP\_ADDRESS:9999/stats 주소로 접속해서 위에서 노드들의 연결 상태 확인&#x20;
11. ETCD 클러스터의 리더가 변경되었는지 확인&#x20;

    ```
    kubectl -n kube-system exec -it etcd-secondcp -- \
    etcdctl -w table \
    --endpoints $ETCD_ENDPOINTS \
    --cacert /etc/kubernetes/pki/etcd/ca.crt \
    --cert /etc/kubernetes/pki/etcd/server.crt \
    --key /etc/kubernetes/pki/etcd/server.key \
    endpoint status
    ```
12. ETCD 클러스터 각 멤버별 상태 확인&#x20;

    ```
    kubectl -n kube-system exec -it etcd-secondcp -- \
    etcdctl -w table \
    --endpoints $ETCD_ENDPOINTS \
    --cacert /etc/kubernetes/pki/etcd/ca.crt \
    --cert /etc/kubernetes/pki/etcd/server.crt \
    --key /etc/kubernetes/pki/etcd/server.key \
    endpoint health
    ```
13. Node 상태 확인

    ```
    kubectl get node
    ```
14. CP 노드에서 kubelet 및 컨테이너 런타임을 재실행 &#x20;

    ```
    {
        sudo systemctl start containerd.service
        sudo systemctl start kubelet
    }
    ```
15. 웹 브라우저를 열고 HAPROXY\_IP\_ADDRESS:9999/stats 주소로 접속해서 위에서 노드들의 연결 상태 확인&#x20;
16. 노드 상태 확인

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

    ```
    kubectl get pod -A -o wide
    ```
18. ETCD 클러스터의 리더가 다시 변경되었는지 확인&#x20;

    ```
    kubectl -n kube-system exec -it etcd-secondcp -- \
    etcdctl -w table \
    --endpoints $ETCD_ENDPOINTS \
    --cacert /etc/kubernetes/pki/etcd/ca.crt \
    --cert /etc/kubernetes/pki/etcd/server.crt \
    --key /etc/kubernetes/pki/etcd/server.key \
    endpoint status
    ```
19. ETCD 클러스터 각 멤버별 상태 확인&#x20;

    ```
    kubectl -n kube-system exec -it etcd-secondcp -- \
    etcdctl -w table \
    --endpoints $ETCD_ENDPOINTS \
    --cacert /etc/kubernetes/pki/etcd/ca.crt \
    --cert /etc/kubernetes/pki/etcd/server.crt \
    --key /etc/kubernetes/pki/etcd/server.key \
    endpoint health
    ```
20. Cloud9에 연결된 터미널로 이동해서 리소스 삭제&#x20;

    ```
    {
        cd ~/environment/container-labs
        terraform destroy --target=module.kubernetes --auto-approve
    }
    ```

<figure><img src="https://2043625433-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F06pWQbCGLce88KEHHrxI%2Fuploads%2FLXw7BcNYTZ7FlGUnqlas%2Fimage.png?alt=media&#x26;token=ed38d329-0d9c-49c1-9f85-c85dbb161ee9" alt=""><figcaption></figcaption></figure>

### Amazon EKS

1. eksctl 설치&#x20;

   ```
   {
       cd ~/environment
       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. 현재 로그인된 IAM 자격증명 확인

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

   ```
   eksctl create cluster \
   --name mycluster \
   --nodes-min=2 \
   --nodes-max=5 \
   --region ap-northeast-2
   ```
6. kubectl 설치&#x20;

   ```
   {
       curl -LO "https://dl.k8s.io/release/v1.27.1/bin/linux/amd64/kubectl"
       sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
       echo 'source <(kubectl completion bash)' >>~/.bashrc
       source <(kubectl completion bash)
   }
   ```
7. Node 목록 확인&#x20;

   ```
   kubectl get node
   ```
8. 쿠버네티스 클러스터 버전 확인&#x20;

   ```
   kubectl version --short
   ```
9. Deployment 생성&#x20;

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

    ```
    kubectl get po
    ```
11. Service 생성&#x20;

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

    ```
    kubectl get svc nginx
    ```
13. 생성된 ELB 주소 확인

    ```
    kubectl get svc nginx \
    -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}{"\n"}'
    ```
14. 웹브라우저에서 위에서 확인한 URL로 접속
15. 리소스 삭제

    ```
    {
        kubectl delete deploy nginx
        kubectl delete svc nginx
    }
    ```
16. 데모 애플리케이션 배포 - <https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/#run-and-expose-php-apache-server>

    ```
    cat <<EOF | kubectl apply -f -
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: php-apache
    spec:
      selector:
        matchLabels:
          app: php-apache
      replicas: 1
      template:
        metadata:
          labels:
            app: php-apache
        spec:
          containers:
          - name: php-apache
            image: k8s.gcr.io/hpa-example
            ports:
            - containerPort: 80
            resources:
              limits:
                cpu: 2
              requests:
                cpu: 1
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: php-apache
      labels:
        app: php-apache
    spec:
      ports:
      - port: 80
      selector:
        app: php-apache
    EOF
    ```
17. Pod의 리소스 사용량 확인

    ```
    kubectl top pod -l app=php-apache
    ```
18. Metrics Server 설치 - <https://github.com/kubernetes-sigs/metrics-server#kubernetes-metrics-server>

    ```
    kubectl apply -f \
    https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
    ```
19. Pod의 리소스 사용량 확인

    ```
    kubectl top pod -l app=php-apache
    ```
20. 데모 애플리케이션에 부하를 발생시키는 Pod 생성

    ```
    kubectl create deploy load-generator \
    --image=busybox:1.28 \
    --replicas=10 \
    -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"
    ```
21. Pod의 리소스 사용량 확인

    ```
    kubectl top pod -l app=php-apache
    ```
22. HPA 생성&#x20;

    ```
    kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=5
    ```
23. 위에서 생성한 HPA 상태 확인&#x20;

    ```
    kubectl get hpa php-apache
    ```
24. HPA 상태 모니터링

    ```
    kubectl get hpa php-apache -w
    ```
25. Ctrl+C를 입력해서 HPA 모니터링을 중지하고 Pod가 생성되었는지 확인&#x20;

    ```
    kubectl get pod -l app=php-apache
    ```
26. Pod의 리소스 사용량 확인&#x20;

    ```
    kubectl top pod -l app=php-apache
    ```
27. Pending 상태의 Pod가 있다면 아래의 명령어를 통해서 그 이유를 확인

    ```
    kubectl describe pod \
    $(kubectl get pod -o=jsonpath='{.items[?(@.status.phase=="Pending")].metadata.name}')
    ```
28. Cluster Autoscaler 설치

    ```
    {
        export CLUSTER_NAME=$(kubectl get node \
        -o=jsonpath='{.items[0].metadata.labels.alpha\.eksctl\.io\/cluster-name}')
        export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
        export ASG_NAME=$(aws autoscaling describe-auto-scaling-groups --query \
        "AutoScalingGroups[? Tags[? (Key=='eks:cluster-name') && Value=='$CLUSTER_NAME']].AutoScalingGroupName" --output text)    
        
        eksctl utils associate-iam-oidc-provider --region=ap-northeast-2 \
        --cluster=$CLUSTER_NAME --approve
        
        eksctl create iamserviceaccount \
        --cluster=$CLUSTER_NAME \
        --namespace=kube-system \
        --name=cluster-autoscaler \
        --attach-policy-arn=arn:aws:iam::aws:policy/AmazonEC2FullAccess \
        --override-existing-serviceaccounts \
        --approve \
        --region ap-northeast-2
        
        kubectl apply -f \
        https://raw.githubusercontent.com/kubernetes/autoscaler/master/cluster-autoscaler/cloudprovider/aws/examples/cluster-autoscaler-autodiscover.yaml
        
        kubectl -n kube-system patch deployment cluster-autoscaler --type=json \
        -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/command", "value": [
        "./cluster-autoscaler",
        "--v=4",
        "--stderrthreshold=info",
        "--cloud-provider=aws",
        "--skip-nodes-with-local-storage=false",
        "--expander=least-waste",
        "--node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/'${CLUSTER_NAME}'",
        "--balance-similar-node-groups",
        "--skip-nodes-with-system-pods=false"
        ]}]'
    }
    ```
29. Cluster Autoscaler 로그 확인

    ```
    kubectl -n kube-system logs deploy/cluster-autoscaler
    ```
30. Pending 상태였던 Pod가 생성 되었는지 확인

    ```
    kubectl get pod -l app=php-apache
    ```
31. Node 갯수 확인

    ```
    kubectl get node
    ```
32. Pod의 리소스 사용량 확인&#x20;

    ```
    kubectl top pod -l app=php-apache
    ```
33. 데모 애플리케이션에 부하를 발생시키는 Pod 삭제

    ```
    kubectl delete deploy load-generator
    ```
34. Pod의 리소스 사용량 확인&#x20;

    ```
    kubectl top pod -l app=php-apache
    ```
35. HPA 상태 확인&#x20;

    ```
    kubectl get hpa php-apache
    ```
36. HPA 상세 내용 확인

    ```
    kubectl describe hpa php-apache
    ```
37. 데모 애플리케이션의 복제본 갯수는 1개로 강제 지정&#x20;

    ```
    kubectl scale deployment php-apache --replicas=1
    ```
38. Pod가 삭제 되었는지 확인&#x20;

    ```
    kubectl get pod -l app=php-apache
    ```
39. 데모 애플리케이션 삭제&#x20;

    ```
    kubectl delete deploy php-apache
    ```
40. Pod가 삭제 되었는지 확인&#x20;

    ```
    kubectl get pod -l app=php-apache
    ```
41. Node가 삭제 되는지 확인

    ```
    kubectl get node
    ```
42. Cluster Autoscaler 로그 확인

    ```
    kubectl -n kube-system logs deploy/cluster-autoscaler
    ```
43. EKS 클러스터 삭제

    ```
    eksctl delete cluster --name mycluster --region ap-northeast-2
    ```
