<?xml version="1.0" encoding="utf-8"?> 
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <generator uri="https://gohugo.io/" version="0.119.0">Hugo</generator><title type="html"><![CDATA[MD/Blog]]></title>
    
    
    
            <link href="https://www.ducea.com/" rel="alternate" type="text/html" title="html" />
            <link href="https://www.ducea.com/rss.xml" rel="alternate" type="application/rss+xml" title="rss" />
            <link href="https://www.ducea.com/atom.xml" rel="self" type="application/atom+xml" title="Atom" />
    <updated>2025-03-31T19:18:39-05:00</updated>
    
    
    
    
        <id>https://www.ducea.com/</id>
    
        
        <entry>
            <title type="html"><![CDATA[HowTo Install and Use Karpenter in EKS]]></title>
            <link href="https://www.ducea.com/2025/01/17/howto-install-and-use-karpenter-in-eks/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://www.ducea.com/2023/12/10/running-graviton2-workloads-on-eks-clusters-with-karpenter/?utm_source=atom_feed" rel="related" type="text/html" title="Running Graviton2 workloads on EKS clusters with Karpenter" />
                <link href="https://www.ducea.com/2024/09/20/managing-aws-resources-in-kubernetes-with-ack/?utm_source=atom_feed" rel="related" type="text/html" title="Managing AWS Resources in Kubernetes with ACK" />
                <link href="https://www.ducea.com/2024/02/18/howto-migrate-your-eks-cluster-to-graviton2/?utm_source=atom_feed" rel="related" type="text/html" title="HowTo Migrate your EKS cluster to Graviton2" />
                <link href="https://www.ducea.com/2023/01/14/howto-migrate-a-managed-aws-elasticsearch-cluster-to-graviton2/?utm_source=atom_feed" rel="related" type="text/html" title="HowTo Migrate a managed AWS Elasticsearch cluster to graviton2" />
                <link href="https://www.ducea.com/2022/11/12/howto-migrate-a-self-managed-elasticsearch-cluster-to-graviton2-instances/?utm_source=atom_feed" rel="related" type="text/html" title="HowTo Migrate a self managed Elasticsearch cluster to graviton2 instances" />
            
                <id>https://www.ducea.com/2025/01/17/howto-install-and-use-karpenter-in-eks/</id>
            
            
            <published>2025-01-17T10:20:55+00:00</published>
            <updated>2025-01-17T10:20:55+00:00</updated>
            
            
            <content type="html"><![CDATA[<p><strong><a href="https://karpenter.sh/">Karpenter</a></strong> is an open-source Kubernetes node autoscaler created by AWS, designed to improve efficiency and cost savings by provisioning and de-provisioning nodes dynamically based on workloads. I have been using karpenter since its first few versions when it was quite limited in features but after the <a href="https://aws.amazon.com/blogs/containers/announcing-karpenter-1-0/">v1.0 release</a> I believe it has become the major player in this field. This article is intended for folks who have traditionally used cluster autoscaler to show how to install and do basic operations with karpenter.</p>
<h3 id="but-first-why-karpenter-over-cluster-autoscaler">But first, why Karpenter over Cluster Autoscaler?</h3>
<p><strong>Cluster Autoscaler</strong> (CA) works by scaling node groups based on pod scheduling failures, but it has a few limitations:</p>
<ul>
<li><strong>Tied to ASGs</strong>: CA relies on AWS Auto Scaling Groups (ASGs), making scaling decisions slower.</li>
<li><strong>Fixed node types</strong>: Nodes in CA are predefined, limiting flexibility.</li>
<li><strong>Inefficient resource allocation</strong>: CA does not dynamically optimize instance selection, potentially leading to wasted resources.</li>
</ul>
<h3 id="advantages-of-karpenter">Advantages of Karpenter:</h3>
<ul>
<li><strong>Direct EC2 instance provisioning</strong>: Karpenter does not require ASGs and provisions instances directly through EC2.</li>
<li><strong>Faster scaling</strong>: Unlike CA, Karpenter reacts immediately to pending pods, minimizing scheduling delays.</li>
<li><strong>Flexible instance selection</strong>: It chooses the most efficient EC2 instance type based on workload requirements.</li>
<li><strong>Automatic node termination</strong>: When nodes are idle, Karpenter deprovisions them automatically, reducing costs.</li>
<li><strong>Better spot instance utilization</strong>: Karpenter supports mixed instance types and Spot Instances more effectively.</li>
</ul>
<h3 id="how-karpenter-works">How Karpenter Works</h3>
<p>Karpenter listens for unscheduled pods and provisions the best-fitting compute capacity in real-time:</p>
<ol>
<li><em>Pod watch</em>: It monitors the Kubernetes API for unscheduled pods.</li>
<li><em>Instance selection</em>: Karpenter selects the most cost-effective instance type based on constraints and requirements.</li>
<li><em>Instance provisioning</em>: It launches the instance directly using the EC2 API.</li>
<li><em>Node registration</em>: The new node joins the cluster, and Karpenter binds pods to it.</li>
<li><em>Node de-provisioning</em>: When nodes become unnecessary, Karpenter automatically removes them.</li>
</ol>
<p>Next, let&rsquo;s look at how to install and use karpenter; the first decision is where to install it: in its own node group or using Fargate; hopefully AWS will have soon a managed solution for karpenter so we don&rsquo;t have to worry about this at all. I like to use the fargate solution as it is simple and it doesn&rsquo;t require a node-group just for karpenter.</p>
<h3 id="install-karpenter-on-aws-fargate">Install Karpenter on AWS Fargate</h3>
<p>Karpenter can be installed on an AWS Fargate node to manage compute resources dynamically. Follow these steps to set it up:</p>
<h4 id="create-a-fargate-profile-for-karpenter">Create a Fargate Profile for Karpenter</h4>
<p>Ensure that your EKS cluster has a Fargate profile for the karpenter namespace:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">aws eks create-fargate-profile --cluster-name my-cluster --fargate-profile-name karpenter-profile \
</span></span><span class="line"><span class="cl">  --pod-execution-role-arn arn:aws:iam::ACCOUNT_ID:role/AmazonEKSFargatePodExecutionRole \
</span></span><span class="line"><span class="cl">  --selectors namespace=karpenter
</span></span></code></pre></div><h4 id="create-a-custom-valuesyaml-file">Create a Custom values.yaml File</h4>
<p>Create a file named karpenter-values.yaml with the following content:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">serviceAccount</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">create</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">karpenter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">controller</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">clusterName</span><span class="p">:</span><span class="w"> </span><span class="l">my-cluster</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">aws</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">defaultInstanceProfile</span><span class="p">:</span><span class="w"> </span><span class="l">KarpenterInstanceProfile</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">interruptionQueue</span><span class="p">:</span><span class="w"> </span><span class="l">karpenter-interruption-queue</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">nodeSelector</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">eks.amazonaws.com/fargate-profile</span><span class="p">:</span><span class="w"> </span><span class="l">karpenter-profile</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">settings</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">consolidation</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">enabled</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">ttlSecondsAfterEmpty</span><span class="p">:</span><span class="w"> </span><span class="m">300</span><span class="w">
</span></span></span></code></pre></div><p>Replace my-cluster with your EKS cluster name and karpenter-profile with your Fargate profile name.</p>
<h4 id="install-karpenter-using-helm-with-the-custom-valuesyaml">Install Karpenter Using Helm with the Custom values.yaml</h4>
<p>Add the Karpenter Helm repository:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">helm repo add karpenter https://charts.karpenter.sh
</span></span><span class="line"><span class="cl">helm repo update
</span></span></code></pre></div><h4 id="install-karpenter-using-the-custom-valuesyaml-file">Install Karpenter using the custom values.yaml file:</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">helm install karpenter karpenter/karpenter --namespace karpenter --create-namespace -f karpenter-values.yaml
</span></span></code></pre></div><h3 id="customizing-bin-packing-behavior">Customizing Bin Packing Behavior</h3>
<p>There are many values that can be set to control how karpenter works (see the helm defaults for all of those); here I just configured some to enable consolidation and how long to wait to delete an idle node. Customize them per your needs.</p>
<ul>
<li>settings.consolidation.enabled: Default is false. When set to true, Karpenter bin packs workloads by terminating underutilized nodes and rescheduling pods.</li>
<li>settings.ttlSecondsAfterEmpty: Default is 30. This defines how long an empty node should remain before being deprovisioned.</li>
<li>settings.limits.resources.cpu: No default limit. This should be set based on your cluster&rsquo;s resource constraints.</li>
</ul>
<p>Once you have it installed it will start doing its thing; watching k8s events and taking action as needed.</p>
<h3 id="troubleshooting-karpenter">Troubleshooting Karpenter</h3>
<p>To diagnose scaling issues, monitor the following logs:
Check Karpenter logs:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">kubectl logs -n karpenter -l app.kubernetes.io/name=karpenter -f
</span></span></code></pre></div><p>Inspect the provisioner status:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">kubectl get provisioners -o wide
</span></span></code></pre></div><p>Check pending pods:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">kubectl get pods --field-selector=status.phase=Pending -A
</span></span></code></pre></div><p>Inspect event logs for scheduling failures:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">kubectl describe pod &lt;POD_NAME&gt;
</span></span></code></pre></div><p>Check for insufficient capacity errors:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">kubectl get events --sort-by=.metadata.creationTimestamp | grep -i karpenter
</span></span></code></pre></div><p>That&rsquo;s it. You have successfully installed and configured Karpenter in your Amazon EKS cluster. With Karpenter, your cluster will automatically scale nodes dynamically based on workload demand, improving cost efficiency and performance.</p>
]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/categories/aws" term="aws" label="AWS" />
                             
                                <category scheme="https://www.ducea.com/categories/k8s" term="k8s" label="K8s" />
                            
                        
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/tags/aws" term="aws" label="aws" />
                             
                                <category scheme="https://www.ducea.com/tags/k8s" term="k8s" label="k8s" />
                             
                                <category scheme="https://www.ducea.com/tags/karpenter" term="karpenter" label="karpenter" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Managing AWS Resources in Kubernetes with ACK]]></title>
            <link href="https://www.ducea.com/2024/09/20/managing-aws-resources-in-kubernetes-with-ack/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://www.ducea.com/2024/02/18/howto-migrate-your-eks-cluster-to-graviton2/?utm_source=atom_feed" rel="related" type="text/html" title="HowTo Migrate your EKS cluster to Graviton2" />
                <link href="https://www.ducea.com/2023/12/10/running-graviton2-workloads-on-eks-clusters-with-karpenter/?utm_source=atom_feed" rel="related" type="text/html" title="Running Graviton2 workloads on EKS clusters with Karpenter" />
                <link href="https://www.ducea.com/2023/01/14/howto-migrate-a-managed-aws-elasticsearch-cluster-to-graviton2/?utm_source=atom_feed" rel="related" type="text/html" title="HowTo Migrate a managed AWS Elasticsearch cluster to graviton2" />
                <link href="https://www.ducea.com/2022/11/12/howto-migrate-a-self-managed-elasticsearch-cluster-to-graviton2-instances/?utm_source=atom_feed" rel="related" type="text/html" title="HowTo Migrate a self managed Elasticsearch cluster to graviton2 instances" />
                <link href="https://www.ducea.com/2009/08/26/amazon-introduces-virtual-private-cloud-amazon-vpc/?utm_source=atom_feed" rel="related" type="text/html" title="Amazon Introduces Virtual Private Cloud (Amazon VPC)" />
            
                <id>https://www.ducea.com/2024/09/20/managing-aws-resources-in-kubernetes-with-ack/</id>
            
            
            <published>2024-09-20T11:20:55+00:00</published>
            <updated>2024-09-20T11:20:55+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>Kubernetes apps often require a number of supporting resources like databases, message queues, and object stores. AWS provides a set of managed services that we can use to provide these resources for our apps, but provisioning and integrating them with Kubernetes is usually complex and time-consuming. Traditionally what I have done in the past, I used Terraform for this, but this was disconnected from the application and required careful orchestration and/or ordering (aka you need to run Terraform first, then deploy the app next, then run terraform one more time, etc.)</p>
<p><a href="https://github.com/aws-controllers-k8s/community"><strong>ACK (AWS Controllers for Kubernetes)</strong></a> is an open-source project from AWS that was launched a few years ago to solve exaclty this problem. Besides ACK there are a few other solutions for this:</p>
<ul>
<li><strong>Crossplane</strong>: An open-source Kubernetes project that allows you to manage cloud infrastructure and services declaratively. Unlike ACK, Crossplane provides a more cloud-agnostic approach and supports multiple cloud providers.</li>
<li><strong>Kubernetes service catalog</strong>: This is a native Kubernetes extension that enables integration with cloud services using the Open Service Broker API. However, it requires cloud providers to implement a broker.</li>
<li><strong>Terraform Kubernetes Operator</strong>: This approach uses Terraform to manage cloud resources through Kubernetes. It provides more flexibility but requires Terraform state management.</li>
</ul>
<p>These are all good solutions, but let&rsquo;s see where <strong>ACK</strong> shines:</p>
<ul>
<li><em>Tightly integrated with AWS</em>: ACK is developed and maintained by AWS, ensuring compatibility and updates aligned with AWS services.</li>
<li><em>Declarative Kubernetes approach</em>: Resources are managed using Kubernetes manifests, aligning with Kubernetes-native workflows.</li>
<li><em>IAM permissions management</em>: Handles permissions automatically via IAM, making it secure and manageable.</li>
</ul>
<p>Next, we are going to look at how to install and use ACK in an existing Kubernetes cluster. We are going to use the helm-based installation so you will need that available in case you don&rsquo;t have it already.</p>
<h2 id="install-ack-controllers">Install ACK Controllers</h2>
<p>ACK provides controllers for multiple AWS services. We can either install them one by one (only the one we intend to use), or we can install all available controllers. Here are the basic steps:</p>
<p>Add the ACK Helm repository:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">helm repo add ack https://aws-controllers-k8s.github.io/helm-charts
</span></span><span class="line"><span class="cl">helm repo update
</span></span></code></pre></div><p>Install all available ACK controllers:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">helm install ack-all ack/ack-all --namespace ack-system --create-namespace
</span></span></code></pre></div><p>This will deploy controllers for all supported AWS services within the ack-system namespace.</p>
<p>If you want to install only specific controllers, you can replace ack-all with the name of the specific controller. For example, to install both the S3 and SQS controllers:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">helm install ack-s3 ack/s3-controller --namespace ack-system --create-namespace
</span></span><span class="line"><span class="cl">helm install ack-sqs ack/sqs-controller --namespace ack-system --create-namespace
</span></span></code></pre></div><p>ACK currently supports controllers for many AWS services:</p>
<ul>
<li>Amazon S3</li>
<li>Amazon SQS</li>
<li>Amazon SNS</li>
<li>Amazon RDS</li>
<li>Amazon DynamoDB</li>
<li>Amazon ElastiCache</li>
<li>etc.</li>
</ul>
<p>To see the full list of supported services, see: <a href="https://aws-controllers-k8s.github.io/community/docs/community/services/">https://aws-controllers-k8s.github.io/community/docs/community/services/</a></p>
<p>Next, let&rsquo;s verify the installation:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">kubectl get pods -n ack-system
</span></span></code></pre></div><p>and ensure all controllers you installed are up and running.</p>
<p>Great, let&rsquo;s use ACK to create some resources to see how easy it is to do that:</p>
<h3 id="deploy-an-sqs-queue">Deploy an SQS Queue</h3>
<p>Create a YAML manifest for the SQS queue:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">sqs.services.k8s.aws/v1alpha1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Queue</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">test-queue</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">queueName</span><span class="p">:</span><span class="w"> </span><span class="l">test-queue</span><span class="w">
</span></span></span></code></pre></div><p>Apply the configuration:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">kubectl apply -f test-queue.yaml
</span></span></code></pre></div><p>Verify the queue creation:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">kubectl get queues.sqs.services.k8s.aws
</span></span></code></pre></div><p>You should see test-queue in the output.</p>
<h3 id="deploy-an-s3-bucket">Deploy an S3 Bucket</h3>
<p>Create a YAML manifest for the S3 bucket:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">s3.services.k8s.aws/v1alpha1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Bucket</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">test-bucket-unique-name</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">test-bucket-unique-name</span><span class="w">
</span></span></span></code></pre></div><p>Apply the configuration:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">kubectl apply -f test-bucket.yaml
</span></span></code></pre></div><p>Verify the bucket creation:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">kubectl get buckets.s3.services.k8s.aws
</span></span></code></pre></div><p>You should see test-bucket-unique-name in the output.</p>
<p>And that&rsquo;s it. It is as simple as that.</p>
<p><em>Note: normally these definitions would be part of the helm deploy of your application (in the same repository) and deployed by a common pipeline that deploys your application (using argo-cd or similar).</em></p>
]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/categories/aws" term="aws" label="AWS" />
                             
                                <category scheme="https://www.ducea.com/categories/k8s" term="k8s" label="K8s" />
                            
                        
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/tags/aws" term="aws" label="aws" />
                             
                                <category scheme="https://www.ducea.com/tags/k8s" term="k8s" label="k8s" />
                             
                                <category scheme="https://www.ducea.com/tags/terraform" term="terraform" label="terraform" />
                             
                                <category scheme="https://www.ducea.com/tags/ack" term="ack" label="ack" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[HowTo Migrate your EKS cluster to Graviton2]]></title>
            <link href="https://www.ducea.com/2024/02/18/howto-migrate-your-eks-cluster-to-graviton2/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://www.ducea.com/2023/12/10/running-graviton2-workloads-on-eks-clusters-with-karpenter/?utm_source=atom_feed" rel="related" type="text/html" title="Running Graviton2 workloads on EKS clusters with Karpenter" />
                <link href="https://www.ducea.com/2023/01/14/howto-migrate-a-managed-aws-elasticsearch-cluster-to-graviton2/?utm_source=atom_feed" rel="related" type="text/html" title="HowTo Migrate a managed AWS Elasticsearch cluster to graviton2" />
                <link href="https://www.ducea.com/2022/11/12/howto-migrate-a-self-managed-elasticsearch-cluster-to-graviton2-instances/?utm_source=atom_feed" rel="related" type="text/html" title="HowTo Migrate a self managed Elasticsearch cluster to graviton2 instances" />
                <link href="https://www.ducea.com/2009/08/26/amazon-introduces-virtual-private-cloud-amazon-vpc/?utm_source=atom_feed" rel="related" type="text/html" title="Amazon Introduces Virtual Private Cloud (Amazon VPC)" />
                <link href="https://www.ducea.com/2009/08/17/using-instance-specific-metadata-in-eucalyptus/?utm_source=atom_feed" rel="related" type="text/html" title="Using instance-specific metadata in Eucalyptus" />
            
                <id>https://www.ducea.com/2024/02/18/howto-migrate-your-eks-cluster-to-graviton2/</id>
            
            
            <published>2024-02-18T10:52:55+00:00</published>
            <updated>2024-02-18T10:52:55+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>In this article, I&rsquo;m going to show you how you can migrate an existing <a href="https://aws.amazon.com/eks/">EKS</a> cluster to <a href="https://aws.amazon.com/ec2/graviton/">Graviton2</a> workers in a few simple steps. I&rsquo;m going to assume you already have an existing EKS cluster working on an Intel based infrastructure (Intel and/or AMD instance types).</p>
