배경
statefulset의 모든 container을 외부에 노출 하도록 하는 방법으로는 metallb의 "loadbalancer" 방법을 사용하면 간단하다. metallb을 설치하여, network card (L2) 환경에서, IP을 만들어 주는 개념이다.
간단한 테스트를 하는 경우, window 환경에 WSL2 + Docker Desktop 구성을 자주 애용한다. "Reset Kubernetes" 하기가 편하고, 그냥 Docker 환경이랑 kubernetes 환경 둘다 구성해서 요리조리 테스트하기 좋다.
유일한 단점이 생겼다. statefulset이 외부 접속이 안되는 것이다.
metallb 을 구성하고, calico을 구성하려는데, Docker Desktop 은 CNI 계층을 직접 컨트롤 하기 때문에, CNI 플러그인 설치가 불가하였다. 따라서, calico, flannel 설치가 안된다.
( 참고 https://github.com/projectcalico/calico/issues/8102, https://dev.to/mikeyglitz/docker-kubernetes-on-wsl-2-4nl1 )
다음에는 CNI 설치가 되는 Minikube에서 테스트를 진행할 것 같다.
이슈 해결 방법
ingress-controller을 사용해서, pod에 port을 하나씩 지정하면 된다. pod-selector을 통해 파드 이름과 포트 이름만 지정하면 끝이다.
먼저, statefulset 생성에 앞서, nginx.conf을 위한 configmap을 생성한다.
파일명 : nginx.conf.template
events {
worker_connections 1024;
}
http {
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/templates/default.conf;
}
파일명 : nginx-index.conf.template
server {
listen 80;
server_name _;
location / {
default_type text/plain;
return 200 "Pod IP: ${pod_ip}\nPod Hostname: ${pod_hostname}\n";
}
}
아래 명령어를 통해, configmap을 생성한다.
$ kubectl create configmap nginx-config --from-file=nginx.conf.template --from-file=nginx-index.conf.template
이제 statefulset 을 생성한다.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nginx
spec:
serviceName: "nginx"
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
securityContext:
runAsUser: 0
runAsGroup: 0
fsGroup: 0
# hostNetwork: true
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
env:
- name: pod_ip
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: pod_hostname
valueFrom:
fieldRef:
fieldPath: metadata.name
command: ["/bin/sh", "-c", "envsubst < /etc/nginx/templates/nginx-index.conf.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"]
volumeMounts:
- name: config-volume
mountPath: /etc/nginx/templates
volumes:
- name: config-volume
configMap:
name: nginx-config
$ k get pod
NAME READY STATUS RESTARTS AGE
nginx-0 1/1 Running 0 23m
nginx-1 1/1 Running 0 23m
nginx-2 1/1 Running 0 23m
이제 서비스 생성을 통해, statefulset 하나하나에 port을 연결하여 사용하자.
apiVersion: v1
kind: Service
metadata:
name: nginx-0
spec:
selector:
statefulset.kubernetes.io/pod-name: nginx-0
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30080
type: NodePort
---
apiVersion: v1
kind: Service
metadata:
name: nginx-1
spec:
selector:
statefulset.kubernetes.io/pod-name: nginx-1
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30081
type: NodePort
---
apiVersion: v1
kind: Service
metadata:
name: nginx-2
spec:
selector:
statefulset.kubernetes.io/pod-name: nginx-2
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30082
type: NodePort
$ curl http://localhost:30080/
$ curl http://localhost:30081/
$ curl http://localhost:30082/
결론! NodePort 타입으로 하나씩 연결해서, 외부 연결이 되었다!
Docker Desktop이 calico 설치가 안되는걸 알기까지 꽤 시간이 걸렸다. 혹시 다른분도 같은 경험을 하고 계실지 몰라 글을 남긴다.