Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improvement(k8s): remove old system garden and improve local-k8s startup time #5136

Merged
merged 95 commits into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from 93 commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
0179c35
refactor: move constant `defaultSystemNamespace` to `constants.ts`
vvagaytsev Oct 16, 2023
fb8e84b
chore: helpers for nginx integration
edvald Sep 26, 2023
6b548ae
refactor: re-arrange the list of the supported contexts
vvagaytsev Sep 26, 2023
8999677
chore: helper to apply manifests from yaml files
vvagaytsev Sep 26, 2023
24b27ab
chore(wip): getting rid of system services
edvald Sep 26, 2023
726ad04
chore: rename some nginx deploy configs
vvagaytsev Sep 26, 2023
d94a450
chore: rename some nginx deploy configs
vvagaytsev Sep 26, 2023
d1fe90b
chore: move nginx configs to `static/kubernetes`
vvagaytsev Sep 26, 2023
1e2a23f
fix(k8s): (wip) convert garden nginx deploy configs to k8s manifests
vvagaytsev Sep 26, 2023
1eb5508
chore: change file extension `yml` -> `yaml`
vvagaytsev Sep 26, 2023
ca59a0d
refactor(k8s): (wip) split provider and environment config handlers
edvald Sep 26, 2023
de955ee
fix(k3s): (wip) add missing nginx configuration
vvagaytsev Sep 26, 2023
2fccbef
fix(k8s): argument type for env config handler
vvagaytsev Sep 26, 2023
31516d0
refactor(k8s): named type for k8s cluster type
vvagaytsev Sep 26, 2023
6523f16
chore: remove unused constant
vvagaytsev Sep 26, 2023
d45f7fb
chore: defensive type-check for k8s cluster type
vvagaytsev Sep 26, 2023
9da6071
docs: update RBAC config guide
edvald Sep 26, 2023
1584bbb
chore: fix compile errors
vvagaytsev Sep 28, 2023
27bb62b
fix(k8s): use standard `getEnvironmentStatus` to ensure namespaces
vvagaytsev Sep 28, 2023
82f00d2
chore: add missing sha256 hash
vvagaytsev Sep 28, 2023
9b1054a
refactor: extract getter to build values for nginx helm chart
vvagaytsev Oct 4, 2023
7704614
refactor: extract some named constants
vvagaytsev Oct 4, 2023
91af7e6
refactor(k3s): gardenless k3s nginx setup
vvagaytsev Sep 28, 2023
4c18412
refactor: gardenless ephemeral nginx setup
vvagaytsev Oct 4, 2023
b649b30
chore: remove duplicate `--namespace` arg
vvagaytsev Oct 11, 2023
dac511b
chore: remove garden config for system services
vvagaytsev Oct 11, 2023
80421e8
fix: pass helm values in the proper format
vvagaytsev Oct 4, 2023
9b670c7
chore: remove unnecessary field from `LocalKubernetesConfig`
vvagaytsev Oct 11, 2023
bfdf724
chore: use explicit types for local k8s configs
vvagaytsev Oct 11, 2023
40e4192
chore: do not install default nginx for local k8s clusters
vvagaytsev Oct 11, 2023
ef370ce
chore: install and uninstall defaultBackend with nginx ingress contro…
twelvemo Oct 16, 2023
2e2f9d2
chore: drop kind nginx support for old k8s versions (< 1.21)
twelvemo Oct 16, 2023
bff45c3
chore: fix ephemeral kubernetes
twelvemo Oct 16, 2023
7129c03
chore: rename function
vvagaytsev Oct 18, 2023
6bd9d22
chore: refactor installing ingress controllers
twelvemo Oct 20, 2023
9813923
refactor: rename module `integrations` => `nginx`
vvagaytsev Oct 20, 2023
0e23fd1
refactor: extract new file `default-backend.ts`
vvagaytsev Oct 20, 2023
31d7dbc
refactor: rename file `nginx.ts` => `ingress-controller.ts`
vvagaytsev Oct 20, 2023
9cabc0c
chore: use defensive type-checks
vvagaytsev Oct 20, 2023
fb33e8e
fix: use specific helm values for k3s and generic cluster types
vvagaytsev Oct 20, 2023
339eda8
chore: remove unnecessary calls of `defaultBackendInstall`
vvagaytsev Oct 20, 2023
0f31bc6
chore: remove unnecessary calls of `defaultBackendUninstall`
vvagaytsev Oct 20, 2023
bcac6bb
chore: narrowed local var scope
vvagaytsev Oct 20, 2023
2f59c4e
chore: re-arranged code
vvagaytsev Oct 20, 2023
f8db41e
refactor: extract named constant for Garden default-backend image
vvagaytsev Oct 20, 2023
77e958c
chore: use named constant instead of hard-coded string
vvagaytsev Oct 20, 2023
68375ed
chore: use `systemNamespace` var instead of hard-coded string
vvagaytsev Oct 20, 2023
ce8d934
refactor: move helm nginx helpers to the dedicated file
vvagaytsev Oct 20, 2023
3d97261
refactor: move generic cluster nginx code to a dedicated file
vvagaytsev Oct 20, 2023
5a59314
refactor: move k3s cluster nginx code to a dedicated file
vvagaytsev Oct 20, 2023
1ae629c
refactor: move microk8s cluster nginx code to a dedicated file
vvagaytsev Oct 20, 2023
ef7eedf
refactor: move minikube cluster nginx code to a dedicated file
vvagaytsev Oct 20, 2023
284e14c
chore: rename file `nginx-kind.ts` => `nginx-kind-manifests.ts`
vvagaytsev Oct 20, 2023
78b8f27
chore: move `nginx-kind-manifests.ts` to `nginx` package
vvagaytsev Oct 20, 2023
9912e3c
refactor: move kind cluster nginx code to a dedicated file
vvagaytsev Oct 20, 2023
51a7d5c
refactor: move ephemeral cluster nginx code to a dedicated file
vvagaytsev Oct 20, 2023
9fbf771
refactor: extract function `helmIngressControllerReady`
vvagaytsev Oct 20, 2023
f406e13
chore: narrow scope of some local vars
vvagaytsev Oct 20, 2023
36338a3
chore(k8s): remove unused static resources
vvagaytsev Oct 23, 2023
096701f
fix(k8s): uninstall only the ingress controller installed by Garden
vvagaytsev Oct 23, 2023
5ffb5a8
chore: remove unused function
vvagaytsev Oct 23, 2023
503dd76
refactor: make `getClusterType` side-effect free function
vvagaytsev Oct 24, 2023
06303ee
fix(ephemeral): restore ingress controller installation
vvagaytsev Oct 24, 2023
83094b2
refactor: more granular cluster types
vvagaytsev Oct 24, 2023
35acfc6
chore: spacing + inline redundant local var
vvagaytsev Oct 24, 2023
28555aa
refactor: configure ingress controllers in a single place
vvagaytsev Oct 24, 2023
8073e6e
refactor: ensure system namespace in the base kubernetes handler
vvagaytsev Oct 24, 2023
0be7a30
chore: use correct section name in logger
vvagaytsev Oct 24, 2023
8a71684
chore: replace if/else with ternary operator
vvagaytsev Oct 24, 2023
383b3c5
chore: add some integ tests around ingress controllers
twelvemo Oct 25, 2023
3f97532
chore: check status of main ingress controller deployed resources
twelvemo Oct 25, 2023
df71e40
chore: wait for all nginx resources to be ready
twelvemo Oct 26, 2023
2c6fa06
chore: explicit type for nginx helm values
vvagaytsev Oct 27, 2023
68db3e3
refactor: extract helper function `getNginxHelmMainResource`
vvagaytsev Oct 27, 2023
fd2b415
refactor: move constant to a dedicated file
vvagaytsev Nov 3, 2023
3f9a121
chore: use ESM imports (post-rebase corrections)
vvagaytsev Nov 7, 2023
57d56af
chore: use narrow-typed named constants as Docker image names
vvagaytsev Nov 7, 2023
d84fe1b
refactor: (1) introduce interface and classes for ingress setup
vvagaytsev Nov 8, 2023
e4774eb
refactor: (2) use interface and classes for ingress setup
vvagaytsev Nov 8, 2023
7d05f5a
refactor: (3) remove unnecessary exports
vvagaytsev Nov 8, 2023
30d0401
refactor: (4) inline functions into class methods
vvagaytsev Nov 8, 2023
b37ca44
refactor: (5) inline functions into class methods
vvagaytsev Nov 8, 2023
f0d8232
refactor: (6) convert interface to abstract class
vvagaytsev Nov 8, 2023
3ec92d2
refactor: (7) introduce abstract method
vvagaytsev Nov 8, 2023
5bcaa29
refactor: (8) inline functions into class methods
vvagaytsev Nov 8, 2023
41f67fb
chore: move `GardenIngressController` to standalone file
vvagaytsev Nov 8, 2023
b972a4a
refactor: (9) convert default backend functions to class
vvagaytsev Nov 8, 2023
3e2ef03
refactor: (10) inline functions into class methods
vvagaytsev Nov 8, 2023
39dc0e2
chore: more generic name for the ABC
vvagaytsev Nov 8, 2023
ded32ca
chore: re-arranged code
vvagaytsev Nov 8, 2023
b1771ee
refactor: (11) inline functions into class methods
vvagaytsev Nov 8, 2023
a4d0fbf
refactor: (12) change signature of `helmValuesGetter`
vvagaytsev Nov 8, 2023
2ea6202
refactor: (13) replace conditional logic with polymorphism
vvagaytsev Nov 8, 2023
175192c
refactor: rename method
vvagaytsev Nov 9, 2023
509d490
chore: add deprecation warning for `plugin kubernetes init-cluster` c…
vvagaytsev Nov 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 4 additions & 4 deletions core/src/plugins/kubernetes/commands/cluster-init.ts
Expand Up @@ -7,12 +7,13 @@
*/

import type { PluginCommand } from "../../../plugin/command.js"
import { prepareSystem, getEnvironmentStatus } from "../init.js"
import { prepareEnvironment, getEnvironmentStatus } from "../init.js"
import chalk from "chalk"

// TODO: remove in 0.14
export const clusterInit: PluginCommand = {
name: "cluster-init",
description: "Initialize or update cluster-wide Garden services.",
description: "[DEPRECATED] Initialize or update cluster-wide Garden services.",
vvagaytsev marked this conversation as resolved.
Show resolved Hide resolved

title: ({ environmentName }) => {
return `Initializing/updating cluster-wide services for ${chalk.white(environmentName)} environment`
Expand All @@ -25,12 +26,11 @@ export const clusterInit: PluginCommand = {
if (status.ready) {
log.info("All services already initialized!")
} else {
result = await prepareSystem({
result = await prepareEnvironment({
ctx,
log,
force: true,
status,
clusterInit: true,
})
}

Expand Down
23 changes: 5 additions & 18 deletions core/src/plugins/kubernetes/commands/uninstall-garden-services.ts
Expand Up @@ -8,9 +8,8 @@

import chalk from "chalk"
import type { PluginCommand } from "../../../plugin/command.js"
import { getKubernetesSystemVariables } from "../init.js"
import type { KubernetesPluginContext } from "../config.js"
import { getSystemGarden } from "../system.js"
import { ingressControllerUninstall } from "../nginx/ingress-controller.js"

export const uninstallGardenServices: PluginCommand = {
name: "uninstall-garden-services",
Expand All @@ -22,25 +21,13 @@ export const uninstallGardenServices: PluginCommand = {

handler: async ({ ctx, log }) => {
const k8sCtx = <KubernetesPluginContext>ctx
const variables = getKubernetesSystemVariables(k8sCtx.provider.config)

const sysGarden = await getSystemGarden(k8sCtx, variables || {}, log)
const actions = await sysGarden.getActionRouter()

const graph = await sysGarden.getConfigGraph({ log, emit: false })
const deploys = graph.getDeploys()

log.info("")

const deployNames = deploys.map((s) => s.name)
const statuses = await actions.deleteDeploys({ graph, log, names: deployNames })

log.info("")

const environmentStatuses = await actions.provider.cleanupAll(log)
if (k8sCtx.provider.config.setupIngressController === "nginx") {
await ingressControllerUninstall(k8sCtx, log)
}

log.info(chalk.green("\nDone!"))

return { result: { serviceStatuses: statuses, environmentStatuses } }
return { result: {} }
},
}
12 changes: 6 additions & 6 deletions core/src/plugins/kubernetes/config.ts
Expand Up @@ -9,7 +9,6 @@
import type { StringMap } from "../../config/common.js"
import {
joi,
joiArray,
joiIdentifier,
joiIdentifierDescription,
joiProviderName,
Expand All @@ -28,7 +27,6 @@ import {
} from "../container/moduleConfig.js"
import type { PluginContext } from "../../plugin-context.js"
import { dedent, deline } from "../../util/string.js"
import { defaultSystemNamespace } from "./system.js"
import type { SyncableKind } from "./types.js"
import { syncableKinds } from "./types.js"
import type { BaseTaskSpec } from "../../config/task.js"
Expand All @@ -42,7 +40,9 @@ import type { SyncDefaults } from "./sync.js"
import { syncDefaultsSchema } from "./sync.js"
import { KUBECTL_DEFAULT_TIMEOUT } from "./kubectl.js"
import { DOCS_BASE_URL } from "../../constants.js"
import { defaultKanikoImageName } from "./constants.js"
import { defaultKanikoImageName, defaultSystemNamespace } from "./constants.js"
import type { LocalKubernetesClusterType } from "./local/config.js"
import type { EphemeralKubernetesClusterType } from "./ephemeral/config.js"

export interface ProviderSecretRef {
name: string
Expand Down Expand Up @@ -122,6 +122,8 @@ export interface ClusterBuildkitCacheConfig {
registry?: ContainerRegistryConfig
}

export type KubernetesClusterType = LocalKubernetesClusterType | EphemeralKubernetesClusterType

export interface KubernetesConfig extends BaseProviderConfig {
buildMode: ContainerBuildMode
clusterBuildkit?: {
Expand Down Expand Up @@ -173,8 +175,7 @@ export interface KubernetesConfig extends BaseProviderConfig {
gardenSystemNamespace: string
tlsCertificates: IngressTlsCertificate[]
certManager?: CertManagerConfig
clusterType?: "kind" | "minikube" | "microk8s" | "k3s"
_systemServices: string[]
clusterType?: KubernetesClusterType
}

export type KubernetesProvider = Provider<KubernetesConfig>
Expand Down Expand Up @@ -633,7 +634,6 @@ export const kubernetesConfigBase = () =>
tlsCertificates: joiSparseArray(tlsCertificateSchema())
.unique("name")
.description("One or more certificates to use for ingress."),
_systemServices: joiArray(joiIdentifier()).meta({ internal: true }),
systemNodeSelector: joiStringMap(joi.string())
.description(
dedent`
Expand Down
7 changes: 7 additions & 0 deletions core/src/plugins/kubernetes/constants.ts
Expand Up @@ -42,6 +42,13 @@ export const buildkitRootlessImageName: DockerImageWithDigest =
"gardendev/buildkit:v0.12.2-rootless@sha256:e30b7830078d51e66f1a861024dcc91f2ae5cb1108789c74d0e43ffe0d065b20"
export const defaultKanikoImageName: DockerImageWithDigest =
"gcr.io/kaniko-project/executor:v1.11.0-debug@sha256:32ba2214921892c2fa7b5f9c4ae6f8f026538ce6b2105a93a36a8b5ee50fe517"
export const defaultGardenIngressControllerDefaultBackendImage: DockerImageWithDigest =
"gardendev/default-backend:v0.1@sha256:1b02920425eea569c6be53bb2e3d2c1182243212de229be375da7a93594498cf"
export const defaultGardenIngressControllerImage: DockerImageWithDigest =
"k8s.gcr.io/ingress-nginx/controller:v1.1.3@sha256:31f47c1e202b39fadecf822a9b76370bd4baed199a005b3e7d4d1455f4fd3fe2"
export const defaultGardenIngressControllerKubeWebhookCertGenImage: DockerImageWithDigest =
"k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1@sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660"

export const buildkitDeploymentName = "garden-buildkit"
export const buildkitContainerName = "buildkitd"
export const defaultSystemNamespace = "garden-system"
2 changes: 1 addition & 1 deletion core/src/plugins/kubernetes/container/build/local.ts
Expand Up @@ -93,7 +93,7 @@ export const localBuild: BuildHandler = async (params) => {
}

/**
* Loads a built local image to a local Kubernetes instance
* Loads a built local image to a local Kubernetes instance.
*/
export async function loadToLocalK8s(params: BuildActionParams<"build", ContainerBuildAction>) {
const { ctx, log, action } = params
Expand Down
49 changes: 26 additions & 23 deletions core/src/plugins/kubernetes/ephemeral/config.ts
Expand Up @@ -10,7 +10,6 @@ import chalk from "chalk"
import fsExtra from "fs-extra"
const { mkdirp, writeFile } = fsExtra
import { load } from "js-yaml"
import { remove } from "lodash-es"
import moment from "moment"
import { join } from "path"
import { joi, joiProviderName } from "../../../config/common.js"
Expand All @@ -19,9 +18,13 @@ import { ConfigurationError } from "../../../exceptions.js"
import type { ConfigureProviderParams } from "../../../plugin/handlers/Provider/configureProvider.js"
import { dedent } from "../../../util/string.js"
import type { KubernetesConfig } from "../config.js"
import { defaultResources } from "../config.js"
import { namespaceSchema } from "../config.js"
import { EPHEMERAL_KUBERNETES_PROVIDER_NAME } from "./ephemeral.js"
import { DEFAULT_GARDEN_CLOUD_DOMAIN } from "../../../constants.js"
import { defaultSystemNamespace } from "../constants.js"

export type EphemeralKubernetesClusterType = "ephemeral"

export const configSchema = () =>
providerConfigBaseSchema()
Expand All @@ -43,12 +46,7 @@ export const configSchema = () =>

export async function configureProvider(params: ConfigureProviderParams<KubernetesConfig>) {
const { base, log, projectName, ctx, config: baseConfig } = params
if (projectName === "garden-system") {
// avoid configuring ephemeral-kubernetes provider and creating ephemeral-cluster for garden-system project
return {
config: baseConfig,
}
}

log.info(`Configuring ${EPHEMERAL_KUBERNETES_PROVIDER_NAME} provider for project ${projectName}`)
if (!ctx.cloudApi) {
throw new ConfigurationError({
Expand All @@ -60,13 +58,16 @@ export async function configureProvider(params: ConfigureProviderParams<Kubernet
message: `${EPHEMERAL_KUBERNETES_PROVIDER_NAME} provider is currently not supported for ${ctx.cloudApi.distroName}.`,
})
}

// creating tmp dir .garden/ephemeral-kubernetes for storing kubeconfig
const ephemeralClusterDirPath = join(ctx.gardenDirPath, "ephemeral-kubernetes")
await mkdirp(ephemeralClusterDirPath)

log.info("Retrieving ephemeral Kubernetes cluster")
const createEphemeralClusterResponse = await ctx.cloudApi.createEphemeralCluster()
const clusterId = createEphemeralClusterResponse.instanceMetadata.instanceId
log.info(`Ephemeral Kubernetes cluster retrieved successfully`)

const deadlineDateTime = moment(createEphemeralClusterResponse.instanceMetadata.deadline)
const diffInNowAndDeadline = moment.duration(deadlineDateTime.diff(moment())).asMinutes().toFixed(1)
log.info(
Expand All @@ -76,6 +77,7 @@ export async function configureProvider(params: ConfigureProviderParams<Kubernet
)}`
)
)

log.info("Fetching kubeconfig for the ephemeral cluster")
const kubeConfig = await ctx.cloudApi.getKubeConfigForCluster(clusterId)
const kubeconfigFileName = `${clusterId}-kubeconfig.yaml`
Expand All @@ -84,8 +86,7 @@ export async function configureProvider(params: ConfigureProviderParams<Kubernet
log.info(`Kubeconfig for ephemeral cluster saved at path: ${chalk.underline(kubeConfigPath)}`)

const parsedKubeConfig: any = load(kubeConfig)
const currentContext = parsedKubeConfig["current-context"]
baseConfig.context = currentContext
baseConfig.context = parsedKubeConfig["current-context"]
baseConfig.kubeconfig = kubeConfigPath

// set deployment registry
Expand All @@ -94,15 +95,21 @@ export async function configureProvider(params: ConfigureProviderParams<Kubernet
namespace: createEphemeralClusterResponse.registry.repository,
insecure: false,
}

// set imagePullSecrets
baseConfig.imagePullSecrets = [
{
name: createEphemeralClusterResponse.registry.imagePullSecret.name,
namespace: createEphemeralClusterResponse.registry.imagePullSecret.namespace,
},
]

// set build mode to kaniko
baseConfig.buildMode = "kaniko"

// set resource requests and limits defaults for builder, sync and util
baseConfig.resources = defaultResources
vvagaytsev marked this conversation as resolved.
Show resolved Hide resolved

// set additional kaniko flags
baseConfig.kaniko = {
extraFlags: [
Expand All @@ -112,28 +119,24 @@ export async function configureProvider(params: ConfigureProviderParams<Kubernet
"--force",
],
}
// set setupIngressController to null while initializing kubernetes plugin
// as we use it later and configure it separately for ephemeral-kubernetes

// set default hostname
baseConfig.defaultHostname = createEphemeralClusterResponse.ingressesHostname

// use garden-system as system namespace for ephemeral-kubernetes
baseConfig.gardenSystemNamespace = defaultSystemNamespace

// set the proper cluster type explicitly
baseConfig.clusterType = "ephemeral"

const kubernetesPluginConfig = {
...params,
config: {
...baseConfig,
setupIngressController: null,
},
}
const { config: updatedConfig } = await base!(kubernetesPluginConfig)

// setup ingress controller unless setupIngressController is set to false/null in provider config
if (baseConfig.setupIngressController) {
const _systemServices = updatedConfig._systemServices
const nginxServices = ["ingress-controller", "default-backend"]
remove(_systemServices, (s) => nginxServices.includes(s))
_systemServices.push("nginx-ephemeral")
updatedConfig.setupIngressController = "nginx"
// set default hostname
updatedConfig.defaultHostname = createEphemeralClusterResponse.ingressesHostname
}

return {
config: updatedConfig,
}
Expand Down
2 changes: 1 addition & 1 deletion core/src/plugins/kubernetes/helm/status.ts
Expand Up @@ -28,7 +28,7 @@ import { gardenAnnotationKey } from "../../../util/string.js"

export const gardenCloudAECPauseAnnotation = gardenAnnotationKey("aec-status")

const helmStatusMap: { [status: string]: DeployState } = {
export const helmStatusMap: { [status: string]: DeployState } = {
unknown: "unknown",
deployed: "ready",
deleted: "missing",
Expand Down