Overview
가시다님이 진행하시는 쿠버네티스 스터디 2주차가 되었다.
오늘은 쿠버네티스 네트워크에 대해 공부를 해보려고 한다.
2주차 과제 내용
[과제1]
파드간 통신 시 tcpdump 내용을 확인하고 관련 스샷을 올려주세요.
Pod 1 -> Pod 2 any 통신
Pod 1 -> Pod 2 ens5 통신
Pod 1 -> Pod 2 ens6 통신 실패
AWS VPC ENI는 첫번째 ENI1(ens5)로만 통신이 되도록 iptables나 라우팅 테이블이 그렇게 설정되어있다.
따라서 ENI2(ens6)으로는 통신되지 않는다.
[과제2]
어떤 방식을 사용하더라고 좋으니, 워커 노드 1대에 100대의 파드가 배포되게 설정하고 관련 스샷을 올려주세요
- 해결방안 : Prefix Delegation, WARM & MIN IP/Prefix Targets
Prefix Delegation을 사용하여 100대의 파드가 배포되게 설정해보자.
아래의 사이트를 참고하였다.
https://trans.yonghochoi.com/translations/aws_vpc_cni_increase_pods_per_node_limits.ko
결과 사진
작업 내용
kops 원클릭 배포를 사용하여 c5.large node 1대를 배포한다.
c5.large 스펙은 아래와 같다.
모델 | vCPU | 메모리(GiB) | 인스턴스 스토리지(GB) | 네트워크 대역폭(Gbps) | EBS 대역폭(Mbps) |
c5.large | 2 | 4 | EBS 전용 | 최대 10 | 최대 4,750 |
생성이 완료되었다.
- 확인해보니 t3.medium으로도 가능하다고 한다.
(somaz:N/A) [root@kops-ec2 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
i-074d6c35d90fc4c1d Ready node 46s v1.24.9
i-0b90857120855f2f6 Ready control-plane 2m6s v1.24.9
CNI 버전 확인
(somaz:N/A) [root@kops-ec2 ~]# kubectl describe daemonset aws-node --namespace kube-system | grep Image | cut -d "/" -f 2
amazon-k8s-cni-init:v1.11.4
amazon-k8s-cni:v1.11.4
c5.x 인스턴스의 ENI 정보를 확인한다.
# c5 타입의 정보(필터) 확인
(somaz:N/A) [root@kops-ec2 ~]# aws ec2 describe-instance-types --filters Name=instance-type,Values=c5.* \
> --query "InstanceTypes[].{Type: InstanceType, MaxENI: NetworkInfo.MaximumNetworkInterfaces, IPv4addr: NetworkInfo.Ipv4AddressesPerInterface}" \
> --output table
---------------------------------------
| DescribeInstanceTypes |
+----------+----------+---------------+
| IPv4addr | MaxENI | Type |
+----------+----------+---------------+
| 30 | 8 | c5.4xlarge |
| 15 | 4 | c5.xlarge |
| 50 | 15 | c5.metal |
| 30 | 8 | c5.12xlarge |
| 50 | 15 | c5.24xlarge |
| 30 | 8 | c5.9xlarge |
| 15 | 4 | c5.2xlarge |
| 10 | 3 | c5.large |
| 50 | 15 | c5.18xlarge |
+----------+----------+---------------+
Node의 Allocatable pod 개수를 확인한다.
(somaz:N/A) [root@kops-ec2 ~]# kubectl describe node |grep Allocatable: -A6
Allocatable:
cpu: 2
ephemeral-storage: 119703055367
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 3698676Ki
pods: 29
--
Allocatable:
cpu: 2
ephemeral-storage: 59763732382
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 3854320Ki
pods: 17
maxPods 개수를 늘린다.
(somaz:N/A) [root@kops-ec2 ~]# kops edit cluster
...
kubelet:
anonymousAuth: false
maxPods: 110
...
접두사 할당 모드 활성화(Enabling prefix assignment mode) 후 WARM_PREFIX_TARTGET을 1로 한다.
(somaz:N/A) [root@kops-ec2 ~]# kubectl set env daemonset aws-node -n kube-system ENABLE_PREFIX_DELEGATION=true
daemonset.apps/aws-node env updated
(somaz:N/A) [root@kops-ec2 ~]# kubectl set env ds aws-node -n kube-system WARM_PREFIX_TARGET=1
daemonset.apps/aws-node env updated
(somaz:N/A) [root@kops-ec2 ~]# kubectl describe daemonsets.apps -n kube-system aws-node | egrep 'ENABLE_PREFIX_DELEGATION|WARM_PREFIX_TARGET'
ENABLE_PREFIX_DELEGATION: true
WARM_PREFIX_TARGET: 1
ENABLE_PREFIX_DELEGATION: true
WARM_PREFIX_TARGET: 1
kops cluster update를 진행한다.
(somaz:N/A) [root@kops-ec2 ~]# kops update cluster --yes && echo && sleep 5 && kops rolling-update cluster
W0125 14:26:40.668176 4212 builder.go:231] failed to digest image "602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon-k8s-cni:v1.11.4"
W0125 14:26:41.129000 4212 builder.go:231] failed to digest image "602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon-k8s-cni-init:v1.11.4"
I0125 14:26:45.064912 4212 executor.go:111] Tasks: 0 done / 103 total; 48 can run
I0125 14:26:45.972186 4212 executor.go:111] Tasks: 48 done / 103 total; 21 can run
I0125 14:26:46.741629 4212 executor.go:111] Tasks: 69 done / 103 total; 28 can run
I0125 14:26:47.492451 4212 executor.go:111] Tasks: 97 done / 103 total; 3 can run
I0125 14:26:47.596862 4212 executor.go:111] Tasks: 100 done / 103 total; 3 can run
I0125 14:26:47.686129 4212 executor.go:111] Tasks: 103 done / 103 total; 0 can run
I0125 14:26:48.434643 4212 dns.go:238] Pre-creating DNS records
I0125 14:26:48.493909 4212 update_cluster.go:326] Exporting kubeconfig for cluster
kOps has set your kubectl context to somaz.link
W0125 14:26:48.512214 4212 update_cluster.go:350] Exported kubeconfig with no user authentication; use --admin, --user or --auth-plugin flags with `kops export kubeconfig`
Cluster changes have been applied to the cloud.
Changes may require instances to restart: kops rolling-update cluster
NAME STATUS NEEDUPDATE READY MIN TARGET MAX NODES
master-ap-northeast-2a NeedsUpdate 1 0 1 1 1 1
nodes-ap-northeast-2a NeedsUpdate 1 0 1 1 1 1
nodes-ap-northeast-2c Ready 0 0 0 0 0 0
Must specify --yes to rolling-update.
(somaz:N/A) [root@kops-ec2 ~]# kops rolling-update cluster --yes
업데이트 후 Node의 Allocatable pod 개수를 확인한다
(somaz:N/A) [root@kops-ec2 ~]# kubectl describe node |grep Allocatable: -A6
Allocatable:
cpu: 2
ephemeral-storage: 59763732382
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 3854328Ki
pods: 110
LimitRange 정책을 삭제한다.
(somaz:N/A) [root@kops-ec2 ~]# kubectl describe limitranges
Name: limits
Namespace: default
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Container cpu - - 100m - -
(somaz:N/A) [root@kops-ec2 ~]# kubectl delete limitranges limits
limitrange "limits" deleted
파드 100개가 생성되는지 nginx pod로 확인해본다.
(somaz:N/A) [root@kops-ec2 ~]# kubectl apply -f ~/pkos/2/nginx-dp.yaml
deployment.apps/nginx-deployment created
(somaz:N/A) [root@kops-ec2 ~]# kubectl scale deployment nginx-deployment --replicas=30
deployment.apps/nginx-deployment scaled
(somaz:N/A) [root@kops-ec2 ~]# kubectl get deployment nginx-deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 30/30 30 30 35s
(somaz:N/A) [root@kops-ec2 ~]# kubectl scale deployment nginx-deployment --replicas=100
deployment.apps/nginx-deployment scaled
(somaz:N/A) [root@kops-ec2 ~]# kubectl get deployment nginx-deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 100/100 100 100 100s
워커 노드에 들어가 네트워크를 확인해본다.
(somaz:N/A) [root@kops-ec2 ~]# aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value}" --filters Name=instance-state-name,Values=running --output table
---------------------------------------------------------------
| DescribeInstances |
+--------------------------------------------+----------------+
| InstanceName | PublicIPAdd |
+--------------------------------------------+----------------+
| master-ap-northeast-2a.masters.somaz.link | 52.78.92.100 |
| nodes-ap-northeast-2a.somaz.link | 3.36.61.175 |
| kops-ec2 | 54.180.9.94 |
+--------------------------------------------+----------------+
(somaz:N/A) [root@kops-ec2 ~]# W1PIP=3.36.61.175
(somaz:N/A) [root@kops-ec2 ~]# ssh -i ~/.ssh/id_rsa ubuntu@$W1PIP
ubuntu@i-0c1fa4e451a8e4f34:~$ ip -c link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 02:9f:34:f0:09:ce brd ff:ff:ff:ff:ff:ff
altname enp0s5
3: eni8ec657da2b7@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP mode DEFAULT group default
link/ether f6:cb:d4:bd:10:7b brd ff:ff:ff:ff:ff:ff link-netns cni-7b863180-b549-af51-90f6-461010a5f043
4: eni617b6dca1c7@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP mode DEFAULT group default
link/ether 0e:8e:97:c7:7d:a0 brd ff:ff:ff:ff:ff:ff link-netns cni-44c2a748-6dad-94b6-5cd0-fc11849ef512
5: eni5c7aa6ebe37@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP mode DEFAULT group default
link/ether da:09:bd:63:8b:9f brd ff:ff:ff:ff:ff:ff link-netns cni-a55591c4-ae4e-4fb5-1532-a78c78c336fd
6: eni09cf4ff0e85@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP mode DEFAULT group default
link/ether 72:0f:4f:3b:0c:f6 brd ff:ff:ff:ff:ff:ff link-netns cni-0f9ff967-def9-d071-5a63-615476707760
23: eni074549d1a1b@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP mode DEFAULT group default
link/ether 02:df:4f:c0:70:22 brd ff:ff:ff:ff:ff:ff link-netns cni-9e63f294-7a51-0d83-5d92-35fa2d10fbf7
24: eni27492347c98@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP mode DEFAULT group default
link/ether 86:07:1c:83:fc:32 brd ff:ff:ff:ff:ff:ff link-netns cni-c57d2653-3351-6dca-5fbb-a9aae728f652
...
118: enica6bfd7fb92@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP mode DEFAULT group default
link/ether c6:b5:a8:38:10:b9 brd ff:ff:ff:ff:ff:ff link-netns cni-18c31f76-abc1-d183-12e9-16996ea8fd62
119: eniae9c9530721@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP mode DEFAULT group default
link/ether 4a:22:24:4e:31:1a brd ff:ff:ff:ff:ff:ff link-netns cni-ef317151-c345-7ff9-7834-463489705b1c
120: eni1d4533ab526@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP mode DEFAULT group default
link/ether 96:37:17:04:f0:35 brd ff:ff:ff:ff:ff:ff link-netns cni-173e2a7a-af25-0f82-283b-7ac1532496ad
121: eni5d8c12d7dfd@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP mode DEFAULT group default
link/ether 06:4a:97:b1:90:8b brd ff:ff:ff:ff:ff:ff link-netns cni-74bf568b-b5e5-a1d2-d93f-3ad797ad9571
122: eni6944f438782@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP mode DEFAULT group default
link/ether da:4a:25:c6:da:a7 brd ff:ff:ff:ff:ff:ff link-netns cni-777d672e-00b0-90bb-2c40-d72663b8ac6e
[과제3]
서비스(NLB)/파드 배포 시 ExternalDNS 설정해서, 각자 자신의 도메인으로 NLB를 통해 애플리케이션(파드)로 접속해보고 관련 스샷을 올려주세요
- 퍼블릭 도메인이 없는 멤버분들은, ExternalDNS 제외하고 NLB 도메인으로 접속한 결과를 올려주세요
결과 사진
작업 내용
git clone 후 네임스페이스 생성 후 변경
# git clone
(somaz:N/A) [root@kops-ec2 ~]# git clone https://github.com/dockersamples/example-voting-appCloning into 'example-voting-app'...
remote: Enumerating objects: 1080, done.
remote: Total 1080 (delta 0), reused 0 (delta 0), pack-reused 1080
Receiving objects: 100% (1080/1080), 1.01 MiB | 15.96 MiB/s, done.
Resolving deltas: 100% (407/407), done.
(somaz:N/A) [root@kops-ec2 ~]# cd example-voting-app/k8s-specifications/
(somaz:N/A) [root@kops-ec2 k8s-specifications]# tree
.
├── db-deployment.yaml
├── db-service.yaml
├── redis-deployment.yaml
├── redis-service.yaml
├── result-deployment.yaml
├── result-service.yaml
├── vote-deployment.yaml
├── vote-service.yaml
└── worker-deployment.yaml
0 directories, 9 files
# 네임스페이스 생성 후 변경
(somaz:N/A) [root@kops-ec2 k8s-specifications]# kubectl create ns vote
namespace/vote created
(somaz:N/A) [root@kops-ec2 k8s-specifications]# kubectl ns vote
Context "somaz.link" modified.
Active namespace is "vote".
서비스 파일 변경
# 서비스 파일 변경
(somaz:vote) [root@kops-ec2 k8s-specifications]# rm -rf vote-service.yaml result-service.yaml
(somaz:vote) [root@kops-ec2 k8s-specifications]# cp ~/pkos/2/vote-service.yaml .
(somaz:vote) [root@kops-ec2 k8s-specifications]# cp ~/pkos/2/result-service.yaml .
(somaz:vote) [root@kops-ec2 k8s-specifications]# cat vote-service.yaml | yh
apiVersion: v1
kind: Service
metadata:
labels:
app: vote
name: vote
annotations:
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: "80"
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
spec:
loadBalancerClass: service.k8s.aws/nlb
type: LoadBalancer
ports:
- name: "vote-service"
port: 80
targetPort: 80
selector:
app: vote
(somaz:vote) [root@kops-ec2 k8s-specifications]# cat result-service.yaml | yh
apiVersion: v1
kind: Service
metadata:
labels:
app: result
name: result
annotations:
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: "80"
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
spec:
loadBalancerClass: service.k8s.aws/nlb
type: LoadBalancer
ports:
- name: "result-service"
port: 80
targetPort: 80
selector:
app: result
서비스 배포 후 다른창 열어서 모니터링
# 서비스 배포
(somaz:N/A) [root@kops-ec2 k8s-specifications]# kubectl apply -f .
deployment.apps/db created
service/db created
deployment.apps/redis created
service/redis created
deployment.apps/result created
service/result created
deployment.apps/vote created
service/vote created
deployment.apps/worker created
# 다른창 열어서 모니터링
(somaz:N/A) [root@kops-ec2 ~]# watch "kubectl get po,svc"
...
Every 2.0s: kubectl get po,svc Sun Jan 15 22:33:30 2023
NAME READY STATUS RESTARTS AGE
pod/db-58478bbc69-gcmxd 1/1 Running 0 37s
pod/pod-1 1/1 Running 0 114m
pod/pod-2 1/1 Running 0 112m
pod/redis-549d6f9fc6-pdj5n 1/1 Running 0 37s
pod/result-b8f984f98-r22zn 1/1 Running 0 37s
pod/vote-64bf8cb656-6b9xt 1/1 Running 0 37s
pod/worker-f54cd56ff-dtrrw 1/1 Running 0 37s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/db ClusterIP 100.71.9.42 <none> 5432/TCP 37s
service/kubernetes ClusterIP 100.64.0.1 <none> 443/TCP 141m
service/redis ClusterIP 100.67.183.131 <none> 6379/TCP 37s
service/result NodePort 100.70.213.29 <none> 5001:31001/TCP 37s
service/vote NodePort 100.67.102.38 <none> 5000:31000/TCP 37s
ExternalDNS 추가
# ExternalDNS 추가
## 각자 자신의 도메인 정보 입력
(somaz:N/A) [root@kops-ec2 k8s-specifications]# MyDOMAIN1=vote.somaz.link
(somaz:N/A) [root@kops-ec2 k8s-specifications]# MyDOMAIN2=result.somaz.link
(somaz:N/A) [root@kops-ec2 k8s-specifications]# kubectl annotate service vote "external-dns.alpha.kubernetes.io/hostname=$MyDOMAIN1."
service/vote annotated
(somaz:N/A) [root@kops-ec2 k8s-specifications]# kubectl annotate service result "external-dns.alpha.kubernetes.io/hostname=$MyDOMAIN2."
service/result annotated
(somaz:N/A) [root@kops-ec2 ~]# kubectl describe svc vote | grep Annotations: -A4
Annotations: external-dns.alpha.kubernetes.io/hostname: vote.somaz.link.
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: true
service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: 80
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
(somaz:vote) [root@kops-ec2 ~]# kubectl describe svc result | grep Annotations: -A4
Annotations: external-dns.alpha.kubernetes.io/hostname: result.somaz.link.
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: true
service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: 80
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
[과제4]
NLB 에 TLS 적용하기
- 사전 준비 : 공인도메인 소유, AWS Route53 도메인등록 상태, NLB 가 위치한 리전(서울)의 인증서 요청/발급 완료상태, ExternalDNS 준비완료상태
결과 사진
작업 내용
[과제3]을 하면서 나머지는 전부 완료한 상태이고, 도메인 인증서를 발급하려고 한다.
도메인 인증서 발급
먼저 AWS의 Certificate Manager로 생성한 인증서는 무료이다.
1. AWS Certificate Manager로 들어가 인증서 요청을 한다.
2. 퍼블릭 인증서 요청을 선택 후 다음으로 이동한다.
3. 본인이 SSL을 설치하고자 하는 도메인을 등록합니다.
아래와 같이 *.somaz.com 식으로 등록하면 *로 인해 하위 도메인들이 모두 사용할 수 있는 인증서가 된다.
(ex.www.somaz.com)
다만, somaz.com에선 사용할 수 없는 인증서이라서 2차 도메인(somaz.com)과 3차 도메인(*.somaz.com)을 사용하려면 아래와 같이 도메인 이름을 모두 추가한다.
그리고 검증방법을 DNS 검증을 선택 후 요청을 누른다.
요청 후 확인을 해보면 인증서가 검증 대기중으로 떠있다.
그리고 해당 인증서로 들어가 Route 53에서 레코드 생성을 해준다.
그리고 30분정도 기다려주면 아래와 같이 결과가 나온다.
신 인증서 (DNS 검증)은 상태가 발급됨, 사용중 X, 갱신 자격 부적격으로 되어있으면 정상입니다.
나머지 작업 내용
ARN 확인, 도메인 변수 지정, 생성
# 사용 리전의 인증서 ARN 확인
(somaz:default) [root@kops-ec2 ~]# aws acm list-certificates --max-items 10
{
"CertificateSummaryList": [
{
"CertificateArn": "arn:aws:acm:ap-northeast-2:611841095956:certificate/75e6fb4f-5999-4701-80f2-ab94e015bc9b",
"DomainName": "*.somaz.link",
"SubjectAlternativeNameSummaries": [
"*.somaz.link",
"somaz.link"
(somaz:default) [root@kops-ec2 ~]# aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text
arn:aws:acm:ap-northeast-2:611841095956:certificate/75e6fb4f-5999-4701-80f2-ab94e015bc9b
(somaz:default) [root@kops-ec2 ~]# CERT_ARN=`aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text`
(somaz:default) [root@kops-ec2 ~]# echo $CERT_ARN
arn:aws:acm:ap-northeast-2:611841095956:certificate/75e6fb4f-5999-4701-80f2-ab94e015bc9b
# 자신의 도메인 변수 지정
(somaz:default) [root@kops-ec2 ~]# MyDomain=websrv.somaz.link
# 생성
cat <<EOF | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy-echo
spec:
replicas: 2
selector:
matchLabels:
app: deploy-websrv
template:
metadata:
labels:
app: deploy-websrv
spec:
terminationGracePeriodSeconds: 0
containers:
- name: akos-websrv
image: k8s.gcr.io/echoserver:1.5
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: svc-nlb-ip-type
annotations:
external-dns.alpha.kubernetes.io/hostname: "${MyDomain}"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: "8080"
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https"
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: ${CERT_ARN}
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http"
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
- port: 443
targetPort: 8080
protocol: TCP
name: https
type: LoadBalancer
loadBalancerClass: service.k8s.aws/nlb
selector:
app: deploy-websrv
EOF
모니터링, 확인
# 모니터링
watch "kubectl get po,svc"
...
Every 2.0s: kubectl get svc,ep Sun Jan 15 23:41:34 2023
NAME TYPE CLUSTER-IP EXTERNAL-IP
PORT(S) AGE
service/kubernetes ClusterIP 100.64.0.1 <none>
443/TCP 3h29m
service/svc-nlb-ip-type LoadBalancer 100.71.185.216 k8s-default-svcnlbip-4eca1f860b-959096705f3c2028.elb.ap-northeast-2.amazonaws.com 80:32663/TCP,443:32662/TCP 41s
NAME ENDPOINTS
AGE
endpoints/kubernetes 172.30.35.141:443
3h29m
endpoints/svc-nlb-ip-type 172.30.48.21:8080,172.30.71.46:8080,172.30.48.21:8080 + 1 more...41s
# 확인
(somaz:default) [root@kops-ec2 ~]# kubectl get svc,ep
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 100.64.0.1 <none> 443/TCP 3h30m
service/svc-nlb-ip-type LoadBalancer 100.71.185.216 k8s-default-svcnlbip-4eca1f860b-959096705f3c2028.elb.ap-northeast-2.amazonaws.com 80:32663/TCP,443:32662/TCP 76s
NAME ENDPOINTS AGE
endpoints/kubernetes 172.30.35.141:443 3h30m
endpoints/svc-nlb-ip-type 172.30.48.21:8080,172.30.71.46:8080,172.30.48.21:8080 + 1 more... 76s
(somaz:default) [root@kops-ec2 ~]# kubectl describe svc svc-nlb-ip-type
Name: svc-nlb-ip-type
Namespace: default
Labels: <none>
Annotations: external-dns.alpha.kubernetes.io/hostname: websrv.somaz.link
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: true
service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: 8080
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
service.beta.kubernetes.io/aws-load-balancer-ssl-cert:
arn:aws:acm:ap-northeast-2:611841095956:certificate/75e6fb4f-5999-4701-80f2-ab94e015bc9b
service.beta.kubernetes.io/aws-load-balancer-ssl-ports: https
Selector: app=deploy-websrv
Type: LoadBalancer
IP Family Policy: SingleStack
IP Families: IPv4
IP: 100.71.185.216
IPs: 100.71.185.216
LoadBalancer Ingress: k8s-default-svcnlbip-4eca1f860b-959096705f3c2028.elb.ap-northeast-2.amazonaws.com
Port: http 80/TCP
TargetPort: 8080/TCP
NodePort: http 32663/TCP
Endpoints: 172.30.48.21:8080,172.30.71.46:8080
Port: https 443/TCP
TargetPort: 8080/TCP
NodePort: https 32662/TCP
Endpoints: 172.30.48.21:8080,172.30.71.46:8080
Session Affinity: None
External Traffic Policy: Cluster
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfullyReconciled 107s service Successfully reconciled
(somaz:default) [root@kops-ec2 ~]# kubectl describe svc svc-nlb-ip-type | grep Annotations: -A8
Annotations: external-dns.alpha.kubernetes.io/hostname: websrv.somaz.link
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: true
service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: 8080
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
service.beta.kubernetes.io/aws-load-balancer-ssl-cert:
arn:aws:acm:ap-northeast-2:611841095956:certificate/75e6fb4f-5999-4701-80f2-ab94e015bc9b
service.beta.kubernetes.io/aws-load-balancer-ssl-ports: https
외부 접속 테스트
# 외부 접속 테스트
(somaz:default) [root@kops-ec2 ~]# curl -s http://websrv.somaz.link| grep Hostname
Hostname: deploy-echo-5c4856dfd6-zmdzk
(somaz:default) [root@kops-ec2 ~]# curl -s -k https://websrv.somaz.link| grep Hostname
Hostname: deploy-echo-5c4856dfd6-zmdzk
스터디 주요 내용
1. CNI란?
Container Network Interface의 약자로 Linux 컨테이너에서 네트워크 인터페이스를 구성하기 위한 규격이다.
컨테이너를 네트워크에 연결하거나 분리하는 것과 관련이 있다.
K8S CNI
CNI는 k8s 네트워크 환경을 구성해주고 다양한 플러그인이 존재한다.
AWS VPC CNI
파드 IP를 할당해주고, 파드의 IP 네트워크 대역과 노드의 IP 대역이 같아서 직접 통신이 가능하다.
K8S Calico CNI와 AWS VPC CNI 차이
파드 간 통신 시 일반적으로 K8S CNI는 오버레이 통신을 하고, AWS VPC CNI는 동일 대역으로 직접 통신을 한다.
워커 노드에 최대 생성 가능한 파드 갯수는 몇개일까?
- Secondary IPv4 addresses : 인스턴스 유형에 최대 ENI 갯수와 할당 가능 IP 수를 조합하여 선정
- IPv4 Prefix Delegation : IPv4 28bit 서브넷(prefix)를 위임하여 할당 가능 IP 수와 인스턴스 유형에 권장하는 최대 갯수로 선정
2. 노드에서 기본 네트워크 정보 확인
Network 네임스페이스는 호스트(Root)와 파드 별(Per Pod)로 구분된다.
특정한 파드(kube-proxy, aws-node)는 호스트(Root)의 IP를 그대로 사용한다.
t3.medium 의 경우 ENI 에 최대 6개의 IP를 가지고 자신의 IP 이외에 추가적으로 5개의 보조 프라이빗 IP를 가진다.
coredns 파드는 veth으로 호스트에는 eniY@ifN 인터페이스와 파드에 eth0가 연결되어 있다.
3. 노드 간 파드 통신
AWS VPC ENI는 첫번째 ENI1(ens5)로만 통신이 되도록 iptables나 라우팅 테이블이 설정되어있다.
따라서 ENI2(ens6)으로는 통신되지 않는다.
4. 파드에서 외부통신
iptable 에 SNAT 을 통하여 노드의 eth0 IP로 변경되어서 외부와 통신된다.
또한 VPC CNI 의 External source network address translation (SNAT) 설정에 따라, 외부(인터넷) 통신 시 SNAT 하거나 혹은 SNAT 없이 통신을 할 수 있다
SNAT(Source NAT)란?
먼저 SNAT는 패킷의 Source 주소를 변경하는 것으로 SNAT 혹은 Source NAT라고 한다.
즉 출발지 주소를 변경하는 것이다. 사설에서 공인으로 통신할 때 많이 사용한다.
( 내부 -> 외부)
- NAT(Network Address Translation) : 즉 IP 패킷 헤더의 IP 주소를 변경하는 기능이다.
- PREROUTING : DNAT를 이용하여 패킷이 생길 때
- POSTROUTING: SNAT를 이용하여 패킷이 나갈 때
- DNAT(Destination NAT) : 도착지 주소를 변경하는 NAT이다. (외부 -> 내부)
- 로드밸런서에 많이 사용한다. 또한, 사내가 아닌 대외망과의 네트워크 구성에도 사용한다.
5. 서비스
서비스에는 ClusterIP 타입과, NodePort 타입, LoadBalancer 타입 총 3개가 있다.
아래의 공부했던 내용을 다시 한번 적어본다.
2022.08.29 - [교육, 커뮤니티 후기] - <인프런> 대세는 쿠버네티스 [초급] - No.9 Object - Service
ClusterIP
그 중 가장 기본적인 방식인 ClusterIP라는 방식이 있다.
이 IP는 Cluster 내에서만 접근이 가능하다. Pod가 가지고 있는 IP와 동일하게 외부에서는 접근이 불가하다.
NodePort
NodePort 타입의 Service는 ClusterIP와 동일한 특성을 가지고 있다.
NodePort 타입만의 큰 특징은 Kubernetes Cluster에 할당되어 있는 모든 Node에게 똑같은 Port가 할당이 된다.
따라서 Node1,2든 해당 IP에 Port로 접속을 하면, Service에 연결이 된다.
LoadBalancer
Load Balancer 타입의 Service는 NodePort와 동일한 특성을 가지고 있다. 추가적으로 LoadBalancer라는 걸 이용해서 각각의 Node에 Traffic을 분산시켜주는 역할을 한다. 다만, Load Balancer가 가지고 있는 IP는 Kubernetes를 설치 햇을 때 생기지 않는다. 별도로 외부접속 IP를 할당을 해주는 Plugin이 설치가 되어있어야 IP가 생긴다.
6. ExternalDNS
K8S 서비스/인그레스 생성 시 도메인을 설정하면, AWS(Route 53), Azure(DNS), GCP(Cloud DNS) 에 A 레코드(TXT 레코드)로 자동 생성/삭제된다.
스터디 2주차 후기
쿠버네티스 네트워크에 대해 중점적으로 배울수 있는 시간이 되었던 것 같습니다!
과제2번이 잘되지 않아 삽질을 좀 하긴 했지만, 가시다님께서 노션에 방법을 공유해주셔 수월하게 해결할 수 있었습니다.
실습과 자료가 적절하고 좋은 스터디인 것 같습니다. 마지막까지 화이팅입니다!
Reference
https://jojoldu.tistory.com/434
https://programforlife.tistory.com/112
https://trans.yonghochoi.com/translations/aws_vpc_cni_increase_pods_per_node_limits.ko
https://sarc.io/index.php/aws/1779-snat-dnat-difference
https://docs.aws.amazon.com/cli/latest/reference/ec2/unassign-private-ip-addresses.html
https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/work-with-prefixes.html
'교육, 커뮤니티 후기 > PKOS 쿠버네티스 스터디' 카테고리의 다른 글
PKOS 쿠버네티스 스터디 6주차 - 얼럿매니저 로깅시스템 (0) | 2023.02.19 |
---|---|
PKOS 쿠버네티스 스터디 5주차 - 프로메테우스 그라파나 (0) | 2023.02.14 |
PKOS 쿠버네티스 스터디 4주차 - Harbor Gitlab Argocd (2) | 2023.02.06 |
PKOS 쿠버네티스 스터디 3주차 - Ingress & Storage (4) | 2023.02.03 |
PKOS 쿠버네티스 스터디 1주차 - kOps 클러스터 배포 (2) | 2023.01.08 |