# 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
    ```


---

# 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://container.youngwjung.com/kubernetes.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.
