개요
하둡/Hbase 에서 데이터센터를 이전하며 Kerberos 인증을 필수로 적용할 필요가 있게 되었다. 이에 따라 적용 및 트러블 슈팅을 하며 알아낸 점들을 생각났을때 정리해둔다. 아래 예제는 커버로스를 키탭 로그인 방식으로 적용할 때 필요한것들을 정리한 것이다.
알아두면 좋은것
- hadoop/hbase 커버로스는 어느쪽이든 1회만 인증하면 된다.
즉 hadoop 으로 커버로스 로그인을 하면 hbase 쓰는데 있어 추가 로그인이 필요없고 그 반대도 마찬가지이다. - jaas 파일은 세미콜론에 유의해야 한다.
- 커버로스 timeout 이후 토큰 refresh 테스트를 위해서는 로컬 krb5.conf의 ticket_lifetime 설정을 바꾸어 테스트 할 수 있다.
Hadoop 커버로스 설정
아래 예제는 hadoop 에 커버로스는 security()
를 통해 적용한 예제인데 Hbase 커버로스 설정없이 단독으로 사용할때는 아래 코드를 바로 사용하면 되고 Hbase와 같이 사용하게 되면 하둡쪽에 security()
만 빼주면 된다.(Hbase 에서 커버로스 로그인하면 하둡에서 로그인을 할 필요가 없기 떄문이다.)
static ConfigurationFactoryBean security(ConfigurationFactoryBean bean) {
bean.setSecurityMethod("kerberos");
bean.setUserPrincipal("hadoop-kwangsiklee-common@kwangsiklee.HADOOP");
bean.setUserKeytab("/opt/hadoop-env/keytabs/hadoop-kwangsiklee-common.keytab");
bean.setNamenodePrincipal("hdfs/_HOST@kwangsiklee.HADOOP");
bean.setRmManagerPrincipal("yarn/_HOST@kwangsiklee.HADOOP");
return bean;
}
/**
* 서비스용 하둡 클러스터 설정
*
* @return
*/
@Bean
public FactoryBean<org.apache.hadoop.conf.Configuration> serviceHadoopConfiguration() {
ConfigurationFactoryBean bean = security(new ConfigurationFactoryBean());
Set<Resource> configurationResources = new LinkedHashSet();
configurationResources.add(context.getResource("classpath:service-core-site.xml"));
configurationResources.add(context.getResource("classpath:service-hdfs-site.xml"));
configurationResources.add(context.getResource("classpath:service-mapred-site.xml"));
bean.setResources(configurationResources);
return bean;
}
/**
* 서비스용 하둡 클러스터 파일시스템 설정
*
* @return
* @throws Exception
*/
@Bean
@DependsOn("applicationProperties")
public FileSystemFactoryBean serviceHadoopFs() throws Exception {
FileSystemFactoryBean bean = new FileSystemFactoryBean();
bean.setConfiguration(serviceHadoopConfiguration().getObject());
return bean;
}
/**
* 서비스용 하둡 클러스터 리소스 로더 설정
*
* @return
* @throws Exception
*/
@Bean
public HdfsResourceLoader serviceHadoopResourceLoader() throws Exception {
return new HdfsResourceLoader(serviceHadoopFs().getObject());
}
Hbase 커버로스 설정
/**
* 서비스용 HBase 클러스터 연결 설정
*
* @return
* @throws Exception
*/
@Bean
public org.apache.hadoop.conf.Configuration serviceHbaseConfiguration() throws Exception {
System.setProperty("zookeeper.sasl.client", "false");
System.setProperty("java.security.auth.login.config", "/opt/hadoop-env/jaas/kwangsiklee-hbase-client.jaas");
System.setProperty("java.security.krb5.conf", "/etc/krb5.conf");
// System.setProperty("sun.security.krb5.debug", "true");
// System.setProperty("sun.security.spnego.debug", "true");
org.apache.hadoop.conf.Configuration conf = new org.apache.hadoop.conf.Configuration(true);
org.apache.hadoop.conf.Configuration hConf = HBaseConfiguration.create(conf);
hConf.addResource(context.getResource("classpath:service-hbase-site.xml").getURL());
hConf.set("hbase.zookeeper.quorum", "kwangsiklee-hbase-manager2.sample.io,kwangsiklee-hbase-manager1.sample.io,kwangsiklee-hbase-manager3.sample.io");
hConf.set("hadoop.security.authentication", "Kerberos");
hConf.set("hbase.security.authentication", "Kerberos");
hConf.set("hbase.master.kerberos.principal", "hbase/_HOST@kwangsiklee.HADOOP");
hConf.set("hbase.regionserver.kerberos.principal", "hbase/_HOST@kwangsiklee.HADOOP");
UserGroupInformation.setConfiguration(hConf);
UserGroupInformation.loginUserFromKeytab("hadoop-kwangsiklee-common@kwangsiklee.HADOOP", "/opt/hadoop-env/keytabs/hadoop-kwangsiklee-common.keytab");
return hConf;
}
/**
* 서비스용 HbaseTemplate 설정
*
* @return
* @throws Exception
*/
@Bean
public HbaseTemplate serviceHbaseTemplate() throws Exception {
HbaseTemplate template = new HbaseTemplate();
template.setConfiguration(serviceHbaseConfiguration());
return template;
}
설정파일
jaas 파일
Client {
com.sun.security.auth.module.Krb5LoginModule required
useTicketCache=false
useKeyTab=true
keyTab="/opt/hadoop-env/keytabs/hadoop-kwangsiklee-common.keytab"
principal="hadoop-kwangsiklee-common@kwangsiklee.HADOOP"
};
krb5.conf
[libdefaults]
default_realm = sample.COM
#default_realm = kwangsiklee.HADOOP
#rdns = false # <우분투의 경우 주석 해제>
dns_lookup_kdc = false
dns_lookup_realm = false
ticket_lifetime = 86400
renew_lifetime = 604800
forwardable = true
default_tgs_enctypes = aes128-cts-hmac-sha1-96 des3-cbc-sha1 arcfour-hmac des-hmac-sha1 des-cbc-md5 des-cbc-crc
default_tkt_enctypes = aes128-cts-hmac-sha1-96 des3-cbc-sha1 arcfour-hmac des-hmac-sha1 des-cbc-md5 des-cbc-crc
permitted_enctypes = aes128-cts-hmac-sha1-96 des3-cbc-sha1 arcfour-hmac des-hmac-sha1 des-cbc-md5 des-cbc-crc
udp_preference_limit = 1
kdc_timeout = 3000
max_retries = 2
ignore_acceptor_hostname = true
[realms]
sample.COM = {
kdc = auth.sample.com
admin_server = kadmin.sample.com
kpasswd_server = kadmin.sample.com
}
kwangsiklee.HADOOP = {
kdc = hadoop-auth.sample.io
admin_server = hadoop-auth.sample.io
admin_server = hadoop-auth-gs1.sample.io
}