mina-kubernetes 1.0.1 → 2.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +45 -0
- data/README.md +34 -13
- data/lib/mina/kubernetes.rb +30 -27
- data/lib/mina/kubernetes/version.rb +2 -2
- data/mina-kubernetes.gemspec +4 -4
- metadata +12 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7930f648e0b70eeb94a1413fee561b8edcdac3c28918bf003bee6c77749f9537
|
4
|
+
data.tar.gz: 5df185bd2d8cf21dbe0d520b799e8654d793400822a9d2522a760614dabf4e97
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 47f3c48b9157ca35688e8b45cee5e20c8c844c05b128e899f5cee1c15b9db60773a16f6b636fcf15c84bcbf27b78b4c66e6c4f5758397c693d277615f7b23abf
|
7
|
+
data.tar.gz: ce3221d0774d3d386c95af184798c9a98d67559f43481ea84b75a13119a6bb57fc35b5eafa9ca60a9a5d4e879805328b0dc5b47f162ff20d885d5e4aea95228c
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
## 2.4.0
|
2
|
+
|
3
|
+
*Enhancements*
|
4
|
+
|
5
|
+
- Use `secrets.ejson` if present
|
6
|
+
|
7
|
+
## 2.3.0
|
8
|
+
|
9
|
+
*Enhancements*
|
10
|
+
|
11
|
+
- Allow using a proxy to connect to a Kubernetes cluster
|
12
|
+
|
13
|
+
## 2.2.4
|
14
|
+
|
15
|
+
*Fixes*
|
16
|
+
|
17
|
+
- run custom command within given namespace instead of `default`
|
18
|
+
|
19
|
+
## 2.2.1 to 2.2.3
|
20
|
+
|
21
|
+
*Fixes*
|
22
|
+
|
23
|
+
- handle nil/undefined options passed to `krane`
|
24
|
+
|
25
|
+
## 2.2.0
|
26
|
+
|
27
|
+
*Enhancements*
|
28
|
+
|
29
|
+
- Using `krane` 1.0.0 (previously `kubernetes-deploy`)
|
30
|
+
- Allow passing of options to `krane`
|
31
|
+
|
32
|
+
## 2.1.0
|
33
|
+
|
34
|
+
Yanked release.
|
35
|
+
|
36
|
+
## 2.0.0
|
37
|
+
|
38
|
+
*Breaking*
|
39
|
+
|
40
|
+
- Using `namespace` config variable instead of `app_name`
|
41
|
+
- Using `kubernetes_context` config variable linking directly to a context set in $KUBE_CONFIG instead of creating a new context from separate `kubernetes_cluster` and `kubernetes_user` config variables
|
42
|
+
|
43
|
+
*Fixes*
|
44
|
+
|
45
|
+
- Not overriding $KUBE_CONFIG environment variable anymore
|
data/README.md
CHANGED
@@ -1,15 +1,19 @@
|
|
1
1
|
# mina-kubernetes
|
2
|
-
Plugin for the [mina](https://github.com/mina-deploy/mina) deployment tool to streamline deployment of resources to Kubernetes
|
2
|
+
Plugin for the [mina](https://github.com/mina-deploy/mina) deployment tool to streamline deployment of resources to Kubernetes clusters, using the [krane](https://github.com/Shopify/krane) gem and [mina-multistage](https://github.com/endoze/mina-multistage) plugin.
|
3
3
|
|
4
|
-
Requires local Docker and [kubectl](https://cloud.google.com/kubernetes-engine/docs/quickstart) with authentication set up to connect to the destination Kubernetes cluster.
|
4
|
+
Requires local Docker and [kubectl](https://cloud.google.com/kubernetes-engine/docs/quickstart) with local authentication set up to connect to the destination Kubernetes cluster as context in your local KUBE_CONFIG. See https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl#generate_kubeconfig_entry for example with Google Kubernetes Engine.
|
5
|
+
|
6
|
+
NB: `docker manifest inspect` is used to check whether the Docker image with requested tag is available. This requires experimental features to be enabled in your local Docker config by adding `"experimental": "enabled"` to `~/.docker/config.json`.
|
7
|
+
If the image repository is not public authentication will need to be set up for your local Docker, for instance see https://cloud.google.com/container-registry/docs/advanced-authentication#gcloud_as_a_docker_credential_helper for images hosted on the Google Cloud Registry
|
5
8
|
|
6
9
|
## Usage
|
7
10
|
|
8
|
-
Add `mina-kubernetes` to your local Gemfile.
|
11
|
+
Add `mina-kubernetes` to your local Gemfile.
|
9
12
|
|
10
13
|
Create a configuration file for mina in `config/deploy.rb` like the one below:
|
11
14
|
```ruby
|
12
15
|
require "mina/default"
|
16
|
+
require "mina/multistage"
|
13
17
|
require "mina/kubernetes"
|
14
18
|
|
15
19
|
task :deploy do
|
@@ -19,22 +23,39 @@ end
|
|
19
23
|
|
20
24
|
Add the following variables to your stage configuration i.e. `config/deploy/production.rb`:
|
21
25
|
```ruby
|
22
|
-
set :
|
23
|
-
set :
|
24
|
-
set :
|
25
|
-
set :kubernetes_user, "kubernetes_user_name"
|
26
|
+
set :namespace, "my_app"
|
27
|
+
set :image_repo, "gcr.io/project-id/myapp"
|
28
|
+
set :kubernetes_context, "kubernetes_context_name"
|
26
29
|
```
|
27
30
|
|
28
31
|
If `set :image_tag, "my_image_tag"` is also defined, it'll be used to deploy the image tagged with this tag on the repository. Otherwise you'll be prompted to pick a branch from current working Git repository and the image to deploy will be assumed to be tagged with the Git commit hash, i.e. `gcr.io/project-123456/my_app:abcd1234`.
|
29
32
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
+
Then add `*.yml.erb` Kubernetes resource definition files in the stage folder, i.e. `config/deploy/production/app.yml.erb`. Occurences of `<%= image_repo %>` and `<%= current_sha %>` in these files will be dynamically replaced on deploy by the image repository URL and the latest commit hash of the selected branch on its git origin.
|
34
|
+
|
35
|
+
You can also get the RAILS_MASTER_KEY for encrypted credentials deployed as a Kubernetes secrets by adding a secrets.yml.erb like below:
|
36
|
+
```yml
|
37
|
+
apiVersion: v1
|
38
|
+
kind: Secret
|
39
|
+
metadata:
|
40
|
+
name: secrets
|
41
|
+
data:
|
42
|
+
RAILS_MASTER_KEY: <%= Base64.strict_encode64(File.read("#{Dir.pwd}/config/credentials/production.key").strip) %>
|
33
43
|
```
|
34
44
|
|
35
|
-
|
45
|
+
When running `mina production deploy`, it'll prompt for a branch and check the image tagged with current commit hash from selected branch is available on the repository. Then the `krane` executable is called to fill in the variables in the resource templates and apply them all to the cluster under the given namespace (see https://github.com/Shopify/krane#deploy-walkthrough for more details)\
|
46
|
+
|
47
|
+
### EJSON Encrypted secrets
|
48
|
+
|
49
|
+
Krane supports generating Kubernetes secrets from an encrypted EJSON file: https://github.com/Shopify/krane#deploying-kubernetes-secrets-from-ejson. As per current Krane documentation "The ejson file must be included in the resources passed to --filenames it can not be read through stdin.", so
|
50
|
+
following convention-over-configuration principles `mina-kubernetes` checks for the presence of a file named `secrets.ejson` in the stage folder and uses it if available.
|
51
|
+
|
52
|
+
### Passing options to krane
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
invoke :"kubernetes:deploy", "--no-prune"
|
56
|
+
```
|
36
57
|
|
37
|
-
|
58
|
+
Refer to https://github.com/Shopify/krane#usage for a complete set of options
|
38
59
|
|
39
60
|
### Tasks available
|
40
61
|
|
@@ -52,4 +73,4 @@ Prompts for branch unless image tag is set, then spins up a temporary pod with t
|
|
52
73
|
|
53
74
|
#### `kubernetes:delete`
|
54
75
|
|
55
|
-
Confirms and delete all resources on cluster under namespace
|
76
|
+
Confirms and delete all resources on cluster under namespace.
|
data/lib/mina/kubernetes.rb
CHANGED
@@ -7,45 +7,37 @@ require "base64"
|
|
7
7
|
# required by mina
|
8
8
|
set :execution_mode, :pretty
|
9
9
|
|
10
|
-
# default for kubernetes-deploy
|
11
|
-
set :kube_config, "~/.kube/config"
|
12
|
-
|
13
10
|
namespace :kubernetes do
|
11
|
+
set :proxy, nil
|
14
12
|
|
15
|
-
|
16
|
-
set :context, "#{fetch(:namespace)}-#{fetch(:stage)}"
|
17
|
-
|
18
|
-
task :deploy do
|
13
|
+
task :deploy, [:options] do |task, args|
|
19
14
|
desc "Set image tag to be latest commit of prompted branch (unless provided) then applies resources to cluster"
|
20
15
|
set_tag_from_branch_commit unless fetch(:image_tag)
|
21
16
|
wait_until_image_ready(fetch(:image_tag))
|
22
17
|
create_namespace_on_cluster
|
23
|
-
|
24
|
-
apply_kubernetes_resources
|
18
|
+
apply_kubernetes_resources(args[:options])
|
25
19
|
end
|
26
20
|
|
27
21
|
task :bash do
|
28
22
|
desc "Spins up temporary pod with image and opens remote interactive bash"
|
29
23
|
set_tag_from_branch_commit unless fetch(:image_tag)
|
30
24
|
wait_until_image_ready(fetch(:image_tag))
|
31
|
-
|
25
|
+
run_command("bash")
|
32
26
|
end
|
33
27
|
|
34
28
|
task :command do
|
35
29
|
desc "Spins up temporary pod with image and runs given command in interactive shell, passing given environment variable"
|
36
30
|
set_tag_from_branch_commit unless fetch(:image_tag)
|
37
31
|
wait_until_image_ready(fetch(:image_tag))
|
38
|
-
|
32
|
+
run_command(fetch(:command), env_hash_arg)
|
39
33
|
end
|
40
34
|
|
41
35
|
task :delete do
|
42
36
|
desc "Delete all resources in namespace on cluster"
|
43
|
-
if TTY::Prompt.new.yes?("This will delete all resources in namespace #{fetch(:namespace)} on
|
37
|
+
if TTY::Prompt.new.yes?("This will delete all resources in namespace #{fetch(:namespace)} on context #{fetch(:kubernetes_context)}, are you sure?")
|
44
38
|
run :local do
|
45
39
|
comment "Deleting all resources in #{fetch(:namespace)}..."
|
46
|
-
command "kubectl delete namespace #{fetch(:namespace)} --
|
47
|
-
comment "Removing local config context..."
|
48
|
-
command "kubectl config unset contexts.#{fetch(:context)}"
|
40
|
+
command "kubectl delete namespace #{fetch(:namespace)} --context=#{fetch(:kubernetes_context)}"
|
49
41
|
end
|
50
42
|
end
|
51
43
|
end
|
@@ -54,6 +46,10 @@ end
|
|
54
46
|
|
55
47
|
private
|
56
48
|
|
49
|
+
def env_hash_arg
|
50
|
+
@env_hash_arg ||= (fetch(:env_hash).is_a?(String) ? JSON.parse(fetch(:env_hash)) : fetch(:env_hash)) || {}
|
51
|
+
end
|
52
|
+
|
57
53
|
def set_tag_from_branch_commit
|
58
54
|
run :local do
|
59
55
|
comment "Updating Git branches..."
|
@@ -66,14 +62,8 @@ end
|
|
66
62
|
def create_namespace_on_cluster
|
67
63
|
run :local do
|
68
64
|
comment "Create/update namespace on Kubernetes cluster..."
|
69
|
-
|
70
|
-
|
71
|
-
end
|
72
|
-
|
73
|
-
def set_local_config_context
|
74
|
-
run :local do
|
75
|
-
comment "Set up local Kubernetes config context..."
|
76
|
-
command "kubectl config set-context #{fetch(:context)} --namespace=#{fetch(:namespace)} --cluster=#{fetch(:kubernetes_cluster)} --user=#{fetch(:kubernetes_user)}"
|
65
|
+
proxy_env = "HTTPS_PROXY=#{fetch(:proxy)}" if fetch(:proxy)
|
66
|
+
command "kubectl create namespace #{fetch(:namespace)} --dry-run -o yaml | #{proxy_env} kubectl apply -f - --context=#{fetch(:kubernetes_context)}"
|
77
67
|
end
|
78
68
|
end
|
79
69
|
|
@@ -93,16 +83,29 @@ def image_available?(commit)
|
|
93
83
|
system("docker manifest inspect #{fetch(:image_repo)}:#{commit} > /dev/null") == true
|
94
84
|
end
|
95
85
|
|
96
|
-
def
|
86
|
+
def run_command(command, env_hash = {})
|
97
87
|
env = env_hash.collect{|k,v| "--env #{k}=#{v}" }.join(" ")
|
98
88
|
label = command.downcase.gsub(" ", "-").gsub(":", "-")
|
89
|
+
proxy_env = "HTTPS_PROXY=#{fetch(:proxy)}" if fetch(:proxy)
|
90
|
+
|
99
91
|
# using system instead of mina's command so tty opens successfully
|
100
|
-
system "kubectl run #{label}-#{SecureRandom.hex(4)} --rm -i --tty --restart=Never --context=#{fetch(:
|
92
|
+
system "#{proxy_env} kubectl run #{label}-#{SecureRandom.hex(4)} --rm -i --tty --restart=Never --context=#{fetch(:kubernetes_context)} --namespace=#{fetch(:namespace)} --image #{fetch(:image_repo)}:#{fetch(:image_tag)} #{env} -- #{command}"
|
101
93
|
end
|
102
94
|
|
103
|
-
def apply_kubernetes_resources
|
95
|
+
def apply_kubernetes_resources(options)
|
104
96
|
run :local do
|
105
97
|
comment "Apply all Kubernetes resources..."
|
106
|
-
|
98
|
+
|
99
|
+
proxy_env = "HTTPS_PROXY=#{fetch(:proxy)}" if fetch(:proxy)
|
100
|
+
filepaths = options&.[](:filepaths) || "config/deploy/#{fetch(:stage)}"
|
101
|
+
|
102
|
+
render_cmd = "#{proxy_env} krane render --bindings=image_repo=#{fetch(:image_repo)},image_tag=#{fetch(:image_tag)},namespace=#{fetch(:namespace)} --current_sha #{fetch(:image_tag)} -f #{filepaths}"
|
103
|
+
deploy_cmd = "#{proxy_env} krane deploy #{fetch(:namespace)} #{fetch(:kubernetes_context)} --stdin "
|
104
|
+
deploy_cmd += options[:deployment_options] if options&.[](:deployment_options)
|
105
|
+
|
106
|
+
ejson_secrets_path = "#{filepaths}/secrets.ejson"
|
107
|
+
deploy_cmd += " --filenames #{ejson_secrets_path}" if File.exists?(ejson_secrets_path)
|
108
|
+
|
109
|
+
command "#{render_cmd} | #{deploy_cmd}"
|
107
110
|
end
|
108
111
|
end
|
data/mina-kubernetes.gemspec
CHANGED
@@ -20,11 +20,11 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.require_paths = ["lib"]
|
21
21
|
|
22
22
|
spec.add_development_dependency 'bundler', '~> 1.11'
|
23
|
-
spec.add_development_dependency 'rake', '
|
24
|
-
|
23
|
+
spec.add_development_dependency 'rake', '>= 12.3.3'
|
24
|
+
|
25
25
|
spec.add_runtime_dependency 'mina', '~> 1.0'
|
26
26
|
spec.add_runtime_dependency 'mina-multistage', '~> 1.0'
|
27
|
-
spec.add_runtime_dependency '
|
27
|
+
spec.add_runtime_dependency 'krane', '~> 1.0'
|
28
28
|
spec.add_runtime_dependency 'tty-prompt'
|
29
29
|
spec.add_runtime_dependency 'tty-spinner'
|
30
|
-
end
|
30
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mina-kubernetes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Antoine Sabourin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-08-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -28,16 +28,16 @@ dependencies:
|
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 12.3.3
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 12.3.3
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: mina
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,19 +67,19 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '1.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: krane
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
75
|
+
version: '1.0'
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
82
|
+
version: '1.0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: tty-prompt
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -116,6 +116,7 @@ extensions: []
|
|
116
116
|
extra_rdoc_files: []
|
117
117
|
files:
|
118
118
|
- ".gitignore"
|
119
|
+
- CHANGELOG.md
|
119
120
|
- README.md
|
120
121
|
- Rakefile
|
121
122
|
- lib/mina/kubernetes.rb
|