EKS 스터디 1주차

Dongmin Han·2023년 4월 27일
2

EKS-STUDY

목록 보기
1/7
post-thumbnail

참여 계기

현재 데브옵스 신입 엔지니어로 회사에서 업무를 진행하는 중이지만, 쿠버네티스 환경에 대한 부족한 실력으로 어려움이 많았다. CKA 자격증을 통해 쿠버네티스 공부를 시작했지만, 실무에 대한 부족함을 느끼던 와중에 회사 동료에게 추천을 받아 CloudNet 팀에서 주관하는 EKS 스터디에 지원했다. 스터디는 1시간 30분가량 가시다님의 강의와 두 분의 경험발표로 구성되었다. 아직 신입 엔지니어이기에 잘 따라가지 못할까 걱정스럽지만 퀄리티 높은 자료와 스터디원분들이기에 배울 것이 많아보여 설렌다.

요약

매번 시작해야지 생각만 했던 블로그를 시작해본다. .! 부족한 점이 많지만 앞으로 수정하며 수준을 높이려 한다. 전체적으로 스터디 내용을 기반으로 정리했고, 쿠버네티스에 대해 부족한 것이 많아 중간중간 기본적인 내용도 추가적으로 정리했다. 1주차의 주제는 Amzaon EKS 설치 및 기본 사용이다. 사전에 제공해주신 AWS CloudFormation을 통해 초기인프라를 형성하고 eksctl 을 통해 클러스터를 배포한다. 배포 후 클러스터에 접근하여 여러 명령어를 통해 시스템을 이해해보며 마무리 되었다.

포스트는 스터디와 같은 순서로 진행된다. 먼저, 아키텍처를 살펴보고 실습을 진행한다.

EKS 아키텍처

먼저, EKS는 Amazon Elastic Kubernetes Service 의 약어이며 AWS에서 제공해주는 관리형 쿠버네티스 서비스이다. 뇌의 역할을 하는 컨트롤 플레인을 자동으로 관리해주고 다른 AWS 서비스와 통합하여 활용가능하다. 편하지만, 금액적으로는 부담스럽다. 상황에 맞게 서비스를 선택해서 이용하면 된다. FinOps의 중요성도 점점 커지는 것 같다. 1주차 경험발표도 관련 사례에 대해 소개해주셨는데, 최적화에 따른 연간 절약 금액이 어마어마했다.

이제 EKS에 아키텍처에 대해 알아보자. 아래의 그림은 EKS의 아키텍처 그림이다.

아키텍처에서 가장 중요한 점은 컨트롤 플레인이다. EKS에서는 AWS가 요소를 직접 관리해준다. ENI를 통해 노드와 API 서버는 통신한다. 위에 그림에서는 클러스터 엔드포인트가 퍼블릭이지만, 제약사항에 따라 프라이빗하게 접근하도록 설정할 수 있다. 실제 프로덕션에서는 아래의 그림과 같이 주로 ENI를 통해 프라이빗 환경에서 통신한다.

실습

실습 아키텍처는 아래와 같다. 비용을 고려해 최소한의 사양으로 준비해주셨다. CloudFormation 을 통해
작업용 EC2를 만든 후 접속하여 EKS를 배포한다.

EKS 배포는 웹 관리 콘솔, eksctl, IaC(CDK, CloudFormation, Terraform ..) 등이 있지만, EKS에서 K8S 클러스터를 생성하고 관리하기 위한 간단한 유틸리티 CLI 도구인 eksctl을 사용했다.

배포

CloudFormation Stack의 출력값으로 EC2의 퍼블릭 아이피를 확인한 후 접속한다. 접속하고 aws configure로 기본적인 인증절차를 거친다.

아래는 작업용 ec2에서 eksctl을 통해 EKS를 배포하는 소스코드이다. 배포하는 데 약 10분정도의 시간이 필요하다.