<h3 id="step-1-add-graviton2-worker-nodes-in-your-cluster">Step 1: add Graviton2 worker nodes in your cluster.</h3>
<p>This depends on how your EKS cluster is configured; you could have one of the following scenarios:</p>
<ul>
<li><strong>NodeGroup workers</strong>: this is a typical EKS install where you have worker nodes deployed in a nodegroup.</li>
<li>No nodegroups or autoscaling workers; these would be managed by something like <strong>Karpenter</strong> where we need to add the Graviton2 nodes like that.</li>
</ul>
<h4 id="nodegoup-setup">NodeGoup setup</h4>
<p>In this case, you will have to add a new nodegroup that has support for Graviton2 instances. Depending on how you created your nodegroups you would use a similar method. For example, I will show how to do this when using the terraform open-source <a href="https://github.com/terraform-aws-modules/terraform-aws-eks">EKS module</a>; this is a snippet of our cluster definition:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-hcl" data-lang="hcl"><span class="line"><span class="cl"><span class="k">module</span> <span class="s2">&#34;eks_cluster&#34;</span> {
</span></span><span class="line"><span class="cl"><span class="n">  source</span>  <span class="o">=</span> <span class="s2">&#34;terraform-aws-modules/eks/aws&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">  cluster_name</span>      <span class="o">=</span> <span class="s2">&#34;my-cluster&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">  cluster_version</span>   <span class="o">=</span> <span class="s2">&#34;1.28&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">  subnets</span>           <span class="o">=</span> <span class="p">[</span><span class="s2">&#34;subnet-xxxxxxx&#34;, &#34;subnet-yyyyyyy&#34;</span><span class="p">]</span> 
</span></span><span class="line"><span class="cl">  <span class="n">vpc_id</span>            <span class="o">=</span> <span class="s2">&#34;vpc-xxxxxxx&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">  manage_aws_auth</span>   <span class="o">=</span> <span class="kt">true</span>
</span></span><span class="line"><span class="cl"><span class="n">  node_groups</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    {
</span></span><span class="line"><span class="cl"><span class="n">      desired_capacity</span> <span class="o">=</span> <span class="m">2</span>
</span></span><span class="line"><span class="cl"><span class="n">      max_capacity</span>     <span class="o">=</span> <span class="m">10</span>
</span></span><span class="line"><span class="cl"><span class="n">      min_capacity</span>     <span class="o">=</span> <span class="m">1</span>
</span></span><span class="line"><span class="cl"><span class="n">      instance_type</span>    <span class="o">=</span> <span class="s2">&#34;m6i.xlarge&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">      name</span>             <span class="o">=</span> <span class="s2">&#34;intel-node-group&#34;</span>
</span></span><span class="line"><span class="cl">    }<span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">...</span>
</span></span><span class="line"><span class="cl">  <span class="p">]</span>
</span></span><span class="line"><span class="cl">}
</span></span></code></pre></div><p>in this case, if we want to add a graviton2 nodegroup we would just have to define a new one similar to the intel one but with graviton2 instances. For ex:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-hcl" data-lang="hcl"><span class="line"><span class="cl">    {
</span></span><span class="line"><span class="cl"><span class="n">      desired_capacity</span> <span class="o">=</span> <span class="m">2</span>
</span></span><span class="line"><span class="cl"><span class="n">      max_capacity</span>     <span class="o">=</span> <span class="m">10</span>
</span></span><span class="line"><span class="cl"><span class="n">      min_capacity</span>     <span class="o">=</span> <span class="m">1</span>
</span></span><span class="line"><span class="cl"><span class="n">      instance_type</span>    <span class="o">=</span> <span class="s2">&#34;m6g.xlarge&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">      name</span>             <span class="o">=</span> <span class="s2">&#34;arm64-node-group&#34;</span>
</span></span><span class="line"><span class="cl">    }<span class="p">,</span>
</span></span></code></pre></div><p>and reapply the terraform for the cluster definition.</p>
<h4 id="karpenter">Karpenter</h4>
<p>If your EKS cluster is using Karpenter to manage worker nodes then it will not use nodegroups and we will need to tell Karpenter to add these into the cluster. I&rsquo;ve written a dedicated article about this use case that you can follow along <a href="https://www.ducea.com/2023/12/10/running-graviton2-workloads-on-eks-clusters-with-karpenter/">here</a>.</p>
<h3 id="step-2-convert-your-workloads-to-graviton2">Step 2: Convert your workloads to graviton2.</h3>
<p>Now that we have graviton2 worker nodes in the cluster we can convert all our workloads to arm64. We have two special cases that we need to handle:</p>
<ul>
<li><strong>daemonsets</strong>; these are special k8s workloads that run on every single node. These are normally monitoring or logging agents, security agents, and other global infrastructure software that we usually don&rsquo;t write ourselves and we install and use in our cluster from either open source or commercial vendors.</li>
<li><strong>custom services</strong>; these are our own software that we have built and run in our clusters.</li>
</ul>
<h4 id="daemonsets">Daemonsets</h4>
<p>If any of your daemonsets doesn&rsquo;t have support for arm64 you will see that immediately after you add your first graviton2 worker in the cluster as those will fail to run there. Most of the time we install these with something like <strong>helm charts</strong> from an open source repository or vendor.</p>
<p>What is needed for this to work is to have all the containers used by the daemonset available for both intel and arm64. This can be seen on the image source in dockerhub or amazon ECR, etc. If there is no support for it we will probably need to work with the vendor or the open source maintainers to have them add support to build a multi-arch containers and have these available.</p>
<p>Assuming that the container registry has support for multi-arch and we have available the arm64 image, EKS nodes are capable of downloading from the registry the appropriate architecture the node is running automatically without any sepecial configuration. <em>Very cool!</em> This is the happy path; where upstream already has support for it or we can get this in the upstream and we don&rsquo;t have to change anything on our end.</p>
<p>Unfortunately, this doesn&rsquo;t work all the time. If that is the case, you will have to build the multi-arch containers yourself. Hopefully, the project has definitions for the dockerfile and it is not so difficult to rebuild the image with something like <a href="https://github.com/docker/buildx">buildx</a> for multi-arch. Once we have that, we can push it to an internal repo, and then use it in the helm chart instead of the official image. Most helm charts will allow us to redefine the image in use with your own custom images; look for that in the <code>values.yaml</code>. This would look something like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">image</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># -- image registry</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">registry</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;docker.io&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># -- Image repository.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">repository</span><span class="p">:</span><span class="w"> </span><span class="l">project/agent</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># -- image tag: latest or defined.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">tag</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># -- image pull policy.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">pullPolicy</span><span class="p">:</span><span class="w"> </span><span class="l">IfNotPresent</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># -- Optional set of image pull secrets.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">pullSecrets</span><span class="p">:</span><span class="w"> </span><span class="p">[]</span><span class="w">
</span></span></span></code></pre></div><p>Where we would replace with the custom registry (maybe a private ECR) and the repository (our custom project in ecr)</p>
<h4 id="custom-software">Custom software</h4>
<p>The rest of the deployments running in the EKS cluster should be our custom software that we should have full control over and be able to compile and build for multi-arch format. While we are in the transition phase and we don&rsquo;t have arm64 images for some deployments we need to make sure we are using a selector to have those run on intel nodes as if not they will fail. We can do this with something like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">      </span><span class="nt">nodeSelector</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">intent</span><span class="p">:</span><span class="w"> </span><span class="l">apps</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">kubernetes.io/arch</span><span class="p">:</span><span class="w"> </span><span class="l">amd64</span><span class="w">
</span></span></span></code></pre></div><p>inside the definition of the service. This will force it to run on the original intel worker nodes.</p>
<p>Once we have built the arm64 image we can just remove that selector and allow it to be deployed on any node type, or we can change it to <code>kubernetes.io/arch: arm64</code> and force it on graviton2 nodes.</p>
<p>Depending on how many services you have deployed in your cluster and how unique they are, this might be a tedious process until you can switch all of those to graviton2 nodes, but this should be worth it, bringing great performance and cost savings along the way.</p>
<p>Once you have migrated all your workloads to graviton2 you can just retire the intel nodegroups and after that, your EKS cluster will be running fully on graviton2. Boom!</p>
]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/categories/aws" term="aws" label="AWS" />
                             
                                <category scheme="https://www.ducea.com/categories/k8s" term="k8s" label="K8s" />
                            
                        
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/tags/aws" term="aws" label="aws" />
                             
                                <category scheme="https://www.ducea.com/tags/k8s" term="k8s" label="k8s" />
                             
                                <category scheme="https://www.ducea.com/tags/graviton2" term="graviton2" label="graviton2" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Running Graviton2 workloads on EKS clusters with Karpenter]]></title>
            <link href="https://www.ducea.com/2023/12/10/running-graviton2-workloads-on-eks-clusters-with-karpenter/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://www.ducea.com/2023/01/14/howto-migrate-a-managed-aws-elasticsearch-cluster-to-graviton2/?utm_source=atom_feed" rel="related" type="text/html" title="HowTo Migrate a managed AWS Elasticsearch cluster to graviton2" />
                <link href="https://www.ducea.com/2022/11/12/howto-migrate-a-self-managed-elasticsearch-cluster-to-graviton2-instances/?utm_source=atom_feed" rel="related" type="text/html" title="HowTo Migrate a self managed Elasticsearch cluster to graviton2 instances" />
                <link href="https://www.ducea.com/2009/08/26/amazon-introduces-virtual-private-cloud-amazon-vpc/?utm_source=atom_feed" rel="related" type="text/html" title="Amazon Introduces Virtual Private Cloud (Amazon VPC)" />
                <link href="https://www.ducea.com/2009/08/17/using-instance-specific-metadata-in-eucalyptus/?utm_source=atom_feed" rel="related" type="text/html" title="Using instance-specific metadata in Eucalyptus" />
                <link href="https://www.ducea.com/2009/08/12/running-s3sync-in-parallel/?utm_source=atom_feed" rel="related" type="text/html" title="Running s3sync in parallel" />
            
                <id>https://www.ducea.com/2023/12/10/running-graviton2-workloads-on-eks-clusters-with-karpenter/</id>
            
            
            <published>2023-12-10T10:52:55+00:00</published>
            <updated>2023-12-10T10:52:55+00:00</updated>
            
            
            <content type="html"><![CDATA[<p><strong>Amazon Elastic Kubernetes Service</strong> (<a href="https://aws.amazon.com/eks/">EKS</a>) provides a managed Kubernetes service, allowing users to deploy, manage, and scale containerized applications using Kubernetes on AWS. With the introduction of <strong>Graviton2</strong> processors, AWS offers enhanced performance and cost savings.</p>
<p><strong>Karpenter</strong> is an open-source node lifecycle management project built for Kubernetes that was created by AWS as an alternative for the cluster autoscaler project.</p>
<p>In this article, we are going to look into what steps are needed to run graviton2 (arm64) based workloads in a EKS cluster that is managed with Karpenter.  I&rsquo;m going to assume you have a running EKS cluster and karpenter is properly configured in the cluster; if you need help setting up a new cluster with karpenter follow along with the documentation at the <a href="https://karpenter.sh/">official site</a></p>
<h3 id="nodepool">NodePool</h3>
<p>The <a href="https://karpenter.sh/docs/concepts/nodepools/">NodePool</a> sets constraints on the nodes that can be created by Karpenter and the pods that can run on those nodes. The NodePool configures things like:</p>
<ul>
<li>Define taints to limit the pods that can run on nodes Karpenter creates</li>
<li>Define any startup taints to inform Karpenter that it should taint the node initially, but that the taint is temporary.</li>
<li>Limit node creation to certain zones, instance types, and <em>computer architectures</em> (like arm64 or amd64)</li>
</ul>
<p>You can get the active karpenter nodepools in your cluster with:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">kubectl describe nodepool
</span></span></code></pre></div><p>Let&rsquo;s say that in our case this is driven by a configuration that looks like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">karpenter.sh/v1beta1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">NodePool</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">default </span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">spec</span><span class="p">:</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">template</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">labels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">intent</span><span class="p">:</span><span class="w"> </span><span class="l">apps</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">requirements</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l">kubernetes.io/arch</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">operator</span><span class="p">:</span><span class="w"> </span><span class="l">In</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">values</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;amd64&#34;</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;karpenter.k8s.aws/instance-cpu&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">operator</span><span class="p">:</span><span class="w"> </span><span class="l">In</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">values</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;4&#34;</span><span class="p">,</span><span class="w"> </span><span class="s2">&#34;8&#34;</span><span class="p">,</span><span class="w"> </span><span class="s2">&#34;16&#34;</span><span class="p">,</span><span class="w"> </span><span class="s2">&#34;32&#34;</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l">karpenter.sh/capacity-type</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">operator</span><span class="p">:</span><span class="w"> </span><span class="l">In</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">values</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;spot&#34;</span><span class="p">,</span><span class="w"> </span><span class="s2">&#34;on-demand&#34;</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l">karpenter.k8s.aws/instance-category</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">operator</span><span class="p">:</span><span class="w"> </span><span class="l">In</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">values</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;c&#34;</span><span class="p">,</span><span class="w"> </span><span class="s2">&#34;m&#34;</span><span class="p">,</span><span class="w"> </span><span class="s2">&#34;r&#34;</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">nodeClassRef</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">default</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">kubelet</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">containerRuntime</span><span class="p">:</span><span class="w"> </span><span class="l">containerd</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">systemReserved</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">cpu</span><span class="p">:</span><span class="w"> </span><span class="l">100m</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">memory</span><span class="p">:</span><span class="w"> </span><span class="l">100Mi</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">disruption</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">consolidationPolicy</span><span class="p">:</span><span class="w"> </span><span class="l">WhenUnderutilized</span><span class="w">
</span></span></span></code></pre></div><p>Here we can see that this nodepool allows only amd64 (intel or amd) type of instances. If we want to support graviton2 (arm64) instances we would need to either update this definition to support that or create a new separate nodepool. Let&rsquo;s just add support in the existing one by adding this key to the requrements:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">       - key: kubernetes.io/arch
</span></span><span class="line"><span class="cl">          operator: In
</span></span><span class="line"><span class="cl">          values: [&#34;amd64&#34;, &#34;arm64&#34;]
</span></span></code></pre></div><p>and then re-apply it with <code>kubectl apply</code>. Now our nodepool supports both intel and graviton2 instance types.</p>
<h3 id="nodeclass">NodeClass</h3>
<p>Another important concept for Karpenter is the <a href="https://karpenter.sh/docs/concepts/nodeclasses/">EC2NodeClass</a>. Node Classes enable configuration of AWS specific settings. Each NodePool must reference an EC2NodeClass using spec.template.spec.nodeClassRef. Here we configure things like subnets, security groups, and what AMIs to use for the instances.</p>
<p>The configuration for this might look something like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">karpenter.k8s.aws/v1beta1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">EC2NodeClass</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">default</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">role</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;${local.node_iam_role_name}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">amiFamily</span><span class="p">:</span><span class="w"> </span><span class="l">AL2 </span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">securityGroupSelectorTerms</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">tags</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">karpenter.sh/discovery</span><span class="p">:</span><span class="w"> </span><span class="l">${local.name}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">subnetSelectorTerms</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">tags</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">karpenter.sh/discovery</span><span class="p">:</span><span class="w"> </span><span class="l">${local.name}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">tags</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">IntentLabel</span><span class="p">:</span><span class="w"> </span><span class="l">apps</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">KarpenterNodePoolName</span><span class="p">:</span><span class="w"> </span><span class="l">default</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">NodeType</span><span class="p">:</span><span class="w"> </span><span class="l">default</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">intent</span><span class="p">:</span><span class="w"> </span><span class="l">apps</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">karpenter.sh/discovery</span><span class="p">:</span><span class="w"> </span><span class="l">${local.name}</span><span class="w">
</span></span></span></code></pre></div><p>Where <code>${local.name}</code> is the name of the cluster and <code>${node_iam_role_name}</code> is the name of the IAM role used for the ec2 instances. A configuration like this where we don&rsquo;t define any of the AMIs and only use the <code>amiFamily: AL2</code> (Amazon Linux 2) will automatically detect and use the latest ami for each of the available architectures we have in our nodepool; so we would not have to change anything in this case!!! ;)</p>
<p>You can see the compiled form with the actual AMIs using:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">kubectl describe ec2nodeclass
</span></span></code></pre></div><p>Still, in some cases, folks will prefer to control this and define manually AMIs like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">status</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">amis</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">id</span><span class="p">:</span><span class="w"> </span><span class="l">ami-01234567890123456</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">custom-ami-amd64</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">requirements</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l">kubernetes.io/arch</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">operator</span><span class="p">:</span><span class="w"> </span><span class="l">In</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">values</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="l">amd64</span><span class="w">
</span></span></span></code></pre></div><p>and if that is the case we need to make sure we have a similar definition for a valid arm64 ami:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">id</span><span class="p">:</span><span class="w"> </span><span class="l">ami-01234567890123456</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">custom-ami-arm64</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">requirements</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l">kubernetes.io/arch</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">operator</span><span class="p">:</span><span class="w"> </span><span class="l">In</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">values</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="l">arm64</span><span class="w">
</span></span></span></code></pre></div><p>That&rsquo;s it; it is as simple as that; we have a nodepool that supports arm64 instances and a nodeclass that defines a proper ami to be used by those.</p>
<p>You can test this with a simple deployment like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">apps/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Deployment</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">workload-graviton</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">replicas</span><span class="p">:</span><span class="w"> </span><span class="m">5</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">selector</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">matchLabels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">workload-graviton</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">template</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">labels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">workload-graviton</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">nodeSelector</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">intent</span><span class="p">:</span><span class="w"> </span><span class="l">apps</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">kubernetes.io/arch</span><span class="p">:</span><span class="w"> </span><span class="l">arm64</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">containers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">graviton2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">public.ecr.aws/eks-distro/kubernetes/pause:3.7</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">imagePullPolicy</span><span class="p">:</span><span class="w"> </span><span class="l">Always</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">resources</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">requests</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">cpu</span><span class="p">:</span><span class="w"> </span><span class="l">512m</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">memory</span><span class="p">:</span><span class="w"> </span><span class="l">512Mi </span><span class="w">
</span></span></span></code></pre></div><p>and apply it with kubectl:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">kubectl apply -f workload-graviton.yaml
</span></span></code></pre></div><p>Give it a couple of minutes and you can see the new node in the cluster:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">kubectl get nodes -L karpenter.sh/capacity-type,beta.kubernetes.io/instance-type,karpenter.sh/nodepool,topology.kubernetes.io/zone -l karpenter.sh/initialized=true
</span></span></code></pre></div><p>the output will look something like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">NAME                          STATUS   ROLES    AGE   VERSION               CAPACITY-TYPE   INSTANCE-TYPE   NODEPOOL   ZONE
</span></span><span class="line"><span class="cl">ip-10-0-62-224.ec2.internal   Ready    &lt;none&gt;   60s   v1.28.5-eks-5e0fdde   spot            c6g.xlarge      default    us-east-1a
</span></span><span class="line"><span class="cl">ip-10-0-79-148.ec2.internal   Ready    &lt;none&gt;   87m   v1.28.5-eks-5e0fdde   on-demand       c6g.xlarge      default    us-east-1b
</span></span></code></pre></div><p>You can also check the karpenter logs with:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">kubectl -n karpenter logs -l app.kubernetes.io/name=karpenter --all-containers=true -f
</span></span></code></pre></div><p><em>Note: if you played along to test this, please don&rsquo;t forget to clean up and delete the resources you no longer need.</em></p>
<p>Finally, I wanted to point out that because karpenter is automatically choosing the most cost-effective instances for your configuration (on-demand vs spot, or graviton2 vs intel) your instances might tilt automatically towards graviton2. You can still control your deployment if you want to run them on amd64 instances (for ex. if you don&rsquo;t have arm64 versions available) using the kubernetes.io/arch spec config.</p>
]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/categories/aws" term="aws" label="AWS" />
                             
                                <category scheme="https://www.ducea.com/categories/k8s" term="k8s" label="K8s" />
                            
                        
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/tags/aws" term="aws" label="aws" />
                             
                                <category scheme="https://www.ducea.com/tags/k8s" term="k8s" label="k8s" />
                             
                                <category scheme="https://www.ducea.com/tags/graviton2" term="graviton2" label="graviton2" />
                             
                                <category scheme="https://www.ducea.com/tags/karpenter" term="karpenter" label="karpenter" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[HowTo Migrate a managed AWS Elasticsearch cluster to graviton2]]></title>
            <link href="https://www.ducea.com/2023/01/14/howto-migrate-a-managed-aws-elasticsearch-cluster-to-graviton2/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://www.ducea.com/2022/11/12/howto-migrate-a-self-managed-elasticsearch-cluster-to-graviton2-instances/?utm_source=atom_feed" rel="related" type="text/html" title="HowTo Migrate a self managed Elasticsearch cluster to graviton2 instances" />
                <link href="https://www.ducea.com/2009/08/26/amazon-introduces-virtual-private-cloud-amazon-vpc/?utm_source=atom_feed" rel="related" type="text/html" title="Amazon Introduces Virtual Private Cloud (Amazon VPC)" />
                <link href="https://www.ducea.com/2009/08/17/using-instance-specific-metadata-in-eucalyptus/?utm_source=atom_feed" rel="related" type="text/html" title="Using instance-specific metadata in Eucalyptus" />
                <link href="https://www.ducea.com/2009/08/12/running-s3sync-in-parallel/?utm_source=atom_feed" rel="related" type="text/html" title="Running s3sync in parallel" />
                <link href="https://www.ducea.com/2009/06/01/howto-update-dns-hostnames-automatically-for-your-amazon-ec2-instances/?utm_source=atom_feed" rel="related" type="text/html" title="HowTo update DNS hostnames automatically for your Amazon EC2 instances" />
            
                <id>https://www.ducea.com/2023/01/14/howto-migrate-a-managed-aws-elasticsearch-cluster-to-graviton2/</id>
            
            
            <published>2023-01-14T10:52:55+00:00</published>
            <updated>2023-01-14T10:52:55+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>Amazon Web Services (AWS) offers managed Amazon Elasticsearch clusters (or OpenSearch as they call their fork of the open source Elasticsearch) for deploying and managing search applications. Lately, I&rsquo;ve been managing several self-managed clusters and showed how I&rsquo;ve migrated those to <a href="https://www.ducea.com/2022/11/12/howto-migrate-a-self-managed-elasticsearch-cluster-to-graviton2-instances/">graviton2</a>; for newer clusters, I&rsquo;ve started exploring the AWS managed solution for Elasticsearch. This has several advantages:</p>
