Skip to content

[image-builder] Backport mkIII from gitpod-com #4251

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

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions chart/templates/image-builder-authkey-secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright (c) 2021 Gitpod GmbH. All rights reserved.
# Licensed under the MIT License. See License-MIT.txt in the project root for license information.

apiVersion: v1
kind: Secret
metadata:
name: image-builder-authkey
labels:
app: {{ template "gitpod.fullname" . }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
type: Opaque
data:
keyfile: {{ randAlphaNum 32 | b64enc }}
16 changes: 12 additions & 4 deletions chart/templates/image-builder-configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,22 @@ metadata:
data:
image-builder.json: |-
{
"builder": {
{{- if $comp.registry.secretName -}}"dockerCfgFile": "/config/pull-secret.json",{{- end -}}
"orchestrator": {
{{- if $comp.registry.secretName -}}"authFile": "/config/pull-secret.json",{{- end -}}
"gitpodLayerLoc": "/app/workspace-image-layer.tar.gz",
"baseImageRepository": "{{ or $comp.registry.baseImageName (print (include "registry-name" $this) "/base-images") }}",
"workspaceImageRepository": "{{ or $comp.registry.workspaceImageName (print (include "registry-name" $this) "/workspace-images") }}",
"imageBuildSalt": "{{ $comp.imageBuildSalt | default "" }}",
"alpineImage": "{{ $comp.alpineImage | default "" }}",
"selfBuildBaseImage": "{{ $comp.selfBuildBaseImage | default "" }}"
"wsman": {
"address": "ws-manager:8080",
"tls": {
"ca": "/wsman-certs/ca.crt",
"crt": "/wsman-certs/tls.crt",
"key": "/wsman-certs/tls.key"
}
},
Comment on lines +36 to +43
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know that the selection of the ws-manager is future work but what do you think of at least having something like this:
(However, that's not a blocker, though. Feel free to ignore.)

Suggested change
"wsman": {
"address": "ws-manager:8080",
"tls": {
"ca": "/wsman-certs/ca.crt",
"crt": "/wsman-certs/tls.crt",
"key": "/wsman-certs/tls.key"
}
},
{{- if $comp.wsman -}}
{{ $comp.wsman | fromYaml | toJson }}
{{- else -}}
"wsman": {
"address": "ws-manager:8080",
"tls": {
"ca": "/wsman-certs/ca.crt",
"crt": "/wsman-certs/tls.crt",
"key": "/wsman-certs/tls.key"
}
},
{{- end -}}

"builderImage": "{{ template "gitpod.comp.imageFull" (dict "root" . "gp" $.Values "comp" (dict "imageName" (printf "%s/bob" $comp.name))) }}",
"builderAuthKeyFile": "/config/authkey"
},
"refCache": {
"interval": "6h",
Expand Down
44 changes: 14 additions & 30 deletions chart/templates/image-builder-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,9 @@ spec:
- name: configuration
configMap:
name: {{ template "gitpod.comp.configMap" $this }}
- name: dind-storage
{{- if $comp.hostDindData }}
hostPath:
path: {{ $comp.hostDindData }}
type: DirectoryOrCreate
{{- else }}
emptyDir: {}
{{- end }}
- name: authkey
secret:
secretName: image-builder-authkey
{{- if $comp.registry.secretName }}
- name: pull-secret
secret:
Expand All @@ -64,30 +59,15 @@ spec:
secret:
secretName: {{ $sec.secret }}
{{- end }}
- name: wsman-tls-certs
secret:
secretName: {{ .Values.components.wsManager.tls.server.secretName }}
enableServiceLinks: false
containers:
- name: dind
image: {{ $comp.dindImage | default "docker:19.03-dind" }}
{{ include "gitpod.container.imagePullPolicy" $this | indent 8 }}
securityContext:
privileged: true
runAsUser: 0
args: [ "dockerd", "--userns-remap=default", "-H tcp://127.0.0.1:2375" {{- if $comp.dindMtu -}}, "--mtu={{ $comp.dindMtu}}"{{- end -}} ]
volumeMounts:
- mountPath: /var/lib/docker
name: dind-storage
{{- range $idx, $sec := $comp.registryCerts }}
- mountPath: /etc/docker/certs.d/{{- if eq $sec.name "builtin" -}}{{ template "gitpod.builtinRegistry.name" $this.root }}{{ else }}{{ $sec.name }}{{ end }}
name: docker-tls-certs-{{ $idx }}
{{- end }}
{{- if $comp.dindResources }}
resources:
{{ toYaml $comp.dindResources | indent 10 }}
{{- end }}
{{ include "gitpod.kube-rbac-proxy" $this | indent 6 }}
- name: image-builder
{{ include "gitpod.container.defaultEnv" $this | indent 8 }}
{{ include "gitpod.container.tracingEnv" $this | indent 8 }}
{{ include "gitpod.kube-rbac-proxy" $this | indent 6 }}
- name: service
image: {{ template "gitpod.comp.imageFull" $this }}
args:
- "run"
Expand All @@ -99,6 +79,12 @@ spec:
- mountPath: /config/image-builder.json
subPath: "image-builder.json"
name: configuration
- mountPath: /config/authkey
subPath: "keyfile"
name: authkey
- mountPath: /wsman-certs
name: wsman-tls-certs
readOnly: true
{{- if $comp.registry }}
{{- if $comp.registry.secretName }}
- mountPath: /config/pull-secret.json
Expand All @@ -116,7 +102,5 @@ spec:
privileged: false
{{ include "gitpod.container.defaultEnv" $this | indent 8 }}
{{ include "gitpod.container.tracingEnv" $this | indent 8 }}
- name: DOCKER_HOST
value: "tcp://localhost:2375"
{{ toYaml .Values.defaults | indent 6 }}
{{ end }}
6 changes: 5 additions & 1 deletion chart/templates/workspace-template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,14 @@ data:
"probe.yaml": |
{{ dict | merge ($comp.templates.probe | default dict) (include "coreWorkspaceAffinity" (dict "comp" $comp "tpe" "probe") | fromYaml) | toJson | indent 4 }}
{{- end }}
{{ if (or $comp.templates.regular $comp.affinity) }}
{{ if (or $comp.templates.ghost $comp.affinity) }}
"ghost.yaml": |
{{ dict | merge ($comp.templates.ghost | default dict) (include "coreWorkspaceAffinity" (dict "comp" $comp "tpe" "ghost") | fromYaml) | toJson | indent 4 }}
{{- end }}
{{ if (or $comp.templates.imagebuild $comp.affinity) }}
"imagebuild.yaml": |
{{ dict | merge ($comp.templates.ghost | default dict) (include "coreWorkspaceAffinity" (dict "comp" $comp "tpe" "imagebuild") | fromYaml) | toJson | indent 4 }}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason that it is $comp.templates.ghost instead of $comp.templates.imagebuild?

Suggested change
{{ dict | merge ($comp.templates.ghost | default dict) (include "coreWorkspaceAffinity" (dict "comp" $comp "tpe" "imagebuild") | fromYaml) | toJson | indent 4 }}
{{ dict | merge ($comp.templates.imagebuild | default dict) (include "coreWorkspaceAffinity" (dict "comp" $comp "tpe" "imagebuild") | fromYaml) | toJson | indent 4 }}

{{- end }}
{{ if (or $comp.templates.regular $comp.affinity) }}
"regular.yaml": |
{{ dict | merge ($comp.templates.regular | default dict) (include "coreWorkspaceAffinity" (dict "comp" $comp "tpe" "regular") | fromYaml) | toJson | indent 4 }}
Expand Down
1 change: 1 addition & 0 deletions chart/templates/ws-manager-configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ data:
{{ if (or $wscomp.templates.prebuild $wscomp.affinity) -}}"prebuildPath": "/workspace-template/prebuild.yaml",{{- end }}
{{ if (or $wscomp.templates.probe $wscomp.affinity) -}}"probePath": "/workspace-template/probe.yaml",{{- end }}
{{ if (or $wscomp.templates.ghost $wscomp.affinity) -}}"ghostPath": "/workspace-template/ghost.yaml",{{- end }}
{{ if (or $wscomp.templates.imagebuild $wscomp.affinity) -}}"ghostPath": "/workspace-template/imagebuild.yaml",{{- end }}
{{ if (or $wscomp.templates.regular $wscomp.affinity) -}}"regularPath": "/workspace-template/regular.yaml",{{- end }}
{{ end -}}
"defaultPath": "/workspace-template/default.yaml"
Expand Down
2 changes: 2 additions & 0 deletions components/BUILD.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ packages:
- components/ide/code:docker
- components/ide/theia:docker
- components/image-builder:docker
- components/image-builder-bob:docker
- components/local-app:docker
- components/local-app-api/typescript-grpcweb:publish
- components/proxy:docker
Expand Down Expand Up @@ -52,6 +53,7 @@ packages:
- components/ee/payment-endpoint:app
- components/ee/ws-scheduler:app
- components/image-builder:app
- components/image-builder-bob:app
- components/registry-facade:app
- components/server:app
- components/service-waiter:app
Expand Down
1 change: 1 addition & 0 deletions components/image-builder-bob/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bob
29 changes: 29 additions & 0 deletions components/image-builder-bob/BUILD.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
packages:
- name: app
type: go
srcs:
- "**/*.go"
- "go.mod"
- "go.sum"
env:
- CGO_ENABLED=0
- GOOS=linux
- GOPROXY=
deps:
- components/common-go:lib
config:
packaging: app
- name: docker
type: docker
srcs:
- supervisor-ide-config.json
- ide-startup.sh
deps:
- :app
- components/image-builder/workspace-image-layer:pack
config:
dockerfile: leeway.Dockerfile
argdeps:
- imageRepoBase
image:
- ${imageRepoBase}/image-builder/bob:${version}
48 changes: 48 additions & 0 deletions components/image-builder-bob/cmd/build.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) 2021 Gitpod GmbH. All rights reserved.
// Licensed under the GNU Affero General Public License (AGPL).
// See License-AGPL.txt in the project root for license information.

package cmd

import (
"os"
"time"

"github.com/gitpod-io/gitpod/image-builder/bob/pkg/builder"

log "github.com/gitpod-io/gitpod/common-go/log"
"github.com/spf13/cobra"
)

// buildCmd represents the build command
var buildCmd = &cobra.Command{
Use: "build",
Short: "Runs the image build and is configured using environment variables (see pkg/builder/config.go for details)",
Run: func(cmd *cobra.Command, args []string) {
if os.Geteuid() != 0 {
log.Fatal("must run as root")
}

// give the headless listener some time to attach
time.Sleep(1 * time.Second)

cfg, err := builder.GetConfigFromEnv()
if err != nil {
log.WithError(err).Fatal("cannot get config")
return
}

b := &builder.Builder{
Config: cfg,
}
err = b.Build()
if err != nil {
log.WithError(err).Fatal("build failed")
return
}
},
}

func init() {
rootCmd.AddCommand(buildCmd)
}
102 changes: 102 additions & 0 deletions components/image-builder-bob/cmd/daemon.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// Copyright (c) 2021 Gitpod GmbH. All rights reserved.
// Licensed under the GNU Affero General Public License (AGPL).
// See License-AGPL.txt in the project root for license information.

package cmd

import (
"context"
"encoding/json"
"fmt"
"os"
"os/signal"
"syscall"

log "github.com/gitpod-io/gitpod/common-go/log"
"github.com/gitpod-io/gitpod/image-builder/bob/pkg/builder"

"github.com/containerd/console"
"github.com/moby/buildkit/client"
"github.com/moby/buildkit/client/llb"
"github.com/moby/buildkit/util/progress/progressui"
"github.com/spf13/cobra"
"golang.org/x/sync/errgroup"
)

// daemonCmd represents the build command
var daemonCmd = &cobra.Command{
Use: "daemon <socket-path>",
Short: "Starts a buildkitd and pre-caches images",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
if os.Geteuid() != 0 {
log.Fatal("must run as root")
}

skt := args[0]
cl, teardown, err := builder.StartBuildkit(skt)
if err != nil {
log.WithError(err).Fatal("cannot start daemon")
}
defer teardown()

rawimgs := os.Getenv("BOB_CACHE_IMAGES")
if rawimgs != "" {
var images []string
err = json.Unmarshal([]byte(rawimgs), &images)
if err != nil {
log.WithError(err).Error("cannot unmarshal BOB_CACHE_IMAGES")
}

if len(images) > 0 {
err = prewarmCache(cl, images)
if err != nil {
log.WithError(err).Error("cannot prewarm cache")
}
}
}

// run until we're told to stop
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
log.Info("👷 image-builder daemon is up and running. Stop with SIGINT or CTRL+C")
<-sigChan
log.Info("Received SIGINT - shutting down")
},
}

func prewarmCache(cl *client.Client, images []string) error {
bld := llb.Image("alpine:latest").Run(llb.Shlex("echo"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would love if we could make the alpine:latest image configurable in the values.yaml file again.

for idx, img := range images {
bld = bld.AddMount(fmt.Sprintf("/mnt/%03d", idx), llb.Image(img)).Run(llb.Shlex("echo"))
}
pulllb, err := bld.Marshal(context.Background())
if err != nil {
log.WithError(err).Fatal("cannot produce iamge pull LLB")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo:

Suggested change
log.WithError(err).Fatal("cannot produce iamge pull LLB")
log.WithError(err).Fatal("cannot produce image pull LLB")

}

log.Info("pulling images")
var (
ch = make(chan *client.SolveStatus)
eg, ctx = errgroup.WithContext(context.Background())
)
eg.Go(func() error {
_, err := cl.Solve(ctx, pulllb, client.SolveOpt{}, ch)
return err
})
eg.Go(func() error {
var c console.Console
// not using shared context to not disrupt display but let is finish reporting errors
return progressui.DisplaySolveStatus(context.TODO(), "", c, os.Stderr, ch)
})
err = eg.Wait()
if err != nil {
return err
}
log.Info("done pulling images")
return nil
}

func init() {
rootCmd.AddCommand(daemonCmd)
}
31 changes: 31 additions & 0 deletions components/image-builder-bob/cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) 2021 Gitpod GmbH. All rights reserved.
// Licensed under the GNU Affero General Public License (AGPL).
// See License-AGPL.txt in the project root for license information.

package cmd

import (
"fmt"
"os"

log "github.com/gitpod-io/gitpod/common-go/log"
"github.com/spf13/cobra"
)

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "bob",
Short: "Bob is the in-workspace component of the image builder. You should never have to interact with it directly.",
}

// Execute runs the root command
func Execute() {
log.Init("bob", "", true, true)
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}

func init() {
}
3 changes: 3 additions & 0 deletions components/image-builder-bob/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

echo '{"message":{"type": "workspaceTaskDone"}}'
Loading