$eksctl create cluster --name $CLUSTER_NAME --region=$AWS_DEFAULT_REGION --nodegroup-name=$CLUSTER_NAME-nodegroup --node-type=t3.medium \
--node-volume-size=30 --vpc-public-subnets "$PubSubnet1,$PubSubnet2" --version 1.24 --ssh-access --external-dns-access --verbose 4**
...
2023-04-27 21:57:09 []  will create 2 separate CloudFormation stacks for cluster itself and the initial managed nodegroup
2023-04-27 21:57:09 []  if you encounter any issues, check CloudFormation console or try 'eksctl utils describe-stacks --region=ap-northeast-2 --cluster=myeks'
2023-04-27 21:57:09 []  Kubernetes API endpoint access will use default of {publicAccess=true, privateAccess=false} for cluster "myeks" in "ap-northeast-2"
2023-04-27 21:57:09 []  CloudWatch logging will not be enabled for cluster "myeks" in "ap-northeast-2"
2023-04-27 21:57:09 []  you can enable it with 'eksctl utils update-cluster-logging --enable-types={SPECIFY-YOUR-LOG-TYPES-HERE (e.g. all)} --region=ap-northeast-2 --cluster=myeks'
2023-04-27 21:57:09 []
2 sequential tasks: { create cluster control plane "myeks",
    2 sequential sub-tasks: {
        wait for control plane to become ready,
        create managed nodegroup "myeks-nodegroup",
    }
}

배포가 완료되면 아래의 그림과 같이 AWS 콘솔을 통해 쿠버네티스 버전, 엔드포인트 등 상태를 확인하여 클러스터가 정상적으로 배포되었는 지 확인할 수 있다.

만약 아래의 그림과 같이 콘솔에서 EKS 리소스를 보는 것이 제한된다면 User 계정으로 로그인하여 문제를 해결할 수 있다. 자세한 내용은Docs에서 확인할 수 있다.

나는 chatgpt, 구글링에서 먼저 확인한 configmap 에 아래와 같이 Users를 추가했지만 변화는 없었다. 이후 스터디에서 제공해주신 포스팅의 계정이 다르면 관리자 계정이 있어도 확인할 수 없다는 내용을 보고, iam user 계정으로 로그인했고 정상적으로 EKS를 확인할 수 있었다.
(아래는 IAM USER: EKS-Study로 로그인했을 때 확인한 모습이다.)

EKS 알아보기

이제 배포된 EKS에 접근하여 여러 명령어를 실행하며 EKS에 대해 더 알아보자.
먼저, 클러스터 엔드포인트를 확인한다. 클러스터 엔드포인트의 끝을 확인하면 AWS에서 관리해주는 컨트롤 플래인의 API 서버의 퍼블릭 아이피를 확인할 수 있다. 이후 노드에 접근해서 통신상태를 확인해보면 kubelet과 kubeproxy가 api server와 통신하는 것이 확인된다.

  • 클러스터 엔드포인트 확인
#클러스터 엔드포인트 확인
$aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint
https://50E14FE698DE0E5CA2055F72AB086163.gr7.ap-northeast-2.eks.amazonaws.com
APIDNS=$(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint | cut -d '/' -f 3)
# dig 명령어를 통해 DNS 서버 조회
$dig +short $APIDNS
3.38.85.93
3.34.237.160
# 노드의 통신
## node ip(52.78.98.82) 해당 파드의 ip
ESTAB 0      0       192.168.1.23:32816 52.95.195.109:443   users:(("ssm-agent-worke",pid=2453,fd=15))
## control plane ip
ESTAB 0      0       192.168.1.23:39834    3.38.85.93:443   users:(("kube-proxy",pid=3104,fd=11))
## node ip
ESTAB 0      0       192.168.1.23:47340  52.95.194.61:443   users:(("ssm-agent-worke",pid=2453,fd=10))
## node ip
ESTAB 0      0       192.168.1.23:42598    10.100.0.1:443   users:(("aws-k8s-agent",pid=3426,fd=7))
## 작업용 ec2 private ip (현재 작업용 ec2에서 ssh 통신 중)
ESTAB 0      56      192.168.1.23:22    192.168.1.100:53084 users:(("sshd",pid=13342,fd=3),("sshd",pid=13310,fd=3))
## control plane ip
ESTAB 0      0       192.168.1.23:37022  3.34.237.160:443   users:(("kubelet",pid=2842,fd=39))

이제 보안 그룹을 확인해보자. 아래의 코드를 보면 아웃바운드 트래픽은 모두 허용하고, 인바운드 트래픽은 그룹 내 트래픽에 대해 허용하는 것을 알 수 있다.

$aws ec2 describe-security-groups --group-ids sg-0866ebfa10533a0b9 --output yaml | yh
SecurityGroups:
- Description: EKS created security group applied to ENI that is attached to EKS Control
    Plane master nodes, as well as any managed workloads.
  GroupId: sg-0866ebfa10533a0b9
  GroupName: eks-cluster-sg-myeks-104368993
  IpPermissions:
  - IpProtocol: '-1'
    IpRanges: []
    Ipv6Ranges: []
    PrefixListIds: []
    UserIdGroupPairs:
    - GroupId: sg-0866ebfa10533a0b9
      UserId: '871103481195'
    - Description: Allow unmanaged nodes to communicate with control plane (all ports)
      GroupId: sg-07536909f8ca01eee
      UserId: '871103481195'
  IpPermissionsEgress:
  - IpProtocol: '-1'
    IpRanges:
    - CidrIp: 0.0.0.0/0
    Ipv6Ranges: []
    PrefixListIds: []
    UserIdGroupPairs: []
  OwnerId: '871103481195'
  ...

이제 배포된 파드를 살펴보자, AWS에서 컨트롤 플레인을 관리하니 우리가 접근할 수 있는 파드는 워커노드에만 존재한다.
또 다른 특이점은 daemonset으로 aws-node가 존재한다. 이것은 모든 노드에 필수적인 네트워크 요소를 설치하기 위해 생성된다. 자세한 내용은 Docs에서 확인할 수 있다.

$k get po -A -o wide
NAMESPACE     NAME                      READY   STATUS    RESTARTS   AGE   IP              NODE                                               NOMINATED NODE   READINESS GATES
kube-system   aws-node-9bfxp            1/1     Running   0          83m   192.168.1.93    ip-192-168-1-93.ap-northeast-2.compute.internal    <none>           <none>
kube-system   aws-node-wp867            1/1     Running   0          83m   192.168.2.247   ip-192-168-2-247.ap-northeast-2.compute.internal   <none>           <none>
kube-system   coredns-dc4979556-n769l   1/1     Running   0          90m   192.168.1.201   ip-192-168-1-93.ap-northeast-2.compute.internal    <none>           <none>
kube-system   coredns-dc4979556-xtmxc   1/1     Running   0          90m   192.168.1.253   ip-192-168-1-93.ap-northeast-2.compute.internal    <none>           <none>
kube-system   kube-proxy-dbfpz          1/1     Running   0          83m   192.168.2.247   ip-192-168-2-247.ap-northeast-2.compute.internal   <none>           <none>
kube-system   kube-proxy-s44d9          1/1     Running   0          83m   192.168.1.93    ip-192-168-1-93.ap-northeast-2.compute.internal    <none>           <none>
#아래는 데몬셋을 확인하는 명령어다.
$k get ds -A
NAMESPACE     NAME         DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
kube-system   aws-node     2         2         2       2            2           <none>          124m
kube-system   kube-proxy   2         2         2       2            2           <none>          124m

이제, 선언형을 알아보기 위해 파드를 3개 생성하는 디플로이를 배포한다. 파드를 증가시키고 감소시키는 명령어를 실행시키면서 모니터링을 통해 실제 동작을 확인한다.

$kubectl create deployment my-webs --image=gcr.io/google-samples/kubernetes-bootcamp:v1 --replicas=3
deployment.apps/my-webs created
$kubectl get pod -w
NAME                     READY   STATUS    RESTARTS   AGE
my-webs-8dd6b4db-8ddbz   1/1     Running   0          3s
my-webs-8dd6b4db-kwgts   1/1     Running   0          3s
my-webs-8dd6b4db-xfdbl   1/1     Running   0          3s

아래의 그림은 강제로 파드를 삭제했을 때 나오는 결과이다. 강제로 삭제해서 파드가 일부 삭제되었지만, 이후 다시 재생성되어 파드의 수는 유지가 된다. 쿠버네티스에서는 현재의 상태와 요구되는 상태를 계속 비교하여 요구되는 상태로 지속적으로 노력하기에 그렇다.

이제 관리형 노드를 추가 및 삭제해보는 실습을 진행해봤다.

