mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-04 10:27:43 +08:00
feat: enhance kubernetes driver
Signed-off-by: Wang Jinglei <morlay.null@gmail.com>
This commit is contained in:
parent
844b901005
commit
a7c704c39d
@ -411,6 +411,7 @@ Passes additional driver-specific options. Details for each driver:
|
|||||||
- `image=IMAGE` - Sets the container image to be used for running buildkit.
|
- `image=IMAGE` - Sets the container image to be used for running buildkit.
|
||||||
- `namespace=NS` - Sets the Kubernetes namespace. Defaults to the current namespace.
|
- `namespace=NS` - Sets the Kubernetes namespace. Defaults to the current namespace.
|
||||||
- `replicas=N` - Sets the number of `Pod` replicas. Defaults to 1.
|
- `replicas=N` - Sets the number of `Pod` replicas. Defaults to 1.
|
||||||
|
- `nodeselector="label1=value1,label2=value2"` - Sets the kv of `Pod` nodeSelector. No Defaults. Example `nodeselector=kubernetes.io/arch=arm64`
|
||||||
- `rootless=(true|false)` - Run the container as a non-root user without `securityContext.privileged`. [Using Ubuntu host kernel is recommended](https://github.com/moby/buildkit/blob/master/docs/rootless.md). Defaults to false.
|
- `rootless=(true|false)` - Run the container as a non-root user without `securityContext.privileged`. [Using Ubuntu host kernel is recommended](https://github.com/moby/buildkit/blob/master/docs/rootless.md). Defaults to false.
|
||||||
- `loadbalance=(sticky|random)` - Load-balancing strategy. If set to "sticky", the pod is chosen using the hash of the context path. Defaults to "sticky"
|
- `loadbalance=(sticky|random)` - Load-balancing strategy. If set to "sticky", the pod is chosen using the hash of the context path. Defaults to "sticky"
|
||||||
|
|
||||||
|
@ -142,6 +142,12 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if in.driver == "kubernetes" {
|
||||||
|
// naming endpoint to make --append works
|
||||||
|
ep = fmt.Sprintf("%s://%s?deployment=%s", in.driver, in.name, in.nodeName)
|
||||||
|
}
|
||||||
|
|
||||||
m, err := csvToMap(in.driverOpts)
|
m, err := csvToMap(in.driverOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/docker/buildx/build"
|
"github.com/docker/buildx/build"
|
||||||
"github.com/docker/buildx/driver"
|
"github.com/docker/buildx/driver"
|
||||||
@ -192,8 +193,7 @@ func driversForNodeGroup(ctx context.Context, dockerCli command.Cli, ng *store.N
|
|||||||
if kcc == nil {
|
if kcc == nil {
|
||||||
kcc = driver.KubeClientConfigInCluster{}
|
kcc = driver.KubeClientConfigInCluster{}
|
||||||
}
|
}
|
||||||
|
d, err := driver.GetDriver(ctx, "buildx_buildkit_"+n.Name, f, dockerapi, kcc, n.Flags, n.ConfigFile, assignDriverOptsByDriverInfo(n.DriverOpts, di), contextPathHash)
|
||||||
d, err := driver.GetDriver(ctx, "buildx_buildkit_"+n.Name, f, dockerapi, kcc, n.Flags, n.ConfigFile, n.DriverOpts, contextPathHash)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
di.Err = err
|
di.Err = err
|
||||||
return nil
|
return nil
|
||||||
@ -211,6 +211,20 @@ func driversForNodeGroup(ctx context.Context, dockerCli command.Cli, ng *store.N
|
|||||||
return dis, nil
|
return dis, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pass platform as driver opts to provide for some drive, like kubernetes
|
||||||
|
func assignDriverOptsByDriverInfo(opts map[string]string, driveInfo build.DriverInfo) map[string]string {
|
||||||
|
m := map[string]string{}
|
||||||
|
|
||||||
|
if len(driveInfo.Platform) > 0 {
|
||||||
|
m["platform"] = strings.Join(platformutil.Format(driveInfo.Platform), ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
for key := range opts {
|
||||||
|
m[key] = opts[key]
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
// clientForEndpoint returns a docker client for an endpoint
|
// clientForEndpoint returns a docker client for an endpoint
|
||||||
func clientForEndpoint(dockerCli command.Cli, name string) (dockerclient.APIClient, error) {
|
func clientForEndpoint(dockerCli command.Cli, name string) (dockerclient.APIClient, error) {
|
||||||
list, err := dockerCli.ContextStore().List()
|
list, err := dockerCli.ContextStore().List()
|
||||||
@ -355,6 +369,9 @@ func loadNodeGroupData(ctx context.Context, dockerCli command.Cli, ngi *nginfo)
|
|||||||
if eg.Wait(); err != nil {
|
if eg.Wait(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// skip when multi drivers
|
||||||
|
if len(ngi.drivers) == 1 {
|
||||||
for _, di := range ngi.drivers {
|
for _, di := range ngi.drivers {
|
||||||
// dynamic nodes are used in Kubernetes driver.
|
// dynamic nodes are used in Kubernetes driver.
|
||||||
// Kubernetes pods are dynamically mapped to BuildKit Nodes.
|
// Kubernetes pods are dynamically mapped to BuildKit Nodes.
|
||||||
@ -375,6 +392,7 @@ func loadNodeGroupData(ctx context.Context, dockerCli command.Cli, ngi *nginfo)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,12 +4,15 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/buildx/driver"
|
"github.com/docker/buildx/driver"
|
||||||
"github.com/docker/buildx/driver/kubernetes/execconn"
|
"github.com/docker/buildx/driver/kubernetes/execconn"
|
||||||
|
"github.com/docker/buildx/driver/kubernetes/manifest"
|
||||||
"github.com/docker/buildx/driver/kubernetes/podchooser"
|
"github.com/docker/buildx/driver/kubernetes/podchooser"
|
||||||
"github.com/docker/buildx/store"
|
"github.com/docker/buildx/store"
|
||||||
|
"github.com/docker/buildx/util/platformutil"
|
||||||
"github.com/docker/buildx/util/progress"
|
"github.com/docker/buildx/util/progress"
|
||||||
"github.com/moby/buildkit/client"
|
"github.com/moby/buildkit/client"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -109,6 +112,16 @@ func (d *Driver) Info(ctx context.Context) (*driver.Info, error) {
|
|||||||
Name: p.Name,
|
Name: p.Name,
|
||||||
// Other fields are unset (TODO: detect real platforms)
|
// Other fields are unset (TODO: detect real platforms)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if p.Annotations != nil {
|
||||||
|
if p, ok := p.Annotations[manifest.AnnotationPlatform]; ok {
|
||||||
|
ps, err := platformutil.Parse(strings.Split(p, ","))
|
||||||
|
if err == nil {
|
||||||
|
node.Platforms = ps
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dynNodes = append(dynNodes, node)
|
dynNodes = append(dynNodes, node)
|
||||||
}
|
}
|
||||||
return &driver.Info{
|
return &driver.Info{
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/docker/buildx/driver/bkimage"
|
"github.com/docker/buildx/driver/bkimage"
|
||||||
"github.com/docker/buildx/driver/kubernetes/manifest"
|
"github.com/docker/buildx/driver/kubernetes/manifest"
|
||||||
"github.com/docker/buildx/driver/kubernetes/podchooser"
|
"github.com/docker/buildx/driver/kubernetes/podchooser"
|
||||||
|
"github.com/docker/buildx/util/platformutil"
|
||||||
dockerclient "github.com/docker/docker/client"
|
dockerclient "github.com/docker/docker/client"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
@ -90,6 +91,24 @@ func (f *factory) New(ctx context.Context, cfg driver.InitConfig) (driver.Driver
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
deploymentOpt.Image = bkimage.DefaultRootlessImage
|
deploymentOpt.Image = bkimage.DefaultRootlessImage
|
||||||
|
case "platform":
|
||||||
|
if v != "" {
|
||||||
|
platforms, err := platformutil.Parse(strings.Split(v, ","))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
deploymentOpt.Platforms = platforms
|
||||||
|
}
|
||||||
|
case "nodeselector":
|
||||||
|
kvs := strings.Split(strings.Trim(v, `"`), ",")
|
||||||
|
s := map[string]string{}
|
||||||
|
for i := range kvs {
|
||||||
|
kv := strings.Split(kvs[i], "=")
|
||||||
|
if len(kv) == 2 {
|
||||||
|
s[kv[0]] = kv[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deploymentOpt.NodeSelector = s
|
||||||
case "loadbalance":
|
case "loadbalance":
|
||||||
switch v {
|
switch v {
|
||||||
case LoadbalanceSticky:
|
case LoadbalanceSticky:
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
package manifest
|
package manifest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/docker/buildx/util/platformutil"
|
||||||
|
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
appsv1 "k8s.io/api/apps/v1"
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
@ -13,19 +17,28 @@ type DeploymentOpt struct {
|
|||||||
Replicas int
|
Replicas int
|
||||||
BuildkitFlags []string
|
BuildkitFlags []string
|
||||||
Rootless bool
|
Rootless bool
|
||||||
|
NodeSelector map[string]string
|
||||||
|
Platforms []v1.Platform
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
containerName = "buildkitd"
|
containerName = "buildkitd"
|
||||||
|
AnnotationPlatform = "buildx.docker.com/platform"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewDeployment(opt *DeploymentOpt) (*appsv1.Deployment, error) {
|
func NewDeployment(opt *DeploymentOpt) (*appsv1.Deployment, error) {
|
||||||
labels := map[string]string{
|
labels := map[string]string{
|
||||||
"app": opt.Name,
|
"app": opt.Name,
|
||||||
}
|
}
|
||||||
|
annotations := map[string]string{}
|
||||||
replicas := int32(opt.Replicas)
|
replicas := int32(opt.Replicas)
|
||||||
privileged := true
|
privileged := true
|
||||||
args := opt.BuildkitFlags
|
args := opt.BuildkitFlags
|
||||||
|
|
||||||
|
if len(opt.Platforms) > 0 {
|
||||||
|
annotations[AnnotationPlatform] = strings.Join(platformutil.Format(opt.Platforms), ",")
|
||||||
|
}
|
||||||
|
|
||||||
d := &appsv1.Deployment{
|
d := &appsv1.Deployment{
|
||||||
TypeMeta: metav1.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
APIVersion: appsv1.SchemeGroupVersion.String(),
|
APIVersion: appsv1.SchemeGroupVersion.String(),
|
||||||
@ -35,6 +48,7 @@ func NewDeployment(opt *DeploymentOpt) (*appsv1.Deployment, error) {
|
|||||||
Namespace: opt.Namespace,
|
Namespace: opt.Namespace,
|
||||||
Name: opt.Name,
|
Name: opt.Name,
|
||||||
Labels: labels,
|
Labels: labels,
|
||||||
|
Annotations: annotations,
|
||||||
},
|
},
|
||||||
Spec: appsv1.DeploymentSpec{
|
Spec: appsv1.DeploymentSpec{
|
||||||
Replicas: &replicas,
|
Replicas: &replicas,
|
||||||
@ -44,6 +58,7 @@ func NewDeployment(opt *DeploymentOpt) (*appsv1.Deployment, error) {
|
|||||||
Template: corev1.PodTemplateSpec{
|
Template: corev1.PodTemplateSpec{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Labels: labels,
|
Labels: labels,
|
||||||
|
Annotations: annotations,
|
||||||
},
|
},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
@ -72,6 +87,11 @@ func NewDeployment(opt *DeploymentOpt) (*appsv1.Deployment, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(opt.NodeSelector) > 0 {
|
||||||
|
d.Spec.Template.Spec.NodeSelector = opt.NodeSelector
|
||||||
|
}
|
||||||
|
|
||||||
return d, nil
|
return d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user