티스토리 뷰
안녕하세요. Kubernetes Advanced Networking Study(=KANS) 3기 모임에서 스터디한 내용을 정리했습니다. 해당 글에서는 K8S Flannel CNI 에 대해 자세히 알아보겠습니다.
CNI(Container Network Inferface)
쿠버네티스는 네트워크 모델의 요건을 만족하는 CNI 플러그인이 있고, 대표적으로 'Calico, Cilium 등'이 있습니다.
쿠버네티스 네트워크 모델 요구사항
1. 파드와 파드 간 통신 시 NAT 없이 통신 가능
2. 노드의 에이전트는 파드와 통신이 가능
3. 호스트 네트워크를 사용하는 파드는 NAT 없이 파드와 통신이 가능
4. 서비스 클러스터 IP 대역과 파드가 사용하는 IP 대역은 중복되지 않아야 함
Flannel CNI
- 네트워킹 환경 지원 (Backends) : VXLAN, host-gw, UDP, 그외에는 아직 실험적임 - 링크 링크2

kind & Flannel 배포 - Docs Blog Github
#
cat <<EOF> kind-cni.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
labels:
mynode: control-plane
extraPortMappings:
- containerPort: 30000
hostPort: 30000
- containerPort: 30001
hostPort: 30001
- containerPort: 30002
hostPort: 30002
kubeadmConfigPatches:
- |
kind: ClusterConfiguration
controllerManager:
extraArgs:
bind-address: 0.0.0.0
etcd:
local:
extraArgs:
listen-metrics-urls: http://0.0.0.0:2381
scheduler:
extraArgs:
bind-address: 0.0.0.0
- |
kind: KubeProxyConfiguration
metricsBindAddress: 0.0.0.0
- role: worker
labels:
mynode: worker
- role: worker
labels:
mynode: worker2
networking:
disableDefaultCNI: true
EOF
kind create cluster --config kind-cni.yaml --name myk8s --image kindest/node:v1.30.4
# 배포 확인
kind get clusters
kind get nodes --name myk8s
kubectl cluster-info
# 네트워크 확인
kubectl cluster-info dump | grep -m 2 -E "cluster-cidr|service-cluster-ip-range"
# 노드 확인 : CRI
kubectl get nodes -o wide
# 노드 라벨 확인
kubectl get nodes myk8s-control-plane -o jsonpath={.metadata.labels} | jq
...
"mynode": "control-plane",
...

kubectl get nodes myk8s-worker -o jsonpath={.metadata.labels} | jq
kubectl get nodes myk8s-worker2 -o jsonpath={.metadata.labels} | jq
# 컨테이너 확인 : 컨테이너 갯수, 컨테이너 이름 확인
docker ps
docker port myk8s-control-plane
docker port myk8s-worker
docker port myk8s-worker2

# 컨테이너 내부 정보 확인
docker exec -it myk8s-control-plane ip -br -c -4 addr
docker exec -it myk8s-worker ip -br -c -4 addr
docker exec -it myk8s-worker2 ip -br -c -4 addr
#
docker exec -it myk8s-control-plane sh -c 'apt update && apt install tree jq psmisc lsof wget bridge-utils tcpdump iputils-ping htop git nano -y'
docker exec -it myk8s-worker sh -c 'apt update && apt install tree jq psmisc lsof wget bridge-utils tcpdump iputils-ping -y'
docker exec -it myk8s-worker2 sh -c 'apt update && apt install tree jq psmisc lsof wget bridge-utils tcpdump iputils-ping -y'
#
docker exec -it myk8s-control-plane bash
---------------------------------------
apt install golang -y
git clone https://github.com/containernetworking/plugins
chmod +x build_linux.sh
#
build_linux.sh
Building plugins
bandwidth
firewall
portmap
sbr
tuning
vrf
bridge
host-device
ipvlan
loopback
macvlan
ptp
vlan
dhcp
host-local
static
exit
---------------------------------------
# 자신의 PC에 복사
docker cp myk8s-control-plane:/opt/cni/bin/bridge .
ls -l bridge
#
watch -d kubectl get pod -A -owide
#
kubectl describe pod -n kube-system -l k8s-app=kube-dns
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 57s default-scheduler 0/1 nodes are available: 1 node(s) had untolerated taint {node.kubernetes.io/not-ready: }. preemption: 0/1 nodes are available: 1 Preemption is not helpful for scheduling.
# Flannel cni 설치
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
# namespace 에 pod-security.kubernetes.io/enforce=privileged Label 확인
kubectl get ns --show-labels
NAME STATUS AGE LABELS
kube-flannel Active 2m49s k8s-app=flannel,kubernetes.io/metadata.name=kube-flannel,pod-security.kubernetes.io/enforce=privileged
kubectl get ds,pod,cm -n kube-flannel
kubectl describe cm -n kube-flannel kube-flannel-cfg
cni-conf.json:
----
{
"name": "cbr0",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "flannel",
"delegate": {
"hairpinMode": true,
"isDefaultGateway": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}
net-conf.json:
----
{
"Network": "10.244.0.0/16",
"EnableNFTables": false,
"Backend": {
"Type": "vxlan"
}
}

kubectl describe ds -n kube-flannel kube-flannel-ds
...
Mounts:
/etc/cni/net.d from cni (rw)
/etc/kube-flannel/ from flannel-cfg (rw)
...
Mounts:
/etc/kube-flannel/ from flannel-cfg (rw)
/run/flannel from run (rw)
/run/xtables.lock from xtables-lock (rw)
Volumes:
run:
Type: HostPath (bare host directory volume)
Path: /run/flannel
HostPathType:
cni-plugin:
Type: HostPath (bare host directory volume)
Path: /opt/cni/bin
HostPathType:
cni:
Type: HostPath (bare host directory volume)
Path: /etc/cni/net.d
HostPathType:
flannel-cfg:
Type: ConfigMap (a volume populated by a ConfigMap)
Name: kube-flannel-cfg
Optional: false
xtables-lock:
Type: HostPath (bare host directory volume)
Path: /run/xtables.lock
HostPathType: FileOrCreate
Priority Class Name: system-node-critical
...
kubectl exec -it ds/kube-flannel-ds -n kube-flannel -c kube-flannel -- ls -l /etc/kube-flannel
# failed to find plugin "bridge" in path [/opt/cni/bin]
kubectl get pod -A -owide
kubectl describe pod -n kube-system -l k8s-app=kube-dns
Warning FailedCreatePodSandBox 35s kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox "786e9caec9c312a0b8af70e14865535575601d024ec02dbb581a1f5ac0b8bb06": plugin type="flannel" failed (add): loadFlannelSubnetEnv failed: open /run/flannel/subnet.env: no such file or directory
Warning FailedCreatePodSandBox 23s kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox "6ccd4607d32cbb95be9ff40b97a436a07e5902e6c24d1e12aa68fefc2f8b548a": plugin type="flannel" failed (add): failed to delegate add: failed to find plugin "bridge" in path [/opt/cni/bin]


위 에러를 해결하기 위해 해당 경로에 bridge 실행파일 생성 후 로컬에 복사합니다.
ls -l bridge

#
kubectl get pod -A -owide
#
docker cp bridge myk8s-control-plane:/opt/cni/bin/bridge
docker cp bridge myk8s-worker:/opt/cni/bin/bridge
docker cp bridge myk8s-worker2:/opt/cni/bin/bridge
docker exec -it myk8s-control-plane chmod 755 /opt/cni/bin/bridge
docker exec -it myk8s-worker chmod 755 /opt/cni/bin/bridge
docker exec -it myk8s-worker2 chmod 755 /opt/cni/bin/bridge
#
docker exec -it myk8s-control-plane ls -l /opt/cni/bin/
docker exec -it myk8s-worker ls -l /opt/cni/bin/
docker exec -it myk8s-worker2 ls -l /opt/cni/bin/
for i in myk8s-control-plane myk8s-worker myk8s-worker2; do echo ">> node $i <<"; docker exec -it $i ls /opt/cni/bin/; echo; done
bridge flannel host-local loopback portmap ptp
#
kubectl get pod -A -owide


Flannel 정보 확인
#
kubectl get ds,pod,cm -n kube-flannel -owide

kubectl describe cm -n kube-flannel kube-flannel-cfg
# iptables 정보 확인
for i in filter nat mangle raw ; do echo ">> IPTables Type : $i <<"; docker exec -it myk8s-control-plane iptables -t $i -S ; echo; done
for i in filter nat mangle raw ; do echo ">> IPTables Type : $i <<"; docker exec -it myk8s-worker iptables -t $i -S ; echo; done
for i in filter nat mangle raw ; do echo ">> IPTables Type : $i <<"; docker exec -it myk8s-worker2 iptables -t $i -S ; echo; done
# flannel 정보 확인 : 대역, MTU
for i in myk8s-control-plane myk8s-worker myk8s-worker2; do echo ">> node $i <<"; docker exec -it $i cat /run/flannel/subnet.env ; echo; done
>> node myk8s-control-plane <<
FLANNEL_NETWORK=10.244.0.0/16
FLANNEL_SUBNET=10.244.0.1/24 # 해당 노드에 파드가 배포 시 할당 할 수 있는 네트워크 대역
FLANNEL_MTU=65485 # MTU 지정
FLANNEL_IPMASQ=true # 파드가 외부(인터넷) 통신 시 해당 노드의 마스커레이딩을 사용
...
# 노드마다 할당된 dedicated subnet (podCIDR) 확인
kubectl get nodes -o jsonpath='{.items[*].spec.podCIDR}' ;echo

# 노드 정보 중 flannel 관련 정보 확인 : VXLAN 모드 정보와, VTEP 정보(노드 IP, VtepMac) 를 확인
kubectl describe node | grep -A3 Annotations

# 각 노드(?) 마다 bash 진입 후 아래 기본 정보 확인 : 먼저 worker 부터 bash 진입 후 확인하자
docker exec -it myk8s-worker bash
docker exec -it myk8s-worker2 bash
docker exec -it myk8s-control-plane bash
----------------------------------------
# 호스트 네트워크 NS와 flannel, kube-proxy 컨테이너의 네트워크 NS 비교 : 파드의 IP와 호스트(서버)의 IP를 비교해보자!
lsns -p 1
lsns -p $(pgrep flanneld)
lsns -p $(pgrep kube-proxy)

# 기본 네트워크 정보 확인
ip -c -br addr
ip -c link | grep -E 'flannel|cni|veth' -A1
ip -c addr
ip -c -d addr show cni0 # 네트워크 네임스페이스 격리 파드가 1개 이상 배치 시 확인됨
ip -c -d addr show flannel.1
5: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default
link/ether 1e:81:fc:d5:8a:42 brd ff:ff:ff:ff:ff:ff promiscuity 0 minmtu 68 maxmtu 65535
vxlan id 1 local 192.168.100.10 dev enp0s8 srcport 0 0 dstport 8472 nolearning ttl auto ageing 300 udpcsum noudp6zerocsumtx noudp6zerocsumrx numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
inet 172.16.0.0/32 brd 172.16.0.0 scope global flannel.1

brctl show
bridge name bridge id STP enabled interfaces
cni0 8000.663bf746b6a8 no vethbce1591c
vethc17ba51b
vethe6540260
# 라우팅 정보 확인 : 다른 노드의 파드 대역(podCIDR)의 라우팅 정보가 업데이트되어 있음을 확인
ip -c route
default via 172.18.0.1 dev eth0
10.244.0.0/24 via 10.244.0.0 dev flannel.1 onlink
10.244.1.0/24 dev cni0 proto kernel scope link src 10.244.1.1
10.244.2.0/24 via 10.244.2.0 dev flannel.1 onlink
172.18.0.0/16 dev eth0 proto kernel scope link src 172.18.0.3

# flannel.1 인터페이스를 통한 ARP 테이블 정보 확인 : 다른 노드의 flannel.1 IP와 MAC 정보를 확인
ip -c neigh show dev flannel.1
# 브리지 fdb 정보에서 해당 MAC 주소와 통신 시 각 노드의 enp0s8
bridge fdb show dev flannel.1

# 다른 노드의 flannel.1 인터페이스로 ping 통신 : VXLAN 오버레이를 통해서 통신
ping -c 1 10.244.0.0
ping -c 1 10.244.1.0
ping -c 1 10.244.2.0
# iptables 필터 테이블 정보 확인 : 파드의 10.244.0.0/16 대역 끼리는 모든 노드에서 전달이 가능
iptables -t filter -S | grep 10.244.0.0
# iptables NAT 테이블 정보 확인 : 10.244.0.0/16 대역 끼리 통신은 마스커레이딩 없이 통신을 하며,
# 10.244.0.0/16 대역에서 동일 대역(10.244.0.0/16)과 멀티캐스트 대역(224.0.0.0/4) 를 제외한 나머지 (외부) 통신 시에는 마스커레이딩을 수행
iptables -t nat -S | grep 'flanneld masq' | grep -v '! -s'
----------------------------------------

[실습] 파드 2개 생성
# [터미널1,2] 워커 노드1,2 - 모니터링
docker exec -it myk8s-worker bash
docker exec -it myk8s-worker2 bash
-----------------------------
watch -d "ip link | egrep 'cni|veth' ;echo; brctl show cni0"
-----------------------------
# [터미널3] cat & here document 명령 조합으로 즉석(?) 리소스 생성
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: pod-1
labels:
app: pod
spec:
nodeSelector:
kubernetes.io/hostname: myk8s-worker
containers:
- name: netshoot-pod
image: nicolaka/netshoot
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
---
apiVersion: v1
kind: Pod
metadata:
name: pod-2
labels:
app: pod
spec:
nodeSelector:
kubernetes.io/hostname: myk8s-worker2
containers:
- name: netshoot-pod
image: nicolaka/netshoot
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
# 파드 확인 : IP 확인
kubectl get pod -o wide

파드 생성 후 정보 확인
# [터미널1,2] 워커 노드1,2
docker exec -it myk8s-worker bash
docker exec -it myk8s-worker2 bash
-----------------------------
# 브리지 정보 확인
brctl show cni0
# 브리지 연결 링크(veth) 확인
bridge link
# 브리지 VLAN 정보 확인
bridge vlan
# cbr(custom bridge) 정보 : kubenet CNI의 bridge - 링크
tree /var/lib/cni/networks/cbr0
/var/lib/cni/networks/cbr0
├── 10.244.2.4.
├── last_reserved_ip.0
└── lock
# 네트워크 관련 정보들 확인
ip -c addr | grep veth -A3
8: veth3060489e@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master cni0 state UP group default
link/ether ea:26:f0:2a:c9:cb brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::e826:f0ff:fe2a:c9cb/64 scope link
valid_lft forever preferred_lft forever
...
-----------------------------

k8s 통신 흐름 이해
- 작성한 지난글[[k8s] Tracing the path of network traffic] 을 참고했습니다.
POD 간 통신 - 동일 노드





POD 간 통신 - 다른 노드






CNI가 위의 항목을 생성하는 방법을 살펴보겠습니다.
컨테이너 네트워크 인터페이스 — CNI

CNI는 Kubernetes 네트워크 요구 사항 중 일부를 해결하기 위해 네트워킹 플러그인이 따라야 하는 일련의 규칙으로 생각할 수 있습니다. CNI는 아래 역할을 담당합니다.
-
- 인터페이스를 만듭니다.
- veth pair를 만듭니다.
- 네임스페이스 네트워킹을 설정합니다.
- 고정 경로를 설정합니다.
- 이더넷 브리지를 구성합니다.
- IP 주소를 할당합니다.
- NAT 규칙을 만듭니다
CNI를 통한 통신 그림



파드 Shell 접속 후 확인 & 패킷 캡처
kubectl exec -it pod-1 -- zsh
-----------------------------
ip -c addr show eth0

# GW IP는 어떤 인터페이스인가? cni0
ip -c route
route -n
ping -c 1 <GW IP>
ping -c 1 <pod-2 IP> # 다른 노드에 배포된 파드 통신 확인
ping -c 8.8.8.8 # 외부 인터넷 IP 접속 확인
curl -s wttr.in/Seoul # 외부 인터넷 도메인 접속 확인
ip -c neigh
exit
-----------------------------


패킷 캡처 후 확인
# [터미널1,2] 워커 노드1,2
docker exec -it myk8s-worker bash
docker exec -it myk8s-worker2 bash
-----------------------------
tcpdump -i cni0 -nn icmp
tcpdump -i flannel.1 -nn icmp #다른 노드의 pod와 통신할 때 vxlan으로 오버레이 연결될 때 사용되므로 안나옴
tcpdump -i eth0 -nn icmp #eth0를 통해 icmp 헤더가 나가는데 vxlan 오버레이에 의해 icmp가 감춰져서 안보임
tcpdump -i eth0 -nn udp port 8472 -w /root/vxlan.pcap
# CTRL+C 취소 후 확인 : ls -l /root/vxlan.pcap
conntrack -L | grep -i icmp
-----------------------------
# [터미널3]
docker cp myk8s-worker:/root/vxlan.pcap .
wireshark vxlan.pcap

wireshark에서 vxlan 기본 udp port 를 4789 -> 8472(flannel)로 바꿔줍니다

- vxlan을 통해 udp 프로토콜로 pod 간 통신이 되는 것을 알 수 있습니다.
실습 도움 툴 설치 : kube-ops-view , metrics-server , prometheus-stack
kube-ops-view
# helm show values geek-cookbook/kube-ops-view
helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set service.main.type=NodePort,service.main.ports.http.nodePort=30000 --set env.TZ="Asia/Seoul" --namespace kube-system
# 설치 확인
kubectl get deploy,pod,svc,ep -n kube-system -l app.kubernetes.io/instance=kube-ops-view
# myk8s-control-plane 노드?에 배치
kubectl get nodes myk8s-control-plane -o jsonpath={.metadata.labels} | jq
kubectl describe node myk8s-control-plane | grep Taints
kubectl -n kube-system get deploy kube-ops-view -o yaml | k neat
kubectl -n kube-system edit deploy kube-ops-view
---
spec:
...
template:
...
spec:
nodeSelector:
mynode: control-plane
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Equal"
effect: "NoSchedule"
---
kubectl -n kube-system get pod -o wide -l app.kubernetes.io/instance=kube-ops-view
# kube-ops-view 접속 URL 확인 (1.5 , 2 배율) : macOS 사용자
echo -e "KUBE-OPS-VIEW URL = http://localhost:30000/#scale=1.5"
echo -e "KUBE-OPS-VIEW URL = http://localhost:30000/#scale=2"
# kube-ops-view 접속 URL 확인 (1.5 , 2 배율) : Windows 사용자
echo -e "KUBE-OPS-VIEW URL = http://192.168.50.10:30000/#scale=1.5"
echo -e "KUBE-OPS-VIEW URL = http://192.168.50.10:30000/#scale=2"
# (참고) 삭제
helm uninstall -n kube-system kube-ops-view


metrics-server
# metrics-server
helm repo add metrics-server https://kubernetes-sigs.github.io/metrics-server/
helm upgrade --install metrics-server metrics-server/metrics-server --set 'args[0]=--kubelet-insecure-tls' -n kube-system
kubectl get all -n kube-system -l app.kubernetes.io/instance=metrics-server
kubectl get apiservices |egrep '(AVAILABLE|metrics)'
# 확인
kubectl top node
kubectl top pod -A --sort-by='cpu'
kubectl top pod -A --sort-by='memory'
# (참고) 삭제
helm uninstall -n kube-system metrics-server
prometheus-stack
#
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
# 파라미터 파일 생성
cat <<EOT > monitor-values.yaml
prometheus:
service:
type: NodePort
nodePort: 30001
prometheusSpec:
podMonitorSelectorNilUsesHelmValues: false
serviceMonitorSelectorNilUsesHelmValues: false
nodeSelector:
mynode: control-plane
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Equal"
effect: "NoSchedule"
grafana:
defaultDashboardsTimezone: Asia/Seoul
adminPassword: kans1234
service:
type: NodePort
nodePort: 30002
nodeSelector:
mynode: control-plane
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Equal"
effect: "NoSchedule"
defaultRules:
create: false
alertmanager:
enabled: false
EOT
# 배포
kubectl create ns monitoring
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --version 62.3.0 -f monitor-values.yaml --namespace monitoring
# 확인
helm list -n monitoring
# Grafana 접속 계정 : admin / kans1234 : macOS 사용자
echo -e "Prometheus URL = http://localhost:30001"
echo -e "Grafana URL = http://localhost:30002"
# Grafana 접속 계정 : admin / kans1234 : Windows 사용자
echo -e "Prometheus URL = http://192.168.50.10:30001"
echo -e "Grafana URL = http://192.168.50.10:30002"
# (참고) helm 삭제
helm uninstall -n monitoring kube-prometheus-stack


Prometheus Target connection refused 관련 정상 동작 설정 : kind k8s yaml 파일에 이미 적용되어 있음
# Prometheus Target connection refused 관련 정상 동작 설정 : kube-proxy
kubectl edit cm -n kube-system kube-proxy
...
metricsBindAddress: "0.0.0.0:10249" ## 추가
...
kubectl rollout restart daemonset -n kube-system kube-proxy
# Prometheus Target connection refused 관련 정상 동작 설정 : kube-controller-manager , kube-scheduler , etcd
docker exec -it myk8s-control-plane bash
----------------------------------------
cat /etc/kubernetes/manifests/kube-controller-manager.yaml | grep bind-address
sed -i "s/bind-address=127.0.0.1/bind-address=0.0.0.0/g" /etc/kubernetes/manifests/kube-controller-manager.yaml
cat /etc/kubernetes/manifests/kube-scheduler.yaml | grep bind-address
sed -i "s/bind-address=127.0.0.1/bind-address=0.0.0.0/g" /etc/kubernetes/manifests/kube-scheduler.yaml
cat /etc/kubernetes/manifests/etcd.yaml | grep 127.0.0.1:2381
sed -i "s/127.0.0.1:2381/0.0.0.0:2381/g" /etc/kubernetes/manifests/etcd.yaml
----------------------------------------
설치 후 iptables 확인
# iptables 정보 확인
for i in filter nat mangle raw ; do echo ">> IPTables Type : $i <<"; docker exec -it myk8s-control-plane iptables -t $i -S ; echo; done
for i in filter nat mangle raw ; do echo ">> IPTables Type : $i <<"; docker exec -it myk8s-worker iptables -t $i -S ; echo; done
for i in filter nat mangle raw ; do echo ">> IPTables Type : $i <<"; docker exec -it myk8s-worker2 iptables -t $i -S ; echo; done
실습 후 kind 삭제
kind delete cluster --name myk8s
'IT > Container&k8s' 카테고리의 다른 글
Calico 기본 통신(동일 노드에서 Pod - Pod 간) (1) | 2024.09.22 |
---|---|
Calico CNI 구성요소 (5) | 2024.09.08 |
POD & PAUSE Container (6) | 2024.09.01 |
KIND(kubernetes in docker) (3) | 2024.09.01 |
K8S Deep Dive (1) | 2024.09.01 |
- Total
- Today
- Yesterday
- NFT
- GCP
- S3
- VPN
- NW
- 혼공단
- operator
- 혼공챌린지
- GKE
- terraform
- AI
- EKS
- IaC
- 혼공파
- OS
- cloud
- SDWAN
- k8s
- PYTHON
- AWS
- controltower
- k8s cni
- k8s calico
- 파이썬
- 도서
- security
- autoscaling
- gcp serverless
- handson
- cni
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |