간단한 웹을 만들어야 하는데,

간단하게 데이터를 다뤄야 할 때 종종 언급이 되는 Redis에 대해서 살펴보려고 한다.

 

"Key-Value 형식의 in-memory 데이터베이스"

 

기존에 내가 알고 있는 Redis에 대한 정보인데

공식 홈페이지에서 다시 한 번 확인해봤다.

 

- https://redis.io/

 

redis.io

 

"The opensource, in-memory data store used by millions ..."

어?! 'database'라고 하지 않고 'data store'라고 설명을 하네?! 라고 느끼는 순간! 사이트 중간에 다시 설명을 해주고 있다.

 

"A vibrant, open source database"

 

뭐, 결국은 내가 알고 있던 "key-value 형식의 in-memory databse"가 맞기는 하지만

스스로는 "data store"라는 정체성을 더 소중히 여기는 것이 아닌가 싶다.

 

서론이 너무 길었는데,

Redis에 대해서 너무나 잘 설명해주고 있는 좋은 아티클 링크 공유하면서 서두를 마치고자 한다.

 

- 6편의 아티클로 Redis에 대해서 심도있게 다루고 있음

  . https://insanelysimple.tistory.com/343

 

- Redis에 대해 소개하면서 "Redis vs Memcached" 비교

  . https://kdhyo98.tistory.com/89

 

 

이제 본론으로 들어가봅시다~!!

 

 

[ Redis 맛보기 ]

 

0. Background

개인적인 취향일 수도 있겠지만,

S/W 개발을 위한 기본적인 환경은 Linux 기반이 좋다고 생각하기 때문에

이번 실습 역시 Linux 배포판 中 Ubuntu 운영체제에서 진행한다.

 

또한, 최근 유행하고 있는 MSA 기조에 맞춰서

Application의 구성은 Container를 기반으로 하며

가장 대중적인 Docker를 활용하도록 하겠다.

 

- 테스트 환경 (필자가 이하 내용을 진행한 환경)

  . Host OS : Windows 10 Pro 21H1

  . VM : VirtualBox v6.1.34 r150636 (Qt5.6.2)

  . Guest OS : Ubuntu 18.04.6 LTS

  . Docker version 20.10.17, build 100c701

 

역시 개인적인 취향이 듬뿍 들어 있는 방식이긴 한데,

Server를 운영할 때 패키지의 버전관리 측면과 더불어 폐쇄망에서의 제약으로 인해

패키지들을 설치 할 때 직접 다운로드 받아서 진행하는 것을 선호한다.

 

- Docker 설치

  . Ubuntu 16.04 / 18.04 : https://www.whatwant.com/entry/Docker-Install-Ubuntu-16041804-64bit-using-Download

  . Ubuntu 20.04 : https://www.whatwant.com/entry/Docker-Install-Ubuntu-Server-2004

 

 

위와 같이 환경을 제시하긴했지만,

Windows/macOS 환경에서도 docker를 사용하기 때문에 비슷하게 동작하지 않을까 한다.

 

 

1. Persistent Volume

Redis가 in-memory data-store 솔루션이지만,

안정적 운영을 위해 메모리에 있는 데이터를 디스크에 쓰는 2가지 옵션을 제공한다.

 

① RDB (Redis Database) : 지정된 시간 간격으로 스냅샷을 파일로 저장

② AOF (Append Only File) : 모든 작업을 기록, 서버가 시작할 때 이 기록을 읽어서 데이터 재구성

 

어떤 옵션을 사용하더라도 데이터 저장이 되는 곳이 필요하고

보다 수월한 백업 등의 작업을 위해 docker volume 공간을 따로 구성하도록 하겠다.

 

# 리스트 확인
$ docker volume ls

# 생성
$ docker volume create [name]

# 상세 조회
$ docker volume inspect [name]

volume

 

2. Redis Config

접근 가능한 IP를 지정하고, 인증을 위한 패스워드를 넣는 등의 환경 설정을 위한 config 파일을 작성해보자.

또한 config 파일은 host에서 관리할 수 있도록 하겠다.

 

# 어떤 네트위크 인터페이스로부터 연결할 수 있도록 할 것인지 관리 (여기에서는 Anywhere)
bind 0.0.0.0

# 사용 포트 관리
port 6379

# Master 노드의 기본 사용자(default user)의 비밀번호 설정
requirepass [사용하고자 하는 비밀번호]

# Redis 에서 사용할 수 있는 최대 메모리 용량. 지정하지 않으면 시스템 전체 용량
maxmemory 2gb

# maxmemory 에 설정된 용량을 초과했을때 삭제할 데이터 선정 방식
# - noeviction : 쓰기 동작에 대해 error 반환 (Default)
# - volatile-lru : expire 가 설정된 key 들중에서 LRU algorithm 에 의해서 선택된 key 제거
# - allkeys-lru : 모든 key 들 중 LRU algorithm에 의해서 선택된 key 제거
# - volatile-random : expire 가 설정된 key 들 중 임의의 key 제거
# - allkeys-random : 모든 key 들 중 임의의 key 제거
# - volatile-ttl : expire time(TTL)이 가장 적게 남은 key 제거 (minor TTL)
maxmemory-policy volatile-ttl

# DB 데이터를 주기적으로 파일로 백업하기 위한 설정입니다.
# Redis 가 재시작되면 이 백업을 통해 DB 를 복구합니다.

save 900 1      # 15분 안에 최소 1개 이상의 key 가 변경 되었을 때
save 300 10     # 5분 안에 최소 10개 이상의 key 가 변경 되었을 때
save 60 10000   # 60초 안에 최소 10000 개 이상의 key 가 변경 되었을 때

 

