becool

20210831 (화) kubernetes 내부,외부 네트워크 본문

kubernetes

20210831 (화) kubernetes 내부,외부 네트워크

gusalstm 2021. 8. 31. 16:48
반응형

9:34 review

 

 Kubernetes 네트워크

   Pod는 일회성으로 동작하며 유동적으로 (생성/추가/삭제) 운영됨

   특정노드에 pod가 스케쥴링되고 IP주소를 동적으로 할당받으므로 클라이언트가 사전에 IP주소 예측불가

   전통적인 방식에서 서버가 고정적인 ip(진입점)를 가졌던 것처럼, Service를 통한 진입점을 제공

   

 - Kubernetes Cluster 내부 네트워크

   - 서비스 (Service)

     Kubernetes Cluster에서 애플리케이션을 실행하는 pod, controller에 대해 단일 네트워크 진입점을 제공하는 object

     별도로 service object를 종료하지 않는 이상 부여된 IP주소가 변경되지 않음

     Label Selector를 이용하여 service object 와 연결할 대상을 관리

     Service에 선택된 pod의 목록은 Endpoint object가 관리

     kubectl get services

     kubectl expose CONTROLLER_TYPE CONTROLLER_NAME --name SERVICE_NAME

     manifest작성 후 SERVICE_FILE_NAME.yaml → kubectl create -f SERVICE_FILE_NAME.yaml

     - Session Affinity

       Client 요청을 처음 요청한 pod와 동일한 pod에 세션을 유지하고자 할 때 사용

       (하나의 pod와 지속적인 통신을 함으로써 데이터 손실이 발생하지 않게 함) 

     - Service (다중포트)

     - 서비스 (named port)

##### named port #####

vagrant@kube-control1:~/work/20210831$ cat test-rs.yaml
#→ 레플리카셋 작성
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: test-rs
spec:
  replicas: 5
  selector:
    matchLabels: #→ label이 일치하는 pods 대상
      app: test-rs-namedport
  template:
    metadata:
      labels: #→ label 작성
        app: test-rs-namedport
    spec:
      containers:
      - name: test
        image: devops2341/go-myweb:latest
        ports:
        - name: test-http
          containerPort: 8080
          protocol: TCP

vagrant@kube-control1:~/work/20210831$ cat test-svc.yaml
#→ 서비스 작성
apiVersion: v1
kind: Service
metadata:
  name: test-svc-namedport
spec:
  ports:
  - name: test-http
    port: 80
    targetPort: test-http #→ targetport를 문자로 표현
  selector:
    app: test-rs-namedport

   - 서비스 탐색 (Service Discovery)

     1) 환경변수를 이용한 Service Discovery

        env 명령어를 통해 저장된 환경변수들을 사용한 탐색

     2) Kubernetes Cluster 내부 DNS를 이용한 Service Discovery

        coredns라는 이름으로 작동하고 있는 deployment (이전 버전에서는 kube-dns을 활용했으므로 용어 주의)

        SERVICE_NAME.NAMESPACE.k8s_OBJECT.k8s_CLUSTER_DOMAIN

        → myapp-svc-nodeport.default.services.cluster.local

      

##### core-dns 동작확인 #####

vagrant@kube-control1:~/work/20210831$ kubectl get all -n kube-system -l k8s-app=kube-dns --show-labels
NAME                          READY   STATUS    RESTARTS   AGE     LABELS
pod/coredns-f9fd979d6-kxj7t   1/1     Running   6          7d19h   k8s-app=kube-dns,pod-template-hash=f9fd979d6
pod/coredns-f9fd979d6-tkn6r   1/1     Running   6          7d19h   k8s-app=kube-dns,pod-template-hash=f9fd979d6

NAME               TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE     LABELS
service/kube-dns   ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   7d19h   k8s-app=kube-dns,kubernetes.io/cluster-service=true,kubernetes.io/name=KubeDNS

NAME                      READY   UP-TO-DATE   AVAILABLE   AGE     LABELS
deployment.apps/coredns   2/2     2            2           7d19h   k8s-app=kube-dns

NAME                                DESIRED   CURRENT   READY   AGE     LABELS
replicaset.apps/coredns-f9fd979d6   2         2         2       7d19h   k8s-app=kube-dns,pod-template-hash=f9fd979d6

