Convert site to Hugo (#8316)
This commit converts content and layout to use Hugo.
This commit is contained in:
committed by
k8s-ci-robot
parent
7745f0e0c5
commit
7f3b633aa0
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: "Access Applications in a Cluster"
|
||||
weight: 70
|
||||
---
|
||||
|
||||
@@ -0,0 +1,335 @@
|
||||
---
|
||||
title: Accessing Clusters
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Accessing the cluster API
|
||||
|
||||
### Accessing for the first time with kubectl
|
||||
|
||||
When accessing the Kubernetes API for the first time, we suggest using the
|
||||
Kubernetes CLI, `kubectl`.
|
||||
|
||||
To access a cluster, you need to know the location of the cluster and have credentials
|
||||
to access it. Typically, this is automatically set-up when you work through
|
||||
a [Getting started guide](/docs/setup/),
|
||||
or someone else setup the cluster and provided you with credentials and a location.
|
||||
|
||||
Check the location and credentials that kubectl knows about with this command:
|
||||
|
||||
```shell
|
||||
$ kubectl config view
|
||||
```
|
||||
|
||||
Many of the [examples](/docs/user-guide/kubectl-cheatsheet) provide an introduction to using
|
||||
kubectl and complete documentation is found in the [kubectl manual](/docs/user-guide/kubectl-overview).
|
||||
|
||||
### Directly accessing the REST API
|
||||
|
||||
Kubectl handles locating and authenticating to the apiserver.
|
||||
If you want to directly access the REST API with an http client like
|
||||
curl or wget, or a browser, there are several ways to locate and authenticate:
|
||||
|
||||
- Run kubectl in proxy mode.
|
||||
- Recommended approach.
|
||||
- Uses stored apiserver location.
|
||||
- Verifies identity of apiserver using self-signed cert. No MITM possible.
|
||||
- Authenticates to apiserver.
|
||||
- In future, may do intelligent client-side load-balancing and failover.
|
||||
- Provide the location and credentials directly to the http client.
|
||||
- Alternate approach.
|
||||
- Works with some types of client code that are confused by using a proxy.
|
||||
- Need to import a root cert into your browser to protect against MITM.
|
||||
|
||||
#### Using kubectl proxy
|
||||
|
||||
The following command runs kubectl in a mode where it acts as a reverse proxy. It handles
|
||||
locating the apiserver and authenticating.
|
||||
Run it like this:
|
||||
|
||||
```shell
|
||||
$ kubectl proxy --port=8080 &
|
||||
```
|
||||
|
||||
See [kubectl proxy](/docs/reference/generated/kubectl/kubectl-commands/#proxy) for more details.
|
||||
|
||||
Then you can explore the API with curl, wget, or a browser, replacing localhost
|
||||
with [::1] for IPv6, like so:
|
||||
|
||||
```shell
|
||||
$ curl http://localhost:8080/api/
|
||||
{
|
||||
"versions": [
|
||||
"v1"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### Without kubectl proxy (before v1.3.x)
|
||||
|
||||
It is possible to avoid using kubectl proxy by passing an authentication token
|
||||
directly to the apiserver, like this:
|
||||
|
||||
```shell
|
||||
$ APISERVER=$(kubectl config view | grep server | cut -f 2- -d ":" | tr -d " ")
|
||||
$ TOKEN=$(kubectl config view | grep token | cut -f 2 -d ":" | tr -d " ")
|
||||
$ curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
|
||||
{
|
||||
"versions": [
|
||||
"v1"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### Without kubectl proxy (post v1.3.x)
|
||||
|
||||
In Kubernetes version 1.3 or later, `kubectl config view` no longer displays the token. Use `kubectl describe secret...` to get the token for the default service account, like this:
|
||||
|
||||
``` shell
|
||||
$ APISERVER=$(kubectl config view | grep server | cut -f 2- -d ":" | tr -d " ")
|
||||
$ TOKEN=$(kubectl describe secret $(kubectl get secrets | grep default | cut -f1 -d ' ') | grep -E '^token' | cut -f2 -d':' | tr -d '\t')
|
||||
$ curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
|
||||
{
|
||||
"kind": "APIVersions",
|
||||
"versions": [
|
||||
"v1"
|
||||
],
|
||||
"serverAddressByClientCIDRs": [
|
||||
{
|
||||
"clientCIDR": "0.0.0.0/0",
|
||||
"serverAddress": "10.0.1.149:443"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The above examples use the `--insecure` flag. This leaves it subject to MITM
|
||||
attacks. When kubectl accesses the cluster it uses a stored root certificate
|
||||
and client certificates to access the server. (These are installed in the
|
||||
`~/.kube` directory). Since cluster certificates are typically self-signed, it
|
||||
may take special configuration to get your http client to use root
|
||||
certificate.
|
||||
|
||||
On some clusters, the apiserver does not require authentication; it may serve
|
||||
on localhost, or be protected by a firewall. There is not a standard
|
||||
for this. [Configuring Access to the API](/docs/admin/accessing-the-api)
|
||||
describes how a cluster admin can configure this. Such approaches may conflict
|
||||
with future high-availability support.
|
||||
|
||||
### Programmatic access to the API
|
||||
|
||||
Kubernetes officially supports [Go](#go-client) and [Python](#python-client)
|
||||
client libraries.
|
||||
|
||||
#### Go client
|
||||
|
||||
* To get the library, run the following command: `go get k8s.io/client-go/<version number>/kubernetes`. See [https://github.com/kubernetes/client-go](https://github.com/kubernetes/client-go) to see which versions are supported.
|
||||
* Write an application atop of the client-go clients. Note that client-go defines its own API objects, so if needed, please import API definitions from client-go rather than from the main repository, e.g., `import "k8s.io/client-go/1.4/pkg/api/v1"` is correct.
|
||||
|
||||
The Go client can use the same [kubeconfig file](/docs/concepts/cluster-administration/authenticate-across-clusters-kubeconfig/)
|
||||
as the kubectl CLI does to locate and authenticate to the apiserver. See this [example](https://git.k8s.io/client-go/examples/out-of-cluster-client-configuration/main.go).
|
||||
|
||||
If the application is deployed as a Pod in the cluster, please refer to the [next section](#accessing-the-api-from-a-pod).
|
||||
|
||||
#### Python client
|
||||
|
||||
To use [Python client](https://github.com/kubernetes-client/python), run the following command: `pip install kubernetes`. See [Python Client Library page](https://github.com/kubernetes-client/python) for more installation options.
|
||||
|
||||
The Python client can use the same [kubeconfig file](/docs/concepts/cluster-administration/authenticate-across-clusters-kubeconfig/)
|
||||
as the kubectl CLI does to locate and authenticate to the apiserver. See this [example](https://github.com/kubernetes-client/python/tree/master/examples/example1.py).
|
||||
|
||||
#### Other languages
|
||||
|
||||
There are [client libraries](/docs/reference/client-libraries/) for accessing the API from other languages.
|
||||
See documentation for other libraries for how they authenticate.
|
||||
|
||||
### Accessing the API from a Pod
|
||||
|
||||
When accessing the API from a pod, locating and authenticating
|
||||
to the apiserver are somewhat different.
|
||||
|
||||
The recommended way to locate the apiserver within the pod is with
|
||||
the `kubernetes.default.svc` DNS name, which resolves to a Service IP which in turn
|
||||
will be routed to an apiserver.
|
||||
|
||||
The recommended way to authenticate to the apiserver is with a
|
||||
[service account](/docs/tasks/configure-pod-container/configure-service-account/) credential. By kube-system, a pod
|
||||
is associated with a service account, and a credential (token) for that
|
||||
service account is placed into the filesystem tree of each container in that pod,
|
||||
at `/var/run/secrets/kubernetes.io/serviceaccount/token`.
|
||||
|
||||
If available, a certificate bundle is placed into the filesystem tree of each
|
||||
container at `/var/run/secrets/kubernetes.io/serviceaccount/ca.crt`, and should be
|
||||
used to verify the serving certificate of the apiserver.
|
||||
|
||||
Finally, the default namespace to be used for namespaced API operations is placed in a file
|
||||
at `/var/run/secrets/kubernetes.io/serviceaccount/namespace` in each container.
|
||||
|
||||
From within a pod the recommended ways to connect to API are:
|
||||
|
||||
- run `kubectl proxy` in a sidecar container in the pod, or as a background
|
||||
process within the container. This proxies the
|
||||
Kubernetes API to the localhost interface of the pod, so that other processes
|
||||
in any container of the pod can access it.
|
||||
- use the Go client library, and create a client using the `rest.InClusterConfig()` and `kubernetes.NewForConfig()` functions.
|
||||
They handle locating and authenticating to the apiserver. [example](https://git.k8s.io/client-go/examples/in-cluster-client-configuration/main.go)
|
||||
|
||||
In each case, the credentials of the pod are used to communicate securely with the apiserver.
|
||||
|
||||
## Accessing services running on the cluster
|
||||
|
||||
The previous section was about connecting the Kubernetes API server. This section is about
|
||||
connecting to other services running on Kubernetes cluster. In Kubernetes, the
|
||||
[nodes](/docs/admin/node), [pods](/docs/user-guide/pods) and [services](/docs/user-guide/services) all have
|
||||
their own IPs. In many cases, the node IPs, pod IPs, and some service IPs on a cluster will not be
|
||||
routable, so they will not be reachable from a machine outside the cluster,
|
||||
such as your desktop machine.
|
||||
|
||||
### Ways to connect
|
||||
|
||||
You have several options for connecting to nodes, pods and services from outside the cluster:
|
||||
|
||||
- Access services through public IPs.
|
||||
- Use a service with type `NodePort` or `LoadBalancer` to make the service reachable outside
|
||||
the cluster. See the [services](/docs/user-guide/services) and
|
||||
[kubectl expose](/docs/reference/generated/kubectl/kubectl-commands/#expose) documentation.
|
||||
- Depending on your cluster environment, this may just expose the service to your corporate network,
|
||||
or it may expose it to the internet. Think about whether the service being exposed is secure.
|
||||
Does it do its own authentication?
|
||||
- Place pods behind services. To access one specific pod from a set of replicas, such as for debugging,
|
||||
place a unique label on the pod and create a new service which selects this label.
|
||||
- In most cases, it should not be necessary for application developer to directly access
|
||||
nodes via their nodeIPs.
|
||||
- Access services, nodes, or pods using the Proxy Verb.
|
||||
- Does apiserver authentication and authorization prior to accessing the remote service.
|
||||
Use this if the services are not secure enough to expose to the internet, or to gain
|
||||
access to ports on the node IP, or for debugging.
|
||||
- Proxies may cause problems for some web applications.
|
||||
- Only works for HTTP/HTTPS.
|
||||
- Described [here](#manually-constructing-apiserver-proxy-urls).
|
||||
- Access from a node or pod in the cluster.
|
||||
- Run a pod, and then connect to a shell in it using [kubectl exec](/docs/reference/generated/kubectl/kubectl-commands/#exec).
|
||||
Connect to other nodes, pods, and services from that shell.
|
||||
- Some clusters may allow you to ssh to a node in the cluster. From there you may be able to
|
||||
access cluster services. This is a non-standard method, and will work on some clusters but
|
||||
not others. Browsers and other tools may or may not be installed. Cluster DNS may not work.
|
||||
|
||||
### Discovering builtin services
|
||||
|
||||
Typically, there are several services which are started on a cluster by kube-system. Get a list of these
|
||||
with the `kubectl cluster-info` command:
|
||||
|
||||
```shell
|
||||
$ kubectl cluster-info
|
||||
|
||||
Kubernetes master is running at https://104.197.5.247
|
||||
elasticsearch-logging is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy
|
||||
kibana-logging is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/kibana-logging/proxy
|
||||
kube-dns is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/kube-dns/proxy
|
||||
grafana is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/monitoring-grafana/proxy
|
||||
heapster is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/monitoring-heapster/proxy
|
||||
```
|
||||
|
||||
This shows the proxy-verb URL for accessing each service.
|
||||
For example, this cluster has cluster-level logging enabled (using Elasticsearch), which can be reached
|
||||
at `https://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/` if suitable credentials are passed. Logging can also be reached through a kubectl proxy, for example at:
|
||||
`http://localhost:8080/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/`.
|
||||
(See [above](#accessing-the-cluster-api) for how to pass credentials or use kubectl proxy.)
|
||||
|
||||
#### Manually constructing apiserver proxy URLs
|
||||
|
||||
As mentioned above, you use the `kubectl cluster-info` command to retrieve the service's proxy URL. To create proxy URLs that include service endpoints, suffixes, and parameters, you simply append to the service's proxy URL:
|
||||
`http://`*`kubernetes_master_address`*`/api/v1/namespaces/`*`namespace_name`*`/services/`*`service_name[:port_name]`*`/proxy`
|
||||
|
||||
If you haven't specified a name for your port, you don't have to specify *port_name* in the URL.
|
||||
|
||||
By default, the API server proxies to your service using http. To use https, prefix the service name with `https:`:
|
||||
`http://`*`kubernetes_master_address`*`/api/v1/namespaces/`*`namespace_name`*`/services/`*`https:service_name:[port_name]`*`/proxy`
|
||||
|
||||
The supported formats for the name segment of the URL are:
|
||||
|
||||
* `<service_name>` - proxies to the default or unnamed port using http
|
||||
* `<service_name>:<port_name>` - proxies to the specified port using http
|
||||
* `https:<service_name>:` - proxies to the default or unnamed port using https (note the trailing colon)
|
||||
* `https:<service_name>:<port_name>` - proxies to the specified port using https
|
||||
|
||||
##### Examples
|
||||
|
||||
* To access the Elasticsearch service endpoint `_search?q=user:kimchy`, you would use: `http://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/_search?q=user:kimchy`
|
||||
* To access the Elasticsearch cluster health information `_cluster/health?pretty=true`, you would use: `https://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/_cluster/health?pretty=true`
|
||||
|
||||
```json
|
||||
{
|
||||
"cluster_name" : "kubernetes_logging",
|
||||
"status" : "yellow",
|
||||
"timed_out" : false,
|
||||
"number_of_nodes" : 1,
|
||||
"number_of_data_nodes" : 1,
|
||||
"active_primary_shards" : 5,
|
||||
"active_shards" : 5,
|
||||
"relocating_shards" : 0,
|
||||
"initializing_shards" : 0,
|
||||
"unassigned_shards" : 5
|
||||
}
|
||||
```
|
||||
|
||||
#### Using web browsers to access services running on the cluster
|
||||
|
||||
You may be able to put an apiserver proxy url into the address bar of a browser. However:
|
||||
|
||||
- Web browsers cannot usually pass tokens, so you may need to use basic (password) auth. Apiserver can be configured to accept basic auth,
|
||||
but your cluster may not be configured to accept basic auth.
|
||||
- Some web apps may not work, particularly those with client side javascript that construct urls in a
|
||||
way that is unaware of the proxy path prefix.
|
||||
|
||||
## Requesting redirects
|
||||
|
||||
The redirect capabilities have been deprecated and removed. Please use a proxy (see below) instead.
|
||||
|
||||
## So Many Proxies
|
||||
|
||||
There are several different proxies you may encounter when using Kubernetes:
|
||||
|
||||
1. The [kubectl proxy](#directly-accessing-the-rest-api):
|
||||
|
||||
- runs on a user's desktop or in a pod
|
||||
- proxies from a localhost address to the Kubernetes apiserver
|
||||
- client to proxy uses HTTP
|
||||
- proxy to apiserver uses HTTPS
|
||||
- locates apiserver
|
||||
- adds authentication headers
|
||||
|
||||
1. The [apiserver proxy](#discovering-builtin-services):
|
||||
|
||||
- is a bastion built into the apiserver
|
||||
- connects a user outside of the cluster to cluster IPs which otherwise might not be reachable
|
||||
- runs in the apiserver processes
|
||||
- client to proxy uses HTTPS (or http if apiserver so configured)
|
||||
- proxy to target may use HTTP or HTTPS as chosen by proxy using available information
|
||||
- can be used to reach a Node, Pod, or Service
|
||||
- does load balancing when used to reach a Service
|
||||
|
||||
1. The [kube proxy](/docs/concepts/services-networking/service/#ips-and-vips):
|
||||
|
||||
- runs on each node
|
||||
- proxies UDP and TCP
|
||||
- does not understand HTTP
|
||||
- provides load balancing
|
||||
- is just used to reach services
|
||||
|
||||
1. A Proxy/Load-balancer in front of apiserver(s):
|
||||
|
||||
- existence and implementation varies from cluster to cluster (e.g. nginx)
|
||||
- sits between all clients and one or more apiservers
|
||||
- acts as load balancer if there are several apiservers.
|
||||
|
||||
1. Cloud Load Balancers on external services:
|
||||
|
||||
- are provided by some cloud providers (e.g. AWS ELB, Google Cloud Load Balancer)
|
||||
- are created automatically when the Kubernetes service has type `LoadBalancer`
|
||||
- use UDP/TCP only
|
||||
- implementation varies by cloud provider.
|
||||
|
||||
Kubernetes users will typically not need to worry about anything other than the first two types. The cluster admin
|
||||
will typically ensure that the latter types are setup correctly.
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
---
|
||||
title: Communicate Between Containers in the Same Pod Using a Shared Volume
|
||||
content_template: templates/task
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
|
||||
This page shows how to use a Volume to communicate between two Containers running
|
||||
in the same Pod.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture prerequisites %}}
|
||||
|
||||
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture steps %}}
|
||||
|
||||
## Creating a Pod that runs two Containers
|
||||
|
||||
In this exercise, you create a Pod that runs two Containers. The two containers
|
||||
share a Volume that they can use to communicate. Here is the configuration file
|
||||
for the Pod:
|
||||
|
||||
{{< code file="two-container-pod.yaml" >}}
|
||||
|
||||
In the configuration file, you can see that the Pod has a Volume named
|
||||
`shared-data`.
|
||||
|
||||
The first container listed in the configuration file runs an nginx server. The
|
||||
mount path for the shared Volume is `/usr/share/nginx/html`.
|
||||
The second container is based on the debian image, and has a mount path of
|
||||
`/pod-data`. The second container runs the following command and then terminates.
|
||||
|
||||
echo Hello from the debian container > /pod-data/index.html
|
||||
|
||||
Notice that the second container writes the `index.html` file in the root
|
||||
directory of the nginx server.
|
||||
|
||||
Create the Pod and the two Containers:
|
||||
|
||||
kubectl create -f https://k8s.io/docs/tasks/access-application-cluster/two-container-pod.yaml
|
||||
|
||||
View information about the Pod and the Containers:
|
||||
|
||||
kubectl get pod two-containers --output=yaml
|
||||
|
||||
Here is a portion of the output:
|
||||
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
...
|
||||
name: two-containers
|
||||
namespace: default
|
||||
...
|
||||
spec:
|
||||
...
|
||||
containerStatuses:
|
||||
|
||||
- containerID: docker://c1d8abd1 ...
|
||||
image: debian
|
||||
...
|
||||
lastState:
|
||||
terminated:
|
||||
...
|
||||
name: debian-container
|
||||
...
|
||||
|
||||
- containerID: docker://96c1ff2c5bb ...
|
||||
image: nginx
|
||||
...
|
||||
name: nginx-container
|
||||
...
|
||||
state:
|
||||
running:
|
||||
...
|
||||
|
||||
You can see that the debian Container has terminated, and the nginx Container
|
||||
is still running.
|
||||
|
||||
Get a shell to nginx Container:
|
||||
|
||||
kubectl exec -it two-containers -c nginx-container -- /bin/bash
|
||||
|
||||
In your shell, verify that nginx is running:
|
||||
|
||||
root@two-containers:/# apt-get update
|
||||
root@two-containers:/# apt-get install curl procps
|
||||
root@two-containers:/# ps aux
|
||||
|
||||
The output is similar to this:
|
||||
|
||||
USER PID ... STAT START TIME COMMAND
|
||||
root 1 ... Ss 21:12 0:00 nginx: master process nginx -g daemon off;
|
||||
|
||||
Recall that the debian Container created the `index.html` file in the nginx root
|
||||
directory. Use `curl` to send a GET request to the nginx server:
|
||||
|
||||
root@two-containers:/# curl localhost
|
||||
|
||||
The output shows that nginx serves a web page written by the debian container:
|
||||
|
||||
Hello from the debian container
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture discussion %}}
|
||||
|
||||
## Discussion
|
||||
|
||||
The primary reason that Pods can have multiple containers is to support
|
||||
helper applications that assist a primary application. Typical examples of
|
||||
helper applications are data pullers, data pushers, and proxies.
|
||||
Helper and primary applications often need to communicate with each other.
|
||||
Typically this is done through a shared filesystem, as shown in this exercise,
|
||||
or through the loopback network interface, localhost. An example of this pattern is a
|
||||
web server along with a helper program that polls a Git repository for new updates.
|
||||
|
||||
The Volume in this exercise provides a way for Containers to communicate during
|
||||
the life of the Pod. If the Pod is deleted and recreated, any data stored in
|
||||
the shared Volume is lost.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture whatsnext %}}
|
||||
|
||||
* Learn more about
|
||||
[patterns for composite containers](http://blog.kubernetes.io/2015/06/the-distributed-system-toolkit-patterns.html).
|
||||
|
||||
* Learn about
|
||||
[composite containers for modular architecture](http://www.slideshare.net/Docker/slideshare-burns).
|
||||
|
||||
* See
|
||||
[Configuring a Pod to Use a Volume for Storage](/docs/tasks/configure-pod-container/configure-volume-storage/).
|
||||
|
||||
* See [Volume](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#volume-v1-core).
|
||||
|
||||
* See [Pod](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#pod-v1-core).
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
|
||||
+345
@@ -0,0 +1,345 @@
|
||||
---
|
||||
title: Configure Access to Multiple Clusters
|
||||
content_template: templates/task
|
||||
---
|
||||
|
||||
|
||||
{{% capture overview %}}
|
||||
|
||||
This page shows how to configure access to multiple clusters by using
|
||||
configuration files. After your clusters, users, and contexts are defined in
|
||||
one or more configuration files, you can quickly switch between clusters by using the
|
||||
`kubectl config use-context` command.
|
||||
|
||||
{{< note >}}
|
||||
**Note:** A file that is used to configure access to a cluster is sometimes called
|
||||
a *kubeconfig file*. This is a generic way of referring to configuration files.
|
||||
It does not mean that there is a file named `kubeconfig`.
|
||||
{{< /note >}}
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture prerequisites %}}
|
||||
|
||||
You need to have the [`kubectl`](/docs/tasks/tools/install-kubectl/) command-line tool installed.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture steps %}}
|
||||
|
||||
## Define clusters, users, and contexts
|
||||
|
||||
Suppose you have two clusters, one for development work and one for scratch work.
|
||||
In the `development` cluster, your frontend developers work in a namespace called `frontend`,
|
||||
and your storage developers work in a namespace called `storage`. In your `scratch` cluster,
|
||||
developers work in the default namespace, or they create auxiliary namespaces as they
|
||||
see fit. Access to the development cluster requires authentication by certificate. Access
|
||||
to the scratch cluster requires authentication by username and password.
|
||||
|
||||
Create a directory named `config-exercise`. In your
|
||||
`config-exercise` directory, create a file named `config-demo` with this content:
|
||||
|
||||
```shell
|
||||
apiVersion: v1
|
||||
kind: Config
|
||||
preferences: {}
|
||||
|
||||
clusters:
|
||||
- cluster:
|
||||
name: development
|
||||
- cluster:
|
||||
name: scratch
|
||||
|
||||
users:
|
||||
- name: developer
|
||||
- name: experimenter
|
||||
|
||||
contexts:
|
||||
- context:
|
||||
name: dev-frontend
|
||||
- context:
|
||||
name: dev-storage
|
||||
- context:
|
||||
name: exp-scratch
|
||||
```
|
||||
|
||||
A configuration file describes clusters, users, and contexts. Your `config-demo` file
|
||||
has the framework to describe two clusters, two users, and three contexts.
|
||||
|
||||
Go to your `config-exercise` directory. Enter these commands to add cluster details to
|
||||
your configuration file:
|
||||
|
||||
```shell
|
||||
kubectl config --kubeconfig=config-demo set-cluster development --server=https://1.2.3.4 --certificate-authority=fake-ca-file
|
||||
kubectl config --kubeconfig=config-demo set-cluster scratch --server=https://5.6.7.8 --insecure-skip-tls-verify
|
||||
```
|
||||
|
||||
Add user details to your configuration file:
|
||||
|
||||
```shell
|
||||
kubectl config --kubeconfig=config-demo set-credentials developer --client-certificate=fake-cert-file --client-key=fake-key-seefile
|
||||
kubectl config --kubeconfig=config-demo set-credentials experimenter --username=exp --password=some-password
|
||||
```
|
||||
|
||||
Add context details to your configuration file:
|
||||
|
||||
```shell
|
||||
kubectl config --kubeconfig=config-demo set-context dev-frontend --cluster=development --namespace=frontend --user=developer
|
||||
kubectl config --kubeconfig=config-demo set-context dev-storage --cluster=development --namespace=storage --user=developer
|
||||
kubectl config --kubeconfig=config-demo set-context exp-scratch --cluster=scratch --namespace=default --user=experimenter
|
||||
```
|
||||
|
||||
Open your `config-demo` file to see the added details. As an alternative to opening the
|
||||
`config-demo` file, you can use the `config view` command.
|
||||
|
||||
```shell
|
||||
kubectl config --kubeconfig=config-demo view
|
||||
```
|
||||
|
||||
The output shows the two clusters, two users, and three contexts:
|
||||
|
||||
```shell
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority: fake-ca-file
|
||||
server: https://1.2.3.4
|
||||
name: development
|
||||
- cluster:
|
||||
insecure-skip-tls-verify: true
|
||||
server: https://5.6.7.8
|
||||
name: scratch
|
||||
contexts:
|
||||
- context:
|
||||
cluster: development
|
||||
namespace: frontend
|
||||
user: developer
|
||||
name: dev-frontend
|
||||
- context:
|
||||
cluster: development
|
||||
namespace: storage
|
||||
user: developer
|
||||
name: dev-storage
|
||||
- context:
|
||||
cluster: scratch
|
||||
namespace: default
|
||||
user: experimenter
|
||||
name: exp-scratch
|
||||
current-context: ""
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: developer
|
||||
user:
|
||||
client-certificate: fake-cert-file
|
||||
client-key: fake-key-file
|
||||
- name: experimenter
|
||||
user:
|
||||
password: some-password
|
||||
username: exp
|
||||
```
|
||||
|
||||
Each context is a triple (cluster, user, namespace). For example, the
|
||||
`dev-frontend` context says, Use the credentials of the `developer`
|
||||
user to access the `frontend` namespace of the `development` cluster.
|
||||
|
||||
Set the current context:
|
||||
|
||||
```shell
|
||||
kubectl config --kubeconfig=config-demo use-context dev-frontend
|
||||
```
|
||||
|
||||
Now whenever you enter a `kubectl` command, the action will apply to the cluster,
|
||||
and namespace listed in the `dev-frontend` context. And the command will use
|
||||
the credentials of the user listed in the `dev-frontend` context.
|
||||
|
||||
To see only the configuration information associated with
|
||||
the current context, use the `--minify` flag.
|
||||
|
||||
```shell
|
||||
kubectl config --kubeconfig=config-demo view --minify
|
||||
```
|
||||
|
||||
The output shows configuration information associated with the `dev-frontend` context:
|
||||
|
||||
```shell
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority: fake-ca-file
|
||||
server: https://1.2.3.4
|
||||
name: development
|
||||
contexts:
|
||||
- context:
|
||||
cluster: development
|
||||
namespace: frontend
|
||||
user: developer
|
||||
name: dev-frontend
|
||||
current-context: dev-frontend
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: developer
|
||||
user:
|
||||
client-certificate: fake-cert-file
|
||||
client-key: fake-key-file
|
||||
```
|
||||
|
||||
Now suppose you want to work for a while in the scratch cluster.
|
||||
|
||||
Change the current context to `exp-scratch`:
|
||||
|
||||
```shell
|
||||
kubectl config --kubeconfig=config-demo use-context exp-scratch
|
||||
```
|
||||
|
||||
Now any `kubectl` command you give will apply to the default namespace of
|
||||
the `scratch` cluster. And the command will use the credentials of the user
|
||||
listed in the `exp-scratch` context.
|
||||
|
||||
View configuration associated with the new current context, `exp-scratch`.
|
||||
|
||||
```shell
|
||||
kubectl config --kubeconfig=config-demo view --minify
|
||||
```
|
||||
|
||||
Finally, suppose you want to work for a while in the `storage` namespace of the
|
||||
`development` cluster.
|
||||
|
||||
Change the current context to `dev-storage`:
|
||||
|
||||
```shell
|
||||
kubectl config --kubeconfig=config-demo use-context dev-storage
|
||||
```
|
||||
|
||||
View configuration associated with the new current context, `dev-storage`.
|
||||
|
||||
|
||||
```shell
|
||||
kubectl config --kubeconfig=config-demo view --minify
|
||||
```
|
||||
|
||||
## Create a second configuration file
|
||||
|
||||
In your `config-exercise` directory, create a file named `config-demo-2` with this content:
|
||||
|
||||
```shell
|
||||
apiVersion: v1
|
||||
kind: Config
|
||||
preferences: {}
|
||||
|
||||
contexts:
|
||||
- context:
|
||||
cluster: development
|
||||
namespace: ramp
|
||||
user: developer
|
||||
name: dev-ramp-up
|
||||
```
|
||||
|
||||
The preceding configuration file defines a new context named `dev-ramp-up`.
|
||||
|
||||
## Set the KUBECONFIG environment variable
|
||||
|
||||
See whether you have an environment variable named `KUBECONFIG`. If so, save the
|
||||
current value of your `KUBECONFIG` environment variable, so you can restore it later.
|
||||
For example, on Linux:
|
||||
|
||||
```shell
|
||||
export KUBECONFIG_SAVED=$KUBECONFIG
|
||||
```
|
||||
|
||||
The `KUBECONFIG` environment variable is a list of paths to configuration files. The list is
|
||||
colon-delimited for Linux and Mac, and semicolon-delimited for Windows. If you have
|
||||
a `KUBECONFIG` environment variable, familiarize yourself with the configuration files
|
||||
in the list.
|
||||
|
||||
Temporarily append two paths to your `KUBECONFIG` environment variable. For example, on Linux:
|
||||
|
||||
```shell
|
||||
export KUBECONFIG=$KUBECONFIG:config-demo:config-demo-2
|
||||
```
|
||||
|
||||
In your `config-exercise` directory, enter this command:
|
||||
|
||||
```shell
|
||||
kubectl config view
|
||||
```
|
||||
|
||||
The output shows merged information from all the files listed in your `KUBECONFIG`
|
||||
environment variable. In particular, notice that the merged information has the
|
||||
`dev-ramp-up` context from the `config-demo-2` file and the three contexts from
|
||||
the `config-demo` file:
|
||||
|
||||
```shell
|
||||
contexts:
|
||||
- context:
|
||||
cluster: development
|
||||
namespace: frontend
|
||||
user: developer
|
||||
name: dev-frontend
|
||||
- context:
|
||||
cluster: development
|
||||
namespace: ramp
|
||||
user: developer
|
||||
name: dev-ramp-up
|
||||
- context:
|
||||
cluster: development
|
||||
namespace: storage
|
||||
user: developer
|
||||
name: dev-storage
|
||||
- context:
|
||||
cluster: scratch
|
||||
namespace: default
|
||||
user: experimenter
|
||||
name: exp-scratch
|
||||
```
|
||||
|
||||
For more information about how kubeconfig files are merged, see
|
||||
[Organizing Cluster Access Using kubeconfig Files](/docs/concepts/configuration/organize-cluster-access-kubeconfig/)
|
||||
|
||||
## Explore the $HOME/.kube directory
|
||||
|
||||
If you already have a cluster, and you can use `kubectl` to interact with
|
||||
the cluster, then you probably have a file named `config` in the `$HOME/.kube`
|
||||
directory.
|
||||
|
||||
Go to `$HOME/.kube`, and see what files are there. Typically, there is a file named
|
||||
`config`. There might also be other configuration files in this directory. Briefly
|
||||
familiarize yourself with the contents of these files.
|
||||
|
||||
## Append $HOME/.kube/config to your KUBECONFIG environment variable
|
||||
|
||||
If you have a `$HOME/.kube/config` file, and it's not already listed in your
|
||||
`KUBECONFIG` environment variable, append it to your `KUBECONFIG` environment variable now.
|
||||
For example, on Linux:
|
||||
|
||||
```shell
|
||||
export KUBECONFIG=$KUBECONFIG:$HOME/.kube/config
|
||||
```
|
||||
|
||||
View configuration information merged from all the files that are now listed
|
||||
in your `KUBECONFIG` environment variable. In your config-exercise directory, enter:
|
||||
|
||||
```shell
|
||||
kubectl config view
|
||||
```
|
||||
|
||||
## Clean up
|
||||
|
||||
Return your `KUBECONFIG` environment variable to its original value. For example, on Linux:
|
||||
|
||||
```shell
|
||||
export KUBECONFIG=$KUBECONFIG_SAVED
|
||||
```
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture whatsnext %}}
|
||||
|
||||
* [Organizing Cluster Access Using kubeconfig Files](/docs/concepts/configuration/organize-cluster-access-kubeconfig/)
|
||||
* [kubectl config](/docs/reference/generated/kubectl/kubectl-commands/)
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
---
|
||||
reviewers:
|
||||
- bprashanth
|
||||
- davidopp
|
||||
title: Configure Your Cloud Provider's Firewalls
|
||||
---
|
||||
|
||||
Many cloud providers (e.g. Google Compute Engine) define firewalls that help prevent inadvertent
|
||||
exposure to the internet. When exposing a service to the external world, you may need to open up
|
||||
one or more ports in these firewalls to serve traffic. This document describes this process, as
|
||||
well as any provider specific details that may be necessary.
|
||||
|
||||
### Restrict Access For LoadBalancer Service
|
||||
|
||||
When using a Service with `spec.type: LoadBalancer`, you can specify the IP ranges that are allowed to access the load balancer
|
||||
by using `spec.loadBalancerSourceRanges`. This field takes a list of IP CIDR ranges, which Kubernetes will use to configure firewall exceptions.
|
||||
This feature is currently supported on Google Compute Engine, Google Kubernetes Engine and AWS. This field will be ignored if the cloud provider does not support the feature.
|
||||
|
||||
Assuming 10.0.0.0/8 is the internal subnet. In the following example, a load balancer will be created that is only accessible to cluster internal IPs.
|
||||
This will not allow clients from outside of your Kubernetes cluster to access the load balancer.
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: myapp
|
||||
spec:
|
||||
ports:
|
||||
- port: 8765
|
||||
targetPort: 9376
|
||||
selector:
|
||||
app: example
|
||||
type: LoadBalancer
|
||||
loadBalancerSourceRanges:
|
||||
- 10.0.0.0/8
|
||||
```
|
||||
|
||||
In the following example, a load balancer will be created that is only accessible to clients with IP addresses from 130.211.204.1 and 130.211.204.2.
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: myapp
|
||||
spec:
|
||||
ports:
|
||||
- port: 8765
|
||||
targetPort: 9376
|
||||
selector:
|
||||
app: example
|
||||
type: LoadBalancer
|
||||
loadBalancerSourceRanges:
|
||||
- 130.211.204.1/32
|
||||
- 130.211.204.2/32
|
||||
```
|
||||
|
||||
### Google Compute Engine
|
||||
|
||||
When using a Service with `spec.type: LoadBalancer`, the firewall will be
|
||||
opened automatically. When using `spec.type: NodePort`, however, the firewall
|
||||
is *not* opened by default.
|
||||
|
||||
Google Compute Engine firewalls are documented [elsewhere](https://cloud.google.com/compute/docs/networking#firewalls_1).
|
||||
|
||||
You can add a firewall with the `gcloud` command line tool:
|
||||
|
||||
```shell
|
||||
gcloud compute firewall-rules create my-rule --allow=tcp:<port>
|
||||
```
|
||||
|
||||
**Note**
|
||||
There is one important security note when using firewalls on Google Compute Engine:
|
||||
|
||||
as of Kubernetes v1.0.0, GCE firewalls are defined per-vm, rather than per-ip
|
||||
address. This means that when you open a firewall for a service's ports,
|
||||
anything that serves on that port on that VM's host IP address may potentially
|
||||
serve traffic. Note that this is not a problem for other Kubernetes services,
|
||||
as they listen on IP addresses that are different than the host node's external
|
||||
IP address.
|
||||
|
||||
Consider:
|
||||
|
||||
* You create a Service with an external load balancer (IP Address 1.2.3.4)
|
||||
and port 80
|
||||
* You open the firewall for port 80 for all nodes in your cluster, so that
|
||||
the external Service actually can deliver packets to your Service
|
||||
* You start an nginx server, running on port 80 on the host virtual machine
|
||||
(IP Address 2.3.4.5). This nginx is also exposed to the internet on
|
||||
the VM's external IP address.
|
||||
|
||||
Consequently, please be careful when opening firewalls in Google Compute Engine
|
||||
or Google Kubernetes Engine. You may accidentally be exposing other services to
|
||||
the wilds of the internet.
|
||||
|
||||
This will be fixed in an upcoming release of Kubernetes.
|
||||
|
||||
### Other cloud providers
|
||||
|
||||
Coming soon.
|
||||
@@ -0,0 +1,205 @@
|
||||
---
|
||||
title: Connect a Front End to a Back End Using a Service
|
||||
content_template: templates/tutorial
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
|
||||
This task shows how to create a frontend and a backend
|
||||
microservice. The backend microservice is a hello greeter. The
|
||||
frontend and backend are connected using a Kubernetes Service object.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture objectives %}}
|
||||
|
||||
* Create and run a microservice using a Deployment object.
|
||||
* Route traffic to the backend using a frontend.
|
||||
* Use a Service object to connect the frontend application to the
|
||||
backend application.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture prerequisites %}}
|
||||
|
||||
* {{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
|
||||
|
||||
* This task uses
|
||||
[Services with external load balancers](/docs/tasks/access-application-cluster/create-external-load-balancer/), which
|
||||
require a supported environment. If your environment does not
|
||||
support this, you can use a Service of type
|
||||
[NodePort](/docs/concepts/services-networking/service/#type-nodeport) instead.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture lessoncontent %}}
|
||||
|
||||
### Creating the backend using a Deployment
|
||||
|
||||
The backend is a simple hello greeter microservice. Here is the configuration
|
||||
file for the backend Deployment:
|
||||
|
||||
{{< code file="hello.yaml" >}}
|
||||
|
||||
Create the backend Deployment:
|
||||
|
||||
```
|
||||
kubectl create -f https://k8s.io/docs/tasks/access-application-cluster/hello.yaml
|
||||
```
|
||||
|
||||
View information about the backend Deployment:
|
||||
|
||||
```
|
||||
kubectl describe deployment hello
|
||||
```
|
||||
|
||||
The output is similar to this:
|
||||
|
||||
```
|
||||
Name: hello
|
||||
Namespace: default
|
||||
CreationTimestamp: Mon, 24 Oct 2016 14:21:02 -0700
|
||||
Labels: app=hello
|
||||
tier=backend
|
||||
track=stable
|
||||
Annotations: deployment.kubernetes.io/revision=1
|
||||
Selector: app=hello,tier=backend,track=stable
|
||||
Replicas: 7 desired | 7 updated | 7 total | 7 available | 0 unavailable
|
||||
StrategyType: RollingUpdate
|
||||
MinReadySeconds: 0
|
||||
RollingUpdateStrategy: 1 max unavailable, 1 max surge
|
||||
Pod Template:
|
||||
Labels: app=hello
|
||||
tier=backend
|
||||
track=stable
|
||||
Containers:
|
||||
hello:
|
||||
Image: "gcr.io/google-samples/hello-go-gke:1.0"
|
||||
Port: 80/TCP
|
||||
Environment: <none>
|
||||
Mounts: <none>
|
||||
Volumes: <none>
|
||||
Conditions:
|
||||
Type Status Reason
|
||||
---- ------ ------
|
||||
Available True MinimumReplicasAvailable
|
||||
Progressing True NewReplicaSetAvailable
|
||||
OldReplicaSets: <none>
|
||||
NewReplicaSet: hello-3621623197 (7/7 replicas created)
|
||||
Events:
|
||||
...
|
||||
```
|
||||
|
||||
### Creating the backend Service object
|
||||
|
||||
The key to connecting a frontend to a backend is the backend
|
||||
Service. A Service creates a persistent IP address and DNS name entry
|
||||
so that the backend microservice can always be reached. A Service uses
|
||||
selector labels to find the Pods that it routes traffic to.
|
||||
|
||||
First, explore the Service configuration file:
|
||||
|
||||
{{< code file="hello-service.yaml" >}}
|
||||
|
||||
In the configuration file, you can see that the Service routes traffic to Pods
|
||||
that have the labels `app: hello` and `tier: backend`.
|
||||
|
||||
Create the `hello` Service:
|
||||
|
||||
```
|
||||
kubectl create -f https://k8s.io/docs/tasks/access-application-cluster/hello-service.yaml
|
||||
```
|
||||
|
||||
At this point, you have a backend Deployment running, and you have a
|
||||
Service that can route traffic to it.
|
||||
|
||||
### Creating the frontend
|
||||
|
||||
Now that you have your backend, you can create a frontend that connects to the backend.
|
||||
The frontend connects to the backend worker Pods by using the DNS name
|
||||
given to the backend Service. The DNS name is "hello", which is the value
|
||||
of the `name` field in the preceding Service configuration file.
|
||||
|
||||
The Pods in the frontend Deployment run an nginx image that is configured
|
||||
to find the hello backend Service. Here is the nginx configuration file:
|
||||
|
||||
{{< code file="frontend/frontend.conf" >}}
|
||||
|
||||
Similar to the backend, the frontend has a Deployment and a Service. The
|
||||
configuration for the Service has `type: LoadBalancer`, which means that
|
||||
the Service uses the default load balancer of your cloud provider.
|
||||
|
||||
{{< code file="frontend.yaml" >}}
|
||||
|
||||
Create the frontend Deployment and Service:
|
||||
|
||||
```
|
||||
kubectl create -f https://k8s.io/docs/tasks/access-application-cluster/frontend.yaml
|
||||
```
|
||||
|
||||
The output verifies that both resources were created:
|
||||
|
||||
```
|
||||
deployment "frontend" created
|
||||
service "frontend" created
|
||||
```
|
||||
|
||||
**Note**: The nginx configuration is baked into the
|
||||
[container image](/docs/tasks/access-application-cluster/frontend/Dockerfile).
|
||||
A better way to do this would be to use a
|
||||
[ConfigMap](/docs/tasks/configure-pod-container/configure-pod-configmap/), so
|
||||
that you can change the configuration more easily.
|
||||
|
||||
### Interact with the frontend Service
|
||||
|
||||
Once you’ve created a Service of type LoadBalancer, you can use this
|
||||
command to find the external IP:
|
||||
|
||||
```
|
||||
kubectl get service frontend
|
||||
```
|
||||
|
||||
The external IP field may take some time to populate. If this is the
|
||||
case, the external IP is listed as `<pending>`.
|
||||
|
||||
```
|
||||
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
frontend 10.51.252.116 <pending> 80/TCP 10s
|
||||
```
|
||||
|
||||
Repeat the same command again until it shows an external IP address:
|
||||
|
||||
```
|
||||
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
frontend 10.51.252.116 XXX.XXX.XXX.XXX 80/TCP 1m
|
||||
```
|
||||
|
||||
### Send traffic through the frontend
|
||||
|
||||
The frontend and backends are now connected. You can hit the endpoint
|
||||
by using the curl command on the external IP of your frontend Service.
|
||||
|
||||
```
|
||||
curl http://<EXTERNAL-IP>
|
||||
```
|
||||
|
||||
The output shows the message generated by the backend:
|
||||
|
||||
```
|
||||
{"message":"Hello"}
|
||||
```
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture whatsnext %}}
|
||||
|
||||
* Learn more about [Services](/docs/concepts/services-networking/service/)
|
||||
* Learn more about [ConfigMaps](/docs/tasks/configure-pod-container/configure-pod-configmap/)
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
---
|
||||
title: Create an External Load Balancer
|
||||
content_template: templates/task
|
||||
---
|
||||
|
||||
|
||||
{{% capture overview %}}
|
||||
|
||||
This page shows how to create an External Load Balancer.
|
||||
|
||||
When creating a service, you have the option of automatically creating a
|
||||
cloud network load balancer. This provides an externally-accessible IP address
|
||||
that sends traffic to the correct port on your cluster nodes
|
||||
_provided your cluster runs in a supported environment and is configured with
|
||||
the correct cloud load balancer provider package_.
|
||||
|
||||
For information on provisioning and using an Ingress resource that can give
|
||||
services externally-reachable URLs, load balance the traffic, terminate SSL etc.,
|
||||
please check the [Ingress](/docs/concepts/services-networking/ingress/)
|
||||
documentation.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture prerequisites %}}
|
||||
|
||||
* {{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture steps %}}
|
||||
|
||||
## Configuration file
|
||||
|
||||
To create an external load balancer, add the following line to your
|
||||
[service configuration file](/docs/concepts/services-networking/service/#type-loadbalancer):
|
||||
|
||||
```json
|
||||
"type": "LoadBalancer"
|
||||
```
|
||||
|
||||
Your configuration file might look like:
|
||||
|
||||
```json
|
||||
{
|
||||
"kind": "Service",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "example-service"
|
||||
},
|
||||
"spec": {
|
||||
"ports": [{
|
||||
"port": 8765,
|
||||
"targetPort": 9376
|
||||
}],
|
||||
"selector": {
|
||||
"app": "example"
|
||||
},
|
||||
"type": "LoadBalancer"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Using kubectl
|
||||
|
||||
You can alternatively create the service with the `kubectl expose` command and
|
||||
its `--type=LoadBalancer` flag:
|
||||
|
||||
```bash
|
||||
kubectl expose rc example --port=8765 --target-port=9376 \
|
||||
--name=example-service --type=LoadBalancer
|
||||
```
|
||||
|
||||
This command creates a new service using the same selectors as the referenced
|
||||
resource (in the case of the example above, a replication controller named
|
||||
`example`).
|
||||
|
||||
For more information, including optional flags, refer to the
|
||||
[`kubectl expose` reference](/docs/reference/generated/kubectl/kubectl-commands/#expose).
|
||||
|
||||
## Finding your IP address
|
||||
|
||||
You can find the IP address created for your service by getting the service
|
||||
information through `kubectl`:
|
||||
|
||||
```bash
|
||||
kubectl describe services example-service
|
||||
```
|
||||
|
||||
which should produce output like this:
|
||||
|
||||
```bash
|
||||
Name: example-service
|
||||
Namespace: default
|
||||
Labels: <none>
|
||||
Annotations: <none>
|
||||
Selector: app=example
|
||||
Type: LoadBalancer
|
||||
IP: 10.67.252.103
|
||||
LoadBalancer Ingress: 123.45.678.9
|
||||
Port: <unnamed> 80/TCP
|
||||
NodePort: <unnamed> 32445/TCP
|
||||
Endpoints: 10.64.0.4:80,10.64.1.5:80,10.64.2.4:80
|
||||
Session Affinity: None
|
||||
Events: <none>
|
||||
```
|
||||
|
||||
The IP address is listed next to `LoadBalancer Ingress`.
|
||||
|
||||
{{< note >}}
|
||||
**Note**: If you are running your service on Minikube, you can find the assigned IP address and port with:
|
||||
{{< /note >}}
|
||||
```bash
|
||||
minikube service example-service --url
|
||||
```
|
||||
|
||||
## Preserving the client source IP
|
||||
|
||||
Due to the implementation of this feature, the source IP seen in the target
|
||||
container will *not be the original source IP* of the client. To enable
|
||||
preservation of the client IP, the following fields can be configured in the
|
||||
service spec (supported in GCE/Google Kubernetes Engine environments):
|
||||
|
||||
* `service.spec.externalTrafficPolicy` - denotes if this Service desires to route
|
||||
external traffic to node-local or cluster-wide endpoints. There are two available
|
||||
options: "Cluster" (default) and "Local". "Cluster" obscures the client source
|
||||
IP and may cause a second hop to another node, but should have good overall
|
||||
load-spreading. "Local" preserves the client source IP and avoids a second hop
|
||||
for LoadBalancer and NodePort type services, but risks potentially imbalanced
|
||||
traffic spreading.
|
||||
* `service.spec.healthCheckNodePort` - specifies the healthcheck nodePort
|
||||
(numeric port number) for the service. If not specified, healthCheckNodePort is
|
||||
created by the service API backend with the allocated nodePort. It will use the
|
||||
user-specified nodePort value if specified by the client. It only has an
|
||||
effect when type is set to "LoadBalancer" and externalTrafficPolicy is set
|
||||
to "Local".
|
||||
|
||||
This feature can be activated by setting `externalTrafficPolicy` to "Local" in the
|
||||
Service Configuration file.
|
||||
|
||||
```json
|
||||
{
|
||||
"kind": "Service",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "example-service"
|
||||
},
|
||||
"spec": {
|
||||
"ports": [{
|
||||
"port": 8765,
|
||||
"targetPort": 9376
|
||||
}],
|
||||
"selector": {
|
||||
"app": "example"
|
||||
},
|
||||
"type": "LoadBalancer",
|
||||
"externalTrafficPolicy": "Local"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Feature availability
|
||||
|
||||
| k8s version | Feature support |
|
||||
| :---------: |:-----------:|
|
||||
| 1.7+ | Supports the full API fields |
|
||||
| 1.5 - 1.6 | Supports Beta Annotations |
|
||||
| <1.5 | Unsupported |
|
||||
|
||||
Below you could find the deprecated Beta annotations used to enable this feature
|
||||
prior to its stable version. Newer Kubernetes versions may stop supporting these
|
||||
after v1.7. Please update existing applications to use the fields directly.
|
||||
|
||||
* `service.beta.kubernetes.io/external-traffic` annotation <-> `service.spec.externalTrafficPolicy` field
|
||||
* `service.beta.kubernetes.io/healthcheck-nodeport` annotation <-> `service.spec.healthCheckNodePort` field
|
||||
|
||||
`service.beta.kubernetes.io/external-traffic` annotation has a different set of values
|
||||
compared to the `service.spec.externalTrafficPolicy` field. The values match as follows:
|
||||
|
||||
* "OnlyLocal" for annotation <-> "Local" for field
|
||||
* "Global" for annotation <-> "Cluster" for field
|
||||
|
||||
**Note that this feature is not currently implemented for all cloudproviders/environments.**
|
||||
|
||||
Known issues:
|
||||
|
||||
* AWS: [kubernetes/kubernetes#35758](https://github.com/kubernetes/kubernetes/issues/35758)
|
||||
* Weave-Net: [weaveworks/weave/#2924](https://github.com/weaveworks/weave/issues/2924)
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture discussion %}}
|
||||
|
||||
## External Load Balancer Providers
|
||||
|
||||
It is important to note that the datapath for this functionality is provided by a load balancer external to the Kubernetes cluster.
|
||||
|
||||
When the service type is set to `LoadBalancer`, Kubernetes provides functionality equivalent to `type=<ClusterIP>` to pods within the cluster and extends it by programming the (external to Kubernetes) load balancer with entries for the Kubernetes pods. The Kubernetes service controller automates the creation of the external load balancer, health checks (if needed), firewall rules (if needed) and retrieves the external IP allocated by the cloud provider and populates it in the service object.
|
||||
|
||||
## Caveats and Limitations when preserving source IPs
|
||||
|
||||
GCE/AWS load balancers do not provide weights for their target pools. This was not an issue with the old LB
|
||||
kube-proxy rules which would correctly balance across all endpoints.
|
||||
|
||||
With the new functionality, the external traffic will not be equally load balanced across pods, but rather
|
||||
equally balanced at the node level (because GCE/AWS and other external LB implementations do not have the ability
|
||||
for specifying the weight per node, they balance equally across all target nodes, disregarding the number of
|
||||
pods on each node).
|
||||
|
||||
We can, however, state that for NumServicePods << NumNodes or NumServicePods >> NumNodes, a fairly close-to-equal
|
||||
distribution will be seen, even without weights.
|
||||
|
||||
Once the external load balancers provide weights, this functionality can be added to the LB programming path.
|
||||
*Future Work: No support for weights is provided for the 1.4 release, but may be added at a future date*
|
||||
|
||||
Internal pod to pod traffic should behave similar to ClusterIP services, with equal probability across all pods.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: frontend
|
||||
spec:
|
||||
selector:
|
||||
app: hello
|
||||
tier: frontend
|
||||
ports:
|
||||
- protocol: "TCP"
|
||||
port: 80
|
||||
targetPort: 80
|
||||
type: LoadBalancer
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: frontend
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: hello
|
||||
tier: frontend
|
||||
track: stable
|
||||
replicas: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: hello
|
||||
tier: frontend
|
||||
track: stable
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: "gcr.io/google-samples/hello-frontend:1.0"
|
||||
lifecycle:
|
||||
preStop:
|
||||
exec:
|
||||
command: ["/usr/sbin/nginx","-s","quit"]
|
||||
@@ -0,0 +1,4 @@
|
||||
FROM nginx:1.9.14
|
||||
|
||||
RUN rm /etc/nginx/conf.d/default.conf
|
||||
COPY frontend.conf /etc/nginx/conf.d
|
||||
@@ -0,0 +1,11 @@
|
||||
upstream hello {
|
||||
server hello;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
|
||||
location / {
|
||||
proxy_pass http://hello;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: hello
|
||||
spec:
|
||||
selector:
|
||||
app: hello
|
||||
tier: backend
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: http
|
||||
@@ -0,0 +1,24 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: hello
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: hello
|
||||
tier: backend
|
||||
track: stable
|
||||
replicas: 7
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: hello
|
||||
tier: backend
|
||||
track: stable
|
||||
spec:
|
||||
containers:
|
||||
- name: hello
|
||||
image: "gcr.io/google-samples/hello-go-gke:1.0"
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
@@ -0,0 +1,4 @@
|
||||
FROM alpine:3.1
|
||||
MAINTAINER Carter Morgan <askcarter@google.com>
|
||||
COPY hello /usr/bin/
|
||||
CMD ["/usr/bin/hello"]
|
||||
@@ -0,0 +1,7 @@
|
||||
Build hello go binary first
|
||||
|
||||
go build -tags netgo -ldflags "-extldflags '-lm -lstdc++ -static'" .
|
||||
|
||||
Then build docker image
|
||||
|
||||
docker build -t hello .
|
||||
@@ -0,0 +1,74 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/braintree/manners"
|
||||
"github.com/GoogleCloudPlatform/kubernetes-workshops/bundles/kubernetes-101/workshop/app/handlers"
|
||||
"github.com/GoogleCloudPlatform/kubernetes-workshops/bundles/kubernetes-101/workshop/app/health"
|
||||
)
|
||||
|
||||
const version = "1.0.0"
|
||||
|
||||
func main() {
|
||||
var (
|
||||
httpAddr = flag.String("http", "0.0.0.0:80", "HTTP service address.")
|
||||
healthAddr = flag.String("health", "0.0.0.0:81", "Health service address.")
|
||||
)
|
||||
flag.Parse()
|
||||
|
||||
log.Println("Starting server...")
|
||||
log.Printf("Health service listening on %s", *healthAddr)
|
||||
log.Printf("HTTP service listening on %s", *httpAddr)
|
||||
|
||||
errChan := make(chan error, 10)
|
||||
|
||||
hmux := http.NewServeMux()
|
||||
hmux.HandleFunc("/healthz", health.HealthzHandler)
|
||||
hmux.HandleFunc("/readiness", health.ReadinessHandler)
|
||||
hmux.HandleFunc("/healthz/status", health.HealthzStatusHandler)
|
||||
hmux.HandleFunc("/readiness/status", health.ReadinessStatusHandler)
|
||||
healthServer := manners.NewServer()
|
||||
healthServer.Addr = *healthAddr
|
||||
healthServer.Handler = handlers.LoggingHandler(hmux)
|
||||
|
||||
go func() {
|
||||
errChan <- healthServer.ListenAndServe()
|
||||
}()
|
||||
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/", handlers.HelloHandler)
|
||||
mux.Handle("/secure", handlers.JWTAuthHandler(handlers.HelloHandler))
|
||||
mux.Handle("/version", handlers.VersionHandler(version))
|
||||
|
||||
httpServer := manners.NewServer()
|
||||
httpServer.Addr = *httpAddr
|
||||
httpServer.Handler = handlers.LoggingHandler(mux)
|
||||
|
||||
go func() {
|
||||
errChan <- httpServer.ListenAndServe()
|
||||
}()
|
||||
|
||||
signalChan := make(chan os.Signal, 1)
|
||||
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
for {
|
||||
select {
|
||||
case err := <-errChan:
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
case s := <-signalChan:
|
||||
log.Println(fmt.Sprintf("Captured %v. Exiting...", s))
|
||||
health.SetReadinessStatus(http.StatusServiceUnavailable)
|
||||
httpServer.BlockingClose()
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
---
|
||||
title: List All Container Images Running in a Cluster
|
||||
content_template: templates/task
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
|
||||
This page shows how to use kubectl to list all of the Container images
|
||||
for Pods running in a cluster.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture prerequisites %}}
|
||||
|
||||
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture steps %}}
|
||||
|
||||
In this exercise you will use kubectl to fetch all of the Pods
|
||||
running in a cluster, and format the output to pull out the list
|
||||
of Containers for each.
|
||||
|
||||
## List all Containers in all namespaces
|
||||
|
||||
- Fetch all Pods in all namespaces using `kubectl get pods --all-namespaces`
|
||||
- Format the output to include only the list of Container image names
|
||||
using `-o jsonpath={..image}`. This will recursively parse out the
|
||||
`image` field from the returned json.
|
||||
- See the [jsonpath reference](/docs/user-guide/jsonpath/)
|
||||
for further information on how to use jsonpath.
|
||||
- Format the output using standard tools: `tr`, `sort`, `uniq`
|
||||
- Use `tr` to replace spaces with newlines
|
||||
- Use `sort` to sort the results
|
||||
- Use `uniq` to aggregate image counts
|
||||
|
||||
```sh
|
||||
kubectl get pods --all-namespaces -o jsonpath="{..image}" |\
|
||||
tr -s '[[:space:]]' '\n' |\
|
||||
sort |\
|
||||
uniq -c
|
||||
```
|
||||
|
||||
The above command will recursively return all fields named `image`
|
||||
for all items returned.
|
||||
|
||||
As an alternative, it is possible to use the absolute path to the image
|
||||
field within the Pod. This ensures the correct field is retrieved
|
||||
even when the field name is repeated,
|
||||
e.g. many fields are called `name` within a given item:
|
||||
|
||||
```sh
|
||||
kubectl get pods --all-namespaces -o jsonpath="{.items[*].spec.containers[*].image}"
|
||||
```
|
||||
|
||||
The jsonpath is interpreted as follows:
|
||||
|
||||
- `.items[*]`: for each returned value
|
||||
- `.spec`: get the spec
|
||||
- `.containers[*]`: for each container
|
||||
- `.image`: get the image
|
||||
|
||||
**Note:** When fetching a single Pod by name, e.g. `kubectl get pod nginx`,
|
||||
the `.items[*]` portion of the path should be omitted because a single
|
||||
Pod is returned instead of a list of items.
|
||||
|
||||
## List Containers by Pod
|
||||
|
||||
The formatting can be controlled further by using the `range` operation to
|
||||
iterate over elements individually.
|
||||
|
||||
```sh
|
||||
kubectl get pods --all-namespaces -o=jsonpath='{range .items[*]}{"\n"}{.metadata.name}{":\t"}{range .spec.containers[*]}{.image}{", "}{end}{end}' |\
|
||||
sort
|
||||
```
|
||||
|
||||
## List Containers filtering by Pod label
|
||||
|
||||
To target only Pods matching a specific label, use the -l flag. The
|
||||
following matches only Pods with labels matching `app=nginx`.
|
||||
|
||||
```sh
|
||||
kubectl get pods --all-namespaces -o=jsonpath="{..image}" -l app=nginx
|
||||
```
|
||||
|
||||
## List Containers filtering by Pod namespace
|
||||
|
||||
To target only pods in a specific namespace, use the namespace flag. The
|
||||
following matches only Pods in the `kube-system` namespace.
|
||||
|
||||
```sh
|
||||
kubectl get pods --namespace kube-system -o jsonpath="{..image}"
|
||||
```
|
||||
|
||||
## List Containers using a go-template instead of jsonpath
|
||||
|
||||
As an alternative to jsonpath, Kubectl supports using [go-templates](https://golang.org/pkg/text/template/)
|
||||
for formatting the output:
|
||||
|
||||
|
||||
```sh
|
||||
kubectl get pods --all-namespaces -o go-template --template="{{range .items}}{{range .spec.containers}}{{.image}} {{end}}{{end}}"
|
||||
```
|
||||
|
||||
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture discussion %}}
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture whatsnext %}}
|
||||
|
||||
### Reference
|
||||
|
||||
* [Jsonpath](/docs/user-guide/jsonpath/) reference guide
|
||||
* [Go template](https://golang.org/pkg/text/template/) reference guide
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
---
|
||||
title: Provide Load-Balanced Access to an Application in a Cluster
|
||||
content_template: templates/tutorial
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
|
||||
This page shows how to create a Kubernetes Service object that provides
|
||||
load-balanced access to an application running in a cluster.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture prerequisites %}}
|
||||
|
||||
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture objectives %}}
|
||||
|
||||
* Run two instances of a Hello World application
|
||||
* Create a Service object
|
||||
* Use the Service object to access the running application
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture lessoncontent %}}
|
||||
|
||||
## Creating a Service for an application running in two pods
|
||||
|
||||
1. Run a Hello World application in your cluster:
|
||||
|
||||
kubectl run hello-world --replicas=2 --labels="run=load-balancer-example" --image=gcr.io/google-samples/node-hello:1.0 --port=8080
|
||||
|
||||
1. List the pods that are running the Hello World application:
|
||||
|
||||
kubectl get pods --selector="run=load-balancer-example"
|
||||
|
||||
The output is similar to this:
|
||||
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
hello-world-2189936611-8fyp0 1/1 Running 0 6m
|
||||
hello-world-2189936611-9isq8 1/1 Running 0 6m
|
||||
|
||||
1. List the replica set for the two Hello World pods:
|
||||
|
||||
kubectl get replicasets --selector="run=load-balancer-example"
|
||||
|
||||
The output is similar to this:
|
||||
|
||||
NAME DESIRED CURRENT AGE
|
||||
hello-world-2189936611 2 2 12m
|
||||
|
||||
1. Create a Service object that exposes the replica set:
|
||||
|
||||
kubectl expose rs <your-replica-set-name> --type="LoadBalancer" --name="example-service"
|
||||
|
||||
where `<your-replica-set-name>` is the name of your replica set.
|
||||
|
||||
1. Display the IP addresses for your service:
|
||||
|
||||
kubectl get services example-service
|
||||
|
||||
The output shows the internal IP address and the external IP address of
|
||||
your service. If the external IP address shows as `<pending>`, repeat the
|
||||
command.
|
||||
|
||||
Note: If you are using Minikube, you don't get an external IP address. The
|
||||
external IP address remains in the pending state.
|
||||
|
||||
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
example-service 10.0.0.160 <pending> 8080/TCP 40s
|
||||
|
||||
1. Use your Service object to access the Hello World application:
|
||||
|
||||
curl <your-external-ip-address>:8080
|
||||
|
||||
where `<your-external-ip-address>` is the external IP address of your
|
||||
service.
|
||||
|
||||
The output is a hello message from the application:
|
||||
|
||||
Hello Kubernetes!
|
||||
|
||||
Note: If you are using Minikube, enter these commands:
|
||||
|
||||
kubectl cluster-info
|
||||
kubectl describe services example-service
|
||||
|
||||
The output displays the IP address of your Minikube node and the NodePort
|
||||
value for your service. Then enter this command to access the Hello World
|
||||
application:
|
||||
|
||||
curl <minikube-node-ip-address>:<service-node-port>
|
||||
|
||||
where `<minikube-node-ip-address>` us the IP address of your Minikube node,
|
||||
and `<service-node-port>` is the NodePort value for your service.
|
||||
|
||||
## Using a service configuration file
|
||||
|
||||
As an alternative to using `kubectl expose`, you can use a
|
||||
[service configuration file](/docs/concepts/services-networking/service/)
|
||||
to create a Service.
|
||||
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture whatsnext %}}
|
||||
|
||||
Learn more about
|
||||
[connecting applications with services](/docs/concepts/services-networking/connect-applications-service/).
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
---
|
||||
title: Use Port Forwarding to Access Applications in a Cluster
|
||||
content_template: templates/task
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
|
||||
This page shows how to use `kubectl port-forward` to connect to a Redis
|
||||
server running in a Kubernetes cluster. This type of connection can be useful
|
||||
for database debugging.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture prerequisites %}}
|
||||
|
||||
* {{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
|
||||
|
||||
* Install [redis-cli](http://redis.io/topics/rediscli).
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture steps %}}
|
||||
|
||||
## Creating Redis deployment and service
|
||||
|
||||
1. Create a Redis deployment:
|
||||
|
||||
kubectl create -f https://k8s.io/docs/tutorials/stateless-application/guestbook/redis-master-deployment.yaml
|
||||
|
||||
The output of a successful command verifies that the deployment was created:
|
||||
|
||||
deployment "redis-master" created
|
||||
|
||||
When the pod is ready, you can get:
|
||||
|
||||
kubectl get pods
|
||||
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
redis-master-765d459796-258hz 1/1 Running 0 50s
|
||||
|
||||
kubectl get deployment
|
||||
|
||||
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
|
||||
redis-master 1 1 1 1 55s
|
||||
|
||||
kubectl get rs
|
||||
NAME DESIRED CURRENT READY AGE
|
||||
redis-master-765d459796 1 1 1 1m
|
||||
|
||||
|
||||
2. Create a Redis service:
|
||||
|
||||
kubectl create -f https://k8s.io/docs/tutorials/stateless-application/guestbook/redis-master-service.yaml
|
||||
|
||||
The output of a successful command verifies that the service was created:
|
||||
|
||||
service "redis-master" created
|
||||
|
||||
Check the service created:
|
||||
|
||||
kubectl get svc | grep redis
|
||||
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
redis-master ClusterIP 10.0.0.213 <none> 6379/TCP 27s
|
||||
|
||||
3. Verify that the Redis server is running in the pod and listening on port 6379:
|
||||
|
||||
|
||||
kubectl get pods redis-master-765d459796-258hz --template='{{(index (index .spec.containers 0).ports 0).containerPort}}{{"\n"}}'
|
||||
|
||||
|
||||
The output displays the port:
|
||||
|
||||
6379
|
||||
|
||||
|
||||
## Forward a local port to a port on the pod
|
||||
|
||||
1. `kubectl port-forward` allows using resource name, such as a service name, to select a matching pod to port forward to since Kubernetes v1.10.
|
||||
|
||||
kubectl port-forward redis-master-765d459796-258hz 6379:6379
|
||||
|
||||
which is the same as
|
||||
|
||||
kubectl port-forward pods/redis-master-765d459796-258hz 6379:6379
|
||||
|
||||
or
|
||||
|
||||
kubectl port-forward deployment/redis-master 6379:6379
|
||||
|
||||
or
|
||||
|
||||
kubectl port-forward rs/redis-master 6379:6379
|
||||
|
||||
or
|
||||
|
||||
kubectl port-forward svc/redis-master 6379:6379
|
||||
|
||||
Any of the above commands works. The output is similar to this:
|
||||
|
||||
I0710 14:43:38.274550 3655 portforward.go:225] Forwarding from 127.0.0.1:6379 -> 6379
|
||||
I0710 14:43:38.274797 3655 portforward.go:225] Forwarding from [::1]:6379 -> 6379
|
||||
|
||||
2. Start the Redis command line interface:
|
||||
|
||||
redis-cli
|
||||
|
||||
3. At the Redis command line prompt, enter the `ping` command:
|
||||
|
||||
127.0.0.1:6379>ping
|
||||
|
||||
A successful ping request returns PONG.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture discussion %}}
|
||||
|
||||
## Discussion
|
||||
|
||||
Connections made to local port 6379 are forwarded to port 6379 of the pod that
|
||||
is running the Redis server. With this connection in place you can use your
|
||||
local workstation to debug the database that is running in the pod.
|
||||
|
||||
{{< warning >}}
|
||||
**Warning**: Due to known limitations, port forward today only works for TCP protocol.
|
||||
The support to UDP protocol is being tracked in
|
||||
[issue 47862](https://github.com/kubernetes/kubernetes/issues/47862).
|
||||
{{< /warning >}}
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture whatsnext %}}
|
||||
Learn more about [kubectl port-forward](/docs/reference/generated/kubectl/kubectl-commands/#port-forward).
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
labels:
|
||||
name: redis
|
||||
redis-sentinel: "true"
|
||||
role: master
|
||||
name: redis-master
|
||||
spec:
|
||||
containers:
|
||||
- name: master
|
||||
image: k8s.gcr.io/redis:v1
|
||||
env:
|
||||
- name: MASTER
|
||||
value: "true"
|
||||
ports:
|
||||
- containerPort: 6379
|
||||
resources:
|
||||
limits:
|
||||
cpu: "0.1"
|
||||
volumeMounts:
|
||||
- mountPath: /redis-master-data
|
||||
name: data
|
||||
- name: sentinel
|
||||
image: kubernetes/redis:v1
|
||||
env:
|
||||
- name: SENTINEL
|
||||
value: "true"
|
||||
ports:
|
||||
- containerPort: 26379
|
||||
volumes:
|
||||
- name: data
|
||||
emptyDir: {}
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
---
|
||||
title: Use a Service to Access an Application in a Cluster
|
||||
content_template: templates/tutorial
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
|
||||
This page shows how to create a Kubernetes Service object that external
|
||||
clients can use to access an application running in a cluster. The Service
|
||||
provides load balancing for an application that has two running instances.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture prerequisites %}}
|
||||
|
||||
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture objectives %}}
|
||||
|
||||
* Run two instances of a Hello World application.
|
||||
* Create a Service object that exposes a node port.
|
||||
* Use the Service object to access the running application.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture lessoncontent %}}
|
||||
|
||||
## Creating a service for an application running in two pods
|
||||
|
||||
1. Run a Hello World application in your cluster:
|
||||
|
||||
kubectl run hello-world --replicas=2 --labels="run=load-balancer-example" --image=gcr.io/google-samples/node-hello:1.0 --port=8080
|
||||
|
||||
The preceding command creates a
|
||||
[Deployment](/docs/concepts/workloads/controllers/deployment/)
|
||||
object and an associated
|
||||
[ReplicaSet](/docs/concepts/workloads/controllers/replicaset/)
|
||||
object. The ReplicaSet has two
|
||||
[Pods](/docs/concepts/workloads/pods/pod/),
|
||||
each of which runs the Hello World application.
|
||||
|
||||
1. Display information about the Deployment:
|
||||
|
||||
kubectl get deployments hello-world
|
||||
kubectl describe deployments hello-world
|
||||
|
||||
1. Display information about your ReplicaSet objects:
|
||||
|
||||
kubectl get replicasets
|
||||
kubectl describe replicasets
|
||||
|
||||
1. Create a Service object that exposes the deployment:
|
||||
|
||||
kubectl expose deployment hello-world --type=NodePort --name=example-service
|
||||
|
||||
1. Display information about the Service:
|
||||
|
||||
kubectl describe services example-service
|
||||
|
||||
The output is similar to this:
|
||||
|
||||
Name: example-service
|
||||
Namespace: default
|
||||
Labels: run=load-balancer-example
|
||||
Annotations: <none>
|
||||
Selector: run=load-balancer-example
|
||||
Type: NodePort
|
||||
IP: 10.32.0.16
|
||||
Port: <unset> 8080/TCP
|
||||
TargetPort: 8080/TCP
|
||||
NodePort: <unset> 31496/TCP
|
||||
Endpoints: 10.200.1.4:8080,10.200.2.5:8080
|
||||
Session Affinity: None
|
||||
Events: <none>
|
||||
|
||||
Make a note of the NodePort value for the service. For example,
|
||||
in the preceding output, the NodePort value is 31496.
|
||||
|
||||
1. List the pods that are running the Hello World application:
|
||||
|
||||
kubectl get pods --selector="run=load-balancer-example" --output=wide
|
||||
|
||||
The output is similar to this:
|
||||
|
||||
NAME READY STATUS ... IP NODE
|
||||
hello-world-2895499144-bsbk5 1/1 Running ... 10.200.1.4 worker1
|
||||
hello-world-2895499144-m1pwt 1/1 Running ... 10.200.2.5 worker2
|
||||
|
||||
1. Get the public IP address of one of your nodes that is running
|
||||
a Hello World pod. How you get this address depends on how you set
|
||||
up your cluster. For example, if you are using Minikube, you can
|
||||
see the node address by running `kubectl cluster-info`. If you are
|
||||
using Google Compute Engine instances, you can use the
|
||||
`gcloud compute instances list` command to see the public addresses of your
|
||||
nodes. For more information about this command, see the [GCE documentation](https://cloud.google.com/sdk/gcloud/reference/compute/instances/list).
|
||||
|
||||
1. On your chosen node, create a firewall rule that allows TCP traffic
|
||||
on your node port. For example, if your Service has a NodePort value of
|
||||
31568, create a firewall rule that allows TCP traffic on port 31568. Different
|
||||
cloud providers offer different ways of configuring firewall rules. See [the
|
||||
GCE documentation on firewall rules](https://cloud.google.com/compute/docs/vpc/firewalls),
|
||||
for example.
|
||||
|
||||
1. Use the node address and node port to access the Hello World application:
|
||||
|
||||
curl http://<public-node-ip>:<node-port>
|
||||
|
||||
where `<public-node-ip>` is the public IP address of your node,
|
||||
and `<node-port>` is the NodePort value for your service.
|
||||
|
||||
The response to a successful request is a hello message:
|
||||
|
||||
Hello Kubernetes!
|
||||
|
||||
## Using a service configuration file
|
||||
|
||||
As an alternative to using `kubectl expose`, you can use a
|
||||
[service configuration file](/docs/concepts/services-networking/service/)
|
||||
to create a Service.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture cleanup %}}
|
||||
|
||||
To delete the Service, enter this command:
|
||||
|
||||
kubectl delete services example-service
|
||||
|
||||
To delete the Deployment, the ReplicaSet, and the Pods that are running
|
||||
the Hello World application, enter this command:
|
||||
|
||||
kubectl delete deployment hello-world
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture whatsnext %}}
|
||||
|
||||
Learn more about
|
||||
[connecting applications with services](/docs/concepts/services-networking/connect-applications-service/).
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: two-containers
|
||||
spec:
|
||||
|
||||
restartPolicy: Never
|
||||
|
||||
volumes:
|
||||
- name: shared-data
|
||||
emptyDir: {}
|
||||
|
||||
containers:
|
||||
|
||||
- name: nginx-container
|
||||
image: nginx
|
||||
volumeMounts:
|
||||
- name: shared-data
|
||||
mountPath: /usr/share/nginx/html
|
||||
|
||||
- name: debian-container
|
||||
image: debian
|
||||
volumeMounts:
|
||||
- name: shared-data
|
||||
mountPath: /pod-data
|
||||
command: ["/bin/sh"]
|
||||
args: ["-c", "echo Hello from the debian container > /pod-data/index.html"]
|
||||
@@ -0,0 +1,170 @@
|
||||
---
|
||||
reviewers:
|
||||
- bryk
|
||||
- mikedanese
|
||||
- rf232
|
||||
title: Web UI (Dashboard)
|
||||
---
|
||||
|
||||
Dashboard is a web-based Kubernetes user interface. You can use Dashboard to deploy containerized applications to a Kubernetes cluster, troubleshoot your containerized application, and manage the cluster itself along with its attendant resources. You can use Dashboard to get an overview of applications running on your cluster, as well as for creating or modifying individual Kubernetes resources (such as Deployments, Jobs, DaemonSets, etc). For example, you can scale a Deployment, initiate a rolling update, restart a pod or deploy new applications using a deploy wizard.
|
||||
|
||||
Dashboard also provides information on the state of Kubernetes resources in your cluster, and on any errors that may have occurred.
|
||||
|
||||

|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Deploying the Dashboard UI
|
||||
|
||||
The Dashboard UI is not deployed by default. To deploy it, run the following command:
|
||||
|
||||
```
|
||||
kubectl create -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml
|
||||
```
|
||||
|
||||
## Accessing the Dashboard UI
|
||||
|
||||
There are multiple ways you can access the Dashboard UI; either by using the kubectl command-line interface, or by accessing the Kubernetes master apiserver using your web browser.
|
||||
|
||||
### Command line proxy
|
||||
You can access Dashboard using the kubectl command-line tool by running the following command:
|
||||
|
||||
```
|
||||
kubectl proxy
|
||||
```
|
||||
|
||||
Kubectl will handle authentication with apiserver and make Dashboard available at http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/.
|
||||
|
||||
The UI can _only_ be accessed from the machine where the command is executed. See `kubectl proxy --help` for more options.
|
||||
|
||||
### Master server
|
||||
You may access the UI directly via the Kubernetes master apiserver. Open a browser and navigate to ``https://<master-ip>:<apiserver-port>/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/``, where `<kubernetes-master>` is IP address or domain name of the Kubernetes
|
||||
master.
|
||||
|
||||
Please note, this works only if the apiserver is set up to allow authentication with username and password. This is not currently the case with some setup tools (e.g., `kubeadm`). Refer to the [authentication admin documentation](/docs/admin/authentication/) for information on how to configure authentication manually.
|
||||
|
||||
If the username and password are configured but unknown to you, then use `kubectl config view` to find it.
|
||||
|
||||
## Welcome view
|
||||
|
||||
When you access Dashboard on an empty cluster, you'll see the welcome page. This page contains a link to this document as well as a button to deploy your first application. In addition, you can view which system applications are running by default in the `kube-system` [namespace](/docs/tasks/administer-cluster/namespaces/) of your cluster, for example the Dashboard itself.
|
||||
|
||||

