CKA

[CKA] Services & Networking

테런 2023. 5. 7. 23:12
  • CKA 시험 비중 (20%)
  • Pod Network
CNI에서 관리하는 포드 간 통신에 사용되는 클러스터 전체 네트워크

 

  • Service Network
Service discovery를 위해 kube-proxy가 관리하는 Cluster-wide 범위의 Virtual IP(Cluster IP)
부하분산, Web 단일진입점(LB) Kubernetes Network Proxy 각각의 Node에서 실행되고, Kubernetes Service API에 정의된 서비스를 각 노드에서 반영 (kube-proxy 역할: iptables rule을 설정하고 외부 네트워크와 Pod를 연결)

 

  • Service Type - ClusterIP(default)
* Pod 그룹(동일한 서비스를 지원하는 Pod 모음)의 단일 진입점 (Virtual IP:LB) 생성
* Selector의 label이 동일한 Pod들을 그룹으로 묶어 단일 진입점 (Virtual IP:LB) 생성
* 클러스터 내부에서만 사용가능
* Service Type 생략 시 deafult로 설정
* 랜덤하게 10.96.0.0/12 범위에서 할당 -> 고정으로도 설정 가능

 

  • 실습
- 동일한 서비스를 제공하는 Pod 그룹에 ClusterIP 생성하기
deployment name: web, image: nginx, port:80, replicas:2
service name: web, type: clusterIP, port: 80
$ kubectl create deployment web --image=nginx --port=80 --replicas=2 --dry-run=client -o yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: web
  name: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: web
    spec:
      containers:
      - image: nginx
        name: nginx
        ports:
        - containerPort: 80
        resources: {}
status: {}

$ kubectl create deployment web --image=nginx --port=80 --replicas=2                 
deployment.apps/web created

$ kubectl get pod -o wide | grep web
web-cff6559d7-72lmx           1/1     Running   0               4m46s   10.244.2.2     minikube-m03   <none>           <none>
web-cff6559d7-qfc4x           1/1     Running   0               4m46s   10.244.3.2     minikube-m04   <none>           <none>

$ kubectl expose deployment web --type=ClusterIP --port=80 --target-port=80 --dry-run=client -o yaml
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: web
  name: web
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: web
  type: ClusterIP
status:
  loadBalancer: {}

$ kubectl expose deployment web --type=ClusterIP --port=80 --target-port=80                          
service/web exposed

$ kubectl get svc web
NAME   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
web    ClusterIP   10.105.239.84   <none>        80/TCP    15s

$ kubectl exec ${Pod Name} -i -t -- bash -il
$ root@web-cff6559d7-72lmx:/# curl 10.105.239.84
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

 

  • Service Type - NodePort
* ClusterIP가 생성된 후 모든 Worker Node에 외부에서 접속 가능한 포트가 예약
* 모든 노드를 대상으로 외부 접속 가능한 포트를 예약
* Default NodePort 범위: 30000-32767
* ClusterIP를 생성 후 NodePort를 예약

 

  • Network Policy
* Kubernetes가 지원하는 Pod 통신 접근 제한
* 일종의 방화벽으로 Pod로 트래픽이 들어오고(Inbound), 나가는(Outbound) 것을 설정하는 정책
* Ingress 트래픽: Inbound 정책. 들어오는 트래픽을 허용할 것 인지 정의
* Egress 트래픽: Outbound 정책. 트래픽이 나갈 수 있는 허용 범위 정의
트래픽 컨트롤 정의
* ipBlock: 특정 IP 대역에서만 들어오는 트래픽만 받을 수 있다.
* podSelector: 특정 label을 가지고 있는 Pod들에서 들어오는 트래픽만 받을 수 있다.
* namespaceSelector: 특정 namespace로부터 들어오는 트래픽만 받을 수 있다.
* Protocol & Port: 특정 Protocol 또는 Port로 설정된 트래픽만 받을 수 있다.

 

  • 실습
- app: web 레이블을 가진 Pod에 특정 namespace의 Pod들만 접근 허용
$ kubectl run webpod --image=nginx --port=80 --labels=app=web --dry-run=client -o yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    app: web
  name: webpod
spec:
  containers:
  - image: nginx
    name: webpod
    ports:
    - containerPort: 80
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

$ kubectl run webpod --image=nginx --port=80 --labels=app=web                         
pod/webpod created

$ kubectl get pod -o wide webpod
NAME     READY   STATUS    RESTARTS   AGE   IP           NODE           NOMINATED NODE   READINESS GATES
webpod   1/1     Running   0          9s    10.244.3.3   minikube-m04   <none>           <none>

$ kubectl create namespace dev
namespace/dev created

$ kubectl create namespace prod
namespace/prod created

$ kubectl label namespaces prod purpose=production
namespace/prod labeled

$ kubectl label namespaces dev purpose=development
namespace/dev labeled

$ kubectl get namespaces -L purpose
NAME              STATUS   AGE   PURPOSE
default           Active   16d   
dev               Active   43s   development
grafana           Active   13d   
ingress-nginx     Active   16d   
kube-node-lease   Active   16d   
kube-public       Active   16d   
kube-system       Active   16d   
prod              Active   41s   production

