17일차_보안 원격 접근 및 CI/CD를 위한 도커 설정

최지웅·2024년 12월 19일
0

인프라

목록 보기
22/31
  • 도커 엔진과 도커 API를 분리하면 컨테이너를 관리하는 도구의 선택지가 넓어지고, 로컬 컴퓨터의 CLI로 도커 엔진 관리가 가능해진다.
  • CI는 지속적 통합, CD는 지속적 배포를 의미한다.

15-1. 도커 API의 엔드포인트 형태(가장 간단한 HTTP접속)

  • 도커에서 로컬 채널로 사용되는 리눅스 소켓 혹은 윈도의 명명 파이프는 트래픽 범위가 로컬 컴퓨터이기에 명시적으로 외부 접근을 허용해야 한다. HTTP접근이 가장 간단하나, 사용하면 안된다. 취약점으로 접속 시 비트코인 마이닝 컨테이너가 실행될 수 있다.
# 1. daemon.json 파일을 수정해 도커 엔진에 비보안 HTTP 접근 허용(위험)
{
	"hosts": [
    	"tcp://0.0.0.0:2375", # 2375포트로 원격 접근 허용
        "npipe://", # 윈도 파이프 로컬 채널을 통한 접근 허용
        :fd://" # 리눅스 소켓 로컬 채널을 통한 접근 허용
    ],
    "insecure-registries": [
    	"registry.local:5000"
    ]
}

# 2. 도커 CLI로 원격 도커 엔진 접속
docker -host tcp://localhost:2375 container ls # TCP 프로토콜을 통해 로컬 도커 엔진에 접속
curl htp://localhost:2375/containers/json # HTTP를 통해 REST API로 접근
  • 위와 같이 도커 서버를 원격으로 접근하게 허용한다면, 아래와 같이 컨테이너를 실행시켜버려서 host권한을 얻을 수 있다
# 3. 컨테이너 원격으로 실행시켜버리기
docker --host tcp://localhost:2375 container run -it -v /:/host-drive diamol/base #linux
docker --host tcp://localhost:2375 container run -it -v C;\C:\host-drive diamol/base # window

ls
ls host-drive

15-2. 보안 원격 접근을 위한 도커 엔진 설정

  • API요청을 받을 수 있는 도커 채널로 HTTPS와 같은 전송계층보안(TLS), 리눅스 원격 접속 표준 프로토콜인 보안 셸(SSH)이 있다.
  • 다만, 도커 데스크롭은 컴퓨터 내 가상머신에서 실행되기에 보안 원격 접근을 허용할 수 없다. CLI에서 진행해야한다.
# 1. TLS로 도커 보안 원격 접근 설정하기
mkdir -p /diamol-certs # 인증서 저장할 디렉 생성
docker container run -v /diamol-certs:/certs -v /etc/docker:/docker diamol/pwd-tls:server # 인증서 및 설정값을 적용헐 컨테이너 실행
pkill dockerd # 새로운 설정을 적용해 도커 재시작
dockerd &>/docker.log &
  • TLS를 사용해 원격 접근이 가능하게 도커 엔진을 설정하려면 경로를 지정하면 된다. 이젠 클라이언트 인증서 및 키 없이 curl로 REST를 호출하거나 CLI로 명령을 내릴 수 없다.
# 2. 도커 엔진에 적용시킬 TLS 원격 접근 허용 설정
{
	"hosts": ["unix://var/run/docker.sock", "tcp://0.0.0.0:2376"],
    "tls": true,
    "tlscacert": "/diamol-certs/ca.pem",
    "tlskey": "/diamol-certs/server-key.pem",
    "tlscert": "/diamol-certs/server-cert.pem"
}
  • 아래는 실제 2376 포트를 이용해 정상적인 방법으로 원격 접속하는 코드이다.
# 3. TLS를 이용한 원격 접속

# 도메인을 환경변수로 설정
pwdDomain="<나의_현재세션_pwd_도메인>"

# 도커 API에 직접 접근 시도(실패)
curl "http://$pwdDomain/containers/json"

# 명령행 도구로 직접 접근 시도(실패)
docker --host "tcp://$pwdDomain" container ls

mkdir -p /tmp/pwd-certs
cd ./ch15/exercises
tar -xvf pwd-client-certs -C /tmp/pwd-certs

docker --host "tcp://$pwdDomain" --tlsverify --tlscacert /tmp/pwd-certs/ca.pem --tlscert /tmp/pwd-certs/client-cert.pem --tlskey /tmp/pwd-certs/client-key.pem container ls # 클라이언트를 이용해 도커 엔진 접근 시도

docker --host "tcp://$pwdDomain" --tlsverify --tlscacert /tmp/pwd-certs/ca.pem --tlscert /tmp/pwd-certs/client-cert.pem --tlskey /tmp/pwd-certs/client-key.pem container run -d -P diamol/apache # 도커 명령행 도구로 명령 내리기
  • TLS 인자를 매번 입력해야하지만 환경 변수로 정의해 둘 수도 있으니 나쁘지 않다.

  • SSH를 이용하면 도커 엔진 실행 중인 컴퓨터에서 원격 접속에 사용할 계정을 추가하면, 이 계정을 통해 원격 명령이 가능하다.

# 4. SSH를 이용해 원격 접속
node1ip="<node1-ip-address-goes-here>" # IP 환경 변수로 정의

ssh root@node1ip # SSH 접속 테스트
exit

docker container ls # node2에서 실행 중인 컨테이너 목록 확인

