Ssoon

[6주차] Ingress 본문

쿠버네티스 네트워크 스터디 3기

[6주차] Ingress

구구달스 2024. 10. 7. 21:54
CloudNet@ 가시다님이 진행하는 쿠버네티스 네트워크 스터디 3기

✅ 기본 환경

🧿 CloudFormation 스택을 배포합니다.

C:\Users\ssoon\KANS>curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/kans/kans-6w.yaml
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 12141  100 12141    0     0  21953      0 --:--:-- --:--:-- --:--:-- 22114

C:\Users\ssoon\KANS>curl -s ipinfo.io/ip
112.152.226.129

C:\Users\ssoon\KANS>aws cloudformation deploy --template-file kans-6w.yaml --stack-name mylab --parameter-overrides MyInstanceType=t3.xlarge KeyName=KANS_KEY SgIngressSshCidr=112.152.226.129/32 --region ap-northeast-2

Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - mylab

C:\Users\ssoon\KANS>ssh -i KANS_KEY.pem ubuntu@3.36.98.49
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 6.8.0-1015-aws x86_64)

🧿 Ingress-Nginx 컨트롤러 설정에 사용할  ingress-nginx-values.yaml 생성합니다.

  • Ingress NGINX 컨트롤러를 NodePort 방식으로 외부에 노출하며, HTTP는 포트 30080, HTTPS는 포트 30443을 사용하도록 설정합니다.
  • 컨트롤러는 "k3s-s" 노드에서만 실행되도록 제한되며, 메트릭 수집과 Prometheus를 위한 모니터링을 활성화합니다.
(⎈|default:N/A) root@k3s-s:~# cat <<EOT> ingress-nginx-values.yaml
controller:
  service:
    type: NodePort
    nodePorts:
      http: 30080
      https: 30443
  nodeSelector:
    kubernetes.io/hostname: "k3s-s"
  metrics:
    enabled: true
  serviceMonitor:
      enabled: true
EOT

🧿 Helm을 사용하여 Ingress NGINX를 설치할 준비합니다.

  • Helm에 Ingress NGINX의 Helm 차트 저장소를 추가
  • 현재 Helm에 등록된 차트 저장소의 목록을 출력
  • Helm 저장소에 있는 차트들의 최신 버전을 업데이트
(⎈|default:N/A) root@k3s-s:~# helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
"ingress-nginx" has been added to your repositories

(⎈|default:N/A) root@k3s-s:~# helm repo list
NAME            URL
ingress-nginx   https://kubernetes.github.io/ingress-nginx

(⎈|default:N/A) root@k3s-s:~# helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "ingress-nginx" chart repository
Update Complete. ⎈Happy Helming!⎈

🧿 Helm을 사용해 ingress-nginx 배포합니다.

  • helm install: Helm을 사용하여 차트를 설치하는 명령어입니다.
  • ingress-nginx: 설치될 Helm 릴리스의 이름입니다.
  • ingress-nginx/ingress-nginx: ingress-nginx 차트를 사용하여 Ingress NGINX를 설치합니다.
  • -f ingress-nginx-values.yaml: ingress-nginx-values.yaml 파일에서 사용자 정의 설정을 사용하겠다는 의미입니다.
  • --namespace ingress: ingress라는 네임스페이스에 설치하겠다는 의미입니다.
  • --version 4.11.2: Helm 차트의 버전을 지정하는 옵션입니다.
(⎈|default:N/A) root@k3s-s:~# kubectl create ns ingress
namespace/ingress created
(⎈|default:N/A) root@k3s-s:~# helm install ingress-nginx ingress-nginx/ingress-nginx -f ingress-nginx-values.yaml --namespace ingress --version 4.11.2
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /etc/rancher/k3s/k3s.yaml
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /etc/rancher/k3s/k3s.yaml
NAME: ingress-nginx
LAST DEPLOYED: Mon Oct  7 19:08:14 2024
NAMESPACE: ingress
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
The ingress-nginx controller has been installed.
Get the application URL by running these commands:
  export HTTP_NODE_PORT=30080
  export HTTPS_NODE_PORT=30443
  export NODE_IP="$(kubectl get nodes --output jsonpath="{.items[0].status.addresses[1].address}")"

  echo "Visit http://${NODE_IP}:${HTTP_NODE_PORT} to access your application via HTTP."
  echo "Visit https://${NODE_IP}:${HTTPS_NODE_PORT} to access your application via HTTPS."

An example Ingress that makes use of the controller:
  apiVersion: networking.k8s.io/v1
  kind: Ingress
  metadata:
    name: example
    namespace: foo
  spec:
    ingressClassName: nginx
    rules:
      - host: www.example.com
        http:
          paths:
            - pathType: Prefix
              backend:
                service:
                  name: exampleService
                  port:
                    number: 80
              path: /
    # This section is only required if TLS is to be enabled for the Ingress
    tls:
      - hosts:
        - www.example.com
        secretName: example-tls

If TLS is enabled for the Ingress, a Secret containing the certificate and key must also be provided:

  apiVersion: v1
  kind: Secret
  metadata:
    name: example-tls
    namespace: foo
  data:
    tls.crt: <base64 encoded cert>
    tls.key: <base64 encoded key>
  type: kubernetes.io/tls

🧿 ingress 네임스페이스에서 실행 중인 모든 리소스를 확인합니다.

  • ingress-nginx-controller:
    • TYPE: NodePort 서비스로, 외부에서 30080 (HTTP), 30443 (HTTPS) 포트를 통해 접속 가능합니다.
    • CLUSTER-IP: 내부 클러스터 IP는 10.10.200.106이며, 외부에는 노출되지 않습니다.
    • PORT(S): 80:30080/TCP (HTTP), 443:30443/TCP (HTTPS) 포트가 노출되어 있습니다.
  • ingress-nginx-controller-admission:
    • TYPE: ClusterIP로 클러스터 내부에서만 접근 가능한 서비스입니다.
    • PORT(S): 443번 포트가 사용됩니다. 이 서비스는 Ingress Admission Webhook을 위한 것으로, 보안 정책을 적용하는 데 사용됩니다.
  • ingress-nginx-controller-metrics:
    • TYPE: ClusterIP로 클러스터 내부에서만 접근 가능한 메트릭 수집을 위한 서비스입니다.
    • PORT(S): 10254번 포트를 통해 NGINX 컨트롤러의 메트릭을 수집할 수 있습니다.
(⎈|default:N/A) root@k3s-s:~# kubectl get all -n ingress
NAME                                           READY   STATUS    RESTARTS   AGE
pod/ingress-nginx-controller-979fc89cf-ccfh2   1/1     Running   0          83s

NAME                                         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
service/ingress-nginx-controller             NodePort    10.10.200.106   <none>        80:30080/TCP,443:30443/TCP   83s
service/ingress-nginx-controller-admission   ClusterIP   10.10.200.247   <none>        443/TCP                      83s
service/ingress-nginx-controller-metrics     ClusterIP   10.10.200.157   <none>        10254/TCP                    83s

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

NAME                                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/ingress-nginx-controller-979fc89cf   1         1         1       83s

🧿 ingress-nginx-controller 서비스의 세부 정보를 확인합니다.

(⎈|default:N/A) root@k3s-s:~# kc describe svc -n ingress ingress-nginx-controller
Name:                     ingress-nginx-controller
Namespace:                ingress
Labels:                   app.kubernetes.io/component=controller
                          app.kubernetes.io/instance=ingress-nginx
                          app.kubernetes.io/managed-by=Helm
                          app.kubernetes.io/name=ingress-nginx
                          app.kubernetes.io/part-of=ingress-nginx
                          app.kubernetes.io/version=1.11.2
                          helm.sh/chart=ingress-nginx-4.11.2
Annotations:              meta.helm.sh/release-name: ingress-nginx
                          meta.helm.sh/release-namespace: ingress
Selector:                 app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.10.200.106
IPs:                      10.10.200.106
Port:                     http  80/TCP	#HTTP 트래픽은 80번 포트를 통해 수신됩니다.
TargetPort:               http/TCP	#트래픽은 80번 포트에서 컨테이너 내부의 http 포트로 전달됩니다.
NodePort:                 http  30080/TCP	#클러스터 외부에서 접근할 수 있는 NodePort는 30080번 포트입니다.
Endpoints:                172.16.0.3:80	#트래픽이 전달될 엔드포인트 Pod의 IP는 172.16.0.3이며, 80번 포트로 연결됩니다.
Port:                     https  443/TCP #HTTPS 트래픽은 443번 포트를 통해 수신됩니다.
TargetPort:               https/TCP	#트래픽은 443번 포트에서 컨테이너 내부의 https 포트로 전달됩니다.
NodePort:                 https  30443/TCP	#클러스터 외부에서 접근할 수 있는 NodePort는 30443번 포트입니다.
Endpoints:                172.16.0.3:443	#트래픽이 전달될 엔드포인트 Pod의 IP는 172.16.0.3이며, 443번 포트로 연결됩니다.
Session Affinity:         None	#이 서비스는 세션 연결이 특정 Pod에 고정되지 않도록 설정되어 있습니다.
External Traffic Policy:  Cluster	#외부 트래픽은 클러스터 내부에서 로드 밸런싱됩니다.
Events:                   <none>

🧿 ingress-nginx-controller 서비스의 externalTrafficPolicy Cluster에서 Local로 변경하는 Kubernetes 패치를 적용합니다.

  • 기존 상태 (Cluster):
    • 외부에서 들어오는 트래픽은 클러스터의 어느 노드로 들어오더라도 클러스터 내의 다른 노드로 라우팅되어 로드 밸런싱됩니다. 즉, 외부에서 접근한 IP가 실제로 트래픽을 처리한 노드의 IP와 일치하지 않을 수 있습니다.
  • 변경된 상태 (Local):
    • 외부에서 들어오는 트래픽은 해당 노드에 Ingress NGINX Pod가 존재하는 경우에만 처리됩니다. 이를 통해 트래픽을 처리하는 노드의 IP가 외부 클라이언트에게 노출되며, 클라이언트는 원래 요청한 노드의 IP로부터 응답을 받습니다. 이것은 Client IP를 보존하기 위해 사용됩니다.
      • Client IP 보존: Local로 설정하면, 클라이언트가 접근할 때 해당 클라이언트의 IP가 서비스에 그대로 전달됩니다. 이것은 클라이언트의 IP 주소를 로깅하거나 특정 IP 기반 규칙을 적용할 때 유용합니다.
(⎈|default:N/A) root@k3s-s:~# kubectl patch svc -n ingress ingress-nginx-controller -p '{"spec":{"externalTrafficPolicy": "Local"}}'
service/ingress-nginx-controller patched

🧿 ingress-nginx-controller ConfigMap 을 확인합니다.

(⎈|default:N/A) root@k3s-s:~# kc describe cm -n ingress ingress-nginx-controller
Name:         ingress-nginx-controller
Namespace:    ingress
Labels:       app.kubernetes.io/component=controller
              app.kubernetes.io/instance=ingress-nginx
              app.kubernetes.io/managed-by=Helm
              app.kubernetes.io/name=ingress-nginx
              app.kubernetes.io/part-of=ingress-nginx
              app.kubernetes.io/version=1.11.2
              helm.sh/chart=ingress-nginx-4.11.2
Annotations:  meta.helm.sh/release-name: ingress-nginx
              meta.helm.sh/release-namespace: ingress

Data
====
allow-snippet-annotations:
----
false

BinaryData
====

Events:
  Type    Reason  Age    From                      Message
  ----    ------  ----   ----                      -------
  Normal  CREATE  2m30s  nginx-ingress-controller  ConfigMap ingress/ingress-nginx-controller

디플로이먼트와 서비스를 생성

🧿 svc1-pod.yaml

  • Deployment:
    • replicas: 1: NGINX를 실행하는 1개의 Pod을 배포합니다.
    • selector template labels app: websrv로 일치하는 Pod이 배포됩니다.
    • image: nginx: NGINX 웹 서버를 실행하는 컨테이너입니다.
  • Service:
    • port: 9001: 클러스터 내에서 서비스가 노출될 포트.
    • targetPort: 80: NGINX 컨테이너 내부에서 사용하는 포트.
    • selector: app: websrv: app: websrv 레이블이 붙은 Pod에 트래픽을 전달.
    • type: ClusterIP: 클러스터 내부에서만 접근할 수 있는 기본 서비스 유형.
cat <<EOT> svc1-pod.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy1-websrv
spec:
  replicas: 1
  selector:
    matchLabels:
      app: websrv
  template:
    metadata:
      labels:
        app: websrv
    spec:
      containers:
      - name: pod-web
        image: nginx
---
apiVersion: v1
kind: Service
metadata:
  name: svc1-web
spec:
  ports:
    - name: web-port
      port: 9001
      targetPort: 80
  selector:
    app: websrv
  type: ClusterIPe
EOT

🧿 svc2-pod.yaml

(⎈|default:N/A) root@k3s-s:~# cat <<EOT> svc2-pod.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy2-guestsrv
spec:
  replicas: 2
  selector:
    matchLabels:
      app: guestsrv
  template:
    metadata:
      labels:
        app: guestsrv
    spec:
      containers:
      - name: pod-guest
        image: gcr.io/google-samples/kubernetes-bootcamp:v1
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: svc2-guest
spec:
  ports:
    - name: guest-port
      port: 9002
      targetPort: 8080
  selector:
    app: guestsrv
  type: NodePort
EOT

🧿 svc3-pod.yaml

(⎈|default:N/A) root@k3s-s:~# cat <<EOT> svc3-pod.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy3-adminsrv
spec:
  replicas: 3
  selector:
    matchLabels:
      app: adminsrv
  template:
    metadata:
      labels:
        app: adminsrv
    spec:
      containers:
      - name: pod-admin
        image: k8s.gcr.io/echoserver:1.5
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: svc3-admin
spec:
  ports:
    - name: admin-port
      port: 9003
      targetPort: 8080
  selector:
    app: adminsrv
EOT

🧿 Kubernetes에서 특정 노드에 taint를 추가하여 해당 노드에서 어떤 Pod도 스케줄링되지 않도록 설정하고 3 개의 yaml파일을 배포합니다.

  • taint nodes: 특정 노드에 taint를 추가하는 명령어입니다.
  • k3s-s: taint를 적용할 노드의 이름입니다.
  • role=controlplane: taint의 키와 값 쌍입니다. 여기서 role은 키이고 controlplane은 값입니다.
  • NoSchedule: taint의 효과입니다. 이 설정은 해당 노드에 스케줄링할 수 있는 Pod가 없도록 만듭니다. 즉, 이 노드에는 taint와 일치하지 않는 Pod만 배치될 수 있습니다.

  • taint의 의미
    • Taint는 Kubernetes에서 노드가 특정 Pod를 수용할 수 없도록 하는 방법입니다. 이는 주로 다음과 같은 경우에 사용됩니다:
    • 제어 플레인 노드 보호: 일반적으로 제어 플레인 노드(control plane node)에서는 특정 Pod(예: 워커 노드에서만 실행해야 하는 Pod)를 실행하고 싶지 않을 때 taint를 사용합니다.
    • 리소스 제한: 특정 노드에서 리소스가 부족할 경우, 그 노드에 Pod가 스케줄링되는 것을 방지할 수 있습니다.
  • Taint 설정 후 Pod 스케줄링
    • Pod 스케줄링: NoSchedule taint가 있는 노드에는 기본적으로 taint와 일치하지 않는 Pod가 스케줄링되지 않습니다. 만약 role=controlplane에 해당하는 Pod가 아니면, 해당 노드에서 실행할 수 없습니다.
    • Toleration: 특정 Pod에 taint를 무시하도록 허용하려면, 해당 Pod의 사양에 toleration을 추가해야 합니다. 이를 통해 taint가 설정된 노드에도 Pod를 배치할 수 있습니다.
(⎈|default:N/A) root@k3s-s:~# kubectl taint nodes k3s-s role=controlplane:NoSchedule
node/k3s-s tainted

(⎈|default:N/A) root@k3s-s:~# kubectl apply -f svc1-pod.yaml,svc2-pod.yaml,svc3-pod.yaml
deployment.apps/deploy1-websrv created
service/svc1-web created
deployment.apps/deploy2-guestsrv created
service/svc2-guest created
deployment.apps/deploy3-adminsrv created
service/svc3-admin created

🧿 현재 클러스터의 Pods, Services, 그리고 Endpoints 정보를 확인합니다.

  • service/kubernetes: 기본 Kubernetes 서비스로, 클러스터 내부에서 API 서버에 접근할 수 있게 해줍니다.
  • svc1-web:
    • TYPE: ClusterIP, 클러스터 내부에서만 접근 가능합니다.
    • CLUSTER-IP: 10.10.200.253, 클러스터 내부의 IP 주소.
    • PORT(S): 9001/TCP, 9001 포트에서 서비스가 노출됩니다.
  • svc2-guest:
    • TYPE: NodePort, 외부에서 접근할 수 있습니다.
    • PORT(S): 9002 포트에서 클러스터 내부로 요청을 수신하며, 외부에서는 31011 포트로 접근할 수 있습니다.
  • svc3-admin:
    • TYPE: ClusterIP, 클러스터 내부에서만 접근 가능합니다.
    • PORT(S): 9003/TCP, 9003 포트에서 서비스가 노출됩니다.

  • endpoints/svc1-web: 172.16.1.7:80, svc1-web 서비스가 연결된 Pod의 IP와 포트.
  • endpoints/svc2-guest: 172.16.1.8:8080, 172.16.2.5:8080 두 개의 Pod에 연결되어 있습니다.
  • endpoints/svc3-admin: 172.16.1.9:8080, 172.16.2.6:8080, 172.16.3.4:8080 세 개의 Pod에 연결되어 있습니다.
(⎈|default:N/A) root@k3s-s:~# kubectl get pod,svc,ep
NAME                                    READY   STATUS    RESTARTS   AGE
pod/deploy1-websrv-5c6b88bd77-lsmrc     1/1     Running   0          14s
pod/deploy2-guestsrv-649875f78b-6p2zq   1/1     Running   0          14s
pod/deploy2-guestsrv-649875f78b-rg8n6   1/1     Running   0          14s
pod/deploy3-adminsrv-7c8f8b8c87-74mkc   1/1     Running   0          14s
pod/deploy3-adminsrv-7c8f8b8c87-bdds5   1/1     Running   0          14s
pod/deploy3-adminsrv-7c8f8b8c87-wn48r   1/1     Running   0          14s

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
service/kubernetes   ClusterIP   10.10.200.1     <none>        443/TCP          25m
service/svc1-web     ClusterIP   10.10.200.253   <none>        9001/TCP         14s
service/svc2-guest   NodePort    10.10.200.110   <none>        9002:31011/TCP   14s
service/svc3-admin   ClusterIP   10.10.200.98    <none>        9003/TCP         14s

NAME                   ENDPOINTS                                         AGE
endpoints/kubernetes   192.168.10.10:6443                                25m
endpoints/svc1-web     172.16.1.7:80                                     14s
endpoints/svc2-guest   172.16.1.8:8080,172.16.2.5:8080                   14s
endpoints/svc3-admin   172.16.1.9:8080,172.16.2.6:8080,172.16.3.4:8080   14s

인그레스(정책) 생성

🧿 Kubernetes에서 Ingress 리소스를 정의합니다.

  • path:
    • 경로를 정의하며, 이 경로에 대한 요청이 들어올 때 해당하는 백엔드 서비스로 라우팅됩니다.
    • path: /: 루트 경로로 모든 요청을 svc1-web 서비스의 80번 포트로 라우팅합니다.
    • path: /guest: /guest 경로로 들어오는 요청은 svc2-guest 서비스의 8080번 포트로 라우팅됩니다.
    • path: /admin: /admin 경로로 들어오는 요청은 svc3-admin 서비스의 8080번 포트로 라우팅됩니다.
  • pathType: Prefix
    • 경로 매칭 방식을 정의합니다. 
    • Prefix는 지정한 경로로 시작하는 모든 요청이 이 경로 규칙에 매칭된다는 의미입니다.
(⎈|default:N/A) root@k3s-s:~# cat <<EOT> ingress1.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-1
  annotations:
    #nginx.ingress.kubernetes.io/upstream-hash-by: "true"
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: svc1-web
            port:
              number: 80
      - path: /guest
        pathType: Prefix
        backend:
          service:
            name: svc2-guest
            port:
              number: 8080
      - path: /admin
        pathType: Prefix
        backend:
          service:
            name: svc3-admin
            port:
              number: 8080
EOT

🧿 생성한 Ingress 리소스의 상태와 구성을 확인합니다.

  • HOSTS: 모든 호스트에 대해(*) 요청을 수신하도록 설정되어 있습니다.
  • ADDRESS: 아직 외부 IP 주소가 할당되지 않았음을 나타냅니다. NGINX Ingress Controller가 외부 트래픽을 수신하도록 설정될 경우에 외부 IP가 나타날 것입니다.
  • PORTS: HTTP(80) 포트를 사용하고 있음을 나타냅니다.

  • Rules:
    • Host: 모든 호스트에 대해 요청을 수신합니다.
    • Path:
      • /: 이 경로로 들어오는 요청은 svc1-web 서비스의 80번 포트로 라우팅됩니다.
      • /guest: 이 경로로 들어오는 요청은 svc2-guest 서비스의 8080번 포트로 라우팅됩니다.
      • /admin: 이 경로로 들어오는 요청은 svc3-admin 서비스의 8080번 포트로 라우팅됩니다.
(⎈|default:N/A) root@k3s-s:~# kubectl apply -f ingress1.yaml
ingress.networking.k8s.io/ingress-1 created

(⎈|default:N/A) root@k3s-s:~# kubectl get ingress
NAME        CLASS   HOSTS   ADDRESS   PORTS   AGE
ingress-1   nginx   *                 80      6s

(⎈|default:N/A) root@k3s-s:~# kc describe ingress ingress-1
Name:             ingress-1
Labels:           <none>
Namespace:        default
Address:
Ingress Class:    nginx
Default backend:  <default>
Rules:
  Host        Path  Backends
  ----        ----  --------
  *
              /        svc1-web:80 ()
              /guest   svc2-guest:8080 ()
              /admin   svc3-admin:8080 ()
Annotations:  <none>
Events:
  Type    Reason  Age   From                      Message
  ----    ------  ----  ----                      -------
  Normal  Sync    10s   nginx-ingress-controller  Scheduled for sync

🧿 NGINX Ingress Controller의 설정 파일인 nginx.conf 을 확인합니다.

  • location /guest/:
    • /guest/ 경로에 대한 요청이 들어오면 이 블록이 처리합니다.
    • set $namespace "default";: 현재 네임스페이스가 default임을 설정합니다.
    • set $ingress_name "ingress-1";: 해당 요청이 ingress-1이라는 Ingress 리소스와 관련됨을 설정합니다.
    • set $service_name "svc2-guest";: 요청이 svc2-guest 서비스로 라우팅되도록 설정합니다.
    • set $service_port "8080";: svc2-guest 서비스의 포트는 8080임을 설정합니다.
  • location /admin/:
    • /admin/ 경로에 대한 요청이 들어오면 이 블록이 처리합니다.
    • 위와 같은 방식으로 설정되어 있으며, 요청은 svc3-admin 서비스의 8080 포트로 라우팅됩니다.
  • location /:
    • 기본 경로(/)에 대한 요청이 들어오면 이 블록이 처리됩니다.
    • 요청은 svc1-web 서비스의 80 포트로 라우팅됩니다.