redis.conf

 

redis.conf

 

3. Redis Image

Redis의 공식 Image 중에서 사용하고자 하는 버전을 찾아보자

- https://hub.docker.com/_/redis?tab=tag

 

Redis Image

 

현재 시점에서는 v7.0.2 가 최신이다.

 

 

4. Run

이제 Redis를 실행시켜 보자.

 

$ docker run \
-d \
--restart=always \
--name=redis \
-p 6379:6379 \
-e TZ=Asia/Seoul \
-v /srv/workspace/redis/redis.conf:/etc/redis/redis.conf \
-v redis_data:/data \
redis:7.0.2 redis-server /etc/redis/redis.conf

 

docker run

 

잘 실행이 되었는지도 확인해 보자.

 

docker logs

 

 

5. Redis Client

Redis에서 실제 값을 입력 해보자.

Redis Client의 실행 명령어는 'redis-cli' 이다.

 

$ docker exec -it redis redis-cli

 

NO AUTH

 

어?! 키 값 저장이 안된다.

redis.conf 작성할 때 명시한 패스워드를 사용하지 않았기 때문이다.

 

패스워드를 넣어서 client를 실행하면 정상 동작 한다.

 

AUTH

 

키 값 저장 및 조회가 잘 되는 것을 볼 수 있다.

 

여기까지~

 

반응형

 

보통 개발 단계에서는

Superuser 권한을 갖고 있는 계정으로 database를 사용하곤 한다. (나만 그런가?)

 

당연히 그 누구도 추천하지 않는, 바람직하지 않은 계정 사용법이다.

 

그러면 적절한 권한을 갖고 있는 개발용 계정을 생성해서 사용해야하고

그래서 지금은 계정 생성 및 삭제, 권한 부여 방법 등에 대해서 살펴볼 시간이다.

 

 

