Monday, February 28, 2022

ASSIGNMENTS: Docker Network Part 2 (Using Host Network)


Step 1: Download required images

docker pull ramansharma95/webapp
docker pull ramansharma95/mysql

Step 2: Create a webapp container with network as host and DO NOT DO a port forwarding on port number 80 as per custom network cause this assignment is run on host network.

docker container run -it --name web --network host -d ramansharma95/webapp

Go to browser and check that you are able to see the default web page. localhost:80

Step 3: Go inside the container (web) and check the code for index.php cause you will need to edit it a little.

docker exec -it web bash

vi /var/www/html/index.php

edit the username from db to host ip address (192.168.33.10).
# you will find that in the index.php, it has connection configs to connect to a server named 'db' but need to edit to host ip address cause its on the same network and also the required username and password to enter that server.

Step 4:- Create a db container with network defined (note this does not require port forwarding)

docker container run -it --name db --network host -d ramansharma95/mysql

Step 5:- Go inside the container (db).

docker exec -it db bash

5.2 connect to mysql with username root and password whizlabs

mysql -uroot -pwhizlabs

5.3 Create a database company

show databases;

create database company;

show databases;

5.4 Create a table employee with name and mobile field.

use company;

create table employee ( name varchar(30), mobile varchar(30) );

5.5 Show all the records in this table

select * from employee;

Step 6: Go to browser and add some employees details in the webpage and check again records in employee table, it should have those records added.

Step 7: Show all the records in this table.

select * from employee;




Docker Storage with Examples



SUMMARY:
A) WHAT IS STORAGE AND THE TYPES
B) EXAMPLES FOR NON-PERSISTENT DATA
C) EXAMPLES FOR PERSISTENT DATA

 Docker Storage

       To keep data for the container is called container's storage. 

       Docker storage is only available on Linux.


Types of Storage

Non Persistent 

      In this type of storage, the data will be lost if the container is deleted.

tmpfs

In this file system, the data will be stored in memory and it is only available during the container's lifetime, which means if the container is stopped or deleted the data will be lost. It is more suitable for the in-memory calculation.

 

Persistent

      In this type of storage, the data will be persisted even though the container gets deleted.

Docker Volume

   It is the storage that is maintained by the docker daemon in the docker area.. The default storage location is /var/lib/docker/volumes folder.

Bind Mount

  It is the storage that is managed by the admin of the system. It is a file or directory which is maintained on the host machine.

 


Docker Volume
It is the storage that is maintained by the docker daemon in the docker area.. The default storage location is /var/lib/docker/volumes folder

Docker volume Commands:

create

Create a volume

inspect

Display detailed information on one or more volumes

ls

List volumes

prune

Remove all unused local volumes

rm

Remove one or more volumes


Bind Mount
It is the storage that is managed by the admin of the system. It is a file or directory which is maintained on the host machine. It is having fewer features as compared to docker volume and it does not have any formal commands to manage these volumes by docker. You can use -v or --mount option to mount a directory of your host machine to the container


Example of Non-Persistent Storage:

Example 1:-

Step 1: Create a container using ubuntu docker image

         docker container run -it --name tmpcontainer -d ubuntu

Step 2: Go inside the container

         docker exec -it tmpcontainer bash

Step 3: In this container, create a directory call test and store some files into it.

  •             mkdir test
  •       cd test
  •       touch file1 file2 file3 file4
  •       ls

Step 4:  Stop the container.

            docker stop tmpcontainer

Step 5:  Start the container and check the test director still persist with all its files.

  •              docker start tmpcontainer
  •       docker exec -it tmpcontainer bash
  •       ls  test

Step 6: Delete the container and think is there any way to get your test directory again.

            docker rm -f tmpcontainer

            No there is no way to get back the test directory data, because the container is deleted so storage in this container was non-persistent.


Example 2:- (tmpfs)

Step 1: Create a container using ubuntu docker image.

         docker container run -it --name tmpcontainer --mount type=tmps,destination=/test -d ubuntu

Step 2: Go inside the container

         docker exec -it tmpcontainer bash

Step 3: In this container, create a directory call test and store some files into it.

  •     cd test
  •     touch file1 file2 file3 file4
  •     ls

Step 4:  Stop the container.

            docker stop tmpcontainer

Step 5:  Start the container and check the test director still persist with all its files or not. The files should be removed means you will not get any data inside test folder..

             docker start tmpcontainer
             docker exec -it tmpcontainer bash
             ls  test

Step 6: Delete the container and think is there any way to get your test directory again.

            docker rm -f tmpcontainer

            No there is no way to get back the test directory data, because the container is deleted so storage in this container was non-persistent.




Example 3:- (tmps with tmpfs-mode)

Create a container with tmpfs and change the permission of destination folder.

    docker container run -it --name c1 --mount type=tmpfs,destination=/tmp1,tmpfs-mode=1700 -d ubuntu




Example of Persistence Storage

Example 1:- (docker volume)

To delete all unused docker volumes:
docker volume prune

Step 1: To create a docker volume (demo-vol)

docker volume create demo-vol

Step 2: List all docker volumes

docker volume ls

Step 3: By default the driver is local and path for this docker volume is /var/lib/docker/volume.

ls /var/lib/docker/volumes/demo-vol/_data

Step 4: Run a container which points its /app directory to demo-vol

docker container run -it --name c1 --mount source=demo-vol,destination=/app -d ubuntu

Step 5: Go inside the container

docker exec -it c1 bash

Step 6: Create some files under /app directory

cd app

touch file1 file2 file3 file4

exit

Step 7: Check these files are available under demo-volume's directory

ls /var/lib/docker/volumes/demo-vol/_data

Step 8: Delete file4 from _data directory and check in c1 container's /app directory, file4 should not be available under this directory.


rm /var/lib/docker/volumes/demo-vol/_data/file4

docker exec -it c1 bash

ls /app

Step 9: Add a new file file5 in-app directory of the container and check this file should be available in demo-volume's data directory.

cd app

touch file5

exit

ls /var/lib/docker/volumes/demo-vol/_data

Step 10: Delete container c1.

docker rm -f c1

Step 11: Make sure your demo-vol data is not deleted.

ls /var/lib/docker/volumes/demo-vol/_data

Step 12: Create a new container and attach demo-vol to that container's /demo directory.

docker container run -it --name c2 --mount source=demo-vol,destination=/demo -d centos

Step 13: Check in the container's demo directory whether all these files exist or not. 

docker exec -it c2 bash

ls demo

Step 14: Delete the volume. Deletion of volume will delete the data as well.

docker rm -f c2

docker volume rm demo-vol

Note: You can use -v option instead of --mount with docker volume to mount a volume eg.

docker container run -it --name c3 -v demo-vol:/demo -d centos

Note: You can also refer to an existing directory of containers that points to docker volume.

docker container run -it --name c3 -v demo-vol:/root -d centos

In the above example, root directory's all files will be stored under demo-vol's data directory.



Example 2:- (Bind Mount)

Step 1: Create a directory (/home/vagrant/myfiles) that you want to map with the container's target directory

mkdir /home/vagrant/myfiles

Step 2: Run a container which maps myfiles directory to container's /app1 directory.


docker container run -it --name bindmountcontainer -v /home/vagrant/myfiles:/app1 -d ubuntu

OR

docker container run -it --name bindmountcontainer --mount type=bind,source=/home/vagrant/myfiles,target=/app1 -d ubuntu

Step 3: Go inside the container and add some files in app1 directory

docker exec -it bindmountcontainer bash

cd app1

touch file1 file2 file3 file4

exit

Step 4: Go to myfiles directory and find all the files that exist in this folder or not.

ls myfiles





ASSIGNMENTS: Docker Volume


 

ASSIGNMENT 1:-

1. Create a docker apache image using Dockerfile.

 2. Create a deploy-vol docker volume.

 3. Run a container using docker apacheimg with port forwarding 80:80 and map /var/www/html folder to deploy-vol.

4. Check default apache page is accessible on the browser.

5. Copy/Create a test.html file under /var/lib/docker/volumes/deploy-vol/_data

6. Check on the browser that you are able to access this webpage (test.html)

7. Go inside the container and create a file newtest.html under /var/www/html and verify that you are able to access it with the browser.


0. mkdir dockvolassignment
0.1 cd dockvolassignment

1. vi Dockerfile

1.2 in Dockerfile:
FROM ubuntu
#from is getting the base image  

ARG DEBIAN_FRONTEND=noninteractive
#noninteractive for automation so it does not ask questions such as geographical..

RUN apt-get update
#run is adding instruction on the instruction layer

