kubernetes-deploy 0.20.4 → 0.20.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f0b4318bc1b5546351e5aaaa8a2e5a40675349c6
4
- data.tar.gz: 3f4df1e8c2010d668118fae08a15de4ab21b67b3
3
+ metadata.gz: b01e4098e730e6ee300284d185adb140cf3cdc80
4
+ data.tar.gz: 6416b255318a78d3a1b6383263bbecd7b3603a4b
5
5
  SHA512:
6
- metadata.gz: db3e58f8c6ae85a41a436f24068a03d7312df2080a62ab05abb818f5723b07e7875be5d3a7af95f56edf67d5f4be5cff5536a2506465152f205f49c32b5686e5
7
- data.tar.gz: 3093b949fa36286f03548c3e91ebbc0378d27dafd922b7677dd7b902b9288fee2e8e2120306b3eaccd70f74337ddf2713842457445410b4fd77ee6030191aa97
6
+ metadata.gz: aeeb95108945428fe39de942b7285843cd8a3960344089386bfbf1cfc1a551a50c1531d3e7d2082187f67640e6978ad1ab00f8ed7176b14d92bb56410ba78380
7
+ data.tar.gz: d0c1753242a3131586627252707ef9674ff94d2ac0e8e9f39f6a147dbc05449b5414ce6f26c1e8ede9bb4bd58d5919bf94ed6629f97ff2abc9db5c74e4b70e82
@@ -1,11 +1,11 @@
1
- # Disableed until minikube can run 1.10
2
- # - name: 'Run Test Suite (:kubernetes: 1.10-latest)'
3
- # command: bin/ci
4
- # agents:
5
- # queue: minikube-ci
6
- # env:
7
- # LOGGING_LEVEL: 4
8
- # KUBERNETES_VERSION: v1.10-latest
1
+ steps:
2
+ - name: 'Run Test Suite (:kubernetes: 1.10-latest)'
3
+ command: bin/ci
4
+ agents:
5
+ queue: minikube-ci
6
+ env:
7
+ LOGGING_LEVEL: 4
8
+ KUBERNETES_VERSION: v1.10-latest
9
9
  - name: 'Run Test Suite (:kubernetes: 1.9-latest)'
10
10
  command: bin/ci
11
11
  agents:
@@ -1,3 +1,11 @@
1
+ steps:
2
+ - name: 'Run Test Suite (:kubernetes: 1.10-latest)'
3
+ command: bin/ci
4
+ agents:
5
+ queue: minikube-ci
6
+ env:
7
+ LOGGING_LEVEL: 4
8
+ KUBERNETES_VERSION: v1.10-latest
1
9
  - name: 'Run Test Suite (:kubernetes: 1.9-latest)'
2
10
  command: bin/ci
3
11
  agents:
data/CHANGELOG.md CHANGED
@@ -1,6 +1,16 @@
1
1
  ### Master
2
2
 
