From 2caba023c61884d1b2a92cbb1c00b10453fd4e42 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Thu, 14 Oct 2021 15:36:06 +0530 Subject: [PATCH 1/6] Add flag to delete VPC resource controller --- pkg/addons/assets.go | 143 +------ .../assets/vpc-admission-webhook-config.yaml | 20 - .../assets/vpc-admission-webhook-csr.yaml | 11 - .../assets/vpc-admission-webhook-dep.yaml | 61 --- pkg/addons/assets/vpc-admission-webhook.yaml | 14 - .../assets/vpc-controller-metadata.yaml | 52 +++ .../assets/vpc-resource-controller-dep.yaml | 64 --- .../assets/vpc-resource-controller.yaml | 33 -- pkg/addons/device_plugin.go | 9 + pkg/addons/vpc_controller.go | 388 +----------------- pkg/ctl/utils/install_vpc_controllers.go | 36 +- pkg/eks/tasks.go | 60 +-- 12 files changed, 130 insertions(+), 761 deletions(-) delete mode 100644 pkg/addons/assets/vpc-admission-webhook-config.yaml delete mode 100644 pkg/addons/assets/vpc-admission-webhook-csr.yaml delete mode 100644 pkg/addons/assets/vpc-admission-webhook-dep.yaml delete mode 100644 pkg/addons/assets/vpc-admission-webhook.yaml create mode 100644 pkg/addons/assets/vpc-controller-metadata.yaml delete mode 100644 pkg/addons/assets/vpc-resource-controller-dep.yaml delete mode 100644 pkg/addons/assets/vpc-resource-controller.yaml diff --git a/pkg/addons/assets.go b/pkg/addons/assets.go index 5baaf0a456..8acdc6f886 100644 --- a/pkg/addons/assets.go +++ b/pkg/addons/assets.go @@ -3,12 +3,7 @@ // assets/efa-device-plugin.yaml (3.084kB) // assets/neuron-device-plugin.yaml (3.623kB) // assets/nvidia-device-plugin.yaml (2.369kB) -// assets/vpc-admission-webhook-config.yaml (524B) -// assets/vpc-admission-webhook-csr.yaml (234B) -// assets/vpc-admission-webhook-dep.yaml (1.675kB) -// assets/vpc-admission-webhook.yaml (231B) -// assets/vpc-resource-controller-dep.yaml (1.679kB) -// assets/vpc-resource-controller.yaml (565B) +// assets/vpc-controller-metadata.yaml (924B) package addons @@ -137,123 +132,23 @@ func nvidiaDevicePluginYaml() (*asset, error) { return a, nil } -var _vpcAdmissionWebhookConfigYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x7c\x91\x4f\x6b\xf3\x30\x0c\xc6\xef\xf9\x14\x22\xf7\xa4\xf4\xf6\xe2\xdb\x4b\x29\x63\x87\xc1\x18\x63\x3b\x8c\x1d\x14\x47\x4d\x45\x62\xcb\x58\x76\x4a\xf7\xe9\x47\xfe\xb4\xac\xb0\xd5\x17\xdb\x7a\xa4\xdf\x63\xc9\x18\xf8\x8d\xa2\xb2\x78\x03\xd8\x3a\xd6\xe9\x18\xa9\x63\x4d\x11\x13\x8b\xaf\xfb\x7f\x5a\xb3\x6c\xc6\x6d\x43\x09\xb7\x45\xcf\xbe\x35\xf0\x94\x13\x26\xf6\xdd\x3b\x35\x47\x91\x7e\x27\xfe\xc0\x5d\x5e\x2a\x0a\x47\x09\x5b\x4c\x68\x0a\x00\x8f\x8e\x0c\x8c\xc1\x56\x57\x7a\x75\x5a\x8a\x2a\x7b\xe8\xd6\x0c\x0d\x68\xc9\x40\x9f\x1b\xaa\xf4\xac\x89\x5c\x01\x30\x60\x43\x83\x4e\x10\x00\x0c\xe1\x0f\x4a\xb1\xee\x73\x62\x75\xcf\xaf\x46\x87\x5f\xe2\xf1\xa4\xb5\x15\x37\x63\xed\xc0\xe4\xd3\xf2\xfa\xc5\x08\x40\x29\x8e\x6c\xe9\x72\xbd\xdb\xc2\x4d\xce\xaf\x4d\x2c\x2b\x60\x3a\x1a\x28\x37\x6e\x1a\x1b\x95\x73\x3c\xe6\x81\xf4\xe2\x52\x81\x04\x5a\xc6\xa7\x06\x3e\xa0\xdc\xbd\xec\xff\xbf\xee\x4b\xf8\xbc\x32\x30\xf0\x43\x94\x1c\x26\xbd\x2c\x6f\xe2\xeb\x0f\xce\xca\xb8\xfd\xa1\x45\x52\xc9\xd1\xd2\xac\x04\x69\x75\xd5\x0e\xc8\x43\x8e\xf4\x2c\x03\xdb\xb3\x81\xc7\xce\x4b\xa4\xe2\x3b\x00\x00\xff\xff\x49\xee\x9e\x02\x0c\x02\x00\x00") +var _vpcControllerMetadataYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x93\xc1\x6e\xc2\x40\x0c\x44\xef\xf9\x8a\xfc\xc0\x06\x71\xab\x72\x2c\xbd\xf6\x02\x52\x7b\x76\x36\x66\xb1\x92\xd8\xa9\xed\x4d\x45\xbf\xbe\x42\x14\x5a\x21\xa8\x82\x38\x27\xe3\x79\x9e\xf1\x86\x10\x0a\x18\xe9\x0d\xd5\x48\xb8\x2e\xa7\x65\xd1\x11\xb7\x75\xb9\x41\x9d\x28\x62\x31\xa0\x43\x0b\x0e\x75\x51\x96\x0c\x03\xd6\xe5\x34\xc6\x00\xed\x40\x76\x50\x84\x4f\x6c\x76\x22\xdd\xcf\x57\x1b\x21\x62\x5d\x76\xb9\xc1\x60\x7b\x73\x1c\x8a\xe2\xd2\xe2\xac\x55\x4c\x64\xae\xe0\x24\x5c\x75\x4f\x56\x91\x2c\xa6\x65\x83\x0e\x27\x88\xd7\xec\xe0\xc4\xe9\xfd\x68\xb2\x12\xde\x52\xca\x47\xc5\x5c\xb2\x10\xb7\xe9\x0e\xba\x88\xea\xb4\xa5\x08\x8e\x76\x1d\x6a\xf5\xfb\xc7\x86\x12\x13\xa7\x35\x7e\x64\x34\x9f\x4b\x54\xfd\x1f\xcf\x38\xda\xe2\x5c\xc3\x0b\x8e\xbd\xec\x07\xe4\xd9\xd3\xef\xd8\x55\x1b\x88\x15\x64\xdf\x89\xd2\xd7\x45\x0d\xa7\x65\xfb\x6c\x8e\xba\x96\xfe\xd6\x29\x28\x9a\x64\x8d\x18\xa2\xb0\xab\xf4\x3d\xea\xa3\x4e\xcf\xc4\x2d\x71\x7a\xc4\xf0\xce\x14\xaf\xcd\x9c\x9f\xe3\x9f\x47\x13\x15\x67\x37\x15\x0e\xb7\x66\xb7\x7d\xbe\x03\x00\x00\xff\xff\xad\xa6\xf6\xbd\x9c\x03\x00\x00") -func vpcAdmissionWebhookConfigYamlBytes() ([]byte, error) { +func vpcControllerMetadataYamlBytes() ([]byte, error) { return bindataRead( - _vpcAdmissionWebhookConfigYaml, - "vpc-admission-webhook-config.yaml", + _vpcControllerMetadataYaml, + "vpc-controller-metadata.yaml", ) } -func vpcAdmissionWebhookConfigYaml() (*asset, error) { - bytes, err := vpcAdmissionWebhookConfigYamlBytes() +func vpcControllerMetadataYaml() (*asset, error) { + bytes, err := vpcControllerMetadataYamlBytes() if err != nil { return nil, err } - info := bindataFileInfo{name: "vpc-admission-webhook-config.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7d, 0x11, 0x23, 0x17, 0x2f, 0xdc, 0x4e, 0x18, 0xaa, 0xc8, 0x66, 0xee, 0xf3, 0xc1, 0x85, 0x63, 0xb1, 0xe3, 0x53, 0x57, 0x80, 0x96, 0xe6, 0x54, 0x26, 0x46, 0x6b, 0x3f, 0x17, 0x20, 0x31, 0x8}} - return a, nil -} - -var _vpcAdmissionWebhookCsrYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x44\x8d\x4b\x4e\xc4\x30\x10\x44\xf7\x3e\x45\x5f\x20\x41\xb3\x43\xde\x72\x03\x90\xd8\x77\xec\xc2\x69\x19\x7f\x70\xb7\x83\xe6\xf6\x28\x13\xa4\xd9\x95\xaa\x9e\x5e\x71\x97\x4f\x0c\x95\x56\x3d\x05\x0c\x93\x2f\x09\x6c\xd0\x35\xbf\xea\x2a\xed\xe5\xb8\x6d\x30\xbe\xb9\x2c\x35\x7a\x7a\x7b\x12\x1f\x92\xaa\xd4\xf4\x8e\x9f\x09\x35\x57\x60\x1c\xd9\xd8\x3b\xa2\xca\x05\x9e\x8e\x1e\x16\x8e\x45\xf4\x94\x2f\xbf\xd8\xf6\xd6\xf2\x9a\xe7\x86\x45\xef\x6a\x28\x4e\x3b\xc2\xc9\xa7\xd1\x66\xd7\x33\x2d\x74\x4d\x9e\xa7\xed\xa8\xf6\x78\x8a\x8e\x68\x2a\x27\xfc\x23\x51\x92\x18\x7f\x93\x4a\xaa\x6c\x73\xe0\xd1\x66\xdc\x09\x35\x48\xdf\x31\x0a\xaa\x5d\x36\x8c\x03\x83\x4e\x9b\xfb\x0b\x00\x00\xff\xff\xf1\x7d\x42\x97\xea\x00\x00\x00") - -func vpcAdmissionWebhookCsrYamlBytes() ([]byte, error) { - return bindataRead( - _vpcAdmissionWebhookCsrYaml, - "vpc-admission-webhook-csr.yaml", - ) -} - -func vpcAdmissionWebhookCsrYaml() (*asset, error) { - bytes, err := vpcAdmissionWebhookCsrYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "vpc-admission-webhook-csr.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x56, 0xf4, 0x54, 0x57, 0xf8, 0xbd, 0x8a, 0x1a, 0x67, 0xb2, 0x29, 0x18, 0xe2, 0x44, 0x8a, 0xc2, 0x7f, 0x44, 0x26, 0x4c, 0x52, 0xe0, 0x70, 0xe0, 0xc8, 0x5a, 0x74, 0x76, 0x2, 0xcd, 0x3e, 0xa}} - return a, nil -} - -var _vpcAdmissionWebhookDepYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x54\xc1\x6e\xdb\x3a\x10\xbc\xfb\x2b\xf6\x92\x97\x93\xa5\x97\xa0\xc8\x81\x40\x0a\x04\x4d\x0a\x04\x6d\x93\xa0\x29\x7a\x5f\x53\x13\x99\x10\x45\xb2\xe4\x4a\x8e\xfe\xbe\xa0\xad\xa4\xb6\x1c\x37\x39\x14\xad\x0e\x3e\xec\xec\xcc\x2c\x87\x5e\x72\x30\xdf\x11\x93\xf1\x4e\x11\x87\x90\xca\xfe\x64\xd6\x18\x57\x29\xba\x44\xb0\x7e\x68\xe1\x64\xd6\x42\xb8\x62\x61\x35\x23\x72\xdc\x42\x51\x1f\xf4\x9c\xab\xd6\xa4\xcc\x9c\xaf\xb0\x58\x7a\xdf\x8c\x68\x0a\xac\xa1\xa8\xe9\x16\x98\xa7\x21\x09\xda\x19\x91\xe5\x05\x6c\xca\x02\x94\x7d\x0e\x29\xa4\x00\x9d\x9b\x22\x82\x35\x9a\x93\xa2\x93\x19\x51\x92\xc8\x82\x7a\xd8\xd0\x65\x08\x50\xf4\x15\x3a\x82\x05\x19\x86\x85\x16\x1f\x37\x70\xcb\xa2\x97\x9f\xb7\xec\x7e\x6b\x48\x24\x68\x83\x65\xc1\xc8\xde\x3a\x6a\xfe\xec\x8e\xd0\x2b\x52\x44\x4f\xf3\xe7\x4f\x7b\x27\x6c\x1c\xe2\x16\x7d\xfe\x4a\x7e\xcf\x36\xb1\xde\x62\x6d\x98\x73\xb1\xe9\x03\xa2\x7c\x34\x16\xe7\x25\x44\x97\x23\xaf\xd4\x88\x92\xd6\xbf\x45\x58\xa7\x3d\xa5\x7d\xc2\x70\x88\xd5\x60\x78\x89\x74\x7b\xbf\x8e\xf0\x7e\x8c\xf6\xb6\x47\x8c\xa6\xc2\xf9\xca\xb8\xca\xaf\xd2\xb4\x9d\x6d\xf2\xd6\xd7\xe2\x93\x54\x88\x71\x0a\xf7\xe7\xef\x26\xa5\xd3\xf7\xff\x9d\x6c\x95\x4c\xcb\x35\x14\x1d\x1f\xa5\xa2\x6a\x62\x01\x1d\x8b\xa3\x54\x1c\xa5\x12\x4d\x2a\x5f\x0c\x4b\xf5\xff\x17\xa7\xc5\xd9\xf1\x54\xe4\xae\xb3\xf6\xce\x5b\xa3\x07\x45\x17\x76\xc5\xc3\xf6\xac\xbd\xb7\x5d\x8b\x2f\xbe\x73\xb2\x17\xef\xe6\x62\x46\xf5\xf9\x3a\x9c\x9d\x0e\xa2\x36\xf3\xee\x58\x96\x8a\xf6\x83\x9c\xf4\x46\x70\x75\xeb\xec\xa0\x48\x62\x87\x11\x5c\xfa\x24\x37\x90\x95\x8f\xcd\x4e\x9d\x1f\x1e\x8c\x33\x32\xfc\x1a\xc9\xf9\x0a\x17\x7b\xd5\x2c\xfb\xa3\x33\x11\xd5\x65\x17\x8d\xab\xef\xf5\x12\x55\x67\x8d\xab\xaf\x6b\xe7\x9f\xcb\x57\x8f\xd0\x9d\xe4\x95\xde\x19\x2a\x6b\x3e\xdd\xe7\x37\xc4\x76\x2f\x81\xf5\xe6\x5c\x3d\x86\x88\x75\xd2\x13\x3c\x77\x34\x18\x14\x2d\x20\x5c\xe4\xed\x8e\x0e\x82\x54\x18\x5f\xfa\xe9\xf1\x89\x7c\x40\xe4\xbc\x94\x74\xed\xf6\xc0\x9e\x6d\x87\x3d\xfd\xec\x60\x8d\xeb\x1e\xdf\xec\xcb\x51\x2f\xff\x94\x33\xb7\xd5\xd9\xf4\x5f\xfa\xc6\x44\xfe\x41\x18\x7f\x27\x87\xcd\xbe\xbc\xf0\x7e\x1d\x5a\x93\x94\x5f\x65\xd9\x95\xdd\xd4\x6e\x0e\xbf\x7b\xa3\xca\xcf\x00\x00\x00\xff\xff\x52\xd4\x1b\x58\x8b\x06\x00\x00") - -func vpcAdmissionWebhookDepYamlBytes() ([]byte, error) { - return bindataRead( - _vpcAdmissionWebhookDepYaml, - "vpc-admission-webhook-dep.yaml", - ) -} - -func vpcAdmissionWebhookDepYaml() (*asset, error) { - bytes, err := vpcAdmissionWebhookDepYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "vpc-admission-webhook-dep.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x3b, 0x48, 0x71, 0x63, 0xbb, 0x59, 0xcc, 0xd5, 0x1b, 0x30, 0xc7, 0x1c, 0x5e, 0xf2, 0x65, 0x72, 0xff, 0xa9, 0x4d, 0x14, 0x6c, 0xce, 0x49, 0xa8, 0x6f, 0x4d, 0x8e, 0x19, 0xf7, 0xee, 0xfa, 0x8c}} - return a, nil -} - -var _vpcAdmissionWebhookYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x8c\x31\xae\xc2\x40\x0c\x05\xfb\x3d\x85\x2f\xe0\xe2\xeb\xa7\xf2\x29\x90\x90\xe8\x9d\xcd\x13\xac\x92\xcd\x5a\x6b\x13\xc4\xed\x51\x22\x0a\x1a\x44\x67\xf9\xcd\x0c\x33\x27\xb5\x72\x41\xf7\xd2\x56\xa1\xed\x2f\xcd\x65\x9d\x84\xce\xe8\x5b\xc9\x48\x15\xa1\x93\x86\x4a\x22\x5a\xb5\x42\x68\xb3\xcc\x3a\xd5\xe2\xbb\xc1\x0f\x8c\xb7\xd6\xe6\xf7\xea\xa6\x19\x42\xf3\x7d\x04\xfb\xd3\x03\x35\x11\x2d\x3a\x62\xf1\x3d\x40\xa4\x66\xdf\x0a\x6e\xc8\x3b\x64\xad\xc7\x41\xf3\x71\x0a\x0d\xc3\xff\xe1\x86\xf6\x2b\xe2\xf4\xf1\x73\x2c\xc8\xd1\xfa\xcf\xf6\x2b\x00\x00\xff\xff\xbc\xa7\x78\x3e\xe7\x00\x00\x00") - -func vpcAdmissionWebhookYamlBytes() ([]byte, error) { - return bindataRead( - _vpcAdmissionWebhookYaml, - "vpc-admission-webhook.yaml", - ) -} - -func vpcAdmissionWebhookYaml() (*asset, error) { - bytes, err := vpcAdmissionWebhookYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "vpc-admission-webhook.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc0, 0x14, 0x3e, 0x68, 0x1c, 0x57, 0x26, 0x7e, 0x3b, 0xab, 0xf1, 0x55, 0x21, 0x61, 0xc3, 0xe1, 0xaf, 0x46, 0xb6, 0xf7, 0xdd, 0x11, 0x29, 0x41, 0x64, 0x57, 0xc8, 0xd4, 0xea, 0x97, 0xba, 0xff}} - return a, nil -} - -var _vpcResourceControllerDepYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x94\x4f\x6f\xdb\x3c\x0c\xc6\xef\xfe\x14\xbc\x14\x3d\xd9\x49\xfa\xbe\x6b\x31\x01\x3b\x14\x6b\xb1\x15\x18\x86\x00\x0d\x76\x67\x24\x26\x16\x2c\x4b\x1a\x45\x3b\xf1\x3e\xfd\xa0\xb5\xf9\xe3\xa6\x5b\x8b\x61\xc3\x7c\x32\x9e\x9f\xc4\x87\x24\x44\x96\x65\x59\x60\xb4\x5f\x88\x93\x0d\x5e\x01\xc6\x98\x26\xfd\xac\x68\xac\x37\x0a\x6e\x28\xba\x30\xb4\xe4\xa5\x68\x49\xd0\xa0\xa0\x2a\x00\x3c\xb6\xa4\xa0\x8f\xba\x64\x4a\xa1\x63\x4d\xa5\x0e\x5e\x38\x38\x47\xfc\xc8\x53\x44\x4d\x0a\x9a\x6e\x49\x65\x1a\x92\x50\x5b\xa4\x48\x3a\x5f\x67\x8a\xce\x6a\x4c\x0a\x66\x05\x40\x22\x47\x5a\x02\x67\x02\xd0\xa2\xe8\xfa\x13\x2e\xc9\xa5\x07\x01\x72\x4a\xbf\x32\xcb\x9f\x58\x62\x05\x4b\xd4\x0d\x79\xb3\xd3\x18\x75\xa3\x20\x09\x2e\x1d\x15\x00\x42\x6d\x74\x28\xf4\xe8\x73\x54\x4e\xfe\xdc\xc8\xf2\x55\xa6\xcf\xdb\x9e\x1a\x03\xec\x0a\xff\xf1\x4f\xdc\x5b\x4d\xd7\x5a\x87\xce\xcb\x4b\x1e\x59\x40\xeb\x89\xf7\xa9\x95\xa0\x43\xdb\xa2\x37\x87\x5c\x4b\x98\xbc\x94\x29\xf2\x3a\x1d\x5f\x28\x93\x18\x62\x96\x9a\x29\xd5\xc1\x99\x77\xd6\xaf\xc2\x9e\xdb\x16\xd7\xa4\xe0\xfc\x2c\x55\xa6\xe1\x8a\x34\x57\x67\xa9\x3a\x4b\x13\x6a\xd2\x64\x63\xbd\x09\x9b\x54\xfe\xc4\x52\xf5\xd3\xea\xa2\xba\x3c\x1f\x07\x9b\x77\xce\xcd\x83\xb3\x7a\x50\x70\xed\x36\x38\xa4\x3d\x77\xb6\x27\x4f\x29\xcd\x39\x2c\xe9\x90\x23\xc0\x0a\xad\xeb\x98\x16\xbb\x1c\x15\xbc\x39\xa2\xb5\x48\xfc\x40\x72\x7c\x01\xa0\x0e\x49\x14\xcc\x2e\xae\xaa\x69\x35\xad\x66\x23\x16\x51\x6a\x05\x93\x9a\xd0\x49\xfd\x6d\x8c\x02\x8b\x82\xcb\xd9\xd5\xd5\xdb\x91\x9e\x74\x4d\xf9\xa5\x7f\x5c\x2c\xe6\x47\xc0\x7a\x2b\x16\xdd\x0d\x39\x1c\xee\x49\x07\x6f\x92\x82\xff\xa6\x47\x27\x22\xb1\x0d\xe6\x79\x26\xb6\xa5\xd0\xc9\x1e\x1e\x8a\x7a\x69\xac\x76\x0f\x48\x77\x6c\x65\x78\x1f\xbc\xd0\x76\xd4\x80\xc8\xb6\xb7\x8e\xd6\x64\x14\x08\x77\x54\x1c\xba\xf2\x99\x64\x13\xb8\x19\xe9\xb8\x5a\xe5\x52\x86\x43\x08\x1f\x0c\x5d\x9f\xa8\x79\x62\xbf\x76\x96\xc9\xdc\x74\x6c\xfd\xfa\x5e\xd7\x64\x3a\x67\xfd\xfa\x6e\xed\xc3\x5e\xbe\xdd\x92\xee\x24\x6f\x91\x51\x13\x73\xcc\xfb\xc7\x19\x5f\x10\xb7\x69\x8c\xcb\x87\x91\xbf\xdd\x46\xa6\x94\x77\xd0\x13\x9e\x4f\x34\x34\x28\x58\x92\x60\x95\xd7\x09\x7b\x12\x4a\x95\x0d\x93\x90\x9e\x1c\x05\x08\x91\x18\xf3\x36\x81\x3b\x7f\x02\x7b\x74\x1d\x9d\xc4\xcf\x0e\xce\xfa\x6e\xfb\x6a\x5f\x64\x5d\xff\x29\x67\x6c\xcd\xe5\xff\xbf\xd7\x91\x7f\xd0\x8c\xbf\xdd\x87\xef\x01\x00\x00\xff\xff\xec\x16\x91\xef\x8f\x06\x00\x00") - -func vpcResourceControllerDepYamlBytes() ([]byte, error) { - return bindataRead( - _vpcResourceControllerDepYaml, - "vpc-resource-controller-dep.yaml", - ) -} - -func vpcResourceControllerDepYaml() (*asset, error) { - bytes, err := vpcResourceControllerDepYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "vpc-resource-controller-dep.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x0, 0xbf, 0x11, 0xf3, 0x5f, 0x76, 0xa3, 0xb2, 0x2e, 0x2f, 0x80, 0xa7, 0x86, 0xae, 0x3f, 0xb7, 0x7e, 0x76, 0xed, 0x68, 0xfe, 0x23, 0x5c, 0x76, 0xb9, 0xd0, 0xd8, 0xed, 0xf9, 0x9d, 0x96, 0x93}} - return a, nil -} - -var _vpcResourceControllerYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x90\x31\x4f\x33\x31\x0c\x86\xf7\xfc\x8a\xa8\x7b\x5a\x7d\xdb\xa7\xdb\x80\x81\xbd\x48\xec\x3e\x9f\xdb\x9a\xe6\xe2\xc8\x76\x0e\xc1\xaf\x47\x77\xd7\xc2\x80\x44\x85\x98\xf2\xc4\xf6\x6b\x4b\x4f\x4a\x29\x40\xe5\x67\x52\x63\x29\x5d\xd4\x1e\x70\x0b\xcd\x4f\xa2\xfc\x0e\xce\x52\xb6\xe7\xff\xb6\x65\xd9\x4d\xff\xc2\x99\xcb\xd0\xc5\x87\xdc\xcc\x49\xf7\x92\x29\x8c\xe4\x30\x80\x43\x17\x62\x2c\x30\x52\x17\xa7\x8a\x49\xc9\xa4\x29\x52\x42\x29\xae\x92\x33\x69\xd0\x96\xc9\xba\x90\x22\x54\x7e\x54\x69\xd5\xe6\x4c\x8a\x9b\x4d\x88\xf1\x1a\xb8\xd4\x8a\x0c\x64\x5f\xb4\x33\x07\x6f\x6b\xa1\xca\xb0\x02\x4a\x39\xf0\x71\x84\x3a\x7f\x27\xd2\xfe\x92\x6d\x75\x00\xa7\x05\x8f\xe4\xcb\x9b\xd9\x56\x78\x05\xc7\xd3\xba\xe6\x93\x50\x69\x9e\xff\x9b\x87\x7b\x2e\x03\x97\xe3\x6f\x74\x48\xa6\x3d\x1d\xe6\xc1\xab\x90\x1f\x8e\x86\x18\xbf\xbb\xbf\x75\xc2\x5a\xff\x42\xe8\x8b\xf4\x35\xfd\x44\x3a\x31\xd2\x1d\xa2\xb4\xe2\x37\x17\xac\x7d\xab\x80\xd4\xc5\x73\xeb\x29\xd9\x9b\x39\x8d\xe1\x23\x00\x00\xff\xff\x83\x2e\x8d\x64\x35\x02\x00\x00") - -func vpcResourceControllerYamlBytes() ([]byte, error) { - return bindataRead( - _vpcResourceControllerYaml, - "vpc-resource-controller.yaml", - ) -} - -func vpcResourceControllerYaml() (*asset, error) { - bytes, err := vpcResourceControllerYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "vpc-resource-controller.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa8, 0xff, 0xd2, 0xc, 0x46, 0xfb, 0xe4, 0x4e, 0xb, 0x26, 0x4a, 0xa0, 0x7d, 0x73, 0x5e, 0xaf, 0x6d, 0xab, 0xfd, 0xe5, 0xc2, 0x4f, 0xed, 0xae, 0xb6, 0xd7, 0x17, 0x38, 0x68, 0xb0, 0xe8, 0x2d}} + info := bindataFileInfo{name: "vpc-controller-metadata.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa6, 0x89, 0x6b, 0xa9, 0x33, 0x90, 0x94, 0x63, 0xb2, 0xaf, 0x3a, 0x5c, 0x22, 0x5b, 0x19, 0xc7, 0xb9, 0x22, 0xd6, 0x5a, 0xbb, 0x68, 0xac, 0xf8, 0x24, 0x68, 0x4d, 0x2c, 0x54, 0x12, 0x18, 0x57}} return a, nil } @@ -348,15 +243,10 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ - "efa-device-plugin.yaml": efaDevicePluginYaml, - "neuron-device-plugin.yaml": neuronDevicePluginYaml, - "nvidia-device-plugin.yaml": nvidiaDevicePluginYaml, - "vpc-admission-webhook-config.yaml": vpcAdmissionWebhookConfigYaml, - "vpc-admission-webhook-csr.yaml": vpcAdmissionWebhookCsrYaml, - "vpc-admission-webhook-dep.yaml": vpcAdmissionWebhookDepYaml, - "vpc-admission-webhook.yaml": vpcAdmissionWebhookYaml, - "vpc-resource-controller-dep.yaml": vpcResourceControllerDepYaml, - "vpc-resource-controller.yaml": vpcResourceControllerYaml, + "efa-device-plugin.yaml": efaDevicePluginYaml, + "neuron-device-plugin.yaml": neuronDevicePluginYaml, + "nvidia-device-plugin.yaml": nvidiaDevicePluginYaml, + "vpc-controller-metadata.yaml": vpcControllerMetadataYaml, } // AssetDebug is true if the assets were built with the debug flag enabled. @@ -406,12 +296,7 @@ var _bintree = &bintree{nil, map[string]*bintree{ "efa-device-plugin.yaml": {efaDevicePluginYaml, map[string]*bintree{}}, "neuron-device-plugin.yaml": {neuronDevicePluginYaml, map[string]*bintree{}}, "nvidia-device-plugin.yaml": {nvidiaDevicePluginYaml, map[string]*bintree{}}, - "vpc-admission-webhook-config.yaml": {vpcAdmissionWebhookConfigYaml, map[string]*bintree{}}, - "vpc-admission-webhook-csr.yaml": {vpcAdmissionWebhookCsrYaml, map[string]*bintree{}}, - "vpc-admission-webhook-dep.yaml": {vpcAdmissionWebhookDepYaml, map[string]*bintree{}}, - "vpc-admission-webhook.yaml": {vpcAdmissionWebhookYaml, map[string]*bintree{}}, - "vpc-resource-controller-dep.yaml": {vpcResourceControllerDepYaml, map[string]*bintree{}}, - "vpc-resource-controller.yaml": {vpcResourceControllerYaml, map[string]*bintree{}}, + "vpc-controller-metadata.yaml": {vpcControllerMetadataYaml, map[string]*bintree{}}, }} // RestoreAsset restores an asset under the given directory. diff --git a/pkg/addons/assets/vpc-admission-webhook-config.yaml b/pkg/addons/assets/vpc-admission-webhook-config.yaml deleted file mode 100644 index 652a257203..0000000000 --- a/pkg/addons/assets/vpc-admission-webhook-config.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: admissionregistration.k8s.io/v1beta1 -kind: MutatingWebhookConfiguration -metadata: - name: vpc-admission-webhook-cfg - namespace: kube-system - labels: - app: vpc-admission-webhook -webhooks: - - name: vpc-admission-webhook.amazonaws.com - clientConfig: - service: - name: vpc-admission-webhook - namespace: kube-system - path: "/mutate" - rules: - - operations: [ "CREATE" ] - apiGroups: [""] - apiVersions: ["v1"] - resources: ["pods"] - failurePolicy: Ignore diff --git a/pkg/addons/assets/vpc-admission-webhook-csr.yaml b/pkg/addons/assets/vpc-admission-webhook-csr.yaml deleted file mode 100644 index 09e4f77a6d..0000000000 --- a/pkg/addons/assets/vpc-admission-webhook-csr.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: certificates.k8s.io/v1beta1 -kind: CertificateSigningRequest -metadata: - name: vpc-admission-webhook.kube-system -spec: - groups: - - system:authenticated - usages: - - digital signature - - key encipherment - - server auth diff --git a/pkg/addons/assets/vpc-admission-webhook-dep.yaml b/pkg/addons/assets/vpc-admission-webhook-dep.yaml deleted file mode 100644 index 2c08acab80..0000000000 --- a/pkg/addons/assets/vpc-admission-webhook-dep.yaml +++ /dev/null @@ -1,61 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: vpc-admission-webhook - namespace: kube-system - labels: - app: vpc-admission-webhook -spec: - replicas: 1 - strategy: - type: Recreate - selector: - matchLabels: - app: vpc-admission-webhook - template: - metadata: - labels: - app: vpc-admission-webhook - spec: - containers: - - name: vpc-admission-webhook - args: - - -tlsCertFile=/etc/webhook/certs/cert.pem - - -tlsKeyFile=/etc/webhook/certs/key.pem - - -OSLabelSelectorOverride=windows - - -alsologtostderr - - -v=4 - - 2>&1 - image: '%s.dkr.ecr.%s.%s/eks/vpc-admission-webhook:v0.2.6' - imagePullPolicy: Always - volumeMounts: - - name: webhook-certs - mountPath: /etc/webhook/certs - readOnly: true - hostNetwork: true - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/os - operator: In - values: - - linux - - key: beta.kubernetes.io/arch - operator: In - values: - - amd64 - - matchExpressions: - - key: kubernetes.io/os - operator: In - values: - - linux - - key: kubernetes.io/arch - operator: In - values: - - amd64 - volumes: - - name: webhook-certs - secret: - secretName: vpc-admission-webhook-certs diff --git a/pkg/addons/assets/vpc-admission-webhook.yaml b/pkg/addons/assets/vpc-admission-webhook.yaml deleted file mode 100644 index b8f351fb12..0000000000 --- a/pkg/addons/assets/vpc-admission-webhook.yaml +++ /dev/null @@ -1,14 +0,0 @@ ---- -apiVersion: v1 -kind: Service -metadata: - name: vpc-admission-webhook - namespace: kube-system - labels: - app: vpc-admission-webhook -spec: - ports: - - port: 443 - targetPort: 443 - selector: - app: vpc-admission-webhook diff --git a/pkg/addons/assets/vpc-controller-metadata.yaml b/pkg/addons/assets/vpc-controller-metadata.yaml new file mode 100644 index 0000000000..93bfd78257 --- /dev/null +++ b/pkg/addons/assets/vpc-controller-metadata.yaml @@ -0,0 +1,52 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: vpc-admission-webhook + namespace: kube-system + +--- +apiVersion: admissionregistration.k8s.io/v1beta1 +kind: MutatingWebhookConfiguration +metadata: + name: vpc-admission-webhook-cfg + namespace: kube-system + +--- +apiVersion: certificates.k8s.io/v1beta1 +kind: CertificateSigningRequest +metadata: + name: vpc-admission-webhook.kube-system + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: vpc-admission-webhook + namespace: kube-system + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: vpc-resource-controller + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: vpc-resource-controller + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: vpc-resource-controller + namespace: kube-system + +--- +apiVersion: v1 +kind: Secret +metadata: + name: vpc-admission-webhook-certs + namespace: kube-system diff --git a/pkg/addons/assets/vpc-resource-controller-dep.yaml b/pkg/addons/assets/vpc-resource-controller-dep.yaml deleted file mode 100644 index 3966657e1b..0000000000 --- a/pkg/addons/assets/vpc-resource-controller-dep.yaml +++ /dev/null @@ -1,64 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: vpc-resource-controller - namespace: kube-system -spec: - replicas: 1 - selector: - matchLabels: - app: vpc-resource-controller - tier: backend - track: stable - template: - metadata: - labels: - app: vpc-resource-controller - tier: backend - track: stable - spec: - serviceAccount: vpc-resource-controller - containers: - - command: - - /vpc-resource-controller - args: - - -stderrthreshold=info - image: '%s.dkr.ecr.%s.%s/eks/windows-vpc-resource-controller:v0.2.6' - imagePullPolicy: Always - livenessProbe: - failureThreshold: 5 - httpGet: - host: 127.0.0.1 - path: /healthz - port: 61779 - scheme: HTTP - initialDelaySeconds: 30 - periodSeconds: 30 - timeoutSeconds: 5 - name: vpc-resource-controller - securityContext: - privileged: true - hostNetwork: true - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/os - operator: In - values: - - linux - - key: beta.kubernetes.io/arch - operator: In - values: - - amd64 - - matchExpressions: - - key: kubernetes.io/os - operator: In - values: - - linux - - key: kubernetes.io/arch - operator: In - values: - - amd64 diff --git a/pkg/addons/assets/vpc-resource-controller.yaml b/pkg/addons/assets/vpc-resource-controller.yaml deleted file mode 100644 index 91b1c9f085..0000000000 --- a/pkg/addons/assets/vpc-resource-controller.yaml +++ /dev/null @@ -1,33 +0,0 @@ ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: vpc-resource-controller -rules: -- apiGroups: - - "" - resources: - - nodes - - nodes/status - - pods - - configmaps - verbs: - - update - - get - - list - - watch - - patch - - create ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: vpc-resource-controller -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: vpc-resource-controller -subjects: -- kind: ServiceAccount - name: vpc-resource-controller - namespace: kube-system diff --git a/pkg/addons/device_plugin.go b/pkg/addons/device_plugin.go index 694668ad8b..70683fe99d 100644 --- a/pkg/addons/device_plugin.go +++ b/pkg/addons/device_plugin.go @@ -71,6 +71,15 @@ type DevicePlugin interface { Deploy() error } +type typeAssertionError struct { + expected interface{} + got interface{} +} + +func (t *typeAssertionError) Error() string { + return fmt.Sprintf("expected type to be %T; got %T", t.expected, t.got) +} + func applyDevicePlugin(dp DevicePlugin) error { list, err := kubernetes.NewList(dp.Manifest()) if err != nil { diff --git a/pkg/addons/vpc_controller.go b/pkg/addons/vpc_controller.go index 4af6c3ab57..f1cbf5f2d6 100644 --- a/pkg/addons/vpc_controller.go +++ b/pkg/addons/vpc_controller.go @@ -1,410 +1,50 @@ package addons import ( - "context" - "fmt" - "time" - - "github.com/cloudflare/cfssl/csr" "github.com/kris-nova/logger" "github.com/pkg/errors" - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/assetutil" "github.com/weaveworks/eksctl/pkg/kubernetes" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/kubernetes/typed/certificates/v1beta1" - admv1beta1 "k8s.io/api/admissionregistration/v1beta1" - appsv1 "k8s.io/api/apps/v1" - certsv1beta1 "k8s.io/api/certificates/v1beta1" - corev1 "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" ) const ( vpcControllerNamespace = metav1.NamespaceSystem - vpcControllerName = "vpc-resource-controller" - webhookServiceName = "vpc-admission-webhook" - - certWaitTimeout = 45 * time.Second ) -// NewVPCController creates a new VPCController -func NewVPCController(rawClient kubernetes.RawClientInterface, irsa IRSAHelper, clusterStatus *api.ClusterStatus, region string, planMode bool) *VPCController { - return &VPCController{ - rawClient: rawClient, - irsa: irsa, - clusterStatus: clusterStatus, - region: region, - planMode: planMode, - } -} - -// A VPCController deploys Windows VPC controller to a cluster +// VPCController deletes an existing installation of VPC controller from worker nodes. type VPCController struct { - rawClient kubernetes.RawClientInterface - irsa IRSAHelper - clusterStatus *api.ClusterStatus - region string - planMode bool -} - -// Deploy deploys VPC controller to the specified cluster -func (v *VPCController) Deploy() (err error) { - defer func() { - if r := recover(); r != nil { - if ae, ok := r.(*assetutil.Error); ok { - err = ae - } else { - panic(r) - } - } - }() - - if err := v.deployVPCResourceController(); err != nil { - return err - } - - if err := v.generateCert(); err != nil { - return err - } - - return v.deployVPCWebhook() -} - -type typeAssertionError struct { - expected interface{} - got interface{} -} - -func (t *typeAssertionError) Error() string { - return fmt.Sprintf("expected type to be %T; got %T", t.expected, t.got) -} - -func (v *VPCController) generateCert() error { - var ( - csrName = fmt.Sprintf("%s.%s", webhookServiceName, vpcControllerNamespace) - csrClientSet = v.rawClient.ClientSet().CertificatesV1beta1().CertificateSigningRequests() - ) - - hasApprovedCert, err := v.hasApprovedCert() - if err != nil { - return err - } - if hasApprovedCert { - // Delete existing CSR if the secret is missing - _, err := v.rawClient.ClientSet().CoreV1().Secrets(vpcControllerNamespace).Get(context.TODO(), "vpc-admission-webhook-certs", metav1.GetOptions{}) - if err != nil { - if !apierrors.IsNotFound(err) { - return err - } - if err := csrClientSet.Delete(context.TODO(), csrName, metav1.DeleteOptions{}); err != nil { - return err - } - } - return nil - } - - csrPEM, privateKey, err := generateCertReq(webhookServiceName, vpcControllerNamespace) - if err != nil { - return errors.Wrap(err, "generating CSR") - } - - manifest := assetutil.MustLoad(vpcAdmissionWebhookCsrYamlBytes) - rawExtension, err := kubernetes.NewRawExtension(manifest) - if err != nil { - return err - } - - certificateSigningRequest, ok := rawExtension.Object.(*certsv1beta1.CertificateSigningRequest) - if !ok { - return &typeAssertionError{&certsv1beta1.CertificateSigningRequest{}, rawExtension.Object} - } - - certificateSigningRequest.Spec.Request = csrPEM - certificateSigningRequest.Name = csrName - - if err := v.applyRawResource(certificateSigningRequest); err != nil { - return errors.Wrap(err, "creating CertificateSigningRequest") - } - - certificateSigningRequest.Status.Conditions = []certsv1beta1.CertificateSigningRequestCondition{ - { - Type: certsv1beta1.CertificateApproved, - LastUpdateTime: metav1.NewTime(time.Now()), - Message: "This CSR was approved by eksctl", - Reason: "eksctl-approve", - }, - } - - if _, err := csrClientSet.UpdateApproval(context.TODO(), certificateSigningRequest, metav1.UpdateOptions{}); err != nil { - return errors.Wrap(err, "updating approval") - } - - logger.Info("waiting for certificate to be available") - - cert, err := watchCSRApproval(csrClientSet, csrName, certWaitTimeout) - if err != nil { - return err - } - - return v.createCertSecrets(privateKey, cert) -} - -func watchCSRApproval(csrClientSet v1beta1.CertificateSigningRequestInterface, csrName string, timeout time.Duration) ([]byte, error) { - watcher, err := csrClientSet.Watch(context.TODO(), metav1.ListOptions{ - FieldSelector: fmt.Sprintf("metadata.name=%s", csrName), - }) - - if err != nil { - return nil, err - } - - defer watcher.Stop() - - timer := time.NewTimer(timeout) - defer timer.Stop() - - for { - select { - case event, ok := <-watcher.ResultChan(): - if !ok { - return nil, errors.New("failed waiting for certificate: unexpected close of ResultChan") - } - switch event.Type { - case watch.Added, watch.Modified: - req := event.Object.(*certsv1beta1.CertificateSigningRequest) - if cert := req.Status.Certificate; cert != nil { - return cert, nil - } - logger.Warning("certificate not yet available (event: %s)", event.Type) - } - case <-timer.C: - return nil, fmt.Errorf("timed out (after %v) waiting for certificate", timeout) - } - - } -} - -func (v *VPCController) createCertSecrets(key, cert []byte) error { - secret := &corev1.Secret{ - TypeMeta: metav1.TypeMeta{ - Kind: "secret", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "vpc-admission-webhook-certs", - Namespace: vpcControllerNamespace, - }, - Data: map[string][]byte{ - "key.pem": key, - "cert.pem": cert, - }, - } - - err := v.applyRawResource(secret) - if err != nil { - return errors.Wrap(err, "error creating secret") - } - return err + RawClient kubernetes.RawClientInterface } -func makePolicyDocument() map[string]interface{} { - return map[string]interface{}{ - "Version": "2012-10-17", - "Statement": []map[string]interface{}{ - { - "Effect": "Allow", - "Action": []string{ - "ec2:AssignPrivateIpAddresses", - "ec2:DescribeInstances", - "ec2:DescribeNetworkInterfaces", - "ec2:UnassignPrivateIpAddresses", - "ec2:DescribeRouteTables", - "ec2:DescribeSubnets", - }, - "Resource": "*", - }, - }, - } -} - -func (v *VPCController) deployVPCResourceController() error { - irsaEnabled, err := v.irsa.IsSupported() +// Delete deletes the resources for VPC controller. +func (v *VPCController) Delete() error { + vpcControllerMetadata, err := vpcControllerMetadataYamlBytes() if err != nil { - return err + return errors.Wrap(err, "unexpected error loading manifests") } - if irsaEnabled { - sa := &api.ClusterIAMServiceAccount{ - ClusterIAMMeta: api.ClusterIAMMeta{ - Name: vpcControllerName, - Namespace: vpcControllerNamespace, - }, - AttachPolicy: makePolicyDocument(), - } - if err := v.irsa.CreateOrUpdate(sa); err != nil { - return errors.Wrap(err, "error enabling IRSA") - } - } else { - // If an OIDC provider isn't associated with the cluster, the VPC controller relies on the managed policy - // attached to the node role for the AWS VPC CNI plugin. - sa := kubernetes.NewServiceAccount(metav1.ObjectMeta{ - Name: vpcControllerName, - Namespace: vpcControllerNamespace, - }) - if err := v.applyRawResource(sa); err != nil { - return err - } - } - if err := v.applyResources(assetutil.MustLoad(vpcResourceControllerYamlBytes)); err != nil { - return err - } - - return v.applyDeployment(assetutil.MustLoad(vpcResourceControllerDepYamlBytes)) -} - -func (v *VPCController) deployVPCWebhook() error { - if err := v.applyResources(assetutil.MustLoad(vpcAdmissionWebhookYamlBytes)); err != nil { - return err - } - if err := v.applyDeployment(assetutil.MustLoad(vpcAdmissionWebhookDepYamlBytes)); err != nil { - return err - } - - manifest := assetutil.MustLoad(vpcAdmissionWebhookConfigYamlBytes) - rawExtension, err := kubernetes.NewRawExtension(manifest) - if err != nil { - return err - } - - mutatingWebhook, ok := rawExtension.Object.(*admv1beta1.MutatingWebhookConfiguration) - if !ok { - return &typeAssertionError{&admv1beta1.MutatingWebhookConfiguration{}, rawExtension.Object} - } - - mutatingWebhook.Webhooks[0].ClientConfig.CABundle = v.clusterStatus.CertificateAuthorityData - return v.applyRawResource(rawExtension.Object) -} - -func (v *VPCController) hasApprovedCert() (bool, error) { - csrClientSet := v.rawClient.ClientSet().CertificatesV1beta1().CertificateSigningRequests() - request, err := csrClientSet.Get(context.TODO(), fmt.Sprintf("%s.%s", webhookServiceName, vpcControllerNamespace), metav1.GetOptions{}) + list, err := kubernetes.NewList(vpcControllerMetadata) if err != nil { - if !apierrors.IsNotFound(err) { - return false, err - } - return false, nil + return errors.Wrap(err, "unexpected error parsing manifests") } - - conditions := request.Status.Conditions - switch len(conditions) { - case 1: - if conditions[0].Type == certsv1beta1.CertificateApproved { - return true, nil - } - return false, fmt.Errorf("expected certificate to be approved; got %q", conditions[0].Type) - - case 0: - return false, nil - default: - return false, fmt.Errorf("unexpected number of request conditions: %d", len(conditions)) - } -} - -func (v *VPCController) applyResources(manifests []byte) error { - list, err := kubernetes.NewList(manifests) - if err != nil { - return err - } - for _, item := range list.Items { - if err := v.applyRawResource(item.Object); err != nil { + if err := v.deleteResource(item.Object); err != nil { return err } } return nil } -func (v *VPCController) applyDeployment(manifests []byte) error { - rawExtension, err := kubernetes.NewRawExtension(manifests) - if err != nil { - return err - } - - deployment, ok := rawExtension.Object.(*appsv1.Deployment) - if !ok { - return &typeAssertionError{&appsv1.Deployment{}, rawExtension.Object} - } - if err := UseRegionalImage(&deployment.Spec.Template, v.region); err != nil { - return err - } - return v.applyRawResource(rawExtension.Object) -} - -func (v *VPCController) applyRawResource(object runtime.Object) error { - rawResource, err := v.rawClient.NewRawResource(object) +func (v *VPCController) deleteResource(o runtime.Object) error { + r, err := v.RawClient.NewRawResource(o) if err != nil { - return err + return errors.Wrap(err, "unexpected error creating raw resource") } - - switch newObject := object.(type) { - case *corev1.Service: - r, found, err := rawResource.Get() - if err != nil { - return err - } - if found { - service, ok := r.(*corev1.Service) - if !ok { - return &typeAssertionError{&corev1.Service{}, r} - } - newObject.Spec.ClusterIP = service.Spec.ClusterIP - newObject.SetResourceVersion(service.GetResourceVersion()) - } - case *admv1beta1.MutatingWebhookConfiguration: - r, found, err := rawResource.Get() - if err != nil { - return err - } - if found { - mwc, ok := r.(*admv1beta1.MutatingWebhookConfiguration) - if !ok { - return &typeAssertionError{&admv1beta1.MutatingWebhookConfiguration{}, r} - } - newObject.SetResourceVersion(mwc.GetResourceVersion()) - } - } - - msg, err := rawResource.CreateOrReplace(v.planMode) + msg, err := r.DeleteSync() if err != nil { - return err + return errors.Wrapf(err, "error deleting resource %q", r.Info.String()) } logger.Info(msg) return nil } - -func generateCertReq(service, namespace string) ([]byte, []byte, error) { - generator := csr.Generator{ - Validator: func(request *csr.CertificateRequest) error { - // ignore validation as all required fields are being set - return nil - }, - } - - serviceCN := fmt.Sprintf("%s.%s.svc", service, namespace) - - return generator.ProcessRequest(&csr.CertificateRequest{ - KeyRequest: &csr.KeyRequest{ - A: "rsa", - S: 2048, - }, - CN: serviceCN, - Hosts: []string{ - service, - fmt.Sprintf("%s.%s", service, namespace), - serviceCN, - }, - }) -} diff --git a/pkg/ctl/utils/install_vpc_controllers.go b/pkg/ctl/utils/install_vpc_controllers.go index 79e3893844..36c7d44fb7 100644 --- a/pkg/ctl/utils/install_vpc_controllers.go +++ b/pkg/ctl/utils/install_vpc_controllers.go @@ -17,12 +17,15 @@ func installWindowsVPCController(cmd *cmdutils.Cmd) { cmd.SetDescription("install-vpc-controllers", "Install Windows VPC controller to support running Windows workloads", "") + var deleteController bool + cmd.CobraCommand.RunE = func(_ *cobra.Command, args []string) error { cmd.NameArg = cmdutils.GetNameArg(args) - return doInstallWindowsVPCController(cmd) + return doInstallWindowsVPCController(cmd, deleteController) } cmd.FlagSetGroup.InFlagSet("General", func(fs *pflag.FlagSet) { + fs.BoolVar(&deleteController, "delete", false, "Deletes VPC resource controller from worker nodes") cmdutils.AddClusterFlagWithDeprecated(fs, cfg.Metadata) cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig) cmdutils.AddConfigFileFlag(fs, &cmd.ClusterConfigFile) @@ -33,33 +36,36 @@ func installWindowsVPCController(cmd *cmdutils.Cmd) { cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, &cmd.ProviderConfig, false) } -func doInstallWindowsVPCController(cmd *cmdutils.Cmd) error { +func doInstallWindowsVPCController(cmd *cmdutils.Cmd, deleteController bool) error { + if !deleteController { + logger.Warning("you no longer need to install the VPC resource controller on Linux worker nodes to run " + + "Windows workloads in EKS clusters. You can enable Windows IP address management on the EKS control plane via " + + "a ConfigMap setting (see https://todo.com for details). eksctl will automatically patch the ConfigMap to enable " + + "Windows IP address management when a Windows nodegroup is created. For existing clusters, you can enable it manually " + + "and re-run this command with the --delete flag to remove the worker node installation of the VPC resource controller") + return nil + } + if err := cmdutils.NewMetadataLoader(cmd).Load(); err != nil { return err } - cfg := cmd.ClusterConfig - meta := cmd.ClusterConfig.Metadata - ctl, err := cmd.NewProviderForExistingCluster() if err != nil { return err } - logger.Info("using region %s", meta.Region) - - if ok, err := ctl.CanUpdate(cfg); !ok { + logger.Info("using region %s", cmd.ClusterConfig.Metadata.Region) + rawClient, err := ctl.NewRawClient(cmd.ClusterConfig) + if err != nil { return err } - - vpcControllerTask := &eks.VPCControllerTask{ - Info: "install Windows VPC controller", - ClusterConfig: cfg, - ClusterProvider: ctl, - PlanMode: cmd.Plan, + deleteControllerTask := &eks.DeleteVPCControllerTask{ + Info: "delete Windows VPC controller", + RawClient: rawClient, } taskTree := &tasks.TaskTree{ - Tasks: []tasks.Task{vpcControllerTask}, + Tasks: []tasks.Task{deleteControllerTask}, } if errs := taskTree.DoAllSync(); len(errs) > 0 { diff --git a/pkg/eks/tasks.go b/pkg/eks/tasks.go index b457a8b22a..2db32a1328 100644 --- a/pkg/eks/tasks.go +++ b/pkg/eks/tasks.go @@ -6,11 +6,9 @@ import ( "time" "github.com/weaveworks/eksctl/pkg/actions/identityproviders" - "github.com/weaveworks/eksctl/pkg/actions/irsa" "github.com/kris-nova/logger" "github.com/pkg/errors" - "github.com/weaveworks/eksctl/pkg/cfn/manager" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" @@ -40,44 +38,25 @@ func (t *clusterConfigTask) Do(errs chan error) error { return err } -// VPCControllerTask represents a task to install the VPC controller -type VPCControllerTask struct { - Info string - ClusterProvider *ClusterProvider - ClusterConfig *api.ClusterConfig - PlanMode bool +// DeleteVPCControllerTask is a task for deleting VPC controller resources. +type DeleteVPCControllerTask struct { + RawClient kubernetes.RawClientInterface + Info string } -// Describe implements Task -func (v *VPCControllerTask) Describe() string { return v.Info } - -// Do implements Task -func (v *VPCControllerTask) Do(errCh chan error) error { +// Do implements Task. +func (v *DeleteVPCControllerTask) Do(errCh chan error) error { defer close(errCh) - rawClient, err := v.ClusterProvider.NewRawClient(v.ClusterConfig) - if err != nil { - return err - } - oidc, err := v.ClusterProvider.NewOpenIDConnectManager(v.ClusterConfig) - if err != nil { - return err - } - stackCollection := manager.NewStackCollection(v.ClusterProvider.Provider, v.ClusterConfig) - - clientSet, err := v.ClusterProvider.NewStdClientSet(v.ClusterConfig) - if err != nil { - return err + vpcController := &addons.VPCController{ + RawClient: v.RawClient, } - irsaManager := irsa.New(v.ClusterConfig.Metadata.Name, stackCollection, oidc, clientSet) - irsa := addons.NewIRSAHelper(oidc, stackCollection, irsaManager, v.ClusterConfig.Metadata.Name) + return vpcController.Delete() +} - // TODO PlanMode doesn't work as intended - vpcController := addons.NewVPCController(rawClient, irsa, v.ClusterConfig.Status, v.ClusterProvider.Provider.Region(), v.PlanMode) - if err := vpcController.Deploy(); err != nil { - return errors.Wrap(err, "error installing VPC controller") - } - return nil +// Describe implements Task. +func (v *DeleteVPCControllerTask) Describe() string { + return v.Info } type devicePluginTask struct { @@ -188,7 +167,7 @@ func (t *restartDaemonsetTask) Do(errCh chan error) error { } // CreateExtraClusterConfigTasks returns all tasks for updating cluster configuration not depending on the control plane availability -func (c *ClusterProvider) CreateExtraClusterConfigTasks(cfg *api.ClusterConfig, installVPCController bool) *tasks.TaskTree { +func (c *ClusterProvider) CreateExtraClusterConfigTasks(cfg *api.ClusterConfig, enableWindowsSupport bool) *tasks.TaskTree { newTasks := &tasks.TaskTree{ Parallel: false, IsSubTask: true, @@ -254,11 +233,12 @@ func (c *ClusterProvider) CreateExtraClusterConfigTasks(cfg *api.ClusterConfig, newTasks.Append(identityproviders.NewAssociateProvidersTask(*cfg.Metadata, cfg.IdentityProviders, c.Provider.EKS())) } - if installVPCController { - newTasks.Append(&VPCControllerTask{ - Info: "install Windows VPC controller", - ClusterConfig: cfg, - ClusterProvider: c, + if enableWindowsSupport { + newTasks.Append(&WindowsIPAMTask{ + Info: "enable Windows IP address management", + ClientsetFunc: func() (kubernetes.Interface, error) { + return c.NewStdClientSet(cfg) + }, }) } From 9258b734c8b48e9769620cef9772713e8a22e940 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Thu, 14 Oct 2021 15:36:55 +0530 Subject: [PATCH 2/6] Enable Windows IPAM when creating a Windows nodegroup --- pkg/actions/nodegroup/create.go | 9 +++ pkg/apis/eksctl.io/v1alpha5/nodegroups.go | 10 +++ pkg/ctl/create/cluster.go | 7 +- pkg/eks/tasks.go | 26 +++++++ pkg/windows/ipam.go | 93 +++++++++++++++++++++++ 5 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 pkg/windows/ipam.go diff --git a/pkg/actions/nodegroup/create.go b/pkg/actions/nodegroup/create.go index 57205cc409..77cc8bbb75 100644 --- a/pkg/actions/nodegroup/create.go +++ b/pkg/actions/nodegroup/create.go @@ -160,6 +160,15 @@ func (m *Manager) nodeCreationTasks(options CreateOpts, nodegroupFilter filter.N taskTree.Append(m.stackManager.NewClusterCompatTask()) } + if m.cfg.HasWindowsNodeGroup() { + taskTree.Append(&eks.WindowsIPAMTask{ + Info: "enable Windows IPAM", + ClientsetFunc: func() (kubernetes.Interface, error) { + return m.ctl.NewStdClientSet(m.cfg) + }, + }) + } + awsNodeUsesIRSA, err := init.DoesAWSNodeUseIRSA(m.ctl.Provider, m.clientSet) if err != nil { return errors.Wrap(err, "couldn't check aws-node for annotation") diff --git a/pkg/apis/eksctl.io/v1alpha5/nodegroups.go b/pkg/apis/eksctl.io/v1alpha5/nodegroups.go index 00382c7ca2..548c6d5928 100644 --- a/pkg/apis/eksctl.io/v1alpha5/nodegroups.go +++ b/pkg/apis/eksctl.io/v1alpha5/nodegroups.go @@ -78,3 +78,13 @@ func (c *ClusterConfig) AllNodeGroups() []*NodeGroupBase { } return baseNodeGroups } + +// HasWindowsNodeGroup returns true if an unmanaged Windows nodegroup exists. +func (c *ClusterConfig) HasWindowsNodeGroup() bool { + for _, ng := range c.NodeGroups { + if IsWindowsImage(ng.AMIFamily) { + return true + } + } + return false +} diff --git a/pkg/ctl/create/cluster.go b/pkg/ctl/create/cluster.go index f3d96d66f1..4b6b163e39 100644 --- a/pkg/ctl/create/cluster.go +++ b/pkg/ctl/create/cluster.go @@ -190,6 +190,11 @@ func doCreateCluster(cmd *cmdutils.Cmd, ngFilter *filter.NodeGroupFilter, params if !eks.SupportsWindowsWorkloads(kubeNodeGroups) { return errors.New("running Windows workloads requires having both Windows and Linux (AmazonLinux2) node groups") } + logger.Warning("you no longer need to install the VPC resource controller on Linux worker nodes to run " + + "Windows workloads in EKS clusters. You can enable Windows IP address management on the EKS control plane via " + + "a ConfigMap setting (see https://todo.com for details). eksctl will automatically patch the ConfigMap to enable " + + "Windows IP address management when a Windows nodegroup is created. For existing clusters, you can enable it manually " + + "and re-run this command with the --delete flag to remove the worker node installation of the VPC resource controller") } else { eks.LogWindowsCompatibility(kubeNodeGroups, cfg.Metadata) } @@ -248,7 +253,7 @@ func doCreateCluster(cmd *cmdutils.Cmd, ngFilter *filter.NodeGroupFilter, params if err != nil { return err } - postClusterCreationTasks := ctl.CreateExtraClusterConfigTasks(cfg, params.InstallWindowsVPCController) + postClusterCreationTasks := ctl.CreateExtraClusterConfigTasks(cfg, eks.SupportsWindowsWorkloads(kubeNodeGroups)) supported, err := utils.IsMinVersion(api.Version1_18, cfg.Metadata.Version) if err != nil { diff --git a/pkg/eks/tasks.go b/pkg/eks/tasks.go index 2db32a1328..47ba733b46 100644 --- a/pkg/eks/tasks.go +++ b/pkg/eks/tasks.go @@ -6,6 +6,7 @@ import ( "time" "github.com/weaveworks/eksctl/pkg/actions/identityproviders" + "github.com/weaveworks/eksctl/pkg/windows" "github.com/kris-nova/logger" "github.com/pkg/errors" @@ -38,6 +39,31 @@ func (t *clusterConfigTask) Do(errs chan error) error { return err } +// WindowsIPAMTask is a task for enabling Windows IPAM. +type WindowsIPAMTask struct { + Info string + ClientsetFunc func() (kubernetes.Interface, error) +} + +// Do implements Task. +func (w *WindowsIPAMTask) Do(errCh chan error) error { + defer close(errCh) + + clientset, err := w.ClientsetFunc() + if err != nil { + return err + } + windowsIPAM := windows.IPAM{ + Clientset: clientset, + } + return windowsIPAM.Enable(context.TODO()) +} + +// Describe implements Task. +func (w *WindowsIPAMTask) Describe() string { + return w.Info +} + // DeleteVPCControllerTask is a task for deleting VPC controller resources. type DeleteVPCControllerTask struct { RawClient kubernetes.RawClientInterface diff --git a/pkg/windows/ipam.go b/pkg/windows/ipam.go new file mode 100644 index 0000000000..a09b5a9b5f --- /dev/null +++ b/pkg/windows/ipam.go @@ -0,0 +1,93 @@ +package windows + +import ( + "context" + "encoding/json" + + "github.com/kris-nova/logger" + + "k8s.io/apimachinery/pkg/types" + + jsonpatch "github.com/evanphx/json-patch/v5" + + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" + + corev1 "k8s.io/api/core/v1" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/pkg/errors" + + "k8s.io/client-go/kubernetes" +) + +const ( + vpcCNIName = "amazon-vpc-cni" + vpcCNINamespace = metav1.NamespaceSystem + windowsIPAMField = "enable-windows-ipam" +) + +// IPAM enables Windows IPAM +type IPAM struct { + Clientset kubernetes.Interface +} + +// Enable enables Windows IPAM +func (w *IPAM) Enable(ctx context.Context) error { + configMaps := w.Clientset.CoreV1().ConfigMaps(metav1.NamespaceSystem) + vpcCNIConfig, err := configMaps.Get(ctx, vpcCNIName, metav1.GetOptions{}) + if err != nil { + if !apierrors.IsNotFound(err) { + return errors.Wrap(err, "error getting resource") + } + return createConfigMap(ctx, configMaps) + } + + if val, ok := vpcCNIConfig.Data[windowsIPAMField]; ok && val == "true" { + logger.Info("Windows IPAM is already enabled") + return nil + } + + patch, err := createPatch(vpcCNIConfig) + if err != nil { + return errors.Wrap(err, "error creating merge patch") + } + + _, err = configMaps.Patch(ctx, vpcCNIName, types.StrategicMergePatchType, patch, metav1.PatchOptions{}) + if err != nil { + return errors.Wrap(err, "failed to patch resource") + } + return nil +} + +func createPatch(cm *corev1.ConfigMap) ([]byte, error) { + oldData, err := json.Marshal(cm) + if err != nil { + return nil, err + } + cm.Data[windowsIPAMField] = "true" + modifiedData, err := json.Marshal(cm) + if err != nil { + return nil, err + } + return jsonpatch.CreateMergePatch(oldData, modifiedData) +} + +func createConfigMap(ctx context.Context, configMaps corev1client.ConfigMapInterface) error { + cm := &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + Kind: "ConfigMap", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: vpcCNIName, + Namespace: vpcCNINamespace, + }, + Data: map[string]string{ + windowsIPAMField: "true", + }, + } + _, err := configMaps.Create(ctx, cm, metav1.CreateOptions{}) + return err +} From 92aefb3312863d43160d97288bd656f57f2853f1 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Thu, 14 Oct 2021 16:39:49 +0530 Subject: [PATCH 3/6] Handle plan mode, deprecate command --- pkg/addons/vpc_controller.go | 16 +++++++++++----- pkg/ctl/create/cluster.go | 12 ++++++------ pkg/ctl/utils/install_vpc_controllers.go | 9 ++++----- pkg/eks/tasks.go | 8 +++++--- pkg/kubernetes/client.go | 7 +++++-- pkg/kubernetes/client_test.go | 2 +- 6 files changed, 32 insertions(+), 22 deletions(-) diff --git a/pkg/addons/vpc_controller.go b/pkg/addons/vpc_controller.go index f1cbf5f2d6..e6f9e059a3 100644 --- a/pkg/addons/vpc_controller.go +++ b/pkg/addons/vpc_controller.go @@ -5,17 +5,21 @@ import ( "github.com/pkg/errors" "github.com/weaveworks/eksctl/pkg/kubernetes" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" ) const ( - vpcControllerNamespace = metav1.NamespaceSystem + VPCControllerInfoMessage = "you no longer need to install the VPC resource controller on Linux worker nodes to run " + + "Windows workloads in EKS clusters. You can enable Windows IP address management on the EKS control plane via " + + "a ConfigMap setting (see https://todo.com for details). eksctl will automatically patch the ConfigMap to enable " + + "Windows IP address management when a Windows nodegroup is created. For existing clusters, you can enable it manually " + + "and run `eksctl utils install-vpc-controllers` with the --delete flag to remove the worker node installation of the VPC resource controller" ) // VPCController deletes an existing installation of VPC controller from worker nodes. type VPCController struct { - RawClient kubernetes.RawClientInterface + RawClient *kubernetes.RawClient + PlanMode bool } // Delete deletes the resources for VPC controller. @@ -41,10 +45,12 @@ func (v *VPCController) deleteResource(o runtime.Object) error { if err != nil { return errors.Wrap(err, "unexpected error creating raw resource") } - msg, err := r.DeleteSync() + msg, err := r.DeleteSync(v.PlanMode) if err != nil { return errors.Wrapf(err, "error deleting resource %q", r.Info.String()) } - logger.Info(msg) + if msg != "" { + logger.Info(msg) + } return nil } diff --git a/pkg/ctl/create/cluster.go b/pkg/ctl/create/cluster.go index 4b6b163e39..45fbb32e77 100644 --- a/pkg/ctl/create/cluster.go +++ b/pkg/ctl/create/cluster.go @@ -6,6 +6,8 @@ import ( "os" "strings" + "github.com/weaveworks/eksctl/pkg/addons" + "github.com/aws/amazon-ec2-instance-selector/v2/pkg/selector" "github.com/weaveworks/eksctl/pkg/kops" "github.com/weaveworks/eksctl/pkg/utils" @@ -71,6 +73,8 @@ func createClusterCmdWithRunFunc(cmd *cmdutils.Cmd, runFunc func(cmd *cmdutils.C fs.BoolVarP(¶ms.InstallWindowsVPCController, "install-vpc-controllers", "", false, "Install VPC controller that's required for Windows workloads") fs.BoolVarP(¶ms.Fargate, "fargate", "", false, "Create a Fargate profile scheduling pods in the default and kube-system namespaces onto Fargate") fs.BoolVarP(¶ms.DryRun, "dry-run", "", false, "Dry-run mode that skips cluster creation and outputs a ClusterConfig") + + _ = fs.MarkDeprecated("install-vpc-controllers", addons.VPCControllerInfoMessage) }) cmd.FlagSetGroup.InFlagSet("Initial nodegroup", func(fs *pflag.FlagSet) { @@ -190,11 +194,7 @@ func doCreateCluster(cmd *cmdutils.Cmd, ngFilter *filter.NodeGroupFilter, params if !eks.SupportsWindowsWorkloads(kubeNodeGroups) { return errors.New("running Windows workloads requires having both Windows and Linux (AmazonLinux2) node groups") } - logger.Warning("you no longer need to install the VPC resource controller on Linux worker nodes to run " + - "Windows workloads in EKS clusters. You can enable Windows IP address management on the EKS control plane via " + - "a ConfigMap setting (see https://todo.com for details). eksctl will automatically patch the ConfigMap to enable " + - "Windows IP address management when a Windows nodegroup is created. For existing clusters, you can enable it manually " + - "and re-run this command with the --delete flag to remove the worker node installation of the VPC resource controller") + logger.Warning(addons.VPCControllerInfoMessage) } else { eks.LogWindowsCompatibility(kubeNodeGroups, cfg.Metadata) } @@ -253,7 +253,7 @@ func doCreateCluster(cmd *cmdutils.Cmd, ngFilter *filter.NodeGroupFilter, params if err != nil { return err } - postClusterCreationTasks := ctl.CreateExtraClusterConfigTasks(cfg, eks.SupportsWindowsWorkloads(kubeNodeGroups)) + postClusterCreationTasks := ctl.CreateExtraClusterConfigTasks(cfg) supported, err := utils.IsMinVersion(api.Version1_18, cfg.Metadata.Version) if err != nil { diff --git a/pkg/ctl/utils/install_vpc_controllers.go b/pkg/ctl/utils/install_vpc_controllers.go index 36c7d44fb7..1306f64e5e 100644 --- a/pkg/ctl/utils/install_vpc_controllers.go +++ b/pkg/ctl/utils/install_vpc_controllers.go @@ -4,6 +4,7 @@ import ( "github.com/kris-nova/logger" "github.com/spf13/cobra" "github.com/spf13/pflag" + "github.com/weaveworks/eksctl/pkg/addons" "github.com/weaveworks/eksctl/pkg/eks" "github.com/weaveworks/eksctl/pkg/utils/tasks" @@ -16,6 +17,7 @@ func installWindowsVPCController(cmd *cmdutils.Cmd) { cmd.ClusterConfig = cfg cmd.SetDescription("install-vpc-controllers", "Install Windows VPC controller to support running Windows workloads", "") + cmd.CobraCommand.Deprecated = addons.VPCControllerInfoMessage var deleteController bool @@ -38,11 +40,7 @@ func installWindowsVPCController(cmd *cmdutils.Cmd) { func doInstallWindowsVPCController(cmd *cmdutils.Cmd, deleteController bool) error { if !deleteController { - logger.Warning("you no longer need to install the VPC resource controller on Linux worker nodes to run " + - "Windows workloads in EKS clusters. You can enable Windows IP address management on the EKS control plane via " + - "a ConfigMap setting (see https://todo.com for details). eksctl will automatically patch the ConfigMap to enable " + - "Windows IP address management when a Windows nodegroup is created. For existing clusters, you can enable it manually " + - "and re-run this command with the --delete flag to remove the worker node installation of the VPC resource controller") + logger.Warning(addons.VPCControllerInfoMessage) return nil } @@ -61,6 +59,7 @@ func doInstallWindowsVPCController(cmd *cmdutils.Cmd, deleteController bool) err } deleteControllerTask := &eks.DeleteVPCControllerTask{ Info: "delete Windows VPC controller", + PlanMode: cmd.Plan, RawClient: rawClient, } diff --git a/pkg/eks/tasks.go b/pkg/eks/tasks.go index 47ba733b46..b749d07170 100644 --- a/pkg/eks/tasks.go +++ b/pkg/eks/tasks.go @@ -66,7 +66,8 @@ func (w *WindowsIPAMTask) Describe() string { // DeleteVPCControllerTask is a task for deleting VPC controller resources. type DeleteVPCControllerTask struct { - RawClient kubernetes.RawClientInterface + RawClient *kubernetes.RawClient + PlanMode bool Info string } @@ -76,6 +77,7 @@ func (v *DeleteVPCControllerTask) Do(errCh chan error) error { vpcController := &addons.VPCController{ RawClient: v.RawClient, + PlanMode: v.PlanMode, } return vpcController.Delete() } @@ -193,7 +195,7 @@ func (t *restartDaemonsetTask) Do(errCh chan error) error { } // CreateExtraClusterConfigTasks returns all tasks for updating cluster configuration not depending on the control plane availability -func (c *ClusterProvider) CreateExtraClusterConfigTasks(cfg *api.ClusterConfig, enableWindowsSupport bool) *tasks.TaskTree { +func (c *ClusterProvider) CreateExtraClusterConfigTasks(cfg *api.ClusterConfig) *tasks.TaskTree { newTasks := &tasks.TaskTree{ Parallel: false, IsSubTask: true, @@ -259,7 +261,7 @@ func (c *ClusterProvider) CreateExtraClusterConfigTasks(cfg *api.ClusterConfig, newTasks.Append(identityproviders.NewAssociateProvidersTask(*cfg.Metadata, cfg.IdentityProviders, c.Provider.EKS())) } - if enableWindowsSupport { + if cfg.HasWindowsNodeGroup() { newTasks.Append(&WindowsIPAMTask{ Info: "enable Windows IP address management", ClientsetFunc: func() (kubernetes.Interface, error) { diff --git a/pkg/kubernetes/client.go b/pkg/kubernetes/client.go index 10b7bf2a3e..cd6494264a 100644 --- a/pkg/kubernetes/client.go +++ b/pkg/kubernetes/client.go @@ -245,7 +245,7 @@ func (c *RawClient) deleteObject(object runtime.RawExtension) error { if err != nil { return err } - status, err := resource.DeleteSync() + status, err := resource.DeleteSync(false) if err != nil { return err } @@ -415,7 +415,7 @@ func (r *RawResource) CreatePatchOrReplace() error { // DeleteSync attempts to delete this Kubernetes resource, or returns doing // nothing if it does not exist. It blocks until the resource has been deleted. -func (r *RawResource) DeleteSync() (string, error) { +func (r *RawResource) DeleteSync(plan bool) (string, error) { _, exists, err := r.Get() if err != nil { return "", err @@ -423,6 +423,9 @@ func (r *RawResource) DeleteSync() (string, error) { if !exists { return "", nil } + if plan { + return r.LogAction(true, "deleted"), nil + } propagationPolicy := metav1.DeletePropagationForeground if _, err := r.Helper.DeleteWithOptions(r.Info.Namespace, r.Info.Name, &metav1.DeleteOptions{ PropagationPolicy: &propagationPolicy, diff --git a/pkg/kubernetes/client_test.go b/pkg/kubernetes/client_test.go index aa037e04ef..5a553a9a77 100644 --- a/pkg/kubernetes/client_test.go +++ b/pkg/kubernetes/client_test.go @@ -243,7 +243,7 @@ var _ = Describe("Kubernetes client wrappers", func() { Expect(err).ToNot(HaveOccurred()) Expect(exists).To(BeTrue()) // The Kubernetes resource already exists. - status, err := rc.DeleteSync() + status, err := rc.DeleteSync(false) Expect(err).ToNot(HaveOccurred()) Expect(status).To(Equal(fmt.Sprintf("deleted %q", rc))) Expect(track).ToNot(BeNil()) From 5439eadd289caf688d0ed5a385b119e9cdaf299d Mon Sep 17 00:00:00 2001 From: cpu1 Date: Thu, 14 Oct 2021 16:42:27 +0530 Subject: [PATCH 4/6] Remove deprecated flag from integration test --- integration/tests/windows/windows_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/integration/tests/windows/windows_test.go b/integration/tests/windows/windows_test.go index 67b08e1994..298726b343 100644 --- a/integration/tests/windows/windows_test.go +++ b/integration/tests/windows/windows_test.go @@ -70,7 +70,6 @@ var _ = Describe("(Integration) [Windows Nodegroups]", func() { "--config-file", "-", "--verbose", "4", "--kubeconfig", params.KubeconfigPath, - "--install-vpc-controllers", ). WithoutArg("--region", params.Region). WithStdin(bytes.NewReader(data)) From 384a7aeb03bb09ae087c018777b6621eb82905d5 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Thu, 14 Oct 2021 16:56:24 +0530 Subject: [PATCH 5/6] Update docs and example --- examples/14-windows-nodes.yaml | 4 +++- userdocs/src/usage/windows-worker-nodes.md | 17 +++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/examples/14-windows-nodes.yaml b/examples/14-windows-nodes.yaml index 59dcb25f5f..698247685c 100644 --- a/examples/14-windows-nodes.yaml +++ b/examples/14-windows-nodes.yaml @@ -1,5 +1,5 @@ # An example of ClusterConfig containing Windows and Linux node groups to support Windows workloads -# This example should be run with `eksctl create cluster -f 14-windows-nodes.yaml --install-vpc-controllers` +# This example should be run with `eksctl create cluster -f 14-windows-nodes.yaml` --- apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig @@ -13,6 +13,8 @@ nodeGroups: amiFamily: WindowsServer2019FullContainer minSize: 2 maxSize: 3 + +managedNodeGroups: - name: linux-ng instanceType: t2.large minSize: 2 diff --git a/userdocs/src/usage/windows-worker-nodes.md b/userdocs/src/usage/windows-worker-nodes.md index 96bd63ba20..3a3dce626f 100644 --- a/userdocs/src/usage/windows-worker-nodes.md +++ b/userdocs/src/usage/windows-worker-nodes.md @@ -1,10 +1,15 @@ # Windows Worker Nodes From version 1.14, Amazon EKS supports [Windows Nodes][eks-user-guide] that allow running Windows containers. -In addition to having Windows nodes, a Linux node in the cluster is required to run the VPC resource controller and CoreDNS, as Microsoft doesn't support host-networking mode yet. Thus, a Windows EKS cluster will be a mixed-mode cluster containing Windows nodes and at least one Linux node. +In addition to having Windows nodes, a Linux node in the cluster is required to run CoreDNS, as Microsoft doesn't support host-networking mode yet. Thus, a Windows EKS cluster will be a mixed-mode cluster containing Windows nodes and at least one Linux node. The Linux nodes are critical to the functioning of the cluster, and thus, for a production-grade cluster, it's recommended to have at least two `t2.large` Linux nodes for HA. -`eksctl` provides a flag to install the VPC resource controller as part of cluster creation, and a command to install it after a cluster has been created. +!!!note + You no longer need to install the VPC resource controller on Linux worker nodes to run Windows workloads in EKS clusters. + You can enable Windows IP address management on the EKS control plane via a ConfigMap setting (see https://todo.com for details). + eksctl will automatically patch the ConfigMap to enable Windows IP address management when a Windows nodegroup is created. + For existing clusters, you can enable it manually and run `eksctl utils install-vpc-controllers` with the `--delete` flag + to remove the worker node installation of the VPC resource controller. ## Creating a new Windows cluster @@ -26,6 +31,8 @@ nodeGroups: amiFamily: WindowsServer2019FullContainer minSize: 2 maxSize: 3 + +managedNodeGroups: - name: linux-ng instanceType: t2.large minSize: 2 @@ -33,7 +40,7 @@ nodeGroups: ``` ```console -eksctl create cluster -f cluster.yaml --install-vpc-controllers +eksctl create cluster -f cluster.yaml ``` @@ -42,7 +49,6 @@ To create a new cluster without using a config file, issue the following command ```console eksctl create cluster --managed=false --name=windows-cluster --node-ami-family=WindowsServer2019CoreContainer eksctl create nodegroup --cluster=windows-cluster --node-ami-family=AmazonLinux2 --nodes-min=2 --node-type=t2.large -eksctl utils install-vpc-controllers --cluster=windows-cluster --approve ``` !!!note @@ -50,11 +56,10 @@ eksctl utils install-vpc-controllers --cluster=windows-cluster --approve ## Adding Windows support to an existing Linux cluster -To enable running Windows workloads on an existing cluster with Linux nodes (`AmazonLinux2` AMI family), you need to add a Windows node group and install the Windows VPC controller: +To enable running Windows workloads on an existing cluster with Linux nodes (`AmazonLinux2` AMI family), you need to add a Windows nodegroup. ```console eksctl create nodegroup --managed=false --cluster=existing-cluster --node-ami-family=WindowsServer2019CoreContainer -eksctl utils install-vpc-controllers --cluster=existing-cluster --approve ``` To ensure workloads are scheduled on the right OS, they must have a `nodeSelector` targeting the OS it must run on: From a6da10ab72027b4997b92ddc0a9b5148bfac7e84 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Thu, 14 Oct 2021 18:47:11 +0530 Subject: [PATCH 6/6] Add tests for IPAM, improve error messages --- pkg/windows/ipam.go | 23 ++--- pkg/windows/ipam_test.go | 97 ++++++++++++++++++++++ pkg/windows/windows_suite_test.go | 11 +++ userdocs/src/usage/windows-worker-nodes.md | 4 +- 4 files changed, 118 insertions(+), 17 deletions(-) create mode 100644 pkg/windows/ipam_test.go create mode 100644 pkg/windows/windows_suite_test.go diff --git a/pkg/windows/ipam.go b/pkg/windows/ipam.go index a09b5a9b5f..a2390e0028 100644 --- a/pkg/windows/ipam.go +++ b/pkg/windows/ipam.go @@ -4,22 +4,15 @@ import ( "context" "encoding/json" - "github.com/kris-nova/logger" - - "k8s.io/apimachinery/pkg/types" - jsonpatch "github.com/evanphx/json-patch/v5" - - corev1client "k8s.io/client-go/kubernetes/typed/core/v1" - + "github.com/kris-nova/logger" + "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/pkg/errors" - + "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes" + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" ) const ( @@ -28,18 +21,18 @@ const ( windowsIPAMField = "enable-windows-ipam" ) -// IPAM enables Windows IPAM +// IPAM enables Windows IPAM in the VPC CNI ConfigMap. type IPAM struct { Clientset kubernetes.Interface } -// Enable enables Windows IPAM +// Enable enables Windows IPAM in the VPC CNI ConfigMap. func (w *IPAM) Enable(ctx context.Context) error { configMaps := w.Clientset.CoreV1().ConfigMaps(metav1.NamespaceSystem) vpcCNIConfig, err := configMaps.Get(ctx, vpcCNIName, metav1.GetOptions{}) if err != nil { if !apierrors.IsNotFound(err) { - return errors.Wrap(err, "error getting resource") + return errors.Wrapf(err, "error getting ConfigMap %q", vpcCNIName) } return createConfigMap(ctx, configMaps) } @@ -56,7 +49,7 @@ func (w *IPAM) Enable(ctx context.Context) error { _, err = configMaps.Patch(ctx, vpcCNIName, types.StrategicMergePatchType, patch, metav1.PatchOptions{}) if err != nil { - return errors.Wrap(err, "failed to patch resource") + return errors.Wrapf(err, "failed to patch resource %q", vpcCNIName) } return nil } diff --git a/pkg/windows/ipam_test.go b/pkg/windows/ipam_test.go new file mode 100644 index 0000000000..97ced2e57c --- /dev/null +++ b/pkg/windows/ipam_test.go @@ -0,0 +1,97 @@ +package windows_test + +import ( + "context" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + . "github.com/onsi/gomega" + + . "github.com/onsi/ginkgo/extensions/table" + "github.com/weaveworks/eksctl/pkg/windows" + "k8s.io/client-go/kubernetes/fake" +) + +type ipamEntry struct { + existingConfigMapData map[string]string + + expectedConfigMapData map[string]string +} + +var _ = DescribeTable("Windows IPAM", func(e ipamEntry) { + var clientset *fake.Clientset + if e.existingConfigMapData != nil { + clientset = fake.NewSimpleClientset(&v1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + Kind: "ConfigMap", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "amazon-vpc-cni", + Namespace: "kube-system", + }, + Data: e.existingConfigMapData, + }) + } else { + clientset = fake.NewSimpleClientset() + } + + ipam := &windows.IPAM{ + Clientset: clientset, + } + ctx := context.Background() + err := ipam.Enable(ctx) + Expect(err).ToNot(HaveOccurred()) + + cm, err := clientset.CoreV1().ConfigMaps("kube-system").Get(ctx, "amazon-vpc-cni", metav1.GetOptions{}) + Expect(err).ToNot(HaveOccurred()) + Expect(cm.Data).To(Equal(e.expectedConfigMapData)) + +}, + Entry("VPC CNI ConfigMap is missing", ipamEntry{ + expectedConfigMapData: map[string]string{ + "enable-windows-ipam": "true", + }, + }), + + Entry("VPC CNI ConfigMap has data", ipamEntry{ + existingConfigMapData: map[string]string{ + "VPC_CNI_1": "yes", + "VPC_CNI_2": "no", + "other": "true", + }, + expectedConfigMapData: map[string]string{ + "VPC_CNI_1": "yes", + "VPC_CNI_2": "no", + "other": "true", + "enable-windows-ipam": "true", + }, + }), + + Entry("VPC CNI ConfigMap has Windows IPAM already enabled", ipamEntry{ + existingConfigMapData: map[string]string{ + "VPC_CNI_1": "yes", + "VPC_CNI_2": "no", + "enable-windows-ipam": "true", + }, + expectedConfigMapData: map[string]string{ + "VPC_CNI_1": "yes", + "VPC_CNI_2": "no", + "enable-windows-ipam": "true", + }, + }), + + Entry("VPC CNI ConfigMap has Windows IPAM explicitly disabled", ipamEntry{ + existingConfigMapData: map[string]string{ + "VPC_CNI_1": "yes", + "VPC_CNI_2": "no", + "enable-windows-ipam": "false", + }, + expectedConfigMapData: map[string]string{ + "VPC_CNI_1": "yes", + "VPC_CNI_2": "no", + "enable-windows-ipam": "true", + }, + }), +) diff --git a/pkg/windows/windows_suite_test.go b/pkg/windows/windows_suite_test.go new file mode 100644 index 0000000000..aa7fa2b4bf --- /dev/null +++ b/pkg/windows/windows_suite_test.go @@ -0,0 +1,11 @@ +package windows_test + +import ( + "testing" + + "github.com/weaveworks/eksctl/pkg/testutils" +) + +func TestWindows(t *testing.T) { + testutils.RegisterAndRun(t) +} diff --git a/userdocs/src/usage/windows-worker-nodes.md b/userdocs/src/usage/windows-worker-nodes.md index 3a3dce626f..3c5998e872 100644 --- a/userdocs/src/usage/windows-worker-nodes.md +++ b/userdocs/src/usage/windows-worker-nodes.md @@ -1,14 +1,14 @@ # Windows Worker Nodes From version 1.14, Amazon EKS supports [Windows Nodes][eks-user-guide] that allow running Windows containers. -In addition to having Windows nodes, a Linux node in the cluster is required to run CoreDNS, as Microsoft doesn't support host-networking mode yet. Thus, a Windows EKS cluster will be a mixed-mode cluster containing Windows nodes and at least one Linux node. +In addition to having Windows nodes, a Linux node in the cluster is required to run CoreDNS, as Microsoft doesn't support host-networking mode yet. Thus, a Windows EKS cluster will be a mixture of Windows nodes and at least one Linux node. The Linux nodes are critical to the functioning of the cluster, and thus, for a production-grade cluster, it's recommended to have at least two `t2.large` Linux nodes for HA. !!!note You no longer need to install the VPC resource controller on Linux worker nodes to run Windows workloads in EKS clusters. You can enable Windows IP address management on the EKS control plane via a ConfigMap setting (see https://todo.com for details). eksctl will automatically patch the ConfigMap to enable Windows IP address management when a Windows nodegroup is created. - For existing clusters, you can enable it manually and run `eksctl utils install-vpc-controllers` with the `--delete` flag + For existing clusters, you can enable it manually, and run `eksctl utils install-vpc-controllers` with the `--delete` flag to remove the worker node installation of the VPC resource controller. ## Creating a new Windows cluster