RUN apt-get -y install apache2

ADD . /var/www/html
#add is copy the file from host machine to docker image folder

ENTRYPOINT apachectl -D FOREGROUND
#entrypoint whenever docker image is used in a container, some commands need to be executed automatically

ENV name DEVOPS
#environment variable is used on the global level

1.3 docker build . -t apacheimg

2. docker volume create deploy-vol

3. docker container run --name assignment1 -v deploy-vol:/var/www/html -dit -p 80:80 apacheimg

4. curl localhost

5. echo "<h1> Welcome to test.html page! </h1>" > /var/lib/docker/volumes/deploy-vol/_data/test.html

6. curl localhost/test.html

7. docker exec -it assignment1 bash

7.2 in container:

echo "<h1> This is newtest page and NOT test page! </h1>" > /var/www/html/newtest.html

7.3 exit container:

exit

7.4 curl localhost/newtest.html


ASSIGNMENT 2:-

1. Attach a docker volume to multiple containers and add or modify the files in any of these containers and check that the changes are getting reflected in all the containers or not.

2. Point #1 is to be repeated for Bind Mount

3. Delete the Bind mount directory which is mapped to a container's destination directory and check the destination behavior means try to create some file or list the files on the destination folder.

4. Continue to Point 3, you may get some error that the source directory does not exist. Create source directory again and check the destination folder and find out whether you are able to create new files in this folder or not.


ANSWERS:
1. yes

2. yes

3. for bind mount: 
touch: cannot touch '/app1/devops3fromc3.txt': No such file or directory
3.2 for volume (means prune the docker volume):

4. for bind mount: 
touch: cannot touch '/app1/devops3fromc3.txt': No such file or directory (but if you create a container after that, it can sync the files) this means that by using bind, once your source is changed, your target will never find the source again even if its the same name.
4.2 for volume (means create a docker volume with same name after pruning it):

5. Restart the container which you are using for #3 and #4 and again check the destination folder to store some data and find out whether you are able to see it in the source folder or not.

Thursday, February 24, 2022

Dockerfile

 




DOCKERFILE (on top of docker image, there is an instruction layer)

A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image. Using docker build users can create an automated build that executes several command-line instructions in succession.

vi Dockerfile (no extensions)

FROM ubuntu #downloading base

ARG DEBIAN_FRONTEND=noninteractive 
#noninteractive for automation so it does not ask geographical bla bla bla..

RUN apt-get update 
#run is adding instruction on the instruction layer

RUN apt-get -y install apache2

ADD . /var/www/html 
#add is copy the file from host machine to docker image folder

ENTRYPOINT apachectl -D FOREGROUND 
#entrypoint whenever docker image is used in a container, some commands need to be executed automatically

ENV name DEVOPS 
#environment variable is used on the global level






BUILD THE DOCKERFILE

docker build . -t webimg



when doing this, docker will create an intermediate container to try each steps. after each steps, it will destroy the intermediate container and go to next step, then create an intermediate container again.

run the build image in a container:


docker container run --name webserver -dit -p 80:80 prod/webimg

from here you can do the following:

A) check if FROM ubuntu is confirmed:
go into the container:
    docker exec -it webserver bash
then run this command:
    uname -a
(this will confirm the ubuntu)

B) check if RUN is confimed:
in container, type:
    service apache2 status

C) check if ADD . is confirmed:
in container, type:
    ls /var/www/html/

D) check if ENV name DEVOPS is confimed:
in container, type:
    env


NIC: Network Interface Card




NIC : Network Interface Card! 

every system has it and with it there is an IP address (Loopback IP). 

there is name resolution (you can use 127.0.0.1 or localhost or me) 

you can check it on vm:
cat /etc/hosts 

or 

if on windows: 
C:\Windows\System32\drivers\etc\hosts

EXAMPLES: Docker Custom Images, Save & Load, Export & Import

 


Below is the syntax to create a new image from a container

        docker commit <<container id>> <<new image name>>

Wednesday, February 23, 2022

ASSIGNMENT: Docker Custom Image (Save & Load / Export & Import)



ASSINGMENT 24 Feb 2022