0. Environment

  - [PostgreSQL을 Docker로 설치하자](https://www.whatwant.com/entry/PostgreSQL-Docker)

 

 

1. psql

  - docker 환경에 특화된 내역이긴 하지만, 기록 차원에서 남긴다.

 

❯ docker exec -it postgres /bin/bash

root@d0b1fa1bb2b1:/# psql -U postgres

psql (14.2 (Debian 14.2-1.pgdg110+1))
Type "help" for help.

postgres=# 

 

 

2. 계정 및 권한 확인

  - `\du`

 

postgres=# \du
                                   List of roles
 Role name |                         Attributes                         | Member of 
-----------+------------------------------------------------------------+-----------
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

 

 

3. 계정 생성

  - `CREATE USER [username] WITH LOGIN PASSWORD '[password]';`

 

postgres=# CREATE USER whatwant WITH LOGIN PASSWORD 'xxxxxxxx';

CREATE ROLE


postgres=# \du
                                   List of roles
 Role name |                         Attributes                         | Member of 
-----------+------------------------------------------------------------+-----------
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 whatwant  |                                                            | {}

 

 

  ▶ Attributes of ROLE

     - 기본값은 `NO-` 속성들이다.

 

SUPERUSER or NOSUPERUSER SUPERUSER 여부
CREATEDB or NOCREATEDB DATABASE를 만들 수 있는 권한
CREATEROLE or NOCREATEROLE ROLE을 만들 수 있는 권한
LOGIN or NOLOGIN LOGIN 허용 여부
INHERIT or NOINHERIT 상속 가능 여부
REPLICATION or NOREPLICATION 복제 권한
BYPASSRLS or NOBYPASSRLS RLS(Row-Level Security) 무시 여부
PASSWORD [password] 패스워드
 VALID UNTIL [timestamp] 패스워드의 유효기간
IN ROLE [role_name] or IN GROUP [role_name] 지정한 ROLE의 구성원으로 포함
ROLE [role_name] or GROUP [role_name] 지정한 ROLE 부여
ADMIN [role_name] 윗 줄의 ROLE 속성 + WITH ADMIN

 

 

4. 권한 부여

  - DATABASE를 하나 생성하고 그에 따른 권한을 부여해보자

 

postgres=# CREATE DATABASE my_db WITH OWNER whatwant ENCODING 'UTF8';

CREATE DATABASE



postgres=# GRANT ALL PRIVILEGES ON DATABASE my_db TO whatwant;
GRANT

 

  ▶ Permission

     - 잘 모르는 내용도 있지만, 일단 리스트업 해본다.

 

SELECT 데이터 조회. UPDATE/DELETE 하려면 포함 필요
INSERT 데이터 추가
UPDATE 데이터 수정
DELETE 데이터 삭제
TRUNCATE 데이터 모두 삭제
REFERENCES 외래키 제약 조건 생성
TRIGGER 트리거
CREATE 스키마 생성
CONNECT 데이터베이스 연결
TEMPORARY 임시 테이블 생성
EXECUTE 함수/프로시저 연산자 허용
USAGE 스키마 객체 접근 허용
ALL PRIVILEGES 모든 권한

 

 

 

pgAdmin4로 확인해보자.

 

 

여기까지...

 

반응형

 

PostgreSQL을 시스템에 직접 붙어서 `psql`을 이용해서 다루는 것도 좋지만,

개인적으로 Web Interface를 통해서 database의 현황을 살펴보는 것을 좋아하기에

PostgreSQL을 설치하고 난 다음에 바로 찾아본 것이 바로 `pgAdmin4`이다.

 

깔끔한 설치를 위해 Docker로 한 번 설치해봤다.

 

 

0. PostgreSQL 설치

  - [PostgreSQL을 Docker로 설치하자](https://www.whatwant.com/entry/PostgreSQL-Docker)

 

 

1. pgAdmin4 설치

  - 그냥 바로 실행하자.

  - email 주소와 password는 각자 취향에 다라 지정해주면 된다.

 

❯ sudo docker run -p 5050:80 -e 'PGADMIN_DEFAULT_EMAIL=abc@email.com' \
                        -e 'PGADMIN_DEFAULT_PASSWORD=password' -d dpage/pgadmin4

Unable to find image 'dpage/pgadmin4:latest' locally
latest: Pulling from dpage/pgadmin4
59bf1c3509f3: Pull complete 
6e9ec7ad2b67: Pull complete 
a0e18fcb2977: Pull complete 
fd2b27e2842d: Pull complete 
51136bc64bc0: Pull complete 
f64eecb587f3: Pull complete 
9cb5237d6528: Pull complete 
facb2de54b7c: Pull complete 
2c30d334d2ee: Pull complete 
27b8ff406ea1: Pull complete 
b87dab9776e7: Pull complete 
3e9a234b4839: Pull complete 
160949aa8885: Pull complete 
02526e9b4604: Pull complete 
Digest: sha256:3a2f4533b0e33baa09260ce02d0912058881c55cef800b73219e19b0a9d75658
Status: Downloaded newer image for dpage/pgadmin4:latest
4fb11f1a591ed35244b6db9045b844cae781ca3b59c54006b172805567dd1326

 

 

2. Connect

  - http://127.0.0.1:5050/

  - 실행할 때 입력한 email 주소와 password를 이용해서 로그인 하면 된다.

 

 

 

3. Add New Server

  - PostgreSQL 서버를 등록해주자.

 

 

  - name 하나 지어주고,

 

 

  - Connection 정보를 입력해주자.

  - `localhost`, `127.0.0.1`로 지정하면 연결이 안된다. IP 적어주자.

  - `Username`과 `Password` 제대로 입력하고 Save 하면 된다.

 

 

  - 이제 짠~

 

 

 

일단 여기까지~

 

반응형

 

개발을 하는 중에 PostgreSQL을 개발PC에 설치할 필요가 생겼는데

그냥 설치하기에는 개발PC가 지저분해질까봐 Docker를 이용해서 설치하려고 한다.

 

[ 개발PC 환경 ]

  - 운영체제: Ubuntu 18.04.6 LTS

  - docker: Docker version 20.10.12, build e91ed57

 

 

사실 포스팅을 굳이 해야할까 싶을 정도로 너무 간단하게 설치가 된다.

 

 

1. Docker Volume 생성

  - 데이터를 조금이라도 안전하게 보관하기 위해서 별도 volume으로 관리하자.

  - 실제 저장 위치도 확인해 볼 수 있다.

 

❯ docker volume create postgres_data

postgres_data


❯ sudo ls -al /var/lib/docker/volumes/

합계 40
drwx-----x  4 root root  4096  3월 21 21:14 .
drwx--x--- 13 root root  4096  3월 21 20:12 ..
brw-------  1 root root  8, 1  3월 21 20:12 backingFsBlockDev
-rw-------  1 root root 32768  3월 21 21:14 metadata.db
drwx-----x  3 root root  4096  2월 13 03:22 portainer_data
drwx-----x  3 root root  4096  3월 21 21:14 postgres_data

 

 

2. run PostgreSQL

  - 실행은 한 줄이면 된다 ^^

  - password는 각자 취향에 맞게 작성하면 된다.

 

❯ docker run -d -p 5432:5432 --name postgres -e POSTGRES_PASSWORD=password \
                 -v postgres_data:/var/lib/postgresql/data postgres

Unable to find image 'postgres:latest' locally
latest: Pulling from library/postgres
ae13dd578326: Pull complete 
723e40c35aaf: Pull complete 
bf97ae6a09b4: Pull complete 
2c965b3c8cbd: Pull complete 
c3cefa46a015: Pull complete 
64a7315fc25c: Pull complete 
b9846b279f7d: Pull complete 
ed988fb8e7d9: Pull complete 
ed4bb4fd8bb5: Pull complete 
ead27f1733c8: Pull complete 
7d493bacd383: Pull complete 
0920535e8417: Pull complete 
db76d5bdbf2c: Pull complete 
Digest: sha256:d1db54eade17ebfaa6cfdca90c83f8cb0d54bcceb1270a0848e0b216d50c325c
Status: Downloaded newer image for postgres:latest
d0b1fa1bb2b1b580e96e1790b6f7bebfcfdc88c885c35e1af57d82379e5df7b7

 

 

3. psql

  - 이대로 끝내면 서운하니까 psql 까지만 접속해보자.

 

❯ docker exec -it postgres /bin/bash

root@d0b1fa1bb2b1:/# psql -U postgres

psql (14.2 (Debian 14.2-1.pgdg110+1))
Type "help" for help.

postgres=# 

 

 

 

여기까지~

반응형

 

# Portainer ?

  - `Docker 관리를 위한 GUI 도구`로 시작해서 지금은 K8s, Azure ACI에 대한 지원까지 확장되고 있다.

  - https://www.portainer.io/

 

 

# 설치 환경

  - Ubuntu 20.04, Docker 20.10.12

❯ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04.3 LTS
Release: 20.04
Codename: focal

❯ docker --version
Docker version 20.10.12, build e91ed57

 

 

# Install Portainer with Docker on Linux

  - Reference: https://docs.portainer.io/v/ce-2.11/start/install/server/docker/linux

 

① create volume

  - portainer에서 사용할 volume을 생성하고 잘 생성되었는지 확인해보자

❯ docker volume create portainer_data
portainer_data

❯ docker volume ls
DRIVER    VOLUME NAME
local     portainer_data

 

② install portainer

  - docker를 이용해 portainer를 설치하고 결과까지 확인해보자

❯ docker run -d -p 8000:8000 -p 9443:9443 --name portainer \
    --restart=always \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v portainer_data:/data \
    portainer/portainer-ce:2.11.0
Unable to find image 'portainer/portainer-ce:2.11.0' locally
2.11.0: Pulling from portainer/portainer-ce
0ea73420e2bb: Pull complete 
c367f59be2e1: Pull complete 
b71b88d796e2: Pull complete 
Digest: sha256:4f126c5114b63e9d1bceb4b368944d14323329a9a0d4e7bb7eb53c9b7435d498
Status: Downloaded newer image for portainer/portainer-ce:2.11.0
92f2bb51b10e3eb9bb09dd7f1731abd8796a8e1611cd42ef1d30b472472d7e13

❯ docker ps
CONTAINER ID   IMAGE                           COMMAND        CREATED          STATUS          PORTS                                                                                            NAMES
92f2bb51b10e   portainer/portainer-ce:2.11.0   "/portainer"   39 seconds ago   Up 25 seconds   0.0.0.0:8000->8000/tcp, :::8000->8000/tcp, 0.0.0.0:9443->9443/tcp, :::9443->9443/tcp, 9000/tcp   portainer

 

③ login

   - `https://localhost:9443` 또는 `https://IP:9443` 주소를 통해 웹 접근 해보자

비공개

  - 인증서 문제로 위와 같은 화면이 나오는데, `고급` 버튼을 누르고 `192.168.100.100(안전하지 않음)` 클릭!

passwd

  - 그리고, 관리자 패스워드 설정을 진행하면 된다

Get Started

  - 다른 서버도 같이 관리할 수 있지만, 지금 우리는 local만 관리할 것이기 때문에 `Get Started`를 클릭하면 된다

Home

  - local 밖에 없으니 하나 밖에 보이지 않는 것이 당연하고, `local`을 클릭해보자

local

 

너무나 깔끔하고 좋다~

 

반응형

 

Docker 또는 Kubernetes 환경에서 Linux를 가지고는 많이 놀아봤지만

Windows를 띄워볼 생각을 해보지는 못했다.

 

Windows 환경에서 Linux를 container로 실행하는 것도 신기하게 여겨졌지만

Windows 자체를 container로 실행하는 것은 생각해보지도 못했다.

 

그러던 중 우연히 찾게된 github.com repository 하나!

 

https://github.com/hectorm/docker-qemu-win2000

 

https://github.com/hectorm/docker-qemu-win2000

 

그렇다! Windows2000을 container로 띄워준다 !!!

 

Windows 2000 on Docker

 

테스트 환경은 다음과 같다.

 

- Host OS

      : Windows 10 Professional

- VM S/W

      : VirtualBox

- Guest OS

      : Ubuntu 18.04 64bit

 

VirtualBox를 이용해서 Ubuntu 환경을 구축한 뒤, Docker 까지 설치했다.

 

Ubuntu in VirtualBox

 

KVM을 사용하기 위해서 VirtualBox 설정을 좀 봐줘야 한다.

 

CPU Core 값도 2 이상 주고,

`네스티드 VT-x/AMD-V 사용하기`를 선택해야 한다.

 

설정

 

제대로 되어 있으면 다음과 같이 확인되어야 한다.

 

vmx / svm

 

`cpu cores` 값도 2 이상이 잡혀 있는지 잘 보고,

`flasg`에 `vmx` 또는 `svm` 값이 보이는지도 잘 확인하자. (안보이면 안된다)

 

 

이걸로 준비 끝이다!

 

docker run --detach \
  --name qemu-win2000 \
  --device /dev/kvm \
  --publish 127.0.0.1:3389:3389/tcp \
  --publish 127.0.0.1:5900:5900/tcp \
  --publish 127.0.0.1:6080:6080/tcp \
  docker.io/hectormolinero/qemu-win2000:latest

 

publish 옵션을 보면 알겠지만,

그리고 README.md에도 잘 설명이 되어있듯이 4가지 방법으로 접근할 수 있다.

 

- RDP (3389/TCP)

      : any RDP client, login with Administrator / password.

- VNC (5900/TCP)

      : any VNC client, without credentials.

- noVNC (6080/TCP)

      : http://127.0.0.1:6080/vnc.html

- Shell

      : docker exec -it qemu-win2000 vmshell

 

 

제일 편한 방법은 `noVNC`

크롬으로 접속만 하면 된다.

 

http://127.0.0.1:6080/vnc.html

 

noVNC

 

noVNC

 

진짜다!

Win2K SP4 !!!

정말이다!

 

 

졸려서 여기까지~ ^^

 

반응형

 

GCP, AWS와 같은 Cloud 업체에서 제공해주는 Managed K8s 환경을 사용하는 것이 아니라,

Local 환경에서 직접 K8s를 설치하는 경우

Ingress를 이용하기 위해서는 추가적인 설치를 해야 한다.

 

다른 네트워크 관련된 것들과 마찬가지로

Ingress도 여러가지 중에 선택적으로 설치해서 사용해야 한다.

 

직접 설치해서 사용하는 경우 일반적으로 Nginx 기반의 Ingress를 선택한다.

그런데, 이 부분에서 고생을 했던 이유가 Nginx 기반 Ingress 자체도 종류가 여러가지라는 것이다.

 

그 중에서 대표적인 Nginx Ingress Controller는 다음의 2가지 이다.

  - kubernetes/ingress-nginx

  - nginxinc/kubernetes-ingress

 

첫번째 것은 Kubernetes 진영에서 배포하고 있는 ingress-nginx 이고,

두번째 것은 Nginx 진영에서 배포하고 있는 nginx-ingress 이다.

 

두 배포판의 차이점을 정리한 내용은 다음 링크에서 확인해보면 된다.

  - https://docs.nginx.com/nginx-ingress-controller/intro/nginx-ingress-controllers

 

 

 

 

기능적으로 Nginx에서 배포하는 것이 좀 더 다양한 것 같기는 한데,

아무래도 Kubernetes 문서에서 보이는 Ingress 내용들의 기준이 되는 것은

`kubernetes/ingress-nginx`일 것이다.

 

 

 

그런데, 문제는 Kubespray로 Kubernetes를 설치할 때

addon으로 ingress를 선택하게 되면

이 때 설치되는 것이 'kubernetes/ingress-nginx'가 아니다.

(잘못알고 있을 수도 있으니, 정확히 알고 계신 분들 계시면 제보 바랍니다)

 

 

 

그래서,

Kubespray를 이용해서 Kubernetes를 설치할 때

addon 설정할 때 ingress를 선택하지 말고

나중에 직접 Ingress를 설치하는 방법으로 하고자 한다.

 

 

Kubernetes는 설치를 마친 상태에서

Ingress 설치를 하는 과정으로 진행해보자.

 

Reference

  - https://github.com/kubernetes/ingress-nginx/

  - https://kubernetes.github.io/ingress-nginx/deploy/

 

 

다양한 환경에서의 설치 방법이 각각 있지만,

우리가 여기에서 살펴볼 것은 Bare-Metal 환경을 기준으로 하겠다.

  - https://kubernetes.github.io/ingress-nginx/deploy/#bare-metal

 

그리고, 이 방법은 `Nodeport` 방식으로 설정된다.

(LoadBalancer가 있으면 그것을 이용하겠지만, 개인적으로 구축한 K8s 환경에서는...)

 

 

 

사실, 설치 방법은 너무나 쉽다.

단 1줄 !!!

 

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.0.0/deploy/static/provider/baremetal/deploy.yaml

 

정말 중요한 것은

잘 동작하는지 검증을 해보는 것일 것이다.

 

Namespace로 작업 공간 확보한 다음

Deployment 만들고 Service 만들어서

Ingress로 접근하도록 해보자.

 

 

① 따로 방을 잡아놓기 위해 Namespace 만들고,

$ nano 01.Namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: test-ingress

 

② Deployment를 이용해 Pod를 만들어 놓자

$ nano 02.Deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deploy

spec:
  replicas: 3

  selector:
    matchLabels:
      app: web

  template:
    metadata:
      name: web-pod
      labels:
        app: web

    spec:
      containers:
      - image: whatwant/node-web:1.0
        name: web
        ports:
        - containerPort: 8080
          protocol: TCP

 

③ Pod들을 연결할 Service를 만들자

$ nano 03.Service.yaml
apiVersion: v1
kind: Service
metadata:
  name: web-svc

spec:
  ports:
  - port: 80
    targetPort: 8080

  selector:
    app: web

 

지금까지 만들어 놓은 YAML을 실행하자

$ kubectl create -f ./01.Namespace.yaml

$ kubectl create --namespace=test-ingress -f ./02.Deployment.yaml

$ kubectl create --namespace=test-ingress -f ./03.Service.yaml

 

 

이제, 본론이다!

Ingress를 만들어서 Service를 외부로 오픈해보자.

$ nano ./04.Ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /

spec:
  rules:
  - http:
      paths:
      - path: /test
        pathType: Prefix
        backend:
          service:
            name: web-svc
            port:
              number: 80

 

만들어 놓은 YAML을 실행하자

$ kubectl create --namespace=test-ingress -f ./04.Ingress.yaml

 

 

이제 Web-Browser로 확인을 하면 되는데,

ingress-nginx가 지금 어떤 IP의 어떤 Port로 서비스 되고 있는 것일까?

$ kubectl get services --namespace=ingress-nginx

NAME                                       TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                               AGE
ingress-nginx-controller                 NodePort    10.233.29.64    <none>          80:32035/TCP,443:32407/TCP   11h
ingress-nginx-controller-admission   ClusterIP     10.233.38.85    <none>          443/TCP                              11h

 

`ingress-nginx`는 지금 `NodePort` 방식으로 서비스 되고 있으므로 IP는 node들의 IP 아무것이나 ...

Port는 http는 32035, https는 32407을 사용하고 있음을 확인할 수 있다.

(당연히 각자의 환경에서 Port는 다를 수 있다)

 

 

그러면, 이제 웹브라우저로 확인해보자.

 

 

어?! 왜 안되지 ?!

멍청하면 손발이 고생한다고... 이 문제를 해결하려고 3일 넘게 잠도 잘 못자고 정말 고생했다 ㅠㅠ

 

엄청난 구글링 시도를 했지만 속시원한 해결책을 찾지 못하다가... 결국은 방법을 찾았다.

 

 

일단, ingress-nginx의 로그를 확인해야 했었다.

$ kubectl logs --namespace=ingress-nginx ingress-nginx-controller-57ffff5864-p52bb -f
-------------------------------------------------------------------------------
NGINX Ingress controller
  Release:       v1.0.0
  Build:         041eb167c7bfccb1d1653f194924b0c5fd885e10
  Repository:    https://github.com/kubernetes/ingress-nginx
  nginx version: nginx/1.20.1

-------------------------------------------------------------------------------

W0918 04:05:51.466315       6 client_config.go:615] Neither --kubeconfig nor --master was specified.  Using the inClusterConfig.  This might not work.
I0918 04:05:51.466488       6 main.go:221] "Creating API client" host="https://10.233.0.1:443"
I0918 04:05:51.476011       6 main.go:265] "Running in Kubernetes cluster" major="1" minor="20" git="v1.20.7" state="clean" commit="132a687512d7fb058d0f5890f07d4121b3f0a2e2" platform="linux/amd64"
I0918 04:05:51.723687       6 main.go:104] "SSL fake certificate created" file="/etc/ingress-controller/ssl/default-fake-certificate.pem"
I0918 04:05:51.740515       6 ssl.go:531] "loading tls certificate" path="/usr/local/certificates/cert" key="/usr/local/certificates/key"
I0918 04:05:51.769911       6 nginx.go:253] "Starting NGINX Ingress controller"
I0918 04:05:51.783535       6 event.go:282] Event(v1.ObjectReference{Kind:"ConfigMap", Namespace:"ingress-nginx", Name:"ingress-nginx-controller", UID:"9e277dae-b490-471f-806f-c88f9554da0f", APIVersion:"v1", ResourceVersion:"32531", FieldPath:""}): type: 'Normal' reason: 'CREATE' ConfigMap ingress-nginx/ingress-nginx-controller
I0918 04:05:52.972526       6 nginx.go:295] "Starting NGINX process"
I0918 04:05:52.972784       6 nginx.go:315] "Starting validation webhook" address=":8443" certPath="/usr/local/certificates/cert" keyPath="/usr/local/certificates/key"
I0918 04:05:52.972852       6 leaderelection.go:243] attempting to acquire leader lease ingress-nginx/ingress-controller-leader...
I0918 04:05:52.973417       6 controller.go:150] "Configuration changes detected, backend reload required"
I0918 04:05:52.985822       6 leaderelection.go:253] successfully acquired lease ingress-nginx/ingress-controller-leader
I0918 04:05:52.992811       6 status.go:84] "New leader elected" identity="ingress-nginx-controller-57ffff5864-p52bb"
I0918 04:05:53.007665       6 status.go:204] "POD is not ready" pod="ingress-nginx/ingress-nginx-controller-57ffff5864-p52bb" node="worker2"
I0918 04:05:53.043798       6 controller.go:167] "Backend successfully reloaded"
I0918 04:05:53.043952       6 controller.go:178] "Initial sync, sleeping for 1 second"
I0918 04:05:53.044349       6 event.go:282] Event(v1.ObjectReference{Kind:"Pod", Namespace:"ingress-nginx", Name:"ingress-nginx-controller-57ffff5864-p52bb", UID:"6b9e8d63-801f-4ac2-8533-8a0164e792bf", APIVersion:"v1", ResourceVersion:"32685", FieldPath:""}): type: 'Normal' reason: 'RELOAD' NGINX reload triggered due to a change in configuration
I0918 05:25:59.272392       6 main.go:101] "successfully validated configuration, accepting" ingress="web-ingress/test-ingress"
I0918 05:25:59.278726       6 store.go:361] "Ignoring ingress because of error while validating ingress class" ingress="test-ingress/web-ingress" error="ingress does not contain a valid IngressClass"
I0918 05:38:54.461751       6 store.go:336] "Ignoring ingress because of error while validating ingress class" ingress="test-ingress/web-ingress" error="ingress does not contain a valid IngressClass"
I0918 05:39:44.049518       6 main.go:101] "successfully validated configuration, accepting" ingress="web-ingress/test-ingress"
I0918 05:39:44.053660       6 store.go:361] "Ignoring ingress because of error while validating ingress class" ingress="test-ingress/web-ingress" error="ingress does not contain a valid IngressClass"

 

