file 프로비저너
file 프로비저너 (file provisioner)
Official
file Packer 프로비저너는 Packer가 빌드한 머신에 파일을 업로드해요. 다음 워크플로우를 권장해요.
출처: Packer 공식 문서
본문
file프로비저너로 파일을 업로드하고shell프로비저너로 파일을 적절한 위치로 옮기고, 권한을 설정하고, 기타 작업을 수행해요.
프로비저닝 사용자(일반적으로 root가 아님)가 접근 권한이 있는 위치에만 파일을 업로드할 수 있어요. /tmp 에 파일을 만들고 shell 프로비저너로 최종 위치로 옮기는 것이 root 소유 위치에 파일을 업로드하는 유일한 방법이에요.
file 프로비저너는 단일 파일과 완전한 디렉터리 모두 업로드할 수 있어요.
Basic Example (기본 예시)
HCL2 / JSON
provisioner "file" {
source = "app.tar.gz"
destination = "/tmp/app.tar.gz"
}
{
"type": "file",
"source": "app.tar.gz",
"destination": "/tmp/app.tar.gz"
}
Configuration Reference (설정 참조)
사용 가능한 구성 옵션은 아래에 나열돼요.
Required Parameters (필수 파라미터):
content(string) —destination으로 복사할 내용이에요. destination이 파일이면 content가 그 파일에 쓰여지고, 디렉터리라면pkr-file-content라는 파일이 생성돼요. destination으로는 파일을 사용하는 걸 권장해요. 여기에는templatefile함수나 어떤 보간(interpolation) 문법도 사용될 수 있어요. 이 속성은 source나 sources와 함께 지정할 수 없어요.source(string) — 머신에 업로드할 로컬 파일 또는 디렉터리의 경로. 절대 또는 상대 경로일 수 있어요. 상대 경로라면 Packer가 실행될 때 작업 디렉터리를 기준으로 해요. 디렉터리라면 끝의 슬래시 존재가 중요해요. 디렉터리 업로드에 대해 아래를 읽어보세요.sources가 설정되지 않았다면 필수예요.destination(string) — 머신 안에서 파일이 업로드될 경로. 이 값은 쓰기 가능한 위치여야 하고 부모 디렉터리들이 이미 존재해야 해요. 프로비저닝 사용자(일반적으로 root가 아님)가 이 디렉터리에 쓸 수 없으면 "Permission Denied" 오류가 나요. source가 파일이라면 destination도 파일로 만드는 게 좋아요. 하지만 destination을 디렉터리로 설정한다면, 최소한 destination이 끝 슬래시로 끝나게 해서 Packer가 최종 업로드 경로에서 source의 기본 이름(basename)을 사용하도록 해야 해요. 그렇게 하지 않으면 파일 업로드가 실패할 수 있어요. destination 파일이 이미 존재하면 덮어써져요.
Optional Parameters (선택 파라미터):
sources([]string) — 업로드할 소스들의 목록. 같은 곳에 업로드할 파일이 여러 개 있으면source옵션 대신 사용할 수 있어요. 주의할 점은 destination이 끝 슬래시가 있는 디렉터리여야 하고,sources에 나열된 모든 파일은 파일 이름을 유지한 채 같은 디렉터리에 업로드돼요.direction(string) — 파일 전송의 방향. 기본값은 "upload"예요. "download"로 설정하면 머신 안의 "source" 파일이 로컬의 "destination" 으로 다운로드돼요.generated(bool) — 고급 사용자 전용. true면 빌드 전 검증이 아니라 업로드 직전에만 파일 존재를 확인해요. 이를 통해 즉석에서 만들어진 파일을 업로드할 수 있어요. 기본값은 false예요. 이 기능은 Packer를 시스템 상태에 의존하게 만들 수 있어서 권장하지 않아요. 파일을 Packer 실행 전에 생성하는 것을 선호하지만, 피할 수 없는 상황이 있을 수 있음을 알고 있어요.
Parameters common to all provisioners (모든 프로비저너 공통 파라미터):
pause_before(duration) — 실행 전에 duration만큼 잠자요.max_retries(int) — 실패 시 프로비저너가 재시도할 최대 횟수. 기본값은 0. 0이면 오류가 재시도되지 않아요.only(array of string) — 나열된 빌더(이름 기준)에 대해서만 프로비저너를 실행해요.override(object) — 특정 빌더에 대해 빌더를 다른 설정으로 재정의해요. 예:
In HCL2:
source "null" "example1" {
communicator = "none"
}
source "null" "example2" {
communicator = "none"
}
build {
sources = ["source.null.example1", "source.null.example2"]
provisioner "shell-local" {
inline = ["echo not overridden"]
override = {
example1 = {
inline = ["echo yes overridden"]
}
}
}
}
In JSON:
{
"builders": [
{
"type": "null",
"name": "example1",
"communicator": "none"
},
{
"type": "null",
"name": "example2",
"communicator": "none"
}
],
"provisioners": [
{
"type": "shell-local",
"inline": ["echo not overridden"],
"override": {
"example1": {
"inline": ["echo yes overridden"]
}
}
}
]
}
timeout(duration) — 프로비저너가 예를 들어1h10m1s또는10m보다 오래 걸리면 타임아웃되어 실패해요.
Directory Uploads (디렉터리 업로드)
file 프로비저너는 완전한 디렉터리를 원격 머신에 업로드할 수도 있어요. 디렉터리를 업로드할 때 알아야 할 몇 가지 중요한 점이 있어요.
첫째, 대상 디렉터리가 이미 존재해야 해요. 만들어야 한다면 file 프로비저너 바로 앞에 shell 프로비저너를 사용해 디렉터리를 만들어 주세요. 대상 디렉터리가 존재하지 않으면 file 프로비저너가 성공할 수도 있지만 결과가 정의되지 않아요.
다음으로, 소스 경로 끝 슬래시의 존재 여부가 디렉터리 이름이 대상 안에 포함될지, 아니면 대상이 생성될지를 결정해요. 예시가 가장 잘 설명해 줘요.
소스가 /foo (곤 슬래시 없음)이고 대상이 /tmp 라면, 로컬 머신의 /foo 내용이 원격 머신의 /tmp/foo 로 업로드돼요. 원격 머신의 foo 디렉터리는 Packer가 만들어요.
하지만 소스가 /foo/ (곤 슬래시 존재)이고 대상이 /tmp 라면, /foo 의 내용이 /tmp 안으로 직접 업로드돼요.
이 동작은 rsync의 표준 동작에서 가져왔어요. 내부적으로 rsync가 사용될 수도 있고 아닐 수도 있다는 점에 유의하세요.
참고: Packer는 운영체제에 따라 동작을 추론하지 않아요. 이는 불필요한 복잡성을 더하고 유지보수성을 떨어뜨리기 때문이에요. 모든 플랫폼에서 일관된 동작을 보장하려면, Windows 게스트에서 작업할 때도 디렉터리를 지정할 때 끝에 있는 정방향 슬래시(forward slash)를 사용하세요.
Uploading files that don't exist before Packer starts (Packer 시작 전에 존재하지 않는 파일 업로드)
일반적으로 source로 사용되는 로컬 파일은 Packer를 실행하기 전에 존재해야 해요. 이는 오타를 잡고 빌드가 시작되면 성공할 것임을 보장하는 데 좋아요. 하지만 이는 빌드 중에 파일을 생성한 뒤 나중에 file 프로비저너로 업로드할 수 없다는 뜻이기도 해요. 편리한 해결 방법은 파일 대신 디렉터리를 업로드하는 거예요. 디렉터리는 여전히 존재해야 하지만 내용은 존재하지 않아도 돼요. Packer 실행 중에 생성된 파일을 디렉터리에 쓰고 나중에 업로드되게 할 수 있어요.
Symbolic link uploads (심볼릭 링크 업로드)
심볼릭 링크를 업로드할 때의 동작은 커뮤니케이터에 따라 달라져요. Docker 커뮤니케이터는 심볼릭 링크를 보존하지만, 다른 모든 커뮤니케이터는 로컬 심볼릭 링크를 일반 파일로 취급해요. 업로드 시 심볼릭 링크를 보존하려면 tar 를 사용하는 걸 권장해요. 다음은 그 예시예요.
$ ls -l files
total 16
drwxr-xr-x 3 mwhooker staff 102 Jan 27 17:10 a
lrwxr-xr-x 1 mwhooker staff 1 Jan 27 17:10 b -> a
-rw-r--r-- 1 mwhooker staff 0 Jan 27 17:10 file1
lrwxr-xr-x 1 mwhooker staff 5 Jan 27 17:10 file1link -> file1
$ ls -l toupload
total 0
-rw-r--r-- 1 mwhooker staff 0 Jan 27 17:10 files.tar
JSON / HCL2
{
"provisioners": [
{
"type": "shell-local",
"command": "tar cf toupload/files.tar files"
},
{
"destination": "/tmp/",
"source": "./toupload",
"type": "file"
},
{
"inline": [
"cd /tmp && tar xf toupload/files.tar",
"rm toupload/files.tar"
],
"type": "shell"
}
]
}
build {
sources = [
"source.docker.example"
]
provisioner "shell-local" {
command = "tar cf toupload/files.tar files"
}
provisioner "file" {
destination = "/tmp/"
source = "./toupload"
}
provisioner "shell" {
inline = [
"cd /tmp && tar xf toupload/files.tar",
"rm toupload/files.tar"
]
}
}
Slowness when transferring large files over WinRM (WinRM으로 큰 파일을 전송할 때 느려짐)
WinRM 전송 방식 때문에 중간 크기의 파일도 업로드·다운로드하는 데 매우 오래 걸릴 수 있어요. Windows에서 file 프로비저너를 사용할 때 느림을 겪고 있다면 SSH 서버를 설정하고 ssh 커뮤니케이터를 사용하는 걸 권장해요. 게스트로 파일만 전송하면 되고 빌더가 지원한다면 http_directory 또는 http_content 지시어를 사용할 수도 있어요. 그러면 해당 디렉터리가 게스트에 HTTP로 제공되고, 환경 변수 PACKER_HTTP_ADDR 이 그 주소로 설정돼요.
더 알아보기 (Learn more)
- 이 페이지는 Packer 공식 문서에서 가져왔어요.