Return to Video

Ansible best current practices

  • Not Synced
    Thank you everyone for coming.
  • Not Synced
    If you were expecting the Postgres talk,
    that was the one before, so
  • Not Synced
    you might need to watch the video stream.
  • Not Synced
    So, Ansible best practices,
  • Not Synced
    I thought about calling it "Ansible,
    my best practices",
  • Not Synced
    so, just warning ahead, this is things
    I stumbled on using Ansible
  • Not Synced
    for the last 2-3 years and
  • Not Synced
    those are very specific things I found
    that worked very well for me.
  • Not Synced
    About me, I do also freelance work,
    do a lot of Ansible in there,
  • Not Synced
    I'm also the Debian maintainer for
    Ansible with Harlan Lieberman-Berg
  • Not Synced
    If there are any bugs in the package,
    just report them.
  • Not Synced
    The talk will be roughly divided into
    4 parts.
  • Not Synced
    The first part will be about why you
    actually want to use config management
  • Not Synced
    and why you specifically want to use
    Ansible.
  • Not Synced
    So, if you're still SSHing into machines
    and editing config files,
  • Not Synced
    you're probably a good candidate
    for using Ansible.
  • Not Synced
    Then, the second part will be about good
    role and playbook patterns
  • Not Synced
    that I have found that work really well
    for me.
  • Not Synced
    The third chapter will be about typical
    antipatterns I've stumbled upon,
  • Not Synced
    either in my work with other people
    using Ansible,
  • Not Synced
    or the IRC support channel, for example.
  • Not Synced
    The fourth part will be like advanced
    tips and tricks you can use
  • Not Synced
    like fun things you can do with Ansible.
  • Not Synced
    Quick elevator pitch, what makes config
    management good?
  • Not Synced
    It actually also serves as a documentation
    of changes on your servers over time
  • Not Synced
    so if you just put the whole config
    management in a git repo
  • Not Synced
    and just regularly commit,
  • Not Synced
    you will actually be able to say
  • Not Synced
    "Why doesn't this work? It used to work
    a year ago"
  • Not Synced
    You can actually check why.
  • Not Synced
    Also, most config management tools have
    a lot better error reporting than
  • Not Synced
    your self-written bash scripts that do
    whatever.
  • Not Synced
    And usually, you have a very good
    reproducibility with config management
  • Not Synced
    and also idempotency, meaning that if you
    run, for example, a playbook several times
  • Not Synced
    you will always get the same result.
  • Not Synced
    Also, it's great if you work in small team
    or you admin ??? in the company
  • Not Synced
    and you have some people working
    on a few things too.
  • Not Synced
    It makes team work a lot easier and
    you will save a lot of time actually
  • Not Synced
    debugging things when things break.
  • Not Synced
    What makes Ansible good?
  • Not Synced
    Comparing it to Chef or Puppet for example
    it's really easy to set up,
  • Not Synced
    you start with two config files, you have
    it installed and you're ready to go.
  • Not Synced
    It's also agentless, so whatever machines
    you actually want to control,
  • Not Synced
    the only thing you they really need to have
    is an SSH daemon and Python 2.6+
  • Not Synced
    so that's virtually any Debian machine
    you have installed and
  • Not Synced
    that ???
  • Not Synced
    Ansible also supports configuration
    of many things like
  • Not Synced
    networking equipment or even Windows
    machines,
  • Not Synced
    they don't need SSH but they use the
    WinRM
  • Not Synced
    but Ansible came a bit late to the game
    so Ansible's still not as good
  • Not Synced
    in coverage like for example Puppet,
  • Not Synced
    which literally, you can configure any
    machine on the planet with that,
  • Not Synced
    as long as it has a CPU.
  • Not Synced
    Next step, I will talk about good
    role patterns.
  • Not Synced
    If you've never worked with Ansible
    before,
  • Not Synced
    this is the point when you watch
    the video stream,
  • Not Synced
    that you pause it and start working
    a few weeks with it
  • Not Synced
    and then unpause the actual video.
  • Not Synced
    A good role should ideally have
    the following layout.
  • Not Synced
    So, in the "roles" directory, you have
    the name of the role and task/main.yml
  • Not Synced
    You have the following rough layout.
  • Not Synced
    At the beginning of the role, you check
    for various conditions,
  • Not Synced
    for example using the "assert" task to
    for example check that
  • Not Synced
    certain variables are defined, things
    are set,
  • Not Synced
    that it's maybe part of a group, things
    like that you actually want to check.
  • Not Synced
    Then, usually, you install packages, you
    can use apt on CentOS machines,
  • Not Synced
    yum, or you can do a git checkout or
    whatever,
  • Not Synced
    then usually you do some templating of
    files where you have certain abstraction
  • Not Synced
    and the variables are actually put into
    the template and
  • Not Synced
    make the actual config file.
  • Not Synced
    There's also good to point out that
    the template module actually has
  • Not Synced
    a "validate" parameter,
  • Not Synced
    that means you can actually use a command
    to check your config files for syntax errors
  • Not Synced
    and if that fails, your playbook will fail
    before actually deploying that config file
  • Not Synced
    so you can for example use Apache with
    the right parameters to actually do
  • Not Synced
    a check on the syntax of the file.
  • Not Synced
    That way, you never end up with a state
    where there's a broken config.
  • Not Synced
    In the end, you usually…
  • Not Synced
    When you change things, you trigger
    handlers to restart any ???
  • Not Synced
    If you use variables, I recommend putting
    sensible defaults in
  • Not Synced
    defaults/main.yml
  • Not Synced
    and then you only have to override
    those variables on specific cases.
  • Not Synced
    Ideally, you should have sensible defaults
    you want to have to get whatever things
  • Not Synced
    you want to have running.
  • Not Synced
    When you start working with it and do that
    a bit more,
  • Not Synced
    you notice a few things and that is
  • Not Synced
    your role should ideally run in "check mode".
  • Not Synced
    "ansible-playbook" has --check that
    basically is just a dry run of
  • Not Synced
    your complete playbook
  • Not Synced
    and with --diff, it will actually show you
    for example file changes,
  • Not Synced
    or file mode changes, stuff like that
  • Not Synced
    and won't actually change anything.
  • Not Synced
    So if you end up editing a lot of stuff,
    you can use that as a check.
  • Not Synced
    I'll later get to some antipatterns that
    actually break that thing.
  • Not Synced
    And, ideally, the way you change files
    and configs and states,
  • Not Synced
    you should make sure that when the actual
    changes are deployed,
  • Not Synced
    and you run it a second time,
  • Not Synced
    that Ansible doesn't report any changes
  • Not Synced
    because if you end up writing your roles
    fairly sloppy, you end up having
  • Not Synced
    a lot of changes and then,
  • Not Synced
    in the end of the report, you have like
    20 changes reported and
  • Not Synced
    you kind of then know those 18,
    they're always there
  • Not Synced
    and you kind of miss the 2 that are
    important, that actually broke your system
  • Not Synced
    If you want to do it really well, you make
    sure that it doesn't report any changes
  • Not Synced
    when you run it twice in a row.
  • Not Synced
    Also, a thing to consider is you can define
    variables in the "defaults" folder
  • Not Synced
    and also in the "vars" folder,
  • Not Synced
    but if you look up how variables get
    inherited, you'll notice that
  • Not Synced
    the "vars" folder is really hard to
    actually override,
  • Not Synced
    so you want to avoid that as much as
    possible.
  • Not Synced
    That much larger section will be about
    typical anti-patterns I've noticed
  • Not Synced
    and I'll come to the first one now.
  • Not Synced
    It's the shell or command module.
  • Not Synced
    When people start using Ansible, that's
    the first thing they go
  • Not Synced
    "Oh well, I know how to use wget or I know
    'apt-get install' "
  • Not Synced
    and then they end up using the shell module
    to do just that.
  • Not Synced
    If you use the shell module or the command
    module, you usually don't want to use that
  • Not Synced
    and that's for several reasons.
  • Not Synced
    There's currently, I think, 1300 different
    modules in Ansible
  • Not Synced
    so there's likely a big chance that
    whatever you want to do,
  • Not Synced
    there's already a module for that, that
    just does that thing.
  • Not Synced
    But those two modules also have several
    problems and that is
  • Not Synced
    the shell module, of course, gets
    interpreted by your actual shell,
  • Not Synced
    so if you have any special variables
    in there,
  • Not Synced
    you'd actually also have to take care of
    any variables you interpret in the shell string.
  • Not Synced
    Then, one of the biggest problems is if
    you run your playbook in check mode,
  • Not Synced
    the shell and the command modules
    won't get run.
  • Not Synced
    So if you're actually doing anything
    with that, they just get skipped
  • Not Synced
    and that would cause that your actual
    check mode and the real mode,
  • Not Synced
    they will start diverging if you use
    a lot of shell module.
  • Not Synced
    The worst, also, bad part about this
    is that these two modules,
  • Not Synced
    they'll always ??? changed
  • Not Synced
    like, you run a command and it exits 0
  • Not Synced
    it's like "Oh, it changed"
  • Not Synced
    To get the reporting right on that module,
    you'd actually have to define for yourself
  • Not Synced
    when this is actually a change or not.
  • Not Synced
    So you'd have to probably get the output
    and then check, for example,
  • Not Synced
    if there's something on stderr or something
    to report an actual error or change.
  • Not Synced
    Then I'll get to the actual examples.
  • Not Synced
    The left is a bad example for using
    the shell module,
  • Not Synced
    I've seen that a lot, it's basically
  • Not Synced
    "Yeah, I actually want this file, so just
    use 'cat /path/file' and I'll use
  • Not Synced
    the register parameter to get the output".
  • Not Synced
    The actual output goes into the "shell_cmd"
    and then
  • Not Synced
    we want to copy it to some other file
    somewhere else and
  • Not Synced
    so we use the Jinja "{{ }}" to define
    the actual content of the file
  • Not Synced
    and then put it into that destination file
  • Not Synced
    That is problematic because, first of all
    if you run it in check mode,
  • Not Synced
    this gets skipped and then this variable
    is undefined and
  • Not Synced
    Ansible will fail with an error, so you
    won't be able to actually
  • Not Synced
    run that in check mode.
  • Not Synced
    The other problem is this will always
    ???
  • Not Synced
    so you'd probably have to…
  • Not Synced
    the most sensible thing would probably
    be to say just "changed when false"
  • Not Synced
    and just acknowledge that that shell
    command won't change anything on this system
  • Not Synced
    The good example would be to use the
    actual "slurp" module that will
  • Not Synced
    just slurp the whole file and base64encode it
  • Not Synced
    and you can access the actual content with
    "path_file.contents" and you then just
  • Not Synced
    base64decode it and write in there.
  • Not Synced
    The nice thing is slurp will never return
    any change, so it won't say it changed
  • Not Synced
    and it also works great in check mode.
  • Not Synced
    Here's an other quick example.
  • Not Synced
    The example on the left, oh yeah wget.
  • Not Synced
    Here's the problem, every time your playbook
    runs, this file will get downloaded
  • Not Synced
    and of course if the file can't be
    retrieved from that URL
  • Not Synced
    it will throw an error and that will
    happen all the time.
  • Not Synced
    The right example is a more clean example
    using the uri module.
  • Not Synced
    You define a URL to retrieve a file from,
    you define where you want to write it to
  • Not Synced
    and you use the "creates" parameter to say
  • Not Synced
    "Just skip the whole thing if the file is
    already there".
Title:
Ansible best current practices
Description:

Talk given by Lee Garrett at Minidebconf Hamburg 2018
https://meetings-archive.debian.net/pub/debian-meetings/2018/miniconf-hamburg/2018-05-20/ansible_bcp.webm

more » « less
Video Language:
English
Team:
Debconf
Project:
2018_mini-debconf-hamburg
Duration:
23:46

English subtitles

Incomplete

Revisions Compare revisions