그렇다. 원인은 로그에 다 있었다 ㅠㅠ

 

`IngressClass`가 문제란다.

이걸 해결하면 되는데...

$ nano ./04.Ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    ingressclass.kubernetes.io/is-default-class: true

spec:
  rules:
  - http:
      paths:
      - path: /test
        pathType: Prefix
        backend:
          service:
            name: web-svc
            port:
              number: 80

 

annotation 한 줄 추가해주면 된다.

 

 

모든 Ingress에 저렇게 입력하기 싫다면,

기본 IngressClass nginx를 수정하면 된다.

 

`ingress-nginx` namespace에 있는 ingressclass를 살펴보면 `nginx` 이름으로 존재하고 있다.

$ kubectl get ingressclasses --namespace=ingress-nginx 

NAME    CONTROLLER             PARAMETERS   AGE
nginx     k8s.io/ingress-nginx     <none>          12h

 

edit 하면 되는데,

막간을 이용해서 tip 하나 추가하자면,

기본적으로 `kubectl edit`를 하게되면 기본 에디터로 `vi`가 실행된다.

 

vi를 싫어하는 나같은 사람들을 위해 에디터 변경을 하는 방법이 있다.

$ export KUBE_EDITOR=nano

 

그리고, 이제 edit를 해보자.

$ kubectl edit ingressclasses nginx --namespace=ingress-nginx
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  annotations:
    ingressclass.kubernetes.io/is-default-class: "true"
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"networking.k8s.io/v1","kind":"IngressClass","metadata":{"annotations":{},"labels":{"app.kubernetes.io/component":"controller","app.kubernetes.io/instance":"ingress-nginx","app.kubernetes.io/managed-by":"Helm","app.kubernetes.io/name":"ingress-nginx","app.kubernetes.io/version":"1.0.0","helm.sh/chart":"ingress-nginx-4.0.1"},"name":"nginx"},"spec":{"controller":"k8s.io/ingress-nginx"}}
  creationTimestamp: "2021-09-18T04:05:10Z"
  generation: 1
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/version: 1.0.0
    helm.sh/chart: ingress-nginx-4.0.1
  name: nginx
  resourceVersion: "102271"
  uid: 13fa4354-bb3d-4dee-ae56-5d14600354cb
