본문으로 건너뛰기

"docker" 태그로 연결된 19개 게시물개의 게시물이 있습니다.

모든 태그 보기

Kubernetes의 모든 것

· 약 4분

매번 용어 찾아보는 게 귀찮아서 정리했다. 어떤 기능을 yaml 로 구성해야하는지 감이 오는 듯하다.

노드

  • 컨테이너가 배치되는 서버
  • 쿠버네티스 클러스터의 관리 대상으로 등록된 도커 호스트
  • 쿠버네티스 클러스터는 마스터와 노드의 그룹으로 구성
  • kubectl get nodes

마스터 노드

  • 스웜의 매니저노드와 비슷한 느낌이다.
  • kube-apiserver: 쿠버네티스 API를 노출하는 컴포넌트 kubectl로부터 리소스를 조작하라는 지시를 받음
  • ectd: 고가용성을 갖춘 분산 Key/Value 스토어로 쿠버네티스 클러스터의 백킹스토어로 쓰인다. (CAS)
  • kube-scheduler: 노드를 모니터링하고 컨테이너를 배치할 적절한 노드탐색
  • kube-controller-manager: 리소스를 제어하는 컨트롤러 실행

일반적인 (non-managed, GKE 등이 없는) 환경에선 마스터 노드서버가 단일 장애지점 (SPOF)가 되지 않도록 마스터를 3대 두는 것이 필수다.

네임스페이스

  • 쿠버네티스 클러스터 안의 가상 클러스터
  • 네임스페이스마다 권한을 줄 수 있으므로 개발팀이 클 때 유용하다.
  • 기본으론 default, docker, kube-public, kube-system 네임스페이스가 있다.
  • kubectl get namespace

파드

  • 컨테이너의 집합 중 가장 작은 단위로, 컨테이너의 실행 방법을 정의
  • 적어도 하나 이상의 컨테이너로 이뤄져있다.
    • nginx reverse proxy + application web server
  • 파드는 노드 안에 들어간다.
  • 함꼐 배포해야 정합성, 일관성이 유지된다면, 같은 파드로 묶어 배포한다.
  • 파드엔 각각 고유의 가상 IP가 할당된다.
  • kubectl get pod

레플리카세트

  • 같은 스펙을 갖는 파드를 여러 개 생성/관리 하는 역할
  • 똑같은 파드의 레플리케이션 개수를 관리하는 리소스이다.
  • 삭제된 파드는 복원할 수 없기 때문에 웹 어플리케이션과 같은 stateless 파드에 사용하기에 좋다.
  • kubectl get replicaset
  • 레플리카셋의 파드명은 container-1b2e3f 처럼 임의로 정해진다.

디플로이먼트

  • 레플리카세트의 리비전을 관리 (빠른 버저닝)
  • 리비전은 컨테이너 이미지가 수정된 경우에 생성된다.
  • kubectl rollout history deployment ..

데몬셋

  • 모든 시스템에서 실행되어야하는 파드와 템플릿 제공
  • 노드 당 하나

서비스

  • 파드의 집합에 접근하기 위한 경로를 정의
  • 쿠버네티스 클러스터 내에서 파드의 집합에 대한 경로나 서비스 디스커버리를 제공하는 리소스
  • 서비스의 대상이 되는 파드는 서비스에서 정의하는 레이블 셀렉터로 정해진다.
  • 서비스의 접근은 같은 네임스페이스라면 서비스명만으로 접근이 가능하다.
    • http://${svc} => http://${svc}.default => http://${svc}.default.svc.local

ClusterIP 서비스

  • 서비스의 기본 타입
  • 쿠버네티스 클러스터의 내부 IP 주소에 서비스를 공개할 수 있다.
  • 다른 파드 그룹으로 접근할 때 서비스를 거쳐 가도록 할 수 있으며, 서비스명으로 네임 레졸루션이 가능해진다.
  • 외부에서는 접근할 수 없다.

NodePort 서비스

  • 쿠버네티스 클러스터 외부에서 접근할 수 있는 서비스
  • 서비스를 L4 레벨에서 노출하는 것이므로 TCP/UDP 모두 다룰 수 있다.
  • kubectl get svc ...

LoadBanlancer 서비스

  • 로컬 쿠버네티스 환경에선 사용할 수 없다.

ExternalName 서비스

  • 쿠버네티스 클러스터에서 외부 호스트를 네임 레졸루션하기 위한 별칭이다.
  • gracefullighut.dev 를 gracefullight 로 접근 가능하게 만든다.