##### FQDN #####

같은 namespace 내에서 질의시 : myapp-svc-clusterip
다른 namespace 에서 질의시 : myapp-svc-clusterip.default.
오브젝트 타입 지정 : myapp-svc-clusterip.default.svc
전체 FQDN 지정: myapp-svc-clusterip.default.svc.cluster.local

vagrant@kube-control1:~$ kubectl run nettool -it --image devops2341/network-multitool:v1 --rm bash
bash-5.1# host myapp-svc-clusterip
bash-5.1# host myapp-svc-clusterip.default
bash-5.1# host myapp-svc-clusterip.default.svc
bash-5.1# host myapp-svc-clusterip.default.svc.cluster.local  → FQDN
myapp-svc-clusterip.default.svc.cluster.local has address 10.100.138.93

   

 - Kubernetes Cluster 외부 네트워크

   서비스 종류

   - Cluster IP

     Kubernetes Cluster 내부 서비스를 제공하기 위한 서비스 타입

     기본적으로 Kubernetes Cluster 내부에서만 접근할 수 있음

   - NodePort

     NodePort + ClusterIP

     Kubernetes Cluster 의 모든 노드에 외부 접근용 포트를 할당하는 서비스 타입

     노드의 Port를 이용하여 외부에서 Kubernetes Cluster에 접근 가능

     노드의 Port를 접근하면 Service에 의해 pod로 리다이렉션

     pod를 실행하지 않는 노드에도 노드 port가 할당되어 접근 가능

     노드의 Port에 할당 가능한 Port 범위 : 30000~32767 범위 (변경가능)

   - LoadBalancer

     LoadBalancer + NodePort + ClusterIP

     NodePort의 확장된 개념이며, 외부의 LoadBalancer를 이용하여 외부에서 접근 가능하도록 하는 서비스 타입

     기본적으로 클라우드 서비스 환경에서 지원 On-premise에서는 애드온설치 필요

   - ExternalName

     Kubernetes Cluster 내부의 pod가 외부의 특정 도메인에 쉽게 접근할 수 있도록 하는 서비스 타입

     Kubernetes Cluster 외부의 도메인 주소가 변경되는 경우 해당 주소를 참조하는 컨테이너 이미지 재작성 필요

      → ExternalName 서비스를 사용시, 애플리케이션을 다시 작성할 필요가 없어지게 된다.

     

<전체실습>

 LoadBalancer → NodePort 가 가르키는 Node의 Port → Cluster IP → Pod 

 LoadBalancer : 현재 on-premise 테스트환경이므로 metallb 애드온을 통해 loadbalancer 서비스 리소스 활용

 

##### 외부 네트워크에서 접속 테스트를 위한 manifest files 작성 #####
##### replicaset 생성 #####
vagrant@kube-control1:~/work/20210831$ cat myapp-rs.yaml 
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myapp-rs
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp-rs
  template:
    metadata:
      labels:
        app: myapp-rs
    spec:
      containers:
      - name: myapp
        image: devops2341/go-myweb:latest
        ports:
        - containerPort: 8080
          protocol: TCP

##### session affinity 설정 #####
vagrant@kube-control1:~/work/20210831$ cat myapp-svc-ses-aff.yaml 
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc-ses-aff
spec:
  sessionAffinity: ClientIP
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: myapp-rs

##### cluster ip 설정 #####
vagrant@kube-control1:~/work/20210831$ cat myapp-svc-clusterip.yaml
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc-clusterip
spec:
  type: ClusterIP
  ports:
  - name: myapp-port
    port: 80
    targetPort: 8080
  selector:
    app: myapp-rs

##### node port 설정 #####
vagrant@kube-control1:~/work/20210831$ cat myapp-svc-nodeport.yaml 
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc-nodeport
spec:
  type: NodePort
  selector:
    app: myapp-rs
  ports:
  - port: 80
    targetPort: 8080
    nodePort: 30000

##### 여기까지 설정 : IP+PORT으로 외부에서 접속 가능 ( control plane, node의 IP + port 30000 )#####