spec:
  controller: k8s.io/ingress-nginx

 

나머지는 모르겠고 ... 위에 색으로 칠한 부분만 추가되어 있으면 된다.

 

 

문제 해결을 위해 열심히 구글링 하면서 알게된 지식 추가 공유 !

 

- Ingress 생성할 때, 연결하고자 하는 Service가 있는 namespace에 같이 존재해야 한다

  . Ingress Controller는 전체 namespace를 바라보고 있기에 가능하다.

 

- Ingress와 연결되는 Service는 Cluster IP와 매핑이 된다.

  . 그래서 Service는 Nodeport 타입이어도 되고, 아니어도 된다.

 

 

이번에는 여기까지~

반응형

 

오늘 포스팅을 위해

그동안 많은 과정을 거쳐왔나보다 ^^

 

- 오래된 노트북 - 우분투 서버로 만들기 (Ubuntu 20.04 Server)

- Ubuntu 18.04 에서 Python3 편하게 사용하기
- Kubernetes Install (Ubuntu 20.04)
- Kubespray 이용하여 Kubernetes 설치하기
- Vagrant 이미지 업로드 (VirtualBox)
- Vagrant 사용하기 - 기본

- Vagrant 여러 개의 VM 생성하기

 

포스팅으로만 하면 위의 내용 정도뿐이지만,

