개요

하둡/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
}