From ff91fef26b048ba6e1d708b6bf8adf397b5ccafc Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Fri, 19 Jun 2015 15:08:36 -0700 Subject: [PATCH] Hopefully make NodePort docs clearer --- api/swagger-spec/v1.json | 8 ++--- docs/services.md | 73 +++++++++++++++++++++------------------- pkg/api/v1/types.go | 4 +-- 3 files changed, 45 insertions(+), 40 deletions(-) diff --git a/api/swagger-spec/v1.json b/api/swagger-spec/v1.json index 0e0703dc1d1..bfbb5de6419 100644 --- a/api/swagger-spec/v1.json +++ b/api/swagger-spec/v1.json @@ -13399,8 +13399,7 @@ "v1.ServiceSpec": { "id": "v1.ServiceSpec", "required": [ - "ports", - "clusterIP" + "ports" ], "properties": { "ports": { @@ -13415,7 +13414,8 @@ "description": "label keys and values that must match in order to receive traffic for this service; if empty, all pods are selected, if not specified, endpoints must be manually specified" }, "clusterIP": { - "type": "string" + "type": "string", + "description": "IP address of the service; usually assigned by the system; if specified, it will be allocated to the service if unused or else creation of the service will fail; cannot be updated; 'None' can be specified for a headless service when proxying is not required" }, "type": { "type": "string", @@ -13461,7 +13461,7 @@ "nodePort": { "type": "integer", "format": "int32", - "description": "the port on each node on which this service is exposed" + "description": "the port on each node on which this service is exposed when type=NodePort or LoadBalancer; usually assigned by the system; if specified, it will be allocated to the service if unused or else creation of the service will fail" } } }, diff --git a/docs/services.md b/docs/services.md index 37e60b33f16..f9c818ac907 100644 --- a/docs/services.md +++ b/docs/services.md @@ -17,8 +17,8 @@ Enter `Services`. A Kubernetes `Service` is an abstraction which defines a logical set of `Pods` and a policy by which to access them - sometimes called a micro-service. The set of `Pods` targeted by a `Service` is (usually) determined by a [`Label -Selector`](labels.md#label-selectors) (see below for why you might want a `Service` without a -selector). +Selector`](labels.md#label-selectors) (see below for why you might want a +`Service` without a selector). As an example, consider an image-processing backend which is running with 3 replicas. Those replicas are fungible - frontends do not care which backend @@ -64,17 +64,17 @@ This specification will create a new `Service` object named "my-service" which targets TCP port 9376 on any `Pod` with the "app=MyApp" label. This `Service` will also be assigned an IP address (sometimes called the "cluster IP"), which is used by the service proxies (see below). The `Service`'s selector will be -evaluated continuously and the results will be posted in an `Endpoints` object +evaluated continuously and the results will be POSTed to an `Endpoints` object also named "my-service". Note that a `Service` can map an incoming port to any `targetPort`. By default -the `targetPort` is the same as the `port` field. Perhaps more interesting is -that `targetPort` can be a string, referring to the name of a port in the -backend `Pods`. The actual port number assigned to that name can be different -in each backend `Pod`. This offers a lot of flexibility for deploying and -evolving your `Services`. For example, you can change the port number that -pods expose in the next version of your backend software, without breaking -clients. +the `targetPort` will be set to the same value as the `port` field. Perhaps +more interesting is that `targetPort` can be a string, referring to the name of +a port in the backend `Pods`. The actual port number assigned to that name can +be different in each backend `Pod`. This offers a lot of flexibility for +deploying and evolving your `Services`. For example, you can change the port +number that pods expose in the next version of your backend software, without +breaking clients. Kubernetes `Services` support `TCP` and `UDP` for protocols. The default is `TCP`. @@ -143,13 +143,12 @@ this example). Every node in a Kubernetes cluster runs a `kube-proxy`. This application watches the Kubernetes master for the addition and removal of `Service` -and `Endpoints` objects. For each `Service` it opens a port (random) on the -local node. Any connections made to that port will be proxied to one of the -corresponding backend `Pods`. Which backend to use is decided based on the +and `Endpoints` objects. For each `Service` it opens a port (randomly chosen) +on the local node. Any connections made to that port will be proxied to one of +the corresponding backend `Pods`. Which backend to use is decided based on the `SessionAffinity` of the `Service`. Lastly, it installs iptables rules which -capture traffic to the `Service`'s `Port` on the `Service`'s cluster IP (which -is entirely virtual) and redirects that traffic to the previously described -port. +capture traffic to the `Service`'s cluster IP (which is virtual) and `Port` and +redirects that traffic to the previously described port. The net result is that any traffic bound for the `Service` is proxied to an appropriate backend without the clients knowing anything about Kubernetes or @@ -202,14 +201,14 @@ disambiguated. For example: ## Choosing your own IP address -A user can specify their own cluster IP address as part of a `Service` creation -request. To do this, set the `spec.clusterIP` field. For example, if they -already have an existing DNS entry that they wish to replace, or legacy systems +You can specify your own cluster IP address as part of a `Service` creation +request. To do this, set the `spec.clusterIP` field. For example, if you +already have an existing DNS entry that you wish to replace, or legacy systems that are configured for a specific IP address and difficult to re-configure. The IP address that a user chooses must be a valid IP address and within the -service_cluster_ip_range CIDR range that is specified by flag to the API server. -If the IP address value is invalid, the apiserver returns a 422 HTTP status code -to indicate that the value is invalid. +service_cluster_ip_range CIDR range that is specified by flag to the API +server. If the IP address value is invalid, the apiserver returns a 422 HTTP +status code to indicate that the value is invalid. ### Why not use round-robin DNS? @@ -273,16 +272,18 @@ a name lookup for "my-service". `Pods` which exist in other `Namespaces` must qualify the name as "my-service.my-ns". The result of these name lookups is the cluster IP. -We will soon add DNS support for multi-port `Services` in the form of SRV -records. +Kubernetes also supports DNS SRV (service) records for named ports. If the +"my-service.my-ns" `Service` has a port named "http" with protocol `TCP`, you +can do a DNS SRV query for "_http._tcp.my-service.my-ns" to discover the port +number for "http". ## Headless services Sometimes you don't need or want load-balancing and a single service IP. In this case, you can create "headless" services by specifying `"None"` for the cluster IP (`spec.clusterIP`). -For such `Services`, a cluster IP is not allocated and service-specific -environment variables for `Pods` are not created. DNS is configured to return + +For such `Services`, a cluster IP is not allocated. DNS is configured to return multiple A records (addresses) for the `Service` name, which point directly to the `Pods` backing the `Service`. Additionally, the kube proxy does not handle these services and there is no load balancing or proxying done by the platform @@ -301,12 +302,13 @@ Service onto an external (outside of your cluster, maybe public internet) IP address. Kubernetes supports two ways of doing this: `NodePort`s and `LoadBalancer`s. -Every `Service` has a `Type` field which defines how the `Service` can be +Every `Service` has a `type` field which defines how the `Service` can be accessed. Valid values for this field are: - * `ClusterIP`: use a cluster-internal IP only - this is the default + * `ClusterIP`: use a cluster-internal IP only - this is the default and is + discussed above * `NodePort`: use a cluster IP, but also expose the service on a port on each - node of the cluster (the same port on each) + node of the cluster (the same port on each node) * `LoadBalancer`: use a ClusterIP and a NodePort, but also ask the cloud provider for a load balancer which forwards to the `Service` @@ -316,11 +318,14 @@ as of Kubernetes 1.0. ### Type = NodePort If you set the `type` field to `"NodePort"`, the Kubernetes master will -allocate you a port (from a flag-configured range, default: 30,000 - 32,767) -on each node for each port exposed by your `Service`. That port will be -reported in your `Service`'s `spec.ports[*].nodePort` field. If you specify -a value in that field, the system will allocate you that port or else will -fail the API transaction. +allocate a port from a flag-configured range (default: 30000-32767), and each +node will proxy that port (the same port number on every node) into your `Service`. +That port will be reported in your `Service`'s `spec.ports[*].nodePort` field. + +If you want a specific port number, you can specify a value in the `nodePort` +field, and the system will allocate you that port or else the API transaction +will fail. The value you specify must be in the configured range for node +ports. This gives developers the freedom to set up their own load balancers, to configure cloud environments that are not fully supported by Kubernetes, or diff --git a/pkg/api/v1/types.go b/pkg/api/v1/types.go index 3bce90ef9b8..60442e7ffff 100644 --- a/pkg/api/v1/types.go +++ b/pkg/api/v1/types.go @@ -1071,7 +1071,7 @@ type ServiceSpec struct { // not be changed by updates. // Valid values are None, empty string (""), or a valid IP address // None can be specified for headless services when proxying is not required - ClusterIP string `json:"clusterIP,omitempty description: IP address of the service; usually assigned by the system; if specified, it will be allocated to the service if unused, and creation of the service will fail otherwise; cannot be updated; 'None' can be specified for a headless service when proxying is not required"` + ClusterIP string `json:"clusterIP,omitempty" description:"IP address of the service; usually assigned by the system; if specified, it will be allocated to the service if unused or else creation of the service will fail; cannot be updated; 'None' can be specified for a headless service when proxying is not required"` // Type determines how the service will be exposed. Valid options: ClusterIP, NodePort, LoadBalancer Type ServiceType `json:"type,omitempty" description:"type of this service; must be ClusterIP, NodePort, or LoadBalancer; defaults to ClusterIP"` @@ -1106,7 +1106,7 @@ type ServicePort struct { // The port on each node on which this service is exposed. // Default is to auto-allocate a port if the ServiceType of this Service requires one. - NodePort int `json:"nodePort" description:"the port on each node on which this service is exposed"` + NodePort int `json:"nodePort" description:"the port on each node on which this service is exposed when type=NodePort or LoadBalancer; usually assigned by the system; if specified, it will be allocated to the service if unused or else creation of the service will fail"` } // Service is a named abstraction of software service (for example, mysql) consisting of local port