<ul>
<li>Simplified management: With Amazon OpenSearch, AWS takes care of the infrastructure management tasks, such as deploying and configuring the Elasticsearch cluster, patching the underlying operating system, and handling backups and disaster recovery. This allows you to focus on using Elasticsearch to build your search applications, rather than worrying about the underlying infrastructure.</li>
<li>Scalability: Amazon OpenSearch makes it easy to scale your Elasticsearch cluster up or down to meet changing demands. You can add or remove nodes to the cluster with just a few clicks, or use features like auto-scaling to automatically adjust the size of the cluster based on workload patterns.</li>
<li>Availability: Amazon OpenSearch is designed for high availability, with built-in replication and failover capabilities. This helps ensure that your search application remains available even in the face of hardware failures or other issues.</li>
<li>Security: Amazon OpenSearch provides a range of security features to help protect your data, including encryption at rest and in transit, access controls, and integration with AWS Identity and Access Management (IAM) for fine-grained access control.</li>
<li>Integration with other AWS services: Amazon OpenSearch integrates with other AWS services, such as Amazon CloudWatch for monitoring, AWS CloudTrail for auditing, and AWS Identity and Access Management (IAM) for access control. This makes it easy to build end-to-end search applications on AWS.</li>
<li>Cost optimization: Using Amazon OpenSearch can help reduce costs by eliminating the need to manage and maintain your own Elasticsearch cluster infrastructure. Additionally, AWS offers Graviton2-based instances that are optimized for running Amazon OpenSearch and provide better performance and cost efficiency compared to traditional x86-based instances.</li>
</ul>
<p>In this post, I&rsquo;ll walk you through the process of upgrading an existing managed Amazon Elasticsearch cluster to Graviton2. We will use the same cluster to perform the upgrade, which means we will upgrade the cluster in place, without creating a new cluster.</p>
<h3 id="step-1-change-the-instance-types-to-graviton2">Step 1: Change the instance types to Graviton2</h3>
<p>This migration is much easier than the self-managed one; it requires only one step ;). We first need to figure out the graviton2 instance type we want to use for our migration. As like with regular ec2 instances AWS provides a wide range of instances for Elasticsearch. The main ones are the &ldquo;m&rdquo; instances which are general-purpose instances, and the &ldquo;r&rdquo; instances are memory-optimized. The number after the instance type (e.g. &ldquo;2xlarge&rdquo; or &ldquo;16xlarge&rdquo;) indicates the number of vCPUs and the amount of memory available on the instance:</p>
<p>The available Amazon OpenSearch-optimized Graviton2 instances are:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">m6g.medium.elasticsearch
</span></span><span class="line"><span class="cl">m6g.large.elasticsearch
</span></span><span class="line"><span class="cl">m6g.xlarge.elasticsearch
</span></span><span class="line"><span class="cl">m6g.2xlarge.elasticsearch
</span></span><span class="line"><span class="cl">m6g.4xlarge.elasticsearch
</span></span><span class="line"><span class="cl">m6g.8xlarge.elasticsearch
</span></span><span class="line"><span class="cl">m6g.12xlarge.elasticsearch
</span></span><span class="line"><span class="cl">m6g.16xlarge.elasticsearch
</span></span><span class="line"><span class="cl">r6g.large.elasticsearch
</span></span><span class="line"><span class="cl">r6g.xlarge.elasticsearch
</span></span><span class="line"><span class="cl">r6g.2xlarge.elasticsearch
</span></span><span class="line"><span class="cl">r6g.4xlarge.elasticsearch
</span></span><span class="line"><span class="cl">r6g.8xlarge.elasticsearch
</span></span><span class="line"><span class="cl">r6g.12xlarge.elasticsearch
</span></span><span class="line"><span class="cl">r6g.16xlarge.elasticsearch
</span></span></code></pre></div><p>Note: we will also need to make sure we run a supported version of the managed AWS Elasticsearch/OpenSearch that supports graviton2 instances. For the older Elasticsearch anything newer than 7.8 should work, and if you are using the OpenSearch version then any version would work as this has been available since version 1.0.0. If you are running an older version you will need first to upgrade to a supported version before moving forward.</p>
<p>The actual migration only requires us to change the instance type. This can be done in the AWS console, using the AWS cli, or a tool like terraform. Since I use terraform to manage all the cloud assets I will show how this is done with terraform; this would look something like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">resource &#34;aws_opensearch_domain&#34; &#34;elasticsearch_domain&#34; {
</span></span><span class="line"><span class="cl">  domain_name           = &#34;search-domain&#34;
</span></span><span class="line"><span class="cl">  elasticsearch_version = &#34;7.10&#34;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  cluster_config {
</span></span><span class="line"><span class="cl">    instance_type           = &#34;m6g.large.elasticsearch&#34; # this replaces the previous m5 type of instance we had
</span></span><span class="line"><span class="cl">    instance_count          = 3
</span></span><span class="line"><span class="cl">    dedicated_master_enabled = true
</span></span><span class="line"><span class="cl">    dedicated_master_count   = 3
</span></span><span class="line"><span class="cl">  }
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  ebs_options {
</span></span><span class="line"><span class="cl">    ebs_enabled = true
</span></span><span class="line"><span class="cl">    volume_type = &#34;gp3&#34;
</span></span><span class="line"><span class="cl">    volume_size = 1000
</span></span><span class="line"><span class="cl">  }
</span></span><span class="line"><span class="cl">... # other elasticsearch cluster configs
</span></span><span class="line"><span class="cl">}
</span></span></code></pre></div><p>I want to point out also that we are now able to use gp3 for the ebs volume which allows for much better performance and increased size allowed per data node. This is great optimization that can make the cluster much faster and reduce the need for extra data nodes (we were able to cut our nodes in half from this combination: graviton2 for better performance and gp3 for higher storage capacity per node)</p>
<p>Once you run <code>terraform apply</code> with the new instance type this will kick in the automatic blue-green deployment from AWS managed Elasticsearch that will spin up a new set of nodes and migrate the data to the new nodes; once this is done the original nodes are automatically removed. Depending on the size of your data in the cluster this might take a long time and terraform might time out (60m by default). If this happens, you can use the AWS console or cli to monitor the status of the migration.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">aws es describe-upgrade --domain-name &lt;domain-name&gt;
</span></span></code></pre></div><p>should show the status of the upgrade for the specified domain. You can also check the health of the cluster after the upgrade:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">aws es describe-elasticsearch-domain --domain-name &lt;domain-name&gt; --query &#39;DomainStatus.ClusterStatus.Health&#39;
</span></span></code></pre></div><p>This command will return the current health status of the Elasticsearch cluster. If the upgrade has been completed successfully, the cluster should have a green health status. If there are any issues with the upgrade, the cluster may have a yellow or red health status, indicating that there are problems that need to be addressed</p>
<p>Note: theoretically there should be no downtime during the process, but the performance might be slightly impacted during the blue-green migration.</p>
<p>As you can see there is a huge advantage while performing such a migration using a managed service compared with the self-managed solution where we had to handle and take care of everything ourselves.</p>
<h3 id="conclusion">Conclusion</h3>
<p>Upgrading a managed Amazon Elasticsearch cluster to Graviton2 is a straightforward process that can provide significant benefits. By upgrading to Graviton2 instances, you can improve performance, reduce costs, and increase the efficiency of your infrastructure. AWS offers several Graviton2 instance types optimized for Amazon OpenSearch, each with its own set of advantages.</p>
<p>In this post, I have walked you through the process of upgrading an existing managed Amazon OpenSearch cluster to Graviton2 instances. We have used the same cluster to perform the upgrade, which means we have upgraded the cluster in place, without creating a new cluster. I have also provided examples and command-line steps to help you through the process.</p>
<p>Overall, upgrading your managed Amazon OpenSearch cluster to Graviton2 instances is a great way to take advantage of the latest technology and improve the performance and cost efficiency of your search application.</p>
]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/categories/aws" term="aws" label="AWS" />
                            
                        
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/tags/aws" term="aws" label="aws" />
                             
                                <category scheme="https://www.ducea.com/tags/elasticsearch" term="elasticsearch" label="elasticsearch" />
                             
                                <category scheme="https://www.ducea.com/tags/graviton2" term="graviton2" label="graviton2" />
                             
                                <category scheme="https://www.ducea.com/tags/terraform" term="terraform" label="terraform" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[HowTo Migrate a self managed Elasticsearch cluster to graviton2 instances]]></title>
            <link href="https://www.ducea.com/2022/11/12/howto-migrate-a-self-managed-elasticsearch-cluster-to-graviton2-instances/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://www.ducea.com/2009/08/26/amazon-introduces-virtual-private-cloud-amazon-vpc/?utm_source=atom_feed" rel="related" type="text/html" title="Amazon Introduces Virtual Private Cloud (Amazon VPC)" />
                <link href="https://www.ducea.com/2009/08/17/using-instance-specific-metadata-in-eucalyptus/?utm_source=atom_feed" rel="related" type="text/html" title="Using instance-specific metadata in Eucalyptus" />
                <link href="https://www.ducea.com/2009/08/12/running-s3sync-in-parallel/?utm_source=atom_feed" rel="related" type="text/html" title="Running s3sync in parallel" />
                <link href="https://www.ducea.com/2009/06/01/howto-update-dns-hostnames-automatically-for-your-amazon-ec2-instances/?utm_source=atom_feed" rel="related" type="text/html" title="HowTo update DNS hostnames automatically for your Amazon EC2 instances" />
                <link href="https://www.ducea.com/2009/05/13/cloud-slam-09-the-1st-virtual-conference-on-cloud-computing/?utm_source=atom_feed" rel="related" type="text/html" title="Cloud Slam 09 - the 1st Virtual Conference on Cloud Computing" />
            
                <id>https://www.ducea.com/2022/11/12/howto-migrate-a-self-managed-elasticsearch-cluster-to-graviton2-instances/</id>
            
            
            <published>2022-11-12T10:52:55+00:00</published>
            <updated>2022-11-12T10:52:55+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>Elasticsearch is an open-source search engine that enables you to store, search, and analyze big data in real time. It is a distributed and scalable search engine that can be used to index and search large volumes of data across multiple nodes. I&rsquo;m currently managing several Elasticsearch clusters running on AWS EC2 instances. AWS offers EC2 instances powered by Graviton2 processors (their custom arm processors) that offer significant performance and cost benefits compared to traditional x86 instances (up to 40% based on AWS benchmarks, with 20% from pure cost savings and 20% from performance improvements compared to similar intel processors). In this blog post, I&rsquo;ll walk you through the process of how we migrated our Elasticsearch clusters to run on Graviton EC2 instances.</p>
<p>The first Elasticsearch version that added support for ARM processors was Elasticsearch 7.8. This version introduced official support for ARM64 architecture and was released on May 26, 2020. Before this release, Elasticsearch was only officially supported on x86-based platforms. So in our case, this required us to migrate to a supported version first. We were running an older version in the stable branch 7.x and we upgraded to 7.17 using the standard Elasticsearch rolling upgrade <a href="https://www.elastic.co/guide/en/elasticsearch/reference/7.17/rolling-upgrades.html">docs</a>.</p>
<p>Here are the steps needed for this migration:</p>
<h3 id="step-1-create-a-new-graviton2-based-ec2-instances">Step 1: Create a new Graviton2-based EC2 instances</h3>
<p>The first step in the migration process is to create new Graviton2-based EC2 instances. You can do this using the AWS Management Console or the AWS CLI, or even better use terraform as I do. Various Linux distributions run on ARM, but I have chosen to use an Amazon Linux 2 AMI because this is very well supported by AWS. We can use the AWS console and use the filter for &ldquo;Architecture&rdquo; to be set to &ldquo;arm64&rdquo; for AMI and find the latest Amazon Linux 2 AMI. Or use a simple aws cli command like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">aws ssm get-parameters --names /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2 --region us-east-1
</span></span></code></pre></div><p>This will return the Graviton2 AMI for the specific region we are using. We would use this in our terraform code to create the new Graviton2 instances; for ex:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"># Elasticsearch nodes
</span></span><span class="line"><span class="cl">resource &#34;aws_instance&#34; &#34;es_nodes&#34; {
</span></span><span class="line"><span class="cl">  count         = 3
</span></span><span class="line"><span class="cl">  ami           = &#34;ami-XXX&#34; # Replace with the AMI we found above
</span></span><span class="line"><span class="cl">  instance_type = &#34;c6g.large&#34;
</span></span><span class="line"><span class="cl">  security_groups = [aws_security_group.es_node_sg.name]
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">  user_data = &lt;&lt;-EOF
</span></span><span class="line"><span class="cl">              #!/bin/bash
</span></span><span class="line"><span class="cl">              echo &#34;cluster.name: es-cluster&#34; &gt;&gt; /etc/elasticsearch/elasticsearch.yml
</span></span><span class="line"><span class="cl">              echo &#34;node.name: ${format(&#34;es-node-%02d&#34;, count.index+1)}&#34; &gt;&gt; /etc/elasticsearch/elasticsearch.yml
</span></span><span class="line"><span class="cl">              echo &#34;network.host: [_ec2_:privateIpv4_, _local_]&#34; &gt;&gt; /etc/elasticsearch/elasticsearch.yml
</span></span><span class="line"><span class="cl">              systemctl restart elasticsearch
</span></span><span class="line"><span class="cl">              EOF
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">  tags = {
</span></span><span class="line"><span class="cl">    Name = &#34;es-node-${count.index+1}&#34;
</span></span><span class="line"><span class="cl">  }
</span></span><span class="line"><span class="cl">}
</span></span></code></pre></div><h3 id="step-2-install-elasticsearch-on-the-new-instance">Step 2: Install Elasticsearch on the new instance</h3>
<p>Normally we would install Elasticsearch on the nodes using the user_data script, but during this migration, we went with a more manual method; you can install Elasticsearch using the RPM or DEB packages provided by Elasticsearch. Here is an example command to install Elasticsearch on an Amazon Linux 2 instance:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
</span></span><span class="line"><span class="cl">sudo tee /etc/yum.repos.d/elasticsearch.repo &lt;&lt;EOF
</span></span><span class="line"><span class="cl">[elasticsearch-7.x]
</span></span><span class="line"><span class="cl">name=Elasticsearch repository for 7.x packages
</span></span><span class="line"><span class="cl">baseurl=https://artifacts.elastic.co/packages/7.x/yum
</span></span><span class="line"><span class="cl">gpgcheck=1
</span></span><span class="line"><span class="cl">gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
</span></span><span class="line"><span class="cl">enabled=1
</span></span><span class="line"><span class="cl">autorefresh=1
</span></span><span class="line"><span class="cl">type=rpm-md
</span></span><span class="line"><span class="cl">EOF
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">sudo yum install -y elasticsearch
</span></span></code></pre></div><h3 id="step-3-configure-elasticsearch-on-the-new-instances">Step 3: Configure Elasticsearch on the new instances</h3>
<p>After installing Elasticsearch on the new Graviton2-based EC2 instance, the next step is to configure Elasticsearch to use the existing data and settings from the old Elasticsearch cluster. You can do this by copying the Elasticsearch configuration files from the old cluster to the new instance.</p>
<p>This might look something like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">rsync -avz --progress --delete /path/to/old/cluster/config/ ec2-user@new-instance-ip:/etc/elasticsearch/
</span></span></code></pre></div><h3 id="step-4-start-elasticsearch-on-the-new-instance">Step 4: Start Elasticsearch on the new instance</h3>
<p>Finally, once the Elasticsearch configuration files are copied to the new Graviton2-based EC2 instance, the next step is to start Elasticsearch on the new instance. You can do this using the Elasticsearch service command. Here is an example command to start Elasticsearch on the new instance:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo service elasticsearch start
</span></span></code></pre></div><h3 id="step-5-verify-the-migration">Step 5: Verify the migration</h3>
<p>The final step in the migration process is to verify that the data and settings from the old Elasticsearch cluster have been successfully migrated to the new Graviton2-based EC2 instance. You can do this by checking the Elasticsearch logs and running some search queries on the new instance.</p>
<p>Here is an example command to check the Elasticsearch logs on the new instance:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo tail -f /var/log/elasticsearch/elasticsearch.log
</span></span></code></pre></div><p>This command shows the Elasticsearch logs on the new instance, and you can use it to check if any errors or warnings are reported during the migration process.</p>
<h3 id="step-6-remove-original-nodes">Step 6: Remove original nodes</h3>
<p>After all the new Graviton2 instances are in sync in the cluster you can go ahead and remove the old intel instances one by one and allow the cluster to rebalance.</p>
<h3 id="conclusion">Conclusion</h3>
<p>Migrating an Elasticsearch cluster to running on Graviton EC2 instances can provide significant performance and cost benefits. In this blog post, I walked you through the process of migrating an existing Elasticsearch cluster to new Graviton2-based EC2 instances. By following the steps outlined in this post, you can easily migrate your Elasticsearch cluster to Graviton2-based EC2 instances and take advantage of the cost/performance improvements they offer.</p>
]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/categories/aws" term="aws" label="AWS" />
                            
                        
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/tags/aws" term="aws" label="aws" />
                             
                                <category scheme="https://www.ducea.com/tags/elasticsearch" term="elasticsearch" label="elasticsearch" />
                             
                                <category scheme="https://www.ducea.com/tags/graviton2" term="graviton2" label="graviton2" />
                             
                                <category scheme="https://www.ducea.com/tags/terraform" term="terraform" label="terraform" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Speedup MySQL InnoDB shutdown]]></title>
            <link href="https://www.ducea.com/2014/01/19/speedup-mysql-innodb-shutdown/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://www.ducea.com/2009/03/17/howto-get-a-small-sample-dataset-from-a-mysql-database-using-mysqldump/?utm_source=atom_feed" rel="related" type="text/html" title="HowTo get a small sample dataset from a mysql database using mysqldump" />
                <link href="https://www.ducea.com/2009/03/13/innodb-plugin-version-103-released-enhances-concurrency-and-scalability-on-multi-core-systems/?utm_source=atom_feed" rel="related" type="text/html" title="InnoDB Plugin Version 1.0.3 released: enhances concurrency and scalability on multi-core systems" />
                <link href="https://www.ducea.com/2009/01/19/running-multiple-instances-of-mysql-on-the-same-machine/?utm_source=atom_feed" rel="related" type="text/html" title="Running multiple instances of MySQL on the same machine" />
                <link href="https://www.ducea.com/2008/02/13/mysql-skip-duplicate-replication-errors/?utm_source=atom_feed" rel="related" type="text/html" title="MySQL skip duplicate replication errors" />
                <link href="https://www.ducea.com/2012/02/07/howto-completely-remove-a-file-from-git-history/?utm_source=atom_feed" rel="related" type="text/html" title="HowTo completely remove a file from Git history" />
            
                <id>https://www.ducea.com/2014/01/19/speedup-mysql-innodb-shutdown/</id>
            
            
            <published>2014-01-19T09:52:55+00:00</published>
            <updated>2014-01-19T09:52:55+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>Depending on the size of the databases you have in mysql innodb the time it takes mysql to restart can be horribly slow (for very big innodb databases). There are some tricks that can speed this up, but the most effective one that I&rsquo;ve found and use all the time in similar situations is to pre-flush the dirty pages right before shutdown; this can be done like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">mysql&gt; set global innodb_max_dirty_pages_pct = 0;
</span></span></code></pre></div><p>You can check the number of dirty pages with the command:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">mysqladmin ext -i10 | grep dirty
</span></span></code></pre></div><p>Let the server run like this for a while and after you see it settle in, the restart (or stop) should be much faster.</p>
]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/categories/linux" term="linux" label="Linux" />
                             
                                <category scheme="https://www.ducea.com/categories/tips-tricks" term="tips-tricks" label="Tips &amp; Tricks" />
                            
                        
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/tags/mysql" term="mysql" label="mysql" />
                             
                                <category scheme="https://www.ducea.com/tags/innodb" term="innodb" label="innodb" />
                             
                                <category scheme="https://www.ducea.com/tags/tips" term="tips" label="tips" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[HowTo Migrate to Chef 11]]></title>
            <link href="https://www.ducea.com/2013/03/05/howto-migrate-to-chef-11/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://www.ducea.com/2013/03/04/knife-backup/?utm_source=atom_feed" rel="related" type="text/html" title="knife-backup" />
                <link href="https://www.ducea.com/2013/02/26/knife-cleanup/?utm_source=atom_feed" rel="related" type="text/html" title="knife-cleanup" />
                <link href="https://www.ducea.com/2013/02/04/bay-area-chef-user-group-update-after-one-year/?utm_source=atom_feed" rel="related" type="text/html" title="Bay Area Chef User Group Update - After One Year" />
                <link href="https://www.ducea.com/2012/05/18/chefconf-2012-san-francisco/?utm_source=atom_feed" rel="related" type="text/html" title="ChefConf 2012 - San Francisco" />
                <link href="https://www.ducea.com/2011/08/23/first-chef-cookbook-contest-announced/?utm_source=atom_feed" rel="related" type="text/html" title="First Chef Cookbook Contest Announced!" />
            
                <id>https://www.ducea.com/2013/03/05/howto-migrate-to-chef-11/</id>
            
            
            <published>2013-03-05T00:00:00+00:00</published>
            <updated>2013-03-05T00:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p><a href="http://www.opscode.com/blog/2013/02/04/chef-11-released/"><strong>Chef 11</strong></a> was released earlier in February and it is awesome! Like most people, I love the new features like partial search, chef-apply and knife-essentials inclusions, awesome formatted output, etc. Of course the open source chef 11 server was <a href="http://www.opscode.com/blog/2013/02/15/the-making-of-erchef-the-chef-11-server/">rewritten completely</a> in erlang with postgresql/mysql support replacing the ruby/couchdb backend stack. solr and rabbitmq are still there ;)… There are many  <a href="http://docs.opscode.com/breaking_changes_chef_11.html">breaking changes</a> meaning you will want to make sure that you fix your cookbooks before upgrading.</p>
<p>When you are ready to upgrade, you will notice that unfortunately there is no official migration path. This howto will document what I&rsquo;ve used myself for such migrations and hopefully will help you too if you are trying to perform a similar upgrade.</p>
<p><strong>Opscode</strong> has done an amazing job with the omnibus installers and starting with Chef 11, the chef server has support for this also. Meaning you can install a new chef server simply by installing the rpm or deb for your platform and everything should be installed for you (ruby/gems, chef, rabbitmq, solr, erlang, postgresql, nginx). Just head over to <a href="http://www.opscode.com/chef/install/">http://www.opscode.com/chef/install/</a> and from the chef-server tab download the version for your OS.</p>
<p>In order to migrate to a new chef server we need to migrate from the old server:</p>
<ul>
<li>clients</li>
<li>nodes</li>
<li>roles</li>
<li>environments</li>
<li>data bags</li>
<li>cookbooks (with all the versions used in each environment)</li>
</ul>
<p>It is important to have all the clients with their proper public keys because if not we would have to re-register each one of them.</p>
<p>Personally, I&rsquo;ve migrated using this process several servers from open source chef 0.10.x to chef 11, but theoretically this should work from any chef server implementation (hosted, private, etc.) because we are downloading and uploading the assets using the api calls.</p>
<h3 id="backup-the-data-from-the-existing-server">Backup the data from the existing server</h3>
<p>You can use my <a href="http://www.ducea.com/2013/03/04/knife-backup/">knife-backup</a> plugin for this. Once you install the gem you can just run it and it will backup all the objects from the existing server:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gem install knife-backup
</span></span><span class="line"><span class="cl">knife backup export
</span></span></code></pre></div><p>This might take a while depending on your number of nodes/clients, cookbooks, etc. you have. Once completed you will have in <code>.chef/chef_server_backup</code> all the needed files.</p>
<p><strong>Optional:</strong> if you have many unused cookbook versions you might want to clean them first before the backup. You can use my <a href="http://www.ducea.com/2013/02/26/knife-cleanup/">knife-cleanup</a> plugin for this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gem install knife-cleanup
</span></span><span class="line"><span class="cl">knife cleanup versions -D
</span></span></code></pre></div><h3 id="install-the-new-chef-11-server">Install the new Chef 11 server</h3>
<p>I would recommend to setup a new server as this would be the safest approach in case something doesn&rsquo;t work out well and you don&rsquo;t have to mess with your current environment. As mentioned earlier you can install the new server very easy with the <a href="http://www.opscode.com/chef/install/">omnibus installer</a>. For example for Ubuntu 12.04 this would look like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">wget https://opscode-omnitruck-release.s3.amazonaws.com/ubuntu/12.04/x86_64/chef-server_11.0.6-1.ubuntu.12.04_amd64.deb
</span></span><span class="line"><span class="cl">dpkg -i chef-server*
</span></span><span class="line"><span class="cl">sudo chef-server-ctl reconfigure
</span></span></code></pre></div><p>You can also use the <a href="https://github.com/opscode-cookbooks/chef-server">chef-server cookbook</a> to install your new server if you prefer that.</p>
<p>Once you have the new chef server up and running, you will need to setup a new admin account and a new knife config. I would recommend to use a special user for this to not interfere with the users that we are trying to import from the old server. I would call it <code>transfer</code>. From the local server this would look like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">mkdir -p ~/.chef
</span></span><span class="line"><span class="cl">sudo cp /etc/chef-server/chef-webui.pem ~/.chef/
</span></span><span class="line"><span class="cl">sudo cp /etc/chef-server/chef-validator.pem ~/.chef/
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">marius@chef:~# knife configure -i
</span></span><span class="line"><span class="cl">WARNING: No knife configuration file found
</span></span><span class="line"><span class="cl">Where should I put the config file? [/marius/.chef/knife.rb]
</span></span><span class="line"><span class="cl">Please enter the chef server URL: [http://localhost:4000] https://localhost
</span></span><span class="line"><span class="cl">Please enter a clientname for the new client: [transfer]
</span></span><span class="line"><span class="cl">Please enter the existing admin clientname: [chef-webui]
</span></span><span class="line"><span class="cl">Please enter the location of the existing admin client&#39;s private key: [/etc/chef/webui.pem] ~/.chef/chef-webui.pem
</span></span><span class="line"><span class="cl">Please enter the validation clientname: [chef-validator]
</span></span><span class="line"><span class="cl">Please enter the location of the validation key: [/etc/chef/validation.pem] ~/.chef/chef-validator.pem
</span></span><span class="line"><span class="cl">Please enter the path to a chef repository (or leave blank):
</span></span><span class="line"><span class="cl">Creating initial API user…
</span></span><span class="line"><span class="cl">Created client[transfer]
</span></span><span class="line"><span class="cl">Configuration file written to /marius/.chef/knife.rb
</span></span></code></pre></div><p>Note: the default server keys will be located in <code>/etc/chef-server/</code> and not in <code>/etc/chef</code> like they used to be, and this is definitely a welcome change. Also the default server url will still look for http and port 4000, but with chef 11 this works behind a nginx load balancer and listens by default on standard https port.</p>
<h3 id="restore-the-data-from-the-old-server">Restore the data from the old server</h3>
<p>Finally, now we can restore all the data from the old server. You can transfer it from the backup and for simplicity drop it in your user <code>.chef</code> folder under <code>.chef/chef_server_backup</code>; be sure to install the <strong>knife-backup</strong> gem to the server and you should be able to run:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">marius@chef:~# knife backup restore
</span></span><span class="line"><span class="cl">WARNING: This will overwrite existing data!
</span></span><span class="line"><span class="cl">WARNING: Backup is at least 1 day old
</span></span><span class="line"><span class="cl">Do you want to restore backup, possibly overwriting exisitng data? (Y/N) y
</span></span><span class="line"><span class="cl">Restoring clients
</span></span><span class="line"><span class="cl">...
</span></span></code></pre></div><p>And this should restore all the data in the new server. Final step would be to regenerate the indexes:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">chef-server-ctl reindex
</span></span></code></pre></div><p>Note: I want to point out that currently knife-backup will skip any clients that already exist on the server as I could not find a way to overwrite them using the api calls. This means that most certainly the validation key will need to be changed as that is a user that for sure will exist on the newly installed server.</p>
<h3 id="final-touches">Final touches</h3>
<p>After the data migration is completed you will probably just have to point your DNS alias to the new server. One issue I&rsquo;ve noticed is that the chef server when installed will use the local dns record in various places in its config files. When working on a temporary server this has caused problems once changing the dns and activating the server. The chef server will send to the client links from where to download the assets (cookbook parts for ex) and if this was unconfigured at install time then you might have to fix it and correct it to the dns entry the clients can download correctly; check it out:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">grep s3_url /var/opt/chef-server/erchef/etc/app.config
</span></span></code></pre></div><p>and restart the chef server after correcting the s3_url:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">chef-server-ctl restart
</span></span></code></pre></div><p>Hopefully this post will help you migrate to <strong>Chef 11</strong>. Feel free to let me know in the comments bellow if you had any issues following this process, or if it worked without any problems. Also if you find any problems with the tools used here <a href="https://github.com/mdxp/knife-cleanup">knife-cleanup</a> or <a href="https://github.com/mdxp/knife-backup">knife-backup</a> please open a ticket on github or submit a patch. Good luck!</p>]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/categories/chef" term="chef" label="Chef" />
                            
                        
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/tags/chef" term="chef" label="chef" />
                             
                                <category scheme="https://www.ducea.com/tags/chef11" term="chef11" label="chef11" />
                             
                                <category scheme="https://www.ducea.com/tags/opschef" term="opschef" label="opschef" />
                             
                                <category scheme="https://www.ducea.com/tags/knife" term="knife" label="knife" />
                             
                                <category scheme="https://www.ducea.com/tags/devops" term="devops" label="devops" />
                             
                                <category scheme="https://www.ducea.com/tags/github" term="github" label="github" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[knife-backup]]></title>
            <link href="https://www.ducea.com/2013/03/04/knife-backup/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://www.ducea.com/2013/02/26/knife-cleanup/?utm_source=atom_feed" rel="related" type="text/html" title="knife-cleanup" />
                <link href="https://www.ducea.com/2013/02/04/bay-area-chef-user-group-update-after-one-year/?utm_source=atom_feed" rel="related" type="text/html" title="Bay Area Chef User Group Update - After One Year" />
                <link href="https://www.ducea.com/2012/05/18/chefconf-2012-san-francisco/?utm_source=atom_feed" rel="related" type="text/html" title="ChefConf 2012 - San Francisco" />
                <link href="https://www.ducea.com/2011/08/23/first-chef-cookbook-contest-announced/?utm_source=atom_feed" rel="related" type="text/html" title="First Chef Cookbook Contest Announced!" />
                <link href="https://www.ducea.com/2011/07/01/howto-upgrade-chef-from-0-10-to-0-10-2-rubygems-install/?utm_source=atom_feed" rel="related" type="text/html" title="HowTo upgrade Chef from 0.10 to 0.10.2 - rubygems install" />
            
                <id>https://www.ducea.com/2013/03/04/knife-backup/</id>
            
            
            <published>2013-03-04T00:00:00+00:00</published>
            <updated>2013-03-04T00:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>While working on migrating a chef server from 0.10.x to version 11, I ended up extending the <a href="https://github.com/stevendanna/knife-hacks/blob/master/plugins/backup_export.rb">BackupExport</a> and <a href="https://github.com/stevendanna/knife-hacks/blob/master/plugins/backup_restore.rb">BackupRestore</a> plugins written by <a href="https://github.com/stevendanna">Steven Danna</a> and <a href="https://github.com/jtimberman">Joshua Timberman</a> and added support for <strong>cookbooks</strong> and <strong>clients</strong>. Currently <a href="https://github.com/mdxp/knife-backup">knife-backup</a> has support for the following objects:</p>
<ul>
<li>clients</li>
<li>nodes</li>
<li>roles</li>
<li>environments</li>
<li>data bags</li>
<li>cookbooks and all their versions.</li>
</ul>
<p><strong>knife-backup</strong> will backup all cookbook versions available on the chef server. Cookbooks are normally available in a repository and should be easy to upload like that, but if you are using various cookbook versions in each environment then it might not be so trivial to find and upload them back to the server; downloading them and having them available to upload like that is simple and clean. If you have too many cookbook versions then you might want to cleanup them first using something like <a href="https://github.com/mdxp/knife-cleanup">knife-cleanup</a>.</p>
<p>If you want to check it out, just install the gem:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gem install knife-backup
</span></span></code></pre></div><p>and then just point it to an existing chef server to backup all its objects with:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">knife backup export
</span></span></code></pre></div><p>If you need to restore then it is simple as:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">knife backup restore [-d DIR]
</span></span></code></pre></div><p>Hope you will find this useful and looking forward for your feedback.<br>
Patches are welcome: <a href="https://github.com/mdxp/knife-backup">knife-backup on github</a></p>]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/categories/chef" term="chef" label="Chef" />
                            
                        
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/tags/chef" term="chef" label="chef" />
                             
                                <category scheme="https://www.ducea.com/tags/opschef" term="opschef" label="opschef" />
                             
                                <category scheme="https://www.ducea.com/tags/knife" term="knife" label="knife" />
                             
                                <category scheme="https://www.ducea.com/tags/devops" term="devops" label="devops" />
                             
                                <category scheme="https://www.ducea.com/tags/github" term="github" label="github" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[knife-cleanup]]></title>
            <link href="https://www.ducea.com/2013/02/26/knife-cleanup/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://www.ducea.com/2013/02/04/bay-area-chef-user-group-update-after-one-year/?utm_source=atom_feed" rel="related" type="text/html" title="Bay Area Chef User Group Update - After One Year" />
                <link href="https://www.ducea.com/2012/05/18/chefconf-2012-san-francisco/?utm_source=atom_feed" rel="related" type="text/html" title="ChefConf 2012 - San Francisco" />
                <link href="https://www.ducea.com/2011/08/23/first-chef-cookbook-contest-announced/?utm_source=atom_feed" rel="related" type="text/html" title="First Chef Cookbook Contest Announced!" />
                <link href="https://www.ducea.com/2011/07/01/howto-upgrade-chef-from-0-10-to-0-10-2-rubygems-install/?utm_source=atom_feed" rel="related" type="text/html" title="HowTo upgrade Chef from 0.10 to 0.10.2 - rubygems install" />
                <link href="https://www.ducea.com/2010/09/27/chef-intro-sf-bay-area-lspe-meetup/?utm_source=atom_feed" rel="related" type="text/html" title="Chef Intro @ SF Bay Area LSPE meetup" />
            
                <id>https://www.ducea.com/2013/02/26/knife-cleanup/</id>
            
            
            <published>2013-02-26T00:00:00+00:00</published>
            <updated>2013-02-26T00:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>I&rsquo;m working on many projects where we have a process that will make sure that every change we introduce in the cookbooks enters as a <strong>new version</strong> and where we use extensively <em>environments</em> to select what versions of cookbooks we want to use in each environment. This sounds like a great idea, and a workflow that I would highly recommend to anyone for sure. Still, after a while, the result is that you will end up with hundreds maybe even thousands of cookbook versions and most of them are <strong>unused</strong> (besides the few ones that you are referencing in each environment and maybe the latest ones). Normally I would not care about this and as long as it is not causing performance issues you should not care about it either. Still you must admit that when debugging any problems, it will make it more complex with all those versions everywhere; see bellow an example.</p>
<p><code>hadoop       0.1.118 0.1.116 0.1.115 0.1.114 0.1.113 0.1.111 0.1.109 0.1.108 0.1.106 0.1.105 0.1.104 0.1.103 0.1.102 0.1.101 0.1.99 0.1.98 0.1.97 0.1.96 0.1.95 0.1.94 0.1.93 0.1.92 0.1.91 0.1.90 0.1.89 0.1.88 0.1.87 0.1.86 0.1.85 0.1.84 0.1.83 0.1.82 0.1.81 0.1.80 0.1.79 0.1.78 0.1.77 0.1.76 0.1.75 0.1.74 0.1.73 0.1.72 0.1.71 0.1.70 0.1.69 0.1.68 0.1.67 0.1.66 0.1.65 0.1.64 0.1.63 0.1.62 0.1.61 0.1.60 0.1.59 0.1.58 0.1.57 0.1.56 0.1.55 0.1.54 0.1.53 0.1.52 0.1.51 0.1.50 0.1.49 0.1.48 0.1.47 0.1.46 0.1.45 0.1.44 0.1.43 0.1.42 0.1.41 0.1.40 0.1.39 0.1.38 0.1.37 0.1.36 0.1.35 0.1.34 0.1.33 0.1.32 0.1.31 0.1.30 0.1.29 0.1.28 0.1.25 0.1.24 0.1.23 0.1.22 0.1.21 0.1.20 0.1.19 0.1.18 0.1.17 0.1.16 0.1.15 0.1.13 0.1.12 0.1.11 0.1.10 0.1.9 0.1.8 0.1.7 0.1.6 0.1.5 0.1.4 0.1.3 0.1.2 0.1.0</code></p>
<p>(and this was the cookbook with the least versions that I&rsquo;ve found to paste here).</p>
<p>While working on <a href="https://github.com/mdxp/knife-backup">knife-backup</a> I realized what a huge waste this was, and decided that I needed a way to clean these and keep on the server just the relevant ones.</p>
<p>To solve this problem I wrote <a href="https://github.com/mdxp/knife-cleanup">knife-cleanup</a> and if you have similar needs you might find it useful. It will cleanup all unused versions of the cookbooks you have on your chef server (this might be hosted opscode platform or open source server). Before doing any deletion it will backup the version it touches (just in case).</p>
<p>If you want to check it out, just install the gem:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gem install knife-cleanup
</span></span></code></pre></div><p>and assuming you have a working knife config you can run it with:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">knife cleanup versions
</span></span></code></pre></div><p>and this will output the versions it would delete.</p>
<p>If you are ready to delete, you can do that with:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">knife cleanup versions -D
</span></span></code></pre></div><p>and you can find the backups of the versions deleted under <code>.cleanup/cookbook_name</code></p>
<p><em>Notes</em>: I&rsquo;ve seen various cases where it is impossible to download a cookbook version (and knife will error out). From my experience there is not much we can do about that, so the script will just ignore the backup, but will delete the corrupt version. You might want to have a full chef server backup before (see <a href="https://github.com/mdxp/knife-backup">knife-backup</a>) just in case.
The way how I&rsquo;m using this is with exact version pining of cookbooks in environments (for more details see <a href="https://github.com/mdxp/chef-jenkins">chef-jenkins</a>); if you are using environments and cookbook versions in a different way, then this might not make sense for you.</p>
<p>Hope you will find this useful and looking forward for your feedback.<br>
Patches are welcome: <a href="https://github.com/mdxp/knife-cleanup">knife-cleanup on github</a></p>]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/categories/chef" term="chef" label="Chef" />
                            
                        
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/tags/chef" term="chef" label="chef" />
                             
                                <category scheme="https://www.ducea.com/tags/opschef" term="opschef" label="opschef" />
                             
                                <category scheme="https://www.ducea.com/tags/knife" term="knife" label="knife" />
                             
                                <category scheme="https://www.ducea.com/tags/devops" term="devops" label="devops" />
                             
                                <category scheme="https://www.ducea.com/tags/github" term="github" label="github" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Bay Area Chef User Group Update - After One Year]]></title>
            <link href="https://www.ducea.com/2013/02/04/bay-area-chef-user-group-update-after-one-year/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://www.ducea.com/2012/05/18/chefconf-2012-san-francisco/?utm_source=atom_feed" rel="related" type="text/html" title="ChefConf 2012 - San Francisco" />
                <link href="https://www.ducea.com/2010/09/27/chef-intro-sf-bay-area-lspe-meetup/?utm_source=atom_feed" rel="related" type="text/html" title="Chef Intro @ SF Bay Area LSPE meetup" />
                <link href="https://www.ducea.com/2011/08/23/first-chef-cookbook-contest-announced/?utm_source=atom_feed" rel="related" type="text/html" title="First Chef Cookbook Contest Announced!" />
                <link href="https://www.ducea.com/2011/07/01/howto-upgrade-chef-from-0-10-to-0-10-2-rubygems-install/?utm_source=atom_feed" rel="related" type="text/html" title="HowTo upgrade Chef from 0.10 to 0.10.2 - rubygems install" />
                <link href="https://www.ducea.com/2010/09/01/nodejs-chef-cookbook-released/?utm_source=atom_feed" rel="related" type="text/html" title="NodeJS chef cookbook released" />
            
                <id>https://www.ducea.com/2013/02/04/bay-area-chef-user-group-update-after-one-year/</id>
            
            
            <published>2013-02-04T00:00:00+00:00</published>
            <updated>2013-02-04T00:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>It&rsquo;s been a little more than a year since I stepped up and became one of the organizers of the <a href="http://www.meetup.com/The-Bay-Area-Chef-User-Group/">Bay Area Chef user group</a>, trying to help my good friend <em><strong>Rob Berger</strong></em> as he was getting swamped with work and could not dedicate as much time to this, as he used to in the past. This post is meant to be a quick review on what happened during this time, what worked well and of course some ideas on how we can improve this in the future. I&rsquo;m also hoping to get <strong>feedback</strong> from our members on what we can do differently in the future to better serve them and make this an even better group.</p>
<p>One of the first things we&rsquo;ve done last year was to introduce the <strong>Chef Cafes</strong>. These are small events (we have a max limit of 10 people set for them) done consistently at the same time (1st and 3rd Thursday of the month) at the best coffee in Mountain View (<a href="http://www.redrockcoffee.org/">Red Rock Coffee</a>) with the intent to facilitate the interaction between people, give them a place where they can regularly meet and discuss about chef, ask questions and also try to help other members in the spirit of the open source community. The first Chef Cafe was on <em>March 1st 2012</em> and it was just me and Rob (we had a good time preparing the future events and just catching up). But after that, we had 16 Chef Cafe&rsquo;s all year long and many of them had 10 or even more people, and each one of them was unique and special in its own way. We had some, where we had new chef users that had various questions on how to use chef and we tried to help them and resolve their blocks in understanding and getting up to speed with chef. On the other hand we had other cafes where we had really advanced uses that brainstormed about various unresolved problems and what was their take on things like cookbook testing, workflow or orchestration. Overall, I think it was a great success and allowed us to be more connected with members, and also more open and helpful to new chef users.</p>
<p>In <strong>2013</strong> we look forward to your suggestions on how we can improve the Chef Cafes and we will try to keep these going. We hope to be able to move one in San Francisco and keep the other one in the South Bay as we had various requests for that. <em>So if you are in the City and you want to get involved with this please ping me.</em></p>
<p>One other thing we have tried to do was to bring consistency and have at least one meetup every month with an awesome presentation on some hot topic in the chef community. This ended up being a little too optimistic :(. Still, we had 6 cool meetups with speakers like:</p>
<ul>
<li><strong>Flip Kromer</strong> on Ironfan</li>
<li><strong>Jim Hopp</strong> on Test-Driven Development</li>
<li><strong>Jesse Robbins</strong> - Hacking culture &amp; Being a force for Awesome</li>
<li><strong>Daniel DeLeo</strong> on Whyrun mode</li>
<li><strong>Nati Shalom</strong> on Cloudify</li>
</ul>
<p>and we also had <strong>Aaron Peterson</strong> running an introductory <em>Chef Workshop</em>; considering the big and diverse audience I think we have done quite a great job with that.</p>
<p>With the experiences we had last year, we are more confident that this year we will be able to run one meetup every month, but we need your help: <em>we are always looking for great speakers and interesting topics; if you want to present at one of our meetups please let us know; also if you know someone that we should invite to present to a meetup please let us know.</em></p>
<p>Most of our meetups last year were hosted by <strong>Survey Monkey</strong> in Palo Alto and we can&rsquo;t thank them enough for their support (special thanks to <em>Tim Sabat</em> for making them possible). We also had one meetup in San Francisco hosted at Scalr offices (thanks Sebastian). This year, we hope to diversify and run each meetup in a different place to make things more interesting; and hopefully more meetups in the City. <em>If you are interested in hosting and sponsoring one of our future meetups please contact me privately and let me know.</em></p>
<p>During last year, our group has grown a lot. We started with <strong>132 members</strong> in the first day of January 2012 and ended up the year with more than <strong>400 members</strong>. This shows that the interest in Chef is obviously growing and hopefully the events we have been organizing are helping grow our local chef community.</p>
<p>If you have <em><strong>any</strong></em> suggestions on what you would like us to do in the future, please let us know. Use the comments bellow, send us a message, whatever works for you; we would love to hear from you and see how we can serve you better. Overall 2012 was great and with your help we can make 2013 even better!</p>]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/categories/meetups" term="meetups" label="Meetups" />
                            
                        
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/tags/meetups" term="meetups" label="meetups" />
                             
                                <category scheme="https://www.ducea.com/tags/chef" term="chef" label="chef" />
                             
                                <category scheme="https://www.ducea.com/tags/opschef" term="opschef" label="opschef" />
                             
                                <category scheme="https://www.ducea.com/tags/devops" term="devops" label="devops" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Finally Migrated to Octopress]]></title>
            <link href="https://www.ducea.com/2012/11/14/finally-migrated-to-octopress/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://www.ducea.com/2012/11/12/disqus-comments-not-visible-in-octopress/?utm_source=atom_feed" rel="related" type="text/html" title="Disqus comments not visible in Octopress" />
                <link href="https://www.ducea.com/2010/05/03/reloaded/?utm_source=atom_feed" rel="related" type="text/html" title="Reloaded" />
                <link href="https://www.ducea.com/2009/04/14/thoughts-on-twitter-and-blogging/?utm_source=atom_feed" rel="related" type="text/html" title="Thoughts on twitter and blogging" />
                <link href="https://www.ducea.com/2009/01/15/blogging-in-2008/?utm_source=atom_feed" rel="related" type="text/html" title="Blogging in 2008" />
                <link href="https://www.ducea.com/2008/12/24/merry-christmas-happy-new-year/?utm_source=atom_feed" rel="related" type="text/html" title="Merry Christmas &amp; Happy New Year!" />
            
                <id>https://www.ducea.com/2012/11/14/finally-migrated-to-octopress/</id>
            
            
            <published>2012-11-14T00:00:00+00:00</published>
            <updated>2012-11-14T00:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>For a while now, I wanted to migrate my blog from Wordpress to <a href="http://octopress.org/">Octopress</a>, but for some reason I kept putting it on the shelf and not doing it. (let&rsquo;s say because of all those client related projects&hellip;). Finally last weekend I&rsquo;ve completed the migration and I&rsquo;m really excited to get back to blogging after this. This post is meant to capture some of the issues I&rsquo;ve encountered during the migration and how to fix them. This is not a full how to migrate post, as there are many such great articles <a href="https://www.google.com/#hl=en&amp;tbo=d&amp;sclient=psy-ab&amp;q=migrate+wordpress+to+octopress">available already</a>.</p>
<h2 id="migrate-old-blog-posts">Migrate old blog posts.</h2>
<p>Believe it or not, I had <strong>364 blog posts</strong> when I started the migration. Meaning a lot of energy was spent in importing those old articles. I&rsquo;ve used <a href="https://github.com/thomasf/exitwp">exitwp</a> to convert the wordpress-xml export of the blog posts; and this produced a reasonably good result. Still I had to run some fixes&hellip;</p>
<ul>
<li>
<p>for code blocks:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"> perl -pi -e <span class="s1">&#39;s/([^\`]|^)(\`)([^\`]|$)/$1\n\`\`\`\n$3/g&#39;</span> *
</span></span></code></pre></div></li>
<li>
<p>to enable comments (as &lsquo;comments: true&rsquo; was missing from all posts)</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">find source/_posts/ -type f -print0 <span class="p">|</span> xargs -0 -I file sed -i <span class="s1">&#39;&#39;</span> <span class="s1">&#39;2 i \
</span></span></span><span class="line"><span class="cl"><span class="s1">  comments: true&#39;</span> file
</span></span></code></pre></div></li>
</ul>
<h2 id="categoriestagsurls">Categories/Tags/URLs</h2>
<p>Enabled the octopress category list plugin and tags plugin, that you can see in the sidebar. Since I had already tags and categories on all posts it was very important to keep the same urls and not break them. Same thing for regular posts urls. Here are the relevant settings form the octopress config file:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="nt">root</span><span class="p">:</span><span class="w"> </span><span class="l">/</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">permalink</span><span class="p">:</span><span class="w"> </span><span class="l">/:year/:month/:day/:title/</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">category_dir</span><span class="p">:</span><span class="w"> </span><span class="l">category</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">tag_dir</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;tag&#34;</span><span class="w">
</span></span></span></code></pre></div><p>Just keep in mind that if you have many tags as I do, the generation of the pages will increase a lot after you enable the tags plugin. You&rsquo;ve been warned!</p>
<h2 id="disqus-comments">Disqus comments</h2>
<p>Not working at all&hellip; I&rsquo;ve wrote a post specifically about this; check it out <a href="http://www.ducea.com/2012/11/12/disqus-comments-not-visible-in-octopress/">here</a></p>
<h2 id="feed-url">Feed Url</h2>
<p>My wordpress blog has been around for a while (6years more or less) and even if I&rsquo;ve always used <strong>feedburner</strong> for my feed, but for some strange reason I&rsquo;ve always used my own <a href="http://www.ducea.com/feed/">feed url</a>. This of course was no longer working with octopress, hence I had to setup a rewrite rule to not break everyone&rsquo;s feed reader:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-apacheconf" data-lang="apacheconf"><span class="line"><span class="cl"><span class="nb">RewriteEngine</span> <span class="k">On</span>
</span></span><span class="line"><span class="cl"><span class="nb">Options</span> +FollowSymLinks -Multiviews
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># Feed url</span>
</span></span><span class="line"><span class="cl"><span class="nb">RewriteRule</span> ^feed/?$ atom.xml [QSA,L]
</span></span></code></pre></div><h2 id="rewrite-non-www-to-www">Rewrite non-www to www</h2>
<p>This was done automatically by wordpress, but octopress will serve just fine the non-www domain. This can cause issues with search engines and such, so I wanted the same behaviour. Apache again to the rescue:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-apacheconf" data-lang="apacheconf"><span class="line"><span class="cl"><span class="nb">RewriteCond</span> %{HTTP_HOST} !^www [NC]
</span></span><span class="line"><span class="cl"><span class="nb">RewriteRule</span> $ http://www.%{HTTP_HOST}%{REQUEST_URI} [L,R]
</span></span></code></pre></div><h2 id="apache-optimizations-caching-compression-etc">Apache optimizations, caching, compression, etc</h2>
<p>After you generated your octopress site, everything is static and fast by default. Still, you want to make sure that apache has some basic caching and compression settings to make it even better. Here are the relevant parts from my config:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-apacheconf" data-lang="apacheconf"><span class="line"><span class="cl"><span class="c">#### CACHING ####</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;IfModule</span> <span class="s">mod_expires.c</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nb">ExpiresActive</span> <span class="k">On</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 1 MONTH</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;FilesMatch</span> <span class="s">&#34;\.(ico|gif|jpe?g|png|flv|pdf|swf|mov|mp3|wmv|ppt)$&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="nb">ExpiresDefault</span> A2419200
</span></span><span class="line"><span class="cl">  <span class="nb">Header</span> append Cache-Control <span class="s2">&#34;public&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/FilesMatch&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 3 DAYS</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;FilesMatch</span> <span class="s">&#34;\.(xml|txt|html|htm|js|css)$&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="nb">ExpiresDefault</span> A259200
</span></span><span class="line"><span class="cl">  <span class="nb">Header</span> append Cache-Control <span class="s2">&#34;private, must-revalidate&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/FilesMatch&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># NEVER CACHE</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;FilesMatch</span> <span class="s">&#34;\.(php|cgi|pl)$&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="nb">ExpiresDefault</span> A0
</span></span><span class="line"><span class="cl">  <span class="nb">Header</span> set Cache-Control <span class="s2">&#34;no-store, no-cache, must-revalidate, max-age=0&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="nb">Header</span> set Pragma <span class="s2">&#34;no-cache&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/FilesMatch&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/IfModule&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c">### Compression ####</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;IfModule</span> <span class="s">mod_deflate.c</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;IfModule</span> <span class="s">mod_setenvif.c</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nb">BrowserMatch</span> ^Mozilla/4 gzip-only-text/html
</span></span><span class="line"><span class="cl">        <span class="nb">BrowserMatch</span> ^Mozilla/4\.0[678] no-gzip
</span></span><span class="line"><span class="cl">        <span class="nb">BrowserMatch</span> \bMSIE !no-gzip !gzip-only-text/html
</span></span><span class="line"><span class="cl">        <span class="nb">BrowserMatch</span> \bMSI[E] !no-gzip !gzip-only-text/html
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;/IfModule&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;IfModule</span> <span class="s">mod_headers.c</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nb">Header</span> append Vary <span class="k">User</span>-Agent env=!dont-vary
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;/IfModule&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;IfModule</span> <span class="s">mod_filter.c</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nb">AddOutputFilterByType</span> DEFLATE text/css application/x-javascript text/x-component text/html text/richtext image/svg+xml text/plain text/xsd text/xsl text/xml image/x-icon
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;/IfModule&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/IfModule&gt;</span>
</span></span></code></pre></div><h2 id="isolated-when-working-on-a-new-post">Isolated when working on a new post</h2>
<p>If you have many posts, the generation of the octopress site will be extremely slow (in my case it takes about 2mins for a full generate) and this makes it basically impossible to work with any new post and see the feedback locally with preview. The solution is well documented and it works by isolating your single post while working on it, and when you are done you integrate back all the other posts before publishing them:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">rake new_post<span class="o">[</span><span class="s1">&#39;Finally Migrated to Octopress&#39;</span><span class="o">]</span>
</span></span><span class="line"><span class="cl">rake isolate<span class="o">[</span>finally-migrated-to-octopress<span class="o">]</span>
</span></span></code></pre></div><p>and now <code>rake generate</code> and <code>rake preview</code> will only work with the new post. Finally when done and ready to publish the awesome new post on the internets:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">rake integrate
</span></span><span class="line"><span class="cl">rake generate
</span></span><span class="line"><span class="cl">rake deploy
</span></span></code></pre></div><h3 id="others">Others</h3>
<ul>
<li>some small customizations to the theme (colors and such)</li>
<li>about me and contact custom asides.</li>
<li>fix the github aside (updated to work with their latest api version and actually return the repos)</li>
<li>and of course the contact form (using a wufoo form)</li>
</ul>]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/categories/general" term="general" label="General" />
                            
                        
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/tags/site" term="site" label="site" />
                             
                                <category scheme="https://www.ducea.com/tags/octopress" term="octopress" label="octopress" />
                             
                                <category scheme="https://www.ducea.com/tags/disqus" term="disqus" label="disqus" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Disqus comments not visible in Octopress]]></title>
            <link href="https://www.ducea.com/2012/11/12/disqus-comments-not-visible-in-octopress/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://www.ducea.com/2010/05/03/reloaded/?utm_source=atom_feed" rel="related" type="text/html" title="Reloaded" />
                <link href="https://www.ducea.com/2009/04/14/thoughts-on-twitter-and-blogging/?utm_source=atom_feed" rel="related" type="text/html" title="Thoughts on twitter and blogging" />
                <link href="https://www.ducea.com/2009/01/15/blogging-in-2008/?utm_source=atom_feed" rel="related" type="text/html" title="Blogging in 2008" />
                <link href="https://www.ducea.com/2008/12/24/merry-christmas-happy-new-year/?utm_source=atom_feed" rel="related" type="text/html" title="Merry Christmas &amp; Happy New Year!" />
                <link href="https://www.ducea.com/2008/10/27/enabling-gravatars/?utm_source=atom_feed" rel="related" type="text/html" title="Enabling Gravatars" />
            
                <id>https://www.ducea.com/2012/11/12/disqus-comments-not-visible-in-octopress/</id>
            
            
            <published>2012-11-12T00:00:00+00:00</published>
            <updated>2012-11-12T00:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>After completing the migration of my blog from Wordpress to Octopress I had the surprise that Disqus comments were <em><strong>not</strong> showing up on the site</em>. I&rsquo;ve already migrated in advance to Disqus and the Wordpress blog was working just fine with the new format. However, once switched to Octopress there were <strong>no comments active on the site</strong>. Strangely, the total number of comments for each post on the index page was showing just fine, but once you clicked on any post there were <em>no comments</em>. I tested adding new comment and it did show up correctly in Disqus.</p>
<p>Trying to understand and debug this issue, I looked in <code>source/_includes/disqus.html</code> and found the code that is generating the javascript variable <strong>disqus_identifier</strong> for the posts:</p>
<script type="application/javascript" src="https://gist.github.com/mdxp/4067374.js"></script>

<p>and looking in the html generated by some blog posts the variables disqus_url and disqus_identifier looked ok, like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">var disqus_identifier = &#39;http://www.ducea.com//2012/11/12/disqus-comments-not-visible-in-octopress/&#39;;
</span></span><span class="line"><span class="cl">var disqus_url = &#39;http://www.ducea.com//2012/11/12/disqus-comments-not-visible-in-octopress/&#39;;
</span></span><span class="line"><span class="cl">var disqus_script = &#39;embed.js&#39;;
</span></span></code></pre></div><p>Still at a closer look I was able to identify the issue; if you look closer at the url above, it has a double <strong>/</strong> in the url, and even if that should not cause any issues and identify the same url, Disqus was actually seeing it as a separate identifier and hence not showing the comments associated with it.
Once I figured it out it was very simple to see where it came form (the site <strong>url</strong> from _config.xml) was:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl">url: http://www.ducea.com/
</span></span></code></pre></div><p>and fixing it, by removing the trailing slash:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl">url: http://www.ducea.com
</span></span></code></pre></div><p>Regenerating and deploying the site:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">rake generate
</span></span><span class="line"><span class="cl">rake deploy
</span></span></code></pre></div><p>fixed the issue and the comments are now back on the site. (you can even try it out here on this post ;)</p>
<p>Hopefully this will help others that are in the same situation&hellip; if you just added an extra slash to the Octopress site url config and didn&rsquo;t realize this brake the Disqus comments.</p>]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/categories/general" term="general" label="General" />
                            
                        
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/tags/site" term="site" label="site" />
                             
                                <category scheme="https://www.ducea.com/tags/octopress" term="octopress" label="octopress" />
                             
                                <category scheme="https://www.ducea.com/tags/disqus" term="disqus" label="disqus" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[ChefConf 2012 - San Francisco]]></title>
            <link href="https://www.ducea.com/2012/05/18/chefconf-2012-san-francisco/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://www.ducea.com/2011/08/23/first-chef-cookbook-contest-announced/?utm_source=atom_feed" rel="related" type="text/html" title="First Chef Cookbook Contest Announced!" />
                <link href="https://www.ducea.com/2011/07/01/howto-upgrade-chef-from-0-10-to-0-10-2-rubygems-install/?utm_source=atom_feed" rel="related" type="text/html" title="HowTo upgrade Chef from 0.10 to 0.10.2 - rubygems install" />
                <link href="https://www.ducea.com/2010/09/27/chef-intro-sf-bay-area-lspe-meetup/?utm_source=atom_feed" rel="related" type="text/html" title="Chef Intro @ SF Bay Area LSPE meetup" />
                <link href="https://www.ducea.com/2010/09/01/nodejs-chef-cookbook-released/?utm_source=atom_feed" rel="related" type="text/html" title="NodeJS chef cookbook released" />
                <link href="https://www.ducea.com/2011/12/03/getting-ready-for-lisa11-boston/?utm_source=atom_feed" rel="related" type="text/html" title="Getting ready for LISA11 - Boston" />
            
                <id>https://www.ducea.com/2012/05/18/chefconf-2012-san-francisco/</id>
            
            
            <published>2012-05-18T19:09:10+00:00</published>
            <updated>2012-05-18T19:09:10+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>This week <strong>Opscode</strong> hosted its inaugural user conference here in San Francisco, and it was an awesome event enjoyed by all chef fans. Even if this was the first one (they are already planing for the future ones), this was by no means a small event, with more than <strong>400 people</strong> attending and the workshops that ran on Tuesday <em>sold out</em>.</p>
