Simple use and configuration of saltstack

Keywords: Nginx Apache JSON saltstack

1. Preface

saltstack is divided into master and slave, which can be used for cluster management

2. Environment

Serr2:172.25.69.2 (main)

Serr3:172.25.69.3 (from)

Serr4:172.25.69.4 (from)

3. Environmental settings

Main: Install saltstack-master, python-setproctitle.x86_64

From: Install salt-minion.noarch

Master: Open the service salt-master

From: Modify the location file / etc/salt/minion

         master: 172.25.69.2

Open the service salt-minion

Main: salt-key-L

Salt-key-A adds all keys

Salt-key-D deletes all keys

Test Connection

4. Installing Apache for Nodes

(1) Modify the main node configuration file

/etc/salt/master

 file_roots:
   base:
     - /srv/salt/

(2) Create apache directory in / srv/salt

(3) Write install.sls file

install-apache:
  pkg.installed:                                       #Default yum installation
    - pkgs:
      - httpd
  
  file.managed:
    - name: /etc/httpd/conf/httpd.conf                         #Target file
    - source: salt://apache/files/httpd.conf source file

  service.running:                                    #When a service starts, a reload is a reload
    - name: httpd
    - reload: true
    - watch:
      - file: install-apache

5. Install Nginx for nodes

(1) Create nginx directory and pkgs directory in / srv/salt

(2) sls files in nginx directory

#####install.sls

include:
  - pkgs.install
install-nginx:
  file.managed:
    - name: /mnt/nginx-1.15.8.tar.gz
    - source: salt://nginx/files/nginx-1.15.8.tar.gz
  
  cmd.run:
    - name: cd /mnt && tar zxf nginx-1.15.8.tar.gz && cd nginx-1.15.8 && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --prefix=/usr/local/nginx && make && make install
    - creates: /usr/local/nginx

######service.sls
include:
  - nginx.install

/usr/local/nginx/sbin/nginx:
  cmd.run:
    - creates: /usr/local/nginx/logs/nginx.pid

/usr/local/nginx/conf/nginx.conf:
  file.managed:
    - source: salt://nginx/files/nginx.conf


/usr/local/nginx/sbin/nginx -s reload:
  cmd.wait:
    - watch:
      - file: /usr/local/nginx/conf/nginx.conf

(3) sls files in pkgs directory

pkgs-install.sls

nginx-make:
  pkg.installed:
    - pkgs:
      - gcc
      - make
      - zlib-devel
      - pcre-devel

(4) Install and start nginx

(5) Settings modification using system D to manage nginx

Write nginx.service file in files directory under nginx directory

