Skip to content
Snippets Groups Projects
Commit 36a01a88 authored by Tiger Watson's avatar Tiger Watson Committed by Thong Kuah
Browse files

Use separate Kubernetes namespaces per environment

Kubernetes deployments on new clusters will now have
a separate namespace per project environment, instead
of sharing a single namespace for the project.

Behaviour of existing clusters is unchanged.

All new functionality is controlled by the
:kubernetes_namespace_per_environment feature flag,
which is safe to enable/disable at any time.
parent 54377159
No related branches found
No related tags found
No related merge requests found
Showing
with 283 additions and 167 deletions
Loading
Loading
@@ -13,11 +13,11 @@ module Clusters
self.reactive_cache_key = ->(finder) { finder.model_name }
self.reactive_cache_worker_finder = ->(_id, *cache_args) { from_cache(*cache_args) }
 
attr_reader :cluster, :project
attr_reader :cluster, :environment
 
def initialize(cluster, project)
def initialize(cluster, environment)
@cluster = cluster
@project = project
@environment = environment
end
 
def with_reactive_cache_memoized(*cache_args, &block)
Loading
Loading
@@ -30,11 +30,11 @@ module Clusters
clear_reactive_cache!(*cache_args)
end
 
def self.from_cache(cluster_id, project_id)
def self.from_cache(cluster_id, environment_id)
cluster = Clusters::Cluster.find(cluster_id)
project = ::Project.find(project_id)
environment = Environment.find(environment_id)
 
new(cluster, project)
new(cluster, environment)
end
 
def calculate_reactive_cache(*)
Loading
Loading
@@ -56,7 +56,7 @@ module Clusters
end
 
def cache_args
[cluster.id, project.id]
[cluster.id, environment.id]
end
 
def service_pod_details(service)
Loading
Loading
@@ -84,7 +84,7 @@ module Clusters
private
 
def search_namespace
@search_namespace ||= cluster.kubernetes_namespace_for(project)
@search_namespace ||= cluster.kubernetes_namespace_for(environment)
end
 
def knative_client
Loading
Loading
# frozen_string_literal: true
module Clusters
class KubernetesNamespaceFinder
attr_reader :cluster, :project, :environment_slug
def initialize(cluster, project:, environment_slug:, allow_blank_token: false)
@cluster = cluster
@project = project
@environment_slug = environment_slug
@allow_blank_token = allow_blank_token
end
def execute
find_namespace(with_environment: cluster.namespace_per_environment?)
end
private
attr_reader :allow_blank_token
def find_namespace(with_environment:)
relation = with_environment ? namespaces.with_environment_slug(environment_slug) : namespaces
relation.find_by_project_id(project.id)
end
def namespaces
if allow_blank_token
cluster.kubernetes_namespaces
else
cluster.kubernetes_namespaces.has_service_account_token
end
end
end
end
Loading
Loading
@@ -3,10 +3,11 @@
module Projects
module Serverless
class FunctionsFinder
include Gitlab::Utils::StrongMemoize
attr_reader :project
 
def initialize(project)
@clusters = project.clusters
@project = project
end
 
Loading
Loading
@@ -16,9 +17,8 @@ module Projects
 
# Possible return values: Clusters::KnativeServicesFinder::KNATIVE_STATE
def knative_installed
states = @clusters.map do |cluster|
cluster.application_knative
cluster.knative_services_finder(project).knative_detected.tap do |state|
states = services_finders.map do |finder|
finder.knative_detected.tap do |state|
return state if state == ::Clusters::KnativeServicesFinder::KNATIVE_STATES['checking'] # rubocop:disable Cop/AvoidReturnFromBlocks
end
end
Loading
Loading
@@ -31,66 +31,70 @@ module Projects
end
 
def invocation_metrics(environment_scope, name)
return unless prometheus_adapter&.can_query?
environment = finders_for_scope(environment_scope).first&.environment
 
cluster = @clusters.find do |c|
environment_scope == c.environment_scope
if environment.present? && environment.prometheus_adapter&.can_query?
func = ::Serverless::Function.new(project, name, environment.deployment_namespace)
environment.prometheus_adapter.query(:knative_invocation, func)
end
func = ::Serverless::Function.new(project, name, cluster.kubernetes_namespace_for(project))
prometheus_adapter.query(:knative_invocation, func)
end
 
def has_prometheus?(environment_scope)
@clusters.any? do |cluster|
environment_scope == cluster.environment_scope && cluster.application_prometheus_available?
finders_for_scope(environment_scope).any? do |finder|
finder.cluster.application_prometheus_available?
end
end
 
private
 
def knative_service(environment_scope, name)
@clusters.map do |cluster|
next if environment_scope != cluster.environment_scope
services = cluster
.knative_services_finder(project)
finders_for_scope(environment_scope).map do |finder|
services = finder
.services
.select { |svc| svc["metadata"]["name"] == name }
 
add_metadata(cluster, services).first unless services.nil?
add_metadata(finder, services).first unless services.nil?
end
end
 
def knative_services
@clusters.map do |cluster|
services = cluster
.knative_services_finder(project)
.services
services_finders.map do |finder|
services = finder.services
 
add_metadata(cluster, services) unless services.nil?
add_metadata(finder, services) unless services.nil?
end
end
 
def add_metadata(cluster, services)
def add_metadata(finder, services)
add_pod_count = services.one?
services.each do |s|
s["environment_scope"] = cluster.environment_scope
s["cluster_id"] = cluster.id
s["environment_scope"] = finder.cluster.environment_scope
s["cluster_id"] = finder.cluster.id
 
if services.length == 1
s["podcount"] = cluster
.knative_services_finder(project)
if add_pod_count
s["podcount"] = finder
.service_pod_details(s["metadata"]["name"])
.length
end
end
end
 
# rubocop: disable CodeReuse/ServiceClass
def prometheus_adapter
@prometheus_adapter ||= ::Prometheus::AdapterService.new(project).prometheus_adapter
def services_finders
strong_memoize(:services_finders) do
available_environments.map(&:knative_services_finder).compact
end
end
def available_environments
@project.environments.available.preload_cluster
end
def finders_for_scope(environment_scope)
services_finders.select do |finder|
environment_scope == finder.cluster.environment_scope
end
end
# rubocop: enable CodeReuse/ServiceClass
end
end
end
Loading
Loading
@@ -53,6 +53,7 @@ module Clusters
validates :name, cluster_name: true
validates :cluster_type, presence: true
validates :domain, allow_blank: true, hostname: { allow_numeric_hostname: true }
validates :namespace_per_environment, inclusion: { in: [true, false] }
 
validate :restrict_modification, on: :update
validate :no_groups, unless: :group_type?
Loading
Loading
@@ -100,16 +101,6 @@ module Clusters
 
scope :default_environment, -> { where(environment_scope: DEFAULT_ENVIRONMENT) }
 
scope :with_knative_installed, -> { joins(:application_knative).merge(Clusters::Applications::Knative.available) }
scope :preload_knative, -> {
preload(
:kubernetes_namespaces,
:platform_kubernetes,
:application_knative
)
}
def self.ancestor_clusters_for_clusterable(clusterable, hierarchy_order: :asc)
return [] if clusterable.is_a?(Instance)
 
Loading
Loading
@@ -177,36 +168,15 @@ module Clusters
platform_kubernetes.kubeclient if kubernetes?
end
 
##
# This is subtly different to #find_or_initialize_kubernetes_namespace_for_project
# below because it will ignore any namespaces that have not got a service account
# token. This provides a guarantee that any namespace selected here can be used
# for cluster operations - a namespace needs to have a service account configured
# before it it can be used.
#
# This is used for selecting a namespace to use when querying a cluster, or
# generating variables to pass to CI.
def kubernetes_namespace_for(project)
find_or_initialize_kubernetes_namespace_for_project(
project, scope: kubernetes_namespaces.has_service_account_token
).namespace
end
##
# This is subtly different to #kubernetes_namespace_for because it will include
# namespaces that have yet to receive a service account token. This allows
# the namespace configuration process to be repeatable - if a namespace has
# already been created without a token we don't need to create another
# record entirely, just set the token on the pre-existing namespace.
#
# This is used for configuring cluster namespaces.
def find_or_initialize_kubernetes_namespace_for_project(project, scope: kubernetes_namespaces)
attributes = { project: project }
attributes[:cluster_project] = cluster_project if project_type?
def kubernetes_namespace_for(environment)
project = environment.project
persisted_namespace = Clusters::KubernetesNamespaceFinder.new(
self,
project: project,
environment_slug: environment.slug
).execute
 
scope.find_or_initialize_by(attributes).tap do |namespace|
namespace.set_defaults
end
persisted_namespace&.namespace || Gitlab::Kubernetes::DefaultNamespace.new(self, project: project).from_environment_slug(environment.slug)
end
 
def allow_user_defined_namespace?
Loading
Loading
@@ -225,10 +195,6 @@ module Clusters
end
end
 
def knative_services_finder(project)
@knative_services_finder ||= KnativeServicesFinder.new(self, project)
end
private
 
def instance_domain
Loading
Loading
Loading
Loading
@@ -9,12 +9,12 @@ module Clusters
belongs_to :cluster_project, class_name: 'Clusters::Project'
belongs_to :cluster, class_name: 'Clusters::Cluster'
belongs_to :project, class_name: '::Project'
belongs_to :environment, optional: true
has_one :platform_kubernetes, through: :cluster
 
before_validation :set_defaults
validates :namespace, presence: true
validates :namespace, uniqueness: { scope: :cluster_id }
validates :environment_id, uniqueness: { scope: [:cluster_id, :project_id] }, allow_nil: true
 
validates :service_account_name, presence: true
 
Loading
Loading
@@ -27,6 +27,7 @@ module Clusters
algorithm: 'aes-256-cbc'
 
scope :has_service_account_token, -> { where.not(encrypted_service_account_token: nil) }
scope :with_environment_slug, -> (slug) { joins(:environment).where(environments: { slug: slug }) }
 
def token_name
"#{namespace}-token"
Loading
Loading
@@ -42,34 +43,8 @@ module Clusters
end
end
 
def set_defaults
self.namespace ||= default_platform_kubernetes_namespace
self.namespace ||= default_project_namespace
self.service_account_name ||= default_service_account_name
end
private
 
def default_service_account_name
return unless namespace
"#{namespace}-service-account"
end
def default_platform_kubernetes_namespace
platform_kubernetes&.namespace.presence
end
def default_project_namespace
Gitlab::NamespaceSanitizer.sanitize(project_slug) if project_slug
end
def project_slug
return unless project
"#{project.path}-#{project.id}".downcase
end
def kubeconfig
to_kubeconfig(
url: api_url,
Loading
Loading
Loading
Loading
@@ -51,11 +51,6 @@ module Clusters
delegate :provided_by_user?, to: :cluster, allow_nil: true
delegate :allow_user_defined_namespace?, to: :cluster, allow_nil: true
 
# This is just to maintain compatibility with KubernetesService, which
# will be removed in https://gitlab.com/gitlab-org/gitlab-ce/issues/39217.
# It can be removed once KubernetesService is gone.
delegate :kubernetes_namespace_for, to: :cluster, allow_nil: true
alias_method :active?, :enabled?
 
enum_with_nil authorization_type: {
Loading
Loading
@@ -66,7 +61,7 @@ module Clusters
 
default_value_for :authorization_type, :rbac
 
def predefined_variables(project:)
def predefined_variables(project:, environment_name:)
Gitlab::Ci::Variables::Collection.new.tap do |variables|
variables.append(key: 'KUBE_URL', value: api_url)
 
Loading
Loading
@@ -77,15 +72,14 @@ module Clusters
end
 
if !cluster.managed?
project_namespace = namespace.presence || "#{project.path}-#{project.id}".downcase
namespace = Gitlab::Kubernetes::DefaultNamespace.new(cluster, project: project).from_environment_name(environment_name)
 
variables
.append(key: 'KUBE_URL', value: api_url)
.append(key: 'KUBE_TOKEN', value: token, public: false, masked: true)
.append(key: 'KUBE_NAMESPACE', value: project_namespace)
.append(key: 'KUBECONFIG', value: kubeconfig(project_namespace), public: false, file: true)
.append(key: 'KUBE_NAMESPACE', value: namespace)
.append(key: 'KUBECONFIG', value: kubeconfig(namespace), public: false, file: true)
 
elsif kubernetes_namespace = cluster.kubernetes_namespaces.has_service_account_token.find_by(project: project)
elsif kubernetes_namespace = find_persisted_namespace(project, environment_name: environment_name)
variables.concat(kubernetes_namespace.predefined_variables)
end
 
Loading
Loading
@@ -111,6 +105,22 @@ module Clusters
 
private
 
##
# Environment slug can be predicted given an environment
# name, so even if the environment isn't persisted yet we
# still know what to look for.
def environment_slug(name)
Gitlab::Slug::Environment.new(name).generate
end
def find_persisted_namespace(project, environment_name:)
Clusters::KubernetesNamespaceFinder.new(
cluster,
project: project,
environment_slug: environment_slug(environment_name)
).execute
end
def kubeconfig(namespace)
to_kubeconfig(
url: api_url,
Loading
Loading
Loading
Loading
@@ -48,6 +48,7 @@ class Environment < ApplicationRecord
end
scope :in_review_folder, -> { where(environment_type: "review") }
scope :for_name, -> (name) { where(name: name) }
scope :preload_cluster, -> { preload(last_deployment: :cluster) }
 
##
# Search environments which have names like the given query.
Loading
Loading
@@ -170,7 +171,7 @@ class Environment < ApplicationRecord
 
def deployment_namespace
strong_memoize(:kubernetes_namespace) do
deployment_platform&.kubernetes_namespace_for(project)
deployment_platform.cluster.kubernetes_namespace_for(self) if deployment_platform
end
end
 
Loading
Loading
@@ -233,6 +234,12 @@ class Environment < ApplicationRecord
end
end
 
def knative_services_finder
if last_deployment&.cluster
Clusters::KnativeServicesFinder.new(last_deployment.cluster, self)
end
end
private
 
def generate_slug
Loading
Loading
Loading
Loading
@@ -1855,8 +1855,12 @@ class Project < ApplicationRecord
end
end
 
def deployment_variables(environment: nil)
deployment_platform(environment: environment)&.predefined_variables(project: self) || []
def deployment_variables(environment:)
platform = deployment_platform(environment: environment)
return [] unless platform.present?
platform.predefined_variables(project: self, environment_name: environment)
end
 
def auto_devops_variables
Loading
Loading
Loading
Loading
@@ -24,7 +24,7 @@ class MockDeploymentService < Service
%w()
end
 
def predefined_variables(project:)
def predefined_variables(project:, environment_name:)
[]
end
 
Loading
Loading
# frozen_string_literal: true
module Clusters
class BuildKubernetesNamespaceService
attr_reader :cluster, :environment
def initialize(cluster, environment:)
@cluster = cluster
@environment = environment
end
def execute
cluster.kubernetes_namespaces.build(attributes)
end
private
def attributes
attributes = {
project: environment.project,
namespace: namespace,
service_account_name: "#{namespace}-service-account"
}
attributes[:cluster_project] = cluster.cluster_project if cluster.project_type?
attributes[:environment] = environment if cluster.namespace_per_environment?
attributes
end
def namespace
Gitlab::Kubernetes::DefaultNamespace.new(cluster, project: environment.project).from_environment_slug(environment.slug)
end
end
end
Loading
Loading
@@ -11,7 +11,8 @@ module Clusters
def execute(access_token: nil)
raise ArgumentError, 'Unknown clusterable provided' unless clusterable
 
cluster_params = params.merge(user: current_user).merge(clusterable_params)
cluster_params = params.merge(global_params).merge(clusterable_params)
cluster_params[:provider_gcp_attributes].try do |provider|
provider[:access_token] = access_token
end
Loading
Loading
@@ -35,6 +36,10 @@ module Clusters
@clusterable ||= params.delete(:clusterable)
end
 
def global_params
{ user: current_user, namespace_per_environment: Feature.enabled?(:kubernetes_namespace_per_environment, default_enabled: true) }
end
def clusterable_params
case clusterable
when ::Project
Loading
Loading
Loading
Loading
@@ -11,7 +11,6 @@ module Clusters
end
 
def execute
configure_kubernetes_namespace
create_project_service_account
configure_kubernetes_token
 
Loading
Loading
@@ -22,10 +21,6 @@ module Clusters
 
attr_reader :cluster, :kubernetes_namespace, :platform
 
def configure_kubernetes_namespace
kubernetes_namespace.set_defaults
end
def create_project_service_account
Clusters::Gcp::Kubernetes::CreateOrUpdateServiceAccountService.namespace_creator(
platform.kubeclient,
Loading
Loading
---
title: Use separate Kubernetes namespaces per environment
merge_request: 30711
author:
type: added
# frozen_string_literal: true
class AddEnvironmentIdToClustersKubernetesNamespaces < ActiveRecord::Migration[5.1]
DOWNTIME = false
def change
add_reference :clusters_kubernetes_namespaces, :environment,
index: true, type: :bigint, foreign_key: { on_delete: :nullify }
end
end
# frozen_string_literal: true
class IndexClustersKubernetesNamespacesOnEnvironmentId < ActiveRecord::Migration[5.1]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
INDEX_NAME = 'index_kubernetes_namespaces_on_cluster_project_environment_id'
disable_ddl_transaction!
def up
add_concurrent_index :clusters_kubernetes_namespaces, [:cluster_id, :project_id, :environment_id], unique: true, name: INDEX_NAME
end
def down
remove_concurrent_index :clusters_kubernetes_namespaces, name: INDEX_NAME
end
end
# frozen_string_literal: true
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddNamespacePerEnvironmentFlagToClusters < ActiveRecord::Migration[5.1]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_column_with_default :clusters, :namespace_per_environment, :boolean, default: false
end
def down
remove_column :clusters, :namespace_per_environment
end
end
Loading
Loading
@@ -880,6 +880,7 @@ ActiveRecord::Schema.define(version: 2019_08_02_235445) do
t.integer "cluster_type", limit: 2, default: 3, null: false
t.string "domain"
t.boolean "managed", default: true, null: false
t.boolean "namespace_per_environment", default: false, null: false
t.index ["enabled"], name: "index_clusters_on_enabled"
t.index ["user_id"], name: "index_clusters_on_user_id"
end
Loading
Loading
@@ -984,9 +985,12 @@ ActiveRecord::Schema.define(version: 2019_08_02_235445) do
t.string "encrypted_service_account_token_iv"
t.string "namespace", null: false
t.string "service_account_name"
t.bigint "environment_id"
t.index ["cluster_id", "namespace"], name: "kubernetes_namespaces_cluster_and_namespace", unique: true
t.index ["cluster_id", "project_id", "environment_id"], name: "index_kubernetes_namespaces_on_cluster_project_environment_id", unique: true
t.index ["cluster_id"], name: "index_clusters_kubernetes_namespaces_on_cluster_id"
t.index ["cluster_project_id"], name: "index_clusters_kubernetes_namespaces_on_cluster_project_id"
t.index ["environment_id"], name: "index_clusters_kubernetes_namespaces_on_environment_id"
t.index ["project_id"], name: "index_clusters_kubernetes_namespaces_on_project_id"
end
 
Loading
Loading
@@ -3711,6 +3715,7 @@ ActiveRecord::Schema.define(version: 2019_08_02_235445) do
add_foreign_key "clusters_applications_runners", "clusters", on_delete: :cascade
add_foreign_key "clusters_kubernetes_namespaces", "cluster_projects", on_delete: :nullify
add_foreign_key "clusters_kubernetes_namespaces", "clusters", on_delete: :cascade
add_foreign_key "clusters_kubernetes_namespaces", "environments", on_delete: :nullify
add_foreign_key "clusters_kubernetes_namespaces", "projects", on_delete: :nullify
add_foreign_key "container_repositories", "projects"
add_foreign_key "dependency_proxy_blobs", "namespaces", column: "group_id", name: "fk_db58bbc5d7", on_delete: :cascade
Loading
Loading
Loading
Loading
@@ -384,13 +384,9 @@ NOTE: **Note:**
[RBAC](#rbac-cluster-resources) is recommended and the GitLab default.
 
GitLab creates the necessary service accounts and privileges to install and run
[GitLab managed applications](#installing-applications). When GitLab creates the cluster:
- A `gitlab` service account with `cluster-admin` privileges is created in the `default` namespace
to manage the newly created cluster.
- A project service account with [`edit`
privileges](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles)
is created in the GitLab-created project namespace for [deployment jobs](#deployment-variables).
[GitLab managed applications](#installing-applications). When GitLab creates the cluster,
a `gitlab` service account with `cluster-admin` privileges is created in the `default` namespace
to manage the newly created cluster.
 
NOTE: **Note:**
Restricted service account for deployment was [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/51716) in GitLab 11.5.
Loading
Loading
@@ -412,32 +408,37 @@ The resources created by GitLab differ depending on the type of cluster.
 
GitLab creates the following resources for ABAC clusters.
 
| Name | Type | Details | Created when |
|:------------------|:---------------------|:----------------------------------|:---------------------------|
| `gitlab` | `ServiceAccount` | `default` namespace | Creating a new GKE Cluster |
| `gitlab-token` | `Secret` | Token for `gitlab` ServiceAccount | Creating a new GKE Cluster |
| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | Installing Helm Tiller |
| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | Installing Helm Tiller |
| Project namespace | `ServiceAccount` | Uses namespace of Project | Deploying to a cluster |
| Project namespace | `Secret` | Token for project ServiceAccount | Deploying to a cluster |
| Name | Type | Details | Created when |
|:----------------------|:---------------------|:-------------------------------------|:---------------------------|
| `gitlab` | `ServiceAccount` | `default` namespace | Creating a new GKE Cluster |
| `gitlab-token` | `Secret` | Token for `gitlab` ServiceAccount | Creating a new GKE Cluster |
| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | Installing Helm Tiller |
| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | Installing Helm Tiller |
| Environment namespace | `Namespace` | Contains all environment-specific resources | Deploying to a cluster |
| Environment namespace | `ServiceAccount` | Uses namespace of environment | Deploying to a cluster |
| Environment namespace | `Secret` | Token for environment ServiceAccount | Deploying to a cluster |
 
#### RBAC cluster resources
 
GitLab creates the following resources for RBAC clusters.
 
| Name | Type | Details | Created when |
|:------------------|:---------------------|:-----------------------------------------------------------------------------------------------------------|:---------------------------|
| `gitlab` | `ServiceAccount` | `default` namespace | Creating a new GKE Cluster |
| `gitlab-admin` | `ClusterRoleBinding` | [`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | Creating a new GKE Cluster |
| `gitlab-token` | `Secret` | Token for `gitlab` ServiceAccount | Creating a new GKE Cluster |
| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | Installing Helm Tiller |
| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | Installing Helm Tiller |
| Project namespace | `ServiceAccount` | Uses namespace of Project | Deploying to a cluster |
| Project namespace | `Secret` | Token for project ServiceAccount | Deploying to a cluster |
| Project namespace | `RoleBinding` | [`edit`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | Deploying to a cluster |
| Name | Type | Details | Created when |
|:----------------------|:---------------------|:-----------------------------------------------------------------------------------------------------------|:---------------------------|
| `gitlab` | `ServiceAccount` | `default` namespace | Creating a new GKE Cluster |
| `gitlab-admin` | `ClusterRoleBinding` | [`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | Creating a new GKE Cluster |
| `gitlab-token` | `Secret` | Token for `gitlab` ServiceAccount | Creating a new GKE Cluster |
| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | Installing Helm Tiller |
| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | Installing Helm Tiller |
| Environment namespace | `Namespace` | Contains all environment-specific resources | Deploying to a cluster |
| Environment namespace | `ServiceAccount` | Uses namespace of environment | Deploying to a cluster |
| Environment namespace | `Secret` | Token for environment ServiceAccount | Deploying to a cluster |
| Environment namespace | `RoleBinding` | [`edit`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | Deploying to a cluster |
NOTE: **Note:**
Environment-specific resources are only created if your cluster is [managed by GitLab](#gitlab-managed-clusters).
 
NOTE: **Note:**
Project-specific resources are only created if your cluster is [managed by GitLab](#gitlab-managed-clusters).
If your project was created before GitLab 12.2 it will use a single namespace for all project environments.
 
#### Security of GitLab Runners
 
Loading
Loading
@@ -640,8 +641,8 @@ GitLab CI/CD build environment.
| Variable | Description |
| -------- | ----------- |
| `KUBE_URL` | Equal to the API URL. |
| `KUBE_TOKEN` | The Kubernetes token of the [project service account](#access-controls). |
| `KUBE_NAMESPACE` | The Kubernetes namespace is auto-generated if not specified. The default value is `<project_name>-<project_id>`. You can overwrite it to use different one if needed, otherwise the `KUBE_NAMESPACE` variable will receive the default value. |
| `KUBE_TOKEN` | The Kubernetes token of the [environment service account](#access-controls). |
| `KUBE_NAMESPACE` | The Kubernetes namespace is auto-generated if not specified. The default value is `<project_name>-<project_id>-<environment>`. You can overwrite it to use different one if needed, otherwise the `KUBE_NAMESPACE` variable will receive the default value. |
| `KUBE_CA_PEM_FILE` | Path to a file containing PEM data. Only present if a custom CA bundle was specified. |
| `KUBE_CA_PEM` | (**deprecated**) Raw PEM data. Only if a custom CA bundle was specified. |
| `KUBECONFIG` | Path to a file containing `kubeconfig` for this deployment. CA bundle would be embedded if specified. This config also embeds the same token defined in `KUBE_TOKEN` so you likely will only need this variable. This variable name is also automatically picked up by `kubectl` so you won't actually need to reference it explicitly if using `kubectl`. |
Loading
Loading
Loading
Loading
@@ -434,7 +434,7 @@ The instructions below relate to installing and running Certbot on a Linux serve
./certbot-auto certonly --manual --preferred-challenges dns -d '*.<namespace>.example.com'
```
 
Where `<namespace>` is the namespace created by GitLab for your serverless project (composed of `<projectname+id>`) and
Where `<namespace>` is the namespace created by GitLab for your serverless project (composed of `<project_name>-<project_id>-<environment>`) and
`example.com` is the domain being used for your project. If you are unsure what the namespace of your project is, navigate
to the **Operations > Serverless** page of your project and inspect
the endpoint provided for your function/app.
Loading
Loading
Loading
Loading
@@ -8,31 +8,51 @@ module Gitlab
def unmet?
deployment_cluster.present? &&
deployment_cluster.managed? &&
(kubernetes_namespace.new_record? || kubernetes_namespace.service_account_token.blank?)
missing_namespace?
end
 
def complete!
return unless unmet?
 
create_or_update_namespace
create_namespace
end
 
private
 
def missing_namespace?
kubernetes_namespace.nil? || kubernetes_namespace.service_account_token.blank?
end
def deployment_cluster
build.deployment&.cluster
end
 
def environment
build.deployment.environment
end
def kubernetes_namespace
strong_memoize(:kubernetes_namespace) do
deployment_cluster.find_or_initialize_kubernetes_namespace_for_project(build.project)
Clusters::KubernetesNamespaceFinder.new(
deployment_cluster,
project: environment.project,
environment_slug: environment.slug,
allow_blank_token: true
).execute
end
end
 
def create_or_update_namespace
def create_namespace
Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService.new(
cluster: deployment_cluster,
kubernetes_namespace: kubernetes_namespace
kubernetes_namespace: kubernetes_namespace || build_namespace_record
).execute
end
def build_namespace_record
Clusters::BuildKubernetesNamespaceService.new(
deployment_cluster,
environment: environment
).execute
end
end
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment