현재 데브옵스 신입 엔지니어로 회사에서 업무를 진행하는 중이지만, 쿠버네티스 환경에 대한 부족한 실력으로 어려움이 많았다. CKA 자격증을 통해 쿠버네티스 공부를 시작했지만, 실무에 대한 부족함을 느끼던 와중에 회사 동료에게 추천을 받아 CloudNet 팀에서 주관하는 EKS 스터디에 지원했다. 스터디는 1시간 30분가량 가시다님의 강의와 두 분의 경험발표로 구성되었다. 아직 신입 엔지니어이기에 잘 따라가지 못할까 걱정스럽지만 퀄리티 높은 자료와 스터디원분들이기에 배울 것이 많아보여 설렌다.
매번 시작해야지 생각만 했던 블로그를 시작해본다. .! 부족한 점이 많지만 앞으로 수정하며 수준을 높이려 한다. 전체적으로 스터디 내용을 기반으로 정리했고, 쿠버네티스에 대해 부족한 것이 많아 중간중간 기본적인 내용도 추가적으로 정리했다. 1주차의 주제는 Amzaon EKS 설치 및 기본 사용이다. 사전에 제공해주신 AWS CloudFormation을 통해 초기인프라를 형성하고 eksctl
을 통해 클러스터를 배포한다. 배포 후 클러스터에 접근하여 여러 명령어를 통해 시스템을 이해해보며 마무리 되었다.
포스트는 스터디와 같은 순서로 진행된다. 먼저, 아키텍처를 살펴보고 실습을 진행한다.
먼저, 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에 대해 더 알아보자.
먼저, 클러스터 엔드포인트를 확인한다. 클러스터 엔드포인트의 끝을 확인하면 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을 이용해서 컨테이너 이미지를 관리해보는 실습을 진행했는 데, 작업은 간단하다.
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 내부에서만 컨트롤 플래인의 접근이 가능하다. 아래의 아키텍처로 구현됨을 확인할 수 있었다.
스터디 중에 진행한 실습은 이렇게 마무리 되었다. 아래에는 추가적으로 진행한 실습 및 자료이다.
Pod Affinity and Anti-Affinity
nodeselector
: 라벨(key - value)을 통해 스케줄링을 지정할 수 있다. (선호도기능은 하지 못한다.)
nodeaffinity
: 특정 노드에 스케줄링되도록 유도한다.(특정 노드 배치 제안)requiredDuringSchedulingIgnoredDuringExecution
: 해당 규칙이 만족되야, 파드를 스케줄링하며 규칙이 만족되지 않으면 스케줄링할 수 없다.preferredDuringSchedulingIgnoredDuringExecution
: 해당 조건을 만족하는 노드를 찾으려고 노력한다. 조건에 맞는 노드가 없으면 일반적으로 스케줄링 된다.In
: 조건에 맞는 노드에 배치NotIn
: 조건과 다른 노드에 배치Exists
: 조건이 있는 노드에 배치Taints
kubectl taint nodes <node-name> key=value:taint-effect
kubectl taint nodes node1 key1=value2:NoSchedule
NoSchedule
PreferNoSchedule
NoExecute
많은 플로그인이 개발되어 활용되고 있다. 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
를 통해 설치 가능하다.)
해당 블로그를 참고해여 작성함.
-o yaml
으로 확인하면 관련된 상태들까지 출력이 되 보기가 불편하다.kubectl get deployment my-nginx -o yaml | kubectl neat
$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" }
...
파드내 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 -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
#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과 비교한기에 정확히 어떤 부분에 변화가 있는 지 파악가능
첫 블로그 포스팅이어서 뿌듯하기도 하다. 하지만, 실습관련되서 정리를 깔끔하게 하지 못한 것 같아 아쉽다.