-
08. 쿠버네티스 핵심 개념 (3)24년 11월 이전/데브옵스(DevOps)를 위한 쿠버네티스 마스터 2021. 7. 25. 19:42반응형
이 문서는 인프런 강의 "데브옵스를 위한 쿠버네티스 마스터"을 듣고 작성되었습니다. 최대한 요약해서 강의 내용을 최소로 하는데 목표를 두고 있어서, 더 친절하고 정확한 내용을 원하신다면 강의를 구매하시는 것을 추천드립니다. => 강의 링크
네임스페이스
namespace
란 물리 쿠버네티스 클러스터 내에서 동작하는 가상 쿠버네티스 클러스터이다. 약간 실제 물리서버에서 동작하는VM
과 성격이 비슷한데, 쉽게 생각해서 리소스들을 분리된 영역으로 격리시켜 관리하는 기술이다.기본적으로 쿠버네티스 클러스터에는 다음의 4가지 네임스페이스가 자동으로 생성된다.
$ kubectl get namespace NAME STATUS AGE default Active 15d kube-node-lease Active 15d kube-public Active 15d kube-system Active 15d
이제
namespace
하나를 생성해보자. 터미널에 다음과 같이ns-test.yaml
을 만든다.apiVersion: v1 kind: Namespace metadata: creationTimestamp: null name: ns-test spec: {} status: {}
이제 터미널에 다음을 입력한다.
$ kubectl create -f ns-test.yaml namespace/ns-test created
namespace
가 잘 만들어졌는지 확인해보자.$ kubectl get ns NAME STATUS AGE default Active 15d kube-node-lease Active 15d kube-public Active 15d kube-system Active 15d # 추가되었다. ns-test Active 39s
이제
namespace
안에pod
을 하나 만들어보자. 터미널에 다음을 입력한다.$ kubectl run nginx --image=nginx -n ns-test pod/nginx created
이제
pod
이 잘 생성되었는지 확인해보자.$ kubectl get pod No resources found in default namespace.
분명 리소스를 생성했는데 안보인다. 왜냐하면, 기본적으로
namespace
는 "default"로 잡혀있다. 내가 원하는namespace
의 리소스를 확인하고 싶다면 다음과 같이 입력하면 된다.# kubectl get <resource> -n <namespace> $ kubectl get pod -n ns-test NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 5m8s
namespace
역시 다음과 같이 삭제할 수 있다.$ kubectl delete -f ns-test.yaml namespace "ns-test" deleted
서비스
Service
란Pod
집합에서 실행 중인 애플리케이션을 네트워크 서비스로 노출하는 추상화된 방법이다.Pod
는 일시적으로 생성되는 컨테이너의 집합인데, 실제 리소스 생성/수정/삭제 시에, IP 주소가 지속적으로 변동되기 떄문에 이를 추적하고 부하를 분산시켜야 한다. 이를 해결하기 위한 것이 바로Service
이다.서비스는 다음과 같이 구성할 수 있다.
src/ch08/k8s/simple-app-svc-v1.yaml
# service apiVersion: v1 kind: Service metadata: name: simple-app-svc spec: sessionAffinity: ClientIP ports: - port: 80 targetPort: 8080 selector: app: simple-app --- # deployment apiVersion: apps/v1 kind: Deployment metadata: name: simple-app-dep labels: app: simple-app spec: replicas: 3 selector: matchLabels: app: simple-app template: metadata: labels: app: simple-app spec: containers: - name: simple-app image: gurumee92/simple-app:v1 ports: - containerPort: 8080
위의 코드는
Service
이고, 아래---
아래 코드는Deployment
이다. 즉 위의 코드는simple-app
컨테이너 3개를 구동시키는Deployment
와, 이를 외부로 노출시키는Service
를 구동시키는 것이다. 다음 명령어로 만들 수 있다.$ pwd /home/gurumee/k8s/ch08 $ kubectl create -f simple-app-svc.yaml service/simple-app-svc created deployment.apps/simple-app-dep created
다음 명령어로 생성된
Service
목록을 확인할 수 있다.$ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6d11h simple-app-svc ClusterIP 10.105.112.199 <none> 80/TCP 50s
여기서 생성된
Pod
들을 보자.$ kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES simple-app-dep-5d4c8d678b-hcqzj 1/1 Running 0 21m 10.32.0.3 slave2 <none> <none> simple-app-dep-5d4c8d678b-jljj2 1/1 Running 0 21m 10.32.0.2 slave2 <none> <none> simple-app-dep-5d4c8d678b-p5sdn 1/1 Running 0 21m 10.32.0.4 slave2 <none> <none>
이 때 IP를 기억해두자. 서비스의 정보를 확인한다.
$ kubectl describe svc simple-app-svc Name: simple-app-svc Namespace: default Labels: <none> Annotations: <none> Selector: app=simple-app # 기본 타입은 ClusterIP이다. Type: ClusterIP IP Family Policy: SingleStack IP Families: IPv4 IP: 10.105.112.199 IPs: 10.105.112.199 Port: <unset> 80/TCP TargetPort: 8080/TCP # 엔드포인트에 Pod들의 IP가 할당된 것을 확인할 수 있다. Endpoints: 10.32.0.2:8080,10.32.0.3:8080,10.32.0.4:8080 Session Affinity: ClientIP Events: <none>
여기서
Endpoints
에Pod
들의 IP가 할당된 것을 확인할 수 있다. 또한 아무 타입 지정을 하지 않으면ClusterIP
로 지정된다. 이게 모든 서비스의 원형 타입이라고 생각하면 된다. 현재 이렇게 분산된 경우, 한 가지만 더 알아두자. 현재 설정으로는 서비스 세션이 고정되지 않는다. 이 때 세션을 고정하기 위한 설정이 있는데 바로sessionAffinity
이다. 다음과 같이 수정한다.src/ch08/k8s/simple-app-svc-v2.yaml
apiVersion: v1 kind: Service metadata: name: simple-app-svc spec: # 세션을 고정하기 위한 설정 sessionAffinity: ClientIP # ... # ...
이렇게 하면, 한 번 요청을 한 경우, 이후부터의 요청은 최초 요청한
Pod
에게 요청을 지속적으로 발생하게 된다. 또한 외부 IP와 연결이 필요한 경우는Service
와 더불어서Endpoints
라는 리소스가 필요하다. 이런 식으로 외부 IP와 연동할 수 있다.서비스
apiVersion: v1 kind: Service metadata: name: external-service spec: ports: - port: 80
엔드포인트
apiVersion: v1 kind: Endpoints metadata: name: external-service subnets: - addresses: - ip: 11.11.11.11 ip: 22.22.22.22 ports: - port: 80
다음 절부터는
VM
이 아닌GCP
혹은EKS
등의 Public Cloud가 제공하는 쿠버네티스 클러스터를 이용하자.서비스를 expose하는 방법 (1) NodePort
서비스를 노출하는 3가지 방법 중 하나이다. 노드 자체 포트를 사용하여
Pod
로 리다이렉트 한다. 다음과 같이 서비스 파일을 생성한다.src/k8s/ch08/simple-app-np.yaml
apiVersion: v1 kind: Service metadata: name: simple-app-np spec: type: NodePort selector: app: simple-app ports: - protocol: TCP port: 80 targetPort: 8080 nodePort: 30001
위에서
type
은NodePort
로 지정되고,ports
에서nodePort
가 "30001"로 지정된 것을 확인할 수 있다. 터미널에서 다음과 같이 입력하면 서비스를 생성할 수 있다.$ kubectl create -f simple-app-np.yaml service/simple-app-np created
또한 서비스 상태를 확인해보자.
$ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.112.0.1 <none> 443/TCP 7m26s simple-app-np NodePort 10.112.13.203 <none> 80:30001/TCP 34s
여기서 80:30001 로 묶여 있는데,
Compute Engine
대시보드로 가보면 다음 노드들이 구성된 것을 확인할 수 있다.이 때 해당 노드 IP:nodePort로 구동되는
Pod
들을 호출할 수 있다. 호출 이전에 방화벽 정책을 통해NodePort
에 대해서 외부로 공개해주어야 한다.$ gcloud compute firewall-rules create simple-app-svc-rules --allow=tcp:30001
그 후 노드 IP:노드 포트로 요청을 할 수가 있다.
# curl <노드 IP>:<노드 포트> $ curl 34.64.75.5:30001 Hello World v1% $ curl 34.64.132.245:30001 Hello World v1% $ curl 34.64.143.114:30001 Hello World v1%
서비스를 expose하는 방법 (2) LoadBalancer
서비스를 노출하는 3가지 방법 중 하나이다. 외부 게이트웨이를 사용해 노드 포트로 리다이렉트 한다.
src/ch08/k8s/simple-app-lb.yaml
apiVersion: v1 kind: Service metadata: name: simple-app-lb spec: type: LoadBalancer selector: app: simple-app ports: - protocol: TCP port: 80 targetPort: 8080
여기서
type
이LoadBalancer
인 것을 알아두자. 그리고nodePort
를 지정하지 않으면 30000 번대 포트에서 무작위로 선택이 된다. 한 번 만들어두자.$ kubectl create -f simple-app-lb.yaml service/simple-app-lb created
그 다음 시간이 좀 지나서 확인해보면 다음과 같이 생성됨을 확인할 수 있다.
$ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.112.0.1 <none> 443/TCP 5m59s simple-app-lb LoadBalancer 10.112.15.122 34.64.122.149 80:31694/TCP 74s
여기에
EXTERNAL-IP
에 IP가 할당된 것을 확인할 수 있다. 애는GCP
네트워크 서비스에서 제공하는 "부하 분산" 즉LoadBalacner
이다. 다음과 같이 확인할 수 있다.외부 IP가 동일하다. 이제 이 IP로 호출할 수 있다. 이떄는
nodePort
가 아닌port
로 지정된 포트 번호로 호출해야 한다.$ curl 34.64.122.149:80 Hello World v1%
서비스를 expose하는 방법 (3) Ingress
서비스를 노출하는 3가지 방법 중 하나이다. 하나의 IP 주소를 통해 여러 서비스를 제공하는 특별한 메커니즘이다. 인그레스 방법은 설정이 조금 빡세다. 먼저
NodePort
용 서비스를 생성해둔다.$ kubectl create -f simple-app-np.yaml service/simple-app-np created
그 후 다음과 같이 인그레스를 만드는 설정 파일을 생성한다.
src/ch08/k8s/simple-app-ingress.yaml
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: simple-app-ingress spec: rules: - host: gurumee.com http: paths: - path: / pathType: Prefix backend: service: name: simple-app-np port: number: 80
host
에Pod
들이 구성된 도메인을 연결해준다. 그 후http.paths.path
를 지정해주고https.paths.backend.service.name
에Pod
을 연결해준다. 이제 터미널에 다음을 입력하여 인그레스를 생성한다.$ kubectl create -f simple-app-ingress.yaml ingress.networking.k8s.io/simple-app-ingress created
다음과 같이 확인할 수 있다.
$ kubectl get ingress NAME CLASS HOSTS ADDRESS PORTS AGE simple-app-ingress <none> gurumee.com 34.149.182.51 80 94s
이제 이 주소로 curl을 날려보자. (여기서는 kubectl이 실행되는 터미널에서 진행해야 한다.)
$ curl 34.149.182.51 response 404 (backend NotFound), service rules for the path non-existent
gurumee.com
이 없기 때문에 404가 뜬다. 이걸 허용하려면 원래 도메인 설정이 필요하나 귀찮으니까/etc/hosts
에서 다음과 같이 수정한다.# Kubernetes-managed hosts file. 127.0.0.1 localhost # 수정된 곳 # ingress IP 매핑된 host 34.149.182.51 gurumee.com ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet fe00::0 ip6-mcastprefix fe00::1 ip6-allnodes fe00::2 ip6-allrouters 172.17.0.4 cs-595878838943-default-boost-l8dqx
그 후 이제는 "Host"에
curl
을 날려보자.$ curl gurumee.com Hello World v1
kubectl
이 실행되는 터미널이 아니라면 어차피 외부에 지정된 도메인이 아니므로 이런식으로 호출은 불가능하다.728x90'레거시 > 데브옵스(DevOps)를 위한 쿠버네티스 마스터' 카테고리의 다른 글
10. 쿠버네티스 핵심 개념 (5) (0) 2021.08.14 09. 쿠버네티스 핵심 개념 (4) (0) 2021.08.05 07. 쿠버네티스 핵심 개념 (2) (0) 2021.07.14 06. 쿠버네티스 핵심 개념 (1) (0) 2021.07.09 05. 쿠버네티스 들어가기 (2) (0) 2021.07.06