[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Modify the service.sls file to

include:
  - nginx.install


/usr/local/nginx/conf/nginx.conf:
  file.managed:
    - source: salt://nginx/files/nginx.conf


service-nginx:
  file.managed:
    - name: /usr/lib/systemd/system/nginx.service
    - source: salt://nginx/files/nginx.service

  service.running:
    - name: nginx
    - reload: True
    - watch:
      - file: /usr/local/nginx/conf/nginx.conf

6. Viewing and setting variables

(1) Variable setting method 1:

Server 3 minion configuration file

grains:

  roles:

    - apache

minion configuration file for server 4

grains:

   roles:

    - nginx

(2) Variable setting method 2:

Create a grain file in the / etc/salt directory

roles:

  - nginx

(3) Variable setting method 3:

my_grains.py

def my_grains():
     grains = {}
     grains['hello'] = 'world'
     grains['salt'] = 'stack'
     return grains

Sending Policy

Command: salt server 3 saltutil. sync_grains

(4) Variable setting method 4:

Modify the main node configuration file / etc/salt/master

pillar_roots:
  base:
    - /srv/pillar

Create directories

top.sls

base:
  '*':
    - web.vars

 vars.sls

{% if grains['fqdn'] == 'server3' %}
webserver: httpd
ip: 172.25.0.3
{% elif grains['fqdn'] == 'server4' %}
webserver: nginx
ip: 172.25.0.4
{% endif %}

wipe cache

Synchronize variable files and view variables

7. Installing keepalived to achieve high availability

(1) Environment

server3: 172.25.69.3(apache,keepalived(master))

server4: 172.25.69.4(nginx,keepalived(backup))

Implementing effect: Local host accesses keepalived virtual ip first by accessing server 3. When server 3 fails to shut down abnormally, virtual ip drifts to server 4.

(1)apache

install.sls

install-apache:
  pkg.installed:
    - pkgs:
      - httpd

  file.managed:
    - name: /etc/httpd/conf/httpd.conf
    - source: salt://apache/files/httpd.conf
    - template: jinja
    - context:
      port: 80

  service.running:
    - name: httpd
    - reload: true
    - watch:
      - file: install-apache

(2)nginx

Configuration as above

(3)keepalived

install.sls

install-keepalived:
  pkg.installed:
    - pkgs:
      - keepalived

  file.managed:
    - name: /etc/keepalived/keepalived.conf
    - source: salt://keepalived/files/keepalived.conf
    - template: jinja
    - context:
      STATE: {{ pillar['state'] }}
      VRID: {{ pillar['vrid'] }}
      PRIORITY: {{ pillar['priority'] }}

  service.running:
    - name: keepalived
    - watch:
      - file: install-keepalived

keepalived.conf

! Configuration File for keepalived

global_defs {
   notification_email {
        root@localhost
   }
   notification_email_from keepalived@localhost
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id LVS_DEVEL
}

vrrp_instance VI_1 {
    state {{ STATE }}
    interface eth0
    virtual_router_id {{ VRID }}
    priority {{ PRIORITY }}
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        172.25.69.69
    }
}

(4) Variables

top.sls

base:
  '*':
    - web.vars

var.sls

{% if grains['fqdn'] == 'server3' %}
ip: 172.25.0.3
state: MASTER
vrid: 100
priority: 100
{% elif grains['fqdn'] == 'server4' %}
ip: 172.25.0.4
state: BACKUP
vrid: 100
priority: 50
{% endif %}

(5) Overall

Command: salt'*'state. high state

(6) Final results

When keepalived of server 3 closes, vip will be transferred to server 4

8,topmaster syndic+master minion

(1) Environment

server2(syndic+master)

server3(minion)

server4(minion)

server5(topmaster)

Serr2: Install salt-syndic,salt-master

Serr3 installation: salt-minion

Serr4 installation: salt-minion

Serr5 installation: salt-master

(2) Setting up configuration files

Modify server 2 master configuration file

syndic_master: server5

Modify server 5 master configuration file

order_masters: True

Serr2 opens server-master

             server-syndic

Serr5 opens server-master

9,salt-ssh

(1) Preparation

Server 3 closes salt-minion

Serr2 Edit / etc/salt/roster, add

server3:

  host: 172.25.69.3

  user: root

  passwd: redhat

(2) Installing salt-ssh

Serr2 installation

(3) Testing

11,salt-api

(1) Preparation

Serr2 installs salt-api

Generate the key. / etc/pki/tls/private/

Generate certificates

(2) Create user saltapi and set password

(3) Modifying configuration files

/etc/salt/master.d/


[root@server2 master.d]# cat api.conf 
rest_cherrypy:
  port: 8000
  ssl_crt: /etc/pki/tls/certs/localhost.crt
  ssl_key: /etc/pki/tls/private/localhost.key


[root@server2 master.d]# cat auth.conf 
external_auth:
  pam:
    saltapi:
      - .*
      - '@wheel'
      - '@runner'
      - '@jobs'

(4) Testing

Command: curl-sSk https://localhost:8000/login-H'Accept: application/x-yaml'-d username=saltapi-d password=redhat-d eauth=pam

Command: curl-sSk https://localhost:8000-H'Accept: application/x-yaml'-H'X-Auth-Token: ff6fe100de92eceed 205812a88e49cb0b47799e9'-d client=local-d tgt='*-d fun=test.

saltapi.py

Provided by github

# -*- coding: utf-8 -*-

import urllib2,urllib
import time

try:
    import json
except ImportError:
    import simplejson as json

