15 안전한 원격 액세스 및 CI/CD

Docker 명령줄은 컨테이너 작업의 원활한 방법을 제공하며 명령줄이 실제로 자체적으로 수행하는 작업은 없으며 Docker 엔진에서 실행되는 API에 지침을 보낼 뿐입니다. 엔진에서 명령줄을 분리하면 두 가지 주요 이점이 있습니다. 다른 도구는 Docker API를 사용할 수 있으므로 명령줄이 컨테이너를 관리하는 유일한 방법은 아니며 실행 중인 원격 컴퓨터와 작동하도록 로컬 명령줄을 구성할 수 있습니다. 익숙한 Docker 명령을 모두 사용하여 노트북에서 컨테이너를 실행하는 것에서 수십 개의 노드가 있는 클러스터를 관리하는 것으로 전환할 수 있다는 것은 놀랍도록 강력합니다.

원격 액세스는 테스트 환경을 관리하거나 프로덕션에서 문제를 디버그하는 방법이며 CI/CD 파이프라인의 CD 부분을 활성화하는 방법이기도 합니다. CI 단계가 성공하면 출시 가능한 버전의 앱이 도커 레지스트리에 저장됩니다. CD는 원격 도커 엔진에 연결하고 앱의 새 버전을 배포하는 파이프라인의 다음 단계입니다.

이 단계는 통합 테스트 모음을 실행하는 테스트 환경이 될 수 있으며, 마지막 단계는 프로덕션 클러스터에 연결하고 앱을 라이브 환경에 배포할 수 있습니다. 이 장에서는 Docker API를 노출하고 보호하는 방법과 컴퓨터 및 CI/CD 파이프라인에서 원격 Docker 엔진에 연결하는 방법을 배웁니다.

15.1 Docker API를 위한 엔드포인트 옵션

Docker를 설치할 때 기본 설정은 엔진이 로컬 채널에서 수신 대기하고 명령줄에서 동일한 채널을 사용하는 것입니다. 로컬 채널은 Linux 소켓을 사용하며 로컬 시스템으로의 트래픽을 제한하는 네트워크 기술입니다. Docker 엔진에 대한 원격 액세스를 활성화하려면 구성에서 명시적으로 설정해야 합니다. 원격 액세스를 위해 채널을 설정하는 옵션이 있지만 가장 간단한 방법은 보안이 없는 HTTP 액세스를 허용하는 것입니다.

암호화되지 않은 HTTP 액세스를 활성화하는 것은 끔찍하게 나쁜 생각입니다. 일반 HTTP 엔드포인트에서 수신 대기하도록 Docker API를 설정하고 네트워크에 액세스할 수 있는 모든 사용자가 인증 없이 Docker 엔진에 연결하고 컨테이너를 관리할 수 있습니다. 개발자 노트북에서는 나쁘지 않다고 생각할 수도 있지만 훌륭하고 쉬운 공격 벡터가 열립니다.

15.2 안전한 원격 액세스를 위한 Docker 구성

Docker는 API가 수신 대기하는 두 가지 채널을 지원합니다.

  • TLS: HTTPS에서 사용하는 디지털 인증서를 기반으로 하는 동일한 암호화 기술. Docker API는 상호 TLS를 사용하므로 서버에는 자신을 식별하고 트래픽을 암호화하는 인증서가 있고 클라이언트에도 자체 식별을 위한 인증서가 있습니다.

  • SSH: Linux 서버에 연결하는 표준 프로토콜. 사용자 이름과 암호 또는 개인 키로 인증할 수 있습니다.

보안 옵션은 클러스터에 대한 액세스 권한이 있는 사용자를 제어하는 다양한 방법을 제공합니다. 그림 15.4는 Docker API가 지원하는 다양한 채널을 보여줍니다.


그림 15.4 암호화 및 인증을 제공하는 Docker API를 노출하는 안전한 방법이 있습니다.

