kubernetes_helper 0.2.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0ca97bfb3e3dcb157198cf9f76092c740ecb3674bb76cdf7c91f6da7755d11fe
4
- data.tar.gz: 581dfe0dbf80c2a7d0115430d6045edfca0d532f10d89ca5db7bcbc70beac706
3
+ metadata.gz: c24816e7925c930deb198ab8b10b9f820ad4f5f23b4b06ee5e65d8d1d0e82208
4
+ data.tar.gz: '06395250bc71d298cfcd7d56409fe98e1a4ecd614ee79e24d7dc9cdbf01d1d1b'
5
5
  SHA512:
6
- metadata.gz: 1642945b8ca5ea192812c686ef4afad9b285deae77ebbdd4734af1b3a877ad0db819c2e306f738303f84a361cbc3d697f02cf711e5ba35ce1a0e0f1148c12878
7
- data.tar.gz: 0f23916d6007d02e858e2db22f563724bf422f59a47807eec956349c60f5141795c7e8c392d4d0c3c2c7ff67ca8f430033120f4dac72a372763c65c9f93f3d62
6
+ metadata.gz: 0a59e813c49a519036e6532537a9d194626395fdf0e5cee6c751f32cfb3e4c5fdff5454ae67dfe0ce500ec2f2c3317915aec8ed9c2f85b175a101e58b2d0d9ad
7
+ data.tar.gz: 915c6cebb2e9f5829274d564c449d5c57ae3aa06ef524002c41e48920379d4126e6da444a9a08dc69df4492ec541c825484d2d579ef39e4e01e325e9dc627417
data/README.md CHANGED
@@ -22,16 +22,16 @@ Or install it yourself as:
22
22
 
23
23
  ## Usage
24
24
 
25
- TODO: Write usage instructions here
26
-
27
- ## Development
28
-
29
-
30
25
  ## TODO
31
26
  - Documentation
32
- - Tests
33
- - Rake generate
27
+ - Include conditional blocks
28
+ - Include hardcoded env values
29
+ - Tasks
30
+ - Add docs to include partials using `include_template 'sample.yml.erb'`
34
31
  - Rake verify files
32
+ - Add one_step_configuration.sh
33
+ - Fix if/end_if for blocks
34
+ - Ability to copy specific template
35
35
 
36
36
  ## Contributing
37
37
 
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ require 'rspec/core/rake_task'
5
5
 
6
6
  RSpec::Core::RakeTask.new(:spec)
7
7
 
8
- task :default => :spec
8
+ task default: :spec
9
9
 
10
10
  path = File.expand_path(__dir__)
11
11
  Dir.glob("#{path}/lib/tasks/**/*.rake").each { |f| import f }
@@ -4,34 +4,30 @@ require 'kubernetes_helper'
4
4
 
5
5
  case ARGV[0]
6
6
  # Parse variables and run provided command.
7
- # Sample: DEPLOY_ENV=beta rake kubernetes_helper:run_command "gcloud compute addresses create \#{ingress.ip_name} --global"'
7
+ # Sample: DEPLOY_ENV=beta rake kubernetes_helper:run_command
8
+ # "gcloud compute addresses create \#{ingress.ip_name} --global"'
8
9
  when 'run_command'
9
10
  KubernetesHelper::Core.new(ENV['DEPLOY_ENV']).run_command(ARGV[1])
10
-
11
11
  # Run the deployment script.
12
- # Sample: DEPLOY_ENV=beta rake kubernetes_helper:run_deployment "cd_gcloud.sh"
12
+ # Sample: DEPLOY_ENV=beta kubernetes_helper run_deployment "cd_gcloud.sh"
13
13
  when 'run_deployment'
14
- script_path = KubernetesHelper.settings_path(ARGV[1])
15
- KubernetesHelper::Core.new(ENV['DEPLOY_ENV']).run_cd_script(script_path)
16
-
14
+ script_path = KubernetesHelper.settings_path(ARGV[1], use_template: true)
15
+ KubernetesHelper::Core.new(ENV['DEPLOY_ENV']).run_script(script_path)
17
16
  # Parses kubernetes yml files (supporting multiple documents, Config variables replacement, include secrets).
