Files
fx-serverless/deploy/kubernetes/kubernetes.go
Changxin Miao 81e18e5b0d Deployment selector should be immutable (#316)
Signed-off-by: Changxin Miao <mcx_221@foxmail.com>
2019-10-14 11:55:08 +08:00

133 lines
2.7 KiB
Go

package kubernetes
import (
"context"
runtime "github.com/metrue/fx/container_runtimes/docker/sdk"
"github.com/metrue/fx/deploy"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
)
// K8S client
type K8S struct {
*kubernetes.Clientset
}
const namespace = "default"
// Create a k8s cluster client
func Create() (*K8S, error) {
config, err := clientcmd.BuildConfigFromKubeconfigGetter("", clientcmd.NewDefaultClientConfigLoadingRules().Load)
if err != nil {
return nil, err
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, err
}
return &K8S{clientset}, nil
}
// Deploy a image to be a service
func (k *K8S) Deploy(
ctx context.Context,
workdir string,
name string,
ports []int32,
) error {
dockerClient, err := runtime.CreateClient(ctx)
if err != nil {
return err
}
if err := dockerClient.BuildImage(ctx, workdir, name); err != nil {
return err
}
image, err := dockerClient.PushImage(ctx, name)
if err != nil {
return err
}
// By using a label selector between Pod and Service, we can link Service and Pod directly, it means a Endpoint will
// be created automatically, then incoming traffic to Service will be forward to Pod.
// Then we have no need to create Endpoint manually anymore.
selector := map[string]string{
"app": "fx-app-" + name,
}
const replicas = int32(3)
if _, err := k.GetDeployment(namespace, name); err != nil {
// TODO enable passing replica from fx CLI
if _, err := k.CreateDeployment(
namespace,
name,
image,
replicas,
selector,
); err != nil {
return err
}
} else {
if _, err := k.UpdateDeployment(namespace, name, image, replicas, selector); err != nil {
return err
}
}
// TODO fx should be able to know what's the target Kubernetes service platform
// it's going to deploy to
const isOnPublicCloud = true
typ := "LoadBalancer"
if !isOnPublicCloud {
typ = "NodePort"
}
if _, err := k.GetService(namespace, name); err != nil {
if _, err := k.CreateService(
namespace,
name,
typ,
ports,
selector,
); err != nil {
return err
}
} else {
if _, err := k.UpdateService(
namespace,
name,
typ,
ports,
selector,
); err != nil {
return err
}
}
return nil
}
// Update a service
func (k *K8S) Update(ctx context.Context, name string) error {
return nil
}
// Destroy a service
func (k *K8S) Destroy(ctx context.Context, name string) error {
if err := k.DeleteService(namespace, name); err != nil {
return err
}
if err := k.DeleteDeployment(namespace, name); err != nil {
return err
}
return nil
}
// GetStatus get status of a service
func (k *K8S) GetStatus(ctx context.Context, name string) error {
return nil
}
var (
_ deploy.Deployer = &K8S{}
)