Repeatable build for Lambda Layers with Yarn Workspaces

I have pretty big monorepo, managed solely by Yarn Workspaces (no Lerna). One of the packages (“workspaces”) contains a set of 3rd party NodeJS libraries that we use as a shared layer for our Lambda functions, collected as dependencies in package.json of this package. Build script for this package is supposed to collect all dependencies in a zip file that will be later published by Terraform. Unfortunately, Yarn cannot build single workspace from the monorepo, so initially we opted to use NPM directly – copy package.json to a build folder, then run “npm install --production” there and zip the resulting node_modules tree.

My main problem with this approach (besides mixing the build tools) was that the build is not repeatable – each time we run npm install we could get newer compatible version of any dependent package, since the version is “locked” by Yarn in the top-level yarn.lock file and NPM (obviously) is not aware about it. So I decided to dive deeper and see how it can be solved in a better way.

It appears that while Yarn hoists all the dependencies to the node_modules of the top-level workspace, you can explicitly opt-out from this behavior for some dependencies – or, in my case, for all dependencies of the given workspace.

Yarn Workspaces configuration before:

"workspaces": [
  "packages/*"
]

Yarn Workspaces configuration after the change, assuming Lambda Layer dependencies are collected under common-lambda workspace:

"workspaces": {
  "packages": [
    "packages/*"
  ],
  "nohoist": [
    "common-lambda/**"
  ]
}

Note that nohoist array should contain the workspace name (including namespace when applicable) and not the workspace folder.

After this change packages/common-lambda/node_modules will contain proper versions of all the dependencies to be packaged as Lambda Layer. Those dependencies will be updated automatically on yarn install and the node_modules folder can be packaged directly.

Windows Azure – Newbie Notes

WinAzure

This week I dedicated some time to check what Windows Azure is about. Here are some notes I gathered during those days. I have some background in VMware and AWS, so the notes are mostly around the differences between those and Windows Azure that I spotted.

The first thing to note is that single Management Console provides access to all Windows Azure functionality pieces. Here those pieces look like the parts of a whole. In AWS each service actually is a separate service (with some of those services being integrated), and the console clearly reflects that.

Virtual Machines and Virtual Networks
Those are two basic concepts that are much the same between Azure and AWS, besides maybe some terminology differences:

Amazon AWSWindows Azure
InstanceVirtual Machine
(Instance) Type(VM) Size
Start, Stop, TerminateStart, Shut Down, Delete
AMI (= Amazon Machine Image)(VM) Images
VPC (= Virtual Private Cloud)(Virtual) Network

My feeling is that similarly named type/size on Azure is much slower than its AWS counterpart, but I cannot prove that with some test results yet.

VM Images
Just like AWS, Azure provides you large set of images to start your VM from. There is no marketplace for 3rd party images yet, but you can create your own images if you need to. Two major differences here are the need to go through all sysprep burden on your own and the fact that the original VM is deleted (sic!) after it was captured as an image. Yet, this may be not that bad to avoid some confusion, considering that original instance is mostly wiped after sysprep.

IP Addresses
Unlike AWS, where internal IP address of an instance within VPC will remain constant for the instance lifetime (that is – until the termination), here both external and internal IP of the VM will not survive the shutdown and will be changed after you turn it on. A possible workaround is to shut down the VM from inside the guest OS and not from the Management Console. This way the VM is considered running by Azure and all VM resources, including IP addresses, are preserved. Note that in this state the VM continues to eat your budget! [ Update (May 2014): Here is a great article on the topic. Also, setting static IP address is now possible via PowerShell. ]

Cloud Service
The concept of cloud service does not exist on AWS, and is not easy to create simple explanations of what it is. The explanation from Microsoft pretends to be complete, but is mostly confusing. There are some better explanations on the net, much more suitable for newbies – for example this one, which explains the concept by giving three examples of cloud services:
1) Small HTML site.
2) Complex 2-tier web application built on ASP.NET and SQL Server.
3) Virtual network with multi-server application cluster and local AD installation.
Each VM lives inside some cloud service, even if it is a cloud service with single VM inside.
Each cloud service has own permanent DNS name under “cloudapp.net” domain, short and fully resolvable on the internet, and single public IP address. The IP address will be released after all VMs in the cloud service go down, but the new IP will be associated with the same DNS name after the service will be up again. Each VM in the service will get own externally available ports (so-called “endpoints”), which are mapped to some private ports on the VM itself. Those port numbers do no change, making configuration of various connection managers (like mRemoteNG) static and easy to maintain. In addition, cloud service may be configured to act as a load-balancer for containing VMs, eliminating the need to maintain separate entity for that (like, say, ELB on AWS).

Name Resolution
There are significant differences related to name resolution between Azure and AWS. The build-in DNS service is intended to provide name resolution for virtual machines that reside in the same cloud service only. That is, even if you have two virtual machines that are located on the same virtual network, but belong to different cloud services, you will need to use your own DNS server solution in order for them to communicate directly by hostname. I guess this is one of the reasons for Azure-provided DNS server not being able to perform reverse lookups.
Pay attention that setting own DNS server in Azure is not so straightforward given that internal IP addresses may change over time. [ Update (May 2014): Things have changed. read about it here. ]

Active Directory
Windows Azure Active Directory is not a Domain Controller. You can use it to sync on-premises AD with Windows Azure AD to easily enable SSO, but you can not join computers to Windows Azure AD. In addition, it appears that you cannot delete Windows Azure Active Directory that you don’t need anymore. Well, at least they don’t charge for it. But anyway, if you do need full Active Directory (with Domain Services) in Azure – recall that it requires own DNS server…

Storage
Windows Azure Blob Storage is somehow similar to S3 in AWS – but only if you need programmatic access. There is no way to upload files there via Management Console, and I was unable to find third party utils or browser extensions that can do it for you without mandatory registration to their service (and providing them your Azure credentials). [ Update (May 2014): CloudBerry Explorer for Microsoft Azure Cloud Storage seems to do that job perfectly! ]

Security
There is no AWS-like separate “security groups” in Azure. Instead, the same functionality is provided by endpoints that are configured directly on VM level (see my notes on cloud services above). The major drawback of this approach is lack of single place to maintain access rules. However, it makes some sense when you recall that each VM has own public port number for the same protocol.

Notes on creation of Windows AMI in EC2

AWSCreating AMI from Windows instance in AWS is simple and easy. The whole process is well-documented, yet here are several notes that I made while experimenting.

Running Sysprep Tool
In the VMware world, you can convert a VM to a template at any moment. Deployment of multiple clones is made possible via Customization Specifications mechanism, where you define how to customize the new VM after cloning. As part of the customization process, vCenter will run Sysprep tool – after the instance was already cloned. In contrary, AWS wants you to run sysprep before the cloning, as preparation to AMI creation. You can do that via EC2ConfigService settings (see below) or manually, but former seems to be the preferred and recommended way.
The unwanted side effect of running sysprep on the original instance is that many of the original instance settings (instance name, Administrator account etc.) are actually reset during the cloning process. There are workarounds that can help you to deal with some consequences, but not all of them.

EC2ConfigService
The EC2ConfigService is Windows service provided and installed by AWS, which takes care about a lot of useful customizations behind the scenes. Examples are generation of Administrator password (one that you retrieve via “Connect” button in EC2 Management Console), setting of computer name, display of system information on the desktop wallpaper and a lot more. But the most important task is to deal with instance cloning – that is, make sure that stuff that is supposed to be unique is really unique and make this cloning process simple and easy.
Note that you cannot install this service on a Windows instance imported from other systems (for example, VMware vCenter). You’ll have to start your original instance from AWS AMI if you want to use EC2ConfigService there.

Instance Name
The name of the original Windows instance will be reset during sysprep process to the default semi-random name provided by AWS (in the form of “WIN-<something>”). The only workaround for that is to use “Set Computer Name” from EC2ConfigService settings. This flag instructs EC2ConfigService to (re)set system name according to the internal IP adrress – which remains constant during the instance lifecycle. The resulting name will not become much more readable, but at least it will not change during the AMI creation process. You’ll have to remove this flag manually on the cloned instances to set more meaningful names there.

Administrative Accounts
The Administrator account from the original instance will not make his way to the cloned instances, so any customizations made there will be lost. The workaround is to create an additional account with administrative permissions and perform the desired customizations there. There are many settings that will go this way too (for example, regional settings or pinned taskbar items), but some will survive – desktop shortcuts, windows explorer options and more.
Another tip is to choose “Keep Existing” in the “Administrator Password” section of EC2ConfigService configuration. While it won’t help you to retain current password in the new instances (because Sysprep tool on Windows 2008 resets it anyway), at least the Administrator password of your original instance will not be changed.

AMI Creation Steps
This is not an ultimate guide on how to create AMI, but rather a note/reminder to myself…

  1. Create a new EC2 instance from AWS AMI
  2. Create new administrative account and start using it instead of the build-in one
  3. (optional) Use “Set Computer Name” option from EC2ConfigService settings
  4. Customize your instance – install software, add desktop shortcuts etc.
  5. Start EC2ConfigService settings utility, go to the “Image” tab and perform the following:
    • (optional) Under “Administrator Password” section, select “Keep Existing” option
    • Click “Shutdown with Sysprep” button and confirm the prompt
  6. Wait while the Sysprep process completed and the instance shuts down
  7. Right-click the instance in the EC2 Management Console, choose “Create Image” and follow the instructions

Tip: Disk Size
When you launch an EC2 instance that you plan to convert to AMI later, pay attention to the disk size. Remember that the disk of the AMI must be at least that big, and the same applies to any instance that will be launched from the new AMI. Provisioning 10GB of spare storage in your AMI will cost you $1 per instance per month, which may be kinda painful in the yearly bill (do the math yourself).

How to unpack RAR files on AWS-hosted Ubuntu servers

It appears that regular unrar package is not available by default via apt-get on AWS Ubuntu servers. If you still need to unpack RAR files and prefer to install packages from default APT repositories only, the right package to install is unrar-free. It will do the job for you in most of the cases.

ubuntu@ip-10-0-0-38:/work/$ sudo apt-get install unrar-free
Reading package lists... Done
Building dependency tree
Reading state information... Done
Suggested packages:
pike7.8 pike7.6 pike
The following NEW packages will be installed:
unrar-free
0 upgraded, 1 newly installed, 0 to remove and 43 not upgraded.
Need to get 24.8 kB of archives.
After this operation, 101 kB of additional disk space will be used.
Get:1 http://us-west-2.ec2.archive.ubuntu.com/ubuntu/ saucy/universe unrar-free amd64 1:0.0.1+cvs20071127-2 [24.8 kB]
Fetched 24.8 kB in 4s (6,201 B/s)
Selecting previously unselected package unrar-free.
(Reading database ... 67423 files and directories currently installed.)
Unpacking unrar-free (from .../unrar-free_1%3a0.0.1+cvs20071127-2_amd64.deb) ...
Processing triggers for man-db ...
Setting up unrar-free (1:0.0.1+cvs20071127-2) ...
update-alternatives: using /usr/bin/unrar-free to provide /usr/bin/unrar (unrar) in auto mode
ubuntu@ip-10-0-0-38:/work$ 

Unfortunately, sometimes unrar-free is not enough – for example, when you have to unpack multipart archives. In this case you’ll have no choice but to obtain the original RAR for Linux software by enabling Multiverse repository. Alternatively, you can download the trial version directly from the official RARLAB site.

Opening SSH to AWS-hosted Linux servers via mRemoteNG

mRemoteNGmRemoteNG is nice and lightweight tabbed session manager. It is a perfect fit to manage your remote server farm with both Windows and Linux machines, since it supports multiple connection protocols out of the box – including SSH and RDP (yet, you may need to update your older Windows client to run newer RDP version).

However, connecting to Linux instances that run on AWS requires a bit more than just SSH client. As you probably know, Linux EC2 instances have password authentication disabled by default to prevent brute-force attacks and want you to supply your private key instead. But there is no such field in mRemoteNG configuration pane! So, how can you configure it to send your private key instead of password?

It appears that mRemoteNG relies on embedded PuTTY to provide SSH support. In turn, PuTTY by itself is able to work with private keys authentication required by AWS. Here is the detailed explanation about the configuration steps.

Continue reading “Opening SSH to AWS-hosted Linux servers via mRemoteNG”