그 뒤에서 공부하고 시행착오를 겪은 것을 합치면.... 에휴...

멍청하면 손발 뿐만 아니라 온몸이 고생한다더니...

 

 

로컬 환경에서 VM을 이용한 Kubernetes 실습 환경을 갖추는 것이 목표이다.

 

VM 생성도 Vagrant를 이용해서 기본적인 사항은 편하게 할 수 있도록 했고,

Kubernetes 설치 과정은 공부를 위해 직접 수행하는 방식으로 구성했다.

 

즉, Ubuntu 꾸미기(?) 등과 같은 과정은 Skip 하고

공부가 필요한 Kubernetes 설치 과정은 가급적 직접 수행해보자.

 

(물론 Kubespray를 사용하지 않고 정말 쌩으로 해보면 좋겠지만... 어느 정도는 ^^)

 

 

 

0. Host Environment

  - 다음 Spec이 최소사양이라는 말은 아니고, 참고하시라고...

    . CPU: AMD Ryzen 5 3600X

    . RAM: 32GB

    . VGA: Nvidia GeForce RTX 2060

    . OS: Windows 10 Pro

 

 

1. Vagrant 설치

  - https://www.vagrantup.com/

 

 

2. VirtualBox 설치

  - https://www.virtualbox.org/

 

 

