-
Notifications
You must be signed in to change notification settings - Fork 35
/
Copy pathcheck-kube-service-available.rb
executable file
·139 lines (123 loc) · 4.01 KB
/
check-kube-service-available.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#! /usr/bin/env ruby
# frozen_string_literal: false
# check-kube-pods-service-available
#
# DESCRIPTION:
# => Check if your kube services are up and ready
#
# OUTPUT:
# plain text
#
# PLATFORMS:
# Linux
#
# DEPENDENCIES:
# gem: sensu-plugin
# gem: kube-client
#
# USAGE:
# -s, --api-server URL URL to API server
# -v, --api-version VERSION API version. Defaults to 'v1'
# --in-cluster Use service account authentication
# --ca-file CA-FILE CA file to verify API server cert
# --cert CERT-FILE Client cert to present
# --key KEY-FILE Client key for the client cert
# -u, --user USER User with access to API
# --password PASSWORD If user is passed, also pass a password
# --token TOKEN Bearer token for authorization
# --token-file TOKEN-FILE File containing bearer token for authorization
# -l, --list SERVICES List of services to check (required)
# -p, --pending SECONDS Time (in seconds) a pod may be pending for and be valid
# --ignore-evicted Ignore evicted pods when calculating availability
#
# NOTES:
#
# LICENSE:
# Barry Martin <[email protected]>
# Released under the same terms as Sensu (the MIT license); see LICENSE
# for details.
#
require 'sensu-plugins-kubernetes/cli'
require 'time'
class AllServicesUp < Sensu::Plugins::Kubernetes::CLI
@options = Sensu::Plugins::Kubernetes::CLI.options.dup
option :service_list,
description: 'List of services to check',
short: '-l SERVICES',
long: '--list',
required: true
option :pendingTime,
description: 'Time (in seconds) a pod may be pending for and be valid',
short: '-p SECONDS',
long: '--pending',
default: 0,
proc: proc(&:to_i)
option :ignoreEvicted,
description: 'Skip evicted pods when deciding if a service is available',
long: '--ignore-evicted',
boolean: true,
default: false
def run
services = parse_list(config[:service_list])
failed_services = []
s = client.get_services
# TODO: come back and clean me up
s.each do |a| # rubocop:disable Metrics/BlockLength
next unless services.include?(a.metadata.name)
# Build the selector key so we can fetch the corresponding pod
selector_key = []
services.delete(a.metadata.name)
a.spec.selector.to_h.each do |k, v|
selector_key << "#{k}=#{v}"
end
next if selector_key.empty?
# Get the pod
pod = nil
begin
pod = client.get_pods(label_selector: selector_key.join(',').to_s)
rescue StandardError
failed_services << a.metadata.name.to_s
end
# Make sure our pod is running
next if pod.nil?
pod_available = false
pod.each do |p|
case p.status.phase
when 'Pending'
next if p.status.startTime.nil?
if (Time.now - Time.parse(p.status.startTime)).to_i < config[:pendingTime]
pod_available = true
break
end
when 'Running'
p.status.conditions.each do |c|
next unless c.type == 'Ready'
if c.status == 'True'
pod_available = true
break
end
break if pod_available
end
when 'Evicted'
next if config[:ignoreEvicted]
end
failed_services << "#{p.metadata.namespace}.#{p.metadata.name}" if pod_available == false
end
end
if failed_services.empty? && services.empty?
ok 'All services are reporting as up'
end
if !failed_services.empty?
critical "All services are not ready: #{failed_services.join(' ')}"
else
critical "Some services could not be checked: #{services.join(' ')}"
end
rescue KubeException => e
critical 'API error: ' << e.message
end
def parse_list(list)
return list.split(',') if list&.include?(',')
return [list] if list
['']
end
end