Skip to content
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

Bootstrap worker nodes using kops-controller #9653

Merged
merged 13 commits into from
Aug 17, 2020
Merged
5 changes: 4 additions & 1 deletion cmd/kops-controller/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ go_library(
deps = [
"//cmd/kops-controller/controllers:go_default_library",
"//cmd/kops-controller/pkg/config:go_default_library",
"//cmd/kops-controller/pkg/server:go_default_library",
"//pkg/nodeidentity:go_default_library",
"//pkg/nodeidentity/aws:go_default_library",
"//pkg/nodeidentity/do:go_default_library",
"//pkg/nodeidentity/gce:go_default_library",
"//pkg/nodeidentity/openstack:go_default_library",
"//upup/pkg/fi:go_default_library",
"//upup/pkg/fi/cloudup/awsup:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/client-go/plugin/pkg/client/auth/gcp:go_default_library",
Expand Down Expand Up @@ -47,7 +50,7 @@ ARCH = [
architecture = arch,
base = "@distroless_base//image",
cmd = ["/kops-controller"],
user = "10001",
user = "10011",
files = [
"//cmd/kops-controller",
],
Expand Down
27 changes: 27 additions & 0 deletions cmd/kops-controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,14 @@ import (
"k8s.io/klog/klogr"
"k8s.io/kops/cmd/kops-controller/controllers"
"k8s.io/kops/cmd/kops-controller/pkg/config"
"k8s.io/kops/cmd/kops-controller/pkg/server"
"k8s.io/kops/pkg/nodeidentity"
nodeidentityaws "k8s.io/kops/pkg/nodeidentity/aws"
nodeidentitydo "k8s.io/kops/pkg/nodeidentity/do"
nodeidentitygce "k8s.io/kops/pkg/nodeidentity/gce"
nodeidentityos "k8s.io/kops/pkg/nodeidentity/openstack"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/awsup"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/yaml"
Expand Down Expand Up @@ -81,6 +84,30 @@ func main() {
}

ctrl.SetLogger(klogr.New())
if opt.Server != nil {
var verifier fi.Verifier
var err error
if opt.Server.Provider.AWS != nil {
verifier, err = awsup.NewAWSVerifier(opt.Server.Provider.AWS)
if err != nil {
setupLog.Error(err, "unable to create verifier")
os.Exit(1)
}
} else {
klog.Fatalf("server cloud provider config not provided")
}

srv, err := server.NewServer(&opt, verifier)
if err != nil {
setupLog.Error(err, "unable to create server")
os.Exit(1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been finding recently that I've been rewriting the kubebuilder main to call into a func run() error function immediately, just to avoid having to log & exit every time!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The structured logging, such as in the handling of addNodeController, makes it tricky to use that pattern.

}
go func() {
err := srv.Start()
setupLog.Error(err, "unable to start server")
os.Exit(1)
}()
}

if err := buildScheme(); err != nil {
setupLog.Error(err, "error building scheme")
Expand Down
1 change: 1 addition & 0 deletions cmd/kops-controller/pkg/config/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ go_library(
srcs = ["options.go"],
importpath = "k8s.io/kops/cmd/kops-controller/pkg/config",
visibility = ["//visibility:public"],
deps = ["//upup/pkg/fi/cloudup/awsup:go_default_library"],
)
29 changes: 27 additions & 2 deletions cmd/kops-controller/pkg/config/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,35 @@ limitations under the License.

package config

import "k8s.io/kops/upup/pkg/fi/cloudup/awsup"

type Options struct {
Cloud string `json:"cloud,omitempty"`
ConfigBase string `json:"configBase,omitempty"`
Cloud string `json:"cloud,omitempty"`
ConfigBase string `json:"configBase,omitempty"`
Server *ServerOptions `json:"server,omitempty"`
}

func (o *Options) PopulateDefaults() {
}

type ServerOptions struct {
// Listen is the network endpoint (ip and port) we should listen on.
Listen string

// Provider is the cloud provider.
Provider ServerProviderOptions `json:"provider"`

// ServerKeyPath is the path to our TLS serving private key.
ServerKeyPath string `json:"serverKeyPath,omitempty"`
// ServerCertificatePath is the path to our TLS serving certificate.
ServerCertificatePath string `json:"serverCertificatePath,omitempty"`

// CABasePath is a base of the path to CA certificate and key files.
CABasePath string `json:"caBasePath"`
// SigningCAs is the list of active signing CAs.
SigningCAs []string `json:"signingCAs"`
}

type ServerProviderOptions struct {
AWS *awsup.AWSVerifierOptions `json:"aws,omitempty"`
}
19 changes: 19 additions & 0 deletions cmd/kops-controller/pkg/server/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")

go_library(
name = "go_default_library",
srcs = [
"keystore.go",
"server.go",
],
importpath = "k8s.io/kops/cmd/kops-controller/pkg/server",
visibility = ["//visibility:public"],
deps = [
"//cmd/kops-controller/pkg/config:go_default_library",
"//pkg/apis/nodeup:go_default_library",
"//pkg/pki:go_default_library",
"//pkg/rbac:go_default_library",
"//upup/pkg/fi:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
],
)
76 changes: 76 additions & 0 deletions cmd/kops-controller/pkg/server/keystore.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
Copyright 2020 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package server

import (
"fmt"
"io/ioutil"
"path"

"k8s.io/kops/pkg/pki"
)

type keystore struct {
keys map[string]keystoreEntry
}

type keystoreEntry struct {
certificate *pki.Certificate
key *pki.PrivateKey
}

var _ pki.Keystore = keystore{}

func (k keystore) FindKeypair(name string) (*pki.Certificate, *pki.PrivateKey, bool, error) {
entry, ok := k.keys[name]
if !ok {
return nil, nil, false, fmt.Errorf("unknown CA %q", name)
}
return entry.certificate, entry.key, false, nil
}

func newKeystore(basePath string, cas []string) (pki.Keystore, error) {
keystore := &keystore{
keys: map[string]keystoreEntry{},
}
for _, name := range cas {
certBytes, err := ioutil.ReadFile(path.Join(basePath, name+".pem"))
if err != nil {
return nil, fmt.Errorf("reading %q certificate: %v", name, err)
}
certificate, err := pki.ParsePEMCertificate(certBytes)
if err != nil {
return nil, fmt.Errorf("parsing %q certificate: %v", name, err)
}

keyBytes, err := ioutil.ReadFile(path.Join(basePath, name+"-key.pem"))
if err != nil {
return nil, fmt.Errorf("reading %q key: %v", name, err)
}
key, err := pki.ParsePEMPrivateKey(keyBytes)
if err != nil {
return nil, fmt.Errorf("parsing %q key: %v", name, err)
}

keystore.keys[name] = keystoreEntry{
certificate: certificate,
key: key,
}
}

return keystore, nil
}
Loading