Search code examples
c#kubernetes.net-corekubernetes-pod

Liveness Probe through C# code giving error


I am trying to implement liveliness probe through C# code (.Net core framework). I simply want to run a curl command inside container like this . Below is the code snippet:

IList<string> command = new List<string>();
V1Probe livnessconfig = null;
command.Add("curl http://localhost:5001/checkhealth/");
V1ExecAction execommand = new V1ExecAction(command);
livnessconfig = new V1Probe { Exec = execommand, InitialDelaySeconds = 10, PeriodSeconds = 10, TimeoutSeconds = 5, FailureThreshold = 3 };

But getting this error in pod description:

Liveness probe errored: rpc error: code = Unknown desc = failed to exec in container: failed to start exec "a80d33b5b2046b8e606ed622da7085013a725": OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "curl http://localhost:5001/checkhealth/": stat curl http://localhost:5001/checkhealth/

Can someone let me know whether this is correct way to provide command to V1ExecAction. Its metadata implementation in K8s.Models showing that V1ExecAction take command in List:

    #region Assembly KubernetesClient, Version=3.0.0.0, Culture=neutral, PublicKeyToken=a0f90e8c9af122d

using Newtonsoft.Json;
using System.Collections.Generic;

namespace k8s.Models
{
    //
    // Summary:
    //     ExecAction describes a "run in container" action.
    public class V1ExecAction
    {
        //
        // Summary:
        //     Initializes a new instance of the V1ExecAction class.
        public V1ExecAction();
        //
        // Summary:
        //     Initializes a new instance of the V1ExecAction class.
        //
        // Parameters:
        //   command:
        //     Command is the command line to execute inside the container, the working directory
        //     for the command is root ('/') in the container's filesystem. The command is simply
        //     exec'd, it is not run inside a shell, so traditional shell instructions ('|',
        //     etc) won't work. To use a shell, you need to explicitly call out to that shell.
        //     Exit status of 0 is treated as live/healthy and non-zero is unhealthy.
        public V1ExecAction(IList<string> command = null);

        //
        // Summary:
        //     Gets or sets command is the command line to execute inside the container, the
        //     working directory for the command is root ('/') in the container's filesystem.
        //     The command is simply exec'd, it is not run inside a shell, so traditional shell
        //     instructions ('|', etc) won't work. To use a shell, you need to explicitly call
 

       //out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy.
         [JsonProperty(PropertyName = "command")]
      public IList<string> Command { get; set; }
  } }

Solution

  • You have confused the Exec form with the Shell form; you can either change your command to use a shell explicitly, or fix the invocation to be compatible with exec. That's what the stat response was trying to tell you: there is no such file named curl http...

    Using sh

    command.Add("sh");
    command.Add("-c");
    command.Add("curl http://localhost:5001/checkhealth/");
    

    Using native exec

    command.Add("curl");
    command.Add("http://localhost:5001/checkhealth/");
    

    While this wasn't what you asked, the next problem you're going to experience is that curl only varies its exit status based on whether it could connect, not 200 versus non-200 HTTP status codes. You will want the --fail argument to have curl vary its return code based on the HTTP status

    You may also want to also include --silent since that health check command output shows up in the kubelet logs and in kubectl describe pod