Kategoriarkiv: DevOps

DevOps Säkerhet

Att jobba med DevOps samt IT-säkerhet är några av de områden som jag gillar mest. Därför är det intressant att ibland stanna upp och reflektera. För inom DevOps handlar det oftast om att skeppa kod så snabbt som möjligt och bygga skalbara och snabba mikroinfrastrukturer med continuous integration. Säkerhet däremot ses ofta som en bromskloss i utvecklingsarbetet.

Det går att fuska med säkerhet: Genomföra saker snabbt men se säkerheten som ett lån med ränta. Att betala tillbaka på lånet snabbare gör att säkerheten blir bättre och det blir inte lika dyrt längre fram (technical debt).

Att ta med säkerheten tidigt i sin planering är viktigt, för använder ni Docker så se till att använda SELinux eller AppArmor (vilket bl.a. Ubuntu Snappy gör som standard).

Exponera ej Elasticsearch, Redis, MongoDB eller andra databaser direkt mot Internet, vilket tyvärr förekommer och nyttjas av elakingar.

Se även till att inte lagra lösenord i klartext och genomför säker radering av information. Visste du exempelvis att Mac OS X har kommandot srm?

srm – securely remove files or directories

Nu är det nog med rant för det blir faktiskt bättre. Och för att ge lite matnyttiga tips tänk på följande:

10 tips till säkrare DevOps

  1. Genomför inte bara backup. Kontrollera även löpande att den verkligen innehåller allt och fungerar. Backup för prod ska ej vara tillgänglig från stage och vice versa.
  2. Prod-, stage- och utvecklingsmiljöer ska ej dela nycklar, lösenord etc.
  3. Tänk på att ej lägga alla ägg i samma korg. Nyttja exempelvis Amazons availability zones.
  4. Kryptera så mycket som möjligt. Inte bara in-transit utan även lokalt, undvik helt klartextprotokoll samt införskaffa SSL-Certifikat.
  5. ossecLogga mycket och filtrera samt arkivera med hjälpmedel såsom OSSEC. Som förresten även kan hålla koll på filintegritet.
  6. Bevaka med verktyg såsom Nagios, Pingdom och New Relic. Glöm inte ändpunkter för API (10 saker som Bit.ly glömde att bevaka).
  7. Genomför löpande säkerhetskontroller med verktyg såsom QualysNessus och Detectity. Även manuella återkommande granskningar är att rekommendera av företag som utför penetrationstester.
  8. Omvärldsbevaka och håll Er uppdaterad när det kommer nya sårbarheter i de mjukvaror som Er infrastruktur använder. Vad är best practices just nu för att lagra lösenord, är det bcrypt, scrypt eller pbkdf2?
  9. Segmentera och filtrera så mycket som möjligt. Ingen enskild server eller konto ska ha tillgång till allt.
  10. Checka aldrig in lösenord, nycklar eller annat känsligt till ett repo.

Tänk inte bara DevOps, tänk även SecOps.

Lös inte nästa problem som du stöter på, på följande sätt (saxat från Stackoverflow)

https stackoverflow

Kör Docker med CoreOS och fleet

Mitt företag Triop AB erbjuder konsulttjänster inom DevOps. Se här: triop.se/devops

Fleet är en av de nyare verktygen som kommer från gänget bakom operativsystemet CoreOS. Fleet är till för att köra din kod på kluster av Dockers som rullar under CoreOS.

fleet ties together systemd and etcd into a distributed init system. Think of it as an extension of systemd that operates at the cluster level instead of the machine level.

Jag tänkte visa när jag startar upp två noder på Amazon EC2 som kör CoreOS och som sedan administreras med hjälp av kommandot fleetctl.

Python-koden för att starta upp nya servrar hittar du längst ner i detta blogginlägg. Det finns några inställningar som du bör göra innan, såsom att nyckelnamnet stämmer och security group har regler som tillåter port 7001, 4001 och 22. Samt EC2 access id och key.

Starta upp klusterchefen

Först och främst startar vi upp en leader. Detta kommuniceras ut via den unika token som återfinnes under discovery i user_data som du bör sätta till ett unikt värde för varje kluster.

$ python ec2-coreos.py
# Starting EC2 server with hostname coreos-roseanne
 - Wait..
 - Wait..
 - Wait..