3
+ *Enhancements*
4
+ - Add Job resource class ([#295](https://github.com/Shopify/kubernetes-deploy/pull/296))
5
+ - Add CustomResourceDefinition resource class ([#306](https://github.com/Shopify/kubernetes-deploy/pull/306))
6
+ - Officially support Kubernetes 1.10 ([#308](https://github.com/Shopify/kubernetes-deploy/pull/308))
7
+ - SyncMediator will only batch fetch resources when there is a sufficiently large enough set of resources
8
+ being tracked ([#316](https://github.com/Shopify/kubernetes-deploy/pull/316))
9
+ - Allow CRs to be pruned based on `kubernetes-deploy.shopify.io/prunable` annotation on the custom resource definitions ([312](https://github.com/Shopify/kubernetes-deploy/pull/312))
10
+ - Add HorizontalPodAutoscaler resource class ([#305](https://github.com/Shopify/kubernetes-deploy/pull/305))
11
+
3
12
  ### 0.20.4
13
+ *Enhancements*
4
14
  - Don't consider pod preempting a failure ([#317](https://github.com/shopify/kubernetes-deploy/pull/317))
5
15
 
6
16
  ### 0.20.3
@@ -8,7 +18,6 @@
8
18
  - Evictions are recoverable so prevent them from triggering fast failure detection ([#293](https://github.com/Shopify/kubernetes-deploy/pull/293)).
9
19
  - Use YAML.safe_load over YAML.load_file ([#295](https://github.com/Shopify/kubernetes-deploy/pull/295)).
10
20
 
11
-
12
21
  *Bug Fixes*
13
22
  - Default rollout strategy is compatible required-rollout annotation ([#289](https://github.com/Shopify/kubernetes-deploy/pull/289)).
14
23
 
@@ -16,7 +25,6 @@
16
25
  *Enhancements*
17
26
  - Emit data dog events when deploys succeed, time out or fail ([#292](https://github.com/Shopify/kubernetes-deploy/pull/292)).
18
27
  ### 0.20.1
19
- *Features*
20
28
 
21
29
  *Bug Fixes*
22
30
  - Display a nice error instead of crashing when a YAML document is missing 'Kind'
data/README.md CHANGED
@@ -241,6 +241,10 @@ before the deployment is considered successful.
241
241
  that use the `RollingUpdate` strategy.
242
242
  - Percent (e.g. 90%): The deploy is successful when the number of new pods that are ready is equal to
243
243
  `spec.replicas` * Percent.
244
+ - `kubernetes-deploy.shopify.io/prunable`: Allows a Custom Resource to be pruned during deployment.
245
+ - _Compatibility_: Custom Resource Definition
246
+ - `true`: The custom resource will be pruned if the resource is not in the deploy directory.
247
+ - All other values: The custom resource will not be pruned.
244
248
 
245
249
  ### Running tasks at the beginning of a deploy
246
250
 
data/dev.yml CHANGED
@@ -8,7 +8,7 @@ up:
8
8
  - custom:
9
9
  name: Minikube Cluster
10
10
  met?: test $(minikube status | grep Running | wc -l) -eq 2 && $(minikube status | grep -q 'Correctly Configured')
11
- meet: minikube start --kubernetes-version=v1.9.4 --vm-driver=hyperkit
11
+ meet: minikube start --kubernetes-version=v1.10.0 --vm-driver=hyperkit
12
12
  down: minikube stop
13
13
  commands:
14
14
  reset-minikube: minikube delete && rm -rf ~/.minikube
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
25
25
  spec.required_ruby_version = '>= 2.3.0'
26
26
  spec.add_dependency "activesupport", ">= 5.0"
27
27
  spec.add_dependency "kubeclient", "~> 3.0"
28
- spec.add_dependency "googleauth", ">= 0.5"
28
+ spec.add_dependency "googleauth", "= 0.6.2" # https://github.com/google/google-auth-library-ruby/issues/153
29
29
  spec.add_dependency "ejson", "1.0.1"
30
30
  spec.add_dependency "colorize", "~> 0.8"
31
31
  spec.add_dependency "statsd-instrument", "~> 2.2"
@@ -27,6 +27,9 @@ require 'kubernetes-deploy/kubernetes_resource'
27
27
  bucket
28
28
  stateful_set
29
29
  cron_job
30
+ job
31
+ custom_resource_definition
32
+ horizontal_pod_autoscaler
30
33
  ).each do |subresource|
31
34
  require "kubernetes-deploy/kubernetes_resource/#{subresource}"
32
35
  end
@@ -35,6 +38,7 @@ require 'kubernetes-deploy/kubectl'
35
38
  require 'kubernetes-deploy/kubeclient_builder'
36
39
  require 'kubernetes-deploy/ejson_secret_provisioner'
37
40
  require 'kubernetes-deploy/renderer'
41
+ require 'kubernetes-deploy/resource_discovery'
38
42
 
39
43
  module KubernetesDeploy
40
44
  class DeployTask
@@ -50,6 +54,7 @@ module KubernetesDeploy
50
54
  ServiceAccount
51
55
  Pod
52
56
  )
57
+
53
58
  PROTECTED_NAMESPACES = %w(
54
59
  default
55
60
  kube-system
@@ -63,6 +68,7 @@ module KubernetesDeploy
63
68
  # core/v1/ReplicationController -- superseded by deployments/replicasets
64
69
  # extensions/v1beta1/ReplicaSet -- managed by deployments
65
70
  # core/v1/Secret -- should not committed / managed by shipit
71
+
66
72
  def prune_whitelist
67
73
  wl = %w(
68
74
  core/v1/ConfigMap
@@ -80,7 +86,7 @@ module KubernetesDeploy
80
86
  if server_version >= Gem::Version.new('1.8.0')
81
87
  wl << "batch/v1beta1/CronJob"
82
88
  end
83
- wl
89
+ wl + cluster_resource_discoverer.crds(@sync_mediator).select(&:prunable?).map(&:group_version_kind)
84
90
  end
85
91
 
86
92
  def server_version
@@ -198,6 +204,10 @@ module KubernetesDeploy
198
204
 
199
205
  private
200
206
 
207
+ def cluster_resource_discoverer
208
+ ResourceDiscovery.new(namespace: @namespace, context: @context, logger: @logger, namespace_tags: @namespace_tags)
209
+ end
210
+
201
211
  def deploy_has_priority_resources?(resources)
202
212
  resources.any? { |r| PREDEPLOY_SEQUENCE.include?(r.type) }
203
213
  end
@@ -247,6 +257,10 @@ module KubernetesDeploy
247
257
  @logger.info " - #{r.id}"
248
258
  end
249
259
  end
260
+ if (global = resources.select(&:global?).presence)
261
+ @logger.warn("Detected non-namespaced #{'resource'.pluralize(global.count)} which will never be pruned:")
262
+ global.each { |r| @logger.warn(" - #{r.id}") }
263
+ end
250
264
  resources
251
265
  end
252
266
 
@@ -36,6 +36,14 @@ module KubernetesDeploy
36
36
  )
37
37
  end
38
38
 
39
+ def build_batch_v1_kubeclient(context)
40
+ _build_kubeclient(
41
+ api_version: "v1",
42
+ context: context,
43
+ endpoint_path: "/apis/batch/"
44
+ )
45
+ end
46
+
39
47
  def build_policy_v1beta1_kubeclient(context)
40
48
  _build_kubeclient(
41
49
  api_version: "v1beta1",
@@ -52,6 +60,22 @@ module KubernetesDeploy
52
60
  )
53
61
  end
54
62
 
63
+ def build_apiextensions_v1beta1_kubeclient(context)
64
+ _build_kubeclient(
65
+ api_version: "v1beta1",
66
+ context: context,
67
+ endpoint_path: "/apis/apiextensions.k8s.io"
68
+ )
69
+ end
70
+
71
+ def build_autoscaling_v1_kubeclient(context)
72
+ _build_kubeclient(
73
+ api_version: "v2beta1",
74
+ context: context,
75
+ endpoint_path: "/apis/autoscaling"
76
+ )
77
+ end
78
+
55
79
  def _build_kubeclient(api_version:, context:, endpoint_path: nil)
56
80
  # Find a context defined in kube conf files that matches the input context by name
57
81
  friendly_configs = config_files.map { |f| GoogleFriendlyConfig.read(f) }
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+ module KubernetesDeploy
3
+ class CustomResourceDefinition < KubernetesResource
4
+ TIMEOUT = 2.minutes
5
+ GLOBAL = true
6
+
7
+ def deploy_succeeded?
8
+ names_accepted_status == "True"
9
+ end
10
+
11
+ def deploy_failed?
12
+ names_accepted_status == "False"
13
+ end
14
+
15
+ def timeout_message
16
+ "The names this CRD is attempting to register were neither accepted nor rejected in time"
17
+ end
18
+
19
+ def status
20
+ if !exists?
21
+ super
22
+ elsif deploy_succeeded?
23
+ "Names accepted"
24
+ else
25
+ "#{names_accepted_condition['reason']} (#{names_accepted_condition['message']})"
26
+ end
27
+ end
28
+
29
+ def group_version_kind
30
+ group = @definition.dig("spec", "group")
31
+ version = @definition.dig("spec", "version")
32
+ "#{group}/#{version}/#{kind}"
33
+ end
34
+
35
+ def kind
36
+ @definition.dig("spec", "names", "kind")
37
+ end
38
+
39
+ def prunable?
40
+ prunable = @definition.dig("metadata", "annotations", "kubernetes-deploy.shopify.io/prunable")
41
+ prunable == "true"
42
+ end
43
+
44
+ private
45
+
46
+ def names_accepted_condition
47
+ conditions = @instance_data.dig("status", "conditions") || []
48
+ conditions.detect { |c| c["type"] == "NamesAccepted" } || {}
49
+ end
50
+
51
+ def names_accepted_status
52
+ names_accepted_condition["status"]
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+ module KubernetesDeploy
3
+ class HorizontalPodAutoscaler < KubernetesResource
4
+ TIMEOUT = 3.minutes
5
+ RECOVERABLE_CONDITIONS = %w(ScalingDisabled FailedGet)
6
+
7
+ def deploy_succeeded?
8
+ scaling_active_condition["status"] == "True"
9
+ end
10
+
11
+ def deploy_failed?
12
+ return false unless exists?
13
+ recoverable = RECOVERABLE_CONDITIONS.any? { |c| scaling_active_condition.fetch("reason", "").start_with?(c) }
14
+ scaling_active_condition["status"] == "False" && !recoverable
15
+ end
16
+
17
+ def kubectl_resource_type
18
+ 'hpa.v2beta1.autoscaling'
19
+ end
20
+
21
+ def status
22
+ if !exists?
23
+ super
24
+ elsif deploy_succeeded?
25
+ "Configured"
26
+ elsif scaling_active_condition.present? || able_to_scale_condition.present?
27
+ condition = scaling_active_condition.presence || able_to_scale_condition
28
+ condition['reason']
29
+ else
30
+ "Unknown"
31
+ end
32
+ end
33
+
34
+ def failure_message
35
+ condition = scaling_active_condition.presence || able_to_scale_condition.presence || {}
36
+ condition['message']
37
+ end
38
+
39
+ def timeout_message
40
+ failure_message.presence || super
41
+ end
42
+
43
+ private
44
+
45
+ def conditions
46
+ @instance_data.dig("status", "conditions") || []
47
+ end
48
+
49
+ def able_to_scale_condition
50
+ conditions.detect { |c| c["type"] == "AbleToScale" } || {}
51
+ end
52
+
53
+ def scaling_active_condition
54
+ conditions.detect { |c| c["type"] == "ScalingActive" } || {}
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+ module KubernetesDeploy
3
+ class Job < KubernetesResource
4
+ TIMEOUT = 10.minutes
5
+
6
+ def deploy_succeeded?
7
+ # Don't block deploys for long running jobs,
8
+ # Instead report success when there is at least 1 active
9
+ return false unless deploy_started?
10
+ done? || running?
11
+ end
12
+
13
+ def deploy_failed?
14
+ return false unless deploy_started?
15
+ return false unless @instance_data.dig("spec", "backoffLimit").present?
16
+ (@instance_data.dig("status", "failed") || 0) >= @instance_data.dig("spec", "backoffLimit")
17
+ end
18
+
19
+ def status
20
+ if !exists?
21
+ super
22
+ elsif done?
23
+ "Succeeded"
24
+ elsif running?
25
+ "Started"
26
+ elsif deploy_failed?
27
+ "Failed"
28
+ else
29
+ "Unknown"
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def done?
36
+ (@instance_data.dig("status", "succeeded") || 0) == @instance_data.dig("spec", "completions")
37
+ end
38
+
39
+ def running?
40
+ now = Time.now.utc
41
+ start_time = @instance_data.dig("status", "startTime")
42
+ # Wait 5 seconds to ensure job doesn't immediately fail.
43
+ return false if !start_time.present? || now - Time.parse(start_time) < 5.second
44
+ (@instance_data.dig("status", "active") || 0) >= 1
45
+ end
46
+ end
47
+ end
@@ -8,6 +8,7 @@ module KubernetesDeploy
8
8
  attr_reader :name, :namespace, :context
9
9
  attr_writer :type, :deploy_started_at
10
10
 
11
+ GLOBAL = false
11
12
  TIMEOUT = 5.minutes
12
13
  LOG_LINE_COUNT = 250
13
14
 
@@ -114,7 +115,7 @@ module KubernetesDeploy
114
115
  end
115
116
 
116
117
  def sync(mediator)
117
- @instance_data = mediator.get_instance(type, name)
118
+ @instance_data = mediator.get_instance(kubectl_resource_type, name)
118
119
  end
119
120
 
120
121
  def deploy_failed?
@@ -146,6 +147,10 @@ module KubernetesDeploy
146
147
  @type || self.class.kind
147
148
  end
148
149
 
150
+ def kubectl_resource_type
151
+ type
152
+ end
153
+
149
154
  def deploy_timed_out?
150
155
  return false unless deploy_started?
151
156
  !deploy_succeeded? && !deploy_failed? && (Time.now.utc - @deploy_started_at > timeout)
@@ -315,6 +320,10 @@ module KubernetesDeploy
315
320
  end
316
321
  end
317
322
 
323
+ def global?
324
+ self.class::GLOBAL
325
+ end
326
+
318
327
  private
319
328
 
320
329
  def validate_timeout_annotation
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KubernetesDeploy
4
+ class ResourceDiscovery
5
+ def initialize(namespace:, context:, logger:, namespace_tags:)
6
+ @namespace = namespace
7
+ @context = context
8
+ @logger = logger
9
+ @namespace_tags = namespace_tags
10
+ end
11
+
12
+ def crds(sync_mediator)
13
+ sync_mediator.get_all(CustomResourceDefinition.kind).map do |r_def|
14
+ CustomResourceDefinition.new(namespace: @namespace, context: @context, logger: @logger,
15
+ definition: r_def, statsd_tags: @namespace_tags)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -15,7 +15,7 @@ module KubernetesDeploy
15
15
  if ENV['STATSD_DEV'].present?
16
16
  ::StatsD.backend = ::StatsD::Instrument::Backends::LoggerBackend.new(Logger.new($stderr))
17
17
  elsif ENV['STATSD_ADDR'].present?
18
- statsd_impl = ENV['STATSD_IMPLEMENTATION'].empty? ? "datadog" : ENV['STATSD_IMPLEMENTATION']
18
+ statsd_impl = ENV['STATSD_IMPLEMENTATION'].present? ? ENV['STATSD_IMPLEMENTATION'] : "datadog"
19
19
  ::StatsD.backend = ::StatsD::Instrument::Backends::UDPBackend.new(ENV['STATSD_ADDR'], statsd_impl)
20
20
  else
21
21
  ::StatsD.backend = ::StatsD::Instrument::Backends::NullBackend.new
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
  module KubernetesDeploy
3
3
  class SyncMediator
4
+ LARGE_BATCH_THRESHOLD = Concurrency::MAX_THREADS * 3
5
+
4
6
  def initialize(namespace:, context:, logger:)
5
7
  @namespace = namespace
6
8
  @context = context
@@ -29,11 +31,14 @@ module KubernetesDeploy
29
31
 
30
32
  def sync(resources)
31
33
  clear_cache
32
- dependencies = resources.map(&:class).uniq.flat_map do |c|
33
- c::SYNC_DEPENDENCIES if c.const_defined?('SYNC_DEPENDENCIES')
34
+
35
+ if resources.count > LARGE_BATCH_THRESHOLD
36
+ dependencies = resources.map(&:class).uniq.flat_map do |c|
37
+ c::SYNC_DEPENDENCIES if c.const_defined?('SYNC_DEPENDENCIES')
38
+ end
39
+ kinds = (resources.map(&:kubectl_resource_type) + dependencies).compact.uniq
40
+ kinds.each { |kind| fetch_by_kind(kind) }
34
41
  end
35
- kinds = (resources.map(&:type) + dependencies).compact.uniq
36
- kinds.each { |kind| fetch_by_kind(kind) }
37
42
 
38
43
  KubernetesDeploy::Concurrency.split_across_threads(resources) do |r|
39
44
  r.sync(dup)
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module KubernetesDeploy
3
- VERSION = "0.20.4"
3
+ VERSION = "0.20.5"
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kubernetes-deploy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.20.4
4
+ version: 0.20.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Katrina Verey
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2018-07-18 00:00:00.000000000 Z
12
+ date: 2018-08-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -43,16 +43,16 @@ dependencies:
43
43
  name: googleauth
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - ">="
46
+ - - '='
47
47
  - !ruby/object:Gem::Version
48
- version: '0.5'
48
+ version: 0.6.2
49
49
  type: :runtime
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - ">="
53
+ - - '='
54
54
  - !ruby/object:Gem::Version
55
- version: '0.5'
55
+ version: 0.6.2
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: ejson
58
58
  requirement: !ruby/object:Gem::Requirement
@@ -227,10 +227,13 @@ files:
227
227
  - lib/kubernetes-deploy/kubernetes_resource/cloudsql.rb
228
228
  - lib/kubernetes-deploy/kubernetes_resource/config_map.rb
229
229
  - lib/kubernetes-deploy/kubernetes_resource/cron_job.rb
230
+ - lib/kubernetes-deploy/kubernetes_resource/custom_resource_definition.rb
230
231
  - lib/kubernetes-deploy/kubernetes_resource/daemon_set.rb
231
232
  - lib/kubernetes-deploy/kubernetes_resource/deployment.rb
232
233
  - lib/kubernetes-deploy/kubernetes_resource/elasticsearch.rb
234
+ - lib/kubernetes-deploy/kubernetes_resource/horizontal_pod_autoscaler.rb
233
235
  - lib/kubernetes-deploy/kubernetes_resource/ingress.rb
236
+ - lib/kubernetes-deploy/kubernetes_resource/job.rb
234
237
  - lib/kubernetes-deploy/kubernetes_resource/memcached.rb
235
238
  - lib/kubernetes-deploy/kubernetes_resource/persistent_volume_claim.rb
236
239
  - lib/kubernetes-deploy/kubernetes_resource/pod.rb
@@ -246,6 +249,7 @@ files:
246
249
  - lib/kubernetes-deploy/kubernetes_resource/statefulservice.rb
247
250
  - lib/kubernetes-deploy/kubernetes_resource/topic.rb
248
251
  - lib/kubernetes-deploy/renderer.rb
252
+ - lib/kubernetes-deploy/resource_discovery.rb
249
253
  - lib/kubernetes-deploy/resource_watcher.rb
250
254
  - lib/kubernetes-deploy/restart_task.rb
251
255
  - lib/kubernetes-deploy/runner_task.rb