##### loadbalancer 설정 #####
vagrant@kube-control1:~/work/20210831$ cat myapp-svc-lb.yaml
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc-loadbalancer
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: myapp-rs

vagrant@kube-control1:~/work/20210831$ kubectl get services
NAME                     TYPE           CLUSTER-IP      EXTERNAL-IP       PORT(S)        AGE
kubernetes               ClusterIP      10.96.0.1       <none>            443/TCP        7d20h
myapp-svc-clusterip      ClusterIP      10.100.138.93   <none>            80/TCP         156m
myapp-svc-loadbalancer   LoadBalancer   10.108.221.7    192.168.200.200   80:30286/TCP   5s
myapp-svc-nodeport       NodePort       10.97.242.100   <none>            80:30000/TCP   18m
myapp-svc-ses-aff        ClusterIP      10.102.211.98   <none>            80/TCP         125m
test-svc-namedport       ClusterIP      10.108.16.205   <none>            80/TCP         102m

##### loadbalancer 서비스에 할당해준 192.168.200.200:80 으로 외부에서 pod까지 접근 가능 #####
+ curl 로 테스트 시 : 정상적으로 다른 replica(pod)에 번갈아가면서 요청 확인가능
+ 웹브라우저 테스트 시 : 하나의 replica에만 요청 → 웹브라우저 cache때문

+ 라운드로빈형태로 lb가 실행되지만, session affinity가 동작중이므로 처음연결된 replica(pod)로 연결
 

##### externalname 설정 #####
vagrant@kube-control1:~/work/20210831$ cat myapp-svc-externalname.yaml
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc-externalname
spec:
  type: ExternalName
  externalName: www.google.com

vagrant@kube-control1:~/work/20210831$ kubectl get services
NAME                     TYPE           CLUSTER-IP      EXTERNAL-IP       PORT(S)        AGE
kubernetes               ClusterIP      10.96.0.1       <none>            443/TCP        7d20h
myapp-svc-clusterip      ClusterIP      10.100.138.93   <none>            80/TCP         170m
myapp-svc-externalname   ExternalName   <none>          www.google.com    <none>         5s
myapp-svc-loadbalancer   LoadBalancer   10.108.221.7    192.168.200.200   80:30286/TCP   14m
myapp-svc-nodeport       NodePort       10.97.242.100   <none>            80:30000/TCP   33m
myapp-svc-ses-aff        ClusterIP      10.102.211.98   <none>            80/TCP         139m
test-svc-namedport       ClusterIP      10.108.16.205   <none>            80/TCP         117m

 

 - 인그레스 (Ingress)

    L7 LoadBalancer 기능을 제공하는 Kubernetes object

    NodePort와 LoadBalancer 타입의 서비스가 L4 수준에서 동작하지만, 인그레스는 L7 수준에서 동작

    NodePort와 LoadBalancer 타입의 service object는 애플리케이션마다 생성필요.

     → 인그레스는 하나의 리소스만으로 각 애플리케이션에 트래픽 전달이 가능

         ※ https://kubernetes.github.io/ingress-nginx/deploy/

     → on-premise 환경이므로 bare-metal 배포버전으로 설치

<Ingress nginx Controller 설치>

##### ① Ingress nginx Controller 설치 #####
vagrant@kube-control1:~$ kubectl create -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.47.0/deploy/static/provider/baremetal/deploy.yaml
→ 1.00 릴리즈 버전으로 에러 발생 → 0.47로 진행

##### ② ingress nginx Controller : running 상태 확인 #####
vagrant@kube-control1:~$ kubectl get pods -n ingress-nginx
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-d6wds        0/1     Completed   0          12m
ingress-nginx-admission-patch-jnhxp         0/1     Completed   0          12m
ingress-nginx-controller-6cb6fdd64b-kcr8l   1/1      Running     0          12m


#####  ③ 서비스 manifests 편집 #####
vagrant@kube-control1:~$ kubectl edit services -n ingress-nginx ingress-nginx-controller
spec:
 Cluster IP
 externalIPs:
  - 192.168.200.21    → 각 노드들의 ip 입력
  - 192.168.200.22
  - 192.168.200.23
 externalTrafficpolicy : Cluster

service/ingress-nginx-controller edited

