Puppet使用ENC報(bào)'Couldnotloadexternalnoderesultsfor'

這個(gè)問(wèn)題出現(xiàn)有一段時(shí)間了,最開(kāi)始的時(shí)候從一天3-5次左右到最近的一天出現(xiàn)10多次的告警郵件...

創(chuàng)新互聯(lián)公司2013年開(kāi)創(chuàng)至今,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目網(wǎng)站設(shè)計(jì)制作、做網(wǎng)站網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元萊州做網(wǎng)站,已為上家服務(wù),為萊州各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:18982081108

因?yàn)镻uppet同步采取了主動(dòng)觸發(fā)和定時(shí)同步兩種策略,幾乎每次的報(bào)錯(cuò)都是在定時(shí)同步時(shí)出現(xiàn)...

Puppet Server采用雙主結(jié)構(gòu),Web ui使用Foreman,為了確定這個(gè)報(bào)錯(cuò)是出現(xiàn)在那臺(tái)服務(wù)器上, 通過(guò)對(duì)源代碼的log增加主機(jī)標(biāo)記最終定位到了這個(gè)錯(cuò)誤只是出現(xiàn)在一臺(tái)服務(wù)器上...,出現(xiàn)的很偶然,但所有的錯(cuò)誤標(biāo)記中,都是它....

Level	Resource	message
err	Puppet	Could not retrieve catalog from remote server: Error 400 on SERVER: Failed when searching for node xxx: 001。,Could not load external node results for xxx: undefined method `inject' for false:FalseClass ::--- false
notice	Puppet	Using cached catalog
err	Puppet	Could not retrieve catalog; skipping run

 

最后面的 :: --- false    其中::是在log中追加的分解符,方便區(qū)分, --- false 是返回的output的信息..

 

在Puppet源代碼中 , 通過(guò)indirector與enc相關(guān)的find方法中可以看到這個(gè)find方法接受一個(gè)參數(shù) request

 indirector/node/exec.rb 
  def find(request)
    output = super or return nil

    # Translate the output to ruby.
    result = translate(request.key, output)

    create_node(request.key, result)
  end

output 是調(diào)用父方法的find

父方法的find會(huì)調(diào)用enc腳本獲取返回值,如果失敗或調(diào)用不成功則為Nil..

這時(shí)會(huì)繼續(xù)通過(guò)translate方法,將yaml輸出轉(zhuǎn)為ruby的對(duì)象

如果output為nil,這時(shí)yaml在讀取這個(gè)數(shù)據(jù)的時(shí)候就會(huì)拋出異常,異常就是收到的Puppet郵件告警的內(nèi)容了。

  def translate(name, output)
    YAML.load(output).inject({}) do |hash, data|                                             
      case data[0]                                                                           
      when String                                                                            
        hash[data[0].intern] = data[1]                                                       
      when Symbol                                                                            
        hash[data[0]] = data[1]                                                              
      else                                                                                   
        raise Puppet::Error, "key is a #{data[0].class}, not a string or symbol"             
      end                                                                                    
                                                                                             
      hash                                                                                   
    end                                                                                      
                                                                                             
  rescue => detail                                                                           
      raise Puppet::Error, "001,Could not load external node results for #{name}: #{detail} ::#{output} "
  end

 

 

羅嗦了一大堆,其實(shí)就是node.rb的腳本在通過(guò)api取參數(shù)的時(shí)候,沒(méi)有獲得200...導(dǎo)致的。

通過(guò)指向一個(gè)錯(cuò)誤的WEB服務(wù)器地址,可以看到 開(kāi)頭--- false。。。。

[root@test puppet]# ruby node1.rb test
--- false
Error retrieving node test: Net::HTTPNotFound

 

分析node.rb

def enc(certname)
  foreman_url      = "#{url}/node/#{certname}?format=yml"
  uri              = URI.parse(foreman_url)
  req              = Net::HTTP::Get.new(uri.request_uri)
  http             = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl     = uri.scheme == 'https'
  if http.use_ssl?
    if SETTINGS[:ssl_ca] && !SETTINGS[:ssl_ca].empty?
      http.ca_file = SETTINGS[:ssl_ca]
      http.verify_mode = OpenSSL::SSL::VERIFY_PEER
    else
      http.verify_mode = OpenSSL::SSL::VERIFY_NONE
    end
    if SETTINGS[:ssl_cert] && !SETTINGS[:ssl_cert].empty? && SETTINGS[:ssl_key] && !SETTINGS[:ssl_key].empty?
      http.cert = OpenSSL::X509::Certificate.new(File.read(SETTINGS[:ssl_cert]))
      http.key  = OpenSSL::PKey::RSA.new(File.read(SETTINGS[:ssl_key]), nil)
    end
  end
  res = http.start { |http| http.request(req) }

  raise "Error retrieving node #{certname}: #{res.class}" unless res.code == "200"
  res.body
end

腳本的前面都是在構(gòu)造一個(gè)http的對(duì)象...,直接看倒數(shù)第三行

可以清楚的看到一個(gè)判斷,然后拋出異常,沒(méi)有任何的重試機(jī)制....,為此我很確信我的web,它如果能有一次重試的機(jī)會(huì),那么下一次一定能正常獲得返回值,  然后我就給了它很多次的機(jī)會(huì)。。。

  #raise "Error retrieving node #{certname}: #{res.class}" unless res.code == "200"
  while res.code != "200"
    res = http.start { |http| http.request(req) }
    puts "Error retrieving node #{certname}: #{res.class}"    sleep 3
  end

這時(shí)有些人可能會(huì)想,while 循環(huán),加3秒重試,,如果一直不成功怎么辦?

在腳本最開(kāi)頭會(huì)有配置timeout的地方,在timeout到了之后,會(huì)關(guān)閉http連接,然后讀取cache。

 

      # query External node
      begin
        result = ""
        timeout(tsecs) do
          result = enc(certname)
          cache(certname, result)
        end
      rescue TimeoutError, SocketError, Errno::EHOSTUNREACH, Errno::ECONNREFUSED
        # Read from cache, we got some sort of an error.
        result = read_cache(certname)

這段代碼可以很清晰的看出,在timeout沒(méi)超時(shí)時(shí)會(huì)調(diào)用enc這個(gè)方法返回結(jié)果,然后在調(diào)用cache方法寫(xiě)入到cache文件

如果超時(shí)或http錯(cuò)誤,則讀取cache,但是這里的異常不包括...,HTTP的...,如果如果是4XX的錯(cuò)誤,不會(huì)觸發(fā)讀取cache的異常..

名稱欄目:Puppet使用ENC報(bào)'Couldnotloadexternalnoderesultsfor'
地址分享:http://muchs.cn/article14/jpegde.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供響應(yīng)式網(wǎng)站、建站公司用戶體驗(yàn)、網(wǎng)站設(shè)計(jì)、品牌網(wǎng)站設(shè)計(jì)服務(wù)器托管

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站建設(shè)