<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.7.4">Jekyll</generator><link href="https://misterhex.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://misterhex.github.io/" rel="alternate" type="text/html" /><updated>2019-01-17T23:27:36+00:00</updated><id>https://misterhex.github.io/feed.xml</id><title type="html">Solving everyday problems with code</title><subtitle>Solving everyday problems with code</subtitle><author><name>Tan Yong Heng</name></author><entry><title type="html">Using Envoy Proxy for client side load balancing</title><link href="https://misterhex.github.io/Envoy-client-load-balancing/" rel="alternate" type="text/html" title="Using Envoy Proxy for client side load balancing" /><published>2020-01-18T00:00:00+00:00</published><updated>2020-01-18T00:00:00+00:00</updated><id>https://misterhex.github.io/Envoy-client-load-balancing</id><content type="html" xml:base="https://misterhex.github.io/Envoy-client-load-balancing/">&lt;p&gt;We are using &lt;a href=&quot;https://www.envoyproxy.io&quot;&gt;Envoy&lt;/a&gt; for client side load balancing.&lt;/p&gt;

&lt;p&gt;We use &lt;a href=&quot;https://github.com/justwatchcom/elasticsearch_exporter&quot;&gt;elasticsearch exporter&lt;/a&gt; for getting prometheus format metrics for monitoring our clusters. 
Our elasticsearch cluster is not configured behind a load balancer, and we don’t have dns pointing to the multiple 
So we needed a way to allow smart client side load balancing, and most application doesn’t have this.&lt;/p&gt;

&lt;p&gt;So rather than making this an application layer concerns, we can move the concerns to the network layers.&lt;/p&gt;

&lt;p&gt;By using envoy, which is a out-of-process proxy, we can easily implement client side load balancing, and also move tls concerns out ( TLS origination ),&lt;/p&gt;

&lt;p&gt;Envoy can do health checks, and passive ejections of endpoints.&lt;/p&gt;

&lt;p&gt;With just a simple envoy side car running beside elasticsearch exporter, we can pull metrics in a highly available manner from a list of elasticsearch nodes, because the metrics are all the same from whichever nodes we query.&lt;/p&gt;

&lt;p&gt;Envoy is amazing, and seeing adoption in many large projects, e.g. &lt;a href=&quot;http://istio.io&quot;&gt;istio&lt;/a&gt;, &lt;a href=&quot;https://aws.amazon.com/app-mesh/&quot;&gt;aws app mesh&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It is also an enabler for a lot of capabilities, such as fault injections, traffic mirroring and shifting for safe canaries deployment.&lt;/p&gt;

&lt;p&gt;Highly recommended to check it out! &lt;a href=&quot;http://envoyproxy.io&quot;&gt;http://envoyproxy.io&lt;/a&gt;&lt;/p&gt;</content><author><name>Tan Yong Heng</name></author><category term="devops" /><category term="envoy" /><category term="elasticsearch" /><summary type="html">We are using Envoy for client side load balancing.</summary></entry><entry><title type="html">Elasticsearch + LVM Striping</title><link href="https://misterhex.github.io/Setting-up-LVM-stripping/" rel="alternate" type="text/html" title="Elasticsearch + LVM Striping" /><published>2019-01-06T00:00:00+00:00</published><updated>2019-01-06T00:00:00+00:00</updated><id>https://misterhex.github.io/Setting-up-LVM-stripping</id><content type="html" xml:base="https://misterhex.github.io/Setting-up-LVM-stripping/">&lt;p&gt;At work, while managing a fleet of elasticsearch clusters, we have several linux boxes that have inconsistent number of block devices attached. So to simplify the playbook, we don’t want each hosts to have different &lt;code class=&quot;highlighter-rouge&quot;&gt;host_vars&lt;/code&gt; with &lt;code class=&quot;highlighter-rouge&quot;&gt;path.data&lt;/code&gt; settings, it will lead to configuration mess.&lt;/p&gt;

&lt;p&gt;So our solutions is to go with &lt;a href=&quot;https://en.wikipedia.org/wiki/Logical_Volume_Manager_(Linux)&quot;&gt;linux logical volume manager&lt;/a&gt;, or &lt;code class=&quot;highlighter-rouge&quot;&gt;lvm&lt;/code&gt; in short, to create a single logically volume with striping enabled, out of multiple physical disks.&lt;/p&gt;

&lt;p&gt;With this solution, for every data nodes in our cluster, we have elasticsearch writing to a common path. We used striping to increase performance. For data durability, elasticsearch sharding model already taken care of that so we don’t need raid 10 properties.&lt;/p&gt;

&lt;p&gt;some reference here on how to setup lvm:
&lt;a href=&quot;https://www.digitalocean.com/community/tutorials/an-introduction-to-lvm-concepts-terminology-and-operations&quot;&gt;https://www.digitalocean.com/community/tutorials/an-introduction-to-lvm-concepts-terminology-and-operations&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and some discussion around raid10 vs elasticsearch multiple data path performance.
&lt;a href=&quot;https://discuss.elastic.co/t/to-multi-path-data-or-hardware-raid-or-not/40143/3&quot;&gt;https://discuss.elastic.co/t/to-multi-path-data-or-hardware-raid-or-not/40143/3&lt;/a&gt;&lt;/p&gt;</content><author><name>Tan Yong Heng</name></author><category term="devops" /><category term="elasticsearch" /><category term="lvm" /><summary type="html">At work, while managing a fleet of elasticsearch clusters, we have several linux boxes that have inconsistent number of block devices attached. So to simplify the playbook, we don’t want each hosts to have different host_vars with path.data settings, it will lead to configuration mess.</summary></entry><entry><title type="html">Mitigating DDOS attacks on AWS</title><link href="https://misterhex.github.io/Mitigating-DDOS-Attacks-On-AWS/" rel="alternate" type="text/html" title="Mitigating DDOS attacks on AWS" /><published>2018-01-23T00:00:00+00:00</published><updated>2018-01-23T00:00:00+00:00</updated><id>https://misterhex.github.io/Mitigating-DDOS-Attacks-On-AWS</id><content type="html" xml:base="https://misterhex.github.io/Mitigating-DDOS-Attacks-On-AWS/">&lt;p&gt;Recently, a friend asked about how to handle ddos attacks on AWS. We discussed and theses are some pointers.&lt;/p&gt;

&lt;p&gt;Lets say there are 3 components; nodejs api, redis, mysql which we need to setup for our web stack in AWS.&lt;/p&gt;