##### ④ 서비스 수정결과 확인 : ingress 설치완료 #####
vagrant@kube-control1:~$ kubectl get services -n ingress-nginx   (수정전)
NAME                                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.108.206.128   <none>        80:31006/TCP,443:31890/TCP   7m6s
ingress-nginx-controller-admission   ClusterIP   10.109.80.0      <none>        443/TCP                      7m6s

vagrant@kube-control1:~$ kubectl get services -n ingress-nginx   (수정후)
NAME                                 TYPE        CLUSTER-IP       EXTERNAL-IP                                    PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.108.206.128   192.168.200.21,192.168.200.22,192.168.200.23   80:31006/TCP,443:31890/TCP   10m
ingress-nginx-controller-admission   ClusterIP   10.109.80.0      <none>                                         443/TCP                      10m

##### ⑤ ingress서비스를 실행할 앱,노드포트,ingress manifests 작성/실행  #####

vagrant@kube-control1:~$ cat myapp-rs.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myapp-rs
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp-rs
  template:
    metadata:
      labels:
        app: myapp-rs
    spec:
      containers:
      - name: myapp
        image: devops2341/go-myweb:latest
        ports:
        - containerPort: 8080
          protocol: TCP

vagrant@kube-control1:~$ cat myapp-np.yaml
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc-np
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 8080
    nodePort: 31111
  selector:
    app: myapp-rs

vagrant@kube-control1:~$ cat myapp-ing.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: myapp-ing
spec:
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: myapp-svc-np
          servicePort: 80

vagrant@kube-control1:~$ kubectl create -f myapp-rs.yaml
replicaset.apps/myapp-rs created
vagrant@kube-control1:~$ kubectl create -f myapp-np.yaml
service/myapp-svc-np created
vagrant@kube-control1:~$ kubectl create -f myapp-ing.yaml
Warning:networking.k8s.io/v1beta1 Ingress is deprecated in v1.19+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
ingress.networking.k8s.io/myapp-ing created

##### ⑥ 설정적용 확인  #####

vagrant@kube-control1:~$ kubectl get pods,deployments,replicasets -n ingress-nginx
NAME                                            READY   STATUS      RESTARTS   AGE
pod/ingress-nginx-admission-create-d6wds        0/1     Completed   0          31m
pod/ingress-nginx-admission-patch-jnhxp         0/1     Completed   0          31m
pod/ingress-nginx-controller-6cb6fdd64b-kcr8l   1/1     Running     0          31m

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ingress-nginx-controller   1/1     1            1           31m

NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/ingress-nginx-controller-6cb6fdd64b   1         1         1       31m

vagrant@kube-control1:~$ kubectl get pods,deployments,replicasets -n default
NAME                 READY   STATUS    RESTARTS   AGE
pod/myapp-rs-54fks   1/1     Running   0          2m10s
pod/myapp-rs-8g9wk   1/1     Running   0          2m10s
pod/myapp-rs-txjm6   1/1     Running   0          2m10s

NAME                       DESIRED   CURRENT   READY   AGE
replicaset.apps/myapp-rs   3         3         3       2m10s

vagrant@kube-control1:~$ kubectl describe ingress
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
Name:             myapp-ing
Namespace:        default
Address:          192.168.200.22
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
  Host               Path  Backends
  ----               ----  --------
  myapp.example.com
                     /   myapp-svc-np:80 (192.168.119.148:8080,192.168.233.227:8080,192.168.9.108:8080)
Annotations:         <none>
Events:
  Type    Reason  Age                    From                      Message
  ----    ------  ----                   ----                      -------
  Normal  Sync    2m22s (x2 over 2m58s)  nginx-ingress-controller  Scheduled for sync

vagrant@kube-control1:~$ kubectl get ingresses
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
NAME        CLASS    HOSTS               ADDRESS          PORTS   AGE
myapp-ing   <none>   myapp.example.com   192.168.200.22   80      3m16s

##### ⑦ 테스트  #####

vagrant@kube-control1:~$ curl --resolve myapp.example.com:80:192.168.200.22 
Hello World!
myapp-rs-54fks
vagrant@kube-control1:~$ curl --resolve myapp.example.com:80:192.168.200.22 http://myapp.example.com/\?det
ail\=header
Hello World!
myapp-rs-8g9wk