Found IP: 46.137.21.3

Du kan även kontrollera att det fungerar att ansluta till den nya servern med IP-adress 46.137.21.3:

$ ssh -p 22 [email protected]
CoreOS (alpha)
[email protected] ~ $

Perfekt. Även kan det vara till fördel att se så att etc verkligen lyssnar på tcp port 4001 och 7001 antingen tittar vi via lsof eller testar att ansluta direkt med curl:

$ curl 46.137.21.3:4001
404 page not found
$ curl 46.137.21.3:7001
404 page not found

Och det fungerar bra. Skulle inte etcd starta upp så kan det bero på att din cloudconfig är felaktig (ej unik nyckel) eller så kan du titta på loggen med journalctl -u etc. Även så kan du starta upp etcd med kommandot:

sudo systemctl start etcd.service

Starta upp en arbetsnod

För att vi ska ha någon mer nod i klustret så startar vi upp en till. Precis som ovan så kör vi bara ec2-coreos.py och väntar några sekunder på att vår nya nod ska starta upp:

$ python ec2-coreos.py
# Starting EC2 server with hostname coreos-alia
 - Wait..
 - Wait..
 - Wait..
 - Wait..
Found IP: 54.220.243.180

Om allt gick som det ska så ska denna nya nod automatiskt ansluta till coreos-roseanne som är leader. Du kan även titta på loggen med journalctl -u etcd om något skulle vara fel eller använda den unika discovery URL:en direkt för att lista alla noder i ditt kluster:

curl https://discovery.etcd.io/db7ce1f96d42b24f38b5c96a3018f1ea|python -mjson.tool

CoreOS Fleet

Då var det dags att administrera vår flotta med noder med hjälp av fleetctl. Jag har på min Mac installerat fleetctl från github men det går även bra via homebrew:

$ brew update
$ brew install fleetctl

Om vi har rätt ssh-nycklar är det bara att köra. Du kan installera rätt ssh nyckel via kommandot ssh-add coreos.pem exempelvis.

Vi börjar med att lista alla maskiner:

$ fleetctl --tunnel=46.137.21.3 list-machines
MACHINE IP METADATA
9c62bc5f... 10.73.195.43 -
f9946c83... 10.35.3.231 -

Perfekt. Då är det dags att slänga ut vårat första jobb som ska utföras i klustret. Det är ett simpelt Hello World test som ska exekveras, så vi lägger följande innehåll i filen myapp.service:

[Unit]
Description=MyApp
After=docker.service
Requires=docker.service

[Service]
ExecStart=/usr/bin/docker run busybox /bin/sh -c "while true; do echo Hello World; sleep 1; done"

Och startar upp:

$ fleetctl --tunnel=46.137.21.3 start myapp.service
Job myapp.service launched on 9c62bc5f.../10.73.195.43

Perfekt. Nu ska jobbet ha startat och vi kan titta med fleetctl journal myapp.service eller list-nodes.

Så här ser det ut med info:

CoreOS Docker FleetOch nu ligger Hello World och kör under Docker på en av noderna vilket fleetctl list-units kan bevittna.

För delning av jobb och leader/follower genomförs av Raft Consensus algortimen.

 ec2-coreos.py

Här återfinnes koden som jag använder för att starta upp nya noder:

#!/usr/bin/env python
## 
## Jonas Lejon 2014
##
## sudo pip install apache-libcloud names

import os, sys, time
import names 
from libcloud.compute.types import Provider
from libcloud.compute.providers import get_driver
import libcloud.security
libcloud.security.CA_CERTS_PATH = ['ca-bundle.crt'] # from Mozilla

EC2_ACCESS_ID     = '' # Paste your Amazon EC2 credentials here
EC2_SECRET_KEY    = ''

userdata = """#cloud-config

coreos:
  etcd:
    # generate a new token for each unique cluster from https://discovery.etcd.io/new
    discovery: https://discovery.etcd.io/unique_token_here
    # multi-region and multi-cloud deployments need to use $public_ipv4
    addr: $public_ipv4:4001
    peer-addr: $public_ipv4:7001
  units:
    - name: etcd.service
      command: start
    - name: fleet.service
      command: start
"""

