Prerequisite #1
Ability to deploy to any server inside a cluster that meets hardware requirements
Deployment
The Code
git clone https://github.com/vfarcic/go-demo.git
cd go-demo
cat docker-compose-test.yml
docker-compose -f docker-compose-test.yml run --rm unit
ll
cat Dockerfile
docker build -t vfarcic/go-demo .
# docker push vfarcic/go-demo
Deployment
Run
docker-compose up -d db app
docker-compose ps
GO_DEMO_PORT=<PORT>
curl -i -XPUT localhost:$GO_DEMO_PORT/demo/hello
docker-compose down
docker-compose ps
Deployment
Run in cluster
export DOCKER_HOST=tcp://swarm-master:2375
docker ps -a --format "table {{.Names}}\t{{.Status}}"
docker info
docker-compose up -d db app
docker-compose ps
curl swarm-master:8500/v1/catalog/service/go-demo \
| jq '.'
Deployment
Run
Deployment
Proxy
curl -i localhost/demo/hello
sudo docker run -d \
--name docker-flow-proxy \
-e CONSUL_ADDRESS=10.100.192.200:8500 \
-p 80:80 -p 8081:8080 \
vfarcic/docker-flow-proxy
curl "localhost:8081/v1/docker-flow-proxy/reconfigure?serviceName=go-demo&servicePath=/demo" \
| jq '.'
curl -i localhost/demo/hello
Deployment
Proxy: Operations
Deployment
Proxy: User
Deployment
Scale
docker-compose ps
docker-compose scale app=3
docker-compose ps
curl "localhost:8081/v1/docker-flow-proxy/reconfigure?serviceName=go-demo&servicePath=/demo" \
| jq '.'
curl -i localhost/demo/hello # Repeat a few times
docker-compose logs app
docker-compose down
Deployment
Scale With Limits
cat docker-compose-limits.yml
docker-compose -f docker-compose-limits.yml up -d db app-big
docker info
docker-compose -f docker-compose-limits.yml up -d db app-small
docker-compose -f docker-compose-limits.yml scale app-small=10
docker info
docker-compose -f docker-compose-limits.yml scale app-big=2
docker-compose -f docker-compose-limits.yml down
Deployment
Networking
docker-compose up -d db app
docker-compose scale app=2
docker-compose ps
curl "localhost:8081/v1/docker-flow-proxy/reconfigure?serviceName=go-demo&servicePath=/demo" \
| jq '.'
curl -i -XPUT localhost/demo/person?name=Viktor
curl -i -XPUT localhost/demo/person?name=Sara
curl -i localhost/demo/person
Deployment
Networking
docker-compose exec app ping -c 1 db
docker-compose exec db ping -c 1 godemo_app_1
docker-compose exec db ping -c 1 godemo_app_2
docker-compose down
Deployment
Networking
Prerequisite #3
Ability to monitor hardware and dynamically adjust cluster capacity (elasticity)
Hardware Health Checks and Watches
Hard Disk Script
df -h
set -- $(df -h | awk '$NF=="/"{print $2" "$3" "$5}')
total=$1
used=$2
used_percent=${3::-1}
printf "Disk Usage: %s/%s (%s%%)\n" $used $total $used_percent
Hardware Health Checks and Watches
Hard Disk Script
exit
vagrant ssh swarm-master
sudo mkdir -p /data/consul/scripts
Hardware Health Checks and Watches
Hard Disk Script
echo '#!/usr/bin/env bash
set -- $(df -h | awk '"'"'$NF=="/"{print $2" "$3" "$5}'"'"')
total=$1
used=$2
used_percent=${3::-1}
printf "Disk Usage: %s/%s (%s%%)\n" $used $total $used_percent
if [ $used_percent -gt 95 ]; then
exit 2
elif [ $used_percent -gt 80 ]; then
exit 1
else
exit 0
fi
' | sudo tee /data/consul/scripts/disk.sh
Hardware Health Checks and Watches
Hard Disk Script
sudo chmod +x /data/consul/scripts/disk.sh
/data/consul/scripts/disk.sh
echo $?
Hardware Health Checks and Watches
Hard Disk Check
echo '{
"checks": [
{
"id": "disk",
"name": "Disk utilization",
"notes": "Critical 95% util, warning 80% util",
"script": "/data/consul/scripts/disk.sh",
"interval": "10s"
}
]
}' | sudo tee /data/consul/config/consul_check.json
sudo killall -HUP consul
Hardware Health Checks and Watches
Hard Disk Check
echo '#!/usr/bin/env bash
read -r JSON
STATUS_ARRAY=($(echo "$JSON" | jq -r ".[].Status"))
CHECK_ID_ARRAY=($(echo "$JSON" | jq -r ".[].CheckID"))
LENGTH=${#STATUS_ARRAY[*]}
for (( i=0; i<=$(( $LENGTH -1 )); i++ ))
do
CHECK_ID=${CHECK_ID_ARRAY[$i]}
STATUS=${STATUS_ARRAY[$i]}
echo -e "Triggering Jenkins job http://10.100.198.200:8080/job/hardware-notification/build"
curl -X POST http://10.100.198.200:8080/job/hardware-notification/build \
--data-urlencode json="{\"parameter\": [{\"name\":\"checkId\", \"value\":\"$CHECK_ID\"}, {\"name\":\"status\", \"value\":\"$STATUS\"}]}"
done' | sudo tee /data/consul/scripts/manage_watches.sh
sudo chmod +x /data/consul/scripts/manage_watches.sh
Hardware Health Checks and Watches
Hard Disk Check
echo '{
"watches": [
{
"type": "checks",
"state": "warning",
"handler": "/data/consul/scripts/manage_watches.sh >>/data/consul/logs/watches.log"
}, {
"type": "checks",
"state": "critical",
"handler": "/data/consul/scripts/manage_watches.sh >>/data/consul/logs/watches.log"
}
]
}' | sudo tee /data/consul/config/watches.json
Hardware Health Checks and Watches
Cluster Hardware Checks
vagrant ssh cd
export DOCKER_HOST=tcp://swarm-master:2375
cat /vagrant/ansible/swarm-healing.yml
cat /vagrant/ansible/roles/consul-healing/files/mem.sh
ansible-playbook /vagrant/ansible/swarm-healing.yml \
-i /vagrant/ansible/hosts/prod \
--extra-vars "elk_ip=10.100.198.200"
http://10.100.192.200:8500/ui/ > Nodes
Prerequisite #5
Ability to predict the future and execute proactive actions
Proactive Healing
Scheduled Scaling
Build With Parameters > Build
Proactive Healing
Scheduled Descaling
Build With Parameters > Build
Proactive Healing
Proxy Stats
Proactive Healing
ELK Setup
cat /vagrant/ansible/roles/logstash/files/haproxy.conf
ansible-playbook /vagrant/ansible/elk-local.yml \
--extra-vars "logstash_config=haproxy.conf" -c local
sudo docker logs logstash
http://10.100.198.200:5601/
Proactive Healing
LogStash API
curl http://10.100.198.200:9200/logstash-*/_search | jq '.'
Proactive Healing
LogStash API
curl http://10.100.198.200:9200/logstash-*/_search -d '{
"query": {
"bool": {
"must": { "match": { "tags" : "haproxy_stats" } },
"must": { "match": { "haproxy_stats.svname" : "BACKEND" } },
"must": { "range": { "@timestamp": { "gt" : "now-1h" } } }
}
}
}' | jq '.'
Proactive Healing
LogStash API
curl http://10.100.198.200:9200/logstash-*/_search -d '{
"size" : 0,
"query": {
"bool": {
"must": { "match": { "tags" : "haproxy_stats" } },
"must": { "match": { "haproxy_stats.svname" : "BACKEND" } },
"must": { "range": { "@timestamp": { "gt" : "now-1h" } } }
}
},
"aggs" : {
"services" : {
"terms" : { "field" : "haproxy_stats.pxname.raw" },
"aggs": { "avg_rtime": { "avg": { "field": "haproxy_stats.rtime" } } }
}
}
}' | jq '.'
Proactive Healing
LogStash API
curl http://10.100.198.200:9200/logstash-*/_search -d '{
"size" : 0,
"query": {
"bool": {
"must": { "match": { "tags" : "haproxy_stats" } },
"must": { "match": { "haproxy_stats.svname" : "BACKEND" } },
"must": { "match": { "haproxy_stats.pxname.raw" : "go-demo-app-be" } },
"must": { "range": { "@timestamp": { "gt" : "now-1h" } } }
}
},
"aggs" : {
"avg_rtime" : {
"avg": { "field": "haproxy_stats.rtime" }
}
}
}' | jq '.'
Proactive Healing
Consul / Jenkins
cat /vagrant/ansible/roles/consul-healing/templates/rtime_up.sh
cat /vagrant/ansible/roles/consul-healing/templates/rtime_down.sh
cat /vagrant/ansible/roles/consul-healing/templates/manage_watches.sh
cat consul_check.ctmpl
http://10.100.198.200:8080/job/service-scale/configure
Proactive Healing
Consul
exit
vagrant ssh swarm-master
sudo sed -i "s/1000 2000/1 2/" /data/consul/config/go-demo_check.json
sudo killall -HUP consul
exit
vagrant ssh cd
curl localhost/demo/hello?delay=2000 # Repeat
Proactive Healing
Consul
exit
vagrant ssh swarm-master
sudo sed -i "s/1 2/1000 2000/" /data/consul/config/go-demo_check.json
sudo killall -HUP consul