| ... | ... |
@@ -228,7 +228,7 @@ func GetClientCertCAPool(options MasterConfig) (*x509.CertPool, error) {
|
| 228 | 228 |
|
| 229 | 229 |
// GetAPIServerCertCAPool returns the cert pool containing the roots for the API server cert |
| 230 | 230 |
func GetAPIServerCertCAPool(options MasterConfig) (*x509.CertPool, error) {
|
| 231 |
- if !UseTLS(options.ServingInfo) {
|
|
| 231 |
+ if !UseTLS(options.ServingInfo.ServingInfo) {
|
|
| 232 | 232 |
return x509.NewCertPool(), nil |
| 233 | 233 |
} |
| 234 | 234 |
|
| ... | ... |
@@ -236,7 +236,7 @@ func GetAPIServerCertCAPool(options MasterConfig) (*x509.CertPool, error) {
|
| 236 | 236 |
} |
| 237 | 237 |
|
| 238 | 238 |
func getOAuthClientCertCAs(options MasterConfig) ([]*x509.Certificate, error) {
|
| 239 |
- if !UseTLS(options.ServingInfo) {
|
|
| 239 |
+ if !UseTLS(options.ServingInfo.ServingInfo) {
|
|
| 240 | 240 |
return nil, nil |
| 241 | 241 |
} |
| 242 | 242 |
|
| ... | ... |
@@ -264,7 +264,7 @@ func getOAuthClientCertCAs(options MasterConfig) ([]*x509.Certificate, error) {
|
| 264 | 264 |
} |
| 265 | 265 |
|
| 266 | 266 |
func getAPIClientCertCAs(options MasterConfig) ([]*x509.Certificate, error) {
|
| 267 |
- if !UseTLS(options.ServingInfo) {
|
|
| 267 |
+ if !UseTLS(options.ServingInfo.ServingInfo) {
|
|
| 268 | 268 |
return nil, nil |
| 269 | 269 |
} |
| 270 | 270 |
|
| ... | ... |
@@ -86,7 +86,7 @@ type MasterConfig struct {
|
| 86 | 86 |
api.TypeMeta |
| 87 | 87 |
|
| 88 | 88 |
// ServingInfo describes how to start serving |
| 89 |
- ServingInfo ServingInfo |
|
| 89 |
+ ServingInfo HTTPServingInfo |
|
| 90 | 90 |
|
| 91 | 91 |
// CORSAllowedOrigins |
| 92 | 92 |
CORSAllowedOrigins []string |
| ... | ... |
@@ -262,6 +262,15 @@ type ServingInfo struct {
|
| 262 | 262 |
ClientCA string |
| 263 | 263 |
} |
| 264 | 264 |
|
| 265 |
+type HTTPServingInfo struct {
|
|
| 266 |
+ ServingInfo |
|
| 267 |
+ // MaxRequestsInFlight is the number of concurrent requests allowed to the server. If zero, no limit. |
|
| 268 |
+ MaxRequestsInFlight int |
|
| 269 |
+ // RequestTimeoutSeconds is the number of seconds before requests are timed out. The default is 60 minutes, if |
|
| 270 |
+ // -1 there is no limit on requests. |
|
| 271 |
+ RequestTimeoutSeconds int |
|
| 272 |
+} |
|
| 273 |
+ |
|
| 265 | 274 |
type MasterClients struct {
|
| 266 | 275 |
// OpenShiftLoopbackKubeConfig is a .kubeconfig filename for system components to loopback to this master |
| 267 | 276 |
OpenShiftLoopbackKubeConfig string |
| ... | ... |
@@ -275,7 +284,7 @@ type DNSConfig struct {
|
| 275 | 275 |
} |
| 276 | 276 |
|
| 277 | 277 |
type AssetConfig struct {
|
| 278 |
- ServingInfo ServingInfo |
|
| 278 |
+ ServingInfo HTTPServingInfo |
|
| 279 | 279 |
|
| 280 | 280 |
// PublicURL is where you can find the asset server (TODO do we really need this?) |
| 281 | 281 |
PublicURL string |
| ... | ... |
@@ -515,6 +524,8 @@ type KubernetesMasterConfig struct {
|
| 515 | 515 |
MasterCount int |
| 516 | 516 |
// ServicesSubnet is the subnet to use for assigning service IPs |
| 517 | 517 |
ServicesSubnet string |
| 518 |
+ // ServicesNodePortRange is the range to use for assigning service public ports on a host. |
|
| 519 |
+ ServicesNodePortRange string |
|
| 518 | 520 |
// StaticNodeNames is the list of nodes that are statically known |
| 519 | 521 |
StaticNodeNames []string |
| 520 | 522 |
// SchedulerConfigFile points to a file that describes how to set up the scheduler. If empty, you get the default scheduling rules. |
| ... | ... |
@@ -522,6 +533,10 @@ type KubernetesMasterConfig struct {
|
| 522 | 522 |
// PodEvictionTimeout controls grace period for deleting pods on failed nodes. |
| 523 | 523 |
// It takes valid time duration string. If empty, you get the default pod eviction timeout. |
| 524 | 524 |
PodEvictionTimeout string |
| 525 |
+ // APIServerArguments are key value pairs that will be passed directly to the Kube apiserver that match the apiservers's |
|
| 526 |
+ // command line arguments. These are not migrated, but if you reference a value that does not exist the server will not |
|
| 527 |
+ // start. These values may override other settings in KubernetesMasterConfig which may cause invalid configurations. |
|
| 528 |
+ APIServerArguments ExtendedArguments |
|
| 525 | 529 |
} |
| 526 | 530 |
|
| 527 | 531 |
type CertInfo struct {
|
| ... | ... |
@@ -15,6 +15,9 @@ func init() {
|
| 15 | 15 |
if len(obj.Controllers) == 0 {
|
| 16 | 16 |
obj.Controllers = ControllersAll |
| 17 | 17 |
} |
| 18 |
+ if obj.ServingInfo.RequestTimeoutSeconds == 0 {
|
|
| 19 |
+ obj.ServingInfo.RequestTimeoutSeconds = 60 * 60 |
|
| 20 |
+ } |
|
| 18 | 21 |
}, |
| 19 | 22 |
func(obj *KubernetesMasterConfig) {
|
| 20 | 23 |
if obj.MasterCount == 0 {
|
| ... | ... |
@@ -23,19 +26,22 @@ func init() {
|
| 23 | 23 |
if len(obj.APILevels) == 0 {
|
| 24 | 24 |
obj.APILevels = newer.DefaultKubernetesAPILevels |
| 25 | 25 |
} |
| 26 |
+ if len(obj.ServicesNodePortRange) == 0 {
|
|
| 27 |
+ obj.ServicesNodePortRange = "30000-32767" |
|
| 28 |
+ } |
|
| 26 | 29 |
if len(obj.PodEvictionTimeout) == 0 {
|
| 27 | 30 |
obj.PodEvictionTimeout = "5m" |
| 28 | 31 |
} |
| 29 | 32 |
}, |
| 30 | 33 |
func(obj *EtcdStorageConfig) {
|
| 31 | 34 |
if len(obj.KubernetesStorageVersion) == 0 {
|
| 32 |
- obj.KubernetesStorageVersion = "v1beta3" |
|
| 35 |
+ obj.KubernetesStorageVersion = "v1" |
|
| 33 | 36 |
} |
| 34 | 37 |
if len(obj.KubernetesStoragePrefix) == 0 {
|
| 35 | 38 |
obj.KubernetesStoragePrefix = "kubernetes.io" |
| 36 | 39 |
} |
| 37 | 40 |
if len(obj.OpenShiftStorageVersion) == 0 {
|
| 38 |
- obj.OpenShiftStorageVersion = "v1beta3" |
|
| 41 |
+ obj.OpenShiftStorageVersion = "v1" |
|
| 39 | 42 |
} |
| 40 | 43 |
if len(obj.OpenShiftStoragePrefix) == 0 {
|
| 41 | 44 |
obj.OpenShiftStoragePrefix = "openshift.io" |
| ... | ... |
@@ -76,7 +76,7 @@ type MasterConfig struct {
|
| 76 | 76 |
v1.TypeMeta `json:",inline"` |
| 77 | 77 |
|
| 78 | 78 |
// ServingInfo describes how to start serving |
| 79 |
- ServingInfo ServingInfo `json:"servingInfo"` |
|
| 79 |
+ ServingInfo HTTPServingInfo `json:"servingInfo"` |
|
| 80 | 80 |
|
| 81 | 81 |
// CORSAllowedOrigins |
| 82 | 82 |
CORSAllowedOrigins []string `json:"corsAllowedOrigins"` |
| ... | ... |
@@ -251,6 +251,15 @@ type ServingInfo struct {
|
| 251 | 251 |
ClientCA string `json:"clientCA"` |
| 252 | 252 |
} |
| 253 | 253 |
|
| 254 |
+type HTTPServingInfo struct {
|
|
| 255 |
+ ServingInfo `json:",inline"` |
|
| 256 |
+ // MaxRequestsInFlight is the number of concurrent requests allowed to the server. If zero, no limit. |
|
| 257 |
+ MaxRequestsInFlight int `json:"maxRequestsInFlight"` |
|
| 258 |
+ // RequestTimeoutSeconds is the number of seconds before requests are timed out. The default is 60 minutes, if |
|
| 259 |
+ // -1 there is no limit on requests. |
|
| 260 |
+ RequestTimeoutSeconds int `json:"requestTimeoutSeconds"` |
|
| 261 |
+} |
|
| 262 |
+ |
|
| 254 | 263 |
type MasterClients struct {
|
| 255 | 264 |
// OpenShiftLoopbackKubeConfig is a .kubeconfig filename for system components to loopback to this master |
| 256 | 265 |
OpenShiftLoopbackKubeConfig string `json:"openshiftLoopbackKubeConfig"` |
| ... | ... |
@@ -264,7 +273,7 @@ type DNSConfig struct {
|
| 264 | 264 |
} |
| 265 | 265 |
|
| 266 | 266 |
type AssetConfig struct {
|
| 267 |
- ServingInfo ServingInfo `json:"servingInfo"` |
|
| 267 |
+ ServingInfo HTTPServingInfo `json:"servingInfo"` |
|
| 268 | 268 |
|
| 269 | 269 |
// PublicURL is where you can find the asset server (TODO do we really need this?) |
| 270 | 270 |
PublicURL string `json:"publicURL"` |
| ... | ... |
@@ -491,11 +500,17 @@ type KubernetesMasterConfig struct {
|
| 491 | 491 |
APILevels []string `json:"apiLevels"` |
| 492 | 492 |
MasterIP string `json:"masterIP"` |
| 493 | 493 |
// MasterCount is the number of expected masters that should be running. This value defaults to 1 and may be set to a positive integer. |
| 494 |
- MasterCount int `json:"masterCount"` |
|
| 495 |
- ServicesSubnet string `json:"servicesSubnet"` |
|
| 496 |
- StaticNodeNames []string `json:"staticNodeNames"` |
|
| 497 |
- SchedulerConfigFile string `json:"schedulerConfigFile"` |
|
| 498 |
- PodEvictionTimeout string `json:"podEvictionTimeout"` |
|
| 494 |
+ MasterCount int `json:"masterCount"` |
|
| 495 |
+ ServicesSubnet string `json:"servicesSubnet"` |
|
| 496 |
+ // ServicesNodePortRange is the range to use for assigning service public ports on a host. |
|
| 497 |
+ ServicesNodePortRange string `json:"servicesNodePortRange"` |
|
| 498 |
+ StaticNodeNames []string `json:"staticNodeNames"` |
|
| 499 |
+ SchedulerConfigFile string `json:"schedulerConfigFile"` |
|
| 500 |
+ PodEvictionTimeout string `json:"podEvictionTimeout"` |
|
| 501 |
+ // APIServerArguments are key value pairs that will be passed directly to the Kube apiserver that match the apiservers's |
|
| 502 |
+ // command line arguments. These are not migrated, but if you reference a value that does not exist the server will not |
|
| 503 |
+ // start. These values may override other settings in KubernetesMasterConfig which may cause invalid configurations. |
|
| 504 |
+ APIServerArguments ExtendedArguments `json:"apiServerArguments"` |
|
| 499 | 505 |
} |
| 500 | 506 |
|
| 501 | 507 |
type CertInfo struct {
|
| ... | ... |
@@ -55,6 +55,8 @@ assetConfig: |
| 55 | 55 |
certFile: "" |
| 56 | 56 |
clientCA: "" |
| 57 | 57 |
keyFile: "" |
| 58 |
+ maxRequestsInFlight: 0 |
|
| 59 |
+ requestTimeoutSeconds: 0 |
|
| 58 | 60 |
corsAllowedOrigins: null |
| 59 | 61 |
dnsConfig: |
| 60 | 62 |
bindAddress: "" |
| ... | ... |
@@ -93,10 +95,12 @@ kubeletClientInfo: |
| 93 | 93 |
port: 0 |
| 94 | 94 |
kubernetesMasterConfig: |
| 95 | 95 |
apiLevels: null |
| 96 |
+ apiServerArguments: null |
|
| 96 | 97 |
masterCount: 0 |
| 97 | 98 |
masterIP: "" |
| 98 | 99 |
podEvictionTimeout: "" |
| 99 | 100 |
schedulerConfigFile: "" |
| 101 |
+ servicesNodePortRange: "" |
|
| 100 | 102 |
servicesSubnet: "" |
| 101 | 103 |
staticNodeNames: null |
| 102 | 104 |
masterClients: |
| ... | ... |
@@ -212,6 +216,8 @@ servingInfo: |
| 212 | 212 |
certFile: "" |
| 213 | 213 |
clientCA: "" |
| 214 | 214 |
keyFile: "" |
| 215 |
+ maxRequestsInFlight: 0 |
|
| 216 |
+ requestTimeoutSeconds: 0 |
|
| 215 | 217 |
` |
| 216 | 218 |
) |
| 217 | 219 |
|
| ... | ... |
@@ -19,6 +19,7 @@ import ( |
| 19 | 19 |
"github.com/openshift/origin/pkg/util/labelselector" |
| 20 | 20 |
) |
| 21 | 21 |
|
| 22 |
+// TODO: this should just be two return arrays, no need to be clever |
|
| 22 | 23 |
type ValidationResults struct {
|
| 23 | 24 |
Warnings fielderrors.ValidationErrorList |
| 24 | 25 |
Errors fielderrors.ValidationErrorList |
| ... | ... |
@@ -52,6 +53,8 @@ func (r ValidationResults) Prefix(prefix string) ValidationResults {
|
| 52 | 52 |
func ValidateMasterConfig(config *api.MasterConfig) ValidationResults {
|
| 53 | 53 |
validationResults := ValidationResults{}
|
| 54 | 54 |
|
| 55 |
+ validationResults.AddErrors(ValidateHTTPServingInfo(config.ServingInfo).Prefix("servingInfo")...)
|
|
| 56 |
+ |
|
| 55 | 57 |
if _, urlErrs := ValidateURL(config.MasterPublicURL, "masterPublicURL"); len(urlErrs) > 0 {
|
| 56 | 58 |
validationResults.AddErrors(urlErrs...) |
| 57 | 59 |
} |
| ... | ... |
@@ -128,7 +131,7 @@ func ValidateMasterConfig(config *api.MasterConfig) ValidationResults {
|
| 128 | 128 |
|
| 129 | 129 |
validationResults.Append(ValidateServiceAccountConfig(config.ServiceAccountConfig, builtInKubernetes).Prefix("serviceAccountConfig"))
|
| 130 | 130 |
|
| 131 |
- validationResults.AddErrors(ValidateServingInfo(config.ServingInfo).Prefix("servingInfo")...)
|
|
| 131 |
+ validationResults.AddErrors(ValidateHTTPServingInfo(config.ServingInfo).Prefix("servingInfo")...)
|
|
| 132 | 132 |
|
| 133 | 133 |
validationResults.AddErrors(ValidateProjectConfig(config.ProjectConfig).Prefix("projectConfig")...)
|
| 134 | 134 |
|
| ... | ... |
@@ -227,7 +230,7 @@ func ValidateServiceAccountConfig(config api.ServiceAccountConfig, builtInKubern |
| 227 | 227 |
func ValidateAssetConfig(config *api.AssetConfig) fielderrors.ValidationErrorList {
|
| 228 | 228 |
allErrs := fielderrors.ValidationErrorList{}
|
| 229 | 229 |
|
| 230 |
- allErrs = append(allErrs, ValidateServingInfo(config.ServingInfo).Prefix("servingInfo")...)
|
|
| 230 |
+ allErrs = append(allErrs, ValidateHTTPServingInfo(config.ServingInfo).Prefix("servingInfo")...)
|
|
| 231 | 231 |
|
| 232 | 232 |
if len(config.LogoutURL) > 0 {
|
| 233 | 233 |
_, urlErrs := ValidateURL(config.LogoutURL, "logoutURL") |
| ... | ... |
@@ -294,6 +297,12 @@ func ValidateKubernetesMasterConfig(config *api.KubernetesMasterConfig) Validati |
| 294 | 294 |
} |
| 295 | 295 |
} |
| 296 | 296 |
|
| 297 |
+ if len(config.ServicesNodePortRange) > 0 {
|
|
| 298 |
+ if _, err := util.ParsePortRange(strings.TrimSpace(config.ServicesNodePortRange)); err != nil {
|
|
| 299 |
+ validationResults.AddErrors(fielderrors.NewFieldInvalid("servicesNodePortRange", config.ServicesNodePortRange, "must be a valid port range (e.g. 30000-32000)"))
|
|
| 300 |
+ } |
|
| 301 |
+ } |
|
| 302 |
+ |
|
| 297 | 303 |
if len(config.SchedulerConfigFile) > 0 {
|
| 298 | 304 |
validationResults.AddErrors(ValidateFile(config.SchedulerConfigFile, "schedulerConfigFile")...) |
| 299 | 305 |
} |
| ... | ... |
@@ -65,6 +65,20 @@ func ValidateServingInfo(info api.ServingInfo) fielderrors.ValidationErrorList {
|
| 65 | 65 |
return allErrs |
| 66 | 66 |
} |
| 67 | 67 |
|
| 68 |
+func ValidateHTTPServingInfo(info api.HTTPServingInfo) fielderrors.ValidationErrorList {
|
|
| 69 |
+ allErrs := ValidateServingInfo(info.ServingInfo) |
|
| 70 |
+ |
|
| 71 |
+ if info.MaxRequestsInFlight < 0 {
|
|
| 72 |
+ allErrs = append(allErrs, fielderrors.NewFieldInvalid("maxRequestsInFlight", info.MaxRequestsInFlight, "must be zero (no limit) or greater"))
|
|
| 73 |
+ } |
|
| 74 |
+ |
|
| 75 |
+ if info.RequestTimeoutSeconds < 0 {
|
|
| 76 |
+ allErrs = append(allErrs, fielderrors.NewFieldInvalid("requestTimeoutSeconds", info.RequestTimeoutSeconds, "must be zero (no limit) or greater"))
|
|
| 77 |
+ } |
|
| 78 |
+ |
|
| 79 |
+ return allErrs |
|
| 80 |
+} |
|
| 81 |
+ |
|
| 68 | 82 |
func ValidateKubeConfig(path string, field string) fielderrors.ValidationErrorList {
|
| 69 | 83 |
allErrs := fielderrors.ValidationErrorList{}
|
| 70 | 84 |
|
| ... | ... |
@@ -3,7 +3,6 @@ package kubernetes |
| 3 | 3 |
import ( |
| 4 | 4 |
"fmt" |
| 5 | 5 |
"io/ioutil" |
| 6 |
- "net" |
|
| 7 | 6 |
"os" |
| 8 | 7 |
"time" |
| 9 | 8 |
|
| ... | ... |
@@ -11,7 +10,6 @@ import ( |
| 11 | 11 |
"github.com/golang/glog" |
| 12 | 12 |
|
| 13 | 13 |
kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api" |
| 14 |
- kclient "github.com/GoogleCloudPlatform/kubernetes/pkg/client" |
|
| 15 | 14 |
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/record" |
| 16 | 15 |
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/nodecontroller" |
| 17 | 16 |
"github.com/GoogleCloudPlatform/kubernetes/pkg/controller" |
| ... | ... |
@@ -27,7 +25,6 @@ import ( |
| 27 | 27 |
"github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/scheduler/factory" |
| 28 | 28 |
|
| 29 | 29 |
"github.com/GoogleCloudPlatform/kubernetes/pkg/namespace" |
| 30 |
- configapi "github.com/openshift/origin/pkg/cmd/server/api" |
|
| 31 | 30 |
) |
| 32 | 31 |
|
| 33 | 32 |
const ( |
| ... | ... |
@@ -36,58 +33,20 @@ const ( |
| 36 | 36 |
KubeAPIPrefixV1 = "/api/v1" |
| 37 | 37 |
) |
| 38 | 38 |
|
| 39 |
-// TODO: Longer term we should read this from some config store, rather than a flag. |
|
| 40 |
-func (c *MasterConfig) EnsurePortalFlags() {
|
|
| 41 |
- if c.PortalNet == nil {
|
|
| 42 |
- glog.Fatal("No --portal-net specified")
|
|
| 43 |
- } |
|
| 44 |
-} |
|
| 45 |
- |
|
| 46 | 39 |
// InstallAPI starts a Kubernetes master and registers the supported REST APIs |
| 47 | 40 |
// into the provided mux, then returns an array of strings indicating what |
| 48 | 41 |
// endpoints were started (these are format strings that will expect to be sent |
| 49 | 42 |
// a single string value). |
| 50 | 43 |
func (c *MasterConfig) InstallAPI(container *restful.Container) []string {
|
| 51 |
- kubeletClient, err := kclient.NewKubeletClient(c.KubeletClientConfig) |
|
| 52 |
- if err != nil {
|
|
| 53 |
- glog.Fatalf("Unable to configure Kubelet client: %v", err)
|
|
| 54 |
- } |
|
| 55 |
- |
|
| 56 |
- masterConfig := &master.Config{
|
|
| 57 |
- PublicAddress: net.ParseIP(c.Options.MasterIP), |
|
| 58 |
- ReadWritePort: c.MasterPort, |
|
| 59 |
- ReadOnlyPort: c.MasterPort, |
|
| 60 |
- |
|
| 61 |
- EtcdHelper: c.EtcdHelper, |
|
| 62 |
- |
|
| 63 |
- EventTTL: 2 * time.Hour, |
|
| 64 |
- |
|
| 65 |
- PortalNet: c.PortalNet, |
|
| 66 |
- |
|
| 67 |
- RequestContextMapper: c.RequestContextMapper, |
|
| 68 |
- |
|
| 69 |
- RestfulContainer: container, |
|
| 70 |
- KubeletClient: kubeletClient, |
|
| 71 |
- APIPrefix: KubeAPIPrefix, |
|
| 72 |
- |
|
| 73 |
- EnableCoreControllers: true, |
|
| 74 |
- |
|
| 75 |
- MasterCount: c.Options.MasterCount, |
|
| 76 |
- |
|
| 77 |
- Authorizer: c.Authorizer, |
|
| 78 |
- AdmissionControl: c.AdmissionControl, |
|
| 79 |
- |
|
| 80 |
- DisableV1Beta3: !configapi.HasKubernetesAPILevel(c.Options, "v1beta3"), |
|
| 81 |
- EnableV1: configapi.HasKubernetesAPILevel(c.Options, "v1"), |
|
| 82 |
- } |
|
| 83 |
- _ = master.New(masterConfig) |
|
| 44 |
+ c.Master.RestfulContainer = container |
|
| 45 |
+ _ = master.New(c.Master) |
|
| 84 | 46 |
|
| 85 | 47 |
messages := []string{}
|
| 86 |
- if !masterConfig.DisableV1Beta3 {
|
|
| 87 |
- messages = append(messages, fmt.Sprintf("Started Kubernetes API at %%s%s", KubeAPIPrefixV1Beta3))
|
|
| 48 |
+ if !c.Master.DisableV1Beta3 {
|
|
| 49 |
+ messages = append(messages, fmt.Sprintf("Started Kubernetes API at %%s%s (deprecated)", KubeAPIPrefixV1Beta3))
|
|
| 88 | 50 |
} |
| 89 |
- if masterConfig.EnableV1 {
|
|
| 90 |
- messages = append(messages, fmt.Sprintf("Started Kubernetes API at %%s%s (experimental)", KubeAPIPrefixV1))
|
|
| 51 |
+ if c.Master.EnableV1 {
|
|
| 52 |
+ messages = append(messages, fmt.Sprintf("Started Kubernetes API at %%s%s", KubeAPIPrefixV1))
|
|
| 91 | 53 |
} |
| 92 | 54 |
|
| 93 | 55 |
return messages |
| ... | ... |
@@ -5,37 +5,30 @@ import ( |
| 5 | 5 |
"fmt" |
| 6 | 6 |
"net" |
| 7 | 7 |
"strconv" |
| 8 |
+ "strings" |
|
| 9 |
+ "time" |
|
| 8 | 10 |
|
| 11 |
+ "github.com/GoogleCloudPlatform/kubernetes/cmd/kube-apiserver/app" |
|
| 9 | 12 |
"github.com/GoogleCloudPlatform/kubernetes/pkg/admission" |
| 10 | 13 |
kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api" |
| 11 | 14 |
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" |
| 12 |
- "github.com/GoogleCloudPlatform/kubernetes/pkg/auth/authorizer" |
|
| 13 | 15 |
kclient "github.com/GoogleCloudPlatform/kubernetes/pkg/client" |
| 14 | 16 |
"github.com/GoogleCloudPlatform/kubernetes/pkg/master" |
| 15 |
- "github.com/GoogleCloudPlatform/kubernetes/pkg/tools" |
|
| 17 |
+ "github.com/GoogleCloudPlatform/kubernetes/pkg/util" |
|
| 18 |
+ kerrors "github.com/GoogleCloudPlatform/kubernetes/pkg/util/errors" |
|
| 16 | 19 |
|
| 17 | 20 |
"github.com/openshift/origin/pkg/cmd/flagtypes" |
| 18 | 21 |
configapi "github.com/openshift/origin/pkg/cmd/server/api" |
| 19 | 22 |
"github.com/openshift/origin/pkg/cmd/server/etcd" |
| 23 |
+ cmdflags "github.com/openshift/origin/pkg/cmd/util/flags" |
|
| 20 | 24 |
) |
| 21 | 25 |
|
| 22 | 26 |
// MasterConfig defines the required values to start a Kubernetes master |
| 23 | 27 |
type MasterConfig struct {
|
| 24 | 28 |
Options configapi.KubernetesMasterConfig |
| 25 | 29 |
|
| 26 |
- MasterPort int |
|
| 27 |
- |
|
| 28 |
- // TODO: remove, not used |
|
| 29 |
- PortalNet *net.IPNet |
|
| 30 |
- |
|
| 31 |
- RequestContextMapper kapi.RequestContextMapper |
|
| 32 |
- |
|
| 33 |
- EtcdHelper tools.EtcdHelper |
|
| 34 |
- KubeClient *kclient.Client |
|
| 35 |
- KubeletClientConfig *kclient.KubeletConfig |
|
| 36 |
- |
|
| 37 |
- Authorizer authorizer.Authorizer |
|
| 38 |
- AdmissionControl admission.Interface |
|
| 30 |
+ Master *master.Config |
|
| 31 |
+ KubeClient *kclient.Client |
|
| 39 | 32 |
} |
| 40 | 33 |
|
| 41 | 34 |
func BuildKubernetesMasterConfig(options configapi.MasterConfig, requestContextMapper kapi.RequestContextMapper, kubeClient *kclient.Client) (*MasterConfig, error) {
|
| ... | ... |
@@ -54,13 +47,13 @@ func BuildKubernetesMasterConfig(options configapi.MasterConfig, requestContextM |
| 54 | 54 |
} |
| 55 | 55 |
|
| 56 | 56 |
kubeletClientConfig := configapi.GetKubeletClientConfig(options) |
| 57 |
- |
|
| 58 |
- portalNet := net.IPNet(flagtypes.DefaultIPNet(options.KubernetesMasterConfig.ServicesSubnet)) |
|
| 57 |
+ kubeletClient, err := kclient.NewKubeletClient(kubeletClientConfig) |
|
| 58 |
+ if err != nil {
|
|
| 59 |
+ return nil, fmt.Errorf("unable to configure Kubelet client: %v", err)
|
|
| 60 |
+ } |
|
| 59 | 61 |
|
| 60 | 62 |
// in-order list of plug-ins that should intercept admission decisions |
| 61 | 63 |
// TODO: Push node environment support to upstream in future |
| 62 |
- admissionControlPluginNames := []string{"NamespaceExists", "NamespaceLifecycle", "OriginPodNodeEnvironment", "LimitRanger", "ServiceAccount", "ResourceQuota"}
|
|
| 63 |
- admissionController := admission.NewFromPlugins(kubeClient, admissionControlPluginNames, "") |
|
| 64 | 64 |
|
| 65 | 65 |
_, portString, err := net.SplitHostPort(options.ServingInfo.BindAddress) |
| 66 | 66 |
if err != nil {
|
| ... | ... |
@@ -71,17 +64,61 @@ func BuildKubernetesMasterConfig(options configapi.MasterConfig, requestContextM |
| 71 | 71 |
return nil, err |
| 72 | 72 |
} |
| 73 | 73 |
|
| 74 |
- kmaster := &MasterConfig{
|
|
| 75 |
- Options: *options.KubernetesMasterConfig, |
|
| 74 |
+ portRange, err := util.ParsePortRange(options.KubernetesMasterConfig.ServicesNodePortRange) |
|
| 75 |
+ if err != nil {
|
|
| 76 |
+ return nil, err |
|
| 77 |
+ } |
|
| 78 |
+ |
|
| 79 |
+ server := app.NewAPIServer() |
|
| 80 |
+ server.EventTTL = 2 * time.Hour |
|
| 81 |
+ server.PortalNet = util.IPNet(flagtypes.DefaultIPNet(options.KubernetesMasterConfig.ServicesSubnet)) |
|
| 82 |
+ server.ServiceNodePorts = *portRange |
|
| 83 |
+ server.AdmissionControl = strings.Join([]string{
|
|
| 84 |
+ "NamespaceExists", "NamespaceLifecycle", "OriginPodNodeEnvironment", "LimitRanger", "ServiceAccount", "ResourceQuota", |
|
| 85 |
+ }, ",") |
|
| 86 |
+ |
|
| 87 |
+ // resolve extended arguments |
|
| 88 |
+ // TODO: this should be done in config validation (along with the above) so we can provide |
|
| 89 |
+ // proper errors |
|
| 90 |
+ if err := cmdflags.Resolve(options.KubernetesMasterConfig.APIServerArguments, server.AddFlags); len(err) > 0 {
|
|
| 91 |
+ return nil, kerrors.NewAggregate(err) |
|
| 92 |
+ } |
|
| 93 |
+ |
|
| 94 |
+ admissionController := admission.NewFromPlugins(kubeClient, strings.Split(server.AdmissionControl, ","), server.AdmissionControlConfigFile) |
|
| 95 |
+ |
|
| 96 |
+ m := &master.Config{
|
|
| 97 |
+ PublicAddress: net.ParseIP(options.KubernetesMasterConfig.MasterIP), |
|
| 98 |
+ ReadWritePort: port, |
|
| 99 |
+ ReadOnlyPort: port, |
|
| 100 |
+ |
|
| 101 |
+ EtcdHelper: ketcdHelper, |
|
| 102 |
+ |
|
| 103 |
+ EventTTL: server.EventTTL, |
|
| 104 |
+ //MinRequestTimeout: server.MinRequestTimeout, |
|
| 105 |
+ |
|
| 106 |
+ PortalNet: (*net.IPNet)(&server.PortalNet), |
|
| 107 |
+ ServiceNodePorts: server.ServiceNodePorts, |
|
| 76 | 108 |
|
| 77 |
- MasterPort: port, |
|
| 78 |
- PortalNet: &portalNet, |
|
| 79 | 109 |
RequestContextMapper: requestContextMapper, |
| 80 |
- EtcdHelper: ketcdHelper, |
|
| 81 |
- KubeClient: kubeClient, |
|
| 82 |
- KubeletClientConfig: kubeletClientConfig, |
|
| 83 |
- Authorizer: apiserver.NewAlwaysAllowAuthorizer(), |
|
| 84 |
- AdmissionControl: admissionController, |
|
| 110 |
+ |
|
| 111 |
+ KubeletClient: kubeletClient, |
|
| 112 |
+ APIPrefix: KubeAPIPrefix, |
|
| 113 |
+ |
|
| 114 |
+ EnableCoreControllers: true, |
|
| 115 |
+ |
|
| 116 |
+ MasterCount: options.KubernetesMasterConfig.MasterCount, |
|
| 117 |
+ |
|
| 118 |
+ Authorizer: apiserver.NewAlwaysAllowAuthorizer(), |
|
| 119 |
+ AdmissionControl: admissionController, |
|
| 120 |
+ |
|
| 121 |
+ DisableV1Beta3: !configapi.HasKubernetesAPILevel(*options.KubernetesMasterConfig, "v1beta3"), |
|
| 122 |
+ EnableV1: configapi.HasKubernetesAPILevel(*options.KubernetesMasterConfig, "v1"), |
|
| 123 |
+ } |
|
| 124 |
+ |
|
| 125 |
+ kmaster := &MasterConfig{
|
|
| 126 |
+ Options: *options.KubernetesMasterConfig, |
|
| 127 |
+ Master: m, |
|
| 128 |
+ KubeClient: kubeClient, |
|
| 85 | 129 |
} |
| 86 | 130 |
|
| 87 | 131 |
return kmaster, nil |
| ... | ... |
@@ -58,15 +58,20 @@ func (c *AssetConfig) Run() {
|
| 58 | 58 |
}) |
| 59 | 59 |
} |
| 60 | 60 |
|
| 61 |
+ timeout := c.Options.ServingInfo.RequestTimeoutSeconds |
|
| 62 |
+ if timeout == -1 {
|
|
| 63 |
+ timeout = 0 |
|
| 64 |
+ } |
|
| 65 |
+ |
|
| 61 | 66 |
server := &http.Server{
|
| 62 | 67 |
Addr: c.Options.ServingInfo.BindAddress, |
| 63 | 68 |
Handler: mux, |
| 64 |
- ReadTimeout: 5 * time.Minute, |
|
| 65 |
- WriteTimeout: 5 * time.Minute, |
|
| 69 |
+ ReadTimeout: time.Duration(timeout) * time.Second, |
|
| 70 |
+ WriteTimeout: time.Duration(timeout) * time.Second, |
|
| 66 | 71 |
MaxHeaderBytes: 1 << 20, |
| 67 | 72 |
} |
| 68 | 73 |
|
| 69 |
- isTLS := configapi.UseTLS(c.Options.ServingInfo) |
|
| 74 |
+ isTLS := configapi.UseTLS(c.Options.ServingInfo.ServingInfo) |
|
| 70 | 75 |
|
| 71 | 76 |
go util.Forever(func() {
|
| 72 | 77 |
if isTLS {
|
| ... | ... |
@@ -494,11 +494,22 @@ func (c *MasterConfig) Run(protected []APIInstaller, unprotected []APIInstaller) |
| 494 | 494 |
handler = contextHandler |
| 495 | 495 |
} |
| 496 | 496 |
|
| 497 |
+ if c.Options.ServingInfo.MaxRequestsInFlight > 0 {
|
|
| 498 |
+ longRunningRE := regexp.MustCompile("[.*\\/watch$][^\\/proxy.*]")
|
|
| 499 |
+ sem := make(chan bool, c.Options.ServingInfo.MaxRequestsInFlight) |
|
| 500 |
+ handler = apiserver.MaxInFlightLimit(sem, longRunningRE, handler) |
|
| 501 |
+ } |
|
| 502 |
+ |
|
| 503 |
+ timeout := c.Options.ServingInfo.RequestTimeoutSeconds |
|
| 504 |
+ if timeout == -1 {
|
|
| 505 |
+ timeout = 0 |
|
| 506 |
+ } |
|
| 507 |
+ |
|
| 497 | 508 |
server := &http.Server{
|
| 498 | 509 |
Addr: c.Options.ServingInfo.BindAddress, |
| 499 | 510 |
Handler: handler, |
| 500 |
- ReadTimeout: 5 * time.Minute, |
|
| 501 |
- WriteTimeout: 5 * time.Minute, |
|
| 511 |
+ ReadTimeout: time.Duration(timeout) * time.Second, |
|
| 512 |
+ WriteTimeout: time.Duration(timeout) * time.Second, |
|
| 502 | 513 |
MaxHeaderBytes: 1 << 20, |
| 503 | 514 |
} |
| 504 | 515 |
|
| ... | ... |
@@ -161,7 +161,7 @@ func BuildMasterConfig(options configapi.MasterConfig) (*MasterConfig, error) {
|
| 161 | 161 |
|
| 162 | 162 |
AdmissionControl: admissionController, |
| 163 | 163 |
|
| 164 |
- TLS: configapi.UseTLS(options.ServingInfo), |
|
| 164 |
+ TLS: configapi.UseTLS(options.ServingInfo.ServingInfo), |
|
| 165 | 165 |
|
| 166 | 166 |
ControllerPlug: plug.NewPlug(!options.PauseControllers), |
| 167 | 167 |
|
| ... | ... |
@@ -226,7 +226,7 @@ func newAuthenticator(config configapi.MasterConfig, etcdHelper tools.EtcdHelper |
| 226 | 226 |
authenticators = append(authenticators, paramtoken.New("access_token", tokenAuthenticator, true))
|
| 227 | 227 |
} |
| 228 | 228 |
|
| 229 |
- if configapi.UseTLS(config.ServingInfo) {
|
|
| 229 |
+ if configapi.UseTLS(config.ServingInfo.ServingInfo) {
|
|
| 230 | 230 |
// build cert authenticator |
| 231 | 231 |
// TODO: add "system:" prefix in authenticator, limit cert to username |
| 232 | 232 |
// TODO: add "system:" prefix to groups in authenticator, limit cert to group name |
| ... | ... |
@@ -150,8 +150,10 @@ func (args MasterArgs) BuildSerializeableMasterConfig() (*configapi.MasterConfig |
| 150 | 150 |
etcdClientInfo := admin.DefaultMasterEtcdClientCertInfo(args.ConfigDir.Value()) |
| 151 | 151 |
|
| 152 | 152 |
config := &configapi.MasterConfig{
|
| 153 |
- ServingInfo: configapi.ServingInfo{
|
|
| 154 |
- BindAddress: args.ListenArg.ListenAddr.URL.Host, |
|
| 153 |
+ ServingInfo: configapi.HTTPServingInfo{
|
|
| 154 |
+ ServingInfo: configapi.ServingInfo{
|
|
| 155 |
+ BindAddress: args.ListenArg.ListenAddr.URL.Host, |
|
| 156 |
+ }, |
|
| 155 | 157 |
}, |
| 156 | 158 |
CORSAllowedOrigins: corsAllowedOrigins.List(), |
| 157 | 159 |
MasterPublicURL: masterPublicAddr.String(), |
| ... | ... |
@@ -164,8 +166,10 @@ func (args MasterArgs) BuildSerializeableMasterConfig() (*configapi.MasterConfig |
| 164 | 164 |
PauseControllers: args.PauseControllers, |
| 165 | 165 |
|
| 166 | 166 |
AssetConfig: &configapi.AssetConfig{
|
| 167 |
- ServingInfo: configapi.ServingInfo{
|
|
| 168 |
- BindAddress: args.GetAssetBindAddress(), |
|
| 167 |
+ ServingInfo: configapi.HTTPServingInfo{
|
|
| 168 |
+ ServingInfo: configapi.ServingInfo{
|
|
| 169 |
+ BindAddress: args.GetAssetBindAddress(), |
|
| 170 |
+ }, |
|
| 169 | 171 |
}, |
| 170 | 172 |
|
| 171 | 173 |
LogoutURL: "", |
| ... | ... |
@@ -357,7 +357,6 @@ func StartMaster(openshiftMasterConfig *configapi.MasterConfig) error {
|
| 357 | 357 |
if err != nil {
|
| 358 | 358 |
return err |
| 359 | 359 |
} |
| 360 |
- kubeConfig.EnsurePortalFlags() |
|
| 361 | 360 |
|
| 362 | 361 |
openshiftConfig.Run([]origin.APIInstaller{kubeConfig}, unprotectedInstallers)
|
| 363 | 362 |
go daemon.SdNotify("READY=1")
|