1. Create a container with an ubuntu image
2. update the repository (apt update -y) in the container
3. install apache2 in a container ( apt install apache2 -y)
4. Create a directory config under /config in the container
5. Add web.config file under /config folder
6. copy an html file from your host machine to container /var/www/html
7. Verify your container is able to browse your html file (curl localhost) ( To install the curl apt install curl)
8. Create a production image (prod/webapp)
9. remove all the containers ( docker rm -f $(docker ps -a -q)
10 create a new container with prod/webapp with 80 container port forwarding and verify you are able to access the website and in the container /config directory exist with web.config file.

ASSIGNMENT: Docker Container *IMPORTANT

 

Assignment


1. Create a container called webserver with ubuntu docker image.
2. Install apache server in the container(webserver)
3. Start apache service in the container
4. Access apache default page on the web browser
5. Create a new webpage myapp.html on the host machine and copy it to /var/www/html folder in webserver container.
6. Access myapp.html page on the browser
7. Check how much memory and cpu is consumed by web server containers.
8. Stop the container and verify that you are not able to access apache website on browser.
9. Start container and now you should be able to access the apache website.
10. Remove  webserver container

EXAMPLES: Docker Container




DOCKER CONTAINERS

Applications like Microservices, WebApp, DbApp, etc are deployed on containers.

A container is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another. 


DOCKER CONTAINER COMMANDS

Find help for all the commands related to container
        
        docker container --help

Find help for a specified command of container ( In below example I am searching the options available for docker container ls command)

        docker container ls --help

Docker (Basic Commands, Images, Containers)



Reference:
Docker Hub: hub.docker.com

SUMMARY:
A) DOCKER COMMANDS
B) DOCKER IMAGES
C) DOCKER CONTAINERS

Tuesday, February 22, 2022

EXTRA INFO: Idempotency - Configuration Management



Configuration tools like puppet, chef, Terraform, Ansible etc are used to orchestrate the configuration on remote systems.

If the desired state of the task is already present on the destination server then these tools do not perform any action because the desired state is already equal to the current state. This concept is called Idempotency.


EXAMPLES: Ansible (20+ Examples!!)


 

Example 1: Create a playbook to run an echo "Hello World" command on dbservers.

Create a hello.yaml in /etc/ansible folder. ( you can give any primary name but the extension should be .yaml or .yml).
        
     touch /etc/ansible/hello.yaml
     vi hello.yaml

In the .yaml file,
Type in:
---
 - name: play for running shell commands
   hosts: dbservers
   tasks:
         - name: Executing command module
           command: echo "Hello World"
Execute:
    ansible-playbook hello.yaml


BUT this does not show the output!!

So to remedy this, the hello.yaml file needs to add some more lines of codes:

register: output
- name:
  debug:
        msg: "{{ output.stdout }}"


now it will show as per picture below!

 



Example 2: Create a playbook to read a file (/tmp/status.txt) using the command module.

---
   - name: play for running shell commands
     hosts: dbservers
     tasks:
             - name: Executing cat command
               command: cat /tmp/status.txt
               register: output
             - name: Printing output of cat command
               debug:
                       msg: "{{ output.stdout }}"


Example 3: Create MULTIPLE plays in a playbook.

  • playbook: multiple.yaml
  • play1: run on dbservers and create a file /tmp/local.txt
  • play2: run on webservers and create a file /tmp/webserver.txt

---

 - name: running shell commands on dbservers

   hosts: dbservers

   tasks:

           - name: creating local.txt on dbservers

             command: touch /tmp/local.txt


 - name: running shell commands on webservers

   hosts: webservers

   tasks:

           - name: creating webservers.txt on webservers

             command: touch /tmp/webservers.txt



done!


Example 4: Create a yaml file called (mul.yaml) and make a script such that it will create a file (testansible.txt) in /tmp and add content ("Hello World") in that .txt file and read it.


touch /etc/ansible/mul.yaml

vi /etc/ansible/mul.yaml

---

 - name: running shell command on dbservers

   hosts: dbservers

   tasks:

           - name: creating a file in /tmp/

             command: touch /tmp/testansible.txt

           - name: adding text in the .txt file (you can use copy module or shell module)

             copy:

                     content: "Hello World"

                     dest: /tmp/testansible.txt

            shell: echo "Hello World2" >> /tmp/testansible.txt

           - name: executing cat command on content of .txt file

             command: cat /tmp/testansible.txt

             register: output

           - name: printing out the content

             debug:

                     msg: "{{ output.stdout }}"


ansible-playbook mul.yaml