$ kubectl get ns --show-labels
NAME              STATUS   AGE   LABELS
default           Active   16d   kubernetes.io/metadata.name=default
dev               Active   59s   kubernetes.io/metadata.name=dev,purpose=development
grafana           Active   13d   kubernetes.io/metadata.name=grafana
ingress-nginx     Active   16d   app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx,kubernetes.io/metadata.name=ingress-nginx
kube-node-lease   Active   16d   kubernetes.io/metadata.name=kube-node-lease
kube-public       Active   16d   kubernetes.io/metadata.name=kube-public
kube-system       Active   16d   kubernetes.io/metadata.name=kube-system
prod              Active   57s   kubernetes.io/metadata.name=prod,purpose=production

$ vi web-allow-prod.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: web-allow-prod
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: web
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              purpose: production
      ports:
        - protocol: TCP
          port: 80
          
$ kubectl apply -f web-allow-prod.yaml 
networkpolicy.networking.k8s.io/web-allow-prod created

$ kubectl get networkpolicies                   
NAME             POD-SELECTOR   AGE
web-allow-prod   app=web        18s

$ kubectl describe networkpolicies                   
Name:         web-allow-prod
Namespace:    default
Created on:   2023-05-07 18:02:33 +0900 KST
Labels:       <none>
Annotations:  <none>
Spec:
  PodSelector:     app=web
  Allowing ingress traffic:
    To Port: 80/TCP
    From:
      NamespaceSelector: purpose=production
  Allowing egress traffic:
    <none> (Selected pods are isolated for egress connectivity)
  Policy Types: Ingress, Egress
  
$ kubectl run testpod -it --rm --image=centos:7 -n dev -- /bin/bash

 

  • Ingress
* L7(애플리케이션 계층) 스위치 역할을 논리적으로 수행
* 클러스터로 접근하는 URL 별로 다른 서비스에 트래픽을 분산
* Service에 외부 URL을 제공, 트래픽을 로드밸런싱, SSL 인증서 처리, Virtual Hosting 지정

 

  • Core DNS
* 쿠버네티스 클러스터에서 사용하는 DNS
* 클러스터 내의 모든 Service에는 DNS 네임이 할당
* 클러스터에서 동작되는 모든 Pod의 /etc/resolv.conf에는 kube-dns가 namespace로 정의되어 있다.
cat /etc/resolv.conf
nameserver 10.96.0.10
search <namespace>.svc.cluster.local svc.cluster.local cluster.local
* 특정 Pod에서 service name이나 pod name으로 접근 가능

 

  • 실습
- Core DNS 테스트
$ kubectl create deployment web --image=nginx --port=80 --replicas=2
deployment.apps/web created

$ kubectl expose deployment web --port=80
service/web exposed

$ kubectl get deployments.apps     
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
web    2/2     2            2           24s

$ kubectl get svc             
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   30m
web          ClusterIP   10.103.65.140   <none>        80/TCP    16s

$ kubectl run dns-test --image=busybox -it --rm -- /bin/sh
If you don't see a command prompt, try pressing enter.
/ # cat /etc/resolv.conf 
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
/ # nslookup 10.103.65.140
Server:		10.96.0.10
Address:	10.96.0.10:53

140.65.103.10.in-addr.arpa	name = web.default.svc.cluster.local

 

  • 실습
- image nginx를 사용하는 resolver pod를 생성하고, resolver-service라는 service를 구성합니다.
- 클러스터 내에서 service와 pod 이름을 조회할 수 있는지 테스트합니다.
dns 조회에 사용하는 pod 이미지는 busybox이고, service와 pod 이름 조회는 nslookup을 사용합니다.
service 조회 결과는 nginx.svc에 pod name 조회 결과는 nginx.pod 파일에 기록합니다.
$ kubectl run resolver --image=nginx
pod/resolver created

$ kubectl expose pod resolver --port=80 --name=resolver-service
service/resolver-service exposed

$ kubectl get pod resolver
NAME       READY   STATUS    RESTARTS   AGE
resolver   1/1     Running   0          37s

$ kubectl get pod resolver -o wide
NAME       READY   STATUS    RESTARTS   AGE   IP            NODE       NOMINATED NODE   READINESS GATES
resolver   1/1     Running   0          40s   10.244.0.10   minikube   <none>           <none>

$ kubectl get svc resolver-service
NAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
resolver-service   ClusterIP   10.111.159.14   <none>        80/TCP    29s

$ kubectl run test --image=busybox -it --rm -- /bin/sh
If you don't see a command prompt, try pressing enter.
/ # nslookup 10.244.0.10
Server:		10.96.0.10
Address:	10.96.0.10:53

10.0.244.10.in-addr.arpa	name = 10-244-0-10.resolver-service.default.svc.cluster.local

/ # nslookup 10.111.159.14
Server:		10.96.0.10
Address:	10.96.0.10:53

14.159.111.10.in-addr.arpa	name = resolver-service.default.svc.cluster.local

/ # exit
Session ended, resume using 'kubectl attach test -c test -i -t' command when the pod is running
pod "test" deleted

$ vi nginx.pod
$ vi nginx.svc
$ cat nginx.pod 
Server:		10.96.0.10
Address:	10.96.0.10:53

10.0.244.10.in-addr.arpa	name = 10-244-0-10.resolver-service.default.svc.cluster.local

$ cat nginx.svc
Server:		10.96.0.10
Address:	10.96.0.10:53

14.159.111.10.in-addr.arpa	name = resolver-service.default.svc.cluster.local

 

출처: TTABAE-LEARN - 이성미 강사