S3 호환 스토리지를 쓰려면 core-site.xml 에 S3A 설정이 필요한데, Impala 만 알아서는 안 된다. 테이블을 만들 때 디렉터리를 실제로 만드는 주체는 Hive Metastore 이므로 HMS 도 같은 설정을 봐야 한다.
ImpalaRuntimeException: Error making 'createTable' RPC to Hive Metastore:
MetaException: ... is not a directory or unable to create one
이 오류는 대개 HMS 쪽에 S3A 설정이나 자격 증명이 없어서 난다. Cloudera Manager 환경이면 Impala · Hive · HDFS 서비스의 core-site.xml 안전 밸브에 같은 값을 넣는다.
<property><name>fs.s3a.endpoint</name><value>https://minio.example.net</value></property>
<property><name>fs.s3a.path.style.access</name><value>true</value></property>
<property><name>fs.s3a.connection.ssl.enabled</name><value>true</value></property>
<property><name>fs.s3a.access.key</name><value>${ACCESS_KEY}</value></property>
<property><name>fs.s3a.secret.key</name><value>${SECRET_KEY}</value></property>
MinIO 는 가상 호스트 방식(bucket.host) DNS 가 없는 경우가 많으므로 fs.s3a.path.style.access=true 가 사실상 필수다.
자격 증명을 평문으로 두지 않으려면 JCEKS 를 쓴다.
hadoop credential create fs.s3a.access.key -provider jceks://hdfs/user/impala/s3.jceks
hadoop credential create fs.s3a.secret.key -provider jceks://hdfs/user/impala/s3.jceks
<property>
<name>hadoop.security.credential.provider.path</name>
<value>jceks://hdfs/user/impala/s3.jceks</value>
</property>
경로는 s3a:// 스킴을 쓴다. https://host/bucket/path 형태의 URL 은 LOCATION 에 그대로 넣을 수 없다.
CREATE EXTERNAL TABLE db.tbl (id BIGINT, name STRING)
STORED AS PARQUET
LOCATION 's3a://bucket/data/tbl';
버킷과 상위 프리픽스는 미리 만들어 둔다. 오브젝트 스토리지에는 디렉터리 개념이 없어 빈 경로가 존재하지 않으므로, 접근 권한이 없거나 경로가 비어 있으면 "디렉터리가 아니다"라는 형태의 오류로 나타난다.
hdfs dfs -ls s3a://bucket/data/
hdfs dfs -mkdir -p s3a://bucket/data/tbl
오브젝트 스토리지는 rename 이 원자적이지 않다. INSERT OVERWRITE 처럼 임시 경로에 쓰고 옮기는 동작이 느리고, 중간 실패 시 잔여 파일이 남을 수 있다.
읽기 지연은 HDFS 보다 크다. 작은 파일이 많으면 차이가 더 벌어지므로 적재 시 파일 크기를 128MB 이상으로 맞춘다.
NiFi 등으로 같은 경로에 적재한다면 적재 주체와 Impala 가 같은 엔드포인트·자격 증명·접근 방식을 보게 한다. 한쪽만 경로 방식 접근을 켜 두면 한쪽에서만 보이는 상황이 생긴다.