#EC2Driver = get_driver(Provider.EC2)
EC2Driver = get_driver(Provider.EC2_EU_WEST)
conn = EC2Driver(EC2_ACCESS_ID, EC2_SECRET_KEY)

hostname = "coreos-" + names.get_first_name(gender='female').lower()

print "# Starting EC2 server with hostname",hostname

MY_SIZE = 't1.micro'
#MY_IMAGE = "ami-8f30fff8" # CoreOS beta at eu-west-1
MY_IMAGE = "ami-87a769f0" # CoreOS alpha at eu-west-1

sizes = conn.list_sizes()
images = conn.list_images()

size = [s for s in sizes if s.id == MY_SIZE][0]
image = [i for i in images if i.id == MY_IMAGE][0]

node = conn.create_node(name=hostname, image=image, size=size, ex_keyname="coreos", ex_userdata=userdata, ex_securitygroup="coreos")
nodes = conn.list_nodes()
time.sleep(5)
while nodes[-1].state != 0:
	time.sleep(5)
	print " - Wait.."
	nodes = conn.list_nodes()
print "Found IP:",nodes[-1].public_ips[0]

Så testar du nya CoreOS

Psst! Du vet väl att du kan hyra mig för att göra underverk när det gäller DevOps, IT-säkerhet eller högprestandasystem. Kontakt hittar du här >

CoreOS är ett nytt spännande lättviktigt operativsystem som är byggt för att användas i klusterinfrastrukturer.

Opertivsystemet (OS) är även byggt för att användas till att köra flertalet Docker containers samt så har CoreOS automatiska säkerhetsuppdateringar med två root-filsystem som växlas mellan beroende om det enda uppdateras eller ej. Filsystemen är read-only samt os:et startas om automatiskt vid uppdateringar (eller kexec). Detta innebär så klart att du ej bör lagra något på lokala filsystemet permanent.

Fler fräsiga finneser är en key-value-storage motor inbyggt vid namn etcd (skriven i Go) som även kan användas för service discovery. Etcd synkroniseras automatiskt i hela ditt kluster vilket gör det ypperligt bra för att exempelvis peka ut var dina tjänster håller hus.

CoreOS kluster

CoreOS har tre utvecklare på heltid som jobbar med projektet samt är baserat på Chromium OS som Goolge står bakom. Har även fått in kapital från Andreessen Horowitz samt  Sequoia Capital.

För att testa CoreOS på Mac OS X med Vagrant gör du bara enligt följande:

$ git clone https://github.com/coreos/coreos-vagrant/
$ cd coreos-vagrant
$ vagrant up
$ vagrant ssh

Här är en skärmdump när jag ansluter via vagrant ssh:

CoreOS VagrantOch sedan är det bara att dra igång vår en container i Docker. I detta fall kör jag Ubuntu 13.10:

Docker Ubuntu 13 10

Och här skapade jag en screencast som visar hela förfarandet:

Har du testat CoreOS? Lämna gärna en kommentar om dina erfarenheter.

Docker med WordPress

Ni som läser denna blogg vet hur förälskad jag är i Docker. Jag tänkte nu försöka förklara hur du kan köra WordPress tillsammans med Docker. Det är ingen lätt process men det finns en stor uppsida:

  • Flexibilitet – Möjlighet att flytta komponenter mellan servrar lätt. Exempelvis lyfta ur databasmotorn eller webbservern.
  • Säkerhet – Allt separeras med hjälp av Linux Containers. Inte lika säkert som separata fysiska servrar eller virtuella maskiner.
  • Skalbarhet – Att växla upp delkomponenter är snabbt och enkelt. Lägga till och ta bort memcached exempelvis.
  • Driftsättning – Gå från utveckling, stage-miljö till driftsättning går snabbt och smidigt. Inga jobbiga beroenden som saknas eller är felaktiga.

Men hur gör man då? Jo först och främst är det några saker man måste tänka på:

  • En docker med Nginx + WordPress
  • Skrivbart filsystem för wp-content utanför dockern till WordPress.
  • En docker med MySQL (eller MariaDB, Percona)
  • Skrivbart filsystem för MySQL-databasen utanför dockern
  • Framtid: En docker med memcached.