(⎈|default:N/A) root@k3s-s:~# kubectl exec deploy/ingress-nginx-controller -n ingress -it -- cat /etc/nginx/nginx.conf | grep 'location /' -A5
                location /guest/ {

                        set $namespace      "default";
                        set $ingress_name   "ingress-1";
                        set $service_name   "svc2-guest";
                        set $service_port   "8080";
--
                location /admin/ {

                        set $namespace      "default";
                        set $ingress_name   "ingress-1";
                        set $service_name   "svc3-admin";
                        set $service_port   "8080";
--
                location / {

                        set $namespace      "default";
                        set $ingress_name   "ingress-1";
                        set $service_name   "svc1-web";
                        set $service_port   "80";
 ...

인그레스를 통한 내부 접속

🧿 Kubernetes 클러스터에서 Ingress 리소스인 ingress-1에 대한 정보와 상태를 확인합니다.

  • HOSTS: * - 모든 호스트에 대해 라우팅이 가능하다는 것을 의미합니다.
  • ADDRESS: 10.10.200.106 - Ingress가 서비스하는 IP 주소입니다.
  • PORTS: 80 - Ingress가 리스닝하고 있는 포트입니다.

  • Rules: Ingress의 라우팅 규칙을 나열합니다.
    • Host: * - 모든 호스트에 대한 요청을 수락합니다.
    • Path:
      • /: 요청을 svc1-web의 80 포트로 라우팅합니다.
      • /guest: 요청을 svc2-guest의 8080 포트로 라우팅합니다.
      • /admin: 요청을 svc3-admin의 8080 포트로 라우팅합니다.
(⎈|default:N/A) root@k3s-s:~# kubectl get ingress
NAME        CLASS   HOSTS   ADDRESS         PORTS   AGE
ingress-1   nginx   *       10.10.200.106   80      2m9s

(⎈|default:N/A) root@k3s-s:~# kubectl describe ingress ingress-1 | sed -n "5, \$p"
Ingress Class:    nginx
Default backend:  <default>
Rules:
  Host        Path  Backends
  ----        ----  --------
  *
              /        svc1-web:80 ()
              /guest   svc2-guest:8080 ()
              /admin   svc3-admin:8080 ()
Annotations:  <none>
Events:
  Type    Reason  Age                 From                      Message
  ----    ------  ----                ----                      -------
  Normal  Sync    2m (x2 over 2m22s)  nginx-ingress-controller  Scheduled for sync

🧿 현재 설정된 Ingress를 통해 각각의 서비스에 접근할 수 있는 URL을 확인합니다.

(⎈|default:N/A) root@k3s-s:~# echo -e "Ingress1 sv1-web URL = http://$(curl -s ipinfo.io/ip):30080"
echo -e "Ingress1 sv2-guest URL = http://$(curl -s ipinfo.io/ip):30080/guest"
echo -e "Ingress1 sv3-admin URL = http://$(curl -s ipinfo.io/ip):30080/admin"
Ingress1 sv1-web URL = http://3.36.98.49:30080
Ingress1 sv2-guest URL = http://3.36.98.49:30080/guest
Ingress1 sv3-admin URL = http://3.36.98.49:30080/admin

🧿 curl -s 3.36.98.49:30080 명령어를 실행하여 ingress 동작을 확인합니다.

C:\Users\ssoon\KANS>curl -s 3.36.98.49:30080
<!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>

=======================================================================================

(⎈|default:N/A) root@k3s-s:~# kubetail -n ingress -l app.kubernetes.io/component=controller
Will tail 1 logs...
ingress-nginx-controller-979fc89cf-ccfh2
[ingress-nginx-controller-979fc89cf-ccfh2] 112.152.226.129 - - [07/Oct/2024:10:28:25 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/8.8.0" 79 0.002 [default-svc1-web-80] [] 172.16.1.7:80 615 0.002 200 83a45519f1d089d5975a957a6c98be1b

🧿curl -s 3.36.98.49:30080/guest 명령어를 실행하여 ingress 동작을 확인합니다.

C:\Users\ssoon\KANS>curl -s 3.36.98.49:30080/guest
Hello Kubernetes bootcamp! | Running on: deploy2-guestsrv-649875f78b-6p2zq | v=1

=======================================================================================

(⎈|default:N/A) root@k3s-s:~# kubetail -n ingress -l app.kubernetes.io/component=controller
[ingress-nginx-controller-979fc89cf-ccfh2] 112.152.226.129 - - [07/Oct/2024:10:29:36 +0000] "GET /guest HTTP/1.1" 200 103 "-" "curl/8.8.0" 84 0.010 [default-svc2-guest-8080] [] 172.16.2.5:8080 103 0.010 200 2fc722b9ebfa9e5acc070d4d624d2b58

🧿curl -s 3.36.98.49:30080/admin 명령어를 실행하여 ingress 동작을 확인합니다.

C:\Users\ssoon\KANS>curl -s 3.36.98.49:30080/admin


Hostname: deploy3-adminsrv-7c8f8b8c87-wn48r

Pod Information:
        -no pod information available-

Server values:
        server_version=nginx: 1.13.0 - lua: 10008

Request Information:
        client_address=172.16.0.3
        method=GET
        real path=/admin
        query=
        request_version=1.1
        request_uri=http://3.36.98.49:8080/admin

Request Headers:
        accept=*/*
        host=3.36.98.49:30080
        user-agent=curl/8.8.0
        x-forwarded-for=112.152.226.129
        x-forwarded-host=3.36.98.49:30080
        x-forwarded-port=80
        x-forwarded-proto=http
        x-forwarded-scheme=http
        x-real-ip=112.152.226.129
        x-request-id=193f855eac3c0f72ff0e0c354b736d68
        x-scheme=http

Request Body:
        -no body in request-
        
=======================================================================================

(⎈|default:N/A) root@k3s-s:~# kubetail -n ingress -l app.kubernetes.io/component=controller
[ingress-nginx-controller-979fc89cf-ccfh2] 112.152.226.129 - - [07/Oct/2024:10:31:58 +0000] "GET /admin HTTP/1.1" 200 658 "-" "curl/8.8.0" 84 0.002 [default-svc3-admin-8080] [] 172.16.3.4:8080 841 0.003 200 193f855eac3c0f72ff0e0c354b736d68

🧿 노드에서 패킷을 캡처해서 확인합니다.


🧿 모든 Deployment, Service, 및 Ingress 리소스를 삭제합니다.

(⎈|default:N/A) root@k3s-s:~# kubectl delete deployments,svc,ingress --all
deployment.apps "deploy1-websrv" deleted
deployment.apps "deploy2-guestsrv" deleted
deployment.apps "deploy3-adminsrv" deleted
service "kubernetes" deleted
service "svc1-web" deleted
service "svc2-guest" deleted
service "svc3-admin" deleted
ingress.networking.k8s.io "ingress-1" deleted
ingress.networking.k8s.io "ingress-2" deleted

Host 기반 라우팅

🧿 ingress2.yaml

    • kans.com 도메인에 / 경로로 접근 시, svc3-admin 서비스의 8080 포트로 요청을 전달합니다.
    • 서브 도메인(예: sub.kans.com)에서 /echo 경로로 접근 시, 동일하게 svc3-admin 서비스의 8080 포트로 요청을 전달합니다.
    • ingress2.yaml 파일의 kans.com $MYDOMAIN1 변수 값인 ssoon.com으로 치환합니다.
(⎈|default:N/A) root@k3s-s:~# cat <<EOT> ingress2.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-2
spec:
  ingressClassName: nginx
  rules:
  - host: kans.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: svc3-admin
            port:
              number: 8080
  - host: "*.kans.com"
    http:
      paths:
      - path: /echo
        pathType: Prefix
        backend:
          service:
            name: svc3-admin
            port:
              number: 8080
EOT

(⎈|default:N/A) root@k3s-s:~# MYDOMAIN1=ssoon.com
(⎈|default:N/A) root@k3s-s:~# sed -i "s/kans.com/$MYDOMAIN1/g" ingress2.yaml

🧿 두 개의 YAML 파일(ingress2.yaml  svc3-pod.yaml)이 클러스터에 배포합니다.

(⎈|default:N/A) root@k3s-s:~# kubectl apply -f ingress2.yaml,svc3-pod.yaml
ingress.networking.k8s.io/ingress-2 created
deployment.apps/deploy3-adminsrv created
service/svc3-admin created

🧿 curl 명령어를 통해 요청한 IP 주소(예: 3.36.98.49:30080)가 404 Not Found 응답을 확인합니다.

C:\Users\ssoon\KANS>curl 3.36.98.49:30080 -v
...
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
...

C:\Users\ssoon\KANS>curl 3.36.98.49:30080/echo -v
...
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
...

 

🧿 Ingress 설정을 확인합니다.

  • Host: ssoon.com, *.ssoon.com
  • Backend: svc3-admin:8080 
  • Address: 10.10.200.106 (이 주소는 Ingress Controller가 노출하는 IP입니다.)
(⎈|default:N/A) root@k3s-s:~# kubectl get ingress
NAME        CLASS   HOSTS                   ADDRESS         PORTS   AGE
ingress-1   nginx   *                       10.10.200.106   80      84m
ingress-2   nginx   ssoon.com,*.ssoon.com   10.10.200.106   80      25s

(⎈|default:N/A) root@k3s-s:~# kubectl describe ingress ingress-2
Name:             ingress-2
Labels:           <none>
Namespace:        default
Address:          10.10.200.106
Ingress Class:    nginx
Default backend:  <default>
Rules:
  Host         Path  Backends
  ----         ----  --------
  ssoon.com
               /   svc3-admin:8080 ()
  *.ssoon.com
               /echo   svc3-admin:8080 ()
Annotations:   <none>
Events:
  Type    Reason  Age                From                      Message
  ----    ------  ----               ----                      -------
  Normal  Sync    20s (x2 over 29s)  nginx-ingress-controller  Scheduled for sync

 

🧿 curl 명령어를 사용하여 ssoon.com:30080에 대한 요청을 시도한 결과를 확인합니다.

  1. curl ssoon.com:30080 -v
    • 기본 경로(/)에 대한 요청이 이루어졌습니다. 이 요청은 정상적으로 파드에 도달하였습니다.
  2. curl ssoon.com:30080/admin
    • /admin 경로에 대한 요청이 이루어졌습니다. 이 요청도 성공적으로 해당 파드로 라우팅되어 응답을 받았습니다.
  3. curl ssoon.com:30080/echo
    • ingress-2 설정에 따라 /echo 경로에 대한 요청이 svc3-admin 서비스로 라우팅되었습니다. 파드에서 이 요청을 처리하고 응답을 반환했습니다. 응답으로 받은 호스트 이름이 deploy3-adminsrv인 것으로 보아, 이 경로에 대한 처리가 잘 이루어졌습니다.
  4. curl ssoon.com:30080/echo/1
    • /echo/1 경로에 대한 요청이 이루어졌습니다. 이 요청도 성공적으로 처리되었음을 나타냅니다.
C:\Users\ssoon\KANS>curl ssoon.com:30080 -v
...
Hostname: deploy3-adminsrv-7c8f8b8c87-wn48r
...

C:\Users\ssoon\KANS>curl ssoon.com:30080/admin
...
Hostname: deploy3-adminsrv-7c8f8b8c87-bdds5
...

C:\Users\ssoon\KANS>curl ssoon.com:30080/echo
...
Hostname: deploy3-adminsrv-7c8f8b8c87-bdds5
...

C:\Users\ssoon\KANS>curl ssoon.com:30080/echo/1
...
Hostname: deploy3-adminsrv-7c8f8b8c87-bdds5
...

🧿 test.ssoon.com:30080로의 요청 중 일부는 404 Not Found 오류를 반환하고 있으며, 일부는 호스트 이름과 함께 응답을 받고 있습니다

  • curl test.ssoon.com:30080  curl test.ssoon.com:30080/admin
    • 두 요청 모두 404 Not Found 응답을 받았습니다. 이는 해당 경로에 대한 리소스가 존재하지 않음을 의미합니다. 즉, 이 요청들은 Ingress 설정에 따른 매핑 규칙에 의해 처리되지 않고 있습니다.
  • curl test.ssoon.com:30080/echo  curl test.ssoon.com:30080/echo/1
    • 이 요청들은 성공적으로 파드로 라우팅되어 응답을 받고 있습니다. 응답에는 파드의 호스트 이름이 포함되어 있어, 이 경로가 올바르게 매핑되어 있음을 나타냅니다.
C:\Users\ssoon\KANS>curl test.ssoon.com:30080
<html>
<head><title>404 Not Found</title></head>
...

C:\Users\ssoon\KANS>curl test.ssoon.com:30080/admin
<html>
<head><title>404 Not Found</title></head>
...

C:\Users\ssoon\KANS>curl test.ssoon.com:30080/echo
...
Hostname: deploy3-adminsrv-7c8f8b8c87-bdds5
...

C:\Users\ssoon\KANS>curl test.ssoon.com:30080/echo/1
...
Hostname: deploy3-adminsrv-7c8f8b8c87-bdds5
...

🧿 모든 Deployment, Service, 및 Ingress 리소스를 삭제합니다.

(⎈|default:N/A) root@k3s-s:~# kubectl delete deployments,svc,ingress --all
deployment.apps "deploy3-adminsrv" deleted
service "kubernetes" deleted
service "svc3-admin" deleted
ingress.networking.k8s.io "ingress-2" deleted

카나리 업그레이드

🧿 canary-svc1-pod.yaml

(⎈|default:N/A) root@k3s-s:~# cat <<EOT> canary-svc1-pod.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dp-v1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: svc-v1
  template:
    metadata:
      labels:
        app: svc-v1
    spec:
      containers:
      - name: pod-v1
        image: k8s.gcr.io/echoserver:1.5
        ports:
        - containerPort: 8080
      terminationGracePeriodSeconds: 0
---
apiVersion: v1
kind: Service
metadata:
  name: svc-v1
spec:
  ports:
    - name: web-port
      port: 9001
      targetPort: 8080
  selector:
    app: svc-v1
EOT

🧿 canary-svc2-pod.yaml

(⎈|default:N/A) root@k3s-s:~# cat <<EOT> canary-svc2-pod.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dp-v2
spec:
  replicas: 3
  selector:
    matchLabels:
      app: svc-v2
  template:
    metadata:
      labels:
        app: svc-v2
    spec:
      containers:
      - name: pod-v2
        image: k8s.gcr.io/echoserver:1.6
        ports:
        - containerPort: 8080
      terminationGracePeriodSeconds: 0
---
apiVersion: v1
kind: Service
metadata:
  name: svc-v2
spec:
  ports:
    - name: web-port
      port: 9001
      targetPort: 8080
  selector:
    app: svc-v2
EOT

🧿 두 개의 YAML 파일을 통해 Kubernetes 클러스터에 리소스를 배포합니다.

(⎈|default:N/A) root@k3s-s:~# kubectl apply -f canary-svc1-pod.yaml,canary-svc2-pod.yaml
deployment.apps/dp-v1 created
service/svc-v1 created
deployment.apps/dp-v2 created
service/svc-v2 created

🧿 Kubernetes 클러스터 내의 서비스, 엔드포인트, 그리고 파드의 상태를 확인합니다.

  • service/kubernetes: Kubernetes 시스템 서비스로, API 서버에 접근하기 위한 서비스입니다. ClusterIP 타입이며, 클러스터 내에서만 접근 가능하고 외부에서는 접근할 수 없습니다.
  • service/svc-v1: 앞서 생성한 svc-v1 서비스로, ClusterIP 타입이며 클러스터 내부 IP 10.10.200.239를 가지고 있습니다. 이 서비스는 포트 9001로 요청을 받아 8080 포트에서 리슨하는 포드로 트래픽을 전달합니다.
  • service/svc-v2: 마찬가지로 svc-v2 서비스이며, 10.10.200.238 IP를 가지고 있습니다. 같은 방식으로 포트 9001에서 요청을 수신합니다.

  • endpoints/kubernetes: Kubernetes API 서버의 엔드포인트입니다.
  • endpoints/svc-v1: svc-v1 서비스와 연결된 포드들의 IP 주소입니다. 세 개의 포드가 8080 포트를 통해 요청을 받을 수 있음을 나타냅니다.
  • endpoints/svc-v2: svc-v2 서비스와 연결된 포드들의 IP 주소입니다. 마찬가지로 세 개의 포드가 연결되어 있습니다.
(⎈|default:N/A) root@k3s-s:~# kubectl get svc,ep,pod
NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/kubernetes   ClusterIP   10.10.200.1     <none>        443/TCP    3m27s
service/svc-v1       ClusterIP   10.10.200.239   <none>        9001/TCP   9s
service/svc-v2       ClusterIP   10.10.200.238   <none>        9001/TCP   9s

NAME                   ENDPOINTS                                          AGE
endpoints/kubernetes   192.168.10.10:6443                                 3m27s
endpoints/svc-v1       172.16.1.11:8080,172.16.2.8:8080,172.16.3.6:8080   9s
endpoints/svc-v2       172.16.1.12:8080,172.16.2.9:8080,172.16.3.7:8080   9s

NAME                         READY   STATUS    RESTARTS   AGE
pod/dp-v1-8684d45558-4jtbh   1/1     Running   0          9s
pod/dp-v1-8684d45558-5phxh   1/1     Running   0          9s
pod/dp-v1-8684d45558-kmgk4   1/1     Running   0          9s
pod/dp-v2-7757c4bdc-2bf9w    1/1     Running   0          9s
pod/dp-v2-7757c4bdc-4pm5k    1/1     Running   0          9s
pod/dp-v2-7757c4bdc-8xmnv    1/1     Running   0          9s

 

🧿 각 파드의 Hostname nginx 서버 버전 정보를 확인합니다.

(⎈|default:N/A) root@k3s-s:~# for pod in $(kubectl get pod -o wide -l app=svc-v1 |awk 'NR>1 {print $6}'); do curl -s $pod:8080 | egrep '(Hostname|nginx)'; done
Hostname: dp-v1-8684d45558-4jtbh
        server_version=nginx: 1.13.0 - lua: 10008
Hostname: dp-v1-8684d45558-5phxh
        server_version=nginx: 1.13.0 - lua: 10008
Hostname: dp-v1-8684d45558-kmgk4
        server_version=nginx: 1.13.0 - lua: 10008
        
(⎈|default:N/A) root@k3s-s:~# for pod in $(kubectl get pod -o wide -l app=svc-v2 |awk 'NR>1 {print $6}'); do curl -s $pod:8080 | egrep '(Hostname|nginx)'; done
Hostname: dp-v2-7757c4bdc-2bf9w
        server_version=nginx: 1.13.1 - lua: 10008
Hostname: dp-v2-7757c4bdc-4pm5k
        server_version=nginx: 1.13.1 - lua: 10008
Hostname: dp-v2-7757c4bdc-8xmnv
        server_version=nginx: 1.13.1 - lua: 10008

🧿 Kubernetes Ingress 리소스를 정의합니다.

  • nginx.ingress.kubernetes.io/canary: "true": 이 Ingress가 카나리 배포임을 나타냅니다. Nginx Ingress 컨트롤러가 이 설정을 사용하여 카나리 배포를 처리합니다.
  • nginx.ingress.kubernetes.io/canary-weight: "10": 전체 요청 중 10%의 트래픽이 svc-v2 서비스로 전송됨을 나타냅니다. 나머지 90%는 이전 버전인 svc-v1 서비스로 전송됩니다.
  • kans.com 호스트에 대한 모든 HTTP 요청을 svc-v2 서비스의 8080 포트로 라우팅하되, 전체 요청의 10%만 svc-v2로 전송하고 나머지 90%는 이전 버전인 svc-v1 서비스로 전송하는 카나리 배포를 정의합니다.
(⎈|default:N/A) root@k3s-s:~# cat <<EOT> canary-ingress1.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-canary-v1
spec:
  ingressClassName: nginx
  rules:
  - host: kans.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: svc-v1
            port:
              number: 8080
EOT

(⎈|default:N/A) root@k3s-s:~# cat <<EOT> canary-ingress2.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-canary-v2
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
  ingressClassName: nginx
  rules:
  - host: kans.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: svc-v2
            port:
              number: 8080
EOT

🧿 canary-ingress1.yaml  canary-ingress2.yaml 파일의 모든 kans.com 문자열은 ssoon.com으로 변경합니다.

(⎈|default:N/A) root@k3s-s:~# MYDOMAIN1=ssoon.com
sed -i "s/kans.com/$MYDOMAIN1/g" canary-ingress1.yaml
sed -i "s/kans.com/$MYDOMAIN1/g" canary-ingress2.yaml

🧿 Kubernetes 클러스터에 두 개의 Ingress 리소스를 배포합니다.

(⎈|default:N/A) root@k3s-s:~# kubectl apply -f canary-ingress1.yaml,canary-ingress2.yaml
ingress.networking.k8s.io/ingress-canary-v1 created
ingress.networking.k8s.io/ingress-canary-v2 created

🧿 curl 명령어를 사용하여 ssoon.com:30080에 HTTP 요청을 보냈을 때의 응답 결과를 확인합니다.

  • 현재 설정한 Ingress와 서비스가 잘 작동하고 있으며, 요청이 올바르게 처리되고 있음을 보여줍니다. 
C:\Users\ssoon\KANS>curl -s ssoon.com:30080
...
Hostname: dp-v1-8684d45558-kmgk4

Pod Information:
        -no pod information available-

Server values:
        server_version=nginx: 1.13.0 - lua: 10008
...

🧿 curl 명령어를 사용하여 sssoon.com:30080에 HTTP 요청을 100번 보내고, 그 결과에서 Nginx 서버의 버전을 추출하고 확인합니다.

  • 89 server_version=nginx: 1.13.0 - lua: 10008:
    • Nginx 버전 1.13.0이 89번 요청에 대한 응답으로 돌아왔음을 나타냅니다.
  • 11 server_version=nginx: 1.13.1 - lua: 10008:
    • Nginx 버전 1.13.1이 11번 요청에 대한 응답으로 돌아왔음을 나타냅니다.
ssoon@DESKTOP-UQRJB87 MINGW64 ~
$ for i in {1..100};  do curl -s ssoon.com:30080 | grep nginx ; done | sort | uniq -c | sort -nr
     89         server_version=nginx: 1.13.0 - lua: 10008
     11         server_version=nginx: 1.13.1 - lua: 10008

🧿 ingress-canary-v2를 업데이트하여 트래픽의 50%를  라우팅하도록 변경합니다.

  • 트래픽 분배: canary-weight를 50으로 설정하면, 들어오는 요청의 50%가 svc-v2로, 나머지 50%는 svc-v1로 라우팅됩니다.
(⎈|default:N/A) root@k3s-s:/tmp# kubectl annotate --overwrite ingress ingress-canary-v2 nginx.ingress.kubernetes.io/canary-weight=50
ingress.networking.k8s.io/ingress-canary-v2 annotated

🧿 curl 명령어를 사용하여 sssoon.com:30080에 HTTP 요청을 100번 보내고, 그 결과에서 Nginx 서버의 버전을 추출하고 확인합니다.

  • 53 server_version=nginx: 1.13.0 - lua: 10008:
    • Nginx 버전 1.13.0이 53번 요청에 대한 응답으로 돌아왔음을 나타냅니다.
  • 47 server_version=nginx: 1.13.1 - lua: 10008:
    • Nginx 버전 1.13.1이 47번 요청에 대한 응답으로 돌아왔음을 나타냅니다.
ssoon@DESKTOP-UQRJB87 MINGW64 ~
$ for i in {1..100};  do curl -s ssoon.com:30080 | grep nginx ; done | sort | uniq -c | sort -nr
     53         server_version=nginx: 1.13.0 - lua: 10008
     47         server_version=nginx: 1.13.1 - lua: 10008

🧿 모든 Deployment, Service, 및 Ingress 리소스를 삭제합니다.

(⎈|default:N/A) root@k3s-s:/tmp# kubectl delete deployments,svc,ingress --all
deployment.apps "dp-v1" deleted
deployment.apps "dp-v2" deleted
service "kubernetes" deleted
service "svc-v1" deleted
service "svc-v2" deleted
ingress.networking.k8s.io "ingress-canary-v1" deleted
ingress.networking.k8s.io "ingress-canary-v2" deleted

HTTPS 처리 (TLS 종료)

🧿 svc-pod.yaml

(⎈|default:N/A) root@k3s-s:/tmp# cat <<EOT> svc-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-https
  labels:
    app: https
spec:
  containers:
  - name: container
    image: k8s.gcr.io/echoserver:1.6
  terminationGracePeriodSeconds: 0
---
apiVersion: v1
kind: Service
metadata:
  name: svc-https
spec:
  selector:
    app: https
  ports:
  - port: 8080
EOT

🧿 ssl-termination-ingress.yaml

  • TLS 설정 (tls):
    • tls::
      • HTTPS 통신을 위해 TLS 설정을 정의합니다.
    • - hosts::
      • 이 TLS 설정을 적용할 호스트 목록을 정의합니다. 여기서는 kans.com을 사용합니다.
    • secretName: secret-https:
      • TLS 인증서와 개인 키를 포함하는 Kubernetes Secret의 이름입니다. 이 Secret은 Ingress가 HTTPS를 통해 안전하게 통신할 수 있도록 필요한 정보를 제공합니다.
(⎈|default:N/A) root@k3s-s:/tmp# cat <<EOT> ssl-termination-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: https
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - kans.com
    secretName: secret-https
  rules:
  - host: kans.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: svc-https
            port:
              number: 8080
EOT

🧿 Pod Service 를 배포합니다.

(⎈|default:N/A) root@k3s-s:/tmp# kubectl apply -f svc-pod.yaml
pod/pod-https created
service/svc-https created

🧿 ssl-termination-ingress.yaml 파일 내에서 kans.com이라는 도메인 이름을 ssoon.com으로  변경하고 배포합니다.

(⎈|default:N/A) root@k3s-s:/tmp# MYDOMAIN1=ssoon.com
echo $MYDOMAIN1
sed -i "s/kans.com/$MYDOMAIN1/g" ssl-termination-ingress.yaml
ssoon.com

(⎈|default:N/A) root@k3s-s:/tmp# kubectl apply -f ssl-termination-ingress.yaml
ingress.networking.k8s.io/https created

🧿 OpenSSL을 사용하여 TLS(SSL) 인증서를 생성합니다.

  • openssl:
    • OpenSSL은 SSL/TLS와 관련된 다양한 작업을 수행할 수 있습니다.
  • req:
    • req는 X.509 인증서 요청을 생성하는 OpenSSL 명령어입니다. 이 명령어를 사용하여 인증서 서명 요청(CSR) 또는 самоподписанный 인증서를 생성할 수 있습니다.
  • -x509:
    • 이 플래그는 X.509 인증서를 생성하라는 의미입니다. 즉, 개인 키를 사용하여 인증서를 직접 생성하겠다는 것입니다.
  • -nodes:
    • 이 플래그는 "No DES"의 약자로, 생성된 개인 키에 대한 암호화를 적용하지 않겠다는 의미입니다. 따라서 생성된 키는 암호화되지 않은 상태로 저장됩니다. 이는 서버에서 자동으로 인증서를 사용할 때 편리합니다.
  • -days 365:
    • 생성된 인증서의 유효 기간을 365일로 설정합니다. 이 기간이 지나면 인증서는 만료됩니다.
  • -newkey rsa:2048:
    • 새 RSA 개인 키를 생성하며, 키의 길이는 2048비트로 설정합니다.
  • -keyout tls.key:
    • 생성된 개인 키를 tls.key라는 파일에 저장합니다.
  • -out tls.crt:
    • 생성된 인증서를 tls.crt라는 파일에 저장합니다.
  • -subj "/CN=$MYDOMAIN1/O=$MYDOMAIN1":
    • 인증서의 주체 정보를 설정합니다.
    • CN(Common Name): 인증서에 대한 주체 이름으로 설정합니다. 여기서는 앞서 설정한 MYDOMAIN1 변수를 사용하여 도메인 이름을 지정합니다.
    • O(Organization): 조직 이름을 설정합니다. 여기에서도 MYDOMAIN1 변수를 사용하여 설정합니다.

  • 두 개의 파일이 생성됩니다:
  • tls.key: 개인 키 파일
  • tls.crt: 생성된 TLS 인증서 파일
(⎈|default:N/A) root@k3s-s:~# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=$MYDOMAIN1/O=$MYDOMAIN1"
.......+..........+..+.......+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...+......+...........+.......+.....+...+....+...+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.......+....+.....+.......+..+......+............+...+....+...........+......+.+...+......+...+........+.......+...+............+.....+..................+....+........+...+..................+....+......+...........+...+......+.......+..+......+.+.....+...+.......+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
....+..+.......+..+.+...+...........+...................+..+...................+......+..+.+..+...+.........+.......+.....+.........+....+..+......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.+.....+.+.....+....+.....+.+..+............+.+...+.....+...................+.....+.+.....+....+...+..+.............+..+.............+..+.+.....+......+.+........+....+..+...............+...+.+......+...+.....+...............+.......+...+..+.+.................+.+..+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.+.......+.........+.....+......+...+.+...............+.........+.....+......+......+....+.....+.+.....+.........+.+...+...........+......+.........+....+......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-----

(⎈|default:N/A) root@k3s-s:~# ls -al | grep tls
-rw-r--r--  1 root root 1168 Oct  7 22:32 tls.crt
-rw-------  1 root root 1704 Oct  7 22:32 tls.key

🧿 Kubernetes 클러스터 내에서 TLS 인증서를 사용하기 위한 Secret을 생성합니다.

  • tls:
    • 생성할 Secret의 유형을 지정합니다. 여기서는 TLS 인증서와 개인 키를 포함한 Secret을 생성합니다.
  • secret-https:
    • 생성할 Secret의 이름입니다. 이 이름은 이후에 Ingress 리소스에서 참조할 수 있습니다.
  • --key tls.key:
    • Secret에 포함될 개인 키 파일을 지정합니다. tls.key는 이전에 생성한 개인 키 파일입니다.
  • --cert tls.crt:
    • Secret에 포함될 인증서 파일을 지정합니다. tls.crt는 이전에 생성한 TLS 인증서 파일입니다.
(⎈|default:N/A) root@k3s-s:~# kubectl create secret tls secret-https --key tls.key --cert tls.crt
secret/secret-https created

🧿 Kubernetes 클러스터에서 생성한 secret-https Secret에 대한 정보를 확인합니다.

  • TYPE: Secret의 유형입니다. kubernetes.io/tls는 TLS 인증서와 개인 키를 포함하는 Secret을 나타냅니다.
  • DATA: Secret에 포함된 데이터 항목의 수입니다. 여기서는 2로, 이는 개인 키와 인증서 파일이 각각 하나씩 포함되어 있다는 것을 의미합니다.
(⎈|default:N/A) root@k3s-s:~# kubectl get secrets secret-https
NAME           TYPE                DATA   AGE
secret-https   kubernetes.io/tls   2      18s

🧿 secret-https라는 이름의 Secret에 대한 자세한 정보를 YAML 형식으로 출력하여 확인합니다.

  • data: Secret에 포함된 실제 데이터입니다. 이 경우에는 TLS 인증서와 개인 키가 포함되어 있습니다.
    • tls.crt: TLS 인증서의 Base64 인코딩된 값입니다.
    • tls.key: TLS 개인 키의 Base64 인코딩된 값입니다.
    • LS0tLS1CR...와 같이 생긴 문자열은 Base64로 인코딩된 데이터의 일부입니다. 이를 디코딩하면 원래의 인증서와 개인 키 정보를 확인할 수 있습니다.
(⎈|default:N/A) root@k3s-s:~# kubectl get secrets secret-https -o yaml
apiVersion: v1
data:
  tls.crt: LS0tLS1CR...
  tls.key: LS0tLS1CR...
metadata:
  creationTimestamp: "2024-10-07T13:33:40Z"
  name: secret-https
  namespace: default
  resourceVersion: "11157"
  uid: b5d983ab-1e52-46d8-a843-104b6c1574d2
type: kubernetes.io/tls

🧿 curl 명령어는 HTTPS 요청을 통해 Kubernetes 클러스터 내에서 실행 중인 Pod에 접근하고 응답을 확인합니다.

  • -L: HTTP 요청에 대해 리다이렉트를 따라가도록 하는 옵션입니다. 서버가 요청을 다른 위치로 리다이렉트하면 이를 따릅니다.
    • 리다이렉션 자동 따라가기: curl로 URL을 요청했을 때, 만약 그 URL이 리다이렉션을 통해 다른 URL로 이동하라고 하면, 기본적으로 curl은 그 새로운 URL로 자동으로 요청을 보내지 않습니다. 여기서 -L 옵션을 사용하면, curl이 리다이렉션을 따라가서 최종 URL에서 응답을 받을 수 있게 해줍니다.
  • -k: SSL 인증서 검증을 건너뛰는 옵션입니다. 
  • curl 명령어의 실행 결과는 HTTPS 요청이 성공적으로 처리되었으며, Nginx가 Pod에서 요청을 처리하는 모습을 보여줍니다
ssoon@DESKTOP-UQRJB87 MINGW64 ~
$ curl -Lk https://$MYDOMAIN1:30443
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   613    0   613    0     0  16687      0 --:--:-- --:--:-- --:--:-- 18029

Hostname: pod-https

Pod Information:
        -no pod information available-

Server values:
        server_version=nginx: 1.13.1 - lua: 10008

Request Information:
        client_address=172.16.0.3
        method=GET
        real path=/
        query=
        request_version=1.1
        request_uri=http://ssoon.com:8080/

Request Headers:
        accept=*/*
        host=ssoon.com:30443
        user-agent=curl/8.9.0
        x-forwarded-for=112.152.226.129
        x-forwarded-host=ssoon.com:30443
        x-forwarded-port=443
        x-forwarded-proto=https
        x-forwarded-scheme=https
        x-real-ip=112.152.226.129
        x-request-id=dd9bc837e62744356530fe661310c307
        x-scheme=https

Request Body:
        -no body in request-

🧿 Kubernetes 클러스터에서 ingress 정보를 확인합니다.

  • ingress-nginx-controller
    • NAMESPACE: ingress
    • NAME: ingress-nginx-controller
    • TYPE: NodePort
      • 클러스터 외부에서 접근할 수 있는 포트를 제공합니다. 노드의 IP 주소와 함께 특정 포트(여기서는 30080과 30443)로 요청을 수신합니다.
    • CLUSTER-IP: 10.10.200.106
      • 클러스터 내에서 이 서비스에 접근할 수 있는 IP 주소입니다.
    • EXTERNAL-IP: <none>
      • 외부에서 접근할 수 있는 IP가 설정되어 있지 않음을 나타냅니다. NodePort로 설정되어 있어 노드 IP를 통해 접근할 수 있습니다.
    • PORT(S): 80:30080/TCP, 443:30443/TCP
      • 클러스터 내의 80 포트는 외부의 30080 포트로, 443 포트는 외부의 30443 포트로 노출됩니다. 즉, HTTP 요청은 30080을 통해, HTTPS 요청은 30443을 통해 받을 수 있습니다.
  • ingress-nginx-controller-admission
    • NAMESPACE: ingress
    • NAME: ingress-nginx-controller-admission
    • TYPE: ClusterIP
      • 클러스터 내부에서만 접근할 수 있는 IP 주소를 제공합니다.
    • CLUSTER-IP: 10.10.200.247
      • 클러스터 내에서 이 서비스에 접근할 수 있는 IP 주소입니다.
    • EXTERNAL-IP: <none>
      • 외부에서 접근할 수 있는 IP가 설정되어 있지 않음을 나타냅니다.
    • PORT(S): 443/TCP
      • HTTPS 트래픽을 위해 443 포트를 사용합니다.
  • ingress-nginx-controller-metrics
    • NAMESPACE: ingress
    • NAME: ingress-nginx-controller-metrics
    • TYPE: ClusterIP
      • 클러스터 내부에서만 접근할 수 있는 IP 주소를 제공합니다.
    • CLUSTER-IP: 10.10.200.157
      • 클러스터 내에서 이 서비스에 접근할 수 있는 IP 주소입니다.
    • EXTERNAL-IP: <none>
      • 외부에서 접근할 수 있는 IP가 설정되어 있지 않음을 나타냅니다.
    • PORT(S): 10254/TCP
      • 메트릭 데이터를 수집하고 노출하기 위한 포트입니다.

  • ingress-nginx-controller는 외부에서 HTTP/HTTPS 요청을 수신하는 주요 서비스로, NodePort를 사용하여 외부와의 통신을 가능하게 합니다.
  • ingress-nginx-controller-admission과 ingress-nginx-controller-metrics는 클러스터 내부에서만 사용되는 서비스로, 각각 admission controller와 메트릭 수집을 담당합니다.
(⎈|default:N/A) root@k3s-s:~# kubectl get svc -A
NAMESPACE     NAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
default       kubernetes                           ClusterIP   10.10.200.1     <none>        443/TCP                      44m
default       svc-https                            ClusterIP   10.10.200.234   <none>        8080/TCP                     9m
ingress       ingress-nginx-controller             NodePort    10.10.200.106   <none>        80:30080/TCP,443:30443/TCP   3h30m
ingress       ingress-nginx-controller-admission   ClusterIP   10.10.200.247   <none>        443/TCP                      3h30m
ingress       ingress-nginx-controller-metrics     ClusterIP   10.10.200.157   <none>        10254/TCP                    3h30m
kube-system   kube-dns                             ClusterIP   10.10.200.10    <none>        53/UDP,53/TCP,9153/TCP       3h45m
kube-system   metrics-server                       ClusterIP   10.10.200.250   <none>        443/TCP                      3h45m

 

 

 

 

 

 

Comments