<p>Even if I have not attended any workshop (they had 2 flavors, one targeted towards a <em>sysadmin workflow</em> and one for <em>developers</em>) the general feeling from people I talked with and attended them was that it was a very good experience, with a lot of hands-on practical examples. Tuesday afternoon, myself I attended the &ldquo;<a href="http://chefconf2012.sched.org/event/bfe13edac99e2b4d8582f0cd1005ee73?iframe=no&amp;w=700&amp;sidebar=no&amp;bg=no">ChefConf Pre-event Hackday: TEST ALL THE THINGS!!!</a>&rdquo; organized by <strong>Bryan Berry</strong> and it was great, and showed how many people are interested in testing their infrastructure as code; it was focused on cookbook testing (unit testing and integration testing), continuous integration with jenkins, and other things like that ;)</p>
<p>The first full day of <a href="http://chefconf.opscode.com/">ChefConf</a> was Wednesday. The conference was structured with main presentations during the mornings and breakout sessions in the afternoon (with 2 main tracks and also a vendor one). From the beginning you could tell that this will be a very well run conference, and even if this was the first one, people like Jesse Robbins have a lot of experience running such events. Not surprisingly <strong>ChefConf</strong> kicked off with <strong>Adam Jacob</strong>&rsquo;s &ldquo;<a href="http://chefconf2012.sched.org/event/5c0fac5d1c23207c0f8516bcf84045b9?iframe=no&amp;w=700&amp;sidebar=no&amp;bg=no">State of the Union Part 1: Chef, Past and Present</a>&rdquo; (<a href="http://www.youtube.com/watch?v=bAWjqE5FCxI&amp;feature=plcp">video</a>) ; <strong>Jesse Robbins</strong> talked about the <strong>community</strong> around chef and how this is a key part of Opscode strategy and their efforts to take this to the next level. He showed this very nice <a href="http://www.youtube.com/watch?v=ZIlWCE4FCqw&amp;feature=plcp">visualization</a> of the commits to the chef github repo.</p>
<p>There were many interesting talks during the day, and they recorded most of them and hopefully will make them available <a href="http://www.youtube.com/user/Opscode/videos">online</a> soon so you can see them if you didn&rsquo;t had the chance to be here (or you want to review them again). I particularly enjoyed:</p>
<ul>
<li>
<p><strong>Ron Vidal</strong> - <a href="http://chefconf2012.sched.org/event/b5e9e27b171a970572ddd93fb5eb44fe?iframe=no&amp;w=700&amp;sidebar=no&amp;bg=no">Operations Secret Sauce: Incident Management</a> (<a href="http://www.youtube.com/watch?v=4d38Ena1Abo&amp;feature=plcp">video</a>); similar to Jesse Robbins <strong><a href="https://www.usenix.org/conference/lisa11/gameday-creating-resiliency-through-destruction">GameDay</a></strong> talk and it was a very nice addition, inspirational and full of interesting points.</p>
</li>
<li>
<p><strong>Jim Hopp</strong>&rsquo;s - <a href="http://chefconf2012.sched.org/event/b2b1a41277c11c865d55b733b4814c1a?iframe=no&amp;w=700&amp;sidebar=no&amp;bg=no">Test-driven Development for Chef Practitioners</a> (<a href="http://www.youtube.com/watch?v=o2e0aZUAVGw&amp;feature=plcp">video</a>); very well prepared and presented. I hope to have Jim to our <a href="http://www.meetup.com/The-Bay-Area-Chef-User-Group/">Chef Bay Area meetup</a> group to present something similar on the subject and run a testing hackaton.</p>
</li>
<li>
<p><strong>Patrick McDonnell</strong>&rsquo;s - <a href="http://chefconf2012.sched.org/event/2cef7591ae7f08836ff89f4dc223280e?iframe=yes&amp;w=700&amp;sidebar=no&amp;bg=no#?iframe=yes&amp;w=700&amp;sidebar=no&amp;bg=no#sched-body-outer">Lessons from Etsy: Avoiding Kitchen Nightmares</a>; people seem to love everything Etsy is doing and they are sharing a lot of their workflow with chef and open sourcing various tools they write.</p>
</li>
<li>
<p>and many others…</p>
</li>
</ul>
<p>In the evening we had a great <strong>Ignite</strong> event ran by <strong>Andrew Shafer</strong> in his unconfundable way. We had 10 ignite speakers and in the middle there was a fun <em>karaoke ignite</em> that had 10 volunteers rambled on some slides they never sow before. If they recorded this, and will show it online look up the ones by <strong>Stephen Nelson-Smith</strong> and <strong>John Vincent</strong> as they were very entertaining.</p>
<p>The second day of the conference started with <strong>Christopher Brown</strong>&rsquo;s &ldquo;<a href="http://chefconf2012.sched.org/event/d60e4ab3b1f2fba2f996214792a649c1?iframe=no&amp;w=700&amp;sidebar=no&amp;bg=no">State of the Union Part 2: Chef, the Future</a>&rdquo; where he outlined some of the future features and main focuses of Opscode for Chef: becoming easier to install and use (<em>omnibus</em> installer), <em>enterprise</em> ready, focus on <em>Windows</em> and also a lot of focus on <em>quality</em>. Opscode is working on a project called <em>kitchen chef</em> that will allow to test the functionality of cookbooks on various environments and platforms, and quickly ensure the quality of the cookbook is maintained during various iterations. Also a lot of work has been put into <em>reporting</em> and handlers. The server side also has been completely rewritten in <em>erlang</em> and <em>sql</em> (from ruby and couchdb) and we should see this soon in the open-source and the private chef server. From the work done you can easily tell that a lot of work has been done on private chef and this is quickly becoming an important asset for Opscode going forward.</p>
<p>There were many great talks during the day from speakers like Artur Bergman, Ben Rockwood, Jason Stowe, John Esser, Rob Hirschfeld, Theo Schlossnagle, etc. I finished my day just like I started Tuesday with another event focused on testing: &ldquo;<a href="http://chefconf2012.sched.org/event/1b5feddb619c6c09bd28f19d95a9c8be?iframe=no&amp;w=700&amp;sidebar=no&amp;bg=no">Test Driven Development Roundtable</a>&rdquo;, ran by <strong>Stephen Nelson-Smith</strong> on a panel with <strong>Seth Chisamore</strong>, <strong>Jim Hopp</strong> and my friend <strong>Rob Berger</strong>. They went over the tools people are using these days and what are the things that are still missing and need to be worked on regarding testing.</p>
<p>Overall, I think this was an <strong>awesome</strong> event and I hope to be able to attend the next one also (hopefully at the same place). My impression is that Opscode is ready to move forward and make the next step and grow the community even bigger: <strong>&ldquo;The revolution will not be televised - it will be coded with chef&rdquo;.</strong></p>]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/categories/conferences" term="conferences" label="Conferences" />
                             
                                <category scheme="https://www.ducea.com/categories/configuration-management" term="configuration-management" label="Configuration management" />
                            
                        
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/tags/chef" term="chef" label="chef" />
                             
                                <category scheme="https://www.ducea.com/tags/chefconf" term="chefconf" label="chefconf" />
                             
                                <category scheme="https://www.ducea.com/tags/conferences" term="conferences" label="Conferences" />
                             
                                <category scheme="https://www.ducea.com/tags/devops" term="devops" label="devops" />
                             
                                <category scheme="https://www.ducea.com/tags/opschef" term="opschef" label="opschef" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[HowTo completely remove a file from Git history]]></title>
            <link href="https://www.ducea.com/2012/02/07/howto-completely-remove-a-file-from-git-history/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://www.ducea.com/2010/08/17/background-a-running-process/?utm_source=atom_feed" rel="related" type="text/html" title="Background a running process" />
                <link href="https://www.ducea.com/2009/06/05/linux-tips-get-the-list-of-subdirectories-with-their-owner-permissions-and-full-paths/?utm_source=atom_feed" rel="related" type="text/html" title="Linux Tips: get the list of subdirectories with their owner &amp; permissions and full paths" />
                <link href="https://www.ducea.com/2009/03/05/bash-tips-if-e-wildcard-file-check-too-many-arguments/?utm_source=atom_feed" rel="related" type="text/html" title="Bash tips: if -e wildcard file check =&gt; [: too many arguments" />
                <link href="https://www.ducea.com/2009/01/19/running-multiple-instances-of-mysql-on-the-same-machine/?utm_source=atom_feed" rel="related" type="text/html" title="Running multiple instances of MySQL on the same machine" />
                <link href="https://www.ducea.com/2008/11/12/using-the-character-in-crontab-entries/?utm_source=atom_feed" rel="related" type="text/html" title="Using the % character in crontab entries" />
            
                <id>https://www.ducea.com/2012/02/07/howto-completely-remove-a-file-from-git-history/</id>
            
            
            <published>2012-02-07T11:40:06+00:00</published>
            <updated>2012-02-07T11:40:06+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>I just started working on a new project and as you would expect one of the first things I did was to download its git repository from <strong>github</strong>. These were just some scripts and should have been very small ~5M, but the clone from gitbhub took about one hour as the full repo folder was 1.5G… (with the biggest size under <strong>.git/objects/pack</strong>) Crazy… <em>What was in the git repository history that would cause something like this?</em> I assumed that at some point in time the repository was much bigger (probably from some file/s that don&rsquo;t exist anymore), but how could I find out what were those files? And more important howto remove them from history? Well if you came here from a <em>google search</em> on &ldquo;how to remove a file from git history&rdquo; then you probably know there are plenty of docs and howtos on how to achieve this but from my experience none of them really worked. This is why I decided to document the steps needed to identify the file from the git repo history that is using all that space and to have it removed fully and bring the repository to a manageable size.</p>
<p>First we need to identify the file that is causing this issue; and for this we will verify all the packed objects and look for the biggest ones:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5
</span></span></code></pre></div><p>(and grab the revisions with the biggest files). Then find the name of the files in those revisions:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git rev-list --objects --all | grep &lt;revision_id&gt;
</span></span></code></pre></div><p>Next, remove the file from all revisions:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git filter-branch --index-filter &#39;git rm --cached --ignore-unmatch &lt;filename&gt;&#39;
</span></span><span class="line"><span class="cl">rm -rf .git/refs/original/
</span></span></code></pre></div><p>Edit .git/packed-refs and remove/comment any external pack-refs. Without this the cleanup might not work. I my case I had refs/remotes/origin/master and some others branches.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">vim .git/packed-refs
</span></span></code></pre></div><p>Finally repack and cleanup and remove those objects:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">git reflog expire --all --expire-unreachable=0
</span></span><span class="line"><span class="cl">git repack -A -d
</span></span><span class="line"><span class="cl">git prune
</span></span></code></pre></div><p>Hopefully these steps will help you completely remove those un-wanted files from your git history. Let me know if you have any problems after following these simple steps.</p>
<p>Note: if you want to test these steps here is how to quickly create a test repo:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"># Make a small repo
</span></span><span class="line"><span class="cl">mkdir test
</span></span><span class="line"><span class="cl">cd test
</span></span><span class="line"><span class="cl">git init
</span></span><span class="line"><span class="cl">echo hi &gt; there
</span></span><span class="line"><span class="cl">git add there
</span></span><span class="line"><span class="cl">git commit -m &#39;Small repo&#39;
</span></span><span class="line"><span class="cl"># Add a random 10M binary file
</span></span><span class="line"><span class="cl">dd if=/dev/urandom of=testme.txt count=10 bs=1M
</span></span><span class="line"><span class="cl">git add testme.txt
</span></span><span class="line"><span class="cl">git commit -m &#39;Add big binary file&#39;
</span></span><span class="line"><span class="cl"># Remove the 10M binary file
</span></span><span class="line"><span class="cl">git rm testme.txt
</span></span><span class="line"><span class="cl">git commit -m &#39;Remove big binary file&#39;
</span></span></code></pre></div>]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/categories/linux" term="linux" label="Linux" />
                             
                                <category scheme="https://www.ducea.com/categories/tips-tricks" term="tips-tricks" label="Tips &amp; Tricks" />
                            
                        
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/tags/git" term="git" label="git" />
                             
                                <category scheme="https://www.ducea.com/tags/howto" term="howto" label="howto" />
                             
                                <category scheme="https://www.ducea.com/tags/tips" term="tips" label="tips" />
                             
                                <category scheme="https://www.ducea.com/tags/tips-tricks" term="tips-tricks" label="Tips &amp; Tricks" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Getting ready for LISA11 - Boston]]></title>
            <link href="https://www.ducea.com/2011/12/03/getting-ready-for-lisa11-boston/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://www.ducea.com/2011/11/30/interview-with-lisa11-program-co-chairs-tom-limoncelli-and-doug-hughes/?utm_source=atom_feed" rel="related" type="text/html" title="Interview with LISA11 Program Co-Chairs: Tom Limoncelli and Doug Hughes" />
                <link href="https://www.ducea.com/2010/11/08/ill-be-at-lisa10-this-week/?utm_source=atom_feed" rel="related" type="text/html" title="I&#39;ll be at LISA10 this week" />
                <link href="https://www.ducea.com/2010/10/04/interview-with-lisa10-program-chair-rudi-van-drunen/?utm_source=atom_feed" rel="related" type="text/html" title="Interview with LISA&#39;10 Program Chair Rudi van Drunen" />
                <link href="https://www.ducea.com/2010/06/30/lisa-2010-blogging-team-announced/?utm_source=atom_feed" rel="related" type="text/html" title="LISA 2010 Blogging Team Announced" />
                <link href="https://www.ducea.com/2011/06/20/velocity-2011-impressions/?utm_source=atom_feed" rel="related" type="text/html" title="Velocity 2011 impressions" />
            
                <id>https://www.ducea.com/2011/12/03/getting-ready-for-lisa11-boston/</id>
            
            
            <published>2011-12-03T22:53:45+00:00</published>
            <updated>2011-12-03T22:53:45+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>I&rsquo;m packing for <strong>Boston</strong> and will be there next week for <a href="http://www.usenix.org/events/lisa11/index.html">LISA11</a>. This will be my second year as part of the <a href="http://blogs.usenix.org/2011/12/02/lisa11-next-week-meet-your-blog-team/">LISA blogging team</a>, and after how much I enjoyed LISA last year in San Jose I wouldn&rsquo;t miss this one even if it is on the other side of the country. I&rsquo;ve tried to finish as much work as possible to be able to focus on the conference ;) but for various reasons of course this was not quite possible, and actually during the first days I will even be on call&hellip; In anycase, I&rsquo;m sure this is going to be a great week full of awesomeness. I will be blogging for the <a href="http://blogs.usenix.org/">USENIX blog</a> every day, so be sure to follow that for fresh articles from me and the other memebers of our team (Ben, Rikki and Matt).</p>
<p>If you are going to <strong>LISA11</strong> in <strong>Boston</strong> next week, we should definitely meetup. Contact me on <a href="http://twitter.com/mariusducea">twitter</a> or <a href="http://www.ducea.com/contact/">email</a>.</p>
<hr>
<p><a href="https://www.usenix.org/blog/limoncelli-test">The Limoncelli Test</a>, was a very interesting presentation by Tom Limoncelli based on a <a href="http://everythingsysadmin.com/the-test.html">blog post</a> he wrote earlier this year. If you haven&rsquo;t done it already I would strongly recommend to take the test and see how does your sysadmin team rank on <a href="http://goto.tomontime.com/test">&ldquo;The Limoncelli Test&rdquo;</a>.</p>
<p><a href="https://www.usenix.org/blog/recovering-linux-hard-drive-disasters">Recovering From Linux Hard Drive Disasters</a> is Theodore Ts&rsquo;o signature training material on what to do if you have any sort of hard drive failure and covers in depth details on how to recover from such disasters caused by software or hardware failures.</p>
<p><a href="https://www.usenix.org/blog/gameday-creating-resiliency-through-destruction">GameDay: Creating Resiliency Through Destruction</a> (<a href="http://www.slideshare.net/jesserobbins/ameday-creating-resiliency-through-destruction">slides</a>): I enjoyed very much Jesse Robbins presentation, where he draws parallels between two of his greatest passions: firefighting and operations. Watch the <a href="http://www.youtube.com/watch?v=zoz0ZjfrQ9s">video</a>.</p>
<p><a href="https://www.usenix.org/blog/sregoogle-thousands-devops-2004">SRE@Google: Thousands of DevOps Since 2004</a>: Tom Limoncelli, describes the technologies and policies that Google uses to do what is (now) called DevOps. Watch the <a href="http://www.youtube.com/watch?v=iIuTnhdTzK0&amp;feature=youtube_gdata">video</a>.</p>
]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/categories/conferences" term="conferences" label="Conferences" />
                            
                        
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/tags/conferences" term="conferences" label="Conferences" />
                             
                                <category scheme="https://www.ducea.com/tags/lisa" term="lisa" label="LISA" />
                             
                                <category scheme="https://www.ducea.com/tags/lisa11" term="lisa11" label="LISA11" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Interview with LISA11 Program Co-Chairs: Tom Limoncelli and Doug Hughes]]></title>
            <link href="https://www.ducea.com/2011/11/30/interview-with-lisa11-program-co-chairs-tom-limoncelli-and-doug-hughes/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://www.ducea.com/2010/10/04/interview-with-lisa10-program-chair-rudi-van-drunen/?utm_source=atom_feed" rel="related" type="text/html" title="Interview with LISA&#39;10 Program Chair Rudi van Drunen" />
                <link href="https://www.ducea.com/2010/06/30/lisa-2010-blogging-team-announced/?utm_source=atom_feed" rel="related" type="text/html" title="LISA 2010 Blogging Team Announced" />
                <link href="https://www.ducea.com/2010/11/08/ill-be-at-lisa10-this-week/?utm_source=atom_feed" rel="related" type="text/html" title="I&#39;ll be at LISA10 this week" />
                <link href="https://www.ducea.com/2011/06/20/velocity-2011-impressions/?utm_source=atom_feed" rel="related" type="text/html" title="Velocity 2011 impressions" />
                <link href="https://www.ducea.com/2011/03/06/drupalcon-chicago-2011/?utm_source=atom_feed" rel="related" type="text/html" title="DrupalCon Chicago 2011" />
            
                <id>https://www.ducea.com/2011/11/30/interview-with-lisa11-program-co-chairs-tom-limoncelli-and-doug-hughes/</id>
            
            
            <published>2011-11-30T22:31:35+00:00</published>
            <updated>2011-11-30T22:31:35+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>One of the advantages of being a member of the <strong>LISA11 Blog Team</strong> is that I was able to talk and interview this year program co-chairs: <strong>Tom Limoncelli</strong> and <strong>Doug Hughes</strong>. This was a great honor for me especially since I&rsquo;ve been a big fan of Tom&rsquo;s work for many years. The full article is available on the USENIX blog: &ldquo;<a href="http://blogs.usenix.org/2011/12/02/tom-limoncelli-and-doug-hughes-interview/">Tom Limoncelli and Doug Hughes Interview</a>&rdquo;</p>
