-
Notifications
You must be signed in to change notification settings - Fork 44
Single Node deployment with bootstrap-in-place #46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
70ddd20
a649ba9
3e64372
290d78b
6d7910f
0f61445
b3b043f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| package main | ||
|
|
||
| import ( | ||
| "errors" | ||
|
|
||
| "github.com/openshift/cluster-bootstrap/pkg/bootstrapinplace" | ||
|
|
||
| "github.com/spf13/cobra" | ||
| ) | ||
|
|
||
| var ( | ||
| CmdBootstrapInPlace = &cobra.Command{ | ||
| Use: "bootstrap-in-place", | ||
| Short: "Create Ignition based on Fedora CoreOS Config", | ||
| Long: "", | ||
| PreRunE: validateBootstrapInPlaceOpts, | ||
| RunE: runCmdBootstrapInPlace, | ||
| SilenceUsage: true, | ||
| } | ||
|
|
||
| bootstrapInPlaceOpts struct { | ||
| assetDir string | ||
| ignitionPath string | ||
| input string | ||
| Strict bool | ||
| Pretty bool | ||
| } | ||
| ) | ||
|
|
||
| func init() { | ||
| cmdRoot.AddCommand(CmdBootstrapInPlace) | ||
| CmdBootstrapInPlace.Flags().BoolVarP(&bootstrapInPlaceOpts.Strict, "strict", "s", true, "fail on any warning") | ||
| CmdBootstrapInPlace.Flags().BoolVarP(&bootstrapInPlaceOpts.Pretty, "pretty", "p", true, "output formatted json") | ||
| CmdBootstrapInPlace.Flags().StringVar(&bootstrapInPlaceOpts.input, "input", "", "fcc input file path") | ||
| CmdBootstrapInPlace.Flags().StringVar(&bootstrapInPlaceOpts.ignitionPath, "output", "o", "Ignition output file path") | ||
| CmdBootstrapInPlace.Flags().StringVarP(&bootstrapInPlaceOpts.assetDir, "asset-dir", "d", "", "allow embedding local files from this directory") | ||
| } | ||
|
|
||
| func runCmdBootstrapInPlace(cmd *cobra.Command, args []string) error { | ||
| bip, err := bootstrapinplace.NewBootstrapInPlaceCommand(bootstrapinplace.BootstrapInPlaceConfig{ | ||
| AssetDir: bootstrapInPlaceOpts.assetDir, | ||
| IgnitionPath: bootstrapInPlaceOpts.ignitionPath, | ||
| Input: bootstrapInPlaceOpts.input, | ||
| Strict: bootstrapInPlaceOpts.Strict, | ||
| Pretty: bootstrapInPlaceOpts.Pretty, | ||
| }) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| return bip.Create() | ||
| } | ||
|
|
||
| func validateBootstrapInPlaceOpts(cmd *cobra.Command, args []string) error { | ||
| if bootstrapInPlaceOpts.ignitionPath == "" { | ||
| return errors.New("missing required flag: --output") | ||
| } | ||
| if bootstrapInPlaceOpts.assetDir == "" { | ||
| return errors.New("missing required flag: --asset-dir") | ||
| } | ||
| if bootstrapInPlaceOpts.input == "" { | ||
| return errors.New("missing required flag: --input") | ||
| } | ||
| return nil | ||
| } | ||
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,20 @@ | ||
| package: github.com/openshift/cluster-bootstrap | ||
| import: | ||
| - package: k8s.io/apimachinery | ||
| version: kubernetes-1.13.4 | ||
| version: 86fb29eff6288413d76bd8506874fddd9fccdff0 | ||
eranco74 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| - package: k8s.io/api | ||
| version: kubernetes-1.13.4 | ||
| version: 5cb15d34447165a97c76ed5a60e4e99c8a01ecfe | ||
| - package: k8s.io/client-go | ||
| version: kubernetes-1.13.4 | ||
| version: b40b2a5939e43f7ffe0028ad67586b7ce50bb675 | ||
| - package: github.com/openshift/library-go | ||
| version: master | ||
| version: 950af653b51af28697df79f1406fc9d21f722db8 | ||
| - package: github.com/json-iterator/go | ||
| version: f2b4162afba35581b6d4a50d3b8f34e33c144682 | ||
| - package: google.golang.org/appengine | ||
| version: b2f4a3cf3c67576a2ee09e1fe62656a5086ce880 | ||
| - package: github.com/spf13/cobra | ||
| version: c439c4fa093711d42e1b01acb1235b52004753c1 | ||
| - package: github.com/spf13/pflag | ||
| version: 583c0c0531f06d5278b7d917446061adc344b5cd | ||
| - package: github.com/coreos/fcct | ||
| version: v0.8.0 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| // Copyright 2019 Red Hat, Inc | ||
|
|
||
| package bootstrapinplace | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "io/ioutil" | ||
| "os" | ||
|
|
||
| "github.com/coreos/fcct/config" | ||
| fcctCommon "github.com/coreos/fcct/config/common" | ||
| ) | ||
|
|
||
| func fail(format string, args ...interface{}) { | ||
| fmt.Printf(format, args...) | ||
| os.Exit(1) | ||
| } | ||
|
|
||
| type BootstrapInPlaceConfig struct { | ||
| AssetDir string | ||
| IgnitionPath string | ||
| Input string | ||
| Strict bool | ||
| Pretty bool | ||
| } | ||
| type BootstrapInPlaceCommand struct { | ||
| config BootstrapInPlaceConfig | ||
| } | ||
|
|
||
| func NewBootstrapInPlaceCommand(config BootstrapInPlaceConfig) (*BootstrapInPlaceCommand, error) { | ||
| return &BootstrapInPlaceCommand{ | ||
| config: config, | ||
| }, nil | ||
| } | ||
|
|
||
| // Creating master ignition that will be used by node after reboot | ||
| // Using fcct tool (tool that takes yaml and according to it creates ignition): | ||
| // 1. Read actions yaml that has all the data needed by fcct to create master.ign | ||
| // 2. Create ignition data | ||
| // 3. Write created data to file | ||
| func (i *BootstrapInPlaceCommand) Create() error { | ||
eranco74 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| infile, err := os.Open(i.config.Input) | ||
| if err != nil { | ||
| fail("Error occurred while trying to open %s: %v\n", i.config.Input, err) | ||
| } | ||
| defer infile.Close() | ||
|
|
||
| dataIn, err := ioutil.ReadAll(infile) | ||
| if err != nil { | ||
| fail("Error occurred while trying to read %s: %v\n", infile.Name(), err) | ||
| } | ||
|
|
||
| dataOut, r, err := config.TranslateBytes(dataIn, fcctCommon.TranslateBytesOptions{ | ||
| TranslateOptions: fcctCommon.TranslateOptions{FilesDir: i.config.AssetDir}, | ||
| Pretty: i.config.Pretty, | ||
| Strict: i.config.Strict}, | ||
| ) | ||
| fmt.Println(r.String()) | ||
| if err != nil { | ||
| fail("Error translating config: %v\n", err) | ||
| } | ||
|
|
||
| outfile, err := os.OpenFile(i.config.IgnitionPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) | ||
| if err != nil { | ||
| fail("Failed to open %s: %v\n", i.config.IgnitionPath, err) | ||
| } | ||
| defer outfile.Close() | ||
|
|
||
| if _, err := outfile.Write(append(dataOut, '\n')); err != nil { | ||
| fail("Failed to write config to %s: %v\n", outfile.Name(), err) | ||
| } | ||
| return nil | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,23 +1,31 @@ | ||
| package start | ||
|
|
||
| import ( | ||
| "context" | ||
| "crypto/tls" | ||
| "fmt" | ||
| "io" | ||
| "k8s.io/apimachinery/pkg/util/wait" | ||
| "net/http" | ||
| "os" | ||
| "path/filepath" | ||
| "strings" | ||
| "time" | ||
| ) | ||
|
|
||
| type bootstrapControlPlane struct { | ||
| assetDir string | ||
| podManifestPath string | ||
| ownedManifests []string | ||
| kubeApiHost string | ||
| } | ||
|
|
||
| // newBootstrapControlPlane constructs a new bootstrap control plane object. | ||
| func newBootstrapControlPlane(assetDir, podManifestPath string) *bootstrapControlPlane { | ||
| func newBootstrapControlPlane(assetDir, podManifestPath string, kubeApiHost string) *bootstrapControlPlane { | ||
| return &bootstrapControlPlane{ | ||
| assetDir: assetDir, | ||
| podManifestPath: podManifestPath, | ||
| kubeApiHost: kubeApiHost, | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -42,7 +50,39 @@ func (b *bootstrapControlPlane) Start() error { | |
| manifestsDir := filepath.Join(b.assetDir, assetPathBootstrapManifests) | ||
| ownedManifests, err := copyDirectory(manifestsDir, b.podManifestPath, false /* overwrite */) | ||
| b.ownedManifests = ownedManifests // always copy in case of partial failure. | ||
| return err | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| // Wait for kube-apiserver to be available and return. | ||
| return b.waitForApi() | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you explain what problem this is looking to solve?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in case required-pods="" (this is the case when running bootstrap-in-place) cluster-bootstrap will fail to publish an event since kube-apiserver isn't up yet. |
||
| } | ||
|
|
||
| // waitForApi will wait until kube-apiserver readyz endpoint is available | ||
| func (b *bootstrapControlPlane) waitForApi() error { | ||
| UserOutput("Waiting up to %v for the Kubernetes API\n", bootstrapPodsRunningTimeout) | ||
| apiContext, cancel := context.WithTimeout(context.Background(), bootstrapPodsRunningTimeout) | ||
| defer cancel() | ||
| customTransport := http.DefaultTransport.(*http.Transport).Clone() | ||
| customTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} | ||
| client := &http.Client{Transport: customTransport} | ||
| previousError := "" | ||
| err := wait.PollUntil(time.Second, func() (bool, error) { | ||
| if _, err := client.Get(fmt.Sprintf("https://%s/readyz", b.kubeApiHost)); err == nil { | ||
| UserOutput("API is up\n") | ||
| return true, nil | ||
| } else if previousError != err.Error() { | ||
| UserOutput("Still waiting for the Kubernetes API: %v \n", err) | ||
| previousError = err.Error() | ||
| } | ||
|
|
||
| return false, nil | ||
| }, apiContext.Done()) | ||
| if err != nil { | ||
| return fmt.Errorf("time out waiting for Kubernetes API") | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| // Teardown brings down the bootstrap control plane and cleans up the temporary manifests and | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.