Add a simple DNS example

This commit is contained in:
Deyuan Deng 2015-04-03 16:58:08 -04:00 committed by Deyuan Deng
parent 33efeb6f60
commit 34f35445d5
10 changed files with 293 additions and 0 deletions

137
cluster-dns/README.md Normal file
View File

@ -0,0 +1,137 @@
## Kubernetes DNS example
This is a toy example demonstrating how to use kubernetes DNS.
### Step Zero: Prerequisites
This example assumes that you have forked the repository and [turned up a Kubernetes cluster](../../docs/getting-started-guides). Make sure DNS is enabled in your setup, see [DNS doc](https://github.com/GoogleCloudPlatform/kubernetes/tree/master/cluster/addons/dns).
```shell
$ cd kubernetes
$ hack/dev-build-and-up.sh
```
### Step One: Create two namespaces
We'll see how cluster DNS works across multiple namespaces, first we need to create two namespaces:
```shell
$ cluster/kubectl.sh create -f examples/cluster-dns/namespace-dev.yaml
$ cluster/kubectl.sh create -f examples/cluster-dns/namespace-prod.yaml
```
Now list all namespaces:
```shell
$ cluster/kubectl.sh get namespaces
NAME LABELS STATUS
default <none> Active
development name=development Active
production name=production Active
```
For kubectl client to work with each namespace, we define two contexts:
```shell
$ cluster/kubectl.sh config set-context dev --namespace=development --cluster=${CLUSTER_NAME} --user=${USER_NAME}
$ cluster/kubectl.sh config set-context prod --namespace=production --cluster=${CLUSTER_NAME} --user=${USER_NAME}
```
### Step Two: Create backend replication controller in each namespace
Use the file `examples/cluster-dns/dns-backend-rc.yaml` to create a backend server replication controller in each namespace.
```shell
$ cluster/kubectl.sh config use-context dev
$ cluster/kubectl.sh create -f examples/cluster-dns/dns-backend-rc.yaml
```
Once that's up you can list the pod in the cluster:
```shell
$ cluster/kubectl.sh get rc
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
dns-backend dns-backend ddysher/dns-backend name=dns-backend 1
```
Now repeat the above commands to create a replication controller in prod namespace:
```shell
$ cluster/kubectl.sh config use-context prod
$ cluster/kubectl.sh create -f examples/cluster-dns/dns-backend-rc.yaml
$ cluster/kubectl.sh get rc
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
dns-backend dns-backend ddysher/dns-backend name=dns-backend 1
```
### Step Three: Create backend service
Use the file `examples/cluster-dns/dns-backend-service.yaml` to create a service for the backend server.
```shell
$ cluster/kubectl.sh config use-context dev
$ cluster/kubectl.sh create -f examples/cluster-dns/dns-backend-service.yaml
```
Once that's up you can list the service in the cluster:
```shell
$ cluster/kubectl.sh get service dns-backend
NAME LABELS SELECTOR IP(S) PORT(S)
dns-backend <none> name=dns-backend 10.0.236.129 8000/TCP
```
Again, repeat the same process for prod namespace:
```shell
$ cluster/kubectl.sh config use-context prod
$ cluster/kubectl.sh create -f examples/cluster-dns/dns-backend-service.yaml
$ cluster/kubectl.sh get service dns-backend
NAME LABELS SELECTOR IP(S) PORT(S)
dns-backend <none> name=dns-backend 10.0.35.246 8000/TCP
```
### Step Four: Create client pod in one namespace
Use the file `examples/cluster-dns/dns-frontend-pod.yaml` to create a client pod in dev namespace. The client pod will make a connection to backend and exit. Specifically, it tries to connect to address `http://dns-backend.development.kubernetes.local:8000`.
```shell
$ cluster/kubectl.sh config use-context dev
$ cluster/kubectl.sh create -f examples/cluster-dns/dns-frontend-pod.yaml
```
Once that's up you can list the pod in the cluster:
```shell
$ cluster/kubectl.sh get pods dns-frontend
POD IP CONTAINER(S) IMAGE(S) HOST LABELS STATUS CREATED MESSAGE
dns-frontend 10.244.2.9 kubernetes-minion-sswf/104.154.55.211 name=dns-frontend Running 3 seconds
dns-frontend ddysher/dns-frontend Running 2 seconds
```
Wait until the pod succeeds, then we can see the output from the client pod:
```shell
$ cluster/kubectl.sh log dns-frontend
2015-05-07T20:13:54.147664936Z 10.0.236.129
2015-05-07T20:13:54.147721290Z Send request to: http://dns-backend.development.kubernetes.local:8000
2015-05-07T20:13:54.147733438Z <Response [200]>
2015-05-07T20:13:54.147738295Z Hello World!
```
Please refer to the [source code](./images/frontend/client.py) about the logs. First line prints out the ip address associated with the service in dev namespace; remaining lines print out our request and server response. If we switch to prod namespace with the same pod config, we'll see the same result, i.e. dns will resolve across namespace.
```shell
$ cluster/kubectl.sh config use-context prod
$ cluster/kubectl.sh create -f examples/cluster-dns/dns-frontend-pod.yaml
$ cluster/kubectl.sh log dns-frontend
2015-05-07T20:13:54.147664936Z 10.0.236.129
2015-05-07T20:13:54.147721290Z Send request to: http://dns-backend.development.kubernetes.local:8000
2015-05-07T20:13:54.147733438Z <Response [200]>
2015-05-07T20:13:54.147738295Z Hello World!
```
#### Note about default namespace
If you prefer not using namespace, then all your services can be addressed using `default` namespace, e.g. `http://dns-backend.default.kubernetes.local:8000`, or shorthand version `http://dns-backend:8000`

View File

@ -0,0 +1,22 @@
apiVersion: v1beta3
kind: ReplicationController
metadata:
name: dns-backend
labels:
name: dns-backend
spec:
replicas: 1
selector:
name: dns-backend
template:
metadata:
labels:
name: dns-backend
spec:
containers:
- name: dns-backend
image: ddysher/dns-backend
ports:
- name: backend-port
containerPort: 8000
protocol: tcp

View File

@ -0,0 +1,9 @@
kind: Service
apiVersion: v1beta3
metadata:
name: dns-backend
spec:
ports:
- port: 8000
selector:
name: dns-backend

View File

@ -0,0 +1,16 @@
apiVersion: v1beta3
kind: Pod
metadata:
name: dns-frontend
labels:
name: dns-frontend
spec:
containers:
- name: dns-frontend
image: ddysher/dns-frontend
command:
- python
- client.py
- http://dns-backend.development.kubernetes.local:8000
imagePullPolicy: Always
restartPolicy: Never

View File

@ -0,0 +1,6 @@
FROM python:2.7
COPY . /dns-backend
WORKDIR /dns-backend
CMD ["python", "server.py"]

View File

@ -0,0 +1,37 @@
#!/usr/bin/env python
# Copyright 2015 The Kubernetes Authors All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
PORT_NUMBER = 8000
# This class will handles any incoming request.
class HTTPHandler(BaseHTTPRequestHandler):
# Handler for the GET requests
def do_GET(self):
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
self.wfile.write("Hello World!")
try:
# Create a web server and define the handler to manage the incoming request.
server = HTTPServer(('', PORT_NUMBER), HTTPHandler)
print 'Started httpserver on port ' , PORT_NUMBER
server.serve_forever()
except KeyboardInterrupt:
print '^C received, shutting down the web server'
server.socket.close()

View File

@ -0,0 +1,8 @@
FROM python:2.7
RUN pip install requests
COPY . /dns-frontend
WORKDIR /dns-frontend
CMD ["python", "client.py"]

View File

@ -0,0 +1,46 @@
#!/usr/bin/env python
# Copyright 2015 The Kubernetes Authors All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import argparse
import requests
import socket
from urlparse import urlparse
def CheckServiceAddress(address):
hostname = urlparse(address).hostname
service_address = socket.gethostbyname(hostname)
print service_address
def GetServerResponse(address):
print 'Send request to:', address
response = requests.get(address)
print response
print response.content
def Main():
parser = argparse.ArgumentParser()
parser.add_argument('address')
args = parser.parse_args()
CheckServiceAddress(args.address)
GetServerResponse(args.address)
if __name__ == "__main__":
Main()

View File

@ -0,0 +1,6 @@
apiVersion: v1beta3
kind: Namespace
metadata:
name: "development"
labels:
name: "development"

View File

@ -0,0 +1,6 @@
apiVersion: v1beta3
kind: Namespace
metadata:
name: "development"
labels:
name: "development"