summaryrefslogtreecommitdiff
path: root/app/models/clusters
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/clusters')
-rw-r--r--app/models/clusters/applications/elastic_stack.rb47
-rw-r--r--app/models/clusters/applications/fluentd.rb20
-rw-r--r--app/models/clusters/applications/ingress.rb7
-rw-r--r--app/models/clusters/applications/jupyter.rb2
-rw-r--r--app/models/clusters/applications/knative.rb4
-rw-r--r--app/models/clusters/applications/runner.rb2
-rw-r--r--app/models/clusters/cluster.rb92
-rw-r--r--app/models/clusters/concerns/application_status.rb9
8 files changed, 145 insertions, 38 deletions
diff --git a/app/models/clusters/applications/elastic_stack.rb b/app/models/clusters/applications/elastic_stack.rb
index afdc1c91c69..0d029aabc3b 100644
--- a/app/models/clusters/applications/elastic_stack.rb
+++ b/app/models/clusters/applications/elastic_stack.rb
@@ -3,7 +3,7 @@
module Clusters
module Applications
class ElasticStack < ApplicationRecord
- VERSION = '1.9.0'
+ VERSION = '3.0.0'
ELASTICSEARCH_PORT = 9200
@@ -18,7 +18,11 @@ module Clusters
default_value_for :version, VERSION
def chart
- 'stable/elastic-stack'
+ 'elastic-stack/elastic-stack'
+ end
+
+ def repository
+ 'https://charts.gitlab.io'
end
def install_command
@@ -27,7 +31,9 @@ module Clusters
version: VERSION,
rbac: cluster.platform_kubernetes_rbac?,
chart: chart,
+ repository: repository,
files: files,
+ preinstall: migrate_to_3_script,
postinstall: post_install_script
)
end
@@ -49,7 +55,7 @@ module Clusters
strong_memoize(:elasticsearch_client) do
next unless kube_client
- proxy_url = kube_client.proxy_url('service', 'elastic-stack-elasticsearch-client', ::Clusters::Applications::ElasticStack::ELASTICSEARCH_PORT, Gitlab::Kubernetes::Helm::NAMESPACE)
+ proxy_url = kube_client.proxy_url('service', service_name, ::Clusters::Applications::ElasticStack::ELASTICSEARCH_PORT, Gitlab::Kubernetes::Helm::NAMESPACE)
Elasticsearch::Client.new(url: proxy_url) do |faraday|
# ensures headers containing auth data are appended to original client options
@@ -69,23 +75,54 @@ module Clusters
end
end
+ def chart_above_v2?
+ Gem::Version.new(version) >= Gem::Version.new('2.0.0')
+ end
+
+ def chart_above_v3?
+ Gem::Version.new(version) >= Gem::Version.new('3.0.0')
+ end
+
private
+ def service_name
+ chart_above_v3? ? 'elastic-stack-elasticsearch-master' : 'elastic-stack-elasticsearch-client'
+ end
+
+ def pvc_selector
+ chart_above_v3? ? "app=elastic-stack-elasticsearch-master" : "release=elastic-stack"
+ end
+
def post_install_script
[
- "timeout -t60 sh /data/helm/elastic-stack/config/wait-for-elasticsearch.sh http://elastic-stack-elasticsearch-client:9200"
+ "timeout -t60 sh /data/helm/elastic-stack/config/wait-for-elasticsearch.sh http://elastic-stack-elasticsearch-master:9200"
]
end
def post_delete_script
[
- Gitlab::Kubernetes::KubectlCmd.delete("pvc", "--selector", "release=elastic-stack")
+ Gitlab::Kubernetes::KubectlCmd.delete("pvc", "--selector", pvc_selector, "--namespace", Gitlab::Kubernetes::Helm::NAMESPACE)
]
end
def kube_client
cluster&.kubeclient&.core_client
end
+
+ def migrate_to_3_script
+ return [] if !updating? || chart_above_v3?
+
+ # Chart version 3.0.0 moves to our own chart at https://gitlab.com/gitlab-org/charts/elastic-stack
+ # and is not compatible with pre-existing resources. We first remove them.
+ [
+ Gitlab::Kubernetes::Helm::DeleteCommand.new(
+ name: 'elastic-stack',
+ rbac: cluster.platform_kubernetes_rbac?,
+ files: files
+ ).delete_command,
+ Gitlab::Kubernetes::KubectlCmd.delete("pvc", "--selector", "release=elastic-stack", "--namespace", Gitlab::Kubernetes::Helm::NAMESPACE)
+ ]
+ end
end
end
end
diff --git a/app/models/clusters/applications/fluentd.rb b/app/models/clusters/applications/fluentd.rb
index a33b1e39ace..3fd6e870edc 100644
--- a/app/models/clusters/applications/fluentd.rb
+++ b/app/models/clusters/applications/fluentd.rb
@@ -4,6 +4,7 @@ module Clusters
module Applications
class Fluentd < ApplicationRecord
VERSION = '2.4.0'
+ CILIUM_CONTAINER_NAME = 'cilium-monitor'
self.table_name = 'clusters_applications_fluentd'
@@ -18,6 +19,8 @@ module Clusters
enum protocol: { tcp: 0, udp: 1 }
+ validate :has_at_least_one_log_enabled?
+
def chart
'stable/fluentd'
end
@@ -39,6 +42,12 @@ module Clusters
private
+ def has_at_least_one_log_enabled?
+ if !waf_log_enabled && !cilium_log_enabled
+ errors.add(:base, _("At least one logging option is required to be enabled"))
+ end
+ end
+
def content_values
YAML.load_file(chart_values_file).deep_merge!(specification)
end
@@ -62,7 +71,7 @@ module Clusters
program fluentd
hostname ${kubernetes_host}
protocol #{protocol}
- packet_size 65535
+ packet_size 131072
<buffer kubernetes_host>
</buffer>
<format>
@@ -85,7 +94,7 @@ module Clusters
<source>
@type tail
@id in_tail_container_logs
- path /var/log/containers/*#{Ingress::MODSECURITY_LOG_CONTAINER_NAME}*.log
+ path #{path_to_logs}
pos_file /var/log/fluentd-containers.log.pos
tag kubernetes.*
read_from_head true
@@ -96,6 +105,13 @@ module Clusters
</source>
EOF
end
+
+ def path_to_logs
+ path = []
+ path << "/var/log/containers/*#{Ingress::MODSECURITY_LOG_CONTAINER_NAME}*.log" if waf_log_enabled
+ path << "/var/log/containers/*#{CILIUM_CONTAINER_NAME}*.log" if cilium_log_enabled
+ path.join(',')
+ end
end
end
end
diff --git a/app/models/clusters/applications/ingress.rb b/app/models/clusters/applications/ingress.rb
index 5985e08d73e..dd354198910 100644
--- a/app/models/clusters/applications/ingress.rb
+++ b/app/models/clusters/applications/ingress.rb
@@ -17,6 +17,7 @@ module Clusters
include ::Clusters::Concerns::ApplicationVersion
include ::Clusters::Concerns::ApplicationData
include AfterCommitQueue
+ include UsageStatistics
default_value_for :ingress_type, :nginx
default_value_for :modsecurity_enabled, true
@@ -29,6 +30,10 @@ module Clusters
enum modsecurity_mode: { logging: 0, blocking: 1 }
+ scope :modsecurity_not_installed, -> { where(modsecurity_enabled: nil) }
+ scope :modsecurity_enabled, -> { where(modsecurity_enabled: true) }
+ scope :modsecurity_disabled, -> { where(modsecurity_enabled: false) }
+
FETCH_IP_ADDRESS_DELAY = 30.seconds
state_machine :status do
@@ -98,7 +103,7 @@ module Clusters
"args" => [
"/bin/sh",
"-c",
- "tail -f /var/log/modsec/audit.log"
+ "tail -F /var/log/modsec/audit.log"
],
"volumeMounts" => [
{
diff --git a/app/models/clusters/applications/jupyter.rb b/app/models/clusters/applications/jupyter.rb
index 42fa4a6f179..056ea355de6 100644
--- a/app/models/clusters/applications/jupyter.rb
+++ b/app/models/clusters/applications/jupyter.rb
@@ -5,7 +5,7 @@ require 'securerandom'
module Clusters
module Applications
class Jupyter < ApplicationRecord
- VERSION = '0.9.0-beta.2'
+ VERSION = '0.9.0'
self.table_name = 'clusters_applications_jupyter'
diff --git a/app/models/clusters/applications/knative.rb b/app/models/clusters/applications/knative.rb
index 1f90318f845..3047da12dd9 100644
--- a/app/models/clusters/applications/knative.rb
+++ b/app/models/clusters/applications/knative.rb
@@ -4,8 +4,8 @@ module Clusters
module Applications
class Knative < ApplicationRecord
VERSION = '0.9.0'
- REPOSITORY = 'https://storage.googleapis.com/triggermesh-charts'
- METRICS_CONFIG = 'https://storage.googleapis.com/triggermesh-charts/istio-metrics.yaml'
+ REPOSITORY = 'https://charts.gitlab.io'
+ METRICS_CONFIG = 'https://gitlab.com/gitlab-org/charts/knative/-/raw/v0.9.0/vendor/istio-metrics.yml'
FETCH_IP_ADDRESS_DELAY = 30.seconds
API_GROUPS_PATH = 'config/knative/api_groups.yml'
diff --git a/app/models/clusters/applications/runner.rb b/app/models/clusters/applications/runner.rb
index 7d67e258991..a861126908f 100644
--- a/app/models/clusters/applications/runner.rb
+++ b/app/models/clusters/applications/runner.rb
@@ -3,7 +3,7 @@
module Clusters
module Applications
class Runner < ApplicationRecord
- VERSION = '0.15.0'
+ VERSION = '0.16.1'
self.table_name = 'clusters_applications_runners'
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb
index 430a9b3c43e..83f558af1a1 100644
--- a/app/models/clusters/cluster.rb
+++ b/app/models/clusters/cluster.rb
@@ -26,6 +26,8 @@ module Clusters
KUBE_INGRESS_BASE_DOMAIN = 'KUBE_INGRESS_BASE_DOMAIN'
APPLICATIONS_ASSOCIATIONS = APPLICATIONS.values.map(&:association_name).freeze
+ self.reactive_cache_work_type = :external_dependency
+
belongs_to :user
belongs_to :management_project, class_name: '::Project', optional: true
@@ -33,6 +35,7 @@ module Clusters
has_many :projects, through: :cluster_projects, class_name: '::Project'
has_one :cluster_project, -> { order(id: :desc) }, class_name: 'Clusters::Project'
has_many :deployment_clusters
+ has_many :deployments, inverse_of: :cluster
has_many :cluster_groups, class_name: 'Clusters::Group'
has_many :groups, through: :cluster_groups, class_name: '::Group'
@@ -203,10 +206,16 @@ module Clusters
end
end
+ def nodes
+ with_reactive_cache do |data|
+ data[:nodes]
+ end
+ end
+
def calculate_reactive_cache
return unless enabled?
- { connection_status: retrieve_connection_status }
+ { connection_status: retrieve_connection_status, nodes: retrieve_nodes }
end
def persisted_applications
@@ -214,11 +223,19 @@ module Clusters
end
def applications
- APPLICATIONS_ASSOCIATIONS.map do |association_name|
- public_send(association_name) || public_send("build_#{association_name}") # rubocop:disable GitlabSecurity/PublicSend
+ APPLICATIONS.each_value.map do |application_class|
+ find_or_build_application(application_class)
end
end
+ def find_or_build_application(application_class)
+ raise ArgumentError, "#{application_class} is not in APPLICATIONS" unless APPLICATIONS.value?(application_class)
+
+ association_name = application_class.association_name
+
+ public_send(association_name) || public_send("build_#{association_name}") # rubocop:disable GitlabSecurity/PublicSend
+ end
+
def provider
if gcp?
provider_gcp
@@ -345,32 +362,55 @@ module Clusters
end
def retrieve_connection_status
- kubeclient.core_client.discover
- rescue *Gitlab::Kubernetes::Errors::CONNECTION
- :unreachable
- rescue *Gitlab::Kubernetes::Errors::AUTHENTICATION
- :authentication_failure
- rescue Kubeclient::HttpError => e
- kubeclient_error_status(e.message)
- rescue => e
- Gitlab::ErrorTracking.track_exception(e, cluster_id: id)
-
- :unknown_failure
- else
- :connected
- end
-
- # KubeClient uses the same error class
- # For connection errors (eg. timeout) and
- # for Kubernetes errors.
- def kubeclient_error_status(message)
- if message&.match?(/timed out|timeout/i)
- :unreachable
- else
- :authentication_failure
+ result = ::Gitlab::Kubernetes::KubeClient.graceful_request(id) { kubeclient.core_client.discover }
+ result[:status]
+ end
+
+ def retrieve_nodes
+ result = ::Gitlab::Kubernetes::KubeClient.graceful_request(id) { kubeclient.get_nodes }
+ cluster_nodes = result[:response].to_a
+
+ result = ::Gitlab::Kubernetes::KubeClient.graceful_request(id) { kubeclient.metrics_client.get_nodes }
+ nodes_metrics = result[:response].to_a
+
+ cluster_nodes.inject([]) do |memo, node|
+ sliced_node = filter_relevant_node_attributes(node)
+
+ matched_node_metric = nodes_metrics.find { |node_metric| node_metric.metadata.name == node.metadata.name }
+
+ sliced_node_metrics = matched_node_metric ? filter_relevant_node_metrics_attributes(matched_node_metric) : {}
+
+ memo << sliced_node.merge(sliced_node_metrics)
end
end
+ def filter_relevant_node_attributes(node)
+ {
+ 'metadata' => {
+ 'name' => node.metadata.name
+ },
+ 'status' => {
+ 'capacity' => {
+ 'cpu' => node.status.capacity.cpu,
+ 'memory' => node.status.capacity.memory
+ },
+ 'allocatable' => {
+ 'cpu' => node.status.allocatable.cpu,
+ 'memory' => node.status.allocatable.memory
+ }
+ }
+ }
+ end
+
+ def filter_relevant_node_metrics_attributes(node_metrics)
+ {
+ 'usage' => {
+ 'cpu' => node_metrics.usage.cpu,
+ 'memory' => node_metrics.usage.memory
+ }
+ }
+ end
+
# To keep backward compatibility with AUTO_DEVOPS_DOMAIN
# environment variable, we need to ensure KUBE_INGRESS_BASE_DOMAIN
# is set if AUTO_DEVOPS_DOMAIN is set on any of the following options:
diff --git a/app/models/clusters/concerns/application_status.rb b/app/models/clusters/concerns/application_status.rb
index 14237439a8d..0b915126f8a 100644
--- a/app/models/clusters/concerns/application_status.rb
+++ b/app/models/clusters/concerns/application_status.rb
@@ -27,6 +27,7 @@ module Clusters
state :update_errored, value: 6
state :uninstalling, value: 7
state :uninstall_errored, value: 8
+ state :uninstalled, value: 10
# Used for applications that are pre-installed by the cluster,
# e.g. Knative in GCP Cloud Run enabled clusters
@@ -35,6 +36,14 @@ module Clusters
# and no exit transitions.
state :pre_installed, value: 9
+ event :make_externally_installed do
+ transition any => :installed
+ end
+
+ event :make_externally_uninstalled do
+ transition any => :uninstalled
+ end
+
event :make_scheduled do
transition [:installable, :errored, :installed, :updated, :update_errored, :uninstall_errored] => :scheduled
end