Wednesday, June 6, 2018

Multiple PHP version with Apache on CentOS 7

Step 1
Install all the necessary repos and packages big thanks to https://rpms.remirepo.net/wizard/
the following commands assume you already sudo su - or you will have to add sudo to each of the commands:
yum install httpd -y
yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
yum install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
yum install yum-utils -y
yum install php56 -y
yum install php72 -y
yum install php56-php-fpm -y
yum install php72-php-fpm -y
stop both fpm servers
systemctl stop php56-php-fpm
systemctl stop php72-php-fpm
by default it listens on 127.0.0.1 port 9000, make them listen on different ports
sed -i 's/:9000/:9056/' /etc/opt/remi/php56/php-fpm.d/www.conf
sed -i 's/:9000/:9072/' /etc/opt/remi/php72/php-fpm.d/www.conf
now two different version of fpm can be started on different ports
systemctl start php72-php-fpm
systemctl start php56-php-fpm


Step 2
make script wrapper to call php56-cgi and php72-cgi

cat > /var/www/cgi-bin/php56.fcgi << EOF
#!/bin/bash
exec /bin/php56-cgi
EOF

cat > /var/www/cgi-bin/php72.fcgi << EOF
#!/bin/bash
exec /bin/php72-cgi
EOF
make them executable by apache
sudo chmod 755 /var/www/cgi-bin/php56.fcgi
sudo chmod 755 /var/www/cgi-bin/php72.fcgi

create php configuration for apache. by default it runs php56-fcgi handler

cat > /etc/httpd/conf.d/php.conf << EOF
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
AddHandler php56-fcgi .php
Action php56-fcgi /cgi-bin/php56.fcgi
Action php72-fcgi /cgi-bin/php72.fcgi

<Directory /var/www/html/php56>
    DirectoryIndex index.php
    AllowOverride all
    Require all granted
</Directory>
<Directory /var/www/html/php72>
    DirectoryIndex index.php
    AllowOverride all
    Require all granted
</Directory>
EOF
Step 2 - Alternative
Remi Collet pointed out this could be replaced by SetHandler with httpd 2.4
cat > /etc/httpd/conf.d/php.conf << EOF
<Directory /var/www/html/php56>
    SetHandler "proxy:fcgi://127.0.0.1:9056" 
    DirectoryIndex index.php
    AllowOverride all
    Require all granted
</Directory>
<Directory /var/www/html/php72>
    SetHandler "proxy:fcgi://127.0.0.1:9072"
    DirectoryIndex index.php
    AllowOverride all
    Require all granted
</Directory>
EOF

  SetHandler "proxy:fcgi://127.0.0.1:9072"  

Step 3
make test pages, create .htaccess to use php72-fcgi
mkdir -p /var/www/html/php56
mkdir -p /var/www/html/php72
echo "" > /var/www/html/php56/index.php
echo "" > /var/www/html/php72/index.php
echo "AddHandler php72-fcgi .php" > /var/www/html/php72/.htaccess

Now you should be able to test it

If you want to startup these instance automatically after server reboot. That's all, you are ready to go!

sudo systemctl enable httpd
sudo systemctl enable php56-php-fpm
sudo systemctl enable php72-php-fpm

Monday, February 19, 2018

DataStax Enterprise Cassandra & supervisord Integration

  • supervisor is in the epel repository.
  • python-setuptools is optional only if superlance is to be installed, superlance is an monitoring alert built for supervisor.
    yum -y install epel-release
    yum install -y supervisor python-setuptools
    easy_install superlance
    
The following creates the configuration for one node of dse cassandra. Please note cassandra is started with -f because any process to be controlled by supervisor needs to be running in the foreground.
cat >> /etc/supervisord.d/dse1.ini << EOF
[program:dse]
command=/opt/dse/bin/dse cassandra -f               ; the program (relative uses PATH, can take args)
process_name=%(program_name)s  ; process_name expr (default %(program_name)s)
numprocs=1                     ; number of processes copies to start (def 1)
directory=/opt/dse/            ; directory to cwd to before exec (def no cwd)
priority=1                     ; the relative start priority (default 999);
autorestart=true              ; retstart at unexpected quit (default: true)
startsecs=30                    ; number of secs prog must stay running (def. 1)
;startretries=3                ; max # of serial start failures (default 3)
;exitcodes=0,2                 ; 'expected' exit codes for process (default 0,2)
;stopsignal=QUIT               ; signal used to kill process (default TERM)
;stopwaitsecs=10               ; max num secs to wait b4 SIGKILL (default 10)
user=cassandra                 ; setuid to this UNIX account to run the program
redirect_stderr=true          ; redirect proc stderr to stdout (default false)
stdout_logfile=/var/log/dse/%(program_name)s-stdout.log        ; stdout log path, NONE for none; default AUTO
EOF
supervisor's configuration file is in /etc/supervisord.conf, the following are a minimal configuration to uncomment. inet_http_server section is to enable the web admin user interface, this should be either disabled in production or enable user and password security. The include section will take all .ini configuration under /etc/supervisord.d/, to allow application team/user to manage these configuration, ownership or permission should be assigned properly in this directory or configuration files.
[unix_http_server]
file=/var/run/supervisor/supervisor.sock   ; (the path to the socket file)

[inet_http_server]         ; inet (TCP) server disabled by default
port=0.0.0.0:9001        ; (ip_address:port specifier, *:port for all iface)

[supervisorctl]
serverurl=unix:///var/run/supervisor/supervisor.sock ; use a unix:// URL  for a unix socket

[include]
files = supervisord.d/*.ini
One of the potential issue running DSE by supervisor is that supervisor inherit the ulimits of the process from systemctl regardless what the system ulimit sets to in /etc/security/limits.*. supervisor offers the following configuration options but it does not cover other parameters such as memlick, stack, rss and etc. this could create issues such as when using DSE's dsefs. minfds=100000 ; (min. avail startup file descriptors;default 1024) minprocs=32768 ; (min. avail process descriptors;default 200)

The workaround of this issue, we have to adjust the systemctl limits by the following

mkdir -p /etc/systemd/system/supervisord.service.d/
cat > /etc/systemd/system/supervisord.service.d/filelimit.conf << EOF
[Service]
LimitNOFILE=1048576
LimitNPROC=600000
LimitMEMLOCK=infinity
LimitFSIZE=infinity
LimitDATA=infinity
LimitRSS=infinity
LimitSTACK=infinity
LimitCPU= infinity
LimitAS=infinity
LimitLOCKS=infinity
LimitSIGPENDING=infinity
LimitMSGQUEUE=infinity
EOF

systemctl daemon-reload
systemd-delta --type=extended
restart supervisor:
systemctl restart supervisor
user with necessary sudo access could control DSE by supervisor:
sudo supervisorctl status
sudo supervisorctl start dse
sudo supervisorctl stop dse
sudo supervisorctl restart dse
Unix admin have to configure the following: allow permission to service account owner to manage /etc/supervisord.d/
chmod -R svc_cassandra:fleet /etc/supervisord.d
provide sudo access in /etc/sudoers.d/cassandra
svc_cassandra           ALL=NOPASSWD: /usr/bin/systemctl * supervisord
svc_cassandra           ALL=NOPASSWD: /usr/bin/supervisorctl *

Tuesday, January 16, 2018

Docker Registry on Cloudian S3

This guide shows how to create a local docker registry on internal Cloudian S3 Storage.

Create a s3-registry-config.yaml config file for docker registry such as the sample config file below.

  • region, regionendpoint, v4auth, secure are critical values to be set exactly the same as the sample for it to work with Element's internal Cloudian S3.
  • By setting rootdirectory to / it will store the data under the following path in S3 bucket: $bucket/docker/registry/v2/
  • version: 0.1
    log:
      fields:
        service: registry
    storage:
      s3:
        accesskey: **************************
        secretkey: **************************************************************
        region: region1
        regionendpoint: http://s3internal.servername
        bucket: dockerreg
        rootdirectory: /
        v4auth: true
        secure: false
      cache:
        blobdescriptor: inmemory
    http:
      addr: :5000
      headers:
        X-Content-Type-Options: [nosniff]
    health:
      storagedriver:
        enabled: true
        interval: 10s
        threshold: 3
    

    start a registry container, note please run the following command from the path where the above configuration file located.

    docker run -d -p 5000:5000 --restart=always --name registry -v `pwd`/s3-registry-config.yaml:/etc/docker/registry/config.yml registry:2
    

    test the local docker registry

    # Pull the ubuntu:16.04 image from Docker Hub.
    docker pull ubuntu:16.04
    
    # Tag the image as localhost:5000/my-ubuntu. This creates an additional tag for the existing image. When the 
    # first part of the tag is a hostname and port, Docker interprets this as the location of a registry, when 
    # pushing.
    docker tag ubuntu:16.04 localhost:5000/my-ubuntu
    
    # Push the image to the local registry running at localhost:5000:
    docker push localhost:5000/my-ubuntu
    
    # Remove the locally-cached ubuntu:16.04 and localhost:5000/my-ubuntu images, so that you can test pulling the # image from your registry. This does not remove the localhost:5000/my-ubuntu image from your registry.
    docker image remove ubuntu:16.04
    docker image remove localhost:5000/my-ubuntu
    
    # Pull the localhost:5000/my-ubuntu image from your local registry.
    docker pull localhost:5000/my-ubuntu
    
    # Validate image data are in the local registry
    aws s3 ls --recursive s3://dockerreg/ --endpoint-url http://s3internal.servername