Docker 엔진에 대한 보안 원격 액세스를 구성하려면 Docker를 실행하는 시스템에 대한 액세스 권한이 필요하지만 도커 데스크톱에서는 이를 알 수 없습니다.

상호 TLS를 사용하여 원격 Docker 엔진에 안전하게 액세스

이를 위해서는 인증서와 키 파일 쌍(키 파일은 인증서의 암호 역할을 함)을 생성해야 합니다. 하나는 Docker API용이고 다른 하나는 클라이언트용입니다. Play with Docker와 작동하는 인증서를 생성하여 이미 수행했으므로 사용할 수 있습니다.

TRY https://labs.play-with-docker.com에서 Docker로 플레이하고 새 노드를 생성하려면 로그인하십시오. 해당 세션에서 인증서를 배포할 컨테이너를 실행하고 인증서를 사용하도록 Docker 엔진을 구성합니다. 그런 다음 Docker를 다시 시작합니다.

  1. create a directory for the certs:
mkdir -p /diamol-certs
  1. run a container that sets up the certs & config:
docker container run -v /diamol-certs:/certs -v /etc/docker:/docker diamol/pwd-tls:server
  1. kill docker & restart with new config
pkill dockerd
dockerd &>/docker.log &

실행한 컨테이너는 노드에서 두 개의 볼륨을 마운트했으며 컨테이너 이미지에서 노드로 인증서와 새 daemon.json 파일을 복사했습니다. 도커 엔진 구성을 변경하면 다시 시작해야 하며, 이는 dockerd 명령이 수행하는 작업입니다. 이 시점에서 엔진은 TLS를 사용하여 포트 2376(보안 TCP 액세스에 대한 규칙)에서 수신 대기합니다.

OPEN PORT 버튼을 클릭하고 포트 2376을 엽니다. 오류 메시지를 표시하는 새 탭이 열립니다. 메시지를 무시하고 해당 새 탭의 URL을 클립보드에 복사합니다. 이것은 세션에 대한 고유한 PWD 도메인입니다.

ip172-18-0-24-c8siqi7njsv00085ai20-2376.direct.labs.play-with-docker.com

과 같을 것이며 로컬 머신에서 PWD의 Docker 엔진으로 연결하는 데 사용할 것입니다.

이제 PWD 인스턴스를 원격으로 관리할 수 있습니다. 사용 중인 인증서는 OpenSSH 도구를 사용하여 생성한 인증서입니다(컨테이너에서 실행- 작동 방식을 확인하는 데 관심이 있는 경우 Dockerfile은 images/cert-generator 폴더에 있습니다).


그림 15.7 상호 TLS에 대한 빠른 가이드-서버 인증서와 클라이언트 인증서는 소유자를 식별하고 CA를 공유합니다.

TLS를 사용하여 Docker 엔진을 보호하려는 경우 하나의 CA, 보호하려는 각 엔진에 대해 하나의 서버 인증서, 액세스를 허용하려는 각 사용자에 대해 하나의 클라이언트 인증서를 생성하게 됩니다. 인증서는 유효기간으로 생성되므로 단기 클라이언트 인증서를 만들어 원격 엔진에 대한 임시 액세스 권한을 부여할 수 있습니다. 이 모든 것이 자동화될 수 있지만 인증서 관리에는 여전히 오버헤드가 있습니다.

TLS를 사용하도록 Docker 엔진을 구성할 때 CA 인증서, 서버 인증서 및 키 쌍에 대한 경로를 지정해야 합니다. 목록 15.2는 PWD 노드에 배포된 TLS 설정을 보여줍니다.

목록 15.2 TLS 액세스를 활성화하기 위한 Docker 데몬 구성

{
    "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"
}

이제 원격 Docker 엔진이 보호되었으므로 CA 인증서, 클라이언트 인증서 및 클라이언트 키를 제공하지 않는 한 REST API나 Docker CLI로 명령을 보낼 수 없습니다. PWD에서 실행한 이미지의 변형을 사용하여 로컬 컴퓨터에서 클라이언트 인증서를 다운로드하고 이를 사용하여 연결할 수 있습니다.