Då sätter vi igång. Jag går ej igenom hur du installerar Docker utan det kan du läsa här eller köra Vagrant som jag gör på Mac OS X.

Installera NginxNginx

Den första dockern vi skapar ska ha Nginx samt WordPress installerat. Port 80 för http ska exponeras utåt.

Först och främst kör vi igång kommandotolken bash i Ubuntu 13.10 samt installerar Nginx.

# mkdir -p /data/wordpress/

Först enligt ovan kommando så skapar vi en gemensam katalog för våra containrar samt värdsystemet som ligger under /data.

# docker run -v /data/wordpress:/data/wordpress -p 80:80 -i -t ubuntu:13.10 /bin/bash
# apt-get update
# apt-get -y dist-upgrade
# apt-get -y install php5-fpm php5-gd php5-mysqlnd nginx php5-cli php5-curl php5-json

Ändra sedan /etc/nginx/sites-enabled/default och lägg till konfigurationsdirektiv enligt exempelvis den konfigg-template du hittar här. Du kan även konfigurera tonvis med andra inställningar i Nginx för att uppnå optimal prestanda, men det är ligger utanför denna guide.

Du måste även sätta root till den delade katalogen /data/wordpress/ i Nginx-konfen samt lägga till nedan i /etc/nginx/nginx.conf:

daemon off;

Vi avslutar dockern genom att trycka ctrl-D eller skriva exit.

Sedan kör vi följande för att spara ändringarna vi har genomfört i vår docker. Obs detta är viktigt annars går allt förlorat:

# docker ps -a

Kontrollera sedan vilket container ID den dockern vi just jobbade med och skriv ner ändringarna permanent genom en commit:

# docker commit 5d jonaslejon/nginx-wp:version1

Det räcker att skriva exempelvis de första två tecken i container ID. Ovan exempel så skriver jag bara 5d.

WordPress installationwordpress

Nästa steg är att ladda hem och installera WordPress. Detta görs genom att vi ansluter till dockern som vi just installerade Nginx på:

# docker run -v /data/wordpress:/data/wordpress -p 80:80 -i -t jonaslejon/nginx-wp:version1 bash

Sedan installerar vi wget samt går vi till root-katalogen för webbservern vilket i mitt fall är enligt följande:

# apt-get -y install wget
# chown www-data /data/wordpress/
# cd /data/wordpress/
# wget http://sv.wordpress.org/wordpress-3.8.1-sv_SE.tar.gz
# tar xvfz wordpress-3.8.1-sv_SE.tar.gz
# mv wordpress/* .
# exit

Då var WordPress och Nginx installerat. Och glöm framförallt inte att göra en commit på ändringarna:

# docker ps -a
# docker commit 7e6b550faa50 jonaslejon/nginx-wp:version3

Installation av MySQL, MariaDB eller Percona Server

Här ska vi inte glömma att skapa MySQL dockern i en helt ny docker och inte fortsätta med föregående Nginx-docker.

# mkdir -p /data/mysql

Först skapar vi en gemensam katalog där filerna till databasen ska leva kvar. Sen kör vi igång en docker och delar katalogen:

# docker run -v /data/mysql:/data/mysql -p 3306:3306 -i -t ubuntu:13.10 /bin/bash
# apt-get -y install mysql-server
# chown ubuntu /data/mysql
# vi /etc/mysql/my.cnf
# service mysql start
# echo "create database wordpress"|mysql -plösenord
# echo "GRANT ALL PRIVILEGES ON wordpress.* TO 'wordpress'@'localhost' IDENTIFIED BY 'wplösenord'" | mysql -plösenord
# exit 
# docker ps -a 
# docker commit 1f9b38696a7f jonaslejon/mysql:version1

Ovan så ändrar du även i konfigg-filen /etc/mysql/my.cnf där datadir finns (jag gör det med vi). Ändra katalogen från /var/lib/mysql till /data/mysql/.

Jag skapar även ovan en ny databas med namnet wordpress samt en användare med namnet wordpress och lösenordet wplösenord.

Om allt sedan fungerar och du har gjort en commit så kan du testa denna docker med:

# docker run -v /data/mysql:/data/mysql -p 3306:3306 -i -t jonaslejon/mysql:version1 /usr/bin/mysqld_safe

Starta upp allt

Då var två stycken Docker-containers skapade. Vi ska nu starta upp dessa och hoppas på att allt går vägen. Skillnaden här är att vi anger -d så att containrarna läggs i bakgrunden:

# docker run -d -v /data/mysql:/data/mysql -p 3306:3306 -i -t jonaslejon/mysql:version1 /usr/bin/mysqld_safe
Det vi gör sedan är att titta med docker ps:
docker ps
Samt kontrollera loggarna från containern:
docker logs

Ser bra ut! Då ska vi starta upp webbservern Nginx:

# docker run -v /data/wordpress:/data/wordpress -p 80:80 -i -t jonaslejon/nginx-wp:version3 sh -c "service php5-fpm start && service nginx start"
Verifiera att allt körs med hjälp av docker ps-kommandot.

Avslutande anmärkningar

Nu behöver du bara konfigurera WordPress genom att surfa till localhost:80. Detta står även under PORTS när du kör docker ps.

IP-adressen som du behöver när du konfigurerar WordPress-installationen till MySQL-databasen kan du få ut genom att köra inspect på rätt container:

# docker inspect c6e0c1e4e5f0|grep -i ipaddress
 "IPAddress": "172.17.0.2",

Om du ansluter via Vagrant mot containrarna så måste du även konfigurera i Vagrantfile alternativt när du kör vagrant up på följande sätt:

# FORWARD_PORTS=80,3306 vagrant [up|reload]

Övrigt

  • Du behöver inte ha en delad /data-katalog som jag kör med. Men bra om du vill ha data som ska leva en längre tid.
  • Du kan även köra Nginx och MySQL på samma container.
  • Supervisord kan vara bra att använda för att starta upp och hålla koll på processer.
  • Det finns färdiga containers i det centrala docker-indexet. Sök genom kommandot docker search wordpress eller klicka här >
  • Det finns ett fiffigt sätt att automatiskt koppla ihop två containers genom att använda -link argumentet. Då läggs miljövariablar innehållandes port samt IP-nummer till automatiskt på följande sätt:

docker link

Gillar du detta blogginlägg? Donera gärna till min Bitcoin-adress nedan eller dela detta inlägg i sociala medier.

  • 13cxyC2sFvNfAAShcAaSs2YMW3Q4ygstD4

Nytt år med nya spännande utmaningar

Som sig bör så har jag haft en härlig semester med mycket skidåkning och är nu tillbaka till ”varmare” breddgrader. HittaRabatt tuffar på som tåget och efterfrågan på rabattkuponger är stor men något lägre efter julhandeln.

Jag har många ideéer och projekt som fortlöper samt har även tid för konsultverksamhet vilket är trevligt då andra kan dra fördel av min kompetens.

DevOps, IT-säkerhet samt Big Data är några av de områden som jag fokuserar på under 2014 och förhoppningsvis så ska jag även bli bättre på att blogga.

Blogbackupr köptes av entreprenören Mikael Falkvidd som kommer att köra vidare projektet (som jag tror mycket på).

Privat så fokuserar jag på Ironman Kalmar 2014 och har snart tränat i två år för den tävlingen: simma 3,8 km, cykla 18 mil och sedan springa 4,2 mil.

2014 bilden är CC christmasstockimages.com

Bild CC http://www.flickr.com/photos/lukechanchan/5311384779/

Vad är DevOps?

Du kanske undrar vad DevOps är för något som jag bloggat om? Förutom att det är ett mode-ord och en rörelse som är på tapeten så betyder det också så klart något.

Enklast förklarat är det ett ord som beskriver automatisering av tre olika närbesläktade verksamheter, nämligen:

  • Utveckling
  • Drift
  • Test (QA)

Och tittar vi mer konkret hur vi kan beskriva DevOps så handlar det om att få mer gjort med mindre mankraft. Oftast genom att skriva kod för automatisk deployment och tester och de verktyg som används är oftast:

Men inte att glömma viktiga verktyg såsom:

Med ovan smörgårsbord av verktyg så går det att bygga underbara lösningar som gör utrullning av versionshanterad kod snyggt, snabbt och smidigt.

DevOps omfattar även continuous integration (CI) och verktyg såsom Jenkins.

