졸업과제 프로젝트를 진행하며 Openstack 플랫폼 상에 쿠버네티스 클러스터와 모니터링 환경을 자동화했던 과정을 정리한 글이다.
졸업과제에서는 쿠버네티스 환경에 대한 사용자의 입력(마스터 노드 수, 워커 노드 수, 노드의 이미지, 노드의 하드웨어 명세 등) 기반 동적인 구축을 진행하며, 본 포스트에선 자동화 구축을 위한 사전설정 및 프로세스를 기술하려고 한다. 기술을 많이 사용하고, 볼륨이 길다 보니 기술에 대한 설명은 하지 않고 필요한 부분만 설명을 진행하고자 한다.
아래 그림은 졸업과제에서 만든 인프라 관리 시스템의 구성도이다.
Orchstrator - Monitor - Openstack 파트가 본 포스트에서 해당한다.
먼저, Octavia는 Openstack의 로드밸런서 기능을 담당하는 컴포넌트이다. 그리고, Octavia Ingress Controller는 Kubernetes 환경에서 Octavia를 사용하여 Ingress 리소스를 관리하는 컨트롤러이다. OpenStack 환경에서 Octavia는 로드 밸런서 서비스로 사용되며, Kubernetes 클러스터와 통합될 때 Ingress 컨트롤러로의 역할을 수행한다. 이러한 통합을 통해 Kubernetes 내에서 트래픽 관리와 분산을 효율적으로 수행할 수 있다. AWS와 대응시켜본다면, Octavia Ingress Controller는 AWS Load Balancer Controller와 같은 기능을 수행한다고 볼 수 있다.
서비스 계정 만들기 및 권한 부여
cat <<EOF > ./serviceaccoumt.yaml
---
kind: ServiceAccount
apiVersion: v1
metadata:
name: octavia-ingress-controller
namespace: kube-system
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: octavia-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: octavia-ingress-controller
namespace: kube-system
EOF
kubectl apply -f serviceaccount.yaml
octaiva-ingress-controller 구성 준비
cat <<EOF > ./config.yaml
---
kind: ConfigMap
apiVersion: v1
metadata:
name: octavia-ingress-controller-config
namespace: kube-system
data:
config: |
cluster-name: default-cluster
openstack:
auth-url: ${OS_AUTH_URL}
domain-name: ${OS_DOMAIN_NAME}
username: ${OS_USERNAME}
password: ${OS_PASSWORD_INPUT}
project-id: ${OS_PROJECT_ID}
region: ${OS_REGION_NAME}
octavia:
subnet-id: 3c5d0988-0daa-4a97-91d4-045eab99c8f0
floating-network-id: f63fe367-91b3-4dad-a9a0-f7e04d9f30d3
EOF
kubectl apply -f config.yaml
octavia-ingress-controller 배포
cat <<EOF > ./deployment.yaml
---
kind: StatefulSet
apiVersion: apps/v1
metadata:
name: octavia-ingress-controller
namespace: kube-system
labels:
k8s-app: octavia-ingress-controller
spec:
replicas: 1
selector:
matchLabels:
k8s-app: octavia-ingress-controller
serviceName: octavia-ingress-controller
template:
metadata:
labels:
k8s-app: octavia-ingress-controller
spec:
serviceAccountName: octavia-ingress-controller
tolerations:
- effect: NoSchedule # Make sure the pod can be scheduled on master kubelet.
operator: Exists
- key: CriticalAddonsOnly # Mark the pod as a critical add-on for rescheduling.
operator: Exists
- effect: NoExecute
operator: Exists
containers:
- name: octavia-ingress-controller
image: docker.io/k8scloudprovider/octavia-ingress-controller:latest
imagePullPolicy: IfNotPresent
args:
- /bin/octavia-ingress-controller
- --config=/etc/config/octavia-ingress-controller-config.yaml
volumeMounts:
- mountPath: /etc/kubernetes
name: kubernetes-config
readOnly: true
- name: ingress-config
mountPath: /etc/config
hostNetwork: true
volumes:
- name: kubernetes-config
hostPath:
path: /etc/kubernetes
type: Directory
- name: ingress-config
configMap:
name: octavia-ingress-controller-config
items:
- key: config
path: octavia-ingress-controller-config.yaml
EOF
kubectl apply -f deployment.yaml
생성 결과
octavia-ingress-controller-0가 생성된 것을 확인할 수 있다.
Ingress Object Test
자, 실제로 로드밸런서가 생성되어 Openstack 내에서 공인 IP를 잘 할당받는지 확인해보자.
예제로 어릴 때 자주 플레이했던 2048 Game Image를 이용하였다.
---
apiVersion: v1
kind: Namespace
metadata:
name: game-2048
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: game-2048
name: deployment-2048
spec:
selector:
matchLabels:
app.kubernetes.io/name: app-2048
replicas: 5
template:
metadata:
labels:
app.kubernetes.io/name: app-2048
spec:
containers:
- image: public.ecr.aws/l6m2t8p7/docker-2048:latest
imagePullPolicy: Always
name: app-2048
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
namespace: game-2048
name: service-2048
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
type: NodePort
selector:
app.kubernetes.io/name: app-2048
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: game-2048
name: ingress-2048
annotations:
ingress.kubernetes.io/rewrite-targer: /
kubernetes.io/ingress.class: "openstack"
octavia.ingress.kubernetes.io/internal: "false"
spec:
ingressClassName: alb
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service-2048
port:
number: 80
IP 할당
아래 사진을 보면 Openstack 내에서 Public Network의 Floating IP Range Pool(AWS의 EIP라고 생각하면 된다)에서 IP가 할당된 것을 볼 수 있다.