mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-10 05:27:07 +08:00
new driver: kubernetes
Tested with `kind` and GKE. Note: "nodes" shown in `docker buildx ls` are unrelated to Kubernetes "nodes". Probably buildx should come up with an alternative term. Usage: $ kind create cluster $ export KUBECONFIG="$(kind get kubeconfig-path --name="kind")" $ docker buildx create --driver kubernetes --driver-opt replicas=3 --use $ docker buildx build -t foo --load . `--load` loads the image into the local Docker. Driver opts: - `image=IMAGE` - Sets the container image to be used for running buildkit. - `namespace=NS` - Sets the Kubernetes namespace. Defaults to the current namespace. - `replicas=N` - Sets the number of `Pod` replicas. Defaults to 1. - `rootless=(true|false)` - Run the container as a non-root user without `securityContext.privileged`. 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" Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
This commit is contained in:
97
driver/kubernetes/podchooser/podchooser.go
Normal file
97
driver/kubernetes/podchooser/podchooser.go
Normal file
@ -0,0 +1,97 @@
|
||||
package podchooser
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/rand"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/serialx/hashring"
|
||||
"github.com/sirupsen/logrus"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
clientcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
)
|
||||
|
||||
type PodChooser interface {
|
||||
ChoosePod(ctx context.Context) (*corev1.Pod, error)
|
||||
}
|
||||
|
||||
type RandomPodChooser struct {
|
||||
RandSource rand.Source
|
||||
PodClient clientcorev1.PodInterface
|
||||
Deployment *appsv1.Deployment
|
||||
}
|
||||
|
||||
func (pc *RandomPodChooser) ChoosePod(ctx context.Context) (*corev1.Pod, error) {
|
||||
pods, err := ListRunningPods(pc.PodClient, pc.Deployment)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
randSource := pc.RandSource
|
||||
if randSource == nil {
|
||||
randSource = rand.NewSource(time.Now().Unix())
|
||||
}
|
||||
rnd := rand.New(randSource)
|
||||
n := rnd.Int() % len(pods)
|
||||
logrus.Debugf("RandomPodChooser.ChoosePod(): len(pods)=%d, n=%d", len(pods), n)
|
||||
return pods[n], nil
|
||||
}
|
||||
|
||||
type StickyPodChooser struct {
|
||||
Key string
|
||||
PodClient clientcorev1.PodInterface
|
||||
Deployment *appsv1.Deployment
|
||||
}
|
||||
|
||||
func (pc *StickyPodChooser) ChoosePod(ctx context.Context) (*corev1.Pod, error) {
|
||||
pods, err := ListRunningPods(pc.PodClient, pc.Deployment)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var podNames []string
|
||||
podMap := make(map[string]*corev1.Pod, len(pods))
|
||||
for _, pod := range pods {
|
||||
podNames = append(podNames, pod.Name)
|
||||
podMap[pod.Name] = pod
|
||||
}
|
||||
ring := hashring.New(podNames)
|
||||
chosen, ok := ring.GetNode(pc.Key)
|
||||
if !ok {
|
||||
// NOTREACHED
|
||||
logrus.Errorf("no pod found for key %q", pc.Key)
|
||||
rpc := &RandomPodChooser{
|
||||
PodClient: pc.PodClient,
|
||||
Deployment: pc.Deployment,
|
||||
}
|
||||
return rpc.ChoosePod(ctx)
|
||||
}
|
||||
return podMap[chosen], nil
|
||||
}
|
||||
|
||||
func ListRunningPods(client clientcorev1.PodInterface, depl *appsv1.Deployment) ([]*corev1.Pod, error) {
|
||||
selector, err := metav1.LabelSelectorAsSelector(depl.Spec.Selector)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
listOpts := metav1.ListOptions{
|
||||
LabelSelector: selector.String(),
|
||||
}
|
||||
podList, err := client.List(listOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var runningPods []*corev1.Pod
|
||||
for i := range podList.Items {
|
||||
pod := &podList.Items[i]
|
||||
if pod.Status.Phase == corev1.PodRunning {
|
||||
logrus.Debugf("pod runnning: %q", pod.Name)
|
||||
runningPods = append(runningPods, pod)
|
||||
}
|
||||
}
|
||||
sort.Slice(runningPods, func(i, j int) bool {
|
||||
return runningPods[i].Name < runningPods[j].Name
|
||||
})
|
||||
return runningPods, nil
|
||||
}
|
Reference in New Issue
Block a user