SlideShare a Scribd company logo
1 of 63
Download to read offline
Presented by: Jakub Wądołowski (@jwadolowski)
+
(Re)discover your AEM
+
Environment
complexity
Complexity keeps growing
+
https://flic.kr/p/p2ZWXH
Start point
+
The next stage
+
Traffic volume keeps growing
+
Typical AEM project scope
• many environments (3+)
• dozens of IP addresses
• a few internal/external (micro)services
• hundreds of connections
+
Things get complicated quickly
+
Hardcoding or manual configuration
+
https://flic.kr/p/bMbzcn
+
Solution research
What’s on the market
• Configuration management
• Chef
• Puppet
• Ansible
• Service discovery
• Consul
• ZooKeeper
• etcd
• Doozer
+
Why Consul? (1)
• Solves 4 basic problems
• service discovery
• load balancing
• health checking
• key-value configuration
+
Why Consul? (2)
• Single Go binary
• Super simple deployment
• Datacenter aware
• Works everywhere (no multicast)
• Easy to operate
+
Consul architecture
• Agent installed on every server
• 2 types of agents
• client
• server (3 or 5 in each DC)
• Communication over gossip protocol
• Queries always go to local agent
+
+
$ consul members
Node Address Status Type Build Protocol DC
abcd-uat-a1 172.11.5.203:8301 alive client 0.6.3 2 eu-west-1a
abcd-uat-adnx1 172.11.6.21:8301 alive client 0.6.3 2 eu-west-1a
abcd-uat-dnx1 172.11.4.122:8301 alive server 0.6.3 2 eu-west-1a
abcd-uat-ips1 172.11.4.6:8301 alive client 0.6.3 2 eu-west-1a
abcd-uat-p1 172.11.5.62:8301 alive server 0.6.3 2 eu-west-1a
abcd-uat-rl1 172.11.6.46:8301 alive client 0.6.3 2 eu-west-1a
abcd-uat-sftp1 172.11.7.23:8301 alive client 0.6.3 2 eu-west-1a
abcd-uat-sm1 172.11.5.157:8301 alive client 0.6.3 2 eu-west-1a
abcd-uat-tcss1 172.11.4.196:8301 alive server 0.6.3 2 eu-west-1a
$ consul members -wan
Node Address Status Type Build Protocol DC
abcd-uat-dnx1.eu-west-1a 172.11.4.122:8302 alive server 0.6.3 2 eu-west-1a
abcd-uat-dnx2.eu-west-1b 172.11.4.141:8302 alive server 0.6.3 2 eu-west-1b
abcd-uat-p1.eu-west-1a 172.11.5.62:8302 alive server 0.6.3 2 eu-west-1a
abcd-uat-p2.eu-west-1b 172.11.5.91:8302 alive server 0.6.3 2 eu-west-1b
abcd-uat-tcss1.eu-west-1a 172.11.4.196:8302 alive server 0.6.3 2 eu-west-1a
abcd-uat-tcss2.eu-west-1b 172.11.4.241:8302 alive server 0.6.3 2 eu-west-1b
Service registry
+
https://flic.kr/p/cwV8W7
+
{
"service": {
"id": "aem_author",
"name": "aem",
"port": 6102,
"tags": [
"author",
"a1"
]
}
}
Discover!
+
https://flic.kr/p/CGmgy3
Services, not IP
addresses!
+
HTTP API
• /v1/catalog/nodes
• /v1/catalog/node/<node>
• /v1/catalog/services
• /v1/catalog/service/<service>
• /v1/catalog/node/<node>
• /v1/catalog/register
• /v1/catalog/deregister
+
+
$ curl -s "http://localhost:8500/v1/catalog/services"
{
"aem": [ "author", "a1", "publish", "p1" ],
"dispatcher": [ "d1" ],
"sftp": [],
"solr": [ "sm1", "slave", "ss1", "master" ],
"tomcat": [ "tm1" ]
}
+
$ curl -s "http://localhost:8500/v1/catalog/service/aem"
[
{
"Address": "10.0.2.15",
"Node": "xyz-vagrant",
"ServiceID": "aem_author",
"ServiceName": "aem",
"ServicePort": 6102,
"ServiceTags": [ “author", “a1" ]
},
{
"Address": "10.0.2.15",
"Node": "xyz-vagrant",
"ServiceID": "aem_publish",
"ServiceName": "aem",
"ServicePort": 6103,
"ServiceTags": [ “publish", “p1" ]
}
]
+
$ curl -s "http://localhost:8500/v1/catalog/service/aem?tag=author"
[
{
"Address": "10.0.2.15",
"CreateIndex": 577,
"ModifyIndex": 577,
"Node": "xyz-vagrant",
"ServiceAddress": "",
"ServiceEnableTagOverride": false,
"ServiceID": "aem_author",
"ServiceName": "aem",
"ServicePort": 6102,
"ServiceTags": [
"author",
"a1"
]
}
]
DNS API
+
[tag.]<service>.service[.datacenter].<domain>
<service>.service.<domain>
+
$ dig @localhost -p 8600 aem.service.consul
; <<>> DiG 9.8.3-P1 <<>> @localhost -p 8600 aem.service.consul
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2476
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available
;; QUESTION SECTION:
;aem.service.consul. IN A
;; ANSWER SECTION:
aem.service.consul. 0 IN A 172.18.5.62
aem.service.consul. 0 IN A 172.18.5.203
;; Query time: 10 msec
;; SERVER: ::1#8600(::1)
;; WHEN: Sat Jul 23 13:53:48 2016
;; MSG SIZE rcvd: 104
+
$ dig @localhost -p 8600 p1.aem.service.consul
; <<>> DiG 9.8.3-P1 <<>> @localhost -p 8600 p1.aem.service.consul
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3947
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available
;; QUESTION SECTION:
;p1.aem.service.consul. IN A
;; ANSWER SECTION:
p1.aem.service.consul. 0 IN A 10.0.2.15
;; Query time: 2 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Sat Jul 23 14:44:59 2016
;; MSG SIZE rcvd: 76
+
$ dig @localhost -p 8600 publish.aem.service.eu-west-1b.consul
; <<>> DiG 9.8.3-P1 <<>> @localhost -p 8600 publish.aem.service.eu-west-1b.consul
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36721
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available
;; QUESTION SECTION:
;publish.aem.service.eu-west-1b.consul. IN A
;; ANSWER SECTION:
publish.aem.service.eu-west-1b.consul. 0 IN A 172.18.5.91
;; Query time: 2 msec
;; SERVER: ::1#8600(::1)
;; WHEN: Sat Jul 23 13:57:01 2016
;; MSG SIZE rcvd: 108
+
$ dig @localhost -p 8600 a1.aem.service.consul SRV
; <<>> DiG 9.8.3-P1 <<>> @localhost -p 8600 a1.aem.service.consul SRV
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45677
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; QUESTION SECTION:
;a1.aem.service.consul. IN SRV
;; ANSWER SECTION:
a1.aem.service.consul. 0 IN SRV 1 1 6102 xyz-vagrant.node.eu-west-1a.consul.
;; ADDITIONAL SECTION:
xyz-vagrant.node.eu-west-1a.consul. 0 IN A 10.0.2.15
;; Query time: 0 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Sat Jul 23 22:50:14 2016
;; MSG SIZE rcvd: 17
+
Consul + AEM
Where’s my publish?
+
https://flic.kr/p/eE48CR
Replication agents
• Number of publish instances and availability
zones (DCs) is constant for each environment
• Publish to DC allocation: ID % AZ.length
• Chef’s responsible for agent configuration
+
+
(1..node['xyz-webapp']['publish_count']).each do |id|
domain = "p#{id}.aem.service.#{az[(id - 1) % az.length]}.consul"
transport_uri = "http://#{domain}:6103/bin/receive?sling:authRequestLogin=1"
cq_jcr "Author: /etc/replication/agents.author/publish#{id}}/jcr:content" do
path "/etc/replication/agents.author/publish#{id}}/jcr:content"
username node['cq']['author']['credentials']['login']
password node['cq']['author']['credentials']['password']
instance "http://localhost:#{node['cq']['author']['port']}"
properties(
'jcr:primaryType' => 'nt:unstructured',
'enabled' => 'true',
'transportUri' => transport_uri,
'transportUser' => 'admin',
'transportPassword' => node['cq']['publish']['credentials']['password'],
'cq:template' => '/libs/cq/replication/templates/agent',
'sling:resourceType' => 'cq/replication/components/agent',
'logLevel' => 'info'
)
encrypted_fields %w(transportPassword)
append false
action :create
end
end
+
(1..node['xyz-webapp']['publish_count']).each do |id|
domain = "p#{id}.aem.service.#{az[(id - 1) % az.length]}.consul"
transport_uri = "http://#{domain}:6103/bin/receive?sling:authRequestLogin=1"
cq_jcr "Author: /etc/replication/agents.author/publish#{id}}/jcr:content" do
path "/etc/replication/agents.author/publish#{id}}/jcr:content"
username node['cq']['author']['credentials']['login']
password node['cq']['author']['credentials']['password']
instance "http://localhost:#{node['cq']['author']['port']}"
properties(
'jcr:primaryType' => 'nt:unstructured',
'enabled' => 'true',
'transportUri' => transport_uri,
'transportUser' => 'admin',
'transportPassword' => node['cq']['publish']['credentials']['password'],
'cq:template' => '/libs/cq/replication/templates/agent',
'sling:resourceType' => 'cq/replication/components/agent',
'logLevel' => 'info'
)
encrypted_fields %w(transportPassword)
append false
action :create
end
end
+
(1..node['xyz-webapp']['publish_count']).each do |id|
domain = "p#{id}.aem.service.#{az[(id - 1) % az.length]}.consul"
transport_uri = "http://#{domain}:6103/bin/receive?sling:authRequestLogin=1"
cq_jcr "Author: /etc/replication/agents.author/publish#{id}}/jcr:content" do
path agent_conf_path
username node['cq']['author']['credentials']['login']
password node['cq']['author']['credentials']['password']
instance "http://localhost:#{node['cq']['author']['port']}"
properties(
'jcr:primaryType' => 'nt:unstructured',
'enabled' => 'true',
'transportUri' => transport_uri,
'transportUser' => 'admin',
'transportPassword' => node['cq']['publish']['credentials']['password'],
'cq:template' => '/libs/cq/replication/templates/agent',
'sling:resourceType' => 'cq/replication/components/agent',
'logLevel' => 'info'
)
encrypted_fields %w(transportPassword)
append false
action :create
end
end
+
(1..node['xyz-webapp']['publish_count']).each do |id|
domain = "p#{id}.aem.service.#{az[(id - 1) % az.length]}.consul"
transport_uri = "http://#{domain}:6103/bin/receive?sling:authRequestLogin=1"
cq_jcr "Author: /etc/replication/agents.author/publish#{id}}/jcr:content" do
path "/etc/replication/agents.author/publish#{id}}/jcr:content"
username node['cq']['author']['credentials']['login']
password node['cq']['author']['credentials']['password']
instance "http://localhost:#{node['cq']['author']['port']}"
properties(
'jcr:primaryType' => 'nt:unstructured',
'enabled' => 'true',
'transportUri' => transport_uri,
'transportUser' => 'admin',
'transportPassword' => node['cq']['publish']['credentials']['password'],
'cq:template' => '/libs/cq/replication/templates/agent',
'sling:resourceType' => 'cq/replication/components/agent',
'logLevel' => 'info'
)
encrypted_fields %w(transportPassword)
append false
action :create
end
end
+
(1..node['xyz-webapp']['publish_count']).each do |id|
domain = "p#{id}.aem.service.#{az[(id - 1) % az.length]}.consul"
transport_uri = "http://#{domain}:6103/bin/receive?sling:authRequestLogin=1"
cq_jcr "Author: /etc/replication/agents.author/publish#{id}}/jcr:content" do
path "/etc/replication/agents.author/publish#{id}}/jcr:content"
username node['cq']['author']['credentials']['login']
password node['cq']['author']['credentials']['password']
instance "http://localhost:#{node['cq']['author']['port']}"
properties(
'jcr:primaryType' => 'nt:unstructured',
'enabled' => 'true',
'transportUri' => transport_uri,
'transportUser' => 'admin',
'transportPassword' => node['cq']['publish']['credentials']['password'],
'cq:template' => '/libs/cq/replication/templates/agent',
'sling:resourceType' => 'cq/replication/components/agent',
'logLevel' => 'info'
)
encrypted_fields %w(transportPassword)
append false
action :create
end
end
DNS assembly
+
https://flic.kr/p/qm4gV8
Transparent DNS
• Consul DNS interface listens on port 8600
• /etc/resolv.conf accepts just IPs
• dnsmasq to the rescue
• DNS "proxy"
• listens on localhost:53
• DNS query routing
• /etc/hosts on steroids
+
+
# dnsmasq logic
if domain ~ /.consul$/
dns_query(domain, "localhost:8600")
else
internal_db.lookup(domain) || upstream_forward(domain)
end
dnsmasq - your
new primary DNS
server
+
+
# /etc/resolv.conf
nameserver 127.0.0.1
nameserver 8.8.8.8
nameserver 8.8.4.4
Pick the right one
+
https://flic.kr/p/c42Qmm
Flush agents
• 1:1 mapping between dispatcher and publish
• config wise each publish instance needs to be
exactly the same
+
dnsmasq helps again
• Yet another domain name space: .local
• Chef renders dnsmasq config using Consul data
• give me all dispatcher servers
• pick the one that matches my ID (p1 => d1)
• expose it under dispatcher.local
+
+
# /etc/dnsmasq.d/local_domains.conf
address=/dispatcher.local/172.19.9.122
address=/publish.local/172.19.9.62
address=/author.local/172.19.9.203
+
# Address of 1st dispatcher
[root@xyz-uat-p1 ~]# dig dispatcher.local +short
172.19.9.122
# Address of 2nd dispatcher
[root@xyz-uat-p2 ~]# dig dispatcher.local +short
172.19.9.141
Undocumented features
+
https://flic.kr/p/bzeVcH
+
/renders
{
/rend
{
/hostname "publish.local"
/port "6103"
/always-resolve "1"
}
}
Health checks
+
https://flic.kr/p/8rhLYf
+
{
"service": {
"check": {
"interval": "10s",
"tcp": "localhost:8080",
"timeout": "1s"
},
"id": "tomcat",
"name": "tomcat",
"port": 8080,
"tags": [
"tm1"
]
}
}
Your front load balancer
is the only one you’ll
ever need
+
Prepared queries
+
https://flic.kr/p/aHfnmc
Prepared queries
• Complex service queries
• Returns set of healthy nodes that meets
predefined criteria
• Example:
• tomcat-cluster.query.consul:8080
• use Tomcat from the same datacenter, as long
as it’s healthy. Otherwise pick the nearest one.
+
Consul locks
+
https://flic.kr/p/p4xhXr
Consul locks
• Distributed locking
• Mutual exclusion or semaphore
• Configurable amount of holders (1 by default)
+
App rollouts
+
https://flic.kr/p/xYdtNW
App rollouts
• Practical use case: deployments
• Solves "at least one of publish must be always
running" problem
+
Summary
• Services, not IP addresses
• Everything supports DNS
• Get rid of internal load balancers
• Simpler deployments
• Can’t imagine a project without Consul
+
+
THANK YOU!

