rabbitmq / rabbitmq-autocluster

RabbitMQ peer discovery and cluster formation plugin, supports RabbitMQ 3.6.x
BSD 3-Clause "New" or "Revised" License
241 stars 54 forks source link

Handle "notReadyAddresses" in kubernetes #24

Closed Gsantomaggio closed 7 years ago

Gsantomaggio commented 7 years ago

Using the StatefulSets the API:

curl -v --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://kubernetes.default.svc.cluster.local:443/api/v1/namespaces/test-rabbitmq/endpoints/rabbitmq

gets this result:

 "subsets": [
    {
      "notReadyAddresses": [
        {
          "ip": "172.17.0.2",
          "hostname": "rabbitmq-0",
          "nodeName": "minikube",
          "targetRef": {
            "kind": "Pod",
            "namespace": "test-rabbitmq",
            "name": "rabbitmq-0",
            "uid": "3523b6ad-3a17-11e7-9fac-080027cbdcae",
            "resourceVersion": "108775"
          }
        }
      ],

notReadyAddresses means that the POD is starting and it is not ready yet.

During the startup It causes:

=INFO REPORT==== 16-May-2017::07:23:26 ===
Error description:
   {could_not_start,rabbit,
       {function_clause,
           [{autocluster_k8s,'-extract_node_list/1-lc$^1/1-1-',
                [undefined],
                [{file,"src/autocluster_k8s.erl"},{line,85}]},
            {autocluster_k8s,'-extract_node_list/1-lc$^0/1-0-',1,
                [{file,"src/autocluster_k8s.erl"},{line,85}]},
            {autocluster_k8s,extract_node_list,1,
                [{file,"src/autocluster_k8s.erl"},{line,85}]},
            {autocluster_k8s,nodelist,0,
                [{file,"src/autocluster_k8s.erl"},{line,30}]},
            {autocluster,ensure_registered,3,
                [{file,"src/autocluster.erl"},{line,107}]},
            {autocluster,init,0,[{file,"src/autocluster.erl"},{line,33}]},
            {rabbit_boot_steps,'-run_step/2-lc$^1/1-1-',1,
                [{file,"src/rabbit_boot_steps.erl"},{line,49}]},
            {rabbit_boot_steps,run_step,2,
                [{file,"src/rabbit_boot_steps.erl"},{line,49}]}]}}

Log files (may contain more information):
   tty
   tty

init terminating in do_boot ()

{"init terminating in do_boot",{could_not_start,rabbit,{function_clause,[{autocluster_k8s,'-extract_node_list/1-lc$^1/1-1-',[undefined],[{file,"src/autocluster_k8s.erl"},{line,85}]},{autocluster_k8s,'-extract_node_list/1-lc$^0/1-0-',1,[{file,"src/autocluster_k8s.erl"},{line,85}]},{autocluster_k8s,extract_node_list,1,[{file,"src/autocluster_k8s.erl"},{line,85}]},{autocluster_k8s,nodelist,0,[{file,"src/autocluster_k8s.erl"},{line,30}]},{autocluster,ensure_registered,3,[{file,"src/autocluster.erl"},{line,107}]},{autocluster,init,0,[{file,"src/autocluster.erl"},{line,33}]},{rabbit_boot_steps,'-run_step/2-lc$^1/1-1-',1,[{file,"src/rabbit_boot_steps.erl"},{line,49}]},{rabbit_boot_steps,run_step,2,[{file,"src/rabbit_boot_steps.erl"},{line,49}]}]}}}

Because proplists:get_value(<<"addresses">>, Subset) is undefined

The possible solution is to return an empty list nodes in case is undefined:

get_address(Subset) ->
  case proplists:get_value(<<"addresses">>, Subset) of 
      undefined -> autocluster_log:info("No nodes ready yet!"), []; 
      Address -> Address  
  end.

%% @spec extract_node_list(k8s_endpoints()) -> list()
%% @doc Return a list of nodes
%%    see http://kubernetes.io/docs/api-reference/v1/definitions/#_v1_endpoints
%% @end
%%
extract_node_list({struct, Response}) ->
    IpLists = [[proplists:get_value(list_to_binary(autocluster_config:get(k8s_address_type)), Address)
        || {struct, Address} <- get_address(Subset)]
           || {struct, Subset} <- proplists:get_value(<<"subsets">>, Response)],
    sets:to_list(sets:union(lists:map(fun sets:from_list/1, IpLists))).