TRY 로컬 시스템에서 PWD 엔진에 연결합니다.

  1. 주소 창에서 PWD 도메인 주소를 복사합니다
    ip172-18-0-24-c8siqi7njsv00085ai20-2376.direct.labs.play-with-docker.com
  2. Store your PWD domain in a variable
pwdDomain="<your-pwd-domain-goes-here>"
  1. Try accessing the Docker API directly:
curl "https://$pwdDomain/containers/json"
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
  1. Now try with the command line:
docker --host "tcp://$pwdDomain" container ls

Error response from daemon: Client sent an HTTP request to an HTTPS server.
  1. PWD 클라이언트 인증서를 로컬 시스템에 추출합니다
mkdir -p /tmp/pwd-certs

cd ./ch15/exercises

tar -xvf pwd-client-certs -C /tmp/pwd-certs
x ca.pem
x client-cert.pem
x client-key.pem
  1. 클라이언트 인증서로 PWD에 연결합니다:
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
  1. You can use any Docker CLI commands:
 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

SSH를 사용하여 보안 원격 액세스.

이 방식은 Docker CLI가 표준 SSH 클라이언트를 사용하고 Docker 엔진에 대한 구성을 변경할 필요가 없다는 것입니다. SSH 서버에서 인증을 처리하므로 생성하거나 관리할 인증서가 없습니다. Docker 머신에서 원격 액세스를 허용하려는 모든 사람에 대해 시스템 사용자를 생성해야 합니다. 원격 시스템에 대해 Docker 명령을 실행할 때 해당 자격 증명을 사용합니다.

TRY PWD 세션으로 돌아가 node1의 IP 주소를 기록한 다음 클릭하여 다른 노드를 만드십시오. 다음 명령을 실행하여 SSH를 사용하여 node2의 명령줄에서 node1에 있는 Docker 엔진을 관리합니다.

  1. Save the IP address of node1 in a variable:
node1ip="<node1-ip-address-goes-here>"
  1. Open an SSH session to verify the connection:
ssh root@$node1ip
exit
  1. List the local containers on node2:
docker container ls
  1. And list the remote containers on node1:
 docker -H ssh://root@$node1ip container ls

운영 담당자는 SSH를 통한 Docker 사용에 대해 엇갈린 감정을 가질 것입니다. 한편으로는 인증서를 관리하는 것보다 훨씬 쉽고 조직에 Linux 관리자 경험이 많다면 새로운 것은 아닙니다. 반면에 Docker 액세스가 필요한 모든 사람에게 서버 액세스 권한을 부여하는 것을 의미하며, 이는 필요한 것보다 더 많은 권한이 있을 수 있습니다.

TLS는 모두 Docker 내에서 처리되고 SSH 서버나 클라이언트가 필요하지 않기 때문에 인증서 오버헤드에도 불구하고 더 나은 옵션일 수 있습니다.

TLS 또는 SSH를 사용하여 Docker 엔진에 대한 액세스를 보호하면 암호화(CLI와 API 간의 트래픽은 네트워크에서 읽을 수 없음) 및 인증(사용자가 연결하려면 ID를 증명해야 함)이 제공됩니다. 보안은 권한 부여 또는 감사를 제공하지 않으므로 사용자가 수행할 수 있는 작업을 제한할 수 없으며 사용자가 수행한 작업에 대한 기록이 없습니다. 이는 누가 어떤 환경에 액세스해야 하는지 고려할 때 알아야 할 사항입니다. 사용자는 또한 사용 환경에 주의해야 합니다. Docker CLI를 사용하면 원격 엔진으로 매우 쉽게 전환할 수 있으며, 랩톱에 연결되어 있다고 생각했기 때문에 중요한 테스트 데이터가 포함된 볼륨을 삭제하는 것은 단순한 실수입니다.