3. Vagrant Up

  - 다음 내용의 Vagrantfile을 이용해서 VM을 생성하자

    (개인적인 취향으로 Host의 git-bash 환경에서 작업하는 것을 좋아하기에

     아래 sh 명령어들이 linux 스타일로 되어있다)

 

host$ mkdir k8s-vm
host$ cd k8s-vm
host$ nano Vagrantfile
host$ vagrant up

 

# -*- mode: ruby -*-
# vi: set ft=ruby :

N = 2


Vagrant.configure("2") do |config|


  config.vm.define "w-k8s-master" do |cfg|

    cfg.vm.box = "whatwant/Ubuntu-20.04-Server"
    cfg.vm.box_version = "0.2.0"

    cfg.vm.hostname = "master"
    cfg.vm.network "public_network", ip: "192.168.100.200"

    cfg.vm.provider "virtualbox" do |vb|
      vb.gui = false
      vb.cpus = "2"
      vb.memory = "2048"
    end

    cfg.vm.provision "shell", inline: <<-SHELL
      apt-get update
      apt-get upgrade -y
    SHELL

  end


  (1..N).each do |i|
    config.vm.define "w-k8s-worker#{i}" do |cfg|

      cfg.vm.box = "whatwant/Ubuntu-20.04-Server"
      cfg.vm.box_version = "0.2.0"

      cfg.vm.hostname = "worker#{i}"
      cfg.vm.network "public_network", ip: "192.168.100.20#{i}"

      cfg.vm.provider "virtualbox" do |vb|
        vb.gui = false
        vb.cpus = "1"
        vb.memory = "1280"
      end

      cfg.vm.provision "shell", inline: <<-SHELL
        apt-get update
        apt-get upgrade -y
      SHELL

    end
  end

end

 

  - master 1대, worker 2대 구성으로 했다.

  - VM 이미지는 Ubuntu 20.04 Server 기반으로 미리 살짝 꾸며둔 것을 이용했다.

  - VM의 CPU/RAM 설정은 가급적 최소한의 규격으로 잡아두었다.

  - `vagrant up` 했을 때 종종 실패를 하는데, 여러 번 try하면 결국 된다.

  - IP 설정은 각자의 공유기 셋팅에 따라 수정이 필요하다.

 

 

4. (master) Kubespray 실행 환경 만들기

  - Kubespray는 ansible 기반이기에 그에 따른 환경을 갖춰야 한다.

  - 필요한 package 설치 후 ssh 접근이 가능하도록 키 생성 & 배포를 진행한다.

  - 패스워드는 `vagrant`이다.

 

