美文网首页玩转大数据
记Ambari自定义组件列表被自动替换为官网问题的排查过程

记Ambari自定义组件列表被自动替换为官网问题的排查过程

作者: AlienPaul | 来源:发表于2020-11-04 15:29 被阅读0次

问题描述

为了让Ambari支持内网安装HDP集群,我们通常会修改repoinfo.xml(位于/var/lib/ambari-server/resources/stacks/HDP/[stack版本]/repos)。如下图所示:

<reposinfo>
  <!--
  <latest>http://public-repo-1.hortonworks.com/HDP/hdp_urlinfo.json</latest>
  -->
  <latest>./hdp_urlinfo.json</latest>
<!-- 其余省略 -->
</reposinfo>

我们将latest标签外网URL替换为一个保存在本地的json文件。该json文件是一个自己编写的版本描述文件,指定了具体组件版本描述xml文件的位置。

但在实际内网上机安装的时候发现如下问题:Ambari server安装执行ambari-server setup的时候,会自动把HDP stack对应的repoinfo.xml文件的latest标签内容修改为hdp官网相关链接,导致组件版本信息在内网环境无法获取。即使是再次手工将repoinfo.xml文件的latest标签修改回来也无济于事,执行ambari-server setup还是会自动修改为官网地址。

追溯根因

一时半会儿没有头绪,干脆从源代码入手。跟踪ambari-server setup时候执行的源码serverSetup.py,约1219行,会找到如下所示片段:

  json_url = get_json_url_from_repo_file()
  if json_url:
    print "Ambari repo file contains latest json url {0}, updating stacks repoinfos with it...".format(json_url)
    properties = get_ambari_properties()
    stack_root = get_stack_location(properties)
    update_latest_in_repoinfos_for_stacks(stack_root, json_url)
  else:
    print "Ambari repo file doesn't contain latest json url, skipping repoinfos modification"

这段代码的含义是如果get_json_url_from_repo_file()函数获取到了json_url,会执行latest标签内容替换操作。

跟踪update_latest_in_repoinfos_for_stacks方法代码,如下所示:

# Go though all stacks and update the repoinfo.xml files
# replace <latest> tag with the passed url
def update_latest_in_repoinfos_for_stacks(stacks_root, json_url_string, predicate=lambda stack_name: stack_name == 'HDP'):
  for stack_name in os.walk(stacks_root).next()[1]:
    if predicate(stack_name):
      for stack_version in os.walk(os.path.join(stacks_root, stack_name)).next()[1]:
        repoinfo_xml_path = os.path.join(stacks_root, stack_name, stack_version, "repos", "repoinfo.xml")
        if os.path.exists(repoinfo_xml_path):
          replace_latest(repoinfo_xml_path, json_url_string)

这段逻辑大意为如果HDP stack的目录结构中存在repoinfo.xml,执行replace_latest方法,替换latest标签的内容为json_url_string变量。

replace_latest方法:

# replace <latest> tag in the file with the passed url
def replace_latest(repoinfo_xml_path, json_url_string):
  tree = ET.parse(repoinfo_xml_path)
  root = tree.getroot()
  latest_tag = root.find("latest")
  if latest_tag is not None:
    latest_tag.text = json_url_string
 
  with open(repoinfo_xml_path, "w") as out:
    out.write(XML_HEADER)
    tree.write(out)

到此为止,我们已经定位到了引起问题的外层调用了。现在需要看下它是怎么获取json_url的。

我们查看get_json_url_from_repo_file方法内容。如下所示:

# parse ambari repo file and get the value of '#json.url = http://...'
def get_json_url_from_repo_file():
  # 获取repo_file的路径全名
  repo_file_path = get_ambari_repo_file_full_name()
  if os.path.exists(repo_file_path):
    with open(repo_file_path, 'r') as repo_file:
      for line in repo_file:
        line = line.rstrip()
        # 如果找到json.url一行,返回这一行等号后的内容
        if "json.url" in line:
          json_url_string = line.split("=", 1)[1].strip()
          return json_url_string
 
  return None

上面的主要逻辑是解析repo_file,找到json.url配置项并返回它的值。

接来下的问题是,这个repo_file在哪里呢?

我们查看get_ambari_repo_file_full_name方法内容:

# Gets the full path of the ambari repo file for the current OS
def get_ambari_repo_file_full_name():
  if OSCheck.is_ubuntu_family():
    ambari_repo_file = "/etc/apt/sources.list.d/ambari.list"
  elif OSCheck.is_redhat_family():
    ambari_repo_file = "/etc/yum.repos.d/ambari.repo"
  elif OSCheck.is_suse_family():
    ambari_repo_file = "/etc/zypp/repos.d/ambari.repo"
  elif OSCheck.is_windows_family():
    ambari_repo_file = os.path.join(os.environ[ChocolateyConsts.CHOCOLATEY_INSTALL_VAR_NAME],
                                    ChocolateyConsts.CHOCOLATEY_CONFIG_DIR, ChocolateyConsts.CHOCOLATEY_CONFIG_FILENAME)
  else:
    raise Exception('Ambari repo file path not set for current OS.')
 
  return ambari_repo_file

到这里就真相大白了,原来ambari找的是Linux系统的软件源配置文件。根据操作系统发行版查找对应的配置文件。

我们出现问题的是CentOS系统,综合这两个方法我们发现,在CentOS中ambari会读取/etc/yum.repos.d/ambari.repo文件,找到json.url这一行,获取它的值,替换为repoinfo.xmllatest标签的内容。

现在就差最后一步,找到“罪魁祸首”。

我们查看服务器的/etc/yum.repos.d/ambari.repo文件,发现如下配置:

[root@manager ~]# cat /etc/yum.repos.d/ambari.repo
#VERSION_NUMBER=2.7.1.0-169
[ambari-2.7.1.0]
#json.url = http://public-repo-1.hortonworks.com/HDP/hdp_urlinfo.json
name=ambari
baseurl=http://xxx.xxxx.xxx/xxx/manager/
gpgcheck=0
enabled=1
priority=1

注意被注释掉的json.url这一行,尽管是被注释掉的,但是根据上面分析,ambari在解析的时候没有考虑到注释。即注释掉也会被解析。

我们被注释的假象蒙骗了,Ambari解析的时候完全不理会这一行开头是否是#号。我们把json.url这一行删除,还原repoinfo.xml之后再重新执行ambari-server setup。问题完美解决。

相关文章

网友评论

    本文标题:记Ambari自定义组件列表被自动替换为官网问题的排查过程

    本文链接:https://www.haomeiwen.com/subject/ncjgvktx.html