15.3 context로 원격 엔진 작업

보안 채널을 사용하는 경우 모든 TLS 인증서 경로와 함께 host 매개변수를 사용하여 로컬 Docker CLI가 원격 시스템을 가리키도록 할 수 있지만 실행하는 모든 명령에 대해 그렇게 하는 것은 어색합니다. Docker를 사용하면 컨텍스트를 사용하여 Docker 엔진 간에 더 쉽게 전환할 수 있습니다. 엔진에 대한 모든 연결 세부 정보를 지정하여 CLI를 사용하여 Docker 컨텍스트를 생성합니다. 여러 컨텍스트를 만들 수 있으며 각 컨텍스트에 대한 모든 연결 세부 정보는 로컬 시스템에 저장됩니다.

TRY 로컬 시스템에서 원격 TLS 지원 Docker 엔진을 사용하기 위한 컨텍스트를 생성합니다.

  1. Create a context using your PWD domain and certs:
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"

for SSH it would be:

# docker context create local-tls --docker "host=ssh://user@server"
  1. List contexts:
docker context ls


default *           moby Current DOCKER_HOST based configuration   unix:///var/run/docker.sock                                                                             swarm
desktop-linux       moby unix:///Users/juseongjung/.docker/run/docker.sock                                                       
pwd-tls             moby tcp://ip172-18-0-49-c8s30lnnjsv000cnmb7g-2376.direct.labs.play-with-docker.com/      

로컬 엔진을 가리키는 기본 컨텍스트가 있음을 알 수 있습니다.

context에는 로컬 및 원격 Docker 엔진 간에 전환하는 데 필요한 모든 정보가 포함되어 있습니다. 이 연습에서는 TLS 보안 엔진을 사용했지만 호스트 매개변수 및 인증서 경로를 SSH 연결 문자열로 교체하여 SSH 보안 엔진으로 동일한 명령을 실행할 수 있습니다.

context는 로컬 CLI를 로컬 네트워크 또는 공용 인터넷의 다른 시스템에 연결할 수 있습니다. context를 전환하는 두 가지 방법이 있습니다. 한 터미널 세션 동안 일시적으로 수행하거나 다시 전환할 때까지 모든 터미널 세션에서 작동하도록 영구적으로 수행할 수 있습니다.

TRY context를 전환하면 Docker 명령이 선택한 엔진으로 전송되므로 호스트 매개변수를 지정할 필요가 없습니다. 환경 변수를 사용하여 일시적으로 전환하거나 컨텍스트 사용 명령을 사용하여 영구적으로 전환할 수 있습니다.

  1. Switch to a named context with an environment variable - this is the preferred way to switch contexts, because it only lasts for this session
export DOCKER_CONTEXT='pwd-tls'
  1. Show the selected context:
docker context ls
  1. List containers on the active context:
docker container ls
  1. Switch back to the default context - switching contexts this way is not recommended because it's permanent across sessions:
docker context use default
  1. list containers again:
docker container ls

docker context use로 설정한 컨텍스트가 시스템 전체의 기본값이 됩니다. 오픈하는 모든 새 터미널 창이나 Docker 명령을 실행하는 배치 프로세스는 해당 컨텍스트를 사용합니다. 선택한 컨텍스트보다 우선적으로 적용되고 현재 터미널 세션에만 적용되는 DOCKER_CONTEXT 환경 변수를 사용하여 이를 재정의할 수 있습니다. 컨텍스트 간에 정기적으로 전환하는 경우 항상 환경 변수 옵션을 사용하고 기본 컨텍스트를 로컬 Docker 엔진으로 유지하는 것이 좋습니다.

15.4 CI 파이프라인에 CD 추가