host$ ssh vagrant@192.168.100.200

master$ sudo apt install ansible python3-argcomplete

master$ ssh-keygen

master$ ssh-copy-id 192.168.100.200

master$ ssh-copy-id 192.168.100.201

master$ ssh-copy-id 192.168.100.202

 

  - ansible에서 접근할 서버 정보들을 입력해놓자

$ sudo nano /etc/ansible/hosts
[all]
master  ansible_ssh_host=192.168.100.200 ip=192.168.100.200 ansible_user=vagrant
worker1 ansible_ssh_host=192.168.100.201 ip=192.168.100.201 ansible_user=vagrant
worker2 ansible_ssh_host=192.168.100.202 ip=192.168.100.202 ansible_user=vagrant

[k8s_master]
master

[k8s_worker]
worker1
worker2

  - 테스트

$ ansible all -m ping

 

 

5. (master/worker) Kubernetes 설치를 위한 환경 설정

  - master/worker 모두 Kubernetes 설치를 위한 환경 설정을 진행해야 한다.

  - swap 공간 사용하지 않도록 하고, 서로 접근이 용이하게 되도록 host 설정을 해주자.

  - ip forward 기능도 활성화 시켜줘야 한다.

 

  - master/worker 접근은 앞에서 했던 것과 마찬가지로 `ssh vagrant@192.168.100.200/201/202` 방식으로...

 

master/worker$ sudo swapoff -a

master/worker$ sudo nano /etc/fstab
# /swap.img   none    swap    sw  0   0

master/worker$ sudo sh -c 'echo 1 > /proc/sys/net/ipv4/ip_forward'

master/worker$ sudo nano /etc/hosts
192.168.100.200 master
192.168.100.201 worker1
192.168.100.202 worker2

 

 

6. (master/worker) Restart

  - 깔끔한 진행을 위해 이 시점에서 모두 restart 진행하고 이후 진행하자!

 

 

7. (master) Kubespray 이요한 Kubernetes 설치

  - 이제 기본환경 준비는 끝났다.

  - Kubespray 설치 준비를 할 차례다.

host$ ssh vagrant@192.168.100.200

master$ cd /srv/install

master$ git clone https://github.com/kubernetes-sigs/kubespray.git

master$ cd kubespray

master$ git checkout v2.16.0

master$ sudo pip install -r requirements.txt

master$ cp -rfp inventory/sample inventory/mycluster

master$ declare -a IPS=(192.168.100.200 192.168.100.201 192.168.100.202)

master$ CONFIG_FILE=inventory/mycluster/hosts.yaml python contrib/inventory_builder/inventory.py ${IPS[@]}

master$ nano ./inventory/mycluster/hosts.yaml

  - 아래와 같이 수정해보자.

all:
  hosts:
    master:
      ansible_host: 192.168.100.200
      ip: 192.168.100.200
      access_ip: 192.168.100.200
    worker1:
      ansible_host: 192.168.100.201
      ip: 192.168.100.201
      access_ip: 192.168.100.201
    worker2:
      ansible_host: 192.168.100.202
      ip: 192.168.100.202
      access_ip: 192.168.100.202
  children:
    kube_control_plane:
      hosts:
        master:
    kube_node:
      hosts:
        worker1:
        worker2:
    etcd:
      hosts:
        master:
    k8s_cluster:
      children:
        kube_control_plane:
        kube_node:
    calico_rr:
      hosts: {}

  - 당연하게도 위의 설정은 각자 IP 환경에 맞게 업데이트

 

master$ nano ./inventory/mycluster/group_vars/k8s_cluster/addons.yml

 

  - addons는 아래 3개 정도만 해보자. (ingress는 나중에 직접 설치할 것이다)

dashboard_enabled: true
helm_enabled: true
metrics_server_enabled: true

 

  - proxy mode도 iptables로 변경해보자

master$ nano ./inventory/mycluster/group_vars/k8s_cluster/k8s-cluster.yml
# Kube-proxy proxyMode configuration.
# Can be ipvs, iptables
kube_proxy_mode: iptables

 

 

8. (master) execute

  - 이제 정말로 준비는 끝났다. 설치 시작~!!

master$ cd /srv/install/kubespray

master$ ansible-playbook -i inventory/mycluster/hosts.yaml --become --become-user=root cluster.yml

 

 

9. (master) 계정 설정

  - root가 아닌 일반 계정에서 `kubectl` 명령어를 사용하기 위한 설정을 하자

 

master$ mkdir -p $HOME/.kube

master$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

master$ sudo chown $(id -u):$(id -g) $HOME/.kube/config

master$ echo "source <(kubectl completion zsh)" >> ~/.zshrc

master$ source ~/.zshrc

 

 

10. (master) 점검

  - 잘 되었는지 살펴보자.

master$ kubectl cluster-info
Kubernetes control plane is running at https://127.0.0.1:6443

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.



master$ kubectl get nodes
NAME    STATUS     ROLES                  AGE   VERSION
node1   Ready      control-plane,master   14m   v1.20.7
node2   NotReady   <none>                 13m   v1.20.7
node3   NotReady   <none>                 13m   v1.20.7

 

 

성공~!!!

반응형

'Dev Tools > Kubernetes' 카테고리의 다른 글

Kubernetes 설치  (0) 2023.04.17
Install `NGINX Ingress Controller` in Kubernetes  (4) 2021.09.18
MinIO StandAlone in Kubernetes  (0) 2021.05.13
Kubespray 이용하여 Kubernetes 설치하기  (4) 2021.05.04
Kubernetes Install (Ubuntu 20.04)  (0) 2020.12.28

+ Recent posts