Setup Systemd Service on Ubuntu 16.04

$ sudo vim /etc/systemd/system/myservice.service
[Unit]
Description=Run the service

[Service]
User=ubuntu
# change the workspace
WorkingDirectory=/usr/local/src

#path to executable. 
#executable is a bash script which calls jar file
ExecStart=/usr/local/src/somescript

SuccessExitStatus=143
TimeoutStopSec=10
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
$ sudo vim /usr/local/src/somescript
#!/bin/sh

java -jar /some/file.jar
sudo systemctl daemon-reload
sudo systemctl enable myservice.service
sudo systemctl start myservice
sudo systemctl status myservice

 

Setup Simple Ruby on Rails App On Ubuntu 16.04 From Scratch

Rails is one of the most popular ruby framework out there. And now, I want to try to run the simple app on Ubuntu 16.04 machine. it’s for testing purpose.

First, update the system and install essential dependencies:

$ sudo apt-get update
$ sudo apt-get build-essential curl sudo vim

Install nodejs:

$ curl -sL https://deb.nodesource.com/setup_9.x | sudo -E bash -
$ apt-get install nodejs

Create a dedicated user for the app, for example, ubuntu user. And this also make the ubuntu user with sudo privilege and run the command without password. Which is useful to run command that needs sudo privilege in the next steps.

$ useradd ubuntu -m
$ echo 'ubuntu ALL=(root) NOPASSWD: ALL' >> /etc/sudoers

swith to ubuntu user and install GPG keys for install rvm:

$ su - ubuntu
ubuntu~$ gpg --keyserver hkp://keys.gnupg.net \ --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 \ 7D2BAF1CF37B13E2069D6956105BD0E739499BDB

Download and install rvm:

ubuntu~$ \curl -sSL https://get.rvm.io | bash -s stable

Install ruby interpreter with version 2.5.1, you might wanna change it with your preferable version:

ubuntu~$ source ~/.rvm/scripts/rvm
ubuntu~$ rvm install 2.5.1
ubuntu~$ rvm use 2.5.1 --default

Install rails with gem, and create new app without writing the Gemfile. Why? because everytime I create new app, I ended up facing errors with dependencies in Gemfile. So, it safe to setup new app without the Gemfile, we’ll create it manually later.

ubuntu~$ gem install rails
ubuntu~$ rails new app --skip-gemfile

Create the Gemfile:

ubuntu~$ touch ~/app/Gemfile
ubuntu~$ vim ~/app/Gemfile

Gemfile, fill these dependencies below into the file, save and exit:

source 'https://rubygems.org'
gem 'rails', '~> 5.2.1'
gem 'bootsnap', '~> 1.3.2'
gem 'tzinfo-data', '~> 1.2018.5'
gem 'listen', '~> 3.1.5'
gem 'sqlite3'

Now, install all the gems with bundle:

ubuntu~$ cd ~/app
ubuntu app~$ bundle install

Try run the rails:

ubuntu app~$ rails server -b 0.0.0.0

 

Run containerized python app in kubernetes

Run containerized python app in kubernetes

First of all we need a Docker image that will be run inside the kubernetes cluster. So I assumed that we already have a kubernetes cluster. So the next we do is to build the docker image or you can use your docker image yourself.

But in this tutorial, I will show you how to run the containerized python app with my version from the start.

What we need

These applications should be installed on your local machine before get started. In my case, I use my remote server with ubuntu 16.04 installed.

1. Docker
2. Kubernetes

Setup Kubernetes on Ubuntu 16.04

Build docker image

Let’s begin with clone of of my repo that contains Dockerfile to build the image:

$ git clone https://github.com/muffat/docker-images.git
$ cd docker-images/simple-python-app/
~/docker-images/simple-python-app$ sudo docker build -t simple .

Wait until the process successfully built. And then you’ll see a new docker image when you type this command:

$ docker images

Push docker image to repository (docker hub)

Before pushing the image to docker hub, we need to tag the successfully built image.

$ docker tag fbd064597ae4 cerpin/simple:1.0

Push the image

$ docker push cerpin/simple
The push refers to a repository [docker.io/cerpin/simple]
bc69ee44ef1a: Pushed 
7957c9ab59bb: Pushed 
2366fc011ccb: Pushed 
b18f9eea2de6: Pushed 
6213b3fcd974: Pushed 
fa767832af66: Pushed 
bcff331e13e3: Mounted from cerpin/test 
2166dba7c95b: Mounted from cerpin/test 
5e95929b2798: Mounted from cerpin/test 
c2af38e6b250: Mounted from cerpin/test 
0a42ee6ceccb: Mounted from cerpin/test

After it pushed. You will have the docker image in the repository and ready to use it:

cerpin/simple:1.0

Run the image in kubernetes

First of all, I’m not a big fan of kubectl command, so I usually make a symlink to create the shorter version of kubectl:

$ sudo ln -s /usr/bin/kubectl /usr/bin/cap

Run the docker image in kubernetes

$ cap run simple --image=cerpin/simple:1.0

Then the container will be created. Just wait a moment until the state becomes Running

$ cap get pods
simple-79d85db8b9-466kd 1/1 Running 0 26m

After it’s ready, expose the service with port 5002 to become LoadBalancer. So the service will be accessible from the outside world

$ cap expose deployment simple --type=LoadBalancer --port=5002

Check the service that has been exposed:

$ cap get services
simple LoadBalancer 10.105.115.251 <pending> 5002:31969/TCP 21m

You will see that the service will have forwarded port to 31969 from 5002.

If you open up the browser and navigate to http://external IP:31969, you’ll see the app is running.

Or, just use a curl command instead:

$ curl http://167.xxx.xxx.xxx:31969
{
"message": "welcome", 
"status": "ok"
}

Setup Kubernetes on Ubuntu 16.04

Summary

This setup is supposedly to install the kubernetes on ubuntu machine with version 16.04 (64bit). I did this in the cloud and have worked perfectly.

# whoami && pwd
root
/root
# apt-get update
# apt-get install -y apt-transport-https
# curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
# echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" > /etc/apt/sources.list.d/kubernetes.list
# apt-get update -y
# apt install docker.io
# apt-get install -y kubelet kubeadm kubernetes-cni

Check the swaps, if there any, swith them off

# /proc/swaps

Init kubernetes for the first time using kubeadm:

# kubeadm init --pod-network-cidr=192.168.0.0/16 --apiserver-advertise-address=<private IP>

*Note: Change <private IP> to <public IP>, if you run the kubernetes master on single node and wish to publicly open.

# cp /etc/kubernetes/admin.conf $HOME/
# export KUBECONFIG=$HOME/admin.conf
# echo "export KUBECONFIG=$HOME/admin.conf" | tee -a ~/.bashrc

Check pods status, wait until all running

# kubectl get pods --all-namespaces

When their status are RUNNING, moving forward install the network/flannel. Please choose between these two below, I prefer to use the calico one (the second).

# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/k8s-manifests/kube-flannel-rbac.yml

# or

# kubectl apply -f https://docs.projectcalico.org/v2.6/getting-started/kubernetes/installation/hosted/kubeadm/1.6/calico.yaml

Continue to taint the nodes:

# kubectl taint nodes --all node-role.kubernetes.io/master-

Install kubernetes dashboard

# kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml

Create user dashboard

create-user.yml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kube-system

create-role.yml

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kube-system
# kubectl create -f create-user.yml
# kubectl create -f create-role.yml
# kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')

How to set the kubernetes dashboard to publicly accessible with public IP

Read this : https://github.com/kubernetes/dashboard/wiki/Accessing-Dashboard—1.7.X-and-above

References

Setup python app in centos from scratch (centos 6.9+uwsgi+nginx+flask+mysql)

Initial setup

$ sudo yum update
$ sudo yum install epel-release
$ sudo yum groupinstall "Development tools"
$ sudo yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel telnet htop
$ sudo yum install python-devel python-virtualenv
$ sudo yum install mysql-connector-python mysql-devel mysql-server

Install Python

Download and install Python : https://www.python.org/

./configure && make && make altinstall

Install uWSGI

$ wget https://bootstrap.pypa.io/get-pip.py
$ which python2.7
$ sudo /usr/local/bin/python2.7 get-pip.py
$ which pip2.7
$ sudo /usr/local/bin/pip2.7 install uWSGI
$ which uwsgi
$ uwsgi --version

Setup vassels

$ sudo mkdir -p /etc/uwsgi/vassels

Setup Emperor service

$ sudo vim /etc/init.d/emperor
#!/bin/sh
# chkconfig: 2345 99 10
# Description: Starts and stops the emperor-uwsgi
# See how we were called.

RUNEMPEROR="/usr/local/bin/uwsgi --emperor=/etc/uwsgi/vassels"

PIDFILE=/var/run/emperor-uwsgi.pid
LOGFILE=/var/log/uwsgi/emperor.log

start() {
  if [ -f /var/run/$PIDNAME ] && kill -0 $(cat /var/run/$PIDNAME); then
    echo 'Service emperor-uwsgi already running' >&2
    return 1
  fi
  echo 'Starting Emperor...' >&2
  local CMD="$RUNEMPEROR &> \"$LOGFILE\" & echo $!"
  su -c "$CMD" > "$PIDFILE"
  echo 'Service started' >&2
}

stop() {
  if [ ! -f "$PIDFILE" ] || ! kill -0 $(cat "$PIDFILE"); then
    echo 'Service emperor-uwsgi not running' >&2
    return 1
  fi
  echo 'Stopping emperor-uwsgi' >&2
  kill -7 $(cat "$PIDFILE") && rm -f "$PIDFILE"
  echo 'Service stopped' >&2
}

status() {
    if [ ! -f "$PIDFILE" ]; then
	echo "Emperor is not running." >&2
	return 1
    else
    	echo "Emperor (pid  `cat ${PIDFILE}`) is running..."
    	ps -ef |grep `cat $PIDFILE`| grep -v grep
    fi
}

case "$1" in
start)
      start
      ;;
stop)
      stop
      ;;
status)
      status
      ;;
restart)
      stop
      start
      ;;
*)
    echo "Usage: emperor {start|stop|restart}"
    exit 1
esac

 Setup app user & environment

$ useradd foobar
$ usermod -md /srv/foobar foobar
$ chmod 755 /srv/foobar
$ sudo su - foobar
foobar@local~$ virtualenv --python=python2.7 ~/venv
foobar@local~$ mkdir www
foobar@local~$ mkdir logs
foobar@local~$ touch logs/uwsgi.log
foobar@local~$ touch uwsgi.ini
foobar@local~$ echo "source ~/venv/bin/activate" >> ~/.bashrc
foobar@local~$ source ~/venv/bin/activate
(venv)foobar@local~$ vim uwsgi.ini
[uwsgi]
master = true
processes = 2
socket = /tmp/foobar.sock

chdir = /srv/foobar/www
virtualenv = /srv/foobar/venv
module = app:app

uid = foobar
chown-socket = foobar:nginx
chmod-socket = 660
vacuum = true

die-on-term = true
python-autoreload = 3
py-autoreload = 1
logger = file:/srv/foobar/logs/uwsgi.log

Exit from foobar user & create uwsgi symlink

(venv)foobar@local~$ exit
$ sudo ln -s /srv/foobar/uwsgi.ini /etc/uwsgi/vassels/foobar.ini

Start emperor service & setup set the startup

$ sudo service emperor start
$ sudo chkconfig emperor on