인그레스

  • 서비스를 쿠버네티스 클러스터 외부로 노출
  • NodePort 서비스는 L4라 HTTP/S의 경로기반 라우팅이 불가능한데, 인그레스는 L7 레벨로 제어가 가능하다.
  • 주로 HTTP/S 서비스를 노출하는 경우 사용한다.
  • 로컬 쿠버네티스 환경에서는 인그레스를 사용해 서비스를 노출시킬 수 없으므로 nginx ingress controller 를 사용한다.

컨피그맵

  • 설정 정보를 정의 후 파드에 전달

퍼시스턴트볼륨

  • 파드가 사용할 스토리지의 크기 및 종류를 정의

퍼시스턴트볼륨 클레임

  • 퍼시스턴트 볼륨을 동적으로 확보

스토리지클래스

  • 퍼시스턴트 볼륨이 확보하는 스토리지의 종류를 정의

스테이트풀세트

  • 같은 스펙으로 모두 동일한 파드를 여러 개 생성하고 관리
  • 스테이트풀셋의 파드명은 backend-0, backend-1 처럼 인덱스로 정해진다.

  • 일회성 파드를 여러 개 생성하고 종료 보장

시크릿

  • 인증 정보 등 비밀 데이터 정의

  • 네임스페이스 안에서 조작 가능한 쿠버네티스 리소스의 규칙 정의
  • 각 쿠버네티스 API 사용 권한 정의
  • 지정된 네임스페이스 내에서만 유효

롤 바인딩

  • 쿠버네티스 리소스 사용자와 롤을 연결

RBAC

  • Role-based access control (RBAC) is a method of regulating access to computer or network resources based on the roles of individual users within an enterprise.
  • Docs

권한 디버깅

## can-i 문으로 권한 확인 가능
$ kubectl auth can-i ...

## kubectl auth can-i create deployments
## yes

클러스터롤

  • 클러스터 전체적으로 조작 가능한 쿠버네티스 리소스의 규칙 정의
  • 클러스터 전체에서 유효

클러스터롤 바인딩

  • 쿠버네티스 리소스 사용자와 클러스터롤을 연결
  • 일반 사용자 및 그룹/서비스 계정과 클러스터롤을 연결

서비스 계정

  • 파드가 쿠버네티스 리소스를 조작할 때 사용하는 계정
  • 구글의 서비스 계정 비슷한 듯

노드어피니티

  • 노드 셀렉터보다 더 세밀한 선택이 가능 (스케줄링 정책 조건 등)

테인트

  • taint
  • 오염 조건을 추가해 노드 스케줄링에서 제외
  • 파드를 특정 노드로 강제할 수 있다.

컨트롤 플레인

  • kubelet, kubenetes master 등 컨트롤 플레인은 시스템 내 모든 쿠버네티스 오브젝트의 레코드를 유지하면서, 오브젝트의 상태를 관리하는 제어 루프를 지속적으로 구동

Dynamic Admission Control

  • 웹훅으로 동작
  • ValidationWebhookConfiguration
  • MutatingWebhookConfiguration

클러스터 데몬

  • 클러스터 모든 서비스에 검사, 실행 필요시 사용

클러스터어시스턴스

  • SSL 인증 배포 등 자동화
  • cert-manager

Mac에서 Kubernetes is starting이 지속되는 현상

· 약 1분

원인

모하비 문제인지 최근 엣지 버전 Docker for Mac 이 문제인지 잘 모르겠지만, 부팅시에 Kubernetes is starting 문구가 지속되며 CPU의 온도를 90도까지 올려버린다.

맥북이 트랜스포머가 되어 곧 제트기가 될 것처럼 굉음이 나는데 해결해보자.

해결

  • Docker > Prefereneces > Reset 에서 Reset to factory defaults 로 공장 초기화를 진행한다.
  • ~/.kube 폴더를 강제로 삭제한다.
  • 다시 쿠버네티스를 실행한다.

여담

쿠버네티스 뿐 아니라 도커 자체가 맥에서 CPU 가 튀는 현상이 있는데, 여기 이슈에서 관리가 되고 있다.

file watch 기능을 끄거나, 볼륨을 해제하거나, 맥 디스크 암호화 기능을 꺼보라는데 신뢰할 수 있는 방법은 아니다.

