github.com/pachyderm/pachyderm@v1.13.4/src/server/cmd/worker/main.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"os"
     6  	"path"
     7  	"time"
     8  
     9  	"github.com/pachyderm/pachyderm/src/client"
    10  	debugclient "github.com/pachyderm/pachyderm/src/client/debug"
    11  	"github.com/pachyderm/pachyderm/src/client/pkg/errors"
    12  	"github.com/pachyderm/pachyderm/src/client/pkg/grpcutil"
    13  	"github.com/pachyderm/pachyderm/src/client/pkg/tracing"
    14  	"github.com/pachyderm/pachyderm/src/client/pps"
    15  	"github.com/pachyderm/pachyderm/src/client/version"
    16  	"github.com/pachyderm/pachyderm/src/client/version/versionpb"
    17  	"github.com/pachyderm/pachyderm/src/server/cmd/worker/assets"
    18  	debugserver "github.com/pachyderm/pachyderm/src/server/debug/server"
    19  	"github.com/pachyderm/pachyderm/src/server/pkg/cmdutil"
    20  	logutil "github.com/pachyderm/pachyderm/src/server/pkg/log"
    21  	"github.com/pachyderm/pachyderm/src/server/pkg/ppsutil"
    22  	"github.com/pachyderm/pachyderm/src/server/pkg/serviceenv"
    23  	"github.com/pachyderm/pachyderm/src/server/worker"
    24  	workerserver "github.com/pachyderm/pachyderm/src/server/worker/server"
    25  	"go.uber.org/automaxprocs/maxprocs"
    26  
    27  	etcd "github.com/coreos/etcd/clientv3"
    28  	log "github.com/sirupsen/logrus"
    29  )
    30  
    31  func main() {
    32  	log.SetFormatter(logutil.FormatterFunc(logutil.Pretty))
    33  	maxprocs.Set(maxprocs.Logger(log.Printf))
    34  
    35  	// Copy certs embedded via go-bindata to /etc/ssl/certs. Because the
    36  	// container running this app is user-specified, we don't otherwise have
    37  	// control over the certs that are available.
    38  	//
    39  	// If an error occurs, don't hard-fail, but do record if any certs are
    40  	// known to be missing so we can inform the user.
    41  	if err := assets.RestoreAssets("/", "etc/ssl/certs"); err != nil {
    42  		log.Warnf("failed to inject TLS certs: %v", err)
    43  	}
    44  
    45  	// append pachyderm bins to path to allow use of pachctl
    46  	os.Setenv("PATH", os.Getenv("PATH")+":/pach-bin")
    47  
    48  	cmdutil.Main(do, &serviceenv.WorkerFullConfiguration{})
    49  }
    50  
    51  // getPipelineInfo gets the PipelineInfo proto describing the pipeline that this
    52  // worker is part of.
    53  // getPipelineInfo has the side effect of adding auth to the passed pachClient
    54  // which is necessary to get the PipelineInfo from pfs.
    55  func getPipelineInfo(pachClient *client.APIClient, env *serviceenv.ServiceEnv) (*pps.PipelineInfo, error) {
    56  	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    57  	defer cancel()
    58  	resp, err := env.GetEtcdClient().Get(ctx, path.Join(env.PPSEtcdPrefix, "pipelines", env.PPSPipelineName))
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  	if len(resp.Kvs) != 1 {
    63  		return nil, errors.Errorf("expected to find 1 pipeline (%s), got %d: %v", env.PPSPipelineName, len(resp.Kvs), resp)
    64  	}
    65  	var pipelinePtr pps.EtcdPipelineInfo
    66  	if err := pipelinePtr.Unmarshal(resp.Kvs[0].Value); err != nil {
    67  		return nil, err
    68  	}
    69  	pachClient.SetAuthToken(pipelinePtr.AuthToken)
    70  	// Notice we use the SpecCommitID from our env, not from etcd. This is
    71  	// because the value in etcd might get updated while the worker pod is
    72  	// being created and we don't want to run the transform of one version of
    73  	// the pipeline in the image of a different verison.
    74  	pipelinePtr.SpecCommit.ID = env.PPSSpecCommitID
    75  	return ppsutil.GetPipelineInfo(pachClient, env.PPSPipelineName, &pipelinePtr)
    76  }
    77  
    78  func do(config interface{}) error {
    79  	// must run InstallJaegerTracer before InitWithKube/pach client initialization
    80  	tracing.InstallJaegerTracerFromEnv()
    81  	env := serviceenv.InitServiceEnv(serviceenv.NewConfiguration(config))
    82  
    83  	// Construct a client that connects to the sidecar.
    84  	pachClient := env.GetPachClient(context.Background())
    85  	pipelineInfo, err := getPipelineInfo(pachClient, env) // get pipeline creds for pachClient
    86  	if err != nil {
    87  		return errors.Wrapf(err, "error getting pipelineInfo")
    88  	}
    89  
    90  	// Construct worker API server.
    91  	workerRcName := ppsutil.PipelineRcName(pipelineInfo.Pipeline.Name, pipelineInfo.Version)
    92  	workerInstance, err := worker.NewWorker(pachClient, env.GetEtcdClient(), env.PPSEtcdPrefix, pipelineInfo, env.PodName, env.Namespace, env.CacheRoot, "/")
    93  	if err != nil {
    94  		return err
    95  	}
    96  
    97  	// Start worker api server
    98  	server, err := grpcutil.NewServer(context.Background(), false)
    99  	if err != nil {
   100  		return err
   101  	}
   102  
   103  	workerserver.RegisterWorkerServer(server.Server, workerInstance.APIServer)
   104  	versionpb.RegisterAPIServer(server.Server, version.NewAPIServer(version.Version, version.APIServerOptions{}))
   105  	debugclient.RegisterDebugServer(server.Server, debugserver.NewDebugServer(env, env.PodName, pachClient))
   106  
   107  	// Put our IP address into etcd, so pachd can discover us
   108  	key := path.Join(env.PPSEtcdPrefix, workerserver.WorkerEtcdPrefix, workerRcName, env.PPSWorkerIP)
   109  
   110  	// Prepare to write "key" into etcd by creating lease -- if worker dies, our
   111  	// IP will be removed from etcd
   112  	ctx, cancel := context.WithTimeout(pachClient.Ctx(), 10*time.Second)
   113  	defer cancel()
   114  
   115  	resp, err := env.GetEtcdClient().Grant(ctx, 10 /* seconds */)
   116  	if err != nil {
   117  		return errors.Wrapf(err, "error granting lease")
   118  	}
   119  
   120  	// keepalive forever
   121  	if _, err := env.GetEtcdClient().KeepAlive(context.Background(), resp.ID); err != nil {
   122  		return errors.Wrapf(err, "error with KeepAlive")
   123  	}
   124  
   125  	// Actually write "key" into etcd
   126  	ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second) // new ctx
   127  	defer cancel()
   128  	if _, err := env.GetEtcdClient().Put(ctx, key, "", etcd.WithLease(resp.ID)); err != nil {
   129  		return errors.Wrapf(err, "error putting IP address")
   130  	}
   131  
   132  	// If server ever exits, return error
   133  	if _, err := server.ListenTCP("", env.PPSWorkerPort); err != nil {
   134  		return err
   135  	}
   136  	return server.Wait()
   137  }