docker -H ssh://root@node1ip container ls # node1에서 원격으로 접근한 도커 엔진에서 실행 중인 컨테이너 목록 확인
  • TLS나 SSH를 적용하면 암호화와 사용자 인증이 함께 적용되는 장점이 있지만, 보안 접속에 따른 권한 조정 기능이나 감시 기능이 없기에 작업 추적이 불가능하기에 사용자들이 자신이 접근하는 환경에 대해 알아서 주의해야한다.

15-3. 도커 컨텍스트를 사용해 원격 엔진에 작업하기

  • 보안 접근을 위한 TLS 인증서 경로 등의 정보를 모두 도커 컨텍스트에 담아, 편리하게 전환이 가능하다.
# 1. 도커 컨텍스트 생성

# TLS를 사용하는 경우
docker context create pwd-tls --docker "host=tcp://$pwdDomain,ca=/tmp/pwd-certs/ca.pem,cert=/tmp/pwd-certs/client-cert.pem,key=/tmp/pwd-certs/client-key.pem"

# SSH를 사용하는 경우
docker context create local-tls --docker "host=ssh://user@server"

# 컨텍스트 목록 확인
docker context ls
  • 컨텍스트는 해당 터미널 세션에만 적용되는 임시적 적환, 컨텍스트 변경 전까지 모든 터미널 세션에 적용하는 영구적 전환이 있다.
# 2. 컨텍스트 전환
export DOCKER_CONTEXT="pwd-tls" # 환경변수로 컨텍스트 지정(임시적 전환. 오버라이드)

docker context ls # 현재 선택된 컨텍스트 확인

docker context use defaul # 기본 컨텍스트로 복귀->다른 터미널 세션도 영향끼치지게 안좋음

docker container ls # 기본 컨텍스트로 안바뀜. 우선순위는 위의 export가 더 높다. 오버라이드 때문에

15-4. 지속적 통합 파이프라인에 지속적 배포 추가하기

  • 앱 빌드+테스트+레지스트리푸시까지가 지속적 통합이고, 여기에 테스트 환경에 앱 배포 후 운영 환경까지 배포하는 단계를 지속적 배포라고 한다.
  • 지속적 배포를 위해 로컬 Git서버, 도커 레지스트리, 젠킨스 서버로 구성된 인프라 스트럭쳐를 만들어보자.
# 1. 컨테이너 실행

# 컴포즈 파일 위치로 이동
cd ch15/exercises/infrastructure

# 컨테이너 실행
docker-compose -f ./docker-compose.yml -f ./docker-compose-linux.yml up -d # linux 기준. 컴포즈 파일의 인증수단을 이용해 TLS인증 완료

# 2. 젠킨스 파이프라인 정의 파일에서 도커 관련 변수를 볼 수 있다. 
environment {
	REGISTRY = "registry.local:5000"
    UAT_ENGINE = "ip172-18-0-59-bngh3ebjagq000ddjbv0-2376.direct.labs.play-with-docker.com:80"
}

# 3. 수정한 코드를 로컬 Git서버에 푸시
git remote add ch15 http://localhost:3000/diamol/diamol.git

git commit -a -m "Play with Docker의 도메인 정보 추가"

git push ch15 # 로그인 정보 요구하면 사용자명이랑 패스워드 입력

# 4. 최종 운영 환경 배포 전 로그 출력 여부 확인
docker container ls
docker container logs timecheck-uat_timecheck_1

# 5. 젠킨스에서 승인 대기 상태 박스 클릭하여 파이프라인 재개
  • CI와 달리 CD는 배포 각 단계마다 스크립트가 있어서 환경변수만 잘 정의되어 있다면 간단하다.
# 6. Jenkinsfile 일부의 사용자 인수 테스트 환경 배포 단계
stage('UAT') {
	steps {
    	withCredentials(
        	[file(credentialsId: 'docker-ca.pem', variable: 'ca'),
             file(credentialsId: 'docker-cert.pem', variable: 'cert'),
             file(credentialsId: 'docker-key.pem', variable: 'key')]) {
             	dir('ch15/exercises') {
                	sh 'chmod +x ./ci/04-uat.bat'
                    sh './ci/04-uat.bat'
                    echo "Deployed to UAT"
                }
             }
        )
    }
}

# 7. 도커 컴포즈 명령 하나로 구성된 실제 스크립트
docker-compose \
	--host tcp://$UAT_ENGINE --tlsverify \
    --tlscacert $ca --tlscert $cert --tlskey $key \
    -p timecheck-uat -f docker-compose.yml -f docker-compose-uat.yml \ 
    up -d
    
# 8. 로컬위의 젠킨스에서 빌드를 마치고 사용자 인수 테스트 환경과 운영 환경에 배포된 앱이 잘 동작하는지 확인
docker container ls

docker container logs timecheck-prod_timecheck_1
  • 애플리케이션이 이미 컨테이너화 됐다면 하루면 간단하게 위 CI/CD 파이프라인을 적용할 수 있다.

15-5. 도커 리소스의 접근 모델

  • 도커 엔진의 보안은 명령행 도구와 API 사이의 통신 암호화, 허가받은 사용자의 API 접근 두가지이다. 이 때, 권한 조정 기능은 없기에 모든 기능을 수행할 수 있거나 없거나 둘 중 하나밖에 선택할 수 없다.
  • 소스 코드의 변경이 생기면 자동으로 CI 파이프라인이 실행되어 어플리케이션이 빌드되고, 이미지가 레지스트리에 푸시되며 최신버전 배포용 YAML파일이 생성되어 별도의 git 저장소에 저장된다. 다음으로 운영 환경 클러스터는 이미지 레지스트리와 인프라스트럭처 저장소의 변화를 탐지하면, YAML과 이미지를 내려받아 스스로 배포를 시작한다. 이를 GitOps라고 한다.
profile
이제 3학년..

0개의 댓글