도커 켜놓고 잠자기 해놓으면 과열로 맥북 켜지지도 않을 수 있어서 해결될 때까진 윈도우에서 돌려야할 듯 싶다.

Docker로 스웨거 설치 후 테마 설정하기 (swagger)

· 약 1분

Swagger UISwagger Editor를 Docker 로 띄워서 빠르게 사용해보자. Swagger Hub에서 작업하는건 한글 입력이 잘 되지 않는 경우가 있었고 OAS3를 사용할 겸 설치하는 게 편하다.

설치

설치는 서버 하나만 있으면 충분하다.

Editor

$ docker run -d \
-p 7000:8080 \
--restart always \
--name swagger-editor \
swaggerapi/swagger-editor

UI

UI 에서는 API 문서를 상대경로로 사용하기 위해 볼륨 마운트를 했다. Docker for Windows에서 c 드라이브를 마운트하기 위해서는 아래처럼 //c/path 로 접근하면 된다.

$ docker run -d \
-p 9010:8080 \
-v //c/swagger-spec:/usr/share/nginx/html/spec \
--restart always \
--name swagger-ui \
swaggerapi/swagger-ui

테마 추가

테마는 나이스한 라이브러리를 사용하자. 두 컨테이너 모두 /usr/share/nginx/html/ 경로의 index.html을 열어 head 안에 넣어주면 된다.

docker exec로 쉘에 접근하는 건 다 하시리라 믿고 다만, 컨테이너에 bash 쉘이 없기에 기본 sh 쉘로 접근하면 된다.

index.html
<link
rel="stylesheet"
href="https://unpkg.com/[email protected]/themes/3.x/theme-material.css"
/>

여담

스웨거에 side menu 가 있는 버전이나 라이브러리가 있으면 좋을텐데, 누가 만들었을 것 같은데 아직 못 찾았다.

Docker jenkins 설치시 permission 오류

· 약 1분

run시에 젠킨스가 올라가지 않고 /var/jenkins/home에 파일 퍼미션 오류가 발생할 때 다음과 같이 해결하면 된다.

해결

마운트한 볼륨에 1000 유저 권한을 준다. (jenkins의 uid는 1000) docker hub에 나와있는 내용이긴 한다.

chown 1000 {볼륨 경로}

Cannot start container iptables failed

· 약 1분

오류

Container를 다시 올릴 때 다음과 같은 오류로 올라가지 않는 경우가 있다. docker kill이 아닌 stop, rm으로 container를 지웠을 때 뭔가 충돌이 나는 것 같다.

Error response from daemon: Cannot start container aca936f2822fce32235e627ff539c58b74b2f4e66cfa701de47ce609e2590d13: iptables failed: iptables -t nat -A DOCKER -p tcp -d 0/0 --dport 50000 -j DNAT --to-destination 172.17.0.10:50000 ! -i docker0: iptables: No chain/target/match by that name.
(exit status 1)

해결

이 중 마음에 드는 방법으로 해결하면 된다.

서비스 restart

docker 서비스를 restart 한다.

iptables rule 추가

오류 메세지에 필요한 rule을 추가한다.

iptables -t filter -N DOCKER
iptables -t nat -N DOCKER

Docker로 LEMP Stack 구축하기

· 약 1분

이 포스트 전에 웹서버 세팅을 하나씩 설치해서 띄워보는 걸 권장하고 Docker, SSH Login, LetsEncrypt, sed 명령어의 사용법을 알고 있어야 한다. 구성할 서버 스택은 다음과 같다.

  • Docker
  • Docker-compose
  • Host 에 사용될 Linux (Centos7)
  • Alpain Linux
  • Nginx ^1.13
  • MariaDB ^10.2
  • PHP ^7.1
  • Laravel =5.4
  • LetsEncrypt
  • HTTP2
  • Redis

Docker 설치

이전 포스트를 참조하자.

Container 쇼핑

Docker Hub에서 마음에 드는 Container 를 사용해도 되지만, 생각처럼 돌아가는 Container 는 다음과 같았다.

Laradock을 안 썼죠?

  1. Laradock 에서 caddy 를 사용하지 않고 nginx 와 certbot 만을 이용해 http2 환경을 구성하는 예제가 없었다.
  2. 그래도 시도해봤으나 certbot 인증시에 DocumentRoot 를 잡지 못하는 현상을 삽질로 매꿀 시간이 없었다.
  3. Git repo 를 Clone 받아서 Docker-compose 로 Container 를 구동하기 때문에 추후 ECS 에 적용할 수가 없는 구조였다.
  4. 직접 구축해보고 싶었다.

세팅

nginx-php-fpm

Laravel 용 및 튜닝을 위해 Docker hub 의 이미지 대신 Git repo 의 이미지를 Clone 해서 세팅을 해보자.

내용 추가 중..

AWS ECS 부수기

· 약 4분

ECS 는 서울 리젼이 아직 없어서 그런가, 구글링해도 사용할만한 데이터가 너무 적었다. (기초 설명은 잘 되있다. 하지만 Hello World Application 을 올리려고 ECS 를 쓰는 건 아니니까..)

용어

Cluster

Amazon ECS 클러스터는 작업을 배치할 수 있는 컨테이너 인스턴스의 논리적 그룹화입니다. 이 공식 설명을 보고 Cluster 에 대한 감을 잡기가 쉽지 않았다.

  • 간단히하면 Docker Container 를 올리는 EC2 Instance 이다.
  • K8S 의 그 클러스터이다.

Task

  • Task 는 작업이라고 번역되며, 하나의 Task Definition JSON 은 하나의 Docker-compose YAML 이라고 보자.

Container Definition

  • 배포되는 각 컨테이너의 정의
  • 파드의 개념

Task Definition

  • 컨테이너의 집합인 Task의 정의
  • 파드의 개념

Service

Amazon ECS 는 단일 ECS 클러스터에서 작업 정의에 지정된 수("원하는 개수")의 인스턴스를 동시에 실행 및 관리할 수 있게 해줍니다. 어떤 이유로 작업이 실패 또는 중지되는 경우 Amazon ECS 서비스 스케줄러가 작업 정의의 다른 인스턴스를 시작하여 이를 대체하고 서비스의 원하는 작업 수를 유지합니다.

  • Task 를 자동으로 관리할 수 있게 하는 기능, LB 나 Auto Scaling 모두 여기서 적용이 된다.
  • 롤링 업데이트 시에 배포 및 오토 스케일링을 담당한다.
  • K8S의 서비스, 디플로이먼트, 레플리카세트의 역할

Repository

AWS Docker 레지스트리 서비스로 AWS Private DockerHub 라고 보자.

네트워크 모드

모드내용
default네트워크 모드 기본값으로 bridge와 같음
awsvpcAWS에서만 제공되는 네트워크 모드 (ENI가 Task 자체 VPC의 IP 주소할당)
bridgeDockerContainer를 호스트와 같은 네트워크에 배치해 라우팅 없이 컨테이너 접근 가능
hostTask가 배치되는 호스트의 네트워크를 공유하는 모드 (Fargate 사용 불가)
noneTask에 속한 컨테이너의 외부 접근이 불가능하고 포트 매핑 사용불가

볼륨 생성

-v 또는 --volume 으로 Host 의 폴더를 Mount 하는 기능이 꼭 필요한데, 설정 창에선 찾기가 너무 힘들었다. ECS 에서는 작업 정의 생성 시에 하단에 볼륨 추가 를 꼭 먼저 클릭해 볼륨부터 추가해야한다.

image from hexo 이름엔 --name 옵션 사용하듯이 닉네임을 넣고 소스 경로엔 Host directory 경로를 넣자.

추가가 되면 컨테이너 추가 시에 탑재 지점 메뉴의 소스 볼륨 select box 에서 선택할 수 있다.

image from hexo

이 짓을 하는 것보단 공식 문서의 Task Definition JSON Parameter 를 보고 JSON 으로 때려박는게 편하다.

예시 JSON 은 아래와 같다. (3306 과 3307 을 열고 Host 의 Data 폴더를 Mount 하는 기본 구성의 MariaDB Image)

mariadb
{
"requiresAttributes": [
{
"value": null,
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.21",
"targetId": null,
"targetType": null
}
],
"taskDefinitionArn": "your task definition arn",
"networkMode": "bridge",
"status": "ACTIVE",
"revision": 3,
"taskRoleArn": null,
"containerDefinitions": [
{
"volumesFrom": [],
"memory": null,
"extraHosts": null,
"dnsServers": null,
"disableNetworking": null,
"dnsSearchDomains": null,
"portMappings": [
{
"hostPort": 3306,
"containerPort": 3306,
"protocol": "tcp"
},
{
"hostPort": 3307,
"containerPort": 3307,
"protocol": "tcp"
}
],
"hostname": null,
"essential": true,
"entryPoint": null,
"mountPoints": [
{
"containerPath": "/var/lib/mysql",
"sourceVolume": "dbdata",
"readOnly": null
}
],
"name": "maria",
"ulimits": null,
"dockerSecurityOptions": null,
"environment": [
{
"name": "MYSQL_DATABASE",
"value": "db"
},
{
"name": "MYSQL_PASSWORD",
"value": "db_pw"
},
{
"name": "MYSQL_ROOT_PASSWORD",
"value": "root_pw"
},
{
"name": "MYSQL_USER",
"value": "db_user"
}
],
"links": null,
"workingDirectory": null,
"readonlyRootFilesystem": false,
"image": "mariadb:latest",
"command": [
"mysqld",
"--character-set-server=utf8",
"--collation-server=utf8_general_ci"
],
"user": null,
"dockerLabels": null,
"logConfiguration": null,
"cpu": 0,
"privileged": null,
"memoryReservation": 500
}
],
"placementConstraints": [],
"volumes": [
{
"host": {
"sourcePath": "/ecs/dbdata"
},
"name": "dbdata"
}
],
"family": "mariadb"
}

고민

Container 를 Task 별로 생성해야하는데, 그럼 Task JSON 에서 link 옵션을 연결할 수가 없다. 이 경우엔 어떻게 Task Definition 을 짜야되나? EC2 에 접근해서 매번 link 를 생성해서 다시 올려야되나?

이 부분을 해결하기 위해선 ecs-task-kite를 사용하거나 VPC 를 구성해 수동으로 연결해 주는 방법 밖에 없다.

쉬운 방법으로 가자면 DB 는 (모든 컨테이너가 하나의 데이터를 바라봐야하는) RDSElastiCache처럼 AWS 의 서비스 사용하고 VPC 를 구성해 Backend, Frontend 단의 서버만 ECS Task 를 만들어서 가변적으로 돌리는 게 좋아보인다.

물론 동기화를 할 수도 있는데... 삽질할 시간에 더 잘 나온 포스팅을 기다려본다.

여담

그냥 모니터링 컨테이너 하나 더 띄우고, HAProxy 컨테이너 올리고 EC2 에 다 때려박고 싶다.

AWS Korea week in review에 소개되었다.

Docker와 Docker-compose 제대로 설치하기

· 약 2분

구글링하면 너무 예전 버전 (1버전 대)의 설치방법만 나와있다.

영문을 따라할 수 있으면 공홈을 보고하면 된다.

Docker 설치

옛 버전 삭제

$ sudo yum remove docker \
docker-common \
docker-selinux \
docker-engine

서비스를 내리고 docker를 삭제해도 /var/lib/docker/ 폴더는 지워지지 않고 여기에 기존 데이터가 모두 남아있다.

필수 패키지 설치

$ sudo yum install -y yum-utils device-mapper-persistent-data lvm2
## docker repo를 등록한다.
$ sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
## yum package를 업데이트
$ sudo yum makecache fast

다운로드

sudo yum install docker-ce

실행

$ sudo systemctl start docker
$ sudo systemctl enable docker

$ sudo docker --version
Docker version 17.06.0-ce, build 02c1d87

Docker-compose 설치

다운로드

## root로 로그인해야한다.
$ curl -L https://github.com/docker/compose/releases/download/1.14.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

실행 권한 부여

$ chmod +x /usr/local/bin/docker-compose

## 설치 확인
$ docker-compose --version
docker-compose version 1.14.0, build 1719ceb

설치가 완료되었다.

Centos6에서 설치하기

centos6 버전에서는 위의 설치방법으로 Docker를 설치할 수 없다. (RHEL7 버전 전용이기에) 다음과 같이 설치하자.

yum install http://mirrors.yun-idc.com/epel/6/i386/epel-release-6-8.noarch.rpm

yum install -y docker-io

service docker start

chkconfig docker on

Docker Error response from daemon: reference does not exist

· 약 1분

Docker rmi명령어로 이미지를 삭제하는데 Error response from daemon: reference does not exist 오류가 나면서 이미지 삭제가 안 되는 경우 다음과 같이 하면된다.

해결

구글링하면 다시 설치하거나 cache를 비우거나 하라는데 해결되진 않았고 쉽게 접근하면 된다. 그냥 이미지 폴더를 날리자

sudo systemctl stop docker
sudo rm -rf /var/lib/docker
sudo systemctl start docker