<p>Also my colleagues from the LISA11 blogging team (Ben, Rikki and Matt) have done some very interesting interviews with some key people from LISA11 to get you prepared for the event. Check out the <a href="http://blogs.usenix.org/">USENIX blog</a> for more from us in the next week.</p>
<p>Here is also a quick intro of our team: &ldquo;<a href="http://blogs.usenix.org/2011/12/02/lisa11-next-week-meet-your-blog-team/">LISA11 Next Week – Meet your blog team!</a>&rdquo;</p>
]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/categories/conferences" term="conferences" label="Conferences" />
                            
                        
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/tags/conferences" term="conferences" label="Conferences" />
                             
                                <category scheme="https://www.ducea.com/tags/interviews" term="interviews" label="interviews" />
                             
                                <category scheme="https://www.ducea.com/tags/lisa" term="lisa" label="LISA" />
                             
                                <category scheme="https://www.ducea.com/tags/lisa11" term="lisa11" label="LISA11" />
                             
                                <category scheme="https://www.ducea.com/tags/usenix" term="usenix" label="USENIX" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Build your own packages easily with FPM]]></title>
            <link href="https://www.ducea.com/2011/08/31/build-your-own-packages-easily-with-fpm/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://www.ducea.com/2009/02/12/bcfg2-096-debian-package-for-etch/?utm_source=atom_feed" rel="related" type="text/html" title="Bcfg2 0.9.6 debian package for etch" />
                <link href="https://www.ducea.com/2007/01/21/debian-snapshot-archive/?utm_source=atom_feed" rel="related" type="text/html" title="Debian Snapshot Archive" />
                <link href="https://www.ducea.com/2009/07/31/debian-adopts-time-based-release-freezes/?utm_source=atom_feed" rel="related" type="text/html" title="Debian adopts time-based release freezes" />
                <link href="https://www.ducea.com/2009/03/10/iotop-simple-top-like-io-monitor/?utm_source=atom_feed" rel="related" type="text/html" title="iotop: simple top-like i/o monitor" />
                <link href="https://www.ducea.com/2009/03/09/iopp-howto-get-io-information-per-process/?utm_source=atom_feed" rel="related" type="text/html" title="iopp: howto get i/o information per process" />
            
                <id>https://www.ducea.com/2011/08/31/build-your-own-packages-easily-with-fpm/</id>
            
            
            <published>2011-08-31T15:13:02+00:00</published>
            <updated>2011-08-31T15:13:02+00:00</updated>
            
            
            <content type="html"><![CDATA[<p><strong>Building packages</strong> is a task that every system administrator will end up doing. Most of the time this is not a very interesting task but someone has to do it, right? Normally you will end up modifying and tweaking based on your own needs an existing package that was built by the maintainers of the Linux distribution that you are using. In time you might even become familiar with the packaging system you are using (rpm, deb, etc.) and you will be able to write a spec file and start from scratch and build a new package if you need to. Still, this <em>process is complicated and requires a lot of work</em>.</p>
<p>Luckily, <a href="http://www.semicomplete.com/blog"><strong>Jordan Sissel</strong></a> has built a tool called <a href="https://github.com/jordansissel/fpm"><strong>FPM</strong></a> (Effing Package Management), exactly for this: to ease the pain of building new packages; packages that you will use for your own infrastructure and you want them customized based on your own needs; and you don&rsquo;t care about upstream rules and standards and other limitations when building such packages. This can be very useful for people deploying their own applications as rpms (or debs) and can simplify a lot of the process of building those packages.</p>
<p>FPM can be easily installed on your build system using rubygems:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gem install fpm
</span></span></code></pre></div><p>Once installed you can use fpm to build <strong>packages</strong> (targets):</p>
<ul>
<li>deb</li>
<li>rpm</li>
<li>solaris</li>
</ul>
<p>from any of the following <strong>sources</strong>:</p>
<ul>
<li>directory (of compiled source of some application)</li>
<li>gem</li>
<li>python eggs</li>
<li>rpm</li>
<li>node npm packages</li>
</ul>
<p>Use the command line help (<code>fpm --help</code>) or the <a href="https://github.com/jordansissel/fpm/wiki">wiki</a> to see full details on how to use it. I&rsquo;ll show some simple examples on how to build some packages from various input sources that I&rsquo;ve found useful myself.</p>
<h3 id="1-package-a-directory---output-of-a-make-install-command">1. Package a directory - output of a &lsquo;make install&rsquo; command</h3>
<p>This is how you would usually package an application that you would install with:<br>
<code>./configure; make; make install</code><br>
For example, here is how you can create an rpm of the latest version of memcached:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">wget http://memcached.googlecode.com/files/memcached-1.4.7.tar.gz
</span></span><span class="line"><span class="cl">tar -zxvf memcached-1.4.7.tar.gz
</span></span><span class="line"><span class="cl">cd memcached-1.4.7
</span></span><span class="line"><span class="cl">./configure --prefix=/usr
</span></span><span class="line"><span class="cl">make
</span></span></code></pre></div><p>so far everything looks like a normal manual installation (that would be followed by make install). Still we will now install it in a separate folder so we can capture the output:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">mkdir /tmp/installdir
</span></span><span class="line"><span class="cl">make install DESTDIR=/tmp/installdir
</span></span></code></pre></div><p>and finally using fpm to create the rpm package:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">fpm -s dir -t rpm -n memcached -v 1.4.7 -C /tmp/installdir
</span></span></code></pre></div><p>where <strong>-s</strong> is the input source type (directory), <strong>-t</strong> is the type of package (rpm), <strong>-n</strong> in the name of the package and <strong>-v</strong> is the version; <strong>-C</strong> is the directory where fpm will look for the files.
Note: you might need to install various libraries to build your package; for ex. in this case I had to install libevent-dev.</p>
<p>If you are packaging your own application you can do this just by pointing to your build folder and set the version of the app. Here is an example for an deb package:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">fpm -s dir -t deb -n myapp -v 0.0.1 -C /build/myapp/0.0.1/
</span></span></code></pre></div><p>There are various other parameters that you can use but basically this is how simple it is to build a package from a directory.
Here is an example on how to define some dependencies on the package you are building (using <strong>-d</strong>; repeat it as many times as needed):</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">fpm -s dir -t deb -n memcached -v 1.4.7 -C /tmp/installdir \
</span></span><span class="line"><span class="cl">-d &#34;libstdc++6 (&gt;= 4.4.5)&#34; \
</span></span><span class="line"><span class="cl">-d &#34;libevent-1.4-2 (&gt;= 1.4.13)&#34;
</span></span></code></pre></div><h3 id="2-ruby-gems-or-python-egg---converted-to-packages">2. Ruby gems or python egg - converted to packages</h3>
<p>You can create a deb or rpm from a gem very simple with fpm:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">fpm -s gem -t deb &lt;gem_name&gt;
</span></span></code></pre></div><p>this will download the gem and create a package named rubygem-&lt;gem_name&gt;
For example:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">fpm -s gem -t deb fpm
</span></span></code></pre></div><p>will create a debian package for fpm: rubygem-fpm_0.3.7_all.deb</p>
<p>You can inspect it with <em>dpkg &ndash;info</em> and you can notice that in this case it will fill nicely all the fields with the maintainer, and dependencies on various other gems. Very cool.</p>
<p>If you use python and want to package various python eggs this will work exactly the same and you will use -s python (it will download the python packages with easy_install first).</p>
<p>Overall <strong>FPM</strong> is a great tool and can help you <em>simplify the way you are building your own packages</em>. Check it out and let me know what you think and if you found it useful. And if you found this useful don’t forget to thank <a href="http://www.twitter.com/jordansissel"><strong>Jordan</strong></a> for his great work on this awesome tool.</p>]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/categories/centos" term="centos" label="Centos" />
                             
                                <category scheme="https://www.ducea.com/categories/debian" term="debian" label="Debian" />
                             
                                <category scheme="https://www.ducea.com/categories/fedora" term="fedora" label="Fedora" />
                             
                                <category scheme="https://www.ducea.com/categories/linux" term="linux" label="Linux" />
                             
                                <category scheme="https://www.ducea.com/categories/rhel" term="rhel" label="RHEL" />
                             
                                <category scheme="https://www.ducea.com/categories/tools" term="tools" label="Tools" />
                             
                                <category scheme="https://www.ducea.com/categories/ubuntu" term="ubuntu" label="Ubuntu" />
                            
                        
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/tags/deb" term="deb" label="deb" />
                             
                                <category scheme="https://www.ducea.com/tags/debian_packages" term="debian_packages" label="debian_packages" />
                             
                                <category scheme="https://www.ducea.com/tags/fpm" term="fpm" label="FPM" />
                             
                                <category scheme="https://www.ducea.com/tags/rpm" term="rpm" label="rpm" />
                             
                                <category scheme="https://www.ducea.com/tags/tools" term="tools" label="Tools" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[First Chef Cookbook Contest Announced!]]></title>
            <link href="https://www.ducea.com/2011/08/23/first-chef-cookbook-contest-announced/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://www.ducea.com/2011/07/01/howto-upgrade-chef-from-0-10-to-0-10-2-rubygems-install/?utm_source=atom_feed" rel="related" type="text/html" title="HowTo upgrade Chef from 0.10 to 0.10.2 - rubygems install" />
                <link href="https://www.ducea.com/2010/09/27/chef-intro-sf-bay-area-lspe-meetup/?utm_source=atom_feed" rel="related" type="text/html" title="Chef Intro @ SF Bay Area LSPE meetup" />
                <link href="https://www.ducea.com/2010/09/01/nodejs-chef-cookbook-released/?utm_source=atom_feed" rel="related" type="text/html" title="NodeJS chef cookbook released" />
                <link href="https://www.ducea.com/2011/08/15/building-vagrant-boxes-with-veewee/?utm_source=atom_feed" rel="related" type="text/html" title="Building Vagrant boxes with veewee" />
                <link href="https://www.ducea.com/2009/06/30/osbridge-configuration-management-panel/?utm_source=atom_feed" rel="related" type="text/html" title="OSBridge: Configuration Management Panel" />
            
                <id>https://www.ducea.com/2011/08/23/first-chef-cookbook-contest-announced/</id>
            
            
            <published>2011-08-23T11:18:14+00:00</published>
            <updated>2011-08-23T11:18:14+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>Yesterday <a href="http://www.opscode.com/"><strong>Opscode</strong></a>, the company behind <a href="http://www.opscode.com/chef/"><strong>Chef</strong></a>, <a href="http://www.opscode.com/blog/2011/08/22/cookbook-contest/">announced</a> the first ever <strong>chef cookbook contest</strong>. In order to participate in the contest you will need to write a new cookbook and submit it by the <em>end of September;</em> this is going to be a little tricky as there are many cookbooks already available on the <a href="http://community.opscode.com/cookbooks">community site</a>. So this is a great idea and it will take care of the few applications that don&rsquo;t already have chef cookbooks. The cookbooks which shows off the awesome Chef features will have better chances to win. The prizes are also interesting: iPad, gift cards, etc. Here are the full details and rules of the contest: <a href="http://www.opscode.com/blog/2011/08/22/cookbook-contest/">http://www.opscode.com/blog/2011/08/22/cookbook-contest/</a></p>
<p>So if you have an <strong>idea</strong> for a chef cookbook, <strong>now</strong> it&rsquo;s the time to start working on it. I&rsquo;m offering my <strong>help for free</strong> for all my blog readers: I will help you write a cookbook by implementing your ideas; help reviewing it or suggest improvements, or whatever else you might need help with. Use the <a href="http://www.ducea.com/contact/">contact</a> form to email me (or DM me on <a href="http://twitter.com/mariusducea">twitter</a>) and let me know how I can help.</p>
<p>If you don&rsquo;t have time to write a new cookbook but you have a great idea for a cookbook that is missing from the opscode community site, please post it bellow in the <strong>comments section</strong> and I&rsquo;m sure some of my blog readers will help create it.</p>
<p>Again this is a brilliant idea from Opscode and it creates a win-win situation for everyone. I&rsquo;m just curious, is this the first idea from their new community manager? If this is the case, great job Jesse ;).</p>
]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/categories/configuration-management" term="configuration-management" label="Configuration management" />
                             
                                <category scheme="https://www.ducea.com/categories/news-from-outside" term="news-from-outside" label="News from Outside" />
                            
                        
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/tags/chef" term="chef" label="chef" />
                             
                                <category scheme="https://www.ducea.com/tags/cookbooks" term="cookbooks" label="cookbooks" />
                             
                                <category scheme="https://www.ducea.com/tags/opschef" term="opschef" label="opschef" />
                             
                                <category scheme="https://www.ducea.com/tags/opscode" term="opscode" label="opscode" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Building Vagrant boxes with veewee]]></title>
            <link href="https://www.ducea.com/2011/08/15/building-vagrant-boxes-with-veewee/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://www.ducea.com/2009/06/30/osbridge-configuration-management-panel/?utm_source=atom_feed" rel="related" type="text/html" title="OSBridge: Configuration Management Panel" />
                <link href="https://www.ducea.com/2011/07/01/howto-upgrade-chef-from-0-10-to-0-10-2-rubygems-install/?utm_source=atom_feed" rel="related" type="text/html" title="HowTo upgrade Chef from 0.10 to 0.10.2 - rubygems install" />
                <link href="https://www.ducea.com/2010/09/27/chef-intro-sf-bay-area-lspe-meetup/?utm_source=atom_feed" rel="related" type="text/html" title="Chef Intro @ SF Bay Area LSPE meetup" />
                <link href="https://www.ducea.com/2010/09/01/nodejs-chef-cookbook-released/?utm_source=atom_feed" rel="related" type="text/html" title="NodeJS chef cookbook released" />
                <link href="https://www.ducea.com/2011/07/22/monitoring-with-icinga-sf-bay-area-lspe-meetup/?utm_source=atom_feed" rel="related" type="text/html" title="Monitoring with Icinga @ SF Bay Area LSPE meetup" />
            
                <id>https://www.ducea.com/2011/08/15/building-vagrant-boxes-with-veewee/</id>
            
            
            <published>2011-08-15T18:49:23+00:00</published>
            <updated>2011-08-15T18:49:23+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>If you used <a href="http://vagrantup.com/"><strong>vagrant</strong></a> (great tool, right?) you have probably downloaded a basebox from some remote location to get you started. This is a great quick start, and there are many good boxes out there that you can use; <a href="http://www.vagrantbox.es/">vagrantbox.es</a> does a great job in listing various public vagrant boxes. But if you are like me, you probably will want to customize the boxes you are using; you might want to install them from scratch based on your own little/or/big customizations. Well if you are like that, then you will be happy to hear that <a href="http://www.jedi.be/blog"><strong>Patrick Debois</strong></a> had exactly the same problem when he decided to write <a href="https://github.com/jedi4ever/veewee"><strong>veewee</strong></a>. And veewee is exactly that missing part of vagrant that allows you to easily build your own vagrant boxes from scratch.</p>
<p>So let&rsquo;s see how we can use veewee. I&rsquo;m assuming you already have vagrant installed (and <a href="http://download.virtualbox.org/virtualbox/">virtualbox</a>), but if you don&rsquo;t please install them first. To install <strong>veewee</strong> we just have to install the veewee gem:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">gem install veewee
</span></span></code></pre></div><p>once you installed veewee you can see a new task added to vagrant: <strong>basebox</strong>.</p>
<p>Here is the list of the <strong>templates</strong> we get out of the box once we install veewee:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">**vagrant basebox templates**
</span></span><span class="line"><span class="cl">The following templates are available:
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;archlinux-i686&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;CentOS-4.8-i386&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;CentOS-5.6-i386&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;CentOS-5.6-i386-netboot&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;Debian-6.0.1a-amd64-netboot&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;Debian-6.0.1a-i386-netboot&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;Fedora-14-amd64&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;Fedora-14-amd64-netboot&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;Fedora-14-i386&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;Fedora-14-i386-netboot&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;freebsd-8.2-experimental&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;freebsd-8.2-pcbsd-i386&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;freebsd-8.2-pcbsd-i386-netboot&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;gentoo-latest-i386-experimental&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;opensuse-11.4-i386-experimental&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;solaris-11-express-i386&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;Sysrescuecd-2.0.0-experimental&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;ubuntu-10.04.2-amd64-netboot&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;ubuntu-10.04.2-server-amd64&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;ubuntu-10.04.2-server-i386&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;ubuntu-10.04.2-server-i386-netboot&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;ubuntu-10.10-server-amd64&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;ubuntu-10.10-server-amd64-netboot&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;ubuntu-10.10-server-i386&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;ubuntu-10.10-server-i386-netboot&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;ubuntu-11.04-server-amd64&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;ubuntu-11.04-server-i386&#39;
</span></span><span class="line"><span class="cl">vagrant basebox define &#39;&#39; &#39;windows-2008R2-amd64-experimental&#39;
</span></span></code></pre></div><p>This means that we can build a box based on <strong>any</strong> of the above templates. <em>That&rsquo;s awesome!</em> Let&rsquo;s say we want to build a debian squeeze box using veewee; we would have to run:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">vagrant basebox define &#39;debian-60&#39; &#39;Debian-6.0.1a-amd64-netboot&#39;
</span></span></code></pre></div><p>and this will create a folder definitions/debian-60 with the following files (the content of the veewee template):</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">definition.rb
</span></span><span class="line"><span class="cl">postinstall.sh
</span></span><span class="line"><span class="cl">preseed.cfg
</span></span></code></pre></div><p>we can modify/tune any of those files based on our custom needs. The file <strong>definition.rb</strong> is the main definition of the template. Here you would define the memory size, disk size, iso file, etc. The content is very easy to understand, but you would normally not have to change many things here. <strong>preseed.cfg</strong> is just a standard preseed file where you would customize the actual install process (you could change here the partitions or their type, timezone setup, etc). And finally <strong>postinstall.sh</strong> that is a bash script that will run at the end of the installation process and it will install ruby, gems , chef and puppet and also the virtualbox guest additions (needed for shared folders).</p>
<p>If you have the iso already place it in <strong>&lsquo;currentdir&rsquo;/iso</strong>. If not, veewee will download it and place it in the appropriate folder before starting the install process:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">vagrant basebox build &#39;debian-60&#39;
</span></span></code></pre></div><p>this will start the installation and you can see all the steps it takes (the keystrokes as they are entered, etc.). This can take a while… Once it is done you can validate the build with:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">vagrant basebox validate &#39;debian-60&#39;
</span></span></code></pre></div><p>(this will run a few basic tests to see if it can connect to the vm as user vagrant, if chef and puppet were installed, if the shared folders are accessible, etc).</p>
<p>And finally you can export it as a vagrant box with:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">vagrant basebox export &#39;debian-60&#39;
</span></span></code></pre></div><p>and add it to vagrant:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">vagrant box add &#39;debian-60&#39; debian-60.box
</span></span></code></pre></div><p>and now you can use it in vagrant with:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">vagrant init &#39;debian-60&#39;
</span></span></code></pre></div><p>That&rsquo;s it. Very simple and now we have our own box built from scratch. As a side note, I found this very useful to test and troubleshoot preseed configurations ;). As you can see there are plenty of templates available in veewee but if you create a new one please consider to share it with others and send it to Patrick on <a href="https://github.com/jedi4ever/veewee">github</a>. I&rsquo;m sure he will be happy to include it in newer versions of veewee. And if you found this useful don&rsquo;t forget to thank <a href="https://twitter.com/#!/patrickdebois">Patrick</a> for his great work on this awesome tool.</p>]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/categories/configuration-management" term="configuration-management" label="Configuration management" />
                             
                                <category scheme="https://www.ducea.com/categories/linux" term="linux" label="Linux" />
                             
                                <category scheme="https://www.ducea.com/categories/macosx" term="macosx" label="MacOSX" />
                             
                                <category scheme="https://www.ducea.com/categories/tools" term="tools" label="Tools" />
                            
                        
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="https://www.ducea.com/tags/chef" term="chef" label="chef" />
                             
                                <category scheme="https://www.ducea.com/tags/puppet" term="puppet" label="puppet" />
                             
                                <category scheme="https://www.ducea.com/tags/vagrant" term="vagrant" label="vagrant" />
                             
                                <category scheme="https://www.ducea.com/tags/veewee" term="veewee" label="veewee" />
                             
                                <category scheme="https://www.ducea.com/tags/virtualbox" term="virtualbox" label="virtualbox" />
                            
                        
                    
                
            
        </entry>
    
</feed>