#아래는 노드의 상태를 확인하기 위해 모니터링 코드
while true; do aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text ; echo "------------------------------" ; sleep 1; done
myeks-myeks-nodegroup-Node	192.168.2.247	3.34.130.220	running
myeks-host	192.168.1.100	43.201.60.122	running
myeks-myeks-nodegroup-Node	192.168.1.93	13.124.119.49	running
------------------------------
myeks-myeks-nodegroup-Node	192.168.2.247	3.34.130.220	running
myeks-host	192.168.1.100	43.201.60.122	running
myeks-myeks-nodegroup-Node	192.168.1.93	13.124.119.49	running
...
# 노드 개수 증가
$eksctl scale nodegroup --cluster $CLUSTER_NAME --name $CLUSTER_NAME-nodegroup --nodes 3 --nodes-min 3 --nodes-max 6
2023-04-28 00:16:29 []  scaling nodegroup "myeks-nodegroup" in cluster myeks
2023-04-28 00:16:30 []  initiated scaling of nodegroup
2023-04-28 00:16:30 []  to see the status of the scaling run `eksctl get nodegroup --cluster myeks --region ap-northeast-2 --name myeks-nodegroup
# 모니터링에서도 노드의 증가가 확인된다.
myeks-myeks-nodegroup-Node	192.168.2.247	3.34.130.220	running
myeks-host	192.168.1.100	43.201.60.122	running
myeks-myeks-nodegroup-Node	192.168.1.93	13.124.119.49	running
myeks-myeks-nodegroup-Node	192.168.1.188	3.36.51.90	running
# 노드 개수 감소
$aws eks update-nodegroup-config --cluster-name $CLUSTER_NAME --nodegroup-name $CLUSTER_NAME-nodegroup --scaling-config minSize=2,maxSize=2,desiredSize=2

순서가 조금 다르지만, 마리오 게임에 대한 배포를 진행해봤다. 배포 yaml 파일을 확인하면 준비해주신 마리오 이미지를 사용하여 하나의 파드를 배포하고, 서비스를 같이 배포하여 외부에서 접근가능하도록 파드를 노출시킨다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mario
  labels:
    app: mario
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mario
  template:
    metadata:
      labels:
        app: mario
    spec:
      containers:
      - name: mario
        image: pengbai/docker-supermario
---
apiVersion: v1
kind: Service
metadata:
   name: mario
spec:
  selector:
    app: mario
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080

k create -f mario.yaml 명령어를 통해 배포를 수행하고, 서비스에 IP를 통해 사이트에 접근하면
마리오 게임을 확인할 수 있다.!

ECR 사용해보기

ECR을 이용해서 컨테이너 이미지를 관리해보는 실습을 진행했는 데, 작업은 간단하다.
docker 로그인을 진행하고 ecr-public에 하나의 리포지토리를 만든 후 docker push 명령어를 통해 이미지를 추가하면 된다.
관련된 소스코드는 아래와 같다.

#ecr login
$aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
$cat /root/.docker/config.json | jq
{
  "auths": {
    "public.ecr.aws": {
      "auth": "QVdTOm...VFY5"
    }
  }
}
aws ecr-public describe-registries --region us-east-1 | jq

{
  "registries": [
    {
      "registryId": "1234567890",
      "registryArn": "arn:aws:ecr-public::1234567890:registry/1234567890",
      "registryUri": "public.ecr.aws/~~",
      "verified": false,
      "aliases": [
        {
          "name": "~~",
          "status": "ACTIVE",
          "primaryRegistryAlias": true,
          "defaultRegistryAlias": true
        }
      ]
    }
  ]
}
aws ecr-public create-repository --repository-name $NICKNAME/nginx --region us-east-1
{
    "repository": {
        "repositoryArn": "arn:aws:ecr-public::1234567890:repository/dongmin/nginx",
        "registryId": "1234567890",
        "repositoryName": "dongmin/nginx",
        "repositoryUri": "public.ecr.aws/~~/dongmin/nginx",
        "createdAt": "2023-05-03T00:29:28.487000+09:00"
    },
    "catalogData": {}
}
public.ecr.aws/g3q7n2p4/dongmin/nginx


$docker push $REPOURI:latest
The push refers to repository [public.ecr.aws/~~/dongmin/nginx]

31531248c7cb: Pushed
f9cb3f1f1d3d: Pushed
f0fb842dea41: Pushed
c1cd5c8c68ef: Pushed
1d54586a1706: Pushed
1003ff723696: Pushed
f1417ff83b31: Pushed
latest: digest: sha256:01ccf4035840dd6c25042b2b5f6b09dd265b4ed5aa7b93ccc4714027c0ce5685 size: 1781
kubectl run mynginx --image $REPOURI
pod/mynginx created

콘솔에서 확인해봐도 정상적으로 이미지가 업로드된 것을 확인할 수 있다.

엔드포인트 변경

아래는 엔드포인트를 퍼블릭에서 public & private 로 변경한 모습이다. 액세스 소스 허용목록이 작업용 ec2의 public ip로만 변경되었다.!

이제 public & private 에서 private로 변경해봤다.

$echo $APIDNS
7955229C1055798D3183C30048A1A1FA.gr7.ap-northeast-2.eks.amazonaws.com
$dig +short $APIDNS
192.168.1.143
192.168.2.246
### 이전의 결과값은
3.38.85.93
3.34.237.160

public Ip를 주는 것이 아닌 private 아이피를 돌려준다. 외부를 통해 API서버로 접근하는 것이 아닌 VPC 내부에서만 컨트롤 플래인의 접근이 가능하다. 아래의 아키텍처로 구현됨을 확인할 수 있었다.

스터디 중에 진행한 실습은 이렇게 마무리 되었다. 아래에는 추가적으로 진행한 실습 및 자료이다.

추가 정리

EKS Workshop

Pod Affinity and Anti-Affinity

nodeselector: 라벨(key - value)을 통해 스케줄링을 지정할 수 있다. (선호도기능은 하지 못한다.)

  • nodeaffinity : 특정 노드에 스케줄링되도록 유도한다.(특정 노드 배치 제안)
    • requiredDuringSchedulingIgnoredDuringExecution : 해당 규칙이 만족되야, 파드를 스케줄링하며 규칙이 만족되지 않으면 스케줄링할 수 없다.
    • preferredDuringSchedulingIgnoredDuringExecution : 해당 조건을 만족하는 노드를 찾으려고 노력한다. 조건에 맞는 노드가 없으면 일반적으로 스케줄링 된다.
    • Available(조건 만족) : 스케줄링할 때만 규정을 지킨다.
      • requiredDuringSchedulingIgnoredDuringExecution : 해당 조건이 아니면, 스케줄링 불가능하다.
      • preferredDuringSchedulingIgnoredDuringExecution : 조건을 선호, 조건에 부합하는 노드가 없어도 가능하다.
    • Planned(선호도) : 실행하면서도 규정을 지킴
      • requiredDuringSchedulingRequiredDuringExecution
      • preferredDuringSchedulingRequiredDuringExecution
    • 연산자(operator)
      • In : 조건에 맞는 노드에 배치
      • NotIn : 조건과 다른 노드에 배치
      • Exists : 조건이 있는 노드에 배치

Taints

  • Taint : 해당 노드에 Taint가 있기에, Taint를 상쇄하는 Toleration 이 없으면 해당 노드에 배치될 수 없다.
  • 기본 문법 : kubectl taint nodes <node-name> key=value:taint-effect
    • ex) kubectl taint nodes node1 key1=value2:NoSchedule
    • effect는 아래의 3가지 가능하다.
      • NoSchedule
      • PreferNoSchedule
      • NoExecute

Kubernetes Tools

많은 플로그인이 개발되어 활용되고 있다. kubectl krew 는 쿠버네티스트 cli 도구 kubect의 플로그인을 관리하는 패키지 매니저이다. krew를 통해 손쉽게 k8s 관련 플로그인을 설치할 수 있다. 폐쇄망과 같은 제약조건이 있을 때는 krew가 아닌 수동으로 설치한다.
스터디에서는 사전에 준비해주셔서 대부분 설치되어있다.

# krew
##intsall
(
  set -x; cd "$(mktemp -d)" &&
  OS="$(uname | tr '[:upper:]' '[:lower:]')" &&
  ARCH="$(uname -m | sed -e 's/x86_64/amd64/' -e 's/\(arm\)\(64\)\?.*/\1\2/' -e 's/aarch64$/arm64/')" &&
  KREW="krew-${OS}_${ARCH}" &&
  curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/${KREW}.tar.gz" &&
  tar zxvf "${KREW}.tar.gz" &&
  ./"${KREW}" install krew
)
##환경변수 적용
export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"
### bash, /etc/profile 에도 업데이트하여 일치시키면 된다.
**echo "export PATH=**${KREW_ROOT:-$HOME/.krew}/bin:$PATH**" >> /etc/profile

# 플러그인 설치
$kubectl krew install ctx
$kubectl krew install ns**

하단의 krew를 통해 대표적인 2가지 플러그인을 설치한다. 먼저, Kubectx는 kubeconfig로 연동되어 있는 context 목록을 확인할 수 있다. kubens는 현재 context의 네임스페이스를 확인할 수 있다.

kubectx
kubectx [context_name] : 특정 context로 변경
-c : current context
-d : context 삭제
-: 이전 context로 복구

kubens
kubens [NAMESPACE_NAME] : 특정 ns로 변경
-c: current ns
- :이전 name space로 복구

# kubectx 활용
**$kubectl config get-contexts
CURRENT   NAME                                                          CLUSTER                                      AUTHINFO                                                      NAMESPACE
          eks-default                                                   NRSON-EKS-CLUSTER.ap-northeast-2.eksctl.io   iam-root-account@NRSON-EKS-CLUSTER.ap-northeast-2.eksctl.io   kube-system
*         iam-root-account@NRSON-EKS-CLUSTER.ap-northeast-2.eksctl.io   NRSON-EKS-CLUSTER.ap-northeast-2.eksctl.io   iam-root-account@NRSON-EKS-CLUSTER.ap-northeast-2.eksctl.io   kube-system
          minikube
$kubectx
eks-default
iam-root-account@NRSON-EKS-CLUSTER.ap-northeast-2.eksctl.io
minikube
$kubectx -c
iam-root-account@NRSON-EKS-CLUSTER.ap-northeast-2.eksctl.io
$kubectx minikube
Switched to context "minikube".
$kubectx -c
minikube**

# kubens 활용
$k ns
default
kube-node-lease
kube-public
kube-system
$k ns kube-public
Context "EKS-study@KANE.ap-northeast-2.eksctl.io" modified.
Active namespace is "kube-public".
$k ns
default
kube-node-lease
kube-public
kube-system
****

kube_ps1(prompt output)

CurrentContext / CurrentNamespace를 표시하는 도구이다.

#install
git clone https://github.com/jonmosco/kube-ps1.git
#.bashrc 에 추가
---
KUBE_PS1_SYMBOL_ENABLE=false
KUBE_PS1_SYMBOL_COLOR=null
KUBE_PS1_CTX_COLOR=null
KUBE_PS1_NS_COLOR=null
---
#아래는 context의 이름을 변경하여 구분하는 것이다.
#아래와 같이 변경시 확연하게 구분할 수 있다.
$cat ~/.kube/config
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1ekNDQWMrZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeU1ETXdOVEU1TURNd00xb1hEVE15...y80ZHM2CnpablQyZmNCQmszNHFGUTNGS1Q1WE5pbXZoQlRidHZucUx4TQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    server: https://407B39524D80486F1EECD325C3180677.yl4.ap-northeast-2.eks.amazonaws.com
  name: NRSON-EKS-CLUSTER.ap-northeast-2.eksctl.io
contexts:
- context:
    cluster: NRSON-EKS-CLUSTER.ap-northeast-2.eksctl.io
    namespace: kube-system
    user: iam-root-account@NRSON-EKS-CLUSTER.ap-northeast-2.eksctl.io
  name: eks-default
- context:
    cluster: NRSON-EKS-CLUSTER.ap-northeast-2.eksctl.io
    namespace: default
    user: iam-root-account@NRSON-EKS-CLUSTER.ap-northeast-2.eksctl.io
  name: kube	=================> kubeapp으로 변경
current-context: kube
kind: Config
preferences: {}
users:

유지보수관련 플러그인(모두 krew를 통해 설치 가능하다.)

해당 블로그를 참고해여 작성함.

  • neat : manifests 정돈에 좋다.
    • -o yaml 으로 확인하면 관련된 상태들까지 출력이 되 보기가 불편하다.
    • ex) kubectl get deployment my-nginx -o yaml | kubectl neat
  • kail : multi pod log 모니터링 별도로 옵션을 주지 않을 경우 클러스터 내 모든 파드를 대상으로 한다. 범위를 좁히기 위해선 아래의 옵션이 있다.
    $kail
    kube-logging/elasticsearch-master-745c995d88-ksldq[elasticsearch-master]: {"type": "server", "timestamp": "2022-03-07T15:41:50,374+0000", "level": "INFO", "component": "o.e.c.s.ClusterApplierService", "cluster.name": "elasticsearch", "node.name": "elasticsearch-master", "cluster.uuid": "w4yuNKxZRi2BxpDgrM37eg", "node.id": "4D8M6FE7Tsqmml7IaddNww",  "message": "added {{elasticsearch-client}{tHAltQHwSK-JAbfVGY-lTw}{DvjfXlbHQiubOqm2HdNCkw}{192.168.161.189}{192.168.161.189:9300}{i}{ml.machine_memory=8124866560, ml.max_open_jobs=20, xpack.installed=true},{elasticsearch-data}{lykb7kBAR5SvmTuSFs_O-g}{cgBjsrwIRWuIs2Ysf6kgkQ}{192.168.167.246}{192.168.167.246:9300}{d}{ml.machine_memory=8124866560, ml.max_open_jobs=20, xpack.installed=true},}, term: 1, version: 12, reason: Publication{term=1, version=12}"  }
    kube-logging/elasticsearch-master-745c995d88-ksldq[elasticsearch-master]: {"type": "server", "timestamp": "2022-03-07T15:41:50,412+0000", "level": "INFO", "component": "o.e.x.i.a.TransportPutLifecycleAction", "cluster.name": "elasticsearch", "node.name": "elasticsearch-master", "cluster.uuid": "w4yuNKxZRi2BxpDgrM37eg", "node.id": "4D8M6FE7Tsqmml7IaddNww",  "message": "adding index lifecycle policy [watch-history-ilm-policy]"  }
    kube-logging/elasticsearch-client-578dd48f84-lnmx8[elasticsearch-client]: {"type": "server", "timestamp": "2022-03-07T15:41:50,601+0000", "level": "INFO", "component": "o.e.x.m.e.l.LocalExporter", "cluster.name": "elasticsearch", "node.name": "elasticsearch-client", "cluster.uuid": "w4yuNKxZRi2BxpDgrM37eg", "node.id": "tHAltQHwSK-JAbfVGY-lTw",  "message": "waiting for elected master node [{elasticsearch-master}{4D8M6FE7Tsqmml7IaddNww}{2CWU2-ZqTeK1gCd6uklb0A}{192.168.144.190}{192.168.144.190:9300}{m}{ml.machine_memory=8124866560, ml.max_open_jobs=20, xpack.installed=true}] to setup local exporter [default_local] (does it have x-pack installed?)"  }
    kube-logging/elasticsearch-data-0[elasticsearch-data]: {"type": "server", "timestamp": "2022-03-07T15:41:50,642+0000", "level": "INFO", "component": "o.e.x.m.e.l.LocalExporter", "cluster.name": "elasticsearch", "node.name": "elasticsearch-data", "cluster.uuid": "w4yuNKxZRi2BxpDgrM37eg", "node.id": "lykb7kBAR5SvmTuSFs_O-g",  "message": "waiting for elected master node [{elasticsearch-master}{4D8M6FE7Tsqmml7IaddNww}{2CWU2-ZqTeK1gCd6uklb0A}{192.168.144.190}{192.168.144.190:9300}{m}{ml.machine_memory=8124866560, ml.max_open_jobs=20, xpack.installed=true}] to setup local exporter [default_local] (does it have x-pack installed?)"  }
    kube-logging/elasticsearch-client-578dd48f84-lnmx8[elasticsearch-client]: {"type": "server", "timestamp": "2022-03-07T15:41:50,928+0000", "level": "INFO", "component": "o.e.l.LicenseService", "cluster.name": "elasticsearch", "node.name": "elasticsearch-client", "cluster.uuid": "w4yuNKxZRi2BxpDgrM37eg", "node.id": "tHAltQHwSK-JAbfVGY-lTw",  "message": "license [1e86dffb-7ce3-40e5-b95f-e79a05cb5a40] mode [basic] - valid"  }
    ...
  • sniff : tcp dump 생성
    • 파드내 TCP 덤프를 생성하여 MSA 개발시 서비스간 네트워크 활동을 기록하는 데 용이다.

      $kubectl sniff my-nginx-6c6c46694f-qv69b
      INFO[0000] using tcpdump path at: '/root/.krew/store/sniff/v1.6.2/static-tcpdump' 
      INFO[0000] no container specified, taking first container we found in pod. 
      INFO[0000] selected container: 'my-nginx'               
      INFO[0000] sniffing method: upload static tcpdump       
      INFO[0000] sniffing on pod: 'my-nginx-6c6c46694f-qv69b' [namespace: 'default', container: 'my-nginx', filter: '', interface: 'any'] 
      INFO[0000] uploading static tcpdump binary from: '/root/.krew/store/sniff/v1.6.2/static-tcpdump' to: '/tmp/static-tcpdump' 
      INFO[0000] uploading file: '/root/.krew/store/sniff/v1.6.2/static-tcpdump' to '/tmp/static-tcpdump' on container: 'my-nginx' 
      INFO[0000] executing command: '[/bin/sh -c test -f /tmp/static-tcpdump]' on container: 'my-nginx', pod: 'my-nginx-6c6c46694f-qv69b', namespace: 'default' 
      INFO[0000] command: '[/bin/sh -c test -f /tmp/static-tcpdump]' executing successfully exitCode: '1', stdErr :'' 
      INFO[0000] file not found on: '/tmp/static-tcpdump', starting to upload 
      INFO[0000] verifying file uploaded successfully         
      INFO[0000] executing command: '[/bin/sh -c test -f /tmp/static-tcpdump]' on container: 'my-nginx', pod: 'my-nginx-6c6c46694f-qv69b', namespace: 'default' 
      INFO[0000] command: '[/bin/sh -c test -f /tmp/static-tcpdump]' executing successfully exitCode: '0', stdErr :'' 
      INFO[0000] file found: ''                               
      INFO[0000] file uploaded successfully                   
      INFO[0000] tcpdump uploaded successfully                
      INFO[0000] spawning wireshark!                          
      INFO[0000] starting sniffer cleanup                     
      INFO[0000] sniffer cleanup completed successfully
  • tree : object 간 소유권 관계 정리
    • Linux tree -a 와 같이 관계를 정의해준다.
kubectl tree deployment my-nginx        
NAMESPACE  NAME                                 READY  REASON  AGE 
default    Deployment/my-nginx                  -              136m
default    ㄴ--ReplicaSet/my-nginx-6c6c46694f   -              136m
default      ㄴ--Pod/my-nginx-6c6c46694f-qv69b  True           136m
  • kubespy : kubespy는 kubernetes의 오브젝트에 대한 상태변화를 모니터링하는 도구이다.
    #install 
    $brew install kubespy
    or
    $wget https://github.com/pulumi/kubespy/releases/download/v0.6.0/kubespy-v0.6.0-linux-amd64.tar.gz
    $tar -xzvf kubespy-v0.6.0-linux-amd64.tar.gz
    $cp kubespy /usr/bin/
    #아래와 같이 추적하는 데 사용 대괄호를 통해 빠르게 표현 (added, deleted, modified)
    $kubespy trace deployment my-nginx
    [ADDED apps/v1/Deployment]  default/my-nginx
        Rolling out Deployment revision 1
        [55;8HDeployment is currently available
        [56;8HRollout successful: new ReplicaSet marked 'available'
    
    ROLLOUT STATUS:
    - [Current rollout | Revision 1] [ADDED]  default/my-nginx-65cff45899
        [60;8HReplicaSet is available [2 Pods available of a 2 minimum]
           - [Ready] my-nginx-65cff45899-cmf4w
           - [Ready] my-nginx-65cff45899-kvv2t
    $kubespy status apps/v1 Deployment my-nginx
    해당 yaml 파일과 비교하여 현재의 상태를 표현한다. yaml과 비교한기에 정확히 어떤 부분에 변화가 있는 지 파악가능

마치며

첫 블로그 포스팅이어서 뿌듯하기도 하다. 하지만, 실습관련되서 정리를 깔끔하게 하지 못한 것 같아 아쉽다.

profile
초보 데브옵스 엔지니어, 피드백은 언제나 환영입니다.

0개의 댓글