&lt;p&gt;Basic architectures setup:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;register the domain with route53 name servers for highly available dns.&lt;/li&gt;
  &lt;li&gt;point route53 to elastic load balancer.&lt;/li&gt;
  &lt;li&gt;elb points to nodejs servers.&lt;/li&gt;
  &lt;li&gt;nodejs api servers should sit in private subnet routed to NAT gateway. ( for outbound http calls to other services or downloading of apt / yum packages.&lt;/li&gt;
  &lt;li&gt;each components should have its own security groups; nodejs, redis, mysql.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Mitigate ddos attacks:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;ensure nodejs web apps is design to be horizontally scalable. ( follow 12factor app design https://12factor.net )&lt;/li&gt;
  &lt;li&gt;use auto scaling group to take traffic spike.&lt;/li&gt;
  &lt;li&gt;use durable message queues in the architecture to smoothen the spike requests to other backend services.&lt;/li&gt;
  &lt;li&gt;use aws sheid for ddos protection; to detect ddos traffic patterns.&lt;/li&gt;
  &lt;li&gt;authenticate caller, and rate limit the api per caller.&lt;/li&gt;
  &lt;li&gt;enable vpc flow log to detect anomaly&lt;/li&gt;
  &lt;li&gt;use monitoring tools to detect attacks and trigger off alerts. ( elastalert, prometheus/grafana )&lt;/li&gt;
  &lt;li&gt;only exposing route53 and elastic load balancer to be public facing allow aws to take care of infrastructure availability.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Accessing the servers:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;using either vpn and bastion, they would sit in the public subnet allowing ssh. then ssh agent forward to access web, mysql, redis servers.&lt;/li&gt;
&lt;/ol&gt;</content><author><name>Tan Yong Heng</name></author><category term="devops" /><category term="aws" /><category term="architecture" /><summary type="html">Recently, a friend asked about how to handle ddos attacks on AWS. We discussed and theses are some pointers.</summary></entry><entry><title type="html">Running Twemproxy In Kubernetes</title><link href="https://misterhex.github.io/Twemproxy-And-Kubernetes/" rel="alternate" type="text/html" title="Running Twemproxy In Kubernetes" /><published>2018-01-20T00:00:00+00:00</published><updated>2018-01-20T00:00:00+00:00</updated><id>https://misterhex.github.io/Twemproxy-And-Kubernetes</id><content type="html" xml:base="https://misterhex.github.io/Twemproxy-And-Kubernetes/">&lt;p&gt;In this post, i would like share on how to setup &lt;a href=&quot;&quot;&gt;twemproxy&lt;/a&gt; for &lt;a href=&quot;&quot;&gt;redis&lt;/a&gt; cluster sharding running in &lt;a href=&quot;&quot;&gt;kubernetes&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;/h2&gt;
&lt;p&gt;These are the tasks required:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Running &lt;code class=&quot;highlighter-rouge&quot;&gt;twemproxy&lt;/code&gt; as a single replica deployment in &lt;code class=&quot;highlighter-rouge&quot;&gt;kubernetes&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Running &lt;code class=&quot;highlighter-rouge&quot;&gt;redis&lt;/code&gt; replicas as &lt;a href=&quot;&quot;&gt;statefulsets&lt;/a&gt; with  with in &lt;code class=&quot;highlighter-rouge&quot;&gt;kubernetes&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Allowing other &lt;code class=&quot;highlighter-rouge&quot;&gt;pods&lt;/code&gt; in &lt;code class=&quot;highlighter-rouge&quot;&gt;kubernetes&lt;/code&gt; to access &lt;code class=&quot;highlighter-rouge&quot;&gt;twemproxy&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Allowing &lt;code class=&quot;highlighter-rouge&quot;&gt;twemproxy&lt;/code&gt; to connect to the redis’s &lt;code class=&quot;highlighter-rouge&quot;&gt;pods&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;twemproxy&quot;&gt;Twemproxy&lt;/h2&gt;
&lt;p&gt;We can run twemproxy as a single &lt;code class=&quot;highlighter-rouge&quot;&gt;deployment&lt;/code&gt; in &lt;code class=&quot;highlighter-rouge&quot;&gt;kubernetes&lt;/code&gt;. We can use the following community image &lt;a href=&quot;https://registry.hub.docker.com/u/jgoodall/twemproxy/&quot;&gt;jgoodall/twemproxy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;twemproxy’s deployment &amp;amp; service spec:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;extensions/v1beta1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Deployment&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;twemproxy&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;twemproxy&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;replicas&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;twemproxy&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;containers&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;jgoodall/twemproxy:latest&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;twemproxy&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;containerPort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;63791&lt;/span&gt;
        &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;containerPort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;63792&lt;/span&gt;
        &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;containerPort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;6222&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;restartPolicy&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Always&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Service&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;twemproxy&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;twemproxy&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;twemproxy&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;63791&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;63791&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;targetPort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;63791&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;63792&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;63792&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;targetPort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;63792&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;6222&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;6222&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;targetPort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;6222&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The configuration above will deploy twemproxy’s &lt;code class=&quot;highlighter-rouge&quot;&gt;deployment&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;service&lt;/code&gt;. &lt;code class=&quot;highlighter-rouge&quot;&gt;service&lt;/code&gt; in kubernetes allow pods to network with each other, this service will allow other pods to reach &lt;code class=&quot;highlighter-rouge&quot;&gt;twemproxy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;twemproxy.yml:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;local&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;0.0.0.0:63791&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;fnv1a_64&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;hash_tag&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{}&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;distribution&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ketama&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;500&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;redis&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;servers&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis-0:6379:1&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis-1:6379:1&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis-2:6379:1&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;0.0.0.0:63792&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;fnv1a_64&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;hash_tag&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{}&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;distribution&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ketama&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;auto_eject_hosts&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;server_retry_timeout&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;30000&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;server_failure_limit&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;3&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;500&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;redis&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;servers&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis-0:6379:1&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis-1:6379:1&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis-2:6379:1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Above is twemproxy’s configuration which need to be mount as &lt;code class=&quot;highlighter-rouge&quot;&gt;configmap volume&lt;/code&gt; in twemproxy’s deployment.&lt;/p&gt;

&lt;h2 id=&quot;redis-statefulset&quot;&gt;Redis Statefulset&lt;/h2&gt;
&lt;p&gt;Next, we need to create redis’s statefulset. Statefulset with 3 replicas will create the following pods &lt;code class=&quot;highlighter-rouge&quot;&gt;redis-0&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;redis-1&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;redis-2&lt;/code&gt;.  Pods created by statefulset will be labeled as &lt;code class=&quot;highlighter-rouge&quot;&gt;statefulset.kubernetes.io/pod-name: &lt;/code&gt;, we can use this as selector for the &lt;code class=&quot;highlighter-rouge&quot;&gt;service&lt;/code&gt;. Unfortunably, we will still need to create 3 services to allow each pod to be addressable by &lt;code class=&quot;highlighter-rouge&quot;&gt;twemproxy&lt;/code&gt;,&lt;/p&gt;

&lt;p&gt;redis statefulset:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;apps/v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;StatefulSet&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;matchLabels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;serviceName&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;redis&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;replicas&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;3&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;terminationGracePeriodSeconds&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;3&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;containers&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis:3.0.7&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;containerPort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;6379&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;redis services:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Service&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;6379&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;clusterIP&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;None&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Service&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis-1&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis-1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;6379&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis-1&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;clusterIP&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;None&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;statefulset.kubernetes.io/pod-name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis-1&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Service&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis-1&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis-1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;6379&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis-1&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;clusterIP&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;None&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;statefulset.kubernetes.io/pod-name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis-1&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Service&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis-2&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis-2&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;6379&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis-2&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;clusterIP&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;None&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;statefulset.kubernetes.io/pod-name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis-2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;</content><author><name>Tan Yong Heng</name></author><category term="devops" /><category term="kubernetes" /><summary type="html">In this post, i would like share on how to setup twemproxy for redis cluster sharding running in kubernetes.</summary></entry><entry><title type="html">Easy Setup Of OpenVPN Bastion Server Using Docker</title><link href="https://misterhex.github.io/Easily-Setup-OpenVPN-Bastion-With-Docker.1/" rel="alternate" type="text/html" title="Easy Setup Of OpenVPN Bastion Server Using Docker" /><published>2018-01-08T00:00:00+00:00</published><updated>2018-01-08T00:00:00+00:00</updated><id>https://misterhex.github.io/Easily-Setup-OpenVPN-Bastion-With-Docker.1</id><content type="html" xml:base="https://misterhex.github.io/Easily-Setup-OpenVPN-Bastion-With-Docker.1/">&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;OpenVPN&lt;/code&gt; is a full-featured open source Secure Socket Layer (SSL) VPN solution. While trying to secure amazon elasticsearch service, we decided that an OpenVPN bastion server would be the simplest way for us to securely access &lt;code class=&quot;highlighter-rouge&quot;&gt;kibana&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;elasticsearch service&lt;/code&gt; from our home, office, or anywhere as long as we have proper client certificate.&lt;/p&gt;

&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;/h2&gt;
&lt;p&gt;We use a small t2.micro amazon linux ami with &lt;code class=&quot;highlighter-rouge&quot;&gt;elastic ip&lt;/code&gt; attached and &lt;code class=&quot;highlighter-rouge&quot;&gt;docker&lt;/code&gt; installed on the machine, the &lt;code class=&quot;highlighter-rouge&quot;&gt;security group&lt;/code&gt; is set to open udp on port &lt;code class=&quot;highlighter-rouge&quot;&gt;1194&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;0.0.0.0/32&lt;/code&gt; cidr range. The server sit in a public subnet of the vpc.&lt;/p&gt;

&lt;p&gt;OpenVPN itself is ran using the docker image &lt;a href=&quot;https://github.com/kylemanna/docker-openvpn&quot;&gt;https://github.com/kylemanna/docker-openvpn&lt;/a&gt;, this is an amazing image that really ease the setup and creation of client certificate of the OpenVPN server.&lt;/p&gt;

&lt;p&gt;Once we have OpenVPN server up and running in docker, and the client &lt;code class=&quot;highlighter-rouge&quot;&gt;.ovpn&lt;/code&gt; files generated, the files can be distributed to the users that require access. We are ready to connect to the vpn.&lt;/p&gt;

&lt;p&gt;I use &lt;a href=&quot;https://tunnelblick.net&quot;&gt;TunnelBlick&lt;/a&gt; as my openvpn client, which is free. Simply install it and drag the &lt;code class=&quot;highlighter-rouge&quot;&gt;.ovpn&lt;/code&gt; file to TunnelBlick and everything is setup.&lt;/p&gt;

&lt;p&gt;Once connected, we could securely access &lt;code class=&quot;highlighter-rouge&quot;&gt;amazon elasticsearch&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;kibana&lt;/code&gt; using its &lt;code class=&quot;highlighter-rouge&quot;&gt;vpc endpoint&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;With Docker, the installation of OpenVPN is easy and simplified. Using OpenVPN as a bastion server is a good way to allow secure access to our aws’s vpc from anywhere.&lt;/p&gt;</content><author><name>Tan Yong Heng</name></author><category term="devops" /><category term="docker" /><summary type="html">OpenVPN is a full-featured open source Secure Socket Layer (SSL) VPN solution. While trying to secure amazon elasticsearch service, we decided that an OpenVPN bastion server would be the simplest way for us to securely access kibana and elasticsearch service from our home, office, or anywhere as long as we have proper client certificate.</summary></entry><entry><title type="html">Troubleshooting Terraform And AWS RequestLimitExceeded</title><link href="https://misterhex.github.io/Troubleshooting-terraform-and-aws-RequestLimitExceeded/" rel="alternate" type="text/html" title="Troubleshooting Terraform And AWS RequestLimitExceeded" /><published>2017-12-27T00:00:00+00:00</published><updated>2017-12-27T00:00:00+00:00</updated><id>https://misterhex.github.io/Troubleshooting-terraform-and-aws-RequestLimitExceeded</id><content type="html" xml:base="https://misterhex.github.io/Troubleshooting-terraform-and-aws-RequestLimitExceeded/">&lt;p&gt;Recently, when running terraform apply, my script has been failing intermittently when provisioning around 90 ec2 instances.&lt;/p&gt;

&lt;p&gt;Luckily, terraform provide debugging output by passing &lt;a href=&quot;https://www.terraform.io/docs/internals/debugging.html&quot;&gt;TF_LOG=debug&lt;/a&gt;. It is interesting that terraform uses &lt;a href=&quot;https://github.com/aws/aws-sdk-go&quot;&gt;aws-sdk-go&lt;/a&gt; under the hood to issues API calls to AWS.&lt;/p&gt;

&lt;p&gt;The root cause of my script failing was due to raising the &lt;a href=&quot;https://www.terraform.io/docs/commands/apply.html#parallelism-n&quot;&gt;parallelism count&lt;/a&gt; beyond the default ( 10 ). When tracing the debug logs, i noticed a lot of API requests to AWS that terraform made has failed with &lt;a href=&quot;http://docs.aws.amazon.com/AWSEC2/latest/APIReference/query-api-troubleshooting.html#api-request-rate&quot;&gt;RequestLimitExceeded&lt;/a&gt;, after setting back to default, i am able to consistently provision &lt;code class=&quot;highlighter-rouge&quot;&gt;200&lt;/code&gt; ec2 instances without failure.&lt;/p&gt;

&lt;p&gt;There are more discussion about this issue on github &lt;a href=&quot;https://github.com/hashicorp/terraform/issues/3579&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;</content><author><name>Tan Yong Heng</name></author><summary type="html">Recently, when running terraform apply, my script has been failing intermittently when provisioning around 90 ec2 instances.</summary></entry><entry><title type="html">What Is Docker?</title><link href="https://misterhex.github.io/What-is-Docker/" rel="alternate" type="text/html" title="What Is Docker?" /><published>2017-12-26T00:00:00+00:00</published><updated>2017-12-26T00:00:00+00:00</updated><id>https://misterhex.github.io/What-is-Docker</id><content type="html" xml:base="https://misterhex.github.io/What-is-Docker/">&lt;p&gt;&lt;a href=&quot;https://www.docker.com&quot;&gt;Docker&lt;/a&gt; is the probably the &lt;em&gt;hottest&lt;/em&gt; technology right now in the technology space. In this post, i am writing about the basic of docker and the challenges it solves.&lt;/p&gt;

&lt;h2 id=&quot;what-is-docker&quot;&gt;What Is Docker?&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Docker is a platform which can be used to &lt;strong&gt;package, distribute and run&lt;/strong&gt; your applications.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Docker provides an easy and efficient way to encapsulate applications (e.g. a Java web application) and any required infrastructure to run that application (e.g. Red hat Linux OS, Apache web server, Tomcat application server, mySQL database etc.) as a single &lt;strong&gt;“Docker image”&lt;/strong&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The image can then be used to launch a &lt;strong&gt;Docker container&lt;/strong&gt; which makes the &lt;strong&gt;containerized&lt;/strong&gt; application available from the host.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;devops-matrix-from-hell&quot;&gt;DevOps Matrix From Hell&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;https://misterhex.github.io/assets/img/matrix-from-hell.png&quot; alt=&quot;cname file content&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DevOps Matrix From Hell&lt;/strong&gt; is the challenge of packaging any application, regardless of language/frameworks/dependencies, so that it can run on any cloud, regardless of operating systems/hardware/infrastructure. This is due to the multipicity of many language/technology/framework stacks that need to installed on so different hardware and operating system environments.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://misterhex.github.io/assets/img/container-for-code.png&quot; alt=&quot;cname file content&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Docker act as a system container for code. It encapsulate all the dependencies within a container. The container can then be run the same way in any environment. Docker solved for the matrix from hell by decoupling the application from the underlying operating system and hardware. It did this by packaging all dependencies inside Docker containers, including the OS.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://misterhex.github.io/assets/img/matrix-from-hell-2.png&quot; alt=&quot;cname file content&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This makes Docker containers “portable”, i.e. they can run on any cloud or machine without the dreaded “it works on this machine” problems. The manipulation and operations of the docker containers is the same for all supported hardware platforms.&lt;/p&gt;

&lt;h2 id=&quot;containers-vs-virtual-machines&quot;&gt;Containers vs Virtual Machines&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;https://misterhex.github.io/assets/img/virtual-machines.png&quot; alt=&quot;cname file content&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Docker container is a kind of light weight virtual machine with considerably smaller memory and disk space footprint than a full blown virtual machine.&lt;/p&gt;

&lt;p&gt;Virtual machines take up a lot of system resources. Each VM runs not just a full copy of an operating system, but a virtual copy of all the hardware that the operating system needs to run. This quickly adds up to a lot of RAM and CPU cycles. In contrast, all that a container requires is enough of an operating system, supporting programs and libraries, and system resources to run a specific program.&lt;/p&gt;

&lt;p&gt;What this means in practice is you can put two to three times as many as applications on a single server with containers than you can with a VM.&lt;/p&gt;

&lt;h2 id=&quot;seperation-of-concerns&quot;&gt;Seperation Of Concerns&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;https://misterhex.github.io/assets/img/seperation-of-concerns.png&quot; alt=&quot;cname file content&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Developers can focus on packaging applications and dependencies as containers, without worrying about underlying infrastructure.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Developers worries about what is &lt;em&gt;inside&lt;/em&gt; the container. e.g. code, libraries, package manager, apps, data, etc&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Operators can focus on managing containers, without worrying about the contents of those containers.&lt;/li&gt;
  &lt;li&gt;Operators worries about what is &lt;em&gt;outside&lt;/em&gt; of the container. e.g. networking, logging, monitoring, dynamic configuration.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;for-developers&quot;&gt;For Developers&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Build once… (finally) run anywhere.&lt;/li&gt;
  &lt;li&gt;No worries about missing dependencies, packages, or mismatched dependencies versioning.&lt;/li&gt;
  &lt;li&gt;Reduce/eliminate concerns about compatibility on different platforms, either your own or your customers.&lt;/li&gt;
  &lt;li&gt;Consistent development environments for your entire team. All developers use the same OS, same system libraries, same language runtime, no matter what host OS they are using&lt;/li&gt;
  &lt;li&gt;Deployment is easy. If it runs in your container, it will run on your server just the same.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;for-operators&quot;&gt;For Operators&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Deployment is more efficient, consistent, and repeatable.&lt;/li&gt;
  &lt;li&gt;Eliminate inconsistencies between development, test, production, and customer environments.&lt;/li&gt;
  &lt;li&gt;Support segregation of duties.&lt;/li&gt;
  &lt;li&gt;Significantly improves the speed and reliability of continuous deployment and continuous.&lt;/li&gt;
  &lt;li&gt;containers are so lightweight, address significant performance, costs, deployment, and portability issues normally associated with virtual machines.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;deep-dive&quot;&gt;Deep Dive&lt;/h2&gt;

&lt;p&gt;Docker works by using linux containers and kernel facilities.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://misterhex.github.io/assets/img/docker-internals.png&quot; alt=&quot;cname file content&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Linux kernel namespaces provides the isolation.&lt;/li&gt;
  &lt;li&gt;Linux kernel cgroups provide the resource limiting ( cpu, memory, I/O )&lt;/li&gt;
  &lt;li&gt;AUFS provide the union file system for docker. ( to avoid duplicating a complete set of files each time you run an image as a new container)&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Tan Yong Heng</name></author><category term="devops" /><category term="docker" /><summary type="html">Docker is the probably the hottest technology right now in the technology space. In this post, i am writing about the basic of docker and the challenges it solves.</summary></entry><entry><title type="html">Tmux</title><link href="https://misterhex.github.io/Tmux/" rel="alternate" type="text/html" title="Tmux" /><published>2017-12-01T00:00:00+00:00</published><updated>2017-12-01T00:00:00+00:00</updated><id>https://misterhex.github.io/Tmux</id><content type="html" xml:base="https://misterhex.github.io/Tmux/">&lt;p&gt;Recently, I discovered the tool; &lt;a href=&quot;https://github.com/tmux/tmux/wiki&quot;&gt;Tmux&lt;/a&gt;. This is an awesome tool that has improved my productivity and i feel i am just scratching the surface of what it can do.&lt;/p&gt;

&lt;h2 id=&quot;what-is-tmux&quot;&gt;What is TMUX?&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Tmux&lt;/code&gt; is a “terminal multiplexer”, it enables a number of terminals (or windows) to be accessed and controlled from a single terminal. tmux is intended to be a simple, modern, BSD-licensed alternative to programs such as GNU screen.&lt;/p&gt;

&lt;p&gt;At the very basic, it allows me to slice up my terminal screens into &lt;code class=&quot;highlighter-rouge&quot;&gt;windows&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;panes&lt;/code&gt; so i can visualize multiple workflow in one screen. This is a lot of productivity improvement for me as i am using a large monitor. Using tmux, i was able to look at more stuffs without creating new bash terminal and switching around.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://misterhex.github.io/assets/img/tmux.png&quot; alt=&quot;cname file content&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;advanced-usage&quot;&gt;Advanced usage&lt;/h2&gt;
&lt;p&gt;Advanced usage of tmux is sessions, we can actually installed &lt;code class=&quot;highlighter-rouge&quot;&gt;tmux&lt;/code&gt; on a remote machine and then let background tasks run in tmux &lt;code class=&quot;highlighter-rouge&quot;&gt;sessions&lt;/code&gt;. Even after we close ssh connections, we can ssh back into the machine and reattached to the tmux session which is still running, this can be use as a replacement for &lt;code class=&quot;highlighter-rouge&quot;&gt;nohup&lt;/code&gt;.&lt;/p&gt;</content><author><name>Tan Yong Heng</name></author><summary type="html">Recently, I discovered the tool; Tmux. This is an awesome tool that has improved my productivity and i feel i am just scratching the surface of what it can do.</summary></entry><entry><title type="html">Kubernetes, Kops, Logging and Monitoring</title><link href="https://misterhex.github.io/Kubernetes-Kops-Logging-And-Monitoring/" rel="alternate" type="text/html" title="Kubernetes, Kops, Logging and Monitoring" /><published>2017-10-25T00:00:00+00:00</published><updated>2017-10-25T00:00:00+00:00</updated><id>https://misterhex.github.io/Kubernetes-Kops-Logging-And-Monitoring</id><content type="html" xml:base="https://misterhex.github.io/Kubernetes-Kops-Logging-And-Monitoring/">&lt;h2 id=&quot;tldr&quot;&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;To quickly setup kubernetes and monitoring using kops, follow my &lt;a href=&quot;https://github.com/Misterhex/kubernetes-logging-monitoring-example&quot;&gt;example github repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;
&lt;p&gt;Recently, i am helping our client move their applications to containerized microservices.&lt;/p&gt;

&lt;p&gt;Moving to &lt;code class=&quot;highlighter-rouge&quot;&gt;docker&lt;/code&gt; containers provide many benefits. However, docker alone does not allow us to orchestrate our containers in productions.   To solve that problem, we need a container platform/orchestrator technology. We adopted &lt;code class=&quot;highlighter-rouge&quot;&gt;kubernetes&lt;/code&gt; as our containers orchestrator of choice. Kubernetes allow us to horizontally scale our microservices across nodes to provide highly availablility and scalability.&lt;/p&gt;

&lt;p&gt;In this post, i would like to document how we are explored the various orchestrator options and how we are running &lt;code class=&quot;highlighter-rouge&quot;&gt;kubernetes&lt;/code&gt; in production.&lt;/p&gt;

&lt;h2 id=&quot;kops--kubernetes-operation&quot;&gt;KOPS ( Kubernetes Operation)&lt;/h2&gt;

&lt;p&gt;There are various ways to operate a kubernetes clusters and it can range from being really complex to simple hosted cloud solutions.&lt;/p&gt;

&lt;p&gt;These are some of the various tools and platforms:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/kubernetes/kops&quot;&gt;Kops&lt;/a&gt; ( run on aws )&lt;/li&gt;
  &lt;li&gt;Openshift&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://cloud.google.com/container-engine/&quot;&gt;Google container engine&lt;/a&gt; ( google cloud )&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.ubuntu.com/kubernetes&quot;&gt;Jujucharms, canonical distribution of kubernetes&lt;/a&gt; ( baremetal, metal cloud ( Machine as a service ), virtual machines )&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/&quot;&gt;Kubeadm&lt;/a&gt; ( baremetal, virtual machines )&lt;/li&gt;
  &lt;li&gt;More..&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After evaluating the various options, we decided with &lt;code class=&quot;highlighter-rouge&quot;&gt;kops&lt;/code&gt; which will provision our cluster on &lt;code class=&quot;highlighter-rouge&quot;&gt;aws&lt;/code&gt;. We found &lt;code class=&quot;highlighter-rouge&quot;&gt;kops&lt;/code&gt; to be the most robust and it works seamlessly for us. Using &lt;code class=&quot;highlighter-rouge&quot;&gt;kops&lt;/code&gt; we get multi-az nodes deployment and auto scaling group at the cluster level. On top of it, our client is already on &lt;code class=&quot;highlighter-rouge&quot;&gt;aws&lt;/code&gt; platform. &lt;code class=&quot;highlighter-rouge&quot;&gt;kops&lt;/code&gt; project has a strong community behind it.&lt;/p&gt;

&lt;p&gt;Learn more about &lt;code class=&quot;highlighter-rouge&quot;&gt;kops&lt;/code&gt; &lt;a href=&quot;https://github.com/kubernetes/kops&quot;&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;kubernetes-dashboard&quot;&gt;Kubernetes Dashboard&lt;/h2&gt;

&lt;p&gt;The first deployment to run in kubernetes is the &lt;code class=&quot;highlighter-rouge&quot;&gt;kubernetes dashboard&lt;/code&gt;. Running kubernetes dashboard allow us to visualize what kubernetes resources are running or getting scheduled, destroyed. It also shows quickly let us know if there is any errors in the cluster.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://misterhex.github.io/assets/img/kube-dashboard.png&quot; alt=&quot;cname file content&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;datastore&quot;&gt;Datastore&lt;/h2&gt;

&lt;p&gt;We run &lt;code class=&quot;highlighter-rouge&quot;&gt;elasticsearch&lt;/code&gt; outside of kubernetes to store log data generated by fluentd and metricbeat daemonsets. Running ELK outside kubernetes is more robust, in case kubernetes clusters goes down, we can still see logs on what happened before kubernetes died.&lt;/p&gt;

&lt;h2 id=&quot;centralized-logging&quot;&gt;Centralized logging&lt;/h2&gt;

&lt;p&gt;It is important that before going into production we setup centralized logging of pods/containers running in kubernetes. Pods/containers are running in different kubernetes nodes, scaling up and down, it is hard to understand what is going on without centralized logging. What we want is a single place to look logs from stdout and stderr streams of running containers to quickly detect and diagnose issues.&lt;/p&gt;

&lt;p&gt;We run &lt;code class=&quot;highlighter-rouge&quot;&gt;fluentd&lt;/code&gt; as daemonsets on every kubernetes nodes. In kubernetes, all containers write their stdout/stderr streams to the &lt;code class=&quot;highlighter-rouge&quot;&gt;/var/log/containers/&lt;/code&gt; folders. Fluentd can be configured to monitor this folder and then send logs into elasticsearch.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://misterhex.github.io/assets/img/centralized_logging.png&quot; alt=&quot;cname file content&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;monitoring&quot;&gt;Monitoring&lt;/h2&gt;

&lt;p&gt;Monitoring is done using &lt;a href=&quot;https://www.elastic.co/products/beats/metricbeat&quot;&gt;metricbeat&lt;/a&gt; and &lt;a href=&quot;https://github.com/kubernetes/kube-state-metrics&quot;&gt;kube-state-metric&lt;/a&gt;. &lt;code class=&quot;highlighter-rouge&quot;&gt;kube-state-metric&lt;/code&gt; is a simple service that listens to the Kubernetes API server and generates metrics about the state of the objects. &lt;code class=&quot;highlighter-rouge&quot;&gt;Metricbeat&lt;/code&gt; grab data from &lt;code class=&quot;highlighter-rouge&quot;&gt;kube-state-metric&lt;/code&gt; into &lt;code class=&quot;highlighter-rouge&quot;&gt;elasticsearch&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Kubernetes dashboard in kibana:
&lt;img src=&quot;https://misterhex.github.io/assets/img/k8_1.png&quot; alt=&quot;cname file content&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Metricbeat dashboard in kibana:
&lt;img src=&quot;https://misterhex.github.io/assets/img/k8_2.png&quot; alt=&quot;cname file content&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Centralized logging and monitoring is important to setup before moving to production with kubernetes. I have created an &lt;a href=&quot;https://github.com/Misterhex/kubernetes-logging-monitoring-example&quot;&gt;example kubernetes github repo&lt;/a&gt; that contains the kubernetes yaml files to deploy everything we discussed.&lt;/p&gt;</content><author><name>Tan Yong Heng</name></author><category term="devops" /><category term="kubernetes" /><category term="docker" /><summary type="html">TL;DR To quickly setup kubernetes and monitoring using kops, follow my example github repository.</summary></entry><entry><title type="html">Deploying Elastic Stack With Ansible Playbook</title><link href="https://misterhex.github.io/Deploying-elastic-stack-with-ansible-playbook/" rel="alternate" type="text/html" title="Deploying Elastic Stack With Ansible Playbook" /><published>2017-10-15T00:00:00+00:00</published><updated>2017-10-15T00:00:00+00:00</updated><id>https://misterhex.github.io/Deploying-elastic-stack-with-ansible-playbook</id><content type="html" xml:base="https://misterhex.github.io/Deploying-elastic-stack-with-ansible-playbook/">&lt;p&gt;As a devops consultant, I have worked with &lt;code class=&quot;highlighter-rouge&quot;&gt;ansible&lt;/code&gt; quite a bit. Following the principles of &lt;a href=&quot;https://www.thoughtworks.com/insights/blog/infrastructure-code-reason-smile&quot;&gt;infrastructure as code&lt;/a&gt; and with the motivation to automate as much infrastructure work as possible, many of our configuration are automated and manage as normal code, we commit them with &lt;code class=&quot;highlighter-rouge&quot;&gt;git&lt;/code&gt; and even run yaml syntax check in our ci/cd pipeline.&lt;/p&gt;

&lt;p&gt;One of the configuration scripts I did was for automating the configuration of the &lt;a href=&quot;https://www.elastic.co&quot;&gt;elastic stack&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This script is availabe at my github repo, &lt;a href=&quot;https://github.com/Misterhex/ansible-elk&quot;&gt;https://github.com/Misterhex/ansible-elk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This script configure:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;elasticsearch cluster with N number of nodes.&lt;/li&gt;
  &lt;li&gt;kibana&lt;/li&gt;
  &lt;li&gt;curator&lt;/li&gt;
  &lt;li&gt;metricbeats on all compute nodes.&lt;/li&gt;
  &lt;li&gt;import default dashboard for metricbeat&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Below is the main playbook file &lt;code class=&quot;highlighter-rouge&quot;&gt;site.yml&lt;/code&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;nn&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;hosts&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;all&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;gather_facts&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;roles&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;python&lt;/span&gt;

&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;hosts&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;elasticsearch&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;cluster_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;openstack_test&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;es_heap_size&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;2g&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;roles&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;java8&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;elastic5x&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;elasticsearch&lt;/span&gt;

&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;hosts&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;kibana&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;kibana_port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;5601&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;roles&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;elastic5x&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;kibana&lt;/span&gt;

&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;hosts&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;compute&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;roles&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;elastic5x&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;metricbeat&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;filebeat&lt;/span&gt;

&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;hosts&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;curator&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;delete_older_than_days&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;roles&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;curator&lt;/span&gt;

&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;hosts&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;compute[0]&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; 
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;import metricbeats dashboards to kibana&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;shell&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/usr/share/metricbeat/scripts/import_dashboards&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;import filebeat dashboards to kibana&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;shell&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/usr/share/filebeat/scripts/import_dashboards&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;concepts&quot;&gt;Concepts&lt;/h3&gt;
&lt;p&gt;Playbook contains &lt;code class=&quot;highlighter-rouge&quot;&gt;plays&lt;/code&gt; that will run when executed, &lt;code class=&quot;highlighter-rouge&quot;&gt;plays&lt;/code&gt; maps to &lt;code class=&quot;highlighter-rouge&quot;&gt;inventory&lt;/code&gt;. &lt;code class=&quot;highlighter-rouge&quot;&gt;Plays&lt;/code&gt; contains &lt;code class=&quot;highlighter-rouge&quot;&gt;Roles&lt;/code&gt;. &lt;code class=&quot;highlighter-rouge&quot;&gt;Roles&lt;/code&gt; are basically recommended encapsulation of a series of &lt;code class=&quot;highlighter-rouge&quot;&gt;steps&lt;/code&gt; that invoke ansible &lt;code class=&quot;highlighter-rouge&quot;&gt;modules&lt;/code&gt;. &lt;code class=&quot;highlighter-rouge&quot;&gt;Modules&lt;/code&gt; are built-in &lt;a href=&quot;https://stackoverflow.com/a/1077421/1610747&quot;&gt;idempontent&lt;/a&gt; functions that configure the target servers. Servers are grouped and defined in &lt;code class=&quot;highlighter-rouge&quot;&gt;inventories&lt;/code&gt;, they are defined in an &lt;code class=&quot;highlighter-rouge&quot;&gt;inventory file&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Below is an example inventory file:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ini&quot; data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;nn&quot;&gt;[all_servers:children]&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;compute&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;elasticsearch&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;kibana&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[all_servers:vars]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;ansible_user&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ubuntu&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;ansible_ssh_private_key_file&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;xxx&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[compute]&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;xxx.xxx.xxx.xxx&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[elasticsearch]&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;xxx.xxx.xxx.xxx&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[kibana]&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;xxx.xxx.xxx.xxx&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;running-the-playbook&quot;&gt;Running the playbook&lt;/h3&gt;
&lt;p&gt;To run the playbook, it is as simple as:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ansible-playbook -i inventory-sample site.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;In conclusion, ansible is a simple yet awesome tools for automating configuration of softwares/services. Get started with installation &lt;a href=&quot;http://docs.ansible.com/ansible/latest/intro_installation.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;</content><author><name>Tan Yong Heng</name></author><category term="devops" /><category term="elasticsearch" /><category term="ansible" /><summary type="html">As a devops consultant, I have worked with ansible quite a bit. Following the principles of infrastructure as code and with the motivation to automate as much infrastructure work as possible, many of our configuration are automated and manage as normal code, we commit them with git and even run yaml syntax check in our ci/cd pipeline.</summary></entry></feed>