18
- # Sample: DEPLOY_ENV=beta rake kubernetes_helper:run_deployment "deployment.yml" "kubectl create"
17
+ # Sample: DEPLOY_ENV=beta kubernetes_helper run_deployment "deployment.yml" "kubectl create"
19
18
  when 'run_yml'
20
19
  output_path = KubernetesHelper.settings_path('tmp_result.yml')
21
20
  KubernetesHelper::Core
22
21
  .new(ENV['DEPLOY_ENV'])
23
- .parse_yml_file(KubernetesHelper.settings_path(ARGV[1]), output_path)
22
+ .parse_yml_file(KubernetesHelper.settings_path(ARGV[1], use_template: true), output_path)
24
23
  KubernetesHelper.run_cmd("#{ARGV[2]} -f #{output_path}")
25
-
26
24
  # Generate template files
27
- when 'generate'
28
- # TODO: ...
29
-
30
- # Verify yml files for possible errors.
31
- # Sample: DEPLOY_ENV=beta rake kubernetes_helper:verify_yml_files
25
+ when 'generate_templates' # Sample: kubernetes_helper generate basic
26
+ mode = ARGV[1] || 'basic'
27
+ KubernetesHelper.copy_templates(mode)
32
28
  when 'verify_yml'
33
- # TODO: ...
34
-
29
+ # Verify yml files for possible errors.
30
+ # TODO: ...
35
31
  else
36
32
  puts 'Invalid command'
37
33
  end
@@ -14,15 +14,18 @@ module KubernetesHelper
14
14
 
15
15
  # @param env_name (String)
16
16
  # @return [Hash]
17
- def self.load_settings(env_name)
17
+ def self.load_settings
18
18
  config_file = File.join(settings_path, 'settings.rb')
19
19
  load config_file
20
- settings[env_name.to_sym]
20
+ settings
21
21
  end
22
22
 
23
- def self.settings_path(file_name = nil)
23
+ def self.settings_path(file_name = nil, use_template: false)
24
24
  path = File.join(Dir.pwd, FOLDER_NAME)
25
- path = File.join(path, file_name) if file_name
25
+ if file_name
26
+ app_path = File.join(path, file_name)
27
+ path = use_template && !File.exist?(app_path) ? templates_path(file_name) : app_path
28
+ end
26
29
  path
27
30
  end
28
31
 
@@ -30,4 +33,20 @@ module KubernetesHelper
30
33
  res = Kernel.system cmd
31
34
  Kernel.abort("::::::::CD: failed running command: #{title || cmd} ==> #{caller}") if res != true
32
35
  end
36
+
37
+ def self.templates_path(file_name = nil)
38
+ path = File.join(File.expand_path(__dir__), 'templates')
39
+ file_name ? File.join(path, file_name) : path
40
+ end
41
+
42
+ # @param mode (basic, advanced)
43
+ def self.copy_templates(mode)
44
+ FileUtils.mkdir(settings_path) unless Dir.exist?(settings_path)
45
+ files = %w[README.md secrets.yml settings.rb]
46
+ files += %w[deployment.yml cd.sh ingress.yml service.yml] if mode == 'advanced'
47
+ files.each do |name|
48
+ path = settings_path(name)
49
+ FileUtils.cp(templates_path(name), path) unless File.exist?(path)
50
+ end
51
+ end
33
52
  end
@@ -2,20 +2,33 @@
2
2
 
3
3
  require 'yaml'
4
4
  require 'json'
5
+ require 'erb'
6
+ # require 'byebug' rescue nil
7
+
5
8
  module KubernetesHelper
9
+ class ErbBinding < OpenStruct
10
+ def get_binding # rubocop:disable Naming/AccessorMethodName:
11
+ binding
12
+ end
13
+
14
+ def include_template(name)
15
+ render_template.call(name)
16
+ end
17
+ end
18
+
6
19
  class Core
7
20
  # @return [Hash]
8
21
  attr_accessor :config_values
9
22
 
10
- # @param env_name (String)
11
- def initialize(env_name)
12
- env_name = env_name.to_s.length > 1 ? env_name : 'beta'
13
- @config_values = KubernetesHelper.load_settings(env_name)
23
+ # @param _env_name (String)
24
+ def initialize(_env_name)
25
+ @config_values = KubernetesHelper.load_settings
14
26
  end
15
27
 
16
28
  def parse_yml_file(file_path, output_path)
17
29
  parsed_content = replace_config_variables(File.read(file_path))
18
- old_yaml = YAML.load_stream(parsed_content) # rubocop:disable Security/YAMLLoad
30
+ File.open(output_path, 'w+') { |f| f << parsed_content } # save as draft to be reviewed if failed
31
+ old_yaml = YAML.load_stream(parsed_content)
19
32
  json_data = old_yaml.to_json # fix to skip anchors
20
33
  yml_data = JSON.parse(json_data)
21
34
  export_documents(yml_data, output_path)
@@ -24,9 +37,13 @@ module KubernetesHelper
24
37
  # @param text (String)
25
38
  # Sample: replicas: '#{deployment.replicas}'
26
39
  def replace_config_variables(text)
27
- text.gsub(/(\#{([^}])*})/) do |code|
28
- find_setting_value(code.gsub('#{', '').gsub('}', ''))
29
- end
40
+ values = config_values.map do |key, value| # rubocop:disable Style/HashTransformValues
41
+ [key, value.is_a?(Hash) ? OpenStruct.new(value) : value]
42
+ end.to_h
43
+ values[:render_template] = method(:render_template)
44
+ bind = ErbBinding.new(values).get_binding
45
+ template = ERB.new(text)
46
+ template.result(bind)
30
47
  end
31
48
 
32
49
  def run_command(command)
@@ -34,13 +51,13 @@ module KubernetesHelper
34
51
  KubernetesHelper.run_cmd(command)
35
52
  end
36
53
 
37
- def run_cd_script(script_path)
54
+ def run_script(script_path)
38
55
  content = replace_config_variables(File.read(script_path))
39
- tmp_file = KubernetesHelper.settings_path('tmp_cd.sh')
56
+ tmp_file = KubernetesHelper.settings_path('tmp_script.sh')
40
57
  File.write(tmp_file, content)
41
58
  KubernetesHelper.run_cmd("chmod +x #{tmp_file}")
42
59
  KubernetesHelper.run_cmd(tmp_file)
43
- File.delete(tmp_file)
60
+ # File.delete(tmp_file) # keep tmp script for analysis purpose
44
61
  end
45
62
 
46
63
  private
@@ -58,20 +75,26 @@ module KubernetesHelper
58
75
  end
59
76
  end
60
77
 
61
- # @param setting_key (String)
62
- # sample: deployment.replicas
63
- def find_setting_value(setting_key)
64
- parent = @config_values
65
- setting_key.split('.').each do |key|
66
- parent = parent[key.to_sym]
78
+ def render_template(template_name)
79
+ path = KubernetesHelper.settings_path(template_name, use_template: true)
80
+ text = "\n#{File.read(path)}"
81
+ replace_config_variables(text)
82
+ end
83
+
84
+ def static_env_vars
85
+ (config_values.dig(:deployment, :env_vars) || {}).map do |key, value|
86
+ {
87
+ 'name' => key.to_s,
88
+ 'value' => value
89
+ }
67
90
  end
68
- parent
69
91
  end
70
92
 
71
93
  # parse secrets auto importer
72
94
  def parse_import_secrets(document)
73
95
  containers = document.dig('spec', 'template', 'spec', 'containers') || []
74
96
  containers.each do |container|
97
+ container['env'] = (container['env'] || []) + static_env_vars
75
98
  if container['import_secrets']
76
99
  container['env'] = container['env'] + import_secrets(*container['import_secrets'])
77
100
  container.delete('import_secrets')
@@ -80,13 +103,21 @@ module KubernetesHelper
80
103
  end
81
104
 
82
105
  def export_documents(yml_data, file_path)
83
- documents = yml_data.delete('documents') || Array(yml_data)
84
106
  File.open(file_path, 'w+') do |f|
85
- documents.each do |document|
107
+ parse_documents(yml_data).each do |document|
86
108
  parse_import_secrets(document)
87
- f << document.to_yaml
109
+ f.write(document.to_yaml)
88
110
  end
89
111
  end
90
112
  end
113
+
114
+ # @return [Array<Hash>]
115
+ def parse_documents(yml_data)
116
+ documents = []
117
+ Array(yml_data).each do |document|
118
+ document['documents'] ? documents.push(*document['documents']) : documents.push(document)
119
+ end
120
+ documents
121
+ end
91
122
  end
92
123
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KubernetesHelper
2
- VERSION = "0.2.1"
4
+ VERSION = '0.3.3'
3
5
  end
@@ -0,0 +1,97 @@
1
+ # Kubernetes app configuration
2
+
3
+ ## Configure a new application environment
4
+ - Create the project on Gcloud
5
+ - Set the project where to work on
6
+ `gcloud config set project my-project`
7
+
8
+ - Create the cluster (Only if not exist)
9
+ `gcloud container clusters create my-cluster`
10
+ `# gcloud container clusters list --region europe-west4-a # to list clusters`
11
+
12
+ - Use the cluster/project as default
13
+ `gcloud container clusters get-credentials my-cluster --zone europe-west4-a`
14
+
15
+ - Install helper for the next commands
16
+ `gem install kubernetes_helper`
17
+
18
+ - Verify or update k8s settings in .kubernetes/settings.rb
19
+
20
+ - Register shared cloudsql proxy configuration (only if not exists)
21
+ ```bash
22
+ DEPLOY_ENV=beta kubernetes_helper run_command "kubectl create secret generic <%=deployment.cloud_secret_name%> --from-file=credentials.json=<path-to-downloaded/credentials.json>"
23
+ ```
24
+
25
+ - Register manually env vars (values must be encrypted using base64)
26
+ Open and register secret values in `.kubernetes/secrets.yml`
27
+ Note: Enter base64 encoded values
28
+ ```bash
29
+ DEPLOY_ENV=beta kubernetes_helper run_yml 'secrets.yml' 'kubectl create'
30
+ # kubectl get secrets # to list all secrets registered
31
+ ```
32
+
33
+ - Create deployment to run application
34
+ ```bash
35
+ DEPLOY_ENV=beta kubernetes_helper run_yml 'deployment.yml' 'kubectl create'
36
+ # kubectl get deployment # to list deployments
37
+ ```
38
+
39
+ - Create service to connect pods and ingress
40
+ ```bash
41
+ DEPLOY_ENV=beta kubernetes_helper run_yml 'service.yml' 'kubectl create'
42
+ # kubectl get services # to list all registered services
43
+ ```
44
+
45
+ - Create the public ip address (only if static ip is required)
46
+ ```bash
47
+ DEPLOY_ENV=beta kubernetes_helper run_command "gcloud compute addresses create <%=ingress.ip_name%> --global"
48
+ # gcloud compute addresses list # to list static ips generated
49
+ # Copy new external ip generated by the previous command and point your domain to it
50
+ ```
51
+
52
+ - Register ingress to receive external http calls (includes ssl certificates if defined)
53
+ ```bash
54
+ DEPLOY_ENV=beta kubernetes_helper run_yml 'ingress.yml' 'kubectl create'
55
+ # kubectl get ingress # to list all registered ingresses
56
+ # kubectl get ManagedCertificate # to list all certificates
57
+ # Domain and ssl propagation can take more than 10 minutes
58
+ # You can start accessing to the app using the generated ip address
59
+ # `kubectl get ManagedCertificate` # to see the status of ssl provisionning
60
+ ```
61
+
62
+ ## Apply any k8s setting changes
63
+ - Secrets
64
+ Open kubernetes secrets and add/edit/remove values and then save it
65
+ `kubectl edit secret ...`
66
+ Once secrets were updated, then restart all related pods, see: https://medium.com/devops-dudes/how-to-propagate-a-change-in-kubernetes-secrets-by-restarting-dependent-pods-b71231827656
67
+
68
+ - Other settings
69
+ ```bash
70
+ DEPLOY_ENV=beta kubernetes_helper run_yml 'deployment.yml' 'kubectl apply'
71
+ ```
72
+
73
+ ## Configure continuous deployment for github actions
74
+ * Go to github repository settings
75
+ * Register a new secret variable with content downloaded from https://console.cloud.google.com/iam-admin/serviceaccounts
76
+ (Make sure to attach a "Editor", "Storage Admin" and "Kubernetes engine cluster admin" role to the service account)
77
+ ```bash
78
+ beta: BETA_CLOUD_TOKEN=<secret content here>
79
+ production: PROD_CLOUD_TOKEN=<secret content here>
80
+ ```
81
+
82
+ * Add action to run deployment:
83
+ ```bash
84
+ env:
85
+ KB_AUTH_TOKEN: secrets.BETA_CLOUD_TOKEN
86
+ run: DEPLOY_ENV=beta kubernetes_helper run_deployment 'cd.sh'
87
+ ```
88
+
89
+ * Sample:
90
+ ```yml
91
+ - run: sudo gem install kubernetes_helper
92
+ - name: Staging deployment
93
+ env: # Env variable saved in github that contains gcloud credential (json format)
94
+ KB_AUTH_TOKEN: ${{ secrets.BETA_GOOGLE_AUTH }}
95
+ run: DEPLOY_ENV=beta kubernetes_helper run_deployment 'cd.sh'
96
+ if: ${{ !contains(fromJson('["main", "master"]'), env.DEPLOY_BRANCH) }}
97
+ ```
@@ -0,0 +1,12 @@
1
+ - apiVersion: autoscaling/v1
2
+ kind: HorizontalPodAutoscaler
3
+ metadata:
4
+ name: <%= "#{deployment.name}-replicas" %>
5
+ spec:
6
+ scaleTargetRef:
7
+ apiVersion: apps/v1
8
+ kind: Deployment
9
+ name: <%= deployment.name %>
10
+ minReplicas: <%= deployment.replicas_range[0] %>
11
+ maxReplicas: <%= deployment.replicas_range[1] %>
12
+ targetCPUUtilizationPercentage: 50
@@ -0,0 +1,18 @@
1
+ ports:
2
+ - containerPort: &sidekiq_alive_port 7433
3
+ livenessProbe: &sidekiq_liveness
4
+ httpGet:
5
+ path: /
6
+ port: *sidekiq_alive_port
7
+ initialDelaySeconds: 80 # app specific. Time your sidekiq takes to start processing.
8
+ timeoutSeconds: 5 # can be much less
9
+ readinessProbe: *sidekiq_liveness
10
+ lifecycle:
11
+ preStop:
12
+ exec:
13
+ # SIGTERM triggers a quick exit; gracefully terminate instead
14
+ command: [
15
+ "/bin/bash",
16
+ "-c",
17
+ "SIDEKIQ_PID=$(ps aux | grep sidekiq | grep busy | awk '{ print $2 }') && kill -SIGTERM $SIDEKIQ_PID",
18
+ ]
@@ -0,0 +1,49 @@
1
+ #!/bin/bash
2
+ set -e
3
+ # expected ENV VAR "KB_AUTH_TOKEN"
4
+
5
+ SCRIPT_DIR=`dirname "$(realpath -s "$0")"` # app_dir/.kubernetes/
6
+ cd "$SCRIPT_DIR/../" # project directory
7
+
8
+ DEPLOYMENTS="<%=[deployment.job_name, deployment.name].join(',')%>"
9
+ IMAGE_NAME="<%=continuous_deployment.image_name%>"
10
+ CLUSTER_NAME="<%=continuous_deployment.cluster_name%>"
11
+ PROJECT_NAME="<%=continuous_deployment.project_name%>"
12
+ CLUSTER_REGION="<%=continuous_deployment.cluster_region%>"
13
+ DOCKER_BUILD_CMD="<%=continuous_deployment.docker_build_cmd || 'build -f Dockerfile'%>"
14
+
15
+ CI_COMMIT_SHA=$(git rev-parse --verify HEAD)
16
+ DEPLOY_NAME="${IMAGE_NAME}:${CI_COMMIT_SHA}"
17
+ LATEST_NAME="${IMAGE_NAME}:latest"
18
+ AUTH_PATH="$SCRIPT_DIR/k8s-auth-token.json"
19
+
20
+ rm -f -- $AUTH_PATH
21
+ echo $KB_AUTH_TOKEN >> $AUTH_PATH
22
+
23
+ ## ***** GOOGLE CONNECTOR
24
+ # Download and install Google Cloud SDK
25
+ if [ -z "$(which gcloud)" ]; then
26
+ export CLOUDSDK_CORE_DISABLE_PROMPTS=1; curl https://sdk.cloud.google.com | bash && source /home/runner/google-cloud-sdk/path.bash.inc && gcloud --quiet components update kubectl
27
+ fi
28
+
29
+ # Connect to cluster
30
+ gcloud auth activate-service-account --key-file $AUTH_PATH --project $PROJECT_NAME
31
+ gcloud docker --authorize-only --project $PROJECT_NAME
32
+ gcloud container clusters get-credentials $CLUSTER_NAME --region $CLUSTER_REGION
33
+ ## ***** END GOOGLE CONNECTOR
34
+
35
+
36
+ ## Build and push containers
37
+ docker $DOCKER_BUILD_CMD -t $DEPLOY_NAME .
38
+ docker tag $DEPLOY_NAME $LATEST_NAME
39
+ docker push $DEPLOY_NAME
40
+ docker push $LATEST_NAME
41
+
42
+ ## Apply deployments
43
+ IFS=',' read -r -a deployments <<< "$DEPLOYMENTS"
44
+ for deployment in "${deployments[@]}"; do
45
+ [ -z "$deployment" ] && continue # if empty value
46
+
47
+ kubectl set image deployment/$deployment $deployment=$DEPLOY_NAME
48
+ [ "$deployment" = "${deployments[0]}" ] && kubectl rollout status deployment/$deployment || true
49
+ done
@@ -0,0 +1,125 @@
1
+ documents:
2
+ - apiVersion: apps/v1
3
+ kind: Deployment
4
+ metadata:
5
+ name: &app_name <%=deployment.name%>
6
+ spec: &default_spec
7
+ replicas: <%=deployment.replicas%>
8
+ selector:
9
+ matchLabels:
10
+ name: *app_name
11
+ strategy:
12
+ type: RollingUpdate
13
+ rollingUpdate:
14
+ maxSurge: 1
15
+ maxUnavailable: 1
16
+ minReadySeconds: 5
17
+ template:
18
+ metadata:
19
+ labels:
20
+ name: *app_name
21
+ spec: &template_spec
22
+ containers:
23
+ - &app_container
24
+ image: '<%=continuous_deployment.image_name%>:latest'
25
+ <% if deployment.command %>
26
+ command: ["/bin/bash", "-c", "<%= deployment.command %>"]
27
+ <% end %>
28
+ name: *app_name
29
+ import_secrets: ['secrets.yml', '<%=secrets.name%>']
30
+ ports:
31
+ - containerPort: &port 3000
32
+ name: '<%=service.backend_port_name%>'
33
+
34
+ <% if deployment.liveness_path %>
35
+ livenessProbe: &liveness_probe
36
+ httpGet:
37
+ path: <%=deployment.liveness_path%>
38
+ port: *port
39
+ initialDelaySeconds: 50
40
+ timeoutSeconds: 3
41
+ periodSeconds: 15
42
+ readinessProbe: *liveness_probe
43
+ <% end %>
44
+
45
+ volumeMounts:
46
+ - &log_volume
47
+ name: applog
48
+ mountPath: /app/log
49
+ - &cloud_credentials_volume
50
+ name: gcloud-creds
51
+ mountPath: /secrets/gcloud
52
+ readOnly: true
53
+
54
+ - &cloudsql_container
55
+ image: gcr.io/cloudsql-docker/gce-proxy:1.09 # Cloud sql proxy
56
+ name: cloudsql-proxy
57
+ command: ["/cloud_sql_proxy", "--dir=/cloudsql",
58
+ "-instances=<%=deployment.cloud_sql_instance%>",
59
+ "-credential_file=/secrets/gcloud/credentials.json"]
60
+ volumeMounts:
61
+ - *cloud_credentials_volume
62
+
63
+ - &logs_container # print to stdout all log files
64
+ name: print-logs
65
+ image: busybox
66
+ command: [/bin/sh, -c, 'until find log/*.log; do sleep 1; done; tail -n+1 -f log/*.log']
67
+ volumeMounts:
68
+ - *log_volume
69
+
70
+ terminationGracePeriodSeconds: 120
71
+ volumes:
72
+ - name: gcloud-creds
73
+ secret:
74
+ secretName: '<%=deployment.cloud_secret_name%>'
75
+ - name: applog
76
+ emptyDir: {}
77
+
78
+ <% if deployment.job_name %>
79
+ - apiVersion: apps/v1
80
+ kind: Deployment
81
+ metadata:
82
+ name: &job_app_name <%=deployment.job_name%>
83
+ spec:
84
+ <<: *default_spec
85
+ replicas: 1
86
+ selector:
87
+ matchLabels:
88
+ name: *job_app_name
89
+ template:
90
+ metadata:
91
+ labels:
92
+ name: *job_app_name
93
+ spec:
94
+ <<: *template_spec
95
+ containers:
96
+ - <<: *app_container
97
+ name: *job_app_name
98
+ <% if deployment.job_command %>
99
+ command: [ "/bin/bash", "-c", "<%= deployment.job_command %>" ]
100
+ <% end %>
101
+
102
+ <% if deployment.job_sidekiq_alive_gem %>
103
+ <%= include_template "_sidekiq_alive_gem.yml.erb" %>
104
+ <% else %>
105
+ ports: [ ]
106
+ <% if (deployment.job_services || []).any? %>
107
+ livenessProbe: &liveness_probe
108
+ exec:
109
+ command: [ /bin/sh, -c,
110
+ 'if [ $(ps -ef | grep "<%= deployment.job_services.join("\|") %>" | grep -v "grep" | wc -l) -lt <%= deployment.job_services.count %> ]; then
111
+ echo "Some required services are not running"; exit 1;
112
+ fi' ]
113
+ initialDelaySeconds: 120
114
+ periodSeconds: 30
115
+ readinessProbe: *liveness_probe
116
+ <% end %>
117
+ <% end %>
118
+
119
+ - *cloudsql_container
120
+ - <<: *logs_container
121
+ <% end %>
122
+
123
+ <% if deployment.replicas_range %>
124
+ <%= include_template "_replicas.yml.erb" %>
125
+ <% end %>
@@ -0,0 +1,33 @@
1
+ <% if ingress.domain_name %>
2
+ apiVersion: networking.gke.io/v1beta1
3
+ kind: ManagedCertificate
4
+ metadata:
5
+ name: '<%=ingress.certificate_name%>'
6
+ spec:
7
+ domains: # does not support for willcard domains
8
+ - '<%=ingress.domain_name%>'
9
+ <% end %>
10
+
11
+ ---
12
+
13
+ apiVersion: extensions/v1beta1
14
+ kind: Ingress
15
+ metadata:
16
+ name: '<%=ingress.name%>'
17
+ annotations:
18
+ kubernetes.io/ingress.class: "gce"
19
+ kubernetes.io/ingress.allow-http: "true"
20
+ ingress.kubernetes.io/ssl-redirect: "true"
21
+
22
+ <% if ingress.ip_name %>
23
+ kubernetes.io/ingress.global-static-ip-name: "<%=ingress.ip_name%>"
24
+ <% end %>
25
+
26
+ <% if ingress.domain_name %>
27
+ networking.gke.io/managed-certificates: '<%=ingress.certificate_name%>'
28
+ <% end %>
29
+
30
+ spec:
31
+ backend:
32
+ serviceName: '<%=service.name%>'
33
+ servicePort: '<%=service.port_name%>'
@@ -0,0 +1,11 @@
1
+ # Every Value has to be base64 encoded
2
+ # IMPORTANT: For security reason, never ever commit secret values, only keys
3
+
4
+ apiVersion: v1
5
+ kind: Secret
6
+ metadata:
7
+ name: '<%=secrets.name%>'
8
+ type: Opaque
9
+ data:
10
+ my_key1: "based_64_value_encoded"
11
+ my_key2: "based_64_value_encoded"
@@ -0,0 +1,27 @@
1
+ ---
2
+ # used to increase request timeout
3
+ apiVersion: cloud.google.com/v1beta1
4
+ kind: BackendConfig
5
+ metadata:
6
+ name: '<%=service.config_name%>'
7
+ spec:
8
+ timeoutSec: 1800
9
+
10
+ ---
11
+
12
+
13
+ kind: Service
14
+ apiVersion: v1
15
+ metadata:
16
+ name: '<%=service.name%>'
17
+ annotations:
18
+ beta.cloud.google.com/backend-config: '{"ports": {"80":"<%=service.config_name%>"}}'
19
+ spec:
20
+ selector:
21
+ name: '<%=deployment.name%>'
22
+ type: NodePort
23
+ ports:
24
+ - port: 80
25
+ protocol: TCP
26
+ name: '<%=service.port_name%>'
27
+ targetPort: '<%=service.backend_port_name%>'
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ is_production = ENV['DEPLOY_ENV'] == 'production'
4
+ app_name = is_production ? 'my_app' : 'my_beta_app'
5
+ settings = {
6
+ deployment: {
7
+ name: app_name,
8
+ replicas: is_production ? 2 : 1,
9
+ cloud_secret_name: "#{is_production ? 'production' : 'beta'}-cloud-secret",
10
+ cloud_sql_instance: 'xxx:xxx:xxx=tcp:5432', # 5432 => postgres, 3306 => mysql
11
+ env_vars: {}, # Sample: { 'CUSTOM_VAR' => 'value' }
12
+ # command: '', # custom container command (default empty to be managed by Dockerfile)
13
+ # liveness_path: '/check_liveness', # nil if not exist
14
+ # job_name: "#{app_name}-job", # enable if there is any background service
15
+ # job_command: 'bundle exec sidekiq -C config/sidekiq.yml',
16
+ # job_services: ['sidekiq', 'cron'] # list of linux services needed.
17
+ },
18
+ ingress: {
19
+ name: "#{app_name}-ingress",
20
+ ip_name: "#{app_name}-static-ip", # nil if static ip is not necessary
21
+ certificate_name: "#{app_name}-lets-encrypt", # nil if ssl is not required
22
+ domain_name: is_production ? 'myapp.com' : 'beta.myapp.com' # nil if domain is not required
23
+ },
24
+ continuous_deployment: {
25
+ image_name: "gcr.io/my-account/#{app_name}",
26
+ project_name: 'my-project-name',
27
+ cluster_name: 'my-cluster-name',
28
+ cluster_region: 'europe-west4-a',
29
+ docker_build_cmd: 'build -f Dockerfile'
30
+ },
31
+ secrets: {
32
+ name: "#{app_name}-secrets"
33
+ },
34
+ service: {
35
+ name: app_name,
36
+ port_name: 'http-port', # max 15 characters
37
+ backend_port_name: 'b-port', # max 15 characters
38
+ config_name: "#{app_name}-backend-config"
39
+ }
40
+ }
41
+
42
+ KubernetesHelper.settings(settings)
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kubernetes_helper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - owen2345
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-07-19 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2021-08-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: erb
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  description: ''
14
28
  email:
15
29
  - owenperedo@gmail.com
@@ -25,6 +39,15 @@ files:
25
39
  - lib/kubernetes_helper/core.rb
26
40
  - lib/kubernetes_helper/railtie.rb
27
41
  - lib/kubernetes_helper/version.rb
42
+ - lib/templates/README.md
43
+ - lib/templates/_replicas.yml.erb
44
+ - lib/templates/_sidekiq_alive_gem.yml.erb
45
+ - lib/templates/cd.sh
46
+ - lib/templates/deployment.yml
47
+ - lib/templates/ingress.yml
48
+ - lib/templates/secrets.yml
49
+ - lib/templates/service.yml
50
+ - lib/templates/settings.rb
28
51
  homepage: https://github.com/owen2345/kubernetes_helper
29
52
  licenses:
30
53
  - MIT