Example 5: Create a variable and store "Hello World" then print it out using the same mul.yaml file as example 4 above.

vi mul.yaml

---

 - name: running shell command on dbservers

   hosts: dbservers

   vars:

           string: "Hello World!"

   tasks:

           - name: creating a file in /tmp/

             command: touch /tmp/testansible.txt

           - name: adding text in the .txt file

             copy:

                     content: "{{ string }}"

                     dest: /tmp/testansible.txt

           - name: executing cat command on content of .txt file

             command: cat /tmp/testansible.txt

             register: output

           - name: printing out the content

             debug:

                     msg: "{{ output.stdout }}"


Example 6: use vars_prompt 

---
 - name: running shell command on dbservers
   hosts: dbservers
   vars_prompt:
           name: data
           prompt: Enter the value
   tasks:
           - name: creating a file in /tmp/
             command: touch /tmp/testansible.txt

           - name: adding text in the .txt file
             copy:
                     content: "{{ data }}"
                     dest: /tmp/testansible.txt

           - name: executing cat command on content of .txt file
             command: cat /tmp/testansible.txt
             register: output

           - name: printing out the content
             debug:
                     msg: "{{ output.stdout }}"


Example 7: Dry Run with --check and check mode

Dry Run

When ansible-playbook is executed with --check it will not make any changes on remote systems. Instead, any module instrumented to support ‘check mode’ (which contains most of the primary core modules, but it is not required that all modules do this) will report what changes they would have made rather than making them. Other modules that do not support check mode will also take no action, but just will not report what changes they might have made.

Example 7.1: Dry Run with --check

Below script is copying /tmp/testing.txt file to webservers /tmp/test.txt. but if you use --check option with ansible-playbook execution it will only do the dry run not actually running the command to copy to webservers.

touch /tmp/testing.txt

touch dryrun.yaml
vi dryrun.yaml
--- 
 - name: play for dry run 
   hosts: webservers 
   tasks: 
         - name: Copying testing.txt file to webservers 
           copy: 
                    src=/tmp/testing.txt 
                    dest=/tmp/test.txt


ansible-playbook dryrun.yml --check


Example 7.2: Dry Run with check_mode

touch dryruncheckmode.yaml
vi dryruncheckmode.yaml
--- 
 - name: play for dbservers multiple tasks 
   hosts: dbservers 
   vars_prompt: 
             name: data 
             prompt: Enter the value 
   tasks: 

        # Task1 
         - name: create a file 
           command: touch /tmp/myfile.txt 
           check_mode: no          (this will not apply dry run) 

         # Task2 
         - name: Add content to the file 
           copy: 
                 content: "{{ data }}" 
                 dest: /tmp/myfile.txt 
           check_mode: yes          (this will apply dry run) 

         # Task 3 
         - name: Read the content 
           command: cat /tmp/myfile.txt     
           register: output 

         # Task 4 
         - name: Print the content 
           debug: 
                 var: output.stdout


ansible-playbook dryruncheckmode.yaml


Example 10: logging with log_path

Playbook:- dryrun.yaml

uncomment log_path in ansible.cfg file to store the log output in /var/log/ansible.log

--- 
 - name: play for dry run 
   hosts: webservers 
   tasks: 
         - name: Copying testing.txt file to webservers 
           copy: src=/tmp/testing.txt 
          dest=/tmp/test.txt

ansible-playbook dryrun.yaml


After execution check /var/log/ansible.log file it should have the log of this file execution.


Example 11: no_log attribute

if no_log =True then no log information is recorded in the log file for that particular module.


Example 12: Error handling ( ignore_errors: True)

Playbook: error.yaml
In the below code, Task3 will be executed because Task2 is having the exception handling.

--- 
 - hosts: webservers 
   tasks: 
        - name: Task1 
          command: date 

        - name: Task2 
          command: date1 
          ignore_errors: True 

        - name: Task3 
          command: ls

ansible-playbook error.yaml



Example 13: Magic variables (Ansible Facts)

Playbook: facts.yaml
Run the below command to find the facts of a host, it also returns the in-built ansible variables. In below command stores the output of these inbuilt variables in facts.log file


ansible dbservers -m ansible.builtin.setup > facts.log


to read the log:
vi facts.log

vi facts.yaml
---
 - name: play for finding the facts using ansible magic variables 
   hosts: webservers 
   tasks: 
             - name: Print some facts 
               debug: 
                             msg: "{{ ansible_facts['os_family'], ansible_facts['nodename'] }}"


ansible-playbook facts.yaml

It should print the OS Name and node name of web servers.


Example 14: create a conditional statement (when) if the server is using the os_family of RedHat.

vi conditional.yaml
---
 - name: play for conditional statements
   hosts: webservers
   tasks:
           - name: install httpd (apache server on CentOS)
             yum:
                     name: httpd
                     state: present
             when: ansible_facts['os_family']=='RedHat'

It should skip for the webservers cause they are debian-based systems.

Example 15: (!= operator)
Create a playbook to install apache2 on OS which doesn't belong to RedHat family

vi conditionnotequals.yaml
---
- name: play for conditonal statements
  hosts: webservers
  tasks:
        - name: install apache2
          apt:
                name: apache2
                state: present
          when: ansible_facts['os_family']!="RedHat"

ansible-playbook conditionnotequals.yaml



Example 16: (or logical operator)
Create a playbook to install apache2 on OS which doesn't belong to RedHat family or belongs to Debian OS family

vi conditionor.yaml
---
- name: play for conditonal statements
  hosts: webservers
  tasks:
        - name: install apache2
          apt:
                name: apache2
                state: present
          when: ansible_facts['os_family']!="RedHat" or ansible_facts['os_family']=="Debian"

ansible-playbook conditionor.yaml



Example 17: (and logical operator)
Create a playbook to install apache2 on OS which doesn't belong to Debian OS family and OS is Ubuntu

vi conditionand.yaml
---
- name: play for conditonal statements
  hosts: webservers
  tasks:
        - name: install apache2
          apt:
                name: apache2
                state: present
          when: ansible_facts['os_family']=="Debian" and ansible_distribution=="Ubuntu"


ansible-playbook conditionand.yaml



Example 18: Loops part 1 (iterate through item)

vi loops1.yaml
---
- name: playbook for loops example
  hosts: dbservers
  tasks:
        - name: print values using loops
          debug:
                msg: "{{ item }}"
          with_items / loop:
                - 1
                - 2
                - 3
                - 4


ansible-playbook loops1.yaml

Example 19: Loops part 2 (iterate through making directories)
Create some directories under /tmp using loop statement

vi loop2.yaml
---
 - name: play for loops
   hosts: dbservers
   tasks:
    - name: Create Multiple directories
      command: mkdir "{{ item }}"
      loop / with_items:
           - /tmp/1
           - /tmp/2
           - /tmp/3
           - /tmp/4

ansible-playbook loops2.yaml

Example 20: Loops part3 (remove directories created on example 19 using loops)

vi loop3.yaml

---
 - name: play for loops
   hosts: dbservers
   vars:
       dirs:
          - /tmp/1
          - /tmp/2
          - /tmp/3
   tasks:
     - name: removing directories
       command: rmdir "{{ item }}"
       with_items / loop: "{{ dirs }}"

ansible-playbook loop3.yaml

Example 21: Multiple Conditions (utilizing in-built commands (succeeded, failed, skipped))

vi multcond.yaml
---
 - name: multiple condition
   hosts: webservers
   vars:
           testskip: test
   tasks:
           - name: Executing a shell script
             command: sh /home/vagrant/test.sh
             register: output
             ignore_errors: True
             when: testskip == "ABC"

           - name: Execute when shell script is executed successfully
             debug:
                     var: output.stdout
             when: output is succeeded

           - name: Execute when shell script execution failed
             debug:
                     msg: "Script execuion is failed"
             when: output is failed

           - name: Execute when shell script is executed successfully
             debug:
                     msg: "Script is skipped"
             when: output is skipped


ansible-playbook multcond.yaml

Example 22: Ansible Tags

You can run a specific task using ansible tags.

vi tags.yaml

---
 - name: using Tags
   hosts: webservers
   tasks:
        - name: Start a service
          service:
            name: apache2
            state: started
          tags: startservice
        - name: Stop apache service
          service:
             name: apache2
             state: stopped
          tags: stopservice
        - name: Restart apahce service
          service:
             name: apache2
             state: restarted
          tags: restartservice

ansible-playbook tags.yaml --tags restartservice

Fluentd

Open-source log data collector > why logs? - for compliance (auditing, company, business) - for security (transparency, monitoring, admin...