class SaltAPI(object):
    __token_id = ''
    def __init__(self,url,username,password):
        self.__url = url.rstrip('/')
        self.__user = username
        self.__password = password

    def token_id(self):
        ''' user login and get token id '''
        params = {'eauth': 'pam', 'username': self.__user, 'password': self.__password}
        encode = urllib.urlencode(params)
        obj = urllib.unquote(encode)
        content = self.postRequest(obj,prefix='/login')
	try:
            self.__token_id = content['return'][0]['token']
        except KeyError:
            raise KeyError

    def postRequest(self,obj,prefix='/'):
        url = self.__url + prefix
        headers = {'X-Auth-Token'   : self.__token_id}
        req = urllib2.Request(url, obj, headers)
        opener = urllib2.urlopen(req)
        content = json.loads(opener.read())
        return content

    def list_all_key(self):
        params = {'client': 'wheel', 'fun': 'key.list_all'}
        obj = urllib.urlencode(params)
        self.token_id()
        content = self.postRequest(obj)
        minions = content['return'][0]['data']['return']['minions']
        minions_pre = content['return'][0]['data']['return']['minions_pre']
        return minions,minions_pre

    def delete_key(self,node_name):
        params = {'client': 'wheel', 'fun': 'key.delete', 'match': node_name}
        obj = urllib.urlencode(params)
        self.token_id()
        content = self.postRequest(obj)
        ret = content['return'][0]['data']['success']
        return ret

    def accept_key(self,node_name):
        params = {'client': 'wheel', 'fun': 'key.accept', 'match': node_name}
        obj = urllib.urlencode(params)
        self.token_id()
        content = self.postRequest(obj)
        ret = content['return'][0]['data']['success']
        return ret

    def remote_noarg_execution(self,tgt,fun):
        ''' Execute commands without parameters '''
        params = {'client': 'local', 'tgt': tgt, 'fun': fun}
        obj = urllib.urlencode(params)
        self.token_id()
        content = self.postRequest(obj)
        ret = content['return'][0][tgt]
        return ret

    def remote_execution(self,tgt,fun,arg):
        ''' Command execution with parameters '''        
        params = {'client': 'local', 'tgt': tgt, 'fun': fun, 'arg': arg}
        obj = urllib.urlencode(params)
        self.token_id()
        content = self.postRequest(obj)
        ret = content['return'][0][tgt]
        return ret

    def target_remote_execution(self,tgt,fun,arg):
        ''' Use targeting for remote execution '''
        params = {'client': 'local', 'tgt': tgt, 'fun': fun, 'arg': arg, 'expr_form': 'nodegroup'}
        obj = urllib.urlencode(params)
        self.token_id()
        content = self.postRequest(obj)
        jid = content['return'][0]['jid']
        return jid

    def deploy(self,tgt,arg):
        ''' Module deployment '''
        params = {'client': 'local', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg}
        obj = urllib.urlencode(params)
        self.token_id()
        content = self.postRequest(obj)
        return content

    def async_deploy(self,tgt,arg):
        ''' Asynchronously send a command to connected minions '''
        params = {'client': 'local_async', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg}
        obj = urllib.urlencode(params)
        self.token_id()
        content = self.postRequest(obj)
        jid = content['return'][0]['jid']
        return jid

    def target_deploy(self,tgt,arg):
        ''' Based on the node group forms deployment '''
        params = {'client': 'local_async', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg, 'expr_form': 'nodegroup'}
        obj = urllib.urlencode(params)
        self.token_id()
        content = self.postRequest(obj)
        jid = content['return'][0]['jid']
        return jid

def main():
    sapi = SaltAPI(url='https://localhost:8000',username='saltapi',password='redhat')
    #sapi.token_id()
    print sapi.list_all_key()
    #sapi.delete_key('test-01')
    #sapi.accept_key('test-01')
    #sapi.deploy('server6','nginx.service')
    #print sapi.remote_noarg_execution('test-01','grains.items')

if __name__ == '__main__':
    main()

 

Posted by ashbai on Sun, 18 Aug 2019 20:30:53 -0700