실습
ClusterIP
Deployment 생성
cat <<'EOF' | kubectl apply -f - apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80 volumeMounts: - name: html mountPath: /usr/share/nginx/html initContainers: - name: index image: curlimages/curl command: - "sh" - "-c" - "echo 'hello from $(POD_NAME), my ip is $(POD_IP)' > /data/index.html" volumeMounts: - name: html mountPath: /data env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_IP valueFrom: fieldRef: fieldPath: status.podIP volumes: - name: html emptyDir: {} EOF
Service 생성
kubectl expose deployment nginx --port 80
생성된 Service 확인
kubectl get svc nginx -o wide
생성된 Endpoint 확인
kubectl get ep nginx
생성된 Pod의 IP주소 확인
kubectl get pod -l app=nginx -o wide
Endpoint에 타겟으로 등록되어 있는 Pod 목록 확인
kubectl get ep nginx \ -o jsonpath='{range .subsets[*].addresses[*]}{.targetRef.name}{"\t"}{.ip}{"\n"}{end}'
생성된 Deployment의 Replica 갯수를 6개로 조정
kubectl scale deployment nginx --replicas=6
생성된 Pod의 IP주소 확인
kubectl get pod -l app=nginx -o wide
Endpoint에 타겟으로 등록되어 있는 Pod 목록 확인
kubectl get ep nginx \ -o jsonpath='{range .subsets[*].addresses[*]}{.targetRef.name}{"\t"}{.ip}{"\n"}{end}'
Pod 생성
kubectl run curl --image=nginx -- sleep 3600
위에서 생성한 Pod에서 Service 호출
kubectl exec curl -- \ bash -c "for i in {1..20};do curl -s $(kubectl get svc nginx -o=jsonpath='{.spec.clusterIP}');done"
새로운 터미널을 열고 kube-proxy 로그 확인 - 아래의 명령어를 입력하고 엔터키를 몇번 입력해서 간격을 만들어두면 새로운 로그를 좀 더 쉽게 알아볼수 있음
kubectl -n kube-system logs ds/kube-proxy -f
기존 터미널로 돌아와서 생성된 Deployment의 Replica 갯수를 3개로 조정
kubectl scale deployment nginx --replicas=3
다른 터미널로 이동해서 kube-proxy 로그 확인
새로운 터미널을 열고 한개의 Node로 Session Manager 연결
aws ssm start-session --target \ $(kubectl get node -o jsonpath='{.items[0].spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+")
Iptable의 모든 규칙 확인
sudo iptables-save
Iptable의 NAT 규칙 확인
sudo iptables -L -t nat
KUBE-SERVICES 규칙 확인
sudo iptables -t nat -L KUBE-SERVICES -n | column -t
생성된 Service의 Cluster IP로 연결된 규칙 값을 환경변수로 저장
export SERVICE_CHAIN=$(sudo iptables -t nat -L KUBE-SERVICES -n | column -t | grep "default/nginx" | grep -oE "^KUBE-SVC-[A-Z0-9]+") echo $SERVICE_CHAIN
Service의 Cluster IP로 연결된 규칙의 상세내용 확인
sudo iptables -t nat -L $SERVICE_CHAIN -n | column -t
위의 명령어로 나온 결과중의 한개의 Chain 규칙 확인
sudo iptables -t nat -L $(sudo iptables -t nat -L $SERVICE_CHAIN -n | column -t | grep -oE "^KUBE-SEP-[A-Z0-9]+" | head -1) \ -n | column -t
첫번째 터미널로 이동해서 생성된 Pod의 IP주소 확인
kubectl get pod -o wide -l app=nginx
생성된 Deployment의 Replica 갯수를 6개로 조정
kubectl scale deployment nginx --replicas=6
두번째 터미널에서 kube-proxy 로그 확인
세번째 터미널로 이동해서 20번 명령어 재실행
첫번째 터미널로 이동해서 CoreDNS 설정 파일 확인
kubectl -n kube-system get cm coredns -o yaml | yq e '.data' -
log 플러그인 활성화 - https://coredns.io/plugins/log
cat <<EOF | kubectl apply -f - apiVersion: v1 kind: ConfigMap metadata: name: coredns namespace: kube-system labels: eks.amazonaws.com/component: coredns k8s-app: kube-dns data: Corefile: | .:53 { errors health kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure fallthrough in-addr.arpa ip6.arpa } prometheus :9153 forward . /etc/resolv.conf cache 30 loop reload loadbalance log } EOF
CoreDNS Pod 재배포
{ kubectl -n kube-system scale deployment coredns --replicas=0 sleep 60 kubectl -n kube-system scale deployment coredns --replicas=2 sleep 10 kubectl -n kube-system get pod -l k8s-app=kube-dns }
두번째 터미널에서 CoreDNS 로그 확인
kubectl -n kube-system logs deploy/coredns -f
첫번째 터미널로 이동해서 Pod안에 설정된 DNS 설정 파일 확인
kubectl exec curl -- cat /etc/resolv.conf
CoreDNS 주소 확인
kubectl -n kube-system get svc kube-dns
CURL 명령어로 Service 이름 호출
kubectl exec curl -- curl -s nginx
두번째 터미널에서 CoreDNS 로그 확인 - 새로운 로그 출력되지 않으면 32번 명령어를 다시 수행
첫번째 터미널로 이동해서 새로운 Namespace 생성
kubectl create ns web
생성한 Namespace 안에 Deployment 생성
kubectl -n web create deployment httpd --image=httpd --port=80
Service 생성
kubectl -n web expose deployment httpd
CURL 명령어로 Service 이름 호출
kubectl exec curl -- curl -s httpd
두번째 터미널에서 CoreDNS 로그 확인 - 새로운 로그 출력되지 않으면 37번 명령어를 다시 수행
CURL 명령어로 Service 호출 - service.namespace
kubectl exec curl -- curl -s httpd.web
CURL 명령어로 Service 호출 - service.namespace.svc
kubectl exec curl -- curl -s httpd.web.svc
CURL 명령어로 Service 호출 - service.namespace.svc.cluster
kubectl exec curl -- curl -s httpd.web.svc.cluster
CURL 명령어로 Service 호출 - FQDN
kubectl exec curl -- curl -s httpd.web.svc.cluster.local
생성한 리소스 삭제
{ kubectl delete ns web kubectl delete pod curl kubectl delete svc nginx kubectl delete deploy nginx }
NodePort
Deployment 생성
kubectl create deployment nginx --image=nginx --port=80 --replicas=3
Service 생성
kubectl expose deployment nginx --type=NodePort
생성된 Service 확인
kubectl get svc nginx -o wide
Node의 공인 IP 주소 확인
kubectl get node -o wide
웹 브라우저를 열고 NODE_EXTERNAL_IP:NODEPORT 주소로 접속 시도 - 아래의 명령어로 주소 확인 가능
echo $(kubectl get node -o=jsonpath='{.items[0].status.addresses[?(@.type=="ExternalIP")].address}')\ :$(kubectl get svc nginx -o=jsonpath='{.spec.ports[0].nodePort}')
접속이 안될 경우에는 Node의 보안그룹 확인
aws ec2 describe-security-groups --group-ids \ $(aws ec2 describe-instances --instance-ids \ $(kubectl get node -o jsonpath='{.items[0].spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+") \ --query 'Reservations[0].Instances[0].SecurityGroups[*].GroupId' --output text) \ --query "SecurityGroups[*].IpPermissions"
보안그룹에 Service에 명시된 포트에 대한 인바운드 규칙이 없을 경우에 아래의 명령어로 규칙 추가
aws ec2 authorize-security-group-ingress --group-id \ $(aws ec2 describe-instances --instance-ids \ $(kubectl get node -o jsonpath='{.items[0].spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+") \ --query 'Reservations[0].Instances[0].SecurityGroups[0].GroupId' --output text) \ --protocol tcp \ --port $(kubectl get svc nginx -o=jsonpath='{.spec.ports[0].nodePort}') \ --cidr 0.0.0.0/0
보안그룹에 인바운드 규칙이 추가되었는지 확인
aws ec2 describe-security-groups --group-ids \ $(aws ec2 describe-instances --instance-ids \ $(kubectl get node -o jsonpath='{.items[0].spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+") \ --query 'Reservations[0].Instances[0].SecurityGroups[*].GroupId' --output text) \ --query "SecurityGroups[*].IpPermissions"
웹 브라우저를 열고 NODE_EXTERNAL_IP:NODEPORT 주소로 접속 시도 - 아래의 명령어로 주소 확인 가능
echo $(kubectl get node -o=jsonpath='{.items[0].status.addresses[?(@.type=="ExternalIP")].address}')\ :$(kubectl get svc nginx -o=jsonpath='{.spec.ports[0].nodePort}')
새로운 터미널을 열고 한개의 Node로 Session Manager 연결
aws ssm start-session --target \ $(kubectl get node -o jsonpath='{.items[0].spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+")
Iptable의 모든 규칙 확인
sudo iptables-save
KUBE-SERVICES 규칙 확인
sudo iptables -t nat -L KUBE-SERVICES -n | column -t
KUBE-NODEPORTS 규칙 확인
sudo iptables -t nat -L KUBE-NODEPORTS -n | column -t
생성된 Service의 NodePort로 연결된 규칙 값을 환경변수로 저장
export NODEPORT_CHAIN=$(sudo iptables -t nat -L KUBE-NODEPORTS -n | column -t | grep "default/nginx" | grep -oE "^KUBE-SVC-[A-Z0-9]+") echo $NODEPORT_CHAIN
KUBE-SERVICES 규칙 중에서 NodePort로 연결된 규칙 확인
sudo iptables -t nat -L KUBE-SERVICES -n | column -t | grep $NODEPORT_CHAIN
첫번째 터미널로 이동해서 Service의 Cluster IP 확인
kubectl get svc nginx
다른 터미널로 이동해서 NodePort로 연결된 규칙의 상세내용 확인
sudo iptables -t nat -L $NODEPORT_CHAIN -n | column -t
위의 명령어로 나온 결과중의 한개의 Chain 규칙 확인
sudo iptables -t nat -L \ $(sudo iptables -t nat -L $NODEPORT_CHAIN -n | column -t | grep -oE "^KUBE-SEP-[A-Z0-9]+" | head -1) \ -n | column -t
첫번째 터미널로 이동해서 생성된 Pod의 IP주소 확인
kubectl get pod -o wide -l app=nginx
다른 터미널로 이동해서 Node에 열려있는 포트 정보 확인
sudo netstat -tlnp
CURL 명령어로 Service 호출
curl localhost:NODEPORT
첫번째 터미널로 이동해서 보안그룹에 추가한 인바운드 규칙 삭제
aws ec2 revoke-security-group-ingress --group-id \ $(aws ec2 describe-instances --instance-ids \ $(kubectl get node -o jsonpath='{.items[0].spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+") \ --query 'Reservations[0].Instances[0].SecurityGroups[0].GroupId' --output text) \ --protocol tcp \ --port $(kubectl get svc nginx -o=jsonpath='{.spec.ports[0].nodePort}') \ --cidr 0.0.0.0/0
인바운드 규칙이 삭제되었는지 확인
aws ec2 describe-security-groups --group-ids \ $(aws ec2 describe-instances --instance-ids \ $(kubectl get node -o jsonpath='{.items[0].spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+") \ --query 'Reservations[0].Instances[0].SecurityGroups[*].GroupId' --output text) \ --query "SecurityGroups[*].IpPermissions"
생성한 리소스 삭제
{ kubectl delete deploy nginx kubectl delete svc nginx }
LoadBalancer
Deployment 생성
kubectl create deployment nginx --image=nginx --port=80 --replicas=3
Service 생성
kubectl expose deployment nginx --type=LoadBalancer
생성된 Service 확인
kubectl get svc nginx -o wide
생성된 Service 객체에 발생한 Event 확인
kubectl describe svc nginx
웹 브라우저를 열고 Service의 External IP 주소로 접속 - 아래의 명령어로 주소 확인 가능
kubectl get svc nginx -o jsonpath='{.status.loadBalancer.ingress[0].hostname}{"\n"}'
생성된 Service 상세 내용 확인
kubectl get svc nginx -o=jsonpath='{.spec}' | jq
생성된 ELB 이름 확인
kubectl get svc nginx -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' | grep -o -E '^[a-z0-9]+'
ELB 상세 내용 확인
aws elb describe-load-balancers --load-balancer-names \ $(kubectl get svc nginx -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' | grep -o -E '^[a-z0-9]+' )
ELB의 Listener 설정 확인
aws elb describe-load-balancers --load-balancer-names \ $(kubectl get svc nginx -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' | grep -o -E '^[a-z0-9]+' ) \ --query 'LoadBalancerDescriptions[*].ListenerDescriptions'
ELB의 보안그룹 확인
aws elb describe-load-balancers --load-balancer-names \ $(kubectl get svc nginx -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' | grep -o -E '^[a-z0-9]+' ) \ --query 'LoadBalancerDescriptions[*].SecurityGroups'
노드에 부여된 보안그룹에 ELB 보안그룹에 대한 새로운 인바운드 규칙이 추가 됐는지 확인
aws ec2 describe-security-groups --group-ids \ $(aws ec2 describe-instances --instance-ids \ $(kubectl get node -o jsonpath='{.items[0].spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+") \ --query 'Reservations[0].Instances[0].SecurityGroups[*].GroupId' --output text) \ --query "SecurityGroups[*].IpPermissions"
새로운 터미널을 열고 한개의 Node로 Session Manager 연결
aws ssm start-session --target \ $(kubectl get node -o jsonpath='{.items[0].spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+")
KUBE-NODEPORTS 규칙 확인
sudo iptables -t nat -L KUBE-NODEPORTS -n | column -t
첫번째 터미널로 이동해서 생성한 리소스 삭제
{ kubectl delete deploy nginx kubectl delete svc nginx }
Network Load Balancer
Deployment 생성
kubectl create deployment tcp-echo --image=istio/tcp-echo-server:1.2 --port=9000
Pod 생성 확인
kubectl get pod -l app=tcp-echo
AWS Cloud Controller Manager를 통해서 CLB 및 NLB를 생성 및 구성하는 방법 리뷰 https://github.com/kubernetes/cloud-provider-aws/blob/master/docs/service_controller.md https://kubernetes.io/docs/concepts/services-networking/service/#aws-nlb-support
Service 생성
cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Service metadata: name: tcp-echo annotations: service.beta.kubernetes.io/aws-load-balancer-type: nlb spec: selector: app: tcp-echo ports: - protocol: TCP port: 9000 targetPort: 9000 type: LoadBalancer EOF
Service 상태 확인
kubectl describe svc tcp-echo
생성된 ELB 상세 내용 확인
aws elbv2 describe-load-balancers --names \ $(kubectl get svc tcp-echo \ -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' \ | grep -o -E '^[a-z0-9]+')
Pod 생성
kubectl run netcat --image=youngwjung/netcat -- sleep 3600
Pod 생성 확인
kubectl get pod netcat
생성한 Pod에서 NLB로 TCP 연결
kubectl exec -it netcat -- \ nc -v -q 1 $(kubectl get svc tcp-echo -o jsonpath='{.status.loadBalancer.ingress[0].hostname}') 9000
연결에 성공했다는 메시지가 나오면 터미널에 아무 글자나 입력해서 응답이 오는지 확인
$ kubectl exec -it netcat -- nc -v -q 1 $(kubectl get svc tcp-echo -o jsonpath='{.status.loadBalancer.ingress[0].hostname}') 9000 Connection to a0db8c37386d148afbd97efc9dc15a8f-744e5fa4f97a926c.elb.ap-northeast-2.amazonaws.com 9000 port [tcp/*] succeeded! kubernetes hello kubernetes aws hello aws world hello world
생성한 리소스 삭제
{ kubectl delete deploy tcp-echo kubectl delete svc tcp-echo kubectl delete pod netcat }
Kubectl Proxy & Port-forwarding
Deployment 생성
kubectl create deployment nginx --image=nginx --port=80 --replicas=1
생성된 Pod 확인
kubectl get po -l app=nginx
Service 생성
kubectl expose deployment nginx
생성된 Service 확인
kubectl get svc nginx
Kubectl proxy 구동
kubectl proxy --port=8080 --accept-hosts=.* --address=0.0.0.0
새로운 터미널을 열고 아래의 주소로 접근 시도
curl -L localhost:8080/api/v1/namespaces/default/services/nginx:80/proxy
생성된 Pod 이름을 환경변수로 저장
{ export POD_NAME=$(kubectl get pod -l app=nginx -o=jsonpath='{.items[0].metadata.name}') echo $POD_NAME }
아래의 주소로 접근 시도
curl -L localhost:8080/api/v1/namespaces/default/pods/$POD_NAME:80/proxy
첫번째 터미널로 이동해서 실행중인 kubectl proxy 프로세스 종료
생성된 Pod 이름을 환경변수로 저장
{ export POD_NAME=$(kubectl get pod -l app=nginx -o=jsonpath='{.items[0].metadata.name}') echo $POD_NAME }
로컬포트를 Pod의 포트로 포워딩
kubectl port-forward $POD_NAME 8080:80 --address=0.0.0.0
다른 터미널로 이동해서 Pod에 배포된 NGINX 서버로 접근 시도
curl localhost:8080
첫번째 터미널로 이동해서 실행중인 kubectl port-forward 프로세스 종료
로컬포트를 Service의 포트로 포워딩
kubectl port-forward svc/nginx 8080:80 --address=0.0.0.0
다른 터미널로 이동해서 Service로 접근 시도
curl localhost:8080
첫번째 터미널로 이동해서 실행중인 kubectl port-forward 프로세스 종료
생성한 리소스 삭제
{ kubectl delete deploy nginx kubectl delete svc nginx }
ExternalName
Service 생성
cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Service metadata: name: k8s spec: type: ExternalName externalName: kubernetes.io EOF
Service 상태 확인
kubectl describe svc k8s
Pod 생성
kubectl run curl --image=curlimages/curl --command -- sleep 3600
위에서 생성한 Service 호출
kubectl exec curl -- curl -sL k8s
위에서 생성한 Service 호출 - 호스트 명시
kubectl exec curl -- curl -sL -H "Host: kubernetes.io" k8s
위에서 생성한 Service 호출 - 호스트 명시하고 새로운 경로 호출
kubectl exec curl -- curl -sL -H "Host: kubernetes.io" k8s/docs
리소스 삭제
{ kubectl delete svc k8s kubectl delete pod curl }
Last updated