이제 보안 액세스가 구성된 원격 Docker 머신이 있으므로 11장에서 Jenkins로 수행한 작업을 기반으로 완전한 CI/CD 파이프라인을 작성할 수 있습니다. 앱을 컨테이너에 넣고 빌드된 이미지를 Docker 레지스트리로 푸시합니다. CD 단계가 추가되어 최종 승인을 위해 테스트 환경에 배포한 다음 프로덕션에 배포합니다.

CI 빌드는 로컬 시스템에서 Docker 엔진으로 빌드하지만 배포는 원격의 Docker 엔진을 사용해야 합니다. 파이프라인은 원격 시스템을 가리키는 호스트 인수와 함께 Docker 및 Docker Compose 명령을 사용하고 보안 자격 증명을 제공하는 연습에서 사용한 것과 동일한 접근 방식을 사용할 수 있습니다.

자격 증명은 다른 어딘가에 있어야 하며 절대 소스 제어에 있어서는 안 됩니다. 소스 코드로 작업해야 하는 사람들은 프로덕션 서버로 작업해야 하는 사람들과 동일하지 않으므로 프로덕션을 위한 자격 증명은 관리되어야 합니다. 대부분의 자동화 서버를 사용하면 빌드 서버 내에 비밀을 저장하고 파이프라인 작업에서 사용할 수 있으며 자격 증명 관리와 소스 제어가 분리됩니다.

TRY 11장과 유사한 로컬 빌드 인프라를 가동할 것이며 로컬 Git 서버, Docker 레지스트리 및 Jenkins 서버가 모두 컨테이너에서 실행됩니다. 이 Jenkins 컨테이너가 로컬 컴퓨터의 PWD 인증서 파일에서 자격 증명을 만들기 시작할 때 실행되는 스크립트가 있으므로 CD 단계가 PWD에 배포됩니다.

  1. Switch to the folder with the Compose files:
cd ch15/exercises/infrastructure
  1. Start the containers
docker-compose -f ./docker-compose.yml -f ./docker-compose-linux.yml up -d

컨테이너가 실행 중이면 http://localhost:8080/credentials에서 Jenkins로 이동하고 사용자 이름 diamol 및 암호 diamol 로 로그인합니다. Docker CA 및 클라이언트 연결에 대한 인증서가 이미 Jenkins에 저장되어 있음을 알 수 있습니다. 이 인증서는 컴퓨터의 PWD 인증서에서 로드되었으며 작업에서 사용할 수 있습니다. 그림 15.12는 Jenkins 자격 증명으로 로드된 인증서를 보여줍니다.


그림 15.12 Jenkins 자격 증명을 사용하여 PWD의 Docker에 연결하는 파이프라인에 대한 TLS 인증서 제공

이것은 완전히 새로운 컨테이너에서 실행되는 새로운 빌드 인프라입니다. Jenkins는 사용하는 자동화 스크립트 덕분에 모두 구성되었으며 사용할 준비가 되었지만 Git 서버에는 수동 설정이 필요합니다. http://localhost:3000으로 이동하여 설치를 완료하고 diamol 이라는 사용자를 만든 다음 diamol 이라는 저장소를 만들어야 합니다.

이에 대한 복습이 필요하면 11장으로 돌아가세요. 그림 11.3, 11.4, 11.5는 무엇을 해야 하는지 보여줍니다.

이 섹션에서 실행할 파이프라인은 10초마다 현지 시간을 보여주는 12장의 새 버전의 timecheck 앱을 빌드합니다. 스크립트는 모두 이 장의 소스 코드에 들어갈 준비가 되어 있지만 고유한 PWD 도메인 이름을 추가하려면 파이프라인을 변경해야 합니다. 그런 다음 빌드가 실행되면 CI 단계를 실행하고 로컬 컨테이너에서 PWD 세션으로 배포합니다. PWD가 사용자 수용 테스트 환경이자 프로덕션이라고 가정하겠습니다.