Favorit ”reactions” Tumblr just nu som är relaterad till detta ämne:

Funderingar, kommentarer? Lämna gärna en kommentar eller kontakta mig.

Docker är kittet i DevOps

Docker

Då och då dyker det upp mjukvara som underlättar livet avsevärt, då man nästan utropar Heureka! När jag först lärde mig använda Fabric så tycke jag att detta var ju guld värt: Att slippa göra samma sak manuellt på flera servrar. DevOps-filosofin i ett nötskal

Men! Nu tog jag mig tid och försökte lära mig Docker. Docker har tagit det hela lite längre och isolerar filer samt processer från underliggande operativsystem samt innehar versionshantering. Vad innebär detta då?

Jo, för sådana som mig som har beroenden långt utanför vad vanliga webbhotell kan leverera såsom Redis, Sphinx och Memcache så är Docker en mjukvara som löser detta.

Man kan kort och gott säga att Docker är ett operativsystem i operativsystemet. Lite som Xen eller Vmware men mycket ”lättare”.

I detta underliggande operativsystem så utgår du från en spegelbild som fungerar som bas och allt du lägger till får en ny revision. Detta gör exempelvis om du vill flytta en webbsajt med Redis, MySQL och Sphinx Search från en server till en annan så behöver du enbart flytta det som ändrats från spegelbilden.

Docker är så klart öppen källkod och helt gratis att använda. Och inte nog med det så är det ett MeetUp om några veckor i Stockholm om just DevOps och Docker med talare från bl.a. Spotify:

DevOps med Python Fabric

DevOpsOm du har precis som mig många servrar som är utspridda på flertalet leverantörer så finns det några smarta hjälpmedel för att underlätta administration och deployment av ny kod. Ett av dessa hjälpmedel heter Fabric och är snarlikt med Capistrano för Ruby.

På en Ubuntu-kärra så är det lättast att bara köra apt-get install fabric så får du prylarna du behöver på ett nafs (alternativt pip install fabric).

Testa sedan med:

$ fab

Fatal error: Couldn't find any fabfiles!

Remember that -f can be used to specify fabfile path, and use -h for help.

Aborting.

Det finns olika sätt att sedan använda fabric för att exekvera kommandon på flertalet servrar. De vanliga är att man skapar fabfiles eller bakar in det man vill göra direkt i sin Python-kod efter en import fabric.

Fabric i Python via import fabric

Rätt enkelt och behövs inte så många rader kod. Vår kod ser ut enligt nedan och startas med python kodnamn.py:

#!env python
from fabric.api import run,env,hosts,execute

env.key_filename = "/home/jonasl/jonasl.pem"
env.user = "ubuntu"

@hosts(['79.125.115.128'])
def uname():
  return run("uname -a")

execute(uname)

Ovan kod beskriver först vilken nyckelfil (pem) vi använder. Precis samma sak som att köra ssh -i jonasl.pem. Och env.user berättar vilken användare vi loggar in med.

Sen använder vi en rolig sak i Python som kallas för dekorator (decorator) och den sätter vilken IP-adress vi ska ansluta mot. Denna dekorator behövs inte i nästa exempel som skiljer sig lite.

Fabric direkt via kommandoskal och fabfile

När man använder kommandot fab så läser Fabric direkt en fil som heter fabfile.py i samma katalog som man står i och där kan man placera kommandon såsom ovan uname som ska köras mot olika servrar. Först skapar vi fabfile.py som ser ut så här:

#!env python
from fabric.api import run,env,hosts,execute

env.key_filename = "/home/jonasl/jonasl.pem"
env.user = "ubuntu"

def uname():
  return run("uname -a")

Sen kör vi bara fab -H ip-nummer uname på följande sätt:

$ fab -H 79.125.115.128 uname
[79.125.115.128] Executing task 'uname'
[79.125.115.128] run: uname -a
[79.125.115.128] out: Linux syslog 3.2.0-53-virtual #81-Ubuntu SMP Thu Aug 22 21:21:26 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
Done.
Disconnecting from 79.125.115.128... done.
$

I nästa avsnitt ska jag gå igenom lite mer hur man kan använda olika server-roller för att skjuta utkod via git.