|
||||
|
||||
## Deploying containerized applications
|
||||
|
||||
Dashboard lets you create and deploy a containerized application as a Deployment and optional Service with a simple wizard. You can either manually specify application details, or upload a YAML or JSON file containing application configuration.
|
||||
|
||||
To access the deploy wizard from the Welcome page, click the respective button. To access the wizard at a later point in time, click the **CREATE** button in the upper right corner of any page.
|
||||
|
||||

|
||||
|
||||
### Specifying application details
|
||||
|
||||
The deploy wizard expects that you provide the following information:
|
||||
|
||||
- **App name** (mandatory): Name for your application. A [label](/docs/concepts/overview/working-with-objects/labels/) with the name will be added to the Deployment and Service, if any, that will be deployed.
|
||||
|
||||
The application name must be unique within the selected Kubernetes [namespace](/docs/tasks/administer-cluster/namespaces/). It must start with a lowercase character, and end with a lowercase character or a number, and contain only lowercase letters, numbers and dashes (-). It is limited to 24 characters. Leading and trailing spaces are ignored.
|
||||
|
||||
- **Container image** (mandatory): The URL of a public Docker [container image](/docs/concepts/containers/images/) on any registry, or a private image (commonly hosted on the Google Container Registry or Docker Hub). The container image specification must end with a colon.
|
||||
|
||||
- **Number of pods** (mandatory): The target number of Pods you want your application to be deployed in. The value must be a positive integer.
|
||||
|
||||
A [Deployment](/docs/concepts/workloads/controllers/deployment/) will be created to maintain the desired number of Pods across your cluster.
|
||||
|
||||
- **Service** (optional): For some parts of your application (e.g. frontends) you may want to expose a [Service](/docs/concepts/services-networking/service/) onto an external, maybe public IP address outside of your cluster (external Service). For external Services, you may need to open up one or more ports to do so. Find more details [here](/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/).
|
||||
|
||||
Other Services that are only visible from inside the cluster are called internal Services.
|
||||
|
||||
Irrespective of the Service type, if you choose to create a Service and your container listens on a port (incoming), you need to specify two ports. The Service will be created mapping the port (incoming) to the target port seen by the container. This Service will route to your deployed Pods. Supported protocols are TCP and UDP. The internal DNS name for this Service will be the value you specified as application name above.
|
||||
|
||||
If needed, you can expand the **Advanced options** section where you can specify more settings:
|
||||
|
||||
- **Description**: The text you enter here will be added as an [annotation](/docs/concepts/overview/working-with-objects/annotations/) to the Deployment and displayed in the application's details.
|
||||
|
||||
- **Labels**: Default [labels](/docs/concepts/overview/working-with-objects/labels/) to be used for your application are application name and version. You can specify additional labels to be applied to the Deployment, Service (if any), and Pods, such as release, environment, tier, partition, and release track.
|
||||
|
||||
Example:
|
||||
|
||||
```conf
|
||||
release=1.0
|
||||
tier=frontend
|
||||
environment=pod
|
||||
track=stable
|
||||
```
|
||||
|
||||
- **Namespace**: Kubernetes supports multiple virtual clusters backed by the same physical cluster. These virtual clusters are called [namespaces](/docs/tasks/administer-cluster/namespaces/). They let you partition resources into logically named groups.
|
||||
|
||||
Dashboard offers all available namespaces in a dropdown list, and allows you to create a new namespace. The namespace name may contain a maximum of 63 alphanumeric characters and dashes (-) but can not contain capital letters.
|
||||
Namespace names should not consist of only numbers. If the name is set as a number, such as 10, the pod will be put in the default namespace.
|
||||
|
||||
In case the creation of the namespace is successful, it is selected by default. If the creation fails, the first namespace is selected.
|
||||
|
||||
- **Image Pull Secret**: In case the specified Docker container image is private, it may require [pull secret](/docs/concepts/configuration/secret/) credentials.
|
||||
|
||||
Dashboard offers all available secrets in a dropdown list, and allows you to create a new secret. The secret name must follow the DNS domain name syntax, e.g. `new.image-pull.secret`. The content of a secret must be base64-encoded and specified in a [`.dockercfg`](/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod) file. The secret name may consist of a maximum of 253 characters.
|
||||
|
||||
In case the creation of the image pull secret is successful, it is selected by default. If the creation fails, no secret is applied.
|
||||
|
||||
- **CPU requirement (cores)** and **Memory requirement (MiB)**: You can specify the minimum [resource limits](/docs/tasks/configure-pod-container/limit-range/) for the container. By default, Pods run with unbounded CPU and memory limits.
|
||||
|
||||
- **Run command** and **Run command arguments**: By default, your containers run the specified Docker image's default [entrypoint command](/docs/user-guide/containers/#containers-and-commands). You can use the command options and arguments to override the default.
|
||||
|
||||
- **Run as privileged**: This setting determines whether processes in [privileged containers](/docs/user-guide/pods/#privileged-mode-for-pod-containers) are equivalent to processes running as root on the host. Privileged containers can make use of capabilities like manipulating the network stack and accessing devices.
|
||||
|
||||
- **Environment variables**: Kubernetes exposes Services through [environment variables](/docs/tasks/inject-data-application/environment-variable-expose-pod-information/). You can compose environment variable or pass arguments to your commands using the values of environment variables. They can be used in applications to find a Service. Values can reference other variables using the `$(VAR_NAME)` syntax.
|
||||
|
||||
### Uploading a YAML or JSON file
|
||||
|
||||
Kubernetes supports declarative configuration. In this style, all configuration is stored in YAML or JSON configuration files using the Kubernetes [API](/docs/concepts/overview/kubernetes-api/) resource schemas.
|
||||
|
||||
As an alternative to specifying application details in the deploy wizard, you can define your application in YAML or JSON files, and upload the files using Dashboard:
|
||||
|
||||

|
||||
|
||||
## Using Dashboard
|
||||
Following sections describe views of the Kubernetes Dashboard UI; what they provide and how can they be used.
|
||||
|
||||
### Navigation
|
||||
|
||||
When there are Kubernetes objects defined in the cluster, Dashboard shows them in the initial view. By default only objects from the _default_ namespace are shown and this can be changed using the namespace selector located in the navigation menu.
|
||||
|
||||
Dashboard shows most Kubernetes object kinds and groups them in a few menu categories.
|
||||
|
||||
#### Admin
|
||||
View for cluster and namespace administrators. It lists Nodes, Namespaces and Persistent Volumes and has detail views for them. Node list view contains CPU and memory usage metrics aggregated across all Nodes. The details view shows the metrics for a Node, its specification, status, allocated resources, events and pods running on the node.
|
||||
|
||||

|
||||
|
||||
#### Workloads
|
||||
Entry point view that shows all applications running in the selected namespace. The view lists applications by workload kind (e.g., Deployments, Replica Sets, Stateful Sets, etc.) and each workload kind can be viewed separately. The lists summarize actionable information about the workloads, such as the number of ready pods for a Replica Set or current memory usage for a Pod.
|
||||
|
||||

|
||||
|
||||
Detail views for workloads show status and specification information and surface relationships between objects. For example, Pods that Replica Set is controlling or New Replica Sets and Horizontal Pod Autoscalers for Deployments.
|
||||
|
||||

|
||||
|
||||
#### Services and discovery
|
||||
Services and discovery view shows Kubernetes resources that allow for exposing services to external world and discovering them within a cluster. For that reason, Service and Ingress views show Pods targeted by them, internal endpoints for cluster connections and external endpoints for external users.
|
||||
|
||||

|
||||
|
||||
#### Storage
|
||||
Storage view shows Persistent Volume Claim resources which are used by applications for storing data.
|
||||
|
||||
#### Config
|
||||
Config view shows all Kubernetes resources that are used for live configuration of applications running in clusters. This is now Config Maps and Secrets. The view allows for editing and managing config objects and displays secrets hidden by default.
|
||||
|
||||

|
||||
|
||||
#### Logs viewer
|
||||
Pod lists and detail pages link to logs viewer that is built into Dashboard. The viewer allows for drilling down logs from containers belonging to a single Pod.
|
||||
|
||||

|
||||
|
||||
## More information
|
||||
|
||||
For more information, see the
|
||||
[Kubernetes Dashboard project page](https://github.com/kubernetes/dashboard).
|
||||
Reference in New Issue
Block a user