TRY ch15/exercises 폴더에서 Jenkinsfile 파일을 엽니다.

  1. environment 섹션에는 Docker 레지스트리 도메인과 UAT 및 프로덕션 Docker 엔진에 대한 변수가 있습니다. pwd-domain 을 실제 PWD 도메인으로 변경합니다.
environment {
 REGISTRY = "registry.local:5000"
 UAT_ENGINE = "ip172-18-0-59-bngh3ebjagq000ddjbv0-2376.direct.labs.play-with-docker.com:80"
 PROD_ENGINE = "ip172-18-0-59-bngh3ebjagq000ddjbv0-2376.direct.labs.play-with-docker.com:80"
}
  1. 이제 변경 사항을 로컬 git 서버에 푸시할 수 있습니다.
git remote add ch15 http://localhost:3000/diamol/diamol.git
git commit -a -m 'Added PWD domains'
git push ch15
# Gogs will ask you to login -
# use the diamol username and password you registered in Gogs
  1. 이제 http://localhost:8080/job/diamol/에서 Jenkins로 이동하고 Build Now를 클릭합니다.

이 파이프라인은 Git에서 코드를 가져오고, 다단계 Dockerfile로 앱을 빌드하고, 앱이 시작되는지 테스트하기 위해 앱을 실행한 다음, 이미지를 로컬 레지스트리에 푸시합니다.

그런 다음 새로운 배포 단계가 있습니다. 먼저 원격 UAT 엔진에 대한 배포가 있고 파이프라인이 중지되어 사람의 승인이 계속될 때까지 기다립니다. 이것은 모든 단계가 자동화되기 때문에 CD를 시작하기에 좋은 방법이지만 여전히 수동 품질 게이트가 있으며 이는 프로덕션에 자동 배포에 익숙하지 않은 조직에 안심할 수 있습니다. 그림 15.13에서 빌드가 UAT 단계까지 전달되었고 이제 Await Approval에서 중지된 것을 볼 수 있습니다.


그림 15.13 Jenkins의 CI/CD 파이프라인이 UAT에 배포되었으며 계속 승인을 기다리고 있습니다.

수동 승인 단계에는 하루 종일 전담 팀과 함께 테스트하는 것이 포함될 수도 있고, 새 배포가 프로덕션과 유사한 환경에서 잘 보이는지 빠르게 확인하는 것일 수도 있습니다. 배포에 만족하면 Jenkins로 돌아가 Approve 신호를 보냅니다. 그런 다음 프로덕션 환경에 배포하는 마지막 단계로 넘어갑니다.

TRY PWD 세션으로 돌아가서 timecheck 컨테이너가 실행 중이고 올바른 로그를 작성하고 있는지 확인하십시오.

docker container ls
docker container logs timecheck-uat_timecheck_1

모든 것이 잘 될 것이라고 확신하므로 Jenkins로 돌아가서 Await Approval 단계에서 파란색 상자를 클릭합니다. 배포 확인을 묻는 창이 나타납니다. Do It을 클릭하십시오!

프로덕션 배포가 거의 완료되었습니다. 그림 15.14에서 내 출력을 볼 수 있습니다. UAT 테스트는 백그라운드로, 승인 단계는 포그라운드로 되어 있습니다.

그림 15.14 UAT 배포가 올바르게 작동하고 앱이 PWD에서 실행 중입니다.

파이프라인의 CD 단계는 CI 단계보다 복잡한 작업을 수행하지 않습니다. 단일 Docker Compose 명령을 사용하여 작업을 수행하는 각 단계에 대한 스크립트 파일이 있으며 관련 재정의 파일을 함께 결합합니다(원격 환경이 Swarm 클러스터인 경우 docker 스택 배포 명령이 될 수 있음). 배포 스크립트는 TLS 인증서 경로 및 Docker 호스트 도메인이 환경 변수에 제공될 것으로 예상하고 이러한 변수는 파이프라인 작업에서 설정됩니다.

Docker 및 Docker Compose CLI로 수행되는 실제 작업과 파이프라인에서 수행되는 작업의 구성을 구분하는 것이 중요합니다. 그러면 특정 자동화 서버에 대한 의존도가 줄어들고 서버 간에 쉽게 전환할 수 있습니다. Listing 15.3은 Jenkinsfile의 일부와 UAT에 배포하는 배치 스크립트를 보여줍니다.

목록 15.3 Jenkins 자격 증명을 사용하여 스크립트 파일에 Docker TLS 인증서 전달

# the deployment stage of the 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"
            }
        }
    }
}
 
# and the actual script just uses Docker Compose:
 
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

Jenkins는 자체 자격 증명에서 셸 스크립트에 대한 TLS 인증서를 제공합니다. 이 빌드를 GitHub Actions로 이동할 수 있으며 GitHub 리포지토리에 저장된 비밀을 사용하여 워크플로를 모방하면 됩니다. 빌드 스크립트 자체는 변경할 필요가 없습니다. 프로덕션 배포 단계는 UAT와 거의 동일합니다. 단지 다른 Compose 파일 세트를 사용하여 환경 설정을 지정합니다. UAT와 프로덕션에 동일한 PWD 환경을 사용하고 있으므로 작업이 완료되면 두 배포가 모두 실행되는 것을 볼 수 있습니다.

TRY 마지막으로 PWD 세션으로 돌아가서 로컬 Jenkins 빌드가 UAT 및 프로덕션 환경에 올바르게 배포되었는지 확인할 수 있습니다.

docker container ls
docker container logs timecheck-prod_timecheck_1

내 출력은 그림 15.15에 있습니다. 로컬 컨테이너의 Jenkins에서 실행되고 두 개의 원격 Docker 환경(이 경우 동일한 환경)에 배포하는 성공적인 CI/CD 파이프라인이 있습니다.

그림 15.15 PWD에 배포. 실제 클러스터를 사용하려면 도메인 이름과 인증서만 변경하면 됩니다.

이것은 놀랍도록 강력합니다. 다양한 환경용 컨테이너를 실행하는 데 Docker 서버와 CI/CD 인프라용으로 Docker를 실행하는 머신만 있으면 됩니다. 하루 만에 자체 앱의 파이프라인으로 이를 증명할 수 있으며(이미 구성 요소를 Docker화했다고 가정) 프로덕션 경로는 클러스터를 회전하고 배포 대상을 변경하기만 하면 됩니다.

그러나 프로덕션 파이프라인을 계획하기 전에 Docker 엔진을 원격으로 사용할 수 있도록 설정할 때(보안이 유지되더라도) 알아야 할 또 하나의 사항이 있습니다. 이것이 Docker 리소스에 대한 액세스 모델입니다.

15.5 Docker의 액세스 모델

Docker 리소스에 대한 액세스 모델은 매우 간단하기 때문에 전체 섹션이 필요하지 않지만 눈에 띄는 데 도움이 되는 자체 섹션이 있습니다. 엔진 보안은 CLI와 API 간의 트래픽을 암호화하고 사용자가 API에 액세스할 수 있도록 인증하는 두 가지에 관한 것입니다. 권한이 없습니다. 액세스 모델은 전부 아니면 전무입니다. API에 연결할 수 없으면 아무것도 할 수 없고, API에 연결할 수 있으면 모든 것을 할 수 있습니다.

그것이 당신을 두렵게 하는지 여부는 배경, 인프라 및 보안 모델의 성숙도에 따라 다릅니다. 관리자를 위한 별도의 네트워크를 사용하고 해당 네트워크에 대한 제한된 IP 액세스를 사용하여 공개 액세스 없이 내부 클러스터를 실행하고 있을 수 있으며 Docker CA를 매일 교체할 수 있습니다. 이는 심층 방어를 제공하지만 여전히 고려해야 할 직원의 공격 벡터가 있습니다(예, Stanley와 Minerva가 훌륭한 팀 플레이어라는 것을 알고 있지만 그들이 사기꾼이 아니라고 정말로 확신합니까? 특히 Stanley).

Kubernetes에는 Docker Enterprise와 마찬가지로 역할 기반 액세스 제어 모델이 있으므로 리소스에 액세스할 수 있는 사용자와 해당 리소스로 수행할 수 있는 작업을 제한할 수 있습니다. 또는 풀 기반 모델을 사용하여 CI/CD 파이프라인을 뒤집는 GitOps 접근 방식이 있습니다. 그러면 새 빌드가 승인되고 클러스터가 업데이트 자체를 배포할 때 클러스터가 인식할 수 있습니다. 그림 15.16은 클러스터에 연결할 필요가 없기 때문에 여기에 공유 자격 증명이 없음을 보여줍니다.


그림 15.16 GitOps의 멋진 신세계 - 모든 것이 Git에 저장되고 클러스터가 배포를 시작합니다.

GitOps는 애플리케이션 소스 코드와 배포 YAML 파일뿐만 아니라 인프라 설정 스크립트까지 모든 것을 반복 가능하고 버전 관리하기 때문에 매우 흥미로운 접근 방식입니다. Git의 전체 스택에 대한 단일 소스를 제공하므로 쉽게 감사하고 롤백할 수 있습니다. 아이디어가 마음에 들지만 처음부터 시작한다면 거기에 도달하는 데 많은 시간이 걸리겠지만 이 장에서 다룬 매우 간단한 CI/CD 파이프라인으로 시작하여 점차적으로 자신감을 얻으면 프로세스와 도구를 발전시키십시오.

15.6 Lab

섹션 15.4의 CD 연습을 따라했다면 CI 단계에서 이미지를 로컬 레지스트리로 푸시하고 PWD가 해당 레지스트리에 액세스할 수 없기 때문에 배포가 어떻게 작동했는지 궁금했을 것입니다. 컨테이너를 실행하기 위해 이미지를 어떻게 가져왔습니까? 글쎄, 그렇지 않았다. 나는 속였다. 배포 재정의 파일은 내가 직접 구축하고 푸시한 Docker Hub의 다른 이미지 태그를 사용합니다(실망하셨다면 죄송합니다. 하지만 이 책의 모든 이미지는 Jenkins 파이프라인으로 구축되었으므로 실제로 동일합니다). 이 실습에서 여러분은 이를 바로잡을 것입니다.

빌드에서 누락된 부분은 이미지를 로컬 레지스트리로 푸시하는 3단계에 있습니다. 일반적인 파이프라인에는 프로덕션 레지스트리에 푸시하기 전에 해당 이미지에 액세스할 수 있는 로컬 서버의 테스트 단계가 있지만 이를 건너뛰고 Docker Hub에 다른 푸시를 추가합니다. 이것이 목표입니다:

  • Docker Hub의 계정과 간단한 "3.0" 태그를 사용하도록 CI 이미지에 태그를 지정합니다.
  • Hub 자격 증명을 안전하게 유지하면서 이미지를 Docker Hub에 푸시합니다.
  • 고유한 Docker Hub 이미지를 사용하여 UAT 및 프로덕션 환경에 배포합니다.

여기에 몇 가지 움직이는 부분이 있지만 기존 파이프라인을 주의 깊게 살펴보고 수행해야 하는 작업을 볼 수 있습니다. 두 가지 힌트: 먼저 Jenkins에서 사용자 이름/비밀번호 자격 증명을 만들고 withCredentials 블록을 사용하여 Jenkinsfile에서 사용할 수 있도록 할 수 있습니다. 둘째, PWD 세션에 대한 열린 포트가 때때로 수신을 중지하므로 Jenkinsfile에서 새 PWD 도메인이 필요한 새 세션을 시작해야 할 수 있습니다.

좋은 웹페이지 즐겨찾기