서론
우선 MongoDB 파드를 생성할 것이다.
MongoDB 파드는 외부의 요청을 받지 않도록 Internal Service로 생성할 것이다.
그리고 MongoExpress Deployment를 생성할 것이다.
MongoExpress 는 DB url이 필요할 것이고, 생성해 두었던 MongoDB와 연결될 것이다.
MongoDB에 접근하기 위해선 인증을 위한 Credentials가 필요하다. DB User와 DB Password가 필요한 것이다.
이 정보들은 MongoExpress의 Deployment.yaml 파일의 environmental 부분에 입력할 것이다. 이는 어떻게 정보를 사용하는지를 나타내기 위함이다.
그리고 DB url을 가지고 있는 ConfigMap을 생성할 것이다.
그리고 Credentials를 가지고 있을 Secret을 생성할 것이다.
이 둘은 Deployment.yaml 파일에서 참조될 것이다.
MongoExpress를 브라우저에서 볼 수 있도록 접근을 허용하기위해 External Service를 생성할 것이다.
External Service는 외부에서 파드로 요청을 전달해주는 매개체가 되어준다.
쿠버네티스 컴포넌트 내부의 요청 흐름도
브라우저에서 MongoExpress url에 접속요청을 보낸다.
MongoExpress의 External Service가 요청을 받아서 MongoExpress 파드로 전달한다.
MongoExpress 파드는 Internal Service를 통해서 MongoDB에 접속한다.
이때 접속을 위해 ConfigMap에서 DB url을 참조한다.
그리고 Secret에서 User 정보를 가져와서 인증작업을 수행한다.
실습
kubectl get all
쿠버네티스 클러스터의 모든 컴포넌트들의 정보를 가져온다.
mongoDB Deployment
# mongo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongodb-deployment
labels:
app: mongodb
spec:
replicas: 1
selector:
matchLabels:
app: mongodb
template:
metadata:
labels:
app: mongodb
spec:
containers:
- name: mongodb
image: mongo:3.2
ports:
- containerPort: 27017
env:
- name: MONGO_INITDB_ROOT_USERNAME
valueFrom:
secretKeyRef:
name: mongodb-secret
key: mongo-root-username
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mongodb-secret
key: mongo-root-password
위 파일을 생성한다.
mongoDB Deployment에 대한 정보를 가지고 있다.
Deployment의 이름은 mongodb-deployment이고 label은 app: mongodb로 설정했다.
Deployment의 replicas는 1이다.
selector에서 labels 이름이 app: mongodb 인 파드들을 가진다고 선언한다.
template에서 파드의 청사진을 입력한다. 파드의 labels과 spec을 입력한다.
ports와 env정보를 입력하기 위해서 아래 사이트를 참고한다.
secretkeyRef는 Secret정보를 가져오는 부분이다.
name은 secret 파일의 metadata의 name과 같고, key는 secret파일에서 data로 적힌 부분의 key값을 입력해주면 된다.
secret 과 관련된 부분은 바로 아래 mongo secret부분에서 다룬다.
mongo Secret
# mongo-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mongodb-secret
type: Opaque
data:
mongo-root-username: dXNlcm5hbWU=
mongo-root-password: cGFzc3dvcmQ=
type 부분이 생소하다.
Opaque는 기본 key-value 페어를 사용하겠다는 뜻이다.
data에는 실제 Credential로 사용될 key-value 페어를 입력한다.
data에 저장된 value 들은 plain text가 아니라 base64로 인코딩된 정보를 저장해야 한다.
Secret에 정보를 저장하는 자체만으로는 정보를 비밀스럽게 유지할 수 없다.
수동으로 인코딩 해서 정보를 넣어보자.
echo -n 'username' | base64
echo -n 'password' | base64
username와 password를 base64로 인코딩하면 위와 같이 암호화된 문자열로 바뀐다.
중요한 점은 Deployment를 생성하기 전에 Secret을 반드시 먼저 만들어야 한다는 점이다.
Deployment를 생성하면서 Secret 정보를 참조하는데, 아직 값이 존재하지 않다면 에러가 발생하게 된다.
Secret 설정파일을 생성했다면 Secret을 생성하자.
kubectl apply -f mongo-secret.yaml
Deployment를 생성하자
kubectl apply -f mongo.yaml
파드가 너무 오랫동안 만들어지지 않으면 kubectl describe pod [파드이름]
을 사용해서 진행 상황을 살펴보도록 하자.
Internal Service
mongoDB와 Secret을 만들었으니 이들을 클러스터 내부에서 사용할 수 있도록 해주는 Internal Service를 만들어야 한다.
방금 만들었던 mongo.yaml에 Service 설정 정보를 추가할 것이다.
yaml 파일에는 다수의 설정 정보들이 입력될 수 있다.
mongo.yaml 파일의 끝에 아래 코드를 추가한다.
---
apiVersion: v1
kind: Service
metadata:
name: mongodb-service
spec:
selector:
app: mongodb
ports:
- protocol: TCP
port: 27017
targetPort: 27017
---
: 정보간의 구분을 위한 문자이다. 반드시 넣도록하자.
selector는 해당 Service가 어떤 파드와 연결될 지 결정해 준다.
ports 부분의 protocol은 TCP를 사용한다.
port: 클러스터에서 서비스의 27017포트로 요청을 보내면 요청을 받는다.(EXPOSE)
targetPort: 서비스의 27017포트로 받은 요청을 연결된 파드의 27017포트를 향해 내보낸다.
port와 targetPort는 서로 다를 수 있다.
하지만 파드의 containerPort와 targetPort는 반드시 동일해야 한다.
Service부분을 입력했으면 Service를 생성해보자.
kubectl apply -f mongo.yaml
MongoExpress Deployment
# mongo-express.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongo-express
labels:
app: mongo-express
spec:
replicas: 1
selector:
matchLabels:
app: mongo-express
template:
metadata:
labels:
app: mongo-express
spec:
containers:
- name: mongo-express
image: mongo-express
ports:
- containerPort: 8081
env:
- name: ME_CONFIG_MONGODB_ADMINUSERNAME
valueFrom:
secretKeyRef:
name: mongodb-secret
key: mongo-root-username
- name: ME_CONFIG_MONGODB_ADMINPASSWORD
valueFrom:
secretKeyRef:
name: mongodb-secret
key: mongo-root-password
- name: ME_CONFIG_MONGODB_SERVER
valueFrom:
configMapKeyRef:
name: mongodb-configmap
key: database_url
mongo-express.yaml 파일의 env 설정에 관한 내용이다.
mongoDB의 User 정보를 입력해야 하고, mongoDB container의 이름을 입력해줘야 한다.
User정보는 Secret에 입력되어있으므로 mongo.yaml에서 secret 정보를 참조할 때와 동일하게 작성해준다.
mongoDB SERVER 부분은 컨테이너의 이름이 필요하다.
mongo.yaml의 spec.container.name에 설정되어 있는 'mongo'를 사용한다.
SERVER 설정은 ConfigMap을 사용해야 한다. ConfigMap은 Secret에 비해서 다른 컴포넌트들이 쉽게 사용할 수 있는 일반적인 정보가 들어간다.
mongo ConfigMap
# mongo-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mongodb-configmap
data:
database_url: mongodb-service
중요한 부분은 mongoDB에 연결하기 위해서 Service를 사용하게 되었다는 것이다.
mongodb-service가 mongoDB 컨테이너로 향하는 요청을 포워딩해주는 통로가 되었다.
Secret과 마찬가지로 mongo-express를 생성하기 전에 ConfigMap을 먼저 생성해야 한다.
kubectl apply -f mongo-configmap.yaml
mongo-express Service
mongo Service를 만들었던 것과 동일하게 mongo-express.yaml 파일의 하단에 아래 코드를 추가한다.
---
apiVersion: v1
kind: Service
metadata:
name: mongo-express-service
spec:
selector:
app: mongo-express
type: LoadBalancer
ports:
- protocol: TCP
port: 8081
targetPort: 8081
nodePort: 30000
targetPort가 mongo-express의 containerPort와 동일하게 8081임을 확인했다.
그리고 type: LoadBalancer를 입력함으로써 External Service로 배포할 수 있게 해준다.
사실 loadbalancer라는 이름이 좋지 못하다. 왜냐하면 Internal service로 결국 loadbalancer의 역할을 동일하게 수행하기 때문이다. 단지 외부의 요청을 받지 못하는 것일 뿐이다.
nodePort는 브라우저에서 접근할 수 있는 port를 의미한다. 그리고 30000-32767 처럼 범위를 설정해 줄 수 있다.
mongo-express Deployment와 Service를 생성하자
kubectl apply -f mongo-express.yaml
mongo-express-service 실행
minikube service 명령어를 통해서 service를 실행해야 한다.
minikube service mongo-express-service
mongo-express-service의 url
minikube service mongo-express-service --url
service 접근
curl http://192.168.49.2:30000
<!DOCTYPE html>
<html lang="en">
<head>
<base href="/">
<meta charset="utf-8">
<title>Home - Mongo Express</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="/public/css/bootstrap.min.css" rel="stylesheet">
<link href="/public/css/bootstrap-theme.min.css" rel="stylesheet">
<link href="/public/css/style.css" rel="stylesheet" />
...
...
<script type="text/javascript">
'use strict';
window.ME_SETTINGS = {
readOnly: 'false' === 'true',
noDelete: 'false' === 'true',
codeMirrorEditorTheme: '',
baseHref: '/',
collapsibleJSON: 'true' === 'true',
collapsibleJSONDefaultUnfold: parseInt('1', 10),
confirmDelete: 'false' === 'true',
dbName: '',
collectionName: '',
bucketName: ''
};
</script>
<script src="/public/index-6145173d12f8f196322e.min.js"></script>
</body>
</html>
위와 같은 html 코드가 출력됨을 볼 수 있다.
curl을 통해 mongo-express-service에 요청을 보내면 다음과 같은 순서로 요청이 전달된다.
주의사항
virtualbox 내부의 minikube에서 external service를 배포한 것이다.
minikube의 ip를 찍어보면 다음과 같다.
내 virtualbox의 localhost IP인 192.168.56.101 와 다름을 볼 수 있다.
호스트(내 컴퓨터)에서 virtualbox의 ip:30000 로 접근을 하면 접근을 할 수 없다.
그래서 virtualbox의 포트포워딩도 설정하고, iptable도 설정해보고, ingress addon까지 설정해보고, minikube tunnel을 실행시켜봐도,
애초에 virtualbox에서 localhost로도 접근이 불가능했다.
minikube가 자신만의 ip를 부여받게되면서 VM의 local로 인식을 하지 못하는 듯 하다. VM(192.168.56.101)으로 요청을 보내면 192.168.49.2 로 요청이 전달되게끔 포트포워딩도 했는데 문제를 해결하지 못했다.
애초에 minikube가 로컬 환경에서의 테스트가 목적인 프로그램이라서 막혀있는것일 수도 있다.
https://velog.io/@moey920/Ubuntu-18.04-%EC%84%9C%EB%B2%84%EC%97%90-Kubeflow-1.4.1-%EB%B2%84%EC%A0%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0
비슷한 문제를 겪은 사람
출처 : https://www.youtube.com/watch?v=X48VuDVv0do
번역 : 나
Chapter : Demo Project: MongoDB and MongoExpress
'DevOps > Kubernetes' 카테고리의 다른 글
[kubernetes] VirtualBox의 Minikube Service 노출시키기 (0) | 2022.03.09 |
---|---|
[kubernetes] #8 네임스페이스를 통해 컴포넌트 구성하기 (0) | 2022.03.06 |
[kubernetes] #6 쿠버네티스 YAML 설정 파일 (0) | 2022.03.02 |
[kubernetes] #5 핵심 kubectl 명령어 (0) | 2022.03.01 |
[kubernetes] #4 Minikube와 kubectl - 클러스터 구축 (0) | 2022.02.28 |