diff --git a/compute/kubernetes/backend.go b/compute/kubernetes/backend.go index addd60363..6359ddf76 100644 --- a/compute/kubernetes/backend.go +++ b/compute/kubernetes/backend.go @@ -147,17 +147,11 @@ func (b *Backend) createJob(task *tes.Task) (*v1.Job, error) { "Cpus": res.GetCpuCores(), "RamGb": res.GetRamGb(), "DiskGb": res.GetDiskGb(), - // TODO: How to handle multiple executors/images? - "Image": task.Executors[0].Image, }) if err != nil { return nil, fmt.Errorf("executing template: %v", err) } - fmt.Println("DEBUG: task.Id:", task.Id) - fmt.Println("DEBUG: b.template:", b.template) - fmt.Println("DEBUG: buf.String():", buf.String()) - decode := scheme.Codecs.UniversalDeserializer().Decode obj, _, err := decode(buf.Bytes(), nil, nil) if err != nil { diff --git a/config/internal/bundle.go b/config/internal/bundle.go index 5ae7cb96e..2cf51a078 100644 --- a/config/internal/bundle.go +++ b/config/internal/bundle.go @@ -3,10 +3,10 @@ // config/gridengine-template.txt (346B) // config/pbs-template.txt (361B) // config/slurm-template.txt (415B) -// config/kubernetes-executor-template.yaml (1.135kB) +// config/kubernetes-executor-template.yaml (1.521kB) // config/default-config.yaml (11.655kB) // config/htcondor-template.txt (505B) -// config/kubernetes-template.yaml (1.354kB) +// config/kubernetes-template.yaml (1.785kB) package config @@ -134,7 +134,7 @@ func configSlurmTemplateTxt() (*asset, error) { return a, nil } -var _configKubernetesExecutorTemplateYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x54\x4f\x6f\xdb\x3e\x0c\xbd\xfb\x53\x10\x6e\x7f\xb7\xda\x75\x2f\xbf\x83\x81\x1d\x8a\x64\x48\x53\xac\x69\xb0\x05\xdd\x61\xd8\x41\x56\xe8\x44\xb3\xfe\x4d\x94\xd3\x05\x46\xbe\xfb\x20\x5b\x31\x9c\x0e\xeb\x74\x62\xf8\x1e\x1f\xf9\x08\xc6\xcc\x8a\x17\x74\x24\x8c\x2e\xa1\x62\x9e\xef\x6f\x0f\x77\x49\x23\xf4\xb6\x84\x47\x53\x25\x0a\x3d\xdb\x32\xcf\xca\x04\x40\x33\x85\x25\x74\x5d\xbe\x61\xd4\x2c\xb7\xa7\x53\xd6\x75\xf9\xa3\xa9\x42\x18\x61\xb2\x8c\x0f\x9c\xd5\xf9\x57\x8f\x49\x56\xa1\xa4\x20\x02\xf0\xc3\x54\xd9\xbb\x52\x64\x91\x97\x90\x00\x54\x8c\x37\xa6\xae\x3f\x09\x25\x7c\x09\x45\x02\xc0\x8d\xb2\x12\xbd\x30\x9a\x4a\xb8\x4b\x00\x3c\x2a\x2b\x99\xc7\x41\xba\xaf\xec\x23\x00\x87\xe4\x99\xf3\x6b\x23\x05\x3f\x96\xb0\xc2\x03\xba\x08\x11\xba\x83\xe0\x78\xcf\xb9\x69\xb5\x5f\xf5\xb3\xd4\xad\xd6\x28\x33\x62\x91\xc3\x8d\xf6\x4c\x68\x74\xd4\x8f\x12\x5e\x16\x37\x10\xa9\xaf\xc6\x35\xe8\xb2\x89\x89\xc8\x03\x10\x8a\xed\x06\x7f\xcb\x10\xbd\x45\xd6\xad\x94\xe7\xb9\xee\xe5\x2b\x3b\xd2\x88\x73\xa3\x14\x0b\xcb\xff\x96\xde\x56\x42\xdf\xd2\x3e\xbd\x81\x34\xe3\xe9\xf7\x91\xc2\xdc\x8e\x7a\xed\xd9\xc0\x9d\xa8\x87\x91\x84\xde\xcd\x85\xeb\x09\x5f\x8d\x6b\xb6\xc2\x4d\x08\x0e\xc9\xb4\x8e\x23\x95\x63\x2a\x24\x7f\xb6\x48\xfe\x22\x07\xc0\x6d\x1b\x44\x44\x0d\x1a\x21\x9f\xd9\x96\xa0\x80\xec\x74\x0a\x8d\x6d\x4b\x21\x00\x94\x84\x10\xa2\xf4\xae\x28\x54\x1a\x22\xbc\x18\x28\x3c\x85\xca\xb8\xe3\x44\xeb\x33\x53\x8b\x0a\x8a\x3c\xca\x59\x27\xb4\xaf\x21\xfd\x2f\x2f\xea\x45\x1a\xe1\x5e\x4a\x12\x0e\xe2\xff\x3f\xfd\x45\x1b\xed\x1e\x15\x3a\x26\x33\xf2\xc6\xc5\xa5\xc7\x36\x73\x41\xcd\x7b\x7d\x06\xfc\xb2\x51\x51\x4c\x3b\x8d\xad\x0e\x46\xb6\x0a\x9f\xc2\xb5\x4c\xb6\x74\x75\x75\x05\xf3\x67\x58\x3d\x6f\x60\xf6\x70\xbf\x5a\x7c\x84\xcd\xc3\xf2\xcb\x08\x77\x9d\x63\x7a\x87\x70\x2d\xb6\xbf\x6e\xe0\x5a\x78\x54\x50\x7e\x80\xfc\xa5\x17\xa3\x89\x93\xf3\x61\x45\x0f\x30\xb1\xa8\x42\xcf\x35\xf3\xfb\x60\xac\xd7\xc8\x67\xe7\xcb\x0c\xe9\x8b\x7d\x50\x5b\x8d\xd4\xf1\x28\xff\x55\xf6\xc6\xec\x60\xf5\xcf\xa3\x8f\xb3\x8d\x65\x36\x7c\x34\xc8\xa3\xf6\x83\x9f\x99\x64\x42\x4d\x2f\x88\x87\xc4\xc5\x7f\xcb\x1e\x38\xfc\x0e\x00\x00\xff\xff\x04\xcd\x20\x4b\x6f\x04\x00\x00") +var _configKubernetesExecutorTemplateYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x54\x4d\x8f\xdb\x36\x10\xbd\xfb\x57\x0c\xe4\x14\xbd\x44\x5a\xed\xa5\x07\x01\x3d\x2c\xbc\xdb\x8d\xd3\xac\xb3\xe8\x2e\xd2\x43\xd1\x03\x45\x8d\x24\xd6\xfc\x2a\x87\x74\x62\x18\xfe\xef\x05\x45\x59\x96\x1d\x74\xa3\xd3\x70\xe6\xf1\xcd\xbc\x99\xa1\x98\x15\x5f\xd0\x91\x30\xba\x82\x9a\x79\xde\xdf\xec\x6e\x17\x5b\xa1\x9b\x0a\x3e\x9a\x7a\xa1\xd0\xb3\x86\x79\x56\x2d\x00\x34\x53\x58\xc1\xe1\x50\xbc\x32\xda\xae\x9b\xe3\x31\x3f\x1c\x8a\x8f\xa6\x8e\xe6\x18\x26\xcb\x78\xc2\x6c\x4e\xa7\x21\x26\x59\x8d\x92\x22\x09\xc0\x3f\xa6\xce\xdf\xa4\x22\x8b\xbc\x82\x05\x40\xcd\xf8\xd6\xb4\xed\x27\xa1\x84\xaf\xa0\x5c\x00\x70\xa3\xac\x44\x2f\x8c\xa6\x0a\x6e\x17\x00\x1e\x95\x95\xcc\x63\xa2\x1e\x6e\x2e\x06\x13\x60\x09\x0f\x9a\x82\x43\x02\xdf\x33\x0f\xbe\x47\xf8\x6a\xdc\x16\x1d\x58\xd3\x80\x0b\x9a\xc0\xe8\xc1\x4d\x4c\x21\x68\xd3\x20\x30\x4a\x0e\x74\xbb\x84\x1b\xb9\x58\xdb\x0a\x2d\xfc\xbe\x1a\xcf\x10\x63\x77\xdf\x39\x01\x1c\xfe\x1b\x84\xc3\xe6\x3e\x38\xa1\xbb\x17\xde\x63\x13\xa4\xd0\xdd\xba\xd3\x66\x72\x3f\x7c\x43\x1e\xa2\x88\xf9\xcd\x3c\x35\xe9\x05\x25\x72\x6f\xdc\x3c\x14\x3f\x15\x67\xf3\x69\xd6\xc6\xf9\xc7\xac\xad\xa0\x0d\x5a\xa3\x8c\xba\x9f\x22\x76\x10\xf2\x5b\xf2\x9d\xf5\xfc\x4c\x29\xcd\x05\x85\x37\xd6\x48\xd3\xed\x7f\xc7\x7d\x05\xd9\x36\xd4\xe8\x34\x7a\xa4\x42\x98\x9b\xde\x90\x8f\xd3\xca\xce\x0d\x3d\xf7\xeb\xd4\x6a\x87\xe4\x99\xf3\xcf\x46\x0a\xbe\xaf\x60\x83\x3b\x74\x63\x28\xa6\x16\x1c\xef\x38\x37\x41\xfb\xcd\x30\xf7\x54\x69\x4e\x6c\xc4\x70\xa3\x3d\x13\x1a\x1d\x0d\x63\x4f\xdd\xd0\x73\x68\x1a\x5c\x3e\x5b\x98\x49\x80\x50\xac\x4b\xbb\xb4\x8e\xd6\x75\xe4\x39\x48\x79\xaa\xeb\x4e\x7e\x65\x7b\x9a\xe2\xdc\x28\xc5\xe2\xa2\xff\x95\xdd\xd4\x42\xdf\x50\x9f\xbd\x87\x2c\xe7\xd9\xdf\x13\x84\xb9\x8e\x06\xee\x55\xc2\xce\xd8\x63\x49\x42\x77\xf7\xc2\x0d\x80\x3f\x8d\xdb\x36\xc2\xcd\x00\x0e\xc9\x04\xc7\x91\xae\xf7\x03\xc9\x5f\xcd\x90\xdb\x10\x49\x44\x0b\x1a\xa1\x58\xd9\x40\x50\x42\x7e\x3c\xc6\xc4\x36\x50\x34\x00\x25\x21\x44\x2b\xbb\x2d\x4b\x95\x45\x0b\x2f\x0a\x1a\xb6\x04\x95\x71\xfb\x19\xd7\x1f\x4c\x3d\xd6\x50\x16\x23\x9d\x75\x42\xfb\x16\xb2\x9f\x8a\xb2\x7d\xcc\xc6\xf0\x40\x25\x09\x13\xf9\x2f\x4f\xff\xc3\x8d\xb6\x47\x85\x8e\xc9\x9c\xbc\x71\x63\xd3\xc7\x34\xf7\x82\xb6\x6f\xe5\x49\xf1\xcb\x44\x65\x39\xcf\x34\x3d\x5a\x80\x9d\x91\x41\xe1\x53\xdc\x97\xa9\x4f\xd1\xbf\x5c\x2e\xe1\xfe\x33\x6c\x3e\xbf\xc2\xea\xc3\xdd\xe6\xf1\x01\x5e\x3f\xac\x5f\x66\x80\xc3\xc1\x31\xdd\x21\xbc\x13\xcd\xb7\xf7\xf0\x4e\x78\x54\x50\xfd\x0a\xc5\x97\x81\x90\x26\x3d\xcb\xd9\x82\x8d\x5a\x60\x16\x02\x50\x31\xf7\x33\xf3\x7d\x94\x38\xf0\x14\xab\xd3\x8e\x46\xf7\x05\x13\x00\x85\x7a\x02\x4f\x0b\xfa\xe3\x8b\xdf\x49\x4f\xc2\xcf\x8f\x60\x79\x5d\xe5\xec\xb2\x8d\x3f\x6d\xf2\xa8\x7d\x52\xb7\x92\x4c\xa8\xea\xa2\x2c\x1e\x5d\x17\x2f\xce\xee\x38\xfc\x17\x00\x00\xff\xff\x52\x41\x10\x0e\xf1\x05\x00\x00") func configKubernetesExecutorTemplateYamlBytes() ([]byte, error) { return bindataRead( @@ -149,8 +149,8 @@ func configKubernetesExecutorTemplateYaml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "config/kubernetes-executor-template.yaml", size: 1135, mode: os.FileMode(0644), modTime: time.Unix(1729109797, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd2, 0x50, 0x93, 0xa6, 0xe6, 0xeb, 0xd, 0x68, 0x45, 0x70, 0x64, 0xcc, 0x9c, 0xdd, 0xbf, 0x81, 0xd4, 0xd, 0xa9, 0x8d, 0xdd, 0xba, 0xe7, 0xa9, 0x23, 0xa, 0x69, 0xa5, 0x10, 0xdd, 0xd8, 0xf7}} + info := bindataFileInfo{name: "config/kubernetes-executor-template.yaml", size: 1521, mode: os.FileMode(0644), modTime: time.Unix(1730912888, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x59, 0x92, 0x28, 0x98, 0xde, 0x1c, 0xe2, 0x20, 0xc2, 0x47, 0x66, 0x4c, 0x5d, 0x7e, 0xfd, 0x12, 0x52, 0x5c, 0x93, 0x94, 0x63, 0xa6, 0x33, 0x67, 0xe6, 0x7a, 0x21, 0x75, 0x90, 0xa, 0xe3, 0xb9}} return a, nil } @@ -169,7 +169,7 @@ func configDefaultConfigYaml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "config/default-config.yaml", size: 11655, mode: os.FileMode(0644), modTime: time.Unix(1729212983, 0)} + info := bindataFileInfo{name: "config/default-config.yaml", size: 11655, mode: os.FileMode(0644), modTime: time.Unix(1729641602, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x61, 0x5a, 0x7d, 0xb0, 0x9b, 0x9d, 0x13, 0x7, 0x49, 0xd0, 0x4c, 0xab, 0xc2, 0xe5, 0x37, 0xfa, 0x4a, 0x5a, 0x9a, 0x68, 0x89, 0x2b, 0x4b, 0x3e, 0xf3, 0x73, 0x35, 0x82, 0xe8, 0xf1, 0xbf, 0x3c}} return a, nil } @@ -194,7 +194,7 @@ func configHtcondorTemplateTxt() (*asset, error) { return a, nil } -var _configKubernetesTemplateYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x9c\x54\xc9\x6e\xdb\x30\x10\xbd\xeb\x2b\x06\x0a\x7a\xd4\x92\x4b\x0f\xbc\x19\x49\x90\xa6\xa8\x95\xa0\x08\x72\xa7\xe8\x91\x4d\x98\x5b\xb8\x38\x30\x04\xfd\x7b\x41\x51\x6e\x2d\x6f\x87\xf2\x44\xce\x1b\xbe\xf7\x66\x38\x12\x35\xfc\x03\xad\xe3\x5a\x11\x68\xa9\x67\x9b\x6a\x77\x9f\x6d\xb9\x5a\x11\xf8\xa9\xdb\x4c\xa2\xa7\x2b\xea\x29\xc9\x00\xee\xee\xe0\xf1\x15\x9a\xd7\x77\x78\xf8\xb1\x68\x9e\x9f\xa0\x59\x2c\x9f\x32\x00\x45\x25\x12\xe8\xfb\xf2\x9d\xba\xed\xcb\x6a\x18\xa6\x98\x33\x94\x25\xa0\x39\x9c\x86\x21\x73\x06\x19\x81\x0c\xa0\xa5\x6c\xab\xbb\xee\x17\x97\xdc\x13\xa8\x33\x00\xa6\xa5\x11\xe8\xb9\x56\x8e\xc0\x7d\x06\xe0\x51\x1a\x41\x3d\x46\x75\x80\xf1\xe6\xb8\x03\x70\x68\x77\x9c\xe1\x82\x31\x1d\x94\x6f\x46\x07\x5d\x50\x0a\x45\xe1\xe8\x94\x63\xd1\x79\x6a\xfd\x9b\x16\x9c\xed\x09\x34\xb8\x43\x3b\x41\x4c\x2b\x4f\xb9\x42\xeb\x46\x2b\x69\x15\x53\x25\x13\xcf\x97\xb6\x5b\xb4\xc5\xbc\xae\xc3\xe2\x92\xae\x91\xc0\x67\xa0\xfb\x92\xeb\x4a\x6f\x5c\x28\xa2\xfd\xa2\xe5\xba\x4a\x04\xa4\xef\xcb\x97\x98\x76\x7e\xf1\x2d\x08\x71\xb0\xb5\x10\x5f\x74\xef\x8e\x32\xa8\x5d\x3b\x72\x74\x8e\xc6\xf2\x64\x26\x3f\x0d\xdb\xa0\xce\x62\x45\xc1\xb4\xea\xf8\xfa\x0c\xa8\xd0\xb3\x2a\x61\xd5\xac\xc6\x72\x4f\xa5\xb8\xc0\xe3\x63\xdd\x8f\xa7\xc0\xe5\x86\x58\x74\x3a\x58\x86\x27\xd6\x23\xf0\x19\xd0\xf9\xb3\x38\x00\x33\x21\x4e\x07\xef\x40\x21\x94\x0f\x26\x38\xa8\xa1\x18\x86\xbe\x1f\x0f\x71\x03\x28\x1c\x42\xdc\xe5\xf7\x75\x2d\xf3\xb8\x43\x35\x57\x4e\x4b\xa2\xd4\x76\x7f\xc4\xf7\x9b\xca\xe7\x16\xea\x72\xa2\x34\x96\x2b\xdf\x41\xfe\xad\xac\xbb\xe7\x7c\x82\x47\x3a\xe1\x30\x09\x7c\x5f\xde\xe0\x47\xb3\x41\x89\x96\x8a\xc2\x79\x6d\xc7\xc7\xff\x2b\xf5\xc8\xdd\xf6\x96\x56\xc2\xe7\x62\x75\x7d\x59\x6d\xa7\x45\x90\xb8\x8c\x53\x7d\x36\x05\xb3\xf1\x9c\x6c\x5c\x99\xcf\xb1\x25\x91\xe4\x8d\xfa\x0d\x81\x4a\x1b\x3f\xbd\xf9\xf1\xd3\x17\x2b\x6e\xab\xeb\x04\x2e\xb4\xe9\xfa\xb5\x94\x83\xa5\x34\x54\x45\xf2\x7e\xc3\xc5\xbf\x01\xcc\xb2\xe3\x72\x2f\x7d\x85\xd7\x38\x53\x7c\x49\xcd\xbc\x3b\xb3\xde\x4c\x1a\xff\xd5\x39\x13\xff\x86\xce\xa3\xf2\x1f\xa3\xf4\x83\xa0\x5c\xce\xb5\x58\x0c\xcd\xfe\x39\x66\xc7\xe0\x4f\x00\x00\x00\xff\xff\x8f\xdc\x15\xbd\x4a\x05\x00\x00") +var _configKubernetesTemplateYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x9c\x55\x4d\x93\xa3\x36\x10\xbd\xf3\x2b\xba\x70\xa5\x72\xc2\x30\x97\x1c\xb8\xa4\x5c\xe3\xc9\x64\x93\xb5\x67\x2a\x33\xb5\x77\x21\x1a\xa3\xb2\xbe\x56\x1f\xde\x50\x2e\xff\xf7\x94\x10\xac\x01\x7b\xe6\x10\x5d\x10\xdd\xad\xf7\xba\x5f\xb7\x80\x68\xf6\x0d\x8d\x65\x4a\x96\x50\x11\x47\xdb\xfc\xf4\x90\x1c\x99\xac\x4b\xf8\x4b\x55\x89\x40\x47\x6a\xe2\x48\x99\x00\xac\x56\xb0\x7d\x81\xfd\xcb\x3b\x3c\xfe\xb9\xd9\x3f\x3f\xc1\x7e\xb3\x7b\x4a\x00\x24\x11\x58\xc2\xf9\xbc\x7e\x27\xf6\xf8\xa5\xbe\x5c\x06\x9b\xd5\x84\x46\xc7\x7e\x7c\xbb\x5c\x12\xab\x91\x96\x90\x00\x54\x84\x1e\x55\xd3\x7c\x65\x82\xb9\x12\x8a\x04\x80\x2a\xa1\x39\x3a\xa6\xa4\x2d\xe1\x21\x01\x70\x28\x34\x27\x0e\x03\x3b\x40\x7f\xb2\xdf\x01\x58\x34\x27\x46\x71\x43\xa9\xf2\xd2\xed\xfb\x0c\x1a\x2f\x25\xf2\xcc\x92\x21\x06\x86\xe7\x0a\x9e\xa4\xf5\x06\x2d\xb8\x96\x38\x70\x2d\xc2\x0f\x65\x8e\x68\x40\xab\x1a\x8c\x97\x16\x94\xec\xcd\x96\x08\x04\xa9\x6a\x04\x62\xa3\x01\xcd\x29\xc6\x0d\x58\xa4\x69\x98\x64\xae\x1b\xf3\x80\xe0\xdb\xdc\x18\x01\x0c\x7e\xf7\xcc\x60\xbd\xf5\x86\xc9\xc3\x1b\x6d\xb1\xf6\x9c\xc9\xc3\x97\x83\x54\x3f\xcd\x4f\xff\x22\xf5\xa1\xde\xe9\xc9\x0c\x38\xa9\x90\xbf\x21\x47\xea\x94\x99\xba\xc2\x12\xa1\x49\x5f\x43\x84\x5d\xba\x00\x88\xd6\xa3\x0e\xa1\xee\x5d\x88\xed\x0b\xf9\x23\xda\xae\xf5\xfc\x6a\x23\xcd\x0c\xc2\x29\xad\xb8\x3a\x74\x7f\x63\x57\x42\x7a\xf4\x15\x1a\x89\x0e\xed\x9a\xa9\xbc\x55\xd6\x85\xae\xa6\x57\x41\xaf\x7a\x25\xc9\x58\xb5\x75\xc4\xb8\x57\xc5\x19\xed\x4a\xd8\xe3\x09\xcd\xe0\xa2\x4a\x3a\xc2\x24\x1a\x5b\x42\x72\xad\x55\x4e\x5b\x17\xdb\x92\xcd\x47\x69\x5c\x2b\x78\x7f\xd9\xbe\x94\xf0\xd6\x2a\xcf\x6b\x70\x2d\xb3\x50\x61\xc0\x6d\xd8\xc1\x1b\x52\x71\xfc\x7d\x12\xce\x04\x39\x60\x09\xdf\x3d\xe9\x42\xfa\xaa\xb5\x3e\x0b\x03\x96\x55\x4c\xe5\x91\xaf\xac\xf1\x84\x5c\x69\x81\xd2\x2d\x4f\xbe\x7a\xce\xc7\x32\x36\xfc\x07\xe9\xec\x24\x82\x98\xc3\x42\xfc\x0c\xd2\x98\x7c\xba\x34\x1b\x2f\x6f\x6c\x59\x16\xb3\xbe\x71\xe4\xe8\x68\x1e\x7d\xf9\x4c\x93\x75\x47\x04\xbf\x83\xe3\x82\x4e\xdb\xa5\xe3\xbe\x80\x06\xad\xf2\x86\xe2\xcd\xdc\x84\x59\x45\xeb\xee\xcc\x13\xd5\x3e\x5c\x60\xd6\x80\x44\x58\x3f\x6a\x6f\xa1\x80\xec\x72\x39\x9f\xfb\x97\xb0\x01\xe4\x16\x21\xec\xd2\x87\xa2\x10\x69\xd8\xa1\x9c\x33\xc7\x25\x50\x28\xd3\x4d\xf0\xfe\x21\xe2\xb9\x82\x62\x3d\x40\x6a\xc3\xa4\x6b\x20\xfd\x65\x5d\x34\xcf\xe9\xe0\xee\xe1\xb8\xc5\x48\xf0\xdb\xee\x13\x7c\xd4\x2d\x0a\x34\x84\x67\xd6\x29\xd3\x77\xff\x27\xd5\x96\xd9\xe3\x67\x5c\xd1\x3f\x27\x2b\x8a\xfb\x6c\x27\xc5\xbd\xc0\x5d\xf8\xf0\x2c\x24\x5b\x2d\x07\x7a\x48\xe4\x83\x89\x0e\x07\x00\x44\x00\x7a\x25\xae\x2d\x21\x57\xda\x0d\x7d\x9f\xb6\x3f\xab\x99\xc9\x3f\x83\xb0\xbe\x8a\x00\x1f\x05\x8d\x69\xc5\xd1\xca\x62\x05\xcb\x0f\xcb\x24\x8f\xeb\x18\x8e\x37\x3b\x1e\xb9\x77\x77\x3f\xc2\x8c\xf6\x1d\xd1\x73\x8d\x66\xfa\x0c\x1c\xff\x4b\xbf\x50\xb8\x0e\xbf\x2e\xeb\x50\xba\x6f\x3d\xfd\x23\x27\x4c\x94\xb3\x10\x00\x1a\x8c\xb3\x5f\x84\x3e\x51\xf8\x2f\x00\x00\xff\xff\x71\xbc\x58\x2c\xf9\x06\x00\x00") func configKubernetesTemplateYamlBytes() ([]byte, error) { return bindataRead( @@ -209,8 +209,8 @@ func configKubernetesTemplateYaml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "config/kubernetes-template.yaml", size: 1354, mode: os.FileMode(0644), modTime: time.Unix(1729214525, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7f, 0x59, 0x5d, 0x1c, 0xec, 0xeb, 0x76, 0x2c, 0x4e, 0xe3, 0xe4, 0x89, 0x72, 0xc4, 0xde, 0x87, 0x68, 0x66, 0x9b, 0xc7, 0x30, 0x87, 0xd8, 0x56, 0xc4, 0xd8, 0x38, 0xef, 0x82, 0xa0, 0x2b, 0x62}} + info := bindataFileInfo{name: "config/kubernetes-template.yaml", size: 1785, mode: os.FileMode(0644), modTime: time.Unix(1730912881, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1f, 0x41, 0xd9, 0xeb, 0x65, 0x4e, 0x19, 0x40, 0xd3, 0x9b, 0xbe, 0x1, 0xe, 0xb5, 0xa8, 0x2f, 0xaa, 0x21, 0xd7, 0x2a, 0x40, 0xd6, 0x36, 0x60, 0x2c, 0xe2, 0x5c, 0x9d, 0x5a, 0x9d, 0xd1, 0x2}} return a, nil } diff --git a/config/kubernetes-executor-template.yaml b/config/kubernetes-executor-template.yaml index ab41fe16b..a8ba9d1e6 100644 --- a/config/kubernetes-executor-template.yaml +++ b/config/kubernetes-executor-template.yaml @@ -14,8 +14,7 @@ spec: serviceAccountName: funnel-sa containers: - name: funnel-worker-{{.TaskId}} - # TODO: Should this be configurable? - image: quay.io/ohsu-comp-bio/funnel:development + image: {{.Image}} imagePullPolicy: Always command: ["/bin/sh", "-c"] args: {{.Command}} @@ -26,15 +25,15 @@ spec: memory: {{if ne .RamGb 0.0 -}}{{printf "%.0fG" .RamGb}}{{else}}{{"16M"}}{{end}} ephemeral-storage: {{if ne .DiskGb 0.0 -}}{{printf "%.0fG" .DiskGb}}{{else}}{{"100M"}}{{end}} - volumeMounts: - ### DO NOT CHANGE THIS - {{range $idx, $item := .Volumes}} - - name: storage - mountPath: {{$item.ContainerPath}} - subPath: {{$.TaskId}}{{$item.ContainerPath}} - {{end}} + # volumeMounts: + # ### DO NOT CHANGE THIS + # {{range $idx, $item := .Volumes}} + # - name: storage + # mountPath: {{$item.ContainerPath}} + # subPath: {{$.TaskId}}{{$item.ContainerPath}} + # {{end}} - volumes: - - name: storage - persistentVolumeClaim: - claimName: funnel-pvc \ No newline at end of file + # volumes: + # - name: storage + # persistentVolumeClaim: + # claimName: funnel-pvc \ No newline at end of file diff --git a/config/kubernetes-template.yaml b/config/kubernetes-template.yaml index e832fac79..0e02cb6bf 100644 --- a/config/kubernetes-template.yaml +++ b/config/kubernetes-template.yaml @@ -29,9 +29,9 @@ spec: memory: {{if ne .RamGb 0.0 -}}{{printf "%.0fG" .RamGb}}{{else}}{{"16M"}}{{end}} ephemeral-storage: {{if ne .DiskGb 0.0 -}}{{printf "%.0fG" .DiskGb}}{{else}}{{"100M"}}{{end}} volumeMounts: - - name: funnel-storage-{{.TaskId}} - mountPath: /opt/funnel/funnel-work-dir/{{.TaskId}} - subPath: {{.TaskId}} + # - name: funnel-storage-{{.TaskId}} + # mountPath: /opt/funnel/funnel-work-dir/{{.TaskId}} + # subPath: {{.TaskId}} - name: config-volume mountPath: /etc/config @@ -39,6 +39,6 @@ spec: - name: config-volume configMap: name: funnel-config - - name: funnel-storage-{{.TaskId}} - persistentVolumeClaim: - claimName: funnel-pvc \ No newline at end of file + # - name: funnel-storage-{{.TaskId}} + # persistentVolumeClaim: + # claimName: funnel-pvc \ No newline at end of file diff --git a/deployments/kubernetes/helm/.cr-release-packages/funnel-0.1.9.tgz b/deployments/kubernetes/helm/.cr-release-packages/funnel-0.1.9.tgz new file mode 100644 index 000000000..9309f792a Binary files /dev/null and b/deployments/kubernetes/helm/.cr-release-packages/funnel-0.1.9.tgz differ diff --git a/deployments/kubernetes/helm/funnel-0.1.2.tgz b/deployments/kubernetes/helm/funnel-0.1.2.tgz new file mode 100644 index 000000000..bb33009c3 Binary files /dev/null and b/deployments/kubernetes/helm/funnel-0.1.2.tgz differ diff --git a/deployments/kubernetes/helm/funnel/Chart.yaml b/deployments/kubernetes/helm/funnel/Chart.yaml new file mode 100644 index 000000000..0200095f7 --- /dev/null +++ b/deployments/kubernetes/helm/funnel/Chart.yaml @@ -0,0 +1,26 @@ +apiVersion: v2 +name: funnel +description: A toolkit for distributed task execution ⚙️ +keywords: + - funnel + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.10 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.11.0" diff --git a/deployments/kubernetes/helm/funnel/config/funnel-server.yaml b/deployments/kubernetes/helm/funnel/config/funnel-server.yaml new file mode 100644 index 000000000..29812b538 --- /dev/null +++ b/deployments/kubernetes/helm/funnel/config/funnel-server.yaml @@ -0,0 +1,90 @@ +Compute: {{ .Values.Compute }} + +Kubernetes: + Executor: "kubernetes" + Namespace: {{ .Release.Namespace }} + +Database: {{ .Values.Database }} + +EventWriters: + {{- range .Values.EventWriters }} + - {{ . }} + {{- end }} + +Logger: + Level: {{ .Values.Logger.Level }} + OutputFile: {{ .Values.Logger.OutputFile }} + +Server: + HostName: {{ .Values.Server.Hostname }} + HTTPPort: {{ .Values.Server.HttpPort }} + RPCPort: {{ .Values.Server.RpcPort }} + DisableHTTPCache: {{ .Values.Server.DisableHttpCache }} + +RPCClient: + ServerAddress: {{ .Values.RPCClient.ServerAddress }} + Timeout: {{ .Values.RPCClient.Timeout }} + MaxRetries: {{ .Values.RPCClient.MaxRetries }} + +Scheduler: + ScheduleRate: {{ .Values.Scheduler.ScheduleRate }} + ScheduleChunk: {{ .Values.Scheduler.ScheduleChunk }} + NodePingTimeout: {{ .Values.Scheduler.NodePingTimeout }} + NodeInitTimeout: {{ .Values.Scheduler.NodeInitTimeout }} + +Node: + ID: {{ .Values.Node.Id }} + Timeout: {{ .Values.Node.Timeout }} + UpdateRate: {{ .Values.Node.UpdateRate }} + Resources: + Cpus: {{ .Values.Node.Resources.cpus }} + RamGb: {{ .Values.Node.Resources.ramGb }} + DiskGb: {{ .Values.Node.Resources.diskGb }} + +Worker: + WorkDir: {{ .Values.Worker.WorkDir }} + PollingRate: {{ .Values.Worker.PollingRate }} + LogUpdateRate: {{ .Values.Worker.LogUpdateRate }} + LogTailSize: {{ .Values.Worker.LogTailSize }} + LeaveWorkDir: {{ .Values.Worker.LeaveWorkDir }} + MaxParallelTransfers: {{ .Values.Worker.MaxParallelTransfers }} + +BoltDB: + Path: {{ .Values.BoltDB.Path }} + +AmazonS3: + Disabled: {{ .Values.AmazonS3.Disabled }} + MaxRetries: {{ .Values.AmazonS3.MaxRetries }} + Key: {{ .Values.AmazonS3.Key }} + Secret: {{ .Values.AmazonS3.Secret }} + +DynamoDB: + TableBasename: {{ .Values.DynamoDB.TableBasename }} + Region: {{ .Values.DynamoDB.Region }} + Key: {{ .Values.DynamoDB.Key }} + Secret: {{ .Values.DynamoDB.Secret }} + +Elastic: + IndexPrefix: {{ .Values.Elastic.IndexPrefix }} + URL: {{ .Values.Elastic.Url }} + +Datastore: + Project: {{ .Values.Datastore.Project }} + CredentialsFile: {{ .Values.Datastore.CredentialsFile }} + +MongoDB: + Addrs: + {{- range .Values.MongoDB.Addrs }} + - {{ . }} + {{- end }} + Database: {{ .Values.MongoDB.Database }} + Timeout: {{ .Values.MongoDB.Timeout }} + Username: {{ .Values.MongoDB.Username }} + Password: {{ .Values.MongoDB.Password }} + +Kafka: + Servers: + {{- range .Values.Kafka.Servers }} + - {{ . }} + {{- end }} + Topic: {{ .Values.Kafka.Topic }} diff --git a/deployments/kubernetes/helm/funnel/config/funnel-worker.yaml b/deployments/kubernetes/helm/funnel/config/funnel-worker.yaml new file mode 100644 index 000000000..5f2a3cb61 --- /dev/null +++ b/deployments/kubernetes/helm/funnel/config/funnel-worker.yaml @@ -0,0 +1,37 @@ +Database: {{ .Values.Database }} + +Compute: {{ .Values.Compute }} + +Kubernetes: + Executor: "kubernetes" + Namespace: {{ .Release.Namespace }} + +Logger: + Level: {{ .Values.Logger.level }} + +RPCClient: + MaxRetries: {{ .Values.RPCClient.maxRetries }} + Timeout: {{ .Values.RPCClient.timeout }} + +EventWriters: + {{- range .Values.EventWriters }} + - {{ . }} + {{- end }} + +AmazonS3: + Disabled: {{ .Values.AmazonS3.Disabled }} + MaxRetries: {{ .Values.AmazonS3.MaxRetries }} + Key: {{ .Values.AmazonS3.Key }} + Secret: {{ .Values.AmazonS3.Secret }} + +Server: + HostName: funnel.{{ .Release.Namespace }}.svc.cluster.local + RPCPort: {{ .Values.Server.RPCPort }} + +Worker: + WorkDir: {{ .Values.Worker.WorkDir }} + PollingRate: {{ .Values.Worker.PollingRate }} + LogUpdateRate: {{ .Values.Worker.LogUpdateRate }} + LogTailSize: {{ .Values.Worker.LogTailSize }} + LeaveWorkDir: {{ .Values.Worker.LeaveWorkDir }} + MaxParallelTransfers: {{ .Values.Worker.MaxParallelTransfers }} diff --git a/deployments/kubernetes/helm/funnel/index.yaml b/deployments/kubernetes/helm/funnel/index.yaml new file mode 100644 index 000000000..51993774e --- /dev/null +++ b/deployments/kubernetes/helm/funnel/index.yaml @@ -0,0 +1,3 @@ +apiVersion: v1 +entries: {} +generated: "2024-10-15T13:51:54.600981-07:00" diff --git a/deployments/kubernetes/helm/funnel/templates/NOTES.txt b/deployments/kubernetes/helm/funnel/templates/NOTES.txt new file mode 100644 index 000000000..19666b112 --- /dev/null +++ b/deployments/kubernetes/helm/funnel/templates/NOTES.txt @@ -0,0 +1,5 @@ +1. To access the Funnel application, use the following instructions: + +To access the service locally, use: + kubectl --namespace {{ .Release.Namespace }} port-forward svc/{{ include "funnel.fullname" . }} 8000:8000 + echo "Visit http://127.0.0.1:8000" diff --git a/deployments/kubernetes/helm/funnel/templates/_helpers.tpl b/deployments/kubernetes/helm/funnel/templates/_helpers.tpl new file mode 100644 index 000000000..a16e840ba --- /dev/null +++ b/deployments/kubernetes/helm/funnel/templates/_helpers.tpl @@ -0,0 +1,67 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "funnel.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "funnel.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "funnel.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "funnel.labels" -}} +helm.sh/chart: {{ include "funnel.chart" . }} +{{ include "funnel.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Values.labels }} +{{- range $key, $value := . }} +{{ $key }}: {{ $value | quote }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "funnel.selectorLabels" -}} +app.kubernetes.io/name: {{ include "funnel.name" . }} +app.kubernetes.io/instance: funnel +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "funnel.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "funnel.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/deployments/kubernetes/helm/funnel/templates/configmap.yaml b/deployments/kubernetes/helm/funnel/templates/configmap.yaml new file mode 100644 index 000000000..af5cc2803 --- /dev/null +++ b/deployments/kubernetes/helm/funnel/templates/configmap.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: funnel-config + namespace: {{ .Release.Namespace }} + +data: + funnel-server.yaml: |- +{{ tpl (.Files.Get "config/funnel-server.yaml") . | indent 4 }} + + funnel-worker.yaml: |- +{{ tpl (.Files.Get "config/funnel-worker.yaml") . | indent 4 }} diff --git a/deployments/kubernetes/helm/funnel/templates/deployment.yaml b/deployments/kubernetes/helm/funnel/templates/deployment.yaml new file mode 100644 index 000000000..ccbed5e15 --- /dev/null +++ b/deployments/kubernetes/helm/funnel/templates/deployment.yaml @@ -0,0 +1,75 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "funnel.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "funnel.labels" . | nindent 4 }} +spec: + replicas: 1 + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 # This ensures only one pod is unavailable during the update process + maxSurge: 0 # No new pod is created until the old one is fully terminated + selector: + matchLabels: + {{- include "funnel.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "funnel.labels" . | nindent 8 }} + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + checksum/values: {{ .Values | quote | sha256sum }} + spec: + serviceAccountName: {{ include "funnel.serviceAccountName" . }} + containers: + - name: funnel + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: Always + command: + - 'funnel' + - 'server' + - 'run' + - '--config' + - '/etc/config/funnel-server.yaml' + resources: + requests: + cpu: {{ .Values.resources.requests.cpu }} + memory: {{ .Values.resources.requests.memory }} + limits: + cpu: {{ .Values.resources.limits.cpu }} + memory: {{ .Values.resources.limits.memory }} + ports: + - name: http + containerPort: 8000 + - name: rpc + containerPort: 9090 + readinessProbe: + httpGet: + path: /healthz + port: 8000 + periodSeconds: 10 + timeoutSeconds: 3 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /healthz + port: 8000 + periodSeconds: 20 + timeoutSeconds: 5 + failureThreshold: 3 + volumeMounts: + - name: funnel-deployment-storage + mountPath: /opt/funnel/funnel-work-dir + - name: config-volume + mountPath: /etc/config + volumes: + - name: funnel-deployment-storage + persistentVolumeClaim: + claimName: funnel-pvc + - name: config-volume + configMap: + name: funnel-config diff --git a/deployments/kubernetes/helm/funnel/templates/pv.yaml b/deployments/kubernetes/helm/funnel/templates/pv.yaml new file mode 100644 index 000000000..8c24b1ea9 --- /dev/null +++ b/deployments/kubernetes/helm/funnel/templates/pv.yaml @@ -0,0 +1,20 @@ +{{- if .Values.storage.pv.enabled }} +apiVersion: v1 +kind: PersistentVolume +metadata: + name: funnel-pv + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: funnel + app.kubernetes.io/instance: funnel +spec: + capacity: + storage: {{ .Values.storage.size }} + accessModes: + - ReadWriteOnce + storageClassName: {{ .Values.storage.className }} + volumeMode: {{ .Values.storage.volumeMode }} + persistentVolumeReclaimPolicy: {{ .Values.storage.pv.reclaimPolicy }} + hostPath: + path: {{ .Values.storage.path | default "/mnt/data" }} +{{- end }} diff --git a/deployments/kubernetes/helm/funnel/templates/pvc.yaml b/deployments/kubernetes/helm/funnel/templates/pvc.yaml new file mode 100644 index 000000000..734de399a --- /dev/null +++ b/deployments/kubernetes/helm/funnel/templates/pvc.yaml @@ -0,0 +1,21 @@ +{{- if .Values.storage.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ .Release.Name }}-pvc + namespace: {{ .Release.Namespace }} + labels: + app: {{ .Chart.Name }} + release: {{ .Release.Name }} + annotations: + "helm.sh/resource-policy": "keep" # Ensures Helm doesn't delete this PVC +spec: + accessModes: + - {{ .Values.storage.accessMode | default "ReadWriteOnce" }} + resources: + requests: + storage: {{ .Values.storage.size | default "10Gi" }} + {{- if .Values.storage.className }} + storageClassName: {{ .Values.storage.className | quote }} + {{- end }} +{{- end }} diff --git a/deployments/kubernetes/helm/funnel/templates/role.yaml b/deployments/kubernetes/helm/funnel/templates/role.yaml new file mode 100644 index 000000000..174813151 --- /dev/null +++ b/deployments/kubernetes/helm/funnel/templates/role.yaml @@ -0,0 +1,17 @@ +{{- if .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: funnel-role + namespace: {{ .Release.Namespace }} +rules: + - apiGroups: [""] + resources: ["pods", "pods/log"] + verbs: ["get", "list", "watch"] + - apiGroups: ["batch", "extensions"] + resources: ["jobs"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + - apiGroups: ["extensions", "apps"] + resources: ["deployments"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +{{- end }} diff --git a/deployments/kubernetes/helm/funnel/templates/rolebinding.yaml b/deployments/kubernetes/helm/funnel/templates/rolebinding.yaml new file mode 100644 index 000000000..efc5e1f5b --- /dev/null +++ b/deployments/kubernetes/helm/funnel/templates/rolebinding.yaml @@ -0,0 +1,14 @@ +{{- if .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: funnel-rolebinding + namespace: {{ .Release.Namespace }} +subjects: + - kind: ServiceAccount + name: funnel-sa +roleRef: + kind: Role + name: funnel-role + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/deployments/kubernetes/helm/funnel/templates/service.yaml b/deployments/kubernetes/helm/funnel/templates/service.yaml new file mode 100644 index 000000000..8780e71fa --- /dev/null +++ b/deployments/kubernetes/helm/funnel/templates/service.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + name: funnel + namespace: {{ .Release.Namespace }} +spec: + type: ClusterIP + ports: + - name: http + protocol: TCP + port: 8000 + targetPort: 8000 + - name: rpc + protocol: TCP + port: 9090 + targetPort: 9090 + selector: + {{- include "funnel.selectorLabels" . | nindent 4 }} diff --git a/deployments/kubernetes/helm/funnel/templates/serviceaccount.yaml b/deployments/kubernetes/helm/funnel/templates/serviceaccount.yaml new file mode 100644 index 000000000..98e0d0e1b --- /dev/null +++ b/deployments/kubernetes/helm/funnel/templates/serviceaccount.yaml @@ -0,0 +1,10 @@ +{{- if .Values.rbac.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: funnel-sa + namespace: {{ .Release.Namespace }} + labels: + {{- include "funnel.labels" . | nindent 4 }} +automountServiceAccountToken: true +{{- end }} diff --git a/deployments/kubernetes/helm/funnel/templates/storageclass.yaml b/deployments/kubernetes/helm/funnel/templates/storageclass.yaml new file mode 100644 index 000000000..b48f0a0f0 --- /dev/null +++ b/deployments/kubernetes/helm/funnel/templates/storageclass.yaml @@ -0,0 +1,17 @@ +{{- if .Values.storage.createStorageClass }} +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: {{ .Values.storage.className | default "funnel-storage" }} + labels: + app.kubernetes.io/name: {{ .Chart.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + annotations: + meta.helm.sh/release-name: {{ .Release.Name }} + meta.helm.sh/release-namespace: {{ .Release.Namespace }} +provisioner: {{ .Values.storage.provisioner | quote }} +reclaimPolicy: Retain +volumeBindingMode: WaitForFirstConsumer +{{- end }} diff --git a/deployments/kubernetes/helm/funnel/templates/tests/test-connection.yaml b/deployments/kubernetes/helm/funnel/templates/tests/test-connection.yaml new file mode 100644 index 000000000..cb2d151cc --- /dev/null +++ b/deployments/kubernetes/helm/funnel/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "funnel.fullname" . }}-test-connection" + labels: + {{- include "funnel.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include "funnel.fullname" . }}:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/deployments/kubernetes/helm/funnel/values.yaml b/deployments/kubernetes/helm/funnel/values.yaml new file mode 100644 index 000000000..01563ac54 --- /dev/null +++ b/deployments/kubernetes/helm/funnel/values.yaml @@ -0,0 +1,425 @@ +# Kubernetes-specifc Settings +replicaCount: 1 + +image: + repository: quay.io/ohsu-comp-bio/funnel + tag: development + pullPolicy: IfNotPresent + +labels: + app: funnel + +rbac: + create: true + +resources: + requests: + cpu: 100m + memory: 100Mi + limits: + cpu: 1000m + memory: 1Gi + +service: + type: ClusterIP + httpPort: 8000 + rpcPort: 9090 + +serviceAccount: + create: true + name: funnel-sa + +storage: + provisioner: kubernetes.io/aws-ebs + enabled: true + size: 10Gi + path: /mnt/data + pv: + enabled: false + reclaimPolicy: Retain + +# Funnel Default Settings +# Ref: https://github.com/ohsu-comp-bio/funnel/blob/master/config/default-config.yaml + +# The name of the active server database backend +# Available backends: boltdb, badger, datastore, dynamodb, elastic, mongodb +Database: boltdb + +# The name of the active compute backend +# Available backends: local, htcondor, slurm, pbs, gridengine, manual, aws-batch, kubernetes +Compute: kubernetes + +# The name of the active event writer backend(s). +# Available backends: log, boltdb, badger, datastore, dynamodb, elastic, mongodb, kafka +EventWriters: + - boltdb + - log + +Logger: + # Logging levels: debug, info, error + Level: info + # Write logs to this path. If empty, logs are written to stderr. + OutputFile: "" + +Server: + # Hostname of the Funnel server. + HostName: localhost + + # Port used for HTTP communication and the web dashboard. + HTTPPort: 8000 + + # Port used for RPC communication. + RPCPort: 9090 + + # Require basic authentication for the server APIs using a password. + # If used, make sure to properly restrict access to the config file + # (e.g. chmod 600 funnel.config.yml) + # BasicAuth: + # - User: user1 + # Password: abc123 + # - User: user2 + # Password: foobar + + # Include a "Cache-Control: no-store" HTTP header in Get/List responses + # to prevent caching by intermediary services. + DisableHTTPCache: true + +RPCClient: + # RPC server address + ServerAddress: localhost:9090 + + # Credentials for Basic authentication for the server APIs using a password. + # If used, make sure to properly restrict access to the config file + # (e.g. chmod 600 funnel.config.yml) + # User: funnel + # Password: abc123 + + # connection timeout. + Timeout: 60s + + # The maximum number of times that a request will be retried for failures. + # Time between retries follows an exponential backoff starting at 5 seconds + # up to 1 minute + MaxRetries: 10 + +# The scheduler is used for the Manual compute backend. +Scheduler: + # How often to run a scheduler iteration. + ScheduleRate: 1s + # How many tasks to schedule in one iteration. + ScheduleChunk: 10 + # How long to wait between updates before marking a node dead. + NodePingTimeout: 1m + # How long to wait for a node to start, before marking the node dead. + NodeInitTimeout: 5m + +Node: + # If empty, a node ID will be automatically generated. + ID: "" + + # If the node has been idle for longer than the timeout, it will shut down. + # -1 means there is no timeout. 0 means timeout immediately after the first task. + Timeout: -1s + + # A Node will automatically try to detect what resources are available to it. + # Defining Resources in the Node configuration overrides this behavior. + Resources: + # CPUs available. + Cpus: 0 + + # RAM available, in GB. + RamGb: 0.0 + + # Disk space available, in GB. + DiskGb: 0.0 + + # For low-level tuning. + # How often to sync with the Funnel server. + UpdateRate: 5s + +Worker: + # Files created during processing will be written in this directory. + WorkDir: ./funnel-work-dir + + # For low-level tuning. + # How often to poll for cancel signals + PollingRate: 5s + + # For low-level tuning. + # How often to send stdout/err task log updates to the Funnel server. + # Setting this to 0 will result in these fields being updated a single time + # after the executor exits. + LogUpdateRate: 5s + + # Max bytes to store for stdout/err in the task log. + LogTailSize: 10000 # 10 KB + + # Normally the worker deletes its working directory after executing. + # This option disables that behavior. + LeaveWorkDir: false + + # Limit the number of concurrent downloads/uploads + MaxParallelTransfers: 10 + +#------------------------------------------------------------------------------- +# Databases and/or Event Writers/Handlers +#------------------------------------------------------------------------------- + +BoltDB: + # Path to the database file + Path: ./funnel-work-dir/funnel.db + +DynamoDB: + # Basename to use for dynamodb tables + TableBasename: funnel + # AWS region + Region: "" + # AWS Access key ID + Key: "" + # AWS Secret Access Key + Secret: "" + +Elastic: + # Prefix to use for indexes (task, events, nodes) + IndexPrefix: funnel + # URL of the elasticsearch server. + URL: http://localhost:9200 + +# Google Cloud Datastore task database. +Datastore: + Project: "" + # Path to account credentials file. + # Optional. If possible, credentials will be automatically discovered + # from the environment. + CredentialsFile: "" + +MongoDB: + # Addrs holds the addresses for the seed servers. + Addrs: + - mongodb://localhost + # Database is the database name used within MongoDB to store funnel data. + Database: funnel + # Timeout is the amount of time to wait for a server to respond when + # first connecting and on follow up operations in the session. If + # timeout is zero, the call may block forever waiting for a connection + # to be established. + Timeout: 5m + # Username and Password inform the credentials for the initial authentication + # done on the database defined by the Database field. + Username: "" + Password: "" + +Kafka: + Servers: + - "" + Topic: funnel + +#------------------------------------------------------------------------------- +# Compute Backends +#------------------------------------------------------------------------------- + +HTCondor: + # Turn off task state reconciler. When enabled, Funnel communicates with the HPC + # scheduler to find tasks that are stuck in a queued state or errored and + # updates the task state accordingly. + DisableReconciler: true + # ReconcileRate is how often the compute backend compares states in Funnel's backend + # to those reported by the backend + ReconcileRate: 10m + TemplateFile: "" + Template: | + universe = vanilla + getenv = True + executable = {{.Executable}} + arguments = worker run --config {{.Config}} --task-id {{.TaskId}} + log = {{.WorkDir}}/condor-event-log + error = {{.WorkDir}}/funnel-stderr + output = {{.WorkDir}}/funnel-stdout + should_transfer_files = YES + when_to_transfer_output = ON_EXIT_OR_EVICT + {{if ne .Cpus 0 -}} + {{printf "request_cpus = %d" .Cpus}} + {{- end}} + {{if ne .RamGb 0.0 -}} + {{printf "request_memory = %.0f GB" .RamGb}} + {{- end}} + {{if ne .DiskGb 0.0 -}} + {{printf "request_disk = %.0f GB" .DiskGb}} + {{- end}} + + queue + +PBS: + # Turn off task state reconciler. When enabled, Funnel communicates with the HPC + # scheduler to find tasks that are stuck in a queued state or errored and + # updates the task state accordingly. + DisableReconciler: true + # ReconcileRate is how often the compute backend compares states in Funnel's backend + # to those reported by the backend + ReconcileRate: 10m + TemplateFile: "" + Template: | + #!bin/bash + #PBS -N {{.TaskId}} + #PBS -o {{.WorkDir}}/funnel-stdout + #PBS -e {{.WorkDir}}/funnel-stderr + {{if ne .Cpus 0 -}} + {{printf "#PBS -l nodes=1:ppn=%d" .Cpus}} + {{- end}} + {{if ne .RamGb 0.0 -}} + {{printf "#PBS -l mem=%.0fgb" .RamGb}} + {{- end}} + {{if ne .DiskGb 0.0 -}} + {{printf "#PBS -l file=%.0fgb" .DiskGb}} + {{- end}} + + {{.Executable}} worker run --config {{.Config}} --taskID {{.TaskId}} + +GridEngine: + TemplateFile: "" + Template: | + #!bin/bash + #$ -N {{.TaskId}} + #$ -o {{.WorkDir}}/funnel-stdout + #$ -e {{.WorkDir}}/funnel-stderr + #$ -l nodes=1 + {{if ne .Cpus 0 -}} + {{printf "#$ -pe mpi %d" .Cpus}} + {{- end}} + {{if ne .RamGb 0.0 -}} + {{printf "#$ -l h_vmem=%.0fG" .RamGb}} + {{- end}} + {{if ne .DiskGb 0.0 -}} + {{printf "#$ -l h_fsize=%.0fG" .DiskGb}} + {{- end}} + + {{.Executable}} worker run --config {{.Config}} --taskID {{.TaskId}} + +Slurm: + # Turn off task state reconciler. When enabled, Funnel communicates with the HPC + # scheduler to find tasks that are stuck in a queued state or errored and + # updates the task state accordingly. + DisableReconciler: true + # ReconcileRate is how often the compute backend compares states in Funnel's backend + # to those reported by the backend + ReconcileRate: 10m + TemplateFile: "" + Template: | + #!/bin/bash + #SBATCH --job-name {{.TaskId}} + #SBATCH --ntasks 1 + #SBATCH --error {{.WorkDir}}/funnel-stderr + #SBATCH --output {{.WorkDir}}/funnel-stdout + {{if ne .Cpus 0 -}} + {{printf "#SBATCH --cpus-per-task %d" .Cpus}} + {{- end}} + {{if ne .RamGb 0.0 -}} + {{printf "#SBATCH --mem %.0fGB" .RamGb}} + {{- end}} + {{if ne .DiskGb 0.0 -}} + {{printf "#SBATCH --tmp %.0fGB" .DiskGb}} + {{- end}} + + {{.Executable}} worker run --config {{.Config}} --taskID {{.TaskId}} + +# AWSBatch describes the configuration for the AWS Batch compute backend. +AWSBatch: + # Turn off task state reconciler. When enabled, Funnel communicates with AWS Batch + # to find tasks that never started and updates task state accordingly. + DisableReconciler: true + # ReconcileRate is how often the compute backend compares states in Funnel's backend + # to those reported by AWS Batch + ReconcileRate: 10m + # JobDefinition can be either a name or the Amazon Resource Name (ARN). + JobDefinition: "funnel-job-def" + # JobQueue can be either a name or the Amazon Resource Name (ARN). + JobQueue: "funnel-job-queue" + # AWS region of the specified job queue and to create the job definition in + Region: "" + Key: "" + Secret: "" + +# Kubernetes describes the configuration for the Kubernetes compute backend. +Kubernetes: + # The executor used to execute tasks. Available executors: docker, kubernetes + Executor: "kubernetes" + # Turn off task state reconciler. When enabled, Funnel communicates with Kubernetes + # to find tasks that are stuck in a queued state or errored and + # updates the task state accordingly. + DisableReconciler: true + # ReconcileRate is how often the compute backend compares states in Funnel's backend + # to those reported by the backend + ReconcileRate: 10m + # Kubernetes Namespace to spawn jobs within + Namespace: "default" + # Kubernetes ServiceAccount to use for the job + ServiceAccount: "funnel-sa" + # Master batch job template. See: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#job-v1-batch + Template: "" + # TemplateFile is the path to the master job template. + TemplateFile: "" + + # Configuration of the Kubernetes executor. + + # Job template used for executing the tasks. + ExecutorTemplate: "" + # ExecutorTemplateFile is the path to the executor template. + ExecutorTemplateFile: "" + +#------------------------------------------------------------------------------- +# Storage +#------------------------------------------------------------------------------- + +# If possible, credentials will be automatically discovered +# from the environment. + +# Local file system. +LocalStorage: + # Whitelist of local directory paths which Funnel is allowed to access. + AllowedDirs: + - ./ + +# HTTPStorage is used to download public files on the web via a GET request. +HTTPStorage: + # Timeout for http(s) GET requests. + Timeout: 30s + +AmazonS3: + Disabled: false + # The maximum number of times that a request will be retried for failures. + MaxRetries: 10 + # AWS Access key ID + Key: "" + # AWS Secret Access Key + Secret: "" + +# Configure storage backends for S3 providers such as Minio and/or Ceph +# GenericS3: +# - Disabled: true +# Endpoint: "" +# Key: "" +# Secret: "" + +GoogleStorage: + Disabled: false + # Path to account credentials file. + # Optional. If possible, credentials will be automatically discovered + # from the environment. + CredentialsFile: "" +# Available backends: local, htcondor, slurm, pbs, gridengine, manual, aws-batch, kubernetes/Kube +Swift: + Disabled: false + UserName: "" + Password: "" + AuthURL: "" + TenantName: "" + TenantID: "" + RegionName: "" + # 500 MB + ChunkSizeBytes: 500000000 + +FTPStorage: + Disabled: false + Timeout: 10s + User: "anonymous" + Password: "anonymous" diff --git a/deployments/kubernetes/helm/local.conf b/deployments/kubernetes/helm/local.conf new file mode 100644 index 000000000..ebc7f568f --- /dev/null +++ b/deployments/kubernetes/helm/local.conf @@ -0,0 +1,2 @@ +storage: + className: standard diff --git a/worker/kubernetes.go b/worker/kubernetes.go index e435b5610..155fc8880 100644 --- a/worker/kubernetes.go +++ b/worker/kubernetes.go @@ -55,6 +55,7 @@ func (kcmd KubernetesCommand) Run(ctx context.Context) error { "RamGb": kcmd.Resources.RamGb, "DiskGb": kcmd.Resources.DiskGb, "ServiceAccount": kcmd.ServiceAccount, + "Image": kcmd.Image, // TODO: How to handle multiple images for the executors? }) if err != nil {