More Related Content

What's hot

Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshare
tomcopeland
 
Inside Sqale's Backend at Sapporo Ruby Kaigi 2012
Inside Sqale's Backend at Sapporo Ruby Kaigi 2012Inside Sqale's Backend at Sapporo Ruby Kaigi 2012
Inside Sqale's Backend at Sapporo Ruby Kaigi 2012
Gosuke Miyashita
 
OpenNebula and SaltStack - OpenNebulaConf 2013
OpenNebula and SaltStack - OpenNebulaConf 2013OpenNebula and SaltStack - OpenNebulaConf 2013
OpenNebula and SaltStack - OpenNebulaConf 2013
databus.pro
 

What's hot (20)

Learn basic ansible using docker
Learn basic ansible using dockerLearn basic ansible using docker
Learn basic ansible using docker
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshare
 
Puppet Camp London Fall 2015 - Service Discovery and Puppet
Puppet Camp London Fall 2015 - Service Discovery and PuppetPuppet Camp London Fall 2015 - Service Discovery and Puppet
Puppet Camp London Fall 2015 - Service Discovery and Puppet
 
Testing your infrastructure with litmus
Testing your infrastructure with litmusTesting your infrastructure with litmus
Testing your infrastructure with litmus
 
Lesson Learned from Using Docker Swarm at Pronto
Lesson Learned from Using Docker Swarm at ProntoLesson Learned from Using Docker Swarm at Pronto
Lesson Learned from Using Docker Swarm at Pronto
 
Build microservice with gRPC in golang
Build microservice with gRPC in golangBuild microservice with gRPC in golang
Build microservice with gRPC in golang
 
How and Why Prometheus' New Storage Engine Pushes the Limits of Time Series D...
How and Why Prometheus' New Storage Engine Pushes the Limits of Time Series D...How and Why Prometheus' New Storage Engine Pushes the Limits of Time Series D...
How and Why Prometheus' New Storage Engine Pushes the Limits of Time Series D...
 
Hiveminder - Everything but the Secret Sauce
Hiveminder - Everything but the Secret SauceHiveminder - Everything but the Secret Sauce
Hiveminder - Everything but the Secret Sauce
 
Golang Project Layout and Practice
Golang Project Layout and PracticeGolang Project Layout and Practice
Golang Project Layout and Practice
 
Test driven infrastructure
Test driven infrastructureTest driven infrastructure
Test driven infrastructure
 
Service discovery and puppet
Service discovery and puppetService discovery and puppet
Service discovery and puppet
 
用 Go 語言打造多台機器 Scale 架構
用 Go 語言打造多台機器 Scale 架構用 Go 語言打造多台機器 Scale 架構
用 Go 語言打造多台機器 Scale 架構
 
MeaNstack on Docker
MeaNstack on DockerMeaNstack on Docker
MeaNstack on Docker
 
GDG Devfest 2019 - Build go kit microservices at kubernetes with ease
GDG Devfest 2019 - Build go kit microservices at kubernetes with easeGDG Devfest 2019 - Build go kit microservices at kubernetes with ease
GDG Devfest 2019 - Build go kit microservices at kubernetes with ease
 
Ubic
UbicUbic
Ubic
 
Inside Sqale's Backend at Sapporo Ruby Kaigi 2012
Inside Sqale's Backend at Sapporo Ruby Kaigi 2012Inside Sqale's Backend at Sapporo Ruby Kaigi 2012
Inside Sqale's Backend at Sapporo Ruby Kaigi 2012
 
Job Queue in Golang
Job Queue in GolangJob Queue in Golang
Job Queue in Golang
 
Plone deployment made easy
Plone deployment made easyPlone deployment made easy
Plone deployment made easy
 
Making environment for_infrastructure_as_code
Making environment for_infrastructure_as_codeMaking environment for_infrastructure_as_code
Making environment for_infrastructure_as_code
 
OpenNebula and SaltStack - OpenNebulaConf 2013
OpenNebula and SaltStack - OpenNebulaConf 2013OpenNebula and SaltStack - OpenNebulaConf 2013
OpenNebula and SaltStack - OpenNebulaConf 2013
 

Similar to (Re)discover your AEM

ql.io: Consuming HTTP at Scale
ql.io: Consuming HTTP at Scale ql.io: Consuming HTTP at Scale
ql.io: Consuming HTTP at Scale
Subbu Allamaraju
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
Tom Croucher
 

Similar to (Re)discover your AEM (20)

Soa with consul
Soa with consulSoa with consul
Soa with consul
 
HashiStack. To the cloud and beyond...
HashiStack. To the cloud and beyond...HashiStack. To the cloud and beyond...
HashiStack. To the cloud and beyond...
 
Real World Lessons on the Pain Points of Node.JS Application
Real World Lessons on the Pain Points of Node.JS ApplicationReal World Lessons on the Pain Points of Node.JS Application
Real World Lessons on the Pain Points of Node.JS Application
 
2019 hashiconf consul-templaterb
2019 hashiconf consul-templaterb2019 hashiconf consul-templaterb
2019 hashiconf consul-templaterb
 
Consul: Service Mesh for Microservices
Consul: Service Mesh for MicroservicesConsul: Service Mesh for Microservices
Consul: Service Mesh for Microservices
 
ql.io: Consuming HTTP at Scale
ql.io: Consuming HTTP at Scale ql.io: Consuming HTTP at Scale
ql.io: Consuming HTTP at Scale
 
Kubernetes internals (Kubernetes 해부하기)
Kubernetes internals (Kubernetes 해부하기)Kubernetes internals (Kubernetes 해부하기)
Kubernetes internals (Kubernetes 해부하기)
 
Kraken Front-Trends
Kraken Front-TrendsKraken Front-Trends
Kraken Front-Trends
 
Pyrax talk
Pyrax talkPyrax talk
Pyrax talk
 
Skydive 5/07/2016
Skydive 5/07/2016Skydive 5/07/2016
Skydive 5/07/2016
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
 
Bootstrapping multidc observability stack
Bootstrapping multidc observability stackBootstrapping multidc observability stack
Bootstrapping multidc observability stack
 
Docker In Bank Unrated
Docker In Bank UnratedDocker In Bank Unrated
Docker In Bank Unrated
 
Easy Cloud Native Transformation using HashiCorp Nomad
Easy Cloud Native Transformation using HashiCorp NomadEasy Cloud Native Transformation using HashiCorp Nomad
Easy Cloud Native Transformation using HashiCorp Nomad
 
Session: A Reference Architecture for Running Modern APIs with NGINX Unit and...
Session: A Reference Architecture for Running Modern APIs with NGINX Unit and...Session: A Reference Architecture for Running Modern APIs with NGINX Unit and...
Session: A Reference Architecture for Running Modern APIs with NGINX Unit and...
 
Service Discovery using etcd, Consul and Kubernetes
Service Discovery using etcd, Consul and KubernetesService Discovery using etcd, Consul and Kubernetes
Service Discovery using etcd, Consul and Kubernetes
 
DSLing your System For Scalability Testing Using Gatling - Dublin Scala User ...
DSLing your System For Scalability Testing Using Gatling - Dublin Scala User ...DSLing your System For Scalability Testing Using Gatling - Dublin Scala User ...
DSLing your System For Scalability Testing Using Gatling - Dublin Scala User ...
 
以Device Shadows與Rules Engine串聯實體世界
以Device Shadows與Rules Engine串聯實體世界以Device Shadows與Rules Engine串聯實體世界
以Device Shadows與Rules Engine串聯實體世界
 
Presto anatomy
Presto anatomyPresto anatomy
Presto anatomy
 
Orchestrating Docker with Terraform and Consul by Mitchell Hashimoto
Orchestrating Docker with Terraform and Consul by Mitchell Hashimoto Orchestrating Docker with Terraform and Consul by Mitchell Hashimoto
Orchestrating Docker with Terraform and Consul by Mitchell Hashimoto
 

More from Jakub Wadolowski

When dispatcher caching is not enough... (extended version)
When dispatcher caching is not enough... (extended version)When dispatcher caching is not enough... (extended version)
When dispatcher caching is not enough... (extended version)
Jakub Wadolowski
 
When dispatcher caching is not enough...
When dispatcher caching is not enough...When dispatcher caching is not enough...
When dispatcher caching is not enough...
Jakub Wadolowski
 

More from Jakub Wadolowski (12)

Don’t reduce dispatcher testing to an afterthought
Don’t reduce dispatcher testing to an afterthoughtDon’t reduce dispatcher testing to an afterthought
Don’t reduce dispatcher testing to an afterthought
 
Automated CI with AEM Cloud service
Automated CI with AEM Cloud serviceAutomated CI with AEM Cloud service
Automated CI with AEM Cloud service
 
The curious case of misrendered JSON
The curious case of misrendered JSONThe curious case of misrendered JSON
The curious case of misrendered JSON
 
The shift to the edge
The shift to the edgeThe shift to the edge
The shift to the edge
 
Image optimization at the edge
Image optimization at the edgeImage optimization at the edge
Image optimization at the edge
 
The shift to the edge
The shift to the edgeThe shift to the edge
The shift to the edge
 
Taming content delivery at scale
Taming content delivery at scaleTaming content delivery at scale
Taming content delivery at scale
 
Into the nooks and crannies of Boden’s digital transformation
Into the nooks and crannies of Boden’s digital transformationInto the nooks and crannies of Boden’s digital transformation
Into the nooks and crannies of Boden’s digital transformation
 
How to seamlessly incorporate CDN into your application stack
How to seamlessly incorporate CDN into your application stackHow to seamlessly incorporate CDN into your application stack
How to seamlessly incorporate CDN into your application stack
 
The underappreciated power of content invalidation
The underappreciated power of content invalidationThe underappreciated power of content invalidation
The underappreciated power of content invalidation
 
When dispatcher caching is not enough... (extended version)
When dispatcher caching is not enough... (extended version)When dispatcher caching is not enough... (extended version)
When dispatcher caching is not enough... (extended version)
 
When dispatcher caching is not enough...
When dispatcher caching is not enough...When dispatcher caching is not enough...
When dispatcher caching is not enough...
 

Recently uploaded

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Recently uploaded (20)

Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 

(Re)discover your AEM

  • 1. Presented by: Jakub Wądołowski (@jwadolowski) + (Re)discover your AEM
  • 7. Typical AEM project scope • many environments (3+) • dozens of IP addresses • a few internal/external (micro)services • hundreds of connections +
  • 9. Hardcoding or manual configuration + https://flic.kr/p/bMbzcn
  • 11. What’s on the market • Configuration management • Chef • Puppet • Ansible • Service discovery • Consul • ZooKeeper • etcd • Doozer +
  • 12. Why Consul? (1) • Solves 4 basic problems • service discovery • load balancing • health checking • key-value configuration +
  • 13. Why Consul? (2) • Single Go binary • Super simple deployment • Datacenter aware • Works everywhere (no multicast) • Easy to operate +
  • 14. Consul architecture • Agent installed on every server • 2 types of agents • client • server (3 or 5 in each DC) • Communication over gossip protocol • Queries always go to local agent +
  • 15.
  • 16.
  • 17. + $ consul members Node Address Status Type Build Protocol DC abcd-uat-a1 172.11.5.203:8301 alive client 0.6.3 2 eu-west-1a abcd-uat-adnx1 172.11.6.21:8301 alive client 0.6.3 2 eu-west-1a abcd-uat-dnx1 172.11.4.122:8301 alive server 0.6.3 2 eu-west-1a abcd-uat-ips1 172.11.4.6:8301 alive client 0.6.3 2 eu-west-1a abcd-uat-p1 172.11.5.62:8301 alive server 0.6.3 2 eu-west-1a abcd-uat-rl1 172.11.6.46:8301 alive client 0.6.3 2 eu-west-1a abcd-uat-sftp1 172.11.7.23:8301 alive client 0.6.3 2 eu-west-1a abcd-uat-sm1 172.11.5.157:8301 alive client 0.6.3 2 eu-west-1a abcd-uat-tcss1 172.11.4.196:8301 alive server 0.6.3 2 eu-west-1a $ consul members -wan Node Address Status Type Build Protocol DC abcd-uat-dnx1.eu-west-1a 172.11.4.122:8302 alive server 0.6.3 2 eu-west-1a abcd-uat-dnx2.eu-west-1b 172.11.4.141:8302 alive server 0.6.3 2 eu-west-1b abcd-uat-p1.eu-west-1a 172.11.5.62:8302 alive server 0.6.3 2 eu-west-1a abcd-uat-p2.eu-west-1b 172.11.5.91:8302 alive server 0.6.3 2 eu-west-1b abcd-uat-tcss1.eu-west-1a 172.11.4.196:8302 alive server 0.6.3 2 eu-west-1a abcd-uat-tcss2.eu-west-1b 172.11.4.241:8302 alive server 0.6.3 2 eu-west-1b
  • 19. + { "service": { "id": "aem_author", "name": "aem", "port": 6102, "tags": [ "author", "a1" ] } }
  • 22. HTTP API • /v1/catalog/nodes • /v1/catalog/node/<node> • /v1/catalog/services • /v1/catalog/service/<service> • /v1/catalog/node/<node> • /v1/catalog/register • /v1/catalog/deregister +
  • 23. + $ curl -s "http://localhost:8500/v1/catalog/services" { "aem": [ "author", "a1", "publish", "p1" ], "dispatcher": [ "d1" ], "sftp": [], "solr": [ "sm1", "slave", "ss1", "master" ], "tomcat": [ "tm1" ] }
  • 24. + $ curl -s "http://localhost:8500/v1/catalog/service/aem" [ { "Address": "10.0.2.15", "Node": "xyz-vagrant", "ServiceID": "aem_author", "ServiceName": "aem", "ServicePort": 6102, "ServiceTags": [ “author", “a1" ] }, { "Address": "10.0.2.15", "Node": "xyz-vagrant", "ServiceID": "aem_publish", "ServiceName": "aem", "ServicePort": 6103, "ServiceTags": [ “publish", “p1" ] } ]
  • 25. + $ curl -s "http://localhost:8500/v1/catalog/service/aem?tag=author" [ { "Address": "10.0.2.15", "CreateIndex": 577, "ModifyIndex": 577, "Node": "xyz-vagrant", "ServiceAddress": "", "ServiceEnableTagOverride": false, "ServiceID": "aem_author", "ServiceName": "aem", "ServicePort": 6102, "ServiceTags": [ "author", "a1" ] } ]
  • 27. + $ dig @localhost -p 8600 aem.service.consul ; <<>> DiG 9.8.3-P1 <<>> @localhost -p 8600 aem.service.consul ; (2 servers found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2476 ;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0 ;; WARNING: recursion requested but not available ;; QUESTION SECTION: ;aem.service.consul. IN A ;; ANSWER SECTION: aem.service.consul. 0 IN A 172.18.5.62 aem.service.consul. 0 IN A 172.18.5.203 ;; Query time: 10 msec ;; SERVER: ::1#8600(::1) ;; WHEN: Sat Jul 23 13:53:48 2016 ;; MSG SIZE rcvd: 104
  • 28. + $ dig @localhost -p 8600 p1.aem.service.consul ; <<>> DiG 9.8.3-P1 <<>> @localhost -p 8600 p1.aem.service.consul ; (2 servers found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3947 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; WARNING: recursion requested but not available ;; QUESTION SECTION: ;p1.aem.service.consul. IN A ;; ANSWER SECTION: p1.aem.service.consul. 0 IN A 10.0.2.15 ;; Query time: 2 msec ;; SERVER: 127.0.0.1#8600(127.0.0.1) ;; WHEN: Sat Jul 23 14:44:59 2016 ;; MSG SIZE rcvd: 76
  • 29. + $ dig @localhost -p 8600 publish.aem.service.eu-west-1b.consul ; <<>> DiG 9.8.3-P1 <<>> @localhost -p 8600 publish.aem.service.eu-west-1b.consul ; (2 servers found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36721 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; WARNING: recursion requested but not available ;; QUESTION SECTION: ;publish.aem.service.eu-west-1b.consul. IN A ;; ANSWER SECTION: publish.aem.service.eu-west-1b.consul. 0 IN A 172.18.5.91 ;; Query time: 2 msec ;; SERVER: ::1#8600(::1) ;; WHEN: Sat Jul 23 13:57:01 2016 ;; MSG SIZE rcvd: 108
  • 30. + $ dig @localhost -p 8600 a1.aem.service.consul SRV ; <<>> DiG 9.8.3-P1 <<>> @localhost -p 8600 a1.aem.service.consul SRV ; (2 servers found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45677 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; QUESTION SECTION: ;a1.aem.service.consul. IN SRV ;; ANSWER SECTION: a1.aem.service.consul. 0 IN SRV 1 1 6102 xyz-vagrant.node.eu-west-1a.consul. ;; ADDITIONAL SECTION: xyz-vagrant.node.eu-west-1a.consul. 0 IN A 10.0.2.15 ;; Query time: 0 msec ;; SERVER: 127.0.0.1#8600(127.0.0.1) ;; WHEN: Sat Jul 23 22:50:14 2016 ;; MSG SIZE rcvd: 17
  • 33. Replication agents • Number of publish instances and availability zones (DCs) is constant for each environment • Publish to DC allocation: ID % AZ.length • Chef’s responsible for agent configuration +
  • 34. + (1..node['xyz-webapp']['publish_count']).each do |id| domain = "p#{id}.aem.service.#{az[(id - 1) % az.length]}.consul" transport_uri = "http://#{domain}:6103/bin/receive?sling:authRequestLogin=1" cq_jcr "Author: /etc/replication/agents.author/publish#{id}}/jcr:content" do path "/etc/replication/agents.author/publish#{id}}/jcr:content" username node['cq']['author']['credentials']['login'] password node['cq']['author']['credentials']['password'] instance "http://localhost:#{node['cq']['author']['port']}" properties( 'jcr:primaryType' => 'nt:unstructured', 'enabled' => 'true', 'transportUri' => transport_uri, 'transportUser' => 'admin', 'transportPassword' => node['cq']['publish']['credentials']['password'], 'cq:template' => '/libs/cq/replication/templates/agent', 'sling:resourceType' => 'cq/replication/components/agent', 'logLevel' => 'info' ) encrypted_fields %w(transportPassword) append false action :create end end
  • 35. + (1..node['xyz-webapp']['publish_count']).each do |id| domain = "p#{id}.aem.service.#{az[(id - 1) % az.length]}.consul" transport_uri = "http://#{domain}:6103/bin/receive?sling:authRequestLogin=1" cq_jcr "Author: /etc/replication/agents.author/publish#{id}}/jcr:content" do path "/etc/replication/agents.author/publish#{id}}/jcr:content" username node['cq']['author']['credentials']['login'] password node['cq']['author']['credentials']['password'] instance "http://localhost:#{node['cq']['author']['port']}" properties( 'jcr:primaryType' => 'nt:unstructured', 'enabled' => 'true', 'transportUri' => transport_uri, 'transportUser' => 'admin', 'transportPassword' => node['cq']['publish']['credentials']['password'], 'cq:template' => '/libs/cq/replication/templates/agent', 'sling:resourceType' => 'cq/replication/components/agent', 'logLevel' => 'info' ) encrypted_fields %w(transportPassword) append false action :create end end
  • 36. + (1..node['xyz-webapp']['publish_count']).each do |id| domain = "p#{id}.aem.service.#{az[(id - 1) % az.length]}.consul" transport_uri = "http://#{domain}:6103/bin/receive?sling:authRequestLogin=1" cq_jcr "Author: /etc/replication/agents.author/publish#{id}}/jcr:content" do path agent_conf_path username node['cq']['author']['credentials']['login'] password node['cq']['author']['credentials']['password'] instance "http://localhost:#{node['cq']['author']['port']}" properties( 'jcr:primaryType' => 'nt:unstructured', 'enabled' => 'true', 'transportUri' => transport_uri, 'transportUser' => 'admin', 'transportPassword' => node['cq']['publish']['credentials']['password'], 'cq:template' => '/libs/cq/replication/templates/agent', 'sling:resourceType' => 'cq/replication/components/agent', 'logLevel' => 'info' ) encrypted_fields %w(transportPassword) append false action :create end end
  • 37. + (1..node['xyz-webapp']['publish_count']).each do |id| domain = "p#{id}.aem.service.#{az[(id - 1) % az.length]}.consul" transport_uri = "http://#{domain}:6103/bin/receive?sling:authRequestLogin=1" cq_jcr "Author: /etc/replication/agents.author/publish#{id}}/jcr:content" do path "/etc/replication/agents.author/publish#{id}}/jcr:content" username node['cq']['author']['credentials']['login'] password node['cq']['author']['credentials']['password'] instance "http://localhost:#{node['cq']['author']['port']}" properties( 'jcr:primaryType' => 'nt:unstructured', 'enabled' => 'true', 'transportUri' => transport_uri, 'transportUser' => 'admin', 'transportPassword' => node['cq']['publish']['credentials']['password'], 'cq:template' => '/libs/cq/replication/templates/agent', 'sling:resourceType' => 'cq/replication/components/agent', 'logLevel' => 'info' ) encrypted_fields %w(transportPassword) append false action :create end end
  • 38. + (1..node['xyz-webapp']['publish_count']).each do |id| domain = "p#{id}.aem.service.#{az[(id - 1) % az.length]}.consul" transport_uri = "http://#{domain}:6103/bin/receive?sling:authRequestLogin=1" cq_jcr "Author: /etc/replication/agents.author/publish#{id}}/jcr:content" do path "/etc/replication/agents.author/publish#{id}}/jcr:content" username node['cq']['author']['credentials']['login'] password node['cq']['author']['credentials']['password'] instance "http://localhost:#{node['cq']['author']['port']}" properties( 'jcr:primaryType' => 'nt:unstructured', 'enabled' => 'true', 'transportUri' => transport_uri, 'transportUser' => 'admin', 'transportPassword' => node['cq']['publish']['credentials']['password'], 'cq:template' => '/libs/cq/replication/templates/agent', 'sling:resourceType' => 'cq/replication/components/agent', 'logLevel' => 'info' ) encrypted_fields %w(transportPassword) append false action :create end end
  • 39.
  • 41. Transparent DNS • Consul DNS interface listens on port 8600 • /etc/resolv.conf accepts just IPs • dnsmasq to the rescue • DNS "proxy" • listens on localhost:53 • DNS query routing • /etc/hosts on steroids +
  • 42. + # dnsmasq logic if domain ~ /.consul$/ dns_query(domain, "localhost:8600") else internal_db.lookup(domain) || upstream_forward(domain) end
  • 43. dnsmasq - your new primary DNS server +
  • 45. Pick the right one + https://flic.kr/p/c42Qmm
  • 46. Flush agents • 1:1 mapping between dispatcher and publish • config wise each publish instance needs to be exactly the same +
  • 47. dnsmasq helps again • Yet another domain name space: .local • Chef renders dnsmasq config using Consul data • give me all dispatcher servers • pick the one that matches my ID (p1 => d1) • expose it under dispatcher.local +
  • 49. + # Address of 1st dispatcher [root@xyz-uat-p1 ~]# dig dispatcher.local +short 172.19.9.122 # Address of 2nd dispatcher [root@xyz-uat-p2 ~]# dig dispatcher.local +short 172.19.9.141
  • 50.
  • 54. + { "service": { "check": { "interval": "10s", "tcp": "localhost:8080", "timeout": "1s" }, "id": "tomcat", "name": "tomcat", "port": 8080, "tags": [ "tm1" ] } }
  • 55. Your front load balancer is the only one you’ll ever need +
  • 57. Prepared queries • Complex service queries • Returns set of healthy nodes that meets predefined criteria • Example: • tomcat-cluster.query.consul:8080 • use Tomcat from the same datacenter, as long as it’s healthy. Otherwise pick the nearest one. +
  • 59. Consul locks • Distributed locking • Mutual exclusion or semaphore • Configurable amount of holders (1 by default) +
  • 61. App rollouts • Practical use case: deployments • Solves "at least one of publish must be always running" problem +
  • 62. Summary • Services, not IP addresses • Everything supports DNS • Get rid of internal load balancers • Simpler deployments • Can’t imagine a project without Consul +