refactor
This commit is contained in:
Родитель
1fcf8da496
Коммит
6e9c0c0ce3
|
@ -23,4 +23,5 @@ node {
|
|||
stage "Deploy"
|
||||
|
||||
sh "sed 's#127.0.0.1:30400/hello-kenzan:latest#'$BUILDIMG'#' applications/hello-kenzan/k8s/deployment.yaml | kubectl apply -f -"
|
||||
sh "kubectl rollout status deployment/hello-kenzan"
|
||||
}
|
117
README.md
117
README.md
|
@ -13,124 +13,19 @@ Begin the tutorial `npm start`
|
|||
|
||||
## Manual tutorial version
|
||||
|
||||
## Part 1
|
||||
## Part 4
|
||||
|
||||
|
||||
### Part 1
|
||||
### Part 4
|
||||
|
||||
### Step1
|
||||
|
||||
Start up the cluster with minikibe
|
||||
Bootstrap etcd operator on the cluster
|
||||
|
||||
`minikube start --memory 6000 --cpus 2 --kubernetes-version v1.6.0`
|
||||
`scripts/etcd.sh`
|
||||
|
||||
### Step2
|
||||
|
||||
Enable addons
|
||||
Setup etcd directory for kubescale
|
||||
|
||||
`minikube addons enable heapster; minikube addons enable ingress`
|
||||
|
||||
### Step3
|
||||
|
||||
Wait 20 seconds and view minikube dashboard
|
||||
|
||||
`sleep 20; minikube service kubernetes-dashboard --namespace kube-system`
|
||||
|
||||
### Step4
|
||||
|
||||
Deploy the public nginx image from DockerHub
|
||||
|
||||
`kubectl run nginx --image nginx --port 80`
|
||||
|
||||
### Step5
|
||||
|
||||
Create a service for deployment
|
||||
|
||||
`kubectl expose deployment nginx --type NodePort --port 80`
|
||||
|
||||
### Step6
|
||||
|
||||
Launch browser to test service
|
||||
|
||||
`minikube service nginx`
|
||||
|
||||
### Step7
|
||||
|
||||
Install registry
|
||||
|
||||
`kubectl apply -f manifests/registry.yml`
|
||||
|
||||
### Step8
|
||||
|
||||
Wait for registry to deploy
|
||||
|
||||
`kubectl rollout status deployments/registry`
|
||||
|
||||
### Step9
|
||||
|
||||
View registry UI
|
||||
|
||||
`minikube service registry-ui`
|
||||
|
||||
### Step10
|
||||
|
||||
Edit the contents of applications/hello-kenzan/index.html
|
||||
|
||||
`nano applications/hello-kenzan/index.html`
|
||||
|
||||
### Step11
|
||||
|
||||
We will now build the image with a special name that is pointing at our cluster registry.
|
||||
|
||||
`docker build -t 127.0.0.1:30400/hello-kenzan:latest -f applications/hello-kenzan/Dockerfile applications/hello-kenzan`
|
||||
|
||||
### Step12
|
||||
|
||||
Before we can push our image we need to set up a temporary proxy. This is a container that listens on 127.0.0.1:30400 and forwads to our cluster. By default the docker client can only push to non https via localhost.
|
||||
|
||||
`docker run -d -e "REGIP=`minikube ip`" --name socat-registry -p 30400:5000 chadmoon/socat:latest bash -c "socat TCP4-LISTEN:5000,fork,reuseaddr TCP4:`minikube ip`:30400"`
|
||||
|
||||
### Step13
|
||||
|
||||
We can now push our image.
|
||||
|
||||
`docker push 127.0.0.1:30400/hello-kenzan:latest`
|
||||
|
||||
### Step14
|
||||
|
||||
Stop the registry proxy
|
||||
|
||||
`docker stop socat-registry; docker rm socat-registry`
|
||||
|
||||
### Step15
|
||||
|
||||
Now that our image is on the cluster we can deploy the manifests
|
||||
|
||||
`kubectl apply -f applications/hello-kenzan/k8s/deployment.yaml`
|
||||
|
||||
### Step16
|
||||
|
||||
View the app
|
||||
|
||||
`minikube service hello-kenzan`## Part 2
|
||||
|
||||
|
||||
### Part 2
|
||||
|
||||
### Step1
|
||||
|
||||
Install Jenkins
|
||||
|
||||
`kubectl apply -f manifests/jenkins.yml; kubectl rollout status deployment/jenkins`
|
||||
|
||||
### Step2
|
||||
|
||||
Get Jenkins admin password
|
||||
|
||||
`kubectl exec -it `kubectl get pods --selector=app=jenkins --output=jsonpath={.items..metadata.name}` cat /root/.jenkins/secrets/initialAdminPassword`
|
||||
|
||||
### Step3
|
||||
|
||||
Configure Jenkins, default settings. Create a new job with type pipeline. Choose "Jenkinsfile from SCM" with target repo as https://github.com/kenzanlabs/kubernetes-ci-cd.git. Run the job.
|
||||
|
||||
`minikube service jenkins`
|
||||
`scripts/kubescale.sh`
|
|
@ -0,0 +1,23 @@
|
|||
FROM node:6
|
||||
|
||||
RUN mkdir /app
|
||||
|
||||
COPY . /app
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN apt-get update
|
||||
|
||||
RUN apt-get install -y apache2
|
||||
|
||||
RUN npm install -g loadtest
|
||||
|
||||
RUN npm install -g nodemon
|
||||
|
||||
RUN npm install
|
||||
|
||||
RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
|
||||
|
||||
RUN chmod +x ./kubectl; mv ./kubectl /usr/local/bin/kubectl
|
||||
|
||||
CMD ["nodemon", "index.js"]
|
|
@ -0,0 +1,95 @@
|
|||
var express = require('express')
|
||||
var app = express()
|
||||
|
||||
var http = require('http').Server(app);
|
||||
var io = require('socket.io')(http);
|
||||
var path = require("path");
|
||||
var Etcd = require('node-etcd')
|
||||
app.use(express.static('public'))
|
||||
var exec = require('child_process').exec;
|
||||
|
||||
var bodyParser = require("body-parser");
|
||||
|
||||
app.use(bodyParser.urlencoded({ extended: false }));
|
||||
app.use(bodyParser.json());
|
||||
|
||||
//etcd = new Etcd("http://localhost:2379")
|
||||
///tmp/test-etcd/etcdctl --endpoints "http://example-etcd-cluster-client-service:2379" mkdir pod-list
|
||||
etcd = new Etcd("http://example-etcd-cluster-client-service:2379")
|
||||
|
||||
//etcd.mkdir("pods");
|
||||
|
||||
watcher = etcd.watcher("pod-list", null, {recursive: true})
|
||||
|
||||
watcher.on("change", showVal);
|
||||
|
||||
function showVal(val) {
|
||||
pods = etcd.getSync("pod-list",{ recursive: true })
|
||||
io.emit('pods', { pods: pods.body.node.nodes });
|
||||
|
||||
}
|
||||
|
||||
app.post('/scale', function (req, res) {
|
||||
exec('kubectl scale --replicas=' + req.body.count + ' deployment/set', function(error, stdout, stderr) {
|
||||
res.send("scaled to " + req.body.count);
|
||||
});
|
||||
})
|
||||
|
||||
app.post('/loadtest/concurrent', function (req, res) {
|
||||
//svc = "http://localhost:8001/api/v1/proxy/namespaces/default/services/set:80"
|
||||
svc = "http://set:80/"
|
||||
// exec('loadtest -c ' + req.body.count + ' -n ' + req.body.count + ' http://set', function(error, stdout, stderr) {
|
||||
exec('ab -c ' + req.body.count + ' -n ' + req.body.count + ' ' + svc, function(error, stdout, stderr) {
|
||||
console.log(stdout);
|
||||
res.send(stdout);
|
||||
});
|
||||
})
|
||||
|
||||
app.post('/loadtest/consecutive', function (req, res) {
|
||||
svc = "http://set:80/"
|
||||
// exec('loadtest -c ' + req.body.count + ' -n ' + req.body.count + ' http://set', function(error, stdout, stderr) {
|
||||
exec('ab -c 1 -n ' + req.body.count + ' ' + svc, function(error, stdout, stderr) {
|
||||
console.log(stdout);
|
||||
res.send(stdout);
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
|
||||
app.get('/up/:podId', function (req, res) {
|
||||
etcd.set("pod-list/" + req.params.podId, req.params.podId);
|
||||
res.send('done');
|
||||
})
|
||||
|
||||
app.get('/down/:podId', function (req, res) {
|
||||
etcd.del("pod-list/" + req.params.podId, req.params.podId);
|
||||
res.send('done');
|
||||
})
|
||||
|
||||
app.get('/hit/:podId', function (req, res) {
|
||||
|
||||
var d = new Date();
|
||||
var n = d.getTime();
|
||||
|
||||
io.emit('hit', { podId: req.params.podId, time: n });
|
||||
console.log('hit!');
|
||||
res.send('done')
|
||||
})
|
||||
|
||||
io.on('connection', function(socket){
|
||||
|
||||
pods = etcd.getSync("pod-list",{ recursive: true })
|
||||
io.emit('pods', { pods: pods.body.node.nodes });
|
||||
});
|
||||
|
||||
app.get('/',function(req,res){
|
||||
|
||||
res.sendFile(path.join(__dirname+'/public/index.html'));
|
||||
|
||||
});
|
||||
|
||||
|
||||
http.listen(3000, function () {
|
||||
console.log('Example app listening on port 3000!')
|
||||
})
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: dashboard-ingress
|
||||
namespace: kube-system
|
||||
spec:
|
||||
rules:
|
||||
- host: dashboard.127.0.0.1.xip.io
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: kubernetes-dashboard
|
||||
servicePort: 80
|
|
@ -0,0 +1,46 @@
|
|||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: ingress-services
|
||||
namespace: kube-system
|
||||
annotations:
|
||||
ingress.kubernetes.io/rewrite-target: /
|
||||
spec:
|
||||
backend:
|
||||
serviceName: default-http-backend
|
||||
servicePort: 80
|
||||
rules:
|
||||
- host: dashboard.127.0.0.1.xip.io
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: kubernetes-dashboard
|
||||
servicePort: 80
|
||||
|
||||
- host: grafana.127.0.0.1.xip.io
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: monitoring-grafana
|
||||
servicePort: 80
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: ingress-services
|
||||
annotations:
|
||||
ingress.kubernetes.io/rewrite-target: /
|
||||
spec:
|
||||
backend:
|
||||
serviceName: default-http-backend
|
||||
servicePort: 80
|
||||
rules:
|
||||
- host: kubescale.127.0.0.1.xip.io
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: kubescale
|
||||
servicePort: 3000
|
|
@ -0,0 +1,96 @@
|
|||
kind: PersistentVolume
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: jenkins
|
||||
labels:
|
||||
type: local
|
||||
spec:
|
||||
capacity:
|
||||
storage: 2Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
hostPath:
|
||||
path: "/data/jenkins/"
|
||||
|
||||
---
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: jenkins-claim
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 2Gi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: jenkins
|
||||
labels:
|
||||
app: jenkins
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: jenkins
|
||||
tier: jenkins
|
||||
type: NodePort
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: jenkins
|
||||
labels:
|
||||
app: jenkins
|
||||
spec:
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: jenkins
|
||||
tier: jenkins
|
||||
spec:
|
||||
containers:
|
||||
- image: chadmoon/jenkins-docker-kubectl:latest
|
||||
name: jenkins
|
||||
securityContext:
|
||||
privileged: true
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: jenkins
|
||||
volumeMounts:
|
||||
- name: jenkins-persistent-storage
|
||||
mountPath: /root/.jenkins
|
||||
- name: docker
|
||||
mountPath: /var/run/docker.sock
|
||||
volumes:
|
||||
- name: docker
|
||||
hostPath:
|
||||
path: /var/run/docker.sock
|
||||
- name: jenkins-persistent-storage
|
||||
persistentVolumeClaim:
|
||||
claimName: jenkins-claim
|
||||
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: jenkins-services
|
||||
annotations:
|
||||
ingress.kubernetes.io/rewrite-target: /
|
||||
spec:
|
||||
backend:
|
||||
serviceName: default-http-backend
|
||||
servicePort: 80
|
||||
rules:
|
||||
- host: jenkins.127.0.0.1.xip.io
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: jenkins
|
||||
servicePort: 8080
|
|
@ -0,0 +1,38 @@
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: kubescale
|
||||
labels:
|
||||
app: kubescale
|
||||
spec:
|
||||
ports:
|
||||
- port: 3000
|
||||
targetPort: 3000
|
||||
selector:
|
||||
app: kubescale
|
||||
tier: kubescale
|
||||
type: NodePort
|
||||
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: kubescale
|
||||
labels:
|
||||
app: kubescale
|
||||
spec:
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: kubescale
|
||||
tier: kubescale
|
||||
spec:
|
||||
containers:
|
||||
- image: 127.0.0.1:30400/kubescale:latest
|
||||
imagePullPolicy: Always
|
||||
name: kubescale
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
name: kubescale
|
|
@ -0,0 +1,142 @@
|
|||
kind: PersistentVolume
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: registry
|
||||
labels:
|
||||
type: local
|
||||
spec:
|
||||
capacity:
|
||||
storage: 4Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
hostPath:
|
||||
path: "/data/registry/"
|
||||
|
||||
---
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: registry-claim
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 4Gi
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: registry
|
||||
labels:
|
||||
app: registry
|
||||
spec:
|
||||
ports:
|
||||
- port: 5000
|
||||
targetPort: 5000
|
||||
nodePort: 30400
|
||||
name: registry
|
||||
selector:
|
||||
app: registry
|
||||
tier: registry
|
||||
type: NodePort
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: registry
|
||||
labels:
|
||||
app: registry
|
||||
spec:
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: registry
|
||||
tier: registry
|
||||
spec:
|
||||
containers:
|
||||
- image: registry:2
|
||||
name: registry
|
||||
volumeMounts:
|
||||
- name: docker
|
||||
mountPath: /var/run/docker.sock
|
||||
- name: registry-persistent-storage
|
||||
mountPath: /var/lib/registry
|
||||
ports:
|
||||
- containerPort: 5000
|
||||
name: registry
|
||||
- name: registryui
|
||||
image: hyper/docker-registry-web
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
env:
|
||||
- name: REGISTRY_URL
|
||||
value: http://localhost:5000/v2
|
||||
- name: REGISTRY_NAME
|
||||
value: cluster-registry
|
||||
volumes:
|
||||
- name: docker
|
||||
hostPath:
|
||||
path: /var/run/docker.sock
|
||||
- name: registry-persistent-storage
|
||||
persistentVolumeClaim:
|
||||
claimName: registry-claim
|
||||
|
||||
# ---
|
||||
# apiVersion: extensions/v1beta1
|
||||
# kind: Deployment
|
||||
# metadata:
|
||||
# name: registryui
|
||||
# spec:
|
||||
# replicas: 1
|
||||
# template:
|
||||
# metadata:
|
||||
# labels:
|
||||
# app: registryui
|
||||
# spec:
|
||||
# containers:
|
||||
# - name: registryui
|
||||
# image: hyper/docker-registry-web
|
||||
# ports:
|
||||
# - containerPort: 8080
|
||||
# env:
|
||||
# - name: REGISTRY_URL
|
||||
# value: http://registry:5000/v2
|
||||
# - name: REGISTRY_NAME
|
||||
# value: cluster-registry
|
||||
|
||||
# ---
|
||||
# apiVersion: v1
|
||||
# kind: Service
|
||||
# metadata:
|
||||
# name: registryui
|
||||
# labels:
|
||||
# app: registryui
|
||||
# spec:
|
||||
# ports:
|
||||
# - port: 8080
|
||||
# targetPort: 8080
|
||||
# name: registry
|
||||
# selector:
|
||||
# app: registryui
|
||||
# tier: registryui
|
||||
# type: NodePort
|
||||
|
||||
|
||||
# ---
|
||||
# apiVersion: extensions/v1beta1
|
||||
# kind: Ingress
|
||||
# metadata:
|
||||
# name: registryui-ingress
|
||||
# spec:
|
||||
# rules:
|
||||
# - host: registry.192.168.64.3.xip.io
|
||||
# http:
|
||||
# paths:
|
||||
# - path: /
|
||||
# backend:
|
||||
# serviceName: registryui
|
||||
# servicePort: 8080
|
|
@ -0,0 +1,43 @@
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: set
|
||||
labels:
|
||||
app: set
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
selector:
|
||||
app: set
|
||||
tier: set
|
||||
type: NodePort
|
||||
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: set
|
||||
labels:
|
||||
app: set
|
||||
spec:
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: set
|
||||
tier: set
|
||||
|
||||
spec:
|
||||
containers:
|
||||
- name: lifecycle-demo-container
|
||||
image: 127.0.0.1:30400/set:latest
|
||||
|
||||
lifecycle:
|
||||
postStart:
|
||||
exec:
|
||||
command: ["/up.sh"]
|
||||
preStop:
|
||||
exec:
|
||||
command: ["/down.sh"]
|
|
@ -0,0 +1,35 @@
|
|||
apiVersion: v1
|
||||
kind: Deployment
|
||||
apiVersion: extensions/v1beta1
|
||||
metadata:
|
||||
name: traefik-ingress-controller
|
||||
namespace: kube-system
|
||||
labels:
|
||||
k8s-app: traefik-ingress-lb
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
k8s-app: traefik-ingress-lb
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: traefik-ingress-lb
|
||||
name: traefik-ingress-lb
|
||||
spec:
|
||||
terminationGracePeriodSeconds: 60
|
||||
hostNetwork: true
|
||||
containers:
|
||||
- image: traefik
|
||||
name: traefik-ingress-lb
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
hostPort: 80
|
||||
- name: admin
|
||||
containerPort: 8081
|
||||
args:
|
||||
- -d
|
||||
- --web
|
||||
- --web.address=:8081
|
||||
- --kubernetes
|
|
@ -0,0 +1,18 @@
|
|||
#!/bin/sh
|
||||
|
||||
if [ "$1" = "" ]; then
|
||||
echo "Usage: ksh <pod> [flags_to_kubectl]"
|
||||
exit 1
|
||||
fi
|
||||
POD=$1
|
||||
shift
|
||||
|
||||
COLUMNS=`tput cols`
|
||||
LINES=`tput lines`
|
||||
TERM=xterm
|
||||
KUBE_SHELL=${KUBE_SHELL:-bash}
|
||||
kubectl exec -i -t $POD "$@" -- env COLUMNS=$COLUMNS LINES=$LINES TERM=$TERM "$KUBE_SHELL"
|
||||
|
||||
#$ ./ksh pod_name
|
||||
#$ ./ksh pod_name --namespace=kube-system
|
||||
#$ KUBE_SHELL=sh ./ksh pod_name
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"name": "app",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"@blueprintjs/core": "^1.12.0",
|
||||
"body-parser": "^1.17.1",
|
||||
"classnames": "^2.2.5",
|
||||
"express": "^4.15.2",
|
||||
"express-ws": "^3.0.0",
|
||||
"node-etcd": "^5.0.3",
|
||||
"node-serialize": "0.0.4",
|
||||
"nodejs-etcd": "^0.1.1",
|
||||
"react": "^15.4.2",
|
||||
"react-addons-css-transition-group": "^15.4.2",
|
||||
"react-dom": "^15.4.2",
|
||||
"socket.io": "^1.7.3",
|
||||
"tether": "^1.4.0",
|
||||
"ws": "^2.2.1"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "node index.js"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
|
@ -0,0 +1,232 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
|
||||
|
||||
<link href="https://unpkg.com/normalize.css@^4.1.1" rel="stylesheet" />
|
||||
<link href="https://unpkg.com/@blueprintjs/core@^1.11.0/dist/blueprint.css" rel="stylesheet" />
|
||||
|
||||
<meta charset="utf-8">
|
||||
<title>Chat example</title>
|
||||
<script src="/socket.io/socket.io.js"></script>
|
||||
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
|
||||
<script src="http://code.jquery.com/color/jquery.color-2.1.2.min.js"></script>
|
||||
|
||||
<style>
|
||||
|
||||
|
||||
|
||||
.card{
|
||||
width: 250px;
|
||||
margin: 5px;
|
||||
float: left;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
<script>
|
||||
var socket = io();
|
||||
|
||||
var firstRun = true;
|
||||
|
||||
socket.on('hit', function(msg){
|
||||
console.log("hit!" + msg.podId)
|
||||
pulse(msg.podId);
|
||||
|
||||
});
|
||||
|
||||
|
||||
socket.on('pods', function(msg){
|
||||
console.log(msg);
|
||||
|
||||
setInterval(function(){
|
||||
if ($("#current").val() != $("#count").val()){
|
||||
$("#progress").show();
|
||||
}else{
|
||||
$("#progress").hide();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$("#pods").html('');
|
||||
|
||||
$("#current").val(msg.pods.length)
|
||||
if(firstRun){
|
||||
$("#count").val(msg.pods.length)
|
||||
firstRun = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
msg.pods.forEach(function(pod) {
|
||||
|
||||
|
||||
|
||||
|
||||
$("#pods").append('<div style="position:relative;" class="' + pod.value + ' card pt-card pt-elevation-2">' + pod.value + '</div>')
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
})
|
||||
|
||||
function down(){
|
||||
$("#count").val(($("#count").val()*1) - 1);
|
||||
scale();
|
||||
}
|
||||
|
||||
function up(){
|
||||
$("#count").val(($("#count").val()*1) + 1);
|
||||
scale();
|
||||
}
|
||||
|
||||
function scale() {
|
||||
$.post( "/scale", { count: $("#count").val() } );
|
||||
|
||||
$("#progress").show();
|
||||
|
||||
}
|
||||
|
||||
function loadTest() {
|
||||
$.post( "/loadtest/" + $("#loadType").val() , { count: $("#loadTest").val() } );
|
||||
|
||||
//$("#progress").show();
|
||||
|
||||
//pulse("set-1165364669-d0lsf")
|
||||
|
||||
}
|
||||
|
||||
function pulse(podId) {
|
||||
//$('.pods').removeClass('pulse')
|
||||
|
||||
|
||||
|
||||
// $('.' + podId + ' .star').fadeIn( 300, function() {
|
||||
|
||||
// $('.' + podId + ' .star').fadeOut( 300)
|
||||
|
||||
// });
|
||||
|
||||
//$('.' + podId + ' .star').show().fadeOut(500)
|
||||
|
||||
//$('.' + podId).slideUp(200).slideDown(200);
|
||||
|
||||
//var el = $('<div class="star" style="top:5px;right:5px;font-size:20px;color:#3DCC91">◉</div>');
|
||||
|
||||
|
||||
$('.' + podId).animate( { backgroundColor: "#3DCC91" }, 500 ).animate( { backgroundColor: "#ffffff" }, 500 ).delay(1000);
|
||||
|
||||
|
||||
|
||||
//el.fadeOut(600)
|
||||
|
||||
|
||||
|
||||
//$('.' + podId).append()
|
||||
//$('.' + podId + ' .star').fadeIn(300).fadeOut(300)
|
||||
|
||||
|
||||
//$('.' + podId).append("<div></div>")
|
||||
|
||||
// $('.' + podId).css("backgroundColor", '#3DCC91');
|
||||
// $('.' + podId).animate({backgroundColor: '#ffffff'}, 500);
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="pt-navbar pt-dark">
|
||||
<div class="pt-navbar-group pt-align-left">
|
||||
<div class="pt-navbar-heading">KubeScale</div>
|
||||
|
||||
<div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="pt-navbar-group pt-align-right">
|
||||
|
||||
|
||||
Current Replicas: <div class="pt-numeric-input pt-control-group"><div class="pt-input-group"><input size="3" id="current" type="text" class="pt-input" readonly style="padding-right: 0px;"></div></div>
|
||||
|
||||
|
||||
|
||||
<span class="pt-navbar-divider"></span>
|
||||
|
||||
Desired Replicas: <div class="pt-numeric-input pt-control-group"><div class="pt-input-group"><input size="3" type="text" onChange="scale()" id="count" class="pt-input" style="padding-right: 0px;"></div><div class="pt-button-group pt-vertical pt-fixed"><button onClick="up()" type="button" class="pt-button pt-icon-chevron-up"></button><button onClick="down()" type="button" class="pt-button pt-icon-chevron-down"></button></div></div>
|
||||
|
||||
<span class="pt-navbar-divider"></span>
|
||||
<!--
|
||||
<div class="pt-numeric-input pt-control-group"><div class="pt-input-group"><input id="loadTest" style="width:40px" type="text" class="pt-input" style="padding-right: 0px;"></div><div class="pt-button-group pt-vertical pt-fixed"><button type="button" class="pt-button pt-icon-chevron-up"></button><button type="button" class="pt-button pt-icon-chevron-down"></button></div></div>
|
||||
-->
|
||||
# of Requests:
|
||||
|
||||
|
||||
|
||||
<div class="pt-control-group">
|
||||
<div class="pt-input-group">
|
||||
|
||||
<input type="text" size="3" id="loadTest" class="pt-input" />
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="pt-input-group">
|
||||
|
||||
|
||||
|
||||
<div class="pt-select">
|
||||
<select id="loadType">
|
||||
|
||||
<option selected value="concurrent">Concurrent</option>
|
||||
<option value="consecutive">Consecutive</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<button type="button" onClick="loadTest()" class="pt-button pt-intent-success">Load Test</button>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="pt-input-group">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</nav>
|
||||
<div style="height:5px;">
|
||||
<div id="progress" class="pt-progress-bar pt-intent-primary">
|
||||
<div class="pt-progress-meter" style="width: 100%"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="pods"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,17 @@
|
|||
FROM node:6
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y curl
|
||||
|
||||
COPY . /app
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY up.sh /up.sh
|
||||
|
||||
COPY down.sh /down.sh
|
||||
|
||||
RUN npm install
|
||||
|
||||
RUN mpm install -g nodemon
|
||||
|
||||
CMD ["nodemon", "server.js"]
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env bash
|
||||
HOSTNAME=`hostname`
|
||||
curl "http://kubescale:3000/down/$HOSTNAME"
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"name": "set",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "node server.js"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"express": "^4.15.2",
|
||||
"sleep": "^5.1.0"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
var express = require('express')
|
||||
var app = express()
|
||||
|
||||
var sleep = require('sleep')
|
||||
|
||||
var exec = require('child_process').exec;
|
||||
|
||||
|
||||
|
||||
app.get('/', function (req, res) {
|
||||
|
||||
exec('export HOSTNAME=`hostname`; curl http://kubescale:3000/hit/$HOSTNAME', function(error, stdout, stderr) {
|
||||
sleep.sleep(1);
|
||||
res.send("hit");
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
|
||||
app.listen(80, function () {
|
||||
console.log('Example app listening on port 80!')
|
||||
})
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env bash
|
||||
HOSTNAME=`hostname`
|
||||
curl "http://kubescale:3000/up/$HOSTNAME"
|
|
@ -0,0 +1,23 @@
|
|||
FROM node:6
|
||||
|
||||
RUN mkdir /app
|
||||
|
||||
COPY . /app
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN apt-get update
|
||||
|
||||
RUN apt-get install -y apache2
|
||||
|
||||
RUN npm install -g loadtest
|
||||
|
||||
RUN npm install -g nodemon
|
||||
|
||||
RUN npm install
|
||||
|
||||
RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
|
||||
|
||||
RUN chmod +x ./kubectl; mv ./kubectl /usr/local/bin/kubectl
|
||||
|
||||
CMD ["nodemon", "index.js"]
|
|
@ -0,0 +1,95 @@
|
|||
var express = require('express')
|
||||
var app = express()
|
||||
|
||||
var http = require('http').Server(app);
|
||||
var io = require('socket.io')(http);
|
||||
var path = require("path");
|
||||
var Etcd = require('node-etcd')
|
||||
app.use(express.static('public'))
|
||||
var exec = require('child_process').exec;
|
||||
|
||||
var bodyParser = require("body-parser");
|
||||
|
||||
app.use(bodyParser.urlencoded({ extended: false }));
|
||||
app.use(bodyParser.json());
|
||||
|
||||
//etcd = new Etcd("http://localhost:2379")
|
||||
///tmp/test-etcd/etcdctl --endpoints "http://example-etcd-cluster-client-service:2379" mkdir pod-list
|
||||
etcd = new Etcd("http://example-etcd-cluster-client-service:2379")
|
||||
|
||||
//etcd.mkdir("pods");
|
||||
|
||||
watcher = etcd.watcher("pod-list", null, {recursive: true})
|
||||
|
||||
watcher.on("change", showVal);
|
||||
|
||||
function showVal(val) {
|
||||
pods = etcd.getSync("pod-list",{ recursive: true })
|
||||
io.emit('pods', { pods: pods.body.node.nodes });
|
||||
|
||||
}
|
||||
|
||||
app.post('/scale', function (req, res) {
|
||||
exec('kubectl scale --replicas=' + req.body.count + ' deployment/set', function(error, stdout, stderr) {
|
||||
res.send("scaled to " + req.body.count);
|
||||
});
|
||||
})
|
||||
|
||||
app.post('/loadtest/concurrent', function (req, res) {
|
||||
//svc = "http://localhost:8001/api/v1/proxy/namespaces/default/services/set:80"
|
||||
svc = "http://set:80/"
|
||||
// exec('loadtest -c ' + req.body.count + ' -n ' + req.body.count + ' http://set', function(error, stdout, stderr) {
|
||||
exec('ab -c ' + req.body.count + ' -n ' + req.body.count + ' ' + svc, function(error, stdout, stderr) {
|
||||
console.log(stdout);
|
||||
res.send(stdout);
|
||||
});
|
||||
})
|
||||
|
||||
app.post('/loadtest/consecutive', function (req, res) {
|
||||
svc = "http://set:80/"
|
||||
// exec('loadtest -c ' + req.body.count + ' -n ' + req.body.count + ' http://set', function(error, stdout, stderr) {
|
||||
exec('ab -c 1 -n ' + req.body.count + ' ' + svc, function(error, stdout, stderr) {
|
||||
console.log(stdout);
|
||||
res.send(stdout);
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
|
||||
app.get('/up/:podId', function (req, res) {
|
||||
etcd.set("pod-list/" + req.params.podId, req.params.podId);
|
||||
res.send('done');
|
||||
})
|
||||
|
||||
app.get('/down/:podId', function (req, res) {
|
||||
etcd.del("pod-list/" + req.params.podId, req.params.podId);
|
||||
res.send('done');
|
||||
})
|
||||
|
||||
app.get('/hit/:podId', function (req, res) {
|
||||
|
||||
var d = new Date();
|
||||
var n = d.getTime();
|
||||
|
||||
io.emit('hit', { podId: req.params.podId, time: n });
|
||||
console.log('hit!');
|
||||
res.send('done')
|
||||
})
|
||||
|
||||
io.on('connection', function(socket){
|
||||
|
||||
pods = etcd.getSync("pod-list",{ recursive: true })
|
||||
io.emit('pods', { pods: pods.body.node.nodes });
|
||||
});
|
||||
|
||||
app.get('/',function(req,res){
|
||||
|
||||
res.sendFile(path.join(__dirname+'/public/index.html'));
|
||||
|
||||
});
|
||||
|
||||
|
||||
http.listen(3000, function () {
|
||||
console.log('Example app listening on port 3000!')
|
||||
})
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: dashboard-ingress
|
||||
namespace: kube-system
|
||||
spec:
|
||||
rules:
|
||||
- host: dashboard.127.0.0.1.xip.io
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: kubernetes-dashboard
|
||||
servicePort: 80
|
|
@ -0,0 +1,46 @@
|
|||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: ingress-services
|
||||
namespace: kube-system
|
||||
annotations:
|
||||
ingress.kubernetes.io/rewrite-target: /
|
||||
spec:
|
||||
backend:
|
||||
serviceName: default-http-backend
|
||||
servicePort: 80
|
||||
rules:
|
||||
- host: dashboard.127.0.0.1.xip.io
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: kubernetes-dashboard
|
||||
servicePort: 80
|
||||
|
||||
- host: grafana.127.0.0.1.xip.io
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: monitoring-grafana
|
||||
servicePort: 80
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: ingress-services
|
||||
annotations:
|
||||
ingress.kubernetes.io/rewrite-target: /
|
||||
spec:
|
||||
backend:
|
||||
serviceName: default-http-backend
|
||||
servicePort: 80
|
||||
rules:
|
||||
- host: kubescale.127.0.0.1.xip.io
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: kubescale
|
||||
servicePort: 3000
|
|
@ -0,0 +1,96 @@
|
|||
kind: PersistentVolume
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: jenkins
|
||||
labels:
|
||||
type: local
|
||||
spec:
|
||||
capacity:
|
||||
storage: 2Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
hostPath:
|
||||
path: "/data/jenkins/"
|
||||
|
||||
---
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: jenkins-claim
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 2Gi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: jenkins
|
||||
labels:
|
||||
app: jenkins
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: jenkins
|
||||
tier: jenkins
|
||||
type: NodePort
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: jenkins
|
||||
labels:
|
||||
app: jenkins
|
||||
spec:
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: jenkins
|
||||
tier: jenkins
|
||||
spec:
|
||||
containers:
|
||||
- image: chadmoon/jenkins-docker-kubectl:latest
|
||||
name: jenkins
|
||||
securityContext:
|
||||
privileged: true
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: jenkins
|
||||
volumeMounts:
|
||||
- name: jenkins-persistent-storage
|
||||
mountPath: /root/.jenkins
|
||||
- name: docker
|
||||
mountPath: /var/run/docker.sock
|
||||
volumes:
|
||||
- name: docker
|
||||
hostPath:
|
||||
path: /var/run/docker.sock
|
||||
- name: jenkins-persistent-storage
|
||||
persistentVolumeClaim:
|
||||
claimName: jenkins-claim
|
||||
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: jenkins-services
|
||||
annotations:
|
||||
ingress.kubernetes.io/rewrite-target: /
|
||||
spec:
|
||||
backend:
|
||||
serviceName: default-http-backend
|
||||
servicePort: 80
|
||||
rules:
|
||||
- host: jenkins.127.0.0.1.xip.io
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: jenkins
|
||||
servicePort: 8080
|
|
@ -0,0 +1,39 @@
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: kubescale
|
||||
labels:
|
||||
app: kubescale
|
||||
spec:
|
||||
ports:
|
||||
- port: 3000
|
||||
targetPort: 3000
|
||||
nodePort: 31980
|
||||
selector:
|
||||
app: kubescale
|
||||
tier: kubescale
|
||||
type: NodePort
|
||||
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: kubescale
|
||||
labels:
|
||||
app: kubescale
|
||||
spec:
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: kubescale
|
||||
tier: kubescale
|
||||
spec:
|
||||
containers:
|
||||
- image: 127.0.0.1:30400/kubescale:latest
|
||||
imagePullPolicy: Always
|
||||
name: kubescale
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
name: kubescale
|
|
@ -0,0 +1,142 @@
|
|||
kind: PersistentVolume
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: registry
|
||||
labels:
|
||||
type: local
|
||||
spec:
|
||||
capacity:
|
||||
storage: 4Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
hostPath:
|
||||
path: "/data/registry/"
|
||||
|
||||
---
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: registry-claim
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 4Gi
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: registry
|
||||
labels:
|
||||
app: registry
|
||||
spec:
|
||||
ports:
|
||||
- port: 5000
|
||||
targetPort: 5000
|
||||
nodePort: 30400
|
||||
name: registry
|
||||
selector:
|
||||
app: registry
|
||||
tier: registry
|
||||
type: NodePort
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: registry
|
||||
labels:
|
||||
app: registry
|
||||
spec:
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: registry
|
||||
tier: registry
|
||||
spec:
|
||||
containers:
|
||||
- image: registry:2
|
||||
name: registry
|
||||
volumeMounts:
|
||||
- name: docker
|
||||
mountPath: /var/run/docker.sock
|
||||
- name: registry-persistent-storage
|
||||
mountPath: /var/lib/registry
|
||||
ports:
|
||||
- containerPort: 5000
|
||||
name: registry
|
||||
- name: registryui
|
||||
image: hyper/docker-registry-web
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
env:
|
||||
- name: REGISTRY_URL
|
||||
value: http://localhost:5000/v2
|
||||
- name: REGISTRY_NAME
|
||||
value: cluster-registry
|
||||
volumes:
|
||||
- name: docker
|
||||
hostPath:
|
||||
path: /var/run/docker.sock
|
||||
- name: registry-persistent-storage
|
||||
persistentVolumeClaim:
|
||||
claimName: registry-claim
|
||||
|
||||
# ---
|
||||
# apiVersion: extensions/v1beta1
|
||||
# kind: Deployment
|
||||
# metadata:
|
||||
# name: registryui
|
||||
# spec:
|
||||
# replicas: 1
|
||||
# template:
|
||||
# metadata:
|
||||
# labels:
|
||||
# app: registryui
|
||||
# spec:
|
||||
# containers:
|
||||
# - name: registryui
|
||||
# image: hyper/docker-registry-web
|
||||
# ports:
|
||||
# - containerPort: 8080
|
||||
# env:
|
||||
# - name: REGISTRY_URL
|
||||
# value: http://registry:5000/v2
|
||||
# - name: REGISTRY_NAME
|
||||
# value: cluster-registry
|
||||
|
||||
# ---
|
||||
# apiVersion: v1
|
||||
# kind: Service
|
||||
# metadata:
|
||||
# name: registryui
|
||||
# labels:
|
||||
# app: registryui
|
||||
# spec:
|
||||
# ports:
|
||||
# - port: 8080
|
||||
# targetPort: 8080
|
||||
# name: registry
|
||||
# selector:
|
||||
# app: registryui
|
||||
# tier: registryui
|
||||
# type: NodePort
|
||||
|
||||
|
||||
# ---
|
||||
# apiVersion: extensions/v1beta1
|
||||
# kind: Ingress
|
||||
# metadata:
|
||||
# name: registryui-ingress
|
||||
# spec:
|
||||
# rules:
|
||||
# - host: registry.192.168.64.3.xip.io
|
||||
# http:
|
||||
# paths:
|
||||
# - path: /
|
||||
# backend:
|
||||
# serviceName: registryui
|
||||
# servicePort: 8080
|
|
@ -0,0 +1,43 @@
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: set
|
||||
labels:
|
||||
app: set
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
selector:
|
||||
app: set
|
||||
tier: set
|
||||
type: NodePort
|
||||
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: set
|
||||
labels:
|
||||
app: set
|
||||
spec:
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: set
|
||||
tier: set
|
||||
|
||||
spec:
|
||||
containers:
|
||||
- name: lifecycle-demo-container
|
||||
image: 127.0.0.1:30400/set:latest
|
||||
|
||||
lifecycle:
|
||||
postStart:
|
||||
exec:
|
||||
command: ["/up.sh"]
|
||||
preStop:
|
||||
exec:
|
||||
command: ["/down.sh"]
|
|
@ -0,0 +1,35 @@
|
|||
apiVersion: v1
|
||||
kind: Deployment
|
||||
apiVersion: extensions/v1beta1
|
||||
metadata:
|
||||
name: traefik-ingress-controller
|
||||
namespace: kube-system
|
||||
labels:
|
||||
k8s-app: traefik-ingress-lb
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
k8s-app: traefik-ingress-lb
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: traefik-ingress-lb
|
||||
name: traefik-ingress-lb
|
||||
spec:
|
||||
terminationGracePeriodSeconds: 60
|
||||
hostNetwork: true
|
||||
containers:
|
||||
- image: traefik
|
||||
name: traefik-ingress-lb
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
hostPort: 80
|
||||
- name: admin
|
||||
containerPort: 8081
|
||||
args:
|
||||
- -d
|
||||
- --web
|
||||
- --web.address=:8081
|
||||
- --kubernetes
|
|
@ -0,0 +1,18 @@
|
|||
#!/bin/sh
|
||||
|
||||
if [ "$1" = "" ]; then
|
||||
echo "Usage: ksh <pod> [flags_to_kubectl]"
|
||||
exit 1
|
||||
fi
|
||||
POD=$1
|
||||
shift
|
||||
|
||||
COLUMNS=`tput cols`
|
||||
LINES=`tput lines`
|
||||
TERM=xterm
|
||||
KUBE_SHELL=${KUBE_SHELL:-bash}
|
||||
kubectl exec -i -t $POD "$@" -- env COLUMNS=$COLUMNS LINES=$LINES TERM=$TERM "$KUBE_SHELL"
|
||||
|
||||
#$ ./ksh pod_name
|
||||
#$ ./ksh pod_name --namespace=kube-system
|
||||
#$ KUBE_SHELL=sh ./ksh pod_name
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"name": "app",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"@blueprintjs/core": "^1.12.0",
|
||||
"body-parser": "^1.17.1",
|
||||
"classnames": "^2.2.5",
|
||||
"express": "^4.15.2",
|
||||
"express-ws": "^3.0.0",
|
||||
"node-etcd": "^5.0.3",
|
||||
"node-serialize": "0.0.4",
|
||||
"nodejs-etcd": "^0.1.1",
|
||||
"react": "^15.4.2",
|
||||
"react-addons-css-transition-group": "^15.4.2",
|
||||
"react-dom": "^15.4.2",
|
||||
"socket.io": "^1.7.3",
|
||||
"tether": "^1.4.0",
|
||||
"ws": "^2.2.1"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "node index.js"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
|
@ -0,0 +1,232 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
|
||||
|
||||
<link href="https://unpkg.com/normalize.css@^4.1.1" rel="stylesheet" />
|
||||
<link href="https://unpkg.com/@blueprintjs/core@^1.11.0/dist/blueprint.css" rel="stylesheet" />
|
||||
|
||||
<meta charset="utf-8">
|
||||
<title>Chat example</title>
|
||||
<script src="/socket.io/socket.io.js"></script>
|
||||
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
|
||||
<script src="http://code.jquery.com/color/jquery.color-2.1.2.min.js"></script>
|
||||
|
||||
<style>
|
||||
|
||||
|
||||
|
||||
.card{
|
||||
width: 250px;
|
||||
margin: 5px;
|
||||
float: left;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
<script>
|
||||
var socket = io();
|
||||
|
||||
var firstRun = true;
|
||||
|
||||
socket.on('hit', function(msg){
|
||||
console.log("hit!" + msg.podId)
|
||||
pulse(msg.podId);
|
||||
|
||||
});
|
||||
|
||||
|
||||
socket.on('pods', function(msg){
|
||||
console.log(msg);
|
||||
|
||||
setInterval(function(){
|
||||
if ($("#current").val() != $("#count").val()){
|
||||
$("#progress").show();
|
||||
}else{
|
||||
$("#progress").hide();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$("#pods").html('');
|
||||
|
||||
$("#current").val(msg.pods.length)
|
||||
if(firstRun){
|
||||
$("#count").val(msg.pods.length)
|
||||
firstRun = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
msg.pods.forEach(function(pod) {
|
||||
|
||||
|
||||
|
||||
|
||||
$("#pods").append('<div style="position:relative;" class="' + pod.value + ' card pt-card pt-elevation-2">' + pod.value + '</div>')
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
})
|
||||
|
||||
function down(){
|
||||
$("#count").val(($("#count").val()*1) - 1);
|
||||
scale();
|
||||
}
|
||||
|
||||
function up(){
|
||||
$("#count").val(($("#count").val()*1) + 1);
|
||||
scale();
|
||||
}
|
||||
|
||||
function scale() {
|
||||
$.post( "/scale", { count: $("#count").val() } );
|
||||
|
||||
$("#progress").show();
|
||||
|
||||
}
|
||||
|
||||
function loadTest() {
|
||||
$.post( "/loadtest/" + $("#loadType").val() , { count: $("#loadTest").val() } );
|
||||
|
||||
//$("#progress").show();
|
||||
|
||||
//pulse("set-1165364669-d0lsf")
|
||||
|
||||
}
|
||||
|
||||
function pulse(podId) {
|
||||
//$('.pods').removeClass('pulse')
|
||||
|
||||
|
||||
|
||||
// $('.' + podId + ' .star').fadeIn( 300, function() {
|
||||
|
||||
// $('.' + podId + ' .star').fadeOut( 300)
|
||||
|
||||
// });
|
||||
|
||||
//$('.' + podId + ' .star').show().fadeOut(500)
|
||||
|
||||
//$('.' + podId).slideUp(200).slideDown(200);
|
||||
|
||||
//var el = $('<div class="star" style="top:5px;right:5px;font-size:20px;color:#3DCC91">◉</div>');
|
||||
|
||||
|
||||
$('.' + podId).animate( { backgroundColor: "#3DCC91" }, 500 ).animate( { backgroundColor: "#ffffff" }, 500 ).delay(1000);
|
||||
|
||||
|
||||
|
||||
//el.fadeOut(600)
|
||||
|
||||
|
||||
|
||||
//$('.' + podId).append()
|
||||
//$('.' + podId + ' .star').fadeIn(300).fadeOut(300)
|
||||
|
||||
|
||||
//$('.' + podId).append("<div></div>")
|
||||
|
||||
// $('.' + podId).css("backgroundColor", '#3DCC91');
|
||||
// $('.' + podId).animate({backgroundColor: '#ffffff'}, 500);
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="pt-navbar pt-dark">
|
||||
<div class="pt-navbar-group pt-align-left">
|
||||
<div class="pt-navbar-heading">KubeScale</div>
|
||||
|
||||
<div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="pt-navbar-group pt-align-right">
|
||||
|
||||
|
||||
Current Replicas: <div class="pt-numeric-input pt-control-group"><div class="pt-input-group"><input size="3" id="current" type="text" class="pt-input" readonly style="padding-right: 0px;"></div></div>
|
||||
|
||||
|
||||
|
||||
<span class="pt-navbar-divider"></span>
|
||||
|
||||
Desired Replicas: <div class="pt-numeric-input pt-control-group"><div class="pt-input-group"><input size="3" type="text" onChange="scale()" id="count" class="pt-input" style="padding-right: 0px;"></div><div class="pt-button-group pt-vertical pt-fixed"><button onClick="up()" type="button" class="pt-button pt-icon-chevron-up"></button><button onClick="down()" type="button" class="pt-button pt-icon-chevron-down"></button></div></div>
|
||||
|
||||
<span class="pt-navbar-divider"></span>
|
||||
<!--
|
||||
<div class="pt-numeric-input pt-control-group"><div class="pt-input-group"><input id="loadTest" style="width:40px" type="text" class="pt-input" style="padding-right: 0px;"></div><div class="pt-button-group pt-vertical pt-fixed"><button type="button" class="pt-button pt-icon-chevron-up"></button><button type="button" class="pt-button pt-icon-chevron-down"></button></div></div>
|
||||
-->
|
||||
# of Requests:
|
||||
|
||||
|
||||
|
||||
<div class="pt-control-group">
|
||||
<div class="pt-input-group">
|
||||
|
||||
<input type="text" size="3" id="loadTest" class="pt-input" />
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="pt-input-group">
|
||||
|
||||
|
||||
|
||||
<div class="pt-select">
|
||||
<select id="loadType">
|
||||
|
||||
<option selected value="concurrent">Concurrent</option>
|
||||
<option value="consecutive">Consecutive</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<button type="button" onClick="loadTest()" class="pt-button pt-intent-success">Load Test</button>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="pt-input-group">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</nav>
|
||||
<div style="height:5px;">
|
||||
<div id="progress" class="pt-progress-bar pt-intent-primary">
|
||||
<div class="pt-progress-meter" style="width: 100%"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="pods"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,27 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
echo "installing etcd operator"
|
||||
kubectl create -f https://raw.githubusercontent.com/coreos/etcd-operator/master/example/deployment.yaml
|
||||
kubectl rollout status -f https://raw.githubusercontent.com/coreos/etcd-operator/master/example/deployment.yaml
|
||||
|
||||
until kubectl get thirdpartyresource cluster.etcd.coreos.com
|
||||
do
|
||||
echo "waiting for operator"
|
||||
sleep 2
|
||||
done
|
||||
|
||||
echo "pausing for 10 seconds for operator to settle"
|
||||
sleep 10
|
||||
|
||||
kubectl create -f https://raw.githubusercontent.com/coreos/etcd-operator/master/example/example-etcd-cluster.yaml
|
||||
|
||||
echo "installing etcd cluster service"
|
||||
kubectl create -f https://raw.githubusercontent.com/coreos/etcd-operator/master/example/example-etcd-cluster-nodeport-service.json
|
||||
|
||||
echo "waiting for etcd cluster to turnup"
|
||||
|
||||
until kubectl get pod example-etcd-cluster-0002
|
||||
do
|
||||
echo "waiting for etcd cluster to turnup"
|
||||
sleep 2
|
||||
done
|
|
@ -0,0 +1,73 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo "creating pod-list etcd directory"
|
||||
kubectl exec -it example-etcd-cluster-0000 apk update
|
||||
kubectl exec -it example-etcd-cluster-0000 apk add ca-certificates
|
||||
kubectl exec -it example-etcd-cluster-0000 apk update-ca-certificates
|
||||
kubectl exec -it example-etcd-cluster-0000 apk add bash wget
|
||||
kubectl exec -it example-etcd-cluster-0000 wget https://gist.githubusercontent.com/moondev/86ebfc39998049d3f0c10848f4c72c57/raw/62cb237a115d4884cec4c5d94751cf5586f44b4b/mkdir.sh
|
||||
kubectl exec -it example-etcd-cluster-0000 chmod +x mkdir.sh
|
||||
kubectl exec -it example-etcd-cluster-0000 /mkdir.sh
|
||||
|
||||
# echo "building kubescale image"
|
||||
|
||||
# TAG=latest
|
||||
|
||||
# docker build -t 127.0.0.1:30400/kubescale:$TAG -f
|
||||
|
||||
# # echo "building set image"
|
||||
|
||||
# cd set; docker build -t 127.0.0.1:30400/set:$TAG -f set/Dockerfile .
|
||||
|
||||
|
||||
# echo "forwarding registry port"
|
||||
|
||||
# export MINIKUBEIP=`minikube ip`
|
||||
|
||||
# #temp container for forwarding to registry
|
||||
# docker run -d -e "MINIKUBEIP=$MINIKUBEIP" --name socat-registry -p 30400:5000 chadmoon/socat:latest bash -c "socat TCP4-LISTEN:5000,fork,reuseaddr TCP4:$MINIKUBEIP:30400"
|
||||
|
||||
# sleep 5
|
||||
|
||||
# echo "pushing kubescale image"
|
||||
# docker push 127.0.0.1:30400/kubescale:latest
|
||||
# docker push 127.0.0.1:30400/set:latest
|
||||
|
||||
# echo "pushing set image"
|
||||
|
||||
# docker push 127.0.0.1:30400/set:latest
|
||||
|
||||
# sleep 2
|
||||
# echo "killing port-forward"
|
||||
|
||||
# docker stop socat-registry
|
||||
# docker rm socat-registry
|
||||
|
||||
# echo "deploying kubescale and set"
|
||||
|
||||
# kubectl apply -f k8s/kubescale.yml
|
||||
# kubectl rollout status deployment/kubescale
|
||||
|
||||
# kubectl apply -f k8s/set.yml
|
||||
# kubectl rollout status deployment/set
|
||||
|
||||
|
||||
# #temp container for forwarding to registry
|
||||
|
||||
|
||||
# docker stop socat-minikube
|
||||
# docker rm socat-minikube
|
||||
|
||||
# proxy container for ingress
|
||||
|
||||
# docker run -d -e "MINIKUBEIP=$MINIKUBEIP" --name socat-minikube -p 80:80 chadmoon/socat:latest bash -c "socat TCP4-LISTEN:80,fork,reuseaddr TCP4:$MINIKUBEIP:80"
|
||||
|
||||
# # kubectl apply -f k8s/ing.yml
|
||||
|
||||
# kubectl apply -f k8s/jenkins.yml
|
||||
# kubectl rollout status deployments/jenkins
|
||||
|
||||
# sleep 10
|
||||
|
||||
# open http://$MINIKUBEIP:31980 || true
|
||||
# xdg-open http://$MINIKUBEIP:31980 || true
|
50
steps.yml
50
steps.yml
|
@ -44,7 +44,7 @@ parts:
|
|||
com: docker push 127.0.0.1:30400/hello-kenzan:latest
|
||||
|
||||
- cap: Stop the registry proxy.
|
||||
com: docker stop socat-registry; docker rm socat-registry
|
||||
com: docker stop socat-registry;
|
||||
|
||||
- cap: Now that our image is on the cluster we can deploy the manifests
|
||||
com: kubectl apply -f applications/hello-kenzan/k8s/deployment.yaml
|
||||
|
@ -62,14 +62,48 @@ parts:
|
|||
- cap: Get Jenkins admin password
|
||||
com: kubectl exec -it `kubectl get pods --selector=app=jenkins --output=jsonpath={.items..metadata.name}` cat /root/.jenkins/secrets/initialAdminPassword
|
||||
|
||||
- cap: Enter the admin password from above and choose "suggested plugins". Create a new job with type pipeline. Scroll down and under "pipeline script" choose "Pipeline script from SCM". Under SCM choose GIT. For "repository url" enter https://github.com/kenzanlabs/kubernetes-ci-cd.git. Save and run the job.
|
||||
- cap: Enter the admin password from above and choose "suggested plugins". Create a new job with type pipeline. Scroll down and under "pipeline script" choose "Pipeline script from SCM". Under SCM choose GIT. Fork repo and put "repository url" as your fork, such as https://github.com/kenzanlabs/kubernetes-ci-cd.git. Save and run the job.
|
||||
com: minikube service jenkins
|
||||
|
||||
# - name: Part 3
|
||||
# intro: part 3 intro here
|
||||
- cap: View updated application
|
||||
com: minikube service hello-kenzan
|
||||
|
||||
# - name: Part 4
|
||||
# intro: part 4 intro here
|
||||
- cap: Push a change to your fork. Run job again. View changes
|
||||
com: minikube service hello-kenzan
|
||||
|
||||
# - name: Part 5
|
||||
# intro: part 5 intro here
|
||||
- name: Part 4
|
||||
intro: Kubescale
|
||||
steps:
|
||||
|
||||
- cap: Bootstrap etcd operator on the cluster
|
||||
com: scripts/etcd.sh
|
||||
|
||||
- cap: Setup etcd directory for kubescale
|
||||
com: scripts/kubescale.sh
|
||||
|
||||
- cap: build kubescale image
|
||||
com: docker build -t 127.0.0.1:30400/kubescale:latest -f applications/kubescale/Dockerfile applications/kubescale
|
||||
|
||||
- cap: build scaling image
|
||||
com: docker build -t 127.0.0.1:30400/set:latest -f applications/kubescale/set/Dockerfile applications/kubescale/set
|
||||
|
||||
- cap: Start the registry proxy.
|
||||
com: docker start socat-registry
|
||||
|
||||
- cap: Push the kubescale image
|
||||
com: docker push 127.0.0.1:30400/kubescale:latest
|
||||
|
||||
- cap: Push the scaling image
|
||||
com: docker push 127.0.0.1:30400/set:latest
|
||||
|
||||
- cap: Stop the registry proxy
|
||||
com: docker stop socat-registry
|
||||
|
||||
- cap: Deploy kubescale
|
||||
com: kubectl apply -f applications/kubescale/k8s/kubescale.yml; kubectl rollout status deployment/kubescale
|
||||
|
||||
- cap: Deploy scaling set
|
||||
com: kubectl apply -f applications/kubescale/k8s/set.yml; kubectl rollout status deployment/set
|
||||
|
||||
- cap: View kubescale application
|
||||
com: minikube service kubescale
|
Загрузка…
Ссылка в новой задаче