[Request Headers]
        GET /?detail=header HTTP/1.1
        X-Forwarded-For: [10.0.2.15]
        X-Forwarded-Host: [myapp.example.com]
        X-Forwarded-Port: [80]
        X-Forwarded-Proto: [http]
        User-Agent: [curl/7.68.0]
        Accept: [*/*]
        X-Request-Id: [6ba116ca538f9a3a1ad81f8828c21c8f]
        X-Real-Ip: [10.0.2.15]
        X-Scheme: [http]

※ 실제 존재하지 않는 도메인이므로 control plane의 /etc/hosts 편집
192.168.200.22 myapp.example.com  → 줄 추가
저장후 curl 명령으로 테스트시 hosts 파일을 우선하여 탐색하므로 확인가능
vagrant@kube-control1:~$ curl http://myapp.example.com
Hello World!
myapp-rs-txjm6

 

728x90

---

 - Headless

   서비스의 ClusterIP가 아닌 개별 pod로 직접 접근할 필요가 있는 경우에 사용하는 서비스 타입

   service가 ip를 갖지 않는다. 

##### headless manifests 작성 #####
vagrant@kube-control1:~/work/20210831$ cat myapp-svc-headless.yaml
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc-headless
spec:
  clusterIP: None
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: myapp-rs-headless

vagrant@kube-control1:~/work/20210831$ cat myapp-rc-headless.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myapp-rs-headless
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp-rs-headless
  template:
    metadata:
      labels:
        app: myapp-rs-headless
    spec:
      containers:
      - name: myapp
        image: devops2341/go-myweb:latest
        ports:
        - containerPort: 8080
          protocol: TCP


##### headless manifests 실행 #####

vagrant@kube-control1:~/work/20210831$ kubectl create -f myapp-rc-headless.yaml
replicaset.apps/myapp-rs-headless created
vagrant@kube-control1:~/work/20210831$ kubectl create -f myapp-svc-headless.yaml
service/myapp-svc-headless created



##### 확인 #####

vagrant@kube-control1:~/work/20210831$ kubectl get services
NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
kubernetes           ClusterIP   10.96.0.1      <none>        443/TCP        8d
myapp-svc-headless   ClusterIP   None           <none>        80/TCP         6s → cluster ip가 할당되지 않음

vagrant@kube-control1:~/work/20210831$ kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
myapp-rs-headless-5ms8f   1/1     Running   0          34s
myapp-rs-headless-66fwt   1/1     Running   0          34s
myapp-rs-headless-j9dwd   1/1     Running   0          34s

vagrant@kube-control1:~/work/20210831$ kubectl get replicasets
NAME                DESIRED   CURRENT   READY   AGE
myapp-rs-headless   3         3         3       46s

vagrant@kube-control1:~/work/20210831$ kubectl get endpoints myapp-svc-headless
NAME                 ENDPOINTS                                                      AGE
myapp-svc-headless   192.168.119.144:8080,192.168.233.218:8080,192.168.9.107:8080   81s → endpoint : pods의 ip

vagrant@kube-control1:~/work/20210831$ kubectl get pods -o wide
NAME                      READY   STATUS    RESTARTS   AGE     IP                NODE         NOMINATED NODE   READINESS GATES
myapp-rs-headless-5ms8f   1/1     Running   0          104s    192.168.9.107     kube-node1   <none>           <none>
myapp-rs-headless-66fwt   1/1     Running   0          104s    192.168.233.218   kube-node2   <none>           <none>
myapp-rs-headless-j9dwd   1/1     Running   0          104s    192.168.119.144   kube-node3   <none>           <none>

##### headless manifests 작성#####
vagrant@kube-control1:~$ kubectl run nettool -it --image devops2341/network-multitool:v1 --rm bash
bash-5.1# curl http://192.168.9.107:8080
Hello World!
myapp-rs-headless-5ms8f
bash-5.1# host myapp-svc-headless
myapp-svc-headless.default.svc.cluster.local has address 192.168.9.107
myapp-svc-headless.default.svc.cluster.local has address 192.168.119.144
myapp-svc-headless.default.svc.cluster.local has address 192.168.233.218

 

 

 

 

728x90
Comments