mirror of https://github.com/kubernetes/kops.git
Merge pull request #2370 from luomiao/userdefined-s3endpoint
Support user-defined s3 endpoint
This commit is contained in:
commit
4dcc6ad067
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package bootstrap
|
package bootstrap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
|
@ -26,6 +27,7 @@ import (
|
||||||
"k8s.io/kops/upup/pkg/fi/nodeup/local"
|
"k8s.io/kops/upup/pkg/fi/nodeup/local"
|
||||||
"k8s.io/kops/upup/pkg/fi/nodeup/nodetasks"
|
"k8s.io/kops/upup/pkg/fi/nodeup/nodetasks"
|
||||||
"k8s.io/kops/util/pkg/vfs"
|
"k8s.io/kops/util/pkg/vfs"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
@ -108,6 +110,25 @@ func (i *Installation) buildSystemdJob() *nodetasks.Service {
|
||||||
manifest.Set("Unit", "Description", "Run kops bootstrap (nodeup)")
|
manifest.Set("Unit", "Description", "Run kops bootstrap (nodeup)")
|
||||||
manifest.Set("Unit", "Documentation", "https://github.com/kubernetes/kops")
|
manifest.Set("Unit", "Documentation", "https://github.com/kubernetes/kops")
|
||||||
|
|
||||||
|
// Pass in required credentials when using user-defined s3 endpoint
|
||||||
|
if os.Getenv("S3_ENDPOINT") != "" {
|
||||||
|
var buffer bytes.Buffer
|
||||||
|
buffer.WriteString("\"S3_ENDPOINT=")
|
||||||
|
buffer.WriteString(os.Getenv("S3_ENDPOINT"))
|
||||||
|
buffer.WriteString("\" ")
|
||||||
|
buffer.WriteString("\"S3_REGION=")
|
||||||
|
buffer.WriteString(os.Getenv("S3_REGION"))
|
||||||
|
buffer.WriteString("\" ")
|
||||||
|
buffer.WriteString("\"S3_ACCESS_KEY_ID=")
|
||||||
|
buffer.WriteString(os.Getenv("S3_ACCESS_KEY_ID"))
|
||||||
|
buffer.WriteString("\" ")
|
||||||
|
buffer.WriteString("\"S3_SECRET_ACCESS_KEY=")
|
||||||
|
buffer.WriteString(os.Getenv("S3_SECRET_ACCESS_KEY"))
|
||||||
|
buffer.WriteString("\" ")
|
||||||
|
|
||||||
|
manifest.Set("Service", "Environment", buffer.String())
|
||||||
|
}
|
||||||
|
|
||||||
manifest.Set("Service", "ExecStart", command)
|
manifest.Set("Service", "ExecStart", command)
|
||||||
manifest.Set("Service", "Type", "oneshot")
|
manifest.Set("Service", "Type", "oneshot")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/blang/semver"
|
"github.com/blang/semver"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
|
@ -26,6 +27,7 @@ import (
|
||||||
"k8s.io/kops/pkg/systemd"
|
"k8s.io/kops/pkg/systemd"
|
||||||
"k8s.io/kops/upup/pkg/fi"
|
"k8s.io/kops/upup/pkg/fi"
|
||||||
"k8s.io/kops/upup/pkg/fi/nodeup/nodetasks"
|
"k8s.io/kops/upup/pkg/fi/nodeup/nodetasks"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -82,6 +84,7 @@ func (b *ProtokubeBuilder) buildSystemdService() (*nodetasks.Service, error) {
|
||||||
"--net=host",
|
"--net=host",
|
||||||
"--privileged",
|
"--privileged",
|
||||||
"--env", "KUBECONFIG=/rootfs/var/lib/kops/kubeconfig",
|
"--env", "KUBECONFIG=/rootfs/var/lib/kops/kubeconfig",
|
||||||
|
b.ProtokubeEnvironmentVariables(),
|
||||||
b.ProtokubeImageName(),
|
b.ProtokubeImageName(),
|
||||||
"/usr/bin/protokube",
|
"/usr/bin/protokube",
|
||||||
}
|
}
|
||||||
|
|
@ -218,3 +221,32 @@ func (t *ProtokubeBuilder) ProtokubeFlags(k8sVersion semver.Version) *ProtokubeF
|
||||||
|
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *ProtokubeBuilder) ProtokubeEnvironmentVariables() string {
|
||||||
|
// Pass in required credentials when using user-defined s3 endpoint
|
||||||
|
if os.Getenv("S3_ENDPOINT") != "" {
|
||||||
|
var buffer bytes.Buffer
|
||||||
|
buffer.WriteString(" ")
|
||||||
|
buffer.WriteString("-e S3_ENDPOINT=")
|
||||||
|
buffer.WriteString("'")
|
||||||
|
buffer.WriteString(os.Getenv("S3_ENDPOINT"))
|
||||||
|
buffer.WriteString("'")
|
||||||
|
buffer.WriteString(" -e S3_REGION=")
|
||||||
|
buffer.WriteString("'")
|
||||||
|
buffer.WriteString(os.Getenv("S3_REGION"))
|
||||||
|
buffer.WriteString("'")
|
||||||
|
buffer.WriteString(" -e S3_ACCESS_KEY_ID=")
|
||||||
|
buffer.WriteString("'")
|
||||||
|
buffer.WriteString(os.Getenv("S3_ACCESS_KEY_ID"))
|
||||||
|
buffer.WriteString("'")
|
||||||
|
buffer.WriteString(" -e S3_SECRET_ACCESS_KEY=")
|
||||||
|
buffer.WriteString("'")
|
||||||
|
buffer.WriteString(os.Getenv("S3_SECRET_ACCESS_KEY"))
|
||||||
|
buffer.WriteString("'")
|
||||||
|
buffer.WriteString(" ")
|
||||||
|
|
||||||
|
return buffer.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,12 @@ limitations under the License.
|
||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"k8s.io/kops/pkg/apis/kops"
|
"k8s.io/kops/pkg/apis/kops"
|
||||||
"k8s.io/kops/pkg/apis/nodeup"
|
"k8s.io/kops/pkg/apis/nodeup"
|
||||||
"k8s.io/kops/pkg/model/resources"
|
"k8s.io/kops/pkg/model/resources"
|
||||||
"k8s.io/kops/upup/pkg/fi"
|
"k8s.io/kops/upup/pkg/fi"
|
||||||
|
"os"
|
||||||
"text/template"
|
"text/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -57,6 +59,18 @@ func (b *BootstrapScript) ResourceNodeUp(ig *kops.InstanceGroup) (*fi.ResourceHo
|
||||||
|
|
||||||
return string(data), nil
|
return string(data), nil
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Pass in extra environment variables for user-defined S3 service
|
||||||
|
"S3Env": func() string {
|
||||||
|
if os.Getenv("S3_ENDPOINT") != "" {
|
||||||
|
return fmt.Sprintf("export S3_ENDPOINT= %s\nexport S3_REGION=%s\nexport S3_ACCESS_KEY_ID=%s\nexport S3_SECRET_ACCESS_KEY=%s\n",
|
||||||
|
os.Getenv("S3_ENDPOINT"),
|
||||||
|
os.Getenv("S3_REGION"),
|
||||||
|
os.Getenv("S3_ACCESS_KEY_ID"),
|
||||||
|
os.Getenv("S3_SECRET_ACCESS_KEY"))
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
templateResource, err := NewTemplateResource("nodeup", resources.AWSNodeUpTemplate, functions, nil)
|
templateResource, err := NewTemplateResource("nodeup", resources.AWSNodeUpTemplate, functions, nil)
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,8 @@ set -o pipefail
|
||||||
NODEUP_URL={{ NodeUpSource }}
|
NODEUP_URL={{ NodeUpSource }}
|
||||||
NODEUP_HASH={{ NodeUpSourceHash }}
|
NODEUP_HASH={{ NodeUpSourceHash }}
|
||||||
|
|
||||||
|
{{ S3Env }}
|
||||||
|
|
||||||
function ensure-install-dir() {
|
function ensure-install-dir() {
|
||||||
INSTALL_DIR="/var/cache/kubernetes-install"
|
INSTALL_DIR="/var/cache/kubernetes-install"
|
||||||
# On ContainerOS, we install to /var/lib/toolbox install (because of noexec)
|
# On ContainerOS, we install to /var/lib/toolbox install (because of noexec)
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
"github.com/aws/aws-sdk-go/aws/endpoints"
|
"github.com/aws/aws-sdk-go/aws/endpoints"
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
"github.com/aws/aws-sdk-go/service/ec2"
|
"github.com/aws/aws-sdk-go/service/ec2"
|
||||||
|
|
@ -34,6 +35,8 @@ type S3Context struct {
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
clients map[string]*s3.S3
|
clients map[string]*s3.S3
|
||||||
bucketLocations map[string]string
|
bucketLocations map[string]string
|
||||||
|
|
||||||
|
getClient func(region string) (*s3.S3, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewS3Context() *S3Context {
|
func NewS3Context() *S3Context {
|
||||||
|
|
@ -43,7 +46,7 @@ func NewS3Context() *S3Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *S3Context) getClient(region string) (*s3.S3, error) {
|
func (s *S3Context) getDefaultClient(region string) (*s3.S3, error) {
|
||||||
s.mutex.Lock()
|
s.mutex.Lock()
|
||||||
defer s.mutex.Unlock()
|
defer s.mutex.Unlock()
|
||||||
|
|
||||||
|
|
@ -61,6 +64,50 @@ func (s *S3Context) getClient(region string) (*s3.S3, error) {
|
||||||
return s3Client, nil
|
return s3Client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *S3Context) getEndpointClient(region string) (*s3.S3, error) {
|
||||||
|
s.mutex.Lock()
|
||||||
|
defer s.mutex.Unlock()
|
||||||
|
|
||||||
|
s3Client := s.clients[region]
|
||||||
|
if s3Client == nil {
|
||||||
|
Endpoint := os.Getenv("S3_ENDPOINT")
|
||||||
|
if Endpoint == "" {
|
||||||
|
return nil, fmt.Errorf("S3_ENDPOINT is required")
|
||||||
|
}
|
||||||
|
AccessKeyID := os.Getenv("S3_ACCESS_KEY_ID")
|
||||||
|
if AccessKeyID == "" {
|
||||||
|
return nil, fmt.Errorf("S3_ACCESS_KEY_ID cannot be empty when S3_ENDPOINT is not empty")
|
||||||
|
}
|
||||||
|
SecretAccessKey := os.Getenv("S3_SECRET_ACCESS_KEY")
|
||||||
|
if SecretAccessKey == "" {
|
||||||
|
return nil, fmt.Errorf("S3_SECRET_ACCESS_KEY cannot be empty when S3_ENDPOINT is not empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
s3Config := &aws.Config{
|
||||||
|
Credentials: credentials.NewStaticCredentials(AccessKeyID, SecretAccessKey, ""),
|
||||||
|
Endpoint: aws.String(Endpoint),
|
||||||
|
Region: aws.String(region),
|
||||||
|
DisableSSL: aws.Bool(true),
|
||||||
|
S3ForcePathStyle: aws.Bool(true),
|
||||||
|
}
|
||||||
|
|
||||||
|
session := session.New()
|
||||||
|
s3Client = s3.New(session, s3Config)
|
||||||
|
s.clients[region] = s3Client
|
||||||
|
}
|
||||||
|
|
||||||
|
return s3Client, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *S3Context) setClientFunc() {
|
||||||
|
Endpoint := os.Getenv("S3_ENDPOINT")
|
||||||
|
if Endpoint == "" {
|
||||||
|
s.getClient = s.getDefaultClient
|
||||||
|
} else {
|
||||||
|
s.getClient = s.getEndpointClient
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *S3Context) getRegionForBucket(bucket string) (string, error) {
|
func (s *S3Context) getRegionForBucket(bucket string) (string, error) {
|
||||||
region := func() string {
|
region := func() string {
|
||||||
s.mutex.Lock()
|
s.mutex.Lock()
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ var _ HasHash = &S3Path{}
|
||||||
func newS3Path(s3Context *S3Context, bucket string, key string) *S3Path {
|
func newS3Path(s3Context *S3Context, bucket string, key string) *S3Path {
|
||||||
bucket = strings.TrimSuffix(bucket, "/")
|
bucket = strings.TrimSuffix(bucket, "/")
|
||||||
key = strings.TrimPrefix(key, "/")
|
key = strings.TrimPrefix(key, "/")
|
||||||
|
s3Context.setClientFunc()
|
||||||
|
|
||||||
return &S3Path{
|
return &S3Path{
|
||||||